mirror of
https://github.com/aptly-dev/aptly.git
synced 2026-04-22 19:58:14 +00:00
186 lines
3.9 KiB
Go
186 lines
3.9 KiB
Go
//Copyright 2013 GoGraphviz Authors
|
|
//
|
|
//Licensed under the Apache License, Version 2.0 (the "License");
|
|
//you may not use this file except in compliance with the License.
|
|
//You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
//Unless required by applicable law or agreed to in writing, software
|
|
//distributed under the License is distributed on an "AS IS" BASIS,
|
|
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
//See the License for the specific language governing permissions and
|
|
//limitations under the License.
|
|
|
|
package gographviz
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/awalterschulze/gographviz/scanner"
|
|
"github.com/awalterschulze/gographviz/token"
|
|
"strings"
|
|
"text/template"
|
|
"unicode"
|
|
)
|
|
|
|
type Escape struct {
|
|
*Graph
|
|
}
|
|
|
|
//Returns a graph which will try to escape some strings when required
|
|
func NewEscape() *Escape {
|
|
return &Escape{NewGraph()}
|
|
}
|
|
|
|
func isHtml(s string) bool {
|
|
if len(s) == 0 {
|
|
return false
|
|
}
|
|
ss := strings.TrimSpace(s)
|
|
if ss[0] != '<' {
|
|
return false
|
|
}
|
|
count := 0
|
|
for _, c := range ss {
|
|
if c == '<' {
|
|
count += 1
|
|
}
|
|
if c == '>' {
|
|
count -= 1
|
|
}
|
|
}
|
|
if count == 0 {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
func isLetter(ch rune) bool {
|
|
return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' ||
|
|
ch >= 0x80 && unicode.IsLetter(ch) && ch != 'ε'
|
|
}
|
|
|
|
func isId(s string) bool {
|
|
i := 0
|
|
pos := false
|
|
for _, c := range s {
|
|
if i == 0 {
|
|
if !isLetter(c) {
|
|
return false
|
|
}
|
|
pos = true
|
|
}
|
|
if unicode.IsSpace(c) {
|
|
return false
|
|
}
|
|
if c == '-' {
|
|
return false
|
|
}
|
|
i++
|
|
}
|
|
return pos
|
|
}
|
|
|
|
func isDigit(ch rune) bool {
|
|
return '0' <= ch && ch <= '9' || ch >= 0x80 && unicode.IsDigit(ch)
|
|
}
|
|
|
|
func isNumber(s string) bool {
|
|
state := 0
|
|
for _, c := range s {
|
|
if state == 0 {
|
|
if isDigit(c) || c == '.' {
|
|
state = 2
|
|
} else if c == '-' {
|
|
state = 1
|
|
} else {
|
|
return false
|
|
}
|
|
} else if state == 1 {
|
|
if isDigit(c) || c == '.' {
|
|
state = 2
|
|
}
|
|
} else if c != '.' && !isDigit(c) {
|
|
return false
|
|
}
|
|
}
|
|
return (state == 2)
|
|
}
|
|
|
|
func isStringLit(s string) bool {
|
|
lex := &scanner.Scanner{}
|
|
lex.Init([]byte(s), token.DOTTokens)
|
|
tok, _ := lex.Scan()
|
|
if tok.Type != token.DOTTokens.Type("string_lit") {
|
|
return false
|
|
}
|
|
tok, _ = lex.Scan()
|
|
if tok.Type != token.EOF {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
func esc(s string) string {
|
|
if len(s) == 0 {
|
|
return s
|
|
}
|
|
if isHtml(s) {
|
|
return s
|
|
}
|
|
ss := strings.TrimSpace(s)
|
|
if ss[0] == '<' {
|
|
return fmt.Sprintf("\"%s\"", strings.Replace(s, "\"", "\\\"", -1))
|
|
}
|
|
if isId(s) {
|
|
return s
|
|
}
|
|
if isNumber(s) {
|
|
return s
|
|
}
|
|
if isStringLit(s) {
|
|
return s
|
|
}
|
|
return fmt.Sprintf("\"%s\"", template.HTMLEscapeString(s))
|
|
}
|
|
|
|
func escAttrs(attrs map[string]string) map[string]string {
|
|
newAttrs := make(map[string]string)
|
|
for k, v := range attrs {
|
|
newAttrs[esc(k)] = esc(v)
|
|
}
|
|
return newAttrs
|
|
}
|
|
|
|
func (this *Escape) SetName(name string) {
|
|
this.Graph.SetName(esc(name))
|
|
}
|
|
|
|
func (this *Escape) AddPortEdge(src, srcPort, dst, dstPort string, directed bool, attrs map[string]string) {
|
|
this.Graph.AddPortEdge(esc(src), srcPort, esc(dst), dstPort, directed, escAttrs(attrs))
|
|
}
|
|
|
|
func (this *Escape) AddEdge(src, dst string, directed bool, attrs map[string]string) {
|
|
this.AddPortEdge(src, "", dst, "", directed, attrs)
|
|
}
|
|
|
|
func (this *Escape) AddNode(parentGraph string, name string, attrs map[string]string) {
|
|
this.Graph.AddNode(esc(parentGraph), esc(name), escAttrs(attrs))
|
|
}
|
|
|
|
func (this *Escape) AddAttr(parentGraph string, field, value string) {
|
|
this.Graph.AddAttr(esc(parentGraph), esc(field), esc(value))
|
|
}
|
|
|
|
func (this *Escape) AddSubGraph(parentGraph string, name string, attrs map[string]string) {
|
|
this.Graph.AddSubGraph(esc(parentGraph), esc(name), escAttrs(attrs))
|
|
}
|
|
|
|
func (this *Escape) IsNode(name string) bool {
|
|
return this.Graph.IsNode(esc(name))
|
|
}
|
|
|
|
func (this *Escape) IsSubGraph(name string) bool {
|
|
return this.Graph.IsSubGraph(esc(name))
|
|
}
|