@salesforce-ux/slds-linter 0.2.0 → 0.2.1
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.
- package/build/commands/emit.d.ts +2 -0
- package/build/commands/emit.js +48 -0
- package/build/commands/lint.d.ts +2 -0
- package/build/commands/lint.js +55 -0
- package/build/commands/report.d.ts +2 -0
- package/build/commands/report.js +66 -0
- package/build/executor/__tests__/executor.test.js +216 -0
- package/build/executor/index.d.ts +20 -0
- package/build/executor/index.js +105 -0
- package/build/index.d.ts +2 -0
- package/build/index.js +33 -0
- package/build/services/__tests__/file-scanner.test.js +47 -0
- package/build/services/artifact-processor.d.ts +6 -0
- package/build/services/artifact-processor.js +37 -0
- package/build/services/batch-processor.d.ts +29 -0
- package/build/services/batch-processor.js +84 -0
- package/build/services/config.resolver.d.ts +6 -0
- package/build/services/config.resolver.js +20 -0
- package/build/services/file-patterns.d.ts +3 -0
- package/build/services/file-patterns.js +21 -0
- package/build/services/file-scanner.d.ts +26 -0
- package/build/services/file-scanner.js +71 -0
- package/build/services/lint-runner.d.ts +17 -0
- package/build/services/lint-runner.js +69 -0
- package/build/services/report-generator.d.ts +43 -0
- package/build/services/report-generator.js +186 -0
- package/build/types/index.d.ts +75 -0
- package/build/types/index.js +0 -0
- package/build/utils/config-utils.d.ts +33 -0
- package/build/utils/config-utils.js +68 -0
- package/build/utils/editorLinkUtil.d.ts +21 -0
- package/build/utils/editorLinkUtil.js +21 -0
- package/build/utils/index.d.ts +2 -0
- package/build/utils/index.js +7 -0
- package/build/utils/lintResultsUtil.d.ts +21 -0
- package/build/utils/lintResultsUtil.js +70 -0
- package/build/utils/logger.d.ts +8 -0
- package/build/utils/logger.js +28 -0
- package/build/utils/nodeVersionUtil.d.ts +19 -0
- package/build/utils/nodeVersionUtil.js +42 -0
- package/build/workers/base.worker.d.ts +15 -0
- package/build/workers/base.worker.js +44 -0
- package/build/workers/eslint.worker.d.ts +1 -0
- package/build/workers/eslint.worker.js +50 -0
- package/build/workers/stylelint.worker.d.ts +1 -0
- package/build/workers/stylelint.worker.js +40 -0
- package/package.json +4 -4
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { LintConfig, ReportConfig, CliOptions } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Normalize and validate a file path
|
|
4
|
+
* This function ensures that the provided path exists and is accessible
|
|
5
|
+
* If no path is provided, it defaults to the current working directory
|
|
6
|
+
*
|
|
7
|
+
* @param inputPath Input file path or undefined
|
|
8
|
+
* @returns Normalized and validated absolute path
|
|
9
|
+
* @throws Error if the path is invalid or inaccessible
|
|
10
|
+
*/
|
|
11
|
+
export declare function normalizeAndValidatePath(inputPath?: string): string;
|
|
12
|
+
/**
|
|
13
|
+
* Normalize directory path with special handling for glob patterns
|
|
14
|
+
* This function preserves glob patterns and resolves regular paths to absolute paths
|
|
15
|
+
* If no directory is provided, it defaults to the current working directory
|
|
16
|
+
*
|
|
17
|
+
* @param directory Input directory or glob pattern or undefined
|
|
18
|
+
* @returns Normalized directory path
|
|
19
|
+
*/
|
|
20
|
+
export declare function normalizeDirectoryPath(directory?: string): string;
|
|
21
|
+
/**
|
|
22
|
+
* Normalize configuration with appropriate defaults
|
|
23
|
+
* This function ensures all required options have valid values
|
|
24
|
+
* It applies provided defaults, then user-provided options, then normalizes paths
|
|
25
|
+
* Used by both CLI commands and Node API functions
|
|
26
|
+
*
|
|
27
|
+
* @param options Options to normalize
|
|
28
|
+
* @param defaultOptions Default options to apply
|
|
29
|
+
* @param isNodeApi Whether this is being called from the Node API
|
|
30
|
+
* @returns Normalized options with appropriate defaults
|
|
31
|
+
*/
|
|
32
|
+
export declare function normalizeCliOptions<T extends CliOptions | LintConfig | ReportConfig>(options: T, defaultOptions?: Partial<T>, isNodeApi?: boolean): T;
|
|
33
|
+
export declare const normalizeConfig: typeof normalizeCliOptions;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// src/utils/config-utils.ts
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { DEFAULT_ESLINT_CONFIG_PATH, DEFAULT_STYLELINT_CONFIG_PATH } from "../services/config.resolver.js";
|
|
4
|
+
import { isDynamicPattern } from "globby";
|
|
5
|
+
import { accessSync } from "fs";
|
|
6
|
+
import { Logger } from "./logger.js";
|
|
7
|
+
function normalizeAndValidatePath(inputPath) {
|
|
8
|
+
if (!inputPath) {
|
|
9
|
+
Logger.debug("No path provided, using current working directory");
|
|
10
|
+
return process.cwd();
|
|
11
|
+
}
|
|
12
|
+
const normalizedPath = path.resolve(inputPath);
|
|
13
|
+
Logger.debug(`Normalized path: ${normalizedPath}`);
|
|
14
|
+
try {
|
|
15
|
+
accessSync(normalizedPath);
|
|
16
|
+
return normalizedPath;
|
|
17
|
+
} catch (error) {
|
|
18
|
+
const errorMessage = `Invalid path: ${inputPath}`;
|
|
19
|
+
Logger.error(errorMessage);
|
|
20
|
+
throw new Error(errorMessage);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function normalizeDirectoryPath(directory) {
|
|
24
|
+
if (!directory) {
|
|
25
|
+
Logger.debug("No directory provided, using current working directory");
|
|
26
|
+
return process.cwd();
|
|
27
|
+
}
|
|
28
|
+
if (isDynamicPattern(directory)) {
|
|
29
|
+
Logger.debug(`Detected glob pattern: ${directory}`);
|
|
30
|
+
return directory;
|
|
31
|
+
}
|
|
32
|
+
Logger.debug(`Normalizing directory path: ${directory}`);
|
|
33
|
+
return path.resolve(directory);
|
|
34
|
+
}
|
|
35
|
+
function normalizeCliOptions(options, defaultOptions = {}, isNodeApi = false) {
|
|
36
|
+
const baseDefaults = {
|
|
37
|
+
files: [],
|
|
38
|
+
configStylelint: isNodeApi ? DEFAULT_STYLELINT_CONFIG_PATH : "",
|
|
39
|
+
configEslint: isNodeApi ? DEFAULT_ESLINT_CONFIG_PATH : ""
|
|
40
|
+
};
|
|
41
|
+
if (!isNodeApi) {
|
|
42
|
+
Object.assign(baseDefaults, {
|
|
43
|
+
fix: false,
|
|
44
|
+
editor: "vscode",
|
|
45
|
+
format: "sarif"
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
const normalizedOptions = {
|
|
49
|
+
...baseDefaults,
|
|
50
|
+
...defaultOptions,
|
|
51
|
+
...options,
|
|
52
|
+
directory: normalizeDirectoryPath(options.directory)
|
|
53
|
+
};
|
|
54
|
+
if (!isNodeApi) {
|
|
55
|
+
normalizedOptions.output = options.output ? normalizeAndValidatePath(options.output) : process.cwd();
|
|
56
|
+
}
|
|
57
|
+
if ("format" in options && !options.format && isNodeApi) {
|
|
58
|
+
normalizedOptions.format = "sarif";
|
|
59
|
+
}
|
|
60
|
+
return normalizedOptions;
|
|
61
|
+
}
|
|
62
|
+
var normalizeConfig = normalizeCliOptions;
|
|
63
|
+
export {
|
|
64
|
+
normalizeAndValidatePath,
|
|
65
|
+
normalizeCliOptions,
|
|
66
|
+
normalizeConfig,
|
|
67
|
+
normalizeDirectoryPath
|
|
68
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns an editor-specific link for opening a file at a given line and column.
|
|
3
|
+
*
|
|
4
|
+
* @param editor - The editor to use (e.g., 'vscode', 'atom', 'sublime').
|
|
5
|
+
* @param absolutePath - The absolute path to the file.
|
|
6
|
+
* @param line - The line number in the file.
|
|
7
|
+
* @param column - The column number in the file.
|
|
8
|
+
* @returns A URL string that can be used to open the file in the specified editor.
|
|
9
|
+
*/
|
|
10
|
+
export declare function getEditorLink(editor: string, absolutePath: string, line: number, column: number): string;
|
|
11
|
+
/**
|
|
12
|
+
* Creates an ANSI hyperlink (if supported) for the line:column text.
|
|
13
|
+
*
|
|
14
|
+
* @param lineCol - The line:column string (e.g., "10:5").
|
|
15
|
+
* @param absolutePath - The absolute path to the file.
|
|
16
|
+
* @param line - The line number in the file.
|
|
17
|
+
* @param column - The column number in the file.
|
|
18
|
+
* @param editor - The editor to use (e.g., 'vscode', 'atom', 'sublime').
|
|
19
|
+
* @returns A string with ANSI escape sequences to create a clickable hyperlink.
|
|
20
|
+
*/
|
|
21
|
+
export declare function createClickableLineCol(lineCol: string, absolutePath: string, line: number, column: number, editor: string): string;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// src/utils/editorLinkUtil.ts
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
function getEditorLink(editor, absolutePath, line, column) {
|
|
4
|
+
if (editor === "vscode") {
|
|
5
|
+
return `vscode://file/${absolutePath}:${line}:${column}`;
|
|
6
|
+
} else if (editor === "atom") {
|
|
7
|
+
return `atom://core/open/file?filename=${absolutePath}&line=${line}&column=${column}`;
|
|
8
|
+
} else if (editor === "sublime") {
|
|
9
|
+
return `file://${absolutePath}:${line}:${column}`;
|
|
10
|
+
} else {
|
|
11
|
+
return `file://${absolutePath}:${line}:${column}`;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
function createClickableLineCol(lineCol, absolutePath, line, column, editor) {
|
|
15
|
+
const link = getEditorLink(editor, absolutePath, line, column);
|
|
16
|
+
return `\x1B]8;;${link}\x07${chalk.blueBright(lineCol)}\x1B]8;;\x07`;
|
|
17
|
+
}
|
|
18
|
+
export {
|
|
19
|
+
createClickableLineCol,
|
|
20
|
+
getEditorLink
|
|
21
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { LintResult, LintResultEntry, SarifResultEntry } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
*
|
|
4
|
+
* @param id - Rule id
|
|
5
|
+
* @returns updated Rule id without the namespace @salesforce-ux
|
|
6
|
+
*/
|
|
7
|
+
export declare function replaceNamespaceinRules(id: string): string;
|
|
8
|
+
/**
|
|
9
|
+
*
|
|
10
|
+
* @param text - The input text that could either be a plain string or a stringified JSON object.
|
|
11
|
+
* @returns The parsed message or the original string if parsing fails.
|
|
12
|
+
*/
|
|
13
|
+
export declare function parseText(text: string): string;
|
|
14
|
+
/**
|
|
15
|
+
* Prints detailed lint results for each file that has issues.
|
|
16
|
+
*
|
|
17
|
+
* @param results - Array of lint results.
|
|
18
|
+
* @param editor - The chosen editor for clickable links (e.g., "vscode", "atom", "sublime").
|
|
19
|
+
*/
|
|
20
|
+
export declare function printLintResults(results: LintResult[], editor: string): void;
|
|
21
|
+
export declare function transformedResults(lintResult: LintResult, entry: LintResultEntry, level: 'error' | 'warning'): SarifResultEntry;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// src/utils/lintResultsUtil.ts
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import { createClickableLineCol } from "./editorLinkUtil.js";
|
|
5
|
+
import { Logger } from "../utils/logger.js";
|
|
6
|
+
function replaceNamespaceinRules(id) {
|
|
7
|
+
return id.includes("@salesforce-ux/") ? id.replace("@salesforce-ux/", "") : id;
|
|
8
|
+
}
|
|
9
|
+
function parseText(text) {
|
|
10
|
+
let safeText = text;
|
|
11
|
+
try {
|
|
12
|
+
const parsed = JSON.parse(text);
|
|
13
|
+
safeText = parsed.message || JSON.stringify(parsed);
|
|
14
|
+
} catch (error) {
|
|
15
|
+
safeText = text;
|
|
16
|
+
}
|
|
17
|
+
return safeText.endsWith(".") ? safeText : `${safeText}.`;
|
|
18
|
+
}
|
|
19
|
+
function printLintResults(results, editor) {
|
|
20
|
+
results.forEach((result) => {
|
|
21
|
+
const hasErrors = result.errors && result.errors.length > 0;
|
|
22
|
+
const hasWarnings = result.warnings && result.warnings.length > 0;
|
|
23
|
+
if (!hasErrors && !hasWarnings) return;
|
|
24
|
+
const absolutePath = result.filePath || "";
|
|
25
|
+
const relativeFile = path.relative(process.cwd(), absolutePath) || "Unknown file";
|
|
26
|
+
Logger.newLine().info(`${chalk.bold(relativeFile)}`);
|
|
27
|
+
if (hasErrors) {
|
|
28
|
+
result.errors.forEach((error) => {
|
|
29
|
+
if (error.line && error.column && absolutePath) {
|
|
30
|
+
const lineCol = `${error.line}:${error.column}`;
|
|
31
|
+
const clickable = createClickableLineCol(lineCol, absolutePath, error.line, error.column, editor);
|
|
32
|
+
const ruleId = error.ruleId ? chalk.dim(replaceNamespaceinRules(error.ruleId)) : "";
|
|
33
|
+
Logger.error(` ${clickable} ${parseText(error.message)} ${ruleId}`);
|
|
34
|
+
} else {
|
|
35
|
+
Logger.error(` ${chalk.red("Error:")} ${parseText(error.message)}`);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
if (hasWarnings) {
|
|
40
|
+
result.warnings.forEach((warn) => {
|
|
41
|
+
if (warn.line && warn.column && absolutePath) {
|
|
42
|
+
const lineCol = `${warn.line}:${warn.column}`;
|
|
43
|
+
const clickable = createClickableLineCol(lineCol, absolutePath, warn.line, warn.column, editor);
|
|
44
|
+
const ruleId = warn.ruleId ? chalk.dim(replaceNamespaceinRules(warn.ruleId)) : "";
|
|
45
|
+
Logger.warning(` ${clickable} ${parseText(warn.message)} ${ruleId}`);
|
|
46
|
+
} else {
|
|
47
|
+
Logger.warning(` ${chalk.yellow("Warning:")} ${parseText(warn.message)}`);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
function transformedResults(lintResult, entry, level) {
|
|
54
|
+
return {
|
|
55
|
+
ruleId: replaceNamespaceinRules(entry.ruleId),
|
|
56
|
+
level,
|
|
57
|
+
messageText: parseText(entry.message),
|
|
58
|
+
fileUri: path.relative(process.cwd(), lintResult.filePath),
|
|
59
|
+
startLine: entry.line,
|
|
60
|
+
startColumn: entry.column,
|
|
61
|
+
endLine: entry.line,
|
|
62
|
+
endColumn: entry.endColumn
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
export {
|
|
66
|
+
parseText,
|
|
67
|
+
printLintResults,
|
|
68
|
+
replaceNamespaceinRules,
|
|
69
|
+
transformedResults
|
|
70
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare class Logger {
|
|
2
|
+
static newLine(): typeof Logger;
|
|
3
|
+
static info(message: string): void;
|
|
4
|
+
static success(message: string): void;
|
|
5
|
+
static warning(message: string): void;
|
|
6
|
+
static error(message: string): void;
|
|
7
|
+
static debug(message: string): void;
|
|
8
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// src/utils/logger.ts
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
var Logger = class {
|
|
4
|
+
static newLine() {
|
|
5
|
+
console.log("\n");
|
|
6
|
+
return this;
|
|
7
|
+
}
|
|
8
|
+
static info(message) {
|
|
9
|
+
console.log(chalk.blue("\u2139"), message);
|
|
10
|
+
}
|
|
11
|
+
static success(message) {
|
|
12
|
+
console.log(chalk.green("\u2713"), message);
|
|
13
|
+
}
|
|
14
|
+
static warning(message) {
|
|
15
|
+
console.warn(chalk.yellow("\u26A0"), message);
|
|
16
|
+
}
|
|
17
|
+
static error(message) {
|
|
18
|
+
console.error(chalk.red("\u2716"), message);
|
|
19
|
+
}
|
|
20
|
+
static debug(message) {
|
|
21
|
+
if (process.env.DEBUG) {
|
|
22
|
+
console.debug(chalk.gray("\u{1F50D}"), message);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
export {
|
|
27
|
+
Logger
|
|
28
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export declare const REQUIRED_NODE_VERSION = ">=18.4.0";
|
|
2
|
+
/**
|
|
3
|
+
* Checks if the current Node.js version meets the required version.
|
|
4
|
+
* @param {string} requiredVersion - The required Node.js version.
|
|
5
|
+
* @returns {boolean} - Returns true if the current version is valid.
|
|
6
|
+
*/
|
|
7
|
+
export declare function checkNodeVersion(requiredVersion: any): boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Validates the Node.js version and exits if it does not meet the requirement.
|
|
10
|
+
*/
|
|
11
|
+
export declare function validateNodeVersion(): void;
|
|
12
|
+
/**
|
|
13
|
+
* Util to resolve dirName from import meta compatible with node v18
|
|
14
|
+
* Letst version of node have import.meta.dirname
|
|
15
|
+
* @param importMeta
|
|
16
|
+
* @returns
|
|
17
|
+
*/
|
|
18
|
+
export declare function resolveDirName(importMeta: ImportMeta): string;
|
|
19
|
+
export declare function resolvePath(specifier: string, importMeta: ImportMeta): string;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// src/utils/nodeVersionUtil.ts
|
|
2
|
+
import semver from "semver";
|
|
3
|
+
import { fileURLToPath } from "url";
|
|
4
|
+
import { dirname } from "path";
|
|
5
|
+
import { resolve } from "import-meta-resolve";
|
|
6
|
+
import { Logger } from "./logger.js";
|
|
7
|
+
var REQUIRED_NODE_VERSION = ">=18.4.0";
|
|
8
|
+
function checkNodeVersion(requiredVersion) {
|
|
9
|
+
return semver.satisfies(process.version, requiredVersion);
|
|
10
|
+
}
|
|
11
|
+
function validateNodeVersion() {
|
|
12
|
+
if (!checkNodeVersion(REQUIRED_NODE_VERSION)) {
|
|
13
|
+
if (checkNodeVersion("<18.4.x")) {
|
|
14
|
+
Logger.warning(
|
|
15
|
+
`SLDS Linter CLI works best with Node.js version v18.4.0 or later.
|
|
16
|
+
We recommend using the latest [Active LTS](https://nodejs.org/en/about/previous-releases) version of Node.js.`
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function resolveDirName(importMeta) {
|
|
22
|
+
if ("dirname" in importMeta) {
|
|
23
|
+
return importMeta.dirname;
|
|
24
|
+
}
|
|
25
|
+
return dirname(fileURLToPath(importMeta.url));
|
|
26
|
+
}
|
|
27
|
+
function resolvePath(specifier, importMeta) {
|
|
28
|
+
let fileUrl = "";
|
|
29
|
+
if ("resolve" in importMeta) {
|
|
30
|
+
fileUrl = importMeta.resolve(specifier);
|
|
31
|
+
} else {
|
|
32
|
+
fileUrl = resolve(specifier, importMeta.url);
|
|
33
|
+
}
|
|
34
|
+
return fileURLToPath(fileUrl);
|
|
35
|
+
}
|
|
36
|
+
export {
|
|
37
|
+
REQUIRED_NODE_VERSION,
|
|
38
|
+
checkNodeVersion,
|
|
39
|
+
resolveDirName,
|
|
40
|
+
resolvePath,
|
|
41
|
+
validateNodeVersion
|
|
42
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { BatchTask } from '../services/batch-processor';
|
|
2
|
+
export declare abstract class BaseWorker<T, R> {
|
|
3
|
+
protected task: BatchTask<T>;
|
|
4
|
+
constructor();
|
|
5
|
+
/**
|
|
6
|
+
* Process a single file
|
|
7
|
+
* @param filePath Path to the file to process
|
|
8
|
+
* @returns Processing result
|
|
9
|
+
*/
|
|
10
|
+
protected abstract processFile(filePath: string): Promise<R>;
|
|
11
|
+
/**
|
|
12
|
+
* Start processing the batch of files
|
|
13
|
+
*/
|
|
14
|
+
process(): Promise<void>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// src/workers/base.worker.ts
|
|
2
|
+
import { parentPort, workerData } from "worker_threads";
|
|
3
|
+
var BaseWorker = class {
|
|
4
|
+
task;
|
|
5
|
+
constructor() {
|
|
6
|
+
this.task = workerData;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Start processing the batch of files
|
|
10
|
+
*/
|
|
11
|
+
async process() {
|
|
12
|
+
try {
|
|
13
|
+
const results = [];
|
|
14
|
+
for (const file of this.task.files) {
|
|
15
|
+
try {
|
|
16
|
+
const result = await this.processFile(file);
|
|
17
|
+
results.push(result);
|
|
18
|
+
} catch (error) {
|
|
19
|
+
results.push({
|
|
20
|
+
file,
|
|
21
|
+
error: error.message
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
const batchResult = {
|
|
26
|
+
success: true,
|
|
27
|
+
results
|
|
28
|
+
};
|
|
29
|
+
parentPort?.postMessage(batchResult);
|
|
30
|
+
} catch (error) {
|
|
31
|
+
const errorResult = {
|
|
32
|
+
success: false,
|
|
33
|
+
error: error.message,
|
|
34
|
+
results: []
|
|
35
|
+
};
|
|
36
|
+
parentPort?.postMessage(errorResult);
|
|
37
|
+
} finally {
|
|
38
|
+
process.exit(0);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
export {
|
|
43
|
+
BaseWorker
|
|
44
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// src/workers/eslint.worker.ts
|
|
2
|
+
import { ESLint } from "eslint";
|
|
3
|
+
import { BaseWorker } from "./base.worker.js";
|
|
4
|
+
var ESLintWorker = class extends BaseWorker {
|
|
5
|
+
eslint;
|
|
6
|
+
constructor() {
|
|
7
|
+
super();
|
|
8
|
+
this.eslint = new ESLint({
|
|
9
|
+
useEslintrc: false,
|
|
10
|
+
fix: this.task.config.fix,
|
|
11
|
+
overrideConfigFile: this.task.config.configPath
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
async processFile(filePath) {
|
|
15
|
+
try {
|
|
16
|
+
const results = await this.eslint.lintFiles([filePath]);
|
|
17
|
+
const fileResult = results[0];
|
|
18
|
+
if (this.task.config.fix && fileResult.output) {
|
|
19
|
+
await ESLint.outputFixes(results);
|
|
20
|
+
}
|
|
21
|
+
return {
|
|
22
|
+
file: filePath,
|
|
23
|
+
warnings: fileResult.messages.filter((msg) => msg.severity === 1).map((warning) => ({
|
|
24
|
+
line: warning.line,
|
|
25
|
+
column: warning.column,
|
|
26
|
+
endColumn: warning.endColumn,
|
|
27
|
+
message: warning.message,
|
|
28
|
+
ruleId: warning.ruleId || "unknown"
|
|
29
|
+
})),
|
|
30
|
+
errors: fileResult.messages.filter((msg) => msg.severity === 2).map((error) => ({
|
|
31
|
+
line: error.line,
|
|
32
|
+
column: error.column,
|
|
33
|
+
endColumn: error.endColumn,
|
|
34
|
+
message: error.message,
|
|
35
|
+
ruleId: error.ruleId || "unknown"
|
|
36
|
+
}))
|
|
37
|
+
};
|
|
38
|
+
} catch (error) {
|
|
39
|
+
return {
|
|
40
|
+
file: filePath,
|
|
41
|
+
error: error.message
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
var worker = new ESLintWorker();
|
|
47
|
+
worker.process().catch((error) => {
|
|
48
|
+
console.error("Worker failed:", error);
|
|
49
|
+
process.exit(1);
|
|
50
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// src/workers/stylelint.worker.ts
|
|
2
|
+
import stylelint from "stylelint";
|
|
3
|
+
import { BaseWorker } from "./base.worker.js";
|
|
4
|
+
var StylelintWorker = class extends BaseWorker {
|
|
5
|
+
async processFile(filePath) {
|
|
6
|
+
try {
|
|
7
|
+
const options = {
|
|
8
|
+
files: filePath,
|
|
9
|
+
fix: this.task.config.fix
|
|
10
|
+
};
|
|
11
|
+
if (this.task.config.configPath) {
|
|
12
|
+
options.configFile = this.task.config.configPath;
|
|
13
|
+
}
|
|
14
|
+
const result = await stylelint.lint(options);
|
|
15
|
+
const fileResult = result.results[0];
|
|
16
|
+
return {
|
|
17
|
+
file: filePath,
|
|
18
|
+
warnings: fileResult.warnings.map((warning) => ({
|
|
19
|
+
line: warning.line,
|
|
20
|
+
column: warning.column,
|
|
21
|
+
endColumn: warning.endColumn,
|
|
22
|
+
message: warning.text,
|
|
23
|
+
ruleId: warning.rule
|
|
24
|
+
})),
|
|
25
|
+
errors: []
|
|
26
|
+
// Stylelint doesn't differentiate between warnings and errors
|
|
27
|
+
};
|
|
28
|
+
} catch (error) {
|
|
29
|
+
return {
|
|
30
|
+
file: filePath,
|
|
31
|
+
error: error.message
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
var worker = new StylelintWorker();
|
|
37
|
+
worker.process().catch((error) => {
|
|
38
|
+
console.error("Worker failed:", error);
|
|
39
|
+
process.exit(1);
|
|
40
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforce-ux/slds-linter",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "SLDS Linter CLI tool for linting styles and components",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"lightning design system linter",
|
|
@@ -27,10 +27,10 @@
|
|
|
27
27
|
"build/**",
|
|
28
28
|
"README.md"
|
|
29
29
|
],
|
|
30
|
-
"bin": "
|
|
30
|
+
"bin": "build/index.js",
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@salesforce-ux/eslint-plugin-slds": "0.2.
|
|
33
|
-
"@salesforce-ux/stylelint-plugin-slds": "0.2.
|
|
32
|
+
"@salesforce-ux/eslint-plugin-slds": "0.2.1",
|
|
33
|
+
"@salesforce-ux/stylelint-plugin-slds": "0.2.1",
|
|
34
34
|
"@typescript-eslint/eslint-plugin": "^5.0.0",
|
|
35
35
|
"@typescript-eslint/parser": "^5.0.0",
|
|
36
36
|
"chalk": "^4.1.2",
|