@master/css-language-service 0.0.0-site.1793659883.g69c9aebcf628

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.
Files changed (44) hide show
  1. package/README.md +131 -0
  2. package/dist/common.d.ts +2 -0
  3. package/dist/common.js +1 -0
  4. package/dist/core.d.ts +34 -0
  5. package/dist/core.js +81 -0
  6. package/dist/document-analysis.d.ts +16 -0
  7. package/dist/document-analysis.js +34 -0
  8. package/dist/features/edit-syntax-colors.d.ts +5 -0
  9. package/dist/features/edit-syntax-colors.js +36 -0
  10. package/dist/features/format-directives.d.ts +5 -0
  11. package/dist/features/format-directives.js +60 -0
  12. package/dist/features/inspect-syntax.d.ts +5 -0
  13. package/dist/features/inspect-syntax.js +48 -0
  14. package/dist/features/render-semantic-tokens.d.ts +6 -0
  15. package/dist/features/render-semantic-tokens.js +36 -0
  16. package/dist/features/render-syntax-colors.d.ts +5 -0
  17. package/dist/features/render-syntax-colors.js +47 -0
  18. package/dist/features/suggest-syntax.d.ts +5 -0
  19. package/dist/features/suggest-syntax.js +165 -0
  20. package/dist/index.d.ts +8 -0
  21. package/dist/index.js +8 -0
  22. package/dist/settings.d.ts +21 -0
  23. package/dist/settings.js +64 -0
  24. package/dist/shiki/hast.d.ts +13 -0
  25. package/dist/shiki/hast.js +174 -0
  26. package/dist/shiki/languages.d.ts +8 -0
  27. package/dist/shiki/languages.js +69 -0
  28. package/dist/shiki.d.ts +159 -0
  29. package/dist/shiki.js +522 -0
  30. package/dist/utils/beautify-css.d.ts +2 -0
  31. package/dist/utils/beautify-css.js +12 -0
  32. package/dist/utils/convert-color-token.d.ts +4 -0
  33. package/dist/utils/convert-color-token.js +31 -0
  34. package/dist/utils/create-css-markdown-documentation.d.ts +6 -0
  35. package/dist/utils/create-css-markdown-documentation.js +12 -0
  36. package/dist/utils/create-doc.d.ts +17 -0
  37. package/dist/utils/create-doc.js +20 -0
  38. package/dist/utils/get-position.d.ts +2 -0
  39. package/dist/utils/get-position.js +8 -0
  40. package/dist/utils/get-range.d.ts +3 -0
  41. package/dist/utils/get-range.js +20 -0
  42. package/package.json +60 -0
  43. package/src/shiki.css +7 -0
  44. package/syntaxes/master-css.tmLanguage.json +881 -0
