@master/css-mcp 2.0.0-rc.88 → 2.0.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.
Files changed (47) hide show
  1. package/README.md +47 -22
  2. package/dist/bin/index.js +4 -5
  3. package/dist/classes.js +153 -168
  4. package/dist/compare.js +99 -83
  5. package/dist/context.d.ts +5 -10
  6. package/dist/context.js +28 -10
  7. package/dist/design-system-schema.js +97 -0
  8. package/dist/directives.js +59 -109
  9. package/dist/document.js +2 -10
  10. package/dist/format.js +67 -56
  11. package/dist/index.d.ts +2 -3
  12. package/dist/index.js +1 -3
  13. package/dist/internal/src/workspace.js +70 -0
  14. package/dist/language.js +27 -23
  15. package/dist/lint.js +86 -96
  16. package/dist/manifest-query.js +40 -100
  17. package/dist/manifest-summary.js +15 -35
  18. package/dist/output-schema.js +207 -0
  19. package/dist/preview-write-lock.js +90 -0
  20. package/dist/project-comparison-schema.js +59 -0
  21. package/dist/project.js +77 -18
  22. package/dist/result.js +67 -8
  23. package/dist/scan.js +93 -73
  24. package/dist/semantic-schema.js +286 -0
  25. package/dist/server.d.ts +10 -9
  26. package/dist/server.js +123 -111
  27. package/dist/setup.js +28 -29
  28. package/dist/source-schema.js +141 -0
  29. package/dist/suggest.js +22 -0
  30. package/dist/tooling-session.js +27 -0
  31. package/package.json +63 -73
  32. package/LICENSE +0 -21
  33. package/dist/classes.d.ts +0 -236
  34. package/dist/compare.d.ts +0 -70
  35. package/dist/contributor.d.ts +0 -149
  36. package/dist/contributor.js +0 -499
  37. package/dist/directives.d.ts +0 -132
  38. package/dist/document.d.ts +0 -24
  39. package/dist/format.d.ts +0 -56
  40. package/dist/language.d.ts +0 -24
  41. package/dist/lint.d.ts +0 -55
  42. package/dist/manifest-query.d.ts +0 -148
  43. package/dist/manifest-summary.d.ts +0 -47
  44. package/dist/project.d.ts +0 -31
  45. package/dist/result.d.ts +0 -8
  46. package/dist/scan.d.ts +0 -156
  47. package/dist/setup.d.ts +0 -67
package/dist/document.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { extname } from "node:path";
2
2
  import { pathToFileURL } from "node:url";
3
3
  import { TextDocument } from "vscode-languageserver-textdocument";
