@master/css-language-service 2.0.0-rc.7 → 2.0.0-rc.71

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 (65) hide show
  1. package/README.md +114 -0
  2. package/dist/common.d.ts +1 -0
  3. package/dist/common.mjs +1 -0
  4. package/dist/core.d.ts +30 -0
  5. package/dist/core.mjs +114 -0
  6. package/dist/features/edit-syntax-colors.d.ts +4 -0
  7. package/dist/features/edit-syntax-colors.mjs +17 -0
  8. package/dist/features/inspect-syntax.d.ts +4 -0
  9. package/dist/features/inspect-syntax.mjs +54 -0
  10. package/dist/features/render-semantic-tokens.d.ts +5 -0
  11. package/dist/features/render-semantic-tokens.mjs +10 -0
  12. package/dist/features/render-syntax-colors.d.ts +4 -0
  13. package/dist/features/render-syntax-colors.mjs +102 -0
  14. package/dist/features/suggest-syntax.d.ts +5 -0
  15. package/dist/features/suggest-syntax.mjs +18 -0
  16. package/dist/index.d.ts +7 -5
  17. package/dist/index.mjs +7 -0
  18. package/dist/settings.d.ts +16 -9
  19. package/dist/settings.mjs +53 -0
  20. package/dist/utils/beautify-css.d.ts +1 -0
  21. package/dist/utils/beautify-css.mjs +11 -0
  22. package/dist/utils/completion-index.d.ts +38 -0
  23. package/dist/utils/completion-index.mjs +268 -0
  24. package/dist/utils/convert-color-token.d.ts +4 -0
  25. package/dist/utils/convert-color-token.mjs +55 -0
  26. package/dist/utils/create-css-markdown-documentation.d.ts +5 -0
  27. package/dist/utils/create-css-markdown-documentation.mjs +15 -0
  28. package/dist/utils/create-doc.d.ts +16 -0
  29. package/dist/utils/create-doc.mjs +21 -0
  30. package/dist/utils/get-class-completion-items.d.ts +4 -0
  31. package/dist/utils/get-class-completion-items.mjs +20 -0
  32. package/dist/utils/get-color-completion-items.d.ts +3 -0
  33. package/dist/utils/get-color-completion-items.mjs +24 -0
  34. package/dist/utils/get-position.d.ts +1 -0
  35. package/dist/utils/get-position.mjs +10 -0
  36. package/dist/utils/get-pseudo-class-completion-items.d.ts +4 -0
  37. package/dist/utils/get-pseudo-class-completion-items.mjs +68 -0
  38. package/dist/utils/get-pseudo-element-completion-items.d.ts +4 -0
  39. package/dist/utils/get-pseudo-element-completion-items.mjs +43 -0
  40. package/dist/utils/get-query-completion-items.d.ts +4 -0
  41. package/dist/utils/get-query-completion-items.mjs +77 -0
  42. package/dist/utils/get-range.d.ts +2 -0
  43. package/dist/utils/get-range.mjs +21 -0
  44. package/dist/utils/get-utility-info.d.ts +4 -0
  45. package/dist/utils/get-utility-info.mjs +19 -0
  46. package/dist/utils/get-value-completion-items.d.ts +4 -0
  47. package/dist/utils/get-value-completion-items.mjs +203 -0
  48. package/dist/utils/query-syntax-completions.d.ts +4 -0
  49. package/dist/utils/query-syntax-completions.mjs +94 -0
  50. package/dist/utils/regex.mjs +3 -0
  51. package/dist/utils/sort-completion-items.d.ts +2 -0
  52. package/dist/utils/sort-completion-items.mjs +11 -0
  53. package/package.json +1 -1
  54. package/dist/constant.d.ts +0 -33
  55. package/dist/index.bundle.js +0 -33
  56. package/dist/position-check.d.ts +0 -20
  57. package/dist/providers/color.d.ts +0 -5
  58. package/dist/providers/completion.d.ts +0 -14
  59. package/dist/providers/hover.d.ts +0 -2
  60. package/dist/settings.bundle.js +0 -1
  61. package/dist/utils/get-css-entry-markdown-description.d.ts +0 -1
  62. package/dist/utils/hex-to-rgb.d.ts +0 -2
  63. package/dist/utils/oklab-to-rgb.d.ts +0 -1
  64. package/dist/utils/oklch-to-oklab.d.ts +0 -1
  65. package/dist/utils/to-two-digit-hex.d.ts +0 -1
