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
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
// layout-code-mismatch: a listing's layout code (2LDK, "3 bedrooms") against the rooms the same listing names
|
|
2
|
+
// (structure/layout-codes.ts). The code letters and counted words are layout-code's, the room names layout-room's, and the
|
|
3
|
+
// field names layout-label's.
|
|
4
|
+
import type { Detector, Finding, ProseDocument } from "../plugin.ts";
|
|
5
|
+
import { cellsOf, tablesOf, type Cell } from "../facts/table-facts.ts";
|
|
6
|
+
import { withoutEdgeMarks } from "../facts/trim-marks.ts";
|
|
7
|
+
import { linesOf, type Line } from "../structure/lines.ts";
|
|
8
|
+
import {
|
|
9
|
+
foldWidth,
|
|
10
|
+
layoutSlip,
|
|
11
|
+
pairByScope,
|
|
12
|
+
parseBreakdown,
|
|
13
|
+
parseLayoutCode,
|
|
14
|
+
type Breakdown,
|
|
15
|
+
type LayoutCode,
|
|
16
|
+
type LayoutSlip,
|
|
17
|
+
type LayoutWords,
|
|
18
|
+
type LetterGroup,
|
|
19
|
+
type RoomGroup,
|
|
20
|
+
} from "../structure/layout-codes.ts";
|
|
21
|
+
import { quoteAt } from "./structure-tree.ts";
|
|
22
|
+
|
|
23
|
+
type LabelGroup = "code" | "breakdown" | "room-column";
|
|
24
|
+
type Labels = ReadonlyMap<string, LabelGroup>;
|
|
25
|
+
|
|
26
|
+
const LETTER_GROUPS: readonly LetterGroup[] = ["living", "dining", "kitchen", "storage", "one-room"];
|
|
27
|
+
const ROOM_GROUPS: readonly RoomGroup[] = ["living", "dining", "kitchen", "room", "storage", "unclear"];
|
|
28
|
+
const LABEL_GROUPS: readonly LabelGroup[] = ["code", "breakdown", "room-column"];
|
|
29
|
+
|
|
30
|
+
const letterGroupOf = (group: string | undefined): LetterGroup | undefined => LETTER_GROUPS.find((known) => known === group);
|
|
31
|
+
|
|
32
|
+
export const layoutWordsOf = (lexicons: ProseDocument["lexicons"]): LayoutWords => {
|
|
33
|
+
const code = lexicons["layout-code"] ?? [];
|
|
34
|
+
return {
|
|
35
|
+
letters: new Map(
|
|
36
|
+
code.flatMap((entry): [string, LetterGroup][] => {
|
|
37
|
+
const group = letterGroupOf(entry.group);
|
|
38
|
+
return group === undefined ? [] : [[entry.pattern, group]];
|
|
39
|
+
}),
|
|
40
|
+
),
|
|
41
|
+
joiners: code.filter((entry) => entry.group === "joiner").map((entry) => entry.pattern),
|
|
42
|
+
counted: code.filter((entry) => entry.group === "counted").map((entry) => entry.pattern),
|
|
43
|
+
counters: code.filter((entry) => entry.group === "counter").map((entry) => entry.pattern),
|
|
44
|
+
rooms: (lexicons["layout-room"] ?? []).flatMap((entry) => {
|
|
45
|
+
const group = ROOM_GROUPS.find((known) => known === entry.group);
|
|
46
|
+
return group === undefined ? [] : [{ pattern: entry.pattern, group }];
|
|
47
|
+
}),
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const labelKey = (label: string): string => foldWidth(withoutEdgeMarks(label)).toLowerCase().replace(/\s+/gu, " ");
|
|
52
|
+
|
|
53
|
+
const labelsOf = (lexicons: ProseDocument["lexicons"]): Labels =>
|
|
54
|
+
new Map(
|
|
55
|
+
(lexicons["layout-label"] ?? []).flatMap((entry): [string, LabelGroup][] => {
|
|
56
|
+
const group = LABEL_GROUPS.find((known) => known === entry.group);
|
|
57
|
+
return group === undefined ? [] : [[labelKey(entry.pattern), group]];
|
|
58
|
+
}),
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
/** A code found in the page, with the breakdown written right with it when there is one (a row, or 2LDK(洋室6帖・…)). */
|
|
62
|
+
type PlacedCode = { readonly code: LayoutCode; readonly scope: number; readonly breakdown?: Breakdown | undefined };
|
|
63
|
+
type PlacedBreakdown = { readonly breakdown: Breakdown; readonly scope: number };
|
|
64
|
+
type Found = { readonly codes: PlacedCode[]; readonly breakdowns: PlacedBreakdown[] };
|
|
65
|
+
const NOTHING: Found = { codes: [], breakdowns: [] };
|
|
66
|
+
|
|
67
|
+
type Context = { readonly words: LayoutWords; readonly labels: Labels; readonly scopeOf: (offset: number) => number };
|
|
68
|
+
|
|
69
|
+
const INLINE_BREAKDOWN = /^[^((]*[((]([^))]+)[))]/u;
|
|
70
|
+
|
|
71
|
+
/** The breakdown written in brackets after the code, when it names a room. */
|
|
72
|
+
const inlineBreakdown = (rest: string, words: LayoutWords): Breakdown | undefined => {
|
|
73
|
+
const inside = INLINE_BREAKDOWN.exec(rest)?.[1];
|
|
74
|
+
if (inside === undefined) return undefined;
|
|
75
|
+
const breakdown = parseBreakdown([inside], words);
|
|
76
|
+
return breakdown.rooms > 0 || breakdown.unclear ? breakdown : undefined;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const codeIn = (text: string, start: number, context: Context, breakdown?: Breakdown): PlacedCode[] => {
|
|
80
|
+
const found = parseLayoutCode(text, context.words);
|
|
81
|
+
if (found === undefined) return [];
|
|
82
|
+
const code = { ...found, start: start + found.start, end: start + found.end };
|
|
83
|
+
const written = breakdown ?? inlineBreakdown(text.slice(found.end), context.words);
|
|
84
|
+
return [{ code, scope: context.scopeOf(code.start), breakdown: written }];
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const field = (group: LabelGroup | undefined, value: string, start: number, context: Context): Found => {
|
|
88
|
+
if (group === "code") return { codes: codeIn(value, start, context), breakdowns: [] };
|
|
89
|
+
if (group === "breakdown") return { codes: [], breakdowns: [{ breakdown: parseBreakdown([value], context.words), scope: context.scopeOf(start) }] };
|
|
90
|
+
return NOTHING;
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const merged = (found: readonly Found[]): Found => ({
|
|
94
|
+
codes: found.flatMap((each) => each.codes),
|
|
95
|
+
breakdowns: found.flatMap((each) => each.breakdowns),
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
const groupOfCell = (cell: Cell | undefined, labels: Labels): LabelGroup | undefined => (cell === undefined ? undefined : labels.get(labelKey(cell.text)));
|
|
99
|
+
|
|
100
|
+
/** A table with a layout column: one listing a row, with its breakdown column when the table has one. */
|
|
101
|
+
const wideRows = (rows: readonly Cell[][], codeColumn: number, breakdownColumn: number, context: Context): Found => ({
|
|
102
|
+
codes: rows.flatMap((cells) => {
|
|
103
|
+
const code = cells[codeColumn];
|
|
104
|
+
const listed = cells[breakdownColumn];
|
|
105
|
+
const breakdown = listed === undefined ? undefined : parseBreakdown([listed.text], context.words);
|
|
106
|
+
return code === undefined ? [] : codeIn(code.text, code.start, context, breakdown);
|
|
107
|
+
}),
|
|
108
|
+
breakdowns: [],
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
const tableFound = (header: Line, rows: readonly Cell[][], context: Context): Found => {
|
|
112
|
+
const groups = cellsOf(header).map((cell) => groupOfCell(cell, context.labels));
|
|
113
|
+
const codeColumn = groups.indexOf("code");
|
|
114
|
+
if (codeColumn !== -1) return wideRows(rows, codeColumn, groups.indexOf("breakdown"), context);
|
|
115
|
+
if (groups[0] === "room-column") {
|
|
116
|
+
const breakdown = parseBreakdown(
|
|
117
|
+
rows.map((cells) => cells[0]?.text ?? ""),
|
|
118
|
+
context.words,
|
|
119
|
+
);
|
|
120
|
+
return { codes: [], breakdowns: [{ breakdown, scope: context.scopeOf(header.start) }] };
|
|
121
|
+
}
|
|
122
|
+
return merged(rows.map(([label, value]) => (value === undefined ? NOTHING : field(groupOfCell(label, context.labels), value.text, value.start, context))));
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
const tablesFound = (source: string, context: Context): Found =>
|
|
126
|
+
merged(tablesOf(linesOf(source)).map((table) => tableFound(table.header, table.rows.map(cellsOf), context)));
|
|
127
|
+
|
|
128
|
+
const LIST_LEAD = /^\s*(?:(?:[-*+]|\d+[.)])\s+)?/u;
|
|
129
|
+
const MAX_LABEL_LENGTH = 24;
|
|
130
|
+
|
|
131
|
+
/** "間取り:2LDK", "- Rooms: Bedroom 1, Bedroom 2" outside tables: the name before the first colon, and the value after it. */
|
|
132
|
+
const labelledLine = (line: Line, context: Context): Found => {
|
|
133
|
+
const colon = line.text.search(/[::]/u);
|
|
134
|
+
if (colon === -1 || line.text.includes("|")) return NOTHING;
|
|
135
|
+
const label = line.text.slice(0, colon).replace(LIST_LEAD, "");
|
|
136
|
+
const rest = line.text.slice(colon + 1);
|
|
137
|
+
const value = rest.trimStart();
|
|
138
|
+
if (label.length > MAX_LABEL_LENGTH || value === "") return NOTHING;
|
|
139
|
+
return field(context.labels.get(labelKey(label)), value, line.start + colon + 1 + rest.length - value.length, context);
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
/** Code and markup are masked in prose, so a colon in code is not read. */
|
|
143
|
+
const linesFound = (prose: string, context: Context): Found => merged(linesOf(prose).map((line) => labelledLine(line, context)));
|
|
144
|
+
|
|
145
|
+
const scopeFinder =
|
|
146
|
+
(doc: ProseDocument) =>
|
|
147
|
+
(offset: number): number =>
|
|
148
|
+
doc.sections.findLastIndex((section) => section.span.start <= offset);
|
|
149
|
+
|
|
150
|
+
const slipsOf = (found: Found): LayoutSlip[] => {
|
|
151
|
+
const direct = found.codes.flatMap((placed): [LayoutCode, Breakdown][] => (placed.breakdown === undefined ? [] : [[placed.code, placed.breakdown]]));
|
|
152
|
+
const pooled = found.codes.filter((placed) => placed.breakdown === undefined);
|
|
153
|
+
const paired = pairByScope(pooled, found.breakdowns).map(([placed, listed]): [LayoutCode, Breakdown] => [placed.code, listed.breakdown]);
|
|
154
|
+
return [...direct, ...paired].flatMap(([code, breakdown]) => layoutSlip(code, breakdown) ?? []);
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
export const layoutCode: Detector = (doc): Finding[] => {
|
|
158
|
+
const context: Context = { words: layoutWordsOf(doc.lexicons), labels: labelsOf(doc.lexicons), scopeOf: scopeFinder(doc) };
|
|
159
|
+
const found = merged([tablesFound(doc.source, context), linesFound(doc.prose ?? doc.source, context)]);
|
|
160
|
+
return slipsOf(found).map((slip) => ({
|
|
161
|
+
rule: "layout-code-mismatch",
|
|
162
|
+
severity: "warning",
|
|
163
|
+
line: 0,
|
|
164
|
+
column: 0,
|
|
165
|
+
quote: quoteAt(doc.source, slip.code.start),
|
|
166
|
+
...(slip.kind === "part" ? { variant: "part" } : {}),
|
|
167
|
+
values: {
|
|
168
|
+
code: slip.code.text,
|
|
169
|
+
stated: slip.code.rooms,
|
|
170
|
+
...(slip.kind === "count" ? { listed: slip.listed } : { part: slip.entry }),
|
|
171
|
+
offset: slip.code.start,
|
|
172
|
+
},
|
|
173
|
+
}));
|
|
174
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ProseDocument, StructureNode } from "../plugin.ts";
|
|
2
|
+
import { nameSpans } from "../compare/proper-nouns.ts";
|
|
3
|
+
import { overlapsAny, spanIndex } from "../compare/spans.ts";
|
|
4
|
+
import { factValues, type FactValue } from "../facts/fact-values.ts";
|
|
5
|
+
import { codeFences } from "./code-fences.ts";
|
|
6
|
+
import { measuredValues, type Measured } from "../facts/measures.ts";
|
|
7
|
+
import { measureUnitsOf } from "../facts/measure-units.ts";
|
|
8
|
+
|
|
9
|
+
/** 文書の中の、単位の語彙表の単位が付いた量。コードの塊の中の量は、項目の値ではない。 */
|
|
10
|
+
export const measuredOf = (doc: ProseDocument): Measured[] => {
|
|
11
|
+
const fences = codeFences(doc.source);
|
|
12
|
+
return measuredValues(doc.source, measureUnitsOf(doc)).filter((value) => !fences.some((fence) => fence.start <= value.start && value.end <= fence.end));
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/** fact-conflict の値に、単位の付いた量を足す。量と重なる値(量の数だけを読んだもの)は量に置き換える。 */
|
|
16
|
+
export const valuesWith = (tree: StructureNode, doc: ProseDocument, measured: readonly Measured[]): FactValue[] => {
|
|
17
|
+
const taken = spanIndex(measured);
|
|
18
|
+
const others = factValues(tree, doc.source, nameSpans(doc)).filter((value) => !overlapsAny(taken, value));
|
|
19
|
+
return [...others, ...measured].toSorted((left, right) => left.start - right.start);
|
|
20
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { MarkupHeading, ProseDocument } from "../plugin.ts";
|
|
2
|
+
import { codesAfterLabels, codesInTitle, modelCodeVariants } from "../model-codes.ts";
|
|
3
|
+
import { proseAndTablesOf } from "../table-text.ts";
|
|
4
|
+
import { tableBodyCells } from "../facts/table-facts.ts";
|
|
5
|
+
import { proseWithCells } from "../table-cells.ts";
|
|
6
|
+
|
|
7
|
+
// 型番の欄の語(型番、Model No.)は語彙表 model-code-label が言う。
|
|
8
|
+
|
|
9
|
+
type ModelCodeFinding = { readonly offset: number; readonly name: string; readonly usual: string; readonly kind: string };
|
|
10
|
+
|
|
11
|
+
/** 文書の題: 一番浅い見出しのうち最初のもの。 */
|
|
12
|
+
const titleOf = (doc: ProseDocument): MarkupHeading | undefined => {
|
|
13
|
+
const headings = doc.markup?.headings ?? [];
|
|
14
|
+
const top = Math.min(...headings.map((heading) => heading.depth));
|
|
15
|
+
return headings.find((heading) => heading.depth === top);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
/** 題か型番の欄に書いた型番を、ほかの所(題・表の升も)で別の形に書いた所。prose は見出しと表を覆うので、題と升の字を書き戻して読む。 */
|
|
19
|
+
export const modelCodeFindings = (doc: ProseDocument, prose: string): ModelCodeFinding[] => {
|
|
20
|
+
const title = titleOf(doc);
|
|
21
|
+
const titleSpans = title === undefined ? [] : [{ start: title.start, end: title.end, text: doc.source.slice(title.start, title.end) }];
|
|
22
|
+
const text = proseWithCells(prose, [...titleSpans, ...(doc.tableCells?.() ?? tableBodyCells(proseAndTablesOf(doc)))]);
|
|
23
|
+
const labels = (doc.lexicons["model-code-label"] ?? []).map((entry) => entry.pattern);
|
|
24
|
+
const titleCodes = title === undefined ? [] : codesInTitle(text, title.start, title.end);
|
|
25
|
+
const anchors = [...titleCodes, ...codesAfterLabels(text, labels)].toSorted((left, right) => left.offset - right.offset);
|
|
26
|
+
return modelCodeVariants(text, anchors).map(({ code, usual }) => ({ offset: code.offset, name: code.surface, usual, kind: "model-code" }));
|
|
27
|
+
};
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import type { Detector, Finding, ProseDocument } from "../plugin.ts";
|
|
2
|
-
import { cuedNamesIn, mentionsIn, nameVariants, suffixedNamesIn, type NameMention, type VariantChars } from "../name-variants.ts";
|
|
2
|
+
import { cuedNamesIn, mentionsIn, nameVariants, suffixedNamesIn, withKnownNeighbours, type NameMention, type VariantChars } from "../name-variants.ts";
|
|
3
|
+
import type { SpellingInput } from "../name-spelling-chars.ts";
|
|
3
4
|
import { nameCueAt, type NameCues } from "../name-cue.ts";
|
|
4
5
|
import { quoteAt } from "./structure-tree.ts";
|
|
5
6
|
import { companyMentionsIn, companyVariants, type CompanyForm, type IsProper } from "../company-names.ts";
|
|
6
|
-
import {
|
|
7
|
-
import
|
|
7
|
+
import { proseAndTablesOf } from "../table-text.ts";
|
|
8
|
+
import { tableBodyCells } from "../facts/table-facts.ts";
|
|
9
|
+
import { cellNamesIn, cellNameVariants, proseNamesOf } from "../table-names.ts";
|
|
10
|
+
import { placeMentionsIn, placeVariants, type PlaceChars, type PlaceReader, type PlaceWord } from "../place-names.ts";
|
|
11
|
+
import type { TableCell, Token } from "../plugin.ts";
|
|
12
|
+
import { proseWithCells } from "../table-cells.ts";
|
|
13
|
+
import { modelCodeFindings } from "./name-variant-model-codes.ts";
|
|
14
|
+
import { labelledSpans, orderNamesOf, quotedSpans, stemOf, titleCaseSpans, wordOrderVariants, type OrderWord } from "../name-word-order.ts";
|
|
8
15
|
|
|
9
16
|
// 人の名前と読ませる敬称(様、さん)は語彙表 person-suffix、人を指す前置き(担当の)は person-lead、名前のすぐ後ろに来る語
|
|
10
17
|
// (です、まで)は name-particle、字体の違う同じ字(斎・斉・齋)は name-variant-char が組(group)ごとに言う。
|
|
@@ -28,10 +35,29 @@ const properOf = (doc: ProseDocument): IsProper => {
|
|
|
28
35
|
const placeWordsOf = (doc: ProseDocument): PlaceWord[] =>
|
|
29
36
|
(doc.lexicons["place-word"] ?? []).map((entry) => ({ pattern: entry.pattern, group: entry.group ?? entry.pattern }));
|
|
30
37
|
|
|
38
|
+
/**
|
|
39
|
+
* 場所の名前の字。方角や位置の字(東、上、新)は語彙表 place-direction、読みの同じ字(洲 と 州)は place-name-char と、字体の違う
|
|
40
|
+
* 同じ字の name-variant-char が組(group)ごとに言う。
|
|
41
|
+
*/
|
|
42
|
+
const placeCharsOf = (doc: ProseDocument, chars: VariantChars): PlaceChars => ({
|
|
43
|
+
directions: new Set(patternsOf(doc, "place-direction")),
|
|
44
|
+
sameReading: new Map([
|
|
45
|
+
...chars,
|
|
46
|
+
...(doc.lexicons["place-name-char"] ?? []).flatMap((entry): [string, string][] => (entry.group === undefined ? [] : [[entry.pattern, entry.group]])),
|
|
47
|
+
]),
|
|
48
|
+
});
|
|
49
|
+
|
|
31
50
|
/** 名前の頭に立たない語の品詞(The、at、and)。 */
|
|
32
51
|
const FUNCTION_POS: ReadonlySet<string> = new Set(["DET", "ADP", "PRON", "CCONJ", "SCONJ", "AUX", "PART"]);
|
|
33
52
|
|
|
34
|
-
|
|
53
|
+
/** 表の本体の升。本文が表を覆わない文書(Markdown でない)には無い。 */
|
|
54
|
+
const cellsOf = (doc: ProseDocument): readonly TableCell[] => doc.tableCells?.() ?? tableBodyCells(proseAndTablesOf(doc));
|
|
55
|
+
|
|
56
|
+
/** 文の語と表の升の語を、文書の順に。 */
|
|
57
|
+
const tokensOf = (doc: ProseDocument): Token[] =>
|
|
58
|
+
[...doc.sentences.flatMap((sentence) => sentence.tokens ?? []), ...cellsOf(doc).flatMap((cell) => cell.tokens ?? [])].toSorted(
|
|
59
|
+
(left, right) => left.span.start - right.span.start,
|
|
60
|
+
);
|
|
35
61
|
|
|
36
62
|
/** 場所の名前の語の数の上限。名前の読みを探す範囲。 */
|
|
37
63
|
const MAX_PLACE_TOKENS = 20;
|
|
@@ -74,37 +100,95 @@ const companyFindings = (doc: ProseDocument, prose: string, reported: readonly R
|
|
|
74
100
|
.filter(({ mention }) => !overlapsAny(reported, mention.offset, mention.surface.length))
|
|
75
101
|
.map(({ mention, usual, kind }) => ({ offset: mention.offset, name: mention.surface, usual, kind: kind === "spelling" ? kind : `company-${kind}` }));
|
|
76
102
|
|
|
77
|
-
/**
|
|
78
|
-
const placeFindings = (doc: ProseDocument, prose: string, reported: readonly Reported[]): Reported[] =>
|
|
79
|
-
placeVariants(placeMentionsIn(prose, placeWordsOf(doc), placeReaderOf(doc)))
|
|
103
|
+
/** 場所の名前の書き分け。表の本体の升の中の名前も読む(見出しの行は読まない)。人や会社の名前の見方がすでに指した所と重なるものは除く。 */
|
|
104
|
+
const placeFindings = (doc: ProseDocument, prose: string, reported: readonly Reported[], chars: VariantChars): Reported[] =>
|
|
105
|
+
placeVariants(placeMentionsIn(proseWithCells(prose, cellsOf(doc)), placeWordsOf(doc), placeReaderOf(doc)), placeCharsOf(doc, chars))
|
|
80
106
|
.filter(({ mention }) => !overlapsAny(reported, mention.offset, mention.surface.length))
|
|
81
107
|
.map(({ mention, usual, kind }) => ({ offset: mention.offset, name: mention.surface, usual, kind }));
|
|
82
108
|
|
|
109
|
+
/** 名前の中で比べる語の品詞。助詞や冠詞(の、of)は語の順に数えない。 */
|
|
110
|
+
const CONTENT_POS: ReadonlySet<string> = new Set(["NOUN", "PROPN", "ADJ", "NUM", "VERB"]);
|
|
111
|
+
|
|
112
|
+
/** 欄の後ろの名前を切る所: 内容語でも名前の中の小さな語(of)でもない語の頭。 */
|
|
113
|
+
const orderStopsOf = (doc: ProseDocument): number[] => {
|
|
114
|
+
const joiners = new Set(patternsOf(doc, "name-title-joiner"));
|
|
115
|
+
return tokensOf(doc)
|
|
116
|
+
.filter((token) => !CONTENT_POS.has(token.pos) && !joiners.has(token.surface.toLowerCase()))
|
|
117
|
+
.map((token) => token.span.start);
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const sentenceStartsOf = (doc: ProseDocument): ReadonlySet<number> => new Set(doc.sentences.flatMap((sentence) => sentence.tokens?.[0]?.span.start ?? []));
|
|
121
|
+
|
|
122
|
+
const orderWordsOf = (doc: ProseDocument): OrderWord[] => {
|
|
123
|
+
const suffixes = patternsOf(doc, "name-stem-suffix");
|
|
124
|
+
return tokensOf(doc)
|
|
125
|
+
.filter((token) => CONTENT_POS.has(token.pos))
|
|
126
|
+
.map((token) => ({ start: token.span.start, end: token.span.end, key: stemOf(token.surface, suffixes) }));
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* 語の順を入れ替えて書いた同じ名前(統計学基礎 と 基礎統計学)。名前と読める所は、括弧の中(name-quote)、大文字で始まる語の並び
|
|
131
|
+
* (name-title-joiner を挟んでよい)、名前を書く欄の後ろ(name-label)。大文字の語の並びどうしは、片方が表の升まるごとに
|
|
132
|
+
* 書いた名前のときだけ比べる。ほかの見方がすでに指した所と重なるものは除く。
|
|
133
|
+
*/
|
|
134
|
+
const orderFindings = (doc: ProseDocument, prose: string, reported: readonly Reported[]): Reported[] => {
|
|
135
|
+
const starts = sentenceStartsOf(doc);
|
|
136
|
+
const spans = [
|
|
137
|
+
...quotedSpans(prose, patternsOf(doc, "name-quote")),
|
|
138
|
+
...titleCaseSpans(prose, patternsOf(doc, "name-title-joiner"), (offset) => starts.has(offset)),
|
|
139
|
+
...labelledSpans(prose, patternsOf(doc, "name-label")),
|
|
140
|
+
];
|
|
141
|
+
const cells = new Set(tableBodyCells(proseAndTablesOf(doc)).map((cell) => cell.text.trim()));
|
|
142
|
+
return wordOrderVariants(orderNamesOf(doc.source, spans, orderWordsOf(doc), orderStopsOf(doc)), cells)
|
|
143
|
+
.filter(({ name }) => !overlapsAny(reported, name.offset, name.surface.length))
|
|
144
|
+
.map(({ name, usual }) => ({ offset: name.offset, name: name.surface, usual, kind: "order" }));
|
|
145
|
+
};
|
|
146
|
+
|
|
83
147
|
/** 人・製品・会社の名前の現れ。解析器が固有名詞と読む語、敬称の付く名前、前後の語で名前と読める漢字。 */
|
|
84
148
|
const nameMentionsOf = (doc: ProseDocument, prose: string, chars: VariantChars): NameMention[] => {
|
|
85
149
|
const cues: NameCues = { leads: patternsOf(doc, "person-lead"), suffixes: patternsOf(doc, "person-suffix"), particles: patternsOf(doc, "name-particle") };
|
|
86
150
|
const tagged = doc.sentences.flatMap((sentence) => mentionsIn(sentence.tokens ?? [], doc.source, cues.suffixes));
|
|
87
151
|
const taggedOrSuffixed = [...tagged, ...suffixedNamesIn(prose, cues.suffixes, chars, tagged)];
|
|
88
|
-
|
|
89
|
-
.
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
.toSorted((left, right) => left.offset - right.offset);
|
|
152
|
+
const cued = [...taggedOrSuffixed, ...cuedNamesIn(prose, cues, chars, taggedOrSuffixed)].map((mention): NameMention => {
|
|
153
|
+
const cue = mention.cue ?? nameCueAt(prose, mention.offset, mention.surface, cues);
|
|
154
|
+
return cue === undefined ? mention : { ...mention, cue };
|
|
155
|
+
});
|
|
156
|
+
return withKnownNeighbours(cued, prose).toSorted((left, right) => left.offset - right.offset);
|
|
94
157
|
};
|
|
95
158
|
|
|
159
|
+
/** 一語の名前の中で同じ音を書く字(ヶ・ケ・が)は語彙表 name-spelling-char が組(group)ごとに言う。 */
|
|
160
|
+
const spellingCharsOf = (doc: ProseDocument): VariantChars =>
|
|
161
|
+
new Map((doc.lexicons["name-spelling-char"] ?? []).flatMap((entry): [string, string][] => (entry.group === undefined ? [] : [[entry.pattern, entry.group]])));
|
|
162
|
+
|
|
163
|
+
/** 名前の中の同じ音の字は、表の升の中の、解析器が固有名詞と読む語(物件名の升の 桜ケ丘)とも比べる。 */
|
|
164
|
+
const spellingInputOf = (doc: ProseDocument): SpellingInput => {
|
|
165
|
+
const suffixes = patternsOf(doc, "person-suffix");
|
|
166
|
+
return { chars: spellingCharsOf(doc), alsoWritten: cellsOf(doc).flatMap((cell) => mentionsIn(cell.tokens ?? [], doc.source, suffixes)) };
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
/** 表の升に書いた名前の書き分け。名前の形をした升を、本文の名前と比べる。ほかの見方がすでに指した所と重なるものは除く。 */
|
|
170
|
+
const tableFindings = (doc: ProseDocument, prose: string, mentions: readonly NameMention[], reported: readonly Reported[]): Reported[] =>
|
|
171
|
+
cellNameVariants(cellNamesIn(cellsOf(doc)), proseNamesOf(mentions, prose))
|
|
172
|
+
.filter(({ name }) => !reported.some((other) => other.offset < name.offset + name.surface.length && name.offset < other.offset + other.name.length))
|
|
173
|
+
.map(({ name, usual, kind }) => ({ offset: name.offset, name: name.surface, usual, kind }));
|
|
174
|
+
|
|
96
175
|
/** 同じ名前を、文書の中で少しだけ違う形に書いた所(GitHub と Github、山田太郎 と 山田太朗)。少ないほうを指す。 */
|
|
97
176
|
export const nameVariant: Detector = (doc): Finding[] => {
|
|
98
177
|
const prose = doc.prose ?? doc.source;
|
|
99
178
|
const chars = variantCharsOf(doc);
|
|
100
|
-
const
|
|
179
|
+
const mentions = nameMentionsOf(doc, prose, chars);
|
|
180
|
+
const names = nameVariants(mentions, chars, spellingInputOf(doc)).map(({ mention, usual, kind }): Reported => ({
|
|
101
181
|
offset: mention.offset,
|
|
102
182
|
name: mention.surface,
|
|
103
183
|
usual,
|
|
104
184
|
kind,
|
|
105
185
|
}));
|
|
106
186
|
const namesAndCompanies = [...names, ...companyFindings(doc, prose, names)];
|
|
107
|
-
|
|
187
|
+
const withTables = [...namesAndCompanies, ...tableFindings(doc, prose, mentions, namesAndCompanies)];
|
|
188
|
+
const withPlaces = [...withTables, ...placeFindings(doc, prose, withTables, chars)];
|
|
189
|
+
const withOrder = [...withPlaces, ...orderFindings(doc, prose, withPlaces)];
|
|
190
|
+
const codes = modelCodeFindings(doc, prose).filter((code) => !overlapsAny(withOrder, code.offset, code.name.length));
|
|
191
|
+
return [...withOrder, ...codes]
|
|
108
192
|
.toSorted((left, right) => left.offset - right.offset)
|
|
109
193
|
.map(({ offset, name, usual, kind }) => ({
|
|
110
194
|
rule: "",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { Detector, Finding, ProseDocument, Sentence, Token } from "../plugin.ts";
|
|
1
|
+
import type { Detector, Finding, ProseDocument, Sentence, TableCell, Token } from "../plugin.ts";
|
|
2
2
|
import { groupBy, oddSpellings, type KeyedWord, type OddSpelling } from "../spelling-variants.ts";
|
|
3
|
-
import { dropsOkurigana,
|
|
3
|
+
import { dropsOkurigana, kanjiKeyAmong, katakanaKey, lemmaReading } from "../kana-spelling.ts";
|
|
4
4
|
import { isKatakanaWord, stemOf } from "../long-vowel.ts";
|
|
5
5
|
import { QUOTATION_MARKS, isWithinAny, quotedSpans } from "../quoted-span.ts";
|
|
6
6
|
import { nameSpans, touchesAny } from "../team-names.ts";
|
|
@@ -12,7 +12,14 @@ import { isPartOfAddress } from "./address-word.ts";
|
|
|
12
12
|
* A word found in the document: where it is, which sentence it is in, its key and spelling, how it is written when that differs, and
|
|
13
13
|
* whether it is written onto the noun after it (取扱事業者).
|
|
14
14
|
*/
|
|
15
|
-
type Placed = KeyedWord & {
|
|
15
|
+
type Placed = KeyedWord & {
|
|
16
|
+
readonly sentence: Sentence;
|
|
17
|
+
readonly offset: number;
|
|
18
|
+
readonly shown?: string;
|
|
19
|
+
readonly compoundHead?: boolean;
|
|
20
|
+
/** Where a run of words ends (タイヤレバー). */
|
|
21
|
+
readonly end?: number;
|
|
22
|
+
};
|
|
16
23
|
|
|
17
24
|
type IsOpen = (start: number, end: number) => boolean;
|
|
18
25
|
|
|
@@ -141,11 +148,12 @@ const readingWords = (sentence: Sentence, isOpen: IsOpen, skips: Skips): Placed[
|
|
|
141
148
|
*/
|
|
142
149
|
const byKanji = (words: readonly Placed[]): Placed[] =>
|
|
143
150
|
[...groupBy(words, (word) => word.key).values()].flatMap((group) => {
|
|
144
|
-
const skeletons = [...new Set(group.map((word) => kanjiSkeleton(word.spelling)).filter((skeleton) => skeleton !== ""))];
|
|
145
151
|
const spellings = [...new Set(group.map((word) => word.spelling))];
|
|
152
|
+
const skeletonOf = (spelling: string): string => kanjiKeyAmong(spelling, spellings);
|
|
153
|
+
const skeletons = [...new Set(spellings.map(skeletonOf).filter((skeleton) => skeleton !== ""))];
|
|
146
154
|
const apart = spellings.some((spelling) => dropsOkurigana(spelling, spellings)) ? "|compound" : "";
|
|
147
155
|
return group.flatMap((word): Placed[] => {
|
|
148
|
-
const own =
|
|
156
|
+
const own = skeletonOf(word.spelling);
|
|
149
157
|
if (own === "" && skeletons.length > 1) return [];
|
|
150
158
|
const use = word.compoundHead === true ? apart : "";
|
|
151
159
|
return [{ ...word, key: `${word.key}|${own === "" ? (skeletons[0] ?? "") : own}${use}` }];
|
|
@@ -161,6 +169,44 @@ const katakanaWords = (sentence: Sentence, isOpen: IsOpen): Placed[] =>
|
|
|
161
169
|
return [...key].length < MIN_KATAKANA_KEY ? [] : [{ key: `kana|${key}`, spelling: stemOf(token.surface), sentence, offset: token.span.start }];
|
|
162
170
|
});
|
|
163
171
|
|
|
172
|
+
const isKatakanaNoun = (token: Token): boolean => token.pos === "NOUN" && isKatakanaWord(token.surface);
|
|
173
|
+
|
|
174
|
+
/** Katakana nouns written onto each other (タイヤ and レバー in タイヤレバー), each run whole: one place may be cut into words another is not. */
|
|
175
|
+
const katakanaRuns = (tokens: readonly Token[]): Token[][] =>
|
|
176
|
+
tokens.reduce<Token[][]>((runs, token, at) => {
|
|
177
|
+
if (!isKatakanaNoun(token)) return runs;
|
|
178
|
+
const last = runs.at(-1);
|
|
179
|
+
if (last !== undefined && isTouching(tokens[at - 1], token) && last.at(-1) === tokens[at - 1]) last.push(token);
|
|
180
|
+
else runs.push([token]);
|
|
181
|
+
return runs;
|
|
182
|
+
}, []);
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Katakana runs keyed like one katakana word, spelled as their words' stems joined: タイヤーレバー (one unknown word) meets
|
|
186
|
+
* タイヤレバー read as タイヤ and レバー, while the final ー of a word inside the run (サーバーリスト and サーバリスト) stays katakana-long-vowel's.
|
|
187
|
+
*/
|
|
188
|
+
const katakanaRunWords = (sentence: Sentence, isOpen: IsOpen): Placed[] =>
|
|
189
|
+
katakanaRuns(sentence.tokens ?? []).flatMap((run): Placed[] => {
|
|
190
|
+
const [first, last] = [run[0], run.at(-1)];
|
|
191
|
+
if (first === undefined || last === undefined) return [];
|
|
192
|
+
const [start, end] = [first.span.start - sentence.span.start, last.span.end - sentence.span.start];
|
|
193
|
+
const key = katakanaKey(run.map((token) => token.surface).join(""));
|
|
194
|
+
if ([...key].length < MIN_KATAKANA_KEY || !isOpen(start, end)) return [];
|
|
195
|
+
return [
|
|
196
|
+
{
|
|
197
|
+
key: `kana|${key}`,
|
|
198
|
+
spelling: run.map((token) => stemOf(token.surface)).join(""),
|
|
199
|
+
shown: run.map((token) => token.surface).join(""),
|
|
200
|
+
sentence,
|
|
201
|
+
offset: first.span.start,
|
|
202
|
+
end: last.span.end,
|
|
203
|
+
},
|
|
204
|
+
];
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
/** Whether a run holds a place another key already points at: the word inside it is said, not the run around it. */
|
|
208
|
+
const coversOffset = (run: Placed, offset: number): boolean => offset >= run.offset && offset < (run.end ?? run.offset + 1);
|
|
209
|
+
|
|
164
210
|
const LATIN_WORD = /[A-Za-z][A-Za-z0-9]*(?:-[A-Za-z0-9]+)*/gu;
|
|
165
211
|
const LOWER = /\p{Ll}/u;
|
|
166
212
|
|
|
@@ -204,6 +250,23 @@ const findingOf = (words: readonly Placed[], odd: OddSpelling<Placed>): Finding
|
|
|
204
250
|
values: { written: odd.word.shown ?? odd.word.spelling, other: shownUsual(words, odd), count: odd.count, of: odd.of, offset: odd.word.offset },
|
|
205
251
|
});
|
|
206
252
|
|
|
253
|
+
/** A cell that is one Latin word in lower case (openapi, contentType): a field name or a value, spelled by the data and not by the writer. */
|
|
254
|
+
const DATA_KEY_CELL = /^\p{Ll}[A-Za-z0-9]*$/u;
|
|
255
|
+
|
|
256
|
+
type Place = { readonly sentence: Sentence; readonly isOpen: IsOpen; readonly readsLatin: boolean };
|
|
257
|
+
|
|
258
|
+
/** A link's brackets and where it goes (`[`, `](#contentType)`, `][ref]`). The prose hides them outside tables; a cell keeps the Markdown as written. */
|
|
259
|
+
const LINK_CHROME = /\]\([^)]*\)|\]\[[^\]]*\]|\[/gu;
|
|
260
|
+
|
|
261
|
+
const withoutLinkChrome = (text: string): string => text.replaceAll(LINK_CHROME, (chrome) => " ".repeat(chrome.length));
|
|
262
|
+
|
|
263
|
+
/** A body cell of a table read as a sentence of its own: the prose covers tables, so a cell's words (片栗粉 in a list of ingredients) are not in the sentences. Header rows stay out. */
|
|
264
|
+
const cellPlace = (cell: TableCell, names: readonly string[]): Place => {
|
|
265
|
+
const text = withoutLinkChrome(cell.text);
|
|
266
|
+
const sentence: Sentence = { span: { start: cell.start, end: cell.end }, text, tokens: cell.tokens ?? [] };
|
|
267
|
+
return { sentence, isOpen: isOpenIn(sentence, names), readsLatin: !DATA_KEY_CELL.test(text.trim()) };
|
|
268
|
+
};
|
|
269
|
+
|
|
207
270
|
/**
|
|
208
271
|
* One word written two ways in one document (出来る and できる, 引っ越し and 引越し, ウィンドウ and ウインドウ, e-mail and email),
|
|
209
272
|
* found without a list of words: the document's own words are grouped by reading or by an evened-out spelling, and the way the
|
|
@@ -211,12 +274,18 @@ const findingOf = (words: readonly Placed[], odd: OddSpelling<Placed>): Finding
|
|
|
211
274
|
*/
|
|
212
275
|
export const orthographicVariant: Detector = (doc, options): Finding[] => {
|
|
213
276
|
const skips: Skips = { skip: new Set([...patternsOf(doc, DISTINCT), ...patternsOf(doc, FUKUSHI)]), idioms: new Set(patternsOf(doc, IDIOM)) };
|
|
214
|
-
const
|
|
277
|
+
const names = doc.names ?? [];
|
|
278
|
+
const placed: Place[] = [
|
|
279
|
+
...doc.sentences.map((sentence) => ({ sentence, isOpen: isOpenIn(sentence, names), readsLatin: true })),
|
|
280
|
+
...(doc.tableCells?.() ?? []).map((cell) => cellPlace(cell, names)),
|
|
281
|
+
];
|
|
215
282
|
const reading = byKanji(placed.flatMap(({ sentence, isOpen }) => readingWords(sentence, isOpen, skips)));
|
|
216
283
|
const katakana = placed.flatMap(({ sentence, isOpen }) => katakanaWords(sentence, isOpen));
|
|
217
|
-
const
|
|
284
|
+
const runs = placed.flatMap(({ sentence, isOpen }) => katakanaRunWords(sentence, isOpen));
|
|
285
|
+
const latin = placed.flatMap(({ sentence, isOpen, readsLatin }) => (readsLatin ? latinWords(sentence, isOpen, skips.skip) : []));
|
|
218
286
|
const odd = [reading, katakana, latin].flatMap((words) => oddSpellings(words, options.limit));
|
|
219
|
-
const
|
|
287
|
+
const oddRuns = oddSpellings(runs, options.limit).filter(({ word }) => !odd.some((other) => coversOffset(word, other.word.offset)));
|
|
288
|
+
const all = [...reading, ...katakana, ...runs, ...latin];
|
|
220
289
|
// A word can be odd by its reading and by its katakana key at once; one place is said once.
|
|
221
|
-
return [...new Map(odd.map((entry) => [entry.word.offset, entry])).values()].map((entry) => findingOf(all, entry));
|
|
290
|
+
return [...new Map([...odd, ...oddRuns].map((entry) => [entry.word.offset, entry])).values()].map((entry) => findingOf(all, entry));
|
|
222
291
|
};
|
|
@@ -5,6 +5,7 @@ import { minorityReport } from "../spacing-minority.ts";
|
|
|
5
5
|
import { isWithinAny, quotedSpans } from "../quoted-span.ts";
|
|
6
6
|
import { digitRunAround, endsWithDivisionLabel, isNumberName, sequenceLabelStarts, type NameContext } from "../number-name.ts";
|
|
7
7
|
import { isSpacedLocationPart, type FloorWords } from "../location-part.ts";
|
|
8
|
+
import { addressSpans, clockTimeSpans, isInsideSpan } from "../spacing-code.ts";
|
|
8
9
|
|
|
9
10
|
/** チームが chaff.yaml の prefer に書いた「使わない書き方」。書いていなければ何も言わない。 */
|
|
10
11
|
export const preferredTerm: Detector = (doc, options): Finding[] => {
|
|
@@ -70,18 +71,27 @@ const followsItemNumber = (text: string, boundary: Boundary, itemNumbers: Readon
|
|
|
70
71
|
const calendarStarts = (sentence: Sentence, units: CalendarUnits): ReadonlySet<number> =>
|
|
71
72
|
new Set(calendarRuns(sentence.text, sentence.tokens, sentence.span.start, units).map(({ run }) => run.start));
|
|
72
73
|
|
|
74
|
+
/** 英字の側がメールアドレスか URL の境目。後ろの空白は、アドレスの終わりを示す区切り。 */
|
|
75
|
+
const besideAddress = (addresses: readonly Span[], boundary: Boundary): boolean =>
|
|
76
|
+
isInsideSpan(addresses, boundary.offset - 1) || isInsideSpan(addresses, boundary.spaced ? boundary.offset + 1 : boundary.offset);
|
|
77
|
+
|
|
78
|
+
/** 文の中で一度だけ探すもの: 日付・時刻の数の頭の位置、コロンで書いた時刻、メールアドレス・URL。 */
|
|
79
|
+
type SentenceCodes = { readonly calendar: ReadonlySet<number>; readonly clockTimes: readonly Span[]; readonly addresses: readonly Span[] };
|
|
80
|
+
|
|
73
81
|
/**
|
|
74
82
|
* 番号・識別子として書かれた数(number-name.ts)、日付・時刻の数、「第1節」の後ろの境目、文頭の項目の番号(「一 JIS」)の後ろの境目は、空け方の好みではないので数えない。
|
|
75
|
-
* 日付・時刻は前の境目(「は 9月」「午後3時」「令和 3
|
|
83
|
+
* 日付・時刻は前の境目(「は 9月」「午後3時」「令和 3 年」)も数えない。日付はまとめて一つの書き方で、数量の空け方の票にはしない。コロンで書いた時刻(13:30)も同じ。
|
|
84
|
+
* メールアドレス・URL の前後の境目も数えない(spacing-code.ts)。
|
|
76
85
|
* 「本社 5階」のように名前の後ろに空白で区切った階・部屋の番号の前の空白も、所在の組の区切りなので数えない(location-part.ts)。
|
|
77
86
|
*/
|
|
78
|
-
const isCounted = (sentence: Sentence, boundary: Boundary, context: NumberContext,
|
|
87
|
+
const isCounted = (sentence: Sentence, boundary: Boundary, context: NumberContext, codes: SentenceCodes): boolean => {
|
|
79
88
|
if (followsItemNumber(sentence.text, boundary, context.itemNumbers)) return false;
|
|
80
89
|
if (boundary.kind !== "after-digit" && endsWithDivisionLabel(sentence.text.slice(0, boundary.offset), context.divisions)) return false;
|
|
81
|
-
if (boundary.kind === "letter") return
|
|
90
|
+
if (boundary.kind === "letter") return !besideAddress(codes.addresses, boundary);
|
|
91
|
+
if (isInsideSpan(codes.clockTimes, digitBeside(boundary))) return false;
|
|
82
92
|
const run = digitRunAround(sentence.text, digitBeside(boundary));
|
|
83
93
|
if (run === undefined) return true;
|
|
84
|
-
if (calendar.has(run.start)) return false;
|
|
94
|
+
if (codes.calendar.has(run.start)) return false;
|
|
85
95
|
if (boundary.kind === "before-digit" && isSpacedLocationPart(sentence.text, run, sentence.tokens, sentence.span.start, context.floors)) return false;
|
|
86
96
|
return !isNumberName(sentence.text, run, sentence.tokens, sentence.span.start, context);
|
|
87
97
|
};
|
|
@@ -153,10 +163,10 @@ export const latinSpacing: Detector = (doc, options): Finding[] => {
|
|
|
153
163
|
};
|
|
154
164
|
const located: Located[] = doc.sentences.flatMap((sentence) => {
|
|
155
165
|
const quoted = quotedSpans(sentence.text);
|
|
156
|
-
const
|
|
166
|
+
const codes = { calendar: calendarStarts(sentence, context.calendar), clockTimes: clockTimeSpans(sentence.text), addresses: addressSpans(sentence.text) };
|
|
157
167
|
return latinBoundaries(sentence.text, doc.source.slice(sentence.span.start, sentence.span.end))
|
|
158
168
|
.filter((boundary) => !isQuoted(quoted, boundary) && !isInsideLink(doc.links, sentence.span.start + boundary.offset))
|
|
159
|
-
.filter((boundary) => isCounted(sentence, boundary, context,
|
|
169
|
+
.filter((boundary) => isCounted(sentence, boundary, context, codes))
|
|
160
170
|
.map((boundary) => ({ sentence, ...boundary }));
|
|
161
171
|
});
|
|
162
172
|
return KINDS.flatMap((kind) =>
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// Party names listed in the reverse of the document's usual order (乙及び甲 where the contract otherwise writes 甲及び乙). The
|
|
2
|
+
// names are the parties the document defines and the language package's standard ones (party-order-label); the words that list
|
|
3
|
+
// them are its party-order-joiner list. A direction (乙から甲へ, 甲が乙に) is no listing and is not read.
|
|
4
|
+
import { definedTerms } from "../structure/definition-use.ts";
|
|
5
|
+
import { partiesOf } from "../structure/party-role.ts";
|
|
6
|
+
import { partyListings, reversedListings, type ListingWords } from "../structure/party-order.ts";
|
|
7
|
+
import { quoteAt } from "./structure-tree.ts";
|
|
8
|
+
import type { Detector, Finding, ProseDocument } from "../plugin.ts";
|
|
9
|
+
|
|
10
|
+
/** The usual order is the one written at least this many times as often as its reverse: a tie or near-tie is no convention. */
|
|
11
|
+
const MIN_USUAL_RATIO = 2;
|
|
12
|
+
const SERIES_GROUP = "series";
|
|
13
|
+
|
|
14
|
+
const patternsOf = (doc: ProseDocument, lexicon: string): string[] => (doc.lexicons[lexicon] ?? []).map((entry) => entry.pattern);
|
|
15
|
+
|
|
16
|
+
const listingWords = (doc: ProseDocument): ListingWords => {
|
|
17
|
+
const standard = patternsOf(doc, "party-order-label");
|
|
18
|
+
const terms = doc.structure === undefined ? [] : definedTerms(doc.structure);
|
|
19
|
+
const parties = partiesOf(doc.source, terms, {
|
|
20
|
+
roles: patternsOf(doc, "party-role"),
|
|
21
|
+
shortNames: patternsOf(doc, "party-short-name"),
|
|
22
|
+
companyForms: patternsOf(doc, "company-form"),
|
|
23
|
+
});
|
|
24
|
+
const joiners = doc.lexicons["party-order-joiner"] ?? [];
|
|
25
|
+
return {
|
|
26
|
+
labels: [...new Set([...standard, ...parties.map((party) => party.term)])],
|
|
27
|
+
bareLabels: standard,
|
|
28
|
+
joiners: joiners.filter((entry) => entry.group !== SERIES_GROUP).map((entry) => entry.pattern),
|
|
29
|
+
seriesMarks: joiners.filter((entry) => entry.group === SERIES_GROUP).map((entry) => entry.pattern),
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const partyOrder: Detector = (doc): Finding[] => {
|
|
34
|
+
const texts = doc.sentences.map((sentence) => ({ start: sentence.span.start, text: sentence.text }));
|
|
35
|
+
const textOf = (listing: { readonly start: number; readonly end: number }): string => doc.source.slice(listing.start, listing.end);
|
|
36
|
+
return reversedListings(partyListings(texts, listingWords(doc)), MIN_USUAL_RATIO).map((slip) => ({
|
|
37
|
+
rule: "party-order",
|
|
38
|
+
severity: "info",
|
|
39
|
+
line: 0,
|
|
40
|
+
column: 0,
|
|
41
|
+
quote: quoteAt(doc.source, slip.listing.start),
|
|
42
|
+
values: {
|
|
43
|
+
written: textOf(slip.listing),
|
|
44
|
+
usual: textOf(slip.usual),
|
|
45
|
+
usualCount: slip.usualCount,
|
|
46
|
+
reverseCount: slip.reverseCount,
|
|
47
|
+
offset: slip.listing.start,
|
|
48
|
+
},
|
|
49
|
+
}));
|
|
50
|
+
};
|