gyojeong 0.2.0 → 0.3.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/NOTICE +3 -0
- package/README.md +43 -7
- package/apps/review-web/dist/assets/{feedback-contract-CMrinGBH.js → feedback-contract-_524rCEj.js} +1 -1
- package/apps/review-web/dist/assets/feedback-wrapper-BPcSoKgo.js +3 -0
- package/apps/review-web/dist/assets/feedback-wrapper-gbapxzQa.css +1 -0
- package/apps/review-web/dist/assets/{index-DOaH7bry.css → index-CxnczdwI.css} +1 -1
- package/apps/review-web/dist/assets/index-DlzIyqhR.js +25 -0
- package/apps/review-web/dist/feedback-wrapper.html +3 -3
- package/apps/review-web/dist/index.html +3 -3
- package/bin/gyojeong.mjs +2 -1
- package/package.json +1 -1
- package/scripts/check.mjs +168 -29
- package/scripts/review-cli.mjs +1248 -136
- package/apps/review-web/dist/assets/feedback-wrapper-Bhgs7aQS.js +0 -3
- package/apps/review-web/dist/assets/feedback-wrapper-DWKFHwo5.css +0 -1
- package/apps/review-web/dist/assets/index-CY49dpth.js +0 -17
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
<meta charset="utf-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
6
|
<title>원본 문서 피드백</title>
|
|
7
|
-
<script type="module" crossorigin src="./assets/feedback-wrapper-
|
|
8
|
-
<link rel="modulepreload" crossorigin href="./assets/feedback-contract-
|
|
9
|
-
<link rel="stylesheet" crossorigin href="./assets/feedback-wrapper-
|
|
7
|
+
<script type="module" crossorigin src="./assets/feedback-wrapper-BPcSoKgo.js"></script>
|
|
8
|
+
<link rel="modulepreload" crossorigin href="./assets/feedback-contract-_524rCEj.js">
|
|
9
|
+
<link rel="stylesheet" crossorigin href="./assets/feedback-wrapper-gbapxzQa.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
12
12
|
<iframe id="source" title="검수할 원본 페이지"></iframe>
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
<meta charset="utf-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
6
|
<title>번역 검토</title>
|
|
7
|
-
<script type="module" crossorigin src="./assets/index-
|
|
8
|
-
<link rel="modulepreload" crossorigin href="./assets/feedback-contract-
|
|
9
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
7
|
+
<script type="module" crossorigin src="./assets/index-DlzIyqhR.js"></script>
|
|
8
|
+
<link rel="modulepreload" crossorigin href="./assets/feedback-contract-_524rCEj.js">
|
|
9
|
+
<link rel="stylesheet" crossorigin href="./assets/index-CxnczdwI.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
12
12
|
<main id="app" aria-live="polite"></main>
|
package/bin/gyojeong.mjs
CHANGED
|
@@ -16,6 +16,7 @@ const COMMANDS = {
|
|
|
16
16
|
url: ['review-cli.mjs', 'Print a review link, starting the server if it stopped', true],
|
|
17
17
|
list: ['review-cli.mjs', 'List open reviews (older than 14 days are marked stale)', true],
|
|
18
18
|
discard: ['review-cli.mjs', 'Delete a review without finishing it in the browser', true],
|
|
19
|
+
rules: ['review-cli.mjs', 'Sync/list rules; --compact true returns the writing rulebook only', true],
|
|
19
20
|
serve: ['review-server.mjs', 'Run the review server in the foreground (default http://127.0.0.1:8377)'],
|
|
20
21
|
};
|
|
21
22
|
|
|
@@ -32,7 +33,7 @@ if (!command || command === '--help' || command === '-h' || !COMMANDS[command])
|
|
|
32
33
|
const out = [`gyojeong ${packageJson.version}`, '', 'Usage: gyojeong <command> [options]', '', ...lines].join('\n');
|
|
33
34
|
if (command && !COMMANDS[command] && command !== '--help' && command !== '-h') {
|
|
34
35
|
console.error(`Unknown command: ${command}\n\n${out}`);
|
|
35
|
-
process.exit(
|
|
36
|
+
process.exit(64);
|
|
36
37
|
}
|
|
37
38
|
console.log(out);
|
|
38
39
|
process.exit(0);
|
package/package.json
CHANGED
package/scripts/check.mjs
CHANGED
|
@@ -79,10 +79,107 @@ function trimUrl(url) {
|
|
|
79
79
|
function maskCode(text) {
|
|
80
80
|
return text.replace(CODE_SPAN_RE, " ");
|
|
81
81
|
}
|
|
82
|
-
|
|
82
|
+
var HASH_COMMENT_LANGUAGES = /* @__PURE__ */ new Set([
|
|
83
|
+
"bash",
|
|
84
|
+
"dockerfile",
|
|
85
|
+
"make",
|
|
86
|
+
"makefile",
|
|
87
|
+
"perl",
|
|
88
|
+
"php",
|
|
89
|
+
"pl",
|
|
90
|
+
"powershell",
|
|
91
|
+
"ps1",
|
|
92
|
+
"py",
|
|
93
|
+
"python",
|
|
94
|
+
"r",
|
|
95
|
+
"rb",
|
|
96
|
+
"ruby",
|
|
97
|
+
"sh",
|
|
98
|
+
"shell",
|
|
99
|
+
"toml",
|
|
100
|
+
"yaml",
|
|
101
|
+
"yml",
|
|
102
|
+
"zsh"
|
|
103
|
+
]);
|
|
104
|
+
var SHELL_COMMENT_LANGUAGES = /* @__PURE__ */ new Set(["bash", "sh", "shell", "zsh"]);
|
|
105
|
+
var WHITESPACE_HASH_COMMENT_LANGUAGES = /* @__PURE__ */ new Set(["yaml", "yml"]);
|
|
106
|
+
var ANYWHERE_HASH_COMMENT_LANGUAGES = /* @__PURE__ */ new Set([
|
|
107
|
+
"perl",
|
|
108
|
+
"php",
|
|
109
|
+
"pl",
|
|
110
|
+
"powershell",
|
|
111
|
+
"ps1",
|
|
112
|
+
"rb",
|
|
113
|
+
"ruby"
|
|
114
|
+
]);
|
|
115
|
+
var MAKE_LANGUAGES = /* @__PURE__ */ new Set(["make", "makefile"]);
|
|
116
|
+
var PHP_ATTRIBUTE_LANGUAGES = /* @__PURE__ */ new Set(["php"]);
|
|
117
|
+
var LINE_HASH_COMMENT_LANGUAGES = /* @__PURE__ */ new Set(["dockerfile"]);
|
|
118
|
+
var SLASH_COMMENT_LANGUAGES = /* @__PURE__ */ new Set([
|
|
119
|
+
"c",
|
|
120
|
+
"c++",
|
|
121
|
+
"cc",
|
|
122
|
+
"cpp",
|
|
123
|
+
"cs",
|
|
124
|
+
"csharp",
|
|
125
|
+
"cxx",
|
|
126
|
+
"go",
|
|
127
|
+
"h",
|
|
128
|
+
"hpp",
|
|
129
|
+
"java",
|
|
130
|
+
"javascript",
|
|
131
|
+
"js",
|
|
132
|
+
"jsonc",
|
|
133
|
+
"jsx",
|
|
134
|
+
"kotlin",
|
|
135
|
+
"kt",
|
|
136
|
+
"less",
|
|
137
|
+
"php",
|
|
138
|
+
"rs",
|
|
139
|
+
"rust",
|
|
140
|
+
"scala",
|
|
141
|
+
"scss",
|
|
142
|
+
"swift",
|
|
143
|
+
"ts",
|
|
144
|
+
"tsx",
|
|
145
|
+
"typescript"
|
|
146
|
+
]);
|
|
147
|
+
var C_STYLE_BLOCK_COMMENT_LANGUAGES = /* @__PURE__ */ new Set([...SLASH_COMMENT_LANGUAGES, "css"]);
|
|
148
|
+
var HTML_COMMENT_LANGUAGES = /* @__PURE__ */ new Set(["html", "markdown", "md", "svelte", "svg", "vue", "xml"]);
|
|
149
|
+
var PAIRED_DELIMITERS = /* @__PURE__ */ new Map([["(", ")"], ["{", "}"], ["[", "]"], ["<", ">"]]);
|
|
150
|
+
var delimitedLiteralStart = (rest, previous, language) => {
|
|
151
|
+
if (language === "ruby" || language === "rb") {
|
|
152
|
+
return rest.match(/^%(?:[qQrwWixI])?([^\w\s])/u);
|
|
153
|
+
}
|
|
154
|
+
if ((language === "perl" || language === "pl") && !/[\w$@%]/u.test(previous)) {
|
|
155
|
+
return rest.match(/^(?:qq|qw|qx|qr|q)([^\w\s])/u);
|
|
156
|
+
}
|
|
157
|
+
return null;
|
|
158
|
+
};
|
|
159
|
+
var slashLiteralStart = (text, index, language) => {
|
|
160
|
+
if (!["perl", "pl", "rb", "ruby"].includes(language) || text[index] !== "/") return false;
|
|
161
|
+
const beforeText = text.slice(0, index);
|
|
162
|
+
const before = beforeText.match(/\S\s*$/u)?.[0].trim() ?? "";
|
|
163
|
+
if (before === "" || /[=(:,!\[\{;~]/u.test(before.at(-1) ?? "")) return true;
|
|
164
|
+
const word = beforeText.match(/([A-Za-z]+)\s*$/u)?.[1]?.toLowerCase();
|
|
165
|
+
if (["rb", "ruby"].includes(language)) {
|
|
166
|
+
return ["and", "if", "not", "or", "return", "then", "unless", "when", "while"].includes(word ?? "");
|
|
167
|
+
}
|
|
168
|
+
return ["m", "qr", "s"].includes(word ?? "");
|
|
169
|
+
};
|
|
170
|
+
function stripComments(text, language = "") {
|
|
171
|
+
const normalizedLanguage = language.toLowerCase();
|
|
172
|
+
const hashComments = HASH_COMMENT_LANGUAGES.has(normalizedLanguage);
|
|
173
|
+
const slashComments = SLASH_COMMENT_LANGUAGES.has(normalizedLanguage);
|
|
174
|
+
const cStyleBlockComments = C_STYLE_BLOCK_COMMENT_LANGUAGES.has(normalizedLanguage);
|
|
175
|
+
const htmlComments = HTML_COMMENT_LANGUAGES.has(normalizedLanguage);
|
|
176
|
+
const knownLanguage = hashComments || slashComments || cStyleBlockComments || htmlComments;
|
|
83
177
|
let out = "";
|
|
84
178
|
let quote = null;
|
|
179
|
+
let quoteOpen = null;
|
|
180
|
+
let quoteDepth = 0;
|
|
85
181
|
let block = null;
|
|
182
|
+
let lineStart = 0;
|
|
86
183
|
for (let i = 0; i < text.length; i += 1) {
|
|
87
184
|
const rest = text.slice(i);
|
|
88
185
|
if (block) {
|
|
@@ -90,48 +187,92 @@ function stripComments(text) {
|
|
|
90
187
|
i += block.length - 1;
|
|
91
188
|
block = null;
|
|
92
189
|
}
|
|
190
|
+
if (text[i] === "\n") {
|
|
191
|
+
lineStart = i + 1;
|
|
192
|
+
}
|
|
93
193
|
continue;
|
|
94
194
|
}
|
|
95
195
|
const char = text[i];
|
|
196
|
+
const atLineStart = /^\s*$/.test(text.slice(lineStart, i));
|
|
197
|
+
const genericSlashComment = !knownLanguage && atLineStart && rest.startsWith("//");
|
|
198
|
+
const genericHashComment = !knownLanguage && atLineStart && char === "#" && !rest.startsWith("#!") && !/^#[\w-]+\s*\{/u.test(rest);
|
|
199
|
+
const genericCStyleBlockComment = !knownLanguage && atLineStart && rest.startsWith("/*");
|
|
200
|
+
const genericHtmlComment = !knownLanguage && atLineStart && rest.startsWith("<!--");
|
|
201
|
+
const previous = text[i - 1] ?? "";
|
|
202
|
+
const makeRecipe = MAKE_LANGUAGES.has(normalizedLanguage) && text[lineStart] === " ";
|
|
203
|
+
const shellHashComment = (SHELL_COMMENT_LANGUAGES.has(normalizedLanguage) || makeRecipe) && char === "#" && (i === 0 || /[\s;&|()<>]/u.test(previous));
|
|
204
|
+
const whitespaceHashComment = WHITESPACE_HASH_COMMENT_LANGUAGES.has(normalizedLanguage) && char === "#" && (i === 0 || /\s/u.test(previous)) && !(PHP_ATTRIBUTE_LANGUAGES.has(normalizedLanguage) && rest.startsWith("#["));
|
|
205
|
+
const lineHashComment = LINE_HASH_COMMENT_LANGUAGES.has(normalizedLanguage) && char === "#" && atLineStart;
|
|
206
|
+
const anywhereHashComment = ANYWHERE_HASH_COMMENT_LANGUAGES.has(normalizedLanguage) && char === "#" && !(PHP_ATTRIBUTE_LANGUAGES.has(normalizedLanguage) && rest.startsWith("#["));
|
|
207
|
+
const makeHashComment = MAKE_LANGUAGES.has(normalizedLanguage) && char === "#" && (makeRecipe ? shellHashComment : true);
|
|
208
|
+
const languageHashComment = hashComments && char === "#" && (SHELL_COMMENT_LANGUAGES.has(normalizedLanguage) || makeRecipe ? shellHashComment : WHITESPACE_HASH_COMMENT_LANGUAGES.has(normalizedLanguage) ? whitespaceHashComment : LINE_HASH_COMMENT_LANGUAGES.has(normalizedLanguage) ? lineHashComment : MAKE_LANGUAGES.has(normalizedLanguage) ? makeHashComment : anywhereHashComment);
|
|
96
209
|
if (quote) {
|
|
97
210
|
out += char;
|
|
98
211
|
if (char === "\\") {
|
|
99
212
|
out += text[i + 1] ?? "";
|
|
100
213
|
i += 1;
|
|
214
|
+
} else if (quoteOpen && char === quoteOpen) {
|
|
215
|
+
quoteDepth += 1;
|
|
101
216
|
} else if (char === quote) {
|
|
102
|
-
|
|
217
|
+
if (quoteDepth > 0) {
|
|
218
|
+
quoteDepth -= 1;
|
|
219
|
+
} else {
|
|
220
|
+
quote = null;
|
|
221
|
+
quoteOpen = null;
|
|
222
|
+
}
|
|
103
223
|
}
|
|
104
224
|
continue;
|
|
105
225
|
}
|
|
226
|
+
const delimitedLiteral = delimitedLiteralStart(rest, previous, normalizedLanguage);
|
|
227
|
+
if (delimitedLiteral) {
|
|
228
|
+
const opener = delimitedLiteral[1];
|
|
229
|
+
const token = delimitedLiteral[0];
|
|
230
|
+
quoteOpen = PAIRED_DELIMITERS.has(opener) ? opener : null;
|
|
231
|
+
quote = PAIRED_DELIMITERS.get(opener) ?? opener;
|
|
232
|
+
quoteDepth = 0;
|
|
233
|
+
out += token;
|
|
234
|
+
i += token.length - 1;
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
106
237
|
if (char === '"' || char === "'" || char === "`") {
|
|
107
238
|
quote = char;
|
|
108
239
|
out += char;
|
|
109
240
|
continue;
|
|
110
241
|
}
|
|
111
|
-
if (
|
|
242
|
+
if (slashLiteralStart(text, i, normalizedLanguage)) {
|
|
243
|
+
quote = "/";
|
|
244
|
+
out += char;
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
if (cStyleBlockComments && rest.startsWith("/*") || genericCStyleBlockComment) {
|
|
112
248
|
block = "*/";
|
|
113
249
|
continue;
|
|
114
250
|
}
|
|
115
|
-
if (rest.startsWith("<!--")) {
|
|
251
|
+
if (htmlComments && rest.startsWith("<!--") || genericHtmlComment) {
|
|
116
252
|
block = "-->";
|
|
117
253
|
continue;
|
|
118
254
|
}
|
|
119
|
-
if (rest.startsWith("//") ||
|
|
255
|
+
if (slashComments && rest.startsWith("//") || languageHashComment || genericSlashComment || genericHashComment) {
|
|
120
256
|
const end = text.indexOf("\n", i);
|
|
121
257
|
if (end === -1) break;
|
|
122
258
|
i = end - 1;
|
|
259
|
+
lineStart = end;
|
|
123
260
|
continue;
|
|
124
261
|
}
|
|
125
262
|
out += char;
|
|
263
|
+
if (char === "\n") {
|
|
264
|
+
lineStart = i + 1;
|
|
265
|
+
}
|
|
126
266
|
}
|
|
127
267
|
return out;
|
|
128
268
|
}
|
|
129
269
|
function normalizeCodeBlock(text) {
|
|
130
270
|
const raw = text.split("\n");
|
|
131
271
|
const open = raw[0] ?? "";
|
|
272
|
+
const language = open.match(/^\s*(?:`{3,}|~{3,})\s*([^\s{]+)/)?.[1] ?? "";
|
|
132
273
|
const closes = raw.length > 1 && /^\s*(`{3,}|~{3,})\s*$/.test(raw[raw.length - 1] ?? "");
|
|
133
274
|
const body = raw.slice(1, closes ? -1 : void 0).join("\n");
|
|
134
|
-
const lines = [open, ...stripComments(body).split("\n")];
|
|
275
|
+
const lines = [open, ...stripComments(body, language).split("\n")];
|
|
135
276
|
const indent = lines[0].match(/^\s*/)[0].length;
|
|
136
277
|
return lines.map((line) => line.slice(Math.min(indent, line.match(/^\s*/)[0].length))).map((line) => line.replace(/\s+$/, "")).filter((line) => line.trim() !== "").join("\n");
|
|
137
278
|
}
|
|
@@ -246,25 +387,18 @@ var ENGLISH_NUMBER_WORDS = {
|
|
|
246
387
|
triple: 3,
|
|
247
388
|
both: 2,
|
|
248
389
|
dozen: 12,
|
|
249
|
-
half: 50
|
|
250
|
-
hex: 16,
|
|
251
|
-
hexadecimal: 16,
|
|
252
|
-
octal: 8,
|
|
253
|
-
binary: 2,
|
|
254
|
-
decimal: 10,
|
|
255
|
-
january: 1,
|
|
256
|
-
february: 2,
|
|
257
|
-
march: 3,
|
|
258
|
-
april: 4,
|
|
259
|
-
may: 5,
|
|
260
|
-
june: 6,
|
|
261
|
-
july: 7,
|
|
262
|
-
august: 8,
|
|
263
|
-
september: 9,
|
|
264
|
-
october: 10,
|
|
265
|
-
november: 11,
|
|
266
|
-
december: 12
|
|
390
|
+
half: 50
|
|
267
391
|
};
|
|
392
|
+
var MONTHS = { january: 1, february: 2, march: 3, april: 4, may: 5, june: 6, july: 7, august: 8, september: 9, october: 10, november: 11, december: 12 };
|
|
393
|
+
var MONTH_DATE_RE = new RegExp(`\\b(${Object.keys(MONTHS).join("|")})\\s+\\d|\\d\\s+(${Object.keys(MONTHS).join("|")})\\b`, "g");
|
|
394
|
+
var SECOND_UNIT_RE = /\b(?:\d+(?:\.\d+)?|a|an|one|per|each|every)\s+second\b|\bseconds\b/g;
|
|
395
|
+
var KOREAN_BASE_RE = /(\d+)\s*진/g;
|
|
396
|
+
var ENGLISH_BASES = { hex: 16, hexadecimal: 16, octal: 8, binary: 2, decimal: 10 };
|
|
397
|
+
var ENGLISH_BASE_RE = new RegExp(`\\b(${Object.keys(ENGLISH_BASES).join("|")})\\b`, "g");
|
|
398
|
+
function sourceBases(prose, language) {
|
|
399
|
+
if (language === "en") return new Set([...prose.toLowerCase().matchAll(ENGLISH_BASE_RE)].map((m) => String(ENGLISH_BASES[m[1]])));
|
|
400
|
+
return new Set([...prose.matchAll(KOREAN_BASE_RE)].map((m) => normalizeNumber(m[1])));
|
|
401
|
+
}
|
|
268
402
|
var KOREAN_NUMBER_WORDS = { \uD55C: 1, \uD558\uB098: 1, \uB450: 2, \uB458: 2, \uC138: 3, \uC14B: 3, \uB124: 4, \uB137: 4, \uB2E4\uC12F: 5, \uC5EC\uC12F: 6, \uC77C\uACF1: 7, \uC5EC\uB35F: 8, \uC544\uD649: 9, \uC5F4: 10 };
|
|
269
403
|
var KOREAN_NUMERAL = "\uD55C|\uD558\uB098|\uB450|\uB458|\uC138|\uC14B|\uB124|\uB137|\uB2E4\uC12F|\uC5EC\uC12F|\uC77C\uACF1|\uC5EC\uB35F|\uC544\uD649|\uC5F4";
|
|
270
404
|
var KOREAN_COUNTER = "\uAC1C|\uBC88|\uAC00\uC9C0|\uBA85|\uB300|\uC904|\uB2E8\uACC4|\uBC30|\uC2DC\uAC04|\uBD84|\uCD08|\uC77C|\uC8FC|\uB2EC|\uACF3|\uCABD|\uC7A5|\uCE78";
|
|
@@ -289,7 +423,9 @@ function digitNumbers(prose) {
|
|
|
289
423
|
function justifiedNumbers(prose, language) {
|
|
290
424
|
const out = /* @__PURE__ */ new Set();
|
|
291
425
|
if (language === "en") {
|
|
292
|
-
|
|
426
|
+
const lower = prose.toLowerCase();
|
|
427
|
+
for (const m of lower.matchAll(MONTH_DATE_RE)) out.add(String(MONTHS[m[1] ?? m[2]]));
|
|
428
|
+
for (const m of lower.replace(SECOND_UNIT_RE, " ").matchAll(/\b[a-z]+\b/g)) {
|
|
293
429
|
if (Object.hasOwn(ENGLISH_NUMBER_WORDS, m[0])) out.add(String(ENGLISH_NUMBER_WORDS[m[0]]));
|
|
294
430
|
}
|
|
295
431
|
if (/\bnon-?negative\b|\bzero-based\b/i.test(prose)) out.add("0");
|
|
@@ -304,14 +440,17 @@ function justifiedNumbers(prose, language) {
|
|
|
304
440
|
}
|
|
305
441
|
function checkNumbers(sourceBlocks, draftBlocks, sourceLanguage, add) {
|
|
306
442
|
const sourceProse = numberProse(sourceBlocks);
|
|
307
|
-
const
|
|
443
|
+
const draftText = numberProse(draftBlocks);
|
|
444
|
+
const bases = sourceBases(sourceProse, sourceLanguage);
|
|
445
|
+
const draftBases = new Set([...draftText.matchAll(KOREAN_BASE_RE)].map((m) => normalizeNumber(m[1])));
|
|
446
|
+
const draftProse = draftText.replace(KOREAN_BASE_RE, " ");
|
|
308
447
|
const sourceDigits = digitNumbers(sourceProse);
|
|
309
448
|
const draftDigits = digitNumbers(draftProse);
|
|
310
449
|
const justified = /* @__PURE__ */ new Set([...sourceDigits, ...justifiedNumbers(sourceProse, sourceLanguage)]);
|
|
311
450
|
const draftWords = justifiedNumbers(draftProse, "ko");
|
|
312
|
-
const draftAll = /* @__PURE__ */ new Set([...draftDigits, ...draftWords]);
|
|
451
|
+
const draftAll = /* @__PURE__ */ new Set([...draftDigits, ...draftWords, ...draftBases]);
|
|
313
452
|
const addedWords = [...draftWords].filter((n) => Number(n) >= 3);
|
|
314
|
-
for (const n of [...draftDigits, ...addedWords]) {
|
|
453
|
+
for (const n of [...draftDigits, ...addedWords, ...[...draftBases].filter((b) => !bases.has(b))]) {
|
|
315
454
|
if (!justified.has(n)) add("fail", "number", `\uC6D0\uBB38\uC5D0 \uC5C6\uB294 \uC22B\uC790\uAC00 \uC0DD\uACBC\uC2B5\uB2C8\uB2E4: ${n}`, { token: n });
|
|
316
455
|
}
|
|
317
456
|
for (const n of sourceDigits) {
|
|
@@ -322,7 +461,7 @@ var EN_WEAK_PROHIBITION = [/\bavoid(?:s|ing)?\b/i, /\b(?:forbid|forbids|disallow
|
|
|
322
461
|
var EN_PERMISSION = /\b(?:may|allowed|permitted|optional|optionally|free to|fine|okay|ok|need not|needn't|not required|no need|(?:do|does)n't need|(?:do|does) not need|(?:do|does)n't have to|(?:do|does) not have to|acceptable)\b/i;
|
|
323
462
|
var EN = {
|
|
324
463
|
prohibition: [
|
|
325
|
-
/(?:^|[
|
|
464
|
+
/(?:^|[.!?:;]\s+|\n\s*(?:[-*+]|\d+[.)])?\s*|\*\*|>\s*)(?:do not|don't|never|avoid)\b(?!\s+(?:need|have to|require))/i,
|
|
326
465
|
// "should not", and "should, however, not"
|
|
327
466
|
/\b(?:must|shall|should)(?:\s+not|n't|,[^,.;!?\n]{1,25},\s+not)\b/i,
|
|
328
467
|
/\b(?:is|are|isn't|aren't)\s+not\s+(?:allowed|permitted)\b/i,
|