chaffjs 0.35.0 → 0.36.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 +35 -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 +14 -0
- package/dist/detectors/acronym-link.d.ts.map +1 -0
- package/dist/detectors/acronym-link.js +32 -0
- package/dist/detectors/acronym-link.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 +23 -4
- 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/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/caps-caption.d.ts +7 -6
- package/dist/detectors/caps-caption.d.ts.map +1 -1
- package/dist/detectors/caps-caption.js +38 -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 +29 -16
- package/dist/detectors/char-shape.js.map +1 -1
- 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/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/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 +25 -5
- 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 +6 -3
- 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/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/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 +31 -1
- package/dist/detectors/email-letter.d.ts.map +1 -1
- package/dist/detectors/email-letter.js +76 -14
- 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/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 +8 -0
- package/dist/detectors/gram-openers.d.ts.map +1 -0
- package/dist/detectors/gram-openers.js +16 -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/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 +76 -12
- package/dist/detectors/kutoten-consistency.js.map +1 -1
- package/dist/detectors/lexicon.d.ts.map +1 -1
- package/dist/detectors/lexicon.js +8 -2
- 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 +11 -4
- package/dist/detectors/mark-shape.d.ts.map +1 -1
- package/dist/detectors/mark-shape.js +58 -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/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 -1
- package/dist/detectors/organisation-run.d.ts.map +1 -1
- package/dist/detectors/organisation-run.js +7 -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 +56 -20
- package/dist/detectors/orthographic-variant.js.map +1 -1
- package/dist/detectors/orthography.d.ts.map +1 -1
- package/dist/detectors/orthography.js +6 -1
- package/dist/detectors/orthography.js.map +1 -1
- package/dist/detectors/oxford-comma.d.ts.map +1 -1
- package/dist/detectors/oxford-comma.js +38 -1
- 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/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 +29 -5
- 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 +2 -0
- package/dist/detectors/sentence-counts.d.ts.map +1 -1
- package/dist/detectors/sentence-counts.js +18 -7
- 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-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 +30 -50
- 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/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 +13 -5
- package/dist/detectors/token-shape.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 +33 -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 +15 -0
- package/dist/latin-word-boundary.d.ts.map +1 -0
- package/dist/latin-word-boundary.js +40 -0
- package/dist/latin-word-boundary.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 +5 -0
- package/dist/link-shape.d.ts.map +1 -1
- package/dist/link-shape.js +18 -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-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/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/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 +11 -0
- package/dist/structure/attached-parts.d.ts.map +1 -0
- package/dist/structure/attached-parts.js +31 -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 +3 -2
- package/dist/structure/definition-use.d.ts.map +1 -1
- package/dist/structure/definition-use.js +99 -31
- package/dist/structure/definition-use.js.map +1 -1
- 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 +3 -1
- package/dist/structure/universal.d.ts.map +1 -1
- package/dist/structure/universal.js +9 -2
- 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 +21 -0
- package/dist/title-line.d.ts.map +1 -0
- package/dist/title-line.js +27 -0
- package/dist/title-line.js.map +1 -0
- package/package.json +3 -3
- 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/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/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/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/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 +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/total-mismatch.yaml +2 -2
- package/rules/translationese-density.yaml +2 -2
- package/rules/undefined-acronym.yaml +4 -2
- package/rules/unfilled-placeholder.yaml +4 -4
- 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 +47 -6
- package/src/detectors/acronym-known.ts +40 -0
- package/src/detectors/acronym-link.ts +37 -0
- package/src/detectors/acronym-name.ts +27 -4
- package/src/detectors/addressee-edge.ts +16 -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/caps-caption.ts +42 -0
- package/src/detectors/caps-phrase.ts +17 -0
- package/src/detectors/char-shape.ts +30 -9
- package/src/detectors/cited-title.ts +15 -3
- package/src/detectors/counter-edge.ts +17 -2
- package/src/detectors/date-any-year.ts +27 -6
- 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 +7 -3
- package/src/detectors/derived-numbers.ts +19 -4
- 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/ellipsis.ts +16 -1
- package/src/detectors/email-letter.ts +97 -21
- package/src/detectors/field-label.ts +25 -0
- package/src/detectors/footnote-mismatch.ts +39 -7
- package/src/detectors/graded-step.ts +52 -0
- package/src/detectors/gram-openers.ts +21 -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/ime-residue.ts +4 -3
- package/src/detectors/kanji-compound-slip.ts +61 -0
- package/src/detectors/kutoten-consistency.ts +93 -14
- package/src/detectors/lexicon.ts +12 -3
- 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 +64 -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/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 +13 -2
- package/src/detectors/orthographic-variant.ts +85 -25
- package/src/detectors/orthography.ts +10 -1
- package/src/detectors/oxford-comma.ts +40 -1
- 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/registry/kanji-compound-slip.ts +4 -0
- package/src/detectors/registry/phrase-in-use.ts +4 -0
- package/src/detectors/requirement-smell.ts +38 -5
- package/src/detectors/scaled-figure-unit.ts +103 -0
- package/src/detectors/sentence-counts.ts +24 -8
- package/src/detectors/sentence-ending.ts +12 -3
- package/src/detectors/sentence-load.ts +9 -2
- package/src/detectors/signals.ts +33 -51
- 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/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 +14 -5
- 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 +47 -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 +46 -0
- package/src/lexicon-genres.ts +1 -1
- package/src/link-shape.ts +19 -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-separator.ts +27 -2
- package/src/nominal-stem.ts +62 -5
- package/src/person-forms.ts +15 -0
- package/src/plugin.ts +5 -0
- package/src/preamble-paragraphs.ts +13 -3
- package/src/spacing-code.ts +5 -1
- package/src/split-noun.ts +63 -0
- package/src/structure/attached-parts.ts +32 -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 +116 -25
- 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 +11 -2
- 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 +52 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Token } from "../plugin.ts";
|
|
2
|
+
|
|
3
|
+
/** 連なりの尻の、宛先に付く語。surface はその語、start は文書全体の座標でその語の始まり。 */
|
|
4
|
+
export type AddresseeSuffix = { readonly surface: string; readonly start: number };
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* 漢字の連なり run(文書全体の座標で end に終わる)の尻が、宛先の名前に付く語(志木市役所市政情報課宛ての「宛」、御中)なら、
|
|
8
|
+
* その語。その語は名前の後ろに付くもので、名前の一部ではない。語の切れ目で始まるときだけ(宛ての語の頭が「宛」)。
|
|
9
|
+
* 折り返しをまたぐ語(御\n中)は span が surface より長いので、end から字数を引かず、end の直前の字を覆う語の始まりを使う。
|
|
10
|
+
*/
|
|
11
|
+
export const trailingAddressee = (tokens: readonly Token[], end: number, run: string, suffixes: readonly string[]): AddresseeSuffix | undefined => {
|
|
12
|
+
const suffix = suffixes.find((word) => word !== "" && run.length > word.length && run.endsWith(word));
|
|
13
|
+
if (suffix === undefined) return undefined;
|
|
14
|
+
const token = tokens.find((candidate) => candidate.span.start < end && end <= candidate.span.end);
|
|
15
|
+
return token !== undefined && token.surface.startsWith(suffix) ? { surface: suffix, start: token.span.start } : undefined;
|
|
16
|
+
};
|
|
@@ -13,6 +13,7 @@ const countWordsOf = (doc: ProseDocument): CountWords => ({
|
|
|
13
13
|
frames: patternsOf(doc, "count-frame"),
|
|
14
14
|
hedgesBefore: patternsOf(doc, "count-hedge", "before"),
|
|
15
15
|
hedgesAfter: patternsOf(doc, "count-hedge", "after"),
|
|
16
|
+
titles: patternsOf(doc, "count-title"),
|
|
16
17
|
});
|
|
17
18
|
|
|
18
19
|
const memberGroup = (doc: ProseDocument, group: string): string[] =>
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import type { Detector, Finding, Lexicon, ProseDocument, Sentence, Span, Token } from "../plugin.ts";
|
|
2
2
|
import { quotedIn } from "../quoted-span.ts";
|
|
3
3
|
import { followsInlineCode } from "./code-before.ts";
|
|
4
|
+
import { isNamedStep, plainStepKeys } from "./graded-step.ts";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* 比べる相手の無い比較(より良い結果、さらに高速に、The new engine is faster.)。何より良いのか、何より速いのかが書かれていない。
|
|
7
8
|
* 語は語彙表 comparative-baseline が言う。group marker は日本語の比べる副詞(より、さらに)、more は英語の比べる語、comparative は比べた形の語
|
|
8
9
|
* (faster、better)、baseline は相手を言う語(従来、以前、than、previous)、exempt は比較でない決まった言い方(より多くの、より詳しく)、
|
|
9
10
|
* condition は比較を条件や仮定の下に置く語(使うと、if、would)。条件を書いた比較は、その条件の無い場合と比べている。
|
|
11
|
+
* beyond は比べた形のすぐ前で、いま述べたものを越えると言う語(even better、still faster)。相手はその直前に書いてある。
|
|
12
|
+
* aim は比べた語の後ろで、今より良くする目当てを言う語(より良い社会、より良いものにする)。比べる相手は今の状態。
|
|
10
13
|
* 同じ文か前の二文に相手を言う語があれば、相手は書いてある。
|
|
11
14
|
*/
|
|
12
15
|
|
|
@@ -17,6 +20,8 @@ export type ComparativeLists = {
|
|
|
17
20
|
readonly baselines: readonly string[];
|
|
18
21
|
readonly exempt: ReadonlySet<string>;
|
|
19
22
|
readonly conditions: ReadonlySet<string>;
|
|
23
|
+
readonly beyond: ReadonlySet<string>;
|
|
24
|
+
readonly aims: ReadonlySet<string>;
|
|
20
25
|
};
|
|
21
26
|
|
|
22
27
|
export type BareComparative = { readonly first: Token; readonly last: Token };
|
|
@@ -44,13 +49,35 @@ const isGradable = (tokens: readonly Token[], at: number): boolean => {
|
|
|
44
49
|
/** 比べる副詞が語の頭に立つか。前が助詞・記号・接続の語か文の頭のときだけ(「学年だより等」の「より」は語の一部)。 */
|
|
45
50
|
const OPENS_WORD = new Set(["ADP", "PUNCT", "SCONJ", "CCONJ", "ADV"]);
|
|
46
51
|
|
|
47
|
-
/**
|
|
52
|
+
/** 語から続く語をつないだもの(もの、ものに、ものにする)と、それぞれの後ろの語の位置。 */
|
|
53
|
+
const MAX_AIM_TOKENS = 3;
|
|
54
|
+
const runsFrom = (tokens: readonly Token[], at: number): { readonly run: string; readonly after: number }[] =>
|
|
55
|
+
tokens
|
|
56
|
+
.slice(at, at + MAX_AIM_TOKENS)
|
|
57
|
+
.reduce<{ run: string; after: number }[]>(
|
|
58
|
+
(runs, token, index) => [...runs, { run: `${runs.at(-1)?.run ?? ""}${token.surface}`, after: at + index + 1 }],
|
|
59
|
+
[],
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
/** 続く語に名詞が付いて、より長い語の頭になっているか(社会保障の「社会」)。 */
|
|
63
|
+
const headsCompound = (tokens: readonly Token[], after: number): boolean => {
|
|
64
|
+
const [last, next] = [tokens[after - 1], tokens[after]];
|
|
65
|
+
return last?.pos === "NOUN" && next?.pos === "NOUN" && last.span.end === next.span.start;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
/** 程度を言う語(at)の後ろが、今より良くする目当てか(より良い社会、より豊かな暮らし、より良いものにする)。 */
|
|
69
|
+
const namesAim = (tokens: readonly Token[], at: number, aims: ReadonlySet<string>): boolean => {
|
|
70
|
+
const next = tokens[at]?.pos === "NOUN" && ADJECTIVAL_TAIL.has(tokens[at + 1]?.surface ?? "") ? at + 2 : at + 1;
|
|
71
|
+
return runsFrom(tokens, next).some(({ run, after }) => aims.has(run) && !headsCompound(tokens, after));
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
/** 日本語: 副詞の「より」「さらに」の直後の、程度を言える語。比較の決まった言い方(より多くの)と、今より良くする目当て(より良い社会)は除く。 */
|
|
48
75
|
const markedAt = (tokens: readonly Token[], at: number, lists: ComparativeLists): BareComparative | undefined => {
|
|
49
76
|
const [marker, word] = [tokens[at], tokens[at + 1]];
|
|
50
77
|
if (marker?.pos !== "ADV" || !lists.markers.has(marker.surface) || word === undefined || lists.exempt.has(word.surface)) return undefined;
|
|
51
78
|
const previous = tokens[at - 1];
|
|
52
79
|
if (previous !== undefined && !OPENS_WORD.has(previous.pos)) return undefined;
|
|
53
|
-
return isGradable(tokens, at + 1) ? { first: marker, last: word } : undefined;
|
|
80
|
+
return isGradable(tokens, at + 1) && !namesAim(tokens, at + 1, lists.aims) ? { first: marker, last: word } : undefined;
|
|
54
81
|
};
|
|
55
82
|
|
|
56
83
|
/** 比べた形の後ろで節が終わるか。読点の後ろに形容詞が続けば、名詞の前に並べた修飾語(better, more predictable results)。 */
|
|
@@ -87,10 +114,16 @@ const predicateAt = (tokens: readonly Token[], at: number, lists: ComparativeLis
|
|
|
87
114
|
const isConditional = (tokens: readonly Token[], found: BareComparative, conditions: ReadonlySet<string>): boolean =>
|
|
88
115
|
tokens.some((token) => token.span.start < found.first.span.start && token.pos !== "CCONJ" && conditions.has(lower(token)));
|
|
89
116
|
|
|
117
|
+
/** 比べた形のすぐ前が、いま述べたものを越えると言う語か(performed even better)。 */
|
|
118
|
+
const goesBeyond = (tokens: readonly Token[], found: BareComparative, beyond: ReadonlySet<string>): boolean => {
|
|
119
|
+
const before = tokens.findLastIndex((token) => token.span.end <= found.first.span.start);
|
|
120
|
+
return beyond.has(lower(tokens[before]));
|
|
121
|
+
};
|
|
122
|
+
|
|
90
123
|
export const bareComparativesIn = (tokens: readonly Token[], lists: ComparativeLists): BareComparative[] =>
|
|
91
124
|
tokens
|
|
92
125
|
.flatMap((_, at) => markedAt(tokens, at, lists) ?? predicateAt(tokens, at, lists) ?? [])
|
|
93
|
-
.filter((found) => !isConditional(tokens, found, lists.conditions));
|
|
126
|
+
.filter((found) => !isConditional(tokens, found, lists.conditions) && !goesBeyond(tokens, found, lists.beyond));
|
|
94
127
|
|
|
95
128
|
/**
|
|
96
129
|
* 語が比べる相手を言う語か。語の形か原形で照らし、一字の語(旧)は語の頭だけ(旧版は相手、復旧は相手でない)。
|
|
@@ -128,6 +161,8 @@ export const listsOf = (lexicon: Lexicon): ComparativeLists => ({
|
|
|
128
161
|
baselines: groupOf(lexicon, "baseline"),
|
|
129
162
|
exempt: new Set(groupOf(lexicon, "exempt")),
|
|
130
163
|
conditions: new Set(groupOf(lexicon, "condition")),
|
|
164
|
+
beyond: new Set(groupOf(lexicon, "beyond")),
|
|
165
|
+
aims: new Set(groupOf(lexicon, "aim")),
|
|
131
166
|
});
|
|
132
167
|
|
|
133
168
|
/** 鉤括弧の中の比較(「給与所得の確定申告がさらに簡単に!」ページ)は題や語を挙げたもので、書き手の比較ではない。 */
|
|
@@ -139,12 +174,18 @@ const isThanAfterCode = (doc: ProseDocument, found: BareComparative): boolean =>
|
|
|
139
174
|
|
|
140
175
|
export const bareComparative: Detector = (doc): Finding[] => {
|
|
141
176
|
const lists = listsOf(doc.lexicons["comparative-baseline"] ?? []);
|
|
177
|
+
const steps = plainStepKeys(
|
|
178
|
+
doc.sentences.map((sentence) => ({ tokens: sentence.tokens ?? [], quoted: quotedIn(sentence) })),
|
|
179
|
+
lists.markers,
|
|
180
|
+
isGradable,
|
|
181
|
+
);
|
|
142
182
|
return doc.sentences.flatMap((sentence, at) => {
|
|
143
183
|
const nearby = doc.sentences.slice(Math.max(0, at - BASELINE_REACH), at + 1);
|
|
144
184
|
if (sentence.embeddedLanguage !== undefined || nearby.some((near) => namesBaseline(near, lists.baselines))) return [];
|
|
145
185
|
const quoted = quotedIn(sentence);
|
|
146
186
|
return bareComparativesIn(sentence.tokens ?? [], lists)
|
|
147
187
|
.filter((found) => !quoted.some((span) => insideSpan(found, span)) && !isThanAfterCode(doc, found))
|
|
188
|
+
.filter((found) => !lists.markers.has(found.first.surface) || !isNamedStep(sentence.tokens ?? [], found.last, steps))
|
|
148
189
|
.map((found) => ({
|
|
149
190
|
rule: "",
|
|
150
191
|
severity: "info",
|
|
@@ -8,6 +8,7 @@ import { quoteAt } from "./structure-tree.ts";
|
|
|
8
8
|
import { amountColumnOf, isTotalRowGap, type BodyRow } from "../structure/total-row-blank.ts";
|
|
9
9
|
import { isAmountNameLine, isTotalLine } from "../structure/total-line.ts";
|
|
10
10
|
import { isTotalLabel, withoutLeadingBlankCells } from "../structure/total.ts";
|
|
11
|
+
import { isSpannedLabelGap } from "../structure/spanned-label-blank.ts";
|
|
11
12
|
|
|
12
13
|
/** Fewer body rows than this, and one blank is as likely a choice as a gap. */
|
|
13
14
|
const MIN_BODY_ROWS = 3;
|
|
@@ -67,8 +68,6 @@ const cellOffset = (cell: MarkdownNode | undefined, row: MarkdownNode | undefine
|
|
|
67
68
|
/** Whether a row is a total, subtotal or tax row, judged from the row's source text. */
|
|
68
69
|
export type IsTotalRow = (rowText: string) => boolean;
|
|
69
70
|
|
|
70
|
-
const NO_TOTAL_ROWS: IsTotalRow = () => false;
|
|
71
|
-
|
|
72
71
|
const rowSource = (source: string, row: MarkdownNode): string => {
|
|
73
72
|
const span = spanOf(row);
|
|
74
73
|
return span === undefined ? "" : source.slice(span.start, span.end);
|
|
@@ -79,30 +78,40 @@ const bodyRowOf = (source: string, row: MarkdownNode, isTotalRow: IsTotalRow): B
|
|
|
79
78
|
cells: (row.children ?? []).map((cell) => (shows(cell) ? sourceOf(source, cell) : undefined)),
|
|
80
79
|
});
|
|
81
80
|
|
|
81
|
+
/** How a table's rows are read: which rows are totals, and the total words that make a cell a row label (Total score). */
|
|
82
|
+
type TableReading = { readonly isTotalRow: IsTotalRow; readonly totalWords: readonly string[] };
|
|
83
|
+
|
|
84
|
+
const NO_TOTALS: TableReading = { isTotalRow: () => false, totalWords: [] };
|
|
85
|
+
|
|
82
86
|
/**
|
|
83
87
|
* The one blank body cell of a column whose other body rows are all filled, unless it is a total row's blank beside its
|
|
84
|
-
* amount
|
|
88
|
+
* amount, or the second column of a label that spans two (| Total score | | 5 |). Such a blank still counts as a second
|
|
89
|
+
* blank, so the rows it shares a column with stay as unreported as before.
|
|
85
90
|
*/
|
|
86
|
-
const columnBlank = (source: string,
|
|
91
|
+
const columnBlank = (source: string, table: TableRows, totalWords: readonly string[], column: number): Blank[] => {
|
|
92
|
+
const { header, body, rows } = table;
|
|
87
93
|
const blanks = rows.flatMap((row, index) => (row.cells[column] === undefined ? [index] : []));
|
|
88
94
|
const at = blanks[0];
|
|
89
95
|
const row = at === undefined ? undefined : rows[at];
|
|
90
96
|
if (blanks.length !== 1 || at === undefined || row === undefined) return [];
|
|
91
97
|
if (isTotalRowGap(row, column, amountColumnOf(rows, header.children?.length ?? 0))) return [];
|
|
98
|
+
if (isSpannedLabelGap(row.cells, column, totalWords)) return [];
|
|
92
99
|
const offset = cellOffset(body[at]?.children?.[column], body[at]);
|
|
93
100
|
const name = sourceOf(source, header.children?.[column]);
|
|
94
101
|
return offset === undefined || name === "" ? [] : [{ offset, name }];
|
|
95
102
|
};
|
|
96
103
|
|
|
104
|
+
type TableRows = { readonly header: MarkdownNode; readonly body: readonly MarkdownNode[]; readonly rows: readonly BodyRow[] };
|
|
105
|
+
|
|
97
106
|
/** The first column is skipped: a blank there often means "same as above". */
|
|
98
|
-
const tableBlanksOf = (source: string, table: MarkdownNode,
|
|
107
|
+
const tableBlanksOf = (source: string, table: MarkdownNode, reading: TableReading): Blank[] => {
|
|
99
108
|
const [header, ...body] = table.children ?? [];
|
|
100
109
|
if (header === undefined || body.length < MIN_BODY_ROWS) return [];
|
|
101
|
-
const rows = body.map((row) => bodyRowOf(source, row, isTotalRow));
|
|
110
|
+
const rows = body.map((row) => bodyRowOf(source, row, reading.isTotalRow));
|
|
102
111
|
const columns = header.children?.length ?? 0;
|
|
103
112
|
return Array.from({ length: columns }, (_unused, column) => column)
|
|
104
113
|
.slice(1)
|
|
105
|
-
.flatMap((column) => columnBlank(source, header, body, rows, column));
|
|
114
|
+
.flatMap((column) => columnBlank(source, { header, body, rows }, reading.totalWords, column));
|
|
106
115
|
};
|
|
107
116
|
|
|
108
117
|
/** Quoted material is someone else's: email replies the document model found, and every Markdown blockquote. */
|
|
@@ -118,8 +127,8 @@ const blocksOutsideQuotes = (source: string, type: string, replies: readonly Spa
|
|
|
118
127
|
};
|
|
119
128
|
|
|
120
129
|
/** Blank cells in every table outside quotes. */
|
|
121
|
-
export const tableBlanks = (source: string, replies: readonly Span[] = [],
|
|
122
|
-
blocksOutsideQuotes(source, "table", replies).flatMap((table) => tableBlanksOf(source, table,
|
|
130
|
+
export const tableBlanks = (source: string, replies: readonly Span[] = [], reading: TableReading = NO_TOTALS): Blank[] =>
|
|
131
|
+
blocksOutsideQuotes(source, "table", replies).flatMap((table) => tableBlanksOf(source, table, reading));
|
|
123
132
|
|
|
124
133
|
type Item = { readonly node: MarkdownNode; readonly text: string | undefined; readonly empty: boolean };
|
|
125
134
|
|
|
@@ -192,5 +201,7 @@ const totalRowOf = (doc: ProseDocument): IsTotalRow => {
|
|
|
192
201
|
return (rowText) => isTotalLine(rowText, totals) || isAmountNameLine(rowText, totals) || isTotalLabel(withoutLeadingBlankCells(rowText), taxes);
|
|
193
202
|
};
|
|
194
203
|
|
|
195
|
-
export const emptyTableCell: Detector = findingsOf("empty-table-cell", (doc) =>
|
|
204
|
+
export const emptyTableCell: Detector = findingsOf("empty-table-cell", (doc) =>
|
|
205
|
+
tableBlanks(doc.source, doc.replyQuotes ?? [], { isTotalRow: totalRowOf(doc), totalWords: patternsOf(doc, "total-label") }),
|
|
206
|
+
);
|
|
196
207
|
export const emptyListItem: Detector = findingsOf("empty-list-item", (doc) => listBlanks(doc.source, doc.replyQuotes ?? []));
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { asideAt } from "./open-end-names.ts";
|
|
2
|
+
|
|
3
|
+
// A vague word pinned down by the bracket right after it: 一定の事項(インボイスに記載が必要な事項), a reasonable fee (USD 50).
|
|
4
|
+
// The aside says what the word leaves open, so the word is not vague there. An aside that only gives the phrase a name
|
|
5
|
+
// (以下「措置」という, hereinafter the "Fee") pins nothing down. Pure: the words that start a name come in.
|
|
6
|
+
|
|
7
|
+
/** What may stand between the vague word and the bracket: the noun it qualifies (事項, fee), no punctuation. */
|
|
8
|
+
const BEFORE_BRACKET = /^[\p{L}\p{N}\p{M} ]{0,12}?(?=[((])/u;
|
|
9
|
+
|
|
10
|
+
const startsWithName = (aside: string, nameMarkers: readonly string[]): boolean => {
|
|
11
|
+
const lower = aside.trimStart().toLowerCase();
|
|
12
|
+
return nameMarkers.some((marker) => marker !== "" && lower.startsWith(marker.toLowerCase()));
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Whether the words right after end (an offset in text) are pinned down by a bracket: at most a short noun, then an
|
|
17
|
+
* aside that opens and closes and holds more than a name. nameMarkers: the words that start a name (以下, hereinafter).
|
|
18
|
+
*/
|
|
19
|
+
export const specifiedByBracket = (text: string, end: number, nameMarkers: readonly string[]): boolean => {
|
|
20
|
+
const rest = text.slice(end);
|
|
21
|
+
const before = BEFORE_BRACKET.exec(rest);
|
|
22
|
+
if (before === null) return false;
|
|
23
|
+
const aside = asideAt(text, end + before[0].length);
|
|
24
|
+
return aside !== undefined && aside.trim() !== "" && !startsWithName(aside, nameMarkers);
|
|
25
|
+
};
|
|
@@ -62,12 +62,36 @@ const CITATION_NUMBERS = /^[\d\s,,、–-]+$/u;
|
|
|
62
62
|
/** 画像の参照(`![alt][label]`)の頭の印。指摘の範囲に含める。 */
|
|
63
63
|
const IMAGE_MARK = "!";
|
|
64
64
|
|
|
65
|
+
/** 印の前の逃がし(\)を数えるのに見る字数。 */
|
|
66
|
+
const ESCAPE_REACH = 16;
|
|
67
|
+
const BACKSLASH = "\\";
|
|
68
|
+
|
|
69
|
+
/** 字の並びの終わりに続く \ の数。 */
|
|
70
|
+
const trailingBackslashes = (text: string): number => {
|
|
71
|
+
const reversed = [...text].reverse();
|
|
72
|
+
const other = reversed.findIndex((char) => char !== BACKSLASH);
|
|
73
|
+
return other === -1 ? reversed.length : other;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
/** start の括弧の直前に、逃がしていない ! がある(「\![x][]」は画像ではなくリンク)。 */
|
|
77
|
+
const imageAt = (source: string, start: number): boolean => {
|
|
78
|
+
if (source.charAt(start - 1) !== IMAGE_MARK) return false;
|
|
79
|
+
return trailingBackslashes(source.slice(Math.max(0, start - 1 - ESCAPE_REACH), start - 1)) % 2 === 0;
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* 名前を省いた画像の参照(`![Complete][]`)は、サイトが全ページに定義を足す印や絵(mdBook の前処理、サイト共通の定義)。
|
|
84
|
+
* 画像の行き先をページの中で一度も書かずに名前だけで呼ぶのは、定義がページの外にあるとき。名前を書いた形(`![alt][logo]`)と
|
|
85
|
+
* リンク(`[text][]`)は指摘する。
|
|
86
|
+
*/
|
|
87
|
+
export const siteDefinedImage = (source: string, start: number, label: string): boolean => label === "" && imageAt(source, start);
|
|
88
|
+
|
|
65
89
|
export const unresolvedReferences = (source: string, markup: Markup): Span[] =>
|
|
66
90
|
markup.texts.flatMap((text) =>
|
|
67
91
|
[...source.slice(text.start, text.end).matchAll(REFERENCE_LIKE)]
|
|
68
|
-
.filter((match) => !CITATION_NUMBERS.test(match[1] ?? ""))
|
|
92
|
+
.filter((match) => !CITATION_NUMBERS.test(match[1] ?? "") && !siteDefinedImage(source, text.start + match.index, match[2] ?? ""))
|
|
69
93
|
.map((match) => ({ start: text.start + match.index, end: text.start + match.index + match[0].length }))
|
|
70
|
-
.map((span) => (source
|
|
94
|
+
.map((span) => (imageAt(source, span.start) ? { start: span.start - 1, end: span.end } : span)),
|
|
71
95
|
);
|
|
72
96
|
|
|
73
97
|
const emptyLinks = (doc: ProseDocument, markup: Markup): Finding[] =>
|
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
* captions this way by convention, and prose that names one ("the FOR FURTHER INFORMATION CONTACT section") repeats it.
|
|
5
5
|
* A line of a hard-wrapped paragraph in capitals (a disclaimer) has text above it, so it is no caption.
|
|
6
6
|
*/
|
|
7
|
+
import { linesOf, type Line } from "../structure/lines.ts";
|
|
8
|
+
import type { Span } from "../plugin.ts";
|
|
7
9
|
|
|
8
10
|
/** Markdown heading or list marks and spaces that may stand before a caption on its line. */
|
|
9
11
|
const LINE_LEAD = /^[ \t]*(?:#{1,6}[ \t]+|[-*+][ \t]+)?$/u;
|
|
@@ -59,3 +61,43 @@ export const captionsOf = (source: string): ReadonlySet<string> => {
|
|
|
59
61
|
}),
|
|
60
62
|
);
|
|
61
63
|
};
|
|
64
|
+
|
|
65
|
+
/** A line ends a sentence when its last mark, past closing quotes and brackets, is a period, a question or an exclamation mark. */
|
|
66
|
+
const SENTENCE_END = /[.!?]["'”’)\]]*[ \t\r]*$/u;
|
|
67
|
+
const UPPER = /[A-Z]/u;
|
|
68
|
+
const LOWER = /[a-z]/u;
|
|
69
|
+
|
|
70
|
+
const isCapitalLine = (line: Line): boolean => {
|
|
71
|
+
const bare = line.text.replace(LEAD, "");
|
|
72
|
+
return UPPER.test(bare) && !LOWER.test(bare);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
/** The lines in paragraphs: runs of lines between blank lines. */
|
|
76
|
+
const paragraphsOf = (lines: readonly Line[]): Line[][] =>
|
|
77
|
+
lines.reduce<Line[][]>((paragraphs, line, index) => {
|
|
78
|
+
if (BLANK_LINE.test(line.text)) return paragraphs;
|
|
79
|
+
const above = lines[index - 1];
|
|
80
|
+
if (above !== undefined && !BLANK_LINE.test(above.text)) paragraphs.at(-1)?.push(line);
|
|
81
|
+
else paragraphs.push([line]);
|
|
82
|
+
return paragraphs;
|
|
83
|
+
}, []);
|
|
84
|
+
|
|
85
|
+
const spanOf = (paragraph: readonly Line[]): Span[] => {
|
|
86
|
+
const first = paragraph[0];
|
|
87
|
+
const last = paragraph.at(-1);
|
|
88
|
+
return first === undefined || last === undefined ? [] : [{ start: first.start, end: last.start + last.text.length }];
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* The paragraphs in capitals at the head of a document, before its first sentence: a letterhead, an office's name, an
|
|
93
|
+
* address block (BOARD OF GOVERNORS / WASHINGTON, D.C. 20551). Every line is in capitals and none ends a sentence, so a
|
|
94
|
+
* disclaimer in capitals, which is sentences, is not one. A document with no sentence has no head to tell apart.
|
|
95
|
+
*/
|
|
96
|
+
export const letterheadSpans = (source: string): Span[] => {
|
|
97
|
+
const paragraphs = paragraphsOf(linesOf(source));
|
|
98
|
+
const firstSentence = paragraphs.findIndex((paragraph) => paragraph.some((line) => SENTENCE_END.test(line.text)));
|
|
99
|
+
return paragraphs
|
|
100
|
+
.slice(0, Math.max(firstSentence, 0))
|
|
101
|
+
.filter((paragraph) => paragraph.every(isCapitalLine))
|
|
102
|
+
.flatMap(spanOf);
|
|
103
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// Phrases set in capitals by convention ("NOW, THEREFORE, BE IT RESOLVED" in a resolution). Pure.
|
|
2
|
+
import { escapeRegExp } from "../orthography.ts";
|
|
3
|
+
|
|
4
|
+
const COMMA_OR_SPACE = /,?\s+/u;
|
|
5
|
+
|
|
6
|
+
const wordsOf = (text: string): string => text.trim().split(COMMA_OR_SPACE).join(" ");
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Whether a run of capitals is made only of the listed phrases of several words, one after another ("NOW, THEREFORE" then
|
|
10
|
+
* "BE IT RESOLVED"). A comma after a word, as a run of capitals writes it, is ignored. One-word entries (MUST) match nothing here.
|
|
11
|
+
*/
|
|
12
|
+
export const isConventionalPhrase = (run: string, entries: Iterable<string>): boolean => {
|
|
13
|
+
const phrases = [...entries].map(wordsOf).filter((phrase) => phrase.includes(" "));
|
|
14
|
+
if (phrases.length === 0) return false;
|
|
15
|
+
const one = `(?:${phrases.map(escapeRegExp).join("|")})`;
|
|
16
|
+
return new RegExp(`^${one}(?: ${one})*$`, "u").test(wordsOf(run));
|
|
17
|
+
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Detector, DocumentProfile, Finding, ProseDocument, Sentence, Span, Token } from "../plugin.ts";
|
|
2
2
|
import { compacted } from "./gram-place.ts";
|
|
3
3
|
import { leadingCounter, trailingPrefix } from "./counter-edge.ts";
|
|
4
|
+
import { trailingAddressee } from "./addressee-edge.ts";
|
|
4
5
|
import { maskAddresses } from "../address-chain.ts";
|
|
5
6
|
import { isAddressRun } from "./place-run.ts";
|
|
6
7
|
import { isOneName } from "./name-run.ts";
|
|
@@ -54,7 +55,15 @@ const runsOf = (sentence: Sentence, profile: DocumentProfile | undefined, names:
|
|
|
54
55
|
};
|
|
55
56
|
|
|
56
57
|
/** 連なりを数えないと決める語彙: 住所の先頭にしか来ない単位(都道府県)と、組織の名前の形と単位と、題の名前を閉じる語。 */
|
|
57
|
-
type NameWords = {
|
|
58
|
+
type NameWords = {
|
|
59
|
+
readonly topUnits: ReadonlySet<string>;
|
|
60
|
+
readonly organisation: OrganisationWords;
|
|
61
|
+
readonly title: TitleWords;
|
|
62
|
+
/** 数の後ろで日付・時刻の位置を言う単位(月)。連なりの頭にあれば、数に付いた助数詞。 */
|
|
63
|
+
readonly positional: readonly string[];
|
|
64
|
+
/** 宛先の名前に付く語(宛、御中)。連なりの尻にあれば、名前の後ろに付いた語。 */
|
|
65
|
+
readonly addressee: readonly string[];
|
|
66
|
+
};
|
|
58
67
|
|
|
59
68
|
/** 1 つの文書で連なりを読むのに要るもの。titled は、文書の中で題として置かれた名前(titledNames)。 */
|
|
60
69
|
type RunContext = {
|
|
@@ -85,16 +94,19 @@ const isTitle = (tokens: readonly Token[], span: Span, text: string, placed: boo
|
|
|
85
94
|
(placed || isTitledName(text, context.titled));
|
|
86
95
|
|
|
87
96
|
/**
|
|
88
|
-
* 数えない連なりは空。頭の、数に付いた助数詞(2日日本弁護士連合会の「日」)と、尻の、数に付く接頭の語(施行令第172
|
|
97
|
+
* 数えない連なりは空。頭の、数に付いた助数詞(2日日本弁護士連合会の「日」)と、尻の、数に付く接頭の語(施行令第172条の「第」)と
|
|
98
|
+
* 宛先に付く語(市政情報課宛ての「宛」)は数えない。
|
|
89
99
|
* 住所か名前かは、それを外した残りで決める(1日日本銀行の「日本銀行」)。品詞が無ければ判定しない。
|
|
90
100
|
*/
|
|
91
101
|
const measuredRun = (tokens: readonly Token[] | undefined, run: KanjiRun, context: RunContext): string => {
|
|
92
102
|
if (run.quoted) return "";
|
|
93
103
|
if (tokens === undefined || run.span === undefined) return run.text;
|
|
94
|
-
const counter = leadingCounter(tokens, run.span.start, run.text);
|
|
104
|
+
const counter = leadingCounter(tokens, run.span.start, run.text, context.words.positional);
|
|
95
105
|
const prefix = trailingPrefix(tokens, run.span.end, run.text);
|
|
96
|
-
const
|
|
97
|
-
|
|
106
|
+
const tail =
|
|
107
|
+
prefix === undefined ? trailingAddressee(tokens, run.span.end, run.text, context.words.addressee) : { surface: prefix.surface, start: prefix.span.start };
|
|
108
|
+
const rest = { start: counter?.span.end ?? run.span.start, end: tail?.start ?? run.span.end };
|
|
109
|
+
const text = run.text.slice(counter?.surface.length ?? 0, run.text.length - (tail?.surface.length ?? 0));
|
|
98
110
|
return isPlaceName(tokens, rest, context.words) || isTitle(tokens, rest, text, run.placed, context) ? "" : text;
|
|
99
111
|
};
|
|
100
112
|
|
|
@@ -120,8 +132,14 @@ export const kanjiRun: Detector = (doc, options): Finding[] => {
|
|
|
120
132
|
const patterns = (id: string): string[] => (doc.lexicons[id] ?? []).map((entry) => entry.pattern);
|
|
121
133
|
const words: NameWords = {
|
|
122
134
|
topUnits: new Set(patterns("prefecture-unit")),
|
|
123
|
-
organisation: {
|
|
135
|
+
organisation: {
|
|
136
|
+
forms: patterns("organisation-form"),
|
|
137
|
+
closingForms: (doc.lexicons["organisation-form"] ?? []).filter((entry) => entry.position !== "before").map((entry) => entry.pattern),
|
|
138
|
+
units: patterns("organisation-unit"),
|
|
139
|
+
},
|
|
124
140
|
title: { endings: patterns("title-ending") },
|
|
141
|
+
positional: patterns("calendar-unit"),
|
|
142
|
+
addressee: patterns("addressee-suffix"),
|
|
125
143
|
};
|
|
126
144
|
const names = doc.names ?? [];
|
|
127
145
|
const context: RunContext = { profile: doc.profile, names, words, titled: titledNames(doc, doc.profile, names) };
|
|
@@ -141,10 +159,12 @@ export const kanjiRun: Detector = (doc, options): Finding[] => {
|
|
|
141
159
|
/**
|
|
142
160
|
* 中黒で並べると、どこまでが 1 つの項目か分からなくなる。
|
|
143
161
|
* 「企画・開発・運用・保守体制」は、保守体制が 1 つなのか保守と体制なのか読めない。
|
|
162
|
+
* 語彙表(nakaguro-word)の、中黒を含めて 1 語の語(キャッシュ・フロー)の中黒は並べていないので数えない。
|
|
144
163
|
*/
|
|
145
|
-
export const middleDot: Detector = (doc, options): Finding[] =>
|
|
146
|
-
|
|
147
|
-
|
|
164
|
+
export const middleDot: Detector = (doc, options): Finding[] => {
|
|
165
|
+
const words = (options.lexicon ?? []).map((entry) => entry.pattern).toSorted((left, right) => right.length - left.length);
|
|
166
|
+
return doc.sentences
|
|
167
|
+
.map((sentence) => ({ sentence, count: parallelDotCount(sentence.text, words) }))
|
|
148
168
|
.filter(({ count }) => count > options.limit)
|
|
149
169
|
.map(({ sentence, count }) => ({
|
|
150
170
|
rule: "no-nakaguro-parallel",
|
|
@@ -154,3 +174,4 @@ export const middleDot: Detector = (doc, options): Finding[] =>
|
|
|
154
174
|
quote: sentence.text.trim(),
|
|
155
175
|
values: { count, limit: options.limit, offset: sentence.span.start },
|
|
156
176
|
}));
|
|
177
|
+
};
|
|
@@ -71,13 +71,24 @@ const VENUE_END = /^\s*(?:[,;.]|$)/u;
|
|
|
71
71
|
*/
|
|
72
72
|
const holdsPhrase = (runs: Runs, start: number, end: number): boolean => firstIn(runs.phrasePair, { start: start + 1, end: end + 1 }) !== -1;
|
|
73
73
|
|
|
74
|
+
const LETTER = /\p{L}/u;
|
|
75
|
+
|
|
76
|
+
/** 語の続きのすぐ前が、題名を導く語(whose full title is、entitled)で終わるか。語の途中(retitled)からは読まない。 */
|
|
77
|
+
const afterTitleCue = (source: string, first: Token, titleCues: readonly string[]): boolean => {
|
|
78
|
+
const before = source.slice(source.lastIndexOf("\n", first.span.start - 1) + 1, first.span.start);
|
|
79
|
+
if (before === before.trimEnd()) return false;
|
|
80
|
+
const lead = before.trimEnd().toLowerCase();
|
|
81
|
+
return titleCues.some((cue) => cue !== "" && lead.endsWith(cue.toLowerCase()) && !LETTER.test(lead.charAt(lead.length - cue.length - 1)));
|
|
82
|
+
};
|
|
83
|
+
|
|
74
84
|
/**
|
|
75
85
|
* 文の and / or が、引用した題名の中にあるか。and / or の両隣が Title Case の語の続きで、2 語以上の句を含み、その続きが
|
|
76
|
-
*
|
|
86
|
+
* 引用符か強調の印で囲まれているか、引用符で閉じた論文名のすぐ後ろにあって読点か文の終わりが続く(誌名)か、題名を導く語
|
|
87
|
+
* (titleCues: whose full title is、entitled)のすぐ後ろにあるとき。
|
|
77
88
|
* 本文の固有名詞の並び(Login.gov, TTS Engineering and USAi)や著者の並びは囲まれていないので、題名と読まない。
|
|
78
89
|
* 文を一度だけ読み、どの位置の問いにも続きを読み直さずに答える。
|
|
79
90
|
*/
|
|
80
|
-
export const citedTitles = (tokens: readonly Token[], source: string): ((at: number) => boolean) => {
|
|
91
|
+
export const citedTitles = (tokens: readonly Token[], source: string, titleCues: readonly string[] = []): ((at: number) => boolean) => {
|
|
81
92
|
const runs = runsOf(tokens, source);
|
|
82
93
|
return (at) => {
|
|
83
94
|
const start = leftStart(runs, at);
|
|
@@ -88,7 +99,8 @@ export const citedTitles = (tokens: readonly Token[], source: string): ((at: num
|
|
|
88
99
|
if (!holdsPhrase(runs, start, end)) return false;
|
|
89
100
|
const before = source.slice(Math.max(0, first.span.start - MARK_REACH), first.span.start);
|
|
90
101
|
const after = source.slice(last.span.end, last.span.end + MARK_REACH);
|
|
91
|
-
|
|
102
|
+
const quoted = (OPENING.test(before) && CLOSING.test(after)) || (AFTER_QUOTED_TITLE.test(before) && VENUE_END.test(after));
|
|
103
|
+
return quoted || afterTitleCue(source, first, titleCues);
|
|
92
104
|
};
|
|
93
105
|
};
|
|
94
106
|
|
|
@@ -16,15 +16,30 @@ const wordBefore = (tokens: readonly Token[], at: number): Token | undefined =>
|
|
|
16
16
|
return beyond !== undefined && touches(beyond, previous) ? beyond : undefined;
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
+
const DIGITS = /^[0-90-9]+$/u;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* 数と一語に解析された日付の単位(全角の「4月」)。連なりは単位から始まるので、単位の分だけの語にして返す。
|
|
23
|
+
* positional は数の後ろに置くだけで暦や時計の位置を言う単位(月、時)。
|
|
24
|
+
*/
|
|
25
|
+
const gluedUnit = (tokens: readonly Token[], start: number, run: string, positional: readonly string[]): Token | undefined => {
|
|
26
|
+
const token = tokens.find((candidate) => candidate.span.start < start && start < candidate.span.end);
|
|
27
|
+
if (token === undefined) return undefined;
|
|
28
|
+
const unit = positional.find((word) => token.surface.endsWith(word) && DIGITS.test(token.surface.slice(0, -word.length)));
|
|
29
|
+
return unit !== undefined && run.startsWith(unit) ? { ...token, surface: unit, span: { start, end: token.span.end } } : undefined;
|
|
30
|
+
};
|
|
31
|
+
|
|
19
32
|
/**
|
|
20
33
|
* 漢字の連なり run(文書全体の座標で start から始まる)の頭が、直前の数に付いた助数詞(2日、第76回、24時間)なら、その助数詞の語。
|
|
21
34
|
* 数字が区切りを見せるので、助数詞は数と読まれ、後ろの複合語の一部ではない。そうでなければ undefined。
|
|
35
|
+
* 解析が助数詞と言わない日付の単位(4月の「月」)も、positional にあれば助数詞と読む。
|
|
22
36
|
* 折り返しをまたぐ語(年\n度)は span が surface より長いので、連なりの残りは span の終わりから始まる。
|
|
23
37
|
*/
|
|
24
|
-
export const leadingCounter = (tokens: readonly Token[], start: number, run: string): Token | undefined => {
|
|
38
|
+
export const leadingCounter = (tokens: readonly Token[], start: number, run: string, positional: readonly string[] = []): Token | undefined => {
|
|
25
39
|
const at = tokens.findIndex((token) => token.span.start === start);
|
|
26
40
|
const counter = tokens[at];
|
|
27
|
-
if (counter === undefined
|
|
41
|
+
if (counter === undefined) return gluedUnit(tokens, start, run, positional);
|
|
42
|
+
if (!(isCounter(counter) || positional.includes(counter.surface)) || !isNumber(wordBefore(tokens, at))) return undefined;
|
|
28
43
|
return run.startsWith(counter.surface) ? counter : undefined;
|
|
29
44
|
};
|
|
30
45
|
|
|
@@ -13,10 +13,11 @@ export const YEAR_SPAN_JOINER_LEXICON = "year-span-joiner";
|
|
|
13
13
|
* `adjacent`: just before the date ("each December 31"). `near`: ending a few characters before it (決算日は、12月31日).
|
|
14
14
|
* `label`: before the bracket the date is in (年末年始閉庁日(12月29日~1月3日)). `continues`: opening a list item just
|
|
15
15
|
* after an example's item, it carries the example on ("- For example, … June 22." then "- If instead … June 25").
|
|
16
|
+
* `listed`: named in one list with the date, only list joiners between (祝休日及び12月29日, "public holidays and December 24").
|
|
16
17
|
*/
|
|
17
|
-
export type MarkerReach = "sentence" | "example" | "adjacent" | "near" | "label" | "continues";
|
|
18
|
+
export type MarkerReach = "sentence" | "example" | "adjacent" | "near" | "label" | "continues" | "listed";
|
|
18
19
|
|
|
19
|
-
export const MARKER_REACHES: readonly MarkerReach[] = ["sentence", "example", "adjacent", "near", "label", "continues"];
|
|
20
|
+
export const MARKER_REACHES: readonly MarkerReach[] = ["sentence", "example", "adjacent", "near", "label", "continues", "listed"];
|
|
20
21
|
|
|
21
22
|
export type AnyYearMarker = { readonly word: string; readonly reach: MarkerReach };
|
|
22
23
|
|
|
@@ -151,8 +152,24 @@ const continuesExample = (date: DateSpan, before: string, source: string, marker
|
|
|
151
152
|
return above !== undefined && exampleItem(source, above, lineStart(source, date.offset) - 1, markers, LIST_REACH);
|
|
152
153
|
};
|
|
153
154
|
|
|
154
|
-
|
|
155
|
+
/** What is left of `gap` once the list joiners at its head and the spaces around them are taken off. */
|
|
156
|
+
const afterJoiners = (gap: string, joiners: readonly string[]): string => {
|
|
157
|
+
const trimmed = gap.trimStart();
|
|
158
|
+
const joiner = joiners.find((candidate) => candidate !== "" && trimmed.startsWith(candidate) && !runsOn(trimmed, candidate));
|
|
159
|
+
return joiner === undefined ? trimmed : afterJoiners(trimmed.slice(joiner.length), joiners);
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
/** The word stands just before the date with only list joiners between: 「祝休日及び」, "holidays, and ". */
|
|
163
|
+
const listedBefore = (before: string, word: string, joiners: readonly string[]): boolean => {
|
|
164
|
+
const found = lastWordAt(before, word);
|
|
165
|
+
if (found === -1) return false;
|
|
166
|
+
const gap = before.slice(found + word.length);
|
|
167
|
+
return gap.trim() !== "" && afterJoiners(gap, joiners) === "";
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
const coversDate = (before: string, dateStart: string, intro: string | undefined, word: string, reach: MarkerReach, joiners: readonly string[]): boolean => {
|
|
155
171
|
if (reach === "adjacent") return isAdjacent(latinLower(before), word);
|
|
172
|
+
if (reach === "listed") return listedBefore(latinLower(before), word, joiners);
|
|
156
173
|
if (reach === "near") return lastWordAt(latinLower(before.slice(-(word.length + NEAR_REACH))), word) !== -1;
|
|
157
174
|
if (reach === "label") return latinLower(labelOf(before) ?? "").includes(word);
|
|
158
175
|
if (reach === "continues") return false;
|
|
@@ -160,11 +177,15 @@ const coversDate = (before: string, dateStart: string, intro: string | undefined
|
|
|
160
177
|
return inItem || inSentence(before, dateStart, word) || (intro !== undefined && introEndsWith(latinLower(intro), word));
|
|
161
178
|
};
|
|
162
179
|
|
|
163
|
-
/**
|
|
164
|
-
|
|
180
|
+
/**
|
|
181
|
+
* The date is a recurring day or a worked example: a marker stands where its reach covers the date. `listJoiners` are the
|
|
182
|
+
* words a `listed` marker may stand before the date with (及び, "and").
|
|
183
|
+
*/
|
|
184
|
+
export const anyYearDate = (date: DateSpan, source: string, markers: readonly AnyYearMarker[], listJoiners: readonly string[] = []): boolean => {
|
|
165
185
|
const before = source.slice(lineStart(source, date.offset), date.offset);
|
|
166
186
|
const intro = introOf(source, before, date.offset);
|
|
167
|
-
const
|
|
187
|
+
const joiners = listJoiners.map(latinLower);
|
|
188
|
+
const covered = markers.some(({ word, reach }) => word !== "" && coversDate(before, source.charAt(date.offset), intro, latinLower(word), reach, joiners));
|
|
168
189
|
return covered || continuesExample(date, before, source, markers);
|
|
169
190
|
};
|
|
170
191
|
|
|
@@ -22,7 +22,8 @@ export const dateFormat: Detector = (doc, options): Finding[] => {
|
|
|
22
22
|
eras: (doc.lexicons["calendar-era"] ?? []).map((entry) => entry.pattern),
|
|
23
23
|
};
|
|
24
24
|
const text = doc.prose ?? doc.source;
|
|
25
|
-
|
|
25
|
+
const stampLabels = (doc.lexicons["date-stamp-label"] ?? []).map((entry) => entry.pattern);
|
|
26
|
+
return dateGroups(text, datesIn(text, words), stampLabels).flatMap((group) => {
|
|
26
27
|
const minority = dateMinority(group, options.limit);
|
|
27
28
|
return minority === undefined ? [] : findingsOf(doc, minority);
|
|
28
29
|
});
|