chaffjs 0.28.0 → 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/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 +38 -16
- 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/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 +6 -1
- package/dist/detectors/amount-scale.d.ts.map +1 -1
- package/dist/detectors/amount-scale.js +33 -9
- package/dist/detectors/amount-scale.js.map +1 -1
- 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/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.map +1 -1
- package/dist/detectors/currency-notation.js +2 -1
- 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 +70 -15
- 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 +76 -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 +82 -8
- 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/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/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 +23 -1
- package/dist/name-variants.d.ts.map +1 -1
- package/dist/name-variants.js +39 -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 +6 -0
- package/dist/structure/amount-scale.d.ts.map +1 -1
- package/dist/structure/amount-scale.js +13 -0
- package/dist/structure/amount-scale.js.map +1 -1
- 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/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 +4 -4
- package/rules/announced-count-mismatch.yaml +9 -4
- package/rules/arrival-before-departure.yaml +48 -0
- 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/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 +14 -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 +38 -16
- 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/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 +50 -17
- 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/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 +2 -1
- 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 +106 -15
- 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 +95 -3
- 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 +106 -13
- 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/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/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 +57 -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 +18 -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/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,179 @@
|
|
|
1
|
+
import type { MarkupHeading } from "../plugin.ts";
|
|
2
|
+
import { CELL_SEPARATOR } from "./bare-numbers.ts";
|
|
3
|
+
import type { DatedPoint } from "./due-date.ts";
|
|
4
|
+
import type { StructureIssue } from "./issues.ts";
|
|
5
|
+
import { linesOf, type Line } from "./lines.ts";
|
|
6
|
+
import { TABLE_RULE } from "./runs.ts";
|
|
7
|
+
import { isTotalLabel } from "./total.ts";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* An action item due before the meeting it was set in. Only minutes are read (a title with 議事録 or Minutes). The meeting
|
|
11
|
+
* date is the first date on a line starting with a meeting-date word (日時, Date) near the top; the deadlines are those of the action sections (a heading with 宿題 or
|
|
12
|
+
* Action items): the cell under a due column (期限, Due) of a table, or a date right after a due word in a list item
|
|
13
|
+
* ((期限 11月2日), (due Oct 3)). An item marked done, and a section on earlier items (前回の宿題), are not read. Pure.
|
|
14
|
+
*/
|
|
15
|
+
export type ActionWords = {
|
|
16
|
+
readonly meeting: readonly string[];
|
|
17
|
+
readonly section: readonly string[];
|
|
18
|
+
readonly earlier: readonly string[];
|
|
19
|
+
readonly due: readonly string[];
|
|
20
|
+
readonly done: readonly string[];
|
|
21
|
+
readonly minutes: readonly string[];
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/** How far from the top the meeting date may be and still be the date of the meeting the minutes record. */
|
|
25
|
+
const MEETING_HEAD_LINES = 12;
|
|
26
|
+
|
|
27
|
+
/** A deadline without a year this many days or fewer after the meeting, read in the next year, is taken as next year's. */
|
|
28
|
+
const MAX_WRAP_DAYS = 92;
|
|
29
|
+
|
|
30
|
+
const MS_PER_DAY = 86_400_000;
|
|
31
|
+
const FULL_DATE = /^\d{4}-\d{2}-\d{2}$/u;
|
|
32
|
+
const MONTH_DAY = /^(?:\d{4}-)?(\d{2})-(\d{2})$/u;
|
|
33
|
+
const LIST_ITEM = /^[ \t]*(?:[-*+]|\d{1,3}[.)])[ \t]/u;
|
|
34
|
+
const LATIN_WORD = /^[A-Za-z ]+$/u;
|
|
35
|
+
|
|
36
|
+
const escaped = (text: string): string => text.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
|
|
37
|
+
|
|
38
|
+
const hasWord = (text: string, word: string): boolean => (LATIN_WORD.test(word) ? new RegExp(`\\b${escaped(word)}\\b`, "iu").test(text) : text.includes(word));
|
|
39
|
+
|
|
40
|
+
const hasAny = (text: string, words: readonly string[]): boolean => words.some((word) => hasWord(text, word));
|
|
41
|
+
|
|
42
|
+
const CHECKED_BOX = /^[ \t]*(?:[-*+]|\d{1,3}[.)])[ \t]+\[[xX]\]/u;
|
|
43
|
+
const BRACKETED = /[((【[][^()()【】[\]]*[))】\]]/gu;
|
|
44
|
+
const TRAIL_SEPARATOR = /[ \t—–::、,]/u;
|
|
45
|
+
const LINE_CLOSERS = new Set(["|", "。", ".", " ", "\t"]);
|
|
46
|
+
|
|
47
|
+
/** The last word of a line, without a closing table bar or a full stop. */
|
|
48
|
+
const lastWord = (text: string): string =>
|
|
49
|
+
(
|
|
50
|
+
text
|
|
51
|
+
.slice(0, text.split("").findLastIndex((unit) => !LINE_CLOSERS.has(unit)) + 1)
|
|
52
|
+
.split(TRAIL_SEPARATOR)
|
|
53
|
+
.at(-1) ?? ""
|
|
54
|
+
).toLowerCase();
|
|
55
|
+
|
|
56
|
+
const cellTexts = (text: string): string[] =>
|
|
57
|
+
text.split(CELL_SEPARATOR).map((cell) =>
|
|
58
|
+
cell
|
|
59
|
+
.replace(/[*_✔✓]/gu, "")
|
|
60
|
+
.trim()
|
|
61
|
+
.toLowerCase(),
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* An item marked done: a checked box, a cell that is a done word alone, a done word in brackets ((済), (done, June 3)),
|
|
66
|
+
* or one ending the line. A done word inside the task (Complete the review) does not mark it.
|
|
67
|
+
*/
|
|
68
|
+
const isMarkedDone = (text: string, words: readonly string[]): boolean => {
|
|
69
|
+
if (CHECKED_BOX.test(text)) return true;
|
|
70
|
+
const alone = new Set(words.map((word) => word.toLowerCase()));
|
|
71
|
+
return cellTexts(text).some((cell) => alone.has(cell)) || alone.has(lastWord(text)) || [...text.matchAll(BRACKETED)].some((match) => hasAny(match[0], words));
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
/** Whether the title (the first top-level heading, or else the first line with text) names minutes. */
|
|
75
|
+
const isMinutes = (lines: readonly Line[], headings: readonly MarkupHeading[], words: readonly string[]): boolean =>
|
|
76
|
+
hasAny(headings.find((heading) => heading.depth === 1)?.text ?? lines.find((line) => line.text.trim() !== "")?.text ?? "", words);
|
|
77
|
+
|
|
78
|
+
const datesIn = (dates: readonly DatedPoint[], start: number, end: number): DatedPoint[] => dates.filter((date) => date.offset >= start && date.offset <= end);
|
|
79
|
+
|
|
80
|
+
const meetingDate = (lines: readonly Line[], dates: readonly DatedPoint[], words: readonly string[]): DatedPoint | undefined =>
|
|
81
|
+
lines
|
|
82
|
+
.slice(0, MEETING_HEAD_LINES)
|
|
83
|
+
.filter((line) => isTotalLabel(line.text, words))
|
|
84
|
+
.map((line) => datesIn(dates, line.start, line.start + line.text.length)[0])
|
|
85
|
+
.find((date) => date !== undefined);
|
|
86
|
+
|
|
87
|
+
type Range = { readonly start: number; readonly end: number };
|
|
88
|
+
|
|
89
|
+
/** Where a heading's section ends: the next heading at its depth or above. */
|
|
90
|
+
const sectionOf = (headings: readonly MarkupHeading[], index: number, end: number): Range => {
|
|
91
|
+
const heading = headings[index];
|
|
92
|
+
const next = headings.slice(index + 1).find((later) => heading !== undefined && later.depth <= heading.depth);
|
|
93
|
+
return { start: heading?.start ?? end, end: next?.start ?? end };
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
/** The action sections, without the parts under a heading on earlier items. */
|
|
97
|
+
const actionRanges = (headings: readonly MarkupHeading[], length: number, words: ActionWords): { take: Range[]; skip: Range[] } => {
|
|
98
|
+
const ranges = headings.map((heading, index) => ({ heading, range: sectionOf(headings, index, length) }));
|
|
99
|
+
return {
|
|
100
|
+
take: ranges.filter(({ heading }) => hasAny(heading.text, words.section)).map(({ range }) => range),
|
|
101
|
+
skip: ranges.filter(({ heading }) => hasAny(heading.text, words.earlier)).map(({ range }) => range),
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const inside = (offset: number, ranges: readonly Range[]): boolean => ranges.some((range) => offset >= range.start && offset < range.end);
|
|
106
|
+
|
|
107
|
+
/** The column of a table header that is a due word alone, if the line is a header (the next line is the table's rule). */
|
|
108
|
+
const dueColumn = (line: Line, next: Line | undefined, words: readonly string[]): number | undefined => {
|
|
109
|
+
if (next === undefined || !TABLE_RULE.test(next.text) || !line.text.includes("|")) return undefined;
|
|
110
|
+
const labels = new Set(words.map((word) => word.toLowerCase()));
|
|
111
|
+
const column = cellTexts(line.text).findIndex((cell) => labels.has(cell));
|
|
112
|
+
return column < 0 ? undefined : column;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const lineEnd = (line: Line): number => line.start + line.text.length;
|
|
116
|
+
|
|
117
|
+
const columnAt = (line: Line, offset: number): number => line.text.slice(0, offset - line.start).split(CELL_SEPARATOR).length - 1;
|
|
118
|
+
|
|
119
|
+
/** The deadline in a table row: the one date in the due column. */
|
|
120
|
+
const rowDeadline = (line: Line, column: number, dates: readonly DatedPoint[]): DatedPoint[] => {
|
|
121
|
+
const inColumn = datesIn(dates, line.start, lineEnd(line)).filter((date) => columnAt(line, date.offset) === column);
|
|
122
|
+
return inColumn.length === 1 ? inColumn : [];
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
/** A due word right before a date, with at most one word between (due Monday, November 2; 期限:11月2日). */
|
|
126
|
+
const dueWordBefore = (words: readonly string[]): RegExp =>
|
|
127
|
+
new RegExp(`(?:^|[\\s((、,;::])(?:${words.map(escaped).join("|")})[ \\t\\u3000::]*(?:\\p{L}+,?[ \\t]+)?$`, "iu");
|
|
128
|
+
|
|
129
|
+
/** The deadlines of a list item: the dates right after a due word. */
|
|
130
|
+
const listDeadlines = (line: Line, dates: readonly DatedPoint[], dueBefore: RegExp): DatedPoint[] =>
|
|
131
|
+
LIST_ITEM.test(line.text) ? datesIn(dates, line.start, lineEnd(line)).filter((date) => dueBefore.test(line.text.slice(0, date.offset - line.start))) : [];
|
|
132
|
+
|
|
133
|
+
/** The deadlines of the tables with a due column and of the list items, outside items marked done. */
|
|
134
|
+
const deadlinesOf = (lines: readonly Line[], dates: readonly DatedPoint[], words: ActionWords): DatedPoint[] => {
|
|
135
|
+
const found: DatedPoint[] = [];
|
|
136
|
+
const dueBefore = dueWordBefore(words.due);
|
|
137
|
+
lines.reduce<number | undefined>((column, line, index) => {
|
|
138
|
+
const header = dueColumn(line, lines[index + 1], words.due);
|
|
139
|
+
if (header !== undefined) return header;
|
|
140
|
+
const inTable = line.text.includes("|") ? column : undefined;
|
|
141
|
+
if (isMarkedDone(line.text, words.done)) return inTable;
|
|
142
|
+
found.push(...(inTable === undefined ? listDeadlines(line, dates, dueBefore) : rowDeadline(line, inTable, dates)));
|
|
143
|
+
return inTable;
|
|
144
|
+
}, undefined);
|
|
145
|
+
return found;
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
const REFERENCE_YEAR = 2001;
|
|
149
|
+
|
|
150
|
+
const dayNumber = (value: string, year: number): number | undefined => {
|
|
151
|
+
const match = MONTH_DAY.exec(value);
|
|
152
|
+
return match === null ? undefined : Date.UTC(year, Number(match[1]) - 1, Number(match[2])) / MS_PER_DAY;
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
/** Whether a deadline is before the meeting. Without a year on one of them, a deadline early in the next year is not. */
|
|
156
|
+
export const isBeforeMeeting = (due: string, meeting: string): boolean => {
|
|
157
|
+
if (FULL_DATE.test(due) && FULL_DATE.test(meeting)) return due < meeting;
|
|
158
|
+
const meetingDay = dayNumber(meeting, REFERENCE_YEAR);
|
|
159
|
+
const dueDay = dayNumber(due, REFERENCE_YEAR);
|
|
160
|
+
const dueNextYear = dayNumber(due, REFERENCE_YEAR + 1);
|
|
161
|
+
if (meetingDay === undefined || dueDay === undefined || dueNextYear === undefined) return false;
|
|
162
|
+
return dueDay < meetingDay && dueNextYear - meetingDay > MAX_WRAP_DAYS;
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
export const actionDueBeforeMeeting = (
|
|
166
|
+
source: string,
|
|
167
|
+
dates: readonly DatedPoint[],
|
|
168
|
+
headings: readonly MarkupHeading[],
|
|
169
|
+
words: ActionWords,
|
|
170
|
+
): StructureIssue[] => {
|
|
171
|
+
if (words.meeting.length === 0 || words.due.length === 0 || words.section.length === 0) return [];
|
|
172
|
+
const lines = linesOf(source);
|
|
173
|
+
const meeting = meetingDate(lines, dates, words.meeting);
|
|
174
|
+
const ranges = actionRanges(headings, source.length, words);
|
|
175
|
+
if (meeting === undefined || ranges.take.length === 0 || !isMinutes(lines, headings, words.minutes)) return [];
|
|
176
|
+
return deadlinesOf(lines, dates, words)
|
|
177
|
+
.filter((due) => inside(due.offset, ranges.take) && !inside(due.offset, ranges.skip) && isBeforeMeeting(due.value, meeting.value))
|
|
178
|
+
.map((due) => ({ offset: due.offset, values: { due: due.value, meeting: meeting.value } }));
|
|
179
|
+
};
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
// amount-range-reversed: a range of amounts whose upper end is below its lower end (月給30万円〜25万円, $90,000–$70,000,
|
|
2
|
+
// 下限30万円・上限25万円). The amounts come read (currency, value, the word of scale they carry); the words that join a range,
|
|
3
|
+
// change a price, and label a bound come from the lexicons. Pure.
|
|
4
|
+
import { escapeRegExp } from "../orthography.ts";
|
|
5
|
+
import { amountValue, type ScaleWord } from "./amount-scale.ts";
|
|
6
|
+
import type { StructureIssue } from "./issues.ts";
|
|
7
|
+
|
|
8
|
+
/** One amount written with its currency. scale is the value of the word of scale written in it (万, million), if any. */
|
|
9
|
+
export type RangeAmount = {
|
|
10
|
+
readonly offset: number;
|
|
11
|
+
readonly end: number;
|
|
12
|
+
readonly currency: string;
|
|
13
|
+
readonly value: number;
|
|
14
|
+
readonly scale: number | undefined;
|
|
15
|
+
readonly position: "before" | "after";
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export type AmountRangeWords = {
|
|
19
|
+
/** The marks and words that make a range on their own (〜, –, to). */
|
|
20
|
+
readonly connectors: readonly string[];
|
|
21
|
+
/** Words that make a range only when a closer follows the second amount (から … まで). */
|
|
22
|
+
readonly openers: readonly string[];
|
|
23
|
+
readonly closers: readonly string[];
|
|
24
|
+
/** Words that, in the same sentence, make a descending pair a change of price and not a range (値下げ, reduced). */
|
|
25
|
+
readonly changes: readonly string[];
|
|
26
|
+
/** Labels of the lower and upper bound (下限, min; 上限, max) and the particles that may follow a label (は, of). */
|
|
27
|
+
readonly lowers: readonly string[];
|
|
28
|
+
readonly uppers: readonly string[];
|
|
29
|
+
readonly links: readonly string[];
|
|
30
|
+
/** The words of scale (万, million, k) and the digits of a number (the currency reader's pattern). */
|
|
31
|
+
readonly scales: readonly ScaleWord[];
|
|
32
|
+
readonly number: string;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/** An end that took its word of scale from the other end (30〜25万円) is believed reversed only this close to the other. */
|
|
36
|
+
const MAX_INHERITED_RATIO = 10;
|
|
37
|
+
|
|
38
|
+
const SEPARATORS = /[\s・、,,;;//||::==()()「」..]/gu;
|
|
39
|
+
|
|
40
|
+
const LATIN = /^[A-Za-z]/u;
|
|
41
|
+
|
|
42
|
+
/** A Latin word is matched at word edges (cut does not match cutting); other scripts as written. */
|
|
43
|
+
const wordPattern = (word: string): string => {
|
|
44
|
+
const escaped = escapeRegExp(word.toLowerCase());
|
|
45
|
+
return LATIN.test(word) ? `(?<![a-z])${escaped}(?![a-z])` : escaped;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const hasWord = (text: string, words: readonly string[]): boolean => words.some((word) => new RegExp(wordPattern(word), "u").test(text.toLowerCase()));
|
|
49
|
+
|
|
50
|
+
const isOneOf = (text: string, words: readonly string[]): boolean => words.some((word) => word.toLowerCase() === text.toLowerCase());
|
|
51
|
+
|
|
52
|
+
const lineBounds = (text: string, offset: number): { readonly start: number; readonly end: number } => {
|
|
53
|
+
const end = text.indexOf("\n", offset);
|
|
54
|
+
return { start: text.lastIndexOf("\n", offset - 1) + 1, end: end === -1 ? text.length : end };
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
/** A sentence ends at 。, or at a full stop followed by a capital or the line end (e.g. does not end one). */
|
|
58
|
+
const SENTENCE_END = /[。!?]|[.!?](?=\s+[A-Z]|\s*$)/gu;
|
|
59
|
+
|
|
60
|
+
/** The sentence holding the range, within its line. */
|
|
61
|
+
const sentenceAround = (text: string, start: number, end: number): string => {
|
|
62
|
+
const line = lineBounds(text, start);
|
|
63
|
+
const ends = [...text.slice(line.start, line.end).matchAll(SENTENCE_END)].map((match) => line.start + match.index);
|
|
64
|
+
const from = ends.filter((at) => at < start).at(-1) ?? line.start;
|
|
65
|
+
const to = ends.find((at) => at >= end) ?? line.end;
|
|
66
|
+
return text.slice(from, to);
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
/** What follows the second amount, on its line, without leading spaces. */
|
|
70
|
+
const restOfLine = (text: string, end: number): string => text.slice(end, lineBounds(text, end).end).trimStart();
|
|
71
|
+
|
|
72
|
+
const ARITHMETIC = /[==]/u;
|
|
73
|
+
|
|
74
|
+
/** Whether the joint between two ends makes them a range: a connector, or an opener with a closer after the second end. */
|
|
75
|
+
const joinsRange = (joint: string, after: string, words: AmountRangeWords): boolean => {
|
|
76
|
+
if (joint.includes("\n")) return false;
|
|
77
|
+
const bare = joint.trim();
|
|
78
|
+
return isOneOf(bare, words.connectors) || (isOneOf(bare, words.openers) && words.closers.some((closer) => after.startsWith(closer)));
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
type End = { readonly offset: number; readonly end: number; readonly value: number; readonly inherited: boolean };
|
|
82
|
+
|
|
83
|
+
type Pair = readonly [End, End];
|
|
84
|
+
|
|
85
|
+
const pairOf = (low: End, high: End): Pair => [low, high];
|
|
86
|
+
|
|
87
|
+
/** A number as written, with the value of its word of scale (undefined when it has none). */
|
|
88
|
+
type Reading = { readonly offset: number; readonly end: number; readonly value: number; readonly scale: number | undefined };
|
|
89
|
+
|
|
90
|
+
const scaleOf = (word: string | undefined, words: AmountRangeWords): number | undefined =>
|
|
91
|
+
word === undefined ? undefined : words.scales.find((scale) => scale.word.toLowerCase() === word.toLowerCase())?.value;
|
|
92
|
+
|
|
93
|
+
const alternation = (patterns: readonly string[]): string => patterns.toSorted((left, right) => right.length - left.length).join("|");
|
|
94
|
+
|
|
95
|
+
const scalePart = (words: AmountRangeWords): string => {
|
|
96
|
+
const scales = alternation(words.scales.map((scale) => escapeRegExp(scale.word)));
|
|
97
|
+
return scales === "" ? "" : `(?:\\s?(${scales}))?`;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const jointPart = (words: AmountRangeWords): string => `(\\s?(?:${alternation([...words.connectors, ...words.openers].map(wordPattern))})\\s?)`;
|
|
101
|
+
|
|
102
|
+
/** A bare number (no currency) and its word of scale, if any. */
|
|
103
|
+
const bareReading = (
|
|
104
|
+
span: { readonly offset: number; readonly end: number },
|
|
105
|
+
digits: string,
|
|
106
|
+
scaleWord: string | undefined,
|
|
107
|
+
words: AmountRangeWords,
|
|
108
|
+
): Reading | undefined => {
|
|
109
|
+
const value = amountValue(digits, []);
|
|
110
|
+
if (value === undefined) return undefined;
|
|
111
|
+
const scale = scaleOf(scaleWord, words);
|
|
112
|
+
return { ...span, value: scale === undefined ? value : value * scale, scale };
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
/** One end of a range written with the word of scale only once: the end without one reads it from the other (30〜25万円, $90–70k). */
|
|
116
|
+
const sharing = (own: Reading, other: Reading): End =>
|
|
117
|
+
own.scale === undefined && other.scale !== undefined
|
|
118
|
+
? { offset: own.offset, end: own.end, value: own.value * other.scale, inherited: true }
|
|
119
|
+
: { offset: own.offset, end: own.end, value: own.value, inherited: false };
|
|
120
|
+
|
|
121
|
+
const sharedPair = (first: Reading, second: Reading): Pair => pairOf(sharing(first, second), sharing(second, first));
|
|
122
|
+
|
|
123
|
+
/** The bare number right before a currency-after amount, joined to it (30〜 before 25万円), sharing its currency. */
|
|
124
|
+
const sharedBefore = (text: string, amount: RangeAmount, floor: number, words: AmountRangeWords): Pair | undefined => {
|
|
125
|
+
const pattern = new RegExp(`(?<![0-90-9.,,A-Za-z])(${words.number})${scalePart(words)}${jointPart(words)}$`, "iu");
|
|
126
|
+
const match = pattern.exec(text.slice(floor, amount.offset));
|
|
127
|
+
if (match === null || !joinsRange(match[3] ?? "", restOfLine(text, amount.end), words)) return undefined;
|
|
128
|
+
const offset = floor + match.index;
|
|
129
|
+
const bare = bareReading({ offset, end: offset + match[0].length - (match[3] ?? "").length }, match[1] ?? "", match[2], words);
|
|
130
|
+
return bare === undefined ? undefined : sharedPair(bare, amount);
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
/** The bare number right after a currency-before amount, joined to it ($90–70k), sharing its currency. */
|
|
134
|
+
const sharedAfter = (text: string, amount: RangeAmount, ceiling: number, words: AmountRangeWords): Pair | undefined => {
|
|
135
|
+
const pattern = new RegExp(`^${jointPart(words)}(${words.number})${scalePart(words)}(?![0-90-9A-Za-z])`, "iu");
|
|
136
|
+
const match = pattern.exec(text.slice(amount.end, ceiling));
|
|
137
|
+
if (match === null || !joinsRange(match[1] ?? "", restOfLine(text, amount.end + match[0].length), words)) return undefined;
|
|
138
|
+
const bare = bareReading({ offset: amount.end + (match[1] ?? "").length, end: amount.end + match[0].length }, match[2] ?? "", match[3], words);
|
|
139
|
+
return bare === undefined ? undefined : sharedPair(amount, bare);
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
const asEnd = (amount: RangeAmount): End => ({ offset: amount.offset, end: amount.end, value: amount.value, inherited: false });
|
|
143
|
+
|
|
144
|
+
/** Both ends written with their currency, joined by a connector. */
|
|
145
|
+
const writtenPair = (text: string, first: RangeAmount, second: RangeAmount, words: AmountRangeWords): Pair | undefined => {
|
|
146
|
+
if (first.currency !== second.currency) return undefined;
|
|
147
|
+
if (!joinsRange(text.slice(first.end, second.offset), restOfLine(text, second.end), words)) return undefined;
|
|
148
|
+
return pairOf(asEnd(first), asEnd(second));
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
const isReversed = ([low, high]: Pair): boolean => {
|
|
152
|
+
if (low.value <= high.value) return false;
|
|
153
|
+
return !(low.inherited || high.inherited) || low.value / high.value <= MAX_INHERITED_RATIO;
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
/** A pair is a range in a sentence that changes no price and holds no equation (5,000円-2,000円=3,000円). */
|
|
157
|
+
const readsAsRange = (text: string, [low, high]: Pair, words: AmountRangeWords): boolean => {
|
|
158
|
+
const start = Math.min(low.offset, high.offset);
|
|
159
|
+
const end = Math.max(low.end, high.end);
|
|
160
|
+
const sentence = sentenceAround(text, start, end);
|
|
161
|
+
return !ARITHMETIC.test(sentence) && !hasWord(sentence, words.changes);
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
/** The pairs of ends read as ranges: two written amounts, or one written amount and a bare number sharing its currency. */
|
|
165
|
+
const pairsOf = (text: string, amounts: readonly RangeAmount[], words: AmountRangeWords): Pair[] =>
|
|
166
|
+
amounts.flatMap((amount, index) => {
|
|
167
|
+
const previous = amounts[index - 1];
|
|
168
|
+
const next = amounts[index + 1];
|
|
169
|
+
const floor = Math.max(previous?.end ?? 0, lineBounds(text, amount.offset).start);
|
|
170
|
+
return [
|
|
171
|
+
previous === undefined ? undefined : writtenPair(text, previous, amount, words),
|
|
172
|
+
amount.position === "after" ? sharedBefore(text, amount, floor, words) : undefined,
|
|
173
|
+
amount.position === "before" ? sharedAfter(text, amount, next?.offset ?? text.length, words) : undefined,
|
|
174
|
+
].filter((pair) => pair !== undefined);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
/** Whether the text is only separators, particles, and at most the given label. */
|
|
178
|
+
const onlyLabel = (text: string, labels: readonly string[], words: AmountRangeWords): boolean => {
|
|
179
|
+
const rest = words.links.reduce((left, link) => left.replace(new RegExp(wordPattern(link), "giu"), " "), text.toLowerCase()).replace(SEPARATORS, "");
|
|
180
|
+
return rest === "" || isOneOf(rest, labels);
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
/** The label written right before the amount, past separators and particles: lower, upper, or none. */
|
|
184
|
+
const labelBefore = (text: string, amount: RangeAmount, floor: number, words: AmountRangeWords): "lower" | "upper" | undefined => {
|
|
185
|
+
const before = text.slice(floor, amount.offset).toLowerCase();
|
|
186
|
+
const ends = (labels: readonly string[]): boolean =>
|
|
187
|
+
labels.some((label) => {
|
|
188
|
+
const match = new RegExp(`^[^]*${wordPattern(label)}([^]*)$`, "u").exec(before);
|
|
189
|
+
return match !== null && onlyLabel(match[1] ?? "", [], words);
|
|
190
|
+
});
|
|
191
|
+
if (ends(words.lowers)) return "lower";
|
|
192
|
+
return ends(words.uppers) ? "upper" : undefined;
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
/** Two adjacent amounts on one line labelled lower and upper bound (下限30万円・上限25万円), in either order. */
|
|
196
|
+
const labelledPairs = (text: string, amounts: readonly RangeAmount[], words: AmountRangeWords): Pair[] =>
|
|
197
|
+
amounts.slice(1).flatMap((second, index) => {
|
|
198
|
+
const first = amounts[index];
|
|
199
|
+
if (first === undefined || first.currency !== second.currency || text.slice(first.end, second.offset).includes("\n")) return [];
|
|
200
|
+
const floor = Math.max(amounts[index - 1]?.end ?? 0, lineBounds(text, first.offset).start);
|
|
201
|
+
const firstLabel = labelBefore(text, first, floor, words);
|
|
202
|
+
const secondLabel = labelBefore(text, second, first.end, words);
|
|
203
|
+
if (firstLabel === undefined || secondLabel === undefined || firstLabel === secondLabel) return [];
|
|
204
|
+
if (!onlyLabel(text.slice(first.end, second.offset), [...words.lowers, ...words.uppers], words)) return [];
|
|
205
|
+
return [firstLabel === "lower" ? pairOf(asEnd(first), asEnd(second)) : pairOf(asEnd(second), asEnd(first))];
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
const issueOf = (text: string, [low, high]: Pair): StructureIssue => {
|
|
209
|
+
const start = Math.min(low.offset, high.offset);
|
|
210
|
+
return { offset: start, values: { range: text.slice(start, Math.max(low.end, high.end)).trim() } };
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
/** The ranges of amounts, written or labelled, whose upper end is below the lower one, once per place, in document order. */
|
|
214
|
+
export const reversedAmountRanges = (text: string, amounts: readonly RangeAmount[], words: AmountRangeWords): StructureIssue[] =>
|
|
215
|
+
[...pairsOf(text, amounts, words), ...labelledPairs(text, amounts, words)]
|
|
216
|
+
.filter((pair) => isReversed(pair) && readsAsRange(text, pair, words))
|
|
217
|
+
.map((pair) => issueOf(text, pair))
|
|
218
|
+
.toSorted((left, right) => left.offset - right.offset)
|
|
219
|
+
.filter((issue, index, issues) => issues[index - 1]?.offset !== issue.offset);
|
|
@@ -73,6 +73,24 @@ export const scaleMixes = (amounts: readonly ScaledAmount[]): ScaleMix[] => {
|
|
|
73
73
|
.toSorted((left, right) => left.odd.offset - right.odd.offset);
|
|
74
74
|
};
|
|
75
75
|
|
|
76
|
+
/** The largest number of significant digits a round figure has (130万円, $1.5 million): a rounded total or a cap. */
|
|
77
|
+
const ROUND_DIGITS = 2;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Leaves out a round figure in the text (約130万円, a cap of $1.5 million) whose only evidence is the exact amounts of a
|
|
81
|
+
* table, none of them the same amount: the text gives the round size and the table the detail, which is not one amount
|
|
82
|
+
* written two ways. The same amount in the table (220万円 and 2,200,000円) stays a mix, and so does a mix within the text.
|
|
83
|
+
*/
|
|
84
|
+
export const withoutRoundTextFigures = (mixes: readonly ScaleMix[], amounts: readonly ScaledAmount[], inTable: (amount: ScaledAmount) => boolean): ScaleMix[] =>
|
|
85
|
+
mixes.filter(({ odd }) => {
|
|
86
|
+
if (inTable(odd) || significantDigits(odd.value) > ROUND_DIGITS) return true;
|
|
87
|
+
const others = amounts.filter(
|
|
88
|
+
(amount) =>
|
|
89
|
+
comparable(amount) && amount.currency === odd.currency && magnitudeOf(amount.value) === magnitudeOf(odd.value) && isScaled(amount) !== isScaled(odd),
|
|
90
|
+
);
|
|
91
|
+
return others.some((amount) => !inTable(amount) || amount.value === odd.value);
|
|
92
|
+
});
|
|
93
|
+
|
|
76
94
|
/** A word of scale and the value it multiplies by (万 10000, million 1000000). */
|
|
77
95
|
export type ScaleWord = { readonly word: string; readonly value: number };
|
|
78
96
|
|
package/src/structure/cite.ts
CHANGED
|
@@ -4,14 +4,18 @@ import { lineStarts, placeOf } from "../position.ts";
|
|
|
4
4
|
// 回答の引用が原文にあるか。番地が木にあり、引用した文がその番地の範囲に書かれていれば一致。
|
|
5
5
|
// 意味が合っているかは見ない。書いてあるかどうかだけを、機械で決める。
|
|
6
6
|
|
|
7
|
+
/** address: where in the source the quote is, as `chaff tree` names it. Empty: anywhere in the source. */
|
|
7
8
|
export type Citation = { readonly address: string; readonly quote: string };
|
|
8
9
|
|
|
10
|
+
/** The address a citation leaves empty: it says the quote is somewhere in the source, not where. */
|
|
11
|
+
export const isAnywhere = (citation: Citation): boolean => citation.address.trim() === "";
|
|
12
|
+
|
|
9
13
|
export type CitationStatus = "ok" | "missing-address" | "quote-elsewhere" | "quote-not-found";
|
|
10
14
|
|
|
11
15
|
export type CitationResult = {
|
|
12
16
|
readonly citation: Citation;
|
|
13
17
|
readonly status: CitationStatus;
|
|
14
|
-
/** 引用文が原文で見つかった位置の、いちばん内側の番地。quote-elsewhere
|
|
18
|
+
/** 引用文が原文で見つかった位置の、いちばん内側の番地。quote-elsewhere のとき、本当はどこに書いてあるか。番地を書かない引用では、見つかった場所。 */
|
|
15
19
|
readonly foundAt?: string;
|
|
16
20
|
/** 引用文が見つかった行。引用文が空なら、番地の行。 */
|
|
17
21
|
readonly line?: number;
|
|
@@ -84,9 +88,23 @@ const innermostHolding = (nodes: readonly Addressed[], occurrence: Occurrence):
|
|
|
84
88
|
.filter(({ node }) => within(node, occurrence))
|
|
85
89
|
.reduce<Addressed | undefined>((best, current) => (best === undefined || current.depth > best.depth ? current : best), undefined)?.node.address;
|
|
86
90
|
|
|
91
|
+
/**
|
|
92
|
+
* 番地を書かない引用。原文のどこかに書いてあれば一致で、見つかった場所の番地と行を添える。番地の無い原文(見出しの無い記事)にも使える。
|
|
93
|
+
* 引用文も空なら、何も示していないので番地が無いとする。一致にすると、書き忘れた引用が通る。
|
|
94
|
+
*/
|
|
95
|
+
const anywhere = (citation: Citation, whole: Normalized, nodes: readonly Addressed[], starts: readonly number[]): CitationResult => {
|
|
96
|
+
const key = normalize(citation.quote).text;
|
|
97
|
+
if (key === "") return { citation, status: "missing-address" };
|
|
98
|
+
const at = whole.text.indexOf(key);
|
|
99
|
+
if (at === -1) return { citation, status: "quote-not-found" };
|
|
100
|
+
const occurrence = { start: whole.index[at] ?? 0, last: whole.index[at + key.length - 1] ?? 0 };
|
|
101
|
+
const foundAt = innermostHolding(nodes, occurrence);
|
|
102
|
+
return { citation, status: "ok", line: placeOf(starts, occurrence.start).line, ...(foundAt === undefined ? {} : { foundAt }) };
|
|
103
|
+
};
|
|
104
|
+
|
|
87
105
|
/**
|
|
88
106
|
* 引用を一件ずつ確かめる。source は木を作った原文そのもの。
|
|
89
|
-
*
|
|
107
|
+
* 引用文が空(空白だけ)なら番地だけを確かめる。番地が空なら、原文のどこかにあるかだけを確かめる。同じ番地が二つある(附則が第1条から振り直す)ときは、どちらかにあれば一致。
|
|
90
108
|
* 原文は一度だけ揃え、引用ごとには番地の範囲を揃え直さない。長い契約書に引用が何百とあっても、引用ごとの代金は原文の長さに比例するだけ。
|
|
91
109
|
*/
|
|
92
110
|
export const checkCitations = (source: string, tree: StructureNode, citations: readonly Citation[]): CitationResult[] => {
|
|
@@ -100,6 +118,7 @@ export const checkCitations = (source: string, tree: StructureNode, citations: r
|
|
|
100
118
|
const whole = normalize(source);
|
|
101
119
|
const starts = lineStarts(source);
|
|
102
120
|
return citations.map((citation): CitationResult => {
|
|
121
|
+
if (isAnywhere(citation)) return anywhere(citation, whole, nodes, starts);
|
|
103
122
|
// 第 1 項に番号の無い書き方では、「12.1」は第12条そのもの。参照の fallback と同じに読む。
|
|
104
123
|
const firstParagraph = citation.address.endsWith(".1") ? byAddress.get(citation.address.slice(0, -2)) : undefined;
|
|
105
124
|
const candidates = byAddress.get(citation.address) ?? firstParagraph ?? [];
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { Amount } from "./total.ts";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 数を足してよい助数詞(16単位、4コマ、3 credits)が付いた数。解析器が助数詞と読まない語(単位、コマ)もここで数量にする。
|
|
5
|
+
* 助数詞の語は total-mismatch の語彙表(summed-counter)から取る。同じ組(group)の語(credit と credits)は同じ単位として足す。
|
|
6
|
+
*/
|
|
7
|
+
export type SummedCounter = { readonly pattern: string; readonly unit: string };
|
|
8
|
+
|
|
9
|
+
/** 前に英字や数や小数点が続く数(v2、A4、1.2.3 の 2)は読まない。日本語は数の前に空白を置かないので、仮名や漢字の後ろはよい。 */
|
|
10
|
+
const NUMBER = /(?<![\p{Script=Latin}\p{N}.,.,])[0-90-9]+(?:[,,][0-90-9]{3})*(?:[..][0-90-9]+)?/gu;
|
|
11
|
+
|
|
12
|
+
/** 助数詞に文字や数、つなぎの - _ が詰めて続くもの(3単位目、4コマ漫画、3 unit-priced)は、別の語の一部。 */
|
|
13
|
+
const CONTINUES_WORD = /^[\p{L}\p{N}_-]/u;
|
|
14
|
+
|
|
15
|
+
/** 序数の印(第3回)。 */
|
|
16
|
+
const ORDINAL_MARK = "第";
|
|
17
|
+
|
|
18
|
+
/** 助数詞を探す長さ。どの助数詞よりも長い。 */
|
|
19
|
+
const LOOKAHEAD = 32;
|
|
20
|
+
|
|
21
|
+
const valueOf = (written: string): number => Number(written.normalize("NFKC").replace(/,/gu, ""));
|
|
22
|
+
|
|
23
|
+
/** 数のすぐ後ろ(空白一つまで)の助数詞。長い語から試す。大文字小文字は区別しない(4 Credits)。 */
|
|
24
|
+
const counterAfter = (source: string, end: number, counters: readonly SummedCounter[]): { unit: string; end: number } | undefined => {
|
|
25
|
+
const gap = source.charAt(end) === " " ? 1 : 0;
|
|
26
|
+
const rest = source.slice(end + gap, end + gap + LOOKAHEAD).toLowerCase();
|
|
27
|
+
const counter = counters.find((candidate) => rest.startsWith(candidate.pattern.toLowerCase()) && !CONTINUES_WORD.test(rest.slice(candidate.pattern.length)));
|
|
28
|
+
return counter === undefined ? undefined : { unit: counter.unit, end: end + gap + counter.pattern.length };
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const overlapsAny = (start: number, end: number, amounts: readonly Amount[]): boolean => amounts.some((amount) => start < amount.end && amount.offset < end);
|
|
32
|
+
|
|
33
|
+
/** 文書の中の、足してよい助数詞の付いた数。木がすでに数量として読んだもの(known)とは重ねない。 */
|
|
34
|
+
export const countedAmounts = (source: string, counters: readonly SummedCounter[], known: readonly Amount[]): Amount[] => {
|
|
35
|
+
const longestFirst = counters.toSorted((left, right) => right.pattern.length - left.pattern.length);
|
|
36
|
+
return [...source.matchAll(NUMBER)].flatMap((match): Amount[] => {
|
|
37
|
+
if (source.charAt(match.index - 1) === ORDINAL_MARK) return [];
|
|
38
|
+
const found = counterAfter(source, match.index + match[0].length, longestFirst);
|
|
39
|
+
if (found === undefined || overlapsAny(match.index, found.end, known)) return [];
|
|
40
|
+
return [{ offset: match.index, end: found.end, value: valueOf(match[0]), unit: found.unit }];
|
|
41
|
+
});
|
|
42
|
+
};
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import type { StructureIssue } from "./issues.ts";
|
|
2
|
-
import {
|
|
2
|
+
import { siblingHeadingRunsOf } from "./heading-runs.ts";
|
|
3
|
+
import { runsOf } from "./runs.ts";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
6
|
+
* 日程として並べた日付の順番。箇条書きの続いた項目、表の続いた行、同じ親の下で同じ深さに並ぶ見出しで、
|
|
7
|
+
* 日付をちょうど一つ持つものを並びとして読む。
|
|
8
|
+
* 並びの向き(古い順か新しい順か)は多いほうで決め、それに逆らう一歩ごとに、その前後のうち並びから外れた日付を言う。新しい順に並べた履歴は正しい並び。
|
|
7
9
|
* 向きが決まらない並び(上がりと下がりが同じ数)は何も言わない。逆らう一歩を言えるのは、日付が 4 つ以上の並びだけになる。
|
|
8
10
|
* 向きに沿って並ぶ日付が半分以下の並びは、日付でなく別のもの(名前、版)で並べた一覧として何も言わない。
|
|
9
11
|
*/
|
|
@@ -12,13 +14,41 @@ export type DatedPoint = { readonly offset: number; readonly value: string };
|
|
|
12
14
|
/** 並びとして比べられる日付の書き方。年月日、年月、月日は、同じ書き方どうしでしか比べない。 */
|
|
13
15
|
const PRECISIONS = [/^\d{4}-\d{2}-\d{2}$/u, /^\d{4}-\d{2}$/u, /^\d{2}-\d{2}$/u];
|
|
14
16
|
|
|
15
|
-
/**
|
|
16
|
-
|
|
17
|
+
/** 並びの一行(箇条書きの項目、表の行、見出し)の原文の範囲。 */
|
|
18
|
+
type Span = { readonly start: number; readonly end: number };
|
|
19
|
+
|
|
20
|
+
/** 見出しの深さと原文の範囲。 */
|
|
21
|
+
export type HeadingSpan = Span & { readonly depth: number };
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* 同じ親の下で同じ深さに並ぶ見出し(変更履歴の版ごとの見出し)。浅い見出しが来たら、それより深い並びは閉じる。
|
|
25
|
+
* 深い見出し(### 追加)は並びを切らず、親ごとに別の並びになる。
|
|
26
|
+
*/
|
|
27
|
+
export const siblingHeadingRuns = (headings: readonly HeadingSpan[]): HeadingSpan[][] => siblingHeadingRunsOf(headings, (heading) => heading);
|
|
28
|
+
|
|
29
|
+
/** 一行のただ一つの日付。二つある行(期間)はどちらを並べたのか決められないので、並びに入れない。 */
|
|
30
|
+
const onlyDateIn = (line: Span, points: readonly DatedPoint[]): DatedPoint | undefined => {
|
|
31
|
+
const inside = points.filter((point) => point.offset >= line.start && point.offset <= line.end);
|
|
32
|
+
return inside.length === 1 ? inside[0] : undefined;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const datedLines = (run: readonly Span[], points: readonly DatedPoint[]): DatedPoint[] =>
|
|
17
36
|
run.flatMap((line) => {
|
|
18
|
-
const
|
|
19
|
-
return
|
|
37
|
+
const date = onlyDateIn(line, points);
|
|
38
|
+
return date === undefined ? [] : [date];
|
|
20
39
|
});
|
|
21
40
|
|
|
41
|
+
/** 見出しの並びは、日付を一つ持つ見出しが続くあいだだけ。日付の無い見出しが混じる並び(問いに更新日を添えた FAQ)は、日付で並べたものではない。 */
|
|
42
|
+
const datedStretches = (run: readonly Span[], points: readonly DatedPoint[]): DatedPoint[][] =>
|
|
43
|
+
run.reduce<DatedPoint[][]>(
|
|
44
|
+
(stretches, heading) => {
|
|
45
|
+
const date = onlyDateIn(heading, points);
|
|
46
|
+
if (date === undefined) return [...stretches, []];
|
|
47
|
+
return [...stretches.slice(0, -1), [...(stretches.at(-1) ?? []), date]];
|
|
48
|
+
},
|
|
49
|
+
[[]],
|
|
50
|
+
);
|
|
51
|
+
|
|
22
52
|
const samePrecision = (dated: readonly DatedPoint[]): boolean => PRECISIONS.some((pattern) => dated.every((point) => pattern.test(point.value)));
|
|
23
53
|
|
|
24
54
|
/** 上がりが多ければ 1、下がりが多ければ -1、同じ数なら 0(向きを決めない)。 */
|
|
@@ -37,23 +67,43 @@ export const longestInOrder = (values: readonly string[], direction: number): nu
|
|
|
37
67
|
/** 日付のうち向きに沿うものが過半を占める。ひとつふたつの書き間違いなら残りが揃うが、名前順の一覧は揃わない。 */
|
|
38
68
|
const mostlyInOrder = (values: readonly string[], direction: number): boolean => longestInOrder(values, direction) * 2 > values.length;
|
|
39
69
|
|
|
40
|
-
|
|
70
|
+
const without = (values: readonly string[], index: number): string[] => values.filter((_, at) => at !== index);
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* 向きに逆らう一歩(at - 1 から at)のうち、並びから外れているほう。取り除いたとき残りが長く揃うほうを指す。
|
|
74
|
+
* 前を取っても後ろを取っても同じだけ揃う(隣どうしの入れ替わり)なら、どちらとも決められないので後ろを指す。
|
|
75
|
+
*/
|
|
76
|
+
export const outOfPlace = (values: readonly string[], at: number, direction: number): number =>
|
|
77
|
+
longestInOrder(without(values, at - 1), direction) > longestInOrder(without(values, at), direction) ? at - 1 : at;
|
|
78
|
+
|
|
79
|
+
/** 外れた日付に、前の日付を添える。先頭の日付には前が無いので、次の日付を添える。 */
|
|
80
|
+
const issueAt = (dated: readonly DatedPoint[], at: number): StructureIssue[] => {
|
|
81
|
+
const point = dated[at];
|
|
82
|
+
if (point === undefined) return [];
|
|
83
|
+
const neighbour = at === 0 ? { next: dated[1]?.value ?? "" } : { previous: dated[at - 1]?.value ?? "" };
|
|
84
|
+
return [{ offset: point.offset, values: { date: point.value, ...neighbour } }];
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
/** 多いほうの向きに逆らう一歩ごとに、並びから外れた日付を指す。 */
|
|
41
88
|
const againstMajority = (dated: readonly DatedPoint[]): StructureIssue[] => {
|
|
42
|
-
const steps = dated
|
|
43
|
-
.slice(1)
|
|
44
|
-
.map((point, index) => ({ point, previous: dated[index], sign: Math.sign(point.value.localeCompare(dated[index]?.value ?? "")) }));
|
|
45
|
-
const up = steps.filter((step) => step.sign > 0).length;
|
|
46
|
-
const down = steps.filter((step) => step.sign < 0).length;
|
|
47
|
-
const majority = majorityOf(up, down);
|
|
48
89
|
const values = dated.map((point) => point.value);
|
|
90
|
+
const signs = values.slice(1).map((value, index) => Math.sign(value.localeCompare(values[index] ?? "")));
|
|
91
|
+
const majority = majorityOf(signs.filter((sign) => sign > 0).length, signs.filter((sign) => sign < 0).length);
|
|
49
92
|
if (majority === 0 || !mostlyInOrder(values, majority)) return [];
|
|
50
|
-
return
|
|
51
|
-
|
|
52
|
-
|
|
93
|
+
return signs.flatMap((sign, index) => {
|
|
94
|
+
if (sign !== -majority) return [];
|
|
95
|
+
return issueAt(dated, outOfPlace(values, index + 1, majority));
|
|
96
|
+
});
|
|
53
97
|
};
|
|
54
98
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
99
|
+
const breaksIn = (dated: readonly DatedPoint[]): StructureIssue[] => (samePrecision(dated) ? againstMajority(dated) : []);
|
|
100
|
+
|
|
101
|
+
/** 見出しを箇条書きの中に書けば(「- ## 3.1.0 - 2026-10-02」)、同じ日付が両方の並びに入る。一度だけ言う。 */
|
|
102
|
+
const oncePerOffset = (issues: readonly StructureIssue[]): StructureIssue[] =>
|
|
103
|
+
issues.filter((issue, index) => issues.findIndex((other) => other.offset === issue.offset) === index);
|
|
104
|
+
|
|
105
|
+
export const dateOrderBreaks = (source: string, points: readonly DatedPoint[], headings: readonly HeadingSpan[] = []): StructureIssue[] =>
|
|
106
|
+
oncePerOffset([
|
|
107
|
+
...runsOf(source).flatMap((run) => breaksIn(datedLines(run, points))),
|
|
108
|
+
...siblingHeadingRuns(headings).flatMap((run) => datedStretches(run, points).flatMap(breaksIn)),
|
|
109
|
+
]);
|