1 // Copyright 2014 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package svg provides tools related to handling of SVG files 6 package svg 7 8 import ( 9 "bytes" 10 "regexp" 11 "strings" 12 ) 13 14 var ( 15 viewBox = regexp.MustCompile(`<svg\s*width="[^"]+"\s*height="[^"]+"\s*viewBox="[^"]+"`) 16 graphId = regexp.MustCompile(`<g id="graph\d"`) 17 svgClose = regexp.MustCompile(`</svg>`) 18 ) 19 20 // Massage enhances the SVG output from DOT to provide better 21 // panning inside a web browser. It uses the SVGPan library, which is 22 // included directly. 23 func Massage(in bytes.Buffer) string { 24 svg := string(in.Bytes()) 25 26 // Work around for dot bug which misses quoting some ampersands, 27 // resulting on unparsable SVG. 28 svg = strings.Replace(svg, "&;", "&;", -1) 29 30 //Dot's SVG output is 31 // 32 // <svg width="___" height="___" 33 // viewBox="___" xmlns=...> 34 // <g id="graph0" transform="..."> 35 // ... 36 // </g> 37 // </svg> 38 // 39 // Change it to 40 // 41 // <svg width="100%" height="100%" 42 // xmlns=...> 43 // <script>...</script> 44 // <g id="viewport" transform="translate(0,0)"> 45 // <g id="graph0" transform="..."> 46 // ... 47 // </g> 48 // </g> 49 // </svg> 50 51 if loc := viewBox.FindStringIndex(svg); loc != nil { 52 svg = svg[:loc[0]] + 53 `<svg width="100%" height="100%"` + 54 svg[loc[1]:] 55 } 56 57 if loc := graphId.FindStringIndex(svg); loc != nil { 58 svg = svg[:loc[0]] + 59 `<script type="text/ecmascript"><![CDATA[` + svgPanJS + `]]></script>` + 60 `<g id="viewport" transform="scale(0.5,0.5) translate(0,0)">` + 61 svg[loc[0]:] 62 } 63 64 if loc := svgClose.FindStringIndex(svg); loc != nil { 65 svg = svg[:loc[0]] + 66 `</g>` + 67 svg[loc[0]:] 68 } 69 70 return svg 71 } 72