4
- //#region src/document.ts
4
+ // src/document.ts
5
5
  const languageByExtension = {
6
6
  ".astro": "astro",
7
7
  ".css": "css",
@@ -30,13 +30,6 @@ function getLanguageId(filePath) {
30
30
  function createMCPTextDocument(filePath, content) {
31
31
  return TextDocument.create(pathToFileURL(filePath).href, getLanguageId(filePath), 0, content);
32
32
  }
33
- function toOffsetRange(document, range) {
34
- if (!range) return;
35
- return {
36
- start: document.offsetAt(range.start),
37
- end: document.offsetAt(range.end)
38
- };
39
- }
40
33
  function applyTextEdits(content, document, edits) {
41
34
  let result = content;
42
35
  const offsetEdits = edits.map((edit) => ({
@@ -47,5 +40,4 @@ function applyTextEdits(content, document, edits) {
47
40
  for (const edit of offsetEdits.sort((a, b) => b.start - a.start || b.end - a.end)) result = result.slice(0, edit.start) + edit.newText + result.slice(edit.end);
48
41
  return result;
49
42
  }
50
- //#endregion
51
- export { applyTextEdits, createMCPTextDocument, getLanguageId, languageByExtension, toOffsetRange };
43
+ export { applyTextEdits, createMCPTextDocument, getLanguageId, languageByExtension };
package/dist/format.js CHANGED
@@ -1,8 +1,10 @@
1
- import { applyTextEdits, createMCPTextDocument, getLanguageId } from "./document.js";
1
+ import { loadWorkspaceManifest, manifestMetadata, requireWorkspaceManifest } from "./project.js";
2
2
  import { resolveSourceFiles } from "./scan.js";
3
+ import { applyTextEdits, createMCPTextDocument, getLanguageId } from "./document.js";
3
4
  import { readFile } from "node:fs/promises";
4
- import CSSLanguageService from "@master/css-language-service";
5
- //#region src/format.ts
5
+ import { createToolingSessionSync } from "@master/css-tooling/node";
6
+ import { MasterCSSLanguageService } from "@master/css-language-service";
7
+ // src/format.ts
6
8
  const DIRECTIVE_FORMAT_PREVIEW_VERSION = 1;
7
9
  const DEFAULT_DIRECTIVE_FORMAT_PATTERNS = ["**/*.{css,scss,less,vue,svelte,astro}"];
8
10
  function formatContent(service, filePath, content, range) {
@@ -14,69 +16,78 @@ function formatContent(service, filePath, content, range) {
14
16
  languageId: getLanguageId(filePath),
15
17
  edits,
16
18
  changed: formatted !== content,
17
- beforeBytes: content.length,
18
- afterBytes: formatted.length,
19
+ beforeBytes: Buffer.byteLength(content, "utf8"),
20
+ afterBytes: Buffer.byteLength(formatted, "utf8"),
19
21
  formatted
20
22
  };
21
23
  }
22
24
  async function previewDirectiveFormat(context, options = {}) {
23
- const service = new CSSLanguageService();
24
- if (options.content !== void 0) {
25
- const filePath = context.resolveVirtualPath(options.filePath || "master.css");
26
- const formatted = formatContent(service, filePath, options.content, options.range);
25
+ const manifest = await loadWorkspaceManifest(context, options.context);
26
+ const service = new MasterCSSLanguageService(void 0, { session: createToolingSessionSync({
27
+ manifest: requireWorkspaceManifest(manifest),
28
+ nativeClassNames: manifest.nativeClassNames
29
+ }) });
30
+ try {
31
+ if (options.content !== void 0) {
32
+ const filePath = context.resolveVirtualPath(options.filePath || "master.css");
33
+ const formatted = formatContent(service, filePath, options.content, options.range);
34
+ return {
35
+ version: DIRECTIVE_FORMAT_PREVIEW_VERSION,
36
+ manifest: manifestMetadata(manifest),
37
+ root: context.root,
38
+ mode: "content",
39
+ files: [{
40
+ filePath,
41
+ languageId: formatted.languageId,
42
+ edits: formatted.edits,
43
+ changed: formatted.changed,
44
+ beforeBytes: formatted.beforeBytes,
45
+ afterBytes: formatted.afterBytes
46
+ }],
47
+ formatted: formatted.formatted,
48
+ summary: {
49
+ files: 1,
50
+ changed: formatted.changed ? 1 : 0,
51
+ edits: formatted.edits.length
52
+ }
53
+ };
54
+ }
55
+ const files = await resolveSourceFiles(context, options.patterns ?? DEFAULT_DIRECTIVE_FORMAT_PATTERNS);
56
+ const formattedFiles = await Promise.all(files.map(async (filePath) => {
57
+ const content = await readFile(filePath, "utf8");
58
+ return formatContent(service, filePath, content, options.range);
59
+ }));
60
+ const preview = await context.createPreview(formattedFiles.filter((file) => file.changed).map((file) => ({
61
+ filePath: file.filePath,
62
+ beforeText: void 0,
63
+ afterText: file.formatted
64
+ })), options.ttlMs);
27
65
  return {
28
66
  version: DIRECTIVE_FORMAT_PREVIEW_VERSION,
67
+ manifest: manifestMetadata(manifest),
29
68
  root: context.root,
30
- mode: "content",
31
- files: [{
32
- filePath,
33
- languageId: formatted.languageId,
34
- edits: formatted.edits,
35
- changed: formatted.changed,
36
- beforeBytes: formatted.beforeBytes,
37
- afterBytes: formatted.afterBytes
38
- }],
39
- formatted: formatted.formatted,
69
+ mode: "files",
70
+ inputs: {
71
+ patterns: options.patterns ?? DEFAULT_DIRECTIVE_FORMAT_PATTERNS,
72
+ files
73
+ },
74
+ preview,
75
+ files: formattedFiles.map((file) => ({
76
+ filePath: file.filePath,
77
+ languageId: file.languageId,
78
+ edits: file.edits,
79
+ changed: file.changed,
80
+ beforeBytes: file.beforeBytes,
81
+ afterBytes: file.afterBytes
82
+ })),
40
83
  summary: {
41
- files: 1,
42
- changed: formatted.changed ? 1 : 0,
43
- edits: formatted.edits.length
84
+ files: formattedFiles.length,
85
+ changed: formattedFiles.filter((file) => file.changed).length,
86
+ edits: formattedFiles.reduce((count, file) => count + file.edits.length, 0)
44
87
  }
45
88
  };
89
+ } finally {
90
+ service.dispose();
46
91
  }
47
- const files = await resolveSourceFiles(context, options.patterns ?? DEFAULT_DIRECTIVE_FORMAT_PATTERNS);
48
- const formattedFiles = await Promise.all(files.map(async (filePath) => {
49
- const content = await readFile(filePath, "utf8");
50
- return formatContent(service, filePath, content, options.range);
51
- }));
52
- const preview = await context.createPreview(formattedFiles.filter((file) => file.changed).map((file) => ({
53
- filePath: file.filePath,
54
- beforeText: void 0,
55
- afterText: file.formatted
56
- })), options.ttlMs);
57
- return {
58
- version: DIRECTIVE_FORMAT_PREVIEW_VERSION,
59
- root: context.root,
60
- mode: "files",
61
- inputs: {
62
- patterns: options.patterns ?? DEFAULT_DIRECTIVE_FORMAT_PATTERNS,
63
- files
64
- },
65
- preview,
66
- files: formattedFiles.map((file) => ({
67
- filePath: file.filePath,
68
- languageId: file.languageId,
69
- edits: file.edits,
70
- changed: file.changed,
71
- beforeBytes: file.beforeBytes,
72
- afterBytes: file.afterBytes
73
- })),
74
- summary: {
75
- files: formattedFiles.length,
76
- changed: formattedFiles.filter((file) => file.changed).length,
77
- edits: formattedFiles.reduce((count, file) => count + file.edits.length, 0)
78
- }
79
- };
80
92
  }
81
- //#endregion
82
93
  export { previewDirectiveFormat };
package/dist/index.d.ts CHANGED
@@ -1,3 +1,2 @@
1
- import MasterCSSMCPContext, { MasterCSSMCPContextOptions } from "./context.js";
2
- import { MasterCSSMCPServerInstance, createMasterCSSMCPServer, startStdioServer } from "./server.js";
3
- export { MasterCSSMCPContext, type MasterCSSMCPContextOptions, type MasterCSSMCPServerInstance, createMasterCSSMCPServer, startStdioServer };
1
+ import { createMasterCSSMCPServer, startMasterCSSMCPStdioServer } from "./server.js";
2
+ export { createMasterCSSMCPServer, startMasterCSSMCPStdioServer };
package/dist/index.js CHANGED
@@ -1,3 +1 @@
1
- import MasterCSSMCPContext from "./context.js";
2
- import { createMasterCSSMCPServer, startStdioServer } from "./server.js";
3
- export { MasterCSSMCPContext, createMasterCSSMCPServer, startStdioServer };
1
+ export { createMasterCSSMCPServer, startMasterCSSMCPStdioServer } from "./server.js";
@@ -0,0 +1,70 @@
1
+ import { createRequire } from "node:module";
2
+ import { existsSync, readFileSync, statSync } from "node:fs";
3
+ import { dirname, join, resolve } from "node:path";
4
+ // ../internal/src/workspace.ts
5
+ function readPackageJSON(file) {
6
+ try {
7
+ return JSON.parse(readFileSync(file, "utf8"));
8
+ } catch {
9
+ return;
10
+ }
11
+ }
12
+ function findPackageDir(entry, packageName) {
13
+ let current = statSync(entry).isDirectory() ? entry : dirname(entry);
14
+ while (current !== dirname(current)) {
15
+ const packageJSONPath = join(current, "package.json");
16
+ if (existsSync(packageJSONPath)) {
17
+ const packageJSON = readPackageJSON(packageJSONPath);
18
+ if (packageJSON?.name === packageName) return {
19
+ directory: current,
20
+ packageJSONPath,
21
+ version: typeof packageJSON.version === "string" ? packageJSON.version : void 0
22
+ };
23
+ }
24
+ current = dirname(current);
25
+ }
26
+ }
27
+ function resolvePackage(name, resolver) {
28
+ const entry = resolver.resolve(name);
29
+ const packageRoot = findPackageDir(entry, name.startsWith("@master/css-preset/") ? "@master/css-preset" : name.startsWith("@master/css-schema/") ? "@master/css-schema" : name.startsWith("@master/css-language-server/") ? "@master/css-language-server" : name);
30
+ if (!packageRoot) throw new Error(`Unable to find package root for ${name} from ${entry}`);
31
+ return {
32
+ name,
33
+ entry,
34
+ directory: packageRoot.directory,
35
+ packageJSON: packageRoot.packageJSONPath,
36
+ version: packageRoot.version
37
+ };
38
+ }
39
+ function tryResolvePackage(name, resolver, errors) {
40
+ try {
41
+ return resolvePackage(name, resolver);
42
+ } catch (error) {
43
+ errors.push({
44
+ name,
45
+ message: error instanceof Error ? error.message : String(error)
46
+ });
47
+ }
48
+ }
49
+ function createWorkspaceRequire(workspaceDir) {
50
+ return createRequire(join(resolve(workspaceDir), "package.json"));
51
+ }
52
+ function createPackageRequire(resolvedPackage) {
53
+ return createRequire(resolvedPackage.packageJSON || join(resolvedPackage.directory, "package.json"));
54
+ }
55
+ function resolveMasterCSSWorkspacePackages(workspaceDir = process.cwd()) {
56
+ const errors = [];
57
+ const workspaceRequire = createWorkspaceRequire(workspaceDir);
58
+ const css = tryResolvePackage("@master/css", workspaceRequire, errors);
59
+ const result = {
60
+ workspaceDir: resolve(workspaceDir),
61
+ errors,
62
+ ...css ? { css } : {}
63
+ };
64
+ if (css) result.presetManifest = tryResolvePackage("@master/css-preset/default-manifest.json", createPackageRequire(css), errors);
65
+ try {
66
+ result.languageServer = resolvePackage("@master/css-language-server/server", workspaceRequire);
67
+ } catch {}
68
+ return result;
69
+ }
70
+ export { resolveMasterCSSWorkspacePackages };
package/dist/language.js CHANGED
@@ -1,28 +1,32 @@
1
+ import { loadWorkspaceManifest, manifestMetadata, requireWorkspaceManifest } from "./project.js";
1
2
  import { createMCPTextDocument } from "./document.js";
2
- import { loadWorkspaceManifest } from "./project.js";
3
- import CSSLanguageService from "@master/css-language-service";
4
- //#region src/language.ts
3
+ import { createToolingSessionSync } from "@master/css-tooling/node";
4
+ import { MasterCSSLanguageService } from "@master/css-language-service";
5
+ // src/language.ts
5
6
  async function suggestSyntax(context, options) {
6
7
  const filePath = context.resolveVirtualPath(options.filePath);
7
- const manifest = await loadWorkspaceManifest(context);
8
- const service = new CSSLanguageService(manifest.status === "loaded" ? { manifest: manifest.manifest } : void 0);
9
- const document = createMCPTextDocument(filePath, options.content);
10
- const completions = service.suggestSyntax(document, options.position, {
11
- triggerKind: options.triggerCharacter ? 2 : 1,
12
- ...options.triggerCharacter ? { triggerCharacter: options.triggerCharacter } : {}
13
- }) ?? [];
14
- const hover = service.inspectSyntax(document, options.position);
15
- const limit = options.limit ?? 50;
16
- return {
17
- manifest: {
18
- status: manifest.status,
19
- entries: manifest.entries,
20
- ...manifest.status === "error" ? { error: manifest.error } : {}
21
- },
22
- completions: completions.slice(0, limit),
23
- total: completions.length,
24
- hover
25
- };
8
+ const manifest = await loadWorkspaceManifest(context, options.context);
9
+ const session = createToolingSessionSync({
10
+ manifest: requireWorkspaceManifest(manifest),
11
+ nativeClassNames: manifest.nativeClassNames
12
+ });
13
+ const service = new MasterCSSLanguageService({ manifest: requireWorkspaceManifest(manifest) }, { session });
14
+ try {
15
+ const document = createMCPTextDocument(filePath, options.content);
16
+ const completions = service.suggestSyntax(document, options.position, {
17
+ triggerKind: options.triggerCharacter ? 2 : 1,
18
+ ...options.triggerCharacter ? { triggerCharacter: options.triggerCharacter } : {}
19
+ }) ?? [];
20
+ const hover = service.inspectSyntax(document, options.position);
21
+ const limit = options.limit ?? 50;
22
+ return {
23
+ manifest: manifestMetadata(manifest),
24
+ completions: completions.slice(0, limit),
25
+ total: completions.length,
26
+ hover
27
+ };
28
+ } finally {
29
+ service.dispose();
30
+ }
26
31
  }
27
- //#endregion
28
32
  export { suggestSyntax };
package/dist/lint.js CHANGED
@@ -1,132 +1,122 @@
1
- import { loadWorkspaceManifest } from "./project.js";
1
+ import { loadWorkspaceManifest, manifestMetadata, requireWorkspaceManifest } from "./project.js";
2
2
  import { resolveSourceFiles } from "./scan.js";
3
3
  import { readFile } from "node:fs/promises";
4
- import { createCSSWithNativeDeclarations } from "@master/css-validator/native-declaration";
5
- import { fixMasterCSSContent, lintMasterCSSContent, resolveMasterCSSLintRules, summarizeMasterCSSLintFiles } from "@master/css-lint";
6
- //#region src/lint.ts
4
+ import { createToolingSessionSync } from "@master/css-tooling/node";
5
+ import { fixMasterCSSContent, lintMasterCSSContent, resolveMasterCSSLintRules, summarizeMasterCSSLintFiles } from "@master/css-tooling/lint";
6
+ // src/lint.ts
7
7
  const DEFAULT_LINT_SOURCE_PATTERNS = ["**/*.{html,htm,js,jsx,cjs,ts,tsx,mts,cts,svelte,astro,vue,md,mdx,pug,php,css,scss,less}"];
8
8
  const DEFAULT_IGNORE_PATTERNS = ["**/node_modules/**", "node_modules"];
9
- const LINT_REPORT_VERSION = 1;
10
- function createManifestDiagnostic(context, message) {
11
- return {
12
- ruleId: "manifest",
13
- code: "manifest-loading-error",
14
- severity: "error",
15
- message,
16
- range: {
17
- start: 0,
18
- end: 0
19
- },
20
- loc: {
21
- start: {
22
- line: 1,
23
- column: 1
24
- },
25
- end: {
26
- line: 1,
27
- column: 1
28
- }
29
- },
30
- source: "Master CSS",
31
- sourceKind: "manifest",
32
- data: { cwd: context.root }
33
- };
34
- }
9
+ const LINT_REPORT_VERSION = 5;
35
10
  async function loadLintState(context, options = {}) {
36
11
  const rules = resolveMasterCSSLintRules(options.rules);
37
- const manifest = await loadWorkspaceManifest(context);
38
- const css = manifest.status === "loaded" ? createCSSWithNativeDeclarations(manifest.manifest) : void 0;
12
+ const manifest = await loadWorkspaceManifest(context, options.context);
13
+ const lintSession = createToolingSessionSync({
14
+ manifest: requireWorkspaceManifest(manifest),
15
+ nativeClassNames: manifest.nativeClassNames
16
+ });
39
17
  const files = await resolveSourceFiles(context, options.patterns ?? DEFAULT_LINT_SOURCE_PATTERNS, options.patterns ? [] : DEFAULT_IGNORE_PATTERNS);
40
18
  return {
41
19
  rules,
42
20
  manifest,
43
- css,
21
+ lintSession,
44
22
  inputs: await Promise.all(files.map(async (filePath) => ({
45
23
  filePath,
46
24
  content: await readFile(filePath, "utf8")
47
25
  })))
48
26
  };
49
27
  }
50
- function lintInputs(inputs, css, rules) {
28
+ function lintInputs(inputs, rules, lintSession) {
51
29
  return inputs.map((input) => lintMasterCSSContent({
52
30
  content: input.content,
53
31
  filePath: input.filePath,
54
- css,
55
- rules
32
+ rules,
33
+ lintSession
56
34
  })).filter((result) => result.diagnostics.length);
57
35
  }
58
- function createManifestFileResult(context, diagnostic) {
36
+ function lintCoverage(files, checkedFiles) {
37
+ const { files: _files, ...summary } = summarizeMasterCSSLintFiles(files);
59
38
  return {
60
- filePath: context.root,
61
- languageId: "manifest",
62
- sourceKind: "manifest",
63
- diagnostics: [diagnostic]
39
+ coverage: {
40
+ status: checkedFiles.length ? "complete" : "no-inputs",
41
+ checkedFiles,
42
+ description: checkedFiles.length ? "Source lint ran on every path in checkedFiles with the enabled rules. The files array lists only diagnostic results; an empty files array means those inputs produced no diagnostics. manifest.entries lists stylesheet entries used to load the manifest, not linted source inputs. Browser behavior is not checked." : "No source inputs matched, so source lint did not run. Zero diagnostics does not verify any source file or browser behavior."
43
+ },
44
+ summary: {
45
+ ...summary,
46
+ checkedFiles: checkedFiles.length,
47
+ filesWithDiagnostics: files.filter((file) => file.diagnostics.length).length
48
+ }
64
49
  };
65
50
  }
66
51
  async function lintProject(context, options = {}) {
67
52
  const state = await loadLintState(context, options);
68
- const files = state.manifest.status === "error" || !state.css ? [createManifestFileResult(context, createManifestDiagnostic(context, `Failed to load Master CSS manifest: ${state.manifest.error}`))] : lintInputs(state.inputs, state.css, state.rules);
69
- return {
70
- version: LINT_REPORT_VERSION,
71
- root: context.root,
72
- manifest: {
73
- status: state.manifest.status,
74
- entries: state.manifest.entries,
75
- diagnostics: state.manifest.status === "error" ? files[0].diagnostics : []
76
- },
77
- files,
78
- summary: summarizeMasterCSSLintFiles(files)
79
- };
53
+ try {
54
+ const files = lintInputs(state.inputs, state.rules, state.lintSession);
55
+ return {
56
+ version: LINT_REPORT_VERSION,
57
+ root: context.root,
58
+ manifest: manifestMetadata(state.manifest),
59
+ files,
60
+ diagnostics: files.flatMap((file) => file.diagnostics),
61
+ ...lintCoverage(files, state.inputs.map((input) => input.filePath))
62
+ };
63
+ } finally {
64
+ state.lintSession?.dispose();
65
+ }
80
66
  }
81
67
  async function lintContent(context, options) {
82
68
  const rules = resolveMasterCSSLintRules(options.rules);
83
69
  const filePath = context.resolveVirtualPath(options.filePath);
84
- const manifest = await loadWorkspaceManifest(context);
85
- const files = manifest.status === "error" ? [createManifestFileResult(context, createManifestDiagnostic(context, `Failed to load Master CSS manifest: ${manifest.error}`))] : [lintMasterCSSContent({
86
- content: options.content,
87
- filePath,
88
- css: createCSSWithNativeDeclarations(manifest.manifest),
89
- rules
90
- })];
91
- return {
92
- version: LINT_REPORT_VERSION,
93
- root: context.root,
94
- manifest: {
95
- status: manifest.status,
96
- entries: manifest.entries,
97
- diagnostics: manifest.status === "error" ? files[0].diagnostics : []
98
- },
99
- files,
100
- summary: summarizeMasterCSSLintFiles(files)
101
- };
70
+ const manifest = await loadWorkspaceManifest(context, options.context);
71
+ const lintSession = createToolingSessionSync({
72
+ manifest: requireWorkspaceManifest(manifest),
73
+ nativeClassNames: manifest.nativeClassNames
74
+ });
75
+ try {
76
+ const files = [lintMasterCSSContent({
77
+ content: options.content,
78
+ filePath,
79
+ rules,
80
+ lintSession
81
+ })].filter((file) => file.diagnostics.length);
82
+ return {
83
+ version: LINT_REPORT_VERSION,
84
+ root: context.root,
85
+ manifest: manifestMetadata(manifest),
86
+ files,
87
+ diagnostics: files.flatMap((file) => file.diagnostics),
88
+ ...lintCoverage(files, [filePath])
89
+ };
90
+ } finally {
91
+ lintSession?.dispose();
92
+ }
102
93
  }
103
94
  async function previewLintFixes(context, options = {}) {
104
95
  const state = await loadLintState(context, options);
105
- if (state.manifest.status === "error" || !state.css) return {
106
- mode: "lint-fixes",
107
- preview: await context.createPreview([], options.ttlMs),
108
- lint: await lintProject(context, options)
109
- };
110
- const changes = [];
111
- for (const input of state.inputs) {
112
- const fixed = fixMasterCSSContent({
113
- content: input.content,
114
- filePath: input.filePath,
115
- css: state.css,
116
- rules: state.rules,
117
- includeDirectiveFixes: Boolean(options.includeDirectiveFixes)
118
- });
119
- if (fixed !== input.content) changes.push({
120
- filePath: input.filePath,
121
- beforeText: input.content,
122
- afterText: fixed
123
- });
96
+ try {
97
+ const changes = [];
98
+ for (const input of state.inputs) {
99
+ const fixed = fixMasterCSSContent({
100
+ content: input.content,
101
+ filePath: input.filePath,
102
+ rules: state.rules,
103
+ lintSession: state.lintSession
104
+ });
105
+ if (fixed !== input.content) changes.push({
106
+ filePath: input.filePath,
107
+ beforeText: input.content,
108
+ afterText: fixed
109
+ });
110
+ }
111
+ const preview = await context.createPreview(changes, options.ttlMs);
112
+ return {
113
+ manifest: manifestMetadata(state.manifest),
114
+ mode: "lint-fixes",
115
+ preview,
116
+ lint: await lintProject(context, options)
117
+ };
118
+ } finally {
119
+ state.lintSession?.dispose();
124
120
  }
125
- return {
126
- mode: "lint-fixes",
127
- preview: await context.createPreview(changes, options.ttlMs),
128
- lint: await lintProject(context, options)
129
- };
130
121
  }
131
- //#endregion
132
122
  export { lintContent, lintProject, previewLintFixes };