chaffjs 0.17.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 +2 -0
- package/dist/calendar-number.d.ts.map +1 -1
- package/dist/calendar-number.js +9 -2
- 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/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 +2 -4
- 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 +2 -0
- package/dist/detectors/acronym-context.d.ts.map +1 -1
- package/dist/detectors/acronym-context.js +12 -4
- package/dist/detectors/acronym-context.js.map +1 -1
- 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/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/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 +7 -4
- 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/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 +34 -1
- 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/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/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 +14 -10
- package/dist/detectors/orthography.js.map +1 -1
- package/dist/detectors/oxford-comma.d.ts +7 -1
- package/dist/detectors/oxford-comma.d.ts.map +1 -1
- package/dist/detectors/oxford-comma.js +135 -229
- package/dist/detectors/oxford-comma.js.map +1 -1
- 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 +67 -46
- package/dist/detectors/signals.js.map +1 -1
- 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 +1 -3
- package/dist/detectors/structure.d.ts.map +1 -1
- package/dist/detectors/structure.js +3 -4
- 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 +90 -98
- 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/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 +33 -10
- 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.js +8 -5
- 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 +119 -17
- package/dist/number-name.js.map +1 -1
- package/dist/orthography.d.ts +2 -0
- package/dist/orthography.d.ts.map +1 -1
- package/dist/orthography.js +9 -4
- 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/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 +115 -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.map +1 -1
- package/dist/quoted-span.js +8 -3
- 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 +87 -33
- 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.d.ts +13 -0
- package/dist/run.d.ts.map +1 -1
- package/dist/run.js +54 -10
- package/dist/run.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/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 +76 -30
- 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/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 +26 -0
- 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 +14 -1
- 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 +28 -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 +31 -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 +33 -0
- package/rules/max-sentence-length.yaml +32 -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 +18 -0
- 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 +18 -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 +22 -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 +18 -4
- package/src/cli-args.ts +6 -0
- package/src/cli-text.ts +8 -4
- package/src/cli.ts +37 -37
- 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 +2 -4
- 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 +16 -4
- 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/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/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 +8 -4
- package/src/detectors/heading-level-skip.ts +19 -0
- package/src/detectors/image-alt-text.ts +11 -0
- package/src/detectors/index.ts +43 -1
- package/src/detectors/kutoten-consistency.ts +96 -0
- package/src/detectors/lead-in.ts +3 -1
- package/src/detectors/lexicon-match.ts +9 -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 +23 -17
- package/src/detectors/oxford-comma.ts +178 -283
- 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 +80 -46
- package/src/detectors/structure-tree.ts +45 -1
- package/src/detectors/structure.ts +3 -4
- 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 +106 -138
- 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/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 +52 -9
- 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 +8 -8
- package/src/number-name.ts +151 -24
- package/src/orthography.ts +10 -3
- package/src/page-furniture.ts +11 -2
- package/src/plain-source.ts +2 -1
- package/src/plugin.ts +101 -1
- package/src/profile/for-file.ts +3 -1
- package/src/quoted-span.ts +9 -3
- 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 +91 -34
- package/src/rule-options.ts +131 -0
- package/src/run.ts +74 -11
- package/src/sentence-shape.ts +4 -5
- package/src/setting-problems.ts +7 -1
- package/src/span-cut.ts +28 -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 +77 -30
- 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/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,80 @@
|
|
|
1
|
+
import { loadAdapter } from "../adapter-load.ts";
|
|
2
|
+
import { buildDocument, teamRules } from "../document.ts";
|
|
3
|
+
import { readMarkdown } from "../markdown-read.ts";
|
|
4
|
+
import { profileFor } from "../profile/for-file.ts";
|
|
5
|
+
import { resolveGenre } from "../resolve-genre.ts";
|
|
6
|
+
import { isMarkdownPath } from "../structure/markdown-path.ts";
|
|
7
|
+
import { uiLanguageOf } from "../ui.ts";
|
|
8
|
+
import { ATOM_KINDS, isAtomKind, type AtomKind } from "../compare/atom.ts";
|
|
9
|
+
import { extractFacts } from "../compare/extract.ts";
|
|
10
|
+
import { outcomeOf, type Allowed, type Compared } from "../compare/outcome.ts";
|
|
11
|
+
import { renderCompact, renderFriendly, renderJson } from "../compare/render.ts";
|
|
12
|
+
import { COMPARE_TEXT } from "../compare/text.ts";
|
|
13
|
+
import { readSource, treeLanguage, type TreeContext } from "./tree.ts";
|
|
14
|
+
|
|
15
|
+
/** Options whose value is the next argument. That value is not a file. */
|
|
16
|
+
const VALUED: ReadonlySet<string> = new Set(["--language", "--genre", "--allow-dropped", "--allow-added"]);
|
|
17
|
+
|
|
18
|
+
export const compareTargets = (argv: readonly string[]): string[] =>
|
|
19
|
+
argv.slice(1).filter((arg, index, all) => !arg.startsWith("--") && !VALUED.has(all[index - 1] ?? ""));
|
|
20
|
+
|
|
21
|
+
/** Every value given to a repeatable option, split at commas: `--allow-dropped url,code --allow-dropped quote`. */
|
|
22
|
+
const optionValues = (argv: readonly string[], name: string): string[] =>
|
|
23
|
+
argv.flatMap((arg, index) => (arg === name ? (argv[index + 1] ?? "").split(",") : [])).filter((value) => value !== "");
|
|
24
|
+
|
|
25
|
+
type ParsedAllowed = { readonly allowed: Allowed } | { readonly unknown: string };
|
|
26
|
+
|
|
27
|
+
/** The kinds allowed to be dropped and added, or the first word that is not a kind. */
|
|
28
|
+
const parseAllowed = (argv: readonly string[]): ParsedAllowed => {
|
|
29
|
+
const dropped = optionValues(argv, "--allow-dropped");
|
|
30
|
+
const added = optionValues(argv, "--allow-added");
|
|
31
|
+
const unknown = [...dropped, ...added].find((kind) => !isAtomKind(kind));
|
|
32
|
+
if (unknown !== undefined) return { unknown };
|
|
33
|
+
const kinds = (values: readonly string[]): Set<AtomKind> => new Set(values.filter(isAtomKind));
|
|
34
|
+
return { allowed: { dropped: kinds(dropped), added: kinds(added) } };
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
type Read = Compared & { readonly language: string };
|
|
38
|
+
|
|
39
|
+
/** One document's facts, read as lint reads it: its language, the team's names, and the parts of speech. */
|
|
40
|
+
const readFacts = async (path: string, argv: readonly string[], context: TreeContext): Promise<Read | undefined> => {
|
|
41
|
+
const source = await readSource(path, context);
|
|
42
|
+
if (source === undefined) return undefined;
|
|
43
|
+
const language = treeLanguage(path, source, argv, context);
|
|
44
|
+
const adapter = await loadAdapter(language);
|
|
45
|
+
await adapter.prepare?.({ pos: true });
|
|
46
|
+
const genre = resolveGenre(path, source, context.config, context.flag(argv, "--genre")).genre;
|
|
47
|
+
const doc = buildDocument(path, source, adapter, teamRules(context.config), profileFor(context.config, path, source, language, genre));
|
|
48
|
+
const root = isMarkdownPath(path) ? readMarkdown(doc.source).root : undefined;
|
|
49
|
+
const extraction = extractFacts({ doc, root, structure: adapter.structure, names: context.config.names ?? [] });
|
|
50
|
+
return { path, extraction, language };
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const renderFor = (argv: readonly string[]): typeof renderFriendly => {
|
|
54
|
+
if (argv.includes("--json")) return (outcome) => renderJson(outcome);
|
|
55
|
+
return argv.includes("--compact") ? renderCompact : renderFriendly;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Whether a rewrite kept every fact: numbers, dates, URLs, code, names, quotations, headings, references and footnotes.
|
|
60
|
+
* Compares; never rewrites. Ends with 1 when a fact was dropped or added, so a rewrite can be checked like a test.
|
|
61
|
+
*/
|
|
62
|
+
export const runCompare = async (targets: readonly string[], argv: readonly string[], context: TreeContext): Promise<number> => {
|
|
63
|
+
const host = COMPARE_TEXT[context.ui ?? "ja"];
|
|
64
|
+
const [beforePath, afterPath] = targets;
|
|
65
|
+
if (beforePath === undefined || afterPath === undefined || targets.length !== 2) {
|
|
66
|
+
console.error(host.usage);
|
|
67
|
+
return 1;
|
|
68
|
+
}
|
|
69
|
+
const parsed = parseAllowed(argv);
|
|
70
|
+
if ("unknown" in parsed) {
|
|
71
|
+
console.error(host.unknownKind(parsed.unknown, ATOM_KINDS.join(", ")));
|
|
72
|
+
return 1;
|
|
73
|
+
}
|
|
74
|
+
const before = await readFacts(beforePath, argv, context);
|
|
75
|
+
const after = before === undefined ? undefined : await readFacts(afterPath, argv, context);
|
|
76
|
+
if (before === undefined || after === undefined) return 1;
|
|
77
|
+
const outcome = outcomeOf(before, after, parsed.allowed);
|
|
78
|
+
console.log(renderFor(argv)(outcome, COMPARE_TEXT[uiLanguageOf(before.language)]));
|
|
79
|
+
return outcome.ok ? 0 : 1;
|
|
80
|
+
};
|
package/src/commands/eval.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { plainSource } from "../plain-source.ts";
|
|
2
|
-
import { readFile } from "node:fs/promises";
|
|
3
1
|
import { loadAdapter } from "../adapter-load.ts";
|
|
4
2
|
import { applyByPath } from "../config/by-path.ts";
|
|
5
3
|
import { buildDocument, teamRules } from "../document.ts";
|
|
6
4
|
import { guessLanguage } from "../detect.ts";
|
|
7
|
-
import { collectTargets } from "../files.ts";
|
|
8
|
-
import {
|
|
5
|
+
import { collectTargets, readDocumentFile } from "../files.ts";
|
|
6
|
+
import { rulesOf } from "../custom/load.ts";
|
|
9
7
|
import { evaluate } from "../eval.ts";
|
|
10
8
|
import { renderEval } from "../render/eval.ts";
|
|
11
|
-
import { neededBy } from "../run.ts";
|
|
9
|
+
import { neededBy, tokenFeaturesOf, wantsTags } from "../run.ts";
|
|
10
|
+
import type { AdapterNeeds, RuleDefinition } from "../plugin.ts";
|
|
11
|
+
import { optionLayersOf } from "../config/option-problems.ts";
|
|
12
12
|
import type { Config } from "../config/load.ts";
|
|
13
13
|
import { profileFor } from "../profile/for-file.ts";
|
|
14
14
|
import { CLI_TEXT } from "../cli-text.ts";
|
|
@@ -28,6 +28,16 @@ const TEXT: Texts<{
|
|
|
28
28
|
},
|
|
29
29
|
};
|
|
30
30
|
|
|
31
|
+
/**
|
|
32
|
+
* What the adapter must prepare. eval measures a rule whatever its level, so a rule named with --rule gets the tags and the
|
|
33
|
+
* token features it reads even when lint would not run it; without --rule, the tags are what lint would prepare.
|
|
34
|
+
*/
|
|
35
|
+
const evalNeeds = (rules: readonly RuleDefinition[], only: string | undefined, config: Config, genre: string, language: string): AdapterNeeds => {
|
|
36
|
+
const measured = rules.filter((rule) => only === undefined || rule.id === only);
|
|
37
|
+
const lint = neededBy(rules, config.rules, config.experimental, genre, language);
|
|
38
|
+
return { pos: lint.pos || (only !== undefined && measured.some(wantsTags)), features: tokenFeaturesOf(measured) };
|
|
39
|
+
};
|
|
40
|
+
|
|
31
41
|
export type Context = {
|
|
32
42
|
readonly config: Config;
|
|
33
43
|
readonly resolveGenre: (path: string, source: string, config: Config) => { genre: string; from: string };
|
|
@@ -51,11 +61,11 @@ export const runEval = async (targets: readonly string[], argv: readonly string[
|
|
|
51
61
|
const only = flag(argv, "--rule");
|
|
52
62
|
const docs = await Promise.all(
|
|
53
63
|
paths.map(async (path) => {
|
|
54
|
-
const source =
|
|
64
|
+
const source = await readDocumentFile(path);
|
|
55
65
|
const language = applyByPath(config.byPath, config.baseDir, path).language ?? config.language ?? guessLanguage(source).language;
|
|
56
66
|
const adapter = await loadAdapter(language);
|
|
57
67
|
const { genre } = resolveGenre(path, source, config);
|
|
58
|
-
await adapter.prepare?.(
|
|
68
|
+
await adapter.prepare?.(evalNeeds(rulesOf(language, config), only, config, genre, language));
|
|
59
69
|
return { doc: buildDocument(path, source, adapter, teamRules(config), profileFor(config, path, source, language, genre)), language, genre };
|
|
60
70
|
}),
|
|
61
71
|
);
|
|
@@ -67,7 +77,7 @@ export const runEval = async (targets: readonly string[], argv: readonly string[
|
|
|
67
77
|
console.error(TEXT[ui].mixed([...mixed].join(", ")));
|
|
68
78
|
return 1;
|
|
69
79
|
}
|
|
70
|
-
const rules =
|
|
80
|
+
const rules = rulesOf(language, config).filter((rule) => only === undefined || rule.id === only);
|
|
71
81
|
if (rules.length === 0) {
|
|
72
82
|
console.error(TEXT[ui].unknownRule(only ?? CLI_TEXT[ui].unnamed));
|
|
73
83
|
return 1;
|
|
@@ -80,6 +90,7 @@ export const runEval = async (targets: readonly string[], argv: readonly string[
|
|
|
80
90
|
genre,
|
|
81
91
|
language,
|
|
82
92
|
config.limits,
|
|
93
|
+
optionLayersOf(config),
|
|
83
94
|
),
|
|
84
95
|
docs.length,
|
|
85
96
|
paths.length,
|
package/src/commands/feedback.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { readDocumentFile } from "../files.ts";
|
|
2
2
|
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { basename, join } from "node:path";
|
|
4
4
|
import type { Finding, RuleDefinition } from "../plugin.ts";
|
|
@@ -86,15 +86,21 @@ const chosen = (findings: readonly Finding[], rule: string | undefined, line: nu
|
|
|
86
86
|
const describe = (findings: readonly Finding[], none: string): string =>
|
|
87
87
|
findings.length === 0 ? none : findings.map((finding) => ` ${String(finding.line)} ${finding.rule}`).join("\n");
|
|
88
88
|
|
|
89
|
-
/**
|
|
90
|
-
|
|
89
|
+
/**
|
|
90
|
+
* Pure: the reported rules' own lines of chaff.yaml's rules (a numeric limit wins over a level), under the style chaff.yaml
|
|
91
|
+
* names, or undefined when none is set. A level the style decided is the style's, so only the style line reproduces it.
|
|
92
|
+
*/
|
|
93
|
+
export const settingsOf = (config: Pick<Config, "rules" | "limits" | "applied">, ruleIds: readonly string[]): string | undefined => {
|
|
94
|
+
const fromStyle = new Set(config.applied?.levelsFrom ?? []);
|
|
91
95
|
const lines = [...new Set(ruleIds)].flatMap((id) => {
|
|
92
96
|
const limit = config.limits[id];
|
|
93
97
|
const level = config.rules[id];
|
|
94
98
|
if (limit !== undefined) return [` ${id}: ${String(limit)}`];
|
|
95
|
-
return level === undefined ? [] : [` ${id}: ${level}`];
|
|
99
|
+
return level === undefined || fromStyle.has(id) ? [] : [` ${id}: ${level}`];
|
|
96
100
|
});
|
|
97
|
-
|
|
101
|
+
const style = config.applied === undefined ? [] : [`style: ${config.applied.style}`];
|
|
102
|
+
const rules = lines.length === 0 ? [] : ["rules:", ...lines];
|
|
103
|
+
return style.length + rules.length === 0 ? undefined : [...style, ...rules].join("\n");
|
|
98
104
|
};
|
|
99
105
|
|
|
100
106
|
/** Pure: a title on one line, no longer than GitHub shows. */
|
|
@@ -179,7 +185,7 @@ export const runFeedback = async (targets: readonly string[], argv: readonly str
|
|
|
179
185
|
console.error(text.notFound(request.path));
|
|
180
186
|
return 1;
|
|
181
187
|
}
|
|
182
|
-
const source =
|
|
188
|
+
const source = await readDocumentFile(request.path);
|
|
183
189
|
const checked = await context.check(request.path);
|
|
184
190
|
const picked = pick(request, checked, source.split("\n").length, context.ui);
|
|
185
191
|
if ("error" in picked) {
|
package/src/commands/test.ts
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import { plainSource } from "../plain-source.ts";
|
|
2
|
-
import { readFile } from "node:fs/promises";
|
|
3
1
|
import { join } from "node:path";
|
|
4
2
|
import { loadAdapter } from "../adapter-load.ts";
|
|
5
3
|
import { applyByPath } from "../config/by-path.ts";
|
|
6
4
|
import { buildDocument, teamRules } from "../document.ts";
|
|
7
5
|
import { guessLanguage } from "../detect.ts";
|
|
8
|
-
import { collectTargets } from "../files.ts";
|
|
6
|
+
import { collectTargets, readDocumentFile } from "../files.ts";
|
|
9
7
|
import { loadRules } from "../rule-load.ts";
|
|
10
8
|
import { counted } from "../render/plural.ts";
|
|
11
9
|
import { CHECKS_FILE, loadChecks, type UserCheck } from "../checks.ts";
|
|
@@ -87,7 +85,7 @@ type SemanticDocument = { readonly doc: ProseDocument; readonly rules: RuleDefin
|
|
|
87
85
|
|
|
88
86
|
/** 意味を読む検査に渡す文書。絞り込みが品詞を使うなら、解析器を読み込んでから作る。dry-run も本番も同じ文書を見る。 */
|
|
89
87
|
const semanticDocument = async (path: string, config: Config, resolveGenre: TestContext["resolveGenre"]): Promise<SemanticDocument> => {
|
|
90
|
-
const source =
|
|
88
|
+
const source = await readDocumentFile(path);
|
|
91
89
|
const language = applyByPath(config.byPath, config.baseDir, path).language ?? config.language ?? guessLanguage(source).language;
|
|
92
90
|
const adapter = await loadAdapter(language);
|
|
93
91
|
const { genre } = resolveGenre(path, source, config);
|
package/src/commands/tree.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { readFile } from "node:fs/promises";
|
|
1
|
+
import { readDocumentFile } from "../files.ts";
|
|
3
2
|
import { loadAdapter } from "../adapter-load.ts";
|
|
4
3
|
import { applyByPath } from "../config/by-path.ts";
|
|
5
4
|
import { profileFor } from "../profile/for-file.ts";
|
|
@@ -8,6 +7,7 @@ import { guessLanguage } from "../detect.ts";
|
|
|
8
7
|
import { isMarkdownPath } from "../structure/markdown-path.ts";
|
|
9
8
|
import { buildStructure } from "../structure/of.ts";
|
|
10
9
|
import { toSexp } from "../structure/sexp.ts";
|
|
10
|
+
import { foldPostOrder } from "../tree-walk.ts";
|
|
11
11
|
import type { Config } from "../config/load.ts";
|
|
12
12
|
import type { StructureNode } from "../plugin.ts";
|
|
13
13
|
import type { Texts, UiLanguage } from "../ui.ts";
|
|
@@ -23,16 +23,19 @@ const TEXT: Texts<{
|
|
|
23
23
|
readonly usage: string;
|
|
24
24
|
readonly unreadable: (path: string, why: string) => string;
|
|
25
25
|
readonly noStructure: (path: string, language: string) => string;
|
|
26
|
+
readonly tooDeepForJson: (path: string, depth: number) => string;
|
|
26
27
|
}> = {
|
|
27
28
|
ja: {
|
|
28
29
|
usage: "使い方: chaff tree <file>... [--format sexp|json] [--language ja|en|…]",
|
|
29
30
|
unreadable: (path, why) => `${path} を読めませんでした: ${why}`,
|
|
30
31
|
noStructure: (path, language) => `${path}: 言語 ${language} のパッケージは文書の構造を読めません(structure がありません)`,
|
|
32
|
+
tooDeepForJson: (path, depth) => `${path}: 木が ${String(depth)} 段と深すぎて、字下げした JSON に書き出せません(--format sexp なら書けることがあります)`,
|
|
31
33
|
},
|
|
32
34
|
en: {
|
|
33
35
|
usage: "usage: chaff tree <file>... [--format sexp|json] [--language ja|en|…]",
|
|
34
36
|
unreadable: (path, why) => `Could not read ${path}: ${why}`,
|
|
35
37
|
noStructure: (path, language) => `${path}: the ${language} package cannot read a document's structure (it has no structure)`,
|
|
38
|
+
tooDeepForJson: (path, depth) => `${path}: the tree is ${String(depth)} levels deep, too deep to write as indented JSON (--format sexp may still write it)`,
|
|
36
39
|
},
|
|
37
40
|
};
|
|
38
41
|
|
|
@@ -48,7 +51,7 @@ export const treeTargets = (argv: readonly string[]): string[] =>
|
|
|
48
51
|
|
|
49
52
|
export const readSource = async (path: string, context: TreeContext): Promise<string | undefined> => {
|
|
50
53
|
try {
|
|
51
|
-
return
|
|
54
|
+
return await readDocumentFile(path);
|
|
52
55
|
} catch (err) {
|
|
53
56
|
console.error(treeText(context).unreadable(path, err instanceof Error ? err.message : String(err)));
|
|
54
57
|
return undefined;
|
|
@@ -83,13 +86,46 @@ export const readTree = async (path: string, argv: readonly string[], context: T
|
|
|
83
86
|
// 日本語は形態素で数量と日付を読む。解析器が無ければ単位の表で読むので、木は作れる。
|
|
84
87
|
await adapter.prepare?.({ pos: true });
|
|
85
88
|
const profile = profileFor(context.config, path, source, language, resolveGenre(path, source, context.config, context.flag(argv, "--genre")).genre);
|
|
86
|
-
return { source, tree: buildStructure({ path, source, language, markdown: isMarkdownPath(path), profile }, adapter.structure) };
|
|
89
|
+
return { source, tree: buildStructure({ path, source, language, markdown: isMarkdownPath(path), profile, lexicons: adapter.lexicons }, adapter.structure) };
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* 字下げした JSON。書けないほど深い木(言語パッケージの番号が何千段も入れ子になる)なら undefined。
|
|
94
|
+
* JSON.stringify は 1 段ごとに呼び直すのでスタックが尽き、字下げの合計は深さの二乗で増えて文字列の上限を超える。どちらも RangeError になる。
|
|
95
|
+
*/
|
|
96
|
+
export const treeJson = (tree: StructureNode): string | undefined => {
|
|
97
|
+
try {
|
|
98
|
+
return JSON.stringify(tree, null, 2);
|
|
99
|
+
} catch (err) {
|
|
100
|
+
if (err instanceof RangeError) return undefined;
|
|
101
|
+
throw err;
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
/** 根を 1 段目と数えた、いちばん深い葉までの段の数。 */
|
|
106
|
+
export const depthOf = (tree: StructureNode): number =>
|
|
107
|
+
foldPostOrder(
|
|
108
|
+
tree,
|
|
109
|
+
(node) => node.children,
|
|
110
|
+
(_node, depths: readonly number[]) => depths.reduce((deepest, depth) => Math.max(deepest, depth), 0) + 1,
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
/** 出力する文字列。JSON に書けないほど深い木なら、その深さ。 */
|
|
114
|
+
export const renderTree = (tree: StructureNode, format: string | undefined): { readonly text: string } | { readonly tooDeep: number } => {
|
|
115
|
+
if (format !== "json") return { text: toSexp(tree) };
|
|
116
|
+
const json = treeJson(tree);
|
|
117
|
+
return json === undefined ? { tooDeep: depthOf(tree) } : { text: json };
|
|
87
118
|
};
|
|
88
119
|
|
|
89
120
|
const printTree = async (path: string, argv: readonly string[], context: TreeContext): Promise<boolean> => {
|
|
90
121
|
const read = await readTree(path, argv, context);
|
|
91
122
|
if (read === undefined) return false;
|
|
92
|
-
|
|
123
|
+
const rendered = renderTree(read.tree, context.flag(argv, "--format"));
|
|
124
|
+
if ("tooDeep" in rendered) {
|
|
125
|
+
console.error(treeText(context).tooDeepForJson(path, rendered.tooDeep));
|
|
126
|
+
return false;
|
|
127
|
+
}
|
|
128
|
+
console.log(rendered.text);
|
|
93
129
|
return true;
|
|
94
130
|
};
|
|
95
131
|
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/** The kinds of fact `chaff compare` reads, in the order it reports them. */
|
|
2
|
+
export const ATOM_KINDS = ["number", "date", "time", "url", "code", "name", "quote", "heading", "reference", "footnote"] as const;
|
|
3
|
+
|
|
4
|
+
export type AtomKind = (typeof ATOM_KINDS)[number];
|
|
5
|
+
|
|
6
|
+
export const isAtomKind = (value: string): value is AtomKind => ATOM_KINDS.some((kind) => kind === value);
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* One fact as a document states it. Two atoms are the same fact when kind and key are equal; `text` is how it was
|
|
10
|
+
* written (1,000円 and 1000円 share a key). Position is only for showing where it is: comparing ignores it.
|
|
11
|
+
*/
|
|
12
|
+
export type Atom = {
|
|
13
|
+
readonly kind: AtomKind;
|
|
14
|
+
readonly key: string;
|
|
15
|
+
readonly text: string;
|
|
16
|
+
readonly line: number;
|
|
17
|
+
/** A number written with no unit the reader knows. It may stand for the same number written with a unit. */
|
|
18
|
+
readonly unitless?: boolean;
|
|
19
|
+
/** For a number: its value alone, without the unit. */
|
|
20
|
+
readonly value?: string;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/** A kind this document could not be fully read for, and why. Zero facts of it then does not mean none were there. */
|
|
24
|
+
export type Unread = { readonly kind: AtomKind; readonly reason: UnreadReason };
|
|
25
|
+
|
|
26
|
+
export type UnreadReason = "no-structure" | "no-dates" | "no-pos" | "plain-text";
|
|
27
|
+
|
|
28
|
+
export type Extraction = {
|
|
29
|
+
readonly atoms: readonly Atom[];
|
|
30
|
+
readonly unread: readonly Unread[];
|
|
31
|
+
/** The prose spelled as name keys are, so the other document can ask whether a name is written here at all. */
|
|
32
|
+
readonly nameText: string;
|
|
33
|
+
};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import type { Span } from "../plugin.ts";
|
|
2
|
+
import { overlapsAny, spanIndex } from "./spans.ts";
|
|
3
|
+
|
|
4
|
+
/** A time of day and where it is written. key is "HH:MM" on a 24-hour clock, with ":SS" when seconds are given. */
|
|
5
|
+
export type ClockTime = Span & { readonly key: string };
|
|
6
|
+
|
|
7
|
+
const DIGIT = "[0-90-9]";
|
|
8
|
+
const COLON = "[::]";
|
|
9
|
+
|
|
10
|
+
/** 10:30, 15:30:05, 3:30 p.m. */
|
|
11
|
+
const COLON_TIME = new RegExp(
|
|
12
|
+
`(?<![0-90-9])(${DIGIT}{1,2})${COLON}(${DIGIT}{2})(?:${COLON}(${DIGIT}{2}))?(?:\\s?([ap])\\.?m\\.?(?![a-z]))?(?![0-90-9])`,
|
|
13
|
+
"giu",
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
/** 3 p.m., 11am. */
|
|
17
|
+
const MERIDIEM_TIME = new RegExp(`(?<![0-90-9::])(${DIGIT}{1,2})\\s?([ap])\\.?m\\.?(?![a-z])`, "giu");
|
|
18
|
+
|
|
19
|
+
/** 午後3時30分, 10時半, 9時. */
|
|
20
|
+
const JAPANESE_TIME = new RegExp(`(午前|午後)?(${DIGIT}{1,2})時(?:(${DIGIT}{1,2})分|(半))?`, "gu");
|
|
21
|
+
|
|
22
|
+
const LAST_HOUR = 24;
|
|
23
|
+
const MINUTES_PER_HOUR = 60;
|
|
24
|
+
const HALF_HOUR = 30;
|
|
25
|
+
const NOON = 12;
|
|
26
|
+
const PADDED = 2;
|
|
27
|
+
|
|
28
|
+
type Reading = { readonly hour: number; readonly minute: number; readonly second?: number | undefined; readonly afternoon?: boolean | undefined };
|
|
29
|
+
|
|
30
|
+
const hourOf = (hour: number, afternoon: boolean | undefined): number => {
|
|
31
|
+
if (afternoon === undefined) return hour;
|
|
32
|
+
if (afternoon) return hour < NOON ? hour + NOON : hour;
|
|
33
|
+
return hour === NOON ? 0 : hour;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const padded = (value: number): string => String(value).padStart(PADDED, "0");
|
|
37
|
+
|
|
38
|
+
/** Whether the hour is one on its clock: up to 12 with a.m. or p.m., else up to 23, and 24 only as 24:00. */
|
|
39
|
+
const isHour = ({ hour, minute, second, afternoon }: Reading): boolean => {
|
|
40
|
+
if (afternoon !== undefined) return hour <= NOON;
|
|
41
|
+
return hour < LAST_HOUR || (hour === LAST_HOUR && minute === 0 && (second ?? 0) === 0);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/** The key, or undefined when the numbers are not a time of day (24:30, 13 p.m., 3:75). */
|
|
45
|
+
const keyOf = (reading: Reading): string | undefined => {
|
|
46
|
+
const { hour, minute, second } = reading;
|
|
47
|
+
if (!isHour(reading) || minute >= MINUTES_PER_HOUR || (second ?? 0) >= MINUTES_PER_HOUR) return undefined;
|
|
48
|
+
const parts = [hourOf(hour, reading.afternoon), minute, ...(second === undefined ? [] : [second])];
|
|
49
|
+
return parts.map(padded).join(":");
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const numberOf = (digits: string | undefined): number | undefined => (digits === undefined ? undefined : Number(digits.normalize("NFKC")));
|
|
53
|
+
|
|
54
|
+
const meridiem = (letter: string | undefined): boolean | undefined => (letter === undefined ? undefined : letter.toLowerCase() === "p");
|
|
55
|
+
|
|
56
|
+
const japaneseMeridiem = (word: string | undefined): boolean | undefined => (word === undefined ? undefined : word === "午後");
|
|
57
|
+
|
|
58
|
+
type Reader = { readonly pattern: RegExp; readonly read: (match: RegExpMatchArray) => Reading };
|
|
59
|
+
|
|
60
|
+
const READERS: readonly Reader[] = [
|
|
61
|
+
{
|
|
62
|
+
pattern: JAPANESE_TIME,
|
|
63
|
+
read: (match) => ({
|
|
64
|
+
hour: numberOf(match[2]) ?? 0,
|
|
65
|
+
minute: match[4] === undefined ? (numberOf(match[3]) ?? 0) : HALF_HOUR,
|
|
66
|
+
afternoon: japaneseMeridiem(match[1]),
|
|
67
|
+
}),
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
pattern: COLON_TIME,
|
|
71
|
+
read: (match) => ({ hour: numberOf(match[1]) ?? 0, minute: numberOf(match[2]) ?? 0, second: numberOf(match[3]), afternoon: meridiem(match[4]) }),
|
|
72
|
+
},
|
|
73
|
+
{ pattern: MERIDIEM_TIME, read: (match) => ({ hour: numberOf(match[1]) ?? 0, minute: 0, afternoon: meridiem(match[2]) }) },
|
|
74
|
+
];
|
|
75
|
+
|
|
76
|
+
/** Times of day in text, in the order written. Where two readings overlap, the earlier reader in READERS wins. */
|
|
77
|
+
export const clockTimes = (text: string): ClockTime[] =>
|
|
78
|
+
READERS.reduce<ClockTime[]>((found, reader) => {
|
|
79
|
+
const taken = spanIndex(found);
|
|
80
|
+
const fresh = [...text.matchAll(reader.pattern)].flatMap((match) => {
|
|
81
|
+
const key = keyOf(reader.read(match));
|
|
82
|
+
const span = { start: match.index, end: match.index + match[0].length };
|
|
83
|
+
return key === undefined || overlapsAny(taken, span) ? [] : [{ ...span, key }];
|
|
84
|
+
});
|
|
85
|
+
return [...found, ...fresh];
|
|
86
|
+
}, []).toSorted((left, right) => left.start - right.start);
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { lineStarts, placeOf } from "../position.ts";
|
|
2
|
+
import type { MarkdownNode } from "../markdown-node.ts";
|
|
3
|
+
import type { ProseDocument, Span, StructurePatterns } from "../plugin.ts";
|
|
4
|
+
import type { Atom, Extraction, Unread } from "./atom.ts";
|
|
5
|
+
import { clockTimes } from "./clock-time.ts";
|
|
6
|
+
import { factTextOf, type FactText } from "./fact-text.ts";
|
|
7
|
+
import { codeAtoms, headingAtoms, urlAtoms } from "./markup-atoms.ts";
|
|
8
|
+
import { nameKey, properNouns, readsProperNouns } from "./proper-nouns.ts";
|
|
9
|
+
import { spanIndex } from "./spans.ts";
|
|
10
|
+
import { atomsOf, bareNumbers, footnotes, numericDates, quotations, teamNames, type TextInput } from "./text-atoms.ts";
|
|
11
|
+
import { treeFacts, type TreeFacts } from "./tree-atoms.ts";
|
|
12
|
+
|
|
13
|
+
export type ExtractInput = {
|
|
14
|
+
readonly doc: ProseDocument;
|
|
15
|
+
/** The Markdown tree, or undefined for a plain-text document. */
|
|
16
|
+
readonly root: MarkdownNode | undefined;
|
|
17
|
+
/** The language package's structure reader: numbers with units, dates and references come from it. */
|
|
18
|
+
readonly structure: StructurePatterns | undefined;
|
|
19
|
+
/** chaff.yaml's `names:`. */
|
|
20
|
+
readonly names: readonly string[];
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const NO_TREE_FACTS: TreeFacts = { atoms: [], taken: [] };
|
|
24
|
+
|
|
25
|
+
const STRUCTURE_KINDS = ["number", "date", "reference"] as const;
|
|
26
|
+
|
|
27
|
+
/** The kinds this document could not be fully read for. Each says why, so "nothing dropped" is never "nothing read". */
|
|
28
|
+
const unreadOf = (input: ExtractInput): Unread[] => [
|
|
29
|
+
...(input.structure === undefined ? STRUCTURE_KINDS.map((kind): Unread => ({ kind, reason: "no-structure" })) : []),
|
|
30
|
+
...(input.structure !== undefined && input.structure.dates === undefined ? [{ kind: "date", reason: "no-dates" } as const] : []),
|
|
31
|
+
...(readsProperNouns(input.doc) ? [] : [{ kind: "name", reason: "no-pos" } as const]),
|
|
32
|
+
...(input.root === undefined ? [{ kind: "code", reason: "plain-text" } as const] : []),
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
type Readers = { readonly facts: FactText; readonly text: TextInput; readonly lineOf: (offset: number) => number };
|
|
36
|
+
|
|
37
|
+
/** Facts read from the prose itself. Each reader skips what an earlier one took, so one figure is one fact. */
|
|
38
|
+
const proseFacts = (input: ExtractInput, readers: Readers, tree: TreeFacts, times: readonly Span[]): Atom[] => {
|
|
39
|
+
const { facts, text, lineOf } = readers;
|
|
40
|
+
const marks = footnotes(facts.codeless);
|
|
41
|
+
const dates = numericDates(facts.text, spanIndex([...tree.taken, ...times]));
|
|
42
|
+
const names = teamNames(facts.text, input.names);
|
|
43
|
+
const taken = [...tree.taken, ...times, ...marks, ...dates];
|
|
44
|
+
return [
|
|
45
|
+
...atomsOf(dates, "date", text),
|
|
46
|
+
...atomsOf(marks, "footnote", text),
|
|
47
|
+
...atomsOf(names, "name", text),
|
|
48
|
+
...bareNumbers(text, spanIndex([...taken, ...facts.listMarkers])),
|
|
49
|
+
...quotations(text),
|
|
50
|
+
// "April" in a date and "Section" in a reference are read with them, not again as names.
|
|
51
|
+
...properNouns({ doc: input.doc, taken: spanIndex([...taken, ...names, ...facts.blanked]), lineOf }),
|
|
52
|
+
];
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const structureFacts = (input: ExtractInput, facts: FactText, times: readonly Span[], lineOf: (offset: number) => number): TreeFacts => {
|
|
56
|
+
const tree = input.doc.structure;
|
|
57
|
+
return tree === undefined ? NO_TREE_FACTS : treeFacts({ tree, source: input.doc.source, blanked: facts.blanked, times: spanIndex(times), lineOf });
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/** Every fact atom of one document, and the kinds it could not be fully read for. */
|
|
61
|
+
export const extractFacts = (input: ExtractInput): Extraction => {
|
|
62
|
+
const source = input.doc.source;
|
|
63
|
+
const starts = lineStarts(source);
|
|
64
|
+
const lineOf = (offset: number): number => placeOf(starts, offset).line;
|
|
65
|
+
const facts = factTextOf(source, input.root);
|
|
66
|
+
const text = { text: facts.text, source, lineOf };
|
|
67
|
+
const times = clockTimes(facts.text);
|
|
68
|
+
const tree = structureFacts(input, facts, times, lineOf);
|
|
69
|
+
const atoms = [
|
|
70
|
+
...tree.atoms,
|
|
71
|
+
...atomsOf(times, "time", text),
|
|
72
|
+
...proseFacts(input, { facts, text, lineOf }, tree, times),
|
|
73
|
+
...urlAtoms(input.doc.markup, facts.bareUrls, lineOf),
|
|
74
|
+
...(input.root === undefined ? [] : codeAtoms(input.root, lineOf)),
|
|
75
|
+
...headingAtoms(input.doc.markup, lineOf),
|
|
76
|
+
];
|
|
77
|
+
return { atoms, unread: unreadOf(input), nameText: nameKey(facts.text) };
|
|
78
|
+
};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { bareUrls, type BareUrl } from "../bare-url.ts";
|
|
2
|
+
import { linkChrome } from "../document.ts";
|
|
3
|
+
import { opaqueSpans } from "../markdown-read.ts";
|
|
4
|
+
import { spanOf, type MarkdownNode } from "../markdown-node.ts";
|
|
5
|
+
import { maskSpans } from "../mask.ts";
|
|
6
|
+
import { eachPreOrder } from "../tree-walk.ts";
|
|
7
|
+
import type { Span } from "../plugin.ts";
|
|
8
|
+
import { overlapsAny, spanIndex, type SpanIndex } from "./spans.ts";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The document as the facts in prose are read from it: the same length as the source, with what is not prose
|
|
12
|
+
* blanked. Code, HTML and front matter are compared as code or not at all; a link's target and a bare URL are
|
|
13
|
+
* compared as URLs. Blanking them keeps the digits of a URL from being read again as numbers.
|
|
14
|
+
*/
|
|
15
|
+
export type FactText = {
|
|
16
|
+
/** The source with code and URLs blanked. Offsets are the source's. */
|
|
17
|
+
readonly text: string;
|
|
18
|
+
/** The source with only code blanked: footnote marks are link syntax, so they are read before links are blanked. */
|
|
19
|
+
readonly codeless: string;
|
|
20
|
+
/** Where the blanked parts are. A fact the structure reader found there is not a fact of the prose. */
|
|
21
|
+
readonly blanked: SpanIndex;
|
|
22
|
+
readonly bareUrls: readonly BareUrl[];
|
|
23
|
+
/** Ordered-list markers (`1.`): they number the list, they do not state a number. */
|
|
24
|
+
readonly listMarkers: readonly Span[];
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/** Nodes whose whole span is not read as prose: a link reference definition's URL is read as a URL, an image is not text. */
|
|
28
|
+
const WHOLE = new Set(["definition", "image", "imageReference"]);
|
|
29
|
+
const LINKS = new Set(["link", "linkReference"]);
|
|
30
|
+
|
|
31
|
+
/** `1.` or `1)` at the start of an ordered list item. */
|
|
32
|
+
const ORDERED_MARKER = /^\s*\d{1,9}[.)]/u;
|
|
33
|
+
|
|
34
|
+
const listMarker = (node: MarkdownNode, source: string): Span[] => {
|
|
35
|
+
const span = spanOf(node);
|
|
36
|
+
if (node.type !== "listItem" || span === undefined) return [];
|
|
37
|
+
const marker = ORDERED_MARKER.exec(source.slice(span.start, span.end));
|
|
38
|
+
return marker === null ? [] : [{ start: span.start, end: span.start + marker[0].length }];
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
type MarkdownParts = { readonly chrome: Span[]; readonly linkSpans: Span[]; readonly listMarkers: Span[] };
|
|
42
|
+
|
|
43
|
+
const markdownParts = (root: MarkdownNode, source: string): MarkdownParts => {
|
|
44
|
+
const parts: MarkdownParts = { chrome: [], linkSpans: [], listMarkers: [] };
|
|
45
|
+
eachPreOrder(root, (node) => {
|
|
46
|
+
const span = spanOf(node);
|
|
47
|
+
if (span === undefined) return;
|
|
48
|
+
if (WHOLE.has(node.type)) parts.chrome.push(span);
|
|
49
|
+
if (LINKS.has(node.type)) {
|
|
50
|
+
parts.chrome.push(...linkChrome(node));
|
|
51
|
+
parts.linkSpans.push(span);
|
|
52
|
+
}
|
|
53
|
+
parts.listMarkers.push(...listMarker(node, source));
|
|
54
|
+
});
|
|
55
|
+
return parts;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/** root is the Markdown tree, or undefined for a plain-text document, where nothing is code and URLs are bare. */
|
|
59
|
+
export const factTextOf = (source: string, root: MarkdownNode | undefined): FactText => {
|
|
60
|
+
const code = root === undefined ? [] : opaqueSpans(root);
|
|
61
|
+
const codeless = maskSpans(source, code);
|
|
62
|
+
const parts = root === undefined ? { chrome: [], linkSpans: [], listMarkers: [] } : markdownParts(root, source);
|
|
63
|
+
const insideLinks = spanIndex(parts.linkSpans);
|
|
64
|
+
// An autolink's text is its URL: it is read once, as the link.
|
|
65
|
+
const bare = bareUrls(codeless).filter((url) => !overlapsAny(insideLinks, url));
|
|
66
|
+
const blanked = [...code, ...parts.chrome, ...bare];
|
|
67
|
+
return { text: maskSpans(source, blanked), codeless, blanked: spanIndex(blanked), bareUrls: bare, listMarkers: parts.listMarkers };
|
|
68
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { spanOf, type MarkdownNode } from "../markdown-node.ts";
|
|
2
|
+
import { eachPreOrder } from "../tree-walk.ts";
|
|
3
|
+
import type { Markup } from "../plugin.ts";
|
|
4
|
+
import type { BareUrl } from "../bare-url.ts";
|
|
5
|
+
import type { Atom } from "./atom.ts";
|
|
6
|
+
|
|
7
|
+
const CODE = new Set(["code", "inlineCode"]);
|
|
8
|
+
|
|
9
|
+
/** Inline code and code blocks, compared as written: the key is the code itself, without its backticks or fences. */
|
|
10
|
+
export const codeAtoms = (root: MarkdownNode, lineOf: (offset: number) => number): Atom[] => {
|
|
11
|
+
const found: Atom[] = [];
|
|
12
|
+
eachPreOrder(root, (node) => {
|
|
13
|
+
const span = spanOf(node);
|
|
14
|
+
if (!CODE.has(node.type) || span === undefined) return;
|
|
15
|
+
const code = node.value ?? "";
|
|
16
|
+
found.push({ kind: "code", key: code, text: code, line: lineOf(span.start) });
|
|
17
|
+
});
|
|
18
|
+
return found;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/** Where links point (a Markdown link, an autolink, a used reference definition) and URLs written bare. */
|
|
22
|
+
export const urlAtoms = (markup: Markup | undefined, bare: readonly BareUrl[], lineOf: (offset: number) => number): Atom[] => [
|
|
23
|
+
...(markup?.links ?? []).map((link) => ({ kind: "url" as const, key: link.destination, text: link.destination, line: lineOf(link.start) })),
|
|
24
|
+
...bare.map((url) => ({ kind: "url" as const, key: url.url, text: url.url, line: lineOf(url.start) })),
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
/** Markdown headings as structure: the key is the level, so a reworded heading is the same heading in another form. */
|
|
28
|
+
export const headingAtoms = (markup: Markup | undefined, lineOf: (offset: number) => number): Atom[] =>
|
|
29
|
+
(markup?.headings ?? []).map((heading) => ({ kind: "heading", key: "#".repeat(heading.depth), text: heading.text, line: lineOf(heading.start) }));
|