@yuu1111/comment-check 2.0.0 → 2.1.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/README.ja.md CHANGED
@@ -24,6 +24,12 @@ src/queue.ts:18:2 undocumented-directive TypeScript directive needs a descriptio
24
24
  Checked 42 files: 1 new, 0 resolved, 3 baselined
25
25
  ```
26
26
 
27
+ 日本語の文末の `。` も止めるProjectはopt-inのruleを指定する
28
+
29
+ ```bash
30
+ comment-check --enable japanese-period .
31
+ ```
32
+
27
33
  ## Rules
28
34
 
29
35
  | Rule | 検出対象 |
@@ -32,12 +38,14 @@ Checked 42 files: 1 new, 0 resolved, 3 baselined
32
38
  | `undocumented-directive` | 説明の無い `@ts-ignore` と `@ts-expect-error` |
33
39
  | `placeholder-comment` | `TODO`、`FIXME`、`XXX`、`HACK` |
34
40
  | `separator-comment` | 記号だけで作った装飾comment |
41
+ | `japanese-period` | 日本語の文を終える `。` を含むcomment(opt-in) |
35
42
 
36
43
  ## Options
37
44
 
38
45
  | Option | Description |
39
46
  |--------|-------------|
40
47
  | `--baseline <path>` | 読み書きするbaseline file(既定は `comment-baseline.json`) |
48
+ | `--enable <rule>` | opt-in ruleを実行する 複数指定できる 未知の名前は設定error |
41
49
  | `--ignore <path>` | 検査から外すpath 複数指定できる |
42
50
  | `--update-baseline` | baselineを現在の検出で置き換える |
43
51
  | `--json` | 新規と解消済みの検出をJSONで出力する |
@@ -47,3 +55,5 @@ Checked 42 files: 1 new, 0 resolved, 3 baselined
47
55
  生成物のディレクトリなどProjectが持つpathは `--ignore` で検査から外す 例えば `--ignore src/generated`
48
56
 
49
57
  baselineはrule、file、comment本文をキーにするため、行が動いてもそのcommentを新規とは報告しない Biomeは `biome-ignore` の理由と未使用の抑制を既に扱うため、このcheckerはBiomeが読まないcommentの細部だけを担当する
58
+
59
+ `japanese-period` は `--enable` で指定するまで動かないため、既存Projectの検出結果は変わらない 最初の `。` の位置を行と桁で報告し、句点が複数あっても1 commentにつき1件にまとめ、comment本文は書き換えない
package/README.md CHANGED
@@ -25,6 +25,13 @@ src/queue.ts:18:2 undocumented-directive TypeScript directive needs a descriptio
25
25
  Checked 42 files: 1 new, 0 resolved, 3 baselined
26
26
  ```
27
27
 
28
+ A project that also keeps Japanese sentences free of a trailing `。` names the
29
+ opt-in rule:
30
+
31
+ ```bash
32
+ comment-check --enable japanese-period .
33
+ ```
34
+
28
35
  ## Rules
29
36
 
30
37
  | Rule | Detects |
@@ -33,12 +40,14 @@ Checked 42 files: 1 new, 0 resolved, 3 baselined
33
40
  | `undocumented-directive` | `@ts-ignore` or `@ts-expect-error` without a description |
34
41
  | `placeholder-comment` | `TODO`, `FIXME`, `XXX`, `HACK` |
35
42
  | `separator-comment` | decorative comments made only of punctuation |
43
+ | `japanese-period` | a Japanese sentence in a comment that ends with `。` (opt-in) |
36
44
 
37
45
  ## Options
38
46
 
39
47
  | Option | Description |
40
48
  |--------|-------------|
41
49
  | `--baseline <path>` | Baseline file to read or write (default `comment-baseline.json`) |
50
+ | `--enable <rule>` | Run an opt-in rule, repeatable; an unknown name is a configuration error |
42
51
  | `--ignore <path>` | Path to leave out, repeatable |
43
52
  | `--update-baseline` | Replace the baseline with the current findings |
44
53
  | `--json` | Print new and resolved findings as JSON |
@@ -52,3 +61,8 @@ The baseline keys on the rule, the file, and the comment text, so moving a line
52
61
  does not report the comment as new. Biome already requires a reason on
53
62
  `biome-ignore` and reports unused suppressions, so this checker only covers the
54
63
  comment trivia that Biome does not read.
64
+
65
+ `japanese-period` stays off until `--enable` names it, so an existing project
66
+ keeps the findings it had. The rule reports the first `。` of a comment at its
67
+ own line and column, reports one finding per comment however many periods it
68
+ holds, and never rewrites the comment.
package/dist/cli.js CHANGED
@@ -286,9 +286,27 @@ function extractComments(source) {
286
286
  }
287
287
 
288
288
  // src/rules.ts
