@codebend3r/gale 0.2.1 → 0.2.3

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.
Binary file
Binary file
package/bin/gale.cjs ADDED
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ /**
5
+ * Launches the bundled Gale binary for this platform.
6
+ *
7
+ * A Node script rather than a shell script so the same launcher works on
8
+ * Windows, where npm wraps it in a .cmd shim. Everything is forwarded: the
9
+ * arguments, stdin/stdout/stderr, the exit code, and any terminating signal.
10
+ */
11
+
12
+ const { spawnSync } = require("node:child_process");
13
+ const { existsSync } = require("node:fs");
14
+ const path = require("node:path");
15
+
16
+ const { binaryFileName, resolveTarget, supportedPlatforms } = require("../platform.cjs");
17
+
18
+ const target = resolveTarget(process.platform, process.arch);
19
+
20
+ if (!target) {
21
+ process.stderr.write(`Unsupported platform: ${process.platform}-${process.arch}\n`);
22
+ process.stderr.write(`Supported: ${supportedPlatforms().join(", ")}\n`);
23
+ process.stderr.write("Build from source instead: cargo install gale-lint\n");
24
+ process.exit(1);
25
+ }
26
+
27
+ const binary = path.join(__dirname, target, binaryFileName(process.platform));
28
+
29
+ if (!existsSync(binary)) {
30
+ process.stderr.write(`Gale binary missing for ${target} at ${binary}\n`);
31
+ process.stderr.write(`This package should ship prebuilt binaries for ${target}.\n`);
32
+ process.stderr.write("Try reinstalling the package, or build from source:\n");
33
+ process.stderr.write(" cargo install gale-lint\n");
34
+ process.exit(1);
35
+ }
36
+
37
+ const result = spawnSync(binary, process.argv.slice(2), {
38
+ stdio: "inherit",
39
+ windowsHide: true,
40
+ });
41
+
42
+ if (result.error) {
43
+ process.stderr.write(`Failed to run ${binary}: ${result.error.message}\n`);
44
+ process.exit(1);
45
+ }
46
+
47
+ if (result.signal) {
48
+ // Re-raise so the parent sees the same signal the linter died from.
49
+ process.kill(process.pid, result.signal);
50
+ }
51
+
52
+ process.exit(result.status ?? 1);
Binary file
Binary file
package/index.d.ts ADDED
@@ -0,0 +1,152 @@
1
+ /**
2
+ * Type declarations for @codebend3r/gale.
3
+ *
4
+ * The shapes mirror Stylelint's public API so a project can swap the import
5
+ * without touching its call sites. Fields Gale never populates are typed as
6
+ * they are in Stylelint but are always empty.
7
+ */
8
+
9
+ export type Severity = "error" | "warning";
10
+
11
+ export type FormatterType = "string" | "json" | "compact" | "verbose" | "tap" | "unix";
12
+
13
+ /** A single problem reported for a source. */
14
+ export interface Warning {
15
+ line: number;
16
+ column: number;
17
+ endLine?: number;
18
+ endColumn?: number;
19
+ rule: string;
20
+ severity: Severity;
21
+ /** The message with ` (rule-name)` appended, as Stylelint prints it. */
22
+ text: string;
23
+ /** Present when the rule's `url` secondary option is set. */
24
+ url?: string;
25
+ }
26
+
27
+ /** The result of linting one source. */
28
+ export interface LintResult {
29
+ source: string;
30
+ warnings: Warning[];
31
+ /** Always empty: Gale reports no deprecations. */
32
+ deprecations: unknown[];
33
+ /** Always empty: Gale does not validate rule options. */
34
+ invalidOptionWarnings: unknown[];
35
+ /** Always empty: parse errors surface as `parse-error` warnings. */
36
+ parseErrors: unknown[];
37
+ errored: boolean;
38
+ ignored: boolean;
39
+ }
40
+
41
+ export interface MaxWarningsExceeded {
42
+ maxWarnings: number;
43
+ foundWarnings: number;
44
+ }
45
+
46
+ /** What `lint()` resolves to. */
47
+ export interface LinterResult {
48
+ cwd: string;
49
+ results: LintResult[];
50
+ errored: boolean;
51
+ /** The formatted report, in the formatter requested (JSON by default). */
52
+ report: string;
53
+ /** The fixed source when `fix` and `code` were both given. */
54
+ code?: string;
55
+ maxWarningsExceeded?: MaxWarningsExceeded;
56
+ /** Always empty: Gale exposes no per-rule metadata. */
57
+ ruleMetadata: Record<string, never>;
58
+ }
59
+
60
+ export type FormatterFunction = (
61
+ results: LintResult[],
62
+ returnValue: { cwd: string; results: LintResult[]; errored: boolean },
63
+ ) => string;
64
+
65
+ /** Rule settings in any of Stylelint's accepted shapes. */
66
+ export type RuleSetting = boolean | null | string | number | unknown[];
67
+
68
+ export interface Config {
69
+ extends?: string | string[];
70
+ plugins?: string[];
71
+ rules?: Record<string, RuleSetting>;
72
+ overrides?: unknown[];
73
+ ignoreFiles?: string | string[];
74
+ ignorePatterns?: string | string[];
75
+ customSyntax?: string;
76
+ defaultSeverity?: Severity;
77
+ ignoreDisables?: boolean;
78
+ reportNeedlessDisables?: boolean;
79
+ reportInvalidScopeDisables?: boolean;
80
+ reportDescriptionlessDisables?: boolean;
81
+ reportUnscopedDisables?: boolean;
82
+ allowEmptyInput?: boolean;
83
+ quiet?: boolean;
84
+ fix?: boolean | "strict" | "lax";
85
+ cache?: boolean;
86
+ cacheLocation?: string;
87
+ [key: string]: unknown;
88
+ }
89
+
90
+ export interface LinterOptions {
91
+ /** Glob pattern(s) for files to lint. */
92
+ files?: string | string[];
93
+ /** CSS source to lint instead of files. */
94
+ code?: string;
95
+ /** Virtual filename for `code`, used for syntax detection. */
96
+ codeFilename?: string;
97
+ /** Inline config object. */
98
+ config?: Config;
99
+ /** Path to a config file. */
100
+ configFile?: string;
101
+ fix?: boolean | "strict" | "lax";
102
+ formatter?: FormatterType | FormatterFunction;
103
+ quiet?: boolean;
104
+ cache?: boolean;
105
+ cacheLocation?: string;
106
+ maxWarnings?: number;
107
+ allowEmptyInput?: boolean;
108
+ ignorePath?: string;
109
+ ignoreDisables?: boolean;
110
+ reportNeedlessDisables?: boolean;
111
+ reportInvalidScopeDisables?: boolean;
112
+ reportDescriptionlessDisables?: boolean;
113
+ /** Working directory; defaults to `process.cwd()`. */
114
+ cwd?: string;
115
+ }
116
+
117
+ /** Lint files or a code string and resolve with a Stylelint-shaped result. */
118
+ export function lint(options?: LinterOptions): Promise<LinterResult>;
119
+
120
+ /** Resolve the effective config for a file, or `undefined` when none applies. */
121
+ export function resolveConfig(
122
+ filePath: string,
123
+ options?: { configFile?: string; cwd?: string },
124
+ ): Promise<Config | undefined>;
125
+
126
+ /** Promise-based formatter functions keyed by name, like `stylelint.formatters`. */
127
+ export const formatters: {
128
+ readonly json: Promise<FormatterFunction>;
129
+ readonly string: Promise<FormatterFunction>;
130
+ readonly compact: Promise<FormatterFunction>;
131
+ readonly verbose: Promise<FormatterFunction>;
132
+ readonly tap: Promise<FormatterFunction>;
133
+ readonly unix: Promise<FormatterFunction>;
134
+ };
135
+
136
+ /**
137
+ * Compatibility stub. Gale runs built-in Rust rules and cannot execute a
138
+ * JavaScript rule; calling this warns and returns an inert plugin object.
139
+ */
140
+ export function createPlugin(
141
+ ruleName: string,
142
+ ruleFunction: (...args: unknown[]) => unknown,
143
+ ): { ruleName: string; rule: (...args: unknown[]) => unknown };
144
+
145
+ declare const _default: {
146
+ lint: typeof lint;
147
+ formatters: typeof formatters;
148
+ resolveConfig: typeof resolveConfig;
149
+ createPlugin: typeof createPlugin;
150
+ };
151
+
152
+ export default _default;
package/index.mjs CHANGED
@@ -12,6 +12,8 @@ import { tmpdir } from "node:os";
12
12
  import { randomBytes } from "node:crypto";