package/README.md ADDED
@@ -0,0 +1,114 @@
1
+ <br>
2
+ <div align="center">
3
+
4
+ <p align="center">
5
+ <a href="https://css.master.co">
6
+ <picture>
7
+ <source media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/33840671/201701649-3bb7d698-abec-4d5f-ac30-ccc4d7bafcd4.svg">
8
+ <source media="(prefers-color-scheme: light)" srcset="https://user-images.githubusercontent.com/33840671/201703010-77bf2373-9899-40cc-98f5-30cf9b546941.svg">
9
+ <img alt="Master CSS" src="https://user-images.githubusercontent.com/33840671/201703010-77bf2373-9899-40cc-98f5-30cf9b546941.svg" width="100%">
10
+ </picture>
11
+ </a>
12
+ </p>
13
+ <p align="center">Language Service for Master CSS</p>
14
+
15
+ <p align="center">
16
+ <a aria-label="GitHub release (latest by date including pre-releases)" href="https://github.com/master-co/css/releases">
17
+ <picture>
18
+ <source media="(prefers-color-scheme: dark)" srcset="https://img.shields.io/github/v/release/master-co/css?include_prereleases&color=212022&label=&style=for-the-badge&logo=github&logoColor=fff">
19
+ <source media="(prefers-color-scheme: light)" srcset="https://img.shields.io/github/v/release/master-co/css?include_prereleases&color=f6f7f8&label=&style=for-the-badge&logo=github&logoColor=%23000">
20
+ <img alt="NPM Version" src="https://img.shields.io/github/v/release/master-co/css?include_prereleases&color=f6f7f8&label=&style=for-the-badge&logo=github">
21
+ </picture>
22
+ </a>
23
+ <a aria-label="NPM Package" href="https://www.npmjs.com/package/@master/css-language-service">
24
+ <picture>
25
+ <source media="(prefers-color-scheme: dark)" srcset="https://img.shields.io/npm/dm/@master/css-language-service?color=212022&label=%20&logo=npm&style=for-the-badge">
26
+ <source media="(prefers-color-scheme: light)" srcset="https://img.shields.io/npm/dm/@master/css-language-service?color=f6f7f8&label=%20&logo=npm&style=for-the-badge">
27
+ <img alt="NPM package ( download / month )" src="https://img.shields.io/npm/dm/@master/css-language-service?color=f6f7f8&label=%20&logo=npm&style=for-the-badge">
28
+ </picture>
29
+ </a>
30
+ <a aria-label="JSDelivr" href="https://www.jsdelivr.com/package/npm/@master/css-language-service">
31
+ <picture>
32
+ <source media="(prefers-color-scheme: dark)" srcset="https://img.shields.io/jsdelivr/npm/hm/@master/css-language-service?color=212022&label=%20&logo=jsdelivr&style=for-the-badge">
33
+ <source media="(prefers-color-scheme: light)" srcset="https://img.shields.io/jsdelivr/npm/hm/@master/css-language-service?color=f6f7f8&label=%20&logo=jsdelivr&style=for-the-badge">
34
+ <img alt="JSDelivr hits (npm scoped)" src="https://img.shields.io/jsdelivr/npm/hm/@master/css-language-service?color=f6f7f8&label=%20&logo=jsdelivr&style=for-the-badge">
35
+ </picture>
36
+ </a>
37
+ <a aria-label="Discord Community" href="https://discord.gg/sZNKpAAAw6">
38
+ <picture>
39
+ <source media="(prefers-color-scheme: dark)" srcset="https://img.shields.io/discord/917780624314613760?color=212022&label=%20&logo=discord&style=for-the-badge">
40
+ <source media="(prefers-color-scheme: light)" srcset="https://img.shields.io/discord/917780624314613760?color=f6f7f8&label=%20&logo=discord&style=for-the-badge">
41
+ <img alt="Discord online" src="https://img.shields.io/discord/917780624314613760?color=f6f7f8&label=%20&logo=discord&style=for-the-badge">
42
+ </picture>
43
+ </a>
44
+ <a aria-label="Follow @mastercorg" href="https://twitter.com/mastercorg">
45
+ <picture>
46
+ <source media="(prefers-color-scheme: dark)" srcset="https://img.shields.io/static/v1?label=%20&message=twitter&color=212022&logo=twitter&style=for-the-badge">
47
+ <source media="(prefers-color-scheme: light)" srcset="https://img.shields.io/static/v1?label=%20&message=twitter&color=f6f7f8&logo=twitter&style=for-the-badge">
48
+ <img alt="Follow @mastercorg" src="https://img.shields.io/static/v1?label=%20&message=twitter&color=f6f7f8&logo=twitter&style=for-the-badge">
49
+ </picture>
50
+ </a>
51
+ <a aria-label="Github Actions" href="https://github.com/master-co/css/actions/workflows/ci-release.yml">
52
+ <picture>
53
+ <source media="(prefers-color-scheme: dark)" srcset="https://img.shields.io/github/actions/workflow/status/master-co/css/ci-release.yml?branch=rc&label=%20&message=twitter&color=212022&logo=githubactions&style=for-the-badge">
54
+ <source media="(prefers-color-scheme: light)" srcset="https://img.shields.io/github/actions/workflow/status/master-co/css/ci-release.yml?branch=rc&label=%20&message=twitter&color=f6f7f8&logo=githubactions&style=for-the-badge&logoColor=%23000">
55
+ <img alt="Github release actions" src="https://img.shields.io/github/actions/workflow/status/master-co/css/ci-release.yml?branch=rc&label=%20&message=twitter&color=f6f7f8&logo=githubactions&style=for-the-badge&logoColor=%23000">
56
+ </picture>
57
+ </a>
58
+ </p>
59
+
60
+ </div>
61
+
62
+ ## Installation
63
+
64
+ ```bash
65
+ npm install @master/css-language-service
66
+ ```
67
+
68
+ ## Usage
69
+
70
+ ```js
71
+ import CSSLanguageService from '@master/css-language-service'
72
+
73
+ const languageService = new CSSLanguageService(customSettings)
74
+ ```
75
+
76
+ `CSSLanguageService` provides stateful completion, hover, color, color presentation, and semantic token features around the editor-neutral primitives in `@master/css-language`.
77
+
78
+ ### Semantic tokens
79
+
80
+ ```ts
81
+ const semanticTokens = languageService.renderSemanticTokens(textDocument)
82
+ ```
83
+
84
+ Semantic tokens are generated with the project manifest, so custom variables, components, utilities, modes, and other manifest-dependent tokens can be classified after the caller loads the manifest.
85
+
86
+ Use `renderSemanticTokensAtPosition()` when a client wants active-only highlighting for the embedded class context at the current editor position.
87
+
88
+ ```ts
89
+ const semanticTokens = languageService.renderSemanticTokensAtPosition(textDocument, position)
90
+ ```
91
+
92
+ CSS directive syntax in CSS-family documents is highlighted by the shared TextMate grammar. Semantic tokens are only added for directive class-list spans such as bare `@compose` preludes and quoted `@safelist` strings.
93
+
94
+ ## Settings
95
+
96
+ ```js
97
+ import { settings } from '@master/css-language-service'
98
+ ```
99
+
100
+ | Setting | Type | Default | Description |
101
+ | --- | --- | --- | --- |
102
+ | `includedLanguages` | `string[]` | Common web and template languages | Language IDs that receive language-service features. |
103
+ | `exclude` | `string[]` | `["**/.git/**", "**/node_modules/**", "**/.hg/**"]` | Glob patterns excluded from all features. |
104
+ | `classAttributes` | `string[]` | `["class", "className"]` | Quoted markup attributes that contain Master CSS class strings. |
105
+ | `classAttributeBindings` | `Record<string, [string, string] \| false>` | Framework binding defaults | Bound attributes such as `:class`, `[ngClass]`, and `class:list`. |
106
+ | `classFunctions` | `string[]` | Common class helpers | Functions and methods whose string arguments contain classes, such as `clsx()` and `classList.add()`. |
107
+ | `classDeclarations` | `string[]` | `[]` | Variable declarations or object properties whose string values contain classes. |
108
+ | `suggestSyntax` | `boolean` | `true` | Enables syntax suggestions. |
109
+ | `inspectSyntax` | `boolean` | `true` | Enables hover inspection and generated CSS previews. |
110
+ | `renderSyntaxColors` | `boolean` | `true` | Enables color rendering. |
111
+ | `editSyntaxColors` | `boolean` | `true` | Enables color editing. |
112
+ | `embeddedSyntaxHighlighting` | `'active' \| 'always' \| 'off'` | `'active'` | Controls embedded semantic token highlighting. |
113
+
114
+ Use `@master/css-language` directly for browser helpers, Shiki integration, TextMate grammar assets, and raw class-position scanning.
@@ -0,0 +1 @@
1
+ export { AT_TRIGGER_CHARACTER, DECLARATION_SEPARATOR_TRIGGER_CHARACTER, GROUP_TRIGGER_CHARACTER, INVOKED_TRIGGER_CHARACTERS, QUERY_TRIGGER_CHARACTERS, SELECTOR_TRIGGER_CHARACTERS, VALUE_TRIGGER_CHARACTERS } from '@master/css-language';
@@ -0,0 +1 @@
1
+ export { AT_TRIGGER_CHARACTER, DECLARATION_SEPARATOR_TRIGGER_CHARACTER, GROUP_TRIGGER_CHARACTER, INVOKED_TRIGGER_CHARACTERS, QUERY_TRIGGER_CHARACTERS, SELECTOR_TRIGGER_CHARACTERS, VALUE_TRIGGER_CHARACTERS } from '@master/css-language';
package/dist/core.d.ts ADDED
@@ -0,0 +1,30 @@
1
+ import { MasterCSS, type ClassPosition } from '@master/css-language';
2
+ import EventEmitter from 'node:events';
3
+ import type { Position } from 'vscode-languageserver-protocol';
4
+ import { type Settings } from './settings';
5
+ import inspectSyntax from './features/inspect-syntax';
6
+ import renderSyntaxColors from './features/render-syntax-colors';
7
+ import editSyntaxColors from './features/edit-syntax-colors';
8
+ import renderSemanticTokens, { renderSemanticTokensAtPosition } from './features/render-semantic-tokens';
9
+ import suggestSyntax from './features/suggest-syntax';
10
+ import { TextDocument } from 'vscode-languageserver-textdocument';
11
+ export type { ClassPosition };
12
+ export default class CSSLanguageService extends EventEmitter {
13
+ customSettings?: Settings | undefined;
14
+ css: MasterCSS;
15
+ settings: Settings;
16
+ private completionIndex?;
17
+ private classPositionCache;
18
+ constructor(customSettings?: Settings | undefined);
19
+ private getCompletionIndex;
20
+ inspectSyntax(...params: Parameters<typeof inspectSyntax>): import("vscode-languageserver-protocol").Hover | undefined;
21
+ renderSyntaxColors(...params: Parameters<typeof renderSyntaxColors>): Promise<import("vscode-languageserver-protocol").ColorInformation[] | undefined> | undefined;
22
+ editSyntaxColors(...params: Parameters<typeof editSyntaxColors>): import("vscode-languageserver-protocol").ColorPresentation[] | undefined;
23
+ renderSemanticTokens(...params: Parameters<typeof renderSemanticTokens>): import("vscode-languageserver-protocol").SemanticTokens | undefined;
24
+ renderSemanticTokensAtPosition(...params: Parameters<typeof renderSemanticTokensAtPosition>): import("vscode-languageserver-protocol").SemanticTokens | undefined;
25
+ suggestSyntax(document: Parameters<typeof suggestSyntax>[0], position: Parameters<typeof suggestSyntax>[1], context: Parameters<typeof suggestSyntax>[2]): import("vscode-languageserver-protocol").CompletionItem[] | undefined;
26
+ getClassPositions(textDocument: TextDocument): ClassPosition[];
27
+ getClassPosition(textDocument: TextDocument, position: Position): ClassPosition | undefined;
28
+ getClassContextPositions(textDocument: TextDocument, position: Position): ClassPosition[];
29
+ isDocumentAccepted(doc: TextDocument): boolean;
30
+ }
package/dist/core.mjs ADDED
@@ -0,0 +1,114 @@
1
+ import { ClassPositionCache, MasterCSS, matchesLanguageServiceNativeDeclaration, defaultManifest, getClassPositions } from '@master/css-language';
2
+ import extend from '@techor/extend';
3
+ import EventEmitter from 'node:events';
4
+ import settings from './settings.mjs';
5
+ import { minimatch } from 'minimatch';
6
+ import inspectSyntax from './features/inspect-syntax.mjs';
7
+ import renderSyntaxColors from './features/render-syntax-colors.mjs';
8
+ import editSyntaxColors from './features/edit-syntax-colors.mjs';
9
+ import renderSemanticTokens, { renderSemanticTokensAtPosition } from './features/render-semantic-tokens.mjs';
10
+ import suggestSyntax from './features/suggest-syntax.mjs';
11
+ import { createCompletionIndex } from './utils/completion-index.mjs';
12
+
13
+ class CSSLanguageService extends EventEmitter {
14
+ customSettings;
15
+ css;
16
+ settings;
17
+ completionIndex;
18
+ classPositionCache = new ClassPositionCache();
19
+ constructor(customSettings){
20
+ super(), this.customSettings = customSettings;
21
+ this.settings = extend(settings, customSettings);
22
+ this.css = MasterCSS.create({
23
+ manifest: this.settings.manifest || defaultManifest,
24
+ nativeDeclarationMatcher: matchesLanguageServiceNativeDeclaration
25
+ });
26
+ }
27
+ getCompletionIndex() {
28
+ this.completionIndex ??= createCompletionIndex(this.css);
29
+ return this.completionIndex;
30
+ }
31
+ inspectSyntax(...params) {
32
+ if (this.settings.inspectSyntax && this.isDocumentAccepted(params[0])) return inspectSyntax?.call(this, ...params);
33
+ }
34
+ renderSyntaxColors(...params) {
35
+ if (this.settings.renderSyntaxColors && this.isDocumentAccepted(params[0])) return renderSyntaxColors?.call(this, ...params);
36
+ }
37
+ editSyntaxColors(...params) {
38
+ if (this.settings.editSyntaxColors && this.isDocumentAccepted(params[0])) return editSyntaxColors?.call(this, ...params);
39
+ }
40
+ renderSemanticTokens(...params) {
41
+ if (this.isDocumentAccepted(params[0])) return renderSemanticTokens?.call(this, ...params);
42
+ }
43
+ renderSemanticTokensAtPosition(...params) {
44
+ if (this.isDocumentAccepted(params[0])) return renderSemanticTokensAtPosition?.call(this, ...params);
45
+ }
46
+ suggestSyntax(document, position, context) {
47
+ if (this.settings.suggestSyntax && this.isDocumentAccepted(document)) return suggestSyntax?.call(this, document, position, context, this.getCompletionIndex());
48
+ }
49
+ getClassPositions(textDocument) {
50
+ return getClassPositions(textDocument, this.settings, {
51
+ cache: this.classPositionCache
52
+ });
53
+ }
54
+ getClassPosition(textDocument, position) {
55
+ const cachedOxcClassPosition = getClassPositions(textDocument, this.settings, {
56
+ position,
57
+ includeEmpty: true,
58
+ provider: 'oxc',
59
+ oxcMode: 'cache-only',
60
+ cache: this.classPositionCache
61
+ })[0];
62
+ if (cachedOxcClassPosition) return cachedOxcClassPosition;
63
+ const regexClassPosition = getClassPositions(textDocument, this.settings, {
64
+ position,
65
+ includeEmpty: true,
66
+ provider: 'regex'
67
+ })[0];
68
+ if (regexClassPosition && !regexClassPosition.raw.includes('${')) {
69
+ return regexClassPosition;
70
+ }
71
+ return getClassPositions(textDocument, this.settings, {
72
+ position,
73
+ includeEmpty: true,
74
+ provider: 'oxc',
75
+ cache: this.classPositionCache
76
+ })[0] ?? regexClassPosition;
77
+ }
78
+ getClassContextPositions(textDocument, position) {
79
+ const cachedOxcClassPositions = getClassPositions(textDocument, this.settings, {
80
+ position,
81
+ provider: 'oxc',
82
+ oxcMode: 'cache-only',
83
+ positionMatch: 'context',
84
+ cache: this.classPositionCache
85
+ });
86
+ if (cachedOxcClassPositions.length) return cachedOxcClassPositions;
87
+ const regexClassPositions = getClassPositions(textDocument, this.settings, {
88
+ position,
89
+ provider: 'regex',
90
+ positionMatch: 'context'
91
+ });
92
+ if (regexClassPositions.length && regexClassPositions.every(({ raw })=>!raw.includes('${'))) {
93
+ return regexClassPositions;
94
+ }
95
+ const oxcClassPositions = getClassPositions(textDocument, this.settings, {
96
+ position,
97
+ provider: 'oxc',
98
+ positionMatch: 'context',
99
+ cache: this.classPositionCache
100
+ });
101
+ return oxcClassPositions.length ? oxcClassPositions : regexClassPositions;
102
+ }
103
+ isDocumentAccepted(doc) {
104
+ if (!this.settings.exclude) return true;
105
+ for (const exclude of this.settings.exclude){
106
+ if (minimatch(doc.uri, exclude)) {
107
+ return false;
108
+ }
109
+ }
110
+ return true;
111
+ }
112
+ }
113
+
114
+ export { CSSLanguageService as default };
@@ -0,0 +1,4 @@
1
+ import type { TextDocument } from 'vscode-languageserver-textdocument';
2
+ import CSSLanguageService from '../core';
3
+ import type { ColorPresentationParams, ColorPresentation } from 'vscode-languageserver-protocol';
4
+ export default function editSyntaxColors(this: CSSLanguageService, document: TextDocument, color: ColorPresentationParams['color'], range: ColorPresentationParams['range']): ColorPresentation[];
@@ -0,0 +1,17 @@
1
+ import convertColorByToken from '../utils/convert-color-token.mjs';
2
+
3
+ function editSyntaxColors(document, color, range) {
4
+ const colorPresentations = [];
5
+ const selectedColorToken = document.getText(range);
6
+ const targetColorToken = convertColorByToken(color, selectedColorToken, this.css);
7
+ if (targetColorToken) colorPresentations.push({
8
+ label: targetColorToken,
9
+ textEdit: {
10
+ range,
11
+ newText: targetColorToken
12
+ }
13
+ });
14
+ return colorPresentations;
15
+ }
16
+
17
+ export { editSyntaxColors as default };
@@ -0,0 +1,4 @@
1
+ import type { Hover, HoverParams } from 'vscode-languageserver-protocol';
2
+ import type CSSLanguageService from '../core';
3
+ import type { TextDocument } from 'vscode-languageserver-textdocument';
4
+ export default function inspectSyntax(this: CSSLanguageService, document: TextDocument, position: HoverParams['position']): Hover | undefined;
@@ -0,0 +1,54 @@
1
+ import createCSSMarkdownDocumentation from '../utils/create-css-markdown-documentation.mjs';
2
+ import { UtilityType, generateCSS } from '@master/css-language';
3
+
4
+ function inspectSyntax(document, position) {
5
+ const classPosition = this.getClassPosition(document, position);
6
+ if (!classPosition) return;
7
+ const { token } = classPosition;
8
+ const range = {
9
+ start: document.positionAt(classPosition.range.start),
10
+ end: document.positionAt(classPosition.range.end)
11
+ };
12
+ const utilities = this.css.generate(token);
13
+ const component = utilities.find((utility)=>utility.type === UtilityType.Semantic && utility.layerName === 'components');
14
+ if (component) {
15
+ const documentation = createCSSMarkdownDocumentation(generateCSS([
16
+ token
17
+ ], this.css));
18
+ if (documentation) {
19
+ return {
20
+ contents: {
21
+ kind: documentation.kind,
22
+ value: `(components) ` + documentation.value
23
+ }
24
+ };
25
+ }
26
+ } else {
27
+ const utility = utilities[0];
28
+ if (utility) {
29
+ if (utility.type === UtilityType.Semantic) {
30
+ const documentation = createCSSMarkdownDocumentation(generateCSS([
31
+ token
32
+ ], this.css));
33
+ if (documentation) {
34
+ return {
35
+ contents: documentation,
36
+ range
37
+ };
38
+ }
39
+ } else {
40
+ const documentation = createCSSMarkdownDocumentation(generateCSS([
41
+ token
42
+ ], this.css));
43
+ if (documentation) {
44
+ return {
45
+ contents: documentation,
46
+ range
47
+ };
48
+ }
49
+ }
50
+ }
51
+ }
52
+ }
53
+
54
+ export { inspectSyntax as default };
@@ -0,0 +1,5 @@
1
+ import type CSSLanguageService from '../core';
2
+ import type { TextDocument } from 'vscode-languageserver-textdocument';
3
+ import type { SemanticTokens } from 'vscode-languageserver-protocol';
4
+ export declare function renderSemanticTokensAtPosition(this: CSSLanguageService, document: TextDocument, position: Parameters<CSSLanguageService['getClassPosition']>[1]): SemanticTokens | undefined;
5
+ export default function renderSemanticTokens(this: CSSLanguageService, document: TextDocument): SemanticTokens | undefined;
@@ -0,0 +1,10 @@
1
+ import { renderSemanticTokens as renderSemanticTokens$1, renderSemanticTokensAtPosition as renderSemanticTokensAtPosition$1 } from '@master/css-language';
2
+
3
+ function renderSemanticTokensAtPosition(document, position) {
4
+ return renderSemanticTokensAtPosition$1(this.css, document, this.getClassContextPositions(document, position), position, this.settings);
5
+ }
6
+ function renderSemanticTokens(document) {
7
+ return renderSemanticTokens$1(this.css, document, this.getClassPositions(document), this.settings);
8
+ }
9
+
10
+ export { renderSemanticTokens as default, renderSemanticTokensAtPosition };
@@ -0,0 +1,4 @@
1
+ import type { ColorInformation } from 'vscode-languageserver-protocol';
2
+ import CSSLanguageService from '../core';
3
+ import type { TextDocument } from 'vscode-languageserver-textdocument';
4
+ export default function renderSyntaxColors(this: CSSLanguageService, document: TextDocument): Promise<ColorInformation[] | undefined>;
@@ -0,0 +1,102 @@
1
+ import { instancePattern } from '../utils/regex.mjs';
2
+ import Color from 'colorjs.io';
3
+ import { UtilityType } from '@master/css-language';
4
+
5
+ function resolveVariableColorValue(variable, variables) {
6
+ let current = variable;
7
+ for(let i = 0; i < 8; i++){
8
+ const value = current?.value;
9
+ if (value === undefined) return;
10
+ const text = String(value);
11
+ const alias = /^\$([a-zA-Z0-9-]+)(?: ?\/ ?.+?)?$|^var\(--([_a-zA-Z0-9-]+)\)$/.exec(text);
12
+ const aliasName = alias?.[1] ?? alias?.[2];
13
+ if (!aliasName) return text;
14
+ current = variables.get(aliasName);
15
+ }
16
+ }
17
+ async function renderSyntaxColors(document) {
18
+ const text = document.getText() ?? '';
19
+ const colorInformations = [];
20
+ try {
21
+ for (const instanceMatch of text.matchAll(instancePattern)){
22
+ if (instanceMatch.index === undefined) break;
23
+ const instanceStartIndex = instanceMatch.index;
24
+ const syntax = instanceMatch[0];
25
+ const rule = this.css.generate(syntax)[0];
26
+ if (rule && rule.type !== UtilityType.Semantic) {
27
+ const keyTokenLength = rule.keyToken?.length ?? 0;
28
+ let currentLength = 0;
29
+ const resolveValueComponent = (valueComponent)=>{
30
+ if (valueComponent.text === undefined) return; // text is always existing, just for type
31
+ const startOffset = instanceStartIndex + keyTokenLength + currentLength;
32
+ // TODO: check number mt:1.875rem
33
+ const valueComponentTokenLength = valueComponent.token.length;
34
+ let color;
35
+ switch(valueComponent.type){
36
+ case 'function':
37
+ if ([
38
+ 'rgb',
39
+ 'rgba',
40
+ 'hsl',
41
+ 'hsla',
42
+ 'hwb',
43
+ 'lab',
44
+ 'lch',
45
+ 'oklab',
46
+ 'oklch',
47
+ 'color'
48
+ ].includes(valueComponent.name)) {
49
+ color = new Color(valueComponent.text);
50
+ } else if (valueComponent.children.length) {
51
+ currentLength += valueComponent.name.length + 1; // function name + '('
52
+ valueComponent.children.forEach(resolveValueComponent);
53
+ }
54
+ break;
55
+ case 'variable':
56
+ if (valueComponent.variable?.namespace?.startsWith('color') && valueComponent.variable.value !== undefined) {
57
+ color = new Color(resolveVariableColorValue(valueComponent.variable, this.css.variables) || String(valueComponent.variable.value));
58
+ if (valueComponent.alpha !== undefined) {
59
+ color.alpha *= valueComponent.alpha;
60
+ }
61
+ }
62
+ break;
63
+ case 'string':
64
+ if (valueComponent.text !== '#' && valueComponent.text?.startsWith('#')) {
65
+ color = new Color(valueComponent.text);
66
+ }
67
+ break;
68
+ }
69
+ // check if rgba is valid
70
+ if (color) {
71
+ const rgbaColor = color.to('srgb');
72
+ colorInformations.push({
73
+ range: {
74
+ start: document.positionAt(startOffset),
75
+ end: document.positionAt(startOffset + valueComponentTokenLength)
76
+ },
77
+ color: {
78
+ red: rgbaColor.r ?? 0,
79
+ green: rgbaColor.g ?? 0,
80
+ blue: rgbaColor.b ?? 0,
81
+ alpha: Number(rgbaColor.alpha)
82
+ }
83
+ });
84
+ }
85
+ currentLength += valueComponentTokenLength || 0;
86
+ };
87
+ rule.valueComponents.forEach(resolveValueComponent);
88
+ }
89
+ }
90
+ } catch (e) {}
91
+ const colorIndexSet = new Set();
92
+ return colorInformations.filter((item)=>{
93
+ if (colorIndexSet.has(item.range.start)) {
94
+ return false;
95
+ } else {
96
+ colorIndexSet.add(item.range.start);
97
+ return true;
98
+ }
99
+ });
100
+ }
101
+
102
+ export { renderSyntaxColors as default };
@@ -0,0 +1,5 @@
1
+ import type { CompletionItem, CompletionParams } from 'vscode-languageserver-protocol';
2
+ import type { TextDocument } from 'vscode-languageserver-textdocument';
3
+ import CSSLanguageService from '../core';
4
+ import type { CompletionIndex } from '../utils/completion-index';
5
+ export default function suggestSyntax(this: CSSLanguageService, document: TextDocument, position: CompletionParams['position'], context: CompletionParams['context'], completionIndex?: CompletionIndex): CompletionItem[] | undefined;
@@ -0,0 +1,18 @@
1
+ import querySyntaxCompletions from '../utils/query-syntax-completions.mjs';
2
+
3
+ function suggestSyntax(document, position, context, completionIndex) {
4
+ const classPosition = this.getClassPosition(document, position);
5
+ if (classPosition !== undefined) {
6
+ const q = context?.triggerCharacter === ' ' ? '' : document.getText({
7
+ start: document.positionAt(classPosition.range.start),
8
+ end: position
9
+ });
10
+ return querySyntaxCompletions(q, this.css, completionIndex);
11
+ }
12
+ // todo
13
+ // else if (isInstance === true && checkConfigColorsBlock(document, position) === true) {
14
+ // return getColorCompletionItems(this.css)
15
+ // }
16
+ }
17
+
18
+ export { suggestSyntax as default };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,7 @@
1
- export { getDocumentColors, getColorValue, getColorPresentation } from './providers/color';
2
- export { checkConfigColorsBlock, getLastInstance, getConfigColorsCompletionItem, getCompletionItem, getReturnItem } from './providers/completion';
3
- export { doHover } from './providers/hover';
4
- export { positionCheck } from './position-check';
5
- export { settings } from './settings';
1
+ export { default, default as CSSLanguageService } from './core';
2
+ export { default as settings, type Settings } from './settings';
3
+ export * from './common';
4
+ export { default as inspectSyntax } from './features/inspect-syntax';
5
+ export { default as renderSyntaxColors } from './features/render-syntax-colors';
6
+ export { default as editSyntaxColors } from './features/edit-syntax-colors';
7
+ export { default as suggestSyntax } from './features/suggest-syntax';
package/dist/index.mjs ADDED
@@ -0,0 +1,7 @@
1
+ export { default as CSSLanguageService, default } from './core.mjs';
2
+ export { default as settings } from './settings.mjs';
3
+ export { default as inspectSyntax } from './features/inspect-syntax.mjs';
4
+ export { default as renderSyntaxColors } from './features/render-syntax-colors.mjs';
5
+ export { default as editSyntaxColors } from './features/edit-syntax-colors.mjs';
6
+ export { default as suggestSyntax } from './features/suggest-syntax.mjs';
7
+ export { AT_TRIGGER_CHARACTER, DECLARATION_SEPARATOR_TRIGGER_CHARACTER, GROUP_TRIGGER_CHARACTER, INVOKED_TRIGGER_CHARACTERS, QUERY_TRIGGER_CHARACTERS, SELECTOR_TRIGGER_CHARACTERS, VALUE_TRIGGER_CHARACTERS } from '@master/css-language';
@@ -1,9 +1,16 @@
1
- export declare const settings: {
2
- languages: string[];
3
- classMatch: string[];
4
- exclude: string[];
5
- suggestions: boolean;
6
- inspect: boolean;
7
- previewColors: boolean;
8
- config: string;
9
- };
1
+ import { type LanguageSettings } from '@master/css-language';
2
+ import type { MasterCSSManifest } from '@master/css';
3
+ /**
4
+ * @example styles https://regex101.com/r/HLPdsw/1
5
+ **/
6
+ declare const settings: Settings;
7
+ export default settings;
8
+ export declare interface Settings extends LanguageSettings {
9
+ includedLanguages?: string[];
10
+ exclude?: string[];
11
+ manifest?: MasterCSSManifest;
12
+ suggestSyntax?: boolean;
13
+ inspectSyntax?: boolean;
14
+ renderSyntaxColors?: boolean;
15
+ editSyntaxColors?: boolean;
16
+ }
@@ -0,0 +1,53 @@
1
+ import { languageSettings } from '@master/css-language';
2
+
3
+ /**
4
+ * @example styles https://regex101.com/r/HLPdsw/1
5
+ **/ const settings = {
6
+ includedLanguages: [
7
+ "html",
8
+ "php",
9
+ "javascript",
10
+ "typescript",
11
+ "javascriptreact",
12
+ "typescriptreact",
13
+ "css",
14
+ "scss",
15
+ "less",
16
+ "vue",
17
+ "svelte",
18
+ "rust",
19
+ "astro",
20
+ "markdown",
21
+ "mdx",
22
+ "astro"
23
+ ],
24
+ /**
25
+ * @example <div class="a b">
26
+ * @example <div className="a b">
27
+ */ classAttributes: languageSettings.classAttributes,
28
+ /**
29
+ * @example <div class={active ? 'a' : 'b'}>
30
+ * @example <div className={active ? 'a' : 'b'}>
31
+ */ classAttributeBindings: languageSettings.classAttributeBindings,
32
+ /**
33
+ * @example const classes = 'a b'
34
+ * @example { classes: { btn: 'a b' } }
35
+ */ classDeclarations: languageSettings.classDeclarations,
36
+ /**
37
+ * @example clsx('a b')
38
+ * @example styled`a b`
39
+ * @example .classList.add('a')
40
+ */ classFunctions: languageSettings.classFunctions,
41
+ exclude: [
42
+ "**/.git/**",
43
+ "**/node_modules/**",
44
+ "**/.hg/**"
45
+ ],
46
+ suggestSyntax: true,
47
+ inspectSyntax: true,
48
+ renderSyntaxColors: true,
49
+ editSyntaxColors: true,
50
+ embeddedSyntaxHighlighting: 'active'
51
+ };
52
+
53
+ export { settings as default };
@@ -0,0 +1 @@
1
+ export default function beautifyCSS(text: string): any;
@@ -0,0 +1,11 @@
1
+ import { css_beautify } from 'js-beautify/js/lib/beautify-css.js';
2
+
3
+ // @ts-expect-error
4
+ function beautifyCSS(text) {
5
+ return css_beautify(text.replace(/@(media|container|supports|layer)\(/g, '@$1 ('), {
6
+ newline_between_rules: false,
7
+ indent_size: 2
8
+ });
9
+ }
10
+
11
+ export { beautifyCSS as default };