chaffjs 0.16.0 → 0.18.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/announced-count.d.ts +26 -0
- package/dist/announced-count.d.ts.map +1 -0
- package/dist/announced-count.js +104 -0
- package/dist/announced-count.js.map +1 -0
- package/dist/bare-url.d.ts +14 -0
- package/dist/bare-url.d.ts.map +1 -0
- package/dist/bare-url.js +28 -0
- package/dist/bare-url.js.map +1 -0
- package/dist/baseline.d.ts +5 -0
- package/dist/baseline.d.ts.map +1 -1
- package/dist/baseline.js +16 -1
- package/dist/baseline.js.map +1 -1
- package/dist/body-section.d.ts +7 -0
- package/dist/body-section.d.ts.map +1 -0
- package/dist/body-section.js +6 -0
- package/dist/body-section.js.map +1 -0
- package/dist/calendar-number.d.ts +9 -2
- package/dist/calendar-number.d.ts.map +1 -1
- package/dist/calendar-number.js +18 -4
- package/dist/calendar-number.js.map +1 -1
- package/dist/cli-args.d.ts +4 -0
- package/dist/cli-args.d.ts.map +1 -1
- package/dist/cli-args.js +5 -0
- package/dist/cli-args.js.map +1 -1
- package/dist/cli-text.d.ts.map +1 -1
- package/dist/cli-text.js +8 -4
- package/dist/cli-text.js.map +1 -1
- package/dist/cli.js +33 -30
- package/dist/cli.js.map +1 -1
- package/dist/closing-numbers.d.ts +20 -0
- package/dist/closing-numbers.d.ts.map +1 -0
- package/dist/closing-numbers.js +56 -0
- package/dist/closing-numbers.js.map +1 -0
- package/dist/commands/compare.d.ts +8 -0
- package/dist/commands/compare.d.ts.map +1 -0
- package/dist/commands/compare.js +72 -0
- package/dist/commands/compare.js.map +1 -0
- package/dist/commands/eval.d.ts.map +1 -1
- package/dist/commands/eval.js +17 -9
- package/dist/commands/eval.js.map +1 -1
- package/dist/commands/feedback.d.ts +5 -2
- package/dist/commands/feedback.d.ts.map +1 -1
- package/dist/commands/feedback.js +11 -5
- package/dist/commands/feedback.js.map +1 -1
- package/dist/commands/test.d.ts.map +1 -1
- package/dist/commands/test.js +13 -13
- package/dist/commands/test.js.map +1 -1
- package/dist/commands/tree.d.ts +13 -0
- package/dist/commands/tree.d.ts.map +1 -1
- package/dist/commands/tree.js +35 -5
- package/dist/commands/tree.js.map +1 -1
- package/dist/compare/atom.d.ts +31 -0
- package/dist/compare/atom.d.ts.map +1 -0
- package/dist/compare/atom.js +4 -0
- package/dist/compare/atom.js.map +1 -0
- package/dist/compare/clock-time.d.ts +8 -0
- package/dist/compare/clock-time.d.ts.map +1 -0
- package/dist/compare/clock-time.js +65 -0
- package/dist/compare/clock-time.js.map +1 -0
- package/dist/compare/extract.d.ts +15 -0
- package/dist/compare/extract.d.ts.map +1 -0
- package/dist/compare/extract.js +58 -0
- package/dist/compare/extract.js.map +1 -0
- package/dist/compare/fact-text.d.ts +23 -0
- package/dist/compare/fact-text.d.ts.map +1 -0
- package/dist/compare/fact-text.js +47 -0
- package/dist/compare/fact-text.js.map +1 -0
- package/dist/compare/markup-atoms.d.ts +11 -0
- package/dist/compare/markup-atoms.d.ts.map +1 -0
- package/dist/compare/markup-atoms.js +23 -0
- package/dist/compare/markup-atoms.js.map +1 -0
- package/dist/compare/match.d.ts +19 -0
- package/dist/compare/match.d.ts.map +1 -0
- package/dist/compare/match.js +84 -0
- package/dist/compare/match.js.map +1 -0
- package/dist/compare/outcome.d.ts +33 -0
- package/dist/compare/outcome.d.ts.map +1 -0
- package/dist/compare/outcome.js +40 -0
- package/dist/compare/outcome.js.map +1 -0
- package/dist/compare/proper-nouns.d.ts +19 -0
- package/dist/compare/proper-nouns.d.ts.map +1 -0
- package/dist/compare/proper-nouns.js +44 -0
- package/dist/compare/proper-nouns.js.map +1 -0
- package/dist/compare/render.d.ts +9 -0
- package/dist/compare/render.d.ts.map +1 -0
- package/dist/compare/render.js +64 -0
- package/dist/compare/render.js.map +1 -0
- package/dist/compare/spans.d.ts +9 -0
- package/dist/compare/spans.d.ts.map +1 -0
- package/dist/compare/spans.js +11 -0
- package/dist/compare/spans.js.map +1 -0
- package/dist/compare/text-atoms.d.ts +24 -0
- package/dist/compare/text-atoms.d.ts.map +1 -0
- package/dist/compare/text-atoms.js +67 -0
- package/dist/compare/text-atoms.js.map +1 -0
- package/dist/compare/text.d.ts +24 -0
- package/dist/compare/text.d.ts.map +1 -0
- package/dist/compare/text.js +90 -0
- package/dist/compare/text.js.map +1 -0
- package/dist/compare/tree-atoms.d.ts +20 -0
- package/dist/compare/tree-atoms.d.ts.map +1 -0
- package/dist/compare/tree-atoms.js +58 -0
- package/dist/compare/tree-atoms.js.map +1 -0
- package/dist/compare/written-names.d.ts +8 -0
- package/dist/compare/written-names.d.ts.map +1 -0
- package/dist/compare/written-names.js +24 -0
- package/dist/compare/written-names.js.map +1 -0
- package/dist/config/load.d.ts +15 -0
- package/dist/config/load.d.ts.map +1 -1
- package/dist/config/load.js +5 -0
- package/dist/config/load.js.map +1 -1
- package/dist/config/option-problems.d.ts +16 -0
- package/dist/config/option-problems.d.ts.map +1 -0
- package/dist/config/option-problems.js +58 -0
- package/dist/config/option-problems.js.map +1 -0
- package/dist/config/read.d.ts +4 -0
- package/dist/config/read.d.ts.map +1 -0
- package/dist/config/read.js +8 -0
- package/dist/config/read.js.map +1 -0
- package/dist/config/rule-problems.d.ts +2 -4
- package/dist/config/rule-problems.d.ts.map +1 -1
- package/dist/config/rule-problems.js +7 -1
- package/dist/config/rule-problems.js.map +1 -1
- package/dist/config/style.d.ts +16 -0
- package/dist/config/style.d.ts.map +1 -0
- package/dist/config/style.js +36 -0
- package/dist/config/style.js.map +1 -0
- package/dist/config/warnings.d.ts +6 -0
- package/dist/config/warnings.d.ts.map +1 -0
- package/dist/config/warnings.js +10 -0
- package/dist/config/warnings.js.map +1 -0
- package/dist/config/write.d.ts.map +1 -1
- package/dist/config/write.js +17 -4
- package/dist/config/write.js.map +1 -1
- package/dist/custom/bounded-match.d.ts +15 -0
- package/dist/custom/bounded-match.d.ts.map +1 -0
- package/dist/custom/bounded-match.js +43 -0
- package/dist/custom/bounded-match.js.map +1 -0
- package/dist/custom/load.d.ts +8 -0
- package/dist/custom/load.d.ts.map +1 -0
- package/dist/custom/load.js +11 -0
- package/dist/custom/load.js.map +1 -0
- package/dist/custom/parse.d.ts +70 -0
- package/dist/custom/parse.d.ts.map +1 -0
- package/dist/custom/parse.js +215 -0
- package/dist/custom/parse.js.map +1 -0
- package/dist/custom/problems.d.ts +5 -0
- package/dist/custom/problems.d.ts.map +1 -0
- package/dist/custom/problems.js +78 -0
- package/dist/custom/problems.js.map +1 -0
- package/dist/custom/regex-safety.d.ts +11 -0
- package/dist/custom/regex-safety.d.ts.map +1 -0
- package/dist/custom/regex-safety.js +110 -0
- package/dist/custom/regex-safety.js.map +1 -0
- package/dist/custom/token-pattern.d.ts +8 -0
- package/dist/custom/token-pattern.d.ts.map +1 -0
- package/dist/custom/token-pattern.js +75 -0
- package/dist/custom/token-pattern.js.map +1 -0
- package/dist/detect.d.ts.map +1 -1
- package/dist/detect.js +24 -2
- package/dist/detect.js.map +1 -1
- package/dist/detectors/acronym-context.d.ts +4 -0
- package/dist/detectors/acronym-context.d.ts.map +1 -1
- package/dist/detectors/acronym-context.js +25 -4
- package/dist/detectors/acronym-context.js.map +1 -1
- package/dist/detectors/acronym-expansion.d.ts +2 -0
- package/dist/detectors/acronym-expansion.d.ts.map +1 -1
- package/dist/detectors/acronym-expansion.js +104 -1
- package/dist/detectors/acronym-expansion.js.map +1 -1
- package/dist/detectors/agreement-slip.d.ts +32 -0
- package/dist/detectors/agreement-slip.d.ts.map +1 -0
- package/dist/detectors/agreement-slip.js +137 -0
- package/dist/detectors/agreement-slip.js.map +1 -0
- package/dist/detectors/ai-phrasing.d.ts +20 -0
- package/dist/detectors/ai-phrasing.d.ts.map +1 -0
- package/dist/detectors/ai-phrasing.js +112 -0
- package/dist/detectors/ai-phrasing.js.map +1 -0
- package/dist/detectors/announced-count.d.ts +4 -0
- package/dist/detectors/announced-count.d.ts.map +1 -0
- package/dist/detectors/announced-count.js +20 -0
- package/dist/detectors/announced-count.js.map +1 -0
- package/dist/detectors/broken-link.d.ts +17 -0
- package/dist/detectors/broken-link.d.ts.map +1 -0
- package/dist/detectors/broken-link.js +66 -0
- package/dist/detectors/broken-link.js.map +1 -0
- package/dist/detectors/cited-name.d.ts.map +1 -1
- package/dist/detectors/cited-name.js +4 -4
- package/dist/detectors/cited-name.js.map +1 -1
- package/dist/detectors/cited-title.d.ts +11 -0
- package/dist/detectors/cited-title.d.ts.map +1 -0
- package/dist/detectors/cited-title.js +75 -0
- package/dist/detectors/cited-title.js.map +1 -0
- package/dist/detectors/concrete-evidence.d.ts +1 -1
- package/dist/detectors/concrete-evidence.d.ts.map +1 -1
- package/dist/detectors/concrete-evidence.js +2 -1
- package/dist/detectors/concrete-evidence.js.map +1 -1
- package/dist/detectors/content-morphemes.d.ts +4 -0
- package/dist/detectors/content-morphemes.d.ts.map +1 -0
- package/dist/detectors/content-morphemes.js +12 -0
- package/dist/detectors/content-morphemes.js.map +1 -0
- package/dist/detectors/contrast-frame.d.ts +17 -0
- package/dist/detectors/contrast-frame.d.ts.map +1 -0
- package/dist/detectors/contrast-frame.js +32 -0
- package/dist/detectors/contrast-frame.js.map +1 -0
- package/dist/detectors/custom.d.ts +8 -0
- package/dist/detectors/custom.d.ts.map +1 -0
- package/dist/detectors/custom.js +71 -0
- package/dist/detectors/custom.js.map +1 -0
- package/dist/detectors/dangling-figure.d.ts +4 -0
- package/dist/detectors/dangling-figure.d.ts.map +1 -0
- package/dist/detectors/dangling-figure.js +18 -0
- package/dist/detectors/dangling-figure.js.map +1 -0
- package/dist/detectors/doubled-punctuation.d.ts +9 -0
- package/dist/detectors/doubled-punctuation.d.ts.map +1 -0
- package/dist/detectors/doubled-punctuation.js +33 -0
- package/dist/detectors/doubled-punctuation.js.map +1 -0
- package/dist/detectors/doubled-word.d.ts +5 -0
- package/dist/detectors/doubled-word.d.ts.map +1 -1
- package/dist/detectors/doubled-word.js +24 -11
- package/dist/detectors/doubled-word.js.map +1 -1
- package/dist/detectors/en-shape.d.ts +0 -1
- package/dist/detectors/en-shape.d.ts.map +1 -1
- package/dist/detectors/en-shape.js +0 -235
- package/dist/detectors/en-shape.js.map +1 -1
- package/dist/detectors/enumerated-runs.d.ts +1 -1
- package/dist/detectors/enumerated-runs.d.ts.map +1 -1
- package/dist/detectors/enumerated-runs.js +15 -4
- package/dist/detectors/enumerated-runs.js.map +1 -1
- package/dist/detectors/gram-furniture.d.ts +6 -0
- package/dist/detectors/gram-furniture.d.ts.map +1 -0
- package/dist/detectors/gram-furniture.js +21 -0
- package/dist/detectors/gram-furniture.js.map +1 -0
- package/dist/detectors/gram-place.d.ts +2 -0
- package/dist/detectors/gram-place.d.ts.map +1 -1
- package/dist/detectors/gram-place.js +9 -7
- package/dist/detectors/gram-place.js.map +1 -1
- package/dist/detectors/gram-windows.d.ts +9 -0
- package/dist/detectors/gram-windows.d.ts.map +1 -0
- package/dist/detectors/gram-windows.js +27 -0
- package/dist/detectors/gram-windows.js.map +1 -0
- package/dist/detectors/heading-case.d.ts +2 -0
- package/dist/detectors/heading-case.d.ts.map +1 -1
- package/dist/detectors/heading-case.js +29 -2
- package/dist/detectors/heading-case.js.map +1 -1
- package/dist/detectors/heading-code-words.d.ts +6 -0
- package/dist/detectors/heading-code-words.d.ts.map +1 -0
- package/dist/detectors/heading-code-words.js +29 -0
- package/dist/detectors/heading-code-words.js.map +1 -0
- package/dist/detectors/heading-echo.d.ts.map +1 -1
- package/dist/detectors/heading-echo.js +17 -20
- package/dist/detectors/heading-echo.js.map +1 -1
- package/dist/detectors/heading-level-skip.d.ts +12 -0
- package/dist/detectors/heading-level-skip.d.ts.map +1 -0
- package/dist/detectors/heading-level-skip.js +11 -0
- package/dist/detectors/heading-level-skip.js.map +1 -0
- package/dist/detectors/heading-overlap.d.ts +13 -0
- package/dist/detectors/heading-overlap.d.ts.map +1 -0
- package/dist/detectors/heading-overlap.js +52 -0
- package/dist/detectors/heading-overlap.js.map +1 -0
- package/dist/detectors/image-alt-text.d.ts +3 -0
- package/dist/detectors/image-alt-text.d.ts.map +1 -0
- package/dist/detectors/image-alt-text.js +9 -0
- package/dist/detectors/image-alt-text.js.map +1 -0
- package/dist/detectors/index.d.ts.map +1 -1
- package/dist/detectors/index.js +40 -2
- package/dist/detectors/index.js.map +1 -1
- package/dist/detectors/kutoten-consistency.d.ts +24 -0
- package/dist/detectors/kutoten-consistency.d.ts.map +1 -0
- package/dist/detectors/kutoten-consistency.js +77 -0
- package/dist/detectors/kutoten-consistency.js.map +1 -0
- package/dist/detectors/lead-in.d.ts +1 -0
- package/dist/detectors/lead-in.d.ts.map +1 -1
- package/dist/detectors/lead-in.js +2 -1
- package/dist/detectors/lead-in.js.map +1 -1
- package/dist/detectors/letter-joined-name.d.ts +13 -0
- package/dist/detectors/letter-joined-name.d.ts.map +1 -0
- package/dist/detectors/letter-joined-name.js +11 -0
- package/dist/detectors/letter-joined-name.js.map +1 -0
- package/dist/detectors/lexicon-match.d.ts +4 -0
- package/dist/detectors/lexicon-match.d.ts.map +1 -1
- package/dist/detectors/lexicon-match.js +7 -2
- package/dist/detectors/lexicon-match.js.map +1 -1
- package/dist/detectors/lexicon.d.ts.map +1 -1
- package/dist/detectors/lexicon.js +5 -2
- package/dist/detectors/lexicon.js.map +1 -1
- package/dist/detectors/list-item.d.ts +45 -0
- package/dist/detectors/list-item.d.ts.map +1 -0
- package/dist/detectors/list-item.js +88 -0
- package/dist/detectors/list-item.js.map +1 -0
- package/dist/detectors/list-items.d.ts +31 -0
- package/dist/detectors/list-items.d.ts.map +1 -0
- package/dist/detectors/list-items.js +113 -0
- package/dist/detectors/list-items.js.map +1 -0
- package/dist/detectors/list-lead-in.d.ts +7 -0
- package/dist/detectors/list-lead-in.d.ts.map +1 -0
- package/dist/detectors/list-lead-in.js +28 -0
- package/dist/detectors/list-lead-in.js.map +1 -0
- package/dist/detectors/list-sentence.d.ts +65 -0
- package/dist/detectors/list-sentence.d.ts.map +1 -0
- package/dist/detectors/list-sentence.js +105 -0
- package/dist/detectors/list-sentence.js.map +1 -0
- package/dist/detectors/list-view.d.ts +34 -0
- package/dist/detectors/list-view.d.ts.map +1 -0
- package/dist/detectors/list-view.js +137 -0
- package/dist/detectors/list-view.js.map +1 -0
- package/dist/detectors/long-vowel.d.ts +7 -0
- package/dist/detectors/long-vowel.d.ts.map +1 -0
- package/dist/detectors/long-vowel.js +57 -0
- package/dist/detectors/long-vowel.js.map +1 -0
- package/dist/detectors/markup-finding.d.ts +6 -0
- package/dist/detectors/markup-finding.d.ts.map +1 -0
- package/dist/detectors/markup-finding.js +19 -0
- package/dist/detectors/markup-finding.js.map +1 -0
- package/dist/detectors/name-numeral.d.ts +1 -1
- package/dist/detectors/name-numeral.d.ts.map +1 -1
- package/dist/detectors/name-numeral.js +2 -7
- package/dist/detectors/name-numeral.js.map +1 -1
- package/dist/detectors/orthography.d.ts.map +1 -1
- package/dist/detectors/orthography.js +16 -12
- package/dist/detectors/orthography.js.map +1 -1
- package/dist/detectors/oxford-comma.d.ts +9 -0
- package/dist/detectors/oxford-comma.d.ts.map +1 -0
- package/dist/detectors/oxford-comma.js +246 -0
- package/dist/detectors/oxford-comma.js.map +1 -0
- package/dist/detectors/place-run.d.ts.map +1 -1
- package/dist/detectors/place-run.js +10 -6
- package/dist/detectors/place-run.js.map +1 -1
- package/dist/detectors/placeholder-text.d.ts +9 -0
- package/dist/detectors/placeholder-text.d.ts.map +1 -0
- package/dist/detectors/placeholder-text.js +18 -0
- package/dist/detectors/placeholder-text.js.map +1 -0
- package/dist/detectors/quote-around.d.ts +3 -0
- package/dist/detectors/quote-around.d.ts.map +1 -0
- package/dist/detectors/quote-around.js +8 -0
- package/dist/detectors/quote-around.js.map +1 -0
- package/dist/detectors/register.d.ts +11 -3
- package/dist/detectors/register.d.ts.map +1 -1
- package/dist/detectors/register.js +28 -9
- package/dist/detectors/register.js.map +1 -1
- package/dist/detectors/roman-numeral.d.ts +2 -0
- package/dist/detectors/roman-numeral.d.ts.map +1 -1
- package/dist/detectors/roman-numeral.js +2 -0
- package/dist/detectors/roman-numeral.js.map +1 -1
- package/dist/detectors/sentence-ending.d.ts +17 -1
- package/dist/detectors/sentence-ending.d.ts.map +1 -1
- package/dist/detectors/sentence-ending.js +13 -7
- package/dist/detectors/sentence-ending.js.map +1 -1
- package/dist/detectors/sentence-length.d.ts.map +1 -1
- package/dist/detectors/sentence-length.js +13 -4
- package/dist/detectors/sentence-length.js.map +1 -1
- package/dist/detectors/signals.d.ts +8 -0
- package/dist/detectors/signals.d.ts.map +1 -1
- package/dist/detectors/signals.js +94 -54
- package/dist/detectors/signals.js.map +1 -1
- package/dist/detectors/stacked-hedge.d.ts +0 -7
- package/dist/detectors/stacked-hedge.d.ts.map +1 -1
- package/dist/detectors/stacked-hedge.js +6 -3
- package/dist/detectors/stacked-hedge.js.map +1 -1
- package/dist/detectors/stray-space.d.ts +7 -0
- package/dist/detectors/stray-space.d.ts.map +1 -0
- package/dist/detectors/stray-space.js +34 -0
- package/dist/detectors/stray-space.js.map +1 -0
- package/dist/detectors/structure-tree.d.ts +6 -0
- package/dist/detectors/structure-tree.d.ts.map +1 -1
- package/dist/detectors/structure-tree.js +37 -1
- package/dist/detectors/structure-tree.js.map +1 -1
- package/dist/detectors/structure.d.ts +4 -4
- package/dist/detectors/structure.d.ts.map +1 -1
- package/dist/detectors/structure.js +7 -6
- package/dist/detectors/structure.js.map +1 -1
- package/dist/detectors/superlative-name.d.ts.map +1 -1
- package/dist/detectors/superlative-name.js +8 -5
- package/dist/detectors/superlative-name.js.map +1 -1
- package/dist/detectors/superlative-scope.d.ts.map +1 -1
- package/dist/detectors/superlative-scope.js +9 -4
- package/dist/detectors/superlative-scope.js.map +1 -1
- package/dist/detectors/token-column.d.ts +46 -0
- package/dist/detectors/token-column.d.ts.map +1 -0
- package/dist/detectors/token-column.js +95 -0
- package/dist/detectors/token-column.js.map +1 -0
- package/dist/detectors/unbalanced-bracket.d.ts +22 -0
- package/dist/detectors/unbalanced-bracket.d.ts.map +1 -0
- package/dist/detectors/unbalanced-bracket.js +119 -0
- package/dist/detectors/unbalanced-bracket.js.map +1 -0
- package/dist/detectors/url-run-on.d.ts +9 -0
- package/dist/detectors/url-run-on.d.ts.map +1 -0
- package/dist/detectors/url-run-on.js +19 -0
- package/dist/detectors/url-run-on.js.map +1 -0
- package/dist/document-sections.d.ts +13 -0
- package/dist/document-sections.d.ts.map +1 -0
- package/dist/document-sections.js +32 -0
- package/dist/document-sections.js.map +1 -0
- package/dist/document.d.ts +11 -4
- package/dist/document.d.ts.map +1 -1
- package/dist/document.js +99 -95
- package/dist/document.js.map +1 -1
- package/dist/email-parts.d.ts +28 -0
- package/dist/email-parts.d.ts.map +1 -0
- package/dist/email-parts.js +230 -0
- package/dist/email-parts.js.map +1 -0
- package/dist/eval.d.ts +2 -1
- package/dist/eval.d.ts.map +1 -1
- package/dist/eval.js +16 -4
- package/dist/eval.js.map +1 -1
- package/dist/figure-references.d.ts +30 -0
- package/dist/figure-references.d.ts.map +1 -0
- package/dist/figure-references.js +76 -0
- package/dist/figure-references.js.map +1 -0
- package/dist/files.d.ts +2 -0
- package/dist/files.d.ts.map +1 -1
- package/dist/files.js +4 -0
- package/dist/files.js.map +1 -1
- package/dist/genre-parse.d.ts +5 -1
- package/dist/genre-parse.d.ts.map +1 -1
- package/dist/genre-parse.js +16 -3
- package/dist/genre-parse.js.map +1 -1
- package/dist/genre-suggest.d.ts.map +1 -1
- package/dist/genre-suggest.js +15 -1
- package/dist/genre-suggest.js.map +1 -1
- package/dist/heading-label.d.ts +22 -0
- package/dist/heading-label.d.ts.map +1 -0
- package/dist/heading-label.js +50 -0
- package/dist/heading-label.js.map +1 -0
- package/dist/in-page-nav.d.ts +4 -1
- package/dist/in-page-nav.d.ts.map +1 -1
- package/dist/in-page-nav.js +53 -18
- package/dist/in-page-nav.js.map +1 -1
- package/dist/joined-view.d.ts.map +1 -1
- package/dist/joined-view.js +1 -0
- package/dist/joined-view.js.map +1 -1
- package/dist/levels.d.ts +5 -1
- package/dist/levels.d.ts.map +1 -1
- package/dist/levels.js +9 -0
- package/dist/levels.js.map +1 -1
- package/dist/line-paragraphs.d.ts +8 -0
- package/dist/line-paragraphs.d.ts.map +1 -1
- package/dist/line-paragraphs.js +36 -11
- package/dist/line-paragraphs.js.map +1 -1
- package/dist/long-vowel.d.ts +35 -0
- package/dist/long-vowel.d.ts.map +1 -0
- package/dist/long-vowel.js +71 -0
- package/dist/long-vowel.js.map +1 -0
- package/dist/markdown-node.d.ts +19 -0
- package/dist/markdown-node.d.ts.map +1 -0
- package/dist/markdown-node.js +6 -0
- package/dist/markdown-node.js.map +1 -0
- package/dist/markdown-read.d.ts +17 -0
- package/dist/markdown-read.d.ts.map +1 -0
- package/dist/markdown-read.js +37 -0
- package/dist/markdown-read.js.map +1 -0
- package/dist/markup.d.ts +22 -0
- package/dist/markup.d.ts.map +1 -0
- package/dist/markup.js +180 -0
- package/dist/markup.js.map +1 -0
- package/dist/mask.d.ts.map +1 -1
- package/dist/mask.js +10 -16
- package/dist/mask.js.map +1 -1
- package/dist/number-name.d.ts +21 -5
- package/dist/number-name.d.ts.map +1 -1
- package/dist/number-name.js +120 -18
- package/dist/number-name.js.map +1 -1
- package/dist/opening-line.d.ts +3 -0
- package/dist/opening-line.d.ts.map +1 -0
- package/dist/opening-line.js +14 -0
- package/dist/opening-line.js.map +1 -0
- package/dist/orthography.d.ts +7 -1
- package/dist/orthography.d.ts.map +1 -1
- package/dist/orthography.js +16 -5
- package/dist/orthography.js.map +1 -1
- package/dist/page-furniture.d.ts +5 -2
- package/dist/page-furniture.d.ts.map +1 -1
- package/dist/page-furniture.js +8 -2
- package/dist/page-furniture.js.map +1 -1
- package/dist/paragraph-length.d.ts +7 -0
- package/dist/paragraph-length.d.ts.map +1 -0
- package/dist/paragraph-length.js +10 -0
- package/dist/paragraph-length.js.map +1 -0
- package/dist/plain-source.d.ts +1 -0
- package/dist/plain-source.d.ts.map +1 -1
- package/dist/plain-source.js +2 -1
- package/dist/plain-source.js.map +1 -1
- package/dist/plugin.d.ts +121 -0
- package/dist/plugin.d.ts.map +1 -1
- package/dist/profile/for-file.d.ts.map +1 -1
- package/dist/profile/for-file.js +3 -1
- package/dist/profile/for-file.js.map +1 -1
- package/dist/quoted-span.d.ts +0 -2
- package/dist/quoted-span.d.ts.map +1 -1
- package/dist/quoted-span.js +9 -4
- package/dist/quoted-span.js.map +1 -1
- package/dist/reasons.d.ts +3 -0
- package/dist/reasons.d.ts.map +1 -1
- package/dist/reasons.js +6 -0
- package/dist/reasons.js.map +1 -1
- package/dist/reference-lists.d.ts +3 -0
- package/dist/reference-lists.d.ts.map +1 -0
- package/dist/reference-lists.js +75 -0
- package/dist/reference-lists.js.map +1 -0
- package/dist/render/explain.d.ts +7 -1
- package/dist/render/explain.d.ts.map +1 -1
- package/dist/render/explain.js +36 -12
- package/dist/render/explain.js.map +1 -1
- package/dist/render/friendly.d.ts.map +1 -1
- package/dist/render/friendly.js +19 -9
- package/dist/render/friendly.js.map +1 -1
- package/dist/render/options.d.ts +7 -0
- package/dist/render/options.d.ts.map +1 -0
- package/dist/render/options.js +50 -0
- package/dist/render/options.js.map +1 -0
- package/dist/render/rules-json.d.ts +4 -1
- package/dist/render/rules-json.d.ts.map +1 -1
- package/dist/render/rules-json.js +102 -12
- package/dist/render/rules-json.js.map +1 -1
- package/dist/render/rules-table.d.ts +4 -0
- package/dist/render/rules-table.d.ts.map +1 -0
- package/dist/render/rules-table.js +70 -0
- package/dist/render/rules-table.js.map +1 -0
- package/dist/render/sarif.js +4 -4
- package/dist/render/sarif.js.map +1 -1
- package/dist/render/semantic.js +3 -3
- package/dist/render/semantic.js.map +1 -1
- package/dist/render/severity-name.d.ts +6 -0
- package/dist/render/severity-name.d.ts.map +1 -0
- package/dist/render/severity-name.js +7 -0
- package/dist/render/severity-name.js.map +1 -0
- package/dist/render/text.d.ts +7 -2
- package/dist/render/text.d.ts.map +1 -1
- package/dist/render/text.js +15 -4
- package/dist/render/text.js.map +1 -1
- package/dist/resolve-genre.d.ts +1 -1
- package/dist/resolve-genre.d.ts.map +1 -1
- package/dist/resolve-genre.js +4 -1
- package/dist/resolve-genre.js.map +1 -1
- package/dist/rule-genres.d.ts +24 -0
- package/dist/rule-genres.d.ts.map +1 -0
- package/dist/rule-genres.js +11 -0
- package/dist/rule-genres.js.map +1 -0
- package/dist/rule-guide.d.ts +54 -0
- package/dist/rule-guide.d.ts.map +1 -0
- package/dist/rule-guide.js +81 -0
- package/dist/rule-guide.js.map +1 -0
- package/dist/rule-load.d.ts.map +1 -1
- package/dist/rule-load.js +94 -32
- package/dist/rule-load.js.map +1 -1
- package/dist/rule-options.d.ts +50 -0
- package/dist/rule-options.d.ts.map +1 -0
- package/dist/rule-options.js +106 -0
- package/dist/rule-options.js.map +1 -0
- package/dist/run-semantic.d.ts +3 -1
- package/dist/run-semantic.d.ts.map +1 -1
- package/dist/run-semantic.js +8 -3
- package/dist/run-semantic.js.map +1 -1
- package/dist/run.d.ts +15 -0
- package/dist/run.d.ts.map +1 -1
- package/dist/run.js +57 -10
- package/dist/run.js.map +1 -1
- package/dist/semantic.d.ts +1 -1
- package/dist/semantic.d.ts.map +1 -1
- package/dist/semantic.js +10 -3
- package/dist/semantic.js.map +1 -1
- package/dist/sentence-shape.d.ts.map +1 -1
- package/dist/sentence-shape.js +4 -4
- package/dist/sentence-shape.js.map +1 -1
- package/dist/setting-problems.d.ts +2 -1
- package/dist/setting-problems.d.ts.map +1 -1
- package/dist/setting-problems.js +6 -1
- package/dist/setting-problems.js.map +1 -1
- package/dist/span-cut.d.ts +6 -0
- package/dist/span-cut.d.ts.map +1 -0
- package/dist/span-cut.js +22 -0
- package/dist/span-cut.js.map +1 -0
- package/dist/span-merge.d.ts +4 -0
- package/dist/span-merge.d.ts.map +1 -0
- package/dist/span-merge.js +12 -0
- package/dist/span-merge.js.map +1 -0
- package/dist/speaker-labels.d.ts +4 -0
- package/dist/speaker-labels.d.ts.map +1 -0
- package/dist/speaker-labels.js +106 -0
- package/dist/speaker-labels.js.map +1 -0
- package/dist/stray-space.d.ts +17 -0
- package/dist/stray-space.d.ts.map +1 -0
- package/dist/stray-space.js +66 -0
- package/dist/stray-space.js.map +1 -0
- package/dist/structure/aside-depth.d.ts +21 -0
- package/dist/structure/aside-depth.d.ts.map +1 -0
- package/dist/structure/aside-depth.js +65 -0
- package/dist/structure/aside-depth.js.map +1 -0
- package/dist/structure/build.d.ts +5 -1
- package/dist/structure/build.d.ts.map +1 -1
- package/dist/structure/build.js +29 -17
- package/dist/structure/build.js.map +1 -1
- package/dist/structure/closed-pairs.d.ts +8 -0
- package/dist/structure/closed-pairs.d.ts.map +1 -0
- package/dist/structure/closed-pairs.js +22 -0
- package/dist/structure/closed-pairs.js.map +1 -0
- package/dist/structure/date-range.d.ts +21 -0
- package/dist/structure/date-range.d.ts.map +1 -0
- package/dist/structure/date-range.js +45 -0
- package/dist/structure/date-range.js.map +1 -0
- package/dist/structure/known-mentions.d.ts +18 -0
- package/dist/structure/known-mentions.d.ts.map +1 -0
- package/dist/structure/known-mentions.js +78 -0
- package/dist/structure/known-mentions.js.map +1 -0
- package/dist/structure/numbering.d.ts +1 -0
- package/dist/structure/numbering.d.ts.map +1 -1
- package/dist/structure/numbering.js +11 -6
- package/dist/structure/numbering.js.map +1 -1
- package/dist/structure/of.d.ts +3 -1
- package/dist/structure/of.d.ts.map +1 -1
- package/dist/structure/of.js +5 -1
- package/dist/structure/of.js.map +1 -1
- package/dist/structure/percent-sum.d.ts +16 -0
- package/dist/structure/percent-sum.d.ts.map +1 -0
- package/dist/structure/percent-sum.js +104 -0
- package/dist/structure/percent-sum.js.map +1 -0
- package/dist/structure/quoted-number.d.ts +8 -0
- package/dist/structure/quoted-number.d.ts.map +1 -0
- package/dist/structure/quoted-number.js +34 -0
- package/dist/structure/quoted-number.js.map +1 -0
- package/dist/structure/relative-find.d.ts.map +1 -1
- package/dist/structure/relative-find.js +34 -46
- package/dist/structure/relative-find.js.map +1 -1
- package/dist/structure/relative-resolve.d.ts.map +1 -1
- package/dist/structure/relative-resolve.js +94 -42
- package/dist/structure/relative-resolve.js.map +1 -1
- package/dist/structure/runs.d.ts +2 -0
- package/dist/structure/runs.d.ts.map +1 -1
- package/dist/structure/runs.js +2 -2
- package/dist/structure/runs.js.map +1 -1
- package/dist/structure/sexp.d.ts +1 -1
- package/dist/structure/sexp.d.ts.map +1 -1
- package/dist/structure/sexp.js +18 -6
- package/dist/structure/sexp.js.map +1 -1
- package/dist/structure/total.d.ts +3 -0
- package/dist/structure/total.d.ts.map +1 -1
- package/dist/structure/total.js +2 -2
- package/dist/structure/total.js.map +1 -1
- package/dist/structure/universal.d.ts +14 -2
- package/dist/structure/universal.d.ts.map +1 -1
- package/dist/structure/universal.js +17 -2
- package/dist/structure/universal.js.map +1 -1
- package/dist/structure/wrapped-tail.d.ts +14 -7
- package/dist/structure/wrapped-tail.d.ts.map +1 -1
- package/dist/structure/wrapped-tail.js +33 -8
- package/dist/structure/wrapped-tail.js.map +1 -1
- package/dist/style-load.d.ts +4 -0
- package/dist/style-load.d.ts.map +1 -0
- package/dist/style-load.js +28 -0
- package/dist/style-load.js.map +1 -0
- package/dist/style-parse.d.ts +19 -0
- package/dist/style-parse.d.ts.map +1 -0
- package/dist/style-parse.js +60 -0
- package/dist/style-parse.js.map +1 -0
- package/dist/subheading-line.d.ts +6 -0
- package/dist/subheading-line.d.ts.map +1 -0
- package/dist/subheading-line.js +57 -0
- package/dist/subheading-line.js.map +1 -0
- package/dist/team-names.d.ts.map +1 -1
- package/dist/team-names.js +11 -14
- package/dist/team-names.js.map +1 -1
- package/dist/template-syntax.d.ts +17 -0
- package/dist/template-syntax.d.ts.map +1 -0
- package/dist/template-syntax.js +140 -0
- package/dist/template-syntax.js.map +1 -0
- package/dist/text-above.d.ts +19 -0
- package/dist/text-above.d.ts.map +1 -0
- package/dist/text-above.js +43 -0
- package/dist/text-above.js.map +1 -0
- package/dist/text-figures.d.ts +10 -0
- package/dist/text-figures.d.ts.map +1 -0
- package/dist/text-figures.js +131 -0
- package/dist/text-figures.js.map +1 -0
- package/dist/trailing-aside.d.ts +2 -0
- package/dist/trailing-aside.d.ts.map +1 -0
- package/dist/trailing-aside.js +53 -0
- package/dist/trailing-aside.js.map +1 -0
- package/dist/tree-walk.d.ts +18 -0
- package/dist/tree-walk.d.ts.map +1 -0
- package/dist/tree-walk.js +45 -0
- package/dist/tree-walk.js.map +1 -0
- package/genres.yaml +60 -2
- package/package.json +5 -3
- package/reference-headings.yaml +17 -0
- package/rules/adverb-overuse.yaml +19 -0
- package/rules/agentless-passive.yaml +19 -0
- package/rules/agreement-slip.yaml +49 -0
- package/rules/ai-generated-composite.yaml +102 -0
- package/rules/ai-tell.yaml +23 -0
- package/rules/announced-count-mismatch.yaml +57 -0
- package/rules/announcing-opener.yaml +51 -0
- package/rules/assistant-residue.yaml +52 -0
- package/rules/bold-density.yaml +31 -0
- package/rules/broken-link.yaml +65 -0
- package/rules/closing-cliche.yaml +33 -0
- package/rules/colon-lead-in.yaml +59 -0
- package/rules/concrete-evidence-density.yaml +41 -0
- package/rules/contraction-consistency.yaml +18 -0
- package/rules/contrast-framing.yaml +57 -0
- package/rules/cushion-phrase-density.yaml +25 -0
- package/rules/dangling-figure-reference.yaml +61 -0
- package/rules/dangling-reference.yaml +53 -1
- package/rules/date-order.yaml +33 -1
- package/rules/date-range-reversed.yaml +46 -0
- package/rules/date-weekday-mismatch.yaml +17 -1
- package/rules/double-keigo.yaml +16 -0
- package/rules/doubled-punctuation.yaml +45 -0
- package/rules/doubled-word.yaml +17 -1
- package/rules/duplicate-definition.yaml +59 -1
- package/rules/emoji-density.yaml +25 -0
- package/rules/empty-conclusion.yaml +29 -0
- package/rules/empty-intensifier.yaml +19 -0
- package/rules/excessive-hedging.yaml +19 -0
- package/rules/expletive-construction.yaml +19 -0
- package/rules/heading-echo.yaml +32 -0
- package/rules/heading-level-skip.yaml +78 -0
- package/rules/hiragana-fukushi.yaml +16 -0
- package/rules/image-alt-text.yaml +54 -0
- package/rules/internal-jargon.yaml +21 -0
- package/rules/katakana-long-vowel.yaml +98 -0
- package/rules/kutoten-consistency.yaml +53 -0
- package/rules/latin-spacing.yaml +23 -4
- package/rules/max-kanji-continuous.yaml +16 -0
- package/rules/max-paragraph-length.yaml +42 -2
- package/rules/max-sentence-length.yaml +36 -0
- package/rules/ngram-repetition.yaml +29 -2
- package/rules/no-doubled-joshi.yaml +16 -0
- package/rules/no-em-dash.yaml +25 -0
- package/rules/no-mixed-desumasu.yaml +27 -2
- package/rules/no-nakaguro-parallel.yaml +20 -0
- package/rules/numbering-gap.yaml +53 -1
- package/rules/oxford-comma-consistency.yaml +19 -1
- package/rules/padded-intro.yaml +19 -0
- package/rules/paragraph-length-variance.yaml +49 -0
- package/rules/percent-sum-mismatch.yaml +58 -0
- package/rules/preamble-length.yaml +56 -0
- package/rules/preferred-term.yaml +27 -0
- package/rules/proper-noun-density.yaml +26 -0
- package/rules/repeated-conjunction.yaml +47 -0
- package/rules/repeated-sentence-head.yaml +23 -0
- package/rules/required-sections.yaml +49 -0
- package/rules/risk-disclosure.yaml +22 -0
- package/rules/rule-of-three.yaml +97 -0
- package/rules/sasete-itadaku.yaml +18 -0
- package/rules/section-length-uniformity.yaml +89 -0
- package/rules/sentence-initial-conjunction-run.yaml +18 -0
- package/rules/sentence-rhythm.yaml +25 -0
- package/rules/stock-transition.yaml +55 -0
- package/rules/stray-space.yaml +56 -0
- package/rules/taigen-dome-in-prose.yaml +19 -0
- package/rules/title-case-consistency.yaml +42 -0
- package/rules/total-mismatch.yaml +37 -1
- package/rules/unbalanced-bracket.yaml +56 -0
- package/rules/undefined-acronym.yaml +23 -0
- package/rules/unfilled-placeholder.yaml +50 -0
- package/rules/unqualified-superlative.yaml +19 -0
- package/rules/unsourced-number.yaml +16 -0
- package/rules/url-run-on.yaml +45 -0
- package/skills/chaff/SKILL.md +70 -0
- package/src/announced-count.ts +148 -0
- package/src/bare-url.ts +35 -0
- package/src/baseline.ts +17 -1
- package/src/body-section.ts +7 -0
- package/src/calendar-number.ts +33 -10
- package/src/cli-args.ts +6 -0
- package/src/cli-text.ts +8 -4
- package/src/cli.ts +37 -37
- package/src/closing-numbers.ts +72 -0
- package/src/commands/compare.ts +80 -0
- package/src/commands/eval.ts +19 -8
- package/src/commands/feedback.ts +12 -6
- package/src/commands/test.ts +20 -17
- package/src/commands/tree.ts +41 -5
- package/src/compare/atom.ts +33 -0
- package/src/compare/clock-time.ts +86 -0
- package/src/compare/extract.ts +78 -0
- package/src/compare/fact-text.ts +68 -0
- package/src/compare/markup-atoms.ts +29 -0
- package/src/compare/match.ts +105 -0
- package/src/compare/outcome.ts +70 -0
- package/src/compare/proper-nouns.ts +65 -0
- package/src/compare/render.ts +102 -0
- package/src/compare/spans.ts +17 -0
- package/src/compare/text-atoms.ts +95 -0
- package/src/compare/text.ts +120 -0
- package/src/compare/tree-atoms.ts +80 -0
- package/src/compare/written-names.ts +26 -0
- package/src/config/load.ts +21 -0
- package/src/config/option-problems.ts +70 -0
- package/src/config/read.ts +8 -0
- package/src/config/rule-problems.ts +12 -2
- package/src/config/style.ts +42 -0
- package/src/config/warnings.ts +13 -0
- package/src/config/write.ts +18 -4
- package/src/custom/bounded-match.ts +58 -0
- package/src/custom/load.ts +15 -0
- package/src/custom/parse.ts +274 -0
- package/src/custom/problems.ts +89 -0
- package/src/custom/regex-safety.ts +118 -0
- package/src/custom/token-pattern.ts +84 -0
- package/src/detect.ts +28 -2
- package/src/detectors/acronym-context.ts +32 -4
- package/src/detectors/acronym-expansion.ts +132 -1
- package/src/detectors/agreement-slip.ts +191 -0
- package/src/detectors/ai-phrasing.ts +137 -0
- package/src/detectors/announced-count.ts +25 -0
- package/src/detectors/broken-link.ts +90 -0
- package/src/detectors/cited-name.ts +6 -5
- package/src/detectors/cited-title.ts +96 -0
- package/src/detectors/concrete-evidence.ts +3 -2
- package/src/detectors/content-morphemes.ts +19 -0
- package/src/detectors/contrast-frame.ts +54 -0
- package/src/detectors/custom.ts +89 -0
- package/src/detectors/dangling-figure.ts +22 -0
- package/src/detectors/doubled-punctuation.ts +49 -0
- package/src/detectors/doubled-word.ts +19 -4
- package/src/detectors/en-shape.ts +0 -269
- package/src/detectors/enumerated-runs.ts +13 -4
- package/src/detectors/gram-furniture.ts +30 -0
- package/src/detectors/gram-place.ts +9 -5
- package/src/detectors/gram-windows.ts +31 -0
- package/src/detectors/heading-case.ts +30 -2
- package/src/detectors/heading-code-words.ts +35 -0
- package/src/detectors/heading-echo.ts +18 -22
- package/src/detectors/heading-level-skip.ts +19 -0
- package/src/detectors/heading-overlap.ts +65 -0
- package/src/detectors/image-alt-text.ts +11 -0
- package/src/detectors/index.ts +49 -2
- package/src/detectors/kutoten-consistency.ts +96 -0
- package/src/detectors/lead-in.ts +3 -1
- package/src/detectors/letter-joined-name.ts +15 -0
- package/src/detectors/lexicon-match.ts +9 -2
- package/src/detectors/lexicon.ts +6 -2
- package/src/detectors/list-item.ts +122 -0
- package/src/detectors/list-items.ts +163 -0
- package/src/detectors/list-lead-in.ts +33 -0
- package/src/detectors/list-sentence.ts +157 -0
- package/src/detectors/list-view.ts +157 -0
- package/src/detectors/long-vowel.ts +66 -0
- package/src/detectors/markup-finding.ts +24 -0
- package/src/detectors/name-numeral.ts +4 -2
- package/src/detectors/orthography.ts +24 -18
- package/src/detectors/oxford-comma.ts +297 -0
- package/src/detectors/place-run.ts +7 -4
- package/src/detectors/placeholder-text.ts +27 -0
- package/src/detectors/quote-around.ts +9 -0
- package/src/detectors/register.ts +37 -10
- package/src/detectors/roman-numeral.ts +3 -0
- package/src/detectors/sentence-ending.ts +14 -7
- package/src/detectors/sentence-length.ts +16 -5
- package/src/detectors/signals.ts +110 -53
- package/src/detectors/stacked-hedge.ts +6 -3
- package/src/detectors/stray-space.ts +40 -0
- package/src/detectors/structure-tree.ts +45 -1
- package/src/detectors/structure.ts +13 -6
- package/src/detectors/superlative-name.ts +7 -4
- package/src/detectors/superlative-scope.ts +8 -3
- package/src/detectors/token-column.ts +149 -0
- package/src/detectors/unbalanced-bracket.ts +153 -0
- package/src/detectors/url-run-on.ts +27 -0
- package/src/document-sections.ts +46 -0
- package/src/document.ts +116 -127
- package/src/email-parts.ts +269 -0
- package/src/eval.ts +14 -4
- package/src/figure-references.ts +112 -0
- package/src/files.ts +5 -0
- package/src/genre-parse.ts +30 -5
- package/src/genre-suggest.ts +15 -2
- package/src/heading-label.ts +55 -0
- package/src/in-page-nav.ts +48 -19
- package/src/joined-view.ts +1 -0
- package/src/levels.ts +14 -1
- package/src/line-paragraphs.ts +56 -10
- package/src/long-vowel.ts +99 -0
- package/src/markdown-node.ts +19 -0
- package/src/markdown-read.ts +44 -0
- package/src/markup.ts +210 -0
- package/src/mask.ts +10 -19
- package/src/number-name.ts +152 -25
- package/src/opening-line.ts +17 -0
- package/src/orthography.ts +20 -5
- package/src/page-furniture.ts +11 -2
- package/src/paragraph-length.ts +9 -0
- package/src/plain-source.ts +2 -1
- package/src/plugin.ts +107 -1
- package/src/profile/for-file.ts +3 -1
- package/src/quoted-span.ts +10 -4
- package/src/reasons.ts +9 -0
- package/src/reference-lists.ts +91 -0
- package/src/render/explain.ts +47 -13
- package/src/render/friendly.ts +20 -9
- package/src/render/options.ts +58 -0
- package/src/render/rules-json.ts +130 -14
- package/src/render/rules-table.ts +91 -0
- package/src/render/sarif.ts +4 -4
- package/src/render/semantic.ts +3 -3
- package/src/render/severity-name.ts +10 -0
- package/src/render/text.ts +21 -7
- package/src/resolve-genre.ts +4 -1
- package/src/rule-genres.ts +25 -0
- package/src/rule-guide.ts +135 -0
- package/src/rule-load.ts +98 -33
- package/src/rule-options.ts +131 -0
- package/src/run-semantic.ts +28 -20
- package/src/run.ts +78 -11
- package/src/semantic.ts +11 -3
- package/src/sentence-shape.ts +4 -5
- package/src/setting-problems.ts +7 -1
- package/src/span-cut.ts +28 -0
- package/src/span-merge.ts +13 -0
- package/src/speaker-labels.ts +129 -0
- package/src/stray-space.ts +81 -0
- package/src/structure/aside-depth.ts +67 -0
- package/src/structure/build.ts +38 -19
- package/src/structure/closed-pairs.ts +20 -0
- package/src/structure/date-range.ts +69 -0
- package/src/structure/known-mentions.ts +96 -0
- package/src/structure/numbering.ts +9 -5
- package/src/structure/of.ts +11 -3
- package/src/structure/percent-sum.ts +135 -0
- package/src/structure/quoted-number.ts +36 -0
- package/src/structure/relative-find.ts +34 -47
- package/src/structure/relative-resolve.ts +104 -42
- package/src/structure/runs.ts +2 -2
- package/src/structure/sexp.ts +17 -5
- package/src/structure/total.ts +2 -2
- package/src/structure/universal.ts +24 -4
- package/src/structure/wrapped-tail.ts +38 -13
- package/src/style-load.ts +28 -0
- package/src/style-parse.ts +77 -0
- package/src/subheading-line.ts +68 -0
- package/src/team-names.ts +13 -13
- package/src/template-syntax.ts +164 -0
- package/src/text-above.ts +49 -0
- package/src/text-figures.ts +147 -0
- package/src/trailing-aside.ts +50 -0
- package/src/tree-walk.ts +48 -0
- package/styles/bunkacho.yaml +25 -0
- package/styles/ieice.yaml +29 -0
- package/styles/jis-z8301-2011.yaml +25 -0
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { ATOM_KINDS, type Atom, type AtomKind } from "./atom.ts";
|
|
2
|
+
import type { Reformed } from "./match.ts";
|
|
3
|
+
import type { Change, Outcome, Side } from "./outcome.ts";
|
|
4
|
+
import type { CompareText } from "./text.ts";
|
|
5
|
+
|
|
6
|
+
/** How much of a fact is shown: a code block is shown by its first line. */
|
|
7
|
+
const SHOWN_WIDTH = 60;
|
|
8
|
+
|
|
9
|
+
/** One line of a fact as written: a code block or a wrapped quotation is shown on one line, cut at SHOWN_WIDTH. */
|
|
10
|
+
const shown = (text: string): string => {
|
|
11
|
+
const oneLine = text.replace(/\s+/gu, " ").trim();
|
|
12
|
+
return oneLine.length > SHOWN_WIDTH ? `${oneLine.slice(0, SHOWN_WIDTH)}…` : oneLine;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const totalOf = (side: Side): number => ATOM_KINDS.reduce((sum, kind) => sum + side.counts[kind], 0);
|
|
16
|
+
|
|
17
|
+
/** The count line. Every kind is listed, zeros too: "nothing dropped" reads as N facts checked, never as nothing looked at. */
|
|
18
|
+
const checkedLine = (outcome: Outcome, text: CompareText): string => {
|
|
19
|
+
const perKind = ATOM_KINDS.map((kind) => `${text.kinds[kind]} ${String(outcome.before.counts[kind])}→${String(outcome.after.counts[kind])}`);
|
|
20
|
+
return text.checked(totalOf(outcome.before), totalOf(outcome.after), perKind.join(text.separator));
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const failing = (changes: readonly Change[]): number => changes.filter((change) => !change.allowed).length;
|
|
24
|
+
|
|
25
|
+
const verdict = (outcome: Outcome, text: CompareText): string => (outcome.ok ? text.clean : text.failed(failing(outcome.dropped), failing(outcome.added)));
|
|
26
|
+
|
|
27
|
+
const kindColumn = (kind: AtomKind, text: CompareText): string => `${text.kind[kind]}: `;
|
|
28
|
+
|
|
29
|
+
const changeLine = (change: Change, path: string, flag: string, text: CompareText): string =>
|
|
30
|
+
` ${kindColumn(change.kind, text)}${shown(change.text)} (${path}:${String(change.line)})${change.allowed ? text.allowed(flag) : ""}`;
|
|
31
|
+
|
|
32
|
+
const reformedLine = (pair: Reformed, text: CompareText): string =>
|
|
33
|
+
` ${kindColumn(pair.before.kind, text)}${shown(pair.before.text)} → ${shown(pair.after.text)} (${text.lines(pair.before.line, pair.after.line)})`;
|
|
34
|
+
|
|
35
|
+
const block = (heading: string, lines: readonly string[]): string[] => (lines.length === 0 ? [] : ["", heading, ...lines]);
|
|
36
|
+
|
|
37
|
+
const unreadBlock = (outcome: Outcome, text: CompareText): string[] => {
|
|
38
|
+
const sides = [outcome.before, outcome.after];
|
|
39
|
+
const lines = sides.flatMap((side) => side.unread.map((unread) => ` ${side.path}: ${text.unread(unread.kind, unread.reason)}`));
|
|
40
|
+
return block(text.unreadHeading, lines);
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/** For a person: what was dropped and added, with the line in each file, then what only changed its form. */
|
|
44
|
+
export const renderFriendly = (outcome: Outcome, text: CompareText): string => {
|
|
45
|
+
const { before, after } = outcome;
|
|
46
|
+
return [
|
|
47
|
+
`${before.path} → ${after.path}`,
|
|
48
|
+
...block(
|
|
49
|
+
text.droppedHeading(outcome.dropped.length, before.path, after.path),
|
|
50
|
+
outcome.dropped.map((change) => changeLine(change, before.path, "--allow-dropped", text)),
|
|
51
|
+
),
|
|
52
|
+
...block(
|
|
53
|
+
text.addedHeading(outcome.added.length, after.path),
|
|
54
|
+
outcome.added.map((change) => changeLine(change, after.path, "--allow-added", text)),
|
|
55
|
+
),
|
|
56
|
+
...block(
|
|
57
|
+
text.reformedHeading(outcome.reformed.length),
|
|
58
|
+
outcome.reformed.map((pair) => reformedLine(pair, text)),
|
|
59
|
+
),
|
|
60
|
+
...unreadBlock(outcome, text),
|
|
61
|
+
"",
|
|
62
|
+
checkedLine(outcome, text),
|
|
63
|
+
verdict(outcome, text),
|
|
64
|
+
].join("\n");
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const compactChange = (change: Change, path: string, word: string): string =>
|
|
68
|
+
`${path}:${String(change.line)}: ${word} ${change.kind} ${shown(change.text)}${change.allowed ? " (allowed)" : ""}`;
|
|
69
|
+
|
|
70
|
+
/** For an engineer and grep: one line per fact, the words dropped / added / reformed and the kind in English. */
|
|
71
|
+
export const renderCompact = (outcome: Outcome, text: CompareText): string => {
|
|
72
|
+
const { before, after } = outcome;
|
|
73
|
+
return [
|
|
74
|
+
...outcome.dropped.map((change) => compactChange(change, before.path, "dropped")),
|
|
75
|
+
...outcome.added.map((change) => compactChange(change, after.path, "added")),
|
|
76
|
+
...outcome.reformed.map(
|
|
77
|
+
(pair) =>
|
|
78
|
+
`${before.path}:${String(pair.before.line)} → ${after.path}:${String(pair.after.line)}: reformed ${pair.before.kind} ${shown(pair.before.text)} → ${shown(pair.after.text)}`,
|
|
79
|
+
),
|
|
80
|
+
...before.unread.map((unread) => `${before.path}: unread ${unread.kind} (${unread.reason})`),
|
|
81
|
+
...after.unread.map((unread) => `${after.path}: unread ${unread.kind} (${unread.reason})`),
|
|
82
|
+
checkedLine(outcome, text),
|
|
83
|
+
text.tally(failing(outcome.dropped), failing(outcome.added), outcome.reformed.length),
|
|
84
|
+
].join("\n");
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const atomJson = (atom: Atom): Readonly<Record<string, string | number>> => ({ kind: atom.kind, key: atom.key, text: atom.text, line: atom.line });
|
|
88
|
+
|
|
89
|
+
/** For an AI to act on: every dropped and added fact with its line, the reformed pairs, and the counts per kind. */
|
|
90
|
+
export const renderJson = (outcome: Outcome): string =>
|
|
91
|
+
JSON.stringify(
|
|
92
|
+
{
|
|
93
|
+
ok: outcome.ok,
|
|
94
|
+
before: outcome.before,
|
|
95
|
+
after: outcome.after,
|
|
96
|
+
dropped: outcome.dropped.map((change) => ({ ...atomJson(change), allowed: change.allowed })),
|
|
97
|
+
added: outcome.added.map((change) => ({ ...atomJson(change), allowed: change.allowed })),
|
|
98
|
+
reformed: outcome.reformed.map((pair) => ({ kind: pair.before.kind, key: pair.before.key, before: atomJson(pair.before), after: atomJson(pair.after) })),
|
|
99
|
+
},
|
|
100
|
+
null,
|
|
101
|
+
2,
|
|
102
|
+
);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Span } from "../plugin.ts";
|
|
2
|
+
import { firstEndingAfter } from "../soft-break.ts";
|
|
3
|
+
import { mergeSpans } from "../span-merge.ts";
|
|
4
|
+
|
|
5
|
+
/** Spans made ready for lookups: sorted and merged, so each lookup is a binary search, not a scan of every span. */
|
|
6
|
+
export type SpanIndex = readonly Span[];
|
|
7
|
+
|
|
8
|
+
export const spanIndex = (spans: readonly Span[]): SpanIndex => mergeSpans(spans, false);
|
|
9
|
+
|
|
10
|
+
/** Whether span shares at least one character with a span in the index. */
|
|
11
|
+
export const overlapsAny = (index: SpanIndex, span: Span): boolean => {
|
|
12
|
+
const region = index[firstEndingAfter(index, span.start)];
|
|
13
|
+
return region !== undefined && region.start < span.end;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/** Whether the character at offset is inside a span in the index. */
|
|
17
|
+
export const coversOffset = (index: SpanIndex, offset: number): boolean => overlapsAny(index, { start: offset, end: offset + 1 });
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { QUOTATION_MARKS, quotedSpans } from "../quoted-span.ts";
|
|
2
|
+
import type { Span } from "../plugin.ts";
|
|
3
|
+
import type { Atom } from "./atom.ts";
|
|
4
|
+
import { coversOffset, overlapsAny, spanIndex, type SpanIndex } from "./spans.ts";
|
|
5
|
+
|
|
6
|
+
/** Where a reader looks, and how it says where it found something. */
|
|
7
|
+
export type TextInput = { readonly text: string; readonly source: string; readonly lineOf: (offset: number) => number };
|
|
8
|
+
|
|
9
|
+
/** A fact found in the text: where it is and its key. */
|
|
10
|
+
export type Found = Span & { readonly key: string };
|
|
11
|
+
|
|
12
|
+
export const atomsOf = (found: readonly Found[], kind: Atom["kind"], input: TextInput): Atom[] =>
|
|
13
|
+
found.map((fact) => ({ kind, key: fact.key, text: input.source.slice(fact.start, fact.end), line: input.lineOf(fact.start) }));
|
|
14
|
+
|
|
15
|
+
const DIGIT = "[0-90-9]";
|
|
16
|
+
const DATE_SEPARATOR = "[-/./.]";
|
|
17
|
+
|
|
18
|
+
/** 2026/4/1, 2026-04-01, 2026.4.1: a year of four digits first, so the order is never in doubt. */
|
|
19
|
+
const NUMERIC_DATE = new RegExp(`(?<![0-90-9])(${DIGIT}{4})${DATE_SEPARATOR}(${DIGIT}{1,2})${DATE_SEPARATOR}(${DIGIT}{1,2})(?![0-90-9])`, "gu");
|
|
20
|
+
|
|
21
|
+
const MONTHS = 12;
|
|
22
|
+
const LAST_DAY = 31;
|
|
23
|
+
const PADDED = 2;
|
|
24
|
+
|
|
25
|
+
const dateKey = (year: string, month: string, day: string): string | undefined => {
|
|
26
|
+
const [m, d] = [Number(month.normalize("NFKC")), Number(day.normalize("NFKC"))];
|
|
27
|
+
if (m < 1 || m > MONTHS || d < 1 || d > LAST_DAY) return undefined;
|
|
28
|
+
return [year.normalize("NFKC"), String(m).padStart(PADDED, "0"), String(d).padStart(PADDED, "0")].join("-");
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/** Dates written in figures only, where the language's date reader did not already read a date. */
|
|
32
|
+
export const numericDates = (text: string, taken: SpanIndex): Found[] =>
|
|
33
|
+
[...text.matchAll(NUMERIC_DATE)].flatMap((match) => {
|
|
34
|
+
const key = dateKey(match[1] ?? "", match[2] ?? "", match[3] ?? "");
|
|
35
|
+
const span = { start: match.index, end: match.index + match[0].length };
|
|
36
|
+
return key === undefined || overlapsAny(taken, span) ? [] : [{ ...span, key }];
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
/** A footnote mark `[^1]`, or the footnote itself `[^1]:`. */
|
|
40
|
+
const FOOTNOTE = /\[\^[^\]\s]+\]:?/gu;
|
|
41
|
+
|
|
42
|
+
export const footnotes = (text: string): Found[] =>
|
|
43
|
+
[...text.matchAll(FOOTNOTE)].map((match) => ({ start: match.index, end: match.index + match[0].length, key: match[0] }));
|
|
44
|
+
|
|
45
|
+
/** 1,200 or 12.5 or 3: the digits, a thousands separator only between groups of three, and a decimal part. */
|
|
46
|
+
const NUMBER = /[0-90-9]+(?:[,,][0-90-9]{3})*(?:[..][0-90-9]+)?/gu;
|
|
47
|
+
|
|
48
|
+
const valueOf = (written: string): string => String(Number(written.normalize("NFKC").replace(/,/gu, "")));
|
|
49
|
+
|
|
50
|
+
/** Numbers no other reader took: written with no unit the language package knows, or with none at all. */
|
|
51
|
+
export const bareNumbers = (input: TextInput, taken: SpanIndex): Atom[] =>
|
|
52
|
+
[...input.text.matchAll(NUMBER)].flatMap((match): Atom[] => {
|
|
53
|
+
if (coversOffset(taken, match.index)) return [];
|
|
54
|
+
const value = valueOf(match[0]);
|
|
55
|
+
return [{ kind: "number", key: `${value} `, text: match[0], line: input.lineOf(match.index), unitless: true, value }];
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
/** A paragraph break: a quotation does not run over one, and reading paragraph by paragraph keeps each read short. */
|
|
59
|
+
const PARAGRAPH_BREAK = /\n[ \t]*\n/gu;
|
|
60
|
+
|
|
61
|
+
const paragraphsOf = (text: string): Span[] => {
|
|
62
|
+
const breaks = [...text.matchAll(PARAGRAPH_BREAK)].map((match) => match.index);
|
|
63
|
+
return [-1, ...breaks].map((from, index) => ({ start: from + 1, end: breaks[index] ?? text.length }));
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
/** What is quoted, as one spelling: line breaks and runs of spaces are how it was wrapped, not what it says. */
|
|
67
|
+
const quoteKey = (inner: string): string => inner.normalize("NFKC").replace(/\s+/gu, " ").trim();
|
|
68
|
+
|
|
69
|
+
/** Quoted strings: 「」『』, “” and "". The key is what is inside; the marks are how it is written. */
|
|
70
|
+
export const quotations = (input: TextInput): Atom[] =>
|
|
71
|
+
paragraphsOf(input.text).flatMap((paragraph) =>
|
|
72
|
+
quotedSpans(input.text.slice(paragraph.start, paragraph.end), QUOTATION_MARKS).flatMap((inner) => {
|
|
73
|
+
const key = quoteKey(input.text.slice(paragraph.start + inner.start, paragraph.start + inner.end));
|
|
74
|
+
const span = { start: paragraph.start + inner.start - 1, end: paragraph.start + inner.end + 1 };
|
|
75
|
+
return key === "" ? [] : atomsOf([{ ...span, key }], "quote", input);
|
|
76
|
+
}),
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
const occurrences = (text: string, name: string): Span[] => {
|
|
80
|
+
const found: Span[] = [];
|
|
81
|
+
for (let at = text.indexOf(name); at !== -1; at = text.indexOf(name, at + name.length)) found.push({ start: at, end: at + name.length });
|
|
82
|
+
return found;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
/** The team's own names (chaff.yaml's `names:`), wherever they are written. Longer names first: "Acme Cloud" before "Acme". */
|
|
86
|
+
export const teamNames = (text: string, names: readonly string[]): Found[] => {
|
|
87
|
+
const longestFirst = [...new Set(names.filter((name) => name !== ""))].toSorted((left, right) => right.length - left.length);
|
|
88
|
+
return longestFirst
|
|
89
|
+
.reduce<Found[]>((taken, name) => {
|
|
90
|
+
const index = spanIndex(taken);
|
|
91
|
+
const fresh = occurrences(text, name).filter((span) => !overlapsAny(index, span));
|
|
92
|
+
return [...taken, ...fresh.map((span) => ({ ...span, key: name }))];
|
|
93
|
+
}, [])
|
|
94
|
+
.toSorted((left, right) => left.start - right.start);
|
|
95
|
+
};
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import type { Texts } from "../ui.ts";
|
|
2
|
+
import type { AtomKind, UnreadReason } from "./atom.ts";
|
|
3
|
+
import { counted } from "../render/plural.ts";
|
|
4
|
+
|
|
5
|
+
export type CompareText = {
|
|
6
|
+
readonly usage: string;
|
|
7
|
+
readonly unknownKind: (kind: string, kinds: string) => string;
|
|
8
|
+
/** A kind counted (numbers 3→3) and a kind of one fact (number: 1,000円). */
|
|
9
|
+
readonly kinds: Readonly<Record<AtomKind, string>>;
|
|
10
|
+
readonly kind: Readonly<Record<AtomKind, string>>;
|
|
11
|
+
readonly unread: (kind: AtomKind, reason: UnreadReason) => string;
|
|
12
|
+
readonly unreadHeading: string;
|
|
13
|
+
readonly droppedHeading: (count: number, before: string, after: string) => string;
|
|
14
|
+
readonly addedHeading: (count: number, after: string) => string;
|
|
15
|
+
readonly reformedHeading: (count: number) => string;
|
|
16
|
+
readonly allowed: (flag: string) => string;
|
|
17
|
+
readonly lines: (before: number, after: number) => string;
|
|
18
|
+
readonly checked: (before: number, after: number, perKind: string) => string;
|
|
19
|
+
readonly separator: string;
|
|
20
|
+
readonly clean: string;
|
|
21
|
+
readonly failed: (dropped: number, added: number) => string;
|
|
22
|
+
/** The tally of the compact output. */
|
|
23
|
+
readonly tally: (dropped: number, added: number, reformed: number) => string;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const KINDS_JA: Readonly<Record<AtomKind, string>> = {
|
|
27
|
+
number: "数",
|
|
28
|
+
date: "日付",
|
|
29
|
+
time: "時刻",
|
|
30
|
+
url: "URL",
|
|
31
|
+
code: "コード",
|
|
32
|
+
name: "固有名詞",
|
|
33
|
+
quote: "引用",
|
|
34
|
+
heading: "見出し",
|
|
35
|
+
reference: "条項の参照",
|
|
36
|
+
footnote: "脚注",
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const KINDS_EN: Readonly<Record<AtomKind, string>> = {
|
|
40
|
+
number: "numbers",
|
|
41
|
+
date: "dates",
|
|
42
|
+
time: "times",
|
|
43
|
+
url: "URLs",
|
|
44
|
+
code: "code",
|
|
45
|
+
name: "names",
|
|
46
|
+
quote: "quotations",
|
|
47
|
+
heading: "headings",
|
|
48
|
+
reference: "references",
|
|
49
|
+
footnote: "footnotes",
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const KIND_EN: Readonly<Record<AtomKind, string>> = {
|
|
53
|
+
number: "number",
|
|
54
|
+
date: "date",
|
|
55
|
+
time: "time",
|
|
56
|
+
url: "URL",
|
|
57
|
+
code: "code",
|
|
58
|
+
name: "name",
|
|
59
|
+
quote: "quotation",
|
|
60
|
+
heading: "heading",
|
|
61
|
+
reference: "reference",
|
|
62
|
+
footnote: "footnote",
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const UNREAD_JA: Readonly<Record<UnreadReason, (kind: AtomKind) => string>> = {
|
|
66
|
+
"no-structure": (kind) =>
|
|
67
|
+
kind === "number" ? "言語パッケージが単位を読まないので、数字だけを比べました" : "言語パッケージが文書の構造を読まないので、読んでいません",
|
|
68
|
+
"no-dates": () => "言語パッケージが日付を読まないので、数字だけで書いた日付(2026-04-01)だけを比べました",
|
|
69
|
+
"no-pos": () => "品詞を読む解析器が無いので、chaff.yaml の names: だけを比べました",
|
|
70
|
+
"plain-text": () => "Markdown ではないので、コードの記法がありません",
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const UNREAD_EN: Readonly<Record<UnreadReason, (kind: AtomKind) => string>> = {
|
|
74
|
+
"no-structure": (kind) =>
|
|
75
|
+
kind === "number"
|
|
76
|
+
? "the language package reads no units, so only the figures were compared"
|
|
77
|
+
: "the language package reads no document structure, so none were read",
|
|
78
|
+
"no-dates": () => "the language package reads no dates, so only dates written in figures (2026-04-01) were compared",
|
|
79
|
+
"no-pos": () => "there is no part-of-speech tagger, so only chaff.yaml's names: were compared",
|
|
80
|
+
"plain-text": () => "the document is not Markdown, so it has no code markup",
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export const COMPARE_TEXT: Texts<CompareText> = {
|
|
84
|
+
ja: {
|
|
85
|
+
usage: "使い方: chaff compare <書き換える前> <書き換えた後> [--compact | --json] [--allow-dropped <種類>] [--allow-added <種類>] [--language ja|en|…]",
|
|
86
|
+
unknownKind: (kind, kinds) => `知らない種類です: ${kind}(使えるのは ${kinds})`,
|
|
87
|
+
kinds: KINDS_JA,
|
|
88
|
+
kind: KINDS_JA,
|
|
89
|
+
unread: (kind, reason) => `${KINDS_JA[kind]}: ${UNREAD_JA[reason](kind)}`,
|
|
90
|
+
unreadHeading: "読めなかったもの",
|
|
91
|
+
droppedHeading: (count, before, after) => `✗ 落ちた事実 ${String(count)} 件(${before} にあって ${after} に無い)`,
|
|
92
|
+
addedHeading: (count, after) => `✗ 足された事実 ${String(count)} 件(${after} にだけある)`,
|
|
93
|
+
reformedHeading: (count) => `i 書き方だけ変わった事実 ${String(count)} 件`,
|
|
94
|
+
allowed: (flag) => `(${flag} で許可)`,
|
|
95
|
+
lines: (before, after) => `${String(before)} 行目 → ${String(after)} 行目`,
|
|
96
|
+
checked: (before, after, perKind) => `照合した事実 ${String(before)} 件 → ${String(after)} 件: ${perKind}`,
|
|
97
|
+
separator: "、",
|
|
98
|
+
clean: "落ちた事実も足された事実もありません",
|
|
99
|
+
failed: (dropped, added) => `落ちた事実 ${String(dropped)} 件、足された事実 ${String(added)} 件`,
|
|
100
|
+
tally: (dropped, added, reformed) => `落ちた ${String(dropped)} 件、足された ${String(added)} 件、書き方だけ ${String(reformed)} 件`,
|
|
101
|
+
},
|
|
102
|
+
en: {
|
|
103
|
+
usage: "usage: chaff compare <before> <after> [--compact | --json] [--allow-dropped <kind>] [--allow-added <kind>] [--language ja|en|…]",
|
|
104
|
+
unknownKind: (kind, kinds) => `Unknown kind: ${kind} (the kinds are ${kinds})`,
|
|
105
|
+
kinds: KINDS_EN,
|
|
106
|
+
kind: KIND_EN,
|
|
107
|
+
unread: (kind, reason) => `${KINDS_EN[kind]}: ${UNREAD_EN[reason](kind)}`,
|
|
108
|
+
unreadHeading: "Not fully read",
|
|
109
|
+
droppedHeading: (count, before, after) => `✗ ${counted(count, "fact")} dropped (in ${before}, not in ${after})`,
|
|
110
|
+
addedHeading: (count, after) => `✗ ${counted(count, "fact")} added (only in ${after})`,
|
|
111
|
+
reformedHeading: (count) => `i ${counted(count, "fact")} written another way`,
|
|
112
|
+
allowed: (flag) => ` (allowed by ${flag})`,
|
|
113
|
+
lines: (before, after) => `line ${String(before)} → line ${String(after)}`,
|
|
114
|
+
checked: (before, after, perKind) => `Facts checked: ${String(before)} → ${String(after)}: ${perKind}`,
|
|
115
|
+
separator: ", ",
|
|
116
|
+
clean: "No fact dropped or added",
|
|
117
|
+
failed: (dropped, added) => `${counted(dropped, "fact")} dropped, ${counted(added, "fact")} added`,
|
|
118
|
+
tally: (dropped, added, reformed) => `${String(dropped)} dropped, ${String(added)} added, ${String(reformed)} written another way`,
|
|
119
|
+
},
|
|
120
|
+
};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { preOrder } from "../tree-walk.ts";
|
|
2
|
+
import type { Span, StructureNode } from "../plugin.ts";
|
|
3
|
+
import type { Atom, AtomKind } from "./atom.ts";
|
|
4
|
+
import { coversOffset, overlapsAny, type SpanIndex } from "./spans.ts";
|
|
5
|
+
|
|
6
|
+
/** Facts the structure reader found, and where they are written, so no other reader reads the same digits again. */
|
|
7
|
+
export type TreeFacts = { readonly atoms: readonly Atom[]; readonly taken: readonly Span[] };
|
|
8
|
+
|
|
9
|
+
export type TreeInput = {
|
|
10
|
+
readonly tree: StructureNode;
|
|
11
|
+
readonly source: string;
|
|
12
|
+
/** Code and URLs: what the reader found there belongs to them. */
|
|
13
|
+
readonly blanked: SpanIndex;
|
|
14
|
+
/** Times of day: 3時30分 is one time, not the quantities 3 時 and 30 分. */
|
|
15
|
+
readonly times: SpanIndex;
|
|
16
|
+
readonly lineOf: (offset: number) => number;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/** Numbered units that are the document's own structure. Items (a list's 1. 2. 3.) are left out: prose may replace a list. */
|
|
20
|
+
const NUMBERED: ReadonlySet<string> = new Set(["chapter", "article"]);
|
|
21
|
+
|
|
22
|
+
const attr = (node: StructureNode, name: string): string => String(node.attrs[name] ?? "");
|
|
23
|
+
|
|
24
|
+
/** The unit as one spelling: GB and GB, % and % are one unit. */
|
|
25
|
+
const unitKey = (unit: string): string => unit.normalize("NFKC");
|
|
26
|
+
|
|
27
|
+
const quantityAtom = (node: StructureNode, text: string, line: number): Atom => {
|
|
28
|
+
const value = attr(node, "value");
|
|
29
|
+
return { kind: "number", key: `${value} ${unitKey(attr(node, "unit"))}`, text, line, value };
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/** The same section in another wording: Section 4.2 and § 4.2 point at one place; Article 4.2 does not. */
|
|
33
|
+
const referenceKey = (node: StructureNode): string => {
|
|
34
|
+
const numbering = attr(node, "numbering") || attr(node, "unitWord");
|
|
35
|
+
const document = attr(node, "document");
|
|
36
|
+
return [numbering, attr(node, "target"), document === "" ? "" : `@${document}`].filter((part) => part !== "").join(" ");
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const leafAtom = (node: StructureNode, kind: AtomKind, text: string, line: number): Atom => {
|
|
40
|
+
if (kind === "number") return quantityAtom(node, text, line);
|
|
41
|
+
return { kind, key: kind === "date" ? attr(node, "value") : referenceKey(node), text, line };
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const LEAF_KINDS: Readonly<Partial<Record<string, AtomKind>>> = { quantity: "number", date: "date", reference: "reference" };
|
|
45
|
+
|
|
46
|
+
/** The label's place on its line (第3条 after "## "), or none when the line does not spell it. */
|
|
47
|
+
const labelSpan = (node: StructureNode, source: string): Span[] => {
|
|
48
|
+
const label = attr(node, "label");
|
|
49
|
+
const lineEnd = source.indexOf("\n", node.span.start);
|
|
50
|
+
const at = source.indexOf(label, node.span.start);
|
|
51
|
+
return label === "" || at === -1 || (lineEnd !== -1 && at > lineEnd) ? [] : [{ start: at, end: at + label.length }];
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const numberedFacts = (node: StructureNode, input: TreeInput): TreeFacts => {
|
|
55
|
+
const heading = attr(node, "heading");
|
|
56
|
+
const text = [attr(node, "label"), heading].filter((part) => part !== "").join(" ");
|
|
57
|
+
return { atoms: [{ kind: "heading", key: `${node.kind} ${node.address}`, text, line: node.line }], taken: labelSpan(node, input.source) };
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const nodeFacts = (node: StructureNode, input: TreeInput): TreeFacts => {
|
|
61
|
+
if (NUMBERED.has(node.kind)) return numberedFacts(node, input);
|
|
62
|
+
const kind = LEAF_KINDS[node.kind];
|
|
63
|
+
if (kind === undefined || coversOffset(input.blanked, node.span.start)) return { atoms: [], taken: [] };
|
|
64
|
+
if (kind === "number" && overlapsAny(input.times, node.span)) return { atoms: [], taken: [] };
|
|
65
|
+
const span = withUnitAfter(node, input.source);
|
|
66
|
+
const text = input.source.slice(span.start, span.end);
|
|
67
|
+
return { atoms: [leafAtom(node, kind, text, input.lineOf(span.start))], taken: [span] };
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
/** A quantity's span may stop before the unit written right after it (25 of 25%); the fact is shown with its unit. */
|
|
71
|
+
const withUnitAfter = (node: StructureNode, source: string): Span => {
|
|
72
|
+
const unit = attr(node, "unit");
|
|
73
|
+
return unit !== "" && source.startsWith(unit, node.span.end) ? { start: node.span.start, end: node.span.end + unit.length } : node.span;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
/** Numbers with their unit, dates, references to articles and sections, and the numbered articles themselves. */
|
|
77
|
+
export const treeFacts = (input: TreeInput): TreeFacts => {
|
|
78
|
+
const facts = preOrder(input.tree).map((node) => nodeFacts(node, input));
|
|
79
|
+
return { atoms: facts.flatMap((fact) => fact.atoms), taken: facts.flatMap((fact) => fact.taken) };
|
|
80
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Atom } from "./atom.ts";
|
|
2
|
+
|
|
3
|
+
const occurrences = (text: string, needle: string): number => {
|
|
4
|
+
let count = 0;
|
|
5
|
+
for (let at = text.indexOf(needle); at !== -1 && needle !== ""; at = text.indexOf(needle, at + needle.length)) count += 1;
|
|
6
|
+
return count;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
const namesPerKey = (atoms: readonly Atom[]): Map<string, number> =>
|
|
10
|
+
atoms.reduce((counts, atom) => (atom.kind === "name" ? counts.set(atom.key, (counts.get(atom.key) ?? 0) + 1) : counts), new Map<string, number>());
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The names among changes that the other document does not write as often as this one names them. The tagger reads
|
|
14
|
+
* a word as a name by its context (赤松 after から, Scammers before could), so a rewrite can change the tagging without
|
|
15
|
+
* changing the name; the spelling decides. otherText is the other document's prose spelled as name keys are.
|
|
16
|
+
*/
|
|
17
|
+
export const unwrittenNames = (changes: readonly Atom[], own: readonly Atom[], otherText: string): Atom[] => {
|
|
18
|
+
const named = namesPerKey(own);
|
|
19
|
+
const left = new Map<string, number>();
|
|
20
|
+
return changes.filter((atom) => {
|
|
21
|
+
if (atom.kind !== "name") return true;
|
|
22
|
+
const remaining = left.get(atom.key) ?? Math.max(0, (named.get(atom.key) ?? 0) - occurrences(otherText, atom.key));
|
|
23
|
+
left.set(atom.key, Math.max(0, remaining - 1));
|
|
24
|
+
return remaining > 0;
|
|
25
|
+
});
|
|
26
|
+
};
|
package/src/config/load.ts
CHANGED
|
@@ -37,6 +37,22 @@ export type Config = {
|
|
|
37
37
|
/** パスごとの上書き。設定ファイルのある場所からの相対で照合する。 */
|
|
38
38
|
readonly byPath: readonly PathRule[];
|
|
39
39
|
readonly baseDir: string;
|
|
40
|
+
/** Options set on rules that take them: { rule id: { option: value } }, as written. rule-options.ts checks them against the rules. */
|
|
41
|
+
readonly options?: Readonly<Record<string, unknown>>;
|
|
42
|
+
/** options as written when it is not a map. Dropping it silently would leave a team thinking its options apply. */
|
|
43
|
+
readonly unreadableOptions?: string | undefined;
|
|
44
|
+
/** The house style chaff.yaml names (styles/*.yaml), as written. A value that is not a name is kept printed, to be reported. */
|
|
45
|
+
readonly style?: string | undefined;
|
|
46
|
+
/** The style once applied (config/style.ts): its id, the rules whose level it decided, and its options. */
|
|
47
|
+
readonly applied?: AppliedStyle | undefined;
|
|
48
|
+
/** custom_rules as written: the team's own rules. custom/parse.ts reads and checks them. */
|
|
49
|
+
readonly customRules?: unknown;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export type AppliedStyle = {
|
|
53
|
+
readonly style: string;
|
|
54
|
+
readonly levelsFrom: readonly string[];
|
|
55
|
+
readonly options: Readonly<Record<string, unknown>>;
|
|
40
56
|
};
|
|
41
57
|
|
|
42
58
|
/** 判定の質が誤検知に直結するので、既定は最上位のモデル。cost は絞り込みで削る。spec §14。 */
|
|
@@ -144,6 +160,7 @@ export const loadConfig = (path: string): Config => {
|
|
|
144
160
|
const declared: unknown = raw["ai_backend"];
|
|
145
161
|
const backend: BackendName = isBackend(declared) ? declared : DEFAULT_BACKEND;
|
|
146
162
|
const names = namesOf(raw["names"]);
|
|
163
|
+
const options: unknown = raw["options"];
|
|
147
164
|
return {
|
|
148
165
|
genre: str(raw["genre"]),
|
|
149
166
|
profile: str(raw["profile"]),
|
|
@@ -163,5 +180,9 @@ export const loadConfig = (path: string): Config => {
|
|
|
163
180
|
unreadableNames: names.unreadable,
|
|
164
181
|
byPath: byPathOf(raw["by_path"]),
|
|
165
182
|
baseDir: dirname(path),
|
|
183
|
+
options: isRecord(options) ? options : {},
|
|
184
|
+
unreadableOptions: options === undefined || options === null || isRecord(options) ? undefined : printed(options),
|
|
185
|
+
style: raw["style"] === undefined || raw["style"] === null ? undefined : (str(raw["style"]) ?? printed(raw["style"])),
|
|
186
|
+
customRules: raw["custom_rules"],
|
|
166
187
|
};
|
|
167
188
|
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { CONFIG_FILE, type Config } from "./load.ts";
|
|
2
|
+
import type { RuleDefinition, RuleOption } from "../plugin.ts";
|
|
3
|
+
import { optionProblems, type OptionLayer, type OptionProblem } from "../rule-options.ts";
|
|
4
|
+
import { styleLevelSource, styleSource } from "./style.ts";
|
|
5
|
+
import type { Texts, UiLanguage } from "../ui.ts";
|
|
6
|
+
|
|
7
|
+
/** Where chaff.yaml's options come from, for settleOptions: the file itself. */
|
|
8
|
+
export const configOptionLayer = (config: Pick<Config, "options">): OptionLayer => ({
|
|
9
|
+
from: CONFIG_FILE,
|
|
10
|
+
values: config.options ?? {},
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
/** Where a rule's settings come from, for explain: the option layers, and the style when it set the level. */
|
|
14
|
+
export const settingSourcesOf = (
|
|
15
|
+
config: Pick<Config, "options" | "applied">,
|
|
16
|
+
ruleId: string,
|
|
17
|
+
): { optionLayers: OptionLayer[]; levelFrom: string | undefined } => ({
|
|
18
|
+
optionLayers: optionLayersOf(config),
|
|
19
|
+
levelFrom: styleLevelSource(config, ruleId),
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
/** Every place options come from, strongest first: chaff.yaml, then its style. */
|
|
23
|
+
export const optionLayersOf = (config: Pick<Config, "options" | "applied">): OptionLayer[] => [
|
|
24
|
+
configOptionLayer(config),
|
|
25
|
+
...(config.applied === undefined ? [] : [{ from: styleSource(config.applied.style), values: config.applied.options }]),
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
type ProblemText = {
|
|
29
|
+
readonly notAMap: (where: string, value: string) => string;
|
|
30
|
+
readonly problem: (where: string, problem: OptionProblem) => string;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const TEXT: Texts<ProblemText> = {
|
|
34
|
+
ja: {
|
|
35
|
+
notAMap: (where, value) => `${where}: options の ${value} は読めません。ルールの名前の下に、オプションの名前と値を並べてください`,
|
|
36
|
+
problem: (where, problem) => {
|
|
37
|
+
if (problem.kind === "unknown-rule") return `${where}: options の ${problem.rule} というルールはありません(npx chaff rules --json で一覧が出ます)`;
|
|
38
|
+
if (problem.kind === "no-options") return `${where}: ${problem.rule} にはオプションがありません。options に書いても何も変わりません`;
|
|
39
|
+
if (problem.kind === "not-a-map") return `${where}: options の ${problem.rule} の下には、オプションの名前と値を並べてください`;
|
|
40
|
+
if (problem.kind === "unknown-option")
|
|
41
|
+
return `${where}: ${problem.rule} に ${problem.option} というオプションはありません(使えるのは ${problem.known.join(" / ")})`;
|
|
42
|
+
return `${where}: ${problem.rule} の ${problem.option} の値 ${problem.value} は読めません(${problem.expected})。既定のまま動きます`;
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
en: {
|
|
46
|
+
notAMap: (where, value) => `${where}: cannot read ${value} under options. Under each rule's name, list option names and values`,
|
|
47
|
+
problem: (where, problem) => {
|
|
48
|
+
if (problem.kind === "unknown-rule") return `${where}: there is no rule named ${problem.rule} under options (npx chaff rules --json lists them)`;
|
|
49
|
+
if (problem.kind === "no-options") return `${where}: ${problem.rule} takes no options, so writing some changes nothing`;
|
|
50
|
+
if (problem.kind === "not-a-map") return `${where}: under options, ${problem.rule} needs option names and values`;
|
|
51
|
+
if (problem.kind === "unknown-option") return `${where}: ${problem.rule} has no option ${problem.option} (it takes ${problem.known.join(" / ")})`;
|
|
52
|
+
return `${where}: cannot read ${problem.value} as ${problem.rule}'s ${problem.option} (${problem.expected}); it stays at its default`;
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const optionsByRule = (rules: readonly RuleDefinition[]): Record<string, Readonly<Record<string, RuleOption>>> =>
|
|
58
|
+
Object.fromEntries(rules.map((rule) => [rule.id, rule.options ?? {}]));
|
|
59
|
+
|
|
60
|
+
/** chaff.yaml's options that change nothing. Said on every run, like an unknown rule under rules: silence would look like it applied. */
|
|
61
|
+
export const configOptionProblems = (
|
|
62
|
+
config: Pick<Config, "options" | "unreadableOptions" | "path">,
|
|
63
|
+
rules: readonly RuleDefinition[],
|
|
64
|
+
ui: UiLanguage,
|
|
65
|
+
): string[] => {
|
|
66
|
+
const text = TEXT[ui];
|
|
67
|
+
const where = config.path ?? "chaff.yaml";
|
|
68
|
+
if (config.unreadableOptions !== undefined) return [text.notAMap(where, config.unreadableOptions)];
|
|
69
|
+
return optionProblems(configOptionLayer(config), optionsByRule(rules)).map((problem) => text.problem(where, problem));
|
|
70
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { CONFIG_FILE, EMPTY, loadConfig, type Config } from "./load.ts";
|
|
4
|
+
import { withStyle } from "./style.ts";
|
|
5
|
+
import { loadStyles } from "../style-load.ts";
|
|
6
|
+
|
|
7
|
+
/** The chaff.yaml in dir with its style applied, or the defaults when there is none. */
|
|
8
|
+
export const readConfigIn = (dir: string): Config => (existsSync(join(dir, CONFIG_FILE)) ? withStyle(loadConfig(join(dir, CONFIG_FILE)), loadStyles()) : EMPTY);
|
|
@@ -1,21 +1,27 @@
|
|
|
1
1
|
import type { Config } from "./load.ts";
|
|
2
|
+
import type { RuleDefinition } from "../plugin.ts";
|
|
2
3
|
import type { Texts, UiLanguage } from "../ui.ts";
|
|
3
4
|
|
|
4
5
|
const TEXT: Texts<{
|
|
5
6
|
readonly unknown: (where: string, id: string) => string;
|
|
6
7
|
readonly unreadable: (where: string, id: string, value: string) => string;
|
|
7
8
|
readonly numberOnSemantic: (where: string, id: string) => string;
|
|
9
|
+
readonly numberOnSeverity: (where: string, id: string) => string;
|
|
8
10
|
}> = {
|
|
9
11
|
ja: {
|
|
10
12
|
unknown: (where, id) => `${where}: ${id} というルールはありません(npx chaff rules --json で一覧が出ます)`,
|
|
11
13
|
unreadable: (where, id, value) => `${where}: ${id} の値 ${value} は読めません(strict / normal / relaxed / off か、正の数)`,
|
|
12
14
|
numberOnSemantic: (where, id) =>
|
|
13
15
|
`${where}: ${id} は意味を読む検査なので数値の上限はありません。normal として動きます(strict / normal / relaxed / off で書いてください)`,
|
|
16
|
+
numberOnSeverity: (where, id) =>
|
|
17
|
+
`${where}: ${id} には数の上限がありません。normal として動きます(段階は指摘の重さを変えます。relaxed で一段軽く、off で止まります)`,
|
|
14
18
|
},
|
|
15
19
|
en: {
|
|
16
20
|
unknown: (where, id) => `${where}: there is no rule named ${id} (npx chaff rules --json lists them)`,
|
|
17
21
|
unreadable: (where, id, value) => `${where}: cannot read ${value} as the level of ${id} (strict / normal / relaxed / off, or a positive number)`,
|
|
18
22
|
numberOnSemantic: (where, id) => `${where}: ${id} reads meaning and has no numeric limit; it runs as normal (write strict / normal / relaxed / off)`,
|
|
23
|
+
numberOnSeverity: (where, id) =>
|
|
24
|
+
`${where}: ${id} has no numeric limit; it runs as normal (its levels set how a finding is marked: relaxed lowers it a step, off stops it)`,
|
|
19
25
|
},
|
|
20
26
|
};
|
|
21
27
|
|
|
@@ -25,7 +31,7 @@ const TEXT: Texts<{
|
|
|
25
31
|
*/
|
|
26
32
|
export const ruleProblems = (
|
|
27
33
|
config: Pick<Config, "rules" | "limits" | "unreadableRules" | "path">,
|
|
28
|
-
known: readonly
|
|
34
|
+
known: readonly Pick<RuleDefinition, "id" | "layer" | "level_sets">[],
|
|
29
35
|
ui: UiLanguage = "ja",
|
|
30
36
|
): string[] => {
|
|
31
37
|
const text = TEXT[ui];
|
|
@@ -39,5 +45,9 @@ export const ruleProblems = (
|
|
|
39
45
|
const numberOnSemantic = Object.keys(config.limits)
|
|
40
46
|
.filter((id) => semantic.has(id))
|
|
41
47
|
.map((id) => text.numberOnSemantic(where, id));
|
|
42
|
-
|
|
48
|
+
const nothingToCount = new Set(known.filter((rule) => rule.layer !== "L4" && rule.level_sets === "severity").map((rule) => rule.id));
|
|
49
|
+
const numberOnSeverity = Object.keys(config.limits)
|
|
50
|
+
.filter((id) => nothingToCount.has(id))
|
|
51
|
+
.map((id) => text.numberOnSeverity(where, id));
|
|
52
|
+
return [...unknown, ...unreadable, ...numberOnSemantic, ...numberOnSeverity];
|
|
43
53
|
};
|