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
|
@@ -53,8 +53,8 @@ example:
|
|
|
53
53
|
Report an incident within 30 minutes and notify the affected teams. Record it in the incident log and fix the cause by the next working day.
|
|
54
54
|
|
|
55
55
|
not_flagged:
|
|
56
|
-
ja: 文書の長さに対して少ないものは指しません。短すぎる文書も測りません。指すのは語のある文ごとに一度で、長い言い方の中の語(in a timely manner の timely)は一つと数えます。英語の法務の文書では、法律や慣行が意味を決めている言い方(reasonable、best efforts、from time to time)の中の語は数えません。要求の文の中の「可能な限り」「必要に応じて」は、要求の書き方として requirement-smell
|
|
57
|
-
en: 'A few vague words for the document''s length are not reported, and very short documents are not measured. Each sentence is reported once, and a word inside a longer phrase ("timely" in "in a timely manner") counts once. In legal documents, a word inside a term that law and practice define ("reasonable", "best efforts", "from time to time") is not counted. Inside a requirement, requirement-smell also reads "where possible" and "as needed".'
|
|
56
|
+
ja: 文書の長さに対して少ないものは指しません。短すぎる文書も測りません。指すのは語のある文ごとに一度で、長い言い方の中の語(in a timely manner の timely)は一つと数えます。英語の法務の文書では、法律や慣行が意味を決めている言い方(reasonable、best efforts、from time to time)の中の語は数えません。要求の文の中の「可能な限り」「必要に応じて」は、要求の書き方として requirement-smell も見ます。すぐ後ろの括弧で中身を書いた語(一定の事項(請求書に書く事項))も数えません。括弧が名前を付けるだけ(以下「本措置」という。)なら数えます。
|
|
57
|
+
en: 'A few vague words for the document''s length are not reported, and very short documents are not measured. Each sentence is reported once, and a word inside a longer phrase ("timely" in "in a timely manner") counts once. In legal documents, a word inside a term that law and practice define ("reasonable", "best efforts", "from time to time") is not counted. Inside a requirement, requirement-smell also reads "where possible" and "as needed". A word that the bracket right after it pins down ("a reasonable fee (USD 50)") is not counted either; a bracket that only names it ("(hereinafter the ""Fee"")") pins nothing down.'
|
|
58
58
|
level_meaning:
|
|
59
59
|
ja: 1000 字あたりあいまいな語 {limit} 個まで
|
|
60
60
|
en: up to {limit} vague words per 1000 words
|
package/skills/chaff/SKILL.md
CHANGED
|
@@ -31,7 +31,9 @@ read. A contract checked as a blog post gets wrong findings, so choose the genre
|
|
|
31
31
|
guessed or default genre shows no guide, and `--no-guide` leaves it out.
|
|
32
32
|
|
|
33
33
|
A rule the genre turns off is listed under "did not run" with the genre as the reason. That is the preset's
|
|
34
|
-
choice, not a gap; turn it back on (`rules:` in `chaff.yaml`) only when the person asks.
|
|
34
|
+
choice, not a gap; turn it back on (`rules:` in `chaff.yaml`) only when the person asks. Some of these are off
|
|
35
|
+
because chaff measured them to be mostly wrong for that kind of document on real, judged documents
|
|
36
|
+
([isamu/chaff-corpus](https://github.com/isamu/chaff-corpus)); turning one back on brings those false findings back.
|
|
35
37
|
|
|
36
38
|
## Run it
|
|
37
39
|
|
|
@@ -75,6 +77,10 @@ calls nothing. Ask the person before a real run; the passages leave the machine.
|
|
|
75
77
|
`npx chaffjs explain <rule-id>` shows why a rule exists, its levels and the current one. Read it before
|
|
76
78
|
relaxing a rule.
|
|
77
79
|
|
|
80
|
+
When a finding is wrong for a reason that is not about this team (chaff misread the text), tell the person and offer
|
|
81
|
+
`npx chaffjs feedback <file> --rule <rule-id> --line <n>`: it drafts a report and sends nothing. A document the
|
|
82
|
+
person may share can go to isamu/chaff-corpus, where wrong findings become test cases and rule fixes.
|
|
83
|
+
|
|
78
84
|
## When numbers or dates disagree
|
|
79
85
|
|
|
80
86
|
The group "Facts that disagree" in `npx chaffjs rules` checks what a sum or a calendar can settle. Among them:
|
package/src/announced-count.ts
CHANGED
|
@@ -20,6 +20,8 @@ export type CountWords = {
|
|
|
20
20
|
readonly hedgesBefore: readonly string[];
|
|
21
21
|
/** 数か数える語のすぐ後ろにあると予告でなくなる語(以上、目、or more)。 */
|
|
22
22
|
readonly hedgesAfter: readonly string[];
|
|
23
|
+
/** 数と合わせて、その一行だけで下の並びの数を言う見出しの語(3行要約、three-line summary)。 */
|
|
24
|
+
readonly titles: readonly string[];
|
|
23
25
|
};
|
|
24
26
|
|
|
25
27
|
export type CountMismatch = { readonly offset: number; readonly phrase: string; readonly announced: number; readonly listed: number };
|
|
@@ -101,7 +103,17 @@ const numberPattern = (words: CountWords): RegExp => {
|
|
|
101
103
|
return new RegExp(latin.length === 0 ? digits : `${digits}|(?<![A-Za-z])(?:${alternation(latin)})(?![A-Za-z])`, "iu");
|
|
102
104
|
};
|
|
103
105
|
|
|
104
|
-
|
|
106
|
+
/**
|
|
107
|
+
* 予告の塊が一行で、数と見出しの語だけ(3行要約、**Three-line summary:**)。前後でそろった強調の印と終わりのコロンは許す。
|
|
108
|
+
* 文の中の「3行要約を書いた」は予告でない。
|
|
109
|
+
*/
|
|
110
|
+
const titlePattern = (words: CountWords): RegExp | undefined => {
|
|
111
|
+
if (words.titles.length === 0) return undefined;
|
|
112
|
+
const numbers = words.numbers.length === 0 ? "\\p{Nd}+" : `\\p{Nd}+|${alternation(words.numbers)}`;
|
|
113
|
+
return new RegExp(`^([ \\t]*(\\*\\*|__|\\*|_)?)((${numbers})[ \\t]?(?:${alternation(words.titles)}))\\2[ \\t]*[::]?[ \\t]*$`, "iu");
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
type Patterns = { readonly phrase: RegExp; readonly number: RegExp; readonly title: RegExp | undefined };
|
|
105
117
|
|
|
106
118
|
/**
|
|
107
119
|
* 数える語の無い数は、先を指す語のすぐ後ろでだけ(the following two:)。「under $75:」の金額を数に読まない。
|
|
@@ -181,20 +193,35 @@ const matchesList = (announced: number, source: string, list: BulletList): boole
|
|
|
181
193
|
|
|
182
194
|
type Context = { readonly source: string; readonly words: CountWords; readonly patterns: Patterns; readonly neighbours: Neighbours };
|
|
183
195
|
|
|
196
|
+
/** 予告の塊のどこに、何と書いて、いくつと言ったか。 */
|
|
197
|
+
type Announcement = { readonly start: number; readonly phrase: string; readonly announced: number };
|
|
198
|
+
|
|
199
|
+
/** 最後の一文の予告(以下の3点)か、塊が見出しの語句だけの予告(3行要約)。 */
|
|
200
|
+
const announcementIn = (lead: string, words: CountWords, patterns: Patterns): Announcement | undefined => {
|
|
201
|
+
const sentenceStart = lastSentenceStart(lead);
|
|
202
|
+
const sentence = lead.slice(sentenceStart);
|
|
203
|
+
const phrase = announcedIn(sentence, words, patterns);
|
|
204
|
+
if (phrase !== undefined)
|
|
205
|
+
return { start: sentenceStart + phrase.start, phrase: sentence.slice(phrase.start, phrase.end).trim(), announced: phrase.announced };
|
|
206
|
+
const title = patterns.title?.exec(lead);
|
|
207
|
+
const written = title?.[3];
|
|
208
|
+
if (title === null || title === undefined || written === undefined) return undefined;
|
|
209
|
+
const announced = valueOf(title[4] ?? "", words.numbers);
|
|
210
|
+
return announced < 1 ? undefined : { start: (title[1] ?? "").length, phrase: written, announced };
|
|
211
|
+
};
|
|
212
|
+
|
|
184
213
|
const mismatchOf = ({ source, words, patterns, neighbours }: Context, list: BulletList): CountMismatch[] => {
|
|
185
214
|
if (hasNeighbour(source, list.span, neighbours)) return [];
|
|
186
215
|
const lead = leadBefore(source, list.span.start);
|
|
187
216
|
if (lead === undefined) return [];
|
|
188
|
-
const
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
if (phrase === undefined || matchesList(phrase.announced, source, list)) return [];
|
|
192
|
-
const offset = lead.start + sentenceStart + phrase.start;
|
|
193
|
-
return [{ offset, phrase: sentence.slice(phrase.start, phrase.end).trim(), announced: phrase.announced, listed: list.items.length }];
|
|
217
|
+
const announcement = announcementIn(lead.text, words, patterns);
|
|
218
|
+
if (announcement === undefined || matchesList(announcement.announced, source, list)) return [];
|
|
219
|
+
return [{ offset: lead.start + announcement.start, phrase: announcement.phrase, announced: announcement.announced, listed: list.items.length }];
|
|
194
220
|
};
|
|
195
221
|
|
|
196
222
|
export const announcedCountMismatches = (source: string, lists: readonly BulletList[], words: CountWords): CountMismatch[] => {
|
|
197
223
|
if (words.counters.length === 0) return [];
|
|
198
|
-
const
|
|
224
|
+
const patterns = { phrase: phrasePattern(words), number: numberPattern(words), title: titlePattern(words) };
|
|
225
|
+
const context = { source, words, patterns, neighbours: neighboursOf(source, lists) };
|
|
199
226
|
return lists.flatMap((list) => mismatchOf(context, list));
|
|
200
227
|
};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { calendarUnitsOf, type CalendarUnits } from "./calendar-number.ts";
|
|
2
|
+
import type { ProseDocument, Sentence } from "./plugin.ts";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 年表の行(「1950年4月 設立」「2003年4月大阪証券取引所上場廃止。」)。日付で始まり、すぐに出来事を書く。
|
|
6
|
+
* 行は名詞で止め、文書の文体とも合わせないのが年表の書き方なので、本文の文として数えない。
|
|
7
|
+
*
|
|
8
|
+
* 日付で始まる文が 1 つだけなら本文(「2020年4月当社は…」)。続けて MIN_ROWS 以上並んだときだけ年表と読む。
|
|
9
|
+
* 行の注記(「当時主要製品は…」)が MAX_GAP 文まで挟まっても同じ年表の続きで、注記も年表の中身として数えない。
|
|
10
|
+
*/
|
|
11
|
+
const MIN_ROWS = 3;
|
|
12
|
+
const MAX_GAP = 4;
|
|
13
|
+
|
|
14
|
+
/** 日付のすぐ後ろにあれば、日付は文の一部で年表の見出しではない(2020年に、2020年4月、当社は)。 */
|
|
15
|
+
const JOINS_DATE = /^[\p{Script=Hiragana}\p{P}\p{Sm}]/u;
|
|
16
|
+
const DIGITS = /^[0-90-9]+/u;
|
|
17
|
+
const CALENDAR_YEAR_DIGITS = 4;
|
|
18
|
+
|
|
19
|
+
type Part = { readonly digits: number; readonly rank: number; readonly end: number };
|
|
20
|
+
|
|
21
|
+
/** 数(全角も)と、その後ろ(空白 1 つまで)の単位。単位が units.chained に無ければ undefined。 */
|
|
22
|
+
const partAt = (text: string, at: number, units: CalendarUnits): Part | undefined => {
|
|
23
|
+
const digits = DIGITS.exec(text.slice(at))?.[0];
|
|
24
|
+
if (digits === undefined) return undefined;
|
|
25
|
+
const unitAt = text[at + digits.length] === " " ? at + digits.length + 1 : at + digits.length;
|
|
26
|
+
const rank = units.chained.findIndex((unit) => text.startsWith(unit, unitAt));
|
|
27
|
+
const unit = units.chained[rank];
|
|
28
|
+
if (unit === undefined) return undefined;
|
|
29
|
+
// 「2020年度」は年度という別の語で、年表の日付ではない。
|
|
30
|
+
if ([...units.year].some((word) => word.length > unit.length && text.startsWith(word, unitAt))) return undefined;
|
|
31
|
+
return { digits: digits.length, rank, end: unitAt + unit.length };
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/** 前より小さい単位(年の後ろの月、月の後ろの日)が続く限り延ばした日付の終わり。 */
|
|
35
|
+
const chainEnd = (text: string, last: Part, units: CalendarUnits): number => {
|
|
36
|
+
const next = partAt(text, last.end, units);
|
|
37
|
+
return next !== undefined && next.rank > last.rank ? chainEnd(text, next, units) : last.end;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/** 文の頭の見出しの札(「2【沿革】」)。本文に流し込んだ見出しの後ろから、最初の行が始まる。 */
|
|
41
|
+
const LEADING_LABEL = /^\s*(?:[0-90-9]+\s*)?【[^】\n]*】\s*/u;
|
|
42
|
+
|
|
43
|
+
/** 文の頭(空白と見出しの札を除く)の、年から始まる日付(1950年4月、昭和56年11月1日)の終わり。年は 4 桁か元号付き。日付で始まらなければ undefined。 */
|
|
44
|
+
const leadingDateEnd = (text: string, units: CalendarUnits): number | undefined => {
|
|
45
|
+
const lead = LEADING_LABEL.exec(text)?.[0].length ?? text.length - text.trimStart().length;
|
|
46
|
+
const era = units.era.find((name) => text.startsWith(name, lead));
|
|
47
|
+
const year = partAt(text, lead + (era?.length ?? 0), units);
|
|
48
|
+
if (year === undefined || year.rank !== 0 || (era === undefined && year.digits !== CALENDAR_YEAR_DIGITS)) return undefined;
|
|
49
|
+
return chainEnd(text, year, units);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/** 年から始まる日付で始まり、助詞も句読点も挟まずに出来事が続く文か。units は日付の単位(年月日の順)と元号。 */
|
|
53
|
+
export const opensWithDateStamp = (text: string, units: CalendarUnits): boolean => {
|
|
54
|
+
const end = leadingDateEnd(text, units);
|
|
55
|
+
if (end === undefined) return false;
|
|
56
|
+
const rest = text.slice(end).trimStart();
|
|
57
|
+
return rest !== "" && !JOINS_DATE.test(rest);
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/** heads[i] が日付で始まる文。年表と読む文の番号(MAX_GAP 文までの間を挟んで MIN_ROWS 以上続く行と、行の間の注記)。 */
|
|
61
|
+
export const chronologyRowIndexes = (heads: readonly boolean[]): ReadonlySet<number> => {
|
|
62
|
+
const dated = heads.flatMap((head, index) => (head ? [index] : []));
|
|
63
|
+
const clusters = dated.reduce<number[][]>((acc, index) => {
|
|
64
|
+
const cluster = acc.at(-1);
|
|
65
|
+
const previous = cluster?.at(-1);
|
|
66
|
+
if (cluster !== undefined && previous !== undefined && index - previous - 1 <= MAX_GAP) cluster.push(index);
|
|
67
|
+
else acc.push([index]);
|
|
68
|
+
return acc;
|
|
69
|
+
}, []);
|
|
70
|
+
return new Set(
|
|
71
|
+
clusters
|
|
72
|
+
.filter((cluster) => cluster.length >= MIN_ROWS)
|
|
73
|
+
.flatMap((cluster) => Array.from({ length: (cluster.at(-1) ?? 0) - (cluster[0] ?? 0) + 1 }, (_, offset) => (cluster[0] ?? 0) + offset)),
|
|
74
|
+
);
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
/** 主題の「は」。年表の行は出来事だけを書き、主題を立てない。立てた文(2021年売上高は110億円です。)は日付で始まっても本文。 */
|
|
78
|
+
const TOPIC = "は";
|
|
79
|
+
const hasTopic = (sentence: Sentence): boolean => (sentence.tokens ?? []).some((token) => token.surface === TOPIC && token.pos === "ADP");
|
|
80
|
+
|
|
81
|
+
/** 文書の中の、年表の行の文。 */
|
|
82
|
+
export const chronologyRows = (doc: ProseDocument): ReadonlySet<Sentence> => {
|
|
83
|
+
const units = calendarUnitsOf(doc);
|
|
84
|
+
const rows = chronologyRowIndexes(doc.sentences.map((sentence) => opensWithDateStamp(sentence.text, units) && !hasTopic(sentence)));
|
|
85
|
+
return new Set(doc.sentences.filter((_, index) => rows.has(index)));
|
|
86
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { escapeRegExp } from "./orthography.ts";
|
|
2
|
+
import type { Span } from "./plugin.ts";
|
|
3
|
+
|
|
4
|
+
/** 会社の名前に使う字(漢字・片仮名・英数字)の続き。かなや句読点で名前は切れる。 */
|
|
5
|
+
const NAME_RUN = /[\p{Script=Han}ァ-ヺーA-Za-zA-Za-z0-90-9&&・]+/gu;
|
|
6
|
+
|
|
7
|
+
/** 漢字か片仮名を含む形(株式会社、㈱、(株))。英字だけの形は日本語の名前の目印にならない。 */
|
|
8
|
+
const NOT_LATIN = /[^\p{Script=Latin}\p{P}\s]/u;
|
|
9
|
+
|
|
10
|
+
const formPattern = (forms: readonly string[]): RegExp =>
|
|
11
|
+
new RegExp(
|
|
12
|
+
[...forms]
|
|
13
|
+
.sort((a, b) => b.length - a.length)
|
|
14
|
+
.map(escapeRegExp)
|
|
15
|
+
.join("|"),
|
|
16
|
+
"gu",
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
/** at を含むか、at で接する名前の字の続き。 */
|
|
20
|
+
const runAround = (runs: readonly Span[], at: number): Span | undefined => runs.find((run) => run.start <= at && at <= run.end);
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* text の中の、日本の会社の形(語彙表 company-form)とその隣の名前の範囲(関東珪曹硝子㈱、株式会社ADEKA)。
|
|
24
|
+
* 名前は書き手が選べない字で書かれるので、表記のゆれを数える語に入れない。形の前は名前の字が続くかぎり、形の後ろも同じ。
|
|
25
|
+
* 名前の字の続きを一度だけ求め、形の両端をそれに合わせて伸ばす。
|
|
26
|
+
*/
|
|
27
|
+
export const japaneseCompanyNameSpans = (text: string, forms: readonly string[]): Span[] => {
|
|
28
|
+
const japanese = forms.filter((form) => NOT_LATIN.test(form));
|
|
29
|
+
if (japanese.length === 0) return [];
|
|
30
|
+
const found = [...text.matchAll(formPattern(japanese))];
|
|
31
|
+
if (found.length === 0) return [];
|
|
32
|
+
const runs = [...text.matchAll(NAME_RUN)].map((match) => ({ start: match.index, end: match.index + match[0].length }));
|
|
33
|
+
return found.map((match) => {
|
|
34
|
+
const end = match.index + match[0].length;
|
|
35
|
+
return { start: runAround(runs, match.index)?.start ?? match.index, end: runAround(runs, end)?.end ?? end };
|
|
36
|
+
});
|
|
37
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Token } from "./plugin.ts";
|
|
2
|
+
|
|
3
|
+
const OPENING = new Set(["(", "("]);
|
|
4
|
+
const CLOSING = new Set([")", ")"]);
|
|
5
|
+
|
|
6
|
+
const isTouching = (left: Token | undefined, right: Token | undefined): boolean =>
|
|
7
|
+
left !== undefined && right !== undefined && left.span.end === right.span.start;
|
|
8
|
+
|
|
9
|
+
const isNounBefore = (token: Token, next: Token | undefined, suffixes: ReadonlySet<string>): next is Token =>
|
|
10
|
+
next?.pos === "NOUN" && isTouching(token, next) && !suffixes.has(next.surface);
|
|
11
|
+
|
|
12
|
+
/** A noun alone in brackets that close onto a noun (卒業(見込)証明書): the brackets mark it optional inside one compound. */
|
|
13
|
+
const isBracketedInCompound = (token: Token, tokens: readonly Token[], at: number, suffixes: ReadonlySet<string>): boolean => {
|
|
14
|
+
const [opening, closing] = [tokens[at - 1], tokens[at + 1]];
|
|
15
|
+
if (opening === undefined || closing === undefined) return false;
|
|
16
|
+
if (!OPENING.has(opening.surface) || !CLOSING.has(closing.surface) || !isTouching(opening, token) || !isTouching(token, closing)) return false;
|
|
17
|
+
return isNounBefore(closing, tokens[at + 2], suffixes);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Whether `token`, read at `at` in `tokens`, is a noun written onto the noun after it (取扱事業者), so official Japanese may
|
|
22
|
+
* drop its okurigana. A listed phrase suffix (割当て等) does not make a compound. `token` may be tokens[at] read as a noun.
|
|
23
|
+
*/
|
|
24
|
+
export const isCompoundHead = (token: Token, tokens: readonly Token[], at: number, suffixes: ReadonlySet<string>): boolean =>
|
|
25
|
+
token.pos === "NOUN" && (isNounBefore(token, tokens[at + 1], suffixes) || isBracketedInCompound(token, tokens, at, suffixes));
|
package/src/date-format.ts
CHANGED
|
@@ -115,9 +115,48 @@ const LINE_HEAD = /(?:^|\|)[\s>*_+-]*(?:\d+[.)]\s+)?$/u;
|
|
|
115
115
|
/** 日付が行の頭(箇条書きの項目や表の升の頭)にあるか。 */
|
|
116
116
|
export const opensLine = (text: string, offset: number): boolean => LINE_HEAD.test(text.slice(text.lastIndexOf("\n", offset - 1) + 1, offset));
|
|
117
117
|
|
|
118
|
+
/** 刻印のラベルと日付の間に来る字(更新日:、Last updated: )。 */
|
|
119
|
+
const STAMP_GAP = /[\s::]/u;
|
|
120
|
+
/** 末尾の、ラベルと日付の間の字を外した文字列。 */
|
|
121
|
+
const withoutGap = (text: string): string => {
|
|
122
|
+
const chars = text.split("");
|
|
123
|
+
return chars.slice(0, chars.findLastIndex((char) => !STAMP_GAP.test(char)) + 1).join("");
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
/** 刻印のラベルの前に来てよい字。行の頭か、ページの部品を区切る空白と縦線(ページID:0014616 更新日:)。 */
|
|
127
|
+
const STAMP_LEAD = /[\s||]/u;
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* text が刻印のラベル word で終わり、ラベルが行の頭か区切りの後ろから始まる。文の中の語(この日付は公開:、The date:、
|
|
131
|
+
* 1Updated)は刻印のラベルではない。語彙表に書いたとおりの字で照らす。
|
|
132
|
+
*/
|
|
133
|
+
const endsWithLabel = (text: string, word: string): boolean => {
|
|
134
|
+
const start = text.length - word.length;
|
|
135
|
+
if (word === "" || start < 0 || !text.endsWith(word)) return false;
|
|
136
|
+
return start === 0 || STAMP_LEAD.test(text.charAt(start - 1));
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* 日付のすぐ前が、ページの更新日・公開日の刻印のラベル(更新日:2026年10月13日、Last updated: 2 October 2026)。
|
|
141
|
+
* 刻印は CMS が付ける付帯情報で、本文の日付の書き方(令和8年…)とは別の書き方をしてよい。
|
|
142
|
+
*/
|
|
143
|
+
export const stampedDate = (text: string, offset: number, stampLabels: readonly string[]): boolean => {
|
|
144
|
+
const before = withoutGap(text.slice(text.lastIndexOf("\n", offset - 1) + 1, offset));
|
|
145
|
+
return stampLabels.some((label) => endsWithLabel(before, label));
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
type DateGroup = "head" | "body" | "stamp";
|
|
149
|
+
|
|
150
|
+
const groupOf = (text: string, date: WrittenDate, stampLabels: readonly string[]): DateGroup => {
|
|
151
|
+
if (stampedDate(text, date.offset, stampLabels)) return "stamp";
|
|
152
|
+
return opensLine(text, date.offset) ? "head" : "body";
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
const GROUP_ORDER: readonly DateGroup[] = ["head", "body", "stamp"];
|
|
156
|
+
|
|
118
157
|
/**
|
|
119
|
-
*
|
|
120
|
-
*
|
|
158
|
+
* 行の頭の日付と、文の中の日付と、更新日・公開日の刻印の日付を分ける。予定表を 2026-10-16 で並べ、文では 14 October 2026 と
|
|
159
|
+
* 書くのは使い分けで、混ざりではない。刻印のラベルは言語パッケージの語彙表(date-stamp-label)が渡す。書き方はそれぞれの組の中でだけ比べる。
|
|
121
160
|
*/
|
|
122
|
-
export const dateGroups = (text: string, dates: readonly WrittenDate[]): WrittenDate[][] =>
|
|
123
|
-
|
|
161
|
+
export const dateGroups = (text: string, dates: readonly WrittenDate[], stampLabels: readonly string[] = []): WrittenDate[][] =>
|
|
162
|
+
GROUP_ORDER.map((group) => dates.filter((date) => groupOf(text, date, stampLabels) === group)).filter((group) => group.length > 0);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Span } from "../plugin.ts";
|
|
2
|
+
import { overlapsAny, type SpanIndex } from "../compare/spans.ts";
|
|
3
|
+
import type { DurationUnit } from "./date-arithmetic.ts";
|
|
4
|
+
|
|
5
|
+
/** A word that names a period (週, 毎月, a week), where it is written beside the count, and the period's unit. */
|
|
6
|
+
export type PeriodWord = { readonly word: string; readonly position: "before" | "after"; readonly unit: DurationUnit };
|
|
7
|
+
|
|
8
|
+
/** The period words, and the named schedules in the document (週休2日制, 4週8休). */
|
|
9
|
+
export type PerPeriodWords = { readonly periods: readonly PeriodWord[]; readonly schedules: SpanIndex };
|
|
10
|
+
|
|
11
|
+
const UNIT_ORDER: readonly DurationUnit[] = ["day", "week", "month", "year"];
|
|
12
|
+
|
|
13
|
+
/** A number or a counter just before the period word: 1年3か月 and 3か月10日 are one length written in two units, not a count per year or month. */
|
|
14
|
+
const COUNTED = /[0-90-9〇一二三四五六七八九十百千かヵヶカケ箇個]$/u;
|
|
15
|
+
|
|
16
|
+
const endsWithPeriod = (before: string, word: string): boolean => before.endsWith(word) && !COUNTED.test(before.slice(0, before.length - word.length));
|
|
17
|
+
|
|
18
|
+
const isBeside = (period: PeriodWord, before: string, after: string): boolean =>
|
|
19
|
+
period.position === "before" ? endsWithPeriod(before, period.word) : after.startsWith(period.word);
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* A number with a unit of time that is not a length to add to a date: a count in each period (週3日、月10日、3 days a week) or a
|
|
23
|
+
* number inside the name of a work schedule (週休2日制の2日、4週8休の4週). A count is in a unit smaller than its period: 毎年1年間 is a
|
|
24
|
+
* year's length. before and after are the text next to the count, lower-cased.
|
|
25
|
+
*/
|
|
26
|
+
export const isCountPerPeriod = (count: Span & { readonly unit: DurationUnit }, before: string, after: string, words: PerPeriodWords): boolean =>
|
|
27
|
+
overlapsAny(words.schedules, count) ||
|
|
28
|
+
words.periods.some((period) => UNIT_ORDER.indexOf(count.unit) < UNIT_ORDER.indexOf(period.unit) && isBeside(period, before, after));
|
|
@@ -6,7 +6,7 @@ import { loneNumeralSpans, nameNumeralSpans } from "./name-numeral.ts";
|
|
|
6
6
|
import { placeholderSpans } from "./placeholder.ts";
|
|
7
7
|
import { numeralWordSpans } from "./numeral-word.ts";
|
|
8
8
|
import { seriesLabelSpans } from "./series-label.ts";
|
|
9
|
-
import { oneOf } from "./acronym-name.ts";
|
|
9
|
+
import { nameSpansOf, oneOf } from "./acronym-name.ts";
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* 大文字の語が略語ではなく、決まった書き方の一部として読める所(3:30 PM、1pm ET、USD 1,000、Kansas City, MO 64108、Fort Lauderdale FL 33304)。
|
|
@@ -114,3 +114,32 @@ export const notAcronymSpansOf = (words: NotationWords): NotAcronymSpans => {
|
|
|
114
114
|
...numeralWordSpans(text),
|
|
115
115
|
];
|
|
116
116
|
};
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* 略語として数えない範囲(書き方の範囲と、名前の中の範囲)を、言語パッケージの語彙表から組み立てる。wordsOf は語彙表の id から語を返す。
|
|
120
|
+
*/
|
|
121
|
+
export const lexiconNotationOf = (wordsOf: (id: string) => string[]): NotAcronymSpans => {
|
|
122
|
+
const notation = notAcronymSpansOf({
|
|
123
|
+
meridiem: wordsOf("meridiem"),
|
|
124
|
+
timeZones: wordsOf("time-zone"),
|
|
125
|
+
currencies: wordsOf("currency-code"),
|
|
126
|
+
usStates: wordsOf("us-state-code"),
|
|
127
|
+
emphasis: wordsOf("emphasis-word"),
|
|
128
|
+
divisions: wordsOf("numbered-division"),
|
|
129
|
+
abbreviatedLabels: wordsOf("abbreviated-label"),
|
|
130
|
+
honorifics: wordsOf("honorific"),
|
|
131
|
+
titles: wordsOf("name-title"),
|
|
132
|
+
dateTimeUnits: wordsOf("date-time-unit"),
|
|
133
|
+
});
|
|
134
|
+
const names = nameSpansOf({
|
|
135
|
+
legalForms: wordsOf("legal-form"),
|
|
136
|
+
companyForms: wordsOf("company-form"),
|
|
137
|
+
determiners: wordsOf("name-determiner"),
|
|
138
|
+
citationSeries: wordsOf("citation-series"),
|
|
139
|
+
carriers: wordsOf("carrier-name"),
|
|
140
|
+
namePrefixes: wordsOf("name-prefix"),
|
|
141
|
+
streetSuffixes: wordsOf("street-suffix"),
|
|
142
|
+
capitalPhrases: wordsOf("capital-phrase"),
|
|
143
|
+
});
|
|
144
|
+
return (text) => [...notation(text), ...names(text)];
|
|
145
|
+
};
|
|
@@ -13,6 +13,9 @@ import { escapeRegExp } from "../orthography.ts";
|
|
|
13
13
|
* 人事部(以下「HR」という。) 括弧の中が定義の語と略語だけ
|
|
14
14
|
* overnight reverse repurchase agreement (ON RRP) 括弧の中が空白で繋いだ略語だけで、前の名前から文字が順に拾える
|
|
15
15
|
* Partnership On Wide Energy and Resources Resilience Asia (POWERR Asia) 括弧の中が略語と添えた語で、前の名前の頭文字と揃う
|
|
16
|
+
* End User Technical Advisory Board (“End User TAB”) 括弧の中が名前の頭の語と略語で、前の名前の頭文字と揃う
|
|
17
|
+
* Special Interest Groups, or SIGs 名前の後ろの読点と言い換えの語(語彙表の definition-alternative)の後ろで、名前の頭文字と揃う
|
|
18
|
+
* 複数形の s を付けた略語(SIGs)の展開は、s の無い略語(SIG)の展開でもある。
|
|
16
19
|
* 括弧と略語の間には、引用符((“MNDA”)、(「MNDA」))と空白だけを許す。
|
|
17
20
|
*/
|
|
18
21
|
const WRAP = String.raw`[\s"“”'‘’「」『』]*`;
|
|
@@ -37,11 +40,14 @@ const DEFINITION_REACH = 60;
|
|
|
37
40
|
/** 定義の語どうし、定義の語と略語の間に来てよいもの(以下、HR)。英字が続けば語の途中((theSLA))。 */
|
|
38
41
|
const MARKER_GAP = String.raw`(?![A-Za-z])[\s、,]*`;
|
|
39
42
|
|
|
43
|
+
/** 複数形の略語の終わりの s(SIGs)。頭文字と比べる文字ではない。 */
|
|
44
|
+
const PLURAL_END = /(?<=[A-Z])s$/u;
|
|
45
|
+
|
|
40
46
|
/**
|
|
41
47
|
* 角括弧は引用の印にも使う([IANA]、[1])。直前の語のうち大文字で始まる語の頭文字が
|
|
42
48
|
* 略語と揃うときだけ展開と見なす。見る語は略語の文字数の 2 倍まで(and や of を挟むため)。
|
|
43
49
|
*/
|
|
44
|
-
const lettersOf = (acronym: string): string => acronym.replaceAll(/[&-]/gu, "");
|
|
50
|
+
const lettersOf = (acronym: string): string => acronym.replaceAll(/[&-]/gu, "").replace(PLURAL_END, "");
|
|
45
51
|
|
|
46
52
|
const initialsOf = (words: readonly string[]): string =>
|
|
47
53
|
words
|
|
@@ -92,16 +98,20 @@ const isNamedBeforeAt = (body: string, acronym: string, at: number): boolean =>
|
|
|
92
98
|
return namesAcronym(named.groups?.["name"] ?? "", acronym);
|
|
93
99
|
};
|
|
94
100
|
|
|
95
|
-
/**
|
|
96
|
-
|
|
101
|
+
/**
|
|
102
|
+
* 言語パッケージの語彙表から読む、括弧の中で略語の前に書く語(以下、hereinafter)と後ろに書く語(という)、名前の後ろの読点に続けて
|
|
103
|
+
* 略語の前に書く言い換えの語(Special Interest Groups, or SIGs の or)。
|
|
104
|
+
*/
|
|
105
|
+
export type DefinitionWords = { readonly markers: readonly string[]; readonly verbs: readonly string[]; readonly alternatives?: readonly string[] };
|
|
97
106
|
|
|
98
|
-
type DefinitionPatterns = { readonly opened: RegExp; readonly closes: RegExp };
|
|
107
|
+
type DefinitionPatterns = { readonly opened: RegExp; readonly closes: RegExp; readonly alternative: RegExp };
|
|
99
108
|
|
|
100
109
|
const oneOf = (words: readonly string[]): string => (words.length === 0 ? "(?!)" : words.map(escapeRegExp).join("|"));
|
|
101
110
|
|
|
102
111
|
const definitionPatterns = (words: DefinitionWords): DefinitionPatterns => ({
|
|
103
112
|
opened: new RegExp(String.raw`[((]\s*(?<markers>(?:(?:${oneOf(words.markers)})${MARKER_GAP})*)${WRAP}(?<![A-Za-z])$`, "iu"),
|
|
104
113
|
closes: new RegExp(String.raw`^${WRAP}(?<verb>(?:${oneOf(words.verbs)})[。.]?)?${WRAP}[))]`, "iu"),
|
|
114
|
+
alternative: new RegExp(String.raw`[,,、]\s*(?:${oneOf(words.alternatives ?? [])})\s*$`, "iu"),
|
|
105
115
|
});
|
|
106
116
|
|
|
107
117
|
/**
|
|
@@ -166,12 +176,39 @@ const isQualifiedAt = (body: string, acronym: string, at: number): boolean => {
|
|
|
166
176
|
return spellsOut(name.endsWith(words) ? name.slice(0, -words.length) : name, acronym);
|
|
167
177
|
};
|
|
168
178
|
|
|
179
|
+
/** 括弧の中で略語の前に置いた、大文字で始まる語((“End User TAB”) の End User)。 */
|
|
180
|
+
const PREFIX = new RegExp(String.raw`[((]${WRAP}(?<words>(?:[A-Z][a-z]+ )+)$`, "u");
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* 括弧の中が、前の名前の頭の語と略語だけの形(End User Technical Advisory Board (“End User TAB”))。添えた語が括弧の前の名前にあり、
|
|
184
|
+
* 名前の頭文字が略語と揃うときだけ展開と見なす。名前に無い語を添えた括弧(Review Board (“Community CRB”))は別の名前。
|
|
185
|
+
*/
|
|
186
|
+
const isPrefixedAt = (body: string, acronym: string, at: number): boolean => {
|
|
187
|
+
const prefix = PREFIX.exec(body.slice(Math.max(0, at - DEFINITION_REACH), at));
|
|
188
|
+
if (prefix === null || !CLOSES.test(body.slice(at + acronym.length, at + acronym.length + NEAR))) return false;
|
|
189
|
+
const name = body.slice(0, at - prefix[0].length);
|
|
190
|
+
const words = (prefix.groups?.["words"] ?? "").trim();
|
|
191
|
+
return name.slice(-DEFINITION_REACH).includes(words) && spellsOut(name, acronym);
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
/** 名前の後ろの読点と言い換えの語に続く略語(Special Interest Groups, or SIGs)。名前の頭文字が略語と揃うときだけ。 */
|
|
195
|
+
const isAlternativeAt = (patterns: DefinitionPatterns, body: string, acronym: string, at: number): boolean => {
|
|
196
|
+
const joined = patterns.alternative.exec(body.slice(Math.max(0, at - DEFINITION_REACH), at));
|
|
197
|
+
return joined !== null && spellsOut(body.slice(0, at - joined[0].length), acronym);
|
|
198
|
+
};
|
|
199
|
+
|
|
169
200
|
const isBracketedAt = (body: string, acronym: string, at: number): boolean => {
|
|
170
201
|
const after = body.slice(at + acronym.length, at + acronym.length + NEAR);
|
|
171
202
|
const before = body.slice(Math.max(0, at - NEAR), at);
|
|
172
203
|
if (OPENS.test(after) || (OPENED.test(before) && CLOSES.test(after))) return true;
|
|
173
204
|
if (SQUARE_OPENED.test(before) && SQUARE_CLOSES.test(after) && spellsOut(body.slice(0, at), acronym)) return true;
|
|
174
|
-
return
|
|
205
|
+
return (
|
|
206
|
+
isSeparatedAt(body, acronym, at) ||
|
|
207
|
+
isNamedBeforeAt(body, acronym, at) ||
|
|
208
|
+
isJointBracketedAt(body, acronym, at) ||
|
|
209
|
+
isQualifiedAt(body, acronym, at) ||
|
|
210
|
+
isPrefixedAt(body, acronym, at)
|
|
211
|
+
);
|
|
175
212
|
};
|
|
176
213
|
|
|
177
214
|
/**
|
|
@@ -358,5 +395,9 @@ export type ExpandedAt = (body: string, acronym: string, at: number) => boolean;
|
|
|
358
395
|
/** body の at にある略語が、その場で展開・定義されているか。語彙表から一度だけ組み立てて、略語ごとに呼ぶ。 */
|
|
359
396
|
export const expansionAt = (words: DefinitionWords): ExpandedAt => {
|
|
360
397
|
const patterns = definitionPatterns(words);
|
|
361
|
-
return (body, acronym, at) =>
|
|
398
|
+
return (body, acronym, at) =>
|
|
399
|
+
isBracketedAt(body, acronym, at) ||
|
|
400
|
+
isDefinedAt(patterns, body, acronym, at) ||
|
|
401
|
+
isAlternativeAt(patterns, body, acronym, at) ||
|
|
402
|
+
isEqualsDefinedAt(body, acronym, at);
|
|
362
403
|
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// Words in capitals that a document itself makes known without spelling them out: a keyword of its code, a cited venue. Pure.
|
|
2
|
+
import { codeFences, codeSpans, withoutCodeBlocks } from "./code-fences.ts";
|
|
3
|
+
|
|
4
|
+
type Span = { readonly start: number; readonly end: number };
|
|
5
|
+
|
|
6
|
+
/** A piece of code between spaces and brackets: a hyphen, a dot, a slash or an underscore keeps a name in one piece. */
|
|
7
|
+
const CODE_TOKEN = /[\w./-]+/gu;
|
|
8
|
+
/** A keyword: a token of letters only (select, from), not a name with parts (net-http-sspi, gsa.gov, --yjit, api_key). */
|
|
9
|
+
const KEYWORD = /^[A-Za-z]+$/u;
|
|
10
|
+
/** The text of an inline link ([text](url)) or of a reference link ([text][label]). */
|
|
11
|
+
const LINK_TEXT = /^\[([^\]]*)\][([]/u;
|
|
12
|
+
/** Capitals followed by a year: a venue and when it was held (FOSDEM 2024). */
|
|
13
|
+
const VENUE_YEAR = /(?<![\w&])([A-Z][A-Z\d]+) (?:19|20)\d{2}(?!\d)/gu;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* The keywords a document's code (fenced blocks and inline code) writes in lower case, in capitals. Prose that writes a
|
|
17
|
+
* keyword of that code in capitals (a SELECT, the WHERE clause, with select and where in the code) names the keyword; it is
|
|
18
|
+
* not an acronym. A word the code too writes in capitals (`TTS`) is the acronym set as code, and gives nothing.
|
|
19
|
+
*/
|
|
20
|
+
export const codeWords = (source: string): Set<string> => {
|
|
21
|
+
const blocks = codeFences(source).flatMap((fence) => fence.lines);
|
|
22
|
+
const inline = codeSpans(withoutCodeBlocks(source)).map((span) => span.text);
|
|
23
|
+
const tokens = [...blocks, ...inline].flatMap((code) => code.match(CODE_TOKEN) ?? []);
|
|
24
|
+
return new Set(tokens.filter((token) => KEYWORD.test(token) && token !== token.toUpperCase()).map((token) => token.toUpperCase()));
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Capitals followed by a year in a link's text (([Jane Roe, FOSDEM 2024, 18:10](https://…))): the venue of a cited talk or
|
|
29
|
+
* paper, as a reference list names one, and the link leads to it. Outside a link, a year after capitals is not read so.
|
|
30
|
+
*/
|
|
31
|
+
export const citedVenues = (source: string, links: readonly Span[]): Set<string> =>
|
|
32
|
+
new Set(
|
|
33
|
+
links.flatMap((link) => {
|
|
34
|
+
const text = LINK_TEXT.exec(source.slice(link.start, link.end))?.[1] ?? "";
|
|
35
|
+
return [...text.matchAll(VENUE_YEAR)].flatMap((match) => (match[1] === undefined ? [] : [match[1]]));
|
|
36
|
+
}),
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
/** Both: the capitals a document makes known, which undefined-acronym does not ask to spell out. */
|
|
40
|
+
export const knownByDocument = (source: string, links: readonly Span[]): string[] => [...codeWords(source), ...citedVenues(source, links)];
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 外のページへのリンクを 1 行に 1 つ並べた一覧(参考の一覧、謝辞)の、リンクの文字。リンク先のページの題名
|
|
3
|
+
* (- [NASA Fprime AI Policy](https://…)、- [User Timing API - Web APIs | MDN](https://…))で、書き手が展開を書き足せない。
|
|
4
|
+
* 文の中のリンク(following [NIST SP 800-61](https://…), as …)は書き手の言葉なので、略語をそのまま数える。
|
|
5
|
+
* 文書の中や手元のファイルへのリンク([README](./README.md))も題名ではない。
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
type Span = { readonly start: number; readonly end: number };
|
|
9
|
+
|
|
10
|
+
const EXTERNAL = /^<?https?:\/\//iu;
|
|
11
|
+
const TEXT_END = "](";
|
|
12
|
+
/** リンクの前に書いてよいもの: 行頭の空白と、箇条書きの印。 */
|
|
13
|
+
const LINE_HEAD = /^[ \t]*(?:(?:[-*+]|\d+[.)])[ \t]+)?$/u;
|
|
14
|
+
/** リンクの後ろに書いてよいもの: 行末までの空白と句読点。 */
|
|
15
|
+
const LINE_TAIL = /^[ \t.,;。、]*(?:\n|$)/u;
|
|
16
|
+
|
|
17
|
+
/** リンクの文字の範囲。[文字](行き先) の形で、行き先が外のページのものだけ。 */
|
|
18
|
+
const externalTextOf = (source: string, link: Span): Span | undefined => {
|
|
19
|
+
const written = source.slice(link.start, link.end);
|
|
20
|
+
const end = written.lastIndexOf(TEXT_END);
|
|
21
|
+
if (!written.startsWith("[") || end === -1 || !EXTERNAL.test(written.slice(end + TEXT_END.length))) return undefined;
|
|
22
|
+
return { start: link.start + 1, end: link.start + end };
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const standsAlone = (source: string, link: Span): boolean => {
|
|
26
|
+
const lineStart = source.lastIndexOf("\n", link.start - 1) + 1;
|
|
27
|
+
const lineEnd = source.indexOf("\n", link.end);
|
|
28
|
+
const tail = lineEnd === -1 ? source.slice(link.end) : source.slice(link.end, lineEnd + 1);
|
|
29
|
+
return LINE_HEAD.test(source.slice(lineStart, link.start)) && LINE_TAIL.test(tail);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/** 1 行に 1 つ並べた外のページへのリンクの、文字の範囲。位置は source の上。 */
|
|
33
|
+
export const linkTitleSpans = (source: string, links: readonly Span[]): Span[] =>
|
|
34
|
+
links.flatMap((link) => {
|
|
35
|
+
const text = externalTextOf(source, link);
|
|
36
|
+
return text !== undefined && standsAlone(source, link) ? [text] : [];
|
|
37
|
+
});
|
|
@@ -12,6 +12,8 @@ type Span = { readonly start: number; readonly end: number };
|
|
|
12
12
|
export type NameWords = {
|
|
13
13
|
/** 会社名の後ろに大文字で書く法人の形(LLC、INC、SE、PTE、PTY)。 */
|
|
14
14
|
readonly legalForms: readonly string[];
|
|
15
|
+
/** 日本の会社の形(株式会社、㈱。語彙表 company-form)。すぐ隣の英字の語は会社の名前(㈱ADEKA、DOWAホールディングス㈱)。 */
|
|
16
|
+
readonly companyForms: readonly string[];
|
|
15
17
|
/** 名詞の前に置く限定の語(the、this、each)。文の頭で大文字になっても(The SE team)名前の語ではない。大小を問わずに照らす。 */
|
|
16
18
|
readonly determiners: readonly string[];
|
|
17
19
|
/** 法令・官報の引用の大文字の部分(45 CFR §164、21 USC §301、94/820/EC)。 */
|
|
@@ -52,20 +54,40 @@ const NAME_WORDS_MAX = 5;
|
|
|
52
54
|
/**
|
|
53
55
|
* 名前の語のすぐ後ろ(読点を挟んでもよい)の法人の形と、その前の名前(JVLS, LLC、CPM Medical Consultants LLC、TRATON SE、
|
|
54
56
|
* GitLab Singapore PTE. LTD.)。名前の語は空白だけで続くものを数え、読点で切れた先(CENTENE CORPORATION, MAYFLOWER …)は入れない。
|
|
55
|
-
* 名前に続けて書いた括弧のすぐ後ろの形(SUNCALL(Guangzhou)CO.,LTD
|
|
57
|
+
* 名前に続けて書いた括弧のすぐ後ろの形(SUNCALL(Guangzhou)CO.,LTD.、SUNCALL CO.,(H.K.)LTD.)も名前の終わり。日本語の文の中の「,」も区切り(JCI(THAILAND)CO.,LTD.)。空白を挟んだ括弧(Section (A) LLC)は名前の一部ではない。形のすぐ前が限定の語なら名前ではない(The SE team)。
|
|
56
58
|
*/
|
|
57
59
|
export const companyNameSpans = (text: string, forms: readonly string[], determiners: readonly string[]): Span[] => {
|
|
58
60
|
if (forms.length === 0) return [];
|
|
59
61
|
const single = `${oneOf(forms)}${EDGE_AFTER}`;
|
|
60
62
|
// 形を重ねて書く(PTE. LTD.、CO.,LTD.)。
|
|
61
|
-
const form = String.raw`${single}(
|
|
62
|
-
const named = new RegExp(String.raw`${EDGE_BEFORE}(?:${NAME_WORD}[ \t]+){0,${NAME_WORDS_MAX - 1}}(?<last>${NAME_WORD})(
|
|
63
|
-
const bracketed = new RegExp(String.raw`(?<=${NAME_WORD}[((][\p{L} ]+[))][ \t]*)${form}`, "gu");
|
|
63
|
+
const form = String.raw`${single}(?:\.?[,,]?[ \t]*${single})*`;
|
|
64
|
+
const named = new RegExp(String.raw`${EDGE_BEFORE}(?:${NAME_WORD}[ \t]+){0,${NAME_WORDS_MAX - 1}}(?<last>${NAME_WORD})(?:[,,][ \t]*|[ \t]+)${form}`, "gu");
|
|
65
|
+
const bracketed = new RegExp(String.raw`(?<=${NAME_WORD}[,,]?[((][\p{L}. ]+[))][ \t]*)${form}`, "gu");
|
|
64
66
|
const determiner = new Set(determiners.map((word) => word.toLowerCase()));
|
|
65
67
|
const names = [...text.matchAll(named)].filter((match) => !determiner.has((match.groups?.["last"] ?? "").toLowerCase()));
|
|
66
68
|
return [...names.map((match) => ({ start: match.index, end: match.index + match[0].length })), ...spansOf(text, bracketed)];
|
|
67
69
|
};
|
|
68
70
|
|
|
71
|
+
/** 日本の会社の名前の英字の語(ADEKA、DOWA)。英字の語と形のあいだに書く名前の続きの片仮名(DOWAホールディングス㈱ の ホールディングス)。 */
|
|
72
|
+
const LATIN_NAME = "[A-Za-zA-Za-z][A-Za-zA-Za-z0-90-9&&]*";
|
|
73
|
+
const KATAKANA_TAIL = "[ァ-ヺー・]*";
|
|
74
|
+
|
|
75
|
+
/** 英字だけの形(英語の Ltd)は英字の語に続けて書かれず、続いて見えれば語の一部。漢字か片仮名を含む形だけを読む。 */
|
|
76
|
+
const NOT_LATIN = /[^\p{Script=Latin}\p{P}\s]/u;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* 日本の会社の形のすぐ後ろの英字の語(㈱ADEKA、株式会社ADEKA)と、片仮名を挟んですぐ前の英字の語(ADEKA株式会社、
|
|
80
|
+
* DOWAホールディングス㈱)。名前の英字で、説明を待つ略語ではない。範囲は英字の語だけ。
|
|
81
|
+
*/
|
|
82
|
+
export const japaneseCompanyNameSpans = (text: string, forms: readonly string[]): Span[] => {
|
|
83
|
+
const japanese = forms.filter((form) => NOT_LATIN.test(form));
|
|
84
|
+
if (japanese.length === 0) return [];
|
|
85
|
+
const form = oneOf(japanese);
|
|
86
|
+
const after = new RegExp(`(?<=${form})${LATIN_NAME}`, "gu");
|
|
87
|
+
const before = new RegExp(`(?<![A-Za-zA-Za-z])${LATIN_NAME}(?=${KATAKANA_TAIL}${form})`, "gu");
|
|
88
|
+
return [...spansOf(text, after), ...spansOf(text, before)];
|
|
89
|
+
};
|
|
90
|
+
|
|
69
91
|
/** 通貨の記号に付けた大文字(USD$、AU$10、US$ 5)。国や通貨の印で、略語ではない。 */
|
|
70
92
|
const CURRENCY_PREFIX = new RegExp(String.raw`${EDGE_BEFORE}\p{Lu}{1,3}(?=[$€£¥])`, "gu");
|
|
71
93
|
|
|
@@ -108,6 +130,7 @@ export const nameSpansOf =
|
|
|
108
130
|
(words: NameWords) =>
|
|
109
131
|
(text: string): Span[] => [
|
|
110
132
|
...companyNameSpans(text, words.legalForms, words.determiners),
|
|
133
|
+
...japaneseCompanyNameSpans(text, words.companyForms),
|
|
111
134
|
...currencySymbolSpans(text),
|
|
112
135
|
...citationSpans(text, words.citationSeries),
|
|
113
136
|
...carrierListSpans(text, words.carriers),
|