@bhsd/common 1.3.1 → 1.4.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.
package/dist/index.d.ts CHANGED
@@ -61,4 +61,9 @@ export declare const lintJSONNative: (str: string, force?: boolean) => JsonError
61
61
  * @param str JSON字符串
62
62
  */
63
63
  export declare const lintJSON: (str: string) => JsonError[];
64
+ /**
65
+ * 诊断JSONC字符串中的语法错误
66
+ * @param str JSONC字符串
67
+ */
68
+ export declare const lintJSONC: (str: string) => JsonError[];
64
69
  export {};
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.lintJSON = exports.lintJSONNative = exports.splitLines = exports.getObjRegex = exports.sanitizeInlineStyle = exports.splitColors = exports.numToHex = exports.rawurldecode = exports.wmf = void 0;
3
+ exports.lintJSONC = exports.lintJSON = exports.lintJSONNative = exports.splitLines = exports.getObjRegex = exports.sanitizeInlineStyle = exports.splitColors = exports.numToHex = exports.rawurldecode = exports.wmf = void 0;
4
4
  exports.getRegex = getRegex;
5
5
  const json_parse_js_1 = require("./json_parse.js");
6
6
  exports.wmf = 'wiktionary|wiki(?:pedia|books|news|quote|source|versity|voyage)';
@@ -142,17 +142,9 @@ const lintJSONNative = (str, force) => {
142
142
  return [];
143
143
  };
144
144
  exports.lintJSONNative = lintJSONNative;
