chaffjs 0.29.0 → 0.31.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/announced-count.d.ts +2 -0
- package/dist/announced-count.d.ts.map +1 -1
- package/dist/announced-count.js +4 -3
- package/dist/announced-count.js.map +1 -1
- package/dist/contacts/addresses.d.ts +21 -0
- package/dist/contacts/addresses.d.ts.map +1 -0
- package/dist/contacts/addresses.js +144 -0
- package/dist/contacts/addresses.js.map +1 -0
- package/dist/contacts/emails.d.ts +11 -0
- package/dist/contacts/emails.d.ts.map +1 -0
- package/dist/contacts/emails.js +51 -0
- package/dist/contacts/emails.js.map +1 -0
- package/dist/contacts/variants.d.ts +14 -0
- package/dist/contacts/variants.d.ts.map +1 -0
- package/dist/contacts/variants.js +25 -0
- package/dist/contacts/variants.js.map +1 -0
- package/dist/derived/battery-runtime.d.ts +85 -0
- package/dist/derived/battery-runtime.d.ts.map +1 -0
- package/dist/derived/battery-runtime.js +217 -0
- package/dist/derived/battery-runtime.js.map +1 -0
- package/dist/derived/period-counts.d.ts +48 -0
- package/dist/derived/period-counts.d.ts.map +1 -0
- package/dist/derived/period-counts.js +128 -0
- package/dist/derived/period-counts.js.map +1 -0
- package/dist/derived/session-hours.d.ts +26 -0
- package/dist/derived/session-hours.d.ts.map +1 -0
- package/dist/derived/session-hours.js +29 -0
- package/dist/derived/session-hours.js.map +1 -0
- package/dist/derived/time-lengths.d.ts +37 -0
- package/dist/derived/time-lengths.d.ts.map +1 -0
- package/dist/derived/time-lengths.js +171 -0
- package/dist/derived/time-lengths.js.map +1 -0
- package/dist/derived/unit-counts.d.ts +7 -0
- package/dist/derived/unit-counts.d.ts.map +1 -0
- package/dist/derived/unit-counts.js +13 -0
- package/dist/derived/unit-counts.js.map +1 -0
- package/dist/derived/use-interval.d.ts +33 -0
- package/dist/derived/use-interval.d.ts.map +1 -0
- package/dist/derived/use-interval.js +93 -0
- package/dist/derived/use-interval.js.map +1 -0
- package/dist/derived/working-hours.d.ts +36 -0
- package/dist/derived/working-hours.d.ts.map +1 -0
- package/dist/derived/working-hours.js +55 -0
- package/dist/derived/working-hours.js.map +1 -0
- package/dist/detectors/acronym-expansion.d.ts +1 -1
- package/dist/detectors/acronym-expansion.d.ts.map +1 -1
- package/dist/detectors/acronym-expansion.js +46 -2
- package/dist/detectors/acronym-expansion.js.map +1 -1
- package/dist/detectors/announced-count.d.ts.map +1 -1
- package/dist/detectors/announced-count.js +1 -0
- package/dist/detectors/announced-count.js.map +1 -1
- package/dist/detectors/capacity-runtime.d.ts +7 -0
- package/dist/detectors/capacity-runtime.d.ts.map +1 -0
- package/dist/detectors/capacity-runtime.js +98 -0
- package/dist/detectors/capacity-runtime.js.map +1 -0
- package/dist/detectors/capitalised-term.d.ts +44 -0
- package/dist/detectors/capitalised-term.d.ts.map +1 -0
- package/dist/detectors/capitalised-term.js +101 -0
- package/dist/detectors/capitalised-term.js.map +1 -0
- package/dist/detectors/contact-variant.d.ts +3 -0
- package/dist/detectors/contact-variant.d.ts.map +1 -0
- package/dist/detectors/contact-variant.js +21 -0
- package/dist/detectors/contact-variant.js.map +1 -0
- package/dist/detectors/count-over-capacity.d.ts +4 -0
- package/dist/detectors/count-over-capacity.d.ts.map +1 -0
- package/dist/detectors/count-over-capacity.js +26 -0
- package/dist/detectors/count-over-capacity.js.map +1 -0
- package/dist/detectors/date-outside-period.d.ts.map +1 -1
- package/dist/detectors/date-outside-period.js +5 -1
- package/dist/detectors/date-outside-period.js.map +1 -1
- package/dist/detectors/date-stamp-order.d.ts +3 -0
- package/dist/detectors/date-stamp-order.d.ts.map +1 -0
- package/dist/detectors/date-stamp-order.js +24 -0
- package/dist/detectors/date-stamp-order.js.map +1 -0
- package/dist/detectors/defined-term-form.d.ts.map +1 -1
- package/dist/detectors/defined-term-form.js +57 -7
- package/dist/detectors/defined-term-form.js.map +1 -1
- package/dist/detectors/definition-use.d.ts +1 -1
- package/dist/detectors/definition-use.d.ts.map +1 -1
- package/dist/detectors/definition-use.js +4 -2
- package/dist/detectors/definition-use.js.map +1 -1
- package/dist/detectors/derived-numbers.d.ts +11 -1
- package/dist/detectors/derived-numbers.d.ts.map +1 -1
- package/dist/detectors/derived-numbers.js +74 -20
- package/dist/detectors/derived-numbers.js.map +1 -1
- package/dist/detectors/due-date.d.ts.map +1 -1
- package/dist/detectors/due-date.js +6 -0
- package/dist/detectors/due-date.js.map +1 -1
- package/dist/detectors/en-shape.d.ts.map +1 -1
- package/dist/detectors/en-shape.js +7 -4
- package/dist/detectors/en-shape.js.map +1 -1
- package/dist/detectors/event-deadline.d.ts +3 -0
- package/dist/detectors/event-deadline.d.ts.map +1 -0
- package/dist/detectors/event-deadline.js +24 -0
- package/dist/detectors/event-deadline.js.map +1 -0
- package/dist/detectors/fact-consistency.d.ts +1 -1
- package/dist/detectors/fact-consistency.d.ts.map +1 -1
- package/dist/detectors/fact-consistency.js +52 -3
- package/dist/detectors/fact-consistency.js.map +1 -1
- package/dist/detectors/heading-case.d.ts +5 -2
- package/dist/detectors/heading-case.d.ts.map +1 -1
- package/dist/detectors/heading-case.js +12 -4
- package/dist/detectors/heading-case.js.map +1 -1
- package/dist/detectors/heading-echo.d.ts +5 -0
- package/dist/detectors/heading-echo.d.ts.map +1 -1
- package/dist/detectors/heading-echo.js +14 -1
- package/dist/detectors/heading-echo.js.map +1 -1
- package/dist/detectors/layout-code.d.ts +5 -0
- package/dist/detectors/layout-code.d.ts.map +1 -0
- package/dist/detectors/layout-code.js +124 -0
- package/dist/detectors/layout-code.js.map +1 -0
- package/dist/detectors/measured-facts.d.ts +8 -0
- package/dist/detectors/measured-facts.d.ts.map +1 -0
- package/dist/detectors/measured-facts.js +18 -0
- package/dist/detectors/measured-facts.js.map +1 -0
- package/dist/detectors/name-variant-model-codes.d.ts +11 -0
- package/dist/detectors/name-variant-model-codes.d.ts.map +1 -0
- package/dist/detectors/name-variant-model-codes.js +21 -0
- package/dist/detectors/name-variant-model-codes.js.map +1 -0
- package/dist/detectors/name-variant.d.ts.map +1 -1
- package/dist/detectors/name-variant.js +78 -10
- package/dist/detectors/name-variant.js.map +1 -1
- package/dist/detectors/orthographic-variant.d.ts.map +1 -1
- package/dist/detectors/orthographic-variant.js +62 -7
- package/dist/detectors/orthographic-variant.js.map +1 -1
- package/dist/detectors/orthography.d.ts.map +1 -1
- package/dist/detectors/orthography.js +12 -6
- package/dist/detectors/orthography.js.map +1 -1
- package/dist/detectors/party-order.d.ts +3 -0
- package/dist/detectors/party-order.d.ts.map +1 -0
- package/dist/detectors/party-order.js +46 -0
- package/dist/detectors/party-order.js.map +1 -0
- package/dist/detectors/quantity-range.d.ts +3 -0
- package/dist/detectors/quantity-range.d.ts.map +1 -0
- package/dist/detectors/quantity-range.js +35 -0
- package/dist/detectors/quantity-range.js.map +1 -0
- package/dist/detectors/range-band.d.ts +5 -0
- package/dist/detectors/range-band.d.ts.map +1 -0
- package/dist/detectors/range-band.js +80 -0
- package/dist/detectors/range-band.js.map +1 -0
- package/dist/detectors/registry/capacity-runtime-mismatch.d.ts +3 -0
- package/dist/detectors/registry/capacity-runtime-mismatch.d.ts.map +1 -0
- package/dist/detectors/registry/capacity-runtime-mismatch.js +3 -0
- package/dist/detectors/registry/capacity-runtime-mismatch.js.map +1 -0
- package/dist/detectors/registry/connection-time-short.d.ts +3 -0
- package/dist/detectors/registry/connection-time-short.d.ts.map +1 -0
- package/dist/detectors/registry/connection-time-short.js +3 -0
- package/dist/detectors/registry/connection-time-short.js.map +1 -0
- package/dist/detectors/registry/contact-variant.d.ts +3 -0
- package/dist/detectors/registry/contact-variant.d.ts.map +1 -0
- package/dist/detectors/registry/contact-variant.js +3 -0
- package/dist/detectors/registry/contact-variant.js.map +1 -0
- package/dist/detectors/registry/count-over-capacity.d.ts +3 -0
- package/dist/detectors/registry/count-over-capacity.d.ts.map +1 -0
- package/dist/detectors/registry/count-over-capacity.js +3 -0
- package/dist/detectors/registry/count-over-capacity.js.map +1 -0
- package/dist/detectors/registry/date-stamp-order.d.ts +3 -0
- package/dist/detectors/registry/date-stamp-order.d.ts.map +1 -0
- package/dist/detectors/registry/date-stamp-order.js +3 -0
- package/dist/detectors/registry/date-stamp-order.js.map +1 -0
- package/dist/detectors/registry/duration-product-mismatch.d.ts +3 -0
- package/dist/detectors/registry/duration-product-mismatch.d.ts.map +1 -0
- package/dist/detectors/registry/duration-product-mismatch.js +3 -0
- package/dist/detectors/registry/duration-product-mismatch.js.map +1 -0
- package/dist/detectors/registry/event-deadline.d.ts +3 -0
- package/dist/detectors/registry/event-deadline.d.ts.map +1 -0
- package/dist/detectors/registry/event-deadline.js +3 -0
- package/dist/detectors/registry/event-deadline.js.map +1 -0
- package/dist/detectors/registry/interval-count-mismatch.d.ts +3 -0
- package/dist/detectors/registry/interval-count-mismatch.d.ts.map +1 -0
- package/dist/detectors/registry/interval-count-mismatch.js +3 -0
- package/dist/detectors/registry/interval-count-mismatch.js.map +1 -0
- package/dist/detectors/registry/layout-code-mismatch.d.ts +3 -0
- package/dist/detectors/registry/layout-code-mismatch.d.ts.map +1 -0
- package/dist/detectors/registry/layout-code-mismatch.js +3 -0
- package/dist/detectors/registry/layout-code-mismatch.js.map +1 -0
- package/dist/detectors/registry/party-order.d.ts +3 -0
- package/dist/detectors/registry/party-order.d.ts.map +1 -0
- package/dist/detectors/registry/party-order.js +3 -0
- package/dist/detectors/registry/party-order.js.map +1 -0
- package/dist/detectors/registry/quantity-range.d.ts +3 -0
- package/dist/detectors/registry/quantity-range.d.ts.map +1 -0
- package/dist/detectors/registry/quantity-range.js +3 -0
- package/dist/detectors/registry/quantity-range.js.map +1 -0
- package/dist/detectors/registry/range-band-mismatch.d.ts +3 -0
- package/dist/detectors/registry/range-band-mismatch.d.ts.map +1 -0
- package/dist/detectors/registry/range-band-mismatch.js +3 -0
- package/dist/detectors/registry/range-band-mismatch.js.map +1 -0
- package/dist/detectors/registry/rent-multiple-mismatch.d.ts +3 -0
- package/dist/detectors/registry/rent-multiple-mismatch.d.ts.map +1 -0
- package/dist/detectors/registry/rent-multiple-mismatch.js +3 -0
- package/dist/detectors/registry/rent-multiple-mismatch.js.map +1 -0
- package/dist/detectors/registry/requirement-lists.d.ts +3 -0
- package/dist/detectors/registry/requirement-lists.d.ts.map +1 -0
- package/dist/detectors/registry/requirement-lists.js +3 -0
- package/dist/detectors/registry/requirement-lists.js.map +1 -0
- package/dist/detectors/registry/return-type.d.ts +3 -0
- package/dist/detectors/registry/return-type.d.ts.map +1 -0
- package/dist/detectors/registry/return-type.js +3 -0
- package/dist/detectors/registry/return-type.js.map +1 -0
- package/dist/detectors/registry/scaled-quantity-mismatch.d.ts +3 -0
- package/dist/detectors/registry/scaled-quantity-mismatch.d.ts.map +1 -0
- package/dist/detectors/registry/scaled-quantity-mismatch.js +3 -0
- package/dist/detectors/registry/scaled-quantity-mismatch.js.map +1 -0
- package/dist/detectors/registry/step-time-sum-mismatch.d.ts +3 -0
- package/dist/detectors/registry/step-time-sum-mismatch.d.ts.map +1 -0
- package/dist/detectors/registry/step-time-sum-mismatch.js +3 -0
- package/dist/detectors/registry/step-time-sum-mismatch.js.map +1 -0
- package/dist/detectors/registry/time-range-reversed.d.ts +3 -0
- package/dist/detectors/registry/time-range-reversed.d.ts.map +1 -0
- package/dist/detectors/registry/time-range-reversed.js +3 -0
- package/dist/detectors/registry/time-range-reversed.js.map +1 -0
- package/dist/detectors/registry/unlisted-item-used.d.ts +3 -0
- package/dist/detectors/registry/unlisted-item-used.d.ts.map +1 -0
- package/dist/detectors/registry/unlisted-item-used.js +3 -0
- package/dist/detectors/registry/unlisted-item-used.js.map +1 -0
- package/dist/detectors/registry/walk-time-distance-mismatch.d.ts +3 -0
- package/dist/detectors/registry/walk-time-distance-mismatch.d.ts.map +1 -0
- package/dist/detectors/registry/walk-time-distance-mismatch.js +3 -0
- package/dist/detectors/registry/walk-time-distance-mismatch.js.map +1 -0
- package/dist/detectors/rent-multiple-mismatch.d.ts +3 -0
- package/dist/detectors/rent-multiple-mismatch.d.ts.map +1 -0
- package/dist/detectors/rent-multiple-mismatch.js +39 -0
- package/dist/detectors/rent-multiple-mismatch.js.map +1 -0
- package/dist/detectors/requirement-lists.d.ts +3 -0
- package/dist/detectors/requirement-lists.d.ts.map +1 -0
- package/dist/detectors/requirement-lists.js +46 -0
- package/dist/detectors/requirement-lists.js.map +1 -0
- package/dist/detectors/return-type.d.ts +3 -0
- package/dist/detectors/return-type.d.ts.map +1 -0
- package/dist/detectors/return-type.js +24 -0
- package/dist/detectors/return-type.js.map +1 -0
- package/dist/detectors/scaled-quantity.d.ts +3 -0
- package/dist/detectors/scaled-quantity.d.ts.map +1 -0
- package/dist/detectors/scaled-quantity.js +37 -0
- package/dist/detectors/scaled-quantity.js.map +1 -0
- package/dist/detectors/signals.d.ts.map +1 -1
- package/dist/detectors/signals.js +3 -1
- package/dist/detectors/signals.js.map +1 -1
- package/dist/detectors/step-time-sum.d.ts +3 -0
- package/dist/detectors/step-time-sum.d.ts.map +1 -0
- package/dist/detectors/step-time-sum.js +46 -0
- package/dist/detectors/step-time-sum.js.map +1 -0
- package/dist/detectors/structure-tree.d.ts +2 -0
- package/dist/detectors/structure-tree.d.ts.map +1 -1
- package/dist/detectors/structure-tree.js +31 -6
- package/dist/detectors/structure-tree.js.map +1 -1
- package/dist/detectors/structure.js +1 -1
- package/dist/detectors/structure.js.map +1 -1
- package/dist/detectors/technical-docs.d.ts +5 -0
- package/dist/detectors/technical-docs.d.ts.map +1 -1
- package/dist/detectors/technical-docs.js +12 -0
- package/dist/detectors/technical-docs.js.map +1 -1
- package/dist/detectors/time-order.d.ts +2 -0
- package/dist/detectors/time-order.d.ts.map +1 -1
- package/dist/detectors/time-order.js +33 -5
- package/dist/detectors/time-order.js.map +1 -1
- package/dist/detectors/undefined-term.d.ts.map +1 -1
- package/dist/detectors/undefined-term.js +19 -3
- package/dist/detectors/undefined-term.js.map +1 -1
- package/dist/detectors/unit-consistency.d.ts +1 -1
- package/dist/detectors/unit-consistency.d.ts.map +1 -1
- package/dist/detectors/unit-consistency.js +46 -38
- package/dist/detectors/unit-consistency.js.map +1 -1
- package/dist/detectors/unlisted-items.d.ts +3 -0
- package/dist/detectors/unlisted-items.d.ts.map +1 -0
- package/dist/detectors/unlisted-items.js +57 -0
- package/dist/detectors/unlisted-items.js.map +1 -0
- package/dist/detectors/use-count-words.d.ts +8 -0
- package/dist/detectors/use-count-words.d.ts.map +1 -0
- package/dist/detectors/use-count-words.js +20 -0
- package/dist/detectors/use-count-words.js.map +1 -0
- package/dist/detectors/use-interval.d.ts +3 -0
- package/dist/detectors/use-interval.d.ts.map +1 -0
- package/dist/detectors/use-interval.js +39 -0
- package/dist/detectors/use-interval.js.map +1 -0
- package/dist/detectors/walk-time-distance-mismatch.d.ts +4 -0
- package/dist/detectors/walk-time-distance-mismatch.d.ts.map +1 -0
- package/dist/detectors/walk-time-distance-mismatch.js +38 -0
- package/dist/detectors/walk-time-distance-mismatch.js.map +1 -0
- package/dist/document.d.ts.map +1 -1
- package/dist/document.js +4 -1
- package/dist/document.js.map +1 -1
- package/dist/facts/approximate-tolerance.d.ts +7 -0
- package/dist/facts/approximate-tolerance.d.ts.map +1 -0
- package/dist/facts/approximate-tolerance.js +16 -0
- package/dist/facts/approximate-tolerance.js.map +1 -0
- package/dist/facts/item-amounts.d.ts +18 -0
- package/dist/facts/item-amounts.d.ts.map +1 -0
- package/dist/facts/item-amounts.js +67 -0
- package/dist/facts/item-amounts.js.map +1 -0
- package/dist/facts/labelled-facts.d.ts +4 -0
- package/dist/facts/labelled-facts.d.ts.map +1 -1
- package/dist/facts/labelled-facts.js +21 -6
- package/dist/facts/labelled-facts.js.map +1 -1
- package/dist/facts/measure-units.d.ts +5 -0
- package/dist/facts/measure-units.d.ts.map +1 -0
- package/dist/facts/measure-units.js +28 -0
- package/dist/facts/measure-units.js.map +1 -0
- package/dist/facts/measures.d.ts +23 -4
- package/dist/facts/measures.d.ts.map +1 -1
- package/dist/facts/measures.js +68 -19
- package/dist/facts/measures.js.map +1 -1
- package/dist/facts/retention-periods.d.ts +51 -0
- package/dist/facts/retention-periods.d.ts.map +1 -0
- package/dist/facts/retention-periods.js +148 -0
- package/dist/facts/retention-periods.js.map +1 -0
- package/dist/facts/table-facts.d.ts +2 -0
- package/dist/facts/table-facts.d.ts.map +1 -1
- package/dist/facts/table-facts.js +2 -0
- package/dist/facts/table-facts.js.map +1 -1
- package/dist/facts/unit-conflicts.d.ts +3 -2
- package/dist/facts/unit-conflicts.d.ts.map +1 -1
- package/dist/facts/unit-conflicts.js +15 -7
- package/dist/facts/unit-conflicts.js.map +1 -1
- package/dist/facts/unit-equivalents.d.ts +13 -0
- package/dist/facts/unit-equivalents.d.ts.map +1 -0
- package/dist/facts/unit-equivalents.js +56 -0
- package/dist/facts/unit-equivalents.js.map +1 -0
- package/dist/facts/unit-tolerance.d.ts +4 -0
- package/dist/facts/unit-tolerance.d.ts.map +1 -0
- package/dist/facts/unit-tolerance.js +13 -0
- package/dist/facts/unit-tolerance.js.map +1 -0
- package/dist/facts/unit-word.d.ts +8 -0
- package/dist/facts/unit-word.d.ts.map +1 -0
- package/dist/facts/unit-word.js +34 -0
- package/dist/facts/unit-word.js.map +1 -0
- package/dist/facts/written-precision.d.ts +10 -0
- package/dist/facts/written-precision.d.ts.map +1 -0
- package/dist/facts/written-precision.js +20 -0
- package/dist/facts/written-precision.js.map +1 -0
- package/dist/kana-spelling.d.ts +12 -0
- package/dist/kana-spelling.d.ts.map +1 -1
- package/dist/kana-spelling.js +23 -0
- package/dist/kana-spelling.js.map +1 -1
- package/dist/model-codes.d.ts +23 -0
- package/dist/model-codes.d.ts.map +1 -0
- package/dist/model-codes.js +81 -0
- package/dist/model-codes.js.map +1 -0
- package/dist/name-spelling-chars.d.ts +16 -0
- package/dist/name-spelling-chars.d.ts.map +1 -0
- package/dist/name-spelling-chars.js +14 -0
- package/dist/name-spelling-chars.js.map +1 -0
- package/dist/name-variants.d.ts +8 -2
- package/dist/name-variants.d.ts.map +1 -1
- package/dist/name-variants.js +72 -7
- package/dist/name-variants.js.map +1 -1
- package/dist/name-word-order.d.ts +49 -0
- package/dist/name-word-order.d.ts.map +1 -0
- package/dist/name-word-order.js +114 -0
- package/dist/name-word-order.js.map +1 -0
- package/dist/phone-numbers.d.ts.map +1 -1
- package/dist/phone-numbers.js +22 -5
- package/dist/phone-numbers.js.map +1 -1
- package/dist/place-names.d.ts +12 -5
- package/dist/place-names.d.ts.map +1 -1
- package/dist/place-names.js +34 -14
- package/dist/place-names.js.map +1 -1
- package/dist/plugin.d.ts +12 -0
- package/dist/plugin.d.ts.map +1 -1
- package/dist/preamble-paragraphs.d.ts +2 -1
- package/dist/preamble-paragraphs.d.ts.map +1 -1
- package/dist/preamble-paragraphs.js +16 -1
- package/dist/preamble-paragraphs.js.map +1 -1
- package/dist/profile/parse.d.ts.map +1 -1
- package/dist/profile/parse.js +11 -0
- package/dist/profile/parse.js.map +1 -1
- package/dist/return-type.d.ts +33 -0
- package/dist/return-type.d.ts.map +1 -0
- package/dist/return-type.js +302 -0
- package/dist/return-type.js.map +1 -0
- package/dist/spacing-code.d.ts +6 -0
- package/dist/spacing-code.d.ts.map +1 -0
- package/dist/spacing-code.js +16 -0
- package/dist/spacing-code.js.map +1 -0
- package/dist/structure/amount-range.d.ts +2 -2
- package/dist/structure/amount-range.d.ts.map +1 -1
- package/dist/structure/amount-range.js +12 -5
- package/dist/structure/amount-range.js.map +1 -1
- package/dist/structure/capacity-count.d.ts +59 -0
- package/dist/structure/capacity-count.d.ts.map +1 -0
- package/dist/structure/capacity-count.js +118 -0
- package/dist/structure/capacity-count.js.map +1 -0
- package/dist/structure/connection-times.d.ts +56 -0
- package/dist/structure/connection-times.d.ts.map +1 -0
- package/dist/structure/connection-times.js +165 -0
- package/dist/structure/connection-times.js.map +1 -0
- package/dist/structure/counted-amounts.d.ts +6 -0
- package/dist/structure/counted-amounts.d.ts.map +1 -1
- package/dist/structure/counted-amounts.js +4 -4
- package/dist/structure/counted-amounts.js.map +1 -1
- package/dist/structure/date-order-tie.d.ts +13 -0
- package/dist/structure/date-order-tie.d.ts.map +1 -0
- package/dist/structure/date-order-tie.js +61 -0
- package/dist/structure/date-order-tie.js.map +1 -0
- package/dist/structure/date-order.d.ts +2 -2
- package/dist/structure/date-order.d.ts.map +1 -1
- package/dist/structure/date-order.js +26 -9
- package/dist/structure/date-order.js.map +1 -1
- package/dist/structure/date-outside-period.d.ts +8 -0
- package/dist/structure/date-outside-period.d.ts.map +1 -1
- package/dist/structure/date-outside-period.js +52 -3
- package/dist/structure/date-outside-period.js.map +1 -1
- package/dist/structure/date-range.d.ts +6 -2
- package/dist/structure/date-range.d.ts.map +1 -1
- package/dist/structure/date-range.js +37 -9
- package/dist/structure/date-range.js.map +1 -1
- package/dist/structure/deadline-after-event.d.ts +23 -0
- package/dist/structure/deadline-after-event.d.ts.map +1 -0
- package/dist/structure/deadline-after-event.js +42 -0
- package/dist/structure/deadline-after-event.js.map +1 -0
- package/dist/structure/definition-use.d.ts +1 -1
- package/dist/structure/definition-use.d.ts.map +1 -1
- package/dist/structure/definition-use.js +55 -2
- package/dist/structure/definition-use.js.map +1 -1
- package/dist/structure/due-date.d.ts.map +1 -1
- package/dist/structure/due-date.js +5 -27
- package/dist/structure/due-date.js.map +1 -1
- package/dist/structure/labelled-date-order.d.ts +38 -0
- package/dist/structure/labelled-date-order.d.ts.map +1 -0
- package/dist/structure/labelled-date-order.js +41 -0
- package/dist/structure/labelled-date-order.js.map +1 -0
- package/dist/structure/layout-codes.d.ts +68 -0
- package/dist/structure/layout-codes.d.ts.map +1 -0
- package/dist/structure/layout-codes.js +161 -0
- package/dist/structure/layout-codes.js.map +1 -0
- package/dist/structure/leg-times.d.ts +2 -0
- package/dist/structure/leg-times.d.ts.map +1 -1
- package/dist/structure/leg-times.js +13 -0
- package/dist/structure/leg-times.js.map +1 -1
- package/dist/structure/measured-amounts.d.ts +17 -0
- package/dist/structure/measured-amounts.d.ts.map +1 -0
- package/dist/structure/measured-amounts.js +110 -0
- package/dist/structure/measured-amounts.js.map +1 -0
- package/dist/structure/party-order.d.ts +33 -0
- package/dist/structure/party-order.d.ts.map +1 -0
- package/dist/structure/party-order.js +79 -0
- package/dist/structure/party-order.js.map +1 -0
- package/dist/structure/quantity-range.d.ts +8 -0
- package/dist/structure/quantity-range.d.ts.map +1 -0
- package/dist/structure/quantity-range.js +36 -0
- package/dist/structure/quantity-range.js.map +1 -0
- package/dist/structure/range-bands.d.ts +75 -0
- package/dist/structure/range-bands.d.ts.map +1 -0
- package/dist/structure/range-bands.js +244 -0
- package/dist/structure/range-bands.js.map +1 -0
- package/dist/structure/rent-multiple.d.ts +76 -0
- package/dist/structure/rent-multiple.d.ts.map +1 -0
- package/dist/structure/rent-multiple.js +186 -0
- package/dist/structure/rent-multiple.js.map +1 -0
- package/dist/structure/requirement-lists.d.ts +37 -0
- package/dist/structure/requirement-lists.d.ts.map +1 -0
- package/dist/structure/requirement-lists.js +89 -0
- package/dist/structure/requirement-lists.js.map +1 -0
- package/dist/structure/scaled-quantities.d.ts +50 -0
- package/dist/structure/scaled-quantities.d.ts.map +1 -0
- package/dist/structure/scaled-quantities.js +153 -0
- package/dist/structure/scaled-quantities.js.map +1 -0
- package/dist/structure/stamp-order.d.ts +16 -0
- package/dist/structure/stamp-order.d.ts.map +1 -0
- package/dist/structure/stamp-order.js +78 -0
- package/dist/structure/stamp-order.js.map +1 -0
- package/dist/structure/step-times.d.ts +49 -0
- package/dist/structure/step-times.d.ts.map +1 -0
- package/dist/structure/step-times.js +128 -0
- package/dist/structure/step-times.js.map +1 -0
- package/dist/structure/term-deadline.d.ts +19 -0
- package/dist/structure/term-deadline.d.ts.map +1 -0
- package/dist/structure/term-deadline.js +28 -0
- package/dist/structure/term-deadline.js.map +1 -0
- package/dist/structure/time-order.d.ts +21 -0
- package/dist/structure/time-order.d.ts.map +1 -1
- package/dist/structure/time-order.js +5 -6
- package/dist/structure/time-order.js.map +1 -1
- package/dist/structure/time-range.d.ts +16 -0
- package/dist/structure/time-range.d.ts.map +1 -0
- package/dist/structure/time-range.js +57 -0
- package/dist/structure/time-range.js.map +1 -0
- package/dist/structure/total-line.d.ts +16 -0
- package/dist/structure/total-line.d.ts.map +1 -0
- package/dist/structure/total-line.js +44 -0
- package/dist/structure/total-line.js.map +1 -0
- package/dist/structure/total.d.ts +7 -1
- package/dist/structure/total.d.ts.map +1 -1
- package/dist/structure/total.js +28 -5
- package/dist/structure/total.js.map +1 -1
- package/dist/structure/unlisted-items.d.ts +70 -0
- package/dist/structure/unlisted-items.d.ts.map +1 -0
- package/dist/structure/unlisted-items.js +152 -0
- package/dist/structure/unlisted-items.js.map +1 -0
- package/dist/structure/version-order.d.ts +2 -0
- package/dist/structure/version-order.d.ts.map +1 -1
- package/dist/structure/version-order.js +10 -0
- package/dist/structure/version-order.js.map +1 -1
- package/dist/structure/walk-time.d.ts +87 -0
- package/dist/structure/walk-time.d.ts.map +1 -0
- package/dist/structure/walk-time.js +195 -0
- package/dist/structure/walk-time.js.map +1 -0
- package/dist/surname-near.d.ts +6 -0
- package/dist/surname-near.d.ts.map +1 -0
- package/dist/surname-near.js +31 -0
- package/dist/surname-near.js.map +1 -0
- package/dist/table-cells.d.ts +13 -0
- package/dist/table-cells.d.ts.map +1 -0
- package/dist/table-cells.js +36 -0
- package/dist/table-cells.js.map +1 -0
- package/dist/table-names.d.ts +42 -0
- package/dist/table-names.d.ts.map +1 -0
- package/dist/table-names.js +94 -0
- package/dist/table-names.js.map +1 -0
- package/package.json +3 -3
- package/profiles/listing.yaml +20 -0
- package/rules/announced-count-mismatch.yaml +2 -2
- package/rules/capacity-runtime-mismatch.yaml +66 -0
- package/rules/connection-time-short.yaml +52 -0
- package/rules/contact-variant.yaml +76 -0
- package/rules/count-over-capacity.yaml +55 -0
- package/rules/date-outside-period.yaml +4 -4
- package/rules/date-stamp-order.yaml +82 -0
- package/rules/deadline-after-event.yaml +67 -0
- package/rules/defined-name-repeated.yaml +2 -2
- package/rules/due-before-issue.yaml +11 -7
- package/rules/duration-mismatch.yaml +7 -4
- package/rules/duration-product-mismatch.yaml +73 -0
- package/rules/fact-conflict.yaml +9 -4
- package/rules/heading-echo.yaml +2 -2
- package/rules/interval-count-mismatch.yaml +54 -0
- package/rules/latin-spacing.yaml +2 -2
- package/rules/layout-code-mismatch.yaml +68 -0
- package/rules/name-variant.yaml +14 -2
- package/rules/no-em-dash.yaml +2 -2
- package/rules/party-order.yaml +84 -0
- package/rules/preamble-length.yaml +2 -2
- package/rules/quantity-range-reversed.yaml +53 -0
- package/rules/range-band-mismatch.yaml +70 -0
- package/rules/rent-multiple-mismatch.yaml +61 -0
- package/rules/required-listed-as-preferred.yaml +102 -0
- package/rules/return-type-mismatch.yaml +79 -0
- package/rules/scaled-quantity-mismatch.yaml +69 -0
- package/rules/step-time-sum-mismatch.yaml +65 -0
- package/rules/time-range-reversed.yaml +48 -0
- package/rules/title-case-consistency.yaml +2 -2
- package/rules/total-mismatch.yaml +2 -2
- package/rules/undefined-term.yaml +21 -7
- package/rules/unit-mismatch.yaml +12 -4
- package/rules/unlisted-item-used.yaml +90 -0
- package/rules/unused-definition.yaml +2 -2
- package/rules/use-before-definition.yaml +2 -2
- package/rules/walk-time-distance-mismatch.yaml +55 -0
- package/src/announced-count.ts +6 -3
- package/src/contacts/addresses.ts +179 -0
- package/src/contacts/emails.ts +63 -0
- package/src/contacts/variants.ts +33 -0
- package/src/derived/battery-runtime.ts +284 -0
- package/src/derived/period-counts.ts +178 -0
- package/src/derived/session-hours.ts +62 -0
- package/src/derived/time-lengths.ts +229 -0
- package/src/derived/unit-counts.ts +18 -0
- package/src/derived/use-interval.ts +151 -0
- package/src/derived/working-hours.ts +97 -0
- package/src/detectors/acronym-expansion.ts +57 -2
- package/src/detectors/announced-count.ts +1 -0
- package/src/detectors/capacity-runtime.ts +128 -0
- package/src/detectors/capitalised-term.ts +147 -0
- package/src/detectors/contact-variant.ts +24 -0
- package/src/detectors/count-over-capacity.ts +37 -0
- package/src/detectors/date-outside-period.ts +5 -1
- package/src/detectors/date-stamp-order.ts +28 -0
- package/src/detectors/defined-term-form.ts +63 -7
- package/src/detectors/definition-use.ts +6 -2
- package/src/detectors/derived-numbers.ts +97 -24
- package/src/detectors/due-date.ts +10 -2
- package/src/detectors/en-shape.ts +11 -4
- package/src/detectors/event-deadline.ts +29 -0
- package/src/detectors/fact-consistency.ts +64 -3
- package/src/detectors/heading-case.ts +13 -4
- package/src/detectors/heading-echo.ts +17 -1
- package/src/detectors/layout-code.ts +174 -0
- package/src/detectors/measured-facts.ts +20 -0
- package/src/detectors/name-variant-model-codes.ts +27 -0
- package/src/detectors/name-variant.ts +99 -15
- package/src/detectors/orthographic-variant.ts +78 -9
- package/src/detectors/orthography.ts +16 -6
- package/src/detectors/party-order.ts +50 -0
- package/src/detectors/quantity-range.ts +47 -0
- package/src/detectors/range-band.ts +125 -0
- package/src/detectors/registry/capacity-runtime-mismatch.ts +4 -0
- package/src/detectors/registry/connection-time-short.ts +4 -0
- package/src/detectors/registry/contact-variant.ts +4 -0
- package/src/detectors/registry/count-over-capacity.ts +4 -0
- package/src/detectors/registry/date-stamp-order.ts +4 -0
- package/src/detectors/registry/duration-product-mismatch.ts +4 -0
- package/src/detectors/registry/event-deadline.ts +4 -0
- package/src/detectors/registry/interval-count-mismatch.ts +4 -0
- package/src/detectors/registry/layout-code-mismatch.ts +4 -0
- package/src/detectors/registry/party-order.ts +4 -0
- package/src/detectors/registry/quantity-range.ts +4 -0
- package/src/detectors/registry/range-band-mismatch.ts +4 -0
- package/src/detectors/registry/rent-multiple-mismatch.ts +4 -0
- package/src/detectors/registry/requirement-lists.ts +4 -0
- package/src/detectors/registry/return-type.ts +4 -0
- package/src/detectors/registry/scaled-quantity-mismatch.ts +4 -0
- package/src/detectors/registry/step-time-sum-mismatch.ts +4 -0
- package/src/detectors/registry/time-range-reversed.ts +4 -0
- package/src/detectors/registry/unlisted-item-used.ts +4 -0
- package/src/detectors/registry/walk-time-distance-mismatch.ts +4 -0
- package/src/detectors/rent-multiple-mismatch.ts +56 -0
- package/src/detectors/requirement-lists.ts +65 -0
- package/src/detectors/return-type.ts +30 -0
- package/src/detectors/scaled-quantity.ts +49 -0
- package/src/detectors/signals.ts +3 -1
- package/src/detectors/step-time-sum.ts +55 -0
- package/src/detectors/structure-tree.ts +42 -6
- package/src/detectors/structure.ts +1 -1
- package/src/detectors/technical-docs.ts +12 -0
- package/src/detectors/time-order.ts +45 -6
- package/src/detectors/undefined-term.ts +20 -3
- package/src/detectors/unit-consistency.ts +50 -38
- package/src/detectors/unlisted-items.ts +72 -0
- package/src/detectors/use-count-words.ts +32 -0
- package/src/detectors/use-interval.ts +51 -0
- package/src/detectors/walk-time-distance-mismatch.ts +45 -0
- package/src/document.ts +4 -1
- package/src/facts/approximate-tolerance.ts +19 -0
- package/src/facts/item-amounts.ts +94 -0
- package/src/facts/labelled-facts.ts +29 -7
- package/src/facts/measure-units.ts +31 -0
- package/src/facts/measures.ts +113 -25
- package/src/facts/retention-periods.ts +216 -0
- package/src/facts/table-facts.ts +3 -0
- package/src/facts/unit-conflicts.ts +22 -9
- package/src/facts/unit-equivalents.ts +70 -0
- package/src/facts/unit-tolerance.ts +17 -0
- package/src/facts/unit-word.ts +35 -0
- package/src/facts/written-precision.ts +23 -0
- package/src/kana-spelling.ts +25 -0
- package/src/model-codes.ts +104 -0
- package/src/name-spelling-chars.ts +34 -0
- package/src/name-variants.ts +83 -7
- package/src/name-word-order.ts +149 -0
- package/src/phone-numbers.ts +26 -6
- package/src/place-names.ts +53 -14
- package/src/plugin.ts +7 -0
- package/src/preamble-paragraphs.ts +21 -2
- package/src/profile/parse.ts +10 -0
- package/src/return-type.ts +361 -0
- package/src/spacing-code.ts +26 -0
- package/src/structure/amount-range.ts +16 -7
- package/src/structure/capacity-count.ts +196 -0
- package/src/structure/connection-times.ts +226 -0
- package/src/structure/counted-amounts.ts +5 -4
- package/src/structure/date-order-tie.ts +86 -0
- package/src/structure/date-order.ts +41 -14
- package/src/structure/date-outside-period.ts +77 -7
- package/src/structure/date-range.ts +45 -9
- package/src/structure/deadline-after-event.ts +67 -0
- package/src/structure/definition-use.ts +59 -2
- package/src/structure/due-date.ts +8 -32
- package/src/structure/labelled-date-order.ts +84 -0
- package/src/structure/layout-codes.ts +210 -0
- package/src/structure/leg-times.ts +15 -0
- package/src/structure/measured-amounts.ts +138 -0
- package/src/structure/party-order.ts +115 -0
- package/src/structure/quantity-range.ts +54 -0
- package/src/structure/range-bands.ts +316 -0
- package/src/structure/rent-multiple.ts +277 -0
- package/src/structure/requirement-lists.ts +145 -0
- package/src/structure/scaled-quantities.ts +225 -0
- package/src/structure/stamp-order.ts +100 -0
- package/src/structure/step-times.ts +169 -0
- package/src/structure/term-deadline.ts +35 -0
- package/src/structure/time-order.ts +8 -7
- package/src/structure/time-range.ts +64 -0
- package/src/structure/total-line.ts +63 -0
- package/src/structure/total.ts +41 -6
- package/src/structure/unlisted-items.ts +207 -0
- package/src/structure/version-order.ts +10 -0
- package/src/structure/walk-time.ts +285 -0
- package/src/surname-near.ts +31 -0
- package/src/table-cells.ts +41 -0
- package/src/table-names.ts +113 -0
|
@@ -107,20 +107,48 @@ const sentenceAround = (source: string, start: DatedSpan, end: DatedSpan): { rea
|
|
|
107
107
|
return { text: flat(source.slice(paragraphStart + from, end.end + to)), before: flat(head.slice(from)).trimEnd() };
|
|
108
108
|
};
|
|
109
109
|
|
|
110
|
-
/**
|
|
110
|
+
/** 同じ文のどこかに変更の語(moved、postponed)があれば、日付を動かした文で、期間ではない。 */
|
|
111
|
+
const isChange = (source: string, start: DatedSpan, end: DatedSpan, words: RangeWords): boolean => {
|
|
112
|
+
const sentence = sentenceAround(source, start, end).text;
|
|
113
|
+
return words.changes.some((change) => hasWord(sentence, change.toLowerCase()));
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
/** 前の語と間の語の組(from … to)。 */
|
|
111
117
|
const framed = (source: string, start: DatedSpan, end: DatedSpan, joint: string, words: RangeWords): boolean => {
|
|
112
|
-
const
|
|
113
|
-
const before = withoutTrailingWeekday(sentence.before, words.weekdays ?? []);
|
|
118
|
+
const before = withoutTrailingWeekday(sentenceAround(source, start, end).before, words.weekdays ?? []);
|
|
114
119
|
const frame = words.frames.find((candidate) => candidate.joint === joint && endsWithWord(before, candidate.lead));
|
|
115
|
-
return frame !== undefined && !
|
|
120
|
+
return frame !== undefined && !isChange(source, start, end, words);
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
const FULL_DATE = /^\d{4}-\d{2}-\d{2}$/u;
|
|
124
|
+
|
|
125
|
+
/** 日付の前に曜日の名を添えた(Monday, October 5, 2026)。同じ行の、日付の直前だけを見る。 */
|
|
126
|
+
const weekdayBefore = (source: string, date: DatedSpan, weekdays: readonly string[]): boolean => {
|
|
127
|
+
const before = source.slice(source.lastIndexOf("\n", date.offset - 1) + 1, date.offset).trimEnd();
|
|
128
|
+
return before !== "" && withoutTrailingWeekday(before, weekdays) !== before;
|
|
116
129
|
};
|
|
117
130
|
|
|
118
|
-
|
|
131
|
+
/**
|
|
132
|
+
* 前の語の無い組の間の語だけ(October 5, 2026 to October 30, 2026)。「to」は日付を動かす文にも出るので、
|
|
133
|
+
* 期間の語で始まる行(Dates: …)か、両方が曜日を添えた年月日のときだけ期間と読む。変更の語のある文は読まない。
|
|
134
|
+
*/
|
|
135
|
+
const bareFramed = (source: string, start: DatedSpan, end: DatedSpan, written: string, words: RangeWords, isLabelled: (offset: number) => boolean): boolean => {
|
|
136
|
+
const weekdays = words.weekdays ?? [];
|
|
137
|
+
const joint = withoutTrailingWeekday(written, weekdays);
|
|
138
|
+
if (!words.frames.some((frame) => frame.joint === joint)) return false;
|
|
139
|
+
const withWeekdays = FULL_DATE.test(start.value) && FULL_DATE.test(end.value) && joint !== written && weekdayBefore(source, start, weekdays);
|
|
140
|
+
return (isLabelled(start.offset) || withWeekdays) && !isChange(source, start, end, words);
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
export const isRange = (source: string, start: DatedSpan, end: DatedSpan, words: RangeWords, isLabelled: (offset: number) => boolean): boolean => {
|
|
119
144
|
const written = jointOf(source, start, end);
|
|
120
145
|
if (written === undefined) return false;
|
|
121
146
|
const joint = withoutTrailingWeekday(written, words.weekdays ?? []);
|
|
122
147
|
return (
|
|
123
|
-
isOneOf(joint, words.connectors) ||
|
|
148
|
+
isOneOf(joint, words.connectors) ||
|
|
149
|
+
(isOneOf(joint, words.openers) && closedAfter(source, end, words.closers)) ||
|
|
150
|
+
framed(source, start, end, joint, words) ||
|
|
151
|
+
bareFramed(source, start, end, written, words, isLabelled)
|
|
124
152
|
);
|
|
125
153
|
};
|
|
126
154
|
|
|
@@ -132,11 +160,19 @@ const writtenPeriod = (source: string, start: DatedSpan, end: DatedSpan): string
|
|
|
132
160
|
.map((part) => part.trim())
|
|
133
161
|
.join(" ");
|
|
134
162
|
|
|
135
|
-
/**
|
|
136
|
-
|
|
163
|
+
/**
|
|
164
|
+
* 隣り合う二つの日付のうち、期間をなし、終わりが始まりより前のもの。期間の書き出しを指し、書いたままの期間を見せる。
|
|
165
|
+
* isLabelled は、その位置の日付が期間の語で始まる行(Dates: …)の、語より後ろにあるか。
|
|
166
|
+
*/
|
|
167
|
+
export const reversedRanges = (
|
|
168
|
+
source: string,
|
|
169
|
+
dates: readonly DatedSpan[],
|
|
170
|
+
words: RangeWords,
|
|
171
|
+
isLabelled: (offset: number) => boolean = () => false,
|
|
172
|
+
): StructureIssue[] =>
|
|
137
173
|
dates.slice(1).flatMap((end, index) => {
|
|
138
174
|
const start = dates[index];
|
|
139
175
|
if (start === undefined || !comparable(start.value, end.value) || end.value >= start.value) return [];
|
|
140
|
-
if (!isRange(source, start, end, words)) return [];
|
|
176
|
+
if (!isRange(source, start, end, words, isLabelled)) return [];
|
|
141
177
|
return [{ offset: start.offset, values: { start: start.value, end: end.value, period: writtenPeriod(source, start, end) } }];
|
|
142
178
|
});
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { mentions } from "./date-outside-period.ts";
|
|
2
|
+
import type { DatedPoint } from "./due-date.ts";
|
|
3
|
+
import type { StructureIssue } from "./issues.ts";
|
|
4
|
+
import { lineNumberAt, linesOf, type Line } from "./lines.ts";
|
|
5
|
+
import { isTotalLabel } from "./total.ts";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 催しの後の申込締切。催しの日の語で始まり時刻のある一行(日時:2026年11月20日(金)14:00〜)が催しの日を書き、
|
|
9
|
+
* 申込の語(申込、RSVP)と締め切りの語(までに、by)のある文か行の、年のある日付がどの催しの日よりも後なら指す。
|
|
10
|
+
* 時刻を求めるのは、手紙の頭の「Date: …」を催しの日と読まないため。催しの後に来てよいもの(アンケート、支払)の語が同じ文にあれば比べない。
|
|
11
|
+
* 文か行に日付が二つ以上あれば、どれが締め切りか分からないので比べない。Pure.
|
|
12
|
+
*/
|
|
13
|
+
export type EventDeadlineWords = {
|
|
14
|
+
readonly events: readonly string[];
|
|
15
|
+
readonly registrations: readonly string[];
|
|
16
|
+
readonly deadlines: readonly string[];
|
|
17
|
+
readonly asides: readonly string[];
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
type Span = { readonly start: number; readonly end: number };
|
|
21
|
+
|
|
22
|
+
const FULL_DATE = /^\d{4}-\d{2}-\d{2}$/u;
|
|
23
|
+
const CLOCK_TIME = /(?<!\d)\d{1,2}[::]\d{2}(?!\d)/u;
|
|
24
|
+
|
|
25
|
+
/** 年月日(2026-11-20)の並びでいちばん後のもの。字の順が日付の順になる。 */
|
|
26
|
+
const latestOf = (values: readonly string[]): string | undefined =>
|
|
27
|
+
values.reduce<string | undefined>((latest, value) => (latest === undefined || value > latest ? value : latest), undefined);
|
|
28
|
+
|
|
29
|
+
const endOf = (line: Line): number => line.start + line.text.length;
|
|
30
|
+
|
|
31
|
+
const datesIn = (dates: readonly DatedPoint[], span: Span): DatedPoint[] => dates.filter((date) => date.offset >= span.start && date.offset < span.end);
|
|
32
|
+
|
|
33
|
+
/** 催しの日: 催しの日の語で始まり、時刻と年のある日付を書いた行の、いちばん後の日付。 */
|
|
34
|
+
const eventDayOf = (line: Line, dates: readonly DatedPoint[], words: EventDeadlineWords): string | undefined => {
|
|
35
|
+
if (!isTotalLabel(line.text, words.events) || !CLOCK_TIME.test(line.text)) return undefined;
|
|
36
|
+
const values = datesIn(dates, { start: line.start, end: endOf(line) }).map((date) => date.value);
|
|
37
|
+
return latestOf(values.filter((value) => FULL_DATE.test(value)));
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/** 日付を囲む文を、その行の中に切ったもの。文が見つからなければ行。 */
|
|
41
|
+
const unitOf = (offset: number, line: Line, sentences: readonly Span[]): Span => {
|
|
42
|
+
const sentence = sentences.find((span) => span.start <= offset && offset < span.end);
|
|
43
|
+
return { start: Math.max(sentence?.start ?? line.start, line.start), end: Math.min(sentence?.end ?? endOf(line), endOf(line)) };
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
/** 申込の締め切りを書いた文か: 申込の語と締め切りの語があり、催しの後に来てよいものの語が無い。 */
|
|
47
|
+
export const isRegistrationDeadline = (text: string, words: EventDeadlineWords): boolean =>
|
|
48
|
+
mentions(text, words.registrations) && mentions(text, words.deadlines) && !mentions(text, words.asides);
|
|
49
|
+
|
|
50
|
+
type Reading = { readonly source: string; readonly lines: readonly Line[]; readonly dates: readonly DatedPoint[]; readonly sentences: readonly Span[] };
|
|
51
|
+
|
|
52
|
+
const lateDeadlines = (reading: Reading, words: EventDeadlineWords, event: string): StructureIssue[] =>
|
|
53
|
+
reading.dates.flatMap((date) => {
|
|
54
|
+
if (!FULL_DATE.test(date.value) || date.value <= event) return [];
|
|
55
|
+
const line = reading.lines[(lineNumberAt(reading.lines, date.offset) ?? 0) - 1];
|
|
56
|
+
if (line === undefined) return [];
|
|
57
|
+
const unit = unitOf(date.offset, line, reading.sentences);
|
|
58
|
+
if (datesIn(reading.dates, unit).length > 1 || !isRegistrationDeadline(reading.source.slice(unit.start, unit.end), words)) return [];
|
|
59
|
+
return [{ offset: date.offset, values: { deadline: date.value, event } }];
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
export const deadlinesAfterEvent = (source: string, dates: readonly DatedPoint[], sentences: readonly Span[], words: EventDeadlineWords): StructureIssue[] => {
|
|
63
|
+
if (words.events.length === 0 || words.registrations.length === 0 || words.deadlines.length === 0) return [];
|
|
64
|
+
const lines = linesOf(source);
|
|
65
|
+
const event = latestOf(lines.flatMap((line) => eventDayOf(line, dates, words) ?? []));
|
|
66
|
+
return event === undefined ? [] : lateDeadlines({ source, lines, dates, sentences }, words, event);
|
|
67
|
+
};
|
|
@@ -148,6 +148,58 @@ const continuesInHan = (texts: readonly BodyText[], term: string, offset: number
|
|
|
148
148
|
return body !== undefined && HAN.test(term.at(-1) ?? "") && HAN.test(body.text.charAt(offset - body.start + term.length));
|
|
149
149
|
};
|
|
150
150
|
|
|
151
|
+
/** 半角の長音・濁点・中黒(ー ゙ ゚ ・)は Katakana の字ではないが、片仮名の名前の一部。 */
|
|
152
|
+
const KATAKANA = /[\p{Script=Katakana}ーー゙゚]/u;
|
|
153
|
+
const NAKAGURO = /[・・]/u;
|
|
154
|
+
|
|
155
|
+
/** 語の外側の隣の字(next)とその向こうの字(beyond)が、片仮名か「・片仮名」か。 */
|
|
156
|
+
const katakanaJoins = (next: string, beyond: string): boolean => KATAKANA.test(next) || (NAKAGURO.test(next) && KATAKANA.test(beyond));
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* 片仮名の端に片仮名が続く現れ、または「・」で片仮名とつないだ現れは、もっと長い名前の一部
|
|
160
|
+
* (クリエイティブ・コモンズ・パブリック・ライセンスのパブリック・ライセンス、サブライセンスのライセンス)。
|
|
161
|
+
*/
|
|
162
|
+
const insideKatakanaName = (texts: readonly BodyText[], term: string, offset: number): boolean => {
|
|
163
|
+
const body = sentenceAt(texts, offset);
|
|
164
|
+
if (body === undefined) return false;
|
|
165
|
+
const at = offset - body.start;
|
|
166
|
+
const end = at + term.length;
|
|
167
|
+
const joinedBefore = at > 0 && katakanaJoins(body.text.charAt(at - 1), at > 1 ? body.text.charAt(at - 2) : "");
|
|
168
|
+
const joinedAfter = katakanaJoins(body.text.charAt(end), body.text.charAt(end + 1));
|
|
169
|
+
return (KATAKANA.test(term.charAt(0)) && joinedBefore) || (KATAKANA.test(term.at(-1) ?? "") && joinedAfter);
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
/** 長い名前の写しと読むのに、語の前で定義の名前と重ならなければならない字の数(手引き の前の「の」と「成」)。 */
|
|
173
|
+
const MIN_ECHO = 2;
|
|
174
|
+
const OPENING_BRACKET = /[\s((]/u;
|
|
175
|
+
|
|
176
|
+
/** 定義の括弧を開けた字((、空白)を後ろから外した、括弧の前の名前。 */
|
|
177
|
+
const nameBefore = (text: string): string => {
|
|
178
|
+
let end = text.length;
|
|
179
|
+
while (end > 0 && OPENING_BRACKET.test(text.charAt(end - 1))) end -= 1;
|
|
180
|
+
return text.slice(0, end);
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
/** 二つの文字列が後ろから何字重なるか。 */
|
|
184
|
+
const sharedTail = (left: string, right: string): number => {
|
|
185
|
+
let shared = 0;
|
|
186
|
+
while (shared < left.length && shared < right.length && left.at(-1 - shared) === right.at(-1 - shared)) shared += 1;
|
|
187
|
+
return shared;
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* 定義の括弧の前に書いた長い名前(…ガイドライン作成の手引き(以下、「手引き」という。))を、定義より前でそのまま書いた所。
|
|
192
|
+
* 名前が語で終わり、語の前の字も名前と同じなら、それは長い名前で、定義した短い名前の使用ではない。
|
|
193
|
+
*/
|
|
194
|
+
const echoesLongName = (texts: readonly BodyText[], defined: DefinedTerm, offset: number): boolean => {
|
|
195
|
+
const defining = sentenceAt(texts, defined.span.start);
|
|
196
|
+
const using = sentenceAt(texts, offset);
|
|
197
|
+
if (defining === undefined || using === undefined) return false;
|
|
198
|
+
const name = nameBefore(defining.text.slice(0, defined.span.start - defining.start));
|
|
199
|
+
const written = using.text.slice(0, offset - using.start + defined.term.length);
|
|
200
|
+
return name.endsWith(defined.term) && sharedTail(name, written) >= defined.term.length + MIN_ECHO;
|
|
201
|
+
};
|
|
202
|
+
|
|
151
203
|
const CAPITAL_OR_NON_LATIN = /\p{Lu}|[^\p{Script=Latin}\p{N}\s\p{P}]/u;
|
|
152
204
|
|
|
153
205
|
/**
|
|
@@ -159,7 +211,7 @@ const isDistinctive = (term: string): boolean => CAPITAL_OR_NON_LATIN.test(term)
|
|
|
159
211
|
/**
|
|
160
212
|
* 文の途中で括弧に入れて定義した語((the "Seller")、以下「甲」という)を、その定義の文より前で使っている所。最初の一つだけ。
|
|
161
213
|
* 定義の文の中の現れ(株式会社GovTech東京(以下「GovTech東京」という。))は、定義する名前そのものなので数えない。札の文も、
|
|
162
|
-
* isTitle
|
|
214
|
+
* isTitle が言う題・見出しの行も、漢字で終わる語にさらに漢字が続く長い語の一部も、定義の括弧の前の長い名前を写した所も数えない。
|
|
163
215
|
* 定義の条("Seller" means、「甲」とは)は条の並びの頭にも終わりにも置く書き方があるので、前で使っても言わない。
|
|
164
216
|
* 定義の語の無い括弧の引用(("The key point is"))は例の引用と同じ形なので、その語を引用符で挙げただけの現れ
|
|
165
217
|
* (Its sentences open with "The key point is")は使用ではない。定義の語のある定義((the "Seller")、以下「買主」という)は、
|
|
@@ -177,7 +229,12 @@ export const usesBeforeDefinition = (
|
|
|
177
229
|
const defining = sentenceAt(texts, defined.span.start)?.start ?? defined.span.start;
|
|
178
230
|
const uses = usesOf(defined.term, texts, spans, "exact", defined.bare === true ? mentioned : NEVER_MENTIONED);
|
|
179
231
|
const first = uses.find(
|
|
180
|
-
(offset) =>
|
|
232
|
+
(offset) =>
|
|
233
|
+
!isLabel(sentenceAt(texts, offset), defined.term) &&
|
|
234
|
+
!isTitle(offset) &&
|
|
235
|
+
!continuesInHan(texts, defined.term, offset) &&
|
|
236
|
+
!insideKatakanaName(texts, defined.term, offset) &&
|
|
237
|
+
!echoesLongName(texts, defined, offset),
|
|
181
238
|
);
|
|
182
239
|
return first !== undefined && first < defining ? [{ term: defined, offset: first }] : [];
|
|
183
240
|
});
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
+
import { datesOutOfOrder } from "./labelled-date-order.ts";
|
|
1
2
|
import type { StructureIssue } from "./issues.ts";
|
|
2
|
-
import { linesOf } from "./lines.ts";
|
|
3
|
-
import { isTotalLabel } from "./total.ts";
|
|
4
3
|
|
|
5
4
|
/**
|
|
6
5
|
* A due date before the issue date. A line (or a list item, or a table's first column) starting with an issue-date word
|
|
@@ -10,37 +9,14 @@ import { isTotalLabel } from "./total.ts";
|
|
|
10
9
|
*/
|
|
11
10
|
export type DueWords = { readonly issue: readonly string[]; readonly due: readonly string[]; readonly passed: readonly string[] };
|
|
12
11
|
|
|
13
|
-
/** How many lines from the issue date a due date may be and still be read as the same document's deadline. */
|
|
14
|
-
const MAX_LINE_GAP = 8;
|
|
15
|
-
|
|
16
12
|
/** A date of the structure tree: where it starts and its value (2026-11-25). */
|
|
17
13
|
export type DatedPoint = { readonly offset: number; readonly value: string };
|
|
18
14
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
type Labelled = { readonly kind: "issue" | "due"; readonly date: DatedPoint; readonly line: number };
|
|
22
|
-
|
|
23
|
-
const kindOf = (text: string, words: DueWords): Labelled["kind"] | undefined => {
|
|
24
|
-
if (isTotalLabel(text, words.issue)) return "issue";
|
|
25
|
-
return isTotalLabel(text, words.due) ? "due" : undefined;
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
const labelledDates = (source: string, dates: readonly DatedPoint[], words: DueWords): Labelled[] =>
|
|
29
|
-
linesOf(source).flatMap((line) => {
|
|
30
|
-
const passed = words.passed.some((word) => line.text.toLowerCase().includes(word.toLowerCase()));
|
|
31
|
-
const kind = passed ? undefined : kindOf(line.text, words);
|
|
32
|
-
const end = line.start + line.text.length;
|
|
33
|
-
const onLine = dates.filter((date) => date.offset >= line.start && date.offset <= end && FULL_DATE.test(date.value));
|
|
34
|
-
const [date] = onLine;
|
|
35
|
-
return kind === undefined || date === undefined || onLine.length > 1 ? [] : [{ kind, date, line: line.number }];
|
|
36
|
-
});
|
|
15
|
+
/** How many lines from the issue date a due date may be and still be read as the same document's deadline. */
|
|
16
|
+
const MAX_LINE_GAP = 8;
|
|
37
17
|
|
|
38
|
-
export const dueBeforeIssue = (source: string, dates: readonly DatedPoint[], words: DueWords): StructureIssue[] =>
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
return labelled
|
|
44
|
-
.filter((entry) => entry.kind === "due" && entry.date.value < issued.date.value && Math.abs(entry.line - issued.line) < MAX_LINE_GAP)
|
|
45
|
-
.map((entry) => ({ offset: entry.date.offset, values: { due: entry.date.value, issued: issued.date.value } }));
|
|
46
|
-
};
|
|
18
|
+
export const dueBeforeIssue = (source: string, dates: readonly DatedPoint[], words: DueWords): StructureIssue[] =>
|
|
19
|
+
datesOutOfOrder(source, dates, { earlier: words.issue, later: words.due, passed: words.passed, maxLineGap: MAX_LINE_GAP }).map(({ earlier, later }) => ({
|
|
20
|
+
offset: later.date.offset,
|
|
21
|
+
values: { due: later.date.value, issued: earlier.date.value },
|
|
22
|
+
}));
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { DatedPoint } from "./due-date.ts";
|
|
2
|
+
import type { StructureIssue } from "./issues.ts";
|
|
3
|
+
import { linesOf } from "./lines.ts";
|
|
4
|
+
import { isTotalLabel } from "./total.ts";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Two labelled dates that must come in order: a line (or a list item, or a table's first column) starting with an
|
|
8
|
+
* earlier-date word and one starting with a later-date word, each with one full date on it. A later date before the
|
|
9
|
+
* first earlier date, and written near it, is out of order. A line with a passed word (期限切れ, overdue) reports on a
|
|
10
|
+
* date rather than setting one and is not read. Pure.
|
|
11
|
+
*/
|
|
12
|
+
export type DateOrderWords = {
|
|
13
|
+
readonly earlier: readonly string[];
|
|
14
|
+
readonly later: readonly string[];
|
|
15
|
+
readonly passed: readonly string[];
|
|
16
|
+
/** How many lines from the earlier date a later date may be and still be read as the same record's. */
|
|
17
|
+
readonly maxLineGap: number;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/** A labelled date: the word that labels it, as the lexicon writes it. */
|
|
21
|
+
export type LabelledDate = { readonly label: string; readonly date: DatedPoint; readonly line: number };
|
|
22
|
+
|
|
23
|
+
export type OutOfOrder = { readonly earlier: LabelledDate; readonly later: LabelledDate };
|
|
24
|
+
|
|
25
|
+
const FULL_DATE = /^\d{4}-\d{2}-\d{2}$/u;
|
|
26
|
+
|
|
27
|
+
type Read = LabelledDate & { readonly kind: "earlier" | "later" };
|
|
28
|
+
|
|
29
|
+
const labelOf = (text: string, words: readonly string[]): string | undefined => words.find((word) => isTotalLabel(text, [word]));
|
|
30
|
+
|
|
31
|
+
const kindOf = (text: string, words: DateOrderWords): Pick<Read, "kind" | "label"> | undefined => {
|
|
32
|
+
const earlier = labelOf(text, words.earlier);
|
|
33
|
+
if (earlier !== undefined) return { kind: "earlier", label: earlier };
|
|
34
|
+
const later = labelOf(text, words.later);
|
|
35
|
+
return later === undefined ? undefined : { kind: "later", label: later };
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const labelledDates = (source: string, dates: readonly DatedPoint[], words: DateOrderWords): Read[] =>
|
|
39
|
+
linesOf(source).flatMap((line) => {
|
|
40
|
+
const passed = words.passed.some((word) => line.text.toLowerCase().includes(word.toLowerCase()));
|
|
41
|
+
const kind = passed ? undefined : kindOf(line.text, words);
|
|
42
|
+
const end = line.start + line.text.length;
|
|
43
|
+
const onLine = dates.filter((date) => date.offset >= line.start && date.offset <= end && FULL_DATE.test(date.value));
|
|
44
|
+
const [date] = onLine;
|
|
45
|
+
return kind === undefined || date === undefined || onLine.length > 1 ? [] : [{ ...kind, date, line: line.number }];
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
export const datesOutOfOrder = (source: string, dates: readonly DatedPoint[], words: DateOrderWords): OutOfOrder[] => {
|
|
49
|
+
if (words.earlier.length === 0 || words.later.length === 0) return [];
|
|
50
|
+
const labelled = labelledDates(source, dates, words);
|
|
51
|
+
const earlier = labelled.find((entry) => entry.kind === "earlier");
|
|
52
|
+
if (earlier === undefined) return [];
|
|
53
|
+
return labelled
|
|
54
|
+
.filter((entry) => entry.kind === "later" && entry.date.value < earlier.date.value && Math.abs(entry.line - earlier.line) < words.maxLineGap)
|
|
55
|
+
.map((later) => ({ earlier, later }));
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/** A lexicon entry naming its pair (group) and its side: before for the earlier date, after for the later one. */
|
|
59
|
+
export type OrderLabel = { readonly pattern: string; readonly group?: string | undefined; readonly position?: "before" | "after" | undefined };
|
|
60
|
+
|
|
61
|
+
const groupsOf = (labels: readonly OrderLabel[]): string[] => [...new Set(labels.flatMap((label) => (label.group === undefined ? [] : [label.group])))];
|
|
62
|
+
|
|
63
|
+
const sideOf = (labels: readonly OrderLabel[], group: string, position: "before" | "after"): string[] =>
|
|
64
|
+
labels.filter((label) => label.group === group && label.position === position).map((label) => label.pattern);
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Every pair of a dated-pair lexicon: the entries of one group with position before label the earlier date, those with
|
|
68
|
+
* position after the later one. The values name both labels, so the message can quote them.
|
|
69
|
+
*/
|
|
70
|
+
export const pairedDatesOutOfOrder = (
|
|
71
|
+
source: string,
|
|
72
|
+
dates: readonly DatedPoint[],
|
|
73
|
+
labels: readonly OrderLabel[],
|
|
74
|
+
passed: readonly string[],
|
|
75
|
+
maxLineGap: number,
|
|
76
|
+
): StructureIssue[] =>
|
|
77
|
+
groupsOf(labels).flatMap((group) =>
|
|
78
|
+
datesOutOfOrder(source, dates, { earlier: sideOf(labels, group, "before"), later: sideOf(labels, group, "after"), passed, maxLineGap }).map(
|
|
79
|
+
({ earlier, later }) => ({
|
|
80
|
+
offset: later.date.offset,
|
|
81
|
+
values: { later: later.date.value, earlier: earlier.date.value, later_label: later.label, earlier_label: earlier.label },
|
|
82
|
+
}),
|
|
83
|
+
),
|
|
84
|
+
);
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
// layout-code-mismatch: a layout code (2LDK, "2 bedrooms") against the rooms a listing names. Pure: the words come in as
|
|
2
|
+
// LayoutWords (the layout-code and layout-room lexicons), the text as strings.
|
|
3
|
+
|
|
4
|
+
export type LayoutPart = "living" | "dining" | "kitchen";
|
|
5
|
+
export type LetterGroup = LayoutPart | "storage" | "one-room";
|
|
6
|
+
export type RoomGroup = LayoutPart | "room" | "storage" | "unclear";
|
|
7
|
+
|
|
8
|
+
export type LayoutWords = {
|
|
9
|
+
/** One-letter marks written right after the number (L, D, K, S, R). */
|
|
10
|
+
readonly letters: ReadonlyMap<string, LetterGroup>;
|
|
11
|
+
/** Marks that add a room not counted (2LDK+S). */
|
|
12
|
+
readonly joiners: readonly string[];
|
|
13
|
+
/** Words after the number that say what it counts ("bedrooms", "BR"). */
|
|
14
|
+
readonly counted: readonly string[];
|
|
15
|
+
readonly rooms: readonly { readonly pattern: string; readonly group: RoomGroup }[];
|
|
16
|
+
/** Words after a number that make it a count of rooms (洋室2室): an entry with one is not read as one room. */
|
|
17
|
+
readonly counters: readonly string[];
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export type LayoutCode = {
|
|
21
|
+
readonly text: string;
|
|
22
|
+
/** Where the code starts and ends in the text it was read from. */
|
|
23
|
+
readonly start: number;
|
|
24
|
+
readonly end: number;
|
|
25
|
+
readonly rooms: number;
|
|
26
|
+
/** The L, D and K a lettered code has. Undefined for a code that says nothing about them ("2 bedrooms", 1R). */
|
|
27
|
+
readonly parts: ReadonlySet<LayoutPart> | undefined;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export type Breakdown = {
|
|
31
|
+
readonly rooms: number;
|
|
32
|
+
/** Each L, D or K part the breakdown names, with the entry that names it. */
|
|
33
|
+
readonly parts: ReadonlyMap<LayoutPart, string>;
|
|
34
|
+
/** An entry that is a room in some listings and not in others, or names two kinds at once. */
|
|
35
|
+
readonly unclear: boolean;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export type LayoutSlip =
|
|
39
|
+
{ readonly kind: "count"; readonly code: LayoutCode; readonly listed: number } | { readonly kind: "part"; readonly code: LayoutCode; readonly entry: string };
|
|
40
|
+
|
|
41
|
+
const FULLWIDTH_OFFSET = 0xfee0;
|
|
42
|
+
const FULLWIDTH_FIRST = 0xff01;
|
|
43
|
+
const FULLWIDTH_LAST = 0xff5e;
|
|
44
|
+
|
|
45
|
+
/** Full-width ASCII (2LDK) as ASCII, one character for one, so offsets stay those of the source. */
|
|
46
|
+
export const foldWidth = (text: string): string =>
|
|
47
|
+
text.replace(/[!-~]/gu, (char) => {
|
|
48
|
+
const code = char.charCodeAt(0);
|
|
49
|
+
return code >= FULLWIDTH_FIRST && code <= FULLWIDTH_LAST ? String.fromCharCode(code - FULLWIDTH_OFFSET) : char;
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
const DIGITS = /\d+/uy;
|
|
53
|
+
const LATIN = /[a-z]/iu;
|
|
54
|
+
const WORD_CHAR = /[\p{L}\p{N}]/u;
|
|
55
|
+
|
|
56
|
+
/** Whether text has pattern at index, and does not run on into a longer word when the pattern is Latin (2BR is a word after a number). */
|
|
57
|
+
const wordAt = (text: string, index: number, pattern: string): boolean => {
|
|
58
|
+
if (text.slice(index, index + pattern.length).toLowerCase() !== pattern.toLowerCase()) return false;
|
|
59
|
+
if (!LATIN.test(pattern)) return true;
|
|
60
|
+
return !WORD_CHAR.test(text.charAt(index + pattern.length)) && !/\p{L}/u.test(text.charAt(index - 1));
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/** The longest code letters run (3SLDK). A longer run is a word, not a code. */
|
|
64
|
+
const MAX_CODE_LETTERS = 5;
|
|
65
|
+
/** The most "+S" a code adds (2LDK+S+納戸). */
|
|
66
|
+
const MAX_JOINS = 3;
|
|
67
|
+
|
|
68
|
+
/** The run of code letters at index (LDK, SLDK), with what they say; empty when the run is longer than a code. */
|
|
69
|
+
const lettersAt = (text: string, index: number, words: LayoutWords): LetterGroup[] => {
|
|
70
|
+
const head = Array.from(text.slice(index, index + MAX_CODE_LETTERS + 1));
|
|
71
|
+
const stop = head.findIndex((char) => !words.letters.has(char));
|
|
72
|
+
const length = stop === -1 ? head.length : stop;
|
|
73
|
+
if (length > MAX_CODE_LETTERS) return [];
|
|
74
|
+
return head.slice(0, length).flatMap((char) => words.letters.get(char) ?? []);
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
/** After a lettered code, each "+S" or "+納戸" that adds a room not counted: the index where they end. */
|
|
78
|
+
const joinedEnd = (text: string, index: number, words: LayoutWords, joins = 0): number => {
|
|
79
|
+
const joiner = words.joiners.find((mark) => text.startsWith(mark, index));
|
|
80
|
+
if (joiner === undefined || joins === MAX_JOINS) return index;
|
|
81
|
+
const after = index + joiner.length;
|
|
82
|
+
const letter = words.letters.get(text.charAt(after)) === "storage" ? 1 : 0;
|
|
83
|
+
const word = words.rooms.find((room) => room.group === "storage" && wordAt(text, after, room.pattern))?.pattern.length ?? letter;
|
|
84
|
+
return word === 0 ? index : joinedEnd(text, after + word, words, joins + 1);
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const letteredCode = (text: string, start: number, digitsEnd: number, words: LayoutWords): LayoutCode | undefined => {
|
|
88
|
+
const groups = lettersAt(text, digitsEnd, words);
|
|
89
|
+
const lettersEnd = digitsEnd + groups.length;
|
|
90
|
+
if (!groups.includes("kitchen") && !groups.includes("one-room")) return undefined;
|
|
91
|
+
if (LATIN.test(text.charAt(lettersEnd))) return undefined;
|
|
92
|
+
const end = joinedEnd(text, lettersEnd, words);
|
|
93
|
+
const parts = groups.includes("one-room") ? undefined : new Set(groups.filter((group): group is LayoutPart => group !== "storage"));
|
|
94
|
+
return { text: text.slice(start, end), start, end, rooms: Number(text.slice(start, digitsEnd)), parts };
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const SPACER = /[ \-‐–]?/uy;
|
|
98
|
+
|
|
99
|
+
const countedCode = (text: string, start: number, digitsEnd: number, words: LayoutWords): LayoutCode | undefined => {
|
|
100
|
+
SPACER.lastIndex = digitsEnd;
|
|
101
|
+
const after = digitsEnd + (SPACER.exec(text)?.[0].length ?? 0);
|
|
102
|
+
const word = words.counted.find((pattern) => wordAt(text, after, pattern));
|
|
103
|
+
if (word === undefined) return undefined;
|
|
104
|
+
const end = after + word.length;
|
|
105
|
+
return { text: text.slice(start, end), start, end, rooms: Number(text.slice(start, digitsEnd)), parts: undefined };
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
const codeAt = (text: string, start: number, words: LayoutWords): LayoutCode | undefined => {
|
|
109
|
+
if (/[\p{L}\p{N}.,]/u.test(text.charAt(start - 1))) return undefined;
|
|
110
|
+
DIGITS.lastIndex = start;
|
|
111
|
+
const digits = DIGITS.exec(text)?.[0];
|
|
112
|
+
if (digits === undefined) return undefined;
|
|
113
|
+
const digitsEnd = start + digits.length;
|
|
114
|
+
return letteredCode(text, start, digitsEnd, words) ?? countedCode(text, start, digitsEnd, words);
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* The one layout code a field value gives (2LDK, 3SLDK, 2LDK+S, "2 bedrooms", 2-bed, 2BR). A value with two codes of
|
|
119
|
+
* different counts ("2LDK or 3DK") gives none: which one the breakdown is for cannot be told.
|
|
120
|
+
*/
|
|
121
|
+
export const parseLayoutCode = (value: string, words: LayoutWords): LayoutCode | undefined => {
|
|
122
|
+
const text = foldWidth(value);
|
|
123
|
+
const codes = [...text.matchAll(/\d+/gu)].flatMap((match) => codeAt(text, match.index, words) ?? []);
|
|
124
|
+
const first = codes[0];
|
|
125
|
+
if (first === undefined || codes.some((code) => code.rooms !== first.rooms)) return undefined;
|
|
126
|
+
return { ...first, text: value.slice(first.start, first.end) };
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
const ENTRY_SEPARATOR = /[、,,・//++;;\n]/u;
|
|
130
|
+
const MULTIPLIER = /(?:[×✕]|(?<=[\s\d])[xX])\s*(\d+)\s*$/u;
|
|
131
|
+
|
|
132
|
+
/** The kinds of room an entry names, by the room words in it; a lone run of code letters (LDK 12帖, S 4帖) by its letters. */
|
|
133
|
+
const groupsOfEntry = (entry: string, words: LayoutWords): RoomGroup[] => {
|
|
134
|
+
const named = words.rooms.filter((room) => positions(entry).some((index) => wordAt(entry, index, room.pattern))).map((room) => room.group);
|
|
135
|
+
if (named.length > 0) return [...new Set(named)];
|
|
136
|
+
const letters = /^[A-Z]+(?![A-Za-z])/u.exec(entry)?.[0] ?? "";
|
|
137
|
+
const groups = [...letters].map((letter) => words.letters.get(letter));
|
|
138
|
+
if (letters === "" || groups.some((group) => group === undefined || group === "one-room")) return [];
|
|
139
|
+
return [...new Set(groups.flatMap((group): RoomGroup[] => (group === undefined || group === "one-room" ? [] : [group])))];
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
const positions = (entry: string): number[] => Array.from({ length: entry.length }, (_, index) => index);
|
|
143
|
+
|
|
144
|
+
/** How many rooms an entry names in words (Bedroom 1 and Bedroom 2 names two). */
|
|
145
|
+
const roomMentions = (entry: string, words: LayoutWords): number => {
|
|
146
|
+
const rooms = words.rooms.filter((room) => room.group === "room");
|
|
147
|
+
return positions(entry).filter((index) => rooms.some((room) => wordAt(entry, index, room.pattern))).length;
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
/** Whether the entry counts rooms with a number (洋室2室, 和室 2間). */
|
|
151
|
+
const countsRooms = (entry: string, words: LayoutWords): boolean =>
|
|
152
|
+
[...entry.matchAll(/\d+\s*/gu)].some((match) => words.counters.some((counter) => entry.startsWith(counter, match.index + match[0].length)));
|
|
153
|
+
|
|
154
|
+
const isPart = (group: RoomGroup): group is LayoutPart => group === "living" || group === "dining" || group === "kitchen";
|
|
155
|
+
|
|
156
|
+
type Tally = { rooms: number; parts: Map<LayoutPart, string>; unclear: boolean };
|
|
157
|
+
|
|
158
|
+
const tallyEntry = (tally: Tally, entry: string, words: LayoutWords): Tally => {
|
|
159
|
+
const groups = groupsOfEntry(entry, words);
|
|
160
|
+
const rooms = groups.includes("room");
|
|
161
|
+
const several = rooms && (groups.length > 1 || roomMentions(entry, words) > 1 || countsRooms(entry, words));
|
|
162
|
+
if (groups.includes("unclear") || several) return { ...tally, unclear: true };
|
|
163
|
+
const times = Number(MULTIPLIER.exec(entry)?.[1] ?? 1);
|
|
164
|
+
const parts = new Map(tally.parts);
|
|
165
|
+
groups.filter(isPart).forEach((part) => parts.set(part, parts.get(part) ?? entry));
|
|
166
|
+
return { rooms: tally.rooms + (rooms ? times : 0), parts, unclear: tally.unclear };
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
/** The rooms a breakdown names ("LDK 11.5帖、洋室 6帖、洋室 5帖", "Bedroom 1, Bedroom 2, Bathroom"). Entries it cannot name are left out. */
|
|
170
|
+
export const parseBreakdown = (entries: readonly string[], words: LayoutWords): Breakdown =>
|
|
171
|
+
entries
|
|
172
|
+
.flatMap((entry) => foldWidth(entry).split(ENTRY_SEPARATOR))
|
|
173
|
+
.map((entry) => entry.trim())
|
|
174
|
+
.filter((entry) => entry !== "")
|
|
175
|
+
.reduce<Tally>((tally, entry) => tallyEntry(tally, entry, words), { rooms: 0, parts: new Map(), unclear: false });
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Where a code and the breakdown of the same listing disagree. Silent when the breakdown names no room (it may list only
|
|
179
|
+
* the LDK), or names one that is counted in some listings and not in others. A lettered code is also checked for an L, D or
|
|
180
|
+
* K part the breakdown names and the code lacks; a one-room code (1R) and a counted code ("2 bedrooms") are not.
|
|
181
|
+
*/
|
|
182
|
+
export const layoutSlip = (code: LayoutCode, breakdown: Breakdown): LayoutSlip | undefined => {
|
|
183
|
+
if (breakdown.unclear || breakdown.rooms === 0) return undefined;
|
|
184
|
+
if (breakdown.rooms !== code.rooms) return { kind: "count", code, listed: breakdown.rooms };
|
|
185
|
+
const parts = code.parts;
|
|
186
|
+
if (parts === undefined) return undefined;
|
|
187
|
+
const extra = [...breakdown.parts].find(([part]) => !parts.has(part));
|
|
188
|
+
return extra === undefined ? undefined : { kind: "part", code, entry: extra[1] };
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* The codes and breakdowns of one page, paired listing by listing: within one scope (a section), the first code with the
|
|
193
|
+
* first breakdown and so on, but only when the scope has as many of each. Any other count is several listings that cannot
|
|
194
|
+
* be told apart, and none is paired.
|
|
195
|
+
*/
|
|
196
|
+
export const pairByScope = <C extends { readonly scope: number }, B extends { readonly scope: number }>(
|
|
197
|
+
codes: readonly C[],
|
|
198
|
+
breakdowns: readonly B[],
|
|
199
|
+
): [C, B][] => {
|
|
200
|
+
const scopes = [...new Set(codes.map((code) => code.scope))];
|
|
201
|
+
return scopes.flatMap((scope) => {
|
|
202
|
+
const inCodes = codes.filter((code) => code.scope === scope);
|
|
203
|
+
const inBreakdowns = breakdowns.filter((breakdown) => breakdown.scope === scope);
|
|
204
|
+
if (inCodes.length !== inBreakdowns.length) return [];
|
|
205
|
+
return inCodes.flatMap((code, index): [C, B][] => {
|
|
206
|
+
const breakdown = inBreakdowns[index];
|
|
207
|
+
return breakdown === undefined ? [] : [[code, breakdown]];
|
|
208
|
+
});
|
|
209
|
+
});
|
|
210
|
+
};
|
|
@@ -196,3 +196,18 @@ export const arrivalsBeforeDeparture = (source: string, times: readonly TimeSpan
|
|
|
196
196
|
.filter((issue, index) => issues.findIndex((other) => other.offset === issue.offset) === index)
|
|
197
197
|
.toSorted((left, right) => left.offset - right.offset);
|
|
198
198
|
};
|
|
199
|
+
|
|
200
|
+
/** 表の着の列に書いた時刻の位置。見出しに着の列の無い表からは読まない。 */
|
|
201
|
+
const columnArrivals = (inputs: Inputs): number[] =>
|
|
202
|
+
tablesOf(inputs.source).flatMap((table) => {
|
|
203
|
+
const arrives = columnOf(inputs.source, table.header, inputs.words.columns, ARRIVAL);
|
|
204
|
+
if (arrives === -1) return [];
|
|
205
|
+
return table.rows.flatMap((row) => cellTime(cellsOf(inputs.source, row.start, row.end)[arrives], inputs)?.offset ?? []);
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
/** 着と読む時刻の位置。行の中の印(「09:50着」「arrives 9:05 AM」)と、表の着の列から。 */
|
|
209
|
+
export const arrivalOffsets = (source: string, times: readonly TimeSpan[], dates: readonly DateSpan[], words: TimeWords): Set<number> => {
|
|
210
|
+
const inputs = { source, times, dates, words };
|
|
211
|
+
const inline = linesOf(source).flatMap((line) => legsInLine(line.start, line.end, inputs).flatMap((leg) => (leg.side === ARRIVAL ? [leg.offset] : [])));
|
|
212
|
+
return new Set([...inline, ...columnArrivals(inputs)]);
|
|
213
|
+
};
|