@cssdoc/tmlanguage 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,55 +4,113 @@
4
4
  "scopeName": "documentation.cssdoc",
5
5
  "injectionSelector": "L:comment.block.css, L:comment.block.scss, L:comment.block.less",
6
6
  "patterns": [
7
- { "include": "#inline-tag" },
8
- { "include": "#modifier-tag" },
9
- { "include": "#part-tag" },
10
- { "include": "#property-tag" },
11
- { "include": "#block-tag" },
12
- { "include": "#custom-property" }
7
+ {
8
+ "include": "#inline-tag"
9
+ },
10
+ {
11
+ "include": "#modifier-tag"
12
+ },
13
+ {
14
+ "include": "#part-tag"
15
+ },
16
+ {
17
+ "include": "#property-tag"
18
+ },
19
+ {
20
+ "include": "#structure-tag"
21
+ },
22
+ {
23
+ "include": "#block-tag"
24
+ },
25
+ {
26
+ "include": "#custom-property"
27
+ }
13
28
  ],
14
29
  "repository": {
15
30
  "inline-tag": {
16
31
  "name": "meta.inline-tag.cssdoc",
17
32
  "begin": "(\\{)(@(?:link|inheritDoc|label))\\b",
18
33
  "beginCaptures": {
19
- "1": { "name": "punctuation.definition.tag.begin.cssdoc" },
20
- "2": { "name": "storage.type.class.cssdoc" }
34
+ "1": {
35
+ "name": "punctuation.definition.tag.begin.cssdoc"
36
+ },
37
+ "2": {
38
+ "name": "storage.type.class.cssdoc"
39
+ }
21
40
  },
22
41
  "end": "(\\})",
23
42
  "endCaptures": {
24
- "1": { "name": "punctuation.definition.tag.end.cssdoc" }
43
+ "1": {
44
+ "name": "punctuation.definition.tag.end.cssdoc"
45
+ }
25
46
  },
26
47
  "patterns": [
27
- { "match": "\\|", "name": "punctuation.separator.cssdoc" },
28
- { "match": "[^}|]+", "name": "markup.underline.link.cssdoc" }
48
+ {
49
+ "match": "\\|",
50
+ "name": "punctuation.separator.cssdoc"
51
+ },
52
+ {
53
+ "match": "[^}|]+",
54
+ "name": "markup.underline.link.cssdoc"
55
+ }
29
56
  ]
30
57
  },
31
58
  "modifier-tag": {
32
- "match": "(@modifier)\\b[ \\t]*(-[A-Za-z][A-Za-z0-9-]*)?",
59
+ "match": "(@(?:modifier))\\b[ \\t]*(-[A-Za-z][A-Za-z0-9-]*)?",
33
60
  "captures": {
34
- "1": { "name": "storage.type.class.cssdoc" },
35
- "2": { "name": "variable.other.modifier.cssdoc" }
61
+ "1": {
62
+ "name": "storage.type.class.cssdoc"
63
+ },
64
+ "2": {
65
+ "name": "variable.other.modifier.cssdoc"
66
+ }
36
67
  }
37
68
  },
38
69
  "part-tag": {
39
- "match": "(@(?:csspart|part|slot))\\b[ \\t]*(\\.?[A-Za-z][A-Za-z0-9_-]*)?",
70
+ "match": "(@(?:part|csspart|slot))\\b[ \\t]*(\\.?[A-Za-z][A-Za-z0-9_-]*)?",
40
71
  "captures": {
41
- "1": { "name": "storage.type.class.cssdoc" },
42
- "2": { "name": "entity.other.attribute-name.part.cssdoc" }
72
+ "1": {
73
+ "name": "storage.type.class.cssdoc"
74
+ },
75
+ "2": {
76
+ "name": "entity.other.attribute-name.part.cssdoc"
77
+ }
43
78
  }
44
79
  },
45
80
  "property-tag": {
46
81
  "match": "(@(?:cssproperty|property))\\b[ \\t]*(--[A-Za-z][A-Za-z0-9-]*)?",
47
82
  "captures": {
48
- "1": { "name": "storage.type.class.cssdoc" },
49
- "2": { "name": "support.type.custom-property.cssdoc" }
83
+ "1": {
84
+ "name": "storage.type.class.cssdoc"
85
+ },
86
+ "2": {
87
+ "name": "support.type.custom-property.cssdoc"
88
+ }
50
89
  }
51
90
  },
52
91
  "block-tag": {
53
92
  "match": "(@(?:component|name|utility|rule|declaration|class|summary|remarks|privateRemarks|deprecated|example|see|since|group|category|defaultValue|cssstate|function|keyframes|animation|layer|container|supports|media|responsive|a11y|accessibility|structure|demo|alpha|beta|experimental|internal|public))\\b",
54
93
  "name": "storage.type.class.cssdoc"
55
94
  },
95
+ "structure-tag": {
96
+ "begin": "(@structure)\\b",
97
+ "beginCaptures": {
98
+ "1": {
99
+ "name": "storage.type.class.cssdoc"
100
+ }
101
+ },
102
+ "end": "(?=@)|(?=\\*/)",
103
+ "patterns": [
104
+ {
105
+ "match": "\\.[A-Za-z][A-Za-z0-9_-]*",
106
+ "name": "entity.other.attribute-name.part.cssdoc"
107
+ },
108
+ {
109
+ "match": "[{}]",
110
+ "name": "punctuation.section.structure.cssdoc"
111
+ }
112
+ ]
113
+ },
56
114
  "custom-property": {
57
115
  "match": "(?<![\\w-])--[A-Za-z][A-Za-z0-9-]*",
58
116
  "name": "support.type.custom-property.cssdoc"
package/dist/index.d.mts CHANGED
@@ -1,5 +1,40 @@
1
1
  //#region src/index.d.ts
2
- /** The scopes the injection layers onto (CSS, plus SCSS/Less and CSS embedded in HTML `<style>`). */
2
+ /** A TextMate capture assignment (`{ "1": { name } }`). */
3
+ type Captures = Record<string, {
4
+ name: string;
5
+ }>;
6
+ /** A TextMate pattern rule — a match rule, a begin/end rule, or a `#repository` reference. */
7
+ interface TmRule {
8
+ name?: string;
9
+ match?: string;
10
+ begin?: string;
11
+ end?: string;
12
+ beginCaptures?: Captures;
13
+ endCaptures?: Captures;
14
+ captures?: Captures;
15
+ patterns?: TmRule[];
16
+ include?: string;
17
+ }
18
+ /** A TextMate injection grammar. */
19
+ interface InjectionGrammar {
20
+ $schema: string;
21
+ name: string;
22
+ scopeName: string;
23
+ injectionSelector: string;
24
+ patterns: TmRule[];
25
+ repository: Record<string, TmRule>;
26
+ }
27
+ /**
28
+ * Build the cssdoc injection grammar from the canonical `@cssdoc/spec` vocabulary. The argument-bearing
29
+ * tags (`@modifier`, `@part`/`@slot`, `@cssproperty`) get their own rules that also colour the token
30
+ * that follows; the inline tags open a `{@link …}` rule; every other tag is a bare keyword.
31
+ */
32
+ declare function buildInjectionGrammar(): InjectionGrammar;
33
+ /**
34
+ * The host scopes the injection layers onto. It fires only where `comment.block.css` (etc.) appears —
35
+ * see {@link InjectionGrammar.injectionSelector} — so listing the JS/HTML/Markdown/framework hosts is
36
+ * safe: cssdoc lights up embedded CSS wherever another grammar embeds it, not just in `.css` files.
37
+ */
3
38
  declare const injectTo: string[];
4
39
  /** The cssdoc doc-comment injection grammar, shaped as a Shiki `LanguageRegistration`. */
5
40
  declare const cssdoc: {
@@ -8,74 +43,8 @@ declare const cssdoc: {
8
43
  name: string;
9
44
  scopeName: string;
10
45
  injectionSelector: string;
11
- patterns: {
12
- include: string;
13
- }[];
14
- repository: {
15
- "inline-tag": {
16
- name: string;
17
- begin: string;
18
- beginCaptures: {
19
- "1": {
20
- name: string;
21
- };
22
- "2": {
23
- name: string;
24
- };
25
- };
26
- end: string;
27
- endCaptures: {
28
- "1": {
29
- name: string;
30
- };
31
- };
32
- patterns: {
33
- match: string;
34
- name: string;
35
- }[];
36
- };
37
- "modifier-tag": {
38
- match: string;
39
- captures: {
40
- "1": {
41
- name: string;
42
- };
43
- "2": {
44
- name: string;
45
- };
46
- };
47
- };
48
- "part-tag": {
49
- match: string;
50
- captures: {
51
- "1": {
52
- name: string;
53
- };
54
- "2": {
55
- name: string;
56
- };
57
- };
58
- };
59
- "property-tag": {
60
- match: string;
61
- captures: {
62
- "1": {
63
- name: string;
64
- };
65
- "2": {
66
- name: string;
67
- };
68
- };
69
- };
70
- "block-tag": {
71
- match: string;
72
- name: string;
73
- };
74
- "custom-property": {
75
- match: string;
76
- name: string;
77
- };
78
- };
46
+ patterns: TmRule[];
47
+ repository: Record<string, TmRule>;
79
48
  };
80
49
  //#endregion
81
- export { cssdoc, cssdoc as default, injectTo };
50
+ export { InjectionGrammar, buildInjectionGrammar, cssdoc, cssdoc as default, injectTo };
package/dist/index.mjs CHANGED
@@ -1,67 +1,4 @@
1
- //#region cssdoc.injection.tmLanguage.json
2
- var cssdoc_injection_tmLanguage_default = {
3
- $schema: "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
4
- name: "cssdoc",
5
- scopeName: "documentation.cssdoc",
6
- injectionSelector: "L:comment.block.css, L:comment.block.scss, L:comment.block.less",
7
- patterns: [
8
- { "include": "#inline-tag" },
9
- { "include": "#modifier-tag" },
10
- { "include": "#part-tag" },
11
- { "include": "#property-tag" },
12
- { "include": "#block-tag" },
13
- { "include": "#custom-property" }
14
- ],
15
- repository: {
16
- "inline-tag": {
17
- "name": "meta.inline-tag.cssdoc",
18
- "begin": "(\\{)(@(?:link|inheritDoc|label))\\b",
19
- "beginCaptures": {
20
- "1": { "name": "punctuation.definition.tag.begin.cssdoc" },
21
- "2": { "name": "storage.type.class.cssdoc" }
22
- },
23
- "end": "(\\})",
24
- "endCaptures": { "1": { "name": "punctuation.definition.tag.end.cssdoc" } },
25
- "patterns": [{
26
- "match": "\\|",
27
- "name": "punctuation.separator.cssdoc"
28
- }, {
29
- "match": "[^}|]+",
30
- "name": "markup.underline.link.cssdoc"
31
- }]
32
- },
33
- "modifier-tag": {
34
- "match": "(@modifier)\\b[ \\t]*(-[A-Za-z][A-Za-z0-9-]*)?",
35
- "captures": {
36
- "1": { "name": "storage.type.class.cssdoc" },
37
- "2": { "name": "variable.other.modifier.cssdoc" }
38
- }
39
- },
40
- "part-tag": {
41
- "match": "(@(?:csspart|part|slot))\\b[ \\t]*(\\.?[A-Za-z][A-Za-z0-9_-]*)?",
42
- "captures": {
43
- "1": { "name": "storage.type.class.cssdoc" },
44
- "2": { "name": "entity.other.attribute-name.part.cssdoc" }
45
- }
46
- },
47
- "property-tag": {
48
- "match": "(@(?:cssproperty|property))\\b[ \\t]*(--[A-Za-z][A-Za-z0-9-]*)?",
49
- "captures": {
50
- "1": { "name": "storage.type.class.cssdoc" },
51
- "2": { "name": "support.type.custom-property.cssdoc" }
52
- }
53
- },
54
- "block-tag": {
55
- "match": "(@(?:component|name|utility|rule|declaration|class|summary|remarks|privateRemarks|deprecated|example|see|since|group|category|defaultValue|cssstate|function|keyframes|animation|layer|container|supports|media|responsive|a11y|accessibility|structure|demo|alpha|beta|experimental|internal|public))\\b",
56
- "name": "storage.type.class.cssdoc"
57
- },
58
- "custom-property": {
59
- "match": "(?<![\\w-])--[A-Za-z][A-Za-z0-9-]*",
60
- "name": "support.type.custom-property.cssdoc"
61
- }
62
- }
63
- };
64
- //#endregion
1
+ import { CSSDOC_TAGS, cssdocTagNamesByArgument, cssdocTagNamesByKind } from "@cssdoc/spec";
65
2
  //#region src/index.ts
66
3
  /**
67
4
  * `@cssdoc/tmlanguage` — a TextMate injection grammar that highlights cssdoc doc-comment tags inside
@@ -69,9 +6,12 @@ var cssdoc_injection_tmLanguage_default = {
69
6
  * CSS grammar's comment scope, so `@component`, `@modifier`, `@cssproperty`, `{@link …}`, the release
70
7
  * modifiers, and custom properties light up wherever CSS is highlighted.
71
8
  *
72
- * The default export is the grammar as a Shiki `LanguageRegistration` (it carries `injectTo`), so it
73
- * drops into a Shiki or VitePress config; the raw grammar is also published at
74
- * `./cssdoc.injection.tmLanguage.json` for VS Code's `contributes.grammars` and other TextMate hosts.
9
+ * The grammar is built from the canonical tag vocabulary in `@cssdoc/spec` via
10
+ * {@link buildInjectionGrammar}, so the tag list is defined exactly once. The default export is the
11
+ * grammar as a Shiki `LanguageRegistration` (it carries `injectTo`), so it drops into a Shiki or
12
+ * VitePress config; the same grammar is also published as `./cssdoc.injection.tmLanguage.json`
13
+ * (generated by `scripts/generate.mjs`, kept in sync by the tests) for VS Code's
14
+ * `contributes.grammars` and other TextMate hosts.
75
15
  *
76
16
  * @example
77
17
  * ```ts
@@ -82,16 +22,120 @@ var cssdoc_injection_tmLanguage_default = {
82
22
  *
83
23
  * @module @cssdoc/tmlanguage
84
24
  */
85
- /** The scopes the injection layers onto (CSS, plus SCSS/Less and CSS embedded in HTML `<style>`). */
25
+ const TAG_SCOPE = "storage.type.class.cssdoc";
26
+ const alt = (names) => names.join("|");
27
+ /**
28
+ * Build the cssdoc injection grammar from the canonical `@cssdoc/spec` vocabulary. The argument-bearing
29
+ * tags (`@modifier`, `@part`/`@slot`, `@cssproperty`) get their own rules that also colour the token
30
+ * that follows; the inline tags open a `{@link …}` rule; every other tag is a bare keyword.
31
+ */
32
+ function buildInjectionGrammar() {
33
+ const inlineTags = alt(cssdocTagNamesByKind("inline"));
34
+ const modifierTags = alt(cssdocTagNamesByArgument("modifier-name"));
35
+ const partTags = alt(cssdocTagNamesByArgument("part-name"));
36
+ const propertyTags = alt(cssdocTagNamesByArgument("custom-property"));
37
+ const blockTags = alt(CSSDOC_TAGS.filter((t) => t.kind !== "inline" && !t.argument).map((t) => t.name));
38
+ return {
39
+ $schema: "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
40
+ name: "cssdoc",
41
+ scopeName: "documentation.cssdoc",
42
+ injectionSelector: "L:comment.block.css, L:comment.block.scss, L:comment.block.less",
43
+ patterns: [
44
+ { include: "#inline-tag" },
45
+ { include: "#modifier-tag" },
46
+ { include: "#part-tag" },
47
+ { include: "#property-tag" },
48
+ { include: "#structure-tag" },
49
+ { include: "#block-tag" },
50
+ { include: "#custom-property" }
51
+ ],
52
+ repository: {
53
+ "inline-tag": {
54
+ name: "meta.inline-tag.cssdoc",
55
+ begin: `(\\{)(@(?:${inlineTags}))\\b`,
56
+ beginCaptures: {
57
+ "1": { name: "punctuation.definition.tag.begin.cssdoc" },
58
+ "2": { name: TAG_SCOPE }
59
+ },
60
+ end: "(\\})",
61
+ endCaptures: { "1": { name: "punctuation.definition.tag.end.cssdoc" } },
62
+ patterns: [{
63
+ match: "\\|",
64
+ name: "punctuation.separator.cssdoc"
65
+ }, {
66
+ match: "[^}|]+",
67
+ name: "markup.underline.link.cssdoc"
68
+ }]
69
+ },
70
+ "modifier-tag": {
71
+ match: `(@(?:${modifierTags}))\\b[ \\t]*(-[A-Za-z][A-Za-z0-9-]*)?`,
72
+ captures: {
73
+ "1": { name: TAG_SCOPE },
74
+ "2": { name: "variable.other.modifier.cssdoc" }
75
+ }
76
+ },
77
+ "part-tag": {
78
+ match: `(@(?:${partTags}))\\b[ \\t]*(\\.?[A-Za-z][A-Za-z0-9_-]*)?`,
79
+ captures: {
80
+ "1": { name: TAG_SCOPE },
81
+ "2": { name: "entity.other.attribute-name.part.cssdoc" }
82
+ }
83
+ },
84
+ "property-tag": {
85
+ match: `(@(?:${propertyTags}))\\b[ \\t]*(--[A-Za-z][A-Za-z0-9-]*)?`,
86
+ captures: {
87
+ "1": { name: TAG_SCOPE },
88
+ "2": { name: "support.type.custom-property.cssdoc" }
89
+ }
90
+ },
91
+ "block-tag": {
92
+ match: `(@(?:${blockTags}))\\b`,
93
+ name: TAG_SCOPE
94
+ },
95
+ "structure-tag": {
96
+ begin: "(@structure)\\b",
97
+ beginCaptures: { "1": { name: TAG_SCOPE } },
98
+ end: "(?=@)|(?=\\*/)",
99
+ patterns: [{
100
+ match: "\\.[A-Za-z][A-Za-z0-9_-]*",
101
+ name: "entity.other.attribute-name.part.cssdoc"
102
+ }, {
103
+ match: "[{}]",
104
+ name: "punctuation.section.structure.cssdoc"
105
+ }]
106
+ },
107
+ "custom-property": {
108
+ match: "(?<![\\w-])--[A-Za-z][A-Za-z0-9-]*",
109
+ name: "support.type.custom-property.cssdoc"
110
+ }
111
+ }
112
+ };
113
+ }
114
+ /**
115
+ * The host scopes the injection layers onto. It fires only where `comment.block.css` (etc.) appears —
116
+ * see {@link InjectionGrammar.injectionSelector} — so listing the JS/HTML/Markdown/framework hosts is
117
+ * safe: cssdoc lights up embedded CSS wherever another grammar embeds it, not just in `.css` files.
118
+ */
86
119
  const injectTo = [
87
120
  "source.css",
88
121
  "source.scss",
89
- "source.less"
122
+ "source.less",
123
+ "source.css.styled",
124
+ "source.ts",
125
+ "source.tsx",
126
+ "source.js",
127
+ "source.jsx",
128
+ "source.vue",
129
+ "source.svelte",
130
+ "source.astro",
131
+ "text.html.markdown",
132
+ "text.html.basic",
133
+ "text.html.derivative"
90
134
  ];
91
135
  /** The cssdoc doc-comment injection grammar, shaped as a Shiki `LanguageRegistration`. */
92
136
  const cssdoc = {
93
- ...cssdoc_injection_tmLanguage_default,
137
+ ...buildInjectionGrammar(),
94
138
  injectTo
95
139
  };
96
140
  //#endregion
97
- export { cssdoc, cssdoc as default, injectTo };
141
+ export { buildInjectionGrammar, cssdoc, cssdoc as default, injectTo };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cssdoc/tmlanguage",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "A TextMate injection grammar that highlights cssdoc doc-comment tags inside CSS comments, the way TSDoc highlights JSDoc tags. Ships as a Shiki language.",
5
5
  "keywords": [
6
6
  "css",
@@ -17,7 +17,7 @@
17
17
  "repository": {
18
18
  "type": "git",
19
19
  "url": "git+https://github.com/thedannywahl/cssdoc.git",
20
- "directory": "syntaxes/cssdoc"
20
+ "directory": "syntaxes/cssdoc/tmlanguage"
21
21
  },
22
22
  "files": [
23
23
  "dist",
@@ -32,6 +32,9 @@
32
32
  "publishConfig": {
33
33
  "access": "public"
34
34
  },
35
+ "dependencies": {
36
+ "@cssdoc/spec": "0.3.0"
37
+ },
35
38
  "devDependencies": {
36
39
  "@types/node": "^24.13.3",
37
40
  "@vitest/coverage-v8": "4.1.9",
@@ -43,6 +46,7 @@
43
46
  "scripts": {
44
47
  "build": "vp pack",
45
48
  "dev": "vp pack --watch",
49
+ "generate": "node scripts/generate.mjs",
46
50
  "test": "vp test",
47
51
  "check": "vp check",
48
52
  "publint": "publint"