@bhsd/common 1.3.1 → 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.
- package/dist/index.d.ts +5 -0
- package/dist/index.js +32 -39
- package/dist/json_parse.js +59 -8
- package/package.json +16 -22
- package/dist/index.mjs +0 -411
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,21 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.lintJSON = exports.lintJSONNative = exports.splitLines = exports.getObjRegex = exports.sanitizeInlineStyle = exports.splitColors = exports.numToHex = exports.rawurldecode = exports.wmf = void 0;
|
|
4
|
-
exports.getRegex = getRegex;
|
|
5
|
-
const json_parse_js_1 = require("./json_parse.js");
|
|
6
|
-
exports.wmf = 'wiktionary|wiki(?:pedia|books|news|quote|source|versity|voyage)';
|
|
1
|
+
import { json_parse, jsonc_parse } from './json_parse.js';
|
|
2
|
+
export const wmf = 'wiktionary|wiki(?:pedia|books|news|quote|source|versity|voyage)';
|
|
7
3
|
/**
|
|
8
4
|
* PHP的`rawurldecode`函数的JavaScript实现
|
|
9
5
|
* @param str 要解码的字符串
|
|
10
6
|
*/
|
|
11
|
-
const rawurldecode = (str) => decodeURIComponent(str.replace(/%(?![\da-f]{2})/giu, '%25'));
|
|
12
|
-
exports.rawurldecode = rawurldecode;
|
|
7
|
+
export const rawurldecode = (str) => decodeURIComponent(str.replace(/%(?![\da-f]{2})/giu, '%25'));
|
|
13
8
|
/**
|
|
14
9
|
* 将0~1之间的数字转换为十六进制
|
|
15
10
|
* @param d 0~1之间的数字
|
|
16
11
|
*/
|
|
17
|
-
const numToHex = (d) => Math.round(d * 255).toString(16).padStart(2, '0');
|
|
18
|
-
exports.numToHex = numToHex;
|
|
12
|
+
export const numToHex = (d) => Math.round(d * 255).toString(16).padStart(2, '0');
|
|
19
13
|
const regex = /* #__PURE__ */ (() => {
|
|
20
14
|
const hexColor = String.raw `#(?:[\da-f]{3,4}|(?:[\da-f]{2}){3,4})(?![\p{L}\p{N}_])`, rgbValue = String.raw `(?:\d*\.)?\d+%?`, hue = String.raw `(?:\d*\.)?\d+(?:deg|grad|rad|turn)?`, rgbColor = String.raw `rgba?\(\s*(?:${String.raw `${new Array(3).fill(rgbValue).join(String.raw `\s+`)}(?:\s*\/\s*${rgbValue})?`}|${String.raw `${new Array(3).fill(rgbValue).join(String.raw `\s*,\s*`)}(?:\s*,\s*${rgbValue})?`})\s*\)`, hslColor = String.raw `hsla?\(\s*(?:${String.raw `${hue}\s+${rgbValue}\s+${rgbValue}(?:\s*\/\s*${rgbValue})?`}|${String.raw `${hue}${String.raw `\s*,\s*(?:\d*\.)?\d+%`.repeat(2)}(?:\s*,\s*${rgbValue})?`})\s*\)`;
|
|
21
15
|
return {
|
|
@@ -28,7 +22,7 @@ const regex = /* #__PURE__ */ (() => {
|
|
|
28
22
|
* @param str 字符串
|
|
29
23
|
* @param hsl 是否包含 HSL
|
|
30
24
|
*/
|
|
31
|
-
const splitColors = (str, hsl = true) => {
|
|
25
|
+
export const splitColors = (str, hsl = true) => {
|
|
32
26
|
const pieces = [], re = regex[hsl ? 'full' : 'rgb'];
|
|
33
27
|
re.lastIndex = 0;
|
|
34
28
|
let mt = re.exec(str), lastIndex = 0;
|
|
@@ -46,15 +40,13 @@ const splitColors = (str, hsl = true) => {
|
|
|
46
40
|
}
|
|
47
41
|
return pieces;
|
|
48
42
|
};
|
|
49
|
-
exports.splitColors = splitColors;
|
|
50
43
|
/**
|
|
51
44
|
* 清理内联样式中的`{`和`}`
|
|
52
45
|
* @param style 内联样式
|
|
53
46
|
*/
|
|
54
|
-
const sanitizeInlineStyle = (style) => style.replace(/[{}]/gu, p => p === '{' ? '{' : '}')
|
|
47
|
+
export const sanitizeInlineStyle = (style) => style.replace(/[{}]/gu, p => p === '{' ? '{' : '}')
|
|
55
48
|
.replace(/^[\s;]+/u, p => p.replace(/;/gu, ' '));
|
|
56
|
-
|
|
57
|
-
function getRegex(f) {
|
|
49
|
+
export function getRegex(f) {
|
|
58
50
|
const map = new Map(), weakMap = new WeakMap();
|
|
59
51
|
return s => {
|
|
60
52
|
const regexp = typeof s === 'string' ? map : weakMap;
|
|
@@ -73,12 +65,12 @@ function getRegex(f) {
|
|
|
73
65
|
* @param f 生成正则表达式的函数
|
|
74
66
|
* @deprecated 需要改为使用`getRegex`
|
|
75
67
|
*/
|
|
76
|
-
|
|
68
|
+
export const getObjRegex = getRegex;
|
|
77
69
|
/**
|
|
78
70
|
* 按行分割字符串并记录每行的起止位置
|
|
79
71
|
* @param str 字符串
|
|
80
72
|
*/
|
|
81
|
-
const splitLines = (str) => {
|
|
73
|
+
export const splitLines = (str) => {
|
|
82
74
|
const lines = [];
|
|
83
75
|
let start = 0;
|
|
84
76
|
for (const line of str.split('\n')) {
|
|
@@ -88,12 +80,11 @@ const splitLines = (str) => {
|
|
|
88
80
|
}
|
|
89
81
|
return lines;
|
|
90
82
|
};
|
|
91
|
-
exports.splitLines = splitLines;
|
|
92
83
|
const mt2num = (mt) => mt && Number(mt[1]);
|
|
93
84
|
const formatJsonError = (str, errors) => {
|
|
94
85
|
let lines;
|
|
95
86
|
const offsetToPosition = (offset) => {
|
|
96
|
-
lines ??=
|
|
87
|
+
lines ??= splitLines(str);
|
|
97
88
|
const line = lines.findIndex(([, , end]) => offset <= end) + 1;
|
|
98
89
|
return {
|
|
99
90
|
line,
|
|
@@ -104,7 +95,7 @@ const formatJsonError = (str, errors) => {
|
|
|
104
95
|
const { line, column, from, to } = error;
|
|
105
96
|
if (from === null || from === undefined) {
|
|
106
97
|
if (line) {
|
|
107
|
-
lines ??=
|
|
98
|
+
lines ??= splitLines(str);
|
|
108
99
|
error.column ??= 1;
|
|
109
100
|
error.from = lines[line - 1][1] + (error.column - 1);
|
|
110
101
|
}
|
|
@@ -129,7 +120,7 @@ const formatJsonError = (str, errors) => {
|
|
|
129
120
|
* @param str JSON字符串
|
|
130
121
|
* @param force 是否强制诊断
|
|
131
122
|
*/
|
|
132
|
-
const lintJSONNative = (str, force) => {
|
|
123
|
+
export const lintJSONNative = (str, force) => {
|
|
133
124
|
if (force || str.trim()) {
|
|
134
125
|
try {
|
|
135
126
|
JSON.parse(str);
|
|
@@ -141,18 +132,9 @@ const lintJSONNative = (str, force) => {
|
|
|
141
132
|
}
|
|
142
133
|
return [];
|
|
143
134
|
};
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* 诊断JSON字符串中的语法错误
|
|
147
|
-
* @param str JSON字符串
|
|
148
|
-
*/
|
|
149
|
-
const lintJSON = (str) => {
|
|
150
|
-
if (!str.trim()) {
|
|
151
|
-
return [];
|
|
152
|
-
}
|
|
153
|
-
let errors;
|
|
135
|
+
const lintJSONBase = (str, parse) => {
|
|
154
136
|
try {
|
|
155
|
-
(
|
|
137
|
+
parse(str);
|
|
156
138
|
}
|
|
157
139
|
catch (e) {
|
|
158
140
|
if (!(e instanceof Error)) {
|
|
@@ -160,13 +142,24 @@ const lintJSON = (str) => {
|
|
|
160
142
|
if (error.message) {
|
|
161
143
|
warnings.push(error);
|
|
162
144
|
}
|
|
163
|
-
|
|
164
|
-
if (error.message) {
|
|
165
|
-
return errors;
|
|
166
|
-
}
|
|
145
|
+
return formatJsonError(str, warnings);
|
|
167
146
|
}
|
|
168
147
|
}
|
|
169
|
-
|
|
170
|
-
|
|
148
|
+
return [];
|
|
149
|
+
};
|
|
150
|
+
/**
|
|
151
|
+
* 诊断JSON字符串中的语法错误
|
|
152
|
+
* @param str JSON字符串
|
|
153
|
+
*/
|
|
154
|
+
export const lintJSON = (str) => {
|
|
155
|
+
if (!str.trim()) {
|
|
156
|
+
return [];
|
|
157
|
+
}
|
|
158
|
+
const errors = lintJSONBase(str, json_parse);
|
|
159
|
+
return errors[errors.length - 1]?.severity === 'error' ? errors : [...errors, ...lintJSONNative(str)];
|
|
171
160
|
};
|
|
172
|
-
|
|
161
|
+
/**
|
|
162
|
+
* 诊断JSONC字符串中的语法错误
|
|
163
|
+
* @param str JSONC字符串
|
|
164
|
+
*/
|
|
165
|
+
export const lintJSONC = (str) => str.trim() ? lintJSONBase(str, jsonc_parse) : [];
|
package/dist/json_parse.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/*
|
|
3
2
|
json_parse.js
|
|
4
3
|
2016-05-02
|
|
@@ -27,8 +26,6 @@
|
|
|
27
26
|
|
|
28
27
|
USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO NOT CONTROL.
|
|
29
28
|
*/
|
|
30
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
31
|
-
exports.json_parse = void 0;
|
|
32
29
|
const escapee = {
|
|
33
30
|
'"': '"',
|
|
34
31
|
"\\": "\\",
|
|
@@ -46,7 +43,7 @@ const stringify = (c) => {
|
|
|
46
43
|
}
|
|
47
44
|
return c === '"' ? `'"'` : JSON.stringify(c);
|
|
48
45
|
};
|
|
49
|
-
|
|
46
|
+
const factory = (jsonc) => {
|
|
50
47
|
// This is a function that can parse a JSON text.
|
|
51
48
|
// It is a simple, recursive descent parser.
|
|
52
49
|
// It does not use eval or regular expressions,
|
|
@@ -203,9 +200,40 @@ exports.json_parse = (() => {
|
|
|
203
200
|
return error("Unterminated string");
|
|
204
201
|
};
|
|
205
202
|
const white = () => {
|
|
206
|
-
// Skip whitespace.
|
|
207
|
-
while (ch
|
|
208
|
-
|
|
203
|
+
// Skip whitespace and comments (JSONC).
|
|
204
|
+
while (ch) {
|
|
205
|
+
// Skip whitespace.
|
|
206
|
+
while (ch && spaces.has(ch)) {
|
|
207
|
+
next();
|
|
208
|
+
}
|
|
209
|
+
if (jsonc && ch === "/") {
|
|
210
|
+
const peek = text.charAt(at);
|
|
211
|
+
if (peek === "/") {
|
|
212
|
+
// Skip single-line comments.
|
|
213
|
+
next(); // skip /
|
|
214
|
+
next(); // skip /
|
|
215
|
+
// @ts-expect-error `ch` modified
|
|
216
|
+
while (ch && ch !== "\n" && ch !== "\r") {
|
|
217
|
+
next();
|
|
218
|
+
}
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
else if (peek === "*") {
|
|
222
|
+
// Skip multi-line comments.
|
|
223
|
+
next(); // skip /
|
|
224
|
+
next(); // skip *
|
|
225
|
+
// @ts-expect-error `ch` modified
|
|
226
|
+
while (ch && !(ch === "*" && text.charAt(at) === "/")) {
|
|
227
|
+
next();
|
|
228
|
+
}
|
|
229
|
+
if (ch === "*") {
|
|
230
|
+
next(); // skip *
|
|
231
|
+
next(); // skip /
|
|
232
|
+
}
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
break;
|
|
209
237
|
}
|
|
210
238
|
};
|
|
211
239
|
const word = () => {
|
|
@@ -242,9 +270,19 @@ exports.json_parse = (() => {
|
|
|
242
270
|
next();
|
|
243
271
|
return; // empty array
|
|
244
272
|
}
|
|
273
|
+
else if (jsonc && ch === ",") {
|
|
274
|
+
next();
|
|
275
|
+
white();
|
|
276
|
+
next("]");
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
245
279
|
let from;
|
|
246
280
|
while (ch) {
|
|
247
281
|
if (ch === "]") {
|
|
282
|
+
if (jsonc) {
|
|
283
|
+
next();
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
248
286
|
error("Trailing comma in array", from, from + 1);
|
|
249
287
|
}
|
|
250
288
|
value();
|
|
@@ -273,9 +311,19 @@ exports.json_parse = (() => {
|
|
|
273
311
|
next();
|
|
274
312
|
return; // empty object
|
|
275
313
|
}
|
|
314
|
+
else if (jsonc && ch === ",") {
|
|
315
|
+
next();
|
|
316
|
+
white();
|
|
317
|
+
next("}");
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
276
320
|
let from;
|
|
277
321
|
while (ch) {
|
|
278
322
|
if (ch === "}") {
|
|
323
|
+
if (jsonc) {
|
|
324
|
+
next();
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
279
327
|
error("Trailing comma in object", from, from + 1);
|
|
280
328
|
}
|
|
281
329
|
from = at;
|
|
@@ -311,6 +359,8 @@ exports.json_parse = (() => {
|
|
|
311
359
|
// or a word.
|
|
312
360
|
white();
|
|
313
361
|
switch (ch) {
|
|
362
|
+
case "":
|
|
363
|
+
return undefined;
|
|
314
364
|
case "{":
|
|
315
365
|
return object();
|
|
316
366
|
case "[":
|
|
@@ -341,4 +391,5 @@ exports.json_parse = (() => {
|
|
|
341
391
|
throw { warnings };
|
|
342
392
|
}
|
|
343
393
|
};
|
|
344
|
-
}
|
|
394
|
+
};
|
|
395
|
+
export const json_parse = /* @__PURE__ */ factory(), jsonc_parse = /* @__PURE__ */ factory(true);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bhsd/common",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"homepage": "https://github.com/bhsd-harry/common#readme",
|
|
5
5
|
"bugs": {
|
|
6
6
|
"url": "https://github.com/bhsd-harry/common/issues"
|
|
@@ -9,44 +9,38 @@
|
|
|
9
9
|
"author": "Bhsd",
|
|
10
10
|
"files": [
|
|
11
11
|
"/dist/*.js",
|
|
12
|
-
"/dist/index.mjs",
|
|
13
12
|
"/dist/index.d.ts"
|
|
14
13
|
],
|
|
15
|
-
"
|
|
16
|
-
".": {
|
|
17
|
-
"types": "./dist/index.d.ts",
|
|
18
|
-
"import": "./dist/index.mjs",
|
|
19
|
-
"require": "./dist/index.js"
|
|
20
|
-
}
|
|
21
|
-
},
|
|
14
|
+
"main": "./dist/index.js",
|
|
22
15
|
"types": "./dist/index.d.ts",
|
|
16
|
+
"type": "module",
|
|
23
17
|
"sideEffects": false,
|
|
24
18
|
"scripts": {
|
|
25
19
|
"prepublishOnly": "npm run build",
|
|
26
|
-
"build": "tsc
|
|
20
|
+
"build": "tsc",
|
|
27
21
|
"lint:ts": "tsc --noEmit && eslint --cache .",
|
|
28
22
|
"lint": "npm run lint:ts",
|
|
29
23
|
"test": "mocha"
|
|
30
24
|
},
|
|
31
25
|
"devDependencies": {
|
|
32
|
-
"@bhsd/code-standard": "^1.
|
|
33
|
-
"@stylistic/eslint-plugin": "^5.
|
|
26
|
+
"@bhsd/code-standard": "^2.1.1",
|
|
27
|
+
"@stylistic/eslint-plugin": "^5.10.0",
|
|
34
28
|
"@types/mocha": "^10.0.10",
|
|
35
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
36
|
-
"@typescript-eslint/parser": "^8.
|
|
37
|
-
"esbuild": "^0.
|
|
38
|
-
"eslint": "^9.39.
|
|
39
|
-
"eslint-plugin-es-x": "^9.
|
|
29
|
+
"@typescript-eslint/eslint-plugin": "^8.57.0",
|
|
30
|
+
"@typescript-eslint/parser": "^8.57.0",
|
|
31
|
+
"esbuild": "^0.27.4",
|
|
32
|
+
"eslint": "^9.39.4",
|
|
33
|
+
"eslint-plugin-es-x": "^9.5.0",
|
|
40
34
|
"eslint-plugin-eslint-comments": "^3.2.0",
|
|
41
|
-
"eslint-plugin-jsdoc": "^
|
|
42
|
-
"eslint-plugin-jsonc": "^
|
|
35
|
+
"eslint-plugin-jsdoc": "^62.7.1",
|
|
36
|
+
"eslint-plugin-jsonc": "^3.1.1",
|
|
43
37
|
"eslint-plugin-promise": "^7.2.1",
|
|
44
|
-
"eslint-plugin-regexp": "^
|
|
45
|
-
"eslint-plugin-unicorn": "^
|
|
38
|
+
"eslint-plugin-regexp": "^3.1.0",
|
|
39
|
+
"eslint-plugin-unicorn": "^63.0.0",
|
|
46
40
|
"mocha": "^11.7.5",
|
|
47
41
|
"typescript": "^5.9.3"
|
|
48
42
|
},
|
|
49
43
|
"engines": {
|
|
50
|
-
"node": ">=
|
|
44
|
+
"node": "^20.19.0 || ^22.13.0 || >=24.11.0"
|
|
51
45
|
}
|
|
52
46
|
}
|
package/dist/index.mjs
DELETED
|
@@ -1,411 +0,0 @@
|
|
|
1
|
-
// src/json_parse.ts
|
|
2
|
-
var escapee = {
|
|
3
|
-
'"': '"',
|
|
4
|
-
"\\": "\\",
|
|
5
|
-
"/": "/",
|
|
6
|
-
b: "\b",
|
|
7
|
-
f: "\f",
|
|
8
|
-
n: "\n",
|
|
9
|
-
r: "\r",
|
|
10
|
-
t: " "
|
|
11
|
-
};
|
|
12
|
-
var spaces = /* @__PURE__ */ new Set([" ", " ", "\n", "\r"]);
|
|
13
|
-
var stringify = (c) => {
|
|
14
|
-
if (c === "") {
|
|
15
|
-
return "end of input";
|
|
16
|
-
}
|
|
17
|
-
return c === '"' ? `'"'` : JSON.stringify(c);
|
|
18
|
-
};
|
|
19
|
-
var json_parse = /* @__PURE__ */ (() => {
|
|
20
|
-
let at;
|
|
21
|
-
let ch;
|
|
22
|
-
let text;
|
|
23
|
-
let warnings;
|
|
24
|
-
const prepareError = (e, from, to) => {
|
|
25
|
-
if (from === void 0) {
|
|
26
|
-
e.from = at - 1;
|
|
27
|
-
} else {
|
|
28
|
-
e.from = from;
|
|
29
|
-
e.to = to ?? at - 1;
|
|
30
|
-
}
|
|
31
|
-
};
|
|
32
|
-
const warn = (message, from, to) => {
|
|
33
|
-
const warning = {
|
|
34
|
-
message,
|
|
35
|
-
severity: "warning"
|
|
36
|
-
};
|
|
37
|
-
prepareError(warning, from, to);
|
|
38
|
-
warnings.push(warning);
|
|
39
|
-
};
|
|
40
|
-
const error = (message, from, to) => {
|
|
41
|
-
const e = {
|
|
42
|
-
warnings,
|
|
43
|
-
message,
|
|
44
|
-
severity: "error"
|
|
45
|
-
};
|
|
46
|
-
prepareError(e, from, to);
|
|
47
|
-
throw e;
|
|
48
|
-
};
|
|
49
|
-
const next = (c) => {
|
|
50
|
-
if (c && c !== ch) {
|
|
51
|
-
error(`Expected ${stringify(c)} instead of ${stringify(ch)}`);
|
|
52
|
-
}
|
|
53
|
-
ch = text.charAt(at);
|
|
54
|
-
at++;
|
|
55
|
-
return ch;
|
|
56
|
-
};
|
|
57
|
-
const number = () => {
|
|
58
|
-
let string2 = "";
|
|
59
|
-
const from = at - 1;
|
|
60
|
-
if (ch === "-") {
|
|
61
|
-
string2 = "-";
|
|
62
|
-
next();
|
|
63
|
-
}
|
|
64
|
-
if (ch === "0") {
|
|
65
|
-
string2 += ch;
|
|
66
|
-
next();
|
|
67
|
-
if (ch >= "0" && ch <= "9") {
|
|
68
|
-
error("Bad number");
|
|
69
|
-
}
|
|
70
|
-
} else if (ch >= "1" && ch <= "9") {
|
|
71
|
-
while (ch >= "0" && ch <= "9") {
|
|
72
|
-
string2 += ch;
|
|
73
|
-
next();
|
|
74
|
-
}
|
|
75
|
-
} else {
|
|
76
|
-
error("No number after minus sign");
|
|
77
|
-
}
|
|
78
|
-
if (ch !== "." && ch !== "e" && ch !== "E") {
|
|
79
|
-
const value3 = Number(string2);
|
|
80
|
-
if (!Number.isSafeInteger(value3)) {
|
|
81
|
-
warn("Not a safe integer", from);
|
|
82
|
-
}
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
if (ch === ".") {
|
|
86
|
-
string2 += ".";
|
|
87
|
-
next();
|
|
88
|
-
if (ch < "0" || ch > "9") {
|
|
89
|
-
error("Unterminated fractional number");
|
|
90
|
-
}
|
|
91
|
-
while (ch >= "0" && ch <= "9") {
|
|
92
|
-
string2 += ch;
|
|
93
|
-
next();
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
if (ch === "e" || ch === "E") {
|
|
97
|
-
string2 += ch;
|
|
98
|
-
next();
|
|
99
|
-
if (ch === "-" || ch === "+") {
|
|
100
|
-
string2 += ch;
|
|
101
|
-
next();
|
|
102
|
-
}
|
|
103
|
-
while (ch >= "0" && ch <= "9") {
|
|
104
|
-
string2 += ch;
|
|
105
|
-
next();
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
const value2 = Number(string2);
|
|
109
|
-
if (!Number.isFinite(value2)) {
|
|
110
|
-
error("Bad number");
|
|
111
|
-
}
|
|
112
|
-
};
|
|
113
|
-
const string = () => {
|
|
114
|
-
let value2 = "";
|
|
115
|
-
if (ch === '"') {
|
|
116
|
-
while (next()) {
|
|
117
|
-
if (ch === '"') {
|
|
118
|
-
next();
|
|
119
|
-
return value2;
|
|
120
|
-
}
|
|
121
|
-
const from = at - 1;
|
|
122
|
-
if (ch === "\\") {
|
|
123
|
-
next();
|
|
124
|
-
if (ch === "u") {
|
|
125
|
-
let i = 0;
|
|
126
|
-
let uffff = 0;
|
|
127
|
-
for (; i < 4; i++) {
|
|
128
|
-
const hex = parseInt(next(), 16);
|
|
129
|
-
if (!isFinite(hex)) {
|
|
130
|
-
break;
|
|
131
|
-
}
|
|
132
|
-
uffff = uffff * 16 + hex;
|
|
133
|
-
}
|
|
134
|
-
if (i < 4) {
|
|
135
|
-
error("Bad unicode escape", from);
|
|
136
|
-
}
|
|
137
|
-
value2 += String.fromCharCode(uffff);
|
|
138
|
-
} else if (typeof escapee[ch] === "string") {
|
|
139
|
-
value2 += escapee[ch];
|
|
140
|
-
} else {
|
|
141
|
-
error("Bad escaped character", from, at);
|
|
142
|
-
}
|
|
143
|
-
} else if (ch < " ") {
|
|
144
|
-
error("Bad control character", from, at);
|
|
145
|
-
} else {
|
|
146
|
-
value2 += ch;
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
} else {
|
|
150
|
-
error(`Expected '"' instead of ${JSON.stringify(ch)}`);
|
|
151
|
-
}
|
|
152
|
-
return error("Unterminated string");
|
|
153
|
-
};
|
|
154
|
-
const white = () => {
|
|
155
|
-
while (ch && spaces.has(ch)) {
|
|
156
|
-
next();
|
|
157
|
-
}
|
|
158
|
-
};
|
|
159
|
-
const word = () => {
|
|
160
|
-
switch (ch) {
|
|
161
|
-
case "t":
|
|
162
|
-
next();
|
|
163
|
-
next("r");
|
|
164
|
-
next("u");
|
|
165
|
-
next("e");
|
|
166
|
-
return;
|
|
167
|
-
case "f":
|
|
168
|
-
next();
|
|
169
|
-
next("a");
|
|
170
|
-
next("l");
|
|
171
|
-
next("s");
|
|
172
|
-
next("e");
|
|
173
|
-
return;
|
|
174
|
-
case "n":
|
|
175
|
-
next();
|
|
176
|
-
next("u");
|
|
177
|
-
next("l");
|
|
178
|
-
next("l");
|
|
179
|
-
return;
|
|
180
|
-
default:
|
|
181
|
-
error(`Unexpected ${JSON.stringify(ch)}`);
|
|
182
|
-
}
|
|
183
|
-
};
|
|
184
|
-
const array = () => {
|
|
185
|
-
next();
|
|
186
|
-
white();
|
|
187
|
-
if (ch === "]") {
|
|
188
|
-
next();
|
|
189
|
-
return;
|
|
190
|
-
}
|
|
191
|
-
let from;
|
|
192
|
-
while (ch) {
|
|
193
|
-
if (ch === "]") {
|
|
194
|
-
error("Trailing comma in array", from, from + 1);
|
|
195
|
-
}
|
|
196
|
-
value();
|
|
197
|
-
white();
|
|
198
|
-
if (ch === "]") {
|
|
199
|
-
next();
|
|
200
|
-
return;
|
|
201
|
-
} else if (ch === ",") {
|
|
202
|
-
from = at - 1;
|
|
203
|
-
next();
|
|
204
|
-
white();
|
|
205
|
-
} else {
|
|
206
|
-
error(`Expected "," or "]" instead of ${stringify(ch)}`);
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
error("Unterminated array");
|
|
210
|
-
};
|
|
211
|
-
const object = () => {
|
|
212
|
-
const keys = /* @__PURE__ */ new Set();
|
|
213
|
-
next();
|
|
214
|
-
white();
|
|
215
|
-
if (ch === "}") {
|
|
216
|
-
next();
|
|
217
|
-
return;
|
|
218
|
-
}
|
|
219
|
-
let from;
|
|
220
|
-
while (ch) {
|
|
221
|
-
if (ch === "}") {
|
|
222
|
-
error("Trailing comma in object", from, from + 1);
|
|
223
|
-
}
|
|
224
|
-
from = at;
|
|
225
|
-
const key = string();
|
|
226
|
-
const to = at - 2;
|
|
227
|
-
white();
|
|
228
|
-
next(":");
|
|
229
|
-
if (keys.has(key)) {
|
|
230
|
-
warn(`Duplicate key ${stringify(key)}`, from, to);
|
|
231
|
-
} else {
|
|
232
|
-
keys.add(key);
|
|
233
|
-
}
|
|
234
|
-
value();
|
|
235
|
-
white();
|
|
236
|
-
if (ch === "}") {
|
|
237
|
-
next();
|
|
238
|
-
return;
|
|
239
|
-
} else if (ch === ",") {
|
|
240
|
-
from = at - 1;
|
|
241
|
-
next();
|
|
242
|
-
white();
|
|
243
|
-
} else {
|
|
244
|
-
error(`Expected "," or "}" instead of ${stringify(ch)}`);
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
error(`Expected '"'`);
|
|
248
|
-
};
|
|
249
|
-
const value = () => {
|
|
250
|
-
white();
|
|
251
|
-
switch (ch) {
|
|
252
|
-
case "{":
|
|
253
|
-
return object();
|
|
254
|
-
case "[":
|
|
255
|
-
return array();
|
|
256
|
-
case '"':
|
|
257
|
-
return string();
|
|
258
|
-
case "-":
|
|
259
|
-
return number();
|
|
260
|
-
default:
|
|
261
|
-
return ch >= "0" && ch <= "9" ? number() : word();
|
|
262
|
-
}
|
|
263
|
-
};
|
|
264
|
-
return (source) => {
|
|
265
|
-
text = source;
|
|
266
|
-
warnings = [];
|
|
267
|
-
at = 0;
|
|
268
|
-
ch = " ";
|
|
269
|
-
value();
|
|
270
|
-
white();
|
|
271
|
-
if (ch) {
|
|
272
|
-
error("Syntax error");
|
|
273
|
-
} else if (warnings.length > 0) {
|
|
274
|
-
throw { warnings };
|
|
275
|
-
}
|
|
276
|
-
};
|
|
277
|
-
})();
|
|
278
|
-
|
|
279
|
-
// src/index.ts
|
|
280
|
-
var wmf = "wiktionary|wiki(?:pedia|books|news|quote|source|versity|voyage)";
|
|
281
|
-
var rawurldecode = (str) => decodeURIComponent(str.replace(/%(?![\da-f]{2})/giu, "%25"));
|
|
282
|
-
var numToHex = (d) => Math.round(d * 255).toString(16).padStart(2, "0");
|
|
283
|
-
var regex = /* @__PURE__ */ (() => {
|
|
284
|
-
const hexColor = String.raw`#(?:[\da-f]{3,4}|(?:[\da-f]{2}){3,4})(?![\p{L}\p{N}_])`, rgbValue = String.raw`(?:\d*\.)?\d+%?`, hue = String.raw`(?:\d*\.)?\d+(?:deg|grad|rad|turn)?`, rgbColor = String.raw`rgba?\(\s*(?:${String.raw`${new Array(3).fill(rgbValue).join(String.raw`\s+`)}(?:\s*\/\s*${rgbValue})?`}|${String.raw`${new Array(3).fill(rgbValue).join(String.raw`\s*,\s*`)}(?:\s*,\s*${rgbValue})?`})\s*\)`, hslColor = String.raw`hsla?\(\s*(?:${String.raw`${hue}\s+${rgbValue}\s+${rgbValue}(?:\s*\/\s*${rgbValue})?`}|${String.raw`${hue}${String.raw`\s*,\s*(?:\d*\.)?\d+%`.repeat(2)}(?:\s*,\s*${rgbValue})?`})\s*\)`;
|
|
285
|
-
return {
|
|
286
|
-
full: new RegExp(String.raw`(^|[^\p{L}\p{N}_])(${hexColor}|${rgbColor}|${hslColor})`, "giu"),
|
|
287
|
-
rgb: new RegExp(String.raw`(^|[^\p{L}\p{N}_])(${hexColor}|${rgbColor})`, "giu")
|
|
288
|
-
};
|
|
289
|
-
})();
|
|
290
|
-
var splitColors = (str, hsl = true) => {
|
|
291
|
-
const pieces = [], re = regex[hsl ? "full" : "rgb"];
|
|
292
|
-
re.lastIndex = 0;
|
|
293
|
-
let mt = re.exec(str), lastIndex = 0;
|
|
294
|
-
while (mt) {
|
|
295
|
-
const index = mt.index + mt[1].length;
|
|
296
|
-
if (index > lastIndex) {
|
|
297
|
-
pieces.push([str.slice(lastIndex, index), lastIndex, index, false]);
|
|
298
|
-
}
|
|
299
|
-
({ lastIndex } = re);
|
|
300
|
-
pieces.push([mt[2], index, lastIndex, str[index - 1] !== "&" || !/^#\d+$/u.test(mt[2])]);
|
|
301
|
-
mt = re.exec(str);
|
|
302
|
-
}
|
|
303
|
-
if (str.length > lastIndex) {
|
|
304
|
-
pieces.push([str.slice(lastIndex), lastIndex, str.length, false]);
|
|
305
|
-
}
|
|
306
|
-
return pieces;
|
|
307
|
-
};
|
|
308
|
-
var sanitizeInlineStyle = (style) => style.replace(/[{}]/gu, (p) => p === "{" ? "{" : "}").replace(/^[\s;]+/u, (p) => p.replace(/;/gu, " "));
|
|
309
|
-
function getRegex(f) {
|
|
310
|
-
const map = /* @__PURE__ */ new Map(), weakMap = /* @__PURE__ */ new WeakMap();
|
|
311
|
-
return (s) => {
|
|
312
|
-
const regexp = typeof s === "string" ? map : weakMap;
|
|
313
|
-
if (regexp.has(s)) {
|
|
314
|
-
const re2 = regexp.get(s);
|
|
315
|
-
re2.lastIndex = 0;
|
|
316
|
-
return re2;
|
|
317
|
-
}
|
|
318
|
-
const re = f(s);
|
|
319
|
-
regexp.set(s, re);
|
|
320
|
-
return re;
|
|
321
|
-
};
|
|
322
|
-
}
|
|
323
|
-
var getObjRegex = getRegex;
|
|
324
|
-
var splitLines = (str) => {
|
|
325
|
-
const lines = [];
|
|
326
|
-
let start = 0;
|
|
327
|
-
for (const line of str.split("\n")) {
|
|
328
|
-
const end = start + line.length;
|
|
329
|
-
lines.push([line, start, end]);
|
|
330
|
-
start = end + 1;
|
|
331
|
-
}
|
|
332
|
-
return lines;
|
|
333
|
-
};
|
|
334
|
-
var mt2num = (mt) => mt && Number(mt[1]);
|
|
335
|
-
var formatJsonError = (str, errors) => {
|
|
336
|
-
let lines;
|
|
337
|
-
const offsetToPosition = (offset) => {
|
|
338
|
-
lines ??= splitLines(str);
|
|
339
|
-
const line = lines.findIndex(([, , end]) => offset <= end) + 1;
|
|
340
|
-
return {
|
|
341
|
-
line,
|
|
342
|
-
column: offset - lines[line - 1][1] + 1
|
|
343
|
-
};
|
|
344
|
-
};
|
|
345
|
-
for (const error of errors) {
|
|
346
|
-
const { line, column, from, to } = error;
|
|
347
|
-
if (from === null || from === void 0) {
|
|
348
|
-
if (line) {
|
|
349
|
-
lines ??= splitLines(str);
|
|
350
|
-
error.column ??= 1;
|
|
351
|
-
error.from = lines[line - 1][1] + (error.column - 1);
|
|
352
|
-
} else {
|
|
353
|
-
error.from = 0;
|
|
354
|
-
error.line = 1;
|
|
355
|
-
error.column = 1;
|
|
356
|
-
}
|
|
357
|
-
} else if (!line || !column) {
|
|
358
|
-
Object.assign(error, offsetToPosition(from));
|
|
359
|
-
}
|
|
360
|
-
if (to !== void 0) {
|
|
361
|
-
({ line: error.endLine, column: error.endColumn } = offsetToPosition(to));
|
|
362
|
-
}
|
|
363
|
-
error.position = error.from;
|
|
364
|
-
}
|
|
365
|
-
return errors;
|
|
366
|
-
};
|
|
367
|
-
var lintJSONNative = (str, force) => {
|
|
368
|
-
if (force || str.trim()) {
|
|
369
|
-
try {
|
|
370
|
-
JSON.parse(str);
|
|
371
|
-
} catch (e) {
|
|
372
|
-
const { message } = e, line = mt2num(/\bline (\d+)/u.exec(message)), column = mt2num(/\bcolumn (\d+)/u.exec(message)), from = mt2num(/\bposition (\d+)/u.exec(message));
|
|
373
|
-
return formatJsonError(str, [{ message, line, column, from, severity: "error" }]);
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
return [];
|
|
377
|
-
};
|
|
378
|
-
var lintJSON = (str) => {
|
|
379
|
-
if (!str.trim()) {
|
|
380
|
-
return [];
|
|
381
|
-
}
|
|
382
|
-
let errors;
|
|
383
|
-
try {
|
|
384
|
-
json_parse(str);
|
|
385
|
-
} catch (e) {
|
|
386
|
-
if (!(e instanceof Error)) {
|
|
387
|
-
const { warnings, ...error } = e;
|
|
388
|
-
if (error.message) {
|
|
389
|
-
warnings.push(error);
|
|
390
|
-
}
|
|
391
|
-
errors = formatJsonError(str, warnings);
|
|
392
|
-
if (error.message) {
|
|
393
|
-
return errors;
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
const nativeErrors = lintJSONNative(str);
|
|
398
|
-
return errors ? [...nativeErrors, ...errors] : nativeErrors;
|
|
399
|
-
};
|
|
400
|
-
export {
|
|
401
|
-
getObjRegex,
|
|
402
|
-
getRegex,
|
|
403
|
-
lintJSON,
|
|
404
|
-
lintJSONNative,
|
|
405
|
-
numToHex,
|
|
406
|
-
rawurldecode,
|
|
407
|
-
sanitizeInlineStyle,
|
|
408
|
-
splitColors,
|
|
409
|
-
splitLines,
|
|
410
|
-
wmf
|
|
411
|
-
};
|