chaffjs 0.35.0 → 0.37.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ja.md +12 -0
- package/README.md +15 -0
- package/dist/announced-count.d.ts +2 -0
- package/dist/announced-count.d.ts.map +1 -1
- package/dist/announced-count.js +29 -7
- package/dist/announced-count.js.map +1 -1
- package/dist/chronology-rows.d.ts +9 -0
- package/dist/chronology-rows.d.ts.map +1 -0
- package/dist/chronology-rows.js +79 -0
- package/dist/chronology-rows.js.map +1 -0
- package/dist/company-name-run.d.ts +8 -0
- package/dist/company-name-run.d.ts.map +1 -0
- package/dist/company-name-run.js +30 -0
- package/dist/company-name-run.js.map +1 -0
- package/dist/compound-head.d.ts +7 -0
- package/dist/compound-head.d.ts.map +1 -0
- package/dist/compound-head.js +19 -0
- package/dist/compound-head.js.map +1 -0
- package/dist/date-format.d.ts +8 -3
- package/dist/date-format.d.ts.map +1 -1
- package/dist/date-format.js +36 -3
- package/dist/date-format.js.map +1 -1
- package/dist/derived/count-per-period.d.ts +23 -0
- package/dist/derived/count-per-period.d.ts.map +1 -0
- package/dist/derived/count-per-period.js +14 -0
- package/dist/derived/count-per-period.js.map +1 -0
- 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 +29 -1
- package/dist/detectors/acronym-context.js.map +1 -1
- package/dist/detectors/acronym-expansion.d.ts +5 -1
- package/dist/detectors/acronym-expansion.d.ts.map +1 -1
- package/dist/detectors/acronym-expansion.js +42 -3
- package/dist/detectors/acronym-expansion.js.map +1 -1
- package/dist/detectors/acronym-known.d.ts +19 -0
- package/dist/detectors/acronym-known.d.ts.map +1 -0
- package/dist/detectors/acronym-known.js +32 -0
- package/dist/detectors/acronym-known.js.map +1 -0
- package/dist/detectors/acronym-link.d.ts +19 -0
- package/dist/detectors/acronym-link.d.ts.map +1 -0
- package/dist/detectors/acronym-link.js +65 -0
- package/dist/detectors/acronym-link.js.map +1 -0
- package/dist/detectors/acronym-mention.d.ts +5 -0
- package/dist/detectors/acronym-mention.d.ts.map +1 -0
- package/dist/detectors/acronym-mention.js +34 -0
- package/dist/detectors/acronym-mention.js.map +1 -0
- package/dist/detectors/acronym-name.d.ts +8 -1
- package/dist/detectors/acronym-name.d.ts.map +1 -1
- package/dist/detectors/acronym-name.js +25 -6
- package/dist/detectors/acronym-name.js.map +1 -1
- package/dist/detectors/addressee-edge.d.ts +13 -0
- package/dist/detectors/addressee-edge.d.ts.map +1 -0
- package/dist/detectors/addressee-edge.js +13 -0
- package/dist/detectors/addressee-edge.js.map +1 -0
- package/dist/detectors/addressee-title-edge.d.ts +21 -0
- package/dist/detectors/addressee-title-edge.d.ts.map +1 -0
- package/dist/detectors/addressee-title-edge.js +22 -0
- package/dist/detectors/addressee-title-edge.js.map +1 -0
- package/dist/detectors/announced-count.d.ts.map +1 -1
- package/dist/detectors/announced-count.js +1 -0
- package/dist/detectors/announced-count.js.map +1 -1
- package/dist/detectors/bare-comparative.d.ts +4 -0
- package/dist/detectors/bare-comparative.d.ts.map +1 -1
- package/dist/detectors/bare-comparative.js +28 -3
- package/dist/detectors/bare-comparative.js.map +1 -1
- package/dist/detectors/blank-structure.d.ts +7 -1
- package/dist/detectors/blank-structure.d.ts.map +1 -1
- package/dist/detectors/blank-structure.js +13 -8
- package/dist/detectors/blank-structure.js.map +1 -1
- package/dist/detectors/bracket-specified.d.ts +6 -0
- package/dist/detectors/bracket-specified.d.ts.map +1 -0
- package/dist/detectors/bracket-specified.js +23 -0
- package/dist/detectors/bracket-specified.js.map +1 -0
- package/dist/detectors/broken-link.d.ts +6 -0
- package/dist/detectors/broken-link.d.ts.map +1 -1
- package/dist/detectors/broken-link.js +23 -2
- package/dist/detectors/broken-link.js.map +1 -1
- package/dist/detectors/capitalised-term.d.ts +4 -0
- package/dist/detectors/capitalised-term.d.ts.map +1 -1
- package/dist/detectors/capitalised-term.js +18 -1
- package/dist/detectors/capitalised-term.js.map +1 -1
- package/dist/detectors/caps-caption.d.ts +17 -6
- package/dist/detectors/caps-caption.d.ts.map +1 -1
- package/dist/detectors/caps-caption.js +65 -0
- package/dist/detectors/caps-caption.js.map +1 -1
- package/dist/detectors/caps-phrase.d.ts +6 -0
- package/dist/detectors/caps-phrase.d.ts.map +1 -0
- package/dist/detectors/caps-phrase.js +16 -0
- package/dist/detectors/caps-phrase.js.map +1 -0
- package/dist/detectors/char-shape.d.ts +1 -0
- package/dist/detectors/char-shape.d.ts.map +1 -1
- package/dist/detectors/char-shape.js +56 -20
- package/dist/detectors/char-shape.js.map +1 -1
- package/dist/detectors/citation-sentence.d.ts +8 -0
- package/dist/detectors/citation-sentence.d.ts.map +1 -0
- package/dist/detectors/citation-sentence.js +40 -0
- package/dist/detectors/citation-sentence.js.map +1 -0
- package/dist/detectors/cited-title.d.ts +3 -2
- package/dist/detectors/cited-title.d.ts.map +1 -1
- package/dist/detectors/cited-title.js +14 -3
- package/dist/detectors/cited-title.js.map +1 -1
- package/dist/detectors/contraction-mention.d.ts +3 -0
- package/dist/detectors/contraction-mention.d.ts.map +1 -0
- package/dist/detectors/contraction-mention.js +22 -0
- package/dist/detectors/contraction-mention.js.map +1 -0
- package/dist/detectors/counter-edge.d.ts +2 -1
- package/dist/detectors/counter-edge.d.ts.map +1 -1
- package/dist/detectors/counter-edge.js +17 -2
- package/dist/detectors/counter-edge.js.map +1 -1
- package/dist/detectors/dash-break.d.ts +7 -0
- package/dist/detectors/dash-break.d.ts.map +1 -0
- package/dist/detectors/dash-break.js +30 -0
- package/dist/detectors/dash-break.js.map +1 -0
- package/dist/detectors/date-any-year.d.ts +7 -3
- package/dist/detectors/date-any-year.d.ts.map +1 -1
- package/dist/detectors/date-any-year.js +30 -8
- package/dist/detectors/date-any-year.js.map +1 -1
- package/dist/detectors/date-format.d.ts.map +1 -1
- package/dist/detectors/date-format.js +2 -1
- package/dist/detectors/date-format.js.map +1 -1
- package/dist/detectors/date-year.d.ts +9 -3
- package/dist/detectors/date-year.d.ts.map +1 -1
- package/dist/detectors/date-year.js +45 -9
- package/dist/detectors/date-year.js.map +1 -1
- package/dist/detectors/deadline-unit.d.ts +20 -0
- package/dist/detectors/deadline-unit.d.ts.map +1 -0
- package/dist/detectors/deadline-unit.js +19 -0
- package/dist/detectors/deadline-unit.js.map +1 -0
- package/dist/detectors/defined-term-form.d.ts.map +1 -1
- package/dist/detectors/defined-term-form.js +33 -7
- package/dist/detectors/defined-term-form.js.map +1 -1
- package/dist/detectors/definition-use.d.ts.map +1 -1
- package/dist/detectors/definition-use.js +14 -6
- package/dist/detectors/definition-use.js.map +1 -1
- package/dist/detectors/derived-numbers.d.ts.map +1 -1
- package/dist/detectors/derived-numbers.js +17 -4
- package/dist/detectors/derived-numbers.js.map +1 -1
- package/dist/detectors/document-shape.d.ts +5 -0
- package/dist/detectors/document-shape.d.ts.map +1 -1
- package/dist/detectors/document-shape.js +15 -1
- package/dist/detectors/document-shape.js.map +1 -1
- package/dist/detectors/doubled-across-aside.d.ts +9 -0
- package/dist/detectors/doubled-across-aside.d.ts.map +1 -0
- package/dist/detectors/doubled-across-aside.js +27 -0
- package/dist/detectors/doubled-across-aside.js.map +1 -0
- package/dist/detectors/doubled-punctuation.d.ts +3 -3
- package/dist/detectors/doubled-punctuation.d.ts.map +1 -1
- package/dist/detectors/doubled-punctuation.js +23 -4
- package/dist/detectors/doubled-punctuation.js.map +1 -1
- package/dist/detectors/doubled-word.d.ts.map +1 -1
- package/dist/detectors/doubled-word.js +2 -1
- package/dist/detectors/doubled-word.js.map +1 -1
- package/dist/detectors/duplicate-heading.d.ts +1 -0
- package/dist/detectors/duplicate-heading.d.ts.map +1 -1
- package/dist/detectors/duplicate-heading.js +25 -3
- package/dist/detectors/duplicate-heading.js.map +1 -1
- package/dist/detectors/ellipsis.d.ts.map +1 -1
- package/dist/detectors/ellipsis.js +13 -1
- package/dist/detectors/ellipsis.js.map +1 -1
- package/dist/detectors/email-letter.d.ts +40 -3
- package/dist/detectors/email-letter.d.ts.map +1 -1
- package/dist/detectors/email-letter.js +110 -17
- package/dist/detectors/email-letter.js.map +1 -1
- package/dist/detectors/field-label.d.ts +7 -0
- package/dist/detectors/field-label.d.ts.map +1 -0
- package/dist/detectors/field-label.js +23 -0
- package/dist/detectors/field-label.js.map +1 -0
- package/dist/detectors/footnote-mismatch.d.ts +6 -1
- package/dist/detectors/footnote-mismatch.d.ts.map +1 -1
- package/dist/detectors/footnote-mismatch.js +28 -7
- package/dist/detectors/footnote-mismatch.js.map +1 -1
- package/dist/detectors/fullwidth-alnum.d.ts.map +1 -1
- package/dist/detectors/fullwidth-alnum.js +7 -1
- package/dist/detectors/fullwidth-alnum.js.map +1 -1
- package/dist/detectors/graded-step.d.ts +20 -0
- package/dist/detectors/graded-step.d.ts.map +1 -0
- package/dist/detectors/graded-step.js +33 -0
- package/dist/detectors/graded-step.js.map +1 -0
- package/dist/detectors/gram-openers.d.ts +9 -0
- package/dist/detectors/gram-openers.d.ts.map +1 -0
- package/dist/detectors/gram-openers.js +40 -0
- package/dist/detectors/gram-openers.js.map +1 -0
- package/dist/detectors/gram-place.d.ts +3 -1
- package/dist/detectors/gram-place.d.ts.map +1 -1
- package/dist/detectors/gram-place.js +8 -0
- package/dist/detectors/gram-place.js.map +1 -1
- package/dist/detectors/gram-predicate.d.ts.map +1 -1
- package/dist/detectors/gram-predicate.js +37 -3
- package/dist/detectors/gram-predicate.js.map +1 -1
- package/dist/detectors/heading-echo.d.ts.map +1 -1
- package/dist/detectors/heading-echo.js +28 -2
- package/dist/detectors/heading-echo.js.map +1 -1
- package/dist/detectors/heading-record-rhythm.d.ts +9 -0
- package/dist/detectors/heading-record-rhythm.d.ts.map +1 -0
- package/dist/detectors/heading-record-rhythm.js +57 -0
- package/dist/detectors/heading-record-rhythm.js.map +1 -0
- package/dist/detectors/ime-residue.d.ts +1 -1
- package/dist/detectors/ime-residue.d.ts.map +1 -1
- package/dist/detectors/ime-residue.js +4 -3
- package/dist/detectors/ime-residue.js.map +1 -1
- package/dist/detectors/kanji-compound-slip.d.ts +3 -0
- package/dist/detectors/kanji-compound-slip.d.ts.map +1 -0
- package/dist/detectors/kanji-compound-slip.js +50 -0
- package/dist/detectors/kanji-compound-slip.js.map +1 -0
- package/dist/detectors/kutoten-consistency.d.ts +10 -2
- package/dist/detectors/kutoten-consistency.d.ts.map +1 -1
- package/dist/detectors/kutoten-consistency.js +83 -12
- package/dist/detectors/kutoten-consistency.js.map +1 -1
- package/dist/detectors/lexicon.d.ts.map +1 -1
- package/dist/detectors/lexicon.js +13 -4
- package/dist/detectors/lexicon.js.map +1 -1
- package/dist/detectors/link-shape.d.ts.map +1 -1
- package/dist/detectors/link-shape.js +9 -3
- package/dist/detectors/link-shape.js.map +1 -1
- package/dist/detectors/list-item-ending.d.ts +18 -0
- package/dist/detectors/list-item-ending.d.ts.map +1 -0
- package/dist/detectors/list-item-ending.js +35 -0
- package/dist/detectors/list-item-ending.js.map +1 -0
- package/dist/detectors/list-parallel.d.ts +18 -5
- package/dist/detectors/list-parallel.d.ts.map +1 -1
- package/dist/detectors/list-parallel.js +116 -36
- package/dist/detectors/list-parallel.js.map +1 -1
- package/dist/detectors/list-sentence.d.ts +4 -0
- package/dist/detectors/list-sentence.d.ts.map +1 -1
- package/dist/detectors/list-sentence.js +1 -1
- package/dist/detectors/list-sentence.js.map +1 -1
- package/dist/detectors/mark-shape.d.ts +13 -4
- package/dist/detectors/mark-shape.d.ts.map +1 -1
- package/dist/detectors/mark-shape.js +73 -10
- package/dist/detectors/mark-shape.js.map +1 -1
- package/dist/detectors/mentioned-phrase.d.ts +9 -0
- package/dist/detectors/mentioned-phrase.d.ts.map +1 -0
- package/dist/detectors/mentioned-phrase.js +25 -0
- package/dist/detectors/mentioned-phrase.js.map +1 -0
- package/dist/detectors/middle-dot.d.ts +2 -2
- package/dist/detectors/middle-dot.d.ts.map +1 -1
- package/dist/detectors/middle-dot.js +4 -2
- package/dist/detectors/middle-dot.js.map +1 -1
- package/dist/detectors/modal-conflict.d.ts.map +1 -1
- package/dist/detectors/modal-conflict.js +5 -2
- package/dist/detectors/modal-conflict.js.map +1 -1
- package/dist/detectors/name-variant.d.ts.map +1 -1
- package/dist/detectors/name-variant.js +6 -0
- package/dist/detectors/name-variant.js.map +1 -1
- package/dist/detectors/notice-paragraph.d.ts +9 -0
- package/dist/detectors/notice-paragraph.d.ts.map +1 -0
- package/dist/detectors/notice-paragraph.js +21 -0
- package/dist/detectors/notice-paragraph.js.map +1 -0
- package/dist/detectors/number-style.d.ts.map +1 -1
- package/dist/detectors/number-style.js +15 -2
- package/dist/detectors/number-style.js.map +1 -1
- package/dist/detectors/number-unit.d.ts.map +1 -1
- package/dist/detectors/number-unit.js +24 -1
- package/dist/detectors/number-unit.js.map +1 -1
- package/dist/detectors/numeral-opener.d.ts +6 -0
- package/dist/detectors/numeral-opener.d.ts.map +1 -1
- package/dist/detectors/numeral-opener.js +24 -1
- package/dist/detectors/numeral-opener.js.map +1 -1
- package/dist/detectors/obligation-without-deadline.d.ts +5 -1
- package/dist/detectors/obligation-without-deadline.d.ts.map +1 -1
- package/dist/detectors/obligation-without-deadline.js +44 -23
- package/dist/detectors/obligation-without-deadline.js.map +1 -1
- package/dist/detectors/open-end-class.d.ts +16 -0
- package/dist/detectors/open-end-class.d.ts.map +1 -0
- package/dist/detectors/open-end-class.js +65 -0
- package/dist/detectors/open-end-class.js.map +1 -0
- package/dist/detectors/open-end-condition.d.ts +7 -0
- package/dist/detectors/open-end-condition.d.ts.map +1 -0
- package/dist/detectors/open-end-condition.js +35 -0
- package/dist/detectors/open-end-condition.js.map +1 -0
- package/dist/detectors/open-end-names.d.ts +9 -3
- package/dist/detectors/open-end-names.d.ts.map +1 -1
- package/dist/detectors/open-end-names.js +5 -2
- package/dist/detectors/open-end-names.js.map +1 -1
- package/dist/detectors/open-end-question.d.ts +15 -0
- package/dist/detectors/open-end-question.d.ts.map +1 -0
- package/dist/detectors/open-end-question.js +37 -0
- package/dist/detectors/open-end-question.js.map +1 -0
- package/dist/detectors/open-end-scope.d.ts +16 -0
- package/dist/detectors/open-end-scope.d.ts.map +1 -0
- package/dist/detectors/open-end-scope.js +47 -0
- package/dist/detectors/open-end-scope.js.map +1 -0
- package/dist/detectors/opening-date.d.ts +10 -0
- package/dist/detectors/opening-date.d.ts.map +1 -0
- package/dist/detectors/opening-date.js +33 -0
- package/dist/detectors/opening-date.js.map +1 -0
- package/dist/detectors/ordinary-phrase.d.ts +20 -0
- package/dist/detectors/ordinary-phrase.d.ts.map +1 -0
- package/dist/detectors/ordinary-phrase.js +54 -0
- package/dist/detectors/ordinary-phrase.js.map +1 -0
- package/dist/detectors/organisation-run.d.ts +5 -7
- package/dist/detectors/organisation-run.d.ts.map +1 -1
- package/dist/detectors/organisation-run.js +10 -0
- package/dist/detectors/organisation-run.js.map +1 -1
- package/dist/detectors/orthographic-variant.d.ts.map +1 -1
- package/dist/detectors/orthographic-variant.js +85 -20
- package/dist/detectors/orthographic-variant.js.map +1 -1
- package/dist/detectors/orthography.d.ts.map +1 -1
- package/dist/detectors/orthography.js +9 -2
- package/dist/detectors/orthography.js.map +1 -1
- package/dist/detectors/oxford-comma.d.ts.map +1 -1
- package/dist/detectors/oxford-comma.js +70 -3
- package/dist/detectors/oxford-comma.js.map +1 -1
- package/dist/detectors/person-consistency.d.ts +2 -1
- package/dist/detectors/person-consistency.d.ts.map +1 -1
- package/dist/detectors/person-consistency.js +5 -3
- package/dist/detectors/person-consistency.js.map +1 -1
- package/dist/detectors/phrase-match.d.ts +2 -0
- package/dist/detectors/phrase-match.d.ts.map +1 -1
- package/dist/detectors/phrase-match.js +11 -4
- package/dist/detectors/phrase-match.js.map +1 -1
- package/dist/detectors/placeholder-text.d.ts.map +1 -1
- package/dist/detectors/placeholder-text.js +18 -3
- package/dist/detectors/placeholder-text.js.map +1 -1
- package/dist/detectors/placeholder.d.ts +3 -1
- package/dist/detectors/placeholder.d.ts.map +1 -1
- package/dist/detectors/placeholder.js +8 -3
- package/dist/detectors/placeholder.js.map +1 -1
- package/dist/detectors/postcode-end.d.ts +3 -0
- package/dist/detectors/postcode-end.d.ts.map +1 -0
- package/dist/detectors/postcode-end.js +15 -0
- package/dist/detectors/postcode-end.js.map +1 -0
- package/dist/detectors/prose-total-words.d.ts +5 -0
- package/dist/detectors/prose-total-words.d.ts.map +1 -0
- package/dist/detectors/prose-total-words.js +14 -0
- package/dist/detectors/prose-total-words.js.map +1 -0
- package/dist/detectors/range-notation.d.ts +2 -2
- package/dist/detectors/range-notation.d.ts.map +1 -1
- package/dist/detectors/range-notation.js +18 -7
- package/dist/detectors/range-notation.js.map +1 -1
- package/dist/detectors/registry/kanji-compound-slip.d.ts +3 -0
- package/dist/detectors/registry/kanji-compound-slip.d.ts.map +1 -0
- package/dist/detectors/registry/kanji-compound-slip.js +3 -0
- package/dist/detectors/registry/kanji-compound-slip.js.map +1 -0
- package/dist/detectors/registry/phrase-in-use.d.ts +3 -0
- package/dist/detectors/registry/phrase-in-use.d.ts.map +1 -0
- package/dist/detectors/registry/phrase-in-use.js +3 -0
- package/dist/detectors/registry/phrase-in-use.js.map +1 -0
- package/dist/detectors/requirement-smell.d.ts.map +1 -1
- package/dist/detectors/requirement-smell.js +35 -7
- package/dist/detectors/requirement-smell.js.map +1 -1
- package/dist/detectors/scaled-figure-unit.d.ts +28 -0
- package/dist/detectors/scaled-figure-unit.d.ts.map +1 -0
- package/dist/detectors/scaled-figure-unit.js +78 -0
- package/dist/detectors/scaled-figure-unit.js.map +1 -0
- package/dist/detectors/sentence-counts.d.ts +12 -2
- package/dist/detectors/sentence-counts.d.ts.map +1 -1
- package/dist/detectors/sentence-counts.js +52 -11
- package/dist/detectors/sentence-counts.js.map +1 -1
- package/dist/detectors/sentence-ending.d.ts +2 -0
- package/dist/detectors/sentence-ending.d.ts.map +1 -1
- package/dist/detectors/sentence-ending.js +10 -3
- 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/sentence-load.d.ts +4 -1
- package/dist/detectors/sentence-load.d.ts.map +1 -1
- package/dist/detectors/sentence-load.js +9 -2
- package/dist/detectors/sentence-load.js.map +1 -1
- package/dist/detectors/signals.d.ts.map +1 -1
- package/dist/detectors/signals.js +44 -52
- package/dist/detectors/signals.js.map +1 -1
- package/dist/detectors/structure-tree.d.ts.map +1 -1
- package/dist/detectors/structure-tree.js +14 -13
- package/dist/detectors/structure-tree.js.map +1 -1
- package/dist/detectors/structure.d.ts.map +1 -1
- package/dist/detectors/structure.js +2 -1
- package/dist/detectors/structure.js.map +1 -1
- package/dist/detectors/subject-name-line.d.ts +8 -0
- package/dist/detectors/subject-name-line.d.ts.map +1 -0
- package/dist/detectors/subject-name-line.js +53 -0
- package/dist/detectors/subject-name-line.js.map +1 -0
- package/dist/detectors/superlative-name.d.ts +5 -0
- package/dist/detectors/superlative-name.d.ts.map +1 -1
- package/dist/detectors/superlative-name.js +9 -0
- package/dist/detectors/superlative-name.js.map +1 -1
- package/dist/detectors/table-header.d.ts.map +1 -1
- package/dist/detectors/table-header.js +13 -1
- package/dist/detectors/table-header.js.map +1 -1
- package/dist/detectors/technical-docs.d.ts.map +1 -1
- package/dist/detectors/technical-docs.js +4 -1
- package/dist/detectors/technical-docs.js.map +1 -1
- package/dist/detectors/term-mention-sentence.d.ts +4 -0
- package/dist/detectors/term-mention-sentence.d.ts.map +1 -0
- package/dist/detectors/term-mention-sentence.js +28 -0
- package/dist/detectors/term-mention-sentence.js.map +1 -0
- package/dist/detectors/titled-run.d.ts +2 -1
- package/dist/detectors/titled-run.d.ts.map +1 -1
- package/dist/detectors/titled-run.js +9 -4
- package/dist/detectors/titled-run.js.map +1 -1
- package/dist/detectors/token-shape.d.ts.map +1 -1
- package/dist/detectors/token-shape.js +15 -5
- package/dist/detectors/token-shape.js.map +1 -1
- package/dist/detectors/undefined-term.d.ts.map +1 -1
- package/dist/detectors/undefined-term.js +5 -0
- package/dist/detectors/undefined-term.js.map +1 -1
- package/dist/detectors/unknown-word.d.ts +4 -1
- package/dist/detectors/unknown-word.d.ts.map +1 -1
- package/dist/detectors/unknown-word.js +1 -1
- package/dist/detectors/unknown-word.js.map +1 -1
- package/dist/detectors/vague-density.d.ts +5 -2
- package/dist/detectors/vague-density.d.ts.map +1 -1
- package/dist/detectors/vague-density.js +17 -4
- package/dist/detectors/vague-density.js.map +1 -1
- package/dist/document-paragraphs.d.ts +4 -0
- package/dist/document-paragraphs.d.ts.map +1 -0
- package/dist/document-paragraphs.js +24 -0
- package/dist/document-paragraphs.js.map +1 -0
- package/dist/document.d.ts.map +1 -1
- package/dist/document.js +2 -19
- package/dist/document.js.map +1 -1
- package/dist/figure-references.d.ts +3 -0
- package/dist/figure-references.d.ts.map +1 -1
- package/dist/figure-references.js +6 -2
- package/dist/figure-references.js.map +1 -1
- package/dist/format-template.d.ts +3 -0
- package/dist/format-template.d.ts.map +1 -0
- package/dist/format-template.js +13 -0
- package/dist/format-template.js.map +1 -0
- package/dist/formula-brackets.d.ts +7 -0
- package/dist/formula-brackets.d.ts.map +1 -0
- package/dist/formula-brackets.js +29 -0
- package/dist/formula-brackets.js.map +1 -0
- package/dist/html/html-markdown.d.ts.map +1 -1
- package/dist/html/html-markdown.js +2 -1
- package/dist/html/html-markdown.js.map +1 -1
- package/dist/html/html-site-chrome.d.ts +5 -0
- package/dist/html/html-site-chrome.d.ts.map +1 -0
- package/dist/html/html-site-chrome.js +56 -0
- package/dist/html/html-site-chrome.js.map +1 -0
- 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/kanji-compound-slip.d.ts +32 -0
- package/dist/kanji-compound-slip.d.ts.map +1 -0
- package/dist/kanji-compound-slip.js +63 -0
- package/dist/kanji-compound-slip.js.map +1 -0
- package/dist/latin-company-form.d.ts +6 -0
- package/dist/latin-company-form.d.ts.map +1 -0
- package/dist/latin-company-form.js +32 -0
- package/dist/latin-company-form.js.map +1 -0
- package/dist/latin-word-boundary.d.ts +20 -0
- package/dist/latin-word-boundary.d.ts.map +1 -0
- package/dist/latin-word-boundary.js +57 -0
- package/dist/latin-word-boundary.js.map +1 -0
- package/dist/leading-label.d.ts +4 -0
- package/dist/leading-label.d.ts.map +1 -0
- package/dist/leading-label.js +14 -0
- package/dist/leading-label.js.map +1 -0
- package/dist/lexicon-genres.d.ts +2 -0
- package/dist/lexicon-genres.d.ts.map +1 -1
- package/dist/lexicon-genres.js +1 -1
- package/dist/lexicon-genres.js.map +1 -1
- package/dist/link-shape.d.ts +6 -0
- package/dist/link-shape.d.ts.map +1 -1
- package/dist/link-shape.js +27 -0
- package/dist/link-shape.js.map +1 -1
- package/dist/link-title.d.ts +4 -0
- package/dist/link-title.d.ts.map +1 -0
- package/dist/link-title.js +33 -0
- package/dist/link-title.js.map +1 -0
- package/dist/list-item-paragraphs.d.ts +15 -0
- package/dist/list-item-paragraphs.d.ts.map +1 -0
- package/dist/list-item-paragraphs.js +19 -0
- package/dist/list-item-paragraphs.js.map +1 -0
- package/dist/literal-quote.d.ts +12 -0
- package/dist/literal-quote.d.ts.map +1 -0
- package/dist/literal-quote.js +43 -0
- package/dist/literal-quote.js.map +1 -0
- package/dist/nado-closed-list.d.ts.map +1 -1
- package/dist/nado-closed-list.js +39 -5
- package/dist/nado-closed-list.js.map +1 -1
- package/dist/name-misspelt-usual.d.ts +5 -0
- package/dist/name-misspelt-usual.d.ts.map +1 -0
- package/dist/name-misspelt-usual.js +19 -0
- package/dist/name-misspelt-usual.js.map +1 -0
- package/dist/name-separator.d.ts.map +1 -1
- package/dist/name-separator.js +25 -2
- package/dist/name-separator.js.map +1 -1
- package/dist/nominal-stem.d.ts +14 -1
- package/dist/nominal-stem.d.ts.map +1 -1
- package/dist/nominal-stem.js +42 -4
- package/dist/nominal-stem.js.map +1 -1
- package/dist/notice-header.d.ts +19 -0
- package/dist/notice-header.d.ts.map +1 -0
- package/dist/notice-header.js +31 -0
- package/dist/notice-header.js.map +1 -0
- package/dist/person-forms.d.ts +8 -0
- package/dist/person-forms.d.ts.map +1 -1
- package/dist/person-forms.js +12 -0
- package/dist/person-forms.js.map +1 -1
- package/dist/plugin.d.ts +5 -0
- package/dist/plugin.d.ts.map +1 -1
- package/dist/preamble-paragraphs.d.ts +3 -2
- package/dist/preamble-paragraphs.d.ts.map +1 -1
- package/dist/preamble-paragraphs.js +8 -2
- package/dist/preamble-paragraphs.js.map +1 -1
- package/dist/sentence-load.d.ts +2 -1
- package/dist/sentence-load.d.ts.map +1 -1
- package/dist/sentence-load.js +11 -3
- package/dist/sentence-load.js.map +1 -1
- package/dist/spacing-code.d.ts +1 -0
- package/dist/spacing-code.d.ts.map +1 -1
- package/dist/spacing-code.js +4 -1
- package/dist/spacing-code.js.map +1 -1
- package/dist/split-noun.d.ts +10 -0
- package/dist/split-noun.d.ts.map +1 -0
- package/dist/split-noun.js +50 -0
- package/dist/split-noun.js.map +1 -0
- package/dist/structure/attached-parts.d.ts +12 -0
- package/dist/structure/attached-parts.d.ts.map +1 -0
- package/dist/structure/attached-parts.js +44 -0
- package/dist/structure/attached-parts.js.map +1 -0
- package/dist/structure/build.d.ts.map +1 -1
- package/dist/structure/build.js +7 -4
- package/dist/structure/build.js.map +1 -1
- package/dist/structure/contents-lines.d.ts +7 -0
- package/dist/structure/contents-lines.d.ts.map +1 -0
- package/dist/structure/contents-lines.js +51 -0
- package/dist/structure/contents-lines.js.map +1 -0
- package/dist/structure/defining-names.d.ts +37 -0
- package/dist/structure/defining-names.d.ts.map +1 -0
- package/dist/structure/defining-names.js +122 -0
- package/dist/structure/defining-names.js.map +1 -0
- package/dist/structure/definition-use.d.ts +8 -4
- package/dist/structure/definition-use.d.ts.map +1 -1
- package/dist/structure/definition-use.js +123 -38
- package/dist/structure/definition-use.js.map +1 -1
- package/dist/structure/gerund-phrase.d.ts +8 -0
- package/dist/structure/gerund-phrase.d.ts.map +1 -0
- package/dist/structure/gerund-phrase.js +30 -0
- package/dist/structure/gerund-phrase.js.map +1 -0
- package/dist/structure/issues.d.ts +4 -1
- package/dist/structure/issues.d.ts.map +1 -1
- package/dist/structure/issues.js +5 -2
- package/dist/structure/issues.js.map +1 -1
- package/dist/structure/list-lead-in.d.ts +19 -0
- package/dist/structure/list-lead-in.d.ts.map +1 -0
- package/dist/structure/list-lead-in.js +85 -0
- package/dist/structure/list-lead-in.js.map +1 -0
- package/dist/structure/modal-conflict.d.ts +7 -2
- package/dist/structure/modal-conflict.d.ts.map +1 -1
- package/dist/structure/modal-conflict.js +36 -7
- package/dist/structure/modal-conflict.js.map +1 -1
- package/dist/structure/negated-act.d.ts +17 -0
- package/dist/structure/negated-act.d.ts.map +1 -0
- package/dist/structure/negated-act.js +32 -0
- package/dist/structure/negated-act.js.map +1 -0
- package/dist/structure/numbering.d.ts +3 -1
- package/dist/structure/numbering.d.ts.map +1 -1
- package/dist/structure/numbering.js +20 -8
- package/dist/structure/numbering.js.map +1 -1
- package/dist/structure/prose-total.d.ts +4 -0
- package/dist/structure/prose-total.d.ts.map +1 -1
- package/dist/structure/prose-total.js +16 -6
- package/dist/structure/prose-total.js.map +1 -1
- package/dist/structure/repeated-number.d.ts +24 -0
- package/dist/structure/repeated-number.d.ts.map +1 -0
- package/dist/structure/repeated-number.js +89 -0
- package/dist/structure/repeated-number.js.map +1 -0
- package/dist/structure/rounded-amount.d.ts +8 -0
- package/dist/structure/rounded-amount.d.ts.map +1 -0
- package/dist/structure/rounded-amount.js +48 -0
- package/dist/structure/rounded-amount.js.map +1 -0
- package/dist/structure/side-step.d.ts +8 -0
- package/dist/structure/side-step.d.ts.map +1 -0
- package/dist/structure/side-step.js +21 -0
- package/dist/structure/side-step.js.map +1 -0
- package/dist/structure/spanned-label-blank.d.ts +8 -0
- package/dist/structure/spanned-label-blank.d.ts.map +1 -0
- package/dist/structure/spanned-label-blank.js +37 -0
- package/dist/structure/spanned-label-blank.js.map +1 -0
- package/dist/structure/universal.d.ts +10 -4
- package/dist/structure/universal.d.ts.map +1 -1
- package/dist/structure/universal.js +26 -7
- package/dist/structure/universal.js.map +1 -1
- package/dist/structure/unspaced-heading.d.ts +10 -0
- package/dist/structure/unspaced-heading.d.ts.map +1 -0
- package/dist/structure/unspaced-heading.js +24 -0
- package/dist/structure/unspaced-heading.js.map +1 -0
- package/dist/structure/written-list-path.d.ts +10 -0
- package/dist/structure/written-list-path.d.ts.map +1 -0
- package/dist/structure/written-list-path.js +37 -0
- package/dist/structure/written-list-path.js.map +1 -0
- package/dist/structure/written-resolve.d.ts +1 -1
- package/dist/structure/written-resolve.d.ts.map +1 -1
- package/dist/structure/written-resolve.js +15 -9
- package/dist/structure/written-resolve.js.map +1 -1
- package/dist/title-line.d.ts +23 -0
- package/dist/title-line.d.ts.map +1 -0
- package/dist/title-line.js +28 -0
- package/dist/title-line.js.map +1 -0
- package/dist/topic-clause.d.ts +7 -0
- package/dist/topic-clause.d.ts.map +1 -0
- package/dist/topic-clause.js +87 -0
- package/dist/topic-clause.js.map +1 -0
- package/dist/uncounted-particles.d.ts +18 -0
- package/dist/uncounted-particles.d.ts.map +1 -0
- package/dist/uncounted-particles.js +47 -0
- package/dist/uncounted-particles.js.map +1 -0
- package/package.json +3 -3
- package/rules/adversative-ga-repeat.yaml +1 -0
- package/rules/all-caps-shouting.yaml +2 -2
- package/rules/announced-count-mismatch.yaml +2 -2
- package/rules/bare-url-mix.yaml +2 -2
- package/rules/bracket-nesting.yaml +2 -2
- package/rules/bracket-width-consistency.yaml +2 -2
- package/rules/broken-link.yaml +2 -2
- package/rules/cliche.yaml +4 -3
- package/rules/code-fence-language-mix.yaml +2 -2
- package/rules/comparative-without-baseline.yaml +2 -2
- package/rules/concrete-evidence-density.yaml +1 -0
- package/rules/contraction-consistency.yaml +2 -2
- package/rules/dangling-figure-reference.yaml +2 -2
- package/rules/date-without-year.yaml +10 -2
- package/rules/defined-term-form.yaml +2 -2
- package/rules/doubled-punctuation.yaml +4 -4
- package/rules/doubled-word.yaml +2 -2
- package/rules/duplicate-definition.yaml +2 -2
- package/rules/duplicate-heading.yaml +2 -2
- package/rules/duration-mismatch.yaml +2 -2
- package/rules/email-greeting-closing.yaml +2 -2
- package/rules/email-subject-length.yaml +2 -2
- package/rules/empty-table-cell.yaml +2 -2
- package/rules/footnote-mismatch.yaml +2 -2
- package/rules/fullwidth-alnum-consistency.yaml +2 -2
- package/rules/heading-echo.yaml +2 -2
- package/rules/ime-residue.yaml +2 -2
- package/rules/kanji-compound-slip.yaml +67 -0
- package/rules/kutoten-consistency.yaml +4 -4
- package/rules/latin-spacing.yaml +2 -2
- package/rules/list-item-form-mix.yaml +2 -2
- package/rules/max-kanji-continuous.yaml +6 -4
- package/rules/max-sentence-length.yaml +2 -2
- package/rules/modal-conflict.yaml +1 -0
- package/rules/nado-closed-list.yaml +2 -2
- package/rules/ngram-repetition.yaml +2 -2
- package/rules/no-doubled-joshi.yaml +2 -2
- package/rules/no-mixed-desumasu.yaml +3 -3
- package/rules/no-nakaguro-parallel.yaml +2 -0
- package/rules/number-without-unit.yaml +9 -4
- package/rules/numbering-gap.yaml +7 -2
- package/rules/numeral-sentence-start.yaml +2 -2
- package/rules/obligation-without-deadline.yaml +2 -2
- package/rules/orthographic-variant.yaml +2 -2
- package/rules/oxford-comma-consistency.yaml +3 -3
- package/rules/preamble-length.yaml +3 -2
- package/rules/range-notation-consistency.yaml +2 -2
- package/rules/requirement-smell.yaml +3 -3
- package/rules/table-header-variant.yaml +2 -2
- package/rules/teki-overuse.yaml +3 -2
- package/rules/title-length.yaml +2 -2
- package/rules/topic-predicate-distance.yaml +2 -2
- package/rules/total-mismatch.yaml +2 -2
- package/rules/translationese-density.yaml +2 -2
- package/rules/undefined-acronym.yaml +5 -2
- package/rules/undefined-term.yaml +2 -2
- package/rules/unfilled-placeholder.yaml +4 -4
- package/rules/unqualified-superlative.yaml +1 -1
- package/rules/unused-definition.yaml +2 -2
- package/rules/use-before-definition.yaml +2 -2
- package/rules/vague-word-density.yaml +2 -2
- package/skills/chaff/SKILL.md +7 -1
- package/src/announced-count.ts +35 -8
- package/src/chronology-rows.ts +86 -0
- package/src/company-name-run.ts +37 -0
- package/src/compound-head.ts +25 -0
- package/src/date-format.ts +43 -4
- package/src/derived/count-per-period.ts +28 -0
- package/src/detectors/acronym-context.ts +30 -1
- package/src/detectors/acronym-expansion.ts +54 -6
- package/src/detectors/acronym-known.ts +40 -0
- package/src/detectors/acronym-link.ts +75 -0
- package/src/detectors/acronym-mention.ts +44 -0
- package/src/detectors/acronym-name.ts +29 -6
- package/src/detectors/addressee-edge.ts +16 -0
- package/src/detectors/addressee-title-edge.ts +39 -0
- package/src/detectors/announced-count.ts +1 -0
- package/src/detectors/bare-comparative.ts +44 -3
- package/src/detectors/blank-structure.ts +21 -10
- package/src/detectors/bracket-specified.ts +25 -0
- package/src/detectors/broken-link.ts +26 -2
- package/src/detectors/capitalised-term.ts +26 -2
- package/src/detectors/caps-caption.ts +76 -0
- package/src/detectors/caps-phrase.ts +17 -0
- package/src/detectors/char-shape.ts +73 -14
- package/src/detectors/citation-sentence.ts +44 -0
- package/src/detectors/cited-title.ts +15 -3
- package/src/detectors/contraction-mention.ts +24 -0
- package/src/detectors/counter-edge.ts +17 -2
- package/src/detectors/dash-break.ts +45 -0
- package/src/detectors/date-any-year.ts +34 -9
- package/src/detectors/date-format.ts +2 -1
- package/src/detectors/date-year.ts +64 -16
- package/src/detectors/deadline-unit.ts +40 -0
- package/src/detectors/defined-term-form.ts +32 -12
- package/src/detectors/definition-use.ts +17 -9
- package/src/detectors/derived-numbers.ts +19 -4
- package/src/detectors/document-shape.ts +20 -1
- package/src/detectors/doubled-across-aside.ts +36 -0
- package/src/detectors/doubled-punctuation.ts +28 -7
- package/src/detectors/doubled-word.ts +2 -1
- package/src/detectors/duplicate-heading.ts +26 -3
- package/src/detectors/ellipsis.ts +16 -1
- package/src/detectors/email-letter.ts +142 -23
- package/src/detectors/field-label.ts +25 -0
- package/src/detectors/footnote-mismatch.ts +39 -7
- package/src/detectors/fullwidth-alnum.ts +9 -1
- package/src/detectors/graded-step.ts +52 -0
- package/src/detectors/gram-openers.ts +50 -0
- package/src/detectors/gram-place.ts +10 -1
- package/src/detectors/gram-predicate.ts +43 -3
- package/src/detectors/heading-echo.ts +31 -3
- package/src/detectors/heading-record-rhythm.ts +57 -0
- package/src/detectors/ime-residue.ts +4 -3
- package/src/detectors/kanji-compound-slip.ts +61 -0
- package/src/detectors/kutoten-consistency.ts +102 -14
- package/src/detectors/lexicon.ts +18 -5
- package/src/detectors/link-shape.ts +10 -3
- package/src/detectors/list-item-ending.ts +51 -0
- package/src/detectors/list-parallel.ts +158 -33
- package/src/detectors/list-sentence.ts +5 -1
- package/src/detectors/mark-shape.ts +89 -10
- package/src/detectors/mentioned-phrase.ts +38 -0
- package/src/detectors/middle-dot.ts +7 -2
- package/src/detectors/modal-conflict.ts +5 -2
- package/src/detectors/name-variant.ts +6 -0
- package/src/detectors/notice-paragraph.ts +33 -0
- package/src/detectors/number-style.ts +14 -2
- package/src/detectors/number-unit.ts +28 -1
- package/src/detectors/numeral-opener.ts +27 -1
- package/src/detectors/obligation-without-deadline.ts +29 -4
- package/src/detectors/open-end-class.ts +78 -0
- package/src/detectors/open-end-condition.ts +40 -0
- package/src/detectors/open-end-names.ts +9 -3
- package/src/detectors/open-end-question.ts +50 -0
- package/src/detectors/open-end-scope.ts +62 -0
- package/src/detectors/opening-date.ts +47 -0
- package/src/detectors/ordinary-phrase.ts +62 -0
- package/src/detectors/organisation-run.ts +18 -2
- package/src/detectors/orthographic-variant.ts +124 -25
- package/src/detectors/orthography.ts +15 -2
- package/src/detectors/oxford-comma.ts +74 -3
- package/src/detectors/person-consistency.ts +5 -3
- package/src/detectors/phrase-match.ts +16 -5
- package/src/detectors/placeholder-text.ts +18 -3
- package/src/detectors/placeholder.ts +10 -3
- package/src/detectors/postcode-end.ts +16 -0
- package/src/detectors/prose-total-words.ts +18 -0
- package/src/detectors/range-notation.ts +26 -6
- package/src/detectors/registry/kanji-compound-slip.ts +4 -0
- package/src/detectors/registry/phrase-in-use.ts +4 -0
- package/src/detectors/requirement-smell.ts +45 -8
- package/src/detectors/scaled-figure-unit.ts +103 -0
- package/src/detectors/sentence-counts.ts +64 -12
- package/src/detectors/sentence-ending.ts +12 -3
- package/src/detectors/sentence-length.ts +17 -4
- package/src/detectors/sentence-load.ts +9 -2
- package/src/detectors/signals.ts +50 -53
- package/src/detectors/structure-tree.ts +14 -14
- package/src/detectors/structure.ts +2 -1
- package/src/detectors/subject-name-line.ts +66 -0
- package/src/detectors/superlative-name.ts +10 -0
- package/src/detectors/table-header.ts +15 -1
- package/src/detectors/technical-docs.ts +5 -1
- package/src/detectors/term-mention-sentence.ts +31 -0
- package/src/detectors/titled-run.ts +9 -4
- package/src/detectors/token-shape.ts +16 -5
- package/src/detectors/undefined-term.ts +8 -0
- package/src/detectors/unknown-word.ts +1 -1
- package/src/detectors/vague-density.ts +20 -4
- package/src/document-paragraphs.ts +27 -0
- package/src/document.ts +3 -23
- package/src/figure-references.ts +7 -2
- package/src/format-template.ts +15 -0
- package/src/formula-brackets.ts +36 -0
- package/src/html/html-markdown.ts +2 -1
- package/src/html/html-site-chrome.ts +104 -0
- package/src/joined-view.ts +1 -0
- package/src/kanji-compound-slip.ts +98 -0
- package/src/latin-company-form.ts +38 -0
- package/src/latin-word-boundary.ts +64 -0
- package/src/leading-label.ts +15 -0
- package/src/lexicon-genres.ts +1 -1
- package/src/link-shape.ts +31 -0
- package/src/link-title.ts +38 -0
- package/src/list-item-paragraphs.ts +22 -0
- package/src/literal-quote.ts +55 -0
- package/src/nado-closed-list.ts +48 -5
- package/src/name-misspelt-usual.ts +25 -0
- package/src/name-separator.ts +27 -2
- package/src/nominal-stem.ts +62 -5
- package/src/notice-header.ts +57 -0
- package/src/person-forms.ts +15 -0
- package/src/plugin.ts +5 -0
- package/src/preamble-paragraphs.ts +13 -3
- package/src/sentence-load.ts +14 -3
- package/src/spacing-code.ts +5 -1
- package/src/split-noun.ts +63 -0
- package/src/structure/attached-parts.ts +47 -0
- package/src/structure/build.ts +7 -4
- package/src/structure/contents-lines.ts +63 -0
- package/src/structure/defining-names.ts +155 -0
- package/src/structure/definition-use.ts +149 -32
- package/src/structure/gerund-phrase.ts +31 -0
- package/src/structure/issues.ts +7 -3
- package/src/structure/list-lead-in.ts +94 -0
- package/src/structure/modal-conflict.ts +42 -7
- package/src/structure/negated-act.ts +49 -0
- package/src/structure/numbering.ts +24 -9
- package/src/structure/prose-total.ts +20 -6
- package/src/structure/repeated-number.ts +110 -0
- package/src/structure/rounded-amount.ts +55 -0
- package/src/structure/side-step.ts +21 -0
- package/src/structure/spanned-label-blank.ts +39 -0
- package/src/structure/universal.ts +33 -9
- package/src/structure/unspaced-heading.ts +27 -0
- package/src/structure/written-list-path.ts +46 -0
- package/src/structure/written-resolve.ts +16 -9
- package/src/title-line.ts +53 -0
- package/src/topic-clause.ts +109 -0
- package/src/uncounted-particles.ts +72 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// A quotation that holds a string to be typed as it stands: an e-mail subject (件名に「応募(総務課)」と記載), a file name
|
|
2
|
+
// (「【様式】(氏名)」とファイル名を変更), a title (titled “Rates (2026)”). Its brackets are the string's own; the writer cannot
|
|
3
|
+
// take them out. Which words around a quotation say so come from the language's literal-quote-cue lexicon. Pure.
|
|
4
|
+
import { QUOTATION_MARKS, quotedSpans } from "./quoted-span.ts";
|
|
5
|
+
import type { LexiconEntry, Span } from "./plugin.ts";
|
|
6
|
+
|
|
7
|
+
export type LiteralCues = { readonly before: readonly string[]; readonly after: readonly string[] };
|
|
8
|
+
|
|
9
|
+
/** The cues of the lexicon: `position: before` stands in front of the quotation (件名に「…」), the rest right after it (「…」と記載). */
|
|
10
|
+
export const literalCues = (entries: readonly LexiconEntry[]): LiteralCues => ({
|
|
11
|
+
before: entries.filter((entry) => entry.position === "before").map((entry) => entry.pattern.toLowerCase()),
|
|
12
|
+
after: entries.filter((entry) => entry.position !== "before").map((entry) => entry.pattern.toLowerCase()),
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
/** Spaces allowed between a cue and its quotation; farther than this the cue is not the quotation's. */
|
|
16
|
+
const GAP = 8;
|
|
17
|
+
const LATIN_LETTER = /[A-Za-z]/u;
|
|
18
|
+
|
|
19
|
+
/** A cue that begins or ends with a Latin letter is a word: named does not match the end of unnamed. */
|
|
20
|
+
const standsBefore = (window: string, cue: string): boolean =>
|
|
21
|
+
window.endsWith(cue) && !(LATIN_LETTER.test(cue.at(0) ?? "") && LATIN_LETTER.test(window.at(-cue.length - 1) ?? ""));
|
|
22
|
+
|
|
23
|
+
const standsAfter = (window: string, cue: string): boolean =>
|
|
24
|
+
window.startsWith(cue) && !(LATIN_LETTER.test(cue.at(-1) ?? "") && LATIN_LETTER.test(window.at(cue.length) ?? ""));
|
|
25
|
+
|
|
26
|
+
/** How far from a quotation to read: the longest cue, one letter more to tell a word from part of one, and the gap. */
|
|
27
|
+
const reachOf = (cues: LiteralCues): number => Math.max(0, ...[...cues.before, ...cues.after].map((cue) => cue.length)) + 1 + GAP;
|
|
28
|
+
|
|
29
|
+
/** Only the few characters next to the quotation are read, so a sentence of many quotations stays linear. */
|
|
30
|
+
const isLiteral = (text: string, quoted: Span, cues: LiteralCues, reach: number): boolean => {
|
|
31
|
+
const opener = quoted.start - 1;
|
|
32
|
+
const closerEnd = quoted.end + 1;
|
|
33
|
+
const before = text
|
|
34
|
+
.slice(Math.max(0, opener - reach), opener)
|
|
35
|
+
.trimEnd()
|
|
36
|
+
.toLowerCase();
|
|
37
|
+
const after = text
|
|
38
|
+
.slice(closerEnd, closerEnd + reach)
|
|
39
|
+
.trimStart()
|
|
40
|
+
.toLowerCase();
|
|
41
|
+
return cues.before.some((cue) => standsBefore(before, cue)) || cues.after.some((cue) => standsAfter(after, cue));
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/** The insides of the quotations the cues mark as a literal string, without the quotation marks. Positions count from 0 in `text`. */
|
|
45
|
+
export const literalQuoteSpans = (text: string, cues: LiteralCues): Span[] => {
|
|
46
|
+
const reach = reachOf(cues);
|
|
47
|
+
return quotedSpans(text, QUOTATION_MARKS).filter((quoted) => isLiteral(text, quoted, cues, reach));
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/** The text with each literal quotation's inside blanked to spaces, so a measure of the sentence's own brackets skips it. */
|
|
51
|
+
export const withoutLiteralQuotes = (text: string, cues: LiteralCues): string => {
|
|
52
|
+
const units = text.split("");
|
|
53
|
+
literalQuoteSpans(text, cues).forEach((span) => units.fill(" ", span.start, span.end));
|
|
54
|
+
return units.join("");
|
|
55
|
+
};
|
package/src/nado-closed-list.ts
CHANGED
|
@@ -38,6 +38,8 @@ const CLAUSE_POS: ReadonlySet<string> = new Set(["AUX", "VERB"]);
|
|
|
38
38
|
/** A verb form that modifies a noun inside a list (a driving licence, used cars). */
|
|
39
39
|
const NOUN_MODIFYING_FORMS: ReadonlySet<string> = new Set(["Ger", "Part"]);
|
|
40
40
|
const LIST_SEPARATOR = /[,、]/u;
|
|
41
|
+
/** The parts of speech a list item is made of. */
|
|
42
|
+
const NAME_POS: ReadonlySet<string> = new Set(["NOUN", "PROPN"]);
|
|
41
43
|
|
|
42
44
|
/** Where a word occurs in a text; a Latin word only as whole words, any case. */
|
|
43
45
|
const placesOf = (text: string, word: string): number[] => {
|
|
@@ -59,12 +61,53 @@ const standsAsOpenWord = (tokens: readonly Token[], at: number, open: string): b
|
|
|
59
61
|
return token !== undefined && open.toLowerCase().startsWith(token.surface.toLowerCase()) && token.features?.NounType !== CLASS_NOUN;
|
|
60
62
|
};
|
|
61
63
|
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
64
|
+
const BRACKET = /[(())]/gu;
|
|
65
|
+
const CLOSE_BRACKET = /[))]/u;
|
|
66
|
+
|
|
67
|
+
/** Where the bracket still open at offset opened, or -1 when none is. */
|
|
68
|
+
const openBracketBefore = (text: string, at: number): number => {
|
|
69
|
+
const stillOpen = [...text.slice(0, at).matchAll(BRACKET)].reduce<number[]>(
|
|
70
|
+
(open, bracket) => (CLOSE_BRACKET.test(bracket[0]) ? open.slice(0, -1) : [...open, bracket.index]),
|
|
71
|
+
[],
|
|
72
|
+
);
|
|
73
|
+
return stillOpen.at(-1) ?? -1;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* The open word ends an aside on the word before the bracket, and the limit stands outside it (従業員(エンジニア、デザイナー等)のみ):
|
|
78
|
+
* the limit governs that word, and the list only gives examples of it.
|
|
79
|
+
*/
|
|
80
|
+
const closesAsideBeforeLimit = (text: string, at: number, skipped: string): boolean => {
|
|
81
|
+
if (!CLOSE_BRACKET.test(skipped)) return false;
|
|
82
|
+
const bracket = openBracketBefore(text, at);
|
|
83
|
+
return LETTER.test(text.slice(0, Math.max(bracket, 0)).trimEnd().at(-1) ?? "");
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const limitRightAfter = (text: string, at: number, open: string, words: ClosedListWords): string | undefined => {
|
|
87
|
+
const rest = text.slice(at + open.length);
|
|
88
|
+
const skipped = BETWEEN_OPEN_AND_LIMIT.exec(rest)?.[0] ?? "";
|
|
89
|
+
const after = rest.slice(skipped.length);
|
|
90
|
+
if (words.notLimits.some((phrase) => startsWithWord(after, phrase)) || closesAsideBeforeLimit(text, at, skipped)) return undefined;
|
|
65
91
|
return longestFirst(words.limitsAfter).find((limit) => startsWithWord(after, limit));
|
|
66
92
|
};
|
|
67
93
|
|
|
94
|
+
const isItemToken = (token: Token | undefined): token is Token => token !== undefined && NAME_POS.has(token.pos);
|
|
95
|
+
|
|
96
|
+
/** Where the run of nouns written right before end starts (監査 in 監査指示 before 等), or end when no noun ends there. */
|
|
97
|
+
const itemStart = (tokens: readonly Token[], end: number): number => {
|
|
98
|
+
const last = tokens.find((token) => token.span.end === end);
|
|
99
|
+
return isItemToken(last) ? itemStart(tokens, last.span.start) : end;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
/** The nouns written right before the open word (指示 in 指示等), by the tokens; empty when none are. */
|
|
103
|
+
const itemBefore = (text: string, tokens: readonly Token[], at: number): string => text.slice(itemStart(tokens, at), at);
|
|
104
|
+
|
|
105
|
+
/** The same list written earlier in the sentence (個別の指示等が … 当該指示等に限り): the open word refers back to it, and leaves nothing new open. */
|
|
106
|
+
const repeatsEarlierList = (text: string, tokens: readonly Token[], at: number, open: string): boolean => {
|
|
107
|
+
const item = itemBefore(text, tokens, at);
|
|
108
|
+
return item !== "" && placesOf(text.slice(0, at - item.length), open).some((earlier) => itemBefore(text, tokens, earlier) === item);
|
|
109
|
+
};
|
|
110
|
+
|
|
68
111
|
const longestFirst = (words: readonly string[]): string[] => [...words].sort((a, b) => b.length - a.length);
|
|
69
112
|
|
|
70
113
|
const insideNotLimit = (text: string, at: number, notLimits: readonly string[]): boolean =>
|
|
@@ -97,9 +140,9 @@ const limitBefore = (text: string, tokens: readonly Token[], at: number, words:
|
|
|
97
140
|
export const openWordsOnClosedLists = (text: string, tokens: readonly Token[], words: ClosedListWords): OpenOnClosed[] =>
|
|
98
141
|
words.open
|
|
99
142
|
.flatMap((open) => placesOf(text, open).map((at) => ({ open, at })))
|
|
100
|
-
.filter(({ open, at }) => standsAsOpenWord(tokens, at, open))
|
|
143
|
+
.filter(({ open, at }) => standsAsOpenWord(tokens, at, open) && !repeatsEarlierList(text, tokens, at, open))
|
|
101
144
|
.flatMap(({ open, at }) => {
|
|
102
|
-
const limit = limitRightAfter(text
|
|
145
|
+
const limit = limitRightAfter(text, at, open, words) ?? limitBefore(text, tokens, at, words);
|
|
103
146
|
return limit === undefined ? [] : [{ offset: at, open, limit }];
|
|
104
147
|
})
|
|
105
148
|
.sort((a, b) => a.offset - b.offset || b.open.length - a.open.length)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// name-variant points at the less frequent form and names the more frequent one as the usual. When the usual form holds a
|
|
2
|
+
// word the dictionary lacks, one letter from the dictionary word the pointed form has in its place ("Release Sechedule" ×3
|
|
3
|
+
// beside "Release Schedule"), the frequent form is a repeated typo, and the pointed form is the right spelling. Pure.
|
|
4
|
+
import { editsOf } from "./spelling.ts";
|
|
5
|
+
|
|
6
|
+
/** Whether a lower-case word is a dictionary word, with its endings (lords, schedules). */
|
|
7
|
+
export type IsKnown = (word: string) => boolean;
|
|
8
|
+
|
|
9
|
+
/** A word the edits are made on: ASCII letters only, as editsOf makes them. */
|
|
10
|
+
const PLAIN_WORD = /^[a-z]+$/u;
|
|
11
|
+
|
|
12
|
+
const wordsOf = (name: string): string[] => name.toLowerCase().trim().split(/\s+/u);
|
|
13
|
+
|
|
14
|
+
/** The usual form's word is a one-letter slip of the pointed form's dictionary word in the same place. */
|
|
15
|
+
const isSlipOf = (usualWord: string, nameWord: string, isKnown: IsKnown): boolean =>
|
|
16
|
+
PLAIN_WORD.test(usualWord) && PLAIN_WORD.test(nameWord) && isKnown(nameWord) && !isKnown(usualWord) && editsOf(usualWord).includes(nameWord);
|
|
17
|
+
|
|
18
|
+
/** Whether the two forms have the same words in the same places but where the usual one has a one-letter slip of a dictionary word. */
|
|
19
|
+
export const usualIsMisspelt = (name: string, usual: string, isKnown: IsKnown): boolean => {
|
|
20
|
+
const nameWords = wordsOf(name);
|
|
21
|
+
const usualWords = wordsOf(usual);
|
|
22
|
+
if (nameWords.length !== usualWords.length) return false;
|
|
23
|
+
const differing = usualWords.flatMap((word, index) => (word === nameWords[index] ? [] : [index]));
|
|
24
|
+
return differing.length > 0 && differing.every((index) => isSlipOf(usualWords[index] ?? "", nameWords[index] ?? "", isKnown));
|
|
25
|
+
};
|
package/src/name-separator.ts
CHANGED
|
@@ -63,6 +63,29 @@ const PAIR_LEAD = /^[ \t\u3000]*(?:(?:[-*+]|\d{1,3}[..))])[ \t\u3000]+)?/u;
|
|
|
63
63
|
const PAIR_LABEL = /^[^\s\d、,,()()||::。!?]{2,12}$/u;
|
|
64
64
|
const PAIR_VALUE = /^\d(?:[^\s、,,()()||。!?]|(?<=\d),(?=\d))*$/u;
|
|
65
65
|
|
|
66
|
+
/**
|
|
67
|
+
* 値の後ろに括弧で添えた説明(10万円 (税込 11万円))の、開く字と閉じる字。囲みは閉じ括弧の手前で終わるので、最後の開き括弧から後ろが説明。
|
|
68
|
+
* 入れ子の括弧((税込 (内訳)))は読まない。
|
|
69
|
+
*/
|
|
70
|
+
const ASIDE_PAIRS: ReadonlyMap<string, string> = new Map([
|
|
71
|
+
["(", ")"],
|
|
72
|
+
["(", ")"],
|
|
73
|
+
]);
|
|
74
|
+
|
|
75
|
+
/** 説明の括弧の後ろに残ってよいもの: 空白と強調の印。語が続けば(で募集します)文の中の値。 */
|
|
76
|
+
const LINE_REST = /^[\s*_]*$/u;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* 組の値。値の後ろに同じ形の括弧で閉じた説明を添えて行が終わるなら、説明を除いた値。閉じていないか、
|
|
80
|
+
* 説明の後ろに語が続けば undefined。fromEnclosureEnd は囲みの終わり(閉じ括弧か行末)から行末まで。
|
|
81
|
+
*/
|
|
82
|
+
const valueOf = (written: string, fromEnclosureEnd: string): string | undefined => {
|
|
83
|
+
const aside = Math.max(...[...ASIDE_PAIRS.keys()].map((open) => written.lastIndexOf(open)));
|
|
84
|
+
if (aside < 0) return written;
|
|
85
|
+
const closed = fromEnclosureEnd[0] === ASIDE_PAIRS.get(written[aside] ?? "");
|
|
86
|
+
return closed && LINE_REST.test(fromEnclosureEnd.slice(1)) ? written.slice(0, aside).trimEnd() : undefined;
|
|
87
|
+
};
|
|
88
|
+
|
|
66
89
|
/** 項目名に出る品詞。名詞だけで、助詞・副詞(およそ)・接頭の語(約)を含めば、量の前置きか文。 */
|
|
67
90
|
const PAIR_LABEL_POS = new Set(["NOUN", "PROPN"]);
|
|
68
91
|
|
|
@@ -92,10 +115,12 @@ const pairAround = (text: string, enclosure: Span, at: number): Span => {
|
|
|
92
115
|
* 項目名が 1 字(約 30名)か名詞でない語を含む組は、文の中の空白として数える。
|
|
93
116
|
*/
|
|
94
117
|
const isLabelledValue = (text: string, boundary: Boundary, tokens: readonly Token[], base: number): boolean => {
|
|
95
|
-
const
|
|
118
|
+
const line = lineAround(text, boundary.offset);
|
|
119
|
+
const enclosure = enclosureAround(text, line, boundary.offset);
|
|
96
120
|
const pair = pairAround(text, enclosure, boundary.offset);
|
|
97
121
|
const label = { start: pair.start, end: boundary.offset };
|
|
98
|
-
|
|
122
|
+
const value = valueOf(text.slice(boundary.offset + 1, pair.end), text.slice(enclosure.end, line.end));
|
|
123
|
+
if (!PAIR_LABEL.test(text.slice(label.start, label.end)) || value === undefined || !PAIR_VALUE.test(value)) return false;
|
|
99
124
|
if (SENTENCE_END.test(text.slice(enclosure.start, enclosure.end))) return false;
|
|
100
125
|
const labelTokens = tokensIn(tokens, label, base);
|
|
101
126
|
return (
|
package/src/nominal-stem.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Token } from "./plugin.ts";
|
|
2
|
+
import { kanjiSkeleton } from "./kana-spelling.ts";
|
|
2
3
|
|
|
3
4
|
/** The last kana of a verb's dictionary form, and the kana its stem form (連用形) ends in instead: 払い込む → 払い込み. */
|
|
4
5
|
const STEM_ENDING: Readonly<Record<string, string>> = { う: "い", く: "き", ぐ: "ぎ", す: "し", つ: "ち", ぬ: "に", ぶ: "び", む: "み", る: "り" };
|
|
@@ -17,20 +18,76 @@ export const isStemForm = (surface: string, lemma: string): boolean => {
|
|
|
17
18
|
/** What carries a verb on (払い込み、払い込んで, 払い込みます, 払い込みやすい): after these the stem form is still the verb. */
|
|
18
19
|
const VERB_GOES_ON = new Set(["AUX", "SCONJ", "VERB", "ADJ"]);
|
|
19
20
|
const CLAUSE_COMMA = new Set(["、", ",", ","]);
|
|
21
|
+
/** The verbs that make a verb of a noun written right before them (申出する, 申出できる): the stem form there is the noun. */
|
|
22
|
+
const LIGHT_VERBS = new Set(["する", "できる", "出来る"]);
|
|
23
|
+
|
|
24
|
+
const carriesTheVerb = (next: Token): boolean => VERB_GOES_ON.has(next.pos) && !(next.pos === "VERB" && LIGHT_VERBS.has(next.lemma ?? ""));
|
|
25
|
+
|
|
26
|
+
/** A word's kanji and reading, one key for 申出 and 申し出 (申出|モウシデ); undefined for a word with no kanji or no reading. */
|
|
27
|
+
export const nounKeyOf = (token: Token): string | undefined => {
|
|
28
|
+
const kanji = kanjiSkeleton(token.surface);
|
|
29
|
+
return kanji === "" || token.reading === undefined ? undefined : `${kanji}|${token.reading}`;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const isAmong = (token: Token, nouns: ReadonlySet<string>): boolean => {
|
|
33
|
+
const key = nounKeyOf(token);
|
|
34
|
+
return key !== undefined && nouns.has(key);
|
|
35
|
+
};
|
|
20
36
|
|
|
21
37
|
/**
|
|
22
38
|
* A free noun after the stem form may begin the next clause (疾病にかかり療養のために), so the stem form stays a verb; a suffix
|
|
23
|
-
* (払込み等),
|
|
39
|
+
* (払込み等), a noun the caller lists as one (受取り前), or any noun after a word the document writes as a noun elsewhere
|
|
40
|
+
* (申し出期限 beside 申出の撤回) may not.
|
|
24
41
|
*/
|
|
25
|
-
const verbGoesOn = (next: Token, suffixes: ReadonlySet<string>): boolean =>
|
|
26
|
-
|
|
42
|
+
const verbGoesOn = (token: Token, next: Token, suffixes: ReadonlySet<string>, nouns: ReadonlySet<string>): boolean =>
|
|
43
|
+
carriesTheVerb(next) ||
|
|
44
|
+
CLAUSE_COMMA.has(next.surface) ||
|
|
45
|
+
(next.pos === "NOUN" && next.features?.["Bound"] !== "Yes" && !suffixes.has(next.surface) && !isAmong(token, nouns));
|
|
27
46
|
|
|
28
47
|
/**
|
|
29
48
|
* A verb's stem form that the verb does not go on from (払込みの期日, 申出により, 株式の買取り)): a noun the analyser read as the
|
|
30
49
|
* verb, returned as the noun it is, spelled as written. Official Japanese spells the noun and the verb apart (払込み, 払い込む),
|
|
31
50
|
* so the two are not one word in two spellings; the noun is compared with nouns. Any other token is returned as it is.
|
|
51
|
+
* nouns holds the document's nouns (documentNounKeys).
|
|
32
52
|
*/
|
|
33
|
-
export const asNounWhereNominal = (
|
|
53
|
+
export const asNounWhereNominal = (
|
|
54
|
+
token: Token,
|
|
55
|
+
next: Token | undefined,
|
|
56
|
+
suffixes: ReadonlySet<string> = new Set(),
|
|
57
|
+
nouns: ReadonlySet<string> = new Set(),
|
|
58
|
+
): Token => {
|
|
34
59
|
if (token.pos !== "VERB" || token.lemma === undefined || !isStemForm(token.surface, token.lemma)) return token;
|
|
35
|
-
return next !== undefined && verbGoesOn(next, suffixes) ? token : { ...token, pos: "NOUN", lemma: token.surface };
|
|
60
|
+
return next !== undefined && verbGoesOn(token, next, suffixes, nouns) ? token : { ...token, pos: "NOUN", lemma: token.surface };
|
|
36
61
|
};
|
|
62
|
+
|
|
63
|
+
/** A particle that ties what is before it to a noun after it (の, での, に関する, における): what follows it is a noun. */
|
|
64
|
+
const ATTRIBUTIVE_PARTICLE = /[のる]$/u;
|
|
65
|
+
|
|
66
|
+
const isStemAfterParticle = (token: Token, previous: Token | undefined, next: Token | undefined): boolean =>
|
|
67
|
+
previous?.pos === "ADP" &&
|
|
68
|
+
ATTRIBUTIVE_PARTICLE.test(previous.surface) &&
|
|
69
|
+
CLAUSE_COMMA.has(next?.surface ?? "") &&
|
|
70
|
+
token.pos === "VERB" &&
|
|
71
|
+
token.lemma !== undefined &&
|
|
72
|
+
isStemForm(token.surface, token.lemma);
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* The sentence with a stem form between a particle that ties it to a noun and a comma (地域の取組み、) read as the noun it is,
|
|
76
|
+
* spelled as written: before a comma the stem form is otherwise the verb (課題に取り組み、成果を上げた).
|
|
77
|
+
*/
|
|
78
|
+
export const withNounsAfterParticles = (tokens: readonly Token[]): readonly Token[] =>
|
|
79
|
+
tokens.map((token, at) => (isStemAfterParticle(token, tokens[at - 1], tokens[at + 1]) ? { ...token, pos: "NOUN", lemma: token.surface } : token));
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* The keys (nounKeyOf) of the nouns a document writes, stem forms the verb does not go on from included (申出 before の): what
|
|
83
|
+
* tells asNounWhereNominal that a stem form before a noun makes a compound (申し出期限) rather than ends a clause (疾病にかかり療養).
|
|
84
|
+
*/
|
|
85
|
+
export const documentNounKeys = (sentences: readonly (readonly Token[])[], suffixes: ReadonlySet<string> = new Set()): Set<string> =>
|
|
86
|
+
new Set(
|
|
87
|
+
sentences.map(withNounsAfterParticles).flatMap((tokens) =>
|
|
88
|
+
tokens.flatMap((token, at) => {
|
|
89
|
+
const key = asNounWhereNominal(token, tokens[at + 1], suffixes).pos === "NOUN" ? nounKeyOf(token) : undefined;
|
|
90
|
+
return key === undefined ? [] : [key];
|
|
91
|
+
}),
|
|
92
|
+
),
|
|
93
|
+
);
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// An official notice's head (通達: 課資2-7 / 各国税局長 殿): a document number and an addressee with an honorific of
|
|
2
|
+
// office. Pure. The words come from the language's notice-header lexicon; a notice takes no greeting and no closing.
|
|
3
|
+
import type { Lexicon } from "./plugin.ts";
|
|
4
|
+
|
|
5
|
+
/** The words of a notice's head, by their group in the notice-header lexicon. */
|
|
6
|
+
export type NoticeWords = {
|
|
7
|
+
/** What a document number starts with (課資2-7: 課). */
|
|
8
|
+
readonly numberPrefixes: readonly string[];
|
|
9
|
+
/** The word before and the word after the number of a document number written 〜第123号. */
|
|
10
|
+
readonly numberHeads: readonly string[];
|
|
11
|
+
readonly numberTails: readonly string[];
|
|
12
|
+
/** The honorific an official notice puts after its addressee (各国税局長 殿). */
|
|
13
|
+
readonly addressees: readonly string[];
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const patternsIn = (lexicon: Lexicon, group: string): string[] => lexicon.filter((entry) => entry.group === group).map((entry) => entry.pattern);
|
|
17
|
+
|
|
18
|
+
export const noticeWordsOf = (lexicon: Lexicon): NoticeWords => ({
|
|
19
|
+
numberPrefixes: patternsIn(lexicon, "number-prefix"),
|
|
20
|
+
numberHeads: patternsIn(lexicon, "number-head"),
|
|
21
|
+
numberTails: patternsIn(lexicon, "number-tail"),
|
|
22
|
+
addressees: patternsIn(lexicon, "addressee"),
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
/** A document number is one short token of a line: 課資2-7, 総務省発第123号. */
|
|
26
|
+
const MAX_NUMBER_LENGTH = 20;
|
|
27
|
+
const DIGIT = /\p{Nd}/u;
|
|
28
|
+
const BLANK = /\s/u;
|
|
29
|
+
/** A document number is written in kanji, digits and dashes; hiragana makes the line words (課題は3つ). */
|
|
30
|
+
const HIRAGANA = /\p{Script=Hiragana}/u;
|
|
31
|
+
|
|
32
|
+
/** What follows the prefix: the office's kanji, then numbers joined by dashes (課資3-7: 資, 3-7). 課題3 has no dash. */
|
|
33
|
+
const PREFIXED_NUMBER_BODY = /^\p{Script=Han}*\p{Nd}+(?:[--‐−–―]\p{Nd}+)+$/u;
|
|
34
|
+
|
|
35
|
+
const isNumberedForm = (line: string, words: NoticeWords): boolean =>
|
|
36
|
+
words.numberPrefixes.some((prefix) => prefix !== "" && line.startsWith(prefix) && PREFIXED_NUMBER_BODY.test(line.slice(prefix.length))) ||
|
|
37
|
+
words.numberTails.some(
|
|
38
|
+
(tail) => tail !== "" && line.endsWith(tail) && words.numberHeads.some((head) => head !== "" && line.slice(0, -tail.length).includes(head)),
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
const isNumberShaped = (line: string): boolean => line.length <= MAX_NUMBER_LENGTH && DIGIT.test(line) && !BLANK.test(line) && !HIRAGANA.test(line);
|
|
42
|
+
|
|
43
|
+
/** Whether a line is a document number alone: short, one run of characters with a digit and no hiragana, in one of the lexicon's forms. */
|
|
44
|
+
export const isDocumentNumber = (line: string, words: NoticeWords): boolean => {
|
|
45
|
+
const trimmed = line.trim();
|
|
46
|
+
return isNumberShaped(trimmed) && isNumberedForm(trimmed, words);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/** Whether a line is an addressee: a name, then the notice's honorific at the line's end (各国税局長 殿). */
|
|
50
|
+
export const isNoticeAddressee = (line: string, words: NoticeWords): boolean => {
|
|
51
|
+
const trimmed = line.trim();
|
|
52
|
+
return words.addressees.some((word) => trimmed.endsWith(word) && trimmed.length > word.length);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/** Whether head lines (before the first sentence) hold both a document number and an addressee of a notice. */
|
|
56
|
+
export const isNoticeHead = (headLines: readonly string[], words: NoticeWords): boolean =>
|
|
57
|
+
headLines.some((line) => isDocumentNumber(line, words)) && headLines.some((line) => isNoticeAddressee(line, words));
|
package/src/person-forms.ts
CHANGED
|
@@ -104,6 +104,21 @@ const usualForm = (forms: readonly string[]): string | undefined => {
|
|
|
104
104
|
return [...counts.entries()].reduce<[string, number] | undefined>((best, next) => (best === undefined || next[1] > best[1] ? next : best), undefined)?.[0];
|
|
105
105
|
};
|
|
106
106
|
|
|
107
|
+
/**
|
|
108
|
+
* Pure: entries without the places of a form that also names something else (本社 is also the head office), unless that
|
|
109
|
+
* form is the slot's usual one. A document that calls itself 当社 writes 本社 for its head office; one that calls itself
|
|
110
|
+
* 本社 still has its stray 当社 pointed at.
|
|
111
|
+
*/
|
|
112
|
+
export const withoutOtherSenses = <T extends { readonly mention: PersonMention }>(entries: readonly T[], otherSenses: ReadonlySet<string>): T[] => {
|
|
113
|
+
const usual = new Map(
|
|
114
|
+
[...new Set(entries.map((entry) => entry.mention.slot))].map((slot) => [
|
|
115
|
+
slot,
|
|
116
|
+
usualForm(entries.filter((entry) => entry.mention.slot === slot).map((entry) => entry.mention.form)),
|
|
117
|
+
]),
|
|
118
|
+
);
|
|
119
|
+
return entries.filter((entry) => !otherSenses.has(entry.mention.form) || usual.get(entry.mention.slot) === entry.mention.form);
|
|
120
|
+
};
|
|
121
|
+
|
|
107
122
|
/**
|
|
108
123
|
* Pure: for each slot, the places that use another form than the document's usual one. Entries are in document order.
|
|
109
124
|
* Nothing when the slot has one form, when the usual form has fewer than MIN_USUAL places, or when the other forms pass
|
package/src/plugin.ts
CHANGED
|
@@ -24,6 +24,11 @@ export type Sentence = {
|
|
|
24
24
|
* 長さの rule はこの単位で数え、この言語の上限と比べる。
|
|
25
25
|
*/
|
|
26
26
|
readonly embeddedLanguage?: EmbeddedLanguage;
|
|
27
|
+
/**
|
|
28
|
+
* 行頭の印で始まる箇条書きの項目を始める文(「①誓約書」「・〜に関する業務」)。adapter が入れる。
|
|
29
|
+
* core は項目ごとに段落を改める。
|
|
30
|
+
*/
|
|
31
|
+
readonly listItem?: true;
|
|
27
32
|
};
|
|
28
33
|
|
|
29
34
|
export type EmbeddedLanguage = { readonly id: string; readonly lengthUnit: LengthUnit };
|
|
@@ -19,10 +19,20 @@ const isNameField = (paragraph: Paragraph, source: string): boolean => {
|
|
|
19
19
|
return value !== undefined && value.split(/\s+/u).every(isNameWord);
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
+
/** A note the text attaches to one of its words (※1 特定の走行環境条件), opened by a mark of the note-mark lexicon. */
|
|
23
|
+
const isNote = (paragraph: Paragraph, source: string, noteMarks: readonly string[]): boolean => {
|
|
24
|
+
const text = source.slice(paragraph.span.start, paragraph.span.end).trimStart();
|
|
25
|
+
return noteMarks.some((mark) => mark !== "" && text.startsWith(mark));
|
|
26
|
+
};
|
|
27
|
+
|
|
22
28
|
/**
|
|
23
29
|
* 本題の前にあって、読み手が読み通す段落。文が一つも終止符で閉じない段落は数えない。
|
|
24
30
|
* 分類の札(「エネルギー・環境」)、著者と所属の行、「印刷」、テンプレートの指示は文ではなく、読ませる前置きではない。
|
|
25
|
-
* 宛先や差出人の欄(To: Minato Manufacturing Inc
|
|
31
|
+
* 宛先や差出人の欄(To: Minato Manufacturing Inc.)も、値が名前だけなら数えない。本文の語に付けた注(※1 …)は、
|
|
32
|
+
* 前置きの段落ではなく注なので数えない。source は段落の範囲を読む文書、noteMarks は語彙表 note-mark の印。
|
|
26
33
|
*/
|
|
27
|
-
export const preambleParagraphs = (paragraphs: readonly Paragraph[], bodyStart: number, source = ""): Paragraph[] =>
|
|
28
|
-
paragraphs.filter(
|
|
34
|
+
export const preambleParagraphs = (paragraphs: readonly Paragraph[], bodyStart: number, source = "", noteMarks: readonly string[] = []): Paragraph[] =>
|
|
35
|
+
paragraphs.filter(
|
|
36
|
+
(paragraph) =>
|
|
37
|
+
paragraph.span.start < bodyStart && paragraph.sentences.some(isClosed) && !isNameField(paragraph, source) && !isNote(paragraph, source, noteMarks),
|
|
38
|
+
);
|
package/src/sentence-load.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// How much one sentence asks the reader to hold at once: brackets inside brackets, clauses chained one after another, and how
|
|
2
2
|
// far the topic stands from the end where its predicate is. Pure: a sentence's text and tokens come in, numbers go out.
|
|
3
3
|
import type { Token } from "./plugin.ts";
|
|
4
|
+
import { topicClauseEnd } from "./topic-clause.ts";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Opening brackets and the mark that closes each. Quotation marks that open and close with the same character are left out, and
|
|
@@ -26,15 +27,24 @@ const OTHER_WIDTH: Readonly<Record<string, string>> = { ")": ")", ")": ")",
|
|
|
26
27
|
/** A formula written in TeX ($d^k = -\nabla f(x^k)$): its brackets are the formula's, not the sentence's. */
|
|
27
28
|
const FORMULA = /\$\$[^$]*\$\$|\$[^$\n]*\$/gu;
|
|
28
29
|
|
|
30
|
+
/**
|
|
31
|
+
* A doubled parenthesis around text with no parenthesis inside (((居住の用に供したとき等)), ((注))): one mark written with two
|
|
32
|
+
* characters, as a directive sets an article's caption, not a bracket inside a bracket.
|
|
33
|
+
*/
|
|
34
|
+
const DOUBLED_PAREN = /\(\(([^()()]*)\)\)|((([^()()]*)))/gu;
|
|
35
|
+
|
|
36
|
+
const singled = (text: string): string =>
|
|
37
|
+
text.replace(DOUBLED_PAREN, (_whole: string, half?: string, full?: string) => (half === undefined ? `(${full ?? ""})` : `(${half})`));
|
|
38
|
+
|
|
29
39
|
/**
|
|
30
40
|
* The deepest the brackets of a text nest: 「計画(案)」 is one, 「(注(a)を参照)」 two, plain text none. A closer with no
|
|
31
41
|
* opener (the 1) of a list) is ignored, an opener never closed counts as open until the end, a closer of the other width closes
|
|
32
|
-
* its opener ((1) is one), and formulas in $…$ are skipped.
|
|
42
|
+
* its opener ((1) is one), a doubled parenthesis ((題)) is one, and formulas in $…$ are skipped.
|
|
33
43
|
*/
|
|
34
44
|
export const bracketDepth = (text: string): number => {
|
|
35
45
|
// The closers still awaited, innermost last. Pushed and popped in place: copying it per character is quadratic on deep nesting.
|
|
36
46
|
const awaited: string[] = [];
|
|
37
|
-
return [...text.replace(FORMULA, " ")].reduce((deepest, char) => {
|
|
47
|
+
return [...singled(text.replace(FORMULA, " "))].reduce((deepest, char) => {
|
|
38
48
|
const innermost = awaited.at(-1);
|
|
39
49
|
if (innermost !== undefined && (innermost === char || innermost === OTHER_WIDTH[char])) awaited.pop();
|
|
40
50
|
else if (BRACKETS[char] !== undefined) awaited.push(BRACKETS[char]);
|
|
@@ -71,6 +81,7 @@ const TOPIC_BEFORE = new Set(["NOUN", "PRON", "PROPN"]);
|
|
|
71
81
|
/**
|
|
72
82
|
* How far the sentence's first topic (会議は, これは) stands from the end of the sentence, where Japanese puts the predicate the
|
|
73
83
|
* topic belongs to, in characters of the words between them (spaces, and a link's address the document hides, are not read).
|
|
84
|
+
* When the topic gets its own predicate in an earlier clause (topicClauseEnd), the distance is to that clause's end.
|
|
74
85
|
* undefined when the sentence has no topic. The distance is the reader's wait: everything between has to be held before the
|
|
75
86
|
* topic is said to do anything.
|
|
76
87
|
*/
|
|
@@ -78,5 +89,5 @@ export const topicDistance = (tokens: readonly Token[]): number | undefined => {
|
|
|
78
89
|
const topic = tokens.findIndex((token, at) => token.surface === "は" && token.pos === "ADP" && TOPIC_BEFORE.has(tokens[at - 1]?.pos ?? ""));
|
|
79
90
|
const last = tokens.findLastIndex((token) => !TRAILING.has(token.pos));
|
|
80
91
|
if (topic === -1 || last <= topic) return undefined;
|
|
81
|
-
return tokens.slice(topic + 1, last).reduce((sum, token) => sum + [...token.surface.replace(/\s/gu, "")].length, 0);
|
|
92
|
+
return tokens.slice(topic + 1, topicClauseEnd(tokens, topic, last) ?? last).reduce((sum, token) => sum + [...token.surface.replace(/\s/gu, "")].length, 0);
|
|
82
93
|
};
|
package/src/spacing-code.ts
CHANGED
|
@@ -7,6 +7,8 @@ import { HYPHEN_CHARS } from "./orthography.ts";
|
|
|
7
7
|
|
|
8
8
|
/** A clock time: hours, a colon, minutes, and seconds optionally (9:05, 13:30, 08:00:15). */
|
|
9
9
|
const CLOCK_TIME = /(?<![\d::.])\d{1,2}[::][0-5]\d(?:[::][0-5]\d)?(?![\d::])/gu;
|
|
10
|
+
/** AM or PM written after a clock time, with a space or without (9:30AM, 9:30 p.m.). */
|
|
11
|
+
const MERIDIEM = /^ ?[AaPp]\.?[Mm]\.?(?![A-Za-z])/u;
|
|
10
12
|
|
|
11
13
|
/** A run of printable ASCII without brackets: an address ends where Japanese text, a space or a bracket starts (…/faq で). */
|
|
12
14
|
const ASCII_RUN = /[!-'*-~]+/gu;
|
|
@@ -43,7 +45,9 @@ const SERIAL_DIGITS = /\d{3}/u;
|
|
|
43
45
|
const spansOf = (text: string, pattern: RegExp): Span[] =>
|
|
44
46
|
[...text.matchAll(pattern)].map((match) => ({ start: match.index, end: match.index + match[0].length }));
|
|
45
47
|
|
|
46
|
-
|
|
48
|
+
/** Clock times, each with the AM or PM written after it (9:30AM). */
|
|
49
|
+
export const clockTimeSpans = (text: string): Span[] =>
|
|
50
|
+
spansOf(text, CLOCK_TIME).map((span) => ({ start: span.start, end: span.end + (MERIDIEM.exec(text.slice(span.end))?.[0].length ?? 0) }));
|
|
47
51
|
|
|
48
52
|
export const addressSpans = (text: string): Span[] => spansOf(text, ASCII_RUN).filter((span) => isAddress(text.slice(span.start, span.end)));
|
|
49
53
|
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { Sentence, Token } from "./plugin.ts";
|
|
2
|
+
import { kanjiSkeleton } from "./kana-spelling.ts";
|
|
3
|
+
|
|
4
|
+
const ALL_KANJI = /^[\p{Script=Han}々]+$/u;
|
|
5
|
+
/** A bound noun that is kanji and then kana (込み): the okurigana half of a word the tokenizer cut (申 and 込み). */
|
|
6
|
+
const KANJI_THEN_KANA = /^[\p{Script=Han}々]+[ぁ-ゖ]+$/u;
|
|
7
|
+
|
|
8
|
+
const isTouching = (head: Token, tail: Token): boolean => head.span.end === tail.span.start;
|
|
9
|
+
|
|
10
|
+
const isKanjiNoun = (token: Token): boolean => token.pos === "NOUN" && ALL_KANJI.test(token.surface);
|
|
11
|
+
|
|
12
|
+
/** 申 and 込み: a kanji noun and a bound noun of kanji and kana written onto it. */
|
|
13
|
+
const isCutAtKanji = (head: Token, tail: Token): boolean =>
|
|
14
|
+
isKanjiNoun(head) && tail.pos === "NOUN" && tail.features?.["Bound"] === "Yes" && KANJI_THEN_KANA.test(tail.surface) && isTouching(head, tail);
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* 申立 and て, the noun's reading already ending in テ (モウシタテ): its last kana cut off as a particle. て never follows a noun as
|
|
18
|
+
* a particle; other kana (の after 長野, ナガノ) do, so only て is read back.
|
|
19
|
+
*/
|
|
20
|
+
const isCutBeforeTe = (head: Token, tail: Token): boolean =>
|
|
21
|
+
isKanjiNoun(head) && tail.surface === "て" && (tail.pos === "ADP" || tail.pos === "SCONJ") && head.reading?.endsWith("テ") === true && isTouching(head, tail);
|
|
22
|
+
|
|
23
|
+
/** The one reading the document gives a noun of these kanji (申込|モウシコミ for 申込); undefined for none or for two. */
|
|
24
|
+
const readingAmong = (kanji: string, nouns: ReadonlySet<string>): string | undefined => {
|
|
25
|
+
const readings = [...nouns].filter((key) => key.startsWith(`${kanji}|`)).map((key) => key.slice(kanji.length + 1));
|
|
26
|
+
return readings.length === 1 ? readings[0] : undefined;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const readingOfJoined = (head: Token, tail: Token, nouns: ReadonlySet<string>): string | undefined => {
|
|
30
|
+
if (isCutAtKanji(head, tail)) return readingAmong(kanjiSkeleton(head.surface + tail.surface), nouns);
|
|
31
|
+
return isCutBeforeTe(head, tail) ? head.reading : undefined;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const joinedOf = (head: Token, tail: Token | undefined, nouns: ReadonlySet<string>): Token | undefined => {
|
|
35
|
+
const reading = tail === undefined ? undefined : readingOfJoined(head, tail, nouns);
|
|
36
|
+
if (tail === undefined || reading === undefined) return undefined;
|
|
37
|
+
const surface = head.surface + tail.surface;
|
|
38
|
+
return { span: { start: head.span.start, end: tail.span.end }, surface, pos: "NOUN", lemma: surface, reading };
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const joinedTokens = (tokens: readonly Token[], nouns: ReadonlySet<string>): Token[] =>
|
|
42
|
+
tokens.reduce<{ readonly out: Token[]; readonly skip: boolean }>(
|
|
43
|
+
({ out, skip }, token, at) => {
|
|
44
|
+
if (skip) return { out, skip: false };
|
|
45
|
+
const joined = joinedOf(token, tokens[at + 1], nouns);
|
|
46
|
+
out.push(joined ?? token);
|
|
47
|
+
return { out, skip: joined !== undefined };
|
|
48
|
+
},
|
|
49
|
+
{ out: [], skip: false },
|
|
50
|
+
).out;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* The sentence with a noun the tokenizer cut in two read whole: a kanji noun and a bound noun of kanji and kana written onto it
|
|
54
|
+
* (申 and 込み at the head of a sentence) are one noun (申込み) when the document writes a noun of the same kanji elsewhere
|
|
55
|
+
* (申し込み, 申込|モウシコミ in nouns), which gives the reading. With no such noun, or two readings for it, the tokens stay as cut.
|
|
56
|
+
* A kanji noun read with its last kana and that kana cut off as て (申立 and て) is one noun too (申立て).
|
|
57
|
+
* nouns holds the document's nouns (documentNounKeys).
|
|
58
|
+
*/
|
|
59
|
+
export const withCutNounsJoined = (sentence: Sentence, nouns: ReadonlySet<string>): Sentence => {
|
|
60
|
+
const tokens = sentence.tokens ?? [];
|
|
61
|
+
const joined = joinedTokens(tokens, nouns);
|
|
62
|
+
return joined.length === tokens.length ? sentence : { ...sentence, tokens: joined };
|
|
63
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// Where an instrument attached to the document starts: a title line naming it (Exhibit A to Merger Agreement, Annex 1).
|
|
2
|
+
// What is attached is a separate document (a restated charter, a form of note), so its definitions are its own. Pure.
|
|
3
|
+
import { escapeRegExp } from "../orthography.ts";
|
|
4
|
+
import { isShortTitle, isTitleLine, type TitleNotion } from "../title-line.ts";
|
|
5
|
+
|
|
6
|
+
/** An instrument's title: any case (EXHIBIT A to the merger agreement), but no `: ; ,` after it, and only blank lines around. */
|
|
7
|
+
export const INSTRUMENT_TITLE: TitleNotion = { sentenceEnd: /[.!?。.?!:;,]$/u, capitalised: false, edge: "blank-line" };
|
|
8
|
+
|
|
9
|
+
/** Bold around a title (## **SCHEDULE A**) is only how it is shown. */
|
|
10
|
+
const BOLD = /\*\*/gu;
|
|
11
|
+
/** A Markdown heading is a block of its own, so it needs no blank line around it (a closing fence may sit just above). */
|
|
12
|
+
const MARKDOWN_HEADING = /^ {0,3}#{1,6}[ \t]/u;
|
|
13
|
+
|
|
14
|
+
type Line = { readonly start: number; readonly text: string };
|
|
15
|
+
|
|
16
|
+
const linesOf = (source: string): Line[] => {
|
|
17
|
+
const starts = [0, ...[...source.matchAll(/\n/gu)].map((match) => match.index + 1)];
|
|
18
|
+
return starts.map((start, index) => ({ start, text: source.slice(start, (starts[index + 1] ?? source.length + 1) - 1) }));
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const opensInstrument = (source: string, lines: readonly Line[], index: number, title: RegExp): boolean => {
|
|
22
|
+
const line = lines[index];
|
|
23
|
+
if (line === undefined) return false;
|
|
24
|
+
const text = line.text.replace(BOLD, "");
|
|
25
|
+
const label = title.exec(text);
|
|
26
|
+
if (label === null) return false;
|
|
27
|
+
const rest = text.slice(label[0].length);
|
|
28
|
+
if (MARKDOWN_HEADING.test(text)) return isShortTitle(rest, INSTRUMENT_TITLE);
|
|
29
|
+
const lineEnd = index === lines.length - 1 ? -1 : line.start + line.text.length;
|
|
30
|
+
return isTitleLine(source, line.start, lineEnd, rest, INSTRUMENT_TITLE);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* The offsets of the lines that open an attached instrument: the line holds a label (Exhibit, Annex), its letter or
|
|
35
|
+
* number and at most a short title with no full stop, and it is a Markdown heading or has a blank line or the
|
|
36
|
+
* document's edge on both sides. Bold around the title is ignored.
|
|
37
|
+
*/
|
|
38
|
+
export const attachedPartStarts = (source: string, labels: readonly string[]): number[] => {
|
|
39
|
+
const words = labels.filter((label) => label !== "").map(escapeRegExp);
|
|
40
|
+
if (words.length === 0) return [];
|
|
41
|
+
const title = new RegExp(String.raw`^[ \t]*(?:#{1,6}[ \t]+)?(?:${words.join("|")})[ \t]+[A-Z0-9](?:[A-Z0-9\-]|\.(?=[A-Z0-9]))*(?=[ \t\r]|$)`, "u");
|
|
42
|
+
const lines = linesOf(source);
|
|
43
|
+
return lines.flatMap((line, index) => (opensInstrument(source, lines, index, title) ? [line.start] : []));
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
/** Which part an offset falls in: 0 for the document itself, n for the n-th attached instrument. */
|
|
47
|
+
export const partAt = (starts: readonly number[], offset: number): number => starts.filter((start) => start <= offset).length;
|