apply to edges

This commit is contained in:
Alexander Wang 2024-11-24 10:45:06 -08:00
parent e5e02613b1
commit 7ea3aa2737
No known key found for this signature in database
GPG key ID: D89FA31966BDBECE
10 changed files with 957 additions and 121 deletions

View file

@ -1065,9 +1065,17 @@ func MakeKeyPath(a []string) *KeyPath {
return kp
}
func (kp *KeyPath) IDA() (ida []string) {
func MakeKeyPathString(a []String) *KeyPath {
kp := &KeyPath{}
for _, el := range a {
kp.Path = append(kp.Path, MakeValueBox(RawString(el.ScalarString(), true)).StringBox())
}
return kp
}
func (kp *KeyPath) IDA() (ida []String) {
for _, el := range kp.Path {
ida = append(ida, el.Unbox().ScalarString())
ida = append(ida, el.Unbox())
}
return ida
}
@ -1578,9 +1586,9 @@ func (s *Substitution) IDA() (ida []string) {
return ida
}
func (i *Import) IDA() (ida []string) {
func (i *Import) IDA() (ida []String) {
for _, el := range i.Path[1:] {
ida = append(ida, el.Unbox().ScalarString())
ida = append(ida, el.Unbox())
}
return ida
}

View file

@ -110,7 +110,7 @@ func (c *compiler) compileBoard(g *d2graph.Graph, ir *d2ir.Map) *d2graph.Graph {
}
func (c *compiler) compileBoardsField(g *d2graph.Graph, ir *d2ir.Map, fieldName string) {
boards := ir.GetField(fieldName)
boards := ir.GetField(d2ast.FlatUnquotedString(fieldName))
if boards.Map() == nil {
return
}
@ -224,7 +224,7 @@ func (c *compiler) errorf(n d2ast.Node, f string, v ...interface{}) {
}
func (c *compiler) compileMap(obj *d2graph.Object, m *d2ir.Map) {
class := m.GetField("class")
class := m.GetField(d2ast.FlatUnquotedString("class"))
if class != nil {
var classNames []string
if class.Primary() != nil {
@ -265,7 +265,7 @@ func (c *compiler) compileMap(obj *d2graph.Object, m *d2ir.Map) {
}
}
}
shape := m.GetField("shape")
shape := m.GetField(d2ast.FlatUnquotedString("shape"))
if shape != nil {
if shape.Composite != nil {
c.errorf(shape.LastPrimaryKey(), "reserved field shape does not accept composite")
@ -388,7 +388,7 @@ func (c *compiler) compileField(obj *d2graph.Object, f *d2ir.Field) {
IsVar: d2ir.IsVar(fr.Context_.ScopeMap),
}
if fr.Context_.ScopeMap != nil && !d2ir.IsVar(fr.Context_.ScopeMap) {
scopeObjIDA := d2graphIDA(d2ir.BoardIDA(fr.Context_.ScopeMap))
scopeObjIDA := d2ir.BoardIDA(fr.Context_.ScopeMap)
r.ScopeObj = obj.Graph.Root.EnsureChild(scopeObjIDA)
}
obj.References = append(obj.References, r)
@ -766,7 +766,7 @@ func compileStyleFieldInit(attrs *d2graph.Attributes, f *d2ir.Field) {
}
func (c *compiler) compileEdge(obj *d2graph.Object, e *d2ir.Edge) {
edge, err := obj.Connect(d2graphIDA(e.ID.SrcPath), d2graphIDA(e.ID.DstPath), e.ID.SrcArrow, e.ID.DstArrow, "")
edge, err := obj.Connect(e.ID.SrcPath, e.ID.DstPath, e.ID.SrcArrow, e.ID.DstArrow, "")
if err != nil {
c.errorf(e.References[0].AST(), err.Error())
return
@ -790,7 +790,7 @@ func (c *compiler) compileEdge(obj *d2graph.Object, e *d2ir.Edge) {
ScopeObj: obj,
}
if er.Context_.ScopeMap != nil && !d2ir.IsVar(er.Context_.ScopeMap) {
scopeObjIDA := d2graphIDA(d2ir.BoardIDA(er.Context_.ScopeMap))
scopeObjIDA := d2ir.BoardIDA(er.Context_.ScopeMap)
r.ScopeObj = edge.Src.Graph.Root.EnsureChild(scopeObjIDA)
}
edge.References = append(edge.References, r)
@ -798,7 +798,7 @@ func (c *compiler) compileEdge(obj *d2graph.Object, e *d2ir.Edge) {
}
func (c *compiler) compileEdgeMap(edge *d2graph.Edge, m *d2ir.Map) {
class := m.GetField("class")
class := m.GetField(d2ast.FlatUnquotedString("class"))
if class != nil {
var classNames []string
if class.Primary() != nil {
@ -1230,7 +1230,11 @@ func (c *compiler) validateBoardLinks(g *d2graph.Graph) {
continue
}
if slices.Equal(linkKey.IDA(), obj.Graph.IDA()) {
formattedIDA := []string{}
for _, id := range linkKey.IDA() {
formattedIDA = append(formattedIDA, id.ScalarString())
}
if slices.Equal(formattedIDA, obj.Graph.IDA()) {
obj.Link = nil
continue
}
@ -1246,34 +1250,34 @@ func (c *compiler) validateBoardLinks(g *d2graph.Graph) {
}
}
func hasBoard(root *d2graph.Graph, ida []string) bool {
func hasBoard(root *d2graph.Graph, ida []d2ast.String) bool {
if len(ida) == 0 {
return true
}
if ida[0] == "root" {
if ida[0].ScalarString() == "root" && ida[0].IsUnquoted() {
return hasBoard(root, ida[1:])
}
id := ida[0]
if len(ida) == 1 {
return root.Name == id
return root.Name == id.ScalarString()
}
nextID := ida[1]
switch id {
switch id.ScalarString() {
case "layers":
for _, b := range root.Layers {
if b.Name == nextID {
if b.Name == nextID.ScalarString() {
return hasBoard(b, ida[2:])
}
}
case "scenarios":
for _, b := range root.Scenarios {
if b.Name == nextID {
if b.Name == nextID.ScalarString() {
return hasBoard(b, ida[2:])
}
}
case "steps":
for _, b := range root.Steps {
if b.Name == nextID {
if b.Name == nextID.ScalarString() {
return hasBoard(b, ida[2:])
}
}
@ -1288,13 +1292,6 @@ func init() {
}
}
func d2graphIDA(irIDA []string) (ida []d2ast.String) {
for _, el := range irIDA {
ida = append(ida, d2ast.RawString(el, true))
}
return ida
}
// Unused for now until shape: edge_group
func (c *compiler) preprocessSeqDiagrams(m *d2ir.Map) {
for _, f := range m.Fields {
@ -1350,8 +1347,8 @@ func (c *compiler) preprocessEdgeGroup(seqDiagram, m *d2ir.Map) {
f := srcParent.GetField(el)
if !isEdgeGroup(f) {
for j := 0; j < i+1; j++ {
e.ID.SrcPath = append([]string{"_"}, e.ID.SrcPath...)
e.ID.DstPath = append([]string{"_"}, e.ID.DstPath...)
e.ID.SrcPath = append([]d2ast.String{d2ast.FlatUnquotedString("_")}, e.ID.SrcPath...)
e.ID.DstPath = append([]d2ast.String{d2ast.FlatUnquotedString("_")}, e.ID.DstPath...)
}
break
}
@ -1361,7 +1358,7 @@ func (c *compiler) preprocessEdgeGroup(seqDiagram, m *d2ir.Map) {
}
func hoistActor(seqDiagram *d2ir.Map, f *d2ir.Field) {
f2 := seqDiagram.GetField(f.Name.ScalarString())
f2 := seqDiagram.GetField(f.Name)
if f2 == nil {
seqDiagram.Fields = append(seqDiagram.Fields, f.Copy(seqDiagram).(*d2ir.Field))
} else {
@ -1420,7 +1417,7 @@ func parentSeqDiagram(n d2ir.Node) *d2ir.Map {
}
func compileConfig(ir *d2ir.Map) (*d2target.Config, error) {
f := ir.GetField("vars", "d2-config")
f := ir.GetField(d2ast.FlatUnquotedString("vars"), d2ast.FlatUnquotedString("d2-config"))
if f == nil || f.Map() == nil {
return nil, nil
}
@ -1429,36 +1426,36 @@ func compileConfig(ir *d2ir.Map) (*d2target.Config, error) {
config := &d2target.Config{}
f = configMap.GetField("sketch")
f = configMap.GetField(d2ast.FlatUnquotedString("sketch"))
if f != nil {
val, _ := strconv.ParseBool(f.Primary().Value.ScalarString())
config.Sketch = &val
}
f = configMap.GetField("theme-id")
f = configMap.GetField(d2ast.FlatUnquotedString("theme-id"))
if f != nil {
val, _ := strconv.Atoi(f.Primary().Value.ScalarString())
config.ThemeID = go2.Pointer(int64(val))
}
f = configMap.GetField("dark-theme-id")
f = configMap.GetField(d2ast.FlatUnquotedString("dark-theme-id"))
if f != nil {
val, _ := strconv.Atoi(f.Primary().Value.ScalarString())
config.DarkThemeID = go2.Pointer(int64(val))
}
f = configMap.GetField("pad")
f = configMap.GetField(d2ast.FlatUnquotedString("pad"))
if f != nil {
val, _ := strconv.Atoi(f.Primary().Value.ScalarString())
config.Pad = go2.Pointer(int64(val))
}
f = configMap.GetField("layout-engine")
f = configMap.GetField(d2ast.FlatUnquotedString("layout-engine"))
if f != nil {
config.LayoutEngine = go2.Pointer(f.Primary().Value.ScalarString())
}
f = configMap.GetField("theme-overrides")
f = configMap.GetField(d2ast.FlatUnquotedString("theme-overrides"))
if f != nil {
overrides, err := compileThemeOverrides(f.Map())
if err != nil {
@ -1466,7 +1463,7 @@ func compileConfig(ir *d2ir.Map) (*d2target.Config, error) {
}
config.ThemeOverrides = overrides
}
f = configMap.GetField("dark-theme-overrides")
f = configMap.GetField(d2ast.FlatUnquotedString("dark-theme-overrides"))
if f != nil {
overrides, err := compileThemeOverrides(f.Map())
if err != nil {
@ -1474,7 +1471,7 @@ func compileConfig(ir *d2ir.Map) (*d2target.Config, error) {
}
config.DarkThemeOverrides = overrides
}
f = configMap.GetField("data")
f = configMap.GetField(d2ast.FlatUnquotedString("data"))
if f != nil && f.Map() != nil {
config.Data = make(map[string]interface{})
for _, f := range f.Map().Fields {

View file

@ -88,12 +88,12 @@ func Compile(ast *d2ast.Map, opts *CompileOptions) (*Map, []string, error) {
}
func (c *compiler) overlayClasses(m *Map) {
classes := m.GetField("classes")
classes := m.GetField(d2ast.FlatUnquotedString("classes"))
if classes == nil || classes.Map() == nil {
return
}
layersField := m.GetField("layers")
layersField := m.GetField(d2ast.FlatUnquotedString("layers"))
if layersField == nil {
return
}
@ -108,7 +108,7 @@ func (c *compiler) overlayClasses(m *Map) {
continue
}
l := lf.Map()
lClasses := l.GetField("classes")
lClasses := l.GetField(d2ast.FlatUnquotedString("classes"))
if lClasses == nil {
lClasses = classes.Copy(l).(*Field)
@ -153,7 +153,7 @@ func (c *compiler) compileSubstitutions(m *Map, varsStack []*Map) {
} else if f.Map() != nil {
if f.Name != nil && f.Name.ScalarString() == "vars" && f.Name.IsUnquoted() {
c.compileSubstitutions(f.Map(), varsStack)
c.validateConfigs(f.Map().GetField("d2-config"))
c.validateConfigs(f.Map().GetField(d2ast.FlatUnquotedString("d2-config")))
} else {
c.compileSubstitutions(f.Map(), varsStack)
}
@ -381,7 +381,7 @@ func (c *compiler) resolveSubstitution(vars *Map, node Node, substitution *d2ast
parent := ParentField(node)
for i, p := range substitution.Path {
f := vars.GetField(p.Unbox().ScalarString())
f := vars.GetField(p.Unbox())
if f == nil {
return nil
}
@ -445,7 +445,7 @@ func (g *globContext) copyApplied(from *globContext) {
func (g *globContext) prefixed(dst *Map) *globContext {
g2 := g.copy()
prefix := d2ast.MakeKeyPath(RelIDA(g2.refctx.ScopeMap, dst))
prefix := d2ast.MakeKeyPathString(RelIDA(g2.refctx.ScopeMap, dst))
g2.refctx.Key = g2.refctx.Key.Copy()
if g2.refctx.Key.Key != nil {
prefix.Path = append(prefix.Path, g2.refctx.Key.Key.Path...)
@ -483,9 +483,9 @@ func (c *compiler) ampersandFilterMap(dst *Map, ast, scopeAST *d2ast.Map) bool {
}
var ks string
if gctx.refctx.Key.HasMultiGlob() {
ks = d2format.Format(d2ast.MakeKeyPath(IDA(dst)))
ks = d2format.Format(d2ast.MakeKeyPathString(IDA(dst)))
} else {
ks = d2format.Format(d2ast.MakeKeyPath(BoardIDA(dst)))
ks = d2format.Format(d2ast.MakeKeyPathString(BoardIDA(dst)))
}
delete(gctx.appliedFields, ks)
delete(gctx.appliedEdges, ks)
@ -992,11 +992,11 @@ func (c *compiler) extendLinks(m *Map, importF *Field, importDir string) {
}
for _, id := range linkIDA[1:] {
if id == "_" {
if id.ScalarString() == "_" && id.IsUnquoted() {
if len(linkIDA) < 2 || len(importIDA) < 2 {
break
}
linkIDA = append([]string{linkIDA[0]}, linkIDA[2:]...)
linkIDA = append([]d2ast.String{linkIDA[0]}, linkIDA[2:]...)
importIDA = importIDA[:len(importIDA)-2]
} else {
break
@ -1004,7 +1004,7 @@ func (c *compiler) extendLinks(m *Map, importF *Field, importDir string) {
}
extendedIDA := append(importIDA, linkIDA[1:]...)
kp := d2ast.MakeKeyPath(extendedIDA)
kp := d2ast.MakeKeyPathString(extendedIDA)
s := d2format.Format(kp)
f.Primary_.Value = d2ast.MakeValueBox(d2ast.FlatUnquotedString(s)).ScalarBox().Unbox()
}
@ -1046,30 +1046,34 @@ func (c *compiler) compileLink(f *Field, refctx *RefContext) {
return
}
if linkIDA[0] == "root" {
if linkIDA[0].ScalarString() == "root" && linkIDA[0].IsUnquoted() {
c.errorf(refctx.Key.Key, "cannot refer to root in link")
return
}
if !linkIDA[0].IsUnquoted() {
return
}
// If it doesn't start with one of these reserved words, the link is definitely not a board link.
if !strings.EqualFold(linkIDA[0], "layers") && !strings.EqualFold(linkIDA[0], "scenarios") && !strings.EqualFold(linkIDA[0], "steps") && linkIDA[0] != "_" {
if !strings.EqualFold(linkIDA[0].ScalarString(), "layers") && !strings.EqualFold(linkIDA[0].ScalarString(), "scenarios") && !strings.EqualFold(linkIDA[0].ScalarString(), "steps") && linkIDA[0].ScalarString() != "_" {
return
}
// Chop off the non-board portion of the scope, like if this is being defined on a nested object (e.g. `x.y.z`)
for i := len(scopeIDA) - 1; i > 0; i-- {
if strings.EqualFold(scopeIDA[i-1], "layers") || strings.EqualFold(scopeIDA[i-1], "scenarios") || strings.EqualFold(scopeIDA[i-1], "steps") {
if scopeIDA[i-1].IsUnquoted() && (strings.EqualFold(scopeIDA[i-1].ScalarString(), "layers") || strings.EqualFold(scopeIDA[i-1].ScalarString(), "scenarios") || strings.EqualFold(scopeIDA[i-1].ScalarString(), "steps")) {
scopeIDA = scopeIDA[:i+1]
break
}
if scopeIDA[i-1] == "root" {
if scopeIDA[i-1].ScalarString() == "root" && scopeIDA[i-1].IsUnquoted() {
scopeIDA = scopeIDA[:i]
break
}
}
// Resolve underscores
for len(linkIDA) > 0 && linkIDA[0] == "_" {
for len(linkIDA) > 0 && linkIDA[0].ScalarString() == "_" && linkIDA[0].IsUnquoted() {
if len(scopeIDA) < 2 {
// Leave the underscore. It will fail in compiler as a standalone board,
// but if imported, will get further resolved in extendLinks
@ -1080,12 +1084,12 @@ func (c *compiler) compileLink(f *Field, refctx *RefContext) {
linkIDA = linkIDA[1:]
}
if len(scopeIDA) == 0 {
scopeIDA = []string{"root"}
scopeIDA = []d2ast.String{d2ast.FlatUnquotedString("root")}
}
// Create the absolute path by appending scope path with value specified
scopeIDA = append(scopeIDA, linkIDA...)
kp := d2ast.MakeKeyPath(scopeIDA)
kp := d2ast.MakeKeyPathString(scopeIDA)
f.Primary_.Value = d2ast.FlatUnquotedString(d2format.Format(kp))
}

View file

@ -377,11 +377,11 @@ func (f *Field) LastRef() Reference {
}
type EdgeID struct {
SrcPath []string `json:"src_path"`
SrcArrow bool `json:"src_arrow"`
SrcPath []d2ast.String `json:"src_path"`
SrcArrow bool `json:"src_arrow"`
DstPath []string `json:"dst_path"`
DstArrow bool `json:"dst_arrow"`
DstPath []d2ast.String `json:"dst_path"`
DstArrow bool `json:"dst_arrow"`
// If nil, then any EdgeID with equal src/dst/arrows matches.
Index *int `json:"index"`
@ -409,8 +409,8 @@ func (eid *EdgeID) Copy() *EdgeID {
tmp := *eid
eid = &tmp
eid.SrcPath = append([]string(nil), eid.SrcPath...)
eid.DstPath = append([]string(nil), eid.DstPath...)
eid.SrcPath = append([]d2ast.String(nil), eid.SrcPath...)
eid.DstPath = append([]d2ast.String(nil), eid.DstPath...)
return eid
}
@ -428,7 +428,7 @@ func (eid *EdgeID) Match(eid2 *EdgeID) bool {
return false
}
for i, s := range eid.SrcPath {
if !strings.EqualFold(s, eid2.SrcPath[i]) {
if !strings.EqualFold(s.ScalarString(), eid2.SrcPath[i].ScalarString()) {
return false
}
}
@ -440,7 +440,7 @@ func (eid *EdgeID) Match(eid2 *EdgeID) bool {
return false
}
for i, s := range eid.DstPath {
if !strings.EqualFold(s, eid2.DstPath[i]) {
if !strings.EqualFold(s.ScalarString(), eid2.DstPath[i].ScalarString()) {
return false
}
}
@ -450,21 +450,21 @@ func (eid *EdgeID) Match(eid2 *EdgeID) bool {
// resolve resolves both underscores and commons in eid.
// It returns the new eid, containing map adjusted for underscores and common ida.
func (eid *EdgeID) resolve(m *Map) (_ *EdgeID, _ *Map, common []string, _ error) {
func (eid *EdgeID) resolve(m *Map) (_ *EdgeID, _ *Map, common []d2ast.String, _ error) {
eid = eid.Copy()
maxUnderscores := go2.Max(countUnderscores(eid.SrcPath), countUnderscores(eid.DstPath))
for i := 0; i < maxUnderscores; i++ {
if eid.SrcPath[0] == "_" {
if eid.SrcPath[0].ScalarString() == "_" && eid.SrcPath[0].IsUnquoted() {
eid.SrcPath = eid.SrcPath[1:]
} else {
mf := ParentField(m)
eid.SrcPath = append([]string{mf.Name.ScalarString()}, eid.SrcPath...)
eid.SrcPath = append([]d2ast.String{mf.Name}, eid.SrcPath...)
}
if eid.DstPath[0] == "_" {
if eid.DstPath[0].ScalarString() == "_" && eid.DstPath[0].IsUnquoted() {
eid.DstPath = eid.DstPath[1:]
} else {
mf := ParentField(m)
eid.DstPath = append([]string{mf.Name.ScalarString()}, eid.DstPath...)
eid.DstPath = append([]d2ast.String{mf.Name}, eid.DstPath...)
}
m = ParentMap(m)
if m == nil {
@ -473,7 +473,7 @@ func (eid *EdgeID) resolve(m *Map) (_ *EdgeID, _ *Map, common []string, _ error)
}
for len(eid.SrcPath) > 1 && len(eid.DstPath) > 1 {
if !strings.EqualFold(eid.SrcPath[0], eid.DstPath[0]) || strings.Contains(eid.SrcPath[0], "*") {
if !strings.EqualFold(eid.SrcPath[0].ScalarString(), eid.DstPath[0].ScalarString()) || strings.Contains(eid.SrcPath[0].ScalarString(), "*") {
return eid, m, common, nil
}
common = append(common, eid.SrcPath[0])
@ -702,9 +702,9 @@ func (m *Map) EdgeCountRecursive() int {
func (m *Map) GetClassMap(name string) *Map {
root := RootMap(m)
classes := root.Map().GetField("classes")
classes := root.Map().GetField(d2ast.FlatUnquotedString("classes"))
if classes != nil && classes.Map() != nil {
class := classes.Map().GetField(name)
class := classes.Map().GetField(d2ast.FlatUnquotedString(name))
if class != nil && class.Map() != nil {
return class.Map()
}
@ -712,8 +712,8 @@ func (m *Map) GetClassMap(name string) *Map {
return nil
}
func (m *Map) GetField(ida ...string) *Field {
for len(ida) > 0 && ida[0] == "_" {
func (m *Map) GetField(ida ...d2ast.String) *Field {
for len(ida) > 0 && ida[0].ScalarString() == "_" && ida[0].IsUnquoted() {
m = ParentMap(m)
if m == nil {
return nil
@ -722,7 +722,7 @@ func (m *Map) GetField(ida ...string) *Field {
return m.getField(ida)
}
func (m *Map) getField(ida []string) *Field {
func (m *Map) getField(ida []d2ast.String) *Field {
if len(ida) == 0 {
return nil
}
@ -730,7 +730,7 @@ func (m *Map) getField(ida []string) *Field {
s := ida[0]
rest := ida[1:]
if s == "_" {
if s.ScalarString() == "_" && s.IsUnquoted() {
return nil
}
@ -738,7 +738,10 @@ func (m *Map) getField(ida []string) *Field {
if f.Name == nil {
continue
}
if !strings.EqualFold(f.Name.ScalarString(), s) {
if !strings.EqualFold(f.Name.ScalarString(), s.ScalarString()) {
continue
}
if f.Name.IsUnquoted() != s.IsUnquoted() {
continue
}
if len(rest) == 0 {
@ -788,9 +791,9 @@ func (m *Map) ensureField(i int, kp *d2ast.KeyPath, refctx *RefContext, create b
if gctx != nil {
var ks string
if refctx.Key.HasMultiGlob() {
ks = d2format.Format(d2ast.MakeKeyPath(IDA(f)))
ks = d2format.Format(d2ast.MakeKeyPathString(IDA(f)))
} else {
ks = d2format.Format(d2ast.MakeKeyPath(BoardIDA(f)))
ks = d2format.Format(d2ast.MakeKeyPathString(BoardIDA(f)))
}
if !kp.HasGlob() {
if !passthrough {
@ -887,7 +890,7 @@ func (m *Map) ensureField(i int, kp *d2ast.KeyPath, refctx *RefContext, create b
return d2parser.Errorf(kp.Path[i].Unbox(), "%s is only allowed at a board root", headString)
}
if findBoardKeyword(headString) != -1 && head.IsUnquoted() && NodeBoardKind(m) == "" {
if findBoardKeyword(head) != -1 && head.IsUnquoted() && NodeBoardKind(m) == "" {
return d2parser.Errorf(kp.Path[i].Unbox(), "%s is only allowed at a board root", headString)
}
@ -945,9 +948,9 @@ func (m *Map) ensureField(i int, kp *d2ast.KeyPath, refctx *RefContext, create b
for _, grefctx := range c.globRefContextStack {
var ks string
if grefctx.Key.HasMultiGlob() {
ks = d2format.Format(d2ast.MakeKeyPath(IDA(f)))
ks = d2format.Format(d2ast.MakeKeyPathString(IDA(f)))
} else {
ks = d2format.Format(d2ast.MakeKeyPath(BoardIDA(f)))
ks = d2format.Format(d2ast.MakeKeyPathString(BoardIDA(f)))
}
gctx2 := c.getGlobContext(grefctx)
gctx2.appliedFields[ks] = struct{}{}
@ -1090,7 +1093,7 @@ func (m *Map) getEdges(eid *EdgeID, refctx *RefContext, gctx *globContext, ea *[
}
if len(common) > 0 {
commonKP := d2ast.MakeKeyPath(common)
commonKP := d2ast.MakeKeyPathString(common)
lastMatch := 0
for i, el := range commonKP.Path {
for j := lastMatch; j < len(refctx.Edge.Src.Path); j++ {
@ -1142,9 +1145,9 @@ func (m *Map) getEdges(eid *EdgeID, refctx *RefContext, gctx *globContext, ea *[
if gctx != nil {
var ks string
if refctx.Key.HasMultiGlob() {
ks = d2format.Format(d2ast.MakeKeyPath(IDA(e)))
ks = d2format.Format(d2ast.MakeKeyPathString(IDA(e)))
} else {
ks = d2format.Format(d2ast.MakeKeyPath(BoardIDA(e)))
ks = d2format.Format(d2ast.MakeKeyPathString(BoardIDA(e)))
}
if _, ok := gctx.appliedEdges[ks]; ok {
continue
@ -1186,7 +1189,7 @@ func (m *Map) createEdge(eid *EdgeID, refctx *RefContext, gctx *globContext, c *
return d2parser.Errorf(refctx.Edge, err.Error())
}
if len(common) > 0 {
commonKP := d2ast.MakeKeyPath(common)
commonKP := d2ast.MakeKeyPathString(common)
lastMatch := 0
for i, el := range commonKP.Path {
for j := lastMatch; j < len(refctx.Edge.Src.Path); j++ {
@ -1303,7 +1306,7 @@ func (m *Map) createEdge2(eid *EdgeID, refctx *RefContext, gctx *globContext, c
return nil, d2parser.Errorf(refctx.Edge, err.Error())
}
if len(common) > 0 {
commonKP := d2ast.MakeKeyPath(common)
commonKP := d2ast.MakeKeyPathString(common)
lastMatch := 0
for i, el := range commonKP.Path {
for j := lastMatch; j < len(refctx.Edge.Src.Path); j++ {
@ -1360,9 +1363,9 @@ func (m *Map) createEdge2(eid *EdgeID, refctx *RefContext, gctx *globContext, c
e2.ID = e2.ID.Copy()
e2.ID.Index = nil
if refctx.Key.HasMultiGlob() {
ks = d2format.Format(d2ast.MakeKeyPath(IDA(e2)))
ks = d2format.Format(d2ast.MakeKeyPathString(IDA(e2)))
} else {
ks = d2format.Format(d2ast.MakeKeyPath(BoardIDA(e2)))
ks = d2format.Format(d2ast.MakeKeyPathString(BoardIDA(e2)))
}
if _, ok := gctx.appliedEdges[ks]; ok {
return nil, nil
@ -1401,11 +1404,11 @@ func (f *Field) AST() d2ast.Node {
func (e *Edge) AST() d2ast.Node {
astEdge := &d2ast.Edge{}
astEdge.Src = d2ast.MakeKeyPath(e.ID.SrcPath)
astEdge.Src = d2ast.MakeKeyPathString(e.ID.SrcPath)
if e.ID.SrcArrow {
astEdge.SrcArrow = "<"
}
astEdge.Dst = d2ast.MakeKeyPath(e.ID.DstPath)
astEdge.Dst = d2ast.MakeKeyPathString(e.ID.DstPath)
if e.ID.DstArrow {
astEdge.DstArrow = ">"
}
@ -1424,7 +1427,7 @@ func (e *Edge) AST() d2ast.Node {
return k
}
func (e *Edge) IDString() string {
func (e *Edge) IDString() d2ast.String {
ast := e.AST().(*d2ast.Key)
if e.ID.Index != nil {
ast.EdgeIndex = &d2ast.EdgeIndex{
@ -1433,7 +1436,8 @@ func (e *Edge) IDString() string {
}
ast.Primary = d2ast.ScalarBox{}
ast.Value = d2ast.ValueBox{}
return d2format.Format(ast)
formatted := d2format.Format(ast)
return d2ast.FlatUnquotedString(formatted)
}
func (a *Array) AST() d2ast.Node {
@ -1465,7 +1469,7 @@ func (m *Map) AST() d2ast.Node {
func (m *Map) appendFieldReferences(i int, kp *d2ast.KeyPath, refctx *RefContext, c *compiler) {
sb := kp.Path[i]
f := m.GetField(sb.Unbox().ScalarString())
f := m.GetField(sb.Unbox())
if f == nil {
return
}
@ -1563,7 +1567,7 @@ func ParentShape(n Node) string {
f, ok := n.(*Field)
if ok {
if f.Map() != nil {
shapef := f.Map().GetField("shape")
shapef := f.Map().GetField(d2ast.FlatUnquotedString("shape"))
if shapef != nil && shapef.Primary() != nil {
return shapef.Primary().Value.ScalarString()
}
@ -1576,30 +1580,30 @@ func ParentShape(n Node) string {
}
}
func countUnderscores(p []string) int {
func countUnderscores(p []d2ast.String) int {
for i, el := range p {
if el != "_" {
if el.ScalarString() != "_" || el.IsUnquoted() {
return i
}
}
return 0
}
func findBoardKeyword(ida ...string) int {
func findBoardKeyword(ida ...d2ast.String) int {
for i := range ida {
if _, ok := d2ast.BoardKeywords[ida[i]]; ok {
if _, ok := d2ast.BoardKeywords[ida[i].ScalarString()]; ok && ida[i].IsUnquoted() {
return i
}
}
return -1
}
func findProhibitedEdgeKeyword(ida ...string) int {
func findProhibitedEdgeKeyword(ida ...d2ast.String) int {
for i := range ida {
if _, ok := d2ast.SimpleReservedKeywords[ida[i]]; ok {
if _, ok := d2ast.SimpleReservedKeywords[ida[i].ScalarString()]; ok && ida[i].IsUnquoted() {
return i
}
if _, ok := d2ast.ReservedKeywordHolders[ida[i]]; ok {
if _, ok := d2ast.ReservedKeywordHolders[ida[i].ScalarString()]; ok && ida[i].IsUnquoted() {
return i
}
}
@ -1643,7 +1647,7 @@ func parentPrimaryKey(n Node) *d2ast.Key {
}
// BoardIDA returns the absolute path to n from the nearest board root.
func BoardIDA(n Node) (ida []string) {
func BoardIDA(n Node) (ida []d2ast.String) {
for {
switch n := n.(type) {
case *Field:
@ -1651,7 +1655,7 @@ func BoardIDA(n Node) (ida []string) {
reverseIDA(ida)
return ida
}
ida = append(ida, n.Name.ScalarString())
ida = append(ida, n.Name)
case *Edge:
ida = append(ida, n.IDString())
}
@ -1664,11 +1668,11 @@ func BoardIDA(n Node) (ida []string) {
}
// IDA returns the absolute path to n.
func IDA(n Node) (ida []string) {
func IDA(n Node) (ida []d2ast.String) {
for {
switch n := n.(type) {
case *Field:
ida = append(ida, n.Name.ScalarString())
ida = append(ida, n.Name)
if n.Root() {
reverseIDA(ida)
return ida
@ -1685,17 +1689,17 @@ func IDA(n Node) (ida []string) {
}
// RelIDA returns the path to n relative to p.
func RelIDA(p, n Node) (ida []string) {
func RelIDA(p, n Node) (ida []d2ast.String) {
for {
switch n := n.(type) {
case *Field:
ida = append(ida, n.Name.ScalarString())
ida = append(ida, n.Name)
if n.Root() {
reverseIDA(ida)
return ida
}
case *Edge:
ida = append(ida, n.String())
ida = append(ida, d2ast.FlatUnquotedString(n.String()))
}
n = n.Parent()
f, fok := n.(*Field)
@ -1707,11 +1711,11 @@ func RelIDA(p, n Node) (ida []string) {
}
}
func reverseIDA(ida []string) {
for i := 0; i < len(ida)/2; i++ {
tmp := ida[i]
ida[i] = ida[len(ida)-i-1]
ida[len(ida)-i-1] = tmp
func reverseIDA[T any](slice []T) {
for i := 0; i < len(slice)/2; i++ {
tmp := slice[i]
slice[i] = slice[len(slice)-i-1]
slice[len(slice)-i-1] = tmp
}
}
@ -1786,7 +1790,7 @@ func (m *Map) Equal(n2 Node) bool {
}
func (m *Map) InClass(key *d2ast.Key) bool {
classes := m.Map().GetField("classes")
classes := m.Map().GetField(d2ast.FlatUnquotedString("classes"))
if classes == nil || classes.Map() == nil {
return false
}
@ -1814,7 +1818,7 @@ func (m *Map) IsClass() bool {
if parentBoard.Map() == nil {
return false
}
classes := parentBoard.Map().GetField("classes")
classes := parentBoard.Map().GetField(d2ast.FlatUnquotedString("classes"))
if classes == nil || classes.Map() == nil {
return false
}
@ -1835,9 +1839,9 @@ func (m *Map) FindBoardRoot(path []string) *Map {
return m
}
layersf := m.GetField("layers")
scenariosf := m.GetField("scenarios")
stepsf := m.GetField("steps")
layersf := m.GetField(d2ast.FlatUnquotedString("layers"))
scenariosf := m.GetField(d2ast.FlatUnquotedString("scenarios"))
stepsf := m.GetField(d2ast.FlatUnquotedString("steps"))
if layersf != nil && layersf.Map() != nil {
for _, f := range layersf.Map().Fields {

View file

@ -2,7 +2,7 @@ package d2ir
func OverlayMap(base, overlay *Map) {
for _, of := range overlay.Fields {
bf := base.GetField(of.Name.ScalarString())
bf := base.GetField(of.Name)
if bf == nil {
base.Fields = append(base.Fields, of.Copy(base).(*Field))
continue
@ -31,7 +31,7 @@ func ExpandSubstitution(m, resolved *Map, placeholder *Field) {
}
for _, of := range resolved.Fields {
bf := m.GetField(of.Name.ScalarString())
bf := m.GetField(of.Name)
if bf == nil {
m.Fields = append(m.Fields[:fi], append([]*Field{of.Copy(m).(*Field)}, m.Fields[fi:]...)...)
fi++

View file

@ -0,0 +1,305 @@
{
"name": "",
"isFolderOnly": false,
"fontFamily": "SourceSansPro",
"shapes": [
{
"id": "my_table",
"type": "sql_table",
"pos": {
"x": 0,
"y": 166
},
"width": 200,
"height": 200,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "N1",
"stroke": "N7",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": {
"Scheme": "https",
"Opaque": "",
"User": null,
"Host": "static.wikia.nocookie.net",
"Path": "/tomandjerry/images/4/46/JerryJumbo3-1-.jpg",
"RawPath": "",
"OmitHost": false,
"ForceQuery": false,
"RawQuery": "",
"Fragment": "",
"RawFragment": ""
},
"iconPosition": "OUTSIDE_TOP_LEFT",
"blend": false,
"fields": null,
"methods": null,
"columns": [
{
"name": {
"label": "shape",
"fontSize": 0,
"fontFamily": "",
"language": "",
"color": "",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 51,
"labelHeight": 26
},
"type": {
"label": "string",
"fontSize": 0,
"fontFamily": "",
"language": "",
"color": "",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 48,
"labelHeight": 26
},
"constraint": null,
"reference": ""
},
{
"name": {
"label": "icon",
"fontSize": 0,
"fontFamily": "",
"language": "",
"color": "",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 35,
"labelHeight": 26
},
"type": {
"label": "string",
"fontSize": 0,
"fontFamily": "",
"language": "",
"color": "",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 48,
"labelHeight": 26
},
"constraint": null,
"reference": ""
},
{
"name": {
"label": "width",
"fontSize": 0,
"fontFamily": "",
"language": "",
"color": "",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 48,
"labelHeight": 26
},
"type": {
"label": "int",
"fontSize": 0,
"fontFamily": "",
"language": "",
"color": "",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 23,
"labelHeight": 26
},
"constraint": null,
"reference": ""
},
{
"name": {
"label": "height",
"fontSize": 0,
"fontFamily": "",
"language": "",
"color": "",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 53,
"labelHeight": 26
},
"type": {
"label": "int",
"fontSize": 0,
"fontFamily": "",
"language": "",
"color": "",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 23,
"labelHeight": 26
},
"constraint": null,
"reference": ""
}
],
"label": "my_table",
"fontSize": 20,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 99,
"labelHeight": 31,
"zIndex": 0,
"level": 1,
"primaryAccentColor": "B2",
"secondaryAccentColor": "AA2",
"neutralAccentColor": "N2"
},
{
"id": "x",
"type": "rectangle",
"pos": {
"x": 74,
"y": 0
},
"width": 53,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B6",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "x",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
}
],
"connections": [
{
"id": "(x -> my_table)[0]",
"src": "x",
"srcArrow": "none",
"dst": "my_table",
"dstArrow": "triangle",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "B1",
"borderRadius": 10,
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N2",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 100,
"y": 66
},
{
"x": 100,
"y": 106
},
{
"x": 100,
"y": 126
},
{
"x": 100,
"y": 166
}
],
"isCurve": true,
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
}
],
"root": {
"id": "",
"type": "",
"pos": {
"x": 0,
"y": 0
},
"width": 0,
"height": 0,
"opacity": 0,
"strokeDash": 0,
"strokeWidth": 0,
"borderRadius": 0,
"fill": "N7",
"stroke": "",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "",
"fontSize": 0,
"fontFamily": "",
"language": "",
"color": "",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"zIndex": 0,
"level": 0
}
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 18 KiB

View file

@ -0,0 +1,300 @@
{
"name": "",
"isFolderOnly": false,
"fontFamily": "SourceSansPro",
"shapes": [
{
"id": "my_table",
"type": "sql_table",
"pos": {
"x": 78,
"y": 217
},
"width": 200,
"height": 200,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "N1",
"stroke": "N7",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": {
"Scheme": "https",
"Opaque": "",
"User": null,
"Host": "static.wikia.nocookie.net",
"Path": "/tomandjerry/images/4/46/JerryJumbo3-1-.jpg",
"RawPath": "",
"OmitHost": false,
"ForceQuery": false,
"RawQuery": "",
"Fragment": "",
"RawFragment": ""
},
"iconPosition": "OUTSIDE_TOP_LEFT",
"blend": false,
"fields": null,
"methods": null,
"columns": [
{
"name": {
"label": "shape",
"fontSize": 0,
"fontFamily": "",
"language": "",
"color": "",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 51,
"labelHeight": 26
},
"type": {
"label": "string",
"fontSize": 0,
"fontFamily": "",
"language": "",
"color": "",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 48,
"labelHeight": 26
},
"constraint": null,
"reference": ""
},
{
"name": {
"label": "icon",
"fontSize": 0,
"fontFamily": "",
"language": "",
"color": "",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 35,
"labelHeight": 26
},
"type": {
"label": "string",
"fontSize": 0,
"fontFamily": "",
"language": "",
"color": "",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 48,
"labelHeight": 26
},
"constraint": null,
"reference": ""
},
{
"name": {
"label": "width",
"fontSize": 0,
"fontFamily": "",
"language": "",
"color": "",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 48,
"labelHeight": 26
},
"type": {
"label": "int",
"fontSize": 0,
"fontFamily": "",
"language": "",
"color": "",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 23,
"labelHeight": 26
},
"constraint": null,
"reference": ""
},
{
"name": {
"label": "height",
"fontSize": 0,
"fontFamily": "",
"language": "",
"color": "",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 53,
"labelHeight": 26
},
"type": {
"label": "int",
"fontSize": 0,
"fontFamily": "",
"language": "",
"color": "",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 23,
"labelHeight": 26
},
"constraint": null,
"reference": ""
}
],
"label": "my_table",
"fontSize": 20,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 99,
"labelHeight": 31,
"zIndex": 0,
"level": 1,
"primaryAccentColor": "B2",
"secondaryAccentColor": "AA2",
"neutralAccentColor": "N2"
},
{
"id": "x",
"type": "rectangle",
"pos": {
"x": 12,
"y": 12
},
"width": 53,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B6",
"stroke": "B1",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "x",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
}
],
"connections": [
{
"id": "(x -> my_table)[0]",
"src": "x",
"srcArrow": "none",
"dst": "my_table",
"dstArrow": "triangle",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "B1",
"borderRadius": 10,
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N2",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 38.5,
"y": 77.6989974975586
},
{
"x": 38.5,
"y": 228.6999969482422
},
{
"x": 78.5,
"y": 228.6999969482422
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
}
],
"root": {
"id": "",
"type": "",
"pos": {
"x": 0,
"y": 0
},
"width": 0,
"height": 0,
"opacity": 0,
"strokeDash": 0,
"strokeWidth": 0,
"borderRadius": 0,
"fill": "N7",
"stroke": "",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "",
"fontSize": 0,
"fontFamily": "",
"language": "",
"color": "",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"zIndex": 0,
"level": 0
}
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 18 KiB

View file

@ -643,3 +643,17 @@ financial.style.fill: "#e8f4f8"
monitoring.style.fill: "#f8e8e8"
projects.style.fill: "#e8f8e8"
team.style.fill: "#f8f0e8"
-- sql-table-reserved --
my_table: {
shape: sql_table
icon: https://static.wikia.nocookie.net/tomandjerry/images/4/46/JerryJumbo3-1-.jpg
width: 200
height: 200
"shape": string
"icon": string
"width": int
"height": int
}
x -> my_table."shape"