289
+ var OPT_IN_RULE_IDS = ["japanese-period"];
289
290
  var PLACEHOLDER_PATTERN = /\b(TODO|FIXME|XXX|HACK)\b/;
290
291
  var SEPARATOR_PATTERN = /^[-=*_#~+./\\|]{4,}$/;
291
292
  var DIRECTIVE_PATTERN = /^@ts-(?:ignore|expect-error)\b([\s\S]*)$/;
293
+ var JAPANESE_PERIOD = "\u3002";
294
+ function parseEnabledRules(values) {
295
+ const enabled = [];
296
+ for (const value of values) {
297
+ if (!OPT_IN_RULE_IDS.includes(value)) {
298
+ throw new Error(`unknown rule: ${value}`);
299
+ }
300
+ const rule = value;
301
+ if (!enabled.includes(rule)) {
302
+ enabled.push(rule);
303
+ }
304
+ }
305
+ return enabled;
306
+ }
307
+ function findJapanesePeriod(text) {
308
+ return text.indexOf(JAPANESE_PERIOD);
309
+ }
292
310
  function normalizeComment(body) {
293
311
  return body.split(`
294
312
  `).map((line) => line.replace(/^\s*\*+\s?/, "")).join(" ").replace(/\s+/g, " ").trim();
@@ -337,31 +355,46 @@ function positionAt(source, offset) {
337
355
  }
338
356
  return { line, column: offset - lineStart + 1 };
339
357
  }
340
- function scanSource(source, file) {
358
+ function scanSource(source, file, enabled = []) {
341
359
  const findings = [];
342
360
  for (const comment of extractComments(source)) {
361
+ const text = normalizeComment(comment.text);
343
362
  const rule = classifyComment(comment.text);
344
- if (rule === null) {
363
+ if (rule !== null) {
364
+ const position2 = positionAt(source, comment.start);
365
+ findings.push({
366
+ column: position2.column,
367
+ file,
368
+ line: position2.line,
369
+ rule,
370
+ text
371
+ });
372
+ }
373
+ if (!enabled.includes("japanese-period")) {
374
+ continue;
375
+ }
376
+ const offset = findJapanesePeriod(comment.text);
377
+ if (offset < 0) {
345
378
  continue;
346
379
  }
347
- const position = positionAt(source, comment.start);
380
+ const position = positionAt(source, comment.start + 2 + offset);
348
381
  findings.push({
349
382
  column: position.column,
350
383
  file,
351
384
  line: position.line,
352
- rule,
353
- text: normalizeComment(comment.text)
385
+ rule: "japanese-period",
386
+ text
354
387
  });
355
388
  }
356
389
  return findings;
357
390
  }
358
- function scanFile(file, cwd = process.cwd()) {
359
- return scanSource(readFileSync(file, "utf8"), normalizePath(relative2(cwd, file)));
391
+ function scanFile(file, cwd = process.cwd(), enabled = []) {
392
+ return scanSource(readFileSync(file, "utf8"), normalizePath(relative2(cwd, file)), enabled);
360
393
  }
361
- function scanFiles(files, cwd = process.cwd()) {
394
+ function scanFiles(files, cwd = process.cwd(), enabled = []) {
362
395
  const findings = [];
363
396
  for (const file of files) {
364
- findings.push(...scanFile(file, cwd));
397
+ findings.push(...scanFile(file, cwd, enabled));
365
398
  }
366
399
  return findings.sort(compareFindings);
367
400
  }
@@ -531,18 +564,20 @@ function runCli(main) {
531
564
  var DEFAULT_BASELINE = "comment-baseline.json";
532
565
  var RULE_MESSAGES = {
533
566
  "broad-suppression": "file-wide suppression hides too much",
567
+ "japanese-period": "a Japanese sentence in a comment does not end with a period",
534
568
  "placeholder-comment": "placeholder comment should be resolved or tracked",
535
569
  "separator-comment": "decorative separator comment adds no information",
536
570
  "undocumented-directive": "TypeScript directive needs a description"
537
571
  };
538
- var USAGE = "Usage: comment-check [--baseline <path>] [--ignore <path>] [--update-baseline] [--json] [path...]";
572
+ var USAGE = "Usage: comment-check [--baseline <path>] [--enable <rule>] [--ignore <path>] [--update-baseline] [--json] [path...]";
539
573
  function parseArguments(argv) {
540
574
  const parsed = parseArgv(argv, {
541
575
  flags: ["json", "update-baseline"],
542
- values: ["baseline", "ignore"]
576
+ values: ["baseline", "enable", "ignore"]
543
577
  });
544
578
  return {
545
579
  baselinePath: parsed.values.get("baseline")?.at(-1) ?? DEFAULT_BASELINE,
580
+ enabled: parseEnabledRules(parsed.values.get("enable") ?? []),
546
581
  ignores: (parsed.values.get("ignore") ?? []).map(normalizePath),
547
582
  json: parsed.flags.has("json"),
548
583
  targets: parsed.targets.length > 0 ? parsed.targets : ["."],
@@ -564,7 +599,7 @@ function main(argv) {
564
599
  extensions: SUPPORTED_EXTENSIONS,
565
600
  ignores: options.ignores
566
601
  });
567
- const findings = scanFiles(files);
602
+ const findings = scanFiles(files, process.cwd(), options.enabled);
568
603
  if (options.update) {
569
604
  const baseline2 = createBaseline(findings);
570
605
  writeBaseline(options.baselinePath, baseline2);
@@ -583,4 +618,10 @@ function main(argv) {
583
618
  }
584
619
  return comparison.added.length > 0 ? 1 : 0;
585
620
  }
586
- runCli(main);
621
+ if (import.meta.main) {
622
+ runCli(main);
623
+ }
624
+ export {
625
+ parseArguments,
626
+ main
627
+ };
package/dist/scan.js CHANGED
@@ -284,9 +284,27 @@ function extractComments(source) {
284
284
  }
285
285
 
286
286
  // src/rules.ts
287
+ var OPT_IN_RULE_IDS = ["japanese-period"];
287
288
  var PLACEHOLDER_PATTERN = /\b(TODO|FIXME|XXX|HACK)\b/;
288
289
  var SEPARATOR_PATTERN = /^[-=*_#~+./\\|]{4,}$/;
289
290
  var DIRECTIVE_PATTERN = /^@ts-(?:ignore|expect-error)\b([\s\S]*)$/;
291
+ var JAPANESE_PERIOD = "\u3002";
292
+ function parseEnabledRules(values) {
293
+ const enabled = [];
294
+ for (const value of values) {
295
+ if (!OPT_IN_RULE_IDS.includes(value)) {
296
+ throw new Error(`unknown rule: ${value}`);
297
+ }
298
+ const rule = value;
299
+ if (!enabled.includes(rule)) {
300
+ enabled.push(rule);
301
+ }
302
+ }
303
+ return enabled;
304
+ }
305
+ function findJapanesePeriod(text) {
306
+ return text.indexOf(JAPANESE_PERIOD);
307
+ }
290
308
  function normalizeComment(body) {
291
309
  return body.split(`
292
310
  `).map((line) => line.replace(/^\s*\*+\s?/, "")).join(" ").replace(/\s+/g, " ").trim();
@@ -335,31 +353,46 @@ function positionAt(source, offset) {
335
353
  }
336
354
  return { line, column: offset - lineStart + 1 };
337
355
  }
338
- function scanSource(source, file) {
356
+ function scanSource(source, file, enabled = []) {
339
357
  const findings = [];
340
358
  for (const comment of extractComments(source)) {
359
+ const text = normalizeComment(comment.text);
341
360
  const rule = classifyComment(comment.text);
342
- if (rule === null) {
361
+ if (rule !== null) {
362
+ const position2 = positionAt(source, comment.start);
363
+ findings.push({
364
+ column: position2.column,
365
+ file,
366
+ line: position2.line,
367
+ rule,
368
+ text
369
+ });
370
+ }
371
+ if (!enabled.includes("japanese-period")) {
372
+ continue;
373
+ }
374
+ const offset = findJapanesePeriod(comment.text);
375
+ if (offset < 0) {
343
376
  continue;
344
377
  }
345
- const position = positionAt(source, comment.start);
378
+ const position = positionAt(source, comment.start + 2 + offset);
346
379
  findings.push({
347
380
  column: position.column,
348
381
  file,
349
382
  line: position.line,
350
- rule,
351
- text: normalizeComment(comment.text)
383
+ rule: "japanese-period",
384
+ text
352
385
  });
353
386
  }
354
387
  return findings;
355
388
  }
356
- function scanFile(file, cwd = process.cwd()) {
357
- return scanSource(readFileSync(file, "utf8"), normalizePath(relative2(cwd, file)));
389
+ function scanFile(file, cwd = process.cwd(), enabled = []) {
390
+ return scanSource(readFileSync(file, "utf8"), normalizePath(relative2(cwd, file)), enabled);
358
391
  }
359
- function scanFiles(files, cwd = process.cwd()) {
392
+ function scanFiles(files, cwd = process.cwd(), enabled = []) {
360
393
  const findings = [];
361
394
  for (const file of files) {
362
- findings.push(...scanFile(file, cwd));
395
+ findings.push(...scanFile(file, cwd, enabled));
363
396
  }
364
397
  return findings.sort(compareFindings);
365
398
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yuu1111/comment-check",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "description": "Shared comment and suppression checker",
5
5
  "repository": {
6
6
  "type": "git",