@@ -0,0 +1,165 @@
1
+ import { analyzeDocument, documentRequest } from "../document-analysis.js";
2
+ import createCSSMarkdownDocumentation from "../utils/create-css-markdown-documentation.js";
3
+ import { CompletionItemKind, InsertTextFormat } from "vscode-languageserver-protocol";
4
+ // src/features/suggest-syntax.ts
5
+ function sortCompletionItems(items) {
6
+ return items.sort((left, right) => (left.sortText || left.label).localeCompare(right.sortText || right.label, void 0, { numeric: true }));
7
+ }
8
+ function documentation(service, entry, className) {
9
+ const text = entry.documentationText || service.session.inspectClassName(className).text;
10
+ return text ? createCSSMarkdownDocumentation(text) : void 0;
11
+ }
12
+ function classCompletionItem(service, entry, label = entry.label, className = entry.label, generateDocumentation = false) {
13
+ return {
14
+ label,
15
+ kind: entry.kind === "property" ? CompletionItemKind.Property : entry.kind === "function" ? CompletionItemKind.Function : CompletionItemKind.Value,
16
+ insertText: entry.kind === "function" ? entry.insertText ?? `${label.slice(0, -2)}($0)` : void 0,
17
+ insertTextFormat: entry.kind === "function" ? InsertTextFormat.Snippet : void 0,
18
+ detail: entry.detail,
19
+ documentation: entry.documentationText || generateDocumentation ? documentation(service, entry, className) : void 0,
20
+ sortText: entry.sortText,
21
+ command: entry.triggerSuggest ? {
22
+ title: "Suggest",
23
+ command: "editor.action.triggerSuggest"
24
+ } : void 0
25
+ };
26
+ }
27
+ /**
28
+ * Root candidates for the class typed so far. A `(property:` head also matches the
29
+ * bare property name, and replaces the whole typed class so its parenthesis is
30
+ * never doubled.
31
+ */
32
+ function rootCompletionItems(service, entries, query, range) {
33
+ return sortCompletionItems(entries.filter(({ label }) => {
34
+ if (label.startsWith(":") || label.startsWith("@")) return false;
35
+ if (label.includes(":") && !label.endsWith(":")) return false;
36
+ return !query || label.startsWith(query) || label.startsWith("(") && label.startsWith(query, 1);
37
+ }).map((entry) => {
38
+ const item = classCompletionItem(service, entry);
39
+ if (range) {
40
+ item.filterText = entry.label.startsWith("(") && !query.startsWith("(") ? entry.label.slice(1) : entry.label;
41
+ item.textEdit = {
42
+ range,
43
+ newText: item.insertText ?? entry.label
44
+ };
45
+ item.insertText = void 0;
46
+ }
47
+ return item;
48
+ }));
49
+ }
50
+ /** Values of a `(property:` head; `suffix` is the text the head still lacks, such as its `)`. */
51
+ function valueCompletionItems(service, entries, key, valuePrefix, range, suffix) {
52
+ const prefix = `(${key}:`;
53
+ return sortCompletionItems(entries.filter(({ kind, label }) => kind !== "property" && label.startsWith(prefix) && label.endsWith(")")).filter(({ label }) => valuePrefix.startsWith("-") || !label.slice(prefix.length).startsWith("-")).map((entry) => {
54
+ const value = entry.label.slice(prefix.length, -1);
55
+ const item = classCompletionItem(service, entry, value, entry.label, entry.label === "(font-style:italic)");
56
+ item.filterText = value;
57
+ item.textEdit = {
58
+ range,
59
+ newText: entry.kind === "function" ? `${value.slice(0, -1)}$0)${suffix}` : `${value}${suffix}`
60
+ };
61
+ item.insertText = void 0;
62
+ return item;
63
+ }));
64
+ }
65
+ const SELECTOR_TRIGGER = /(?:::?|[_>+~])$/u;
66
+ const hasSyntaxError = (diagnostics) => Boolean(diagnostics?.some(({ code }) => code === "CLASS_SYNTAX_ERROR"));
67
+ function selectorCompletionItems(service, entries, field) {
68
+ const elementOnly = field.endsWith("::");
69
+ const triggerLength = elementOnly ? 2 : field.endsWith(":") ? 1 : 0;
70
+ const byLabel = /* @__PURE__ */ new Map();
71
+ for (const entry of entries) {
72
+ if (!entry.label.startsWith(":")) continue;
73
+ if (elementOnly && !entry.label.startsWith("::")) continue;
74
+ const label = entry.label;
75
+ if (byLabel.has(label)) continue;
76
+ const insertText = triggerLength ? label.slice(triggerLength) : void 0;
77
+ const className = `${field}${triggerLength ? label.slice(triggerLength) : label}`;
78
+ const includeDocumentation = (/* @__PURE__ */ new Set([
79
+ ":first-child",
80
+ ":hover",
81
+ "::placeholder"
82
+ ])).has(label);
83
+ byLabel.set(label, {
84
+ label,
85
+ insertText,
86
+ kind: CompletionItemKind.Function,
87
+ detail: entry.detail,
88
+ documentation: entry.documentationText || includeDocumentation ? documentation(service, entry, className) : void 0,
89
+ sortText: entry.sortText
90
+ });
91
+ }
92
+ return sortCompletionItems([...byLabel.values()]);
93
+ }
94
+ function queryCompletionItems(entries) {
95
+ return sortCompletionItems(entries.filter(({ label }) => label.startsWith("@")).map((entry) => ({
96
+ label: entry.label,
97
+ filterText: entry.label.slice(1),
98
+ insertText: entry.label.slice(1),
99
+ detail: entry.detail,
100
+ kind: entry.kind === "function" ? CompletionItemKind.Function : CompletionItemKind.Keyword,
101
+ sortText: entry.sortText
102
+ })));
103
+ }
104
+ function suggestSyntax(document, position, context) {
105
+ const offset = document.offsetAt(position);
106
+ const keyframe = analyzeDocument(this, document).keyframePositions.find(({ range }) => offset >= range.start && offset <= range.end);
107
+ if (keyframe) return this.session.completionIndex().keyframes.map((entry) => ({
108
+ label: entry.name,
109
+ kind: CompletionItemKind.Value,
110
+ documentation: createCSSMarkdownDocumentation(entry.text),
111
+ textEdit: {
112
+ range: {
113
+ start: document.positionAt(keyframe.range.start),
114
+ end: document.positionAt(keyframe.range.end)
115
+ },
116
+ newText: keyframe.raw ? entry.insertText : ` ${entry.insertText} `
117
+ }
118
+ }));
119
+ const classPosition = this.getClassPosition(document, position);
120
+ if (!classPosition) return;
121
+ const field = context?.triggerCharacter === " " ? "" : document.getText({
122
+ start: document.positionAt(classPosition.range.start),
123
+ end: position
124
+ });
125
+ const entries = this.session.completionIndex().classEntries;
126
+ if (!field || context?.triggerCharacter === " ") return rootCompletionItems(this, entries, "");
127
+ if (field.startsWith("@") || field.startsWith("~")) return [];
128
+ const typed = {
129
+ start: document.positionAt(classPosition.range.start),
130
+ end: position
131
+ };
132
+ const trigger = field.match(SELECTOR_TRIGGER)?.[0];
133
+ if (trigger && trigger.length < field.length) {
134
+ const head = this.session.inspectClassName(field.slice(0, -trigger.length));
135
+ if (head.kind !== "unknown" && !hasSyntaxError(head.diagnostics)) return selectorCompletionItems(this, entries, field);
136
+ }
137
+ if (field.startsWith("(")) {
138
+ const head = this.session.nativeDeclarationCompletion({
139
+ ...documentRequest(this, document),
140
+ offset
141
+ });
142
+ if (head) {
143
+ if (head.kind === "none" || !head.range) return [];
144
+ const range = {
145
+ start: document.positionAt(head.range.start),
146
+ end: document.positionAt(head.range.end)
147
+ };
148
+ if (head.kind === "property") return rootCompletionItems(this, entries, `(${head.prefix}`, {
149
+ start: typed.start,
150
+ end: range.end
151
+ });
152
+ return valueCompletionItems(this, entries, head.property ?? "", head.prefix, range, head.suffix ?? "");
153
+ }
154
+ }
155
+ const inspection = this.session.inspectClassName(field);
156
+ if (hasSyntaxError(inspection.diagnostics)) return [];
157
+ const suffix = inspection.suffix ?? "";
158
+ if (suffix.includes("@")) {
159
+ if (field.endsWith("@")) return queryCompletionItems(entries);
160
+ return [];
161
+ }
162
+ if (suffix || inspection.kind === "declaration") return [];
163
+ return rootCompletionItems(this, entries, field, typed);
164
+ }
165
+ export { suggestSyntax as default };
@@ -0,0 +1,8 @@
1
+ import { MasterCSSLanguageServiceSettings, defaultLanguageServiceSettings } from "./settings.js";
2
+ import inspectSyntax from "./features/inspect-syntax.js";
3
+ import renderSyntaxColors from "./features/render-syntax-colors.js";
4
+ import editSyntaxColors from "./features/edit-syntax-colors.js";
5
+ import suggestSyntax from "./features/suggest-syntax.js";
6
+ import { MasterCSSLanguageService, MasterCSSLanguageServiceOptions } from "./core.js";
7
+ import { AT_TRIGGER_CHARACTER, INVOKED_TRIGGER_CHARACTERS, QUERY_TRIGGER_CHARACTERS, SELECTOR_TRIGGER_CHARACTERS, VALUE_TRIGGER_CHARACTERS } from "./common.js";
8
+ export { AT_TRIGGER_CHARACTER, INVOKED_TRIGGER_CHARACTERS, MasterCSSLanguageService, type MasterCSSLanguageServiceOptions, type MasterCSSLanguageServiceSettings, QUERY_TRIGGER_CHARACTERS, SELECTOR_TRIGGER_CHARACTERS, VALUE_TRIGGER_CHARACTERS, defaultLanguageServiceSettings, editSyntaxColors, inspectSyntax, renderSyntaxColors, suggestSyntax };
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ import { defaultLanguageServiceSettings } from "./settings.js";
2
+ import { AT_TRIGGER_CHARACTER, INVOKED_TRIGGER_CHARACTERS, QUERY_TRIGGER_CHARACTERS, SELECTOR_TRIGGER_CHARACTERS, VALUE_TRIGGER_CHARACTERS } from "./common.js";
3
+ import inspectSyntax from "./features/inspect-syntax.js";
4
+ import renderSyntaxColors from "./features/render-syntax-colors.js";
5
+ import editSyntaxColors from "./features/edit-syntax-colors.js";
6
+ import suggestSyntax from "./features/suggest-syntax.js";
7
+ import { MasterCSSLanguageService } from "./core.js";
8
+ export { AT_TRIGGER_CHARACTER, INVOKED_TRIGGER_CHARACTERS, MasterCSSLanguageService, QUERY_TRIGGER_CHARACTERS, SELECTOR_TRIGGER_CHARACTERS, VALUE_TRIGGER_CHARACTERS, defaultLanguageServiceSettings, editSyntaxColors, inspectSyntax, renderSyntaxColors, suggestSyntax };
@@ -0,0 +1,21 @@
1
+ import { MasterCSSManifest } from "@master/css-schema/manifest";
2
+ /**
3
+ * @example styles https://regex101.com/r/HLPdsw/1
4
+ **/
5
+ interface MasterCSSLanguageServiceSettings {
6
+ includedLanguages?: string[];
7
+ exclude?: string[];
8
+ manifest?: MasterCSSManifest;
9
+ classAttributes?: string[];
10
+ classFunctions?: string[];
11
+ classDeclarations?: string[];
12
+ classAttributeBindings?: Record<string, [string, string] | false>;
13
+ embeddedSyntaxHighlighting?: 'active' | 'always' | 'off';
14
+ suggestSyntax?: boolean;
15
+ inspectSyntax?: boolean;
16
+ renderSyntaxColors?: boolean;
17
+ editSyntaxColors?: boolean;
18
+ formatDirectives?: boolean;
19
+ }
20
+ declare const defaultLanguageServiceSettings: Readonly<MasterCSSLanguageServiceSettings>;
21
+ export { MasterCSSLanguageServiceSettings, defaultLanguageServiceSettings };
@@ -0,0 +1,64 @@
1
+ import { CLASS_ATTRIBUTES, CLASS_DECLARATIONS, CLASS_FUNCTIONS } from "@master/css-tooling/language";
2
+ // src/settings.ts
3
+ const defaultLanguageServiceSettings = Object.freeze({
4
+ includedLanguages: Object.freeze([
5
+ "html",
6
+ "php",
7
+ "javascript",
8
+ "typescript",
9
+ "javascriptreact",
10
+ "typescriptreact",
11
+ "css",
12
+ "scss",
13
+ "less",
14
+ "vue",
15
+ "svelte",
16
+ "rust",
17
+ "astro",
18
+ "markdown",
19
+ "mdx",
20
+ "astro"
21
+ ]),
22
+ /**
23
+ * @example <div class="a b">
24
+ * @example <div className="a b">
25
+ */
26
+ classAttributes: Object.freeze([...CLASS_ATTRIBUTES]),
27
+ /**
28
+ * @example <div class={active ? 'a' : 'b'}>
29
+ * @example <div className={active ? 'a' : 'b'}>
30
+ */
31
+ classAttributeBindings: Object.freeze({
32
+ "className": Object.freeze(["{", "}"]),
33
+ "class": Object.freeze(["{", "}"]),
34
+ "class:list": Object.freeze(["{", "}"]),
35
+ ":class": Object.freeze(["\"", "\""]),
36
+ "v-bind:class": Object.freeze(["\"", "\""]),
37
+ "[class]": Object.freeze(["\"", "\""]),
38
+ "[className]": Object.freeze(["\"", "\""]),
39
+ "[ngClass]": Object.freeze(["\"", "\""])
40
+ }),
41
+ /**
42
+ * @example const classes = 'a b'
43
+ * @example { classes: { btn: 'a b' } }
44
+ */
45
+ classDeclarations: Object.freeze([...CLASS_DECLARATIONS]),
46
+ /**
47
+ * @example clsx('a b')
48
+ * @example styled`a b`
49
+ * @example .classList.add('a')
50
+ */
51
+ classFunctions: Object.freeze([...CLASS_FUNCTIONS]),
52
+ exclude: Object.freeze([
53
+ "**/.git/**",
54
+ "**/node_modules/**",
55
+ "**/.hg/**"
56
+ ]),
57
+ suggestSyntax: true,
58
+ inspectSyntax: true,
59
+ renderSyntaxColors: true,
60
+ editSyntaxColors: true,
61
+ formatDirectives: true,
62
+ embeddedSyntaxHighlighting: "active"
63
+ });
64
+ export { defaultLanguageServiceSettings };
@@ -0,0 +1,13 @@
1
+ interface ShikiPosition {
2
+ line: number;
3
+ character: number;
4
+ }
5
+ interface ShikiDecoration {
6
+ start: number | ShikiPosition;
7
+ end: number | ShikiPosition;
8
+ tagName?: string;
9
+ properties?: Record<string, unknown>;
10
+ transform?: (element: unknown, type: 'wrapper' | 'line' | 'token') => unknown | undefined;
11
+ }
12
+ declare function applyClassAttributeValueWrappers(root: unknown, source: string, decorations: ShikiDecoration[], sourceLineNumbers?: WeakMap<object, number>): void;
13
+ export { applyClassAttributeValueWrappers };
@@ -0,0 +1,174 @@
1
+ // src/shiki/hast.ts
2
+ function resolveClassNames(value) {
3
+ if (Array.isArray(value)) return value.flatMap(resolveClassNames);
4
+ return typeof value === "string" ? value.split(/\\s+/).filter(Boolean) : [];
5
+ }
6
+ function isHastElement(node) {
7
+ return Boolean(node && typeof node === "object" && node.type === "element");
8
+ }
9
+ function getHastText(node) {
10
+ if (!node || typeof node !== "object") return "";
11
+ if (node.type === "text") return node.value;
12
+ if (!isHastElement(node)) return "";
13
+ return (node.children ?? []).map(getHastText).join("");
14
+ }
15
+ function hasHastClass(element, className) {
16
+ return resolveClassNames(element.properties?.class).includes(className);
17
+ }
18
+ function collectCodeElements(node, codeElements = []) {
19
+ if (isHastElement(node) && node.tagName === "code") codeElements.push(node);
20
+ const children = node && typeof node === "object" && Array.isArray(node.children) ? node.children : [];
21
+ for (const child of children) collectCodeElements(child, codeElements);
22
+ return codeElements;
23
+ }
24
+ function createSourceLineRanges(source) {
25
+ const ranges = [];
26
+ let start = 0;
27
+ for (let index = 0; index < source.length; index++) {
28
+ if (source[index] !== "\n") continue;
29
+ ranges.push({
30
+ start,
31
+ end: index
32
+ });
33
+ start = index + 1;
34
+ }
35
+ ranges.push({
36
+ start,
37
+ end: source.length
38
+ });
39
+ return ranges;
40
+ }
41
+ function createHastText(value) {
42
+ return value ? {
43
+ type: "text",
44
+ value
45
+ } : void 0;
46
+ }
47
+ function cloneHastElement(element, children) {
48
+ return {
49
+ ...element,
50
+ properties: element.properties ? { ...element.properties } : void 0,
51
+ children
52
+ };
53
+ }
54
+ function pushHastNode(target, node) {
55
+ if (node) target.push(node);
56
+ }
57
+ function pushHastElementSlice(target, element, children) {
58
+ if (children.length) target.push(cloneHastElement(element, children));
59
+ }
60
+ function splitHastNodeByRange(node, nodeStart, start, end) {
61
+ const before = [];
62
+ const inside = [];
63
+ const after = [];
64
+ const nodeTextLength = getHastText(node).length;
65
+ const nodeEnd = nodeStart + nodeTextLength;
66
+ if (nodeEnd <= start) {
67
+ before.push(node);
68
+ return {
69
+ before,
70
+ inside,
71
+ after,
72
+ length: nodeTextLength
73
+ };
74
+ }
75
+ if (nodeStart >= end) {
76
+ after.push(node);
77
+ return {
78
+ before,
79
+ inside,
80
+ after,
81
+ length: nodeTextLength
82
+ };
83
+ }
84
+ if (node.type === "text") {
85
+ const localStart = Math.max(0, start - nodeStart);
86
+ const localEnd = Math.min(node.value.length, end - nodeStart);
87
+ pushHastNode(before, createHastText(node.value.slice(0, localStart)));
88
+ pushHastNode(inside, createHastText(node.value.slice(localStart, localEnd)));
89
+ pushHastNode(after, createHastText(node.value.slice(localEnd)));
90
+ return {
91
+ before,
92
+ inside,
93
+ after,
94
+ length: nodeTextLength
95
+ };
96
+ }
97
+ if (start <= nodeStart && nodeEnd <= end) {
98
+ inside.push(node);
99
+ return {
100
+ before,
101
+ inside,
102
+ after,
103
+ length: nodeTextLength
104
+ };
105
+ }
106
+ const splitChildren = splitHastNodesByRange(node.children ?? [], Math.max(0, start - nodeStart), Math.min(nodeTextLength, end - nodeStart));
107
+ pushHastElementSlice(before, node, splitChildren.before);
108
+ pushHastElementSlice(inside, node, splitChildren.inside);
109
+ pushHastElementSlice(after, node, splitChildren.after);
110
+ return {
111
+ before,
112
+ inside,
113
+ after,
114
+ length: nodeTextLength
115
+ };
116
+ }
117
+ function splitHastNodesByRange(nodes, start, end) {
118
+ const before = [];
119
+ const inside = [];
120
+ const after = [];
121
+ let offset = 0;
122
+ for (const node of nodes) {
123
+ const splitNode = splitHastNodeByRange(node, offset, start, end);
124
+ before.push(...splitNode.before);
125
+ inside.push(...splitNode.inside);
126
+ after.push(...splitNode.after);
127
+ offset += splitNode.length;
128
+ }
129
+ return {
130
+ before,
131
+ inside,
132
+ after
133
+ };
134
+ }
135
+ function applyClassAttributeValueWrapperToLine(line, start, end, decoration) {
136
+ const splitChildren = splitHastNodesByRange(line.children ?? [], start, end);
137
+ if (!splitChildren.inside.length) return;
138
+ const wrapper = {
139
+ type: "element",
140
+ tagName: decoration.tagName ?? "span",
141
+ properties: { ...decoration.properties ?? {} },
142
+ children: splitChildren.inside
143
+ };
144
+ const transformedWrapper = decoration.transform?.(wrapper, "wrapper");
145
+ line.children = [
146
+ ...splitChildren.before,
147
+ isHastElement(transformedWrapper) ? transformedWrapper : wrapper,
148
+ ...splitChildren.after
149
+ ];
150
+ }
151
+ function applyClassAttributeValueWrappers(root, source, decorations, sourceLineNumbers) {
152
+ if (!decorations.length) return;
153
+ const sourceLineRanges = createSourceLineRanges(source);
154
+ const codeElements = collectCodeElements(root);
155
+ for (const codeElement of codeElements) {
156
+ const lines = (codeElement.children ?? []).filter((child) => isHastElement(child) && hasHastClass(child, "line"));
157
+ const linesBySourceIndex = new Map(lines.map((line, index) => [(sourceLineNumbers?.get(line) ?? index + 1) - 1, line]));
158
+ for (const decoration of decorations) {
159
+ const { start, end } = decoration;
160
+ if (typeof start !== "number" || typeof end !== "number") continue;
161
+ for (let lineIndex = 0; lineIndex < sourceLineRanges.length; lineIndex++) {
162
+ const lineRange = sourceLineRanges[lineIndex];
163
+ if (end <= lineRange.start || start >= lineRange.end) continue;
164
+ const line = linesBySourceIndex.get(lineIndex);
165
+ if (!line) continue;
166
+ const visibleLineEnd = lineRange.start + getHastText(line).length;
167
+ const lineStart = Math.max(start, lineRange.start) - lineRange.start;
168
+ const lineEnd = Math.min(end, lineRange.end, visibleLineEnd) - lineRange.start;
169
+ if (lineStart < lineEnd) applyClassAttributeValueWrapperToLine(line, lineStart, lineEnd, decoration);
170
+ }
171
+ }
172
+ }
173
+ }
174
+ export { applyClassAttributeValueWrappers };
@@ -0,0 +1,8 @@
1
+ declare const languageServiceLanguageIds: Record<string, string>;
2
+ declare const cssDirectiveLanguageIds: Set<string>;
3
+ declare const classAttributeValueWrappersKey = "__masterCSSClassAttributeValueWrappers";
4
+ declare function isMasterCSSClassListLanguage(lang?: string): boolean;
5
+ declare function getMasterCSSShikiLanguageId(lang?: string): string | undefined;
6
+ declare function isMasterCSSShikiSupportedLanguage(lang?: string): boolean;
7
+ declare function getLanguageServiceLanguageId(lang?: string): string | undefined;
8
+ export { classAttributeValueWrappersKey, cssDirectiveLanguageIds, getLanguageServiceLanguageId, getMasterCSSShikiLanguageId, isMasterCSSClassListLanguage, isMasterCSSShikiSupportedLanguage, languageServiceLanguageIds };
@@ -0,0 +1,69 @@
1
+ // src/shiki/languages.ts
2
+ const shikiLanguageIds = {
3
+ html: "html",
4
+ "angular-html": "angular-html",
5
+ js: "javascript",
6
+ javascript: "javascript",
7
+ jsx: "jsx",
8
+ javascriptreact: "jsx",
9
+ ts: "typescript",
10
+ typescript: "typescript",
11
+ tsx: "tsx",
12
+ typescriptreact: "tsx",
13
+ css: "css",
14
+ scss: "scss",
15
+ less: "less",
16
+ postcss: "postcss",
17
+ vue: "vue",
18
+ svelte: "svelte",
19
+ astro: "astro",
20
+ md: "markdown",
21
+ markdown: "markdown",
22
+ mdx: "mdx"
23
+ };
24
+ const languageServiceLanguageIds = {
25
+ html: "html",
26
+ "angular-html": "html",
27
+ js: "javascript",
28
+ javascript: "javascript",
29
+ jsx: "javascriptreact",
30
+ javascriptreact: "javascriptreact",
31
+ ts: "typescript",
32
+ typescript: "typescript",
33
+ tsx: "typescriptreact",
34
+ typescriptreact: "typescriptreact",
35
+ css: "css",
36
+ scss: "scss",
37
+ less: "less",
38
+ postcss: "postcss",
39
+ vue: "vue",
40
+ svelte: "svelte",
41
+ astro: "astro",
42
+ md: "markdown",
43
+ markdown: "markdown",
44
+ mdx: "mdx"
45
+ };
46
+ const masterCSSClassListLanguageIds = /* @__PURE__ */ new Set(["mcss", "master-css"]);
47
+ const cssDirectiveLanguageIds = /* @__PURE__ */ new Set([
48
+ "css",
49
+ "scss",
50
+ "less",
51
+ "postcss"
52
+ ]);
53
+ const classAttributeValueWrappersKey = "__masterCSSClassAttributeValueWrappers";
54
+ const masterCSSShikiSupportedLanguageIds = /* @__PURE__ */ new Set([...Object.keys(shikiLanguageIds), ...Object.values(shikiLanguageIds)]);
55
+ function isMasterCSSClassListLanguage(lang) {
56
+ return Boolean(lang && masterCSSClassListLanguageIds.has(lang));
57
+ }
58
+ function getMasterCSSShikiLanguageId(lang) {
59
+ if (!lang) return;
60
+ return shikiLanguageIds[lang] ?? lang;
61
+ }
62
+ function isMasterCSSShikiSupportedLanguage(lang) {
63
+ const languageId = getMasterCSSShikiLanguageId(lang);
64
+ return Boolean(languageId && masterCSSShikiSupportedLanguageIds.has(languageId));
65
+ }
66
+ function getLanguageServiceLanguageId(lang) {
67
+ return lang ? languageServiceLanguageIds[lang] ?? lang : void 0;
68
+ }
69
+ export { classAttributeValueWrappersKey, cssDirectiveLanguageIds, getLanguageServiceLanguageId, getMasterCSSShikiLanguageId, isMasterCSSClassListLanguage, isMasterCSSShikiSupportedLanguage, languageServiceLanguageIds };