Home | History | Annotate | Download | only in svg
      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, "&;", "&amp;;", -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