mirror of
				https://github.com/goccy/go-yaml.git
				synced 2025-10-30 04:41:06 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			868 lines
		
	
	
	
		
			22 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			868 lines
		
	
	
	
		
			22 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| //go:build js && wasm
 | |
| 
 | |
| package main
 | |
| 
 | |
| import (
 | |
| 	"bytes"
 | |
| 	"context"
 | |
| 	"errors"
 | |
| 	"fmt"
 | |
| 	"io"
 | |
| 	"strings"
 | |
| 	"syscall/js"
 | |
| 
 | |
| 	"github.com/goccy/go-graphviz"
 | |
| 	"github.com/goccy/go-json"
 | |
| 	"github.com/goccy/go-yaml"
 | |
| 	"github.com/goccy/go-yaml/ast"
 | |
| 	"github.com/goccy/go-yaml/lexer"
 | |
| 	"github.com/goccy/go-yaml/parser"
 | |
| 	"github.com/goccy/go-yaml/token"
 | |
| )
 | |
| 
 | |
| func response(v any, err error) map[string]any {
 | |
| 	if err != nil {
 | |
| 		return map[string]any{
 | |
| 			"error": err.Error(),
 | |
| 		}
 | |
| 	}
 | |
| 	return map[string]any{
 | |
| 		"response": v,
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func decode(this js.Value, args []js.Value) any {
 | |
| 	v := args[0].String()
 | |
| 	b, err := Decode(v)
 | |
| 	if err != nil {
 | |
| 		return response(nil, err)
 | |
| 	}
 | |
| 	return response(string(b), nil)
 | |
| }
 | |
| 
 | |
| func tokenize(this js.Value, args []js.Value) any {
 | |
| 	v := args[0].String()
 | |
| 	b, err := Tokenize(v)
 | |
| 	if err != nil {
 | |
| 		return response(nil, err)
 | |
| 	}
 | |
| 	return response(string(b), nil)
 | |
| }
 | |
| 
 | |
| func parseGroup(this js.Value, args []js.Value) any {
 | |
| 	v := args[0].String()
 | |
| 	b, err := ParseGroup(v)
 | |
| 	if err != nil {
 | |
| 		return response(nil, err)
 | |
| 	}
 | |
| 	return response(string(b), nil)
 | |
| }
 | |
| 
 | |
| func parse(this js.Value, args []js.Value) any {
 | |
| 	v := args[0].String()
 | |
| 	b, err := Parse(context.Background(), v)
 | |
| 	if err != nil {
 | |
| 		return response(nil, err)
 | |
| 	}
 | |
| 	return response(string(b), nil)
 | |
| }
 | |
| 
 | |
| func Decode(v string) ([]byte, error) {
 | |
| 	var ret []string
 | |
| 	dec := yaml.NewDecoder(strings.NewReader(v))
 | |
| 	for {
 | |
| 		var v any
 | |
| 		if err := dec.Decode(&v); err != nil {
 | |
| 			if err == io.EOF {
 | |
| 				break
 | |
| 			}
 | |
| 			return nil, errors.New(yaml.FormatError(err, true, true))
 | |
| 		}
 | |
| 		got, err := json.MarshalIndentWithOption(v, "", "  ", json.Colorize(json.DefaultColorScheme))
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 		ret = append(ret, string(got))
 | |
| 	}
 | |
| 	return []byte(strings.Join(ret, "\n")), nil
 | |
| }
 | |
| 
 | |
| type Token struct {
 | |
| 	Type   string `json:"type"`
 | |
| 	Value  string `json:"value"`
 | |
| 	Origin string `json:"origin"`
 | |
| 	Error  string `json:"error"`
 | |
| 	Line   int    `json:"line"`
 | |
| 	Column int    `json:"column"`
 | |
| 	Offset int    `json:"offset"`
 | |
| }
 | |
| 
 | |
| func Tokenize(v string) ([]byte, error) {
 | |
| 	tks := lexer.Tokenize(v)
 | |
| 	ret := make([]*Token, 0, len(tks))
 | |
| 	for _, tk := range tks {
 | |
| 		ret = append(ret, toToken(tk))
 | |
| 	}
 | |
| 	b, err := json.Marshal(ret)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return b, nil
 | |
| }
 | |
| 
 | |
| func toToken(tk *token.Token) *Token {
 | |
| 	if tk == nil {
 | |
| 		return nil
 | |
| 	}
 | |
| 	return &Token{
 | |
| 		Type:   tk.Type.String(),
 | |
| 		Value:  tk.Value,
 | |
| 		Origin: tk.Origin,
 | |
| 		Error:  tk.Error,
 | |
| 		Line:   tk.Position.Line,
 | |
| 		Column: tk.Position.Column,
 | |
| 		Offset: tk.Position.Offset,
 | |
| 	}
 | |
| }
 | |
| 
 | |
| type GroupedToken struct {
 | |
| 	Token       *Token      `json:"token"`
 | |
| 	Group       *TokenGroup `json:"group"`
 | |
| 	LineComment *Token      `json:"lineComment"`
 | |
| }
 | |
| 
 | |
| type TokenGroup struct {
 | |
| 	Type   string          `json:"type"`
 | |
| 	Tokens []*GroupedToken `json:"tokens"`
 | |
| }
 | |
| 
 | |
| func toGroupedToken(tk *parser.Token) *GroupedToken {
 | |
| 	if tk == nil {
 | |
| 		return nil
 | |
| 	}
 | |
| 	return &GroupedToken{
 | |
| 		Token:       toToken(tk.Token),
 | |
| 		Group:       toTokenGroup(tk.Group),
 | |
| 		LineComment: toToken(tk.LineComment),
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func toTokenGroup(g *parser.TokenGroup) *TokenGroup {
 | |
| 	if g == nil {
 | |
| 		return nil
 | |
| 	}
 | |
| 	tokens := make([]*GroupedToken, 0, len(g.Tokens))
 | |
| 	for _, tk := range g.Tokens {
 | |
| 		tokens = append(tokens, toGroupedToken(tk))
 | |
| 	}
 | |
| 	return &TokenGroup{
 | |
| 		Type:   g.Type.String(),
 | |
| 		Tokens: tokens,
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func ParseGroup(v string) ([]byte, error) {
 | |
| 	tks, err := parser.CreateGroupedTokens(lexer.Tokenize(v))
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	ret := make([]*GroupedToken, 0, len(tks))
 | |
| 	for _, tk := range tks {
 | |
| 		ret = append(ret, toGroupedToken(tk))
 | |
| 	}
 | |
| 	b, err := json.Marshal(ret)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return b, nil
 | |
| }
 | |
| 
 | |
| func Parse(ctx context.Context, v string) ([]byte, error) {
 | |
| 	gv, err := graphviz.New(ctx)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	file, err := parser.ParseBytes([]byte(v), parser.ParseComments)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	graph, err := gv.Graph()
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	graph.SetCompound(true)
 | |
| 	defer func() {
 | |
| 		if err := graph.Close(); err != nil {
 | |
| 			panic(err)
 | |
| 		}
 | |
| 		gv.Close()
 | |
| 	}()
 | |
| 	renderer := &NodeRenderer{}
 | |
| 	if _, err := renderer.renderFile(graph, file); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	var out bytes.Buffer
 | |
| 	if err := gv.Render(ctx, graph, graphviz.SVG, &out); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return out.Bytes(), nil
 | |
| }
 | |
| 
 | |
| type NodeRenderer struct {
 | |
| 	id    int
 | |
| 	edges []*Edge
 | |
| }
 | |
| 
 | |
| type Edge struct {
 | |
| 	start *Node
 | |
| 	end   *Node
 | |
| }
 | |
| 
 | |
| type Node struct {
 | |
| 	graphName string
 | |
| 	node      *graphviz.Node
 | |
| }
 | |
| 
 | |
| func (r *NodeRenderer) createID() string {
 | |
| 	r.id++
 | |
| 	return fmt.Sprint(r.id)
 | |
| }
 | |
| 
 | |
| func (r *NodeRenderer) createNodeGraph(parent *graphviz.Graph, node any, name string) (*graphviz.Graph, error) {
 | |
| 	id := r.createID()
 | |
| 	sub, err := parent.CreateSubGraphByName("cluster" + id)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	sub.SetCompound(true)
 | |
| 	sub.SetLabel(name)
 | |
| 	sub.SetStyle(graphviz.FilledGraphStyle)
 | |
| 	sub.SetBackgroundColor("white")
 | |
| 	return sub, nil
 | |
| }
 | |
| 
 | |
| func (r *NodeRenderer) createNode(graph *graphviz.Graph, name string) (*graphviz.Node, error) {
 | |
| 	node, err := graph.CreateNodeByName(r.createID())
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	node.SetLabel(name)
 | |
| 	node.SetStyle(graphviz.FilledNodeStyle)
 | |
| 	node.SetFillColor("white")
 | |
| 	return node, nil
 | |
| }
 | |
| 
 | |
| func (r *NodeRenderer) createEdge(fromGraph *graphviz.Graph, fromNode *graphviz.Node, toGraph *graphviz.Graph) error {
 | |
| 	to, err := toGraph.FirstNode()
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	edge, err := fromGraph.CreateEdgeByName("", fromNode, to)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	fromGraphName, err := fromGraph.Name()
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	toGraphName, err := toGraph.Name()
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	edge.SetLogicalTail(fromGraphName)
 | |
| 	edge.SetLogicalHead(toGraphName)
 | |
| 	edge.SetMinLen(2)
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (r *NodeRenderer) renderFile(graph *graphviz.Graph, file *ast.File) (*graphviz.Graph, error) {
 | |
| 	fileGraph, err := r.createNodeGraph(graph, file, "FileNode")
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	fileGraph.SetBackgroundColor("ivory")
 | |
| 	for idx, doc := range file.Docs {
 | |
| 		node, err := r.createNode(fileGraph, fmt.Sprintf("docs[%d]", idx))
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 		docGraph, err := r.renderDocument(fileGraph, doc)
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 		if err := r.createEdge(fileGraph, node, docGraph); err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 	}
 | |
| 	return fileGraph, nil
 | |
| }
 | |
| 
 | |
| func (r *NodeRenderer) renderDocument(graph *graphviz.Graph, doc *ast.DocumentNode) (*graphviz.Graph, error) {
 | |
| 	docGraph, err := r.createNodeGraph(graph, doc, "DocumentNode")
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	docGraph.SetBackgroundColor("mintcream")
 | |
| 	if err := r.renderToken(docGraph, doc.Start); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if err := r.renderToken(docGraph, doc.End); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	body, err := r.createNode(docGraph, "body")
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	bodyGraph, err := r.renderNode(docGraph, doc.Body)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if err := r.createEdge(docGraph, body, bodyGraph); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return docGraph, nil
 | |
| }
 | |
| 
 | |
| func (r *NodeRenderer) renderNode(graph *graphviz.Graph, node ast.Node) (*graphviz.Graph, error) {
 | |
| 	switch n := node.(type) {
 | |
| 	case *ast.MappingNode:
 | |
| 		return r.renderMappingNode(graph, n)
 | |
| 	case *ast.NullNode:
 | |
| 		return r.renderNullNode(graph, n)
 | |
| 	case *ast.IntegerNode:
 | |
| 		return r.renderIntegerNode(graph, n)
 | |
| 	case *ast.FloatNode:
 | |
| 		return r.renderFloatNode(graph, n)
 | |
| 	case *ast.StringNode:
 | |
| 		return r.renderStringNode(graph, n)
 | |
| 	case *ast.LiteralNode:
 | |
| 		return r.renderLiteralNode(graph, n)
 | |
| 	case *ast.MergeKeyNode:
 | |
| 		return r.renderMergeKeyNode(graph, n)
 | |
| 	case *ast.BoolNode:
 | |
| 		return r.renderBoolNode(graph, n)
 | |
| 	case *ast.InfinityNode:
 | |
| 		return r.renderInfinityNode(graph, n)
 | |
| 	case *ast.NanNode:
 | |
| 		return r.renderNaNNode(graph, n)
 | |
| 	case *ast.MappingKeyNode:
 | |
| 		return r.renderMappingKeyNode(graph, n)
 | |
| 	case *ast.SequenceNode:
 | |
| 		return r.renderSequenceNode(graph, n)
 | |
| 	case *ast.AnchorNode:
 | |
| 		return r.renderAnchorNode(graph, n)
 | |
| 	case *ast.AliasNode:
 | |
| 		return r.renderAliasNode(graph, n)
 | |
| 	case *ast.DirectiveNode:
 | |
| 		return r.renderDirectiveNode(graph, n)
 | |
| 	case *ast.TagNode:
 | |
| 		return r.renderTagNode(graph, n)
 | |
| 	case *ast.CommentNode:
 | |
| 	case *ast.CommentGroupNode:
 | |
| 	}
 | |
| 	return nil, fmt.Errorf("unexpected node type %T", node)
 | |
| }
 | |
| 
 | |
| func (r *NodeRenderer) renderMappingNode(graph *graphviz.Graph, node *ast.MappingNode) (*graphviz.Graph, error) {
 | |
| 	mapGraph, err := r.createNodeGraph(graph, node, "MappingNode")
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	mapGraph.SetBackgroundColor("honeydew")
 | |
| 	if err := r.renderPath(mapGraph, node.GetPath()); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if err := r.renderToken(mapGraph, node.Start); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if err := r.renderToken(mapGraph, node.End); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if _, err := r.renderCommentGroupNode(mapGraph, node.GetComment(), yaml.CommentHeadPosition); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if _, err := r.renderCommentGroupNode(mapGraph, node.FootComment, yaml.CommentFootPosition); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	for idx, value := range node.Values {
 | |
| 		node, err := r.createNode(mapGraph, fmt.Sprintf("values[%d]", idx))
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 		valueGraph, err := r.renderMappingValueNode(mapGraph, value)
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 		if err := r.createEdge(mapGraph, node, valueGraph); err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 	}
 | |
| 	return mapGraph, nil
 | |
| }
 | |
| 
 | |
| func (r *NodeRenderer) renderMappingValueNode(graph *graphviz.Graph, node *ast.MappingValueNode) (*graphviz.Graph, error) {
 | |
| 	valueGraph, err := r.createNodeGraph(graph, node, "MappingValueNode")
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	valueGraph.SetBackgroundColor("seashell")
 | |
| 	if err := r.renderPath(valueGraph, node.GetPath()); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if err := r.renderToken(valueGraph, node.Start); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if _, err := r.renderCommentGroupNode(valueGraph, node.GetComment(), yaml.CommentHeadPosition); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if _, err := r.renderCommentGroupNode(valueGraph, node.FootComment, yaml.CommentFootPosition); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	keyNode, err := r.createNode(valueGraph, "key")
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	valueNode, err := r.createNode(valueGraph, "value")
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	keyGraph, err := r.renderNode(valueGraph, node.Key)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	valueContentGraph, err := r.renderNode(valueGraph, node.Value)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if err := r.createEdge(valueGraph, keyNode, keyGraph); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if err := r.createEdge(valueGraph, valueNode, valueContentGraph); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return valueGraph, nil
 | |
| }
 | |
| 
 | |
| func (r *NodeRenderer) renderStringNode(graph *graphviz.Graph, n *ast.StringNode) (*graphviz.Graph, error) {
 | |
| 	subGraph, err := r.createNodeGraph(graph, n, "StringNode")
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	subGraph.SetBackgroundColor("lavenderblush")
 | |
| 	if err := r.renderPath(subGraph, n.GetPath()); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if err := r.renderToken(subGraph, n.Token); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if _, err := r.renderCommentGroupNode(subGraph, n.GetComment(), yaml.CommentLinePosition); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return subGraph, nil
 | |
| }
 | |
| 
 | |
| func (r *NodeRenderer) renderNullNode(graph *graphviz.Graph, n *ast.NullNode) (*graphviz.Graph, error) {
 | |
| 	subGraph, err := r.createNodeGraph(graph, n, "NullNode")
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	subGraph.SetBackgroundColor("lavenderblush")
 | |
| 	if err := r.renderPath(subGraph, n.GetPath()); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if _, err := r.renderCommentGroupNode(subGraph, n.GetComment(), yaml.CommentLinePosition); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if _, err := r.createNode(subGraph, "null"); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return subGraph, nil
 | |
| }
 | |
| 
 | |
| func (r *NodeRenderer) renderIntegerNode(graph *graphviz.Graph, n *ast.IntegerNode) (*graphviz.Graph, error) {
 | |
| 	subGraph, err := r.createNodeGraph(graph, n, "IntegerNode")
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	subGraph.SetBackgroundColor("lavenderblush")
 | |
| 	if err := r.renderPath(subGraph, n.GetPath()); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if _, err := r.renderCommentGroupNode(subGraph, n.GetComment(), yaml.CommentLinePosition); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if _, err := r.createNode(subGraph, n.Token.Value); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return subGraph, nil
 | |
| }
 | |
| 
 | |
| func (r *NodeRenderer) renderFloatNode(graph *graphviz.Graph, n *ast.FloatNode) (*graphviz.Graph, error) {
 | |
| 	subGraph, err := r.createNodeGraph(graph, n, "FloatNode")
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	subGraph.SetBackgroundColor("lavenderblush")
 | |
| 	if err := r.renderPath(subGraph, n.GetPath()); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if _, err := r.createNode(subGraph, n.Token.Value); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return subGraph, nil
 | |
| }
 | |
| 
 | |
| func (r *NodeRenderer) renderLiteralNode(graph *graphviz.Graph, n *ast.LiteralNode) (*graphviz.Graph, error) {
 | |
| 	subGraph, err := r.createNodeGraph(graph, n, "LiteralNode")
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	subGraph.SetBackgroundColor("beige")
 | |
| 	if err := r.renderPath(subGraph, n.GetPath()); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if _, err := r.renderCommentGroupNode(subGraph, n.GetComment(), yaml.CommentLinePosition); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	value, err := r.createNode(subGraph, "value")
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	strGraph, err := r.renderStringNode(subGraph, n.Value)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if err := r.createEdge(subGraph, value, strGraph); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return subGraph, nil
 | |
| }
 | |
| 
 | |
| func (r *NodeRenderer) renderMergeKeyNode(graph *graphviz.Graph, n *ast.MergeKeyNode) (*graphviz.Graph, error) {
 | |
| 	subGraph, err := r.createNodeGraph(graph, n, "MergeKeyNode")
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	subGraph.SetBackgroundColor("cornsilk")
 | |
| 	if err := r.renderPath(subGraph, n.GetPath()); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if _, err := r.renderCommentGroupNode(subGraph, n.GetComment(), yaml.CommentHeadPosition); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if _, err := r.createNode(subGraph, n.Token.Value); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return subGraph, nil
 | |
| }
 | |
| 
 | |
| func (r *NodeRenderer) renderBoolNode(graph *graphviz.Graph, n *ast.BoolNode) (*graphviz.Graph, error) {
 | |
| 	subGraph, err := r.createNodeGraph(graph, n, "BoolNode")
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	subGraph.SetBackgroundColor("lavenderblush")
 | |
| 	if err := r.renderPath(subGraph, n.GetPath()); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if _, err := r.renderCommentGroupNode(subGraph, n.GetComment(), yaml.CommentLinePosition); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if _, err := r.createNode(subGraph, n.Token.Value); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return subGraph, nil
 | |
| }
 | |
| 
 | |
| func (r *NodeRenderer) renderInfinityNode(graph *graphviz.Graph, n *ast.InfinityNode) (*graphviz.Graph, error) {
 | |
| 	subGraph, err := r.createNodeGraph(graph, n, "InfinityNode")
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	subGraph.SetBackgroundColor("lavenderblush")
 | |
| 	if err := r.renderPath(subGraph, n.GetPath()); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if _, err := r.renderCommentGroupNode(subGraph, n.GetComment(), yaml.CommentLinePosition); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if _, err := r.createNode(subGraph, n.Token.Value); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return subGraph, nil
 | |
| }
 | |
| 
 | |
| func (r *NodeRenderer) renderNaNNode(graph *graphviz.Graph, n *ast.NanNode) (*graphviz.Graph, error) {
 | |
| 	subGraph, err := r.createNodeGraph(graph, n, "NaNNode")
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	subGraph.SetBackgroundColor("lavenderblush")
 | |
| 	if err := r.renderPath(subGraph, n.GetPath()); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if _, err := r.renderCommentGroupNode(subGraph, n.GetComment(), yaml.CommentLinePosition); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if _, err := r.createNode(subGraph, n.Token.Value); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return subGraph, nil
 | |
| }
 | |
| 
 | |
| func (r *NodeRenderer) renderMappingKeyNode(graph *graphviz.Graph, n *ast.MappingKeyNode) (*graphviz.Graph, error) {
 | |
| 	subGraph, err := r.createNodeGraph(graph, n, "MappingKeyNode")
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	subGraph.SetBackgroundColor("cornsilk")
 | |
| 	if err := r.renderPath(subGraph, n.GetPath()); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if _, err := r.renderCommentGroupNode(subGraph, n.GetComment(), yaml.CommentHeadPosition); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	value, err := r.createNode(subGraph, "value")
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	valueGraph, err := r.renderNode(subGraph, n.Value)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if err := r.createEdge(subGraph, value, valueGraph); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return subGraph, nil
 | |
| }
 | |
| 
 | |
| func (r *NodeRenderer) renderSequenceNode(graph *graphviz.Graph, n *ast.SequenceNode) (*graphviz.Graph, error) {
 | |
| 	subGraph, err := r.createNodeGraph(graph, n, "SequenceNode")
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	subGraph.SetBackgroundColor("honeydew")
 | |
| 	if err := r.renderPath(subGraph, n.GetPath()); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if err := r.renderToken(subGraph, n.Start); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if err := r.renderToken(subGraph, n.End); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	for _, head := range n.ValueHeadComments {
 | |
| 		if _, err := r.renderCommentGroupNode(subGraph, head, yaml.CommentHeadPosition); err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 	}
 | |
| 	if _, err := r.renderCommentGroupNode(subGraph, n.FootComment, yaml.CommentFootPosition); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	for idx, value := range n.Values {
 | |
| 		node, err := r.createNode(subGraph, fmt.Sprintf("values[%d]", idx))
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 		valueGraph, err := r.renderNode(subGraph, value)
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 		if err := r.createEdge(subGraph, node, valueGraph); err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 	}
 | |
| 	return subGraph, nil
 | |
| }
 | |
| 
 | |
| func (r *NodeRenderer) renderAnchorNode(graph *graphviz.Graph, n *ast.AnchorNode) (*graphviz.Graph, error) {
 | |
| 	subGraph, err := r.createNodeGraph(graph, n, "AnchorNode")
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	subGraph.SetBackgroundColor("oldlace")
 | |
| 	if err := r.renderPath(subGraph, n.GetPath()); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if _, err := r.renderCommentGroupNode(subGraph, n.GetComment(), yaml.CommentLinePosition); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if err := r.renderToken(subGraph, n.Start); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	name, err := r.createNode(subGraph, "name")
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	value, err := r.createNode(subGraph, "value")
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	nameGraph, err := r.renderNode(subGraph, n.Name)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	valueGraph, err := r.renderNode(subGraph, n.Value)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if err := r.createEdge(subGraph, name, nameGraph); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if err := r.createEdge(subGraph, value, valueGraph); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return subGraph, nil
 | |
| }
 | |
| 
 | |
| func (r *NodeRenderer) renderAliasNode(graph *graphviz.Graph, n *ast.AliasNode) (*graphviz.Graph, error) {
 | |
| 	subGraph, err := r.createNodeGraph(graph, n, "AliasNode")
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	subGraph.SetBackgroundColor("lavenderblush")
 | |
| 	if err := r.renderPath(subGraph, n.GetPath()); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if _, err := r.renderCommentGroupNode(subGraph, n.GetComment(), yaml.CommentLinePosition); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if err := r.renderToken(subGraph, n.Start); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	value, err := r.createNode(subGraph, "value")
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	valueGraph, err := r.renderNode(subGraph, n.Value)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if err := r.createEdge(subGraph, value, valueGraph); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return subGraph, nil
 | |
| }
 | |
| 
 | |
| func (r *NodeRenderer) renderDirectiveNode(graph *graphviz.Graph, n *ast.DirectiveNode) (*graphviz.Graph, error) {
 | |
| 	subGraph, err := r.createNodeGraph(graph, n, "DirectiveNode")
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	subGraph.SetBackgroundColor("snow")
 | |
| 	if err := r.renderToken(subGraph, n.Start); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if _, err := r.renderCommentGroupNode(subGraph, n.GetComment(), yaml.CommentLinePosition); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	name, err := r.createNode(subGraph, "name")
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	nameGraph, err := r.renderNode(subGraph, n.Name)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if err := r.createEdge(subGraph, name, nameGraph); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	for idx, value := range n.Values {
 | |
| 		val, err := r.createNode(subGraph, fmt.Sprintf("values[%d]", idx))
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 		valGraph, err := r.renderNode(subGraph, value)
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 		if err := r.createEdge(subGraph, val, valGraph); err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 	}
 | |
| 	return subGraph, nil
 | |
| }
 | |
| 
 | |
| func (r *NodeRenderer) renderTagNode(graph *graphviz.Graph, n *ast.TagNode) (*graphviz.Graph, error) {
 | |
| 	subGraph, err := r.createNodeGraph(graph, n, "TagNode")
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	subGraph.SetBackgroundColor("ghostwhite")
 | |
| 	if err := r.renderPath(subGraph, n.GetPath()); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if _, err := r.renderCommentGroupNode(subGraph, n.GetComment(), yaml.CommentLinePosition); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if err := r.renderToken(subGraph, n.Start); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	value, err := r.createNode(subGraph, "value")
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	valueGraph, err := r.renderNode(subGraph, n.Value)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if err := r.createEdge(subGraph, value, valueGraph); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return subGraph, nil
 | |
| }
 | |
| 
 | |
| func (r *NodeRenderer) renderCommentGroupNode(graph *graphviz.Graph, n *ast.CommentGroupNode, pos yaml.CommentPosition) (*graphviz.Graph, error) {
 | |
| 	if n == nil {
 | |
| 		return nil, nil
 | |
| 	}
 | |
| 	subGraph, err := r.createNodeGraph(graph, n, fmt.Sprintf("CommentGroupNode (%s)", pos))
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	subGraph.SetBackgroundColor("whitesmoke")
 | |
| 	for _, cm := range n.Comments {
 | |
| 		if err := r.renderToken(subGraph, cm.Token); err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 	}
 | |
| 	return subGraph, nil
 | |
| }
 | |
| 
 | |
| func (r *NodeRenderer) renderPath(graph *graphviz.Graph, p string) error {
 | |
| 	node, err := graph.CreateNodeByName(r.createID())
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	node.SetLabel(fmt.Sprintf("{path|%s}", p))
 | |
| 	node.SetShape("record")
 | |
| 	node.SetStyle(graphviz.FilledNodeStyle)
 | |
| 	node.SetFillColor("white")
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (r *NodeRenderer) renderToken(graph *graphviz.Graph, tk *token.Token) error {
 | |
| 	if tk == nil {
 | |
| 		return nil
 | |
| 	}
 | |
| 	node, err := graph.CreateNodeByName(r.createID())
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	pos := tk.Position
 | |
| 	node.SetLabel(fmt.Sprintf("{pos|%d:%d}|{value|%s}", pos.Line, pos.Column, tk.Value))
 | |
| 	node.SetShape("record")
 | |
| 	node.SetStyle(graphviz.FilledNodeStyle)
 | |
| 	node.SetFillColor("white")
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func main() {
 | |
| 	js.Global().Set("decode", js.FuncOf(decode))
 | |
| 	js.Global().Set("tokenize", js.FuncOf(tokenize))
 | |
| 	js.Global().Set("parseGroup", js.FuncOf(parseGroup))
 | |
| 	js.Global().Set("parse", js.FuncOf(parse))
 | |
| 
 | |
| 	<-make(chan struct{})
 | |
| }
 | 
