| // Copyright 2014 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // Package svg provides tools related to handling of SVG files |
| package svg |
| |
| import ( |
| "bytes" |
| "regexp" |
| "strings" |
| ) |
| |
| var ( |
| viewBox = regexp.MustCompile(`<svg\s*width="[^"]+"\s*height="[^"]+"\s*viewBox="[^"]+"`) |
| graphId = regexp.MustCompile(`<g id="graph\d"`) |
| svgClose = regexp.MustCompile(`</svg>`) |
| ) |
| |
| // Massage enhances the SVG output from DOT to provide bettern |
| // panning inside a web browser. It uses the SVGPan library, which is |
| // accessed through the svgPan URL. |
| func Massage(in bytes.Buffer, svgPan string) string { |
| svg := string(in.Bytes()) |
| |
| // Work around for dot bug which misses quoting some ampersands, |
| // resulting on unparsable SVG. |
| svg = strings.Replace(svg, "&;", "&;", -1) |
| if svgPan == "" { |
| return svg |
| } |
| |
| //Dot's SVG output is |
| // |
| // <svg width="___" height="___" |
| // viewBox="___" xmlns=...> |
| // <g id="graph0" transform="..."> |
| // ... |
| // </g> |
| // </svg> |
| // |
| // Change it to |
| // |
| // <svg width="100%" height="100%" |
| // xmlns=...> |
| // <script xlink:href=" ...$svgpan.. "/> |
| |
| // <g id="viewport" transform="translate(0,0)"> |
| // <g id="graph0" transform="..."> |
| // ... |
| // </g> |
| // </g> |
| // </svg> |
| |
| if loc := viewBox.FindStringIndex(svg); loc != nil { |
| svg = svg[:loc[0]] + |
| `<svg width="100%" height="100%"` + |
| svg[loc[1]:] |
| } |
| |
| if loc := graphId.FindStringIndex(svg); loc != nil { |
| svg = svg[:loc[0]] + |
| `<script xlink:href="` + svgPan + `"/>` + |
| `<g id="viewport" transform="scale(0.5,0.5) translate(0,0)">` + |
| svg[loc[0]:] |
| } |
| |
| if loc := svgClose.FindStringIndex(svg); loc != nil { |
| svg = svg[:loc[0]] + |
| `</g>` + |
| svg[loc[0]:] |
| } |
| |
| return svg |
| } |