145
- /**
146
- * 诊断JSON字符串中的语法错误
147
- * @param str JSON字符串
148
- */
149
- const lintJSON = (str) => {
150
- if (!str.trim()) {
151
- return [];
152
- }
153
- let errors;
145
+ const lintJSONBase = (str, parse) => {
154
146
  try {
155
- (0, json_parse_js_1.json_parse)(str);
147
+ parse(str);
156
148
  }
157
149
  catch (e) {
158
150
  if (!(e instanceof Error)) {
@@ -160,13 +152,26 @@ const lintJSON = (str) => {
160
152
  if (error.message) {
161
153
  warnings.push(error);
162
154
  }
163
- errors = formatJsonError(str, warnings);
164
- if (error.message) {
165
- return errors;
166
- }
155
+ return formatJsonError(str, warnings);
167
156
  }
168
157
  }
169
- const nativeErrors = (0, exports.lintJSONNative)(str);
170
- return errors ? [...nativeErrors, ...errors] : nativeErrors;
158
+ return [];
159
+ };
160
+ /**
161
+ * 诊断JSON字符串中的语法错误
162
+ * @param str JSON字符串
163
+ */
164
+ const lintJSON = (str) => {
165
+ if (!str.trim()) {
166
+ return [];
167
+ }
168
+ const errors = lintJSONBase(str, json_parse_js_1.json_parse);
169
+ return errors[errors.length - 1]?.severity === 'error' ? errors : [...errors, ...(0, exports.lintJSONNative)(str)];
171
170
  };
172
171
  exports.lintJSON = lintJSON;
172
+ /**
173
+ * 诊断JSONC字符串中的语法错误
174
+ * @param str JSONC字符串
175
+ */
176
+ const lintJSONC = (str) => str.trim() ? lintJSONBase(str, json_parse_js_1.jsonc_parse) : [];
177
+ exports.lintJSONC = lintJSONC;
package/dist/index.mjs CHANGED
@@ -16,7 +16,7 @@ var stringify = (c) => {
16
16
  }
17
17
  return c === '"' ? `'"'` : JSON.stringify(c);
18
18
  };
19
- var json_parse = /* @__PURE__ */ (() => {
19
+ var factory = (jsonc) => {
20
20
  let at;
21
21
  let ch;
22
22
  let text;
@@ -152,8 +152,33 @@ var json_parse = /* @__PURE__ */ (() => {
152
152
  return error("Unterminated string");
153
153
  };
154
154
  const white = () => {
155
- while (ch && spaces.has(ch)) {
156
- next();
155
+ while (ch) {
156
+ while (ch && spaces.has(ch)) {
157
+ next();
158
+ }
159
+ if (jsonc && ch === "/") {
160
+ const peek = text.charAt(at);
161
+ if (peek === "/") {
162
+ next();
163
+ next();
164
+ while (ch && ch !== "\n" && ch !== "\r") {
165
+ next();
166
+ }
167
+ continue;
168
+ } else if (peek === "*") {
169
+ next();
170
+ next();
171
+ while (ch && !(ch === "*" && text.charAt(at) === "/")) {
172
+ next();
173
+ }
174
+ if (ch === "*") {
175
+ next();
176
+ next();
177
+ }
178
+ continue;
179
+ }
180
+ }
181
+ break;
157
182
  }
158
183
  };
159
184
  const word = () => {
@@ -187,10 +212,19 @@ var json_parse = /* @__PURE__ */ (() => {
187
212
  if (ch === "]") {
188
213
  next();
189
214
  return;
215
+ } else if (jsonc && ch === ",") {
216
+ next();
217
+ white();
218
+ next("]");
219
+ return;
190
220
  }
191
221
  let from;
192
222
  while (ch) {
193
223
  if (ch === "]") {
224
+ if (jsonc) {
225
+ next();
226
+ return;
227
+ }
194
228
  error("Trailing comma in array", from, from + 1);
195
229
  }
196
230
  value();
@@ -215,10 +249,19 @@ var json_parse = /* @__PURE__ */ (() => {
215
249
  if (ch === "}") {
216
250
  next();
217
251
  return;
252
+ } else if (jsonc && ch === ",") {
253
+ next();
254
+ white();
255
+ next("}");
256
+ return;
218
257
  }
219
258
  let from;
220
259
  while (ch) {
221
260
  if (ch === "}") {
261
+ if (jsonc) {
262
+ next();
263
+ return;
264
+ }
222
265
  error("Trailing comma in object", from, from + 1);
223
266
  }
224
267
  from = at;
@@ -249,6 +292,8 @@ var json_parse = /* @__PURE__ */ (() => {
249
292
  const value = () => {
250
293
  white();
251
294
  switch (ch) {
295
+ case "":
296
+ return void 0;
252
297
  case "{":
253
298
  return object();
254
299
  case "[":
@@ -274,7 +319,9 @@ var json_parse = /* @__PURE__ */ (() => {
274
319
  throw { warnings };
275
320
  }
276
321
  };
277
- })();
322
+ };
323
+ var json_parse = /* @__PURE__ */ factory();
324
+ var jsonc_parse = /* @__PURE__ */ factory(true);
278
325
 
279
326
  // src/index.ts
280
327
  var wmf = "wiktionary|wiki(?:pedia|books|news|quote|source|versity|voyage)";
@@ -375,32 +422,33 @@ var lintJSONNative = (str, force) => {
375
422
  }
376
423
  return [];
377
424
  };
378
- var lintJSON = (str) => {
379
- if (!str.trim()) {
380
- return [];
381
- }
382
- let errors;
425
+ var lintJSONBase = (str, parse) => {
383
426
  try {
384
- json_parse(str);
427
+ parse(str);
385
428
  } catch (e) {
386
429
  if (!(e instanceof Error)) {
387
430
  const { warnings, ...error } = e;
388
431
  if (error.message) {
389
432
  warnings.push(error);
390
433
  }
391
- errors = formatJsonError(str, warnings);
392
- if (error.message) {
393
- return errors;
394
- }
434
+ return formatJsonError(str, warnings);
395
435
  }
396
436
  }
397
- const nativeErrors = lintJSONNative(str);
398
- return errors ? [...nativeErrors, ...errors] : nativeErrors;
437
+ return [];
438
+ };
439
+ var lintJSON = (str) => {
440
+ if (!str.trim()) {
441
+ return [];
442
+ }
443
+ const errors = lintJSONBase(str, json_parse);
444
+ return errors[errors.length - 1]?.severity === "error" ? errors : [...errors, ...lintJSONNative(str)];
399
445
  };
446
+ var lintJSONC = (str) => str.trim() ? lintJSONBase(str, jsonc_parse) : [];
400
447
  export {
401
448
  getObjRegex,
402
449
  getRegex,
403
450
  lintJSON,
451
+ lintJSONC,
404
452
  lintJSONNative,
405
453
  numToHex,
406
454
  rawurldecode,
@@ -28,7 +28,7 @@
28
28
  USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO NOT CONTROL.
29
29
  */
30
30
  Object.defineProperty(exports, "__esModule", { value: true });
31
- exports.json_parse = void 0;
31
+ exports.jsonc_parse = exports.json_parse = void 0;
32
32
  const escapee = {
33
33
  '"': '"',
34
34
  "\\": "\\",
@@ -46,7 +46,7 @@ const stringify = (c) => {
46
46
  }
47
47
  return c === '"' ? `'"'` : JSON.stringify(c);
48
48
  };
49
- exports.json_parse = (() => {
49
+ const factory = (jsonc) => {
50
50
  // This is a function that can parse a JSON text.
51
51
  // It is a simple, recursive descent parser.
52
52
  // It does not use eval or regular expressions,
@@ -203,9 +203,40 @@ exports.json_parse = (() => {
203
203
  return error("Unterminated string");
204
204
  };
205
205
  const white = () => {
206
- // Skip whitespace.
207
- while (ch && spaces.has(ch)) {
208
- next();
206
+ // Skip whitespace and comments (JSONC).
207
+ while (ch) {
208
+ // Skip whitespace.
209
+ while (ch && spaces.has(ch)) {
210
+ next();
211
+ }
212
+ if (jsonc && ch === "/") {
213
+ const peek = text.charAt(at);
214
+ if (peek === "/") {
215
+ // Skip single-line comments.
216
+ next(); // skip /
217
+ next(); // skip /
218
+ // @ts-expect-error `ch` modified
219
+ while (ch && ch !== "\n" && ch !== "\r") {
220
+ next();
221
+ }
222
+ continue;
223
+ }
224
+ else if (peek === "*") {
225
+ // Skip multi-line comments.
226
+ next(); // skip /
227
+ next(); // skip *
228
+ // @ts-expect-error `ch` modified
229
+ while (ch && !(ch === "*" && text.charAt(at) === "/")) {
230
+ next();
231
+ }
232
+ if (ch === "*") {
233
+ next(); // skip *
234
+ next(); // skip /
235
+ }
236
+ continue;
237
+ }
238
+ }
239
+ break;
209
240
  }
210
241
  };
211
242
  const word = () => {
@@ -242,9 +273,19 @@ exports.json_parse = (() => {
242
273
  next();
243
274
  return; // empty array
244
275
  }
276
+ else if (jsonc && ch === ",") {
277
+ next();
278
+ white();
279
+ next("]");
280
+ return;
281
+ }
245
282
  let from;
246
283
  while (ch) {
247
284
  if (ch === "]") {
285
+ if (jsonc) {
286
+ next();
287
+ return;
288
+ }
248
289
  error("Trailing comma in array", from, from + 1);
249
290
  }
250
291
  value();
@@ -273,9 +314,19 @@ exports.json_parse = (() => {
273
314
  next();
274
315
  return; // empty object
275
316
  }
317
+ else if (jsonc && ch === ",") {
318
+ next();
319
+ white();
320
+ next("}");
321
+ return;
322
+ }
276
323
  let from;
277
324
  while (ch) {
278
325
  if (ch === "}") {
326
+ if (jsonc) {
327
+ next();
328
+ return;
329
+ }
279
330
  error("Trailing comma in object", from, from + 1);
280
331
  }
281
332
  from = at;
@@ -311,6 +362,8 @@ exports.json_parse = (() => {
311
362
  // or a word.
312
363
  white();
313
364
  switch (ch) {
365
+ case "":
366
+ return undefined;
314
367
  case "{":
315
368
  return object();
316
369
  case "[":
@@ -341,4 +394,5 @@ exports.json_parse = (() => {
341
394
  throw { warnings };
342
395
  }
343
396
  };
344
- })();
397
+ };
398
+ exports.json_parse = factory(), exports.jsonc_parse = factory(true);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bhsd/common",
3
- "version": "1.3.1",
3
+ "version": "1.4.0",
4
4
  "homepage": "https://github.com/bhsd-harry/common#readme",
5
5
  "bugs": {
6
6
  "url": "https://github.com/bhsd-harry/common/issues"
@@ -29,24 +29,24 @@
29
29
  "test": "mocha"
30
30
  },
31
31
  "devDependencies": {
32
- "@bhsd/code-standard": "^1.3.2",
33
- "@stylistic/eslint-plugin": "^5.5.0",
32
+ "@bhsd/code-standard": "^2.1.1",
33
+ "@stylistic/eslint-plugin": "^5.10.0",
34
34
  "@types/mocha": "^10.0.10",
35
- "@typescript-eslint/eslint-plugin": "^8.46.4",
36
- "@typescript-eslint/parser": "^8.46.4",
37
- "esbuild": "^0.25.12",
38
- "eslint": "^9.39.1",
39
- "eslint-plugin-es-x": "^9.1.2",
35
+ "@typescript-eslint/eslint-plugin": "^8.57.0",
36
+ "@typescript-eslint/parser": "^8.57.0",
37
+ "esbuild": "^0.27.4",
38
+ "eslint": "^9.39.4",
39
+ "eslint-plugin-es-x": "^9.5.0",
40
40
  "eslint-plugin-eslint-comments": "^3.2.0",
41
- "eslint-plugin-jsdoc": "^61.2.1",
42
- "eslint-plugin-jsonc": "^2.21.0",
41
+ "eslint-plugin-jsdoc": "^62.7.1",
42
+ "eslint-plugin-jsonc": "^3.1.1",
43
43
  "eslint-plugin-promise": "^7.2.1",
44
- "eslint-plugin-regexp": "^2.10.0",
45
- "eslint-plugin-unicorn": "^62.0.0",
44
+ "eslint-plugin-regexp": "^3.1.0",
45
+ "eslint-plugin-unicorn": "^63.0.0",
46
46
  "mocha": "^11.7.5",
47
47
  "typescript": "^5.9.3"
48
48
  },
49
49
  "engines": {
50
- "node": ">=18.17.0"
50
+ "node": ">=20.19.0"
51
51
  }
52
52
  }