chaffjs 0.30.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/time-lengths.d.ts.map +1 -1
- package/dist/derived/time-lengths.js +12 -9
- package/dist/derived/time-lengths.js.map +1 -1
- 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/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/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 +2 -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 +9 -1
- package/dist/detectors/derived-numbers.d.ts.map +1 -1
- package/dist/detectors/derived-numbers.js +2 -2
- 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 +25 -4
- 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/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/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/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/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/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/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 +22 -5
- 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 +1 -0
- package/dist/detectors/time-order.d.ts.map +1 -1
- package/dist/detectors/time-order.js +3 -1
- package/dist/detectors/time-order.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/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/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 +3 -2
- package/dist/name-variants.d.ts.map +1 -1
- package/dist/name-variants.js +4 -7
- package/dist/name-variants.js.map +1 -1
- 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 +5 -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/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/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-outside-period.d.ts +3 -1
- package/dist/structure/date-outside-period.d.ts.map +1 -1
- package/dist/structure/date-outside-period.js +8 -5
- package/dist/structure/date-outside-period.js.map +1 -1
- package/dist/structure/date-range.d.ts +1 -0
- package/dist/structure/date-range.d.ts.map +1 -1
- package/dist/structure/date-range.js +1 -1
- 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/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/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/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-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/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/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/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/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 +8 -2
- package/rules/no-em-dash.yaml +2 -2
- 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/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/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/time-lengths.ts +12 -9
- package/src/derived/use-interval.ts +151 -0
- package/src/detectors/announced-count.ts +1 -0
- package/src/detectors/capacity-runtime.ts +128 -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 +2 -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 +3 -3
- 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 +32 -6
- package/src/detectors/orthographic-variant.ts +78 -9
- package/src/detectors/orthography.ts +16 -6
- 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/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/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/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/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/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 +30 -5
- package/src/detectors/structure.ts +1 -1
- package/src/detectors/technical-docs.ts +12 -0
- package/src/detectors/time-order.ts +5 -1
- 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/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/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 +8 -7
- package/src/phone-numbers.ts +26 -6
- package/src/place-names.ts +53 -14
- package/src/plugin.ts +2 -0
- package/src/preamble-paragraphs.ts +21 -2
- package/src/profile/parse.ts +10 -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/counted-amounts.ts +5 -4
- package/src/structure/date-outside-period.ts +11 -6
- package/src/structure/date-range.ts +1 -1
- 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/measured-amounts.ts +138 -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/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-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/walk-time.ts +285 -0
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import type { Detector, Finding, ProseDocument } from "../plugin.ts";
|
|
2
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
7
|
import { proseAndTablesOf } from "../table-text.ts";
|
|
7
8
|
import { tableBodyCells } from "../facts/table-facts.ts";
|
|
8
9
|
import { cellNamesIn, cellNameVariants, proseNamesOf } from "../table-names.ts";
|
|
9
|
-
import { placeMentionsIn, placeVariants, type PlaceReader, type PlaceWord } from "../place-names.ts";
|
|
10
|
+
import { placeMentionsIn, placeVariants, type PlaceChars, type PlaceReader, type PlaceWord } from "../place-names.ts";
|
|
10
11
|
import type { TableCell, Token } from "../plugin.ts";
|
|
11
12
|
import { proseWithCells } from "../table-cells.ts";
|
|
13
|
+
import { modelCodeFindings } from "./name-variant-model-codes.ts";
|
|
12
14
|
import { labelledSpans, orderNamesOf, quotedSpans, stemOf, titleCaseSpans, wordOrderVariants, type OrderWord } from "../name-word-order.ts";
|
|
13
15
|
|
|
14
16
|
// 人の名前と読ませる敬称(様、さん)は語彙表 person-suffix、人を指す前置き(担当の)は person-lead、名前のすぐ後ろに来る語
|
|
@@ -33,6 +35,18 @@ const properOf = (doc: ProseDocument): IsProper => {
|
|
|
33
35
|
const placeWordsOf = (doc: ProseDocument): PlaceWord[] =>
|
|
34
36
|
(doc.lexicons["place-word"] ?? []).map((entry) => ({ pattern: entry.pattern, group: entry.group ?? entry.pattern }));
|
|
35
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
|
+
|
|
36
50
|
/** 名前の頭に立たない語の品詞(The、at、and)。 */
|
|
37
51
|
const FUNCTION_POS: ReadonlySet<string> = new Set(["DET", "ADP", "PRON", "CCONJ", "SCONJ", "AUX", "PART"]);
|
|
38
52
|
|
|
@@ -87,8 +101,8 @@ const companyFindings = (doc: ProseDocument, prose: string, reported: readonly R
|
|
|
87
101
|
.map(({ mention, usual, kind }) => ({ offset: mention.offset, name: mention.surface, usual, kind: kind === "spelling" ? kind : `company-${kind}` }));
|
|
88
102
|
|
|
89
103
|
/** 場所の名前の書き分け。表の本体の升の中の名前も読む(見出しの行は読まない)。人や会社の名前の見方がすでに指した所と重なるものは除く。 */
|
|
90
|
-
const placeFindings = (doc: ProseDocument, prose: string, reported: readonly Reported[]): Reported[] =>
|
|
91
|
-
placeVariants(placeMentionsIn(proseWithCells(prose, cellsOf(doc)), placeWordsOf(doc), placeReaderOf(doc)))
|
|
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))
|
|
92
106
|
.filter(({ mention }) => !overlapsAny(reported, mention.offset, mention.surface.length))
|
|
93
107
|
.map(({ mention, usual, kind }) => ({ offset: mention.offset, name: mention.surface, usual, kind }));
|
|
94
108
|
|
|
@@ -142,6 +156,16 @@ const nameMentionsOf = (doc: ProseDocument, prose: string, chars: VariantChars):
|
|
|
142
156
|
return withKnownNeighbours(cued, prose).toSorted((left, right) => left.offset - right.offset);
|
|
143
157
|
};
|
|
144
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
|
+
|
|
145
169
|
/** 表の升に書いた名前の書き分け。名前の形をした升を、本文の名前と比べる。ほかの見方がすでに指した所と重なるものは除く。 */
|
|
146
170
|
const tableFindings = (doc: ProseDocument, prose: string, mentions: readonly NameMention[], reported: readonly Reported[]): Reported[] =>
|
|
147
171
|
cellNameVariants(cellNamesIn(cellsOf(doc)), proseNamesOf(mentions, prose))
|
|
@@ -153,7 +177,7 @@ export const nameVariant: Detector = (doc): Finding[] => {
|
|
|
153
177
|
const prose = doc.prose ?? doc.source;
|
|
154
178
|
const chars = variantCharsOf(doc);
|
|
155
179
|
const mentions = nameMentionsOf(doc, prose, chars);
|
|
156
|
-
const names = nameVariants(mentions, chars).map(({ mention, usual, kind }): Reported => ({
|
|
180
|
+
const names = nameVariants(mentions, chars, spellingInputOf(doc)).map(({ mention, usual, kind }): Reported => ({
|
|
157
181
|
offset: mention.offset,
|
|
158
182
|
name: mention.surface,
|
|
159
183
|
usual,
|
|
@@ -161,8 +185,10 @@ export const nameVariant: Detector = (doc): Finding[] => {
|
|
|
161
185
|
}));
|
|
162
186
|
const namesAndCompanies = [...names, ...companyFindings(doc, prose, names)];
|
|
163
187
|
const withTables = [...namesAndCompanies, ...tableFindings(doc, prose, mentions, namesAndCompanies)];
|
|
164
|
-
const withPlaces = [...withTables, ...placeFindings(doc, prose, withTables)];
|
|
165
|
-
|
|
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]
|
|
166
192
|
.toSorted((left, right) => left.offset - right.offset)
|
|
167
193
|
.map(({ offset, name, usual, kind }) => ({
|
|
168
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,47 @@
|
|
|
1
|
+
// quantity-range-reversed: a range of measured quantities whose upper end is below its lower end (5–2 kg, 30〜10 cm,
|
|
2
|
+
// 40〜-10℃), decided by structure/amount-range.ts as amount-range-reversed is. The quantities are read with the unit
|
|
3
|
+
// lexicons (unit-length, unit-mass, …); the joints are range-connector, range-opener, range-closer and quantity-range-word;
|
|
4
|
+
// quantity-change-word (its lead group: a word right before the range) and quantity-bound-label say what makes a pair a
|
|
5
|
+
// change and what labels a bound.
|
|
6
|
+
import type { Detector, Finding, ProseDocument } from "../plugin.ts";
|
|
7
|
+
import { measuredValues } from "../facts/measures.ts";
|
|
8
|
+
import { measureUnitsOf } from "../facts/measure-units.ts";
|
|
9
|
+
import { reversedAmountRanges, type AmountRangeWords } from "../structure/amount-range.ts";
|
|
10
|
+
import { quantityRangeEnds, unledRanges } from "../structure/quantity-range.ts";
|
|
11
|
+
import { AMOUNT } from "./currency-notation.ts";
|
|
12
|
+
import { proseAndTablesOf } from "../table-text.ts";
|
|
13
|
+
import { quoteAround } from "./quote-around.ts";
|
|
14
|
+
|
|
15
|
+
/** A bare end may carry a minus sign (-10〜-40℃); a hyphen right after a digit or a letter is a range mark (5-10 kg). */
|
|
16
|
+
const SIGNED_NUMBER = `(?:[-−-](?=[0-90-9]))?${AMOUNT}`;
|
|
17
|
+
|
|
18
|
+
const patternsOf = (doc: ProseDocument, lexicon: string, group?: string): string[] =>
|
|
19
|
+
(doc.lexicons[lexicon] ?? []).filter((entry) => group === undefined || entry.group === group).map((entry) => entry.pattern);
|
|
20
|
+
|
|
21
|
+
const ungroupedOf = (doc: ProseDocument, lexicon: string): string[] =>
|
|
22
|
+
(doc.lexicons[lexicon] ?? []).filter((entry) => entry.group === undefined).map((entry) => entry.pattern);
|
|
23
|
+
|
|
24
|
+
const wordsOf = (doc: ProseDocument): AmountRangeWords => ({
|
|
25
|
+
connectors: [...patternsOf(doc, "range-connector"), ...patternsOf(doc, "quantity-range-word")],
|
|
26
|
+
openers: patternsOf(doc, "range-opener"),
|
|
27
|
+
closers: patternsOf(doc, "range-closer"),
|
|
28
|
+
changes: ungroupedOf(doc, "quantity-change-word"),
|
|
29
|
+
lowers: patternsOf(doc, "quantity-bound-label", "lower"),
|
|
30
|
+
uppers: patternsOf(doc, "quantity-bound-label", "upper"),
|
|
31
|
+
links: patternsOf(doc, "quantity-bound-label", "link"),
|
|
32
|
+
scales: [],
|
|
33
|
+
number: SIGNED_NUMBER,
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
export const quantityRange: Detector = (doc): Finding[] => {
|
|
37
|
+
const text = proseAndTablesOf(doc);
|
|
38
|
+
const reversed = reversedAmountRanges(text, quantityRangeEnds(text, measuredValues(text, measureUnitsOf(doc))), wordsOf(doc));
|
|
39
|
+
return unledRanges(text, reversed, patternsOf(doc, "quantity-change-word", "lead")).map((issue) => ({
|
|
40
|
+
rule: "quantity-range-reversed",
|
|
41
|
+
severity: "warning",
|
|
42
|
+
line: 0,
|
|
43
|
+
column: 0,
|
|
44
|
+
quote: quoteAround(text, issue.offset),
|
|
45
|
+
values: { ...issue.values, offset: issue.offset },
|
|
46
|
+
}));
|
|
47
|
+
};
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
// range-band-mismatch: neighbouring bands of one table column or one list that overlap or leave a gap (structure/range-bands.ts).
|
|
2
|
+
// The words that bound a band are range-band-word's, the units range-band-unit's, and the column headings that say what bare
|
|
3
|
+
// numbers count range-band-heading's.
|
|
4
|
+
import type { Detector, Finding, ProseDocument } from "../plugin.ts";
|
|
5
|
+
import { cellsOf, tablesOf } from "../facts/table-facts.ts";
|
|
6
|
+
import { linesOf } from "../structure/lines.ts";
|
|
7
|
+
import {
|
|
8
|
+
bandSlips,
|
|
9
|
+
headingOf,
|
|
10
|
+
parseBand,
|
|
11
|
+
runKindOf,
|
|
12
|
+
type BandMarker,
|
|
13
|
+
type BandSlip,
|
|
14
|
+
type BandWords,
|
|
15
|
+
type PlacedBand,
|
|
16
|
+
type UnitKind,
|
|
17
|
+
} from "../structure/range-bands.ts";
|
|
18
|
+
import { quoteAt } from "./structure-tree.ts";
|
|
19
|
+
|
|
20
|
+
const MARKER_GROUPS: Readonly<Record<string, Pick<BandMarker, "side" | "kind">>> = {
|
|
21
|
+
"lower-inclusive": { side: "low", kind: "inclusive" },
|
|
22
|
+
"lower-exclusive": { side: "low", kind: "exclusive" },
|
|
23
|
+
"upper-inclusive": { side: "high", kind: "inclusive" },
|
|
24
|
+
"upper-exclusive": { side: "high", kind: "exclusive" },
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const isUnitKind = (group: string | undefined): group is UnitKind => group === "integer" || group === "continuous";
|
|
28
|
+
|
|
29
|
+
export const bandWordsOf = (lexicons: ProseDocument["lexicons"]): BandWords => {
|
|
30
|
+
const words = lexicons["range-band-word"] ?? [];
|
|
31
|
+
const patterns = (group: string): string[] => words.filter((entry) => entry.group === group).map((entry) => entry.pattern);
|
|
32
|
+
return {
|
|
33
|
+
connectors: patterns("connector"),
|
|
34
|
+
openers: words.filter((entry) => entry.group === "connector" && entry.position === "before").map((entry) => entry.pattern),
|
|
35
|
+
leads: patterns("lead"),
|
|
36
|
+
markers: words.flatMap((entry) => {
|
|
37
|
+
const marker = MARKER_GROUPS[entry.group ?? ""];
|
|
38
|
+
return marker === undefined ? [] : [{ pattern: entry.pattern, ...marker, position: entry.position ?? "after" }];
|
|
39
|
+
}),
|
|
40
|
+
units: (lexicons["range-band-unit"] ?? []).flatMap((entry) =>
|
|
41
|
+
isUnitKind(entry.group) ? [{ pattern: entry.pattern, kind: entry.group, position: entry.position ?? "after" }] : [],
|
|
42
|
+
),
|
|
43
|
+
headings: (lexicons["range-band-heading"] ?? []).flatMap((entry) => (isUnitKind(entry.group) ? [{ pattern: entry.pattern, kind: entry.group }] : [])),
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
type Slot = { readonly text: string; readonly start: number; readonly end: number };
|
|
48
|
+
|
|
49
|
+
/** Runs of consecutive slots that each state a band. A slot that is not one (合計, a blank) ends the run. */
|
|
50
|
+
const bandRuns = (slots: readonly (Slot | undefined)[], words: BandWords): PlacedBand[][] =>
|
|
51
|
+
slots
|
|
52
|
+
.reduce<PlacedBand[][]>(
|
|
53
|
+
(runs, slot) => {
|
|
54
|
+
const band = slot === undefined ? undefined : parseBand(slot.text, words);
|
|
55
|
+
if (slot === undefined || band === undefined) return [...runs, []];
|
|
56
|
+
const last = runs.at(-1) ?? [];
|
|
57
|
+
return [...runs.slice(0, -1), [...last, { band, start: slot.start, end: slot.end, text: slot.text.trim() }]];
|
|
58
|
+
},
|
|
59
|
+
[[]],
|
|
60
|
+
)
|
|
61
|
+
.filter((run) => run.length > 1);
|
|
62
|
+
|
|
63
|
+
const slipsOfRuns = (runs: readonly PlacedBand[][], heading: ReturnType<typeof headingOf>, words: BandWords): BandSlip[] =>
|
|
64
|
+
runs.flatMap((run) => {
|
|
65
|
+
const kind = runKindOf(
|
|
66
|
+
run.map((placed) => placed.band),
|
|
67
|
+
heading,
|
|
68
|
+
words,
|
|
69
|
+
);
|
|
70
|
+
return kind === undefined ? [] : bandSlips(run, kind);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
const trimmedSlot = (text: string, start: number): Slot => {
|
|
74
|
+
const lead = text.length - text.trimStart().length;
|
|
75
|
+
return { text: text.trim(), start: start + lead, end: start + lead + text.trim().length };
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const tableSlips = (source: string, words: BandWords): BandSlip[] =>
|
|
79
|
+
tablesOf(linesOf(source)).flatMap((table) => {
|
|
80
|
+
const headings = cellsOf(table.header);
|
|
81
|
+
const rows = table.rows.map(cellsOf);
|
|
82
|
+
return headings.flatMap((heading, column) =>
|
|
83
|
+
slipsOfRuns(
|
|
84
|
+
bandRuns(
|
|
85
|
+
rows.map((cells) => {
|
|
86
|
+
const cell = cells[column];
|
|
87
|
+
return cell === undefined ? undefined : trimmedSlot(cell.text, cell.start);
|
|
88
|
+
}),
|
|
89
|
+
words,
|
|
90
|
+
),
|
|
91
|
+
headingOf(heading.text, words),
|
|
92
|
+
words,
|
|
93
|
+
),
|
|
94
|
+
);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
const LIST_MARKER = /^\s*(?:[-*+]|\d+[.)])\s+/u;
|
|
98
|
+
/** Where the band at the head of a list item ends: a colon, a comma, a bracket, or a dash set off by spaces. */
|
|
99
|
+
const ITEM_HEAD_END = /[::、,,((]|\s[-–—]\s|\t/u;
|
|
100
|
+
|
|
101
|
+
const listSlips = (doc: ProseDocument, words: BandWords): BandSlip[] =>
|
|
102
|
+
doc.lists.flatMap((list) => {
|
|
103
|
+
const heads = list.itemSpans.map((span): Slot | undefined => {
|
|
104
|
+
const item = doc.source.slice(span.start, span.end).split("\n")[0] ?? "";
|
|
105
|
+
const marker = LIST_MARKER.exec(item)?.[0];
|
|
106
|
+
if (marker === undefined) return undefined;
|
|
107
|
+
const body = item.slice(marker.length);
|
|
108
|
+
const end = ITEM_HEAD_END.exec(body)?.index ?? body.length;
|
|
109
|
+
return trimmedSlot(body.slice(0, end), span.start + marker.length);
|
|
110
|
+
});
|
|
111
|
+
return slipsOfRuns(bandRuns(heads, words), undefined, words);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
export const rangeBand: Detector = (doc): Finding[] => {
|
|
115
|
+
const words = bandWordsOf(doc.lexicons);
|
|
116
|
+
return [...tableSlips(doc.source, words), ...listSlips(doc, words)].map((slip) => ({
|
|
117
|
+
rule: "range-band-mismatch",
|
|
118
|
+
severity: "warning",
|
|
119
|
+
line: 0,
|
|
120
|
+
column: 0,
|
|
121
|
+
quote: quoteAt(doc.source, slip.later.start),
|
|
122
|
+
...(slip.kind === "gap" ? { variant: "gap" } : {}),
|
|
123
|
+
values: { earlier: slip.earlier.text, later: slip.later.text, offset: slip.later.start },
|
|
124
|
+
}));
|
|
125
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// rent-multiple-mismatch: a deposit or key money given in months of rent beside an amount that is not that many months of
|
|
2
|
+
// the rent (structure/rent-multiple.ts). The amounts are currency-notation's, read with amount-multiplier's words of scale;
|
|
3
|
+
// the labels are rent-label and rent-multiple-label, the words rent-multiple-word, the counts number-word (digit), and a
|
|
4
|
+
// range of rent is joined by range-connector or amount-range-word.
|
|
5
|
+
import type { Detector, Finding, ProseDocument } from "../plugin.ts";
|
|
6
|
+
import { rentMultipleMismatches, type RentAmount, type RentMultipleWords } from "../structure/rent-multiple.ts";
|
|
7
|
+
import { scaledAmountOf, scaleWordsOf } from "./amount-scale.ts";
|
|
8
|
+
import { amountsIn, formsOf } from "./currency-notation.ts";
|
|
9
|
+
import { proseAndTablesOf } from "../table-text.ts";
|
|
10
|
+
import { quoteAround } from "./quote-around.ts";
|
|
11
|
+
|
|
12
|
+
const patternsOf = (doc: ProseDocument, lexicon: string, group?: string): string[] =>
|
|
13
|
+
(doc.lexicons[lexicon] ?? []).filter((entry) => group === undefined || entry.group === group).map((entry) => entry.pattern);
|
|
14
|
+
|
|
15
|
+
const numberWordsOf = (doc: ProseDocument): RentMultipleWords["numberWords"] =>
|
|
16
|
+
(doc.lexicons["number-word"] ?? []).flatMap((entry) =>
|
|
17
|
+
entry.group === "digit" && entry.weight !== undefined ? [{ word: entry.pattern, value: entry.weight }] : [],
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
const wordsOf = (doc: ProseDocument): RentMultipleWords => ({
|
|
21
|
+
rents: patternsOf(doc, "rent-label", "rent"),
|
|
22
|
+
fees: patternsOf(doc, "rent-label", "fee"),
|
|
23
|
+
multiples: patternsOf(doc, "rent-multiple-label"),
|
|
24
|
+
months: patternsOf(doc, "rent-multiple-word", "month"),
|
|
25
|
+
links: patternsOf(doc, "rent-multiple-word", "link"),
|
|
26
|
+
periods: patternsOf(doc, "rent-multiple-word", "period"),
|
|
27
|
+
skips: patternsOf(doc, "rent-multiple-word", "skip"),
|
|
28
|
+
connectors: [...patternsOf(doc, "range-connector"), ...patternsOf(doc, "amount-range-word")],
|
|
29
|
+
numberWords: numberWordsOf(doc),
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
const amountsOf = (text: string, doc: ProseDocument): RentAmount[] => {
|
|
33
|
+
const scales = scaleWordsOf(doc);
|
|
34
|
+
return amountsIn(
|
|
35
|
+
text,
|
|
36
|
+
formsOf(doc),
|
|
37
|
+
scales.map((scale) => scale.word),
|
|
38
|
+
).flatMap((amount) => {
|
|
39
|
+
const read = scaledAmountOf(text, amount, scales);
|
|
40
|
+
return read === undefined
|
|
41
|
+
? []
|
|
42
|
+
: [{ offset: read.offset, end: amount.offset + amount.written.length, currency: read.currency, value: read.value, scale: read.unit }];
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export const rentMultipleMismatch: Detector = (doc): Finding[] => {
|
|
47
|
+
const text = proseAndTablesOf(doc);
|
|
48
|
+
return rentMultipleMismatches(text, amountsOf(text, doc), wordsOf(doc)).map((issue) => ({
|
|
49
|
+
rule: "rent-multiple-mismatch",
|
|
50
|
+
severity: "warning",
|
|
51
|
+
line: 0,
|
|
52
|
+
column: 0,
|
|
53
|
+
quote: quoteAround(text, issue.offset),
|
|
54
|
+
values: { ...issue.values, offset: issue.offset },
|
|
55
|
+
}));
|
|
56
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// One row of a servings table (4人分 / 8人分, Serves 4 / Serves 8) that does not scale by the columns' ratio while the other rows
|
|
2
|
+
// do. The column marks, the amounts left to the cook and the spellings of one unit come from the language packages.
|
|
3
|
+
import { scaleSlips, type ScaleWords } from "../structure/scaled-quantities.ts";
|
|
4
|
+
import type { MeasureUnit } from "../facts/measures.ts";
|
|
5
|
+
import { quoteAt } from "./structure-tree.ts";
|
|
6
|
+
import type { Detector, Finding, ProseDocument } from "../plugin.ts";
|
|
7
|
+
|
|
8
|
+
const DIMENSIONS = ["unit-mass", "unit-volume"] as const;
|
|
9
|
+
|
|
10
|
+
const measuresOf = (doc: ProseDocument): MeasureUnit[] =>
|
|
11
|
+
DIMENSIONS.flatMap((dimension) =>
|
|
12
|
+
(doc.lexicons[dimension] ?? []).flatMap((entry) =>
|
|
13
|
+
entry.weight === undefined
|
|
14
|
+
? []
|
|
15
|
+
: [{ pattern: entry.pattern, dimension, factors: [entry.weight], zero: 0, before: entry.position === "before", context: [] }],
|
|
16
|
+
),
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
const wordsOf = (doc: ProseDocument): ScaleWords => ({
|
|
20
|
+
columns: (doc.lexicons["servings-column"] ?? []).map((entry) => ({ pattern: entry.pattern, position: entry.position })),
|
|
21
|
+
unscaled: (doc.lexicons["unscaled-amount"] ?? []).map((entry) => entry.pattern),
|
|
22
|
+
unitForms: (doc.lexicons["scaled-unit-form"] ?? []).map((entry) => ({ pattern: entry.pattern, group: entry.group ?? entry.pattern })),
|
|
23
|
+
measures: measuresOf(doc),
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const DECIMALS = 1000;
|
|
27
|
+
const shown = (amount: number): string => String(Math.round(amount * DECIMALS) / DECIMALS);
|
|
28
|
+
|
|
29
|
+
export const scaledQuantityMismatch: Detector = (doc): Finding[] =>
|
|
30
|
+
scaleSlips(doc.source, wordsOf(doc)).map((slip) => {
|
|
31
|
+
const offset = slip.cell.start + (slip.cell.text.length - slip.cell.text.trimStart().length);
|
|
32
|
+
return {
|
|
33
|
+
rule: "scaled-quantity-mismatch",
|
|
34
|
+
severity: "warning",
|
|
35
|
+
line: 0,
|
|
36
|
+
column: 0,
|
|
37
|
+
quote: quoteAt(doc.source, offset),
|
|
38
|
+
values: {
|
|
39
|
+
item: slip.item.text.trim(),
|
|
40
|
+
written: slip.cell.text.trim(),
|
|
41
|
+
column: slip.heading,
|
|
42
|
+
other: slip.other.text.trim(),
|
|
43
|
+
otherColumn: slip.otherHeading,
|
|
44
|
+
expected: shown(slip.expected),
|
|
45
|
+
scaledRows: slip.scaledRows,
|
|
46
|
+
offset,
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
});
|