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
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// one list is reported. です/ます against plain endings inside a list is no-mixed-desumasu's, not this.
|
|
4
4
|
import { minorityWithin } from "../orthography.ts";
|
|
5
5
|
import { isQuotedAt } from "./bold-label.ts";
|
|
6
|
+
import { endsAsHeadline, markOrSkipped, withoutFootnoteReference, withoutTrailingMarks } from "./list-item-ending.ts";
|
|
6
7
|
import type { BulletList, Detector, Finding, ProseDocument, Sentence, Span, Token } from "../plugin.ts";
|
|
7
8
|
|
|
8
9
|
/** What an item is made of: a phrase or a sentence (ending), and the word it opens with (head, English only). */
|
|
@@ -12,6 +13,7 @@ export type Axis = "ending" | "head";
|
|
|
12
13
|
export const FORMS: Readonly<Record<Axis, readonly [string, string]>> = { ending: ["phrase", "sentence"], head: ["verb", "noun"] };
|
|
13
14
|
|
|
14
15
|
const SKIPPED_AT_END = new Set(["PUNCT", "SYM", "X"]);
|
|
16
|
+
const isMark = markOrSkipped(SKIPPED_AT_END);
|
|
15
17
|
const NOMINAL = new Set(["NOUN", "PROPN", "NUM", "PRON"]);
|
|
16
18
|
const PREDICATE = new Set(["VERB", "AUX", "ADJ"]);
|
|
17
19
|
const NOUN_HEAD = new Set(["NOUN", "ADJ", "DET", "NUM", "PRON", "PROPN"]);
|
|
@@ -33,12 +35,16 @@ const withoutClosingAside = (tokens: readonly Token[]): readonly Token[] => {
|
|
|
33
35
|
return open <= 0 ? tokens : tokens.slice(0, open);
|
|
34
36
|
};
|
|
35
37
|
|
|
36
|
-
/**
|
|
37
|
-
|
|
38
|
+
/**
|
|
39
|
+
* Japanese: a predicate at the end (出します, 済ませる, 早い) is a sentence; a noun (月末, 確認すること) or a headline's
|
|
40
|
+
* あり / なし after a noun (翻訳あり) is a phrase. Marks after the last word (!!, a footnote reference) are not words.
|
|
41
|
+
*/
|
|
42
|
+
const japaneseEnding = (sentences: readonly Sentence[], headlineEndings: ReadonlySet<string>): string | undefined => {
|
|
38
43
|
if (sentences.length > 1) return "sentence";
|
|
39
|
-
const
|
|
44
|
+
const words = withoutTrailingMarks(withoutClosingAside(withoutFootnoteReference(sentences[0]?.tokens ?? [], isMark)), isMark);
|
|
45
|
+
const last = words.at(-1);
|
|
40
46
|
if (last === undefined) return undefined;
|
|
41
|
-
if (NOMINAL.has(last.pos)) return "phrase";
|
|
47
|
+
if (NOMINAL.has(last.pos) || endsAsHeadline(words, headlineEndings)) return "phrase";
|
|
42
48
|
return PREDICATE.has(last.pos) ? "sentence" : undefined;
|
|
43
49
|
};
|
|
44
50
|
|
|
@@ -72,47 +78,124 @@ const AFTER_ADJECTIVE = new Set(["ADP", "PART"]);
|
|
|
72
78
|
const isNounOrAdjective = (token: Token): boolean =>
|
|
73
79
|
token.pos === "NOUN" || token.pos === "ADJ" || (token.pos === "PROPN" && token.features?.["OrdinaryWord"] === "Yes");
|
|
74
80
|
|
|
81
|
+
/** A verb in the base form an instruction takes (describe), not a past or third-person form (described, describes). */
|
|
82
|
+
const isBaseVerb = (token: Token | undefined): boolean =>
|
|
83
|
+
token?.pos === "VERB" && token.features?.["VerbForm"] === undefined && token.lemma === token.surface.toLowerCase();
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* An -ed word the tagger left without VerbForm (decreased, agreed, unauthorized): like a participle, it may modify the noun
|
|
87
|
+
* after it. Proceed and need end in -ed too but are their own base forms.
|
|
88
|
+
*/
|
|
89
|
+
const isPastForm = (token: Token): boolean =>
|
|
90
|
+
token.pos === "VERB" &&
|
|
91
|
+
token.features?.["VerbForm"] === undefined &&
|
|
92
|
+
/ed$/iu.test(token.surface) &&
|
|
93
|
+
(token.lemma !== token.surface.toLowerCase() || !/eed$/iu.test(token.surface));
|
|
94
|
+
|
|
95
|
+
/** An -s word read as a verb that the tagger could not take back to a base form (Revisions): a plural noun, misread. Discuss and Focus are verbs. */
|
|
96
|
+
const isMisreadPlural = (token: Token): boolean =>
|
|
97
|
+
token.pos === "VERB" && token.features?.["VerbForm"] === undefined && /[^su]s$/iu.test(token.surface) && token.lemma === token.surface.toLowerCase();
|
|
98
|
+
|
|
99
|
+
/** Participles (Generated files) and gerunds (Recovering from illness) open noun phrases and duties alike, so neither form. */
|
|
100
|
+
const NEITHER_FORM_VERB = new Set(["Part", "Ger"]);
|
|
101
|
+
|
|
102
|
+
/** The head as the first word's tag gives it. */
|
|
103
|
+
const headFromTag = (first: Token): string | undefined => {
|
|
104
|
+
if (isUnsure(first) || isPastForm(first) || isMisreadPlural(first)) return undefined;
|
|
105
|
+
if (first.pos === "VERB") return NEITHER_FORM_VERB.has(first.features?.["VerbForm"] ?? "") ? undefined : "verb";
|
|
106
|
+
return NOUN_HEAD.has(first.pos) ? "noun" : undefined;
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
/** What the axes read besides the item's own words: the adapter's word lists, and the nouns of the item's list. */
|
|
110
|
+
export type HeadContext = {
|
|
111
|
+
/** Verbs the tagger does not know as verbs (click), from the adapter's instruction-verb word list. */
|
|
112
|
+
readonly instructionVerbs: ReadonlySet<string>;
|
|
113
|
+
/** Words that open an instruction or an adjective phrase (Secure the server, Secure configuration), from verb-or-adjective. */
|
|
114
|
+
readonly verbOrAdjective: ReadonlySet<string>;
|
|
115
|
+
/** The lemmas the tagger read as nouns anywhere in the item's list. */
|
|
116
|
+
readonly nounsInList: ReadonlySet<string>;
|
|
117
|
+
/** Words that end a Japanese item as a headline does after a noun (翻訳あり), from headline-ending. */
|
|
118
|
+
readonly headlineEndings: ReadonlySet<string>;
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
export const NO_HEAD_CONTEXT: HeadContext = { instructionVerbs: new Set(), verbOrAdjective: new Set(), nounsInList: new Set(), headlineEndings: new Set() };
|
|
122
|
+
|
|
123
|
+
type HeadReading = "verb" | "noun" | "unjudged" | undefined;
|
|
124
|
+
|
|
125
|
+
/** Reads the head from the item's tokens, its first word at `at`; undefined leaves it to the next reader. */
|
|
126
|
+
type HeadReader = (tokens: readonly Token[], at: number, context: HeadContext) => HeadReading;
|
|
127
|
+
|
|
128
|
+
/** A subject and its verb in one word (you're, we've): the item opens with its subject, as "you love …" does. */
|
|
129
|
+
const SUBJECT_CONTRACTION = /^(?:i|you|we|they|he|she|it)['’]\p{L}+$/iu;
|
|
130
|
+
|
|
131
|
+
const subjectContraction: HeadReader = (tokens, at) => (SUBJECT_CONTRACTION.test(tokens[at]?.surface ?? "") ? "noun" : undefined);
|
|
132
|
+
|
|
133
|
+
/** Secure, Open: a verb before "the", "a" or "your" (Secure the server), else maybe an adjective (Secure configuration). */
|
|
134
|
+
const verbOrAdjective: HeadReader = (tokens, at, context) => {
|
|
135
|
+
if (!context.verbOrAdjective.has(tokens[at]?.surface.toLowerCase() ?? "")) return undefined;
|
|
136
|
+
return opensObject(tokens[at + 1]) ? "verb" : "unjudged";
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
/** A verb the tagger does not know. Before a common noun the word may head a compound (Click fraud, Scroll bar), so its tag decides. */
|
|
140
|
+
const instructionVerb: HeadReader = (tokens, at, context) =>
|
|
141
|
+
context.instructionVerbs.has(tokens[at]?.surface.toLowerCase() ?? "") && tokens[at + 1]?.pos !== "NOUN" ? "verb" : undefined;
|
|
142
|
+
|
|
143
|
+
const isSeriesJoint = (token: Token): boolean => token.surface === "," || token.pos === "CCONJ";
|
|
144
|
+
|
|
145
|
+
/** The single words of a series the item opens with: "Scope, estimate and describe tasks" gives Scope, estimate, describe. */
|
|
146
|
+
const openingSeries = (tokens: readonly Token[], at: number): readonly Token[] => {
|
|
147
|
+
const word = tokens[at];
|
|
148
|
+
if (word === undefined) return [];
|
|
149
|
+
const after = tokens.findIndex((token, index) => index > at && !isSeriesJoint(token));
|
|
150
|
+
return after === -1 || after === at + 1 ? [word] : [word, ...openingSeries(tokens, after)];
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
/** A series one of whose later words is a verb in its base form (Instrument, monitor and profile): it is a series of verbs. */
|
|
154
|
+
const seriesOfVerbs: HeadReader = (tokens, at) => (openingSeries(tokens, at).slice(1).some(isBaseVerb) ? "verb" : undefined);
|
|
155
|
+
|
|
75
156
|
/**
|
|
76
|
-
* The
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
* (Washing dishes): neither is judged.
|
|
157
|
+
* The first two words overrule the first word's tag. "Open the console" and "Press the button" open with a verb. "Clean up
|
|
158
|
+
* after closing" and "Bake in the oven" may open with a verb or an adjective phrase (Close to the station), and "Washing
|
|
159
|
+
* machine space" with a compound noun or a gerund and its object (Washing dishes): neither is judged.
|
|
80
160
|
*/
|
|
81
|
-
const
|
|
161
|
+
const nextWord: HeadReader = (tokens, at) => {
|
|
162
|
+
const first = tokens[at];
|
|
163
|
+
// The word right after, punctuation included: in "Next, the candidate" the comma ends the opener.
|
|
164
|
+
const next = tokens[at + 1];
|
|
165
|
+
if (first === undefined) return undefined;
|
|
82
166
|
if (isNounOrAdjective(first) && opensObject(next)) return "verb";
|
|
83
167
|
if (first.pos === "ADJ" && AFTER_ADJECTIVE.has(next?.pos ?? "")) return "unjudged";
|
|
84
168
|
return first.features?.["VerbForm"] === "Ger" && next?.pos === "NOUN" ? "unjudged" : undefined;
|
|
85
169
|
};
|
|
86
170
|
|
|
87
|
-
/**
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
if (first.pos === "VERB") return first.features?.["VerbForm"] === "Part" ? undefined : "verb";
|
|
92
|
-
return NOUN_HEAD.has(first.pos) ? "noun" : undefined;
|
|
171
|
+
/** A verb that the same list uses as a noun (holiday pay … pay during your notice), with no object after it: either reading. */
|
|
172
|
+
const nounElsewhereInList: HeadReader = (tokens, at, context) => {
|
|
173
|
+
const first = tokens[at];
|
|
174
|
+
return first?.pos === "VERB" && context.nounsInList.has(first.lemma ?? "") && !opensObject(tokens[at + 1]) ? "unjudged" : undefined;
|
|
93
175
|
};
|
|
94
176
|
|
|
95
|
-
const
|
|
177
|
+
const HEAD_READERS: readonly HeadReader[] = [subjectContraction, verbOrAdjective, instructionVerb, seriesOfVerbs, nextWord, nounElsewhereInList];
|
|
178
|
+
|
|
179
|
+
const englishHead = (sentences: readonly Sentence[], context: HeadContext): string | undefined => {
|
|
96
180
|
const tokens = sentences[0]?.tokens ?? [];
|
|
97
181
|
const at = tokens.findIndex((token) => !SKIPPED_AT_END.has(token.pos));
|
|
98
182
|
const first = tokens[at];
|
|
99
183
|
if (at === -1 || first === undefined || isTitleCase(sentences[0]?.text ?? "")) return undefined;
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
if (instructionVerbs.has(first.surface.toLowerCase()) && next?.pos !== "NOUN") return "verb";
|
|
104
|
-
const overruled = headFromNextWord(first, next);
|
|
105
|
-
if (overruled === undefined) return headFromTag(first);
|
|
106
|
-
return overruled === "verb" ? "verb" : undefined;
|
|
184
|
+
const reading = HEAD_READERS.reduce<HeadReading>((found, reader) => found ?? reader(tokens, at, context), undefined);
|
|
185
|
+
if (reading === undefined) return headFromTag(first);
|
|
186
|
+
return reading === "unjudged" ? undefined : reading;
|
|
107
187
|
};
|
|
108
188
|
|
|
109
|
-
/**
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
189
|
+
/** An item's form on an axis, or undefined when its words do not tell. Japanese items have no head axis (the verb comes last). */
|
|
190
|
+
/** An item that ends in a colon (Other kinds of decisions:) leads into what follows it: its ending is not its own, its opening still is. */
|
|
191
|
+
const LEAD_IN = /[::]$/u;
|
|
192
|
+
|
|
193
|
+
const leadsIn = (sentences: readonly Sentence[]): boolean => LEAD_IN.test(sentences.at(-1)?.text.trim() ?? "");
|
|
194
|
+
|
|
195
|
+
export const formOf = (axis: Axis, sentences: readonly Sentence[], language: string, context: HeadContext = NO_HEAD_CONTEXT): string | undefined => {
|
|
196
|
+
if (axis === "ending" && leadsIn(sentences)) return undefined;
|
|
197
|
+
if (language === "ja") return axis === "ending" ? japaneseEnding(sentences, context.headlineEndings) : undefined;
|
|
198
|
+
return axis === "ending" ? englishEnding(sentences) : englishHead(sentences, context);
|
|
116
199
|
};
|
|
117
200
|
|
|
118
201
|
const within = (inner: Span, outer: Span): boolean => inner.start >= outer.start && inner.end <= outer.end;
|
|
@@ -123,6 +206,33 @@ export const itemSentences = (doc: ProseDocument, item: Span): Sentence[] => {
|
|
|
123
206
|
return doc.sentences.filter((sentence) => within(sentence.span, item) && !nested.some((span) => within(sentence.span, span)));
|
|
124
207
|
};
|
|
125
208
|
|
|
209
|
+
/**
|
|
210
|
+
* Where an item's own words end: before a line in it that opens, unindented, with a note lead (※応募書類は返却できません。,
|
|
211
|
+
* "Note: …"). Markdown reads such a line as the last item's, but the note is about the whole list.
|
|
212
|
+
*/
|
|
213
|
+
export const itemOwnEnd = (source: string, item: Span, noteLeads: readonly string[]): number => {
|
|
214
|
+
const lineStarts = [...source.slice(item.start, item.end).matchAll(/\n/gu)].map((match) => item.start + match.index + 1);
|
|
215
|
+
const noteLine = lineStarts.find((start) => noteLeads.some((lead) => lead !== "" && source.startsWith(lead, start)));
|
|
216
|
+
return noteLine === undefined ? item.end : noteLine - 1;
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
/** The sentence up to `end`: a note line under the item is not part of the item's last sentence. */
|
|
220
|
+
const cutAt = (sentence: Sentence, end: number, source: string): Sentence =>
|
|
221
|
+
sentence.span.end <= end
|
|
222
|
+
? sentence
|
|
223
|
+
: {
|
|
224
|
+
...sentence,
|
|
225
|
+
span: { start: sentence.span.start, end },
|
|
226
|
+
text: source.slice(sentence.span.start, end),
|
|
227
|
+
...(sentence.tokens === undefined ? {} : { tokens: sentence.tokens.filter((token) => token.span.end <= end) }),
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
/** The item's own sentences, up to a note line under it. */
|
|
231
|
+
const ownSentences = (doc: ProseDocument, item: Span, noteLeads: readonly string[]): Sentence[] => {
|
|
232
|
+
const end = itemOwnEnd(doc.source, item, noteLeads);
|
|
233
|
+
return itemSentences(doc, item).flatMap((sentence) => (sentence.span.start < end ? [cutAt(sentence, end, doc.source)] : []));
|
|
234
|
+
};
|
|
235
|
+
|
|
126
236
|
type Item = { readonly sentences: readonly Sentence[]; readonly form: string };
|
|
127
237
|
|
|
128
238
|
const findingOf = (axis: Axis, item: Item, count: number, of: number, limit: number): Finding => {
|
|
@@ -162,17 +272,32 @@ const isJudged = (written: string, sentences: readonly Sentence[]): boolean => {
|
|
|
162
272
|
|
|
163
273
|
const runsOn = (sentences: readonly Sentence[]): boolean => RUNNING_ON.test(sentences.at(-1)?.text.trim() ?? "");
|
|
164
274
|
|
|
275
|
+
const wordsOf = (doc: ProseDocument, lexicon: string): ReadonlySet<string> =>
|
|
276
|
+
new Set((doc.lexicons[lexicon] ?? []).map((entry) => entry.pattern.toLowerCase()));
|
|
277
|
+
|
|
278
|
+
const headContext = (doc: ProseDocument, items: readonly (readonly Sentence[])[]): HeadContext => ({
|
|
279
|
+
instructionVerbs: wordsOf(doc, "instruction-verb"),
|
|
280
|
+
verbOrAdjective: wordsOf(doc, "verb-or-adjective"),
|
|
281
|
+
headlineEndings: wordsOf(doc, "headline-ending"),
|
|
282
|
+
nounsInList: new Set(
|
|
283
|
+
items.flatMap((sentences) =>
|
|
284
|
+
sentences.flatMap((sentence) => (sentence.tokens ?? []).flatMap((token) => (token.pos === "NOUN" && token.lemma !== undefined ? [token.lemma] : []))),
|
|
285
|
+
),
|
|
286
|
+
),
|
|
287
|
+
});
|
|
288
|
+
|
|
165
289
|
const listFindings = (doc: ProseDocument, list: BulletList, limit: number): Finding[] => {
|
|
166
|
-
const
|
|
290
|
+
const noteLeads = (doc.lexicons["list-note-lead"] ?? []).map((entry) => entry.pattern);
|
|
291
|
+
const sentencesOf = list.itemSpans.map((span) => ownSentences(doc, span, noteLeads));
|
|
167
292
|
if (sentencesOf.some(runsOn)) return [];
|
|
168
293
|
const judged = sentencesOf.filter((sentences, index) => {
|
|
169
294
|
const span = list.itemSpans[index];
|
|
170
295
|
return span !== undefined && isJudged(doc.source.slice(span.start, sentences.at(-1)?.span.end ?? span.end), sentences);
|
|
171
296
|
});
|
|
172
|
-
const
|
|
297
|
+
const context = headContext(doc, judged);
|
|
173
298
|
return AXES.flatMap((axis) => {
|
|
174
299
|
const items = judged.flatMap((sentences) => {
|
|
175
|
-
const form = formOf(axis, sentences, doc.language,
|
|
300
|
+
const form = formOf(axis, sentences, doc.language, context);
|
|
176
301
|
return form === undefined ? [] : [{ sentences, form }];
|
|
177
302
|
});
|
|
178
303
|
const odd = minorityWithin(items, (item) => item.form === FORMS[axis][0], limit);
|
|
@@ -12,6 +12,10 @@ export type ListWords = {
|
|
|
12
12
|
readonly example: Lexicon;
|
|
13
13
|
readonly pair: ReadonlySet<string>;
|
|
14
14
|
readonly region: Lexicon;
|
|
15
|
+
/** 題名を導く語(whose full title is、entitled)。すぐ後ろの Title Case の語の続きは題名で、その中の読点は題名を付けた人のもの。 */
|
|
16
|
+
readonly titleCue?: readonly string[];
|
|
17
|
+
/** 文頭で順番を言う一語(First, Next, Finally)。解析器が形容詞と読んでも、並びの項目ではなく導入の語。 */
|
|
18
|
+
readonly sequence?: ReadonlySet<string>;
|
|
15
19
|
};
|
|
16
20
|
|
|
17
21
|
const LIST_CONJUNCTION: ReadonlySet<string> = new Set(["and", "or"]);
|
|
@@ -193,6 +197,6 @@ export const listSentenceOf = (tokens: readonly Token[], words: ListWords, sourc
|
|
|
193
197
|
exampleStarts: byDepth(depths, (index) => (exampleEnds[index]?.length ?? 0) > 0),
|
|
194
198
|
pairOpeners: pairOpenersOf(tokens, depths, words.pair),
|
|
195
199
|
commas: byDepth(depths, (index) => tokens[index]?.surface === "," && !regionCommas.has(index)),
|
|
196
|
-
inCitedTitle: citedTitles(tokens, source),
|
|
200
|
+
inCitedTitle: citedTitles(tokens, source, words.titleCue),
|
|
197
201
|
};
|
|
198
202
|
};
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import type { Detector, Finding, Lexicon, ProseDocument, Sentence } from "../plugin.ts";
|
|
2
2
|
import { escapeRegExp } from "../orthography.ts";
|
|
3
|
+
import { isConventionalPhrase } from "./caps-phrase.ts";
|
|
3
4
|
import { minorityReport } from "../spacing-minority.ts";
|
|
5
|
+
import { externalLinkTitleSpans } from "../link-title.ts";
|
|
6
|
+
import { formulaBracketSpans } from "../formula-brackets.ts";
|
|
4
7
|
import { isWithinAny, quotedSpans } from "../quoted-span.ts";
|
|
5
|
-
import { captionsOf, isCaptionAt } from "./caps-caption.ts";
|
|
8
|
+
import { capitalLineSpans, captionsOf, isCaptionAt, isWithinSorted } from "./caps-caption.ts";
|
|
9
|
+
import { lineStarts } from "../position.ts";
|
|
6
10
|
|
|
7
11
|
/** The letters a mark must touch to count as part of the document's text, by language. */
|
|
8
12
|
const SCRIPT: Readonly<Record<string, RegExp>> = {
|
|
@@ -43,15 +47,17 @@ const besideLetter = (text: string, at: number, step: number, script: RegExp): b
|
|
|
43
47
|
const touchesScript = (text: string, at: number, script: RegExp): boolean => besideLetter(text, at, -1, script) || besideLetter(text, at, 1, script);
|
|
44
48
|
|
|
45
49
|
/**
|
|
46
|
-
* The marks in a sentence that touch a letter of the document's script, outside 「」『』 quotations
|
|
50
|
+
* The marks in a sentence that touch a letter of the document's script, outside 「」『』 quotations and outside the brackets
|
|
51
|
+
* of a formula (× (1 - 時間 ÷ 月平均)), which follow the formula's notation. spaced is the lexicon's pattern side.
|
|
47
52
|
* The letters beside a mark are read in the source, so a mark that opens a sentence (。(2)当社) counts wherever the sentence starts.
|
|
48
53
|
*/
|
|
49
54
|
export const marksIn = (source: string, sentence: Sentence, forms: ReadonlyMap<string, Form>, script: RegExp): Mark[] => {
|
|
50
55
|
const quoted = quotedSpans(sentence.text);
|
|
56
|
+
const formulas = formulaBracketSpans(sentence.text);
|
|
51
57
|
return sentence.text.split("").flatMap((char, at) => {
|
|
52
58
|
const form = forms.get(char);
|
|
53
59
|
if (form === undefined || !touchesScript(source, sentence.span.start + at, script)) return [];
|
|
54
|
-
if (isWithinAny(quoted, { start: at, end: at })) return [];
|
|
60
|
+
if (isWithinAny(quoted, { start: at, end: at }) || isWithinAny(formulas, { start: at, end: at + 1 })) return [];
|
|
55
61
|
return [{ sentence, char, form, offset: sentence.span.start + at, spaced: form.side }];
|
|
56
62
|
});
|
|
57
63
|
};
|
|
@@ -83,20 +89,84 @@ const minorityFindings = <T extends Sided>(items: readonly T[], limit: number, v
|
|
|
83
89
|
/** Sentences written in the document's own language; a quoted sentence in another language follows its own marks. */
|
|
84
90
|
const ownSentences = (doc: ProseDocument): readonly Sentence[] => doc.sentences.filter((sentence) => sentence.embeddedLanguage === undefined);
|
|
85
91
|
|
|
92
|
+
/**
|
|
93
|
+
* A bracketed item number opening a line ((1)開催趣旨, (ア), (iv), a list bullet before it), both brackets of one width.
|
|
94
|
+
* It numbers the line, a style of its own: the brackets of the prose around it may be written the other width. A
|
|
95
|
+
* bracketed word at a line's head ((背景), (注)) is not a number, and an item number the prose refers to (次の(1)及び(2))
|
|
96
|
+
* is written in the prose; both stay with the prose's brackets.
|
|
97
|
+
*/
|
|
98
|
+
const LINE_HEAD = /^\s*(?:[-*+] +)?/u;
|
|
99
|
+
const BRACKETED = /^([(([[])([^))\]]]{1,4})([))\]]])/u;
|
|
100
|
+
const NUMBERING = /^(?:[0-90-9]{1,3}|[一二三四五六七八九十]{1,3}|[A-Za-zA-Za-zァ-ヶぁ-んヲ-ン])$/u;
|
|
101
|
+
/** Roman numerals i to x, either case. */
|
|
102
|
+
const ROMAN = /^(?:i{2,3}|iv|vi{1,3}|ix|I{2,3}|IV|VI{1,3}|IX)$/u;
|
|
103
|
+
const CLOSER_OF: Readonly<Record<string, string>> = { "(": ")", "(": ")", "[": "]", "[": "]" };
|
|
104
|
+
|
|
105
|
+
const isItemNumber = (text: string): boolean => NUMBERING.test(text) || ROMAN.test(text);
|
|
106
|
+
|
|
107
|
+
/** The offsets in a line of its item number's opening and closing bracket, or none. */
|
|
108
|
+
const enumeratorIn = (line: string): readonly number[] => {
|
|
109
|
+
const head = LINE_HEAD.exec(line)?.[0].length ?? 0;
|
|
110
|
+
const found = BRACKETED.exec(line.slice(head));
|
|
111
|
+
if (found === null || CLOSER_OF[found[1] ?? ""] !== found[3] || !isItemNumber(found[2] ?? "")) return [];
|
|
112
|
+
return [head, head + found[0].length - 1];
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
/** The offsets in `source` of each line's item number's opening and closing bracket. */
|
|
116
|
+
export const enumeratorBracketOffsets = (source: string): ReadonlySet<number> => {
|
|
117
|
+
const starts = lineStarts(source);
|
|
118
|
+
return new Set(source.split("\n").flatMap((line, index) => enumeratorIn(line).map((at) => (starts[index] ?? 0) + at)));
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
/** Appended to a mark's kind for an item number's bracket. A lexicon's group, a word from YAML, never holds a NUL. */
|
|
122
|
+
const ENUMERATOR_KIND = "\u0000enumerator";
|
|
123
|
+
|
|
124
|
+
/** A line's item number's bracket is a kind of its own, compared only with the other item numbers' brackets. */
|
|
125
|
+
const withEnumeratorKind = (mark: Mark, enumerators: ReadonlySet<number>): Mark =>
|
|
126
|
+
enumerators.has(mark.offset) ? { ...mark, form: { ...mark.form, kind: `${mark.form.kind}${ENUMERATOR_KIND}` } } : mark;
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* A doubled parenthesis around text with no parenthesis inside, such as ((居住の用に供したとき等)) or ((注)): one mark written
|
|
130
|
+
* with two characters, as a directive sets an article's caption. Its width is that notation's, not the prose's.
|
|
131
|
+
*/
|
|
132
|
+
const DOUBLED_PAREN = /\(\([^()()\n]*\)\)|(([^()()\n]*))/gu;
|
|
133
|
+
const PAIR_LENGTH = 2;
|
|
134
|
+
|
|
135
|
+
/** The offsets in `source` of every character of a doubled parenthesis. */
|
|
136
|
+
export const doubledParenOffsets = (source: string): ReadonlySet<number> =>
|
|
137
|
+
new Set(
|
|
138
|
+
[...source.matchAll(DOUBLED_PAREN)].flatMap((match) => {
|
|
139
|
+
const end = match.index + match[0].length;
|
|
140
|
+
return [match.index, match.index + 1, end - PAIR_LENGTH, end - 1];
|
|
141
|
+
}),
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
const DOUBLED_KIND = "\u0000doubled";
|
|
145
|
+
|
|
146
|
+
/** A doubled parenthesis is a kind of its own, compared only with the other doubled parentheses. */
|
|
147
|
+
const withDoubledKind = (mark: Mark, doubled: ReadonlySet<number>): Mark =>
|
|
148
|
+
doubled.has(mark.offset) ? { ...mark, form: { ...mark.form, kind: `${mark.form.kind}${DOUBLED_KIND}` } } : mark;
|
|
149
|
+
|
|
86
150
|
/**
|
|
87
151
|
* A mark written two ways in one document (( and (, “ and "), the less common way reported. The two ways come from the
|
|
88
152
|
* lexicon; neither is called right. Only marks next to a letter of the document's script count, so a bracket in code-like
|
|
89
|
-
* text (f(x)) or an English aside in a Japanese document does not.
|
|
153
|
+
* text (f(x)) or an English aside in a Japanese document does not. A line enumerator's brackets ((1)) are compared apart.
|
|
90
154
|
*/
|
|
91
155
|
export const markConsistency: Detector = (doc, options): Finding[] => {
|
|
92
156
|
const script = SCRIPT[doc.language];
|
|
93
157
|
if (script === undefined) return [];
|
|
158
|
+
// A link that quotes an outside page's title keeps that page's marks ((コンテキスト内) in a WCAG title).
|
|
159
|
+
const titles = externalLinkTitleSpans(doc.source, doc.links);
|
|
94
160
|
const forms = formsOf(options.lexicon ?? []);
|
|
95
|
-
const
|
|
161
|
+
const enumerators = enumeratorBracketOffsets(doc.source);
|
|
162
|
+
const doubled = doubledParenOffsets(doc.source);
|
|
163
|
+
const marks = ownSentences(doc).flatMap((sentence) =>
|
|
164
|
+
marksIn(doc.source, sentence, forms, script).map((mark) => withDoubledKind(withEnumeratorKind(mark, enumerators), doubled)),
|
|
165
|
+
);
|
|
96
166
|
const kinds = [...new Set(marks.map((mark) => mark.form.kind))];
|
|
97
167
|
return kinds.flatMap((kind) =>
|
|
98
168
|
minorityFindings(
|
|
99
|
-
marks.filter((mark) => mark.form.kind === kind),
|
|
169
|
+
marks.filter((mark) => mark.form.kind === kind && !isWithinAny(titles, { start: mark.offset, end: mark.offset + 1 })),
|
|
100
170
|
options.limit,
|
|
101
171
|
(mark) => ({ mark: mark.char, usual: mark.form.other }),
|
|
102
172
|
),
|
|
@@ -205,21 +275,30 @@ export const lowerCaseWords = (source: string): ReadonlySet<string> =>
|
|
|
205
275
|
|
|
206
276
|
/**
|
|
207
277
|
* Whether more than half the words of a capital run are also written elsewhere in lower case. Words the lexicon lists as
|
|
208
|
-
* written in capitals by convention (MUST NOT in a specification) count like acronyms
|
|
278
|
+
* written in capitals by convention (MUST NOT in a specification) count like acronyms, and a run made of its phrases
|
|
279
|
+
* (NOW, THEREFORE, BE IT RESOLVED) is not shouting.
|
|
209
280
|
*/
|
|
210
281
|
export const isShouting = (run: string, known: ReadonlySet<string>, conventional: ReadonlySet<string>): boolean => {
|
|
282
|
+
if (isConventionalPhrase(run, conventional)) return false;
|
|
211
283
|
const words = run.split(/,? /u);
|
|
212
284
|
const ordinary = words.filter((word) => !conventional.has(word) && known.has(word.toLowerCase()));
|
|
213
285
|
const long = words.filter((word) => word.length > 1);
|
|
214
286
|
return long.length >= MIN_LONG_WORDS && ordinary.length * 2 > words.length;
|
|
215
287
|
};
|
|
216
288
|
|
|
217
|
-
/**
|
|
289
|
+
/**
|
|
290
|
+
* Runs of three or more all-capital words that are ordinary words, not acronyms ("DO NOT DELETE THIS"), and not a
|
|
291
|
+
* caption, a mention of one, a paragraph of capital lines that ends no sentence (a letterhead, a heading), or a roster name.
|
|
292
|
+
*/
|
|
218
293
|
export const capsShouting: Detector = (doc, options): Finding[] => {
|
|
219
294
|
const known = lowerCaseWords(doc.prose ?? doc.source);
|
|
220
295
|
const conventional = new Set((options.lexicon ?? []).map((entry) => entry.pattern));
|
|
221
296
|
const captions = captionsOf(doc.source);
|
|
222
|
-
const
|
|
223
|
-
const
|
|
297
|
+
const capitalLines = capitalLineSpans(doc.source);
|
|
298
|
+
const isCaptionOrLetterhead = (hit: Hit): boolean =>
|
|
299
|
+
captions.has(hit.matched) ||
|
|
300
|
+
isCaptionAt(doc.source, hit.offset, hit.offset + hit.matched.length) ||
|
|
301
|
+
isWithinSorted(capitalLines, { start: hit.offset, end: hit.offset + hit.matched.length });
|
|
302
|
+
const hits = hitsOf(ownSentences(doc), CAPS_RUN).filter((hit) => isShouting(hit.matched, known, conventional) && !isCaptionOrLetterhead(hit));
|
|
224
303
|
return reportFrom(hits, options.limit);
|
|
225
304
|
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// A phrase that is mentioned rather than used: named as a term (when saying "raise the bar", the phrase "low-hanging
|
|
2
|
+
// fruit", 「徹底解説」という言い方). The writer is talking about the words, not leaning on them. The cue words come from the
|
|
3
|
+
// language's mention-cue word list: group before stands right before the phrase, group after right after it. Pure.
|
|
4
|
+
import type { LexiconEntry, Sentence, Token } from "../plugin.ts";
|
|
5
|
+
import { entryEndsAt, entryRanges, type TokenRange } from "./lexicon-match.ts";
|
|
6
|
+
|
|
7
|
+
const BEFORE = "before";
|
|
8
|
+
const AFTER = "after";
|
|
9
|
+
|
|
10
|
+
/** Quote marks and brackets that may stand between the cue and the phrase ("raise the bar", 「徹底解説」). */
|
|
11
|
+
const QUOTE_MARKS = new Set(["'", '"', "‘", "’", "“", "”", "「", "」", "『", "』", "(", ")", "(", ")"]);
|
|
12
|
+
|
|
13
|
+
export type MentionCues = { readonly before: readonly LexiconEntry[]; readonly after: readonly LexiconEntry[] };
|
|
14
|
+
|
|
15
|
+
export const mentionCuesOf = (entries: readonly LexiconEntry[]): MentionCues => ({
|
|
16
|
+
before: entries.filter((entry) => entry.group === BEFORE),
|
|
17
|
+
after: entries.filter((entry) => entry.group === AFTER),
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const isQuoteMark = (token: Token | undefined): boolean => token !== undefined && QUOTE_MARKS.has(token.surface);
|
|
21
|
+
|
|
22
|
+
/** The index past the quote marks from `at` in direction `step`. */
|
|
23
|
+
const pastQuotes = (tokens: readonly Token[], at: number, step: 1 | -1): number => (isQuoteMark(tokens[at]) ? pastQuotes(tokens, at + step, step) : at);
|
|
24
|
+
|
|
25
|
+
const startsAt = (tokens: readonly Token[], entry: LexiconEntry, start: number): boolean => entryEndsAt(tokens, entry, start + (entry.tokens?.length ?? 0));
|
|
26
|
+
|
|
27
|
+
const isMention = (tokens: readonly Token[], range: TokenRange, cues: MentionCues): boolean => {
|
|
28
|
+
const before = pastQuotes(tokens, range.start - 1, -1) + 1;
|
|
29
|
+
const after = pastQuotes(tokens, range.end, 1);
|
|
30
|
+
return cues.before.some((cue) => entryEndsAt(tokens, cue, before)) || cues.after.some((cue) => startsAt(tokens, cue, after));
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
/** Whether every use of the entry in the sentence is a mention. Without tokens no use can be told apart, so none is. */
|
|
34
|
+
export const onlyMentioned = (sentence: Sentence, entry: LexiconEntry, cues: MentionCues): boolean => {
|
|
35
|
+
const tokens = sentence.tokens;
|
|
36
|
+
const ranges = entryRanges(sentence, entry);
|
|
37
|
+
return tokens !== undefined && ranges.length > 0 && ranges.every((range) => isMention(tokens, range, cues));
|
|
38
|
+
};
|
|
@@ -3,8 +3,13 @@ const MIDDLE_DOT = /・/gu;
|
|
|
3
3
|
/** 文頭か行頭(前に空白だけ)の「・」。前に並べる項目が無いので、箇条書きの印。 */
|
|
4
4
|
const BULLET_DOT = /(^|\n)[^\S\n]*・/gu;
|
|
5
5
|
|
|
6
|
+
/** 中黒を含めて 1 語の語(キャッシュ・フロー)を、中黒を除いた形にする。この中黒は語の切れ目で、項目を並べてはいない。 */
|
|
7
|
+
const withoutWordDots = (text: string, words: readonly string[]): string =>
|
|
8
|
+
words.reduce((joined, word) => joined.replaceAll(word, word.replaceAll("・", "")), text);
|
|
9
|
+
|
|
6
10
|
/**
|
|
7
|
-
*
|
|
11
|
+
* 項目を並べる中黒の数。箇条書きの印の「・」と、中黒を含めて 1 語の語(words: キャッシュ・フロー)の中黒は数えない。
|
|
8
12
|
* 「・ 水分を補給すること」が何行続いても、どこまでが 1 つの項目かは改行で読める。
|
|
9
13
|
*/
|
|
10
|
-
export const parallelDotCount = (text: string): number =>
|
|
14
|
+
export const parallelDotCount = (text: string, words: readonly string[] = []): number =>
|
|
15
|
+
[...withoutWordDots(text, words).replace(BULLET_DOT, "$1").matchAll(MIDDLE_DOT)].length;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import type { Detector, Finding, StructureNode } from "../plugin.ts";
|
|
2
2
|
import { inDocumentOrder } from "../structure/issues.ts";
|
|
3
|
+
import { listLeadIns } from "../structure/list-lead-in.ts";
|
|
3
4
|
import { modalConflicts, modalStatements, type Obligation } from "../structure/modal-conflict.ts";
|
|
4
5
|
import { linesOf, lineNumberAt } from "../structure/lines.ts";
|
|
5
6
|
import { quoteAt } from "./structure-tree.ts";
|
|
7
|
+
import { negationsMarked, negationWords } from "../structure/negated-act.ts";
|
|
6
8
|
|
|
7
9
|
export const obligationsOf = (tree: StructureNode): Obligation[] =>
|
|
8
10
|
inDocumentOrder(tree).flatMap((node) =>
|
|
@@ -12,10 +14,11 @@ export const obligationsOf = (tree: StructureNode): Obligation[] =>
|
|
|
12
14
|
);
|
|
13
15
|
|
|
14
16
|
/** 同じ主語と行為に、前の文と逆の様相(しなければならない と してはならない、may と must not)を書いた文。 */
|
|
15
|
-
export const modalConflict: Detector = (
|
|
17
|
+
export const modalConflict: Detector = (written): Finding[] => {
|
|
18
|
+
const doc = { ...written, sentences: negationsMarked(written.sentences, negationWords(written.lexicons["negation-word"])) };
|
|
16
19
|
if (doc.structure === undefined) return [];
|
|
17
20
|
const lines = linesOf(doc.source);
|
|
18
|
-
return modalConflicts(modalStatements(obligationsOf(doc.structure), doc.sentences)).map(({ statement, earlier }) => ({
|
|
21
|
+
return modalConflicts(modalStatements(obligationsOf(doc.structure), doc.sentences, listLeadIns(doc.source, doc.sentences))).map(({ statement, earlier }) => ({
|
|
19
22
|
rule: "",
|
|
20
23
|
severity: "warning",
|
|
21
24
|
line: 0,
|
|
@@ -24,6 +24,9 @@ import { isOrdinaryToken, withOrdinaryWords } from "../name-ordinary-word.ts";
|
|
|
24
24
|
import { isInPersonField } from "../person-field.ts";
|
|
25
25
|
import { labelledSpans, orderNamesOf, quotedSpans, stemOf, titleCaseSpans, wordOrderVariants, type OrderWord } from "../name-word-order.ts";
|
|
26
26
|
import { isGroupPairOf, notDefinedTerms, outsideCapitals, sentenceIndexOf, withGivenNames } from "./name-variant-apart.ts";
|
|
27
|
+
import { usualIsMisspelt } from "../name-misspelt-usual.ts";
|
|
28
|
+
import { spellerOf } from "./unknown-word.ts";
|
|
29
|
+
import { isKnownWord } from "../spelling.ts";
|
|
27
30
|
|
|
28
31
|
// 人の名前と読ませる敬称(様、さん)は語彙表 person-suffix、人を指す前置き(担当の)は person-lead、名前のすぐ後ろに来る語
|
|
29
32
|
// (です、まで)は name-particle、字体の違う同じ字(斎・斉・齋)は name-variant-char が組(group)ごとに言う。
|
|
@@ -387,7 +390,10 @@ export const nameVariant: Detector = (doc): Finding[] => {
|
|
|
387
390
|
const withProducts = [...withPlaces, ...productFindings(doc, prose, withPlaces)];
|
|
388
391
|
const withOrder = [...withProducts, ...orderFindings(doc, prose, withProducts)];
|
|
389
392
|
const codes = modelCodeFindings(doc, prose).filter((code) => !overlapsAny(withOrder, code.offset, code.name.length));
|
|
393
|
+
const dictionary = doc.dictionary?.();
|
|
394
|
+
const speller = dictionary === undefined ? undefined : spellerOf(doc, dictionary);
|
|
390
395
|
return [...withOrder, ...codes]
|
|
396
|
+
.filter(({ name, usual }) => speller === undefined || !usualIsMisspelt(name, usual, (word) => isKnownWord(word, speller)))
|
|
391
397
|
.toSorted((left, right) => left.offset - right.offset)
|
|
392
398
|
.map(({ offset, name, usual, kind }) => ({
|
|
393
399
|
rule: "",
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { entryIn } from "./lexicon-match.ts";
|
|
2
|
+
import type { LexiconEntry, Paragraph, Sentence } from "../plugin.ts";
|
|
3
|
+
|
|
4
|
+
/** 一文だけの断りは本文の書き損じのことがある。段落ごと別の調子で揃えてあるときだけ、意図した別の声と読む。 */
|
|
5
|
+
const MIN_SENTENCES = 2;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 断り書きの段落(「…無償で提供します。…一切の責任を負いません。…ご了承ください。」)の文。
|
|
9
|
+
* 免責や変更の予告は、である調の文書でもですます調で書く決まり文句で、本文と文末の調子を比べるものではない。
|
|
10
|
+
* 断りの語(cues)を含み、調子を持つ文が MIN_SENTENCES 以上あって、それがみな同じ、文書の多いほう(majority)ではない調子の段落だけ。
|
|
11
|
+
* 調子が混ざった段落と、文書と同じ調子の段落は、本文と同じに数える。
|
|
12
|
+
*/
|
|
13
|
+
export const noticeSentences = <R>(
|
|
14
|
+
paragraphs: readonly Paragraph[],
|
|
15
|
+
cues: readonly LexiconEntry[],
|
|
16
|
+
registerOf: (sentence: Sentence) => R | undefined,
|
|
17
|
+
majority: R | undefined,
|
|
18
|
+
): Set<Sentence> =>
|
|
19
|
+
new Set(
|
|
20
|
+
paragraphs.flatMap((paragraph) => {
|
|
21
|
+
const registers = new Set(
|
|
22
|
+
paragraph.sentences.flatMap((sentence) => {
|
|
23
|
+
const register = registerOf(sentence);
|
|
24
|
+
return register === undefined ? [] : [register];
|
|
25
|
+
}),
|
|
26
|
+
);
|
|
27
|
+
const counted = paragraph.sentences.filter((sentence) => registerOf(sentence) !== undefined).length;
|
|
28
|
+
const [only] = registers;
|
|
29
|
+
const ownVoice = counted >= MIN_SENTENCES && registers.size === 1 && only !== majority;
|
|
30
|
+
const notice = ownVoice && paragraph.sentences.some((sentence) => cues.some((cue) => entryIn(sentence, cue)));
|
|
31
|
+
return notice ? paragraph.sentences : [];
|
|
32
|
+
}),
|
|
33
|
+
);
|
|
@@ -51,12 +51,24 @@ const MAGNITUDES = /^[一百千万億]+$/u;
|
|
|
51
51
|
|
|
52
52
|
const isIdiomNumeral = (numeral: string): boolean => MAGNITUDES.test(numeral);
|
|
53
53
|
|
|
54
|
-
|
|
54
|
+
/**
|
|
55
|
+
* A number set off by a space from a word that only begins with a counter: 三, a space, 人事委員会 is the item number 三 of a list,
|
|
56
|
+
* not 三人. The tokenizer reads 人事 as one word there and 人 alone in 3 人が来た.
|
|
57
|
+
*/
|
|
58
|
+
const isBeforeLongerWord = (numeral: string, written: string, offset: number, tokens: readonly Token[]): boolean => {
|
|
59
|
+
const counter = written.slice(numeral.length).trimStart();
|
|
60
|
+
if (counter.length === written.length - numeral.length) return false;
|
|
61
|
+
const word = tokens.find((token) => token.span.start === offset + written.length - counter.length);
|
|
62
|
+
return word !== undefined && word.surface.length > counter.length;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const countMarks = (text: string, base: number, words: NumberWords, tokens: readonly Token[]): NumberMark[] => {
|
|
55
66
|
const pattern = countPattern(words);
|
|
56
67
|
if (pattern === undefined) return [];
|
|
57
68
|
return [...text.matchAll(pattern)].flatMap((match): NumberMark[] => {
|
|
58
69
|
const [written, digits, kanji] = match;
|
|
59
70
|
if (kanji !== undefined && isIdiomNumeral(kanji)) return [];
|
|
71
|
+
if (isBeforeLongerWord(digits ?? kanji ?? "", written, base + match.index, tokens)) return [];
|
|
60
72
|
return [{ kind: "count", style: digits === undefined ? "kanji" : "digits", written, offset: base + match.index }];
|
|
61
73
|
});
|
|
62
74
|
};
|
|
@@ -176,7 +188,7 @@ const englishCountMarks = (sentence: Sentence, words: NumberWords): NumberMark[]
|
|
|
176
188
|
export const numberMarksIn = (sentence: Sentence, words: NumberWords, language: string, source: string): NumberMark[] => {
|
|
177
189
|
const base = sentence.span.start;
|
|
178
190
|
const marks = [
|
|
179
|
-
...countMarks(sentence.text, base, words),
|
|
191
|
+
...countMarks(sentence.text, base, words, sentence.tokens ?? []),
|
|
180
192
|
...groupingMarks(sentence.text, base, words, source),
|
|
181
193
|
...percentMarks(sentence.text, base, words),
|
|
182
194
|
...(language === "ja" ? [] : englishCountMarks(sentence, words)),
|