13
13
  import { fileURLToPath } from "node:url";
14
14
 
15
+ import { binaryFileName, resolveTarget } from "./platform.cjs";
16
+
15
17
  const __filename = fileURLToPath(import.meta.url);
16
18
  const __dirname = dirname(__filename);
17
19
 
@@ -27,10 +29,13 @@ function findBinary() {
27
29
  return override;
28
30
  }
29
31
 
30
- // 1. Check the bin/ directory within the npm package
31
- const localBin = join(__dirname, "bin", "gale");
32
- if (existsSync(localBin)) {
33
- return localBin;
32
+ // 1. The binary bundled for this platform inside the npm package
33
+ const target = resolveTarget(process.platform, process.arch);
34
+ if (target) {
35
+ const bundled = join(__dirname, "bin", target, binaryFileName(process.platform));
36
+ if (existsSync(bundled)) {
37
+ return bundled;
38
+ }
34
39
  }
35
40
 
36
41
  // 2. Fall back to gale on PATH
@@ -129,9 +134,14 @@ function parseJsonOutput(jsonString) {
129
134
  warnings: (entry.warnings || []).map((w) => ({
130
135
  line: w.line,
131
136
  column: w.column,
137
+ endLine: w.endLine,
138
+ endColumn: w.endColumn,
132
139
  rule: w.rule,
133
140
  severity: w.severity || "warning",
134
141
  text: w.text,
142
+ // Only present when the rule's `url` secondary option is set, as in
143
+ // Stylelint, where an undefined url is dropped by JSON.stringify.
144
+ ...(w.url !== undefined ? { url: w.url } : {}),
135
145
  })),
136
146
  deprecations: [],
137
147
  invalidOptionWarnings: [],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codebend3r/gale",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "description": "An extremely fast CSS linter, written in Rust. Drop-in replacement for Stylelint.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -22,19 +22,23 @@
22
22
  ],
23
23
  "type": "module",
24
24
  "main": "index.mjs",
25
+ "types": "index.d.ts",
25
26
  "exports": {
26
27
  ".": {
28
+ "types": "./index.d.ts",
27
29
  "import": "./index.mjs",
28
30
  "require": "./index.cjs"
29
31
  }
30
32
  },
31
33
  "bin": {
32
- "gale": "bin/gale"
34
+ "gale": "bin/gale.cjs"
33
35
  },
34
36
  "files": [
35
37
  "bin/",
36
38
  "index.cjs",
39
+ "index.d.ts",
37
40
  "index.mjs",
41
+ "platform.cjs",
38
42
  "test.mjs",
39
43
  "README.md"
40
44
  ],
package/platform.cjs ADDED
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * Maps a Node.js platform and architecture to the Rust target whose binary
5
+ * ships inside this package, and names the binary for that platform.
6
+ *
7
+ * Shared by the `gale` launcher and the programmatic API. CommonJS so the
8
+ * launcher can require it synchronously on every supported Node version.
9
+ */
10
+
11
+ const TARGETS = {
12
+ "darwin-arm64": "aarch64-apple-darwin",
13
+ "darwin-x64": "x86_64-apple-darwin",
14
+ "linux-arm64": "aarch64-unknown-linux-gnu",
15
+ "linux-x64": "x86_64-unknown-linux-gnu",
16
+ "win32-arm64": "aarch64-pc-windows-msvc",
17
+ "win32-x64": "x86_64-pc-windows-msvc",
18
+ };
19
+
20
+ /**
21
+ * The Rust target triple for a platform/arch pair, or `null` when Gale does
22
+ * not ship a binary for it.
23
+ *
24
+ * @param {string} platform - `process.platform`
25
+ * @param {string} arch - `process.arch`
26
+ * @returns {string | null}
27
+ */
28
+ function resolveTarget(platform, arch) {
29
+ return TARGETS[`${platform}-${arch}`] ?? null;
30
+ }
31
+
32
+ /**
33
+ * The file name of the Gale binary on a platform.
34
+ *
35
+ * @param {string} platform - `process.platform`
36
+ * @returns {string}
37
+ */
38
+ function binaryFileName(platform) {
39
+ return platform === "win32" ? "gale.exe" : "gale";
40
+ }
41
+
42
+ /** Every `platform-arch` pair a binary ships for, for error messages. */
43
+ function supportedPlatforms() {
44
+ return Object.keys(TARGETS);
45
+ }
46
+
47
+ exports.resolveTarget = resolveTarget;
48
+ exports.binaryFileName = binaryFileName;
49
+ exports.supportedPlatforms = supportedPlatforms;
package/bin/gale DELETED
@@ -1,54 +0,0 @@
1
- #!/bin/sh
2
-
3
- set -eu
4
-
5
- platform="$(uname -s)-$(uname -m)"
6
-
7
- case "$platform" in
8
- Darwin-arm64)
9
- target="aarch64-apple-darwin"
10
- ;;
11
- Darwin-x86_64)
12
- target="x86_64-apple-darwin"
13
- ;;
14
- Linux-aarch64|Linux-arm64)
15
- target="aarch64-unknown-linux-gnu"
16
- ;;
17
- Linux-x86_64)
18
- target="x86_64-unknown-linux-gnu"
19
- ;;
20
- *)
21
- echo "Unsupported platform: $platform" >&2
22
- echo "Supported: Darwin-arm64, Darwin-x86_64, Linux-aarch64, Linux-x86_64" >&2
23
- exit 1
24
- ;;
25
- esac
26
-
27
- script="$0"
28
-
29
- while [ -L "$script" ]; do
30
- script_dir="$(CDPATH= cd "$(dirname "$script")" && pwd)"
31
- link="$(readlink "$script")"
32
-
33
- case "$link" in
34
- /*)
35
- script="$link"
36
- ;;
37
- *)
38
- script="$script_dir/$link"
39
- ;;
40
- esac
41
- done
42
-
43
- bin_dir="$(CDPATH= cd "$(dirname "$script")" && pwd)"
44
- binary="$bin_dir/$target/gale"
45
-
46
- if [ ! -x "$binary" ]; then
47
- echo "Gale binary missing for $target at $binary" >&2
48
- echo "This package should ship prebuilt binaries for $target." >&2
49
- echo "Try reinstalling the package, or build from source:" >&2
50
- echo " cargo install gale-lint" >&2
51
- exit 1
52
- fi
53
-
54
- exec "$binary" "$@"