@codebend3r/gale 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/README.md CHANGED
@@ -27,4 +27,4 @@ console.log(result.errored);
27
27
  console.log(result.results);
28
28
  ```
29
29
 
30
- See the full documentation at [github.com/LyricalString/gale](https://github.com/LyricalString/gale).
30
+ See the full documentation at [github.com/codebend3r/gale](https://github.com/codebend3r/gale).
Binary file
Binary file
Binary file
Binary file
package/index.mjs CHANGED
@@ -20,6 +20,13 @@ const __dirname = dirname(__filename);
20
20
  // ---------------------------------------------------------------------------
21
21
 
22
22
  function findBinary() {
23
+ // 0. An explicit override wins. Test suites and monorepos use this to point
24
+ // at a freshly built binary instead of the bundled one.
25
+ const override = process.env.GALE_BINARY;
26
+ if (override) {
27
+ return override;
28
+ }
29
+
23
30
  // 1. Check the bin/ directory within the npm package
24
31
  const localBin = join(__dirname, "bin", "gale");
25
32
  if (existsSync(localBin)) {
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@codebend3r/gale",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "An extremely fast CSS linter, written in Rust. Drop-in replacement for Stylelint.",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
8
- "url": "https://github.com/LyricalString/gale"
8
+ "url": "https://github.com/codebend3r/gale"
9
9
  },
10
- "homepage": "https://github.com/LyricalString/gale",
11
- "bugs": "https://github.com/LyricalString/gale/issues",
10
+ "homepage": "https://github.com/codebend3r/gale",
11
+ "bugs": "https://github.com/codebend3r/gale/issues",
12
12
  "keywords": [
13
13
  "css",
14
14
  "linter",
@@ -39,7 +39,7 @@
39
39
  "README.md"
40
40
  ],
41
41
  "engines": {
42
- "node": ">=16.0.0"
42
+ "node": ">=20.0.0"
43
43
  },
44
44
  "scripts": {
45
45
  "test": "node test.mjs"
package/test.mjs CHANGED
@@ -8,18 +8,45 @@
8
8
  * Requires a working gale binary (either in npm/bin/ or on PATH).
9
9
  */
10
10
 
11
+ import { createRequire } from "node:module";
12
+
11
13
  import { lint, formatters, resolveConfig, createPlugin } from "./index.mjs";
12
14
 
15
+ const require = createRequire(import.meta.url);
16
+
13
17
  let passed = 0;
14
18
  let failed = 0;
19
+ let current = "";
20
+
21
+ // Dots reporter: one "." per passing assertion, "F" per failure. Failure
22
+ // details are printed on their own line so the dots stay readable.
23
+ function section(name) {
24
+ current = name;
25
+ }
26
+
27
+ function fail(message) {
28
+ process.stdout.write("F");
29
+ console.error(`\n FAIL [${current}] ${message}`);
30
+ failed++;
31
+ }
15
32
 
16
33
  function assert(condition, message) {
17
34
  if (condition) {
18
- console.log(` PASS: ${message}`);
35
+ process.stdout.write(".");
19
36
  passed++;
20
37
  } else {
21
- console.error(` FAIL: ${message}`);
22
- failed++;
38
+ fail(message);
39
+ }
40
+ }
41
+
42
+ // Runs fn with console.warn muted, for APIs that warn by design.
43
+ function quietly(fn) {
44
+ const warn = console.warn;
45
+ console.warn = () => {};
46
+ try {
47
+ return fn();
48
+ } finally {
49
+ console.warn = warn;
23
50
  }
24
51
  }
25
52
 
@@ -28,7 +55,7 @@ function assert(condition, message) {
28
55
  // ---------------------------------------------------------------------------
29
56
 
30
57
  async function testLintCodeEmptyBlock() {
31
- console.log("\nTest 1: lint({ code: 'a {}' })");
58
+ section("Test 1: lint({ code: 'a {}' })");
32
59
 
33
60
  try {
34
61
  const result = await lint({ code: "a {}" });
@@ -50,8 +77,7 @@ async function testLintCodeEmptyBlock() {
50
77
  assert(typeof first.ignored === "boolean", "first result has ignored boolean");
51
78
  }
52
79
  } catch (err) {
53
- console.error(` ERROR: ${err.message}`);
54
- failed++;
80
+ fail(`ERROR: ${err.message}`);
55
81
  }
56
82
  }
57
83
 
@@ -60,7 +86,7 @@ async function testLintCodeEmptyBlock() {
60
86
  // ---------------------------------------------------------------------------
61
87
 
62
88
  async function testLintCodeWithConfig() {
63
- console.log("\nTest 2: lint({ code: 'a { color: pink; }', config: { rules: { 'color-named': 'never' } } })");
89
+ section("Test 2: lint({ code: 'a { color: pink; }', config: { rules: { 'color-named': 'never' } } })");
64
90
 
65
91
  try {
66
92
  const result = await lint({
@@ -86,13 +112,10 @@ async function testLintCodeWithConfig() {
86
112
  w.rule === "color-named",
87
113
  `warning rule is "color-named" (got "${w.rule}")`,
88
114
  );
89
- } else {
90
- console.log(" INFO: No warnings returned (gale may not flag this without config).");
91
115
  }
92
116
  }
93
117
  } catch (err) {
94
- console.error(` ERROR: ${err.message}`);
95
- failed++;
118
+ fail(`ERROR: ${err.message}`);
96
119
  }
97
120
  }
98
121
 
@@ -101,7 +124,7 @@ async function testLintCodeWithConfig() {
101
124
  // ---------------------------------------------------------------------------
102
125
 
103
126
  async function testResolveConfig() {
104
- console.log("\nTest 3: resolveConfig('test.css')");
127
+ section("Test 3: resolveConfig('test.css')");
105
128
 
106
129
  try {
107
130
  const config = await resolveConfig("test.css");
@@ -111,8 +134,7 @@ async function testResolveConfig() {
111
134
  "resolveConfig returns object or undefined",
112
135
  );
113
136
  } catch (err) {
114
- console.error(` ERROR: ${err.message}`);
115
- failed++;
137
+ fail(`ERROR: ${err.message}`);
116
138
  }
117
139
  }
118
140
 
@@ -121,7 +143,7 @@ async function testResolveConfig() {
121
143
  // ---------------------------------------------------------------------------
122
144
 
123
145
  async function testFormattersJson() {
124
- console.log("\nTest 4: formatters.json resolves to a function");
146
+ section("Test 4: formatters.json resolves to a function");
125
147
 
126
148
  try {
127
149
  const jsonFormatter = await formatters.json;
@@ -144,8 +166,7 @@ async function testFormattersJson() {
144
166
  const parsed = JSON.parse(output);
145
167
  assert(Array.isArray(parsed), "JSON formatter output is parseable as array");
146
168
  } catch (err) {
147
- console.error(` ERROR: ${err.message}`);
148
- failed++;
169
+ fail(`ERROR: ${err.message}`);
149
170
  }
150
171
  }
151
172
 
@@ -154,9 +175,9 @@ async function testFormattersJson() {
154
175
  // ---------------------------------------------------------------------------
155
176
 
156
177
  async function testCreatePlugin() {
157
- console.log("\nTest 5: createPlugin returns stub");
178
+ section("Test 5: createPlugin returns stub");
158
179
 
159
- const plugin = createPlugin("my-rule", () => {});
180
+ const plugin = quietly(() => createPlugin("my-rule", () => {}));
160
181
  assert(plugin.ruleName === "my-rule", 'plugin.ruleName is "my-rule"');
161
182
  assert(typeof plugin.rule === "function", "plugin.rule is a function");
162
183
  }
@@ -166,7 +187,7 @@ async function testCreatePlugin() {
166
187
  // ---------------------------------------------------------------------------
167
188
 
168
189
  async function testLinterResultShape() {
169
- console.log("\nTest 6: LinterResult has correct shape");
190
+ section("Test 6: LinterResult has correct shape");
170
191
 
171
192
  try {
172
193
  const result = await lint({ code: "a { color: red; }" });
@@ -179,8 +200,39 @@ async function testLinterResultShape() {
179
200
  assert("maxWarningsExceeded" in result, "result has maxWarningsExceeded key");
180
201
  assert("code" in result, "result has code key");
181
202
  } catch (err) {
182
- console.error(` ERROR: ${err.message}`);
183
- failed++;
203
+ fail(`ERROR: ${err.message}`);
204
+ }
205
+ }
206
+
207
+ // ---------------------------------------------------------------------------
208
+ // Test 7: CommonJS entry point bridges to the ESM implementation
209
+ // ---------------------------------------------------------------------------
210
+
211
+ async function testCommonJsEntry() {
212
+ section("Test 7: require('./index.cjs') exposes the same API");
213
+
214
+ try {
215
+ const cjs = require("./index.cjs");
216
+
217
+ assert(typeof cjs.lint === "function", "cjs.lint is a function");
218
+ assert(typeof cjs.resolveConfig === "function", "cjs.resolveConfig is a function");
219
+ assert(typeof cjs.createPlugin === "function", "cjs.createPlugin is a function");
220
+ assert(cjs.default === cjs, "cjs.default points back at module.exports");
221
+
222
+ const jsonFormatter = await cjs.formatters.json;
223
+ assert(typeof jsonFormatter === "function", "cjs.formatters.json resolves to a function");
224
+
225
+ const result = await cjs.lint({
226
+ code: "a {}",
227
+ config: { rules: { "block-no-empty": true } },
228
+ });
229
+ assert(Array.isArray(result.results), "cjs.lint returns results");
230
+ assert(
231
+ result.results[0]?.warnings[0]?.rule === "block-no-empty",
232
+ "cjs.lint reports block-no-empty",
233
+ );
234
+ } catch (err) {
235
+ fail(`ERROR: ${err.message}`);
184
236
  }
185
237
  }
186
238
 
@@ -189,16 +241,15 @@ async function testLinterResultShape() {
189
241
  // ---------------------------------------------------------------------------
190
242
 
191
243
  async function main() {
192
- console.log("=== @codebend3r/gale programmatic API tests ===");
193
-
194
244
  await testLintCodeEmptyBlock();
195
245
  await testLintCodeWithConfig();
196
246
  await testResolveConfig();
197
247
  await testFormattersJson();
198
248
  await testCreatePlugin();
199
249
  await testLinterResultShape();
250
+ await testCommonJsEntry();
200
251
 
201
- console.log(`\n=== Results: ${passed} passed, ${failed} failed ===`);
252
+ console.log(`\n${passed} passed, ${failed} failed (Node ${process.versions.node})`);
202
253
 
203
254
  if (failed > 0) {
204
255
  process.exit(1);