diff --git a/examples/classes.d2 b/examples/classes.d2 new file mode 100644 index 0000000..6ca1dcf --- /dev/null +++ b/examples/classes.d2 @@ -0,0 +1,34 @@ +direction: right +classes: { + load balancer { + label: load\nbalancer + width: 100 + height: 200 + style: { + stroke-width: 0 + fill: "#44C7B1" + shadow: true + border-radius: 5 + } + } + unhealthy: { + style: { + fill: "#FE7070" + stroke: "#F69E03" + } + } +} + +web traffic -> web lb +web lb.class: load balancer + +web lb -> api1 +web lb -> api2 +web lb -> api3 + +api2.class: unhealthy + +api1 -> cache lb +api3 -> cache lb + +cache lb.class: load balancer diff --git a/flake.lock b/flake.lock index a6d455d..197a9a8 100644 --- a/flake.lock +++ b/flake.lock @@ -15,13 +15,28 @@ "type": "github" } }, + "flake-utils_2": { + "locked": { + "lastModified": 1678901627, + "narHash": "sha256-U02riOqrKKzwjsxc/400XnElV+UtPUQWpANPlyazjH0=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "93a2b84fc4b70d9e089d029deacc3583435c2ed6", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, "nixpkgs": { "locked": { - "lastModified": 1669927173, - "narHash": "sha256-Z7rSKzC5OuWv5Q7RRNQPZb0jVJRJk0BJB6/fGZzaAIU=", + "lastModified": 1686737040, + "narHash": "sha256-R+JicNaI9mcxodtHkci894txjt4IMsfOnlAarA/r0xQ=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "9063accddd2e68dcc71032459a58399e977374c9", + "rev": "6d1d80a232a355a65dc4d3bfea1f108e8dac1340", "type": "github" }, "original": { @@ -31,10 +46,114 @@ "type": "github" } }, + "nixpkgs_2": { + "locked": { + "lastModified": 1680005833, + "narHash": "sha256-BTMEjs+7hpmaP3n4hFVddrObMssANidP4EHgSpB0Lk0=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "bd4e35e14a0130268c8f7b253a15e09d76ec95b7", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_volar": { + "locked": { + "lastModified": 1682598396, + "narHash": "sha256-vheqVF2Cfa2+gpqeymDukd/7ecNp+eamV5Ll0S9ElQ8=", + "owner": "ehllie", + "repo": "nixpkgs", + "rev": "fc9529215f7ebd9ff5a5c498c60f781f0beeaedd", + "type": "github" + }, + "original": { + "owner": "ehllie", + "ref": "volar", + "repo": "nixpkgs", + "type": "github" + } + }, + "poetry2nix": { + "inputs": { + "flake-utils": [ + "tools", + "flake-utils" + ], + "nixpkgs": [ + "tools", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1679994832, + "narHash": "sha256-LSsvtnkambdSWeNYT8wWTjSFVFyyIYxrI77QDfzUCHI=", + "owner": "nix-community", + "repo": "poetry2nix", + "rev": "2a72eea5fbccc262855c87e3032837f8465db385", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "poetry2nix", + "type": "github" + } + }, "root": { "inputs": { "flake-utils": "flake-utils", - "nixpkgs": "nixpkgs" + "nixpkgs": "nixpkgs", + "tools": "tools" + } + }, + "tools": { + "inputs": { + "flake-utils": "flake-utils_2", + "nixpkgs": "nixpkgs_2", + "nixpkgs_volar": "nixpkgs_volar", + "poetry2nix": "poetry2nix", + "wd2": "wd2" + }, + "locked": { + "lastModified": 1686758138, + "narHash": "sha256-aisJq5OU8qcvt82B6eSm8kOEukPAn7R5Qz9nIx1e7UQ=", + "ref": "refs/heads/main", + "rev": "32e27cb105f1ed5c7ee89032be6fb1a087eaa977", + "revCount": 44, + "type": "git", + "url": "https://git.pleshevski.ru/mynix/tools" + }, + "original": { + "type": "git", + "url": "https://git.pleshevski.ru/mynix/tools" + } + }, + "wd2": { + "inputs": { + "flake-utils": [ + "tools", + "flake-utils" + ], + "nixpkgs": [ + "tools", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1680536082, + "narHash": "sha256-vGZxdADceCFjJAEuNYkpEvAPT8SD4Wd0cGSlhHTBDZk=", + "ref": "refs/heads/main", + "rev": "c4f9e3ea2679800dc04dc02957a8b460b2fc36cc", + "revCount": 22, + "type": "git", + "url": "https://git.pleshevski.ru/pleshevskiy/wd2" + }, + "original": { + "type": "git", + "url": "https://git.pleshevski.ru/pleshevskiy/wd2" } } }, diff --git a/flake.nix b/flake.nix index d35a900..e6d9597 100644 --- a/flake.nix +++ b/flake.nix @@ -2,9 +2,10 @@ inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; flake-utils.url = "github:numtide/flake-utils"; + tools.url = "git+https://git.pleshevski.ru/mynix/tools"; }; - outputs = { self, nixpkgs, flake-utils, ... }: + outputs = { self, nixpkgs, flake-utils, tools, ... }: flake-utils.lib.eachDefaultSystem (system: let pkgs = import nixpkgs { inherit system; }; @@ -13,6 +14,7 @@ devShells.default = pkgs.mkShell { packages = with pkgs; [ jq + tools.packages.${system}.d2 nodejs-18_x tree-sitter nodePackages.eslint diff --git a/grammar.js b/grammar.js index b9987e6..49315ef 100644 --- a/grammar.js +++ b/grammar.js @@ -6,6 +6,7 @@ const PREC = { CONTAINER: 2, CONNECTION: 2, SHAPE: 3, + CLASSES: 4, IDENTIFIER: 0, ARROW: 0, ATTRIBUTE: 0, @@ -33,6 +34,9 @@ module.exports = grammar({ [$._container_block], [$._connection_block], [$._style_attribute_block], + [$._classes_block], + [$._classes_item_block], + [$.class_list], ], rules: { @@ -44,6 +48,7 @@ module.exports = grammar({ seq( choice( alias($._root_attribute, $.attribute), + $.classes, $.shape, $.container, $.connection @@ -82,6 +87,57 @@ module.exports = grammar({ "}" ), + // classes + + classes: ($) => + prec( + PREC.CLASSES, + seq( + $.keyword_classes, + choice( + optional(seq($.dot, $._classes_item)), + seq( + optional(seq($._colon, optional($.label))), + optional(alias($._classes_block, $.block)) + ) + ) + ) + ), + + _classes_block: ($) => + seq( + "{", + repeat(choice($._eol, seq($._classes_item, $._end))), + optional(seq($._classes_item, optional($._end))), + "}" + ), + + _classes_item: ($) => + seq( + $._class_name, + choice( + optional(seq($.dot, $._shape_attribute)), + seq( + optional(seq($._colon, optional($.label))), + optional(alias($._classes_item_block, $.class_block)) + ) + ) + ), + + _classes_item_block: ($) => + seq( + "{", + repeat(choice($._eol, seq($._classes_item_attribute, $._end))), + optional(seq($._classes_item_attribute, optional($._end))), + "}" + ), + + _classes_item_attribute: ($) => + choice( + alias($._base_shape_attribute, $.attribute), + alias($._style_attribute, $.attribute) + ), + // containers container: ($) => @@ -93,7 +149,7 @@ module.exports = grammar({ seq($.dot, choice($.shape, $.container)), seq( optional(seq($._colon, optional($.label))), - optional(seq(alias($._container_block, $.block))) + optional(alias($._container_block, $.block)) ) ) ) @@ -119,8 +175,8 @@ module.exports = grammar({ $.shape_key, optional( choice( - seq($.dot, alias($._style_attribute, $.attribute)), - seq(optional(seq($._colon, choice($.label, $.text_block)))) + seq($.dot, $._shape_attribute), + seq($._colon, choice($.label, $.text_block)) ) ) ) @@ -168,7 +224,7 @@ module.exports = grammar({ "label", "constraint", "icon", - "style", + $.keyword_style, $._common_style_attr_key, $._text_attr_key ), @@ -177,11 +233,24 @@ module.exports = grammar({ ), _shape_attribute: ($) => - choice( - alias($._base_shape_attribute, $.attribute), - alias($._style_attribute, $.attribute) + alias( + choice($._class_attribute, $._base_shape_attribute, $._style_attribute), + $.attribute ), + _class_attribute: ($) => + seq($.keyword_class, $._colon, choice($.class_list, $._class_name)), + + class_list: ($) => + seq( + "[", + repeat(choice($._eol, seq($._class_name, $._end))), + optional(seq($._class_name, optional($._end))), + "]" + ), + + _class_name: ($) => alias($.shape_key, $.class_name), + _base_shape_attribute: ($) => seq(alias($._shape_attr_key, $.attr_key), $._colon, $.attr_value), @@ -208,7 +277,7 @@ module.exports = grammar({ prec( PREC.ATTRIBUTE, seq( - alias("style", $.attr_key), + $.keyword_style, choice( seq($.dot, alias($._inner_style_attribute, $.attribute)), seq($._colon, alias($._style_attribute_block, $.block)) @@ -245,6 +314,7 @@ module.exports = grammar({ "grid-columns", "grid-rows" ), + _style_attr_key: ($) => choice($._common_style_attr_key, "3d"), _common_style_attr_key: ($) => @@ -295,6 +365,10 @@ module.exports = grammar({ _connection_arrowhead_attr_key: ($) => choice("source-arrowhead", "target-arrowhead"), + keyword_classes: (_) => "classes", + keyword_class: (_) => "class", + keyword_style: (_) => "style", + // label: ($) => choice($.string, $._unquoted_string), diff --git a/queries/highlights.scm b/queries/highlights.scm index b3f4cee..9484360 100644 --- a/queries/highlights.scm +++ b/queries/highlights.scm @@ -1,9 +1,15 @@ ;------------------------------------------------------------------------------- -(container_key) @constant +(container_key) @string.special (shape_key) @variable (attr_key) @property (reserved) @error +[ + (keyword_style) + (keyword_classes) + (keyword_class) +] @keyword +(class_name) @constant ; Literals ;------------------------------------------------------------------------------- @@ -37,6 +43,8 @@ ] @punctuation.delimiter [ + "[" + "]" "{" "}" "|" diff --git a/src/grammar.json b/src/grammar.json index 08bf7eb..6a69750 100644 --- a/src/grammar.json +++ b/src/grammar.json @@ -30,6 +30,10 @@ "named": true, "value": "attribute" }, + { + "type": "SYMBOL", + "name": "classes" + }, { "type": "SYMBOL", "name": "shape" @@ -251,6 +255,339 @@ } ] }, + "classes": { + "type": "PREC", + "value": 4, + "content": { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "keyword_classes" + }, + { + "type": "CHOICE", + "members": [ + { + "type": "CHOICE", + "members": [ + { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "dot" + }, + { + "type": "SYMBOL", + "name": "_classes_item" + } + ] + }, + { + "type": "BLANK" + } + ] + }, + { + "type": "SEQ", + "members": [ + { + "type": "CHOICE", + "members": [ + { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "_colon" + }, + { + "type": "CHOICE", + "members": [ + { + "type": "SYMBOL", + "name": "label" + }, + { + "type": "BLANK" + } + ] + } + ] + }, + { + "type": "BLANK" + } + ] + }, + { + "type": "CHOICE", + "members": [ + { + "type": "ALIAS", + "content": { + "type": "SYMBOL", + "name": "_classes_block" + }, + "named": true, + "value": "block" + }, + { + "type": "BLANK" + } + ] + } + ] + } + ] + } + ] + } + }, + "_classes_block": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "{" + }, + { + "type": "REPEAT", + "content": { + "type": "CHOICE", + "members": [ + { + "type": "SYMBOL", + "name": "_eol" + }, + { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "_classes_item" + }, + { + "type": "SYMBOL", + "name": "_end" + } + ] + } + ] + } + }, + { + "type": "CHOICE", + "members": [ + { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "_classes_item" + }, + { + "type": "CHOICE", + "members": [ + { + "type": "SYMBOL", + "name": "_end" + }, + { + "type": "BLANK" + } + ] + } + ] + }, + { + "type": "BLANK" + } + ] + }, + { + "type": "STRING", + "value": "}" + } + ] + }, + "_classes_item": { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "_class_name" + }, + { + "type": "CHOICE", + "members": [ + { + "type": "CHOICE", + "members": [ + { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "dot" + }, + { + "type": "SYMBOL", + "name": "_shape_attribute" + } + ] + }, + { + "type": "BLANK" + } + ] + }, + { + "type": "SEQ", + "members": [ + { + "type": "CHOICE", + "members": [ + { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "_colon" + }, + { + "type": "CHOICE", + "members": [ + { + "type": "SYMBOL", + "name": "label" + }, + { + "type": "BLANK" + } + ] + } + ] + }, + { + "type": "BLANK" + } + ] + }, + { + "type": "CHOICE", + "members": [ + { + "type": "ALIAS", + "content": { + "type": "SYMBOL", + "name": "_classes_item_block" + }, + "named": true, + "value": "class_block" + }, + { + "type": "BLANK" + } + ] + } + ] + } + ] + } + ] + }, + "_classes_item_block": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "{" + }, + { + "type": "REPEAT", + "content": { + "type": "CHOICE", + "members": [ + { + "type": "SYMBOL", + "name": "_eol" + }, + { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "_classes_item_attribute" + }, + { + "type": "SYMBOL", + "name": "_end" + } + ] + } + ] + } + }, + { + "type": "CHOICE", + "members": [ + { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "_classes_item_attribute" + }, + { + "type": "CHOICE", + "members": [ + { + "type": "SYMBOL", + "name": "_end" + }, + { + "type": "BLANK" + } + ] + } + ] + }, + { + "type": "BLANK" + } + ] + }, + { + "type": "STRING", + "value": "}" + } + ] + }, + "_classes_item_attribute": { + "type": "CHOICE", + "members": [ + { + "type": "ALIAS", + "content": { + "type": "SYMBOL", + "name": "_base_shape_attribute" + }, + "named": true, + "value": "attribute" + }, + { + "type": "ALIAS", + "content": { + "type": "SYMBOL", + "name": "_style_attribute" + }, + "named": true, + "value": "attribute" + } + ] + }, "container": { "type": "PREC", "value": 2, @@ -327,18 +664,13 @@ "type": "CHOICE", "members": [ { - "type": "SEQ", - "members": [ - { - "type": "ALIAS", - "content": { - "type": "SYMBOL", - "name": "_container_block" - }, - "named": true, - "value": "block" - } - ] + "type": "ALIAS", + "content": { + "type": "SYMBOL", + "name": "_container_block" + }, + "named": true, + "value": "block" }, { "type": "BLANK" @@ -464,46 +796,28 @@ "name": "dot" }, { - "type": "ALIAS", - "content": { - "type": "SYMBOL", - "name": "_style_attribute" - }, - "named": true, - "value": "attribute" + "type": "SYMBOL", + "name": "_shape_attribute" } ] }, { "type": "SEQ", "members": [ + { + "type": "SYMBOL", + "name": "_colon" + }, { "type": "CHOICE", "members": [ { - "type": "SEQ", - "members": [ - { - "type": "SYMBOL", - "name": "_colon" - }, - { - "type": "CHOICE", - "members": [ - { - "type": "SYMBOL", - "name": "label" - }, - { - "type": "SYMBOL", - "name": "text_block" - } - ] - } - ] + "type": "SYMBOL", + "name": "label" }, { - "type": "BLANK" + "type": "SYMBOL", + "name": "text_block" } ] } @@ -704,8 +1018,8 @@ "value": "icon" }, { - "type": "STRING", - "value": "style" + "type": "SYMBOL", + "name": "keyword_style" }, { "type": "SYMBOL", @@ -723,28 +1037,129 @@ ] }, "_shape_attribute": { - "type": "CHOICE", - "members": [ - { - "type": "ALIAS", - "content": { + "type": "ALIAS", + "content": { + "type": "CHOICE", + "members": [ + { + "type": "SYMBOL", + "name": "_class_attribute" + }, + { "type": "SYMBOL", "name": "_base_shape_attribute" }, - "named": true, - "value": "attribute" - }, - { - "type": "ALIAS", - "content": { + { "type": "SYMBOL", "name": "_style_attribute" - }, - "named": true, - "value": "attribute" + } + ] + }, + "named": true, + "value": "attribute" + }, + "_class_attribute": { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "keyword_class" + }, + { + "type": "SYMBOL", + "name": "_colon" + }, + { + "type": "CHOICE", + "members": [ + { + "type": "SYMBOL", + "name": "class_list" + }, + { + "type": "SYMBOL", + "name": "_class_name" + } + ] } ] }, + "class_list": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "[" + }, + { + "type": "REPEAT", + "content": { + "type": "CHOICE", + "members": [ + { + "type": "SYMBOL", + "name": "_eol" + }, + { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "_class_name" + }, + { + "type": "SYMBOL", + "name": "_end" + } + ] + } + ] + } + }, + { + "type": "CHOICE", + "members": [ + { + "type": "SEQ", + "members": [ + { + "type": "SYMBOL", + "name": "_class_name" + }, + { + "type": "CHOICE", + "members": [ + { + "type": "SYMBOL", + "name": "_end" + }, + { + "type": "BLANK" + } + ] + } + ] + }, + { + "type": "BLANK" + } + ] + }, + { + "type": "STRING", + "value": "]" + } + ] + }, + "_class_name": { + "type": "ALIAS", + "content": { + "type": "SYMBOL", + "name": "shape_key" + }, + "named": true, + "value": "class_name" + }, "_base_shape_attribute": { "type": "SEQ", "members": [ @@ -823,13 +1238,8 @@ "type": "SEQ", "members": [ { - "type": "ALIAS", - "content": { - "type": "STRING", - "value": "style" - }, - "named": true, - "value": "attr_key" + "type": "SYMBOL", + "name": "keyword_style" }, { "type": "CHOICE", @@ -1264,6 +1674,18 @@ } ] }, + "keyword_classes": { + "type": "STRING", + "value": "classes" + }, + "keyword_class": { + "type": "STRING", + "value": "class" + }, + "keyword_style": { + "type": "STRING", + "value": "style" + }, "label": { "type": "CHOICE", "members": [ @@ -1591,6 +2013,15 @@ ], [ "_style_attribute_block" + ], + [ + "_classes_block" + ], + [ + "_classes_item_block" + ], + [ + "class_list" ] ], "precedences": [], diff --git a/src/node-types.json b/src/node-types.json index 18b88b5..45b6b0d 100644 --- a/src/node-types.json +++ b/src/node-types.json @@ -69,10 +69,26 @@ "type": "block", "named": true }, + { + "type": "class_list", + "named": true + }, + { + "type": "class_name", + "named": true + }, { "type": "dot", "named": true }, + { + "type": "keyword_class", + "named": true + }, + { + "type": "keyword_style", + "named": true + }, { "type": "label", "named": true @@ -92,6 +108,14 @@ "type": "attribute", "named": true }, + { + "type": "class_block", + "named": true + }, + { + "type": "class_name", + "named": true + }, { "type": "connection", "named": true @@ -100,6 +124,14 @@ "type": "container", "named": true }, + { + "type": "dot", + "named": true + }, + { + "type": "label", + "named": true + }, { "type": "shape", "named": true @@ -112,6 +144,94 @@ "named": true, "fields": {} }, + { + "type": "class_block", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": false, + "types": [ + { + "type": "attribute", + "named": true + } + ] + } + }, + { + "type": "class_list", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": false, + "types": [ + { + "type": "class_name", + "named": true + } + ] + } + }, + { + "type": "class_name", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": false, + "types": [ + { + "type": "escape_sequence", + "named": true + }, + { + "type": "string", + "named": true + } + ] + } + }, + { + "type": "classes", + "named": true, + "fields": {}, + "children": { + "multiple": true, + "required": true, + "types": [ + { + "type": "attribute", + "named": true + }, + { + "type": "block", + "named": true + }, + { + "type": "class_block", + "named": true + }, + { + "type": "class_name", + "named": true + }, + { + "type": "dot", + "named": true + }, + { + "type": "keyword_classes", + "named": true + }, + { + "type": "label", + "named": true + } + ] + } + }, { "type": "connection", "named": true, @@ -287,6 +407,10 @@ "type": "attribute", "named": true }, + { + "type": "classes", + "named": true + }, { "type": "connection", "named": true @@ -364,6 +488,14 @@ "type": ";", "named": false }, + { + "type": "[", + "named": false + }, + { + "type": "]", + "named": false + }, { "type": "animated", "named": false @@ -460,6 +592,18 @@ "type": "italic", "named": false }, + { + "type": "keyword_class", + "named": true + }, + { + "type": "keyword_classes", + "named": true + }, + { + "type": "keyword_style", + "named": true + }, { "type": "label", "named": false diff --git a/src/parser.c b/src/parser.c index e9074d9..f80d5ff 100644 Binary files a/src/parser.c and b/src/parser.c differ diff --git a/test/corpus/attributes.txt b/test/corpus/attributes.txt index 6e580a6..5e98b4f 100644 --- a/test/corpus/attributes.txt +++ b/test/corpus/attributes.txt @@ -62,18 +62,18 @@ foo.style.text-transform: uppercase -------------------------------------------------------------------------------- (source_file - (shape (shape_key) (dot) (attribute (attr_key) (dot) (attribute (attr_key) (attr_value (float))))) - (shape (shape_key) (dot) (attribute (attr_key) (dot) (attribute (attr_key) (attr_value)))) - (shape (shape_key) (dot) (attribute (attr_key) (dot) (attribute (attr_key) (attr_value)))) - (shape (shape_key) (dot) (attribute (attr_key) (dot) (attribute (attr_key) (attr_value (integer))))) - (shape (shape_key) (dot) (attribute (attr_key) (dot) (attribute (attr_key) (attr_value (integer))))) - (shape (shape_key) (dot) (attribute (attr_key) (dot) (attribute (attr_key) (attr_value (integer))))) - (shape (shape_key) (dot) (attribute (attr_key) (dot) (attribute (attr_key) (attr_value)))) - (shape (shape_key) (dot) (attribute (attr_key) (dot) (attribute (attr_key) (attr_value (boolean))))) - (shape (shape_key) (dot) (attribute (attr_key) (dot) (attribute (attr_key) (attr_value (boolean))))) - (shape (shape_key) (dot) (attribute (attr_key) (dot) (attribute (attr_key) (attr_value (boolean))))) - (shape (shape_key) (dot) (attribute (attr_key) (dot) (attribute (attr_key) (attr_value)))) - (shape (shape_key) (dot) (attribute (attr_key) (dot) (attribute (attr_key) (attr_value)))) + (shape (shape_key) (dot) (attribute (keyword_style) (dot) (attribute (attr_key) (attr_value (float))))) + (shape (shape_key) (dot) (attribute (keyword_style) (dot) (attribute (attr_key) (attr_value)))) + (shape (shape_key) (dot) (attribute (keyword_style) (dot) (attribute (attr_key) (attr_value)))) + (shape (shape_key) (dot) (attribute (keyword_style) (dot) (attribute (attr_key) (attr_value (integer))))) + (shape (shape_key) (dot) (attribute (keyword_style) (dot) (attribute (attr_key) (attr_value (integer))))) + (shape (shape_key) (dot) (attribute (keyword_style) (dot) (attribute (attr_key) (attr_value (integer))))) + (shape (shape_key) (dot) (attribute (keyword_style) (dot) (attribute (attr_key) (attr_value)))) + (shape (shape_key) (dot) (attribute (keyword_style) (dot) (attribute (attr_key) (attr_value (boolean))))) + (shape (shape_key) (dot) (attribute (keyword_style) (dot) (attribute (attr_key) (attr_value (boolean))))) + (shape (shape_key) (dot) (attribute (keyword_style) (dot) (attribute (attr_key) (attr_value (boolean))))) + (shape (shape_key) (dot) (attribute (keyword_style) (dot) (attribute (attr_key) (attr_value)))) + (shape (shape_key) (dot) (attribute (keyword_style) (dot) (attribute (attr_key) (attr_value)))) ) ================================================================================ @@ -100,7 +100,7 @@ foo.style: { (shape (shape_key) (dot) (attribute - (attr_key) + (keyword_style) (block (attribute (attr_key) (attr_value (float))) (attribute (attr_key) (attr_value)) @@ -174,17 +174,17 @@ foo: { (container (container_key) (block - (attribute (attr_key) (dot) (attribute (attr_key) (attr_value (float)))) - (attribute (attr_key) (dot) (attribute (attr_key) (attr_value))) - (attribute (attr_key) (dot) (attribute (attr_key) (attr_value))) - (attribute (attr_key) (dot) (attribute (attr_key) (attr_value (integer)))) - (attribute (attr_key) (dot) (attribute (attr_key) (attr_value (integer)))) - (attribute (attr_key) (dot) (attribute (attr_key) (attr_value (integer)))) - (attribute (attr_key) (dot) (attribute (attr_key) (attr_value))) - (attribute (attr_key) (dot) (attribute (attr_key) (attr_value (boolean)))) - (attribute (attr_key) (dot) (attribute (attr_key) (attr_value (boolean)))) - (attribute (attr_key) (dot) (attribute (attr_key) (attr_value (boolean)))) - (attribute (attr_key) (dot) (attribute (attr_key) (attr_value))) + (attribute (keyword_style) (dot) (attribute (attr_key) (attr_value (float)))) + (attribute (keyword_style) (dot) (attribute (attr_key) (attr_value))) + (attribute (keyword_style) (dot) (attribute (attr_key) (attr_value))) + (attribute (keyword_style) (dot) (attribute (attr_key) (attr_value (integer)))) + (attribute (keyword_style) (dot) (attribute (attr_key) (attr_value (integer)))) + (attribute (keyword_style) (dot) (attribute (attr_key) (attr_value (integer)))) + (attribute (keyword_style) (dot) (attribute (attr_key) (attr_value))) + (attribute (keyword_style) (dot) (attribute (attr_key) (attr_value (boolean)))) + (attribute (keyword_style) (dot) (attribute (attr_key) (attr_value (boolean)))) + (attribute (keyword_style) (dot) (attribute (attr_key) (attr_value (boolean)))) + (attribute (keyword_style) (dot) (attribute (attr_key) (attr_value))) ) ) ) @@ -215,7 +215,7 @@ foo: { (container_key) (block (attribute - (attr_key) + (keyword_style) (block (attribute (attr_key) (attr_value (float))) (attribute (attr_key) (attr_value)) @@ -262,7 +262,7 @@ foo -> bar: { (shape_key) (block (attribute - (attr_key) + (keyword_style) (block (attribute (attr_key) (attr_value (float))) (attribute (attr_key) (attr_value)) @@ -367,7 +367,7 @@ foo -> bar: { (attr_key) (block (attribute - (attr_key) + (keyword_style) (block (attribute (attr_key) (attr_value (float))) (attribute (attr_key) (attr_value)) @@ -436,7 +436,7 @@ foo.style: {opacity: 0.5; fill: red} (shape (shape_key) (dot) (attribute - (attr_key) + (keyword_style) (block (attribute (attr_key) (attr_value (float))) (attribute (attr_key) (attr_value)) diff --git a/test/corpus/classes.txt b/test/corpus/classes.txt new file mode 100644 index 0000000..a840f96 --- /dev/null +++ b/test/corpus/classes.txt @@ -0,0 +1,198 @@ +================================================================================ +Declare empty classes keyword in the root +================================================================================ +classes + +-------------------------------------------------------------------------------- + +(source_file + (classes (keyword_classes)) +) + +================================================================================ +Declare classes block with item block +================================================================================ +classes: { + foo: { + style: { + fill: "#44C7B1" + } + } +} + +-------------------------------------------------------------------------------- + +(source_file + (classes + (keyword_classes) + (block + (class_name) + (class_block + (attribute + (keyword_style) + (block + (attribute + (attr_key) + (attr_value + (string (string_fragment)) + ) + ) + ) + ) + ) + ) + ) +) + +================================================================================ +Declare classes block with item inline +================================================================================ +classes: { + foo.style: { + fill: "#44C7B1" + } +} + +-------------------------------------------------------------------------------- + +(source_file + (classes + (keyword_classes) + (block + (class_name) + (dot) + (attribute + (keyword_style) + (block + (attribute + (attr_key) + (attr_value + (string (string_fragment)) + ) + ) + ) + ) + ) + ) +) + +================================================================================ +Declare classes inline with item inline +================================================================================ +classes.foo.style: { + fill: "#44C7B1" +} + +-------------------------------------------------------------------------------- + +(source_file + (classes + (keyword_classes) + (dot) + (class_name) + (dot) + (attribute + (keyword_style) + (block + (attribute + (attr_key) + (attr_value + (string (string_fragment)) + ) + ) + ) + ) + ) +) + +================================================================================ +Declare classes inline with item block +================================================================================ +classes.foo: { + style: { + fill: "#44C7B1" + } +} + +-------------------------------------------------------------------------------- + +(source_file + (classes + (keyword_classes) + (dot) + (class_name) + (class_block + (attribute + (keyword_style) + (block + (attribute + (attr_key) + (attr_value + (string (string_fragment)) + ) + ) + ) + ) + ) + ) +) + +================================================================================ +Declare shape with a class +================================================================================ +foo.class: biz + +-------------------------------------------------------------------------------- + +(source_file + (shape + (shape_key) + (dot) + (attribute + (keyword_class) + (class_name) + ) + ) +) + +================================================================================ +Declare shape with many classes +================================================================================ +foo.class: [biz; baz] + +-------------------------------------------------------------------------------- + +(source_file + (shape + (shape_key) + (dot) + (attribute + (keyword_class) + (class_list + (class_name) + (class_name) + ) + ) + ) +) + +================================================================================ +Declare a class in the container +================================================================================ +foo: { + class: biz +} + +-------------------------------------------------------------------------------- + +(source_file + (container + (container_key) + (block + (attribute + (keyword_class) + (class_name) + ) + ) + ) +) diff --git a/test/highlight/attribute.d2 b/test/highlight/attribute.d2 index 3dfd5a2..c9187c1 100644 --- a/test/highlight/attribute.d2 +++ b/test/highlight/attribute.d2 @@ -10,7 +10,7 @@ shape: oval baaaz.style: { # <- variable - # ^ property + # ^ keyword fill: red # <- property # ^ string @@ -22,12 +22,13 @@ foo: Label { # ^ string style.fill: red; - # <- property + # <- keyword # ^ property } foo: { style: { + # <- keyword opacity: 0.5 # ^ float fill: red @@ -54,6 +55,6 @@ foo: Label { # ^ string style.fill: red - # <- property + # <- keyword # ^ property } diff --git a/test/highlight/classes.d2 b/test/highlight/classes.d2 new file mode 100644 index 0000000..5f24a74 --- /dev/null +++ b/test/highlight/classes.d2 @@ -0,0 +1,40 @@ +classes: { +# <- keyword +# ^ punctuation.delimiter +# ^ punctuation.bracket + load balancer { + label: load\nbalancer + width: 100 + height: 200 + style: { + stroke-width: 0 + fill: "#44C7B1" + shadow: true + border-radius: 5 + } + } + unhealthy: { + style: { + fill: "#FE7070" + stroke: "#F69E03" + } + } +} + +web traffic -> web lb +web lb.class: load balancer +# <- variable +# ^ punctuation.delimiter +# ^ keyword +# ^ punctuation.delimiter + +web lb -> api1 +web lb -> api2 +web lb -> api3 + +api2.class: unhealthy + +api1 -> cache lb +api3 -> cache lb + +cache lb.class: load balancer