chaffjs 0.27.1 → 0.29.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.md +2 -1
- package/dist/ai-score/of-document.d.ts.map +1 -1
- package/dist/ai-score/of-document.js +23 -14
- package/dist/ai-score/of-document.js.map +1 -1
- package/dist/ai-score/render.d.ts.map +1 -1
- package/dist/ai-score/render.js +13 -4
- package/dist/ai-score/render.js.map +1 -1
- package/dist/ai-score/score.d.ts +16 -1
- package/dist/ai-score/score.d.ts.map +1 -1
- package/dist/ai-score/score.js +15 -3
- package/dist/ai-score/score.js.map +1 -1
- package/dist/ai-score/signals.d.ts +2 -4
- package/dist/ai-score/signals.d.ts.map +1 -1
- package/dist/ai-score/signals.js +11 -2
- package/dist/ai-score/signals.js.map +1 -1
- package/dist/ai-score/text.d.ts +2 -0
- package/dist/ai-score/text.d.ts.map +1 -1
- package/dist/ai-score/text.js +4 -2
- package/dist/ai-score/text.js.map +1 -1
- package/dist/announced-count.d.ts +2 -0
- package/dist/announced-count.d.ts.map +1 -1
- package/dist/announced-count.js +14 -7
- package/dist/announced-count.js.map +1 -1
- package/dist/check-source.d.ts +3 -1
- package/dist/check-source.d.ts.map +1 -1
- package/dist/check-source.js +3 -1
- package/dist/check-source.js.map +1 -1
- package/dist/cli-text.d.ts.map +1 -1
- package/dist/cli-text.js +42 -18
- package/dist/cli-text.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +2 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/cite-claims.d.ts +36 -0
- package/dist/commands/cite-claims.d.ts.map +1 -0
- package/dist/commands/cite-claims.js +81 -0
- package/dist/commands/cite-claims.js.map +1 -0
- package/dist/commands/cite-page.d.ts +14 -0
- package/dist/commands/cite-page.d.ts.map +1 -0
- package/dist/commands/cite-page.js +47 -0
- package/dist/commands/cite-page.js.map +1 -0
- package/dist/commands/cite-scaffold.d.ts +16 -0
- package/dist/commands/cite-scaffold.d.ts.map +1 -0
- package/dist/commands/cite-scaffold.js +21 -0
- package/dist/commands/cite-scaffold.js.map +1 -0
- package/dist/commands/cite.d.ts +3 -12
- package/dist/commands/cite.d.ts.map +1 -1
- package/dist/commands/cite.js +110 -51
- package/dist/commands/cite.js.map +1 -1
- package/dist/company-names.d.ts +34 -0
- package/dist/company-names.d.ts.map +1 -0
- package/dist/company-names.js +158 -0
- package/dist/company-names.js.map +1 -0
- package/dist/default-values.d.ts +17 -0
- package/dist/default-values.d.ts.map +1 -0
- package/dist/default-values.js +134 -0
- package/dist/default-values.js.map +1 -0
- package/dist/deprecated-use.d.ts +17 -0
- package/dist/deprecated-use.d.ts.map +1 -0
- package/dist/deprecated-use.js +95 -0
- package/dist/deprecated-use.js.map +1 -0
- package/dist/derived/number-word-counts.d.ts +10 -0
- package/dist/derived/number-word-counts.d.ts.map +1 -0
- package/dist/derived/number-word-counts.js +21 -0
- package/dist/derived/number-word-counts.js.map +1 -0
- package/dist/derived/stays.d.ts +43 -0
- package/dist/derived/stays.d.ts.map +1 -0
- package/dist/derived/stays.js +105 -0
- package/dist/derived/stays.js.map +1 -0
- package/dist/detectors/acronym-context.d.ts +2 -2
- package/dist/detectors/acronym-context.d.ts.map +1 -1
- package/dist/detectors/acronym-context.js +6 -0
- package/dist/detectors/acronym-context.js.map +1 -1
- package/dist/detectors/address-word.d.ts +3 -0
- package/dist/detectors/address-word.d.ts.map +1 -0
- package/dist/detectors/address-word.js +7 -0
- package/dist/detectors/address-word.js.map +1 -0
- package/dist/detectors/agreement-slip.d.ts.map +1 -1
- package/dist/detectors/agreement-slip.js +4 -1
- package/dist/detectors/agreement-slip.js.map +1 -1
- package/dist/detectors/ai-phrasing.d.ts +0 -4
- package/dist/detectors/ai-phrasing.d.ts.map +1 -1
- package/dist/detectors/ai-phrasing.js +5 -1
- package/dist/detectors/ai-phrasing.js.map +1 -1
- package/dist/detectors/amount-range.d.ts +3 -0
- package/dist/detectors/amount-range.d.ts.map +1 -0
- package/dist/detectors/amount-range.js +38 -0
- package/dist/detectors/amount-range.js.map +1 -0
- package/dist/detectors/amount-scale.d.ts +8 -0
- package/dist/detectors/amount-scale.d.ts.map +1 -0
- package/dist/detectors/amount-scale.js +74 -0
- package/dist/detectors/amount-scale.js.map +1 -0
- package/dist/detectors/announced-count.d.ts +1 -1
- package/dist/detectors/announced-count.d.ts.map +1 -1
- package/dist/detectors/announced-count.js +18 -3
- package/dist/detectors/announced-count.js.map +1 -1
- package/dist/detectors/bare-comparative.d.ts.map +1 -1
- package/dist/detectors/bare-comparative.js +4 -1
- package/dist/detectors/bare-comparative.js.map +1 -1
- package/dist/detectors/block-quotation.d.ts +13 -0
- package/dist/detectors/block-quotation.d.ts.map +1 -0
- package/dist/detectors/block-quotation.js +86 -0
- package/dist/detectors/block-quotation.js.map +1 -0
- package/dist/detectors/bracket-label.d.ts +10 -0
- package/dist/detectors/bracket-label.d.ts.map +1 -0
- package/dist/detectors/bracket-label.js +51 -0
- package/dist/detectors/bracket-label.js.map +1 -0
- package/dist/detectors/change-rate.d.ts.map +1 -1
- package/dist/detectors/change-rate.js +12 -1
- package/dist/detectors/change-rate.js.map +1 -1
- package/dist/detectors/citation-entry.d.ts +5 -0
- package/dist/detectors/citation-entry.d.ts.map +1 -1
- package/dist/detectors/citation-entry.js +19 -5
- package/dist/detectors/citation-entry.js.map +1 -1
- package/dist/detectors/code-before.d.ts +6 -0
- package/dist/detectors/code-before.d.ts.map +1 -0
- package/dist/detectors/code-before.js +15 -0
- package/dist/detectors/code-before.js.map +1 -0
- package/dist/detectors/connective-hierarchy.d.ts +11 -1
- package/dist/detectors/connective-hierarchy.d.ts.map +1 -1
- package/dist/detectors/connective-hierarchy.js +26 -6
- package/dist/detectors/connective-hierarchy.js.map +1 -1
- package/dist/detectors/currency-notation.d.ts +3 -1
- package/dist/detectors/currency-notation.d.ts.map +1 -1
- package/dist/detectors/currency-notation.js +4 -3
- package/dist/detectors/currency-notation.js.map +1 -1
- package/dist/detectors/date-outside-period.d.ts +4 -0
- package/dist/detectors/date-outside-period.d.ts.map +1 -0
- package/dist/detectors/date-outside-period.js +34 -0
- package/dist/detectors/date-outside-period.js.map +1 -0
- package/dist/detectors/default-values.d.ts +3 -0
- package/dist/detectors/default-values.d.ts.map +1 -0
- package/dist/detectors/default-values.js +14 -0
- package/dist/detectors/default-values.js.map +1 -0
- package/dist/detectors/defined-term-form.d.ts +6 -2
- package/dist/detectors/defined-term-form.d.ts.map +1 -1
- package/dist/detectors/defined-term-form.js +72 -12
- 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 +8 -1
- package/dist/detectors/definition-use.js.map +1 -1
- package/dist/detectors/deprecated-use.d.ts +3 -0
- package/dist/detectors/deprecated-use.d.ts.map +1 -0
- package/dist/detectors/deprecated-use.js +14 -0
- package/dist/detectors/deprecated-use.js.map +1 -0
- package/dist/detectors/derived-numbers.d.ts +1 -1
- package/dist/detectors/derived-numbers.d.ts.map +1 -1
- package/dist/detectors/derived-numbers.js +79 -16
- package/dist/detectors/derived-numbers.js.map +1 -1
- package/dist/detectors/document-shape.d.ts +1 -0
- package/dist/detectors/document-shape.d.ts.map +1 -1
- package/dist/detectors/document-shape.js +4 -1
- package/dist/detectors/document-shape.js.map +1 -1
- package/dist/detectors/due-date.d.ts +3 -0
- package/dist/detectors/due-date.d.ts.map +1 -0
- package/dist/detectors/due-date.js +38 -0
- package/dist/detectors/due-date.js.map +1 -0
- package/dist/detectors/en-shape.d.ts.map +1 -1
- package/dist/detectors/en-shape.js +17 -9
- package/dist/detectors/en-shape.js.map +1 -1
- package/dist/detectors/fact-consistency.d.ts.map +1 -1
- package/dist/detectors/fact-consistency.js +89 -2
- package/dist/detectors/fact-consistency.js.map +1 -1
- package/dist/detectors/heading-echo.d.ts.map +1 -1
- package/dist/detectors/heading-echo.js +10 -1
- package/dist/detectors/heading-echo.js.map +1 -1
- package/dist/detectors/kana-function-word.d.ts +12 -0
- package/dist/detectors/kana-function-word.d.ts.map +1 -0
- package/dist/detectors/kana-function-word.js +59 -0
- package/dist/detectors/kana-function-word.js.map +1 -0
- package/dist/detectors/line-amount.d.ts +3 -0
- package/dist/detectors/line-amount.d.ts.map +1 -0
- package/dist/detectors/line-amount.js +22 -0
- package/dist/detectors/line-amount.js.map +1 -0
- package/dist/detectors/location-pointer.d.ts +6 -0
- package/dist/detectors/location-pointer.d.ts.map +1 -0
- package/dist/detectors/location-pointer.js +22 -0
- package/dist/detectors/location-pointer.js.map +1 -0
- package/dist/detectors/mark-shape.d.ts.map +1 -1
- package/dist/detectors/mark-shape.js +13 -1
- package/dist/detectors/mark-shape.js.map +1 -1
- package/dist/detectors/nado-closed-list.d.ts +3 -0
- package/dist/detectors/nado-closed-list.d.ts.map +1 -0
- package/dist/detectors/nado-closed-list.js +21 -0
- package/dist/detectors/nado-closed-list.js.map +1 -0
- package/dist/detectors/name-variant.d.ts.map +1 -1
- package/dist/detectors/name-variant.js +92 -10
- package/dist/detectors/name-variant.js.map +1 -1
- package/dist/detectors/next-word.d.ts.map +1 -1
- package/dist/detectors/next-word.js +41 -8
- package/dist/detectors/next-word.js.map +1 -1
- package/dist/detectors/number-word-figure.d.ts +5 -0
- package/dist/detectors/number-word-figure.d.ts.map +1 -0
- package/dist/detectors/number-word-figure.js +32 -0
- package/dist/detectors/number-word-figure.js.map +1 -0
- package/dist/detectors/obligation-without-deadline.d.ts +39 -0
- package/dist/detectors/obligation-without-deadline.d.ts.map +1 -0
- package/dist/detectors/obligation-without-deadline.js +148 -0
- package/dist/detectors/obligation-without-deadline.js.map +1 -0
- package/dist/detectors/open-end-names.d.ts +23 -0
- package/dist/detectors/open-end-names.d.ts.map +1 -0
- package/dist/detectors/open-end-names.js +95 -0
- package/dist/detectors/open-end-names.js.map +1 -0
- package/dist/detectors/ordinal-run-gaps.d.ts +8 -0
- package/dist/detectors/ordinal-run-gaps.d.ts.map +1 -0
- package/dist/detectors/ordinal-run-gaps.js +80 -0
- package/dist/detectors/ordinal-run-gaps.js.map +1 -0
- package/dist/detectors/orthographic-variant.d.ts.map +1 -1
- package/dist/detectors/orthographic-variant.js +26 -9
- package/dist/detectors/orthographic-variant.js.map +1 -1
- package/dist/detectors/orthography.d.ts.map +1 -1
- package/dist/detectors/orthography.js +5 -0
- package/dist/detectors/orthography.js.map +1 -1
- package/dist/detectors/parameter-table.d.ts +3 -0
- package/dist/detectors/parameter-table.d.ts.map +1 -0
- package/dist/detectors/parameter-table.js +16 -0
- package/dist/detectors/parameter-table.js.map +1 -0
- package/dist/detectors/phone-number-variant.d.ts +3 -0
- package/dist/detectors/phone-number-variant.d.ts.map +1 -0
- package/dist/detectors/phone-number-variant.js +18 -0
- package/dist/detectors/phone-number-variant.js.map +1 -0
- package/dist/detectors/prerequisite-order.d.ts +3 -0
- package/dist/detectors/prerequisite-order.d.ts.map +1 -0
- package/dist/detectors/prerequisite-order.js +30 -0
- package/dist/detectors/prerequisite-order.js.map +1 -0
- package/dist/detectors/quote-unnamed-speaker.d.ts +3 -0
- package/dist/detectors/quote-unnamed-speaker.d.ts.map +1 -0
- package/dist/detectors/quote-unnamed-speaker.js +18 -0
- package/dist/detectors/quote-unnamed-speaker.js.map +1 -0
- package/dist/detectors/quote-without-source.d.ts +12 -2
- package/dist/detectors/quote-without-source.d.ts.map +1 -1
- package/dist/detectors/quote-without-source.js +45 -11
- package/dist/detectors/quote-without-source.js.map +1 -1
- package/dist/detectors/registry/amount-range.d.ts +3 -0
- package/dist/detectors/registry/amount-range.d.ts.map +1 -0
- package/dist/detectors/registry/amount-range.js +3 -0
- package/dist/detectors/registry/amount-range.js.map +1 -0
- package/dist/detectors/registry/amount-scale.d.ts +3 -0
- package/dist/detectors/registry/amount-scale.d.ts.map +1 -0
- package/dist/detectors/registry/amount-scale.js +3 -0
- package/dist/detectors/registry/amount-scale.js.map +1 -0
- package/dist/detectors/registry/arrival-before-departure.d.ts +3 -0
- package/dist/detectors/registry/arrival-before-departure.d.ts.map +1 -0
- package/dist/detectors/registry/arrival-before-departure.js +3 -0
- package/dist/detectors/registry/arrival-before-departure.js.map +1 -0
- package/dist/detectors/registry/date-outside-period.d.ts +3 -0
- package/dist/detectors/registry/date-outside-period.d.ts.map +1 -0
- package/dist/detectors/registry/date-outside-period.js +3 -0
- package/dist/detectors/registry/date-outside-period.js.map +1 -0
- package/dist/detectors/registry/default-values.d.ts +3 -0
- package/dist/detectors/registry/default-values.d.ts.map +1 -0
- package/dist/detectors/registry/default-values.js +3 -0
- package/dist/detectors/registry/default-values.js.map +1 -0
- package/dist/detectors/registry/deprecated-use.d.ts +3 -0
- package/dist/detectors/registry/deprecated-use.d.ts.map +1 -0
- package/dist/detectors/registry/deprecated-use.js +3 -0
- package/dist/detectors/registry/deprecated-use.js.map +1 -0
- package/dist/detectors/registry/due-date.d.ts +3 -0
- package/dist/detectors/registry/due-date.d.ts.map +1 -0
- package/dist/detectors/registry/due-date.js +3 -0
- package/dist/detectors/registry/due-date.js.map +1 -0
- package/dist/detectors/registry/kana-function-word.d.ts +3 -0
- package/dist/detectors/registry/kana-function-word.d.ts.map +1 -0
- package/dist/detectors/registry/kana-function-word.js +3 -0
- package/dist/detectors/registry/kana-function-word.js.map +1 -0
- package/dist/detectors/registry/line-amount.d.ts +3 -0
- package/dist/detectors/registry/line-amount.d.ts.map +1 -0
- package/dist/detectors/registry/line-amount.js +3 -0
- package/dist/detectors/registry/line-amount.js.map +1 -0
- package/dist/detectors/registry/nado-closed-list.d.ts +3 -0
- package/dist/detectors/registry/nado-closed-list.d.ts.map +1 -0
- package/dist/detectors/registry/nado-closed-list.js +3 -0
- package/dist/detectors/registry/nado-closed-list.js.map +1 -0
- package/dist/detectors/registry/number-word-figure.d.ts +3 -0
- package/dist/detectors/registry/number-word-figure.d.ts.map +1 -0
- package/dist/detectors/registry/number-word-figure.js +3 -0
- package/dist/detectors/registry/number-word-figure.js.map +1 -0
- package/dist/detectors/registry/obligation-without-deadline.d.ts +3 -0
- package/dist/detectors/registry/obligation-without-deadline.d.ts.map +1 -0
- package/dist/detectors/registry/obligation-without-deadline.js +3 -0
- package/dist/detectors/registry/obligation-without-deadline.js.map +1 -0
- package/dist/detectors/registry/parameter-table.d.ts +3 -0
- package/dist/detectors/registry/parameter-table.d.ts.map +1 -0
- package/dist/detectors/registry/parameter-table.js +3 -0
- package/dist/detectors/registry/parameter-table.js.map +1 -0
- package/dist/detectors/registry/phone-number-variant.d.ts +3 -0
- package/dist/detectors/registry/phone-number-variant.d.ts.map +1 -0
- package/dist/detectors/registry/phone-number-variant.js +3 -0
- package/dist/detectors/registry/phone-number-variant.js.map +1 -0
- package/dist/detectors/registry/prerequisite-order.d.ts +3 -0
- package/dist/detectors/registry/prerequisite-order.d.ts.map +1 -0
- package/dist/detectors/registry/prerequisite-order.js +3 -0
- package/dist/detectors/registry/prerequisite-order.js.map +1 -0
- package/dist/detectors/registry/quote-unnamed-speaker.d.ts +3 -0
- package/dist/detectors/registry/quote-unnamed-speaker.d.ts.map +1 -0
- package/dist/detectors/registry/quote-unnamed-speaker.js +3 -0
- package/dist/detectors/registry/quote-unnamed-speaker.js.map +1 -0
- package/dist/detectors/registry/tax-amount.d.ts +3 -0
- package/dist/detectors/registry/tax-amount.d.ts.map +1 -0
- package/dist/detectors/registry/tax-amount.js +3 -0
- package/dist/detectors/registry/tax-amount.js.map +1 -0
- package/dist/detectors/registry/time-order.d.ts +3 -0
- package/dist/detectors/registry/time-order.d.ts.map +1 -0
- package/dist/detectors/registry/time-order.js +3 -0
- package/dist/detectors/registry/time-order.js.map +1 -0
- package/dist/detectors/registry/ui-label.d.ts +3 -0
- package/dist/detectors/registry/ui-label.d.ts.map +1 -0
- package/dist/detectors/registry/ui-label.js +3 -0
- package/dist/detectors/registry/ui-label.js.map +1 -0
- package/dist/detectors/registry/undefined-call.d.ts +3 -0
- package/dist/detectors/registry/undefined-call.d.ts.map +1 -0
- package/dist/detectors/registry/undefined-call.js +3 -0
- package/dist/detectors/registry/undefined-call.js.map +1 -0
- package/dist/detectors/registry/undefined-term.d.ts +3 -0
- package/dist/detectors/registry/undefined-term.d.ts.map +1 -0
- package/dist/detectors/registry/undefined-term.js +3 -0
- package/dist/detectors/registry/undefined-term.js.map +1 -0
- package/dist/detectors/registry/version-order.d.ts +3 -0
- package/dist/detectors/registry/version-order.d.ts.map +1 -0
- package/dist/detectors/registry/version-order.js +3 -0
- package/dist/detectors/registry/version-order.js.map +1 -0
- package/dist/detectors/registry/warning-action.d.ts +3 -0
- package/dist/detectors/registry/warning-action.d.ts.map +1 -0
- package/dist/detectors/registry/warning-action.js +3 -0
- package/dist/detectors/registry/warning-action.js.map +1 -0
- package/dist/detectors/requirement-smell.d.ts.map +1 -1
- package/dist/detectors/requirement-smell.js +25 -8
- package/dist/detectors/requirement-smell.js.map +1 -1
- package/dist/detectors/structure-tree.d.ts +12 -4
- package/dist/detectors/structure-tree.d.ts.map +1 -1
- package/dist/detectors/structure-tree.js +31 -14
- package/dist/detectors/structure-tree.js.map +1 -1
- package/dist/detectors/superlative-scope.d.ts.map +1 -1
- package/dist/detectors/superlative-scope.js +11 -1
- package/dist/detectors/superlative-scope.js.map +1 -1
- package/dist/detectors/tax-amount.d.ts +3 -0
- package/dist/detectors/tax-amount.d.ts.map +1 -0
- package/dist/detectors/tax-amount.js +19 -0
- package/dist/detectors/tax-amount.js.map +1 -0
- package/dist/detectors/technical-docs.d.ts.map +1 -1
- package/dist/detectors/technical-docs.js +5 -1
- package/dist/detectors/technical-docs.js.map +1 -1
- package/dist/detectors/term-extension.d.ts +14 -0
- package/dist/detectors/term-extension.d.ts.map +1 -0
- package/dist/detectors/term-extension.js +67 -0
- package/dist/detectors/term-extension.js.map +1 -0
- package/dist/detectors/time-order.d.ts +4 -0
- package/dist/detectors/time-order.d.ts.map +1 -0
- package/dist/detectors/time-order.js +32 -0
- package/dist/detectors/time-order.js.map +1 -0
- package/dist/detectors/ui-label.d.ts +3 -0
- package/dist/detectors/ui-label.d.ts.map +1 -0
- package/dist/detectors/ui-label.js +16 -0
- package/dist/detectors/ui-label.js.map +1 -0
- package/dist/detectors/unbalanced-bracket.d.ts.map +1 -1
- package/dist/detectors/unbalanced-bracket.js +8 -13
- package/dist/detectors/unbalanced-bracket.js.map +1 -1
- package/dist/detectors/undefined-call.d.ts +3 -0
- package/dist/detectors/undefined-call.d.ts.map +1 -0
- package/dist/detectors/undefined-call.js +18 -0
- package/dist/detectors/undefined-call.js.map +1 -0
- package/dist/detectors/undefined-term.d.ts +22 -0
- package/dist/detectors/undefined-term.d.ts.map +1 -0
- package/dist/detectors/undefined-term.js +85 -0
- package/dist/detectors/undefined-term.js.map +1 -0
- package/dist/detectors/unknown-word.d.ts +1 -1
- package/dist/detectors/unknown-word.js +3 -3
- package/dist/detectors/unknown-word.js.map +1 -1
- package/dist/detectors/vague-deadline.d.ts +4 -0
- package/dist/detectors/vague-deadline.d.ts.map +1 -1
- package/dist/detectors/vague-deadline.js +3 -3
- package/dist/detectors/vague-deadline.js.map +1 -1
- package/dist/detectors/version-mismatch.d.ts.map +1 -1
- package/dist/detectors/version-mismatch.js +18 -1
- package/dist/detectors/version-mismatch.js.map +1 -1
- package/dist/detectors/version-order.d.ts +3 -0
- package/dist/detectors/version-order.d.ts.map +1 -0
- package/dist/detectors/version-order.js +43 -0
- package/dist/detectors/version-order.js.map +1 -0
- package/dist/detectors/warning-action.d.ts +3 -0
- package/dist/detectors/warning-action.d.ts.map +1 -0
- package/dist/detectors/warning-action.js +48 -0
- package/dist/detectors/warning-action.js.map +1 -0
- package/dist/facts/condition-pairs.d.ts +51 -0
- package/dist/facts/condition-pairs.d.ts.map +1 -0
- package/dist/facts/condition-pairs.js +203 -0
- package/dist/facts/condition-pairs.js.map +1 -0
- package/dist/facts/counted-facts.d.ts +16 -0
- package/dist/facts/counted-facts.d.ts.map +1 -0
- package/dist/facts/counted-facts.js +45 -0
- package/dist/facts/counted-facts.js.map +1 -0
- package/dist/facts/event-dates.d.ts +26 -0
- package/dist/facts/event-dates.d.ts.map +1 -0
- package/dist/facts/event-dates.js +38 -0
- package/dist/facts/event-dates.js.map +1 -0
- package/dist/facts/fact-scope.d.ts +2 -0
- package/dist/facts/fact-scope.d.ts.map +1 -1
- package/dist/facts/fact-scope.js +5 -0
- package/dist/facts/fact-scope.js.map +1 -1
- package/dist/facts/labelled-facts.d.ts +2 -0
- package/dist/facts/labelled-facts.d.ts.map +1 -1
- package/dist/facts/labelled-facts.js +9 -1
- package/dist/facts/labelled-facts.js.map +1 -1
- package/dist/facts/table-facts.d.ts +16 -0
- package/dist/facts/table-facts.d.ts.map +1 -1
- package/dist/facts/table-facts.js +2 -2
- package/dist/facts/table-facts.js.map +1 -1
- package/dist/grade/ai-score.d.ts +1 -1
- package/dist/grade/ai-score.d.ts.map +1 -1
- package/dist/grade/text.js +2 -2
- package/dist/grade/text.js.map +1 -1
- package/dist/heading-numbering.js +2 -2
- package/dist/heading-numbering.js.map +1 -1
- package/dist/html/fetch-page.d.ts +20 -0
- package/dist/html/fetch-page.d.ts.map +1 -0
- package/dist/html/fetch-page.js +51 -0
- package/dist/html/fetch-page.js.map +1 -0
- package/dist/html/fetched-text.d.ts +5 -0
- package/dist/html/fetched-text.d.ts.map +1 -0
- package/dist/html/fetched-text.js +25 -0
- package/dist/html/fetched-text.js.map +1 -0
- package/dist/html/html-content-block.d.ts +6 -0
- package/dist/html/html-content-block.d.ts.map +1 -0
- package/dist/html/html-content-block.js +86 -0
- package/dist/html/html-content-block.js.map +1 -0
- package/dist/html/html-elements.d.ts +41 -0
- package/dist/html/html-elements.d.ts.map +1 -0
- package/dist/html/html-elements.js +91 -0
- package/dist/html/html-elements.js.map +1 -0
- package/dist/html/html-footnote-marks.d.ts +2 -0
- package/dist/html/html-footnote-marks.d.ts.map +1 -0
- package/dist/html/html-footnote-marks.js +15 -0
- package/dist/html/html-footnote-marks.js.map +1 -0
- package/dist/html/html-heading-links.d.ts +6 -0
- package/dist/html/html-heading-links.d.ts.map +1 -0
- package/dist/html/html-heading-links.js +71 -0
- package/dist/html/html-heading-links.js.map +1 -0
- package/dist/html/html-lost-tags.d.ts +3 -0
- package/dist/html/html-lost-tags.d.ts.map +1 -0
- package/dist/html/html-lost-tags.js +11 -0
- package/dist/html/html-lost-tags.js.map +1 -0
- package/dist/html/html-markdown.d.ts +2 -0
- package/dist/html/html-markdown.d.ts.map +1 -0
- package/dist/html/html-markdown.js +347 -0
- package/dist/html/html-markdown.js.map +1 -0
- package/dist/html/html-preformatted.d.ts +17 -0
- package/dist/html/html-preformatted.d.ts.map +1 -0
- package/dist/html/html-preformatted.js +82 -0
- package/dist/html/html-preformatted.js.map +1 -0
- package/dist/html/html-reader-only.d.ts +6 -0
- package/dist/html/html-reader-only.d.ts.map +1 -0
- package/dist/html/html-reader-only.js +63 -0
- package/dist/html/html-reader-only.js.map +1 -0
- package/dist/html/html-run-in-headings.d.ts +2 -0
- package/dist/html/html-run-in-headings.d.ts.map +1 -0
- package/dist/html/html-run-in-headings.js +36 -0
- package/dist/html/html-run-in-headings.js.map +1 -0
- package/dist/html/html-tables.d.ts +3 -0
- package/dist/html/html-tables.d.ts.map +1 -0
- package/dist/html/html-tables.js +58 -0
- package/dist/html/html-tables.js.map +1 -0
- package/dist/html/html-widgets.d.ts +3 -0
- package/dist/html/html-widgets.d.ts.map +1 -0
- package/dist/html/html-widgets.js +71 -0
- package/dist/html/html-widgets.js.map +1 -0
- package/dist/html/markup-text.d.ts +5 -0
- package/dist/html/markup-text.d.ts.map +1 -0
- package/dist/html/markup-text.js +32 -0
- package/dist/html/markup-text.js.map +1 -0
- package/dist/html/page-document.d.ts +9 -0
- package/dist/html/page-document.d.ts.map +1 -0
- package/dist/html/page-document.js +19 -0
- package/dist/html/page-document.js.map +1 -0
- package/dist/inline-count.d.ts +19 -0
- package/dist/inline-count.d.ts.map +1 -0
- package/dist/inline-count.js +109 -0
- package/dist/inline-count.js.map +1 -0
- package/dist/kana-spelling.d.ts +5 -0
- package/dist/kana-spelling.d.ts.map +1 -1
- package/dist/kana-spelling.js +5 -0
- package/dist/kana-spelling.js.map +1 -1
- package/dist/location-part.d.ts +13 -0
- package/dist/location-part.d.ts.map +1 -0
- package/dist/location-part.js +24 -0
- package/dist/location-part.js.map +1 -0
- package/dist/nado-closed-list.d.ts +20 -0
- package/dist/nado-closed-list.d.ts.map +1 -0
- package/dist/nado-closed-list.js +72 -0
- package/dist/nado-closed-list.js.map +1 -0
- package/dist/name-cue.d.ts +17 -0
- package/dist/name-cue.d.ts.map +1 -0
- package/dist/name-cue.js +29 -0
- package/dist/name-cue.js.map +1 -0
- package/dist/name-variants.d.ts +41 -5
- package/dist/name-variants.d.ts.map +1 -1
- package/dist/name-variants.js +93 -8
- package/dist/name-variants.js.map +1 -1
- package/dist/paragraph-runs.d.ts +6 -1
- package/dist/paragraph-runs.d.ts.map +1 -1
- package/dist/paragraph-runs.js +9 -2
- package/dist/paragraph-runs.js.map +1 -1
- package/dist/parameter-table.d.ts +19 -0
- package/dist/parameter-table.d.ts.map +1 -0
- package/dist/parameter-table.js +191 -0
- package/dist/parameter-table.js.map +1 -0
- package/dist/phone-numbers.d.ts +23 -0
- package/dist/phone-numbers.d.ts.map +1 -0
- package/dist/phone-numbers.js +83 -0
- package/dist/phone-numbers.js.map +1 -0
- package/dist/place-names.d.ts +55 -0
- package/dist/place-names.d.ts.map +1 -0
- package/dist/place-names.js +196 -0
- package/dist/place-names.js.map +1 -0
- package/dist/plugin.d.ts +4 -0
- package/dist/plugin.d.ts.map +1 -1
- package/dist/prerequisite-order.d.ts +16 -0
- package/dist/prerequisite-order.d.ts.map +1 -0
- package/dist/prerequisite-order.js +29 -0
- package/dist/prerequisite-order.js.map +1 -0
- package/dist/profile/parse.d.ts.map +1 -1
- package/dist/profile/parse.js +10 -1
- package/dist/profile/parse.js.map +1 -1
- package/dist/reasons.d.ts +2 -0
- package/dist/reasons.d.ts.map +1 -1
- package/dist/reasons.js +2 -0
- package/dist/reasons.js.map +1 -1
- package/dist/render/rules-json.d.ts.map +1 -1
- package/dist/render/rules-json.js +4 -0
- package/dist/render/rules-json.js.map +1 -1
- package/dist/render/rules-table.d.ts.map +1 -1
- package/dist/render/rules-table.js +6 -2
- package/dist/render/rules-table.js.map +1 -1
- package/dist/rule-genres.d.ts +5 -2
- package/dist/rule-genres.d.ts.map +1 -1
- package/dist/rule-genres.js +2 -0
- package/dist/rule-genres.js.map +1 -1
- package/dist/rule-load.d.ts.map +1 -1
- package/dist/rule-load.js +2 -1
- package/dist/rule-load.js.map +1 -1
- package/dist/run.d.ts.map +1 -1
- package/dist/run.js +5 -1
- package/dist/run.js.map +1 -1
- package/dist/spelling.d.ts +2 -0
- package/dist/spelling.d.ts.map +1 -1
- package/dist/spelling.js +6 -0
- package/dist/spelling.js.map +1 -1
- package/dist/structure/action-due.d.ts +21 -0
- package/dist/structure/action-due.d.ts.map +1 -0
- package/dist/structure/action-due.js +126 -0
- package/dist/structure/action-due.js.map +1 -0
- package/dist/structure/amount-range.d.ts +30 -0
- package/dist/structure/amount-range.d.ts.map +1 -0
- package/dist/structure/amount-range.js +153 -0
- package/dist/structure/amount-range.js.map +1 -0
- package/dist/structure/amount-scale.d.ts +35 -0
- package/dist/structure/amount-scale.d.ts.map +1 -0
- package/dist/structure/amount-scale.js +83 -0
- package/dist/structure/amount-scale.js.map +1 -0
- package/dist/structure/cite.d.ts +5 -2
- package/dist/structure/cite.d.ts.map +1 -1
- package/dist/structure/cite.js +20 -1
- package/dist/structure/cite.js.map +1 -1
- package/dist/structure/counted-amounts.d.ts +12 -0
- package/dist/structure/counted-amounts.d.ts.map +1 -0
- package/dist/structure/counted-amounts.js +30 -0
- package/dist/structure/counted-amounts.js.map +1 -0
- package/dist/structure/date-order.d.ts +24 -3
- package/dist/structure/date-order.d.ts.map +1 -1
- package/dist/structure/date-order.js +49 -17
- package/dist/structure/date-order.js.map +1 -1
- package/dist/structure/date-outside-period.d.ts +27 -0
- package/dist/structure/date-outside-period.d.ts.map +1 -0
- package/dist/structure/date-outside-period.js +86 -0
- package/dist/structure/date-outside-period.js.map +1 -0
- package/dist/structure/definition-use.d.ts +5 -2
- package/dist/structure/definition-use.d.ts.map +1 -1
- package/dist/structure/definition-use.js +11 -3
- package/dist/structure/definition-use.js.map +1 -1
- package/dist/structure/due-date.d.ts +19 -0
- package/dist/structure/due-date.d.ts.map +1 -0
- package/dist/structure/due-date.js +30 -0
- package/dist/structure/due-date.js.map +1 -0
- package/dist/structure/heading-runs.d.ts +9 -0
- package/dist/structure/heading-runs.d.ts.map +1 -0
- package/dist/structure/heading-runs.js +23 -0
- package/dist/structure/heading-runs.js.map +1 -0
- package/dist/structure/install-pin.d.ts +46 -0
- package/dist/structure/install-pin.d.ts.map +1 -0
- package/dist/structure/install-pin.js +85 -0
- package/dist/structure/install-pin.js.map +1 -0
- package/dist/structure/leg-times.d.ts +34 -0
- package/dist/structure/leg-times.d.ts.map +1 -0
- package/dist/structure/leg-times.js +135 -0
- package/dist/structure/leg-times.js.map +1 -0
- package/dist/structure/line-amount-unit.d.ts +24 -0
- package/dist/structure/line-amount-unit.d.ts.map +1 -0
- package/dist/structure/line-amount-unit.js +24 -0
- package/dist/structure/line-amount-unit.js.map +1 -0
- package/dist/structure/line-amount.d.ts +40 -0
- package/dist/structure/line-amount.d.ts.map +1 -0
- package/dist/structure/line-amount.js +118 -0
- package/dist/structure/line-amount.js.map +1 -0
- package/dist/structure/number-word-figure.d.ts +37 -0
- package/dist/structure/number-word-figure.d.ts.map +1 -0
- package/dist/structure/number-word-figure.js +151 -0
- package/dist/structure/number-word-figure.js.map +1 -0
- package/dist/structure/numbering.d.ts +1 -0
- package/dist/structure/numbering.d.ts.map +1 -1
- package/dist/structure/numbering.js +3 -0
- package/dist/structure/numbering.js.map +1 -1
- package/dist/structure/ordinal-runs.d.ts +45 -0
- package/dist/structure/ordinal-runs.d.ts.map +1 -0
- package/dist/structure/ordinal-runs.js +78 -0
- package/dist/structure/ordinal-runs.js.map +1 -0
- package/dist/structure/percent-sum-prose.d.ts +1 -1
- package/dist/structure/percent-sum-prose.d.ts.map +1 -1
- package/dist/structure/percent-sum-prose.js +45 -3
- package/dist/structure/percent-sum-prose.js.map +1 -1
- package/dist/structure/percent-sum.d.ts +8 -0
- package/dist/structure/percent-sum.d.ts.map +1 -1
- package/dist/structure/percent-sum.js +8 -1
- package/dist/structure/percent-sum.js.map +1 -1
- package/dist/structure/release-list.d.ts +9 -0
- package/dist/structure/release-list.d.ts.map +1 -0
- package/dist/structure/release-list.js +46 -0
- package/dist/structure/release-list.js.map +1 -0
- package/dist/structure/share-column.d.ts +7 -0
- package/dist/structure/share-column.d.ts.map +1 -0
- package/dist/structure/share-column.js +22 -0
- package/dist/structure/share-column.js.map +1 -0
- package/dist/structure/stated-period.d.ts +31 -0
- package/dist/structure/stated-period.d.ts.map +1 -0
- package/dist/structure/stated-period.js +127 -0
- package/dist/structure/stated-period.js.map +1 -0
- package/dist/structure/subject-change.d.ts +8 -0
- package/dist/structure/subject-change.d.ts.map +1 -0
- package/dist/structure/subject-change.js +31 -0
- package/dist/structure/subject-change.js.map +1 -0
- package/dist/structure/tax.d.ts +25 -0
- package/dist/structure/tax.d.ts.map +1 -0
- package/dist/structure/tax.js +86 -0
- package/dist/structure/tax.js.map +1 -0
- package/dist/structure/time-marks.d.ts +58 -0
- package/dist/structure/time-marks.d.ts.map +1 -0
- package/dist/structure/time-marks.js +74 -0
- package/dist/structure/time-marks.js.map +1 -0
- package/dist/structure/time-order.d.ts +21 -0
- package/dist/structure/time-order.d.ts.map +1 -0
- package/dist/structure/time-order.js +108 -0
- package/dist/structure/time-order.js.map +1 -0
- package/dist/structure/title-lines.d.ts +8 -0
- package/dist/structure/title-lines.d.ts.map +1 -0
- package/dist/structure/title-lines.js +27 -0
- package/dist/structure/title-lines.js.map +1 -0
- package/dist/structure/total.d.ts.map +1 -1
- package/dist/structure/total.js +3 -1
- package/dist/structure/total.js.map +1 -1
- package/dist/structure/version-mismatch.d.ts +1 -5
- package/dist/structure/version-mismatch.d.ts.map +1 -1
- package/dist/structure/version-mismatch.js +65 -12
- package/dist/structure/version-mismatch.js.map +1 -1
- package/dist/structure/version-order.d.ts +23 -0
- package/dist/structure/version-order.d.ts.map +1 -0
- package/dist/structure/version-order.js +67 -0
- package/dist/structure/version-order.js.map +1 -0
- package/dist/table-text.d.ts +9 -0
- package/dist/table-text.d.ts.map +1 -0
- package/dist/table-text.js +36 -0
- package/dist/table-text.js.map +1 -0
- package/dist/ui-labels.d.ts +16 -0
- package/dist/ui-labels.d.ts.map +1 -0
- package/dist/ui-labels.js +42 -0
- package/dist/ui-labels.js.map +1 -0
- package/dist/undefined-call.d.ts +13 -0
- package/dist/undefined-call.d.ts.map +1 -0
- package/dist/undefined-call.js +55 -0
- package/dist/undefined-call.js.map +1 -0
- package/dist/unnamed-speaker.d.ts +23 -0
- package/dist/unnamed-speaker.d.ts.map +1 -0
- package/dist/unnamed-speaker.js +176 -0
- package/dist/unnamed-speaker.js.map +1 -0
- package/dist/warning-action.d.ts +22 -0
- package/dist/warning-action.d.ts.map +1 -0
- package/dist/warning-action.js +58 -0
- package/dist/warning-action.js.map +1 -0
- package/genres.yaml +2 -0
- package/package.json +4 -3
- package/profiles/statute.yaml +8 -0
- package/rules/agreement-slip.yaml +2 -2
- package/rules/amount-range-reversed.yaml +52 -0
- package/rules/amount-scale-consistency.yaml +74 -0
- package/rules/announced-count-mismatch.yaml +9 -4
- package/rules/arrival-before-departure.yaml +48 -0
- package/rules/change-rate-mismatch.yaml +5 -4
- package/rules/connective-hierarchy.yaml +3 -3
- package/rules/currency-notation-consistency.yaml +2 -2
- package/rules/date-order.yaml +9 -4
- package/rules/date-outside-period.yaml +64 -0
- package/rules/default-value-mismatch.yaml +79 -0
- package/rules/defined-term-form.yaml +9 -7
- package/rules/deprecated-option-used.yaml +78 -0
- package/rules/doubled-nado.yaml +28 -12
- package/rules/due-before-issue.yaml +68 -0
- package/rules/duplicate-definition.yaml +2 -2
- package/rules/duration-mismatch.yaml +12 -4
- package/rules/elapsed-years-mismatch.yaml +2 -2
- package/rules/heading-echo.yaml +2 -2
- package/rules/hyphen-as-dash.yaml +2 -2
- package/rules/kana-function-word.yaml +58 -0
- package/rules/latin-spacing.yaml +6 -5
- package/rules/line-amount-mismatch.yaml +58 -0
- package/rules/nado-closed-list.yaml +77 -0
- package/rules/name-variant.yaml +17 -2
- package/rules/number-word-figure-mismatch.yaml +76 -0
- package/rules/numbering-gap.yaml +2 -2
- package/rules/obligation-without-deadline.yaml +95 -0
- package/rules/one-sentence-paragraph-run.yaml +2 -3
- package/rules/parameter-table-mismatch.yaml +90 -0
- package/rules/percent-sum-mismatch.yaml +2 -2
- package/rules/phone-number-variant.yaml +68 -0
- package/rules/prerequisite-after-step.yaml +78 -0
- package/rules/quote-unnamed-speaker.yaml +67 -0
- package/rules/quote-without-source.yaml +6 -6
- package/rules/requirement-smell.yaml +3 -3
- package/rules/sentence-initial-conjunction-run.yaml +13 -7
- package/rules/summary-fact-mismatch.yaml +4 -4
- package/rules/tax-mismatch.yaml +71 -0
- package/rules/time-order.yaml +65 -0
- package/rules/title-length.yaml +2 -2
- package/rules/ui-label-variant.yaml +70 -0
- package/rules/unbalanced-bracket.yaml +4 -4
- package/rules/uncomparable-graded.yaml +29 -10
- package/rules/undefined-function-call.yaml +77 -0
- package/rules/undefined-term.yaml +72 -0
- package/rules/unknown-word.yaml +2 -2
- package/rules/unqualified-superlative.yaml +2 -2
- package/rules/use-before-definition.yaml +2 -2
- package/rules/version-mismatch.yaml +12 -4
- package/rules/version-order.yaml +85 -0
- package/rules/very-adjective.yaml +31 -13
- package/rules/warning-without-action.yaml +64 -0
- package/rules/wordy-phrase.yaml +27 -9
- package/src/ai-score/of-document.ts +19 -9
- package/src/ai-score/render.ts +24 -4
- package/src/ai-score/score.ts +24 -3
- package/src/ai-score/signals.ts +12 -2
- package/src/ai-score/text.ts +7 -2
- package/src/announced-count.ts +19 -12
- package/src/check-source.ts +11 -2
- package/src/cli-text.ts +42 -18
- package/src/cli.ts +2 -1
- package/src/commands/cite-claims.ts +103 -0
- package/src/commands/cite-page.ts +61 -0
- package/src/commands/cite-scaffold.ts +27 -0
- package/src/commands/cite.ts +127 -58
- package/src/company-names.ts +202 -0
- package/src/default-values.ts +158 -0
- package/src/deprecated-use.ts +122 -0
- package/src/derived/number-word-counts.ts +28 -0
- package/src/derived/stays.ts +145 -0
- package/src/detectors/acronym-context.ts +10 -2
- package/src/detectors/address-word.ts +9 -0
- package/src/detectors/agreement-slip.ts +7 -1
- package/src/detectors/ai-phrasing.ts +6 -1
- package/src/detectors/amount-range.ts +54 -0
- package/src/detectors/amount-scale.ts +96 -0
- package/src/detectors/announced-count.ts +29 -11
- package/src/detectors/bare-comparative.ts +7 -2
- package/src/detectors/block-quotation.ts +95 -0
- package/src/detectors/bracket-label.ts +58 -0
- package/src/detectors/change-rate.ts +15 -2
- package/src/detectors/citation-entry.ts +20 -5
- package/src/detectors/code-before.ts +14 -0
- package/src/detectors/connective-hierarchy.ts +39 -11
- package/src/detectors/currency-notation.ts +4 -3
- package/src/detectors/date-outside-period.ts +38 -0
- package/src/detectors/default-values.ts +17 -0
- package/src/detectors/defined-term-form.ts +84 -15
- package/src/detectors/definition-use.ts +10 -2
- package/src/detectors/deprecated-use.ts +17 -0
- package/src/detectors/derived-numbers.ts +115 -17
- package/src/detectors/document-shape.ts +6 -1
- package/src/detectors/due-date.ts +47 -0
- package/src/detectors/en-shape.ts +27 -11
- package/src/detectors/fact-consistency.ts +110 -2
- package/src/detectors/heading-echo.ts +11 -1
- package/src/detectors/kana-function-word.ts +71 -0
- package/src/detectors/line-amount.ts +33 -0
- package/src/detectors/location-pointer.ts +30 -0
- package/src/detectors/mark-shape.ts +18 -1
- package/src/detectors/nado-closed-list.ts +25 -0
- package/src/detectors/name-variant.ts +114 -11
- package/src/detectors/next-word.ts +56 -9
- package/src/detectors/number-word-figure.ts +43 -0
- package/src/detectors/obligation-without-deadline.ts +192 -0
- package/src/detectors/open-end-names.ts +140 -0
- package/src/detectors/ordinal-run-gaps.ts +101 -0
- package/src/detectors/orthographic-variant.ts +39 -14
- package/src/detectors/orthography.ts +6 -1
- package/src/detectors/parameter-table.ts +17 -0
- package/src/detectors/phone-number-variant.ts +18 -0
- package/src/detectors/prerequisite-order.ts +35 -0
- package/src/detectors/quote-unnamed-speaker.ts +19 -0
- package/src/detectors/quote-without-source.ts +57 -10
- package/src/detectors/registry/amount-range.ts +4 -0
- package/src/detectors/registry/amount-scale.ts +4 -0
- package/src/detectors/registry/arrival-before-departure.ts +4 -0
- package/src/detectors/registry/date-outside-period.ts +4 -0
- package/src/detectors/registry/default-values.ts +4 -0
- package/src/detectors/registry/deprecated-use.ts +4 -0
- package/src/detectors/registry/due-date.ts +4 -0
- package/src/detectors/registry/kana-function-word.ts +4 -0
- package/src/detectors/registry/line-amount.ts +4 -0
- package/src/detectors/registry/nado-closed-list.ts +4 -0
- package/src/detectors/registry/number-word-figure.ts +4 -0
- package/src/detectors/registry/obligation-without-deadline.ts +4 -0
- package/src/detectors/registry/parameter-table.ts +4 -0
- package/src/detectors/registry/phone-number-variant.ts +4 -0
- package/src/detectors/registry/prerequisite-order.ts +4 -0
- package/src/detectors/registry/quote-unnamed-speaker.ts +4 -0
- package/src/detectors/registry/tax-amount.ts +4 -0
- package/src/detectors/registry/time-order.ts +4 -0
- package/src/detectors/registry/ui-label.ts +4 -0
- package/src/detectors/registry/undefined-call.ts +4 -0
- package/src/detectors/registry/undefined-term.ts +4 -0
- package/src/detectors/registry/version-order.ts +4 -0
- package/src/detectors/registry/warning-action.ts +4 -0
- package/src/detectors/requirement-smell.ts +29 -9
- package/src/detectors/structure-tree.ts +43 -21
- package/src/detectors/superlative-scope.ts +13 -1
- package/src/detectors/tax-amount.ts +25 -0
- package/src/detectors/technical-docs.ts +7 -1
- package/src/detectors/term-extension.ts +67 -0
- package/src/detectors/time-order.ts +49 -0
- package/src/detectors/ui-label.ts +17 -0
- package/src/detectors/unbalanced-bracket.ts +7 -14
- package/src/detectors/undefined-call.ts +19 -0
- package/src/detectors/undefined-term.ts +103 -0
- package/src/detectors/unknown-word.ts +3 -3
- package/src/detectors/vague-deadline.ts +3 -3
- package/src/detectors/version-mismatch.ts +26 -5
- package/src/detectors/version-order.ts +50 -0
- package/src/detectors/warning-action.ts +49 -0
- package/src/facts/condition-pairs.ts +289 -0
- package/src/facts/counted-facts.ts +59 -0
- package/src/facts/event-dates.ts +63 -0
- package/src/facts/fact-scope.ts +6 -0
- package/src/facts/labelled-facts.ts +13 -1
- package/src/facts/table-facts.ts +3 -3
- package/src/grade/ai-score.ts +1 -1
- package/src/grade/text.ts +2 -2
- package/src/heading-numbering.ts +2 -2
- package/src/html/fetch-page.ts +64 -0
- package/src/html/fetched-text.ts +32 -0
- package/src/html/html-content-block.ts +107 -0
- package/src/html/html-elements.ts +127 -0
- package/src/html/html-footnote-marks.ts +20 -0
- package/src/html/html-heading-links.ts +93 -0
- package/src/html/html-lost-tags.ts +14 -0
- package/src/html/html-markdown.ts +481 -0
- package/src/html/html-preformatted.ts +110 -0
- package/src/html/html-reader-only.ts +82 -0
- package/src/html/html-run-in-headings.ts +43 -0
- package/src/html/html-tables.ts +76 -0
- package/src/html/html-widgets.ts +114 -0
- package/src/html/markup-text.ts +35 -0
- package/src/html/page-document.ts +22 -0
- package/src/inline-count.ts +146 -0
- package/src/kana-spelling.ts +7 -0
- package/src/location-part.ts +30 -0
- package/src/nado-closed-list.ts +106 -0
- package/src/name-cue.ts +35 -0
- package/src/name-variants.ts +152 -11
- package/src/paragraph-runs.ts +12 -2
- package/src/parameter-table.ts +208 -0
- package/src/phone-numbers.ts +98 -0
- package/src/place-names.ts +248 -0
- package/src/plugin.ts +4 -0
- package/src/prerequisite-order.ts +39 -0
- package/src/profile/parse.ts +10 -1
- package/src/reasons.ts +4 -0
- package/src/render/rules-json.ts +4 -0
- package/src/render/rules-table.ts +6 -3
- package/src/rule-genres.ts +5 -2
- package/src/rule-load.ts +3 -2
- package/src/run.ts +3 -1
- package/src/spelling.ts +8 -0
- package/src/structure/action-due.ts +179 -0
- package/src/structure/amount-range.ts +219 -0
- package/src/structure/amount-scale.ts +115 -0
- package/src/structure/cite.ts +21 -2
- package/src/structure/counted-amounts.ts +42 -0
- package/src/structure/date-order.ts +72 -22
- package/src/structure/date-outside-period.ts +127 -0
- package/src/structure/definition-use.ts +24 -3
- package/src/structure/due-date.ts +46 -0
- package/src/structure/heading-runs.ts +24 -0
- package/src/structure/install-pin.ts +115 -0
- package/src/structure/leg-times.ts +198 -0
- package/src/structure/line-amount-unit.ts +35 -0
- package/src/structure/line-amount.ts +162 -0
- package/src/structure/number-word-figure.ts +199 -0
- package/src/structure/numbering.ts +3 -0
- package/src/structure/ordinal-runs.ts +107 -0
- package/src/structure/percent-sum-prose.ts +46 -3
- package/src/structure/percent-sum.ts +16 -2
- package/src/structure/release-list.ts +69 -0
- package/src/structure/share-column.ts +25 -0
- package/src/structure/stated-period.ts +161 -0
- package/src/structure/subject-change.ts +35 -0
- package/src/structure/tax.ts +114 -0
- package/src/structure/time-marks.ts +127 -0
- package/src/structure/time-order.ts +140 -0
- package/src/structure/title-lines.ts +33 -0
- package/src/structure/total.ts +5 -1
- package/src/structure/version-mismatch.ts +67 -13
- package/src/structure/version-order.ts +84 -0
- package/src/table-text.ts +39 -0
- package/src/ui-labels.ts +55 -0
- package/src/undefined-call.ts +65 -0
- package/src/unnamed-speaker.ts +224 -0
- package/src/warning-action.ts +73 -0
- package/styles/koyobun.yaml +7 -4
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// number-word-figure-mismatch: a number in words and its figure in brackets disagree (structure/number-word-figure.ts).
|
|
2
|
+
// The number words are the lexicon number-word; the marks around the figure are currency-notation's and the unit words of
|
|
3
|
+
// number-word; the words of scale inside the bracket ($5 million) are amount-multiplier's.
|
|
4
|
+
import type { Detector, Finding, ProseDocument } from "../plugin.ts";
|
|
5
|
+
import { wordFigureSlips, type NumberVocabulary, type NumberWord, type NumberWordKind } from "../structure/number-word-figure.ts";
|
|
6
|
+
import { proseAndTablesOf } from "../table-text.ts";
|
|
7
|
+
import { quoteAround } from "./quote-around.ts";
|
|
8
|
+
|
|
9
|
+
const KINDS: readonly NumberWordKind[] = ["digit", "place", "scale", "joiner", "lead", "unit"];
|
|
10
|
+
|
|
11
|
+
const numberWordsOf = (doc: ProseDocument): NumberWord[] =>
|
|
12
|
+
(doc.lexicons["number-word"] ?? []).flatMap((entry) => {
|
|
13
|
+
const kind = KINDS.find((candidate) => candidate === entry.group);
|
|
14
|
+
return kind === undefined ? [] : [{ word: entry.pattern, kind, value: entry.weight ?? 0 }];
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
export const vocabularyOf = (doc: ProseDocument): NumberVocabulary => {
|
|
18
|
+
const words = numberWordsOf(doc);
|
|
19
|
+
const currencies = doc.lexicons["currency-notation"] ?? [];
|
|
20
|
+
const units = words.filter((word) => word.kind === "unit").map((word) => word.word);
|
|
21
|
+
return {
|
|
22
|
+
words,
|
|
23
|
+
marksBefore: currencies.filter((entry) => entry.position === "before").map((entry) => entry.pattern),
|
|
24
|
+
marksAfter: [...currencies.filter((entry) => entry.position === "after").map((entry) => entry.pattern), ...units],
|
|
25
|
+
multipliers: (doc.lexicons["amount-multiplier"] ?? []).flatMap((entry) =>
|
|
26
|
+
entry.weight === undefined ? [] : [{ word: entry.pattern, value: entry.weight }],
|
|
27
|
+
),
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const NUMBER_FORMAT = new Intl.NumberFormat("en-US", { maximumFractionDigits: 2 });
|
|
32
|
+
|
|
33
|
+
export const numberWordFigure: Detector = (doc): Finding[] => {
|
|
34
|
+
const text = proseAndTablesOf(doc);
|
|
35
|
+
return wordFigureSlips(text, vocabularyOf(doc)).map((slip) => ({
|
|
36
|
+
rule: "number-word-figure-mismatch",
|
|
37
|
+
severity: "warning",
|
|
38
|
+
line: 0,
|
|
39
|
+
column: 0,
|
|
40
|
+
quote: quoteAround(text, slip.offset, slip.end),
|
|
41
|
+
values: { written: slip.written, words: NUMBER_FORMAT.format(slip.words), figure: NUMBER_FORMAT.format(slip.figure), offset: slip.offset },
|
|
42
|
+
}));
|
|
43
|
+
};
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
// A duty that happens at a point in time (pay, deliver, return, notify; 支払う, 提出する, 通知する) written with no time at
|
|
2
|
+
// all, in a contract that gives most of its other duties a limit: by when must it be done? The drafter decides whether
|
|
3
|
+
// duties carry limits, so only the minority in one document is pointed at, as vague-deadline does. A sentence holding
|
|
4
|
+
// a vague limit (promptly) is vague-deadline's; one stating an amount (pays a fee of $9,000) sets a price, and its
|
|
5
|
+
// timing is another clause's. The words come from the language package's word lists: timed-duty (the act),
|
|
6
|
+
// duty-marker (shall, will), duty-ending (う, するものとする: what may follow a Japanese act at the sentence end),
|
|
7
|
+
// stated-deadline (by the, までに) with concrete-deadline and vague-deadline, deadline-permission and currency-notation. Pure.
|
|
8
|
+
import { quoteAt } from "./structure-tree.ts";
|
|
9
|
+
import { escapeRegExp } from "../orthography.ts";
|
|
10
|
+
import { grantsRight, statesConcrete, vagueIn } from "./vague-deadline.ts";
|
|
11
|
+
import type { Detector, Finding, LexiconEntry, ProseDocument } from "../plugin.ts";
|
|
12
|
+
|
|
13
|
+
export type UntimedDuty = { readonly offset: number; readonly act: string };
|
|
14
|
+
|
|
15
|
+
/** sameLine: the sentence goes on the line of the one before it (no line break between them). */
|
|
16
|
+
type Text = { readonly start: number; readonly text: string; readonly sameLine?: boolean };
|
|
17
|
+
|
|
18
|
+
/** What the word lists give the decision. */
|
|
19
|
+
export type DutyWords = {
|
|
20
|
+
readonly acts: readonly string[];
|
|
21
|
+
readonly markers: readonly string[];
|
|
22
|
+
/** Words that, between the marker and the act, make the duty one not to act (will not submit). */
|
|
23
|
+
readonly negations: readonly string[];
|
|
24
|
+
readonly endings: readonly string[];
|
|
25
|
+
/** Phrases or frames that give a sentence a limit: concrete-deadline and stated-deadline. */
|
|
26
|
+
readonly limits: readonly string[];
|
|
27
|
+
/** Words that, where they stand, are no limit though a limit's words are in them (解除の日までの委託料: までの). */
|
|
28
|
+
readonly notLimits: readonly string[];
|
|
29
|
+
readonly vague: readonly string[];
|
|
30
|
+
/** Words that send the reader to other terms for how the act is done (according to the terms in the Order Form). */
|
|
31
|
+
readonly deferrals: readonly string[];
|
|
32
|
+
readonly permissions: readonly LexiconEntry[];
|
|
33
|
+
readonly currencies: readonly LexiconEntry[];
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const LATIN = /\p{Script=Latin}/u;
|
|
37
|
+
const LETTER = /\p{L}/u;
|
|
38
|
+
const DIGIT = /\p{Nd}/u;
|
|
39
|
+
const SENTENCE_MARKS = new Set(["。", ".", ".", "!", "?", "!", "?", ";", ":"]);
|
|
40
|
+
/** How many words an aside between the duty marker and the act may hold: "shall, at its option, return". */
|
|
41
|
+
const MARKER_REACH_WORDS = 4;
|
|
42
|
+
/** How far before an amount's trailing mark its number may end (88万円, 1,000 円). */
|
|
43
|
+
const AMOUNT_REACH = 3;
|
|
44
|
+
|
|
45
|
+
const withoutEnding = (text: string): string => {
|
|
46
|
+
const chars = [...text.trimEnd()];
|
|
47
|
+
const last = chars.findLastIndex((char) => !SENTENCE_MARKS.has(char) && char.trim() !== "");
|
|
48
|
+
return chars.slice(0, last + 1).join("");
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const latinWords = (lower: string): { readonly word: string; readonly at: number }[] =>
|
|
52
|
+
[...lower.matchAll(/[\p{L}']+/gu)].map((match) => ({ word: match[0], at: match.index }));
|
|
53
|
+
|
|
54
|
+
/** The act a Latin-script duty binds: an act word within reach after a duty marker (shall return, will notify). */
|
|
55
|
+
const latinActAt = (lower: string, words: DutyWords): { readonly act: string; readonly at: number } | undefined => {
|
|
56
|
+
const tokens = latinWords(lower);
|
|
57
|
+
const markerWords = words.markers.map((marker) => marker.toLowerCase().split(/\s+/u));
|
|
58
|
+
const markerEnds = tokens.flatMap((_, index) =>
|
|
59
|
+
markerWords.filter((parts) => parts.every((part, offset) => tokens[index + offset]?.word === part)).map((parts) => index + parts.length),
|
|
60
|
+
);
|
|
61
|
+
const acts = new Set(words.acts.map((act) => act.toLowerCase()));
|
|
62
|
+
const negations = new Set(words.negations.map((word) => word.toLowerCase()));
|
|
63
|
+
return markerEnds
|
|
64
|
+
.flatMap((end) => {
|
|
65
|
+
const reach = tokens.slice(end, end + MARKER_REACH_WORDS);
|
|
66
|
+
const act = reach.findIndex((token) => acts.has(token.word));
|
|
67
|
+
const found = reach[act];
|
|
68
|
+
const marker = tokens[end - 1];
|
|
69
|
+
if (found === undefined || marker === undefined || reach.slice(0, act).some((token) => negations.has(token.word))) return [];
|
|
70
|
+
// The act is the verb right after the marker, or after an aside set off by a comma ("shall, at its option, return");
|
|
71
|
+
// a later act word is an object ("shall send each invoice").
|
|
72
|
+
const aside = lower
|
|
73
|
+
.slice(marker.at + marker.word.length, found.at)
|
|
74
|
+
.trimStart()
|
|
75
|
+
.startsWith(",");
|
|
76
|
+
return act === 0 || aside ? [found] : [];
|
|
77
|
+
})
|
|
78
|
+
.map((token) => ({ act: token.word, at: token.at }))[0];
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
/** The act a duty written as the sentence's last predicate binds (支払う, 通知するものとする, 通知します). */
|
|
82
|
+
const endingActAt = (text: string, words: DutyWords): { readonly act: string; readonly at: number } | undefined => {
|
|
83
|
+
const ending = withoutEnding(text);
|
|
84
|
+
const act = words.acts.find((stem) => stem !== "" && words.endings.some((tail) => ending.endsWith(`${stem}${tail}`)));
|
|
85
|
+
if (act === undefined) return undefined;
|
|
86
|
+
return { act, at: ending.lastIndexOf(act) };
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const actIn = (text: string, words: DutyWords): { readonly act: string; readonly at: number } | undefined =>
|
|
90
|
+
words.acts.some((act) => LATIN.test(act)) ? latinActAt(text.toLowerCase(), words) : endingActAt(text, words);
|
|
91
|
+
|
|
92
|
+
/** An amount (¥1,000, 1,000円, $9,000) in the sentence: it sets what is paid, and when is another clause's. */
|
|
93
|
+
export const statesAmount = (text: string, currencies: readonly LexiconEntry[]): boolean =>
|
|
94
|
+
currencies
|
|
95
|
+
.filter((entry) => entry.pattern !== "")
|
|
96
|
+
.some((entry) => {
|
|
97
|
+
const parts = text.split(entry.pattern);
|
|
98
|
+
return parts.slice(1).some((after, index) => {
|
|
99
|
+
const before = parts[index] ?? "";
|
|
100
|
+
return entry.position === "before" ? DIGIT.test(after.trimStart().charAt(0)) : DIGIT.test(before.trimEnd().slice(-AMOUNT_REACH));
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
const isWordStart = (text: string, at: number): boolean => !LETTER.test(text.charAt(at - 1));
|
|
105
|
+
|
|
106
|
+
/** The sentence with the words that are no limit blanked out, so that a limit's words inside them are not read. */
|
|
107
|
+
const withoutNotLimits = (text: Text, notLimits: readonly string[]): Text => ({
|
|
108
|
+
start: text.start,
|
|
109
|
+
text: notLimits.filter((word) => word !== "").reduce((masked, word) => masked.replaceAll(word, " ".repeat(word.length)), text.text),
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
const FRAME = "…";
|
|
113
|
+
|
|
114
|
+
/** A phrase in the sentence; a Latin one only as whole words (by the, not by their). */
|
|
115
|
+
const phraseIn = (text: string, phrase: string): boolean => {
|
|
116
|
+
const lower = text.toLowerCase();
|
|
117
|
+
const wanted = phrase.toLowerCase().trim();
|
|
118
|
+
if (wanted === "") return false;
|
|
119
|
+
if (!LATIN.test(wanted)) return lower.includes(wanted);
|
|
120
|
+
return [...lower.matchAll(new RegExp(escapeRegExp(wanted), "gu"))].some(
|
|
121
|
+
(match) => !LETTER.test(lower.charAt(match.index - 1)) && !LETTER.test(lower.charAt(match.index + wanted.length)),
|
|
122
|
+
);
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
/** A limit in the sentence: a frame (within … days) or a phrase (by the, までに), outside the words that are no limit. */
|
|
126
|
+
const statesLimit = (text: Text, words: DutyWords): boolean => {
|
|
127
|
+
const masked = withoutNotLimits(text, words.notLimits);
|
|
128
|
+
const frames = words.limits.filter((limit) => limit.includes(FRAME));
|
|
129
|
+
return statesConcrete(masked, frames) || words.limits.some((limit) => !limit.includes(FRAME) && phraseIn(masked.text, limit));
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
const limited = (text: Text, words: DutyWords): boolean => statesLimit(text, words) || vagueIn(text, words.vague).length > 0;
|
|
133
|
+
|
|
134
|
+
/** For each sentence, the index after the last sentence on its line: the time of a duty often follows it (Fees are due within 30 days). */
|
|
135
|
+
const lineEnds = (texts: readonly Text[]): number[] => {
|
|
136
|
+
const ends: number[] = [];
|
|
137
|
+
texts.reduceRight((after, _text, index) => {
|
|
138
|
+
const end = texts[index + 1]?.sameLine === true ? after : index + 1;
|
|
139
|
+
ends[index] = end;
|
|
140
|
+
return end;
|
|
141
|
+
}, texts.length);
|
|
142
|
+
return ends;
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Each duty to act at a point in time whose sentence, and the rest of whose line, states no limit, holds no vague one, grants no right and states
|
|
147
|
+
* no amount, when more sentences of the document state a limit than hold such a duty: these duties are then the
|
|
148
|
+
* document's minority.
|
|
149
|
+
*/
|
|
150
|
+
export const untimedDuties = (texts: readonly Text[], words: DutyWords): UntimedDuty[] => {
|
|
151
|
+
const ends = lineEnds(texts);
|
|
152
|
+
const found = texts.flatMap((text, index) => {
|
|
153
|
+
const line = texts.slice(index, ends[index]);
|
|
154
|
+
if (line.some((later) => limited(later, words) || words.deferrals.some((deferral) => phraseIn(later.text, deferral)))) return [];
|
|
155
|
+
if (grantsRight(text, words.permissions) || statesAmount(text.text, words.currencies)) return [];
|
|
156
|
+
const act = actIn(text.text, words);
|
|
157
|
+
if (act === undefined || (LATIN.test(act.act) && !isWordStart(text.text, act.at))) return [];
|
|
158
|
+
return [{ offset: text.start + act.at, act: text.text.slice(act.at, act.at + act.act.length) }];
|
|
159
|
+
});
|
|
160
|
+
const limitedSentences = texts.filter((text) => statesLimit(text, words)).length;
|
|
161
|
+
return limitedSentences > found.length ? found : [];
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
const patternsOf = (doc: ProseDocument, lexicon: string): string[] => (doc.lexicons[lexicon] ?? []).map((entry) => entry.pattern);
|
|
165
|
+
|
|
166
|
+
export const obligationWithoutDeadline: Detector = (doc): Finding[] =>
|
|
167
|
+
untimedDuties(
|
|
168
|
+
doc.sentences.map((sentence, index) => ({
|
|
169
|
+
start: sentence.span.start,
|
|
170
|
+
text: sentence.text,
|
|
171
|
+
sameLine: index > 0 && !doc.source.slice(doc.sentences[index - 1]?.span.end ?? 0, sentence.span.start).includes("\n"),
|
|
172
|
+
})),
|
|
173
|
+
{
|
|
174
|
+
acts: patternsOf(doc, "timed-duty"),
|
|
175
|
+
markers: patternsOf(doc, "duty-marker"),
|
|
176
|
+
negations: patternsOf(doc, "duty-negation"),
|
|
177
|
+
endings: patternsOf(doc, "duty-ending"),
|
|
178
|
+
limits: [...patternsOf(doc, "concrete-deadline"), ...patternsOf(doc, "stated-deadline")],
|
|
179
|
+
notLimits: patternsOf(doc, "stated-deadline-not"),
|
|
180
|
+
vague: patternsOf(doc, "vague-deadline"),
|
|
181
|
+
deferrals: patternsOf(doc, "duty-terms-elsewhere"),
|
|
182
|
+
permissions: doc.lexicons["deadline-permission"] ?? [],
|
|
183
|
+
currencies: doc.lexicons["currency-notation"] ?? [],
|
|
184
|
+
},
|
|
185
|
+
).map((duty) => ({
|
|
186
|
+
rule: "obligation-without-deadline",
|
|
187
|
+
severity: "info",
|
|
188
|
+
line: 0,
|
|
189
|
+
column: 0,
|
|
190
|
+
quote: quoteAt(doc.source, duty.offset),
|
|
191
|
+
values: { word: duty.act, offset: duty.offset },
|
|
192
|
+
}));
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import type { LexiconEntry, ProseDocument, Sentence, Token } from "../plugin.ts";
|
|
2
|
+
import { escapeRegExp } from "../orthography.ts";
|
|
3
|
+
import { entryRanges, type TokenRange } from "./lexicon-match.ts";
|
|
4
|
+
|
|
5
|
+
// A word that leaves a list open (等, etc.) is also part of names a document gives itself: 「業務執行取締役等」,
|
|
6
|
+
// 銀行等(…をいう。), the head of a definition item (四の二 親会社等 …をいう。), and longer nouns built on them
|
|
7
|
+
// (監査等委員会設置会社). There the document closes the list, so the word leaves nothing open. Pure: the document and the
|
|
8
|
+
// language's words come in.
|
|
9
|
+
|
|
10
|
+
/** The parts of speech a name is made of. */
|
|
11
|
+
const NAME_POS = new Set(["NOUN", "PROPN"]);
|
|
12
|
+
/** A quoted name: what 「」『』“”"" hold, short enough to be a term rather than a sentence. */
|
|
13
|
+
const QUOTED = /[「『“"]([^「」『』“”"\n]{1,40})[」』”"]/gu;
|
|
14
|
+
/** The brackets of an aside that can define the name in front of it: 銀行等(銀行…をいう。). */
|
|
15
|
+
const ASIDE_CLOSE: Readonly<Record<string, string>> = { "(": ")", "(": ")" };
|
|
16
|
+
/** How far an aside is read for its closing bracket. A definition's aside is a clause, not a page. */
|
|
17
|
+
const MAX_ASIDE_CHARS = 600;
|
|
18
|
+
/** The label before the head of a definition item, with the space after it (四の二 , (a) ). */
|
|
19
|
+
const ITEM_LABEL = /^\s*\S{1,8}\s+$/u;
|
|
20
|
+
/** A word right after the head that makes it the subject of a sentence (親会社等は), not the head of an item. */
|
|
21
|
+
const FUNCTION_POS = new Set(["ADP", "AUX", "PART", "SCONJ", "CCONJ", "PUNCT"]);
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* One place where an open-end word stands: its sentence's tokens, the tokens the word covers, the noun it is part of
|
|
25
|
+
* (first and last token: 監査 … 会社 around 等 in 監査等委員会設置会社), and the word's document offsets.
|
|
26
|
+
*/
|
|
27
|
+
type Occurrence = {
|
|
28
|
+
readonly sentence: Sentence;
|
|
29
|
+
readonly tokens: readonly Token[];
|
|
30
|
+
readonly range: TokenRange;
|
|
31
|
+
readonly first: number;
|
|
32
|
+
readonly last: number;
|
|
33
|
+
readonly start: number;
|
|
34
|
+
readonly end: number;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/** A quoted name and where the open-end word stands in it. */
|
|
38
|
+
type QuotedName = { readonly name: string; readonly at: readonly number[] };
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The names a document gives that contain an open-end word: the ones it quotes, the ones it defines in an aside right
|
|
42
|
+
* after them (whole, as written there), and the heads of its definition items (which may run on into the definition).
|
|
43
|
+
*/
|
|
44
|
+
export type OpenEndNames = { readonly quoted: readonly QuotedName[]; readonly defined: ReadonlySet<string>; readonly heads: readonly string[] };
|
|
45
|
+
|
|
46
|
+
const attached = (left: Token | undefined, right: Token | undefined): boolean =>
|
|
47
|
+
left !== undefined && right !== undefined && left.span.end === right.span.start;
|
|
48
|
+
const isNameToken = (token: Token | undefined): boolean => token !== undefined && NAME_POS.has(token.pos);
|
|
49
|
+
|
|
50
|
+
/** The index of the first noun of the run written right before index, or index itself when none is. */
|
|
51
|
+
const runStart = (tokens: readonly Token[], index: number): number =>
|
|
52
|
+
isNameToken(tokens[index - 1]) && attached(tokens[index - 1], tokens[index]) ? runStart(tokens, index - 1) : index;
|
|
53
|
+
|
|
54
|
+
/** The index of the last noun of the run written right after index, or index itself when none is. */
|
|
55
|
+
const runEnd = (tokens: readonly Token[], index: number): number =>
|
|
56
|
+
isNameToken(tokens[index + 1]) && attached(tokens[index], tokens[index + 1]) ? runEnd(tokens, index + 1) : index;
|
|
57
|
+
|
|
58
|
+
const occurrencesIn = (sentence: Sentence, entry: LexiconEntry): Occurrence[] => {
|
|
59
|
+
const tokens = sentence.tokens ?? [];
|
|
60
|
+
return entryRanges(sentence, entry).flatMap((range) => {
|
|
61
|
+
const firstWord = tokens[range.start];
|
|
62
|
+
const lastWord = tokens[range.end - 1];
|
|
63
|
+
if (firstWord === undefined || lastWord === undefined) return [];
|
|
64
|
+
const first = runStart(tokens, range.start);
|
|
65
|
+
const last = runEnd(tokens, range.end - 1);
|
|
66
|
+
return [{ sentence, tokens, range, first, last, start: firstWord.span.start, end: lastWord.span.end }];
|
|
67
|
+
});
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const startOf = (occurrence: Occurrence, index: number): number => occurrence.tokens[index]?.span.start ?? occurrence.start;
|
|
71
|
+
const endOf = (occurrence: Occurrence, index: number): number => occurrence.tokens[index]?.span.end ?? occurrence.end;
|
|
72
|
+
|
|
73
|
+
/** The noun the word is part of, as written (当該監査等委員会). */
|
|
74
|
+
const nounOf = (source: string, occurrence: Occurrence): string => source.slice(startOf(occurrence, occurrence.first), endOf(occurrence, occurrence.last));
|
|
75
|
+
|
|
76
|
+
/** The text inside the aside that opens at offset, or undefined when none opens there or it does not close soon. */
|
|
77
|
+
export const asideAt = (source: string, offset: number): string | undefined => {
|
|
78
|
+
const open = source.charAt(offset);
|
|
79
|
+
const close = ASIDE_CLOSE[open];
|
|
80
|
+
if (close === undefined) return undefined;
|
|
81
|
+
const chars = Array.from(source.slice(offset + 1, offset + 1 + MAX_ASIDE_CHARS));
|
|
82
|
+
const depths: number[] = [];
|
|
83
|
+
chars.forEach((char) => depths.push((depths.at(-1) ?? 1) + (char === open ? 1 : 0) - (char === close ? 1 : 0)));
|
|
84
|
+
const end = depths.indexOf(0);
|
|
85
|
+
return end === -1 ? undefined : chars.slice(0, end).join("");
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const says = (text: string, statements: readonly string[]): boolean => statements.some((word) => text.includes(word));
|
|
89
|
+
|
|
90
|
+
/** Whether the noun is defined in the aside right after it (銀行等(銀行…をいう。)). */
|
|
91
|
+
const definedInAside = (source: string, occurrence: Occurrence, statements: readonly string[]): boolean => {
|
|
92
|
+
const aside = asideAt(source, endOf(occurrence, occurrence.last));
|
|
93
|
+
return aside !== undefined && says(aside, statements);
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
/** Whether the noun heads a definition item: a label before it, no particle right after the word, and a definition in the rest (四の二 親会社等 …をいう。). */
|
|
97
|
+
const headsItem = (source: string, occurrence: Occurrence, statements: readonly string[]): boolean => {
|
|
98
|
+
const next = occurrence.tokens[occurrence.range.end];
|
|
99
|
+
if (next !== undefined && next.surface.trim() !== "" && FUNCTION_POS.has(next.pos)) return false;
|
|
100
|
+
const before = source.slice(occurrence.sentence.span.start, startOf(occurrence, occurrence.first));
|
|
101
|
+
return ITEM_LABEL.test(before) && says(source.slice(endOf(occurrence, occurrence.last), occurrence.sentence.span.end), statements);
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const quotedNames = (source: string, words: readonly LexiconEntry[]): QuotedName[] =>
|
|
105
|
+
[...source.matchAll(QUOTED)].flatMap((match) => {
|
|
106
|
+
const name = match[1] ?? "";
|
|
107
|
+
const at = words.flatMap((word) => [...name.matchAll(new RegExp(escapeRegExp(word.pattern), "gu"))].map((found) => found.index));
|
|
108
|
+
return at.length === 0 ? [] : [{ name, at }];
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
/** The names a document gives that contain an open-end word. statements: the language's words of a definition (をいう, means). */
|
|
112
|
+
export const openEndNames = (doc: ProseDocument, words: readonly LexiconEntry[], statements: readonly string[]): OpenEndNames => {
|
|
113
|
+
const occurrences = doc.sentences.flatMap((sentence) => words.flatMap((word) => occurrencesIn(sentence, word)));
|
|
114
|
+
const defined = occurrences.filter((occurrence) => definedInAside(doc.source, occurrence, statements)).map((occurrence) => nounOf(doc.source, occurrence));
|
|
115
|
+
const heads = occurrences.filter((occurrence) => headsItem(doc.source, occurrence, statements)).map((occurrence) => nounOf(doc.source, occurrence));
|
|
116
|
+
return { quoted: quotedNames(doc.source, words), defined: new Set(defined), heads: [...new Set(heads)] };
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
/** Whether a quoted name holds this occurrence: the text around it reads the whole name (当該責任追及等 holds 「責任追及等」). */
|
|
120
|
+
const inQuotedName = (source: string, occurrence: Occurrence, quoted: readonly QuotedName[]): boolean =>
|
|
121
|
+
quoted.some(({ name, at }) => at.some((index) => source.startsWith(name, occurrence.start - index)));
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* The parts of the noun, cut at word boundaries, that hold the word and a noun before it: 当該監査等委員, 監査等委員, 監査等 … for 当該監査等委員.
|
|
125
|
+
* A part that is a defined name narrows it (当該金銭等, 特定役員等), and the definition closes its list.
|
|
126
|
+
*/
|
|
127
|
+
const partsHoldingWord = (source: string, occurrence: Occurrence): string[] => {
|
|
128
|
+
const { tokens, range, first, last } = occurrence;
|
|
129
|
+
const starts = tokens.slice(first, range.start).map((token) => token.span.start);
|
|
130
|
+
const ends = tokens.slice(range.end - 1, last + 1).map((token) => token.span.end);
|
|
131
|
+
return starts.flatMap((start) => ends.map((end) => source.slice(start, end)));
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const isNamed = (source: string, occurrence: Occurrence, names: OpenEndNames): boolean =>
|
|
135
|
+
inQuotedName(source, occurrence, names.quoted) ||
|
|
136
|
+
partsHoldingWord(source, occurrence).some((part) => names.defined.has(part) || names.heads.some((head) => head.startsWith(part)));
|
|
137
|
+
|
|
138
|
+
/** Where the word first stands outside a name the document gives (its document offset), or undefined when it never does. */
|
|
139
|
+
export const openEndAt = (doc: ProseDocument, sentence: Sentence, word: LexiconEntry, names: OpenEndNames): number | undefined =>
|
|
140
|
+
occurrencesIn(sentence, word).find((occurrence) => !isNamed(doc.source, occurrence, names))?.start;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
// The leads numbering-gap reads for a schedule's numbered runs (第N回, Week N): the first cell of each table's rows, the
|
|
2
|
+
// start of each list's items, and the start of each section's other lines. The comparison is structure/ordinal-runs.ts.
|
|
3
|
+
import type { ProseDocument, Section } from "../plugin.ts";
|
|
4
|
+
import { proseAndTablesOf } from "../table-text.ts";
|
|
5
|
+
import { runsOf } from "../structure/runs.ts";
|
|
6
|
+
import type { StructureIssue } from "../structure/issues.ts";
|
|
7
|
+
import { framesAt, ordinalFramesOf, ordinalRunBreaks, ordinalRuns, type Lead, type OrdinalFrame } from "../structure/ordinal-runs.ts";
|
|
8
|
+
|
|
9
|
+
type Line = { readonly start: number; readonly text: string };
|
|
10
|
+
|
|
11
|
+
/** A table, a list or a section's lines: the leads compared as one block, and where the block's first lead is. */
|
|
12
|
+
type Block = { readonly leads: readonly Lead[]; readonly start: number };
|
|
13
|
+
|
|
14
|
+
const EMPHASIS = String.raw`(?:\*\*|__|\*|_)?`;
|
|
15
|
+
const TABLE_LEAD = new RegExp(String.raw`^[ \t]*\|?[ \t]*${EMPHASIS}`, "u");
|
|
16
|
+
const LIST_LEAD = new RegExp(String.raw`^[ \t]*(?:[-*+]|\d{1,9}[.)])[ \t]+(?:\[[ xX]\][ \t]+)?${EMPHASIS}`, "u");
|
|
17
|
+
const LINE_LEAD = new RegExp(String.raw`^[ \t\u3000]*${EMPHASIS}`, "u");
|
|
18
|
+
const QUOTED_LINE = /^[ \t]*>/u;
|
|
19
|
+
|
|
20
|
+
const linesOf = (text: string): Line[] => {
|
|
21
|
+
const starts = [0, ...[...text.matchAll(/\n/gu)].map((match) => match.index + 1)];
|
|
22
|
+
return starts.map((start, index) => ({ start, text: text.slice(start, (starts[index + 1] ?? text.length + 1) - 1) }));
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const lineAt = (text: string, offset: number): string => {
|
|
26
|
+
const end = text.indexOf("\n", offset);
|
|
27
|
+
return text.slice(offset, end === -1 ? text.length : end);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const leadOf = (text: string, offset: number, marks: RegExp, frames: readonly OrdinalFrame[]): Lead => {
|
|
31
|
+
const line = lineAt(text, offset);
|
|
32
|
+
const skipped = marks.exec(line)?.[0].length ?? 0;
|
|
33
|
+
return { offset: offset + skipped, read: framesAt(line.slice(skipped), frames) };
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const tableBlocks = (text: string, frames: readonly OrdinalFrame[]): Block[] =>
|
|
37
|
+
runsOf(text)
|
|
38
|
+
.filter((run) => run[0]?.kind === "table" && run.length > 0)
|
|
39
|
+
.map((run) => ({ leads: run.map((line) => leadOf(text, line.start, TABLE_LEAD, frames)), start: run[0]?.start ?? 0 }));
|
|
40
|
+
|
|
41
|
+
const isQuotedAt = (source: string, offset: number): boolean => QUOTED_LINE.test(lineAt(source, source.lastIndexOf("\n", offset - 1) + 1));
|
|
42
|
+
|
|
43
|
+
const listBlocks = (doc: ProseDocument, text: string, frames: readonly OrdinalFrame[]): Block[] =>
|
|
44
|
+
doc.lists
|
|
45
|
+
.filter((list) => !isQuotedAt(doc.source, list.span.start))
|
|
46
|
+
.map((list) => ({ leads: list.itemSpans.map((item) => leadOf(text, item.start, LIST_LEAD, frames)), start: list.span.start }));
|
|
47
|
+
|
|
48
|
+
const sectionIndexAt = (sections: readonly Section[], offset: number): number => sections.findLastIndex((section) => section.span.start <= offset);
|
|
49
|
+
|
|
50
|
+
/** The lines outside tables, lists and quotations, one block per section. */
|
|
51
|
+
const lineBlocks = (doc: ProseDocument, text: string, frames: readonly OrdinalFrame[]): Block[] => {
|
|
52
|
+
const inList = (offset: number): boolean => doc.lists.some((list) => offset >= list.span.start && offset < list.span.end);
|
|
53
|
+
const bySection = new Map<number, Lead[]>();
|
|
54
|
+
linesOf(text)
|
|
55
|
+
.filter((line) => !line.text.includes("|"))
|
|
56
|
+
.map((line) => leadOf(text, line.start, LINE_LEAD, frames))
|
|
57
|
+
.filter((lead) => lead.read.length > 0 && !inList(lead.offset) && !isQuotedAt(doc.source, lead.offset))
|
|
58
|
+
.forEach((lead) => {
|
|
59
|
+
const key = sectionIndexAt(doc.sections, lead.offset);
|
|
60
|
+
const leads = bySection.get(key) ?? [];
|
|
61
|
+
leads.push(lead);
|
|
62
|
+
bySection.set(key, leads);
|
|
63
|
+
});
|
|
64
|
+
return [...bySection.values()].map((leads) => ({ leads, start: leads[0]?.offset ?? 0 }));
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
/** How many lines above a block are read for a word saying it lists only some items (a caption, a table's header row). */
|
|
68
|
+
const LINES_ABOVE = 3;
|
|
69
|
+
const LATIN_WORD = /^[A-Za-z][A-Za-z ]*$/u;
|
|
70
|
+
|
|
71
|
+
const markerTest = (marker: string): ((text: string) => boolean) => {
|
|
72
|
+
if (!LATIN_WORD.test(marker)) return (text) => text.includes(marker);
|
|
73
|
+
const word = new RegExp(String.raw`(?<![A-Za-z])${marker}(?![A-Za-z])`, "iu");
|
|
74
|
+
return (text) => word.test(text);
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
/** The heading over the block and the few lines right above it, as written. */
|
|
78
|
+
const contextAbove = (doc: ProseDocument, start: number): string => {
|
|
79
|
+
const section = doc.sections[sectionIndexAt(doc.sections, start)];
|
|
80
|
+
const from = section?.span.start ?? 0;
|
|
81
|
+
const above = linesOf(doc.source.slice(from, start))
|
|
82
|
+
.map((line) => line.text)
|
|
83
|
+
.filter((line) => line.trim() !== "")
|
|
84
|
+
.slice(-LINES_ABOVE);
|
|
85
|
+
return [section?.heading ?? "", ...above].join("\n");
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* The skips and repeats in the document's 第N回 / Week N runs. A block whose heading or the lines right above it say it
|
|
90
|
+
* lists only some (抜粋, selected) is not read: its numbers skip by choice.
|
|
91
|
+
*/
|
|
92
|
+
export const ordinalRunGaps = (doc: ProseDocument): StructureIssue[] => {
|
|
93
|
+
const frames = ordinalFramesOf(doc.lexicons["ordinal-frame"] ?? []);
|
|
94
|
+
if (frames.length === 0) return [];
|
|
95
|
+
const partial = (doc.lexicons["partial-listing-marker"] ?? []).map((entry) => markerTest(entry.pattern));
|
|
96
|
+
const text = proseAndTablesOf(doc);
|
|
97
|
+
return [...tableBlocks(text, frames), ...listBlocks(doc, text, frames), ...lineBlocks(doc, text, frames)]
|
|
98
|
+
.filter((block) => block.leads.some((lead) => lead.read.length > 0))
|
|
99
|
+
.filter((block) => !partial.some((names) => names(contextAbove(doc, block.start))))
|
|
100
|
+
.flatMap((block) => ordinalRuns(block.leads).flatMap(ordinalRunBreaks));
|
|
101
|
+
};
|
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
import type { Detector, Finding, ProseDocument, Sentence, Token } from "../plugin.ts";
|
|
2
2
|
import { groupBy, oddSpellings, type KeyedWord, type OddSpelling } from "../spelling-variants.ts";
|
|
3
|
-
import { kanjiSkeleton, katakanaKey, lemmaReading } from "../kana-spelling.ts";
|
|
3
|
+
import { dropsOkurigana, kanjiSkeleton, katakanaKey, lemmaReading } from "../kana-spelling.ts";
|
|
4
4
|
import { isKatakanaWord, stemOf } from "../long-vowel.ts";
|
|
5
5
|
import { QUOTATION_MARKS, isWithinAny, quotedSpans } from "../quoted-span.ts";
|
|
6
6
|
import { nameSpans, touchesAny } from "../team-names.ts";
|
|
7
7
|
import { furiganaSpans } from "../furigana.ts";
|
|
8
8
|
import { acronymsIn, isCapitalsNotSpelling } from "../capitals-with-small.ts";
|
|
9
|
+
import { isPartOfAddress } from "./address-word.ts";
|
|
9
10
|
|
|
10
|
-
/**
|
|
11
|
-
|
|
11
|
+
/**
|
|
12
|
+
* A word found in the document: where it is, which sentence it is in, its key and spelling, how it is written when that differs, and
|
|
13
|
+
* whether it is written onto the noun after it (取扱事業者).
|
|
14
|
+
*/
|
|
15
|
+
type Placed = KeyedWord & { readonly sentence: Sentence; readonly offset: number; readonly shown?: string; readonly compoundHead?: boolean };
|
|
12
16
|
|
|
13
17
|
type IsOpen = (start: number, end: number) => boolean;
|
|
14
18
|
|
|
@@ -50,7 +54,21 @@ const followsTeForm = (previous: Token | undefined): boolean =>
|
|
|
50
54
|
(previous?.pos === "SCONJ" && (previous.surface === "て" || previous.surface === "で")) ||
|
|
51
55
|
(previous?.pos === "CCONJ" && TE_FORM_CONJUNCTION.test(previous.surface));
|
|
52
56
|
|
|
53
|
-
|
|
57
|
+
/** は or も after a word ending in で, て or く: the ない after them negates (事実ではない, どれでもない, 高くはない); it is not 無い. */
|
|
58
|
+
const TOPIC_AFTER_LINK = new Set(["は", "も"]);
|
|
59
|
+
const LINK_END = /[でてく]$/u;
|
|
60
|
+
const NEGATION = new Set(["ない", "無い"]);
|
|
61
|
+
|
|
62
|
+
/** では and でも read as one word after a space (2 ではなく). */
|
|
63
|
+
const LINK_AND_TOPIC = new Set(["では", "でも"]);
|
|
64
|
+
|
|
65
|
+
const followsLinkAndTopic = (previous: Token | undefined, before: Token | undefined): boolean =>
|
|
66
|
+
LINK_AND_TOPIC.has(previous?.surface ?? "") || (previous?.pos === "ADP" && TOPIC_AFTER_LINK.has(previous.surface) && LINK_END.test(before?.surface ?? ""));
|
|
67
|
+
|
|
68
|
+
const negatesAfterTopic = ({ token, previous, before }: InContext): boolean =>
|
|
69
|
+
token.pos === "ADJ" && NEGATION.has(token.lemma ?? "") && followsLinkAndTopic(previous, before);
|
|
70
|
+
|
|
71
|
+
const isHelper = (word: InContext): boolean => word.token.features?.["Bound"] === "Yes" || followsTeForm(word.previous) || negatesAfterTopic(word);
|
|
54
72
|
|
|
55
73
|
const isTouching = (left: Token | undefined, right: Token): boolean => left !== undefined && left.span.end === right.span.start;
|
|
56
74
|
|
|
@@ -84,6 +102,13 @@ const KATAKANA_END = /\p{Script=Katakana}$/u;
|
|
|
84
102
|
const isCutFromKatakana = ({ token, previous }: InContext): boolean =>
|
|
85
103
|
ONE_KATAKANA_HEAD.test(token.surface) && token.surface.length > 1 && isTouching(previous, token) && KATAKANA_END.test(previous?.surface ?? "");
|
|
86
104
|
|
|
105
|
+
/**
|
|
106
|
+
* で read as the verb 出る right after a word with no particle between (JSON でない): the copula's で, which the tokenizer
|
|
107
|
+
* misreads after a space or a name. 出る after a particle (結果がでない) or at the head of a sentence (でない音) is the verb.
|
|
108
|
+
*/
|
|
109
|
+
const isCopulaReadAsVerb = ({ token, previous }: InContext): boolean =>
|
|
110
|
+
token.pos === "VERB" && token.surface === "で" && previous !== undefined && previous.pos !== "ADP";
|
|
111
|
+
|
|
87
112
|
type Skips = { readonly skip: ReadonlySet<string>; readonly idioms: ReadonlySet<string> };
|
|
88
113
|
|
|
89
114
|
const readingKeyOf = (word: InContext, { skip, idioms }: Skips): string | undefined => {
|
|
@@ -91,7 +116,7 @@ const readingKeyOf = (word: InContext, { skip, idioms }: Skips): string | undefi
|
|
|
91
116
|
const lemma = token.lemma;
|
|
92
117
|
if (!CONTENT.has(token.pos) || token.reading === undefined || lemma === undefined || !JAPANESE_WORD.test(lemma) || skip.has(lemma)) return undefined;
|
|
93
118
|
const reading = lemmaReading(token.surface, lemma, token.reading);
|
|
94
|
-
if (reading === undefined || [...reading].length < MIN_READING || skip.has(reading) || isCutFromKatakana(word)) return undefined;
|
|
119
|
+
if (reading === undefined || [...reading].length < MIN_READING || skip.has(reading) || isCutFromKatakana(word) || isCopulaReadAsVerb(word)) return undefined;
|
|
95
120
|
return `${token.pos}|${useOf(word, idioms)}|${reading}`;
|
|
96
121
|
};
|
|
97
122
|
|
|
@@ -102,22 +127,28 @@ const readingWords = (sentence: Sentence, isOpen: IsOpen, skips: Skips): Placed[
|
|
|
102
127
|
const key = readingKeyOf({ token, previous: tokens[at - 1], before: tokens[at - 2] }, skips);
|
|
103
128
|
const local = token.span.start - sentence.span.start;
|
|
104
129
|
if (key === undefined || token.lemma === undefined || !isOpen(local, local + token.surface.length)) return [];
|
|
105
|
-
|
|
130
|
+
const next = tokens[at + 1];
|
|
131
|
+
const compoundHead = token.pos === "NOUN" && next?.pos === "NOUN" && isTouching(token, next);
|
|
132
|
+
return [{ key, spelling: token.lemma, sentence, offset: token.span.start, compoundHead }];
|
|
106
133
|
});
|
|
107
134
|
};
|
|
108
135
|
|
|
109
136
|
/**
|
|
110
137
|
* Same reading is not yet same word: 書く and 描く are both カク. Spellings meet only when they keep the same kanji (引っ越し, 引越し)
|
|
111
138
|
* or one is all kana. A kana spelling joins the kanji one only when the reading has a single kanji spelling in the document;
|
|
112
|
-
* with two (橋 and 箸 beside はし) it cannot say which, and is left out.
|
|
139
|
+
* with two (橋 and 箸 beside はし) it cannot say which, and is left out. Official Japanese drops okurigana at the head of a compound
|
|
140
|
+
* (取扱事業者 beside 個人情報の取扱い), so where the document writes a word both ways, its compound heads are compared apart.
|
|
113
141
|
*/
|
|
114
142
|
const byKanji = (words: readonly Placed[]): Placed[] =>
|
|
115
143
|
[...groupBy(words, (word) => word.key).values()].flatMap((group) => {
|
|
116
144
|
const skeletons = [...new Set(group.map((word) => kanjiSkeleton(word.spelling)).filter((skeleton) => skeleton !== ""))];
|
|
145
|
+
const spellings = [...new Set(group.map((word) => word.spelling))];
|
|
146
|
+
const apart = spellings.some((spelling) => dropsOkurigana(spelling, spellings)) ? "|compound" : "";
|
|
117
147
|
return group.flatMap((word): Placed[] => {
|
|
118
148
|
const own = kanjiSkeleton(word.spelling);
|
|
119
149
|
if (own === "" && skeletons.length > 1) return [];
|
|
120
|
-
|
|
150
|
+
const use = word.compoundHead === true ? apart : "";
|
|
151
|
+
return [{ ...word, key: `${word.key}|${own === "" ? (skeletons[0] ?? "") : own}${use}` }];
|
|
121
152
|
});
|
|
122
153
|
});
|
|
123
154
|
|
|
@@ -143,12 +174,6 @@ const latinSpelling = (word: string): string =>
|
|
|
143
174
|
.map((part) => part.charAt(0).toLowerCase() + part.slice(1))
|
|
144
175
|
.join("-");
|
|
145
176
|
|
|
146
|
-
/** A word joined to a dot, an at sign or a slash is part of an address or a file name (github.com, user@example), spelled as it must be. */
|
|
147
|
-
const ADDRESS_NEIGHBOUR = /[.@/\\_]/u;
|
|
148
|
-
|
|
149
|
-
const isPartOfAddress = (text: string, start: number, end: number): boolean =>
|
|
150
|
-
ADDRESS_NEIGHBOUR.test(text.charAt(start - 1)) || (ADDRESS_NEIGHBOUR.test(text.charAt(end)) && /\w/u.test(text.charAt(end + 1)));
|
|
151
|
-
|
|
152
177
|
/**
|
|
153
178
|
* Latin words keyed without hyphens and case (e-mail and email, GitHub and Github). A word in capitals only (TEAMS, MAY) is
|
|
154
179
|
* emphasis or an acronym, not a spelling of the word, and is left out; so are a name in capitals with an ending (SENDs) and
|
|
@@ -4,6 +4,7 @@ import { escapeRegExp, latinBoundaries, occurrencesOutside, type Boundary, type
|
|
|
4
4
|
import { minorityReport } from "../spacing-minority.ts";
|
|
5
5
|
import { isWithinAny, quotedSpans } from "../quoted-span.ts";
|
|
6
6
|
import { digitRunAround, endsWithDivisionLabel, isNumberName, sequenceLabelStarts, type NameContext } from "../number-name.ts";
|
|
7
|
+
import { isSpacedLocationPart, type FloorWords } from "../location-part.ts";
|
|
7
8
|
|
|
8
9
|
/** チームが chaff.yaml の prefer に書いた「使わない書き方」。書いていなければ何も言わない。 */
|
|
9
10
|
export const preferredTerm: Detector = (doc, options): Finding[] => {
|
|
@@ -35,12 +36,13 @@ const digitBeside = (boundary: Boundary): number => {
|
|
|
35
36
|
|
|
36
37
|
/**
|
|
37
38
|
* 文書全体で一度だけ読むもの(number-name.ts の NameContext に加えて)。calendar は日付・時刻の単位、
|
|
38
|
-
* divisions は「第1
|
|
39
|
+
* divisions は「第1節」のように「第」と番号の後ろに書く区切りの語、floors は階・部屋の番号を読む語(5階、201号室、地下 1階)。
|
|
39
40
|
*/
|
|
40
41
|
type NumberContext = NameContext & {
|
|
41
42
|
readonly calendar: CalendarUnits;
|
|
42
43
|
readonly divisions: ReadonlySet<string>;
|
|
43
44
|
readonly itemNumbers: ReadonlySet<string>;
|
|
45
|
+
readonly floors: FloorWords;
|
|
44
46
|
};
|
|
45
47
|
|
|
46
48
|
/** 文頭の項目の番号の後ろと見る境目の位置の上限。番号は短く文の頭にあるので、これより後ろの境目は番号の後ろではない。長い文で文頭からの切り出しを繰り返さない。 */
|
|
@@ -71,6 +73,7 @@ const calendarStarts = (sentence: Sentence, units: CalendarUnits): ReadonlySet<n
|
|
|
71
73
|
/**
|
|
72
74
|
* 番号・識別子として書かれた数(number-name.ts)、日付・時刻の数、「第1節」の後ろの境目、文頭の項目の番号(「一 JIS」)の後ろの境目は、空け方の好みではないので数えない。
|
|
73
75
|
* 日付・時刻は前の境目(「は 9月」「午後3時」「令和 3 年」)も数えない。日付はまとめて一つの書き方で、数量の空け方の票にはしない。
|
|
76
|
+
* 「本社 5階」のように名前の後ろに空白で区切った階・部屋の番号の前の空白も、所在の組の区切りなので数えない(location-part.ts)。
|
|
74
77
|
*/
|
|
75
78
|
const isCounted = (sentence: Sentence, boundary: Boundary, context: NumberContext, calendar: ReadonlySet<number>): boolean => {
|
|
76
79
|
if (followsItemNumber(sentence.text, boundary, context.itemNumbers)) return false;
|
|
@@ -79,6 +82,7 @@ const isCounted = (sentence: Sentence, boundary: Boundary, context: NumberContex
|
|
|
79
82
|
const run = digitRunAround(sentence.text, digitBeside(boundary));
|
|
80
83
|
if (run === undefined) return true;
|
|
81
84
|
if (calendar.has(run.start)) return false;
|
|
85
|
+
if (boundary.kind === "before-digit" && isSpacedLocationPart(sentence.text, run, sentence.tokens, sentence.span.start, context.floors)) return false;
|
|
82
86
|
return !isNumberName(sentence.text, run, sentence.tokens, sentence.span.start, context);
|
|
83
87
|
};
|
|
84
88
|
|
|
@@ -145,6 +149,7 @@ export const latinSpacing: Detector = (doc, options): Finding[] => {
|
|
|
145
149
|
calendar: calendarUnitsOf(doc),
|
|
146
150
|
divisions: labelsAt(doc, "after"),
|
|
147
151
|
itemNumbers: numberedItems(patternList(doc, "item-number"), doc.prose ?? doc.source),
|
|
152
|
+
floors: { units: patternsOf(doc, "floor-unit"), levels: patternsOf(doc, "floor-level") },
|
|
148
153
|
};
|
|
149
154
|
const located: Located[] = doc.sentences.flatMap((sentence) => {
|
|
150
155
|
const quoted = quotedSpans(sentence.text);
|