d2fmt: lowercase reserved keywords
This commit is contained in:
parent
5e96290e45
commit
de518f5c5e
9 changed files with 296 additions and 261 deletions
201
d2ast/keywords.go
Normal file
201
d2ast/keywords.go
Normal file
|
|
@ -0,0 +1,201 @@
|
||||||
|
package d2ast
|
||||||
|
|
||||||
|
import "oss.terrastruct.com/d2/lib/label"
|
||||||
|
|
||||||
|
// All reserved keywords. See init below.
|
||||||
|
var ReservedKeywords map[string]struct{}
|
||||||
|
|
||||||
|
// Non Style/Holder keywords.
|
||||||
|
var SimpleReservedKeywords = map[string]struct{}{
|
||||||
|
"label": {},
|
||||||
|
"desc": {},
|
||||||
|
"shape": {},
|
||||||
|
"icon": {},
|
||||||
|
"constraint": {},
|
||||||
|
"tooltip": {},
|
||||||
|
"link": {},
|
||||||
|
"near": {},
|
||||||
|
"width": {},
|
||||||
|
"height": {},
|
||||||
|
"direction": {},
|
||||||
|
"top": {},
|
||||||
|
"left": {},
|
||||||
|
"grid-rows": {},
|
||||||
|
"grid-columns": {},
|
||||||
|
"grid-gap": {},
|
||||||
|
"vertical-gap": {},
|
||||||
|
"horizontal-gap": {},
|
||||||
|
"class": {},
|
||||||
|
"vars": {},
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReservedKeywordHolders are reserved keywords that are meaningless on its own and must hold composites
|
||||||
|
var ReservedKeywordHolders = map[string]struct{}{
|
||||||
|
"style": {},
|
||||||
|
"source-arrowhead": {},
|
||||||
|
"target-arrowhead": {},
|
||||||
|
}
|
||||||
|
|
||||||
|
// CompositeReservedKeywords are reserved keywords that can hold composites
|
||||||
|
var CompositeReservedKeywords = map[string]struct{}{
|
||||||
|
"classes": {},
|
||||||
|
"constraint": {},
|
||||||
|
"label": {},
|
||||||
|
"icon": {},
|
||||||
|
}
|
||||||
|
|
||||||
|
// StyleKeywords are reserved keywords which cannot exist outside of the "style" keyword
|
||||||
|
var StyleKeywords = map[string]struct{}{
|
||||||
|
"opacity": {},
|
||||||
|
"stroke": {},
|
||||||
|
"fill": {},
|
||||||
|
"fill-pattern": {},
|
||||||
|
"stroke-width": {},
|
||||||
|
"stroke-dash": {},
|
||||||
|
"border-radius": {},
|
||||||
|
|
||||||
|
// Only for text
|
||||||
|
"font": {},
|
||||||
|
"font-size": {},
|
||||||
|
"font-color": {},
|
||||||
|
"bold": {},
|
||||||
|
"italic": {},
|
||||||
|
"underline": {},
|
||||||
|
"text-transform": {},
|
||||||
|
|
||||||
|
// Only for shapes
|
||||||
|
"shadow": {},
|
||||||
|
"multiple": {},
|
||||||
|
"double-border": {},
|
||||||
|
|
||||||
|
// Only for squares
|
||||||
|
"3d": {},
|
||||||
|
|
||||||
|
// Only for edges
|
||||||
|
"animated": {},
|
||||||
|
"filled": {},
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO maybe autofmt should allow other values, and transform them to conform
|
||||||
|
// e.g. left-center becomes center-left
|
||||||
|
var NearConstantsArray = []string{
|
||||||
|
"top-left",
|
||||||
|
"top-center",
|
||||||
|
"top-right",
|
||||||
|
|
||||||
|
"center-left",
|
||||||
|
"center-right",
|
||||||
|
|
||||||
|
"bottom-left",
|
||||||
|
"bottom-center",
|
||||||
|
"bottom-right",
|
||||||
|
}
|
||||||
|
var NearConstants map[string]struct{}
|
||||||
|
|
||||||
|
// LabelPositionsArray are the values that labels and icons can set `near` to
|
||||||
|
var LabelPositionsArray = []string{
|
||||||
|
"top-left",
|
||||||
|
"top-center",
|
||||||
|
"top-right",
|
||||||
|
|
||||||
|
"center-left",
|
||||||
|
"center-center",
|
||||||
|
"center-right",
|
||||||
|
|
||||||
|
"bottom-left",
|
||||||
|
"bottom-center",
|
||||||
|
"bottom-right",
|
||||||
|
|
||||||
|
"outside-top-left",
|
||||||
|
"outside-top-center",
|
||||||
|
"outside-top-right",
|
||||||
|
|
||||||
|
"outside-left-top",
|
||||||
|
"outside-left-center",
|
||||||
|
"outside-left-bottom",
|
||||||
|
|
||||||
|
"outside-right-top",
|
||||||
|
"outside-right-center",
|
||||||
|
"outside-right-bottom",
|
||||||
|
|
||||||
|
"outside-bottom-left",
|
||||||
|
"outside-bottom-center",
|
||||||
|
"outside-bottom-right",
|
||||||
|
}
|
||||||
|
var LabelPositions map[string]struct{}
|
||||||
|
|
||||||
|
var LabelPositionsMapping = map[string]label.Position{
|
||||||
|
"top-left": label.InsideTopLeft,
|
||||||
|
"top-center": label.InsideTopCenter,
|
||||||
|
"top-right": label.InsideTopRight,
|
||||||
|
|
||||||
|
"center-left": label.InsideMiddleLeft,
|
||||||
|
"center-center": label.InsideMiddleCenter,
|
||||||
|
"center-right": label.InsideMiddleRight,
|
||||||
|
|
||||||
|
"bottom-left": label.InsideBottomLeft,
|
||||||
|
"bottom-center": label.InsideBottomCenter,
|
||||||
|
"bottom-right": label.InsideBottomRight,
|
||||||
|
|
||||||
|
"outside-top-left": label.OutsideTopLeft,
|
||||||
|
"outside-top-center": label.OutsideTopCenter,
|
||||||
|
"outside-top-right": label.OutsideTopRight,
|
||||||
|
|
||||||
|
"outside-left-top": label.OutsideLeftTop,
|
||||||
|
"outside-left-center": label.OutsideLeftMiddle,
|
||||||
|
"outside-left-bottom": label.OutsideLeftBottom,
|
||||||
|
|
||||||
|
"outside-right-top": label.OutsideRightTop,
|
||||||
|
"outside-right-center": label.OutsideRightMiddle,
|
||||||
|
"outside-right-bottom": label.OutsideRightBottom,
|
||||||
|
|
||||||
|
"outside-bottom-left": label.OutsideBottomLeft,
|
||||||
|
"outside-bottom-center": label.OutsideBottomCenter,
|
||||||
|
"outside-bottom-right": label.OutsideBottomRight,
|
||||||
|
}
|
||||||
|
|
||||||
|
var FillPatterns = []string{
|
||||||
|
"none",
|
||||||
|
"dots",
|
||||||
|
"lines",
|
||||||
|
"grain",
|
||||||
|
"paper",
|
||||||
|
}
|
||||||
|
|
||||||
|
var TextTransforms = []string{"none", "uppercase", "lowercase", "capitalize"}
|
||||||
|
|
||||||
|
// BoardKeywords contains the keywords that create new boards.
|
||||||
|
var BoardKeywords = map[string]struct{}{
|
||||||
|
"layers": {},
|
||||||
|
"scenarios": {},
|
||||||
|
"steps": {},
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
ReservedKeywords = make(map[string]struct{})
|
||||||
|
for k, v := range SimpleReservedKeywords {
|
||||||
|
ReservedKeywords[k] = v
|
||||||
|
}
|
||||||
|
for k, v := range StyleKeywords {
|
||||||
|
ReservedKeywords[k] = v
|
||||||
|
}
|
||||||
|
for k, v := range ReservedKeywordHolders {
|
||||||
|
CompositeReservedKeywords[k] = v
|
||||||
|
}
|
||||||
|
for k, v := range BoardKeywords {
|
||||||
|
CompositeReservedKeywords[k] = v
|
||||||
|
}
|
||||||
|
for k, v := range CompositeReservedKeywords {
|
||||||
|
ReservedKeywords[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
NearConstants = make(map[string]struct{}, len(NearConstantsArray))
|
||||||
|
for _, k := range NearConstantsArray {
|
||||||
|
NearConstants[k] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
LabelPositions = make(map[string]struct{}, len(LabelPositionsArray))
|
||||||
|
for _, k := range LabelPositionsArray {
|
||||||
|
LabelPositions[k] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -271,7 +271,7 @@ func (c *compiler) compileMap(obj *d2graph.Object, m *d2ir.Map) {
|
||||||
if f.Name == "shape" {
|
if f.Name == "shape" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if _, ok := d2graph.BoardKeywords[f.Name]; ok {
|
if _, ok := d2ast.BoardKeywords[f.Name]; ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
c.compileField(obj, f)
|
c.compileField(obj, f)
|
||||||
|
|
@ -293,12 +293,12 @@ func (c *compiler) compileMap(obj *d2graph.Object, m *d2ir.Map) {
|
||||||
|
|
||||||
func (c *compiler) compileField(obj *d2graph.Object, f *d2ir.Field) {
|
func (c *compiler) compileField(obj *d2graph.Object, f *d2ir.Field) {
|
||||||
keyword := strings.ToLower(f.Name)
|
keyword := strings.ToLower(f.Name)
|
||||||
_, isStyleReserved := d2graph.StyleKeywords[keyword]
|
_, isStyleReserved := d2ast.StyleKeywords[keyword]
|
||||||
if isStyleReserved {
|
if isStyleReserved {
|
||||||
c.errorf(f.LastRef().AST(), "%v must be style.%v", f.Name, f.Name)
|
c.errorf(f.LastRef().AST(), "%v must be style.%v", f.Name, f.Name)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_, isReserved := d2graph.SimpleReservedKeywords[keyword]
|
_, isReserved := d2ast.SimpleReservedKeywords[keyword]
|
||||||
if f.Name == "classes" {
|
if f.Name == "classes" {
|
||||||
if f.Map() != nil {
|
if f.Map() != nil {
|
||||||
if len(f.Map().Edges) > 0 {
|
if len(f.Map().Edges) > 0 {
|
||||||
|
|
@ -309,7 +309,7 @@ func (c *compiler) compileField(obj *d2graph.Object, f *d2ir.Field) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for _, cf := range classesField.Map().Fields {
|
for _, cf := range classesField.Map().Fields {
|
||||||
if _, ok := d2graph.ReservedKeywords[cf.Name]; !ok {
|
if _, ok := d2ast.ReservedKeywords[cf.Name]; !ok {
|
||||||
c.errorf(cf.LastRef().AST(), "%s is an invalid class field, must be reserved keyword", cf.Name)
|
c.errorf(cf.LastRef().AST(), "%s is an invalid class field, must be reserved keyword", cf.Name)
|
||||||
}
|
}
|
||||||
if cf.Name == "class" {
|
if cf.Name == "class" {
|
||||||
|
|
@ -440,7 +440,7 @@ func (c *compiler) compilePosition(attrs *d2graph.Attributes, f *d2ir.Field) {
|
||||||
case *d2ast.Null:
|
case *d2ast.Null:
|
||||||
attrs.LabelPosition = nil
|
attrs.LabelPosition = nil
|
||||||
default:
|
default:
|
||||||
if _, ok := d2graph.LabelPositions[scalar.ScalarString()]; !ok {
|
if _, ok := d2ast.LabelPositions[scalar.ScalarString()]; !ok {
|
||||||
c.errorf(f.LastPrimaryKey(), `invalid "near" field`)
|
c.errorf(f.LastPrimaryKey(), `invalid "near" field`)
|
||||||
} else {
|
} else {
|
||||||
switch name {
|
switch name {
|
||||||
|
|
@ -686,7 +686,7 @@ func (c *compiler) compileStyle(attrs *d2graph.Attributes, m *d2ir.Map) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *compiler) compileStyleField(attrs *d2graph.Attributes, f *d2ir.Field) {
|
func (c *compiler) compileStyleField(attrs *d2graph.Attributes, f *d2ir.Field) {
|
||||||
if _, ok := d2graph.StyleKeywords[strings.ToLower(f.Name)]; !ok {
|
if _, ok := d2ast.StyleKeywords[strings.ToLower(f.Name)]; !ok {
|
||||||
c.errorf(f.LastRef().AST(), `invalid style keyword: "%s"`, f.Name)
|
c.errorf(f.LastRef().AST(), `invalid style keyword: "%s"`, f.Name)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -814,7 +814,7 @@ func (c *compiler) compileEdgeMap(edge *d2graph.Edge, m *d2ir.Map) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, f := range m.Fields {
|
for _, f := range m.Fields {
|
||||||
_, ok := d2graph.ReservedKeywords[f.Name]
|
_, ok := d2ast.ReservedKeywords[f.Name]
|
||||||
if !ok {
|
if !ok {
|
||||||
c.errorf(f.References[0].AST(), `edge map keys must be reserved keywords`)
|
c.errorf(f.References[0].AST(), `edge map keys must be reserved keywords`)
|
||||||
continue
|
continue
|
||||||
|
|
@ -825,12 +825,12 @@ func (c *compiler) compileEdgeMap(edge *d2graph.Edge, m *d2ir.Map) {
|
||||||
|
|
||||||
func (c *compiler) compileEdgeField(edge *d2graph.Edge, f *d2ir.Field) {
|
func (c *compiler) compileEdgeField(edge *d2graph.Edge, f *d2ir.Field) {
|
||||||
keyword := strings.ToLower(f.Name)
|
keyword := strings.ToLower(f.Name)
|
||||||
_, isStyleReserved := d2graph.StyleKeywords[keyword]
|
_, isStyleReserved := d2ast.StyleKeywords[keyword]
|
||||||
if isStyleReserved {
|
if isStyleReserved {
|
||||||
c.errorf(f.LastRef().AST(), "%v must be style.%v", f.Name, f.Name)
|
c.errorf(f.LastRef().AST(), "%v must be style.%v", f.Name, f.Name)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_, isReserved := d2graph.SimpleReservedKeywords[keyword]
|
_, isReserved := d2ast.SimpleReservedKeywords[keyword]
|
||||||
if isReserved {
|
if isReserved {
|
||||||
c.compileReserved(&edge.Attributes, f)
|
c.compileReserved(&edge.Attributes, f)
|
||||||
return
|
return
|
||||||
|
|
@ -868,7 +868,7 @@ func (c *compiler) compileArrowheads(edge *d2graph.Edge, f *d2ir.Field) {
|
||||||
if f.Map() != nil {
|
if f.Map() != nil {
|
||||||
for _, f2 := range f.Map().Fields {
|
for _, f2 := range f.Map().Fields {
|
||||||
keyword := strings.ToLower(f2.Name)
|
keyword := strings.ToLower(f2.Name)
|
||||||
_, isReserved := d2graph.SimpleReservedKeywords[keyword]
|
_, isReserved := d2ast.SimpleReservedKeywords[keyword]
|
||||||
if isReserved {
|
if isReserved {
|
||||||
c.compileReserved(attrs, f2)
|
c.compileReserved(attrs, f2)
|
||||||
continue
|
continue
|
||||||
|
|
@ -985,7 +985,7 @@ func (c *compiler) compileSQLTable(obj *d2graph.Object) {
|
||||||
|
|
||||||
func (c *compiler) validateKeys(obj *d2graph.Object, m *d2ir.Map) {
|
func (c *compiler) validateKeys(obj *d2graph.Object, m *d2ir.Map) {
|
||||||
for _, f := range m.Fields {
|
for _, f := range m.Fields {
|
||||||
if _, ok := d2graph.BoardKeywords[f.Name]; ok {
|
if _, ok := d2ast.BoardKeywords[f.Name]; ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
c.validateKey(obj, f)
|
c.validateKey(obj, f)
|
||||||
|
|
@ -994,7 +994,7 @@ func (c *compiler) validateKeys(obj *d2graph.Object, m *d2ir.Map) {
|
||||||
|
|
||||||
func (c *compiler) validateKey(obj *d2graph.Object, f *d2ir.Field) {
|
func (c *compiler) validateKey(obj *d2graph.Object, f *d2ir.Field) {
|
||||||
keyword := strings.ToLower(f.Name)
|
keyword := strings.ToLower(f.Name)
|
||||||
_, isReserved := d2graph.ReservedKeywords[keyword]
|
_, isReserved := d2ast.ReservedKeywords[keyword]
|
||||||
if isReserved {
|
if isReserved {
|
||||||
switch obj.Shape.Value {
|
switch obj.Shape.Value {
|
||||||
case d2target.ShapeCircle, d2target.ShapeSquare:
|
case d2target.ShapeCircle, d2target.ShapeSquare:
|
||||||
|
|
@ -1067,7 +1067,7 @@ func (c *compiler) validateNear(g *d2graph.Graph) {
|
||||||
for _, obj := range g.Objects {
|
for _, obj := range g.Objects {
|
||||||
if obj.NearKey != nil {
|
if obj.NearKey != nil {
|
||||||
nearObj, isKey := g.Root.HasChild(d2graph.Key(obj.NearKey))
|
nearObj, isKey := g.Root.HasChild(d2graph.Key(obj.NearKey))
|
||||||
_, isConst := d2graph.NearConstants[d2graph.Key(obj.NearKey)[0]]
|
_, isConst := d2ast.NearConstants[d2graph.Key(obj.NearKey)[0]]
|
||||||
if isKey {
|
if isKey {
|
||||||
// Doesn't make sense to set near to an ancestor or descendant
|
// Doesn't make sense to set near to an ancestor or descendant
|
||||||
nearIsAncestor := false
|
nearIsAncestor := false
|
||||||
|
|
@ -1097,7 +1097,7 @@ func (c *compiler) validateNear(g *d2graph.Graph) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if nearObj.NearKey != nil {
|
if nearObj.NearKey != nil {
|
||||||
_, nearObjNearIsConst := d2graph.NearConstants[d2graph.Key(nearObj.NearKey)[0]]
|
_, nearObjNearIsConst := d2ast.NearConstants[d2graph.Key(nearObj.NearKey)[0]]
|
||||||
if nearObjNearIsConst {
|
if nearObjNearIsConst {
|
||||||
c.errorf(obj.NearKey, "near keys cannot be set to an object with a constant near key")
|
c.errorf(obj.NearKey, "near keys cannot be set to an object with a constant near key")
|
||||||
continue
|
continue
|
||||||
|
|
@ -1117,7 +1117,7 @@ func (c *compiler) validateNear(g *d2graph.Graph) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
c.errorf(obj.NearKey, "near key %#v must be the absolute path to a shape or one of the following constants: %s", d2format.Format(obj.NearKey), strings.Join(d2graph.NearConstantsArray, ", "))
|
c.errorf(obj.NearKey, "near key %#v must be the absolute path to a shape or one of the following constants: %s", d2format.Format(obj.NearKey), strings.Join(d2ast.NearConstantsArray, ", "))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -135,6 +135,12 @@ func (p *printer) interpolationBoxes(boxes []d2ast.InterpolationBox, isDoubleStr
|
||||||
}
|
}
|
||||||
b.StringRaw = &s
|
b.StringRaw = &s
|
||||||
}
|
}
|
||||||
|
if !isDoubleString {
|
||||||
|
if _, ok := d2ast.ReservedKeywords[strings.ToLower(*b.StringRaw)]; ok {
|
||||||
|
s := strings.ToLower(*b.StringRaw)
|
||||||
|
b.StringRaw = &s
|
||||||
|
}
|
||||||
|
}
|
||||||
p.sb.WriteString(*b.StringRaw)
|
p.sb.WriteString(*b.StringRaw)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,6 @@ x -> y
|
||||||
exp: `x -> y
|
exp: `x -> y
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
name: "complex",
|
name: "complex",
|
||||||
in: `
|
in: `
|
||||||
|
|
@ -853,6 +852,35 @@ jeremy: {
|
||||||
!&shape: rectangle
|
!&shape: rectangle
|
||||||
label: I'm not a rectangle
|
label: I'm not a rectangle
|
||||||
}
|
}
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "lowercase-reserved",
|
||||||
|
in: `jacob: {
|
||||||
|
SHAPE: circle
|
||||||
|
}
|
||||||
|
jeremy.SHAPE: rectangle
|
||||||
|
alice.STYLE.fill: red
|
||||||
|
bob.style.FILL: red
|
||||||
|
carmen.STYLE.FILL: red
|
||||||
|
coop: {
|
||||||
|
STYLE: {
|
||||||
|
FILL: blue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
exp: `jacob: {
|
||||||
|
shape: circle
|
||||||
|
}
|
||||||
|
jeremy.shape: rectangle
|
||||||
|
alice.style.fill: red
|
||||||
|
bob.style.fill: red
|
||||||
|
carmen.style.fill: red
|
||||||
|
coop: {
|
||||||
|
style: {
|
||||||
|
fill: blue
|
||||||
|
}
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -268,8 +268,8 @@ func (s *Style) Apply(key, value string) error {
|
||||||
if s.FillPattern == nil {
|
if s.FillPattern == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if !go2.Contains(FillPatterns, strings.ToLower(value)) {
|
if !go2.Contains(d2ast.FillPatterns, strings.ToLower(value)) {
|
||||||
return fmt.Errorf(`expected "fill-pattern" to be one of: %s`, strings.Join(FillPatterns, ", "))
|
return fmt.Errorf(`expected "fill-pattern" to be one of: %s`, strings.Join(d2ast.FillPatterns, ", "))
|
||||||
}
|
}
|
||||||
s.FillPattern.Value = value
|
s.FillPattern.Value = value
|
||||||
case "stroke-width":
|
case "stroke-width":
|
||||||
|
|
@ -409,8 +409,8 @@ func (s *Style) Apply(key, value string) error {
|
||||||
if s.TextTransform == nil {
|
if s.TextTransform == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if !go2.Contains(textTransforms, strings.ToLower(value)) {
|
if !go2.Contains(d2ast.TextTransforms, strings.ToLower(value)) {
|
||||||
return fmt.Errorf(`expected "text-transform" to be one of (%s)`, strings.Join(textTransforms, ", "))
|
return fmt.Errorf(`expected "text-transform" to be one of (%s)`, strings.Join(d2ast.TextTransforms, ", "))
|
||||||
}
|
}
|
||||||
s.TextTransform.Value = value
|
s.TextTransform.Value = value
|
||||||
default:
|
default:
|
||||||
|
|
@ -667,7 +667,7 @@ func (obj *Object) HasChild(ids []string) (*Object, bool) {
|
||||||
return obj, true
|
return obj, true
|
||||||
}
|
}
|
||||||
if len(ids) == 1 && ids[0] != "style" {
|
if len(ids) == 1 && ids[0] != "style" {
|
||||||
_, ok := ReservedKeywords[ids[0]]
|
_, ok := d2ast.ReservedKeywords[ids[0]]
|
||||||
if ok {
|
if ok {
|
||||||
return obj, true
|
return obj, true
|
||||||
}
|
}
|
||||||
|
|
@ -818,9 +818,9 @@ func (obj *Object) EnsureChild(ida []string) *Object {
|
||||||
return obj
|
return obj
|
||||||
}
|
}
|
||||||
|
|
||||||
_, is := ReservedKeywordHolders[ida[0]]
|
_, is := d2ast.ReservedKeywordHolders[ida[0]]
|
||||||
if len(ida) == 1 && !is {
|
if len(ida) == 1 && !is {
|
||||||
_, ok := ReservedKeywords[ida[0]]
|
_, ok := d2ast.ReservedKeywords[ida[0]]
|
||||||
if ok {
|
if ok {
|
||||||
return obj
|
return obj
|
||||||
}
|
}
|
||||||
|
|
@ -1120,7 +1120,7 @@ func (obj *Object) IsConstantNear() bool {
|
||||||
if isKey {
|
if isKey {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
_, isConst := NearConstants[keyPath[0]]
|
_, isConst := d2ast.NearConstants[keyPath[0]]
|
||||||
return isConst
|
return isConst
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1235,7 +1235,7 @@ func (e *Edge) AbsID() string {
|
||||||
func (obj *Object) Connect(srcID, dstID []string, srcArrow, dstArrow bool, label string) (*Edge, error) {
|
func (obj *Object) Connect(srcID, dstID []string, srcArrow, dstArrow bool, label string) (*Edge, error) {
|
||||||
for _, id := range [][]string{srcID, dstID} {
|
for _, id := range [][]string{srcID, dstID} {
|
||||||
for _, p := range id {
|
for _, p := range id {
|
||||||
if _, ok := ReservedKeywords[p]; ok {
|
if _, ok := d2ast.ReservedKeywords[p]; ok {
|
||||||
return nil, errors.New("cannot connect to reserved keyword")
|
return nil, errors.New("cannot connect to reserved keyword")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1428,12 +1428,12 @@ func (g *Graph) SetDimensions(mtexts []*d2target.MText, ruler *textmeasure.Ruler
|
||||||
// user-specified label/icon positions
|
// user-specified label/icon positions
|
||||||
if obj.HasLabel() && obj.Attributes.LabelPosition != nil {
|
if obj.HasLabel() && obj.Attributes.LabelPosition != nil {
|
||||||
scalar := *obj.Attributes.LabelPosition
|
scalar := *obj.Attributes.LabelPosition
|
||||||
position := LabelPositionsMapping[scalar.Value]
|
position := d2ast.LabelPositionsMapping[scalar.Value]
|
||||||
obj.LabelPosition = go2.Pointer(position.String())
|
obj.LabelPosition = go2.Pointer(position.String())
|
||||||
}
|
}
|
||||||
if obj.Icon != nil && obj.Attributes.IconPosition != nil {
|
if obj.Icon != nil && obj.Attributes.IconPosition != nil {
|
||||||
scalar := *obj.Attributes.IconPosition
|
scalar := *obj.Attributes.IconPosition
|
||||||
position := LabelPositionsMapping[scalar.Value]
|
position := d2ast.LabelPositionsMapping[scalar.Value]
|
||||||
obj.IconPosition = go2.Pointer(position.String())
|
obj.IconPosition = go2.Pointer(position.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1673,205 +1673,6 @@ func Key(k *d2ast.KeyPath) []string {
|
||||||
return d2format.KeyPath(k)
|
return d2format.KeyPath(k)
|
||||||
}
|
}
|
||||||
|
|
||||||
// All reserved keywords. See init below.
|
|
||||||
var ReservedKeywords map[string]struct{}
|
|
||||||
|
|
||||||
// Non Style/Holder keywords.
|
|
||||||
var SimpleReservedKeywords = map[string]struct{}{
|
|
||||||
"label": {},
|
|
||||||
"desc": {},
|
|
||||||
"shape": {},
|
|
||||||
"icon": {},
|
|
||||||
"constraint": {},
|
|
||||||
"tooltip": {},
|
|
||||||
"link": {},
|
|
||||||
"near": {},
|
|
||||||
"width": {},
|
|
||||||
"height": {},
|
|
||||||
"direction": {},
|
|
||||||
"top": {},
|
|
||||||
"left": {},
|
|
||||||
"grid-rows": {},
|
|
||||||
"grid-columns": {},
|
|
||||||
"grid-gap": {},
|
|
||||||
"vertical-gap": {},
|
|
||||||
"horizontal-gap": {},
|
|
||||||
"class": {},
|
|
||||||
"vars": {},
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReservedKeywordHolders are reserved keywords that are meaningless on its own and must hold composites
|
|
||||||
var ReservedKeywordHolders = map[string]struct{}{
|
|
||||||
"style": {},
|
|
||||||
"source-arrowhead": {},
|
|
||||||
"target-arrowhead": {},
|
|
||||||
}
|
|
||||||
|
|
||||||
// CompositeReservedKeywords are reserved keywords that can hold composites
|
|
||||||
var CompositeReservedKeywords = map[string]struct{}{
|
|
||||||
"classes": {},
|
|
||||||
"constraint": {},
|
|
||||||
"label": {},
|
|
||||||
"icon": {},
|
|
||||||
}
|
|
||||||
|
|
||||||
// StyleKeywords are reserved keywords which cannot exist outside of the "style" keyword
|
|
||||||
var StyleKeywords = map[string]struct{}{
|
|
||||||
"opacity": {},
|
|
||||||
"stroke": {},
|
|
||||||
"fill": {},
|
|
||||||
"fill-pattern": {},
|
|
||||||
"stroke-width": {},
|
|
||||||
"stroke-dash": {},
|
|
||||||
"border-radius": {},
|
|
||||||
|
|
||||||
// Only for text
|
|
||||||
"font": {},
|
|
||||||
"font-size": {},
|
|
||||||
"font-color": {},
|
|
||||||
"bold": {},
|
|
||||||
"italic": {},
|
|
||||||
"underline": {},
|
|
||||||
"text-transform": {},
|
|
||||||
|
|
||||||
// Only for shapes
|
|
||||||
"shadow": {},
|
|
||||||
"multiple": {},
|
|
||||||
"double-border": {},
|
|
||||||
|
|
||||||
// Only for squares
|
|
||||||
"3d": {},
|
|
||||||
|
|
||||||
// Only for edges
|
|
||||||
"animated": {},
|
|
||||||
"filled": {},
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO maybe autofmt should allow other values, and transform them to conform
|
|
||||||
// e.g. left-center becomes center-left
|
|
||||||
var NearConstantsArray = []string{
|
|
||||||
"top-left",
|
|
||||||
"top-center",
|
|
||||||
"top-right",
|
|
||||||
|
|
||||||
"center-left",
|
|
||||||
"center-right",
|
|
||||||
|
|
||||||
"bottom-left",
|
|
||||||
"bottom-center",
|
|
||||||
"bottom-right",
|
|
||||||
}
|
|
||||||
var NearConstants map[string]struct{}
|
|
||||||
|
|
||||||
// LabelPositionsArray are the values that labels and icons can set `near` to
|
|
||||||
var LabelPositionsArray = []string{
|
|
||||||
"top-left",
|
|
||||||
"top-center",
|
|
||||||
"top-right",
|
|
||||||
|
|
||||||
"center-left",
|
|
||||||
"center-center",
|
|
||||||
"center-right",
|
|
||||||
|
|
||||||
"bottom-left",
|
|
||||||
"bottom-center",
|
|
||||||
"bottom-right",
|
|
||||||
|
|
||||||
"outside-top-left",
|
|
||||||
"outside-top-center",
|
|
||||||
"outside-top-right",
|
|
||||||
|
|
||||||
"outside-left-top",
|
|
||||||
"outside-left-center",
|
|
||||||
"outside-left-bottom",
|
|
||||||
|
|
||||||
"outside-right-top",
|
|
||||||
"outside-right-center",
|
|
||||||
"outside-right-bottom",
|
|
||||||
|
|
||||||
"outside-bottom-left",
|
|
||||||
"outside-bottom-center",
|
|
||||||
"outside-bottom-right",
|
|
||||||
}
|
|
||||||
var LabelPositions map[string]struct{}
|
|
||||||
|
|
||||||
// convert to label.Position
|
|
||||||
var LabelPositionsMapping = map[string]label.Position{
|
|
||||||
"top-left": label.InsideTopLeft,
|
|
||||||
"top-center": label.InsideTopCenter,
|
|
||||||
"top-right": label.InsideTopRight,
|
|
||||||
|
|
||||||
"center-left": label.InsideMiddleLeft,
|
|
||||||
"center-center": label.InsideMiddleCenter,
|
|
||||||
"center-right": label.InsideMiddleRight,
|
|
||||||
|
|
||||||
"bottom-left": label.InsideBottomLeft,
|
|
||||||
"bottom-center": label.InsideBottomCenter,
|
|
||||||
"bottom-right": label.InsideBottomRight,
|
|
||||||
|
|
||||||
"outside-top-left": label.OutsideTopLeft,
|
|
||||||
"outside-top-center": label.OutsideTopCenter,
|
|
||||||
"outside-top-right": label.OutsideTopRight,
|
|
||||||
|
|
||||||
"outside-left-top": label.OutsideLeftTop,
|
|
||||||
"outside-left-center": label.OutsideLeftMiddle,
|
|
||||||
"outside-left-bottom": label.OutsideLeftBottom,
|
|
||||||
|
|
||||||
"outside-right-top": label.OutsideRightTop,
|
|
||||||
"outside-right-center": label.OutsideRightMiddle,
|
|
||||||
"outside-right-bottom": label.OutsideRightBottom,
|
|
||||||
|
|
||||||
"outside-bottom-left": label.OutsideBottomLeft,
|
|
||||||
"outside-bottom-center": label.OutsideBottomCenter,
|
|
||||||
"outside-bottom-right": label.OutsideBottomRight,
|
|
||||||
}
|
|
||||||
|
|
||||||
var FillPatterns = []string{
|
|
||||||
"none",
|
|
||||||
"dots",
|
|
||||||
"lines",
|
|
||||||
"grain",
|
|
||||||
"paper",
|
|
||||||
}
|
|
||||||
|
|
||||||
var textTransforms = []string{"none", "uppercase", "lowercase", "capitalize"}
|
|
||||||
|
|
||||||
// BoardKeywords contains the keywords that create new boards.
|
|
||||||
var BoardKeywords = map[string]struct{}{
|
|
||||||
"layers": {},
|
|
||||||
"scenarios": {},
|
|
||||||
"steps": {},
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
ReservedKeywords = make(map[string]struct{})
|
|
||||||
for k, v := range SimpleReservedKeywords {
|
|
||||||
ReservedKeywords[k] = v
|
|
||||||
}
|
|
||||||
for k, v := range StyleKeywords {
|
|
||||||
ReservedKeywords[k] = v
|
|
||||||
}
|
|
||||||
for k, v := range ReservedKeywordHolders {
|
|
||||||
CompositeReservedKeywords[k] = v
|
|
||||||
}
|
|
||||||
for k, v := range BoardKeywords {
|
|
||||||
CompositeReservedKeywords[k] = v
|
|
||||||
}
|
|
||||||
for k, v := range CompositeReservedKeywords {
|
|
||||||
ReservedKeywords[k] = v
|
|
||||||
}
|
|
||||||
|
|
||||||
NearConstants = make(map[string]struct{}, len(NearConstantsArray))
|
|
||||||
for _, k := range NearConstantsArray {
|
|
||||||
NearConstants[k] = struct{}{}
|
|
||||||
}
|
|
||||||
|
|
||||||
LabelPositions = make(map[string]struct{}, len(LabelPositionsArray))
|
|
||||||
for _, k := range LabelPositionsArray {
|
|
||||||
LabelPositions[k] = struct{}{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *Graph) GetBoard(name string) *Graph {
|
func (g *Graph) GetBoard(name string) *Graph {
|
||||||
for _, l := range g.Layers {
|
for _, l := range g.Layers {
|
||||||
if l.Name == name {
|
if l.Name == name {
|
||||||
|
|
|
||||||
17
d2ir/d2ir.go
17
d2ir/d2ir.go
|
|
@ -11,7 +11,6 @@ import (
|
||||||
|
|
||||||
"oss.terrastruct.com/d2/d2ast"
|
"oss.terrastruct.com/d2/d2ast"
|
||||||
"oss.terrastruct.com/d2/d2format"
|
"oss.terrastruct.com/d2/d2format"
|
||||||
"oss.terrastruct.com/d2/d2graph"
|
|
||||||
"oss.terrastruct.com/d2/d2parser"
|
"oss.terrastruct.com/d2/d2parser"
|
||||||
"oss.terrastruct.com/d2/d2target"
|
"oss.terrastruct.com/d2/d2target"
|
||||||
)
|
)
|
||||||
|
|
@ -624,7 +623,7 @@ func (m *Map) IsContainer() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
for _, f := range m.Fields {
|
for _, f := range m.Fields {
|
||||||
_, isReserved := d2graph.ReservedKeywords[f.Name]
|
_, isReserved := d2ast.ReservedKeywords[f.Name]
|
||||||
if !isReserved {
|
if !isReserved {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
@ -815,9 +814,9 @@ func (m *Map) ensureField(i int, kp *d2ast.KeyPath, refctx *RefContext, create b
|
||||||
|
|
||||||
head := kp.Path[i].Unbox().ScalarString()
|
head := kp.Path[i].Unbox().ScalarString()
|
||||||
|
|
||||||
if _, ok := d2graph.ReservedKeywords[strings.ToLower(head)]; ok {
|
if _, ok := d2ast.ReservedKeywords[strings.ToLower(head)]; ok {
|
||||||
head = strings.ToLower(head)
|
head = strings.ToLower(head)
|
||||||
if _, ok := d2graph.CompositeReservedKeywords[head]; !ok && i < len(kp.Path)-1 {
|
if _, ok := d2ast.CompositeReservedKeywords[head]; !ok && i < len(kp.Path)-1 {
|
||||||
return d2parser.Errorf(kp.Path[i].Unbox(), fmt.Sprintf(`"%s" must be the last part of the key`, head))
|
return d2parser.Errorf(kp.Path[i].Unbox(), fmt.Sprintf(`"%s" must be the last part of the key`, head))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -872,7 +871,7 @@ func (m *Map) ensureField(i int, kp *d2ast.KeyPath, refctx *RefContext, create b
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
shape := ParentShape(m)
|
shape := ParentShape(m)
|
||||||
if _, ok := d2graph.ReservedKeywords[strings.ToLower(head)]; !ok && len(c.globRefContextStack) > 0 {
|
if _, ok := d2ast.ReservedKeywords[strings.ToLower(head)]; !ok && len(c.globRefContextStack) > 0 {
|
||||||
if shape == d2target.ShapeClass || shape == d2target.ShapeSQLTable {
|
if shape == d2target.ShapeClass || shape == d2target.ShapeSQLTable {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -971,7 +970,7 @@ func (m *Map) DeleteField(ida ...string) *Field {
|
||||||
// If a field was deleted from a keyword-holder keyword and that holder is empty,
|
// If a field was deleted from a keyword-holder keyword and that holder is empty,
|
||||||
// then that holder becomes meaningless and should be deleted too
|
// then that holder becomes meaningless and should be deleted too
|
||||||
parent := ParentField(f)
|
parent := ParentField(f)
|
||||||
for keywordHolder := range d2graph.ReservedKeywordHolders {
|
for keywordHolder := range d2ast.ReservedKeywordHolders {
|
||||||
if parent != nil && parent.Name == keywordHolder && len(parent.Map().Fields) == 0 {
|
if parent != nil && parent.Name == keywordHolder && len(parent.Map().Fields) == 0 {
|
||||||
keywordHolderParentMap := ParentMap(parent)
|
keywordHolderParentMap := ParentMap(parent)
|
||||||
for i, f := range keywordHolderParentMap.Fields {
|
for i, f := range keywordHolderParentMap.Fields {
|
||||||
|
|
@ -1527,7 +1526,7 @@ func countUnderscores(p []string) int {
|
||||||
|
|
||||||
func findBoardKeyword(ida ...string) int {
|
func findBoardKeyword(ida ...string) int {
|
||||||
for i := range ida {
|
for i := range ida {
|
||||||
if _, ok := d2graph.BoardKeywords[ida[i]]; ok {
|
if _, ok := d2ast.BoardKeywords[ida[i]]; ok {
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1536,10 +1535,10 @@ func findBoardKeyword(ida ...string) int {
|
||||||
|
|
||||||
func findProhibitedEdgeKeyword(ida ...string) int {
|
func findProhibitedEdgeKeyword(ida ...string) int {
|
||||||
for i := range ida {
|
for i := range ida {
|
||||||
if _, ok := d2graph.SimpleReservedKeywords[ida[i]]; ok {
|
if _, ok := d2ast.SimpleReservedKeywords[ida[i]]; ok {
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
if _, ok := d2graph.ReservedKeywordHolders[ida[i]]; ok {
|
if _, ok := d2ast.ReservedKeywordHolders[ida[i]]; ok {
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"oss.terrastruct.com/d2/d2ast"
|
"oss.terrastruct.com/d2/d2ast"
|
||||||
"oss.terrastruct.com/d2/d2graph"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (m *Map) multiGlob(pattern []string) ([]*Field, bool) {
|
func (m *Map) multiGlob(pattern []string) ([]*Field, bool) {
|
||||||
|
|
@ -22,11 +21,11 @@ func (m *Map) multiGlob(pattern []string) ([]*Field, bool) {
|
||||||
|
|
||||||
func (m *Map) _doubleGlob(fa *[]*Field) {
|
func (m *Map) _doubleGlob(fa *[]*Field) {
|
||||||
for _, f := range m.Fields {
|
for _, f := range m.Fields {
|
||||||
if _, ok := d2graph.ReservedKeywords[f.Name]; ok {
|
if _, ok := d2ast.ReservedKeywords[f.Name]; ok {
|
||||||
if f.Name == "layers" {
|
if f.Name == "layers" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if _, ok := d2graph.BoardKeywords[f.Name]; !ok {
|
if _, ok := d2ast.BoardKeywords[f.Name]; !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// We don't ever want to append layers, scenarios or steps directly.
|
// We don't ever want to append layers, scenarios or steps directly.
|
||||||
|
|
@ -46,8 +45,8 @@ func (m *Map) _doubleGlob(fa *[]*Field) {
|
||||||
|
|
||||||
func (m *Map) _tripleGlob(fa *[]*Field) {
|
func (m *Map) _tripleGlob(fa *[]*Field) {
|
||||||
for _, f := range m.Fields {
|
for _, f := range m.Fields {
|
||||||
if _, ok := d2graph.ReservedKeywords[f.Name]; ok {
|
if _, ok := d2ast.ReservedKeywords[f.Name]; ok {
|
||||||
if _, ok := d2graph.BoardKeywords[f.Name]; !ok {
|
if _, ok := d2ast.BoardKeywords[f.Name]; !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// We don't ever want to append layers, scenarios or steps directly.
|
// We don't ever want to append layers, scenarios or steps directly.
|
||||||
|
|
@ -69,7 +68,7 @@ func matchPattern(s string, pattern []string) bool {
|
||||||
if len(pattern) == 0 {
|
if len(pattern) == 0 {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if _, ok := d2graph.ReservedKeywords[s]; ok {
|
if _, ok := d2ast.ReservedKeywords[s]; ok {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -372,7 +372,7 @@ func _set(g *d2graph.Graph, baseAST *d2ast.Map, key string, tag, value *string)
|
||||||
if mk.Key != nil {
|
if mk.Key != nil {
|
||||||
found := true
|
found := true
|
||||||
for _, idel := range d2graph.Key(mk.Key) {
|
for _, idel := range d2graph.Key(mk.Key) {
|
||||||
_, ok := d2graph.ReservedKeywords[idel]
|
_, ok := d2ast.ReservedKeywords[idel]
|
||||||
if ok {
|
if ok {
|
||||||
reserved = true
|
reserved = true
|
||||||
break
|
break
|
||||||
|
|
@ -544,7 +544,7 @@ func _set(g *d2graph.Graph, baseAST *d2ast.Map, key string, tag, value *string)
|
||||||
attrs = edge.Attributes
|
attrs = edge.Attributes
|
||||||
|
|
||||||
if mk.EdgeKey != nil {
|
if mk.EdgeKey != nil {
|
||||||
if _, ok := d2graph.ReservedKeywords[mk.EdgeKey.Path[0].Unbox().ScalarString()]; !ok {
|
if _, ok := d2ast.ReservedKeywords[mk.EdgeKey.Path[0].Unbox().ScalarString()]; !ok {
|
||||||
return errors.New("edge key must be reserved")
|
return errors.New("edge key must be reserved")
|
||||||
}
|
}
|
||||||
reserved = true
|
reserved = true
|
||||||
|
|
@ -856,7 +856,7 @@ func appendMapKey(m *d2ast.Map, mk *d2ast.Key) {
|
||||||
if len(m.Nodes) == 1 &&
|
if len(m.Nodes) == 1 &&
|
||||||
mk.Key != nil &&
|
mk.Key != nil &&
|
||||||
len(mk.Key.Path) > 0 {
|
len(mk.Key.Path) > 0 {
|
||||||
_, ok := d2graph.ReservedKeywords[mk.Key.Path[0].Unbox().ScalarString()]
|
_, ok := d2ast.ReservedKeywords[mk.Key.Path[0].Unbox().ScalarString()]
|
||||||
if ok {
|
if ok {
|
||||||
// Allow one line reserved key (like shape) maps.
|
// Allow one line reserved key (like shape) maps.
|
||||||
// TODO: This needs to be smarter as certain keys are only reserved in context.
|
// TODO: This needs to be smarter as certain keys are only reserved in context.
|
||||||
|
|
@ -1077,7 +1077,7 @@ func hoistRefChildren(g *d2graph.Graph, key *d2ast.KeyPath, ref d2graph.Referenc
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if n.MapKey.Key != nil {
|
if n.MapKey.Key != nil {
|
||||||
_, ok := d2graph.ReservedKeywords[n.MapKey.Key.Path[0].Unbox().ScalarString()]
|
_, ok := d2ast.ReservedKeywords[n.MapKey.Key.Path[0].Unbox().ScalarString()]
|
||||||
if ok {
|
if ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
@ -1130,7 +1130,7 @@ func renameConflictsToParent(g *d2graph.Graph, key *d2ast.KeyPath) (*d2graph.Gra
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if n.MapKey.Key != nil {
|
if n.MapKey.Key != nil {
|
||||||
_, ok := d2graph.ReservedKeywords[n.MapKey.Key.Path[0].Unbox().ScalarString()]
|
_, ok := d2ast.ReservedKeywords[n.MapKey.Key.Path[0].Unbox().ScalarString()]
|
||||||
if ok {
|
if ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
@ -1150,7 +1150,7 @@ func renameConflictsToParent(g *d2graph.Graph, key *d2ast.KeyPath) (*d2graph.Gra
|
||||||
absKey.Path = append(absKey.Path, k.Path[0])
|
absKey.Path = append(absKey.Path, k.Path[0])
|
||||||
absKeys = append(absKeys, absKey)
|
absKeys = append(absKeys, absKey)
|
||||||
}
|
}
|
||||||
} else if _, ok := d2graph.ReservedKeywords[ref.Key.Path[len(ref.Key.Path)-1].Unbox().ScalarString()]; !ok {
|
} else if _, ok := d2ast.ReservedKeywords[ref.Key.Path[len(ref.Key.Path)-1].Unbox().ScalarString()]; !ok {
|
||||||
absKey, err := d2parser.ParseKey(ref.ScopeObj.AbsID())
|
absKey, err := d2parser.ParseKey(ref.ScopeObj.AbsID())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
absKey = &d2ast.KeyPath{}
|
absKey = &d2ast.KeyPath{}
|
||||||
|
|
@ -1254,7 +1254,7 @@ func deleteReserved(g *d2graph.Graph, boardPath []string, baseAST *d2ast.Map, mk
|
||||||
}
|
}
|
||||||
targetKey = mk.EdgeKey
|
targetKey = mk.EdgeKey
|
||||||
}
|
}
|
||||||
_, ok := d2graph.ReservedKeywords[targetKey.Path[len(targetKey.Path)-1].Unbox().ScalarString()]
|
_, ok := d2ast.ReservedKeywords[targetKey.Path[len(targetKey.Path)-1].Unbox().ScalarString()]
|
||||||
if !ok {
|
if !ok {
|
||||||
return g, nil
|
return g, nil
|
||||||
}
|
}
|
||||||
|
|
@ -1297,7 +1297,7 @@ func deleteReserved(g *d2graph.Graph, boardPath []string, baseAST *d2ast.Map, mk
|
||||||
imported := false
|
imported := false
|
||||||
parts := d2graph.Key(targetKey)
|
parts := d2graph.Key(targetKey)
|
||||||
for i, id := range parts {
|
for i, id := range parts {
|
||||||
_, ok := d2graph.ReservedKeywords[id]
|
_, ok := d2ast.ReservedKeywords[id]
|
||||||
if ok {
|
if ok {
|
||||||
if id == "style" {
|
if id == "style" {
|
||||||
isNestedKey = true
|
isNestedKey = true
|
||||||
|
|
@ -1475,7 +1475,7 @@ func deleteObject(g *d2graph.Graph, baseAST *d2ast.Map, key *d2ast.KeyPath, obj
|
||||||
}
|
}
|
||||||
ref.Key.Path = append(ref.Key.Path[:ref.KeyPathIndex], ref.Key.Path[ref.KeyPathIndex+1:]...)
|
ref.Key.Path = append(ref.Key.Path[:ref.KeyPathIndex], ref.Key.Path[ref.KeyPathIndex+1:]...)
|
||||||
withoutSpecial := go2.Filter(ref.Key.Path, func(x *d2ast.StringBox) bool {
|
withoutSpecial := go2.Filter(ref.Key.Path, func(x *d2ast.StringBox) bool {
|
||||||
_, isReserved := d2graph.ReservedKeywords[x.Unbox().ScalarString()]
|
_, isReserved := d2ast.ReservedKeywords[x.Unbox().ScalarString()]
|
||||||
isSpecial := isReserved || x.Unbox().ScalarString() == "_"
|
isSpecial := isReserved || x.Unbox().ScalarString() == "_"
|
||||||
return !isSpecial
|
return !isSpecial
|
||||||
})
|
})
|
||||||
|
|
@ -1494,7 +1494,7 @@ func deleteObject(g *d2graph.Graph, baseAST *d2ast.Map, key *d2ast.KeyPath, obj
|
||||||
for i := 0; i < len(ref.MapKey.Value.Map.Nodes); i++ {
|
for i := 0; i < len(ref.MapKey.Value.Map.Nodes); i++ {
|
||||||
n := ref.MapKey.Value.Map.Nodes[i]
|
n := ref.MapKey.Value.Map.Nodes[i]
|
||||||
if n.MapKey != nil && n.MapKey.Key != nil {
|
if n.MapKey != nil && n.MapKey.Key != nil {
|
||||||
_, ok := d2graph.ReservedKeywords[n.MapKey.Key.Path[0].Unbox().ScalarString()]
|
_, ok := d2ast.ReservedKeywords[n.MapKey.Key.Path[0].Unbox().ScalarString()]
|
||||||
if ok {
|
if ok {
|
||||||
deleteFromMap(ref.MapKey.Value.Map, n.MapKey)
|
deleteFromMap(ref.MapKey.Value.Map, n.MapKey)
|
||||||
i--
|
i--
|
||||||
|
|
@ -1661,7 +1661,7 @@ func Rename(g *d2graph.Graph, boardPath []string, key, newName string) (_ *d2gra
|
||||||
mk2.Key = mk.Key
|
mk2.Key = mk.Key
|
||||||
mk = mk2
|
mk = mk2
|
||||||
} else {
|
} else {
|
||||||
_, ok := d2graph.ReservedKeywords[newName]
|
_, ok := d2ast.ReservedKeywords[newName]
|
||||||
if ok {
|
if ok {
|
||||||
return nil, "", fmt.Errorf("cannot rename to reserved keyword: %#v", newName)
|
return nil, "", fmt.Errorf("cannot rename to reserved keyword: %#v", newName)
|
||||||
}
|
}
|
||||||
|
|
@ -1686,7 +1686,7 @@ func Rename(g *d2graph.Graph, boardPath []string, key, newName string) (_ *d2gra
|
||||||
|
|
||||||
func trimReservedSuffix(path []*d2ast.StringBox) []*d2ast.StringBox {
|
func trimReservedSuffix(path []*d2ast.StringBox) []*d2ast.StringBox {
|
||||||
for i, p := range path {
|
for i, p := range path {
|
||||||
if _, ok := d2graph.ReservedKeywords[p.Unbox().ScalarString()]; ok {
|
if _, ok := d2ast.ReservedKeywords[p.Unbox().ScalarString()]; ok {
|
||||||
return path[:i]
|
return path[:i]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1933,9 +1933,9 @@ func move(g *d2graph.Graph, boardPath []string, key, newKey string, includeDesce
|
||||||
ida = resolvedIDA
|
ida = resolvedIDA
|
||||||
}
|
}
|
||||||
// e.g. "a.b.shape: circle"
|
// e.g. "a.b.shape: circle"
|
||||||
_, endsWithReserved := d2graph.ReservedKeywords[ida[len(ida)-1]]
|
_, endsWithReserved := d2ast.ReservedKeywords[ida[len(ida)-1]]
|
||||||
ida = go2.Filter(ida, func(x string) bool {
|
ida = go2.Filter(ida, func(x string) bool {
|
||||||
_, ok := d2graph.ReservedKeywords[x]
|
_, ok := d2ast.ReservedKeywords[x]
|
||||||
return !ok
|
return !ok
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -1976,7 +1976,7 @@ func move(g *d2graph.Graph, boardPath []string, key, newKey string, includeDesce
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if n.MapKey.Key != nil {
|
if n.MapKey.Key != nil {
|
||||||
_, ok := d2graph.ReservedKeywords[n.MapKey.Key.Path[0].Unbox().ScalarString()]
|
_, ok := d2ast.ReservedKeywords[n.MapKey.Key.Path[0].Unbox().ScalarString()]
|
||||||
if ok {
|
if ok {
|
||||||
detachedMK.Value.Map.Nodes = append(detachedMK.Value.Map.Nodes, n)
|
detachedMK.Value.Map.Nodes = append(detachedMK.Value.Map.Nodes, n)
|
||||||
}
|
}
|
||||||
|
|
@ -2222,7 +2222,7 @@ func filterReserved(value d2ast.ValueBox) (with, without d2ast.ValueBox) {
|
||||||
forWithout = append(forWithout, n)
|
forWithout = append(forWithout, n)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
_, ok := d2graph.ReservedKeywords[n.MapKey.Key.Path[0].Unbox().ScalarString()]
|
_, ok := d2ast.ReservedKeywords[n.MapKey.Key.Path[0].Unbox().ScalarString()]
|
||||||
if !ok {
|
if !ok {
|
||||||
flushComments(&forWithout)
|
flushComments(&forWithout)
|
||||||
forWithout = append(forWithout, n)
|
forWithout = append(forWithout, n)
|
||||||
|
|
@ -2299,7 +2299,7 @@ func updateNear(prevG, g *d2graph.Graph, from, to *string, includeDescendants bo
|
||||||
}
|
}
|
||||||
if n.MapKey.Key.Path[len(n.MapKey.Key.Path)-1].Unbox().ScalarString() == "near" {
|
if n.MapKey.Key.Path[len(n.MapKey.Key.Path)-1].Unbox().ScalarString() == "near" {
|
||||||
k := n.MapKey.Value.ScalarBox().Unbox().ScalarString()
|
k := n.MapKey.Value.ScalarBox().Unbox().ScalarString()
|
||||||
if _, ok := d2graph.NearConstants[k]; ok {
|
if _, ok := d2ast.NearConstants[k]; ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if strings.EqualFold(k, *from) && to == nil {
|
if strings.EqualFold(k, *from) && to == nil {
|
||||||
|
|
@ -2925,7 +2925,7 @@ func DeleteIDDeltas(g *d2graph.Graph, boardPath []string, key string) (deltas ma
|
||||||
if mk.Key != nil {
|
if mk.Key != nil {
|
||||||
ida := d2graph.Key(mk.Key)
|
ida := d2graph.Key(mk.Key)
|
||||||
// Deleting a reserved field cannot possibly have any deltas
|
// Deleting a reserved field cannot possibly have any deltas
|
||||||
if _, ok := d2graph.ReservedKeywords[ida[len(ida)-1]]; ok {
|
if _, ok := d2ast.ReservedKeywords[ida[len(ida)-1]]; ok {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3256,7 +3256,7 @@ func getMostNestedRefs(obj *d2graph.Object) []d2graph.Reference {
|
||||||
|
|
||||||
func filterReservedPath(path []*d2ast.StringBox) (filtered []*d2ast.StringBox) {
|
func filterReservedPath(path []*d2ast.StringBox) (filtered []*d2ast.StringBox) {
|
||||||
for _, box := range path {
|
for _, box := range path {
|
||||||
if _, ok := d2graph.ReservedKeywords[strings.ToLower(box.Unbox().ScalarString())]; ok {
|
if _, ok := d2ast.ReservedKeywords[strings.ToLower(box.Unbox().ScalarString())]; ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
filtered = append(filtered, box)
|
filtered = append(filtered, box)
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"github.com/alecthomas/chroma/v2/lexers"
|
"github.com/alecthomas/chroma/v2/lexers"
|
||||||
"github.com/alecthomas/chroma/v2/styles"
|
"github.com/alecthomas/chroma/v2/styles"
|
||||||
|
|
||||||
|
"oss.terrastruct.com/d2/d2ast"
|
||||||
"oss.terrastruct.com/d2/d2graph"
|
"oss.terrastruct.com/d2/d2graph"
|
||||||
"oss.terrastruct.com/d2/d2renderers/d2fonts"
|
"oss.terrastruct.com/d2/d2renderers/d2fonts"
|
||||||
"oss.terrastruct.com/d2/d2renderers/d2latex"
|
"oss.terrastruct.com/d2/d2renderers/d2latex"
|
||||||
|
|
@ -1975,7 +1976,7 @@ func Render(diagram *d2target.Diagram, opts *RenderOpts) ([]byte, error) {
|
||||||
|
|
||||||
bufStr := buf.String()
|
bufStr := buf.String()
|
||||||
patternDefs := ""
|
patternDefs := ""
|
||||||
for _, pattern := range d2graph.FillPatterns {
|
for _, pattern := range d2ast.FillPatterns {
|
||||||
if strings.Contains(bufStr, fmt.Sprintf("%s-overlay", pattern)) || diagram.Root.FillPattern == pattern {
|
if strings.Contains(bufStr, fmt.Sprintf("%s-overlay", pattern)) || diagram.Root.FillPattern == pattern {
|
||||||
if patternDefs == "" {
|
if patternDefs == "" {
|
||||||
fmt.Fprint(upperBuf, `<style type="text/css"><![CDATA[`)
|
fmt.Fprint(upperBuf, `<style type="text/css"><![CDATA[`)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue