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,202 @@
|
|
|
1
|
+
import { nameKey } from "./name-variants.ts";
|
|
2
|
+
import { escapeRegExp } from "./orthography.ts";
|
|
3
|
+
|
|
4
|
+
// 会社の名前を、文書の中で二通りに書いた所(株式会社アオバシステム と アオバシステム株式会社、Aoba Systems Inc. と Aoba Systems Ltd.)。
|
|
5
|
+
// 会社の形の語(株式会社、Inc)は語彙表 company-form が言う。group が同じ語は同じ形(Inc と Incorporated、株式会社 と (株))、
|
|
6
|
+
// position は名前のどちら側に立つか(無ければどちらにも立つ)。名前の部分は、形の語のすぐ隣の、名前に使う字の連なり。
|
|
7
|
+
|
|
8
|
+
export type CompanyForm = { readonly pattern: string; readonly group: string; readonly position?: "before" | "after" | undefined };
|
|
9
|
+
|
|
10
|
+
/** surface は形の語も含めた書いたまま。base は名前の部分、form は形の組、position は形の語が名前のどちら側にあるか。 */
|
|
11
|
+
export type CompanyMention = {
|
|
12
|
+
readonly surface: string;
|
|
13
|
+
readonly offset: number;
|
|
14
|
+
readonly base: string;
|
|
15
|
+
readonly form: string;
|
|
16
|
+
readonly position: "before" | "after";
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/** 二つの書き方の違い。spelling は記号・幅・大小だけ、form は会社の形、position は形の語の側、near は名前の一字違い。 */
|
|
20
|
+
type CompanyRelation = "spelling" | "form" | "position" | "near";
|
|
21
|
+
|
|
22
|
+
type CompanyVariant = { readonly mention: CompanyMention; readonly usual: string; readonly kind: CompanyRelation };
|
|
23
|
+
|
|
24
|
+
/** 名前の部分が、品詞解析が固有名詞と読んだ語に掛かるか。漢字だけの名前(清算、当該)は、ふつうの語と区別がつかない。 */
|
|
25
|
+
export type IsProper = (start: number, end: number) => boolean;
|
|
26
|
+
|
|
27
|
+
const LATIN = /\p{Script=Latin}/u;
|
|
28
|
+
const LETTER = /\p{L}/u;
|
|
29
|
+
/** 漢字・かなの名前に使う字。ひらがなは名前の外(の、は、まで)。 */
|
|
30
|
+
const CJK_NAME = /[\p{Script=Katakana}\p{Script=Han}\p{Script=Latin}\p{N}ー・&&]/u;
|
|
31
|
+
const NOT_HAN_LETTER = /(?!\p{Script=Han})\p{L}/u;
|
|
32
|
+
/** 英字の名前の一語。大文字か数字で始まる。 */
|
|
33
|
+
const LATIN_WORD = /^[\p{Lu}\p{N}][\p{L}\p{N}&'’.-]*$/u;
|
|
34
|
+
const AMPERSAND = "&";
|
|
35
|
+
/** 形の語のすぐあとに空白一つで大文字の語が続けば、形の語は長い名前の一部(Limited Partnership、Corporation Tax)。Inc. のあとの文や行は続きでない。 */
|
|
36
|
+
const CONTINUED = /^ \p{Lu}/u;
|
|
37
|
+
|
|
38
|
+
const occurrencesOf = (source: string, pattern: string): number[] => [...source.matchAll(new RegExp(escapeRegExp(pattern), "gu"))].map((match) => match.index);
|
|
39
|
+
|
|
40
|
+
/** 英字の語の続き。ハイフンでつないだ語(Limited-time)も一つの語。 */
|
|
41
|
+
const WORD_CONTINUES = /[\p{L}\p{N}-]/u;
|
|
42
|
+
|
|
43
|
+
/** 英字の形の語は、語の続き(Including の Inc、Limited-time の Limited)では形の語と読まない。 */
|
|
44
|
+
const standsAsWord = (source: string, pattern: string, at: number): boolean =>
|
|
45
|
+
!LATIN.test(pattern) || (!LETTER.test(source.charAt(at - 1)) && !WORD_CONTINUES.test(source.charAt(at + pattern.length)));
|
|
46
|
+
|
|
47
|
+
type Span = { readonly start: number; readonly end: number };
|
|
48
|
+
|
|
49
|
+
/** 英字の名前: 形の語の前の、大文字で始まる語の続き。頭の、固有名詞と読めない語(文頭の Contact)は外す。 */
|
|
50
|
+
const latinBaseBefore = (source: string, end: number, isProper: IsProper): Span | undefined => {
|
|
51
|
+
const before = source.slice(0, end).replace(/,?\s$/u, "");
|
|
52
|
+
const words = [...before.matchAll(/\S+/gu)].map((match): Span => ({ start: match.index, end: match.index + match[0].length }));
|
|
53
|
+
const isNameWord = (span: Span): boolean => {
|
|
54
|
+
const word = source.slice(span.start, span.end);
|
|
55
|
+
return LATIN_WORD.test(word) || word === AMPERSAND;
|
|
56
|
+
};
|
|
57
|
+
const run = words.slice(
|
|
58
|
+
words.findLastIndex((span, index) => !isNameWord(span) || before.slice(span.end, words[index + 1]?.start ?? before.length).includes("\n")) + 1,
|
|
59
|
+
);
|
|
60
|
+
const first = run.find((span) => isProper(span.start, span.end));
|
|
61
|
+
return first === undefined ? undefined : { start: first.start, end: before.length };
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const CJK_BEFORE = new RegExp(`${CJK_NAME.source}+$`, "u");
|
|
65
|
+
const CJK_AFTER = new RegExp(`^${CJK_NAME.source}+`, "u");
|
|
66
|
+
const SPACES: ReadonlySet<string> = new Set([" ", "\u3000"]);
|
|
67
|
+
|
|
68
|
+
/** 漢字・かなの名前: 形の語の隣の、名前に使う字の続き。形の語との間の空白一つは名前の外。 */
|
|
69
|
+
const cjkBaseBefore = (source: string, end: number): Span | undefined => {
|
|
70
|
+
const stop = SPACES.has(source.charAt(end - 1)) ? end - 1 : end;
|
|
71
|
+
const match = CJK_BEFORE.exec(source.slice(0, stop));
|
|
72
|
+
return match === null ? undefined : { start: match.index, end: stop };
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const cjkBaseAfter = (source: string, start: number): Span | undefined => {
|
|
76
|
+
const from = SPACES.has(source.charAt(start)) ? start + 1 : start;
|
|
77
|
+
const match = CJK_AFTER.exec(source.slice(from));
|
|
78
|
+
return match === null ? undefined : { start: from, end: from + match[0].length };
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
/** 名前の部分の字数。一字(法令の項目の印 イ、ロ)は名前と読まない。 */
|
|
82
|
+
const MIN_BASE_LENGTH = 2;
|
|
83
|
+
|
|
84
|
+
/** 名前と読めるか。二字以上で、記号で始まり終わらず、漢字だけなら固有名詞と読めるもの。 */
|
|
85
|
+
const isNameBase = (source: string, span: Span, isProper: IsProper): boolean => {
|
|
86
|
+
const base = source.slice(span.start, span.end);
|
|
87
|
+
if ([...base].length < MIN_BASE_LENGTH || /^[・&&]|[・&&]$/u.test(base)) return false;
|
|
88
|
+
return NOT_HAN_LETTER.test(base) || isProper(span.start, span.end);
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const mentionOf = (source: string, base: Span, form: Span, group: string): CompanyMention => {
|
|
92
|
+
const position = form.start < base.start ? "before" : "after";
|
|
93
|
+
const [start, end] = [Math.min(base.start, form.start), Math.max(base.end, form.end)];
|
|
94
|
+
return { surface: source.slice(start, end), offset: start, base: source.slice(base.start, base.end), form: group, position };
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const baseBefore = (source: string, at: number, latin: boolean, isProper: IsProper): Span | undefined =>
|
|
98
|
+
latin ? latinBaseBefore(source, at, isProper) : cjkBaseBefore(source, at);
|
|
99
|
+
|
|
100
|
+
/** 形の語の一つの現れから、会社の名前の現れ。名前が前にあればそれを、無ければ後ろを取る。 */
|
|
101
|
+
const mentionAt = (source: string, form: CompanyForm, at: number, isProper: IsProper): CompanyMention | undefined => {
|
|
102
|
+
const formSpan = { start: at, end: at + form.pattern.length };
|
|
103
|
+
const latin = LATIN.test(form.pattern);
|
|
104
|
+
if (latin && CONTINUED.test(source.slice(formSpan.end))) return undefined;
|
|
105
|
+
const before = form.position === "before" ? undefined : baseBefore(source, at, latin, isProper);
|
|
106
|
+
if (before !== undefined && isNameBase(source, before, isProper)) return mentionOf(source, before, formSpan, form.group);
|
|
107
|
+
const after = form.position === "after" || latin ? undefined : cjkBaseAfter(source, formSpan.end);
|
|
108
|
+
return after !== undefined && isNameBase(source, after, isProper) ? mentionOf(source, after, formSpan, form.group) : undefined;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
/** 文書の中の会社の名前の現れ。長い形の語(Co., Ltd)を先に取り、その中の短い語(Ltd)は数えない。 */
|
|
112
|
+
export const companyMentionsIn = (source: string, forms: readonly CompanyForm[], isProper: IsProper): CompanyMention[] => {
|
|
113
|
+
const taken: Span[] = [];
|
|
114
|
+
return forms
|
|
115
|
+
.toSorted((left, right) => right.pattern.length - left.pattern.length)
|
|
116
|
+
.flatMap((form) =>
|
|
117
|
+
occurrencesOf(source, form.pattern).flatMap((at) => {
|
|
118
|
+
const end = at + form.pattern.length;
|
|
119
|
+
if (!standsAsWord(source, form.pattern, at) || taken.some((span) => span.start < end && at < span.end)) return [];
|
|
120
|
+
taken.push({ start: at, end });
|
|
121
|
+
const mention = mentionAt(source, form, at, isProper);
|
|
122
|
+
return mention === undefined ? [] : [mention];
|
|
123
|
+
}),
|
|
124
|
+
)
|
|
125
|
+
.toSorted((left, right) => left.offset - right.offset);
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
const MIN_SLIP_LENGTH = 7;
|
|
129
|
+
|
|
130
|
+
const spliced = (chars: readonly string[], at: number, count: number): string => chars.toSpliced(at, count).join("");
|
|
131
|
+
const firstDifference = (left: readonly string[], right: readonly string[]): number => left.findIndex((char, index) => char !== right[index]);
|
|
132
|
+
|
|
133
|
+
/** 一字の抜けなら、その字。 */
|
|
134
|
+
const droppedChars = (longer: readonly string[], shorter: readonly string[]): string[] | undefined => {
|
|
135
|
+
if (longer.length !== shorter.length + 1) return undefined;
|
|
136
|
+
const at = firstDifference(longer, shorter);
|
|
137
|
+
return spliced(longer, at, 1) === shorter.join("") ? [longer[at] ?? ""] : undefined;
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
/** 一字の置き換えか、隣どうしの入れ替えなら、その字。 */
|
|
141
|
+
const replacedChars = (left: readonly string[], right: readonly string[]): string[] | undefined => {
|
|
142
|
+
const at = firstDifference(left, right);
|
|
143
|
+
const changed = [left[at] ?? "", right[at] ?? ""];
|
|
144
|
+
if (left.length !== right.length || at < 0) return undefined;
|
|
145
|
+
if (spliced(left, at, 1) === spliced(right, at, 1)) return changed;
|
|
146
|
+
const swapped = left[at] === right[at + 1] && left[at + 1] === right[at] && spliced(left, at, 2) === spliced(right, at, 2);
|
|
147
|
+
return swapped ? changed : undefined;
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* 名前の部分が一字違いか(置き換え・抜け・隣どうしの入れ替え)。違う字が漢字なら見ない。漢字の一字違い(日本電気 と 日本電機)
|
|
152
|
+
* は別の会社のことがある。短い名前(Alpha と Alpho)も別の会社のことが多い。
|
|
153
|
+
*/
|
|
154
|
+
const isSlip = (left: string, right: string): boolean => {
|
|
155
|
+
const [leftChars, rightChars] = [[...left], [...right]];
|
|
156
|
+
if (Math.min(leftChars.length, rightChars.length) < MIN_SLIP_LENGTH) return false;
|
|
157
|
+
const changed = replacedChars(leftChars, rightChars) ?? droppedChars(leftChars, rightChars) ?? droppedChars(rightChars, leftChars);
|
|
158
|
+
return changed !== undefined && changed.every((char) => NOT_HAN_LETTER.test(char));
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
/** 名前の部分が同じ二つ。同じ形の短い書き方と長い書き方(株式会社 と (株)、Inc と Incorporated)は書き分けと見ない。 */
|
|
162
|
+
const sameNameRelation = (left: CompanyMention, right: CompanyMention): CompanyRelation | undefined => {
|
|
163
|
+
if (left.form !== right.form) return "form";
|
|
164
|
+
if (left.position !== right.position) return "position";
|
|
165
|
+
return nameKey(left.surface) === nameKey(right.surface) ? "spelling" : undefined;
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* 二つの書き方が、同じ会社を二通りに書いたものか。名前の部分が同じ(記号・幅・大小を除いて)なら、形の組か形の語の側の違い、
|
|
170
|
+
* どちらも同じなら記号・幅・大小だけの違い。名前の部分が違うのは、形も側も同じで、漢字でない字の一字違いのときだけ(Aoba Systems と
|
|
171
|
+
* Aoba System)。名前の違う会社(親会社と子会社、別の取引先)は、名前の部分が一字より多く違うので同じと見ない。
|
|
172
|
+
*/
|
|
173
|
+
export const companyRelation = (left: CompanyMention, right: CompanyMention): CompanyRelation | undefined => {
|
|
174
|
+
if (left.surface === right.surface) return undefined;
|
|
175
|
+
const [leftKey, rightKey] = [nameKey(left.base), nameKey(right.base)];
|
|
176
|
+
if (leftKey === rightKey) return sameNameRelation(left, right);
|
|
177
|
+
return left.form === right.form && left.position === right.position && isSlip(leftKey, rightKey) ? "near" : undefined;
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
type Tally = { readonly first: CompanyMention; readonly count: number };
|
|
181
|
+
|
|
182
|
+
const talliesOf = (mentions: readonly CompanyMention[]): Tally[] => {
|
|
183
|
+
const tallies = new Map<string, Tally>();
|
|
184
|
+
mentions.forEach((mention) => {
|
|
185
|
+
const tally = tallies.get(mention.surface);
|
|
186
|
+
tallies.set(mention.surface, { first: tally?.first ?? mention, count: (tally?.count ?? 0) + 1 });
|
|
187
|
+
});
|
|
188
|
+
return [...tallies.values()];
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
/** 多いほうが先。同数なら先に書いたほう。 */
|
|
192
|
+
const byUsage = (left: Tally, right: Tally): number => right.count - left.count || left.first.offset - right.first.offset;
|
|
193
|
+
|
|
194
|
+
/** 同じ会社の、少ないほうの書き方。同じ会社と言える相手のうち一番多いものと比べる。書き方ごとに最初の現れを一つ。 */
|
|
195
|
+
export const companyVariants = (mentions: readonly CompanyMention[]): CompanyVariant[] => {
|
|
196
|
+
const tallies = talliesOf(mentions);
|
|
197
|
+
return tallies.flatMap((tally) => {
|
|
198
|
+
const [usual] = tallies.filter((other) => other === tally || companyRelation(tally.first, other.first) !== undefined).toSorted(byUsage);
|
|
199
|
+
const kind = usual === undefined || usual === tally ? undefined : companyRelation(tally.first, usual.first);
|
|
200
|
+
return usual === undefined || kind === undefined ? [] : [{ mention: tally.first, usual: usual.first.surface, kind }];
|
|
201
|
+
});
|
|
202
|
+
};
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
// One parameter's default stated two ways on a page: the signature says `width = 72`, the options table says 72, and the
|
|
2
|
+
// prose says "`width` defaults to 80". Pure; reads the Markdown source. The words of a default column (Default, 既定値)
|
|
3
|
+
// and of a default in prose (defaults to, の既定値は) come from the language's lexicons.
|
|
4
|
+
import { codeFences } from "./detectors/code-fences.ts";
|
|
5
|
+
|
|
6
|
+
/** Where a default is stated, from the most to the least authoritative: the code, a table, a sentence. */
|
|
7
|
+
type Source = "code" | "table" | "prose";
|
|
8
|
+
type Stated = { readonly name: string; readonly value: string; readonly offset: number; readonly source: Source };
|
|
9
|
+
|
|
10
|
+
/** A default that disagrees with the one the code (or else a table) states. */
|
|
11
|
+
export type DefaultSlip = { readonly name: string; readonly value: string; readonly offset: number; readonly expected: string };
|
|
12
|
+
|
|
13
|
+
export type DefaultWords = { readonly headers: readonly string[]; readonly phrases: readonly string[] };
|
|
14
|
+
|
|
15
|
+
type Line = { readonly text: string; readonly start: number };
|
|
16
|
+
|
|
17
|
+
const RANK: Readonly<Record<Source, number>> = { code: 0, table: 1, prose: 2 };
|
|
18
|
+
/** The values read: a code span, a quoted string, or a literal (a number, true, false, null). */
|
|
19
|
+
const QUOTED: readonly RegExp[] = [/^`([^`]+)`/u, /^"([^"]*)"/u, /^'([^']*)'/u];
|
|
20
|
+
const LITERAL = /^(?:-?\d+(?:\.\d+)?|true|false|True|False|null|none|None|undefined)(?!\w|\.\d)/u;
|
|
21
|
+
const NAME_SPAN = /`([A-Za-z_$][\w$]*)`/gu;
|
|
22
|
+
const IDENTIFIER = /^[A-Za-z_$][\w$]*/u;
|
|
23
|
+
const SPREAD = /^(?:\.\.\.|\*{1,2})/u;
|
|
24
|
+
/** How far after the name a default phrase may start: "`width` defaults to", "`width` の既定値は". */
|
|
25
|
+
const PHRASE_REACH = 4;
|
|
26
|
+
/** A declaration, not a call: a keyword first, or a return type after the list. A call's width=40 is an argument. */
|
|
27
|
+
const KEYWORD_FIRST = /^[ \t]*(?:(?:export|async)[ \t]+)*(?:def|function\*?|fn|func)[ \t]/u;
|
|
28
|
+
const RETURN_TYPE = /\)[ \t]*(?::|->)/u;
|
|
29
|
+
const DELIMITER_ROW = /^[ \t|:-]+$/u;
|
|
30
|
+
|
|
31
|
+
const linesOf = (source: string): Line[] => {
|
|
32
|
+
const starts = [0, ...[...source.matchAll(/\n/gu)].map((match) => match.index + 1)];
|
|
33
|
+
return starts.map((start, index) => ({ text: source.slice(start, (starts[index + 1] ?? source.length + 1) - 1), start }));
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const valueAt = (text: string): string | undefined => {
|
|
37
|
+
const trimmed = text.trimStart();
|
|
38
|
+
const quoted = QUOTED.map((pattern) => pattern.exec(trimmed)?.[1]).find((value) => value !== undefined);
|
|
39
|
+
return quoted ?? LITERAL.exec(trimmed)?.[0];
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/** The text between a line's first ( and the ) that closes it. */
|
|
43
|
+
const parameterList = (text: string): { readonly list: string; readonly from: number } | undefined => {
|
|
44
|
+
const open = text.indexOf("(");
|
|
45
|
+
const state = { depth: 0, close: -1 };
|
|
46
|
+
Array.from(text.slice(open)).some((char, index) => {
|
|
47
|
+
if (char === "(") state.depth += 1;
|
|
48
|
+
if (char === ")") state.depth -= 1;
|
|
49
|
+
if (state.depth === 0) state.close = open + index;
|
|
50
|
+
return state.depth === 0;
|
|
51
|
+
});
|
|
52
|
+
return open === -1 || state.close === -1 ? undefined : { list: text.slice(open + 1, state.close), from: open + 1 };
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/** width = 72, width: int = 72, *args: a parameter's name and its default value, if it has one. */
|
|
56
|
+
const parameterDefault = (part: string): { readonly name: string; readonly value: string } | undefined => {
|
|
57
|
+
const trimmed = part.trim().replace(SPREAD, "");
|
|
58
|
+
const name = IDENTIFIER.exec(trimmed)?.[0];
|
|
59
|
+
const equals = trimmed.search(/=(?!=)/u);
|
|
60
|
+
const value = equals === -1 ? undefined : valueAt(trimmed.slice(equals + 1));
|
|
61
|
+
return name === undefined || value === undefined ? undefined : { name, value };
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const QUOTES = "\"'`";
|
|
65
|
+
|
|
66
|
+
/** A parameter list split at its commas, leaving a comma inside quotes or brackets (sep = ", ") in its parameter. */
|
|
67
|
+
const splitParameters = (list: string): string[] => {
|
|
68
|
+
const state = { quote: "", depth: 0, from: 0 };
|
|
69
|
+
const parts: string[] = [];
|
|
70
|
+
[...list].forEach((char, index) => {
|
|
71
|
+
if (state.quote !== "") {
|
|
72
|
+
if (char === state.quote) state.quote = "";
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (QUOTES.includes(char)) state.quote = char;
|
|
76
|
+
if ("([{".includes(char)) state.depth += 1;
|
|
77
|
+
if (")]}".includes(char)) state.depth -= 1;
|
|
78
|
+
if (char !== "," || state.depth !== 0) return;
|
|
79
|
+
parts.push(list.slice(state.from, index));
|
|
80
|
+
state.from = index + 1;
|
|
81
|
+
});
|
|
82
|
+
return [...parts, list.slice(state.from)];
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const isDeclaration = (text: string): boolean => KEYWORD_FIRST.test(text) || RETURN_TYPE.test(text);
|
|
86
|
+
|
|
87
|
+
const inCodeLine = (line: Line, base: number): Stated[] => {
|
|
88
|
+
const params = isDeclaration(line.text) ? parameterList(line.text) : undefined;
|
|
89
|
+
if (params === undefined) return [];
|
|
90
|
+
return splitParameters(params.list).flatMap((part, index, parts) => {
|
|
91
|
+
const found = parameterDefault(part);
|
|
92
|
+
const from = params.from + parts.slice(0, index).reduce((length, earlier) => length + earlier.length + 1, 0);
|
|
93
|
+
return found === undefined ? [] : [{ ...found, offset: base + line.start + line.text.indexOf(found.name, from), source: "code" as const }];
|
|
94
|
+
});
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const inCode = (source: string): Stated[] =>
|
|
98
|
+
codeFences(source).flatMap((fence) => linesOf(source.slice(fence.start, fence.end)).flatMap((line) => inCodeLine(line, fence.start)));
|
|
99
|
+
|
|
100
|
+
const cellsOf = (text: string): string[] =>
|
|
101
|
+
text
|
|
102
|
+
.split("|")
|
|
103
|
+
.slice(1, -1)
|
|
104
|
+
.map((cell) => cell.trim());
|
|
105
|
+
|
|
106
|
+
/** The rows of every table with a default column, as (first cell name, default cell). */
|
|
107
|
+
const inTables = (lines: readonly Line[], headers: ReadonlySet<string>): Stated[] =>
|
|
108
|
+
lines.flatMap((line, index) => {
|
|
109
|
+
const column = cellsOf(line.text).findIndex((cell) => headers.has(cell.replace(/[*`]/gu, "").toLowerCase()));
|
|
110
|
+
const delimiter = lines[index + 1]?.text ?? "";
|
|
111
|
+
if (column <= 0 || !delimiter.includes("---") || !DELIMITER_ROW.test(delimiter)) return [];
|
|
112
|
+
const end = lines.findIndex((row, at) => at > index + 1 && !row.text.trimStart().startsWith("|"));
|
|
113
|
+
return lines.slice(index + 2, end === -1 ? lines.length : end).flatMap((row) => {
|
|
114
|
+
const cells = cellsOf(row.text);
|
|
115
|
+
const name = /^`?([A-Za-z_$][\w$]*)`?$/u.exec(cells[0] ?? "")?.[1];
|
|
116
|
+
const value = valueAt(cells[column] ?? "");
|
|
117
|
+
return name === undefined || value === undefined ? [] : [{ name, value, offset: row.start + row.text.indexOf(name), source: "table" as const }];
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
/** "`width` defaults to 80", "`width` の既定値は 80 文字": a code name, a default phrase right after it, then the value. */
|
|
122
|
+
const inProse = (lines: readonly Line[], phrases: readonly string[]): Stated[] =>
|
|
123
|
+
lines.flatMap((line) =>
|
|
124
|
+
[...line.text.matchAll(NAME_SPAN)].flatMap((match) => {
|
|
125
|
+
const after = line.text.slice(match.index + match[0].length);
|
|
126
|
+
const phrase = phrases.map((candidate) => ({ candidate, at: after.toLowerCase().indexOf(candidate) })).find(({ at }) => at !== -1 && at <= PHRASE_REACH);
|
|
127
|
+
const value = phrase === undefined ? undefined : valueAt(after.slice(phrase.at + phrase.candidate.length));
|
|
128
|
+
return value === undefined ? [] : [{ name: match[1] ?? "", value, offset: line.start + match.index + 1, source: "prose" as const }];
|
|
129
|
+
}),
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
/** Python writes the same literals capitalised: True is true, None is null. */
|
|
133
|
+
const LITERAL_SPELLINGS: Readonly<Record<string, string>> = { True: "true", False: "false", None: "null", none: "null" };
|
|
134
|
+
|
|
135
|
+
const normalized = (value: string): string => LITERAL_SPELLINGS[value] ?? value;
|
|
136
|
+
|
|
137
|
+
const sameValue = (left: string, right: string): boolean =>
|
|
138
|
+
normalized(left) === normalized(right) || (Number.isFinite(Number(left)) && Number(left) === Number(right) && left !== "" && right !== "");
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Every stated default that differs from the name's most authoritative statement (the code, else a table). Two
|
|
142
|
+
* sentences that disagree with no code or table to settle it are left alone.
|
|
143
|
+
*/
|
|
144
|
+
export const defaultSlips = (source: string, words: DefaultWords): DefaultSlip[] => {
|
|
145
|
+
const fences = codeFences(source);
|
|
146
|
+
const lines = linesOf(source).filter((line) => !fences.some((fence) => line.start >= fence.start && line.start < fence.end));
|
|
147
|
+
const stated = [...inCode(source), ...inTables(lines, new Set(words.headers)), ...inProse(lines, words.phrases)];
|
|
148
|
+
return stated.flatMap((statement) => {
|
|
149
|
+
const above = stated.filter((other) => other.name === statement.name && RANK[other.source] < RANK[statement.source]);
|
|
150
|
+
const top = Math.min(...above.map((other) => RANK[other.source]));
|
|
151
|
+
const authorities = above.filter((other) => RANK[other.source] === top);
|
|
152
|
+
// Two functions on one page may give one parameter name two defaults; then no statement settles the others.
|
|
153
|
+
const authority = authorities.every((other) => sameValue(other.value, authorities[0]?.value ?? "")) ? authorities[0] : undefined;
|
|
154
|
+
return authority === undefined || sameValue(authority.value, statement.value)
|
|
155
|
+
? []
|
|
156
|
+
: [{ name: statement.name, value: statement.value, offset: statement.offset, expected: authority.value }];
|
|
157
|
+
});
|
|
158
|
+
};
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// A name the document calls deprecated (`indent` is deprecated; | `indent` | 0 | 非推奨 |) still used in one of its code
|
|
2
|
+
// examples ({ indent: 2 }, --indent, indent=2). Pure; reads the Markdown source. The words that mark a name deprecated
|
|
3
|
+
// (deprecated, 非推奨) and the phrases that negate them come from the language's lexicons.
|
|
4
|
+
import { codeFences } from "./detectors/code-fences.ts";
|
|
5
|
+
|
|
6
|
+
/** A deprecated name used in code: where it is used, and where the document calls it deprecated. */
|
|
7
|
+
export type DeprecatedUse = { readonly name: string; readonly offset: number; readonly marked: number };
|
|
8
|
+
|
|
9
|
+
/** The lowercase words that mark a name deprecated, and the phrases that negate one ("not deprecated", 非推奨ではな). */
|
|
10
|
+
export type DeprecationWords = { readonly words: readonly string[]; readonly negated: readonly string[] };
|
|
11
|
+
|
|
12
|
+
type Line = { readonly text: string; readonly start: number };
|
|
13
|
+
type Marked = { readonly name: string; readonly offset: number };
|
|
14
|
+
type Span = { readonly start: number; readonly end: number };
|
|
15
|
+
type Found = { readonly at: number; readonly end: number };
|
|
16
|
+
|
|
17
|
+
/** A name in code marks: `indent`, or the flag `--indent`, which is the name indent. */
|
|
18
|
+
const CODE_SPAN = /`-{0,2}([A-Za-z_$][\w$-]*)`/gu;
|
|
19
|
+
const FIRST_CELL_NAME = /`-{0,2}([A-Za-z_$][\w$-]*)`|^\s*-{0,2}([A-Za-z_$][\w$-]*)\s*$/u;
|
|
20
|
+
const TABLE_ROW = /^[ \t]{0,3}\|/u;
|
|
21
|
+
/** An anchor before a field name in a table cell: <a name="schemaExample"></a>example. */
|
|
22
|
+
const HTML_TAG = /<[^<>]*>/gu;
|
|
23
|
+
/** Where one statement ends: a sentence or a clause after a semicolon ("`indent` is deprecated; use `prefix`"). */
|
|
24
|
+
const STATEMENT_END = /[.;。;!?!?]/u;
|
|
25
|
+
/** A block that declares an API (interface Options { indent: number }) documents the name, and does not use it. */
|
|
26
|
+
const DECLARATION_BLOCK = /^[ \t]*(?:export[ \t]+)?(?:interface|class|type[ \t]+[\w$]+[ \t]*=)/mu;
|
|
27
|
+
|
|
28
|
+
const linesOf = (source: string): Line[] => {
|
|
29
|
+
const starts = [0, ...[...source.matchAll(/\n/gu)].map((match) => match.index + 1)];
|
|
30
|
+
return starts.map((start, index) => ({ text: source.slice(start, (starts[index + 1] ?? source.length + 1) - 1), start }));
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const insideOne = (spans: readonly Span[], offset: number): boolean => spans.some((span) => offset >= span.start && offset < span.end);
|
|
34
|
+
|
|
35
|
+
const occurrences = (text: string, words: readonly string[]): Found[] => {
|
|
36
|
+
const lower = text.toLowerCase();
|
|
37
|
+
return words.flatMap((word) => {
|
|
38
|
+
const found: Found[] = [];
|
|
39
|
+
for (let at = lower.indexOf(word); at !== -1; at = lower.indexOf(word, at + word.length)) found.push({ at, end: at + word.length });
|
|
40
|
+
return found;
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/** The deprecation words in a text, less those inside a negated phrase ("is not deprecated"). */
|
|
45
|
+
const wordsIn = (text: string, words: DeprecationWords): Found[] => {
|
|
46
|
+
const negated = occurrences(text, words.negated);
|
|
47
|
+
return occurrences(text, words.words).filter((word) => !negated.some((phrase) => phrase.at <= word.at && word.end <= phrase.end));
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/** Characters between a code span and the word: "`indent` を非推奨" is nearer than "非推奨にし、`prefix`". */
|
|
51
|
+
const gap = (span: Found, word: Found): number => (span.end <= word.at ? word.at - span.end : span.at - word.end);
|
|
52
|
+
|
|
53
|
+
/** A table row's first-cell name, and whether its later cells call it deprecated. */
|
|
54
|
+
const rowOf = (line: Line, words: DeprecationWords): (Marked & { readonly deprecated: boolean }) | undefined => {
|
|
55
|
+
const cells = line.text.split("|");
|
|
56
|
+
const first = cells.findIndex((cell) => cell.trim() !== "");
|
|
57
|
+
if (first === -1) return undefined;
|
|
58
|
+
const name = FIRST_CELL_NAME.exec((cells[first] ?? "").replace(HTML_TAG, ""));
|
|
59
|
+
const written = name?.[1] ?? name?.[2];
|
|
60
|
+
const deprecated = wordsIn(cells.slice(first + 1).join("|"), words).length > 0;
|
|
61
|
+
return written === undefined ? undefined : { name: written, offset: line.start + line.text.indexOf(written), deprecated };
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const markedInRow = (line: Line, words: DeprecationWords): Marked[] => {
|
|
65
|
+
const row = rowOf(line, words);
|
|
66
|
+
return row?.deprecated === true ? [{ name: row.name, offset: row.offset }] : [];
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Names a table also lists without calling them deprecated: one page may describe two fields of one name, of which only
|
|
71
|
+
* one is deprecated (an example field of one object, and of another), and an example cannot tell which it uses.
|
|
72
|
+
*/
|
|
73
|
+
const listedAlive = (lines: readonly Line[], words: DeprecationWords): Set<string> =>
|
|
74
|
+
new Set(
|
|
75
|
+
lines.flatMap((line) => (line.text.includes("|") ? [rowOf(line, words)] : [])).flatMap((row) => (row === undefined || row.deprecated ? [] : [row.name])),
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
/** In a statement, the code name nearest to each deprecation word: "`indent` is deprecated", "Deprecated: `indent`". */
|
|
79
|
+
const markedInProse = (line: Line, words: DeprecationWords): Marked[] =>
|
|
80
|
+
wordsIn(line.text, words).flatMap((word) => {
|
|
81
|
+
const { at } = word;
|
|
82
|
+
const from = Math.max(...[...line.text.slice(0, at).matchAll(new RegExp(STATEMENT_END, "gu"))].map((match) => match.index + 1), 0);
|
|
83
|
+
const after = line.text.slice(at).search(STATEMENT_END);
|
|
84
|
+
const to = after === -1 ? line.text.length : at + after;
|
|
85
|
+
const spans = [...line.text.slice(from, to).matchAll(CODE_SPAN)].map((match) => ({
|
|
86
|
+
name: match[1] ?? "",
|
|
87
|
+
at: from + match.index,
|
|
88
|
+
end: from + match.index + match[0].length,
|
|
89
|
+
}));
|
|
90
|
+
const nearest = spans.toSorted((left, right) => gap(left, word) - gap(right, word))[0];
|
|
91
|
+
return nearest === undefined ? [] : [{ name: nearest.name, offset: line.start + line.text.indexOf(nearest.name, nearest.at) }];
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
const escape = (text: string): string => text.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
|
|
95
|
+
|
|
96
|
+
/** A name used as an option in code: a key ({ indent: 2 }, "indent": 2), an argument (indent=2) or a flag (--indent). */
|
|
97
|
+
const usePattern = (name: string): RegExp =>
|
|
98
|
+
new RegExp(`(?:(?<![\\w$.-])["']?${escape(name)}["']?[ \\t]*(?::(?!:)|=(?!=))|(?<![\\w-])--${escape(name)}(?![\\w-]))`, "u");
|
|
99
|
+
|
|
100
|
+
const usesIn = (line: Line, marks: ReadonlyMap<string, number>): DeprecatedUse[] =>
|
|
101
|
+
[...marks].flatMap(([name, marked]) => {
|
|
102
|
+
const match = usePattern(name).exec(line.text);
|
|
103
|
+
return match === null ? [] : [{ name, offset: line.start + match.index + match[0].indexOf(name), marked }];
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* The code lines that use a name the document calls deprecated. A code line that says so itself (`indent: 2 // deprecated`)
|
|
108
|
+
* shows the old use on purpose and is left out, and so is a block that declares an API rather than using it.
|
|
109
|
+
*/
|
|
110
|
+
export const deprecatedUses = (source: string, words: DeprecationWords): DeprecatedUse[] => {
|
|
111
|
+
if (words.words.length === 0) return [];
|
|
112
|
+
const fences = codeFences(source);
|
|
113
|
+
const lines = linesOf(source);
|
|
114
|
+
const prose = lines.filter((line) => !insideOne(fences, line.start));
|
|
115
|
+
const alive = listedAlive(prose, words);
|
|
116
|
+
const marked = prose
|
|
117
|
+
.flatMap((line) => (TABLE_ROW.test(line.text) ? markedInRow(line, words) : markedInProse(line, words)))
|
|
118
|
+
.filter((mark) => !alive.has(mark.name));
|
|
119
|
+
const firstMark = new Map(marked.toReversed().map((mark) => [mark.name, mark.offset]));
|
|
120
|
+
const examples = fences.filter((fence) => !DECLARATION_BLOCK.test(source.slice(fence.start, fence.end)));
|
|
121
|
+
return lines.filter((line) => insideOne(examples, line.start) && wordsIn(line.text, words).length === 0).flatMap((line) => usesIn(line, firstMark));
|
|
122
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Span } from "../plugin.ts";
|
|
2
|
+
import { escapeRegExp } from "../orthography.ts";
|
|
3
|
+
|
|
4
|
+
// A count written as a word before its unit ("twelve years", "Ten years"), which the tree does not read as a quantity.
|
|
5
|
+
// Pure: the number words come in order from one (the lexicon count-number, the position is the number).
|
|
6
|
+
|
|
7
|
+
export type WordCount = Span & { readonly amount: number };
|
|
8
|
+
|
|
9
|
+
const alternation = (words: readonly string[]): string =>
|
|
10
|
+
words
|
|
11
|
+
.filter((word) => word !== "")
|
|
12
|
+
.map(escapeRegExp)
|
|
13
|
+
.join("|");
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Each number word standing as a word of its own, followed by one of the units after a space. A word joined to letters,
|
|
17
|
+
* digits or a dash on either side is the tail of a larger number (二十年's 十, "twenty-one years", "fortyten").
|
|
18
|
+
*/
|
|
19
|
+
export const numberWordCounts = (source: string, numberWords: readonly string[], units: readonly string[]): WordCount[] => {
|
|
20
|
+
const [words, unitWords] = [alternation(numberWords), alternation(units)];
|
|
21
|
+
if (words === "" || unitWords === "") return [];
|
|
22
|
+
const pattern = new RegExp(`(?<![\\p{L}\\p{N}\\p{Pd}])(${words})\\s+(?:${unitWords})(?![\\p{L}\\p{N}])`, "giu");
|
|
23
|
+
const lowered = numberWords.map((word) => word.toLowerCase());
|
|
24
|
+
return [...source.matchAll(pattern)].flatMap((match) => {
|
|
25
|
+
const position = lowered.indexOf((match[1] ?? "").toLowerCase());
|
|
26
|
+
return position < 0 ? [] : [{ start: match.index, end: match.index + match[0].length, amount: position + 1 }];
|
|
27
|
+
});
|
|
28
|
+
};
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import type { Span } from "../plugin.ts";
|
|
2
|
+
import { bySentence } from "./sentence-buckets.ts";
|
|
3
|
+
import { calendarDateOf, dateOf, shifted } from "./date-arithmetic.ts";
|
|
4
|
+
import type { DatedValue } from "./durations.ts";
|
|
5
|
+
import { cellsOf, tablesOf, type Cell } from "../facts/table-facts.ts";
|
|
6
|
+
import { linesOf } from "../structure/lines.ts";
|
|
7
|
+
import { withoutEdgeMarks } from "../facts/trim-marks.ts";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* 泊数。チェックインからチェックアウトまでの泊数は、二つの日付の差の日数(10月12日から10月14日までは2泊)。
|
|
11
|
+
* 一つの文に日付がちょうど二つと泊数がちょうど一つあるときと、チェックイン・チェックアウト・泊数の列がそろった表の行で比べる。
|
|
12
|
+
* 「2泊3日」のように泊数と日数を並べたものは、日数が泊数より一つ多いかを見る。Pure.
|
|
13
|
+
*/
|
|
14
|
+
export type Count = Span & { readonly amount: number };
|
|
15
|
+
|
|
16
|
+
export type NightsMismatch = { readonly start: DatedValue; readonly end: DatedValue; readonly nights: Span; readonly expected: number };
|
|
17
|
+
|
|
18
|
+
export type NightsDaysMismatch = { readonly nights: Count; readonly days: Count; readonly expected: number };
|
|
19
|
+
|
|
20
|
+
export type StayColumnWords = {
|
|
21
|
+
readonly checkIn: readonly string[];
|
|
22
|
+
readonly checkOut: readonly string[];
|
|
23
|
+
readonly nights: readonly string[];
|
|
24
|
+
/** The words of a nights unit (泊, nights) a nights cell may write after its number. */
|
|
25
|
+
readonly units: readonly string[];
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const DAY_MS = 86_400_000;
|
|
29
|
+
|
|
30
|
+
type Between = { start: DatedValue; end: DatedValue; nights: number };
|
|
31
|
+
|
|
32
|
+
const daysFrom = (from: Date, to: Date): number => Math.round((to.getTime() - from.getTime()) / DAY_MS);
|
|
33
|
+
|
|
34
|
+
/** 月日だけの二つの日付は、近いほうの向き(12月30日と1月2日は年をまたいで3泊、10月14日と10月12日は2泊)。 */
|
|
35
|
+
const nearerWay = (first: DatedValue, second: DatedValue, firstDay: Date, secondDay: Date): Between => {
|
|
36
|
+
const forward = daysFrom(firstDay, secondDay);
|
|
37
|
+
const ahead = forward < 0 ? daysFrom(firstDay, shifted(secondDay, 1, "year")) : forward;
|
|
38
|
+
const back = -forward < 0 ? daysFrom(secondDay, shifted(firstDay, 1, "year")) : -forward;
|
|
39
|
+
return back < ahead ? { start: second, end: first, nights: back } : { start: first, end: second, nights: ahead };
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/** 二つの日付の間の泊数。年まで書いたら早いほうから。年の有る日付と無い日付の組は読まない。 */
|
|
43
|
+
const nightsBetween = (first: DatedValue, second: DatedValue): Between | undefined => {
|
|
44
|
+
const [firstDate, secondDate] = [calendarDateOf(first.value), calendarDateOf(second.value)];
|
|
45
|
+
if (firstDate === undefined || secondDate === undefined || (firstDate.year === undefined) !== (secondDate.year === undefined)) return undefined;
|
|
46
|
+
const [firstDay, secondDay] = [dateOf(firstDate), dateOf(secondDate)];
|
|
47
|
+
if (firstDate.year === undefined) return nearerWay(first, second, firstDay, secondDay);
|
|
48
|
+
const forward = daysFrom(firstDay, secondDay);
|
|
49
|
+
return forward < 0 ? { start: second, end: first, nights: -forward } : { start: first, end: second, nights: forward };
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const mismatchOf = (first: DatedValue, second: DatedValue, nights: Count): NightsMismatch | undefined => {
|
|
53
|
+
const between = nightsBetween(first, second);
|
|
54
|
+
if (between === undefined || between.nights <= 0 || between.nights === nights.amount) return undefined;
|
|
55
|
+
return { start: between.start, end: between.end, nights, expected: between.nights };
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/** 一つの文の中の、二つの日付と泊数。 */
|
|
59
|
+
export const stayNightsMismatches = (sentences: readonly Span[], dates: readonly DatedValue[], nights: readonly Count[]): NightsMismatch[] => {
|
|
60
|
+
const datesIn = bySentence(sentences, dates);
|
|
61
|
+
return [...bySentence(sentences, nights).entries()].flatMap(([index, inNights]) => {
|
|
62
|
+
const inDates = datesIn.get(index) ?? [];
|
|
63
|
+
const [first, second] = inDates;
|
|
64
|
+
const [count] = inNights;
|
|
65
|
+
if (inDates.length !== 2 || inNights.length !== 1 || first === undefined || second === undefined || count === undefined) return [];
|
|
66
|
+
const mismatch = mismatchOf(first, second, count);
|
|
67
|
+
return mismatch === undefined ? [] : [mismatch];
|
|
68
|
+
});
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const normalizedGap = (text: string): string => text.normalize("NFKC").trim().toLowerCase().replace(/\s+/gu, " ");
|
|
72
|
+
|
|
73
|
+
const joined = (source: string, left: Span, right: Span, joiners: readonly string[]): boolean => {
|
|
74
|
+
if (right.start < left.end) return false;
|
|
75
|
+
const gap = normalizedGap(source.slice(left.end, right.start));
|
|
76
|
+
return gap === "" || joiners.some((joiner) => normalizedGap(joiner) === gap);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
/** 泊数と日数を並べたもの(2泊3日、2 days, 1 night)。泊数の直前か直後に、つなぎの語だけを挟んで日数がある。 */
|
|
80
|
+
export const nightsDaysPairs = (
|
|
81
|
+
source: string,
|
|
82
|
+
nights: readonly Count[],
|
|
83
|
+
days: readonly Count[],
|
|
84
|
+
joiners: readonly string[],
|
|
85
|
+
): { nights: Count; days: Count }[] =>
|
|
86
|
+
nights.flatMap((count) => {
|
|
87
|
+
const paired = days.find((day) => joined(source, count, day, joiners) || joined(source, day, count, joiners));
|
|
88
|
+
return paired === undefined ? [] : [{ nights: count, days: paired }];
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
/** 日数が泊数より一つ多くない組。 */
|
|
92
|
+
export const nightsDaysMismatches = (pairs: readonly { nights: Count; days: Count }[]): NightsDaysMismatch[] =>
|
|
93
|
+
pairs.flatMap((pair) => (pair.days.amount === pair.nights.amount + 1 ? [] : [{ ...pair, expected: pair.nights.amount + 1 }]));
|
|
94
|
+
|
|
95
|
+
const keyOf = (text: string): string => withoutEdgeMarks(text).normalize("NFKC").toLowerCase().replace(/\s+/gu, " ");
|
|
96
|
+
|
|
97
|
+
const columnOf = (header: readonly Cell[], names: readonly string[]): number => {
|
|
98
|
+
const wanted = new Set(names.map(keyOf));
|
|
99
|
+
return header.findIndex((cell) => wanted.has(keyOf(cell.text)));
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const LEADING_DIGITS = /^\d+/u;
|
|
103
|
+
|
|
104
|
+
/** 泊数の升の数(「2」「2泊」「2 nights」)。それ以外を書いた升は読まない。 */
|
|
105
|
+
const nightsInCell = (cell: Cell, units: readonly string[]): Count | undefined => {
|
|
106
|
+
const key = keyOf(cell.text);
|
|
107
|
+
const digits = LEADING_DIGITS.exec(key)?.[0];
|
|
108
|
+
if (digits === undefined) return undefined;
|
|
109
|
+
const rest = key.slice(digits.length).trim();
|
|
110
|
+
if (rest !== "" && !units.some((unit) => keyOf(unit) === rest)) return undefined;
|
|
111
|
+
const offset = cell.text.length - cell.text.trimStart().length;
|
|
112
|
+
return { start: cell.start + offset, end: cell.end, amount: Number(digits) };
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const onlyDateIn = (cell: Cell | undefined, dates: readonly DatedValue[]): DatedValue | undefined => {
|
|
116
|
+
if (cell === undefined) return undefined;
|
|
117
|
+
const inside = dates.filter((date) => date.start >= cell.start && date.end <= cell.end);
|
|
118
|
+
return inside.length === 1 ? inside[0] : undefined;
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
type StayColumns = { readonly checkIn: number; readonly checkOut: number; readonly nights: number };
|
|
122
|
+
|
|
123
|
+
const rowMismatch = (cells: readonly Cell[], columns: StayColumns, dates: readonly DatedValue[], units: readonly string[]): NightsMismatch | undefined => {
|
|
124
|
+
const checkIn = onlyDateIn(cells[columns.checkIn], dates);
|
|
125
|
+
const checkOut = onlyDateIn(cells[columns.checkOut], dates);
|
|
126
|
+
const nightsCell = cells[columns.nights];
|
|
127
|
+
const nights = nightsCell === undefined ? undefined : nightsInCell(nightsCell, units);
|
|
128
|
+
return checkIn === undefined || checkOut === undefined || nights === undefined ? undefined : mismatchOf(checkIn, checkOut, nights);
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
/** チェックイン・チェックアウト・泊数の列がある表の、行ごとの泊数。 */
|
|
132
|
+
export const tableNightsMismatches = (source: string, dates: readonly DatedValue[], words: StayColumnWords): NightsMismatch[] =>
|
|
133
|
+
tablesOf(linesOf(source)).flatMap(({ header, rows }) => {
|
|
134
|
+
const headerCells = cellsOf(header);
|
|
135
|
+
const columns = {
|
|
136
|
+
checkIn: columnOf(headerCells, words.checkIn),
|
|
137
|
+
checkOut: columnOf(headerCells, words.checkOut),
|
|
138
|
+
nights: columnOf(headerCells, words.nights),
|
|
139
|
+
};
|
|
140
|
+
if (Object.values(columns).some((index) => index < 0)) return [];
|
|
141
|
+
return rows.flatMap((row) => {
|
|
142
|
+
const mismatch = rowMismatch(cellsOf(row), columns, dates, words.units);
|
|
143
|
+
return mismatch === undefined ? [] : [mismatch];
|
|
144
|
+
});
|
|
145
|
+
});
|