hyper-html-api 0.13.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -1
- package/conformance/MANIFEST.json +2 -2
- package/conformance/cases/all-matches-read-quoted.expected.json +3 -0
- package/conformance/cases/all-matches-read-quoted.html +5 -0
- package/conformance/cases/all-matches-read-quoted.meta +7 -0
- package/conformance/cases/all-matches-read-quoted.parsed.json +3 -0
- package/conformance/cases/all-matches-read.expected.json +3 -0
- package/conformance/cases/all-matches-read.html +6 -0
- package/conformance/cases/all-matches-read.meta +7 -0
- package/conformance/cases/all-matches-read.parsed.json +3 -0
- package/conformance/cases/codec-form-nested.error.json +5 -0
- package/conformance/cases/codec-form-nested.html +4 -0
- package/conformance/cases/codec-form-nested.meta +6 -0
- package/conformance/cases/codec-form-nested.parsed.json +5 -0
- package/conformance/cases/codec-form-star.error.json +5 -0
- package/conformance/cases/codec-form-star.html +4 -0
- package/conformance/cases/codec-form-star.meta +6 -0
- package/conformance/cases/codec-form-star.parsed.json +3 -0
- package/conformance/cases/codec-form-under-v1.error.json +5 -0
- package/conformance/cases/codec-form-under-v1.html +4 -0
- package/conformance/cases/codec-form-under-v1.meta +6 -0
- package/conformance/cases/codec-form-under-v1.parsed.json +3 -0
- package/conformance/cases/codec-unknown-name.error.json +5 -0
- package/conformance/cases/codec-unknown-name.html +4 -0
- package/conformance/cases/codec-unknown-name.meta +6 -0
- package/conformance/cases/codec-unknown-name.parsed.json +3 -0
- package/conformance/cases/tag-version-2-plain.expected.json +7 -0
- package/conformance/cases/tag-version-2-plain.html +5 -0
- package/conformance/cases/tag-version-2-plain.meta +6 -0
- package/conformance/cases/tag-version-2-plain.parsed.json +4 -0
- package/conformance/cases/tag-wrong-version.error.json +1 -1
- package/conformance/cases/tag-wrong-version.html +1 -1
- package/conformance/cases/write-all-matches-attr.after.html +1 -0
- package/conformance/cases/write-all-matches-attr.after.json +3 -0
- package/conformance/cases/write-all-matches-attr.data.json +1 -0
- package/conformance/cases/write-all-matches-attr.html +1 -0
- package/conformance/cases/write-all-matches-attr.meta +6 -0
- package/conformance/cases/write-all-matches-attr.write.json +4 -0
- package/conformance/cases/write-all-matches-group.after.html +1 -0
- package/conformance/cases/write-all-matches-group.after.json +3 -0
- package/conformance/cases/write-all-matches-group.data.json +1 -0
- package/conformance/cases/write-all-matches-group.html +1 -0
- package/conformance/cases/write-all-matches-group.meta +6 -0
- package/conformance/cases/write-all-matches-group.write.json +4 -0
- package/conformance/cases/write-all-matches-text.after.html +1 -0
- package/conformance/cases/write-all-matches-text.after.json +3 -0
- package/conformance/cases/write-all-matches-text.data.json +1 -0
- package/conformance/cases/write-all-matches-text.html +1 -0
- package/conformance/cases/write-all-matches-text.meta +6 -0
- package/conformance/cases/write-all-matches-text.write.json +4 -0
- package/conformance/cases/write-all-matches-unmatched.data.json +1 -0
- package/conformance/cases/write-all-matches-unmatched.error.json +14 -0
- package/conformance/cases/write-all-matches-unmatched.html +1 -0
- package/conformance/cases/write-all-matches-unmatched.meta +6 -0
- package/conformance/sheet/body-data-write.body.json +3 -0
- package/conformance/sheet/body-data-write.data.json +3 -0
- package/conformance/sheet/body-data-write.html +25 -0
- package/conformance/sheet/body-data-write.meta +5 -0
- package/conformance/sheet/body-patch-key-in-rules.body.json +3 -0
- package/conformance/sheet/body-patch-key-in-rules.data.json +13 -0
- package/conformance/sheet/body-patch-key-in-rules.html +18 -0
- package/conformance/sheet/body-patch-key-in-rules.meta +5 -0
- package/conformance/sheet/body-patch-not-array.body.json +3 -0
- package/conformance/sheet/body-patch-not-array.data.json +3 -0
- package/conformance/sheet/body-patch-not-array.html +25 -0
- package/conformance/sheet/body-patch-not-array.meta +5 -0
- package/conformance/sheet/body-patch-on-sheet.body.json +3 -0
- package/conformance/sheet/body-patch-on-sheet.data.json +14 -0
- package/conformance/sheet/body-patch-on-sheet.html +25 -0
- package/conformance/sheet/body-patch-on-sheet.meta +5 -0
- package/conformance/sheet/body-patch-version-1.body.json +3 -0
- package/conformance/sheet/body-patch-version-1.data.json +13 -0
- package/conformance/sheet/body-patch-version-1.html +4 -0
- package/conformance/sheet/body-patch-version-1.meta +5 -0
- package/conformance/sheet/body-patch-with-other-key.body.json +3 -0
- package/conformance/sheet/body-patch-with-other-key.data.json +14 -0
- package/conformance/sheet/body-patch-with-other-key.html +25 -0
- package/conformance/sheet/body-patch-with-other-key.meta +5 -0
- package/conformance/sheet/body-patch-without-operation-id.body.json +3 -0
- package/conformance/sheet/body-patch-without-operation-id.data.json +13 -0
- package/conformance/sheet/body-patch-without-operation-id.html +25 -0
- package/conformance/sheet/body-patch-without-operation-id.meta +5 -0
- package/conformance/sheet/params-bad-range.error.json +6 -0
- package/conformance/sheet/params-bad-range.html +25 -0
- package/conformance/sheet/params-bad-range.meta +6 -0
- package/conformance/sheet/params-bad-render.error.json +6 -0
- package/conformance/sheet/params-bad-render.html +25 -0
- package/conformance/sheet/params-bad-render.meta +6 -0
- package/conformance/sheet/params-bad-shape.error.json +6 -0
- package/conformance/sheet/params-bad-shape.html +25 -0
- package/conformance/sheet/params-bad-shape.meta +6 -0
- package/conformance/sheet/params-cache-buster.expected.json +128 -0
- package/conformance/sheet/params-cache-buster.html +25 -0
- package/conformance/sheet/params-cache-buster.meta +6 -0
- package/conformance/sheet/params-data-alone.expected.json +128 -0
- package/conformance/sheet/params-data-alone.html +25 -0
- package/conformance/sheet/params-data-alone.meta +6 -0
- package/conformance/sheet/params-empty.error.json +6 -0
- package/conformance/sheet/params-empty.html +25 -0
- package/conformance/sheet/params-empty.meta +6 -0
- package/conformance/sheet/params-index.expected.json +19 -0
- package/conformance/sheet/params-index.html +25 -0
- package/conformance/sheet/params-index.meta +6 -0
- package/conformance/sheet/params-none.expected.json +128 -0
- package/conformance/sheet/params-none.html +25 -0
- package/conformance/sheet/params-none.meta +6 -0
- package/conformance/sheet/params-range.expected.json +17 -0
- package/conformance/sheet/params-range.html +25 -0
- package/conformance/sheet/params-range.meta +6 -0
- package/conformance/sheet/params-render-without-range.error.json +6 -0
- package/conformance/sheet/params-render-without-range.html +25 -0
- package/conformance/sheet/params-render-without-range.meta +6 -0
- package/conformance/sheet/params-repeated.error.json +6 -0
- package/conformance/sheet/params-repeated.html +25 -0
- package/conformance/sheet/params-repeated.meta +6 -0
- package/conformance/sheet/params-unknown-sheet.error.json +6 -0
- package/conformance/sheet/params-unknown-sheet.html +25 -0
- package/conformance/sheet/params-unknown-sheet.meta +6 -0
- package/conformance/sheet/params-with-data.error.json +6 -0
- package/conformance/sheet/params-with-data.html +25 -0
- package/conformance/sheet/params-with-data.meta +6 -0
- package/conformance/sheet/sheet-contract-cells.expected.json +57 -0
- package/conformance/sheet/sheet-contract-cells.html +10 -0
- package/conformance/sheet/sheet-contract-cells.meta +6 -0
- package/conformance/sheet/sheet-contract-formulas.expected.json +29 -0
- package/conformance/sheet/sheet-contract-formulas.html +10 -0
- package/conformance/sheet/sheet-contract-formulas.meta +6 -0
- package/conformance/sheet/sheet-contract-values.expected.json +29 -0
- package/conformance/sheet/sheet-contract-values.html +10 -0
- package/conformance/sheet/sheet-contract-values.meta +6 -0
- package/conformance/sheet/sheet-contract-whole.expected.json +59 -0
- package/conformance/sheet/sheet-contract-whole.html +10 -0
- package/conformance/sheet/sheet-contract-whole.meta +5 -0
- package/conformance/sheet/sheet-hostile-01.expected.json +18 -0
- package/conformance/sheet/sheet-hostile-01.html +6 -0
- package/conformance/sheet/sheet-hostile-01.meta +5 -0
- package/conformance/sheet/sheet-hostile-02.expected.json +18 -0
- package/conformance/sheet/sheet-hostile-02.html +6 -0
- package/conformance/sheet/sheet-hostile-02.meta +5 -0
- package/conformance/sheet/sheet-hostile-03.expected.json +18 -0
- package/conformance/sheet/sheet-hostile-03.html +6 -0
- package/conformance/sheet/sheet-hostile-03.meta +5 -0
- package/conformance/sheet/sheet-hostile-04.expected.json +18 -0
- package/conformance/sheet/sheet-hostile-04.html +6 -0
- package/conformance/sheet/sheet-hostile-04.meta +5 -0
- package/conformance/sheet/sheet-hostile-05.expected.json +18 -0
- package/conformance/sheet/sheet-hostile-05.html +6 -0
- package/conformance/sheet/sheet-hostile-05.meta +5 -0
- package/conformance/sheet/sheet-hostile-06.expected.json +21 -0
- package/conformance/sheet/sheet-hostile-06.html +6 -0
- package/conformance/sheet/sheet-hostile-06.meta +5 -0
- package/conformance/sheet/sheet-hostile-07.expected.json +21 -0
- package/conformance/sheet/sheet-hostile-07.html +6 -0
- package/conformance/sheet/sheet-hostile-07.meta +5 -0
- package/conformance/sheet/sheet-hostile-08.expected.json +21 -0
- package/conformance/sheet/sheet-hostile-08.html +6 -0
- package/conformance/sheet/sheet-hostile-08.meta +5 -0
- package/conformance/sheet/sheet-hostile-09.expected.json +21 -0
- package/conformance/sheet/sheet-hostile-09.html +6 -0
- package/conformance/sheet/sheet-hostile-09.meta +5 -0
- package/conformance/sheet/sheet-hostile-10.expected.json +21 -0
- package/conformance/sheet/sheet-hostile-10.html +6 -0
- package/conformance/sheet/sheet-hostile-10.meta +5 -0
- package/conformance/sheet/sheet-hostile-11.expected.json +22 -0
- package/conformance/sheet/sheet-hostile-11.html +6 -0
- package/conformance/sheet/sheet-hostile-11.meta +5 -0
- package/conformance/sheet/sheet-hostile-12.expected.json +18 -0
- package/conformance/sheet/sheet-hostile-12.html +6 -0
- package/conformance/sheet/sheet-hostile-12.meta +5 -0
- package/conformance/sheet/sheet-hostile-13.expected.json +18 -0
- package/conformance/sheet/sheet-hostile-13.html +6 -0
- package/conformance/sheet/sheet-hostile-13.meta +5 -0
- package/conformance/sheet/sheet-hostile-14.expected.json +21 -0
- package/conformance/sheet/sheet-hostile-14.html +6 -0
- package/conformance/sheet/sheet-hostile-14.meta +5 -0
- package/conformance/sheet/sheet-hostile-15.expected.json +18 -0
- package/conformance/sheet/sheet-hostile-15.html +0 -0
- package/conformance/sheet/sheet-hostile-15.meta +5 -0
- package/conformance/sheet/sheet-hostile-16.expected.json +18 -0
- package/conformance/sheet/sheet-hostile-16.html +6 -0
- package/conformance/sheet/sheet-hostile-16.meta +5 -0
- package/conformance/sheet/sheet-hostile-17.expected.json +18 -0
- package/conformance/sheet/sheet-hostile-17.html +6 -0
- package/conformance/sheet/sheet-hostile-17.meta +5 -0
- package/conformance/sheet/sheet-hostile-18.expected.json +18 -0
- package/conformance/sheet/sheet-hostile-18.html +6 -0
- package/conformance/sheet/sheet-hostile-18.meta +5 -0
- package/conformance/sheet/sheet-hostile-19.expected.json +18 -0
- package/conformance/sheet/sheet-hostile-19.html +6 -0
- package/conformance/sheet/sheet-hostile-19.meta +5 -0
- package/conformance/sheet/sheet-hostile-20.expected.json +16 -0
- package/conformance/sheet/sheet-hostile-20.html +6 -0
- package/conformance/sheet/sheet-hostile-20.meta +5 -0
- package/conformance/sheet/sheet-hostile-21.expected.json +18 -0
- package/conformance/sheet/sheet-hostile-21.html +6 -0
- package/conformance/sheet/sheet-hostile-21.meta +5 -0
- package/conformance/sheet/sheet-hostile-22.expected.json +21 -0
- package/conformance/sheet/sheet-hostile-22.html +6 -0
- package/conformance/sheet/sheet-hostile-22.meta +5 -0
- package/conformance/sheet/sheet-hostile-23.expected.json +18 -0
- package/conformance/sheet/sheet-hostile-23.html +6 -0
- package/conformance/sheet/sheet-hostile-23.meta +5 -0
- package/conformance/sheet/sheet-hostile-24.expected.json +18 -0
- package/conformance/sheet/sheet-hostile-24.html +6 -0
- package/conformance/sheet/sheet-hostile-24.meta +5 -0
- package/conformance/sheet/sheet-hostile-25.expected.json +18 -0
- package/conformance/sheet/sheet-hostile-25.html +6 -0
- package/conformance/sheet/sheet-hostile-25.meta +5 -0
- package/conformance/sheet/sheet-hostile-26.expected.json +18 -0
- package/conformance/sheet/sheet-hostile-26.html +6 -0
- package/conformance/sheet/sheet-hostile-26.meta +5 -0
- package/conformance/sheet/sheet-hostile-27.expected.json +24 -0
- package/conformance/sheet/sheet-hostile-27.html +7 -0
- package/conformance/sheet/sheet-hostile-27.meta +5 -0
- package/conformance/sheet/sheet-hostile-28.expected.json +18 -0
- package/conformance/sheet/sheet-hostile-28.html +6 -0
- package/conformance/sheet/sheet-hostile-28.meta +5 -0
- package/conformance/sheet/sheet-hostile-29.expected.json +18 -0
- package/conformance/sheet/sheet-hostile-29.html +6 -0
- package/conformance/sheet/sheet-hostile-29.meta +5 -0
- package/conformance/sheet/sheet-hostile-30.expected.json +18 -0
- package/conformance/sheet/sheet-hostile-30.html +6 -0
- package/conformance/sheet/sheet-hostile-30.meta +5 -0
- package/conformance/sheet/sheet-hostile-31.expected.json +19 -0
- package/conformance/sheet/sheet-hostile-31.html +6 -0
- package/conformance/sheet/sheet-hostile-31.meta +5 -0
- package/conformance/sheet/sheet-hostile-32.expected.json +24 -0
- package/conformance/sheet/sheet-hostile-32.html +6 -0
- package/conformance/sheet/sheet-hostile-32.meta +5 -0
- package/conformance/sheet/sheet-hostile-33.expected.json +18 -0
- package/conformance/sheet/sheet-hostile-33.html +6 -0
- package/conformance/sheet/sheet-hostile-33.meta +5 -0
- package/conformance/sheet/sheet-hostile-34.expected.json +24 -0
- package/conformance/sheet/sheet-hostile-34.html +8 -0
- package/conformance/sheet/sheet-hostile-34.meta +5 -0
- package/conformance/sheet/sheet-hostile-35.expected.json +24 -0
- package/conformance/sheet/sheet-hostile-35.html +8 -0
- package/conformance/sheet/sheet-hostile-35.meta +5 -0
- package/conformance/sheet/sheet-patch-append.after.html +27 -0
- package/conformance/sheet/sheet-patch-append.after.json +143 -0
- package/conformance/sheet/sheet-patch-append.data.json +15 -0
- package/conformance/sheet/sheet-patch-append.html +25 -0
- package/conformance/sheet/sheet-patch-append.meta +5 -0
- package/conformance/sheet/sheet-patch-append.write.json +7 -0
- package/conformance/sheet/sheet-patch-bad-range.data.json +11 -0
- package/conformance/sheet/sheet-patch-bad-range.error.json +6 -0
- package/conformance/sheet/sheet-patch-bad-range.html +25 -0
- package/conformance/sheet/sheet-patch-bad-range.meta +5 -0
- package/conformance/sheet/sheet-patch-bad-value.data.json +13 -0
- package/conformance/sheet/sheet-patch-bad-value.error.json +6 -0
- package/conformance/sheet/sheet-patch-bad-value.html +25 -0
- package/conformance/sheet/sheet-patch-bad-value.meta +5 -0
- package/conformance/sheet/sheet-patch-clean-tab-beside-edited.after.html +25 -0
- package/conformance/sheet/sheet-patch-clean-tab-beside-edited.after.json +129 -0
- package/conformance/sheet/sheet-patch-clean-tab-beside-edited.data.json +11 -0
- package/conformance/sheet/sheet-patch-clean-tab-beside-edited.html +25 -0
- package/conformance/sheet/sheet-patch-clean-tab-beside-edited.meta +5 -0
- package/conformance/sheet/sheet-patch-clean-tab-beside-edited.write.json +7 -0
- package/conformance/sheet/sheet-patch-covered-cell.data.json +10 -0
- package/conformance/sheet/sheet-patch-covered-cell.error.json +6 -0
- package/conformance/sheet/sheet-patch-covered-cell.html +10 -0
- package/conformance/sheet/sheet-patch-covered-cell.meta +5 -0
- package/conformance/sheet/sheet-patch-empty.data.json +1 -0
- package/conformance/sheet/sheet-patch-empty.error.json +6 -0
- package/conformance/sheet/sheet-patch-empty.html +25 -0
- package/conformance/sheet/sheet-patch-empty.meta +5 -0
- package/conformance/sheet/sheet-patch-fallback-route.after.html +24 -0
- package/conformance/sheet/sheet-patch-fallback-route.after.json +86 -0
- package/conformance/sheet/sheet-patch-fallback-route.data.json +10 -0
- package/conformance/sheet/sheet-patch-fallback-route.html +24 -0
- package/conformance/sheet/sheet-patch-fallback-route.meta +5 -0
- package/conformance/sheet/sheet-patch-fallback-route.write.json +7 -0
- package/conformance/sheet/sheet-patch-first-tab.after.html +25 -0
- package/conformance/sheet/sheet-patch-first-tab.after.json +129 -0
- package/conformance/sheet/sheet-patch-first-tab.data.json +10 -0
- package/conformance/sheet/sheet-patch-first-tab.html +25 -0
- package/conformance/sheet/sheet-patch-first-tab.meta +5 -0
- package/conformance/sheet/sheet-patch-first-tab.write.json +7 -0
- package/conformance/sheet/sheet-patch-formula.after.html +25 -0
- package/conformance/sheet/sheet-patch-formula.after.json +128 -0
- package/conformance/sheet/sheet-patch-formula.data.json +11 -0
- package/conformance/sheet/sheet-patch-formula.html +25 -0
- package/conformance/sheet/sheet-patch-formula.meta +5 -0
- package/conformance/sheet/sheet-patch-formula.write.json +7 -0
- package/conformance/sheet/sheet-patch-no-sheet-rule.data.json +10 -0
- package/conformance/sheet/sheet-patch-no-sheet-rule.error.json +6 -0
- package/conformance/sheet/sheet-patch-no-sheet-rule.html +18 -0
- package/conformance/sheet/sheet-patch-no-sheet-rule.meta +5 -0
- package/conformance/sheet/sheet-patch-no-values.data.json +6 -0
- package/conformance/sheet/sheet-patch-no-values.error.json +6 -0
- package/conformance/sheet/sheet-patch-no-values.html +25 -0
- package/conformance/sheet/sheet-patch-no-values.meta +5 -0
- package/conformance/sheet/sheet-patch-not-canonical.data.json +11 -0
- package/conformance/sheet/sheet-patch-not-canonical.error.json +6 -0
- package/conformance/sheet/sheet-patch-not-canonical.html +25 -0
- package/conformance/sheet/sheet-patch-not-canonical.meta +5 -0
- package/conformance/sheet/sheet-patch-outside-sheet.data.json +11 -0
- package/conformance/sheet/sheet-patch-outside-sheet.error.json +6 -0
- package/conformance/sheet/sheet-patch-outside-sheet.html +25 -0
- package/conformance/sheet/sheet-patch-outside-sheet.meta +5 -0
- package/conformance/sheet/sheet-patch-range.after.html +25 -0
- package/conformance/sheet/sheet-patch-range.after.json +126 -0
- package/conformance/sheet/sheet-patch-range.data.json +11 -0
- package/conformance/sheet/sheet-patch-range.html +25 -0
- package/conformance/sheet/sheet-patch-range.meta +5 -0
- package/conformance/sheet/sheet-patch-range.write.json +7 -0
- package/conformance/sheet/sheet-patch-two-tabs.after.html +25 -0
- package/conformance/sheet/sheet-patch-two-tabs.after.json +130 -0
- package/conformance/sheet/sheet-patch-two-tabs.data.json +20 -0
- package/conformance/sheet/sheet-patch-two-tabs.html +25 -0
- package/conformance/sheet/sheet-patch-two-tabs.meta +5 -0
- package/conformance/sheet/sheet-patch-two-tabs.write.json +7 -0
- package/conformance/sheet/sheet-patch-typed.after.html +25 -0
- package/conformance/sheet/sheet-patch-typed.after.json +121 -0
- package/conformance/sheet/sheet-patch-typed.data.json +13 -0
- package/conformance/sheet/sheet-patch-typed.html +25 -0
- package/conformance/sheet/sheet-patch-typed.meta +5 -0
- package/conformance/sheet/sheet-patch-typed.write.json +7 -0
- package/conformance/sheet/sheet-patch-unknown-sheet.data.json +11 -0
- package/conformance/sheet/sheet-patch-unknown-sheet.error.json +6 -0
- package/conformance/sheet/sheet-patch-unknown-sheet.html +25 -0
- package/conformance/sheet/sheet-patch-unknown-sheet.meta +5 -0
- package/conformance/sheet/sheet-read-bad-range.error.json +6 -0
- package/conformance/sheet/sheet-read-bad-range.html +25 -0
- package/conformance/sheet/sheet-read-bad-range.meta +6 -0
- package/conformance/sheet/sheet-read-bad-render.error.json +6 -0
- package/conformance/sheet/sheet-read-bad-render.html +25 -0
- package/conformance/sheet/sheet-read-bad-render.meta +6 -0
- package/conformance/sheet/sheet-read-digest.expected.json +91 -0
- package/conformance/sheet/sheet-read-digest.html +25 -0
- package/conformance/sheet/sheet-read-digest.meta +6 -0
- package/conformance/sheet/sheet-read-empty.expected.json +11 -0
- package/conformance/sheet/sheet-read-empty.html +6 -0
- package/conformance/sheet/sheet-read-empty.meta +5 -0
- package/conformance/sheet/sheet-read-escapes.expected.json +108 -0
- package/conformance/sheet/sheet-read-escapes.html +22 -0
- package/conformance/sheet/sheet-read-escapes.meta +5 -0
- package/conformance/sheet/sheet-read-formulas-formatted.expected.json +298 -0
- package/conformance/sheet/sheet-read-formulas-formatted.html +16 -0
- package/conformance/sheet/sheet-read-formulas-formatted.meta +5 -0
- package/conformance/sheet/sheet-read-grid-in-comment.expected.json +85 -0
- package/conformance/sheet/sheet-read-grid-in-comment.html +24 -0
- package/conformance/sheet/sheet-read-grid-in-comment.meta +5 -0
- package/conformance/sheet/sheet-read-grid-in-script.expected.json +85 -0
- package/conformance/sheet/sheet-read-grid-in-script.html +24 -0
- package/conformance/sheet/sheet-read-grid-in-script.meta +5 -0
- package/conformance/sheet/sheet-read-grid-in-template.expected.json +85 -0
- package/conformance/sheet/sheet-read-grid-in-template.html +24 -0
- package/conformance/sheet/sheet-read-grid-in-template.meta +5 -0
- package/conformance/sheet/sheet-read-grid-in-textarea.expected.json +85 -0
- package/conformance/sheet/sheet-read-grid-in-textarea.html +24 -0
- package/conformance/sheet/sheet-read-grid-in-textarea.meta +5 -0
- package/conformance/sheet/sheet-read-grid-outside-read-by-rule.expected.json +94 -0
- package/conformance/sheet/sheet-read-grid-outside-read-by-rule.html +24 -0
- package/conformance/sheet/sheet-read-grid-outside-read-by-rule.meta +5 -0
- package/conformance/sheet/sheet-read-grid-outside-sheet.expected.json +85 -0
- package/conformance/sheet/sheet-read-grid-outside-sheet.html +24 -0
- package/conformance/sheet/sheet-read-grid-outside-sheet.meta +5 -0
- package/conformance/sheet/sheet-read-hand-edited.expected.json +85 -0
- package/conformance/sheet/sheet-read-hand-edited.html +18 -0
- package/conformance/sheet/sheet-read-hand-edited.meta +5 -0
- package/conformance/sheet/sheet-read-index.expected.json +19 -0
- package/conformance/sheet/sheet-read-index.html +25 -0
- package/conformance/sheet/sheet-read-index.meta +6 -0
- package/conformance/sheet/sheet-read-merged.expected.json +59 -0
- package/conformance/sheet/sheet-read-merged.html +10 -0
- package/conformance/sheet/sheet-read-merged.meta +5 -0
- package/conformance/sheet/sheet-read-no-tag.error.json +5 -0
- package/conformance/sheet/sheet-read-no-tag.html +18 -0
- package/conformance/sheet/sheet-read-no-tag.meta +5 -0
- package/conformance/sheet/sheet-read-padded-name-index.expected.json +19 -0
- package/conformance/sheet/sheet-read-padded-name-index.html +25 -0
- package/conformance/sheet/sheet-read-padded-name-index.meta +6 -0
- package/conformance/sheet/sheet-read-padded-name-lookup.expected.json +83 -0
- package/conformance/sheet/sheet-read-padded-name-lookup.html +25 -0
- package/conformance/sheet/sheet-read-padded-name-lookup.meta +6 -0
- package/conformance/sheet/sheet-read-padded-name-trimmed-lookup.error.json +6 -0
- package/conformance/sheet/sheet-read-padded-name-trimmed-lookup.html +25 -0
- package/conformance/sheet/sheet-read-padded-name-trimmed-lookup.meta +6 -0
- package/conformance/sheet/sheet-read-padded-name.expected.json +128 -0
- package/conformance/sheet/sheet-read-padded-name.html +25 -0
- package/conformance/sheet/sheet-read-padded-name.meta +5 -0
- package/conformance/sheet/sheet-read-range-cells.expected.json +55 -0
- package/conformance/sheet/sheet-read-range-cells.html +25 -0
- package/conformance/sheet/sheet-read-range-cells.meta +6 -0
- package/conformance/sheet/sheet-read-range-first-tab.expected.json +12 -0
- package/conformance/sheet/sheet-read-range-first-tab.html +25 -0
- package/conformance/sheet/sheet-read-range-first-tab.meta +6 -0
- package/conformance/sheet/sheet-read-range-formulas.expected.json +24 -0
- package/conformance/sheet/sheet-read-range-formulas.html +25 -0
- package/conformance/sheet/sheet-read-range-formulas.meta +6 -0
- package/conformance/sheet/sheet-read-range-values.expected.json +24 -0
- package/conformance/sheet/sheet-read-range-values.html +25 -0
- package/conformance/sheet/sheet-read-range-values.meta +6 -0
- package/conformance/sheet/sheet-read-sheet-by-id.expected.json +46 -0
- package/conformance/sheet/sheet-read-sheet-by-id.html +25 -0
- package/conformance/sheet/sheet-read-sheet-by-id.meta +6 -0
- package/conformance/sheet/sheet-read-sheet-by-name.expected.json +46 -0
- package/conformance/sheet/sheet-read-sheet-by-name.html +25 -0
- package/conformance/sheet/sheet-read-sheet-by-name.meta +6 -0
- package/conformance/sheet/sheet-read-styled.expected.json +48 -0
- package/conformance/sheet/sheet-read-styled.html +10 -0
- package/conformance/sheet/sheet-read-styled.meta +5 -0
- package/conformance/sheet/sheet-read-tiny.expected.json +85 -0
- package/conformance/sheet/sheet-read-tiny.html +18 -0
- package/conformance/sheet/sheet-read-tiny.meta +5 -0
- package/conformance/sheet/sheet-read-two-tabs.expected.json +128 -0
- package/conformance/sheet/sheet-read-two-tabs.html +25 -0
- package/conformance/sheet/sheet-read-two-tabs.meta +5 -0
- package/conformance/sheet/sheet-read-unknown-sheet.error.json +6 -0
- package/conformance/sheet/sheet-read-unknown-sheet.html +25 -0
- package/conformance/sheet/sheet-read-unknown-sheet.meta +6 -0
- package/conformance/sheet/sheet-read-version-1-codec.error.json +5 -0
- package/conformance/sheet/sheet-read-version-1-codec.html +25 -0
- package/conformance/sheet/sheet-read-version-1-codec.meta +5 -0
- package/conformance/sheet/sheet-write-whole-refused.data.json +3 -0
- package/conformance/sheet/sheet-write-whole-refused.error.json +7 -0
- package/conformance/sheet/sheet-write-whole-refused.html +25 -0
- package/conformance/sheet/sheet-write-whole-refused.meta +5 -0
- package/conformance/sheet-guard-extraction.json +616 -0
- package/conformance/sheet-guard.json +32362 -0
- package/conformance/sheet-read-shapes.json +1 -0
- package/dist/hyper-html-api.engine.esm.js +1 -1
- package/dist/hyper-html-api.engine.min.js +1 -1
- package/dist/hyper-html-api.min.js +8 -8
- package/dist/hyper-html-api.upgrade.min.js +2 -2
- package/package.json +6 -3
- package/src/codecs/sheet.js +127 -0
- package/src/codecs/sheet.vendor.js +887 -0
- package/src/dom-api.js +20 -11
- package/src/engine/apply.js +17 -7
- package/src/engine/codecs.js +80 -0
- package/src/engine/errors.js +20 -1
- package/src/engine/extract.js +17 -3
- package/src/engine/index.js +9 -5
- package/src/engine/round-trip.js +24 -10
- package/src/engine/rule-syntax.js +29 -3
- package/src/engine/rules-tag.js +3 -2
- package/src/engine/write-plan.js +4 -3
- package/src/page.js +15 -5
- package/src/patch-document.js +122 -0
- package/src/read.js +163 -0
- package/src/site.js +164 -0
- package/src/upgrade/codec-carry.js +23 -0
- package/src/upgrade/extract-all.js +12 -3
- package/src/upgrade/migrate.js +31 -3
- package/src/upgrade/rules-tags.js +4 -4
- package/src/upgrade/shape-match.js +32 -13
- package/src/write.js +44 -5
|
@@ -0,0 +1,887 @@
|
|
|
1
|
+
// GENERATED — do not edit. Bundled from sapjs/src/grid/codec/ via sapjs
|
|
2
|
+
// `node scripts/propagate.js --only hyper-html-api`. Edit the sapjs source and re-run.
|
|
3
|
+
|
|
4
|
+
// src/grid/codec/value.js
|
|
5
|
+
var NUMBER = /^-?(0|[1-9][0-9]*)(\.[0-9]+)?$/;
|
|
6
|
+
var MAX_DIGITS = 15;
|
|
7
|
+
function significantDigits(text) {
|
|
8
|
+
return text.replace(/^-/, "").replace(".", "").replace(/^0+/, "").replace(/0+$/, "").length;
|
|
9
|
+
}
|
|
10
|
+
function typed(text, forceText = false) {
|
|
11
|
+
if (text === "") return null;
|
|
12
|
+
if (forceText) return text;
|
|
13
|
+
if (text === "TRUE") return true;
|
|
14
|
+
if (text === "FALSE") return false;
|
|
15
|
+
if (!NUMBER.test(text)) return text;
|
|
16
|
+
const digits = significantDigits(text);
|
|
17
|
+
if (digits > MAX_DIGITS) return text;
|
|
18
|
+
const number = Number(text);
|
|
19
|
+
if (!Number.isFinite(number) || number === 0 && digits > 0) return text;
|
|
20
|
+
return number === 0 ? 0 : number;
|
|
21
|
+
}
|
|
22
|
+
function shown(value) {
|
|
23
|
+
if (value === null || value === void 0) return "";
|
|
24
|
+
if (value === true) return "TRUE";
|
|
25
|
+
if (value === false) return "FALSE";
|
|
26
|
+
if (typeof value === "string") return value;
|
|
27
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
28
|
+
throw new TypeError(`grid codec: ${String(value)} is not a finite number, a boolean or text`);
|
|
29
|
+
}
|
|
30
|
+
if (value === 0) return "0";
|
|
31
|
+
const [mantissa, exponent] = value.toExponential(MAX_DIGITS - 1).split("e");
|
|
32
|
+
const sign = mantissa[0] === "-" ? "-" : "";
|
|
33
|
+
const digits = mantissa.replace("-", "").replace(".", "").replace(/0+$/, "");
|
|
34
|
+
const point = Number(exponent) + 1;
|
|
35
|
+
if (point <= 0) return `${sign}0.${"0".repeat(-point)}${digits}`;
|
|
36
|
+
const whole = digits.padEnd(point, "0").slice(0, point);
|
|
37
|
+
const fraction = digits.slice(point);
|
|
38
|
+
return fraction ? `${sign}${whole}.${fraction}` : `${sign}${whole}`;
|
|
39
|
+
}
|
|
40
|
+
function cellValue(cell) {
|
|
41
|
+
if (!cell || cell.hidden) return null;
|
|
42
|
+
return typed(cell.v ?? cell.text, cell.t === true);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// src/grid/codec/write.js
|
|
46
|
+
var FORBIDDEN = /[\r\0]/;
|
|
47
|
+
var MAX_COUNT = 9999999;
|
|
48
|
+
var EMPTY_CELL = "<td></td>";
|
|
49
|
+
function clean(value, what) {
|
|
50
|
+
const text = String(value);
|
|
51
|
+
if (FORBIDDEN.test(text)) throw new TypeError(`grid codec: ${what} holds a carriage return or NUL`);
|
|
52
|
+
return text;
|
|
53
|
+
}
|
|
54
|
+
var textEscape = (value) => clean(value, "cell text").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
55
|
+
var attrEscape = (value) => clean(value, "attribute value").replace(/&/g, "&").replace(/"/g, """);
|
|
56
|
+
var attr = (name, value) => ` ${name}="${attrEscape(value)}"`;
|
|
57
|
+
function count(value, min, what) {
|
|
58
|
+
if (!Number.isInteger(value) || value < min || value > MAX_COUNT) {
|
|
59
|
+
throw new RangeError(`grid codec: ${what} must be a whole number from ${min} to ${MAX_COUNT}`);
|
|
60
|
+
}
|
|
61
|
+
return value;
|
|
62
|
+
}
|
|
63
|
+
function cellHtml(cell) {
|
|
64
|
+
if (!cell) return EMPTY_CELL;
|
|
65
|
+
if (typeof cell.text !== "string") throw new TypeError("grid codec: cell text must be a string");
|
|
66
|
+
if (cell.hidden && cell.text !== "") throw new TypeError("grid codec: a hidden cell holds no text");
|
|
67
|
+
let attrs = "";
|
|
68
|
+
if (cell.n) attrs += " n";
|
|
69
|
+
if (cell.t) attrs += " t";
|
|
70
|
+
if (cell.f !== void 0) attrs += attr("f", cell.f);
|
|
71
|
+
if (cell.v !== void 0) attrs += attr("v", cell.v);
|
|
72
|
+
if (cell.fmt !== void 0) attrs += attr("fmt", cell.fmt);
|
|
73
|
+
if (cell.colspan !== void 0) attrs += ` colspan="${count(cell.colspan, 2, "colspan")}"`;
|
|
74
|
+
if (cell.rowspan !== void 0) attrs += ` rowspan="${count(cell.rowspan, 2, "rowspan")}"`;
|
|
75
|
+
if (cell.hidden) attrs += " hidden";
|
|
76
|
+
if (cell.style !== void 0) attrs += attr("style", cell.style);
|
|
77
|
+
return `<td${attrs}>${textEscape(cell.text)}</td>`;
|
|
78
|
+
}
|
|
79
|
+
function rowHtml(row) {
|
|
80
|
+
const cells = row.cells.map(cellHtml);
|
|
81
|
+
while (cells.length > 0 && cells[cells.length - 1] === EMPTY_CELL) cells.pop();
|
|
82
|
+
const style = row.style !== void 0 ? attr("style", row.style) : "";
|
|
83
|
+
return `<tr${attr("data-id", row.id)}${attr("data-pos", row.pos)}${style}>${cells.join("")}</tr>`;
|
|
84
|
+
}
|
|
85
|
+
function colHtml(col) {
|
|
86
|
+
let attrs = attr("data-id", col.id) + attr("data-pos", col.pos);
|
|
87
|
+
if (col.fmt !== void 0) attrs += attr("fmt", col.fmt);
|
|
88
|
+
if (col.width !== void 0) attrs += ` style="width:${count(col.width, 0, "width")}px"`;
|
|
89
|
+
return `<col${attrs}>`;
|
|
90
|
+
}
|
|
91
|
+
function tableHtml(sheet, { groupSize = 50 } = {}) {
|
|
92
|
+
count(groupSize, 1, "groupSize");
|
|
93
|
+
const rows = sheet.rows ?? [];
|
|
94
|
+
const firstData = rows.findIndex((row) => !row.frozen);
|
|
95
|
+
const frozen = firstData === -1 ? rows : rows.slice(0, firstData);
|
|
96
|
+
const data = firstData === -1 ? [] : rows.slice(firstData);
|
|
97
|
+
if (data.some((row) => row.frozen)) throw new TypeError("grid codec: frozen rows come before every other row");
|
|
98
|
+
let html = "<table grid";
|
|
99
|
+
if (sheet.freezeCols) html += ` freeze-cols="${count(sheet.freezeCols, 1, "freezeCols")}"`;
|
|
100
|
+
if (sheet.stale) html += " stale";
|
|
101
|
+
html += `><colgroup>${(sheet.cols ?? []).map(colHtml).join("")}</colgroup>
|
|
102
|
+
`;
|
|
103
|
+
if (frozen.length > 0) html += `<thead>
|
|
104
|
+
${frozen.map(rowHtml).join("\n")}
|
|
105
|
+
</thead>`;
|
|
106
|
+
const groups = Math.max(1, Math.ceil(data.length / groupSize));
|
|
107
|
+
for (let g = 0; g < groups; g++) {
|
|
108
|
+
const group = data.slice(g * groupSize, (g + 1) * groupSize);
|
|
109
|
+
html += "<tbody>\n";
|
|
110
|
+
if (group.length > 0) html += `${group.map(rowHtml).join("\n")}
|
|
111
|
+
`;
|
|
112
|
+
html += "</tbody>";
|
|
113
|
+
}
|
|
114
|
+
return `${html}</table>`;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// src/grid/codec/scan.js
|
|
118
|
+
var CodecMiss = class extends Error {
|
|
119
|
+
constructor(message) {
|
|
120
|
+
super(message);
|
|
121
|
+
this.name = "CodecMiss";
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
var MAX_COUNT_DIGITS = 7;
|
|
125
|
+
var NO_SINK = {};
|
|
126
|
+
var ATTR_REFS = /&|"|[&\r\0]/g;
|
|
127
|
+
var TEXT_REFS = /&|<|>|[&>\r\0]/g;
|
|
128
|
+
var ATTR_DECODED = { "&": "&", """: '"' };
|
|
129
|
+
var TEXT_DECODED = { "&": "&", "<": "<", ">": ">" };
|
|
130
|
+
var cursor = 0;
|
|
131
|
+
function miss(why, at) {
|
|
132
|
+
throw new CodecMiss(`grid codec: ${why} at ${at}`);
|
|
133
|
+
}
|
|
134
|
+
function decode(raw, refs, decoded, at) {
|
|
135
|
+
return raw.replace(refs, (match) => decoded[match] ?? miss(`character ${JSON.stringify(match)} outside the grammar`, at));
|
|
136
|
+
}
|
|
137
|
+
function expect(src, i, literal) {
|
|
138
|
+
if (!src.startsWith(literal, i)) miss(`expected ${JSON.stringify(literal)}`, i);
|
|
139
|
+
return i + literal.length;
|
|
140
|
+
}
|
|
141
|
+
function skipSpace(src, i) {
|
|
142
|
+
for (; ; ) {
|
|
143
|
+
const c = src.charCodeAt(i);
|
|
144
|
+
if (c !== 32 && c !== 10 && c !== 9) return i;
|
|
145
|
+
i++;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
function flag(src, i, literal) {
|
|
149
|
+
if (!src.startsWith(literal, i)) return false;
|
|
150
|
+
const next = src.charCodeAt(i + literal.length);
|
|
151
|
+
return next === 32 || next === 62;
|
|
152
|
+
}
|
|
153
|
+
function readAval(src, i) {
|
|
154
|
+
const end = src.indexOf('"', i);
|
|
155
|
+
if (end === -1) miss("open attribute value", i);
|
|
156
|
+
cursor = end + 1;
|
|
157
|
+
return decode(src.slice(i, end), ATTR_REFS, ATTR_DECODED, i);
|
|
158
|
+
}
|
|
159
|
+
function readCount(src, i, min) {
|
|
160
|
+
let end = i;
|
|
161
|
+
while (end - i <= MAX_COUNT_DIGITS) {
|
|
162
|
+
const c = src.charCodeAt(end);
|
|
163
|
+
if (c < 48 || c > 57) break;
|
|
164
|
+
end++;
|
|
165
|
+
}
|
|
166
|
+
const digits = src.slice(i, end);
|
|
167
|
+
if (digits.length === 0 || digits.length > MAX_COUNT_DIGITS) miss("bad count", i);
|
|
168
|
+
if (digits.length > 1 && digits[0] === "0") miss("count with a leading zero", i);
|
|
169
|
+
const value = Number(digits);
|
|
170
|
+
if (value < min) miss(`count below ${min}`, i);
|
|
171
|
+
cursor = end;
|
|
172
|
+
return value;
|
|
173
|
+
}
|
|
174
|
+
function readCol(src, i) {
|
|
175
|
+
i = expect(src, i, '<col data-id="');
|
|
176
|
+
const col = { id: readAval(src, i) };
|
|
177
|
+
i = expect(src, cursor, ' data-pos="');
|
|
178
|
+
col.pos = readAval(src, i);
|
|
179
|
+
i = cursor;
|
|
180
|
+
if (src.startsWith(' fmt="', i)) {
|
|
181
|
+
col.fmt = readAval(src, i + 6);
|
|
182
|
+
i = cursor;
|
|
183
|
+
}
|
|
184
|
+
if (src.startsWith(' style="width:', i)) {
|
|
185
|
+
col.width = readCount(src, i + 14, 0);
|
|
186
|
+
i = expect(src, cursor, 'px"');
|
|
187
|
+
}
|
|
188
|
+
cursor = expect(src, i, ">");
|
|
189
|
+
return col;
|
|
190
|
+
}
|
|
191
|
+
function readCell(src, i) {
|
|
192
|
+
i = expect(src, i, "<td");
|
|
193
|
+
const cell = {};
|
|
194
|
+
let bare = true;
|
|
195
|
+
if (flag(src, i, " n")) {
|
|
196
|
+
cell.n = true;
|
|
197
|
+
i += 2;
|
|
198
|
+
bare = false;
|
|
199
|
+
}
|
|
200
|
+
if (flag(src, i, " t")) {
|
|
201
|
+
cell.t = true;
|
|
202
|
+
i += 2;
|
|
203
|
+
bare = false;
|
|
204
|
+
}
|
|
205
|
+
if (src.startsWith(' f="', i)) {
|
|
206
|
+
cell.f = readAval(src, i + 4);
|
|
207
|
+
i = cursor;
|
|
208
|
+
bare = false;
|
|
209
|
+
}
|
|
210
|
+
if (src.startsWith(' v="', i)) {
|
|
211
|
+
cell.v = readAval(src, i + 4);
|
|
212
|
+
i = cursor;
|
|
213
|
+
bare = false;
|
|
214
|
+
}
|
|
215
|
+
if (src.startsWith(' fmt="', i)) {
|
|
216
|
+
cell.fmt = readAval(src, i + 6);
|
|
217
|
+
i = cursor;
|
|
218
|
+
bare = false;
|
|
219
|
+
}
|
|
220
|
+
if (src.startsWith(' colspan="', i)) {
|
|
221
|
+
cell.colspan = readCount(src, i + 10, 2);
|
|
222
|
+
i = expect(src, cursor, '"');
|
|
223
|
+
bare = false;
|
|
224
|
+
}
|
|
225
|
+
if (src.startsWith(' rowspan="', i)) {
|
|
226
|
+
cell.rowspan = readCount(src, i + 10, 2);
|
|
227
|
+
i = expect(src, cursor, '"');
|
|
228
|
+
bare = false;
|
|
229
|
+
}
|
|
230
|
+
if (flag(src, i, " hidden")) {
|
|
231
|
+
cell.hidden = true;
|
|
232
|
+
i += 7;
|
|
233
|
+
bare = false;
|
|
234
|
+
}
|
|
235
|
+
if (src.startsWith(' style="', i)) {
|
|
236
|
+
cell.style = readAval(src, i + 8);
|
|
237
|
+
i = cursor;
|
|
238
|
+
bare = false;
|
|
239
|
+
}
|
|
240
|
+
i = expect(src, i, ">");
|
|
241
|
+
const lt = src.indexOf("<", i);
|
|
242
|
+
if (lt === -1) miss("open cell", i);
|
|
243
|
+
const text = decode(src.slice(i, lt), TEXT_REFS, TEXT_DECODED, i);
|
|
244
|
+
cursor = expect(src, lt, "</td>");
|
|
245
|
+
if (cell.hidden && text !== "") miss("a hidden cell with text", i);
|
|
246
|
+
if (bare && text === "") return null;
|
|
247
|
+
return Object.assign({ text }, cell);
|
|
248
|
+
}
|
|
249
|
+
function readRow(src, i, frozen) {
|
|
250
|
+
i = expect(src, i, '<tr data-id="');
|
|
251
|
+
const row = { id: readAval(src, i) };
|
|
252
|
+
i = expect(src, cursor, ' data-pos="');
|
|
253
|
+
row.pos = readAval(src, i);
|
|
254
|
+
i = cursor;
|
|
255
|
+
if (frozen) row.frozen = true;
|
|
256
|
+
if (src.startsWith(' style="', i)) {
|
|
257
|
+
row.style = readAval(src, i + 8);
|
|
258
|
+
i = cursor;
|
|
259
|
+
}
|
|
260
|
+
i = expect(src, i, ">");
|
|
261
|
+
row.cells = [];
|
|
262
|
+
while (!src.startsWith("</tr>", i)) {
|
|
263
|
+
row.cells.push(readCell(src, i));
|
|
264
|
+
i = cursor;
|
|
265
|
+
}
|
|
266
|
+
if (row.cells.length > 0 && row.cells[row.cells.length - 1] === null) miss("a row that ends with an empty cell", i);
|
|
267
|
+
cursor = i + 5;
|
|
268
|
+
return row;
|
|
269
|
+
}
|
|
270
|
+
function readGroup(src, i, frozen, sink, index) {
|
|
271
|
+
const start = i;
|
|
272
|
+
const close = frozen ? "</thead>" : "</tbody>";
|
|
273
|
+
i = expect(src, i, frozen ? "<thead>" : "<tbody>");
|
|
274
|
+
for (; ; ) {
|
|
275
|
+
i = skipSpace(src, i);
|
|
276
|
+
if (src.startsWith(close, i)) break;
|
|
277
|
+
const rowStart = i;
|
|
278
|
+
const row = readRow(src, i, frozen);
|
|
279
|
+
i = cursor;
|
|
280
|
+
sink.row?.(row, rowStart, i, index++);
|
|
281
|
+
}
|
|
282
|
+
cursor = i + close.length;
|
|
283
|
+
sink.group?.(start, cursor, frozen);
|
|
284
|
+
return index;
|
|
285
|
+
}
|
|
286
|
+
function scanGrid(src, at, sink = NO_SINK) {
|
|
287
|
+
let i = expect(src, at, "<table grid");
|
|
288
|
+
const table = {};
|
|
289
|
+
if (src.startsWith(' freeze-cols="', i)) {
|
|
290
|
+
table.freezeCols = readCount(src, i + 14, 1);
|
|
291
|
+
i = expect(src, cursor, '"');
|
|
292
|
+
}
|
|
293
|
+
if (flag(src, i, " stale")) {
|
|
294
|
+
table.stale = true;
|
|
295
|
+
i += 6;
|
|
296
|
+
}
|
|
297
|
+
i = expect(src, i, ">");
|
|
298
|
+
sink.table?.(table);
|
|
299
|
+
i = skipSpace(src, i);
|
|
300
|
+
if (src.startsWith("<colgroup>", i)) {
|
|
301
|
+
i += 10;
|
|
302
|
+
for (; ; ) {
|
|
303
|
+
i = skipSpace(src, i);
|
|
304
|
+
if (src.startsWith("</colgroup>", i)) break;
|
|
305
|
+
const col = readCol(src, i);
|
|
306
|
+
i = cursor;
|
|
307
|
+
sink.col?.(col);
|
|
308
|
+
}
|
|
309
|
+
i = skipSpace(src, i + 11);
|
|
310
|
+
}
|
|
311
|
+
let index = 0;
|
|
312
|
+
if (src.startsWith("<thead>", i)) {
|
|
313
|
+
index = readGroup(src, i, true, sink, index);
|
|
314
|
+
i = skipSpace(src, cursor);
|
|
315
|
+
}
|
|
316
|
+
while (src.startsWith("<tbody>", i)) {
|
|
317
|
+
index = readGroup(src, i, false, sink, index);
|
|
318
|
+
i = skipSpace(src, cursor);
|
|
319
|
+
}
|
|
320
|
+
return expect(src, i, "</table>");
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// src/grid/codec/cut.js
|
|
324
|
+
var MARKER = /^[A-Za-z0-9_-]+$/;
|
|
325
|
+
var holeHtml = (marker, n) => `<table grid data-hole="${marker}-${n}"></table>`;
|
|
326
|
+
function holeMarker(src) {
|
|
327
|
+
for (; ; ) {
|
|
328
|
+
const bytes = globalThis.crypto.getRandomValues(new Uint8Array(12));
|
|
329
|
+
const marker = `h${Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("")}`;
|
|
330
|
+
if (!src.includes(marker)) return marker;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
function checkMarker(marker, src) {
|
|
334
|
+
if (!MARKER.test(marker)) throw new Error("grid codec: a hole marker is letters, digits, - and _ only");
|
|
335
|
+
if (src.includes(marker)) throw new Error("grid codec: the hole marker occurs in the document");
|
|
336
|
+
}
|
|
337
|
+
function cutGrids(src, marker) {
|
|
338
|
+
checkMarker(marker, src);
|
|
339
|
+
const regions = [];
|
|
340
|
+
const parts = [];
|
|
341
|
+
let from = 0;
|
|
342
|
+
let at = 0;
|
|
343
|
+
for (; ; ) {
|
|
344
|
+
const start = src.indexOf("<table grid", at);
|
|
345
|
+
if (start === -1) break;
|
|
346
|
+
let end;
|
|
347
|
+
try {
|
|
348
|
+
end = scanGrid(src, start);
|
|
349
|
+
} catch (error) {
|
|
350
|
+
if (!(error instanceof CodecMiss)) throw error;
|
|
351
|
+
at = start + 1;
|
|
352
|
+
continue;
|
|
353
|
+
}
|
|
354
|
+
parts.push(src.slice(from, start), holeHtml(marker, regions.length));
|
|
355
|
+
regions.push({ start, end });
|
|
356
|
+
from = end;
|
|
357
|
+
at = end;
|
|
358
|
+
}
|
|
359
|
+
parts.push(src.slice(from));
|
|
360
|
+
return { rest: parts.join(""), regions };
|
|
361
|
+
}
|
|
362
|
+
function joinGrids(rest, marker, src, regions, bytes = []) {
|
|
363
|
+
const parts = [];
|
|
364
|
+
let from = 0;
|
|
365
|
+
regions.forEach((region, n) => {
|
|
366
|
+
const hole = holeHtml(marker, n);
|
|
367
|
+
const at = rest.indexOf(hole, from);
|
|
368
|
+
if (at === -1) throw new Error(`grid codec: hole ${n} is missing`);
|
|
369
|
+
parts.push(rest.slice(from, at), bytes[n] ?? src.slice(region.start, region.end));
|
|
370
|
+
from = at + hole.length;
|
|
371
|
+
});
|
|
372
|
+
parts.push(rest.slice(from));
|
|
373
|
+
return parts.join("");
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// src/grid/codec/read.js
|
|
377
|
+
var RENDERS = ["values", "formulas", "cells"];
|
|
378
|
+
var A1 = /^([A-Z]{1,3})([1-9][0-9]{0,6})$/;
|
|
379
|
+
var MAX_COLUMN = 16384;
|
|
380
|
+
var QueryRefused = class extends Error {
|
|
381
|
+
constructor(code, message) {
|
|
382
|
+
super(message);
|
|
383
|
+
this.name = "QueryRefused";
|
|
384
|
+
this.code = code;
|
|
385
|
+
}
|
|
386
|
+
};
|
|
387
|
+
function gridModel(src, at) {
|
|
388
|
+
const sheet = { cols: [], rows: [] };
|
|
389
|
+
scanGrid(src, at, {
|
|
390
|
+
table: (table) => Object.assign(sheet, table),
|
|
391
|
+
col: (col) => sheet.cols.push(col),
|
|
392
|
+
row: (row) => sheet.rows.push(row)
|
|
393
|
+
});
|
|
394
|
+
return sheet;
|
|
395
|
+
}
|
|
396
|
+
function cellJson(cell) {
|
|
397
|
+
if (!cell || cell.hidden) return null;
|
|
398
|
+
const v = cellValue(cell);
|
|
399
|
+
const plain = cell.f === void 0 && cell.v === void 0 && cell.fmt === void 0 && cell.style === void 0 && cell.colspan === void 0 && cell.rowspan === void 0;
|
|
400
|
+
if (plain) return v;
|
|
401
|
+
const out = {};
|
|
402
|
+
if (cell.f !== void 0) out.f = cell.f;
|
|
403
|
+
out.v = v;
|
|
404
|
+
if (cell.text !== shown(v)) out.text = cell.text;
|
|
405
|
+
if (cell.fmt !== void 0) out.fmt = cell.fmt;
|
|
406
|
+
if (cell.style !== void 0) out.style = cell.style;
|
|
407
|
+
if (cell.colspan !== void 0) out.colspan = cell.colspan;
|
|
408
|
+
if (cell.rowspan !== void 0) out.rowspan = cell.rowspan;
|
|
409
|
+
return out;
|
|
410
|
+
}
|
|
411
|
+
function rowJson(row) {
|
|
412
|
+
const cells = row.cells.map(cellJson);
|
|
413
|
+
while (cells.length > 0 && cells[cells.length - 1] === null) cells.pop();
|
|
414
|
+
return { id: row.id, cells };
|
|
415
|
+
}
|
|
416
|
+
function tabJson(sheet) {
|
|
417
|
+
const tab = { cols: sheet.cols.map((col) => col.id), rows: sheet.rows.map(rowJson) };
|
|
418
|
+
if (sheet.stale) tab.stale = true;
|
|
419
|
+
return tab;
|
|
420
|
+
}
|
|
421
|
+
function tabIndex(sheet) {
|
|
422
|
+
return {
|
|
423
|
+
rows: sheet.rows.length,
|
|
424
|
+
cols: sheet.cols.length,
|
|
425
|
+
frozenRows: sheet.rows.filter((row) => row.frozen).length
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
function columnNumber(letters) {
|
|
429
|
+
let n = 0;
|
|
430
|
+
for (const letter of letters) n = n * 26 + (letter.charCodeAt(0) - 64);
|
|
431
|
+
return n;
|
|
432
|
+
}
|
|
433
|
+
function parseCell(text, range) {
|
|
434
|
+
const match = A1.exec(text);
|
|
435
|
+
const column = match ? columnNumber(match[1]) : 0;
|
|
436
|
+
if (!match || column > MAX_COLUMN) {
|
|
437
|
+
throw new QueryRefused("bad_range", `range ${JSON.stringify(range)} is not an A1 cell or rectangle such as B2 or A1:C3`);
|
|
438
|
+
}
|
|
439
|
+
return { row: Number(match[2]) - 1, col: column - 1 };
|
|
440
|
+
}
|
|
441
|
+
function parseRange(range) {
|
|
442
|
+
if (typeof range !== "string") throw new QueryRefused("bad_range", "range must be text such as A1:C3");
|
|
443
|
+
const parts = range.split(":");
|
|
444
|
+
if (parts.length > 2) throw new QueryRefused("bad_range", `range ${JSON.stringify(range)} has more than one colon`);
|
|
445
|
+
const start = parseCell(parts[0], range);
|
|
446
|
+
const end = parts.length === 2 ? parseCell(parts[1], range) : start;
|
|
447
|
+
if (end.row < start.row || end.col < start.col) {
|
|
448
|
+
throw new QueryRefused("bad_range", `range ${JSON.stringify(range)} is reversed: write the top left cell first`);
|
|
449
|
+
}
|
|
450
|
+
return { r0: start.row, c0: start.col, r1: end.row, c1: end.col };
|
|
451
|
+
}
|
|
452
|
+
function readRange(sheet, range, render = "values") {
|
|
453
|
+
if (!RENDERS.includes(render)) {
|
|
454
|
+
throw new QueryRefused("bad_render", `render must be one of ${RENDERS.join(", ")}`);
|
|
455
|
+
}
|
|
456
|
+
const { r0, c0, r1, c1 } = parseRange(range);
|
|
457
|
+
const lastRow = Math.min(r1, sheet.rows.length - 1);
|
|
458
|
+
const lastCol = Math.min(c1, sheet.cols.length - 1);
|
|
459
|
+
const rows = sheet.rows.slice(r0, lastRow + 1);
|
|
460
|
+
const width = Math.max(0, lastCol - c0 + 1);
|
|
461
|
+
if (render === "cells") {
|
|
462
|
+
return {
|
|
463
|
+
cols: sheet.cols.slice(c0, lastCol + 1).map((col) => col.id),
|
|
464
|
+
rows: rows.map((row) => rowJson({ id: row.id, cells: row.cells.slice(c0, c0 + width) }))
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
const pick = render === "formulas" ? (cell) => cell && !cell.hidden && cell.f !== void 0 ? cell.f : cellValue(cell) : cellValue;
|
|
468
|
+
return {
|
|
469
|
+
values: rows.map((row) => Array.from({ length: width }, (_, i) => pick(row.cells[c0 + i] ?? null)))
|
|
470
|
+
};
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
// src/grid/codec/canonical.js
|
|
474
|
+
var MAX_COUNT2 = 9999999;
|
|
475
|
+
var domAdapter = {
|
|
476
|
+
name: (node) => node.localName,
|
|
477
|
+
attr: (node, name) => node.getAttribute(name),
|
|
478
|
+
children: (node) => Array.from(node.children),
|
|
479
|
+
text: (node) => node.textContent
|
|
480
|
+
};
|
|
481
|
+
var has = (adapter, node, name) => adapter.attr(node, name) !== null;
|
|
482
|
+
var cleanText = (text) => text.replace(/\r\n?/g, "\n").replace(/\0/g, "");
|
|
483
|
+
function count2(value, min) {
|
|
484
|
+
if (value === null || !/^[0-9]{1,7}$/.test(value.trim())) return void 0;
|
|
485
|
+
const n = Number(value.trim());
|
|
486
|
+
return n >= min && n <= MAX_COUNT2 ? n : void 0;
|
|
487
|
+
}
|
|
488
|
+
function cellModel(adapter, td) {
|
|
489
|
+
const cell = { text: cleanText(adapter.text(td)) };
|
|
490
|
+
let bare = true;
|
|
491
|
+
const set = (key, value) => {
|
|
492
|
+
if (value === void 0 || value === null || value === false) return;
|
|
493
|
+
cell[key] = value;
|
|
494
|
+
bare = false;
|
|
495
|
+
};
|
|
496
|
+
set("n", has(adapter, td, "n"));
|
|
497
|
+
set("t", has(adapter, td, "t"));
|
|
498
|
+
for (const key of ["f", "v", "fmt"]) {
|
|
499
|
+
const value = adapter.attr(td, key);
|
|
500
|
+
set(key, value === null ? void 0 : cleanText(value));
|
|
501
|
+
}
|
|
502
|
+
set("colspan", count2(adapter.attr(td, "colspan"), 2));
|
|
503
|
+
set("rowspan", count2(adapter.attr(td, "rowspan"), 2));
|
|
504
|
+
if (has(adapter, td, "hidden")) {
|
|
505
|
+
set("hidden", true);
|
|
506
|
+
cell.text = "";
|
|
507
|
+
}
|
|
508
|
+
const style = adapter.attr(td, "style");
|
|
509
|
+
set("style", style === null ? void 0 : cleanText(style));
|
|
510
|
+
return bare && cell.text === "" ? null : cell;
|
|
511
|
+
}
|
|
512
|
+
function rowModel(adapter, tr, frozen) {
|
|
513
|
+
const row = { id: cleanText(adapter.attr(tr, "data-id") ?? ""), pos: cleanText(adapter.attr(tr, "data-pos") ?? "") };
|
|
514
|
+
if (frozen) row.frozen = true;
|
|
515
|
+
const style = adapter.attr(tr, "style");
|
|
516
|
+
if (style !== null) row.style = cleanText(style);
|
|
517
|
+
row.cells = adapter.children(tr).filter((node) => adapter.name(node) === "td" || adapter.name(node) === "th").map((td) => cellModel(adapter, td));
|
|
518
|
+
return row;
|
|
519
|
+
}
|
|
520
|
+
function colModel(adapter, node) {
|
|
521
|
+
const col = { id: cleanText(adapter.attr(node, "data-id") ?? ""), pos: cleanText(adapter.attr(node, "data-pos") ?? "") };
|
|
522
|
+
const fmt = adapter.attr(node, "fmt");
|
|
523
|
+
if (fmt !== null) col.fmt = cleanText(fmt);
|
|
524
|
+
const width = /width:\s*([0-9]{1,7})px/.exec(adapter.attr(node, "style") ?? "");
|
|
525
|
+
if (width) col.width = Number(width[1]);
|
|
526
|
+
return col;
|
|
527
|
+
}
|
|
528
|
+
function treeModel(adapter, table) {
|
|
529
|
+
const sheet = { cols: [], rows: [] };
|
|
530
|
+
const freezeCols = count2(adapter.attr(table, "freeze-cols"), 1);
|
|
531
|
+
if (freezeCols !== void 0) sheet.freezeCols = freezeCols;
|
|
532
|
+
if (has(adapter, table, "stale")) sheet.stale = true;
|
|
533
|
+
const frozen = [];
|
|
534
|
+
const data = [];
|
|
535
|
+
for (const part of adapter.children(table)) {
|
|
536
|
+
const name = adapter.name(part);
|
|
537
|
+
if (name === "colgroup") {
|
|
538
|
+
for (const col of adapter.children(part)) if (adapter.name(col) === "col") sheet.cols.push(colModel(adapter, col));
|
|
539
|
+
} else if (name === "col") {
|
|
540
|
+
sheet.cols.push(colModel(adapter, part));
|
|
541
|
+
} else if (name === "thead" || name === "tbody" || name === "tfoot") {
|
|
542
|
+
const into = name === "thead" ? frozen : data;
|
|
543
|
+
for (const tr of adapter.children(part)) if (adapter.name(tr) === "tr") into.push(rowModel(adapter, tr, name === "thead"));
|
|
544
|
+
} else if (name === "tr") {
|
|
545
|
+
data.push(rowModel(adapter, part, false));
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
sheet.rows = [...frozen, ...data];
|
|
549
|
+
return sheet;
|
|
550
|
+
}
|
|
551
|
+
function canonicalGrid(adapter, table, options) {
|
|
552
|
+
return tableHtml(treeModel(adapter, table), options);
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
// src/grid/codec/styles.js
|
|
556
|
+
var STYLE_PROPERTIES = [
|
|
557
|
+
"font-weight",
|
|
558
|
+
"font-style",
|
|
559
|
+
"text-decoration",
|
|
560
|
+
"color",
|
|
561
|
+
"background",
|
|
562
|
+
"background-color",
|
|
563
|
+
"text-align",
|
|
564
|
+
"white-space",
|
|
565
|
+
"border",
|
|
566
|
+
"border-top",
|
|
567
|
+
"border-right",
|
|
568
|
+
"border-bottom",
|
|
569
|
+
"border-left"
|
|
570
|
+
];
|
|
571
|
+
var ALLOWED = new Set(STYLE_PROPERTIES);
|
|
572
|
+
var VALUE = /^(?:[a-zA-Z0-9#%.,+ -]|(?:rgb|rgba|hsl|hsla)\([0-9.,%+ -]*\))+$/;
|
|
573
|
+
function filterStyle(css) {
|
|
574
|
+
if (typeof css !== "string") return void 0;
|
|
575
|
+
const kept = /* @__PURE__ */ new Map();
|
|
576
|
+
for (const declaration of css.split(";")) {
|
|
577
|
+
const colon = declaration.indexOf(":");
|
|
578
|
+
if (colon === -1) continue;
|
|
579
|
+
const property = declaration.slice(0, colon).trim().toLowerCase();
|
|
580
|
+
const value = declaration.slice(colon + 1).trim().replace(/\s+/g, " ");
|
|
581
|
+
if (!ALLOWED.has(property) || value === "" || !VALUE.test(value)) continue;
|
|
582
|
+
kept.set(property, value);
|
|
583
|
+
}
|
|
584
|
+
if (kept.size === 0) return void 0;
|
|
585
|
+
return Array.from(kept, ([property, value]) => `${property}:${value}`).join(";");
|
|
586
|
+
}
|
|
587
|
+
var isCanonicalStyle = (css) => typeof css === "string" && filterStyle(css) === css;
|
|
588
|
+
|
|
589
|
+
// src/grid/codec/order-keys.js
|
|
590
|
+
var DIGITS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
|
591
|
+
var VALID_KEY = /^[0-9A-Za-z]*[1-9A-Za-z]$/;
|
|
592
|
+
var isKey = (key) => typeof key === "string" && VALID_KEY.test(key);
|
|
593
|
+
function midpoint(a, b) {
|
|
594
|
+
if (b !== null) {
|
|
595
|
+
let n = 0;
|
|
596
|
+
while ((a[n] || "0") === b[n]) n++;
|
|
597
|
+
if (n > 0) return b.slice(0, n) + midpoint(a.slice(n), b.slice(n));
|
|
598
|
+
}
|
|
599
|
+
const da = a ? DIGITS.indexOf(a[0]) : 0;
|
|
600
|
+
const db = b !== null ? DIGITS.indexOf(b[0]) : DIGITS.length;
|
|
601
|
+
if (db - da > 1) return DIGITS[Math.round((da + db) / 2)];
|
|
602
|
+
if (b !== null && b.length > 1) return b.slice(0, 1);
|
|
603
|
+
return DIGITS[da] + midpoint(a.slice(1), null);
|
|
604
|
+
}
|
|
605
|
+
function keyBetween(a = null, b = null) {
|
|
606
|
+
if (a !== null && !isKey(a)) throw new TypeError(`grid codec: invalid order key ${a}`);
|
|
607
|
+
if (b !== null && !isKey(b)) throw new TypeError(`grid codec: invalid order key ${b}`);
|
|
608
|
+
if (a !== null && b !== null && a >= b) throw new RangeError(`grid codec: order key ${a} is not before ${b}`);
|
|
609
|
+
return midpoint(a ?? "", b);
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
// src/grid/codec/patch.js
|
|
613
|
+
var GROUP_SIZE = 50;
|
|
614
|
+
function randomId() {
|
|
615
|
+
const bytes = globalThis.crypto.getRandomValues(new Uint8Array(6));
|
|
616
|
+
return `r${Array.from(bytes, (b) => (b % 36).toString(36)).join("")}`;
|
|
617
|
+
}
|
|
618
|
+
function content(value) {
|
|
619
|
+
if (value === null) return {};
|
|
620
|
+
if (typeof value === "number") {
|
|
621
|
+
if (!Number.isFinite(value)) throw new QueryRefused("bad_value", `${value} is not a finite number`);
|
|
622
|
+
return { text: shown(value), n: true };
|
|
623
|
+
}
|
|
624
|
+
if (typeof value === "boolean") return { text: shown(value) };
|
|
625
|
+
if (typeof value !== "string") throw new QueryRefused("bad_value", "a value is a number, true, false, text or null");
|
|
626
|
+
if (value.includes("\0")) throw new QueryRefused("bad_value", "text holds a NUL character");
|
|
627
|
+
const text = value.replace(/\r\n?/g, "\n");
|
|
628
|
+
if (text.startsWith("=")) return { text: "", f: text };
|
|
629
|
+
return typed(text) === text || text === "" ? { text } : { text, t: true };
|
|
630
|
+
}
|
|
631
|
+
function setCell(old, value) {
|
|
632
|
+
const cell = { text: "", ...content(value) };
|
|
633
|
+
for (const key of ["fmt", "colspan", "rowspan", "style"]) if (old && old[key] !== void 0) cell[key] = old[key];
|
|
634
|
+
return Object.keys(cell).length === 1 && cell.text === "" ? null : cell;
|
|
635
|
+
}
|
|
636
|
+
function checkGrid(values, what) {
|
|
637
|
+
if (!Array.isArray(values) || values.length === 0 || !values.every((row) => Array.isArray(row))) {
|
|
638
|
+
throw new QueryRefused("bad_patch", `${what} is a non-empty array of rows, each an array of values`);
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
function readGrid(src) {
|
|
642
|
+
const grid = { cols: [], rows: [], groups: [], startEnd: 0, table: null };
|
|
643
|
+
grid.end = scanGrid(src, 0, {
|
|
644
|
+
table: (table) => {
|
|
645
|
+
grid.table = table;
|
|
646
|
+
},
|
|
647
|
+
col: (col) => grid.cols.push(col),
|
|
648
|
+
row: (row2, start, end) => grid.rows.push({ row: row2, start, end }),
|
|
649
|
+
group: (start, end, frozen) => grid.groups.push({ start, end, frozen, rows: 0 })
|
|
650
|
+
});
|
|
651
|
+
grid.startEnd = src.indexOf(">") + 1;
|
|
652
|
+
let row = 0;
|
|
653
|
+
for (const group of grid.groups) {
|
|
654
|
+
while (row < grid.rows.length && grid.rows[row].start < group.end) {
|
|
655
|
+
group.rows++;
|
|
656
|
+
row++;
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
return grid;
|
|
660
|
+
}
|
|
661
|
+
function applyRange(grid, op, edited) {
|
|
662
|
+
checkGrid(op.values, "values");
|
|
663
|
+
const { r0, c0, r1, c1 } = parseRange(op.range);
|
|
664
|
+
const height = op.values.length;
|
|
665
|
+
const width = Math.max(...op.values.map((row) => row.length));
|
|
666
|
+
const single = r0 === r1 && c0 === c1;
|
|
667
|
+
if (!single && (height !== r1 - r0 + 1 || op.values.some((row) => row.length !== c1 - c0 + 1))) {
|
|
668
|
+
throw new QueryRefused("bad_patch", `values must be ${r1 - r0 + 1} rows of ${c1 - c0 + 1} for range ${op.range}`);
|
|
669
|
+
}
|
|
670
|
+
if (r0 + height > grid.rows.length || c0 + width > grid.cols.length) {
|
|
671
|
+
throw new QueryRefused("outside_sheet", `range ${op.range} reaches past the sheet's rows or columns; append new rows instead`);
|
|
672
|
+
}
|
|
673
|
+
let cells = 0;
|
|
674
|
+
op.values.forEach((values, i) => {
|
|
675
|
+
const index = r0 + i;
|
|
676
|
+
const row = edited.get(index) ?? { ...grid.rows[index].row, cells: [...grid.rows[index].row.cells] };
|
|
677
|
+
values.forEach((value, j) => {
|
|
678
|
+
const col = c0 + j;
|
|
679
|
+
const old = row.cells[col] ?? null;
|
|
680
|
+
if (old && old.hidden) throw new QueryRefused("covered_cell", `range ${op.range} writes into a merged cell's covered position`);
|
|
681
|
+
while (row.cells.length <= col) row.cells.push(null);
|
|
682
|
+
row.cells[col] = setCell(old, value);
|
|
683
|
+
cells++;
|
|
684
|
+
});
|
|
685
|
+
edited.set(index, row);
|
|
686
|
+
});
|
|
687
|
+
return cells;
|
|
688
|
+
}
|
|
689
|
+
function lastKey(grid, appended) {
|
|
690
|
+
if (appended.length > 0) return appended[appended.length - 1].pos;
|
|
691
|
+
for (let i = grid.rows.length - 1; i >= 0; i--) if (isKey(grid.rows[i].row.pos)) return grid.rows[i].row.pos;
|
|
692
|
+
return null;
|
|
693
|
+
}
|
|
694
|
+
function patchGrid(src, ops, { newId = randomId } = {}) {
|
|
695
|
+
if (!Array.isArray(ops) || ops.length === 0) throw new QueryRefused("bad_patch", "patch is a non-empty list of operations");
|
|
696
|
+
const grid = readGrid(src);
|
|
697
|
+
const ids = /* @__PURE__ */ new Set([...grid.rows.map(({ row }) => row.id), ...grid.cols.map((col) => col.id)]);
|
|
698
|
+
const edited = /* @__PURE__ */ new Map();
|
|
699
|
+
const appended = [];
|
|
700
|
+
let cells = 0;
|
|
701
|
+
for (const op of ops) {
|
|
702
|
+
if (op && typeof op.range === "string" && op.append === void 0) {
|
|
703
|
+
cells += applyRange(grid, op, edited);
|
|
704
|
+
} else if (op && op.append !== void 0 && op.range === void 0) {
|
|
705
|
+
checkGrid(op.append, "append");
|
|
706
|
+
for (const values of op.append) {
|
|
707
|
+
if (values.length > grid.cols.length) throw new QueryRefused("outside_sheet", "an appended row has more values than the sheet has columns");
|
|
708
|
+
let id = newId();
|
|
709
|
+
while (ids.has(id)) id = newId();
|
|
710
|
+
ids.add(id);
|
|
711
|
+
const row = { id, pos: keyBetween(lastKey(grid, appended), null), cells: values.map((value) => setCell(null, value)) };
|
|
712
|
+
cells += row.cells.filter(Boolean).length;
|
|
713
|
+
appended.push(row);
|
|
714
|
+
}
|
|
715
|
+
} else {
|
|
716
|
+
throw new QueryRefused("bad_patch", "an operation is { range, values } or { append }");
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
const edits = [];
|
|
720
|
+
const { freezeCols } = grid.table;
|
|
721
|
+
edits.push({ start: 0, end: grid.startEnd, bytes: `<table grid${freezeCols ? ` freeze-cols="${freezeCols}"` : ""} stale>` });
|
|
722
|
+
for (const [index, row] of edited) edits.push({ start: grid.rows[index].start, end: grid.rows[index].end, bytes: rowHtml(row) });
|
|
723
|
+
if (appended.length > 0) {
|
|
724
|
+
const last = grid.groups[grid.groups.length - 1];
|
|
725
|
+
let room = last && !last.frozen ? GROUP_SIZE - last.rows : 0;
|
|
726
|
+
let at = last && !last.frozen ? last.end - "</tbody>".length : grid.end - "</table>".length;
|
|
727
|
+
let rest = appended;
|
|
728
|
+
if (room > 0) {
|
|
729
|
+
edits.push({ start: at, end: at, bytes: rest.slice(0, room).map((row) => `${rowHtml(row)}
|
|
730
|
+
`).join("") });
|
|
731
|
+
rest = rest.slice(room);
|
|
732
|
+
}
|
|
733
|
+
at = grid.end - "</table>".length;
|
|
734
|
+
let bytes = "";
|
|
735
|
+
for (let i = 0; i < rest.length; i += GROUP_SIZE) {
|
|
736
|
+
bytes += `<tbody>
|
|
737
|
+
${rest.slice(i, i + GROUP_SIZE).map((row) => `${rowHtml(row)}
|
|
738
|
+
`).join("")}</tbody>`;
|
|
739
|
+
}
|
|
740
|
+
if (bytes) edits.push({ start: at, end: at, bytes });
|
|
741
|
+
}
|
|
742
|
+
edits.sort((a, b) => a.start - b.start);
|
|
743
|
+
let out = "";
|
|
744
|
+
let from = 0;
|
|
745
|
+
for (const edit of edits) {
|
|
746
|
+
out += src.slice(from, edit.start) + edit.bytes;
|
|
747
|
+
from = edit.end;
|
|
748
|
+
}
|
|
749
|
+
out += src.slice(from);
|
|
750
|
+
return { bytes: out, changed: { cells, rows: appended.length } };
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
// src/grid/codec/digest.js
|
|
754
|
+
var OFFSET = 2166136261;
|
|
755
|
+
var PRIME = 16777619;
|
|
756
|
+
function fnv1a(text, hash = OFFSET) {
|
|
757
|
+
const step = (byte) => {
|
|
758
|
+
hash = Math.imul(hash ^ byte, PRIME) >>> 0;
|
|
759
|
+
};
|
|
760
|
+
for (const char of text) {
|
|
761
|
+
let code = char.codePointAt(0);
|
|
762
|
+
if (code >= 55296 && code <= 57343) code = 65533;
|
|
763
|
+
if (code < 128) {
|
|
764
|
+
step(code);
|
|
765
|
+
} else if (code < 2048) {
|
|
766
|
+
step(192 | code >> 6);
|
|
767
|
+
step(128 | code & 63);
|
|
768
|
+
} else if (code < 65536) {
|
|
769
|
+
step(224 | code >> 12);
|
|
770
|
+
step(128 | code >> 6 & 63);
|
|
771
|
+
step(128 | code & 63);
|
|
772
|
+
} else {
|
|
773
|
+
step(240 | code >> 18);
|
|
774
|
+
step(128 | code >> 12 & 63);
|
|
775
|
+
step(128 | code >> 6 & 63);
|
|
776
|
+
step(128 | code & 63);
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
return hash >>> 0;
|
|
780
|
+
}
|
|
781
|
+
var hex = (hash) => hash.toString(16).padStart(8, "0");
|
|
782
|
+
function cellInput(cell) {
|
|
783
|
+
if (!cell || cell.hidden) return "";
|
|
784
|
+
return cell.f ?? cell.v ?? cell.text;
|
|
785
|
+
}
|
|
786
|
+
var columnId = (cols, index) => cols[index]?.id || `#${index}`;
|
|
787
|
+
function columnIds(sheet) {
|
|
788
|
+
return sheet.cols.map((col, index) => col?.id || `#${index}`);
|
|
789
|
+
}
|
|
790
|
+
function rowDigest(row, cols) {
|
|
791
|
+
let filled = 0;
|
|
792
|
+
let mass = 0;
|
|
793
|
+
let inputs = OFFSET;
|
|
794
|
+
let columns = 0;
|
|
795
|
+
const occupied = [];
|
|
796
|
+
row.cells.forEach((cell, index) => {
|
|
797
|
+
const input = cellInput(cell);
|
|
798
|
+
inputs = fnv1a(`${input}\0`, inputs);
|
|
799
|
+
if (input === "") return;
|
|
800
|
+
filled++;
|
|
801
|
+
mass += input.trim().length;
|
|
802
|
+
columns = (columns ^ fnv1a(columnId(cols, index))) >>> 0;
|
|
803
|
+
occupied.push(index);
|
|
804
|
+
});
|
|
805
|
+
return filled === 0 ? null : [row.id, filled, mass, hex(inputs), hex(columns), maskHex(occupied)];
|
|
806
|
+
}
|
|
807
|
+
function maskHex(indexes) {
|
|
808
|
+
const nibbles = [];
|
|
809
|
+
for (const index of indexes) {
|
|
810
|
+
const at = index >> 2;
|
|
811
|
+
while (nibbles.length <= at) nibbles.push(0);
|
|
812
|
+
nibbles[at] |= 1 << (index & 3);
|
|
813
|
+
}
|
|
814
|
+
while (nibbles.length > 1 && nibbles[nibbles.length - 1] === 0) nibbles.pop();
|
|
815
|
+
return nibbles.length ? nibbles.reverse().map((n) => n.toString(16)).join("") : "0";
|
|
816
|
+
}
|
|
817
|
+
function maskIndexes(mask) {
|
|
818
|
+
const indexes = [];
|
|
819
|
+
for (let i = 0; i < mask.length; i++) {
|
|
820
|
+
const nibble = parseInt(mask[mask.length - 1 - i], 16);
|
|
821
|
+
for (let bit = 0; bit < 4; bit++) if (nibble & 1 << bit) indexes.push(i * 4 + bit);
|
|
822
|
+
}
|
|
823
|
+
return indexes;
|
|
824
|
+
}
|
|
825
|
+
var occupiedIds = (mask, cols) => maskIndexes(mask).map((index) => cols[index] || `#${index}`);
|
|
826
|
+
var positional = (cols, index) => !cols[index] || cols[index] === `#${index}`;
|
|
827
|
+
function rowChange(before, after, beforeCols = [], afterCols = []) {
|
|
828
|
+
if (!after) return "destruction";
|
|
829
|
+
if (after[1] < before[1]) return "destruction";
|
|
830
|
+
const nowIds = new Set(occupiedIds(after[5], afterCols));
|
|
831
|
+
const nowIndexes = new Set(maskIndexes(after[5]));
|
|
832
|
+
const cleared = maskIndexes(before[5]).some((index) => positional(beforeCols, index) ? !nowIndexes.has(index) : !nowIds.has(beforeCols[index]));
|
|
833
|
+
if (cleared) return "destruction";
|
|
834
|
+
const columnsSame = before[4] === after[4] || beforeCols.every((_, index) => positional(beforeCols, index));
|
|
835
|
+
if (before[3] === after[3] && columnsSame && before[5] === after[5]) return "same";
|
|
836
|
+
return "modification";
|
|
837
|
+
}
|
|
838
|
+
function gridDigest(sheet) {
|
|
839
|
+
return sheet.rows.map((row) => rowDigest(row, sheet.cols)).filter(Boolean);
|
|
840
|
+
}
|
|
841
|
+
function tabDigest(sheet) {
|
|
842
|
+
return { cols: columnIds(sheet), rows: gridDigest(sheet) };
|
|
843
|
+
}
|
|
844
|
+
export {
|
|
845
|
+
CodecMiss,
|
|
846
|
+
MAX_DIGITS,
|
|
847
|
+
QueryRefused,
|
|
848
|
+
RENDERS,
|
|
849
|
+
STYLE_PROPERTIES,
|
|
850
|
+
attrEscape,
|
|
851
|
+
canonicalGrid,
|
|
852
|
+
cellHtml,
|
|
853
|
+
cellInput,
|
|
854
|
+
cellJson,
|
|
855
|
+
cellValue,
|
|
856
|
+
colHtml,
|
|
857
|
+
columnIds,
|
|
858
|
+
cutGrids,
|
|
859
|
+
domAdapter,
|
|
860
|
+
filterStyle,
|
|
861
|
+
fnv1a,
|
|
862
|
+
gridDigest,
|
|
863
|
+
gridModel,
|
|
864
|
+
hex,
|
|
865
|
+
holeHtml,
|
|
866
|
+
holeMarker,
|
|
867
|
+
isCanonicalStyle,
|
|
868
|
+
joinGrids,
|
|
869
|
+
maskHex,
|
|
870
|
+
maskIndexes,
|
|
871
|
+
parseRange,
|
|
872
|
+
patchGrid,
|
|
873
|
+
readRange,
|
|
874
|
+
rowChange,
|
|
875
|
+
rowDigest,
|
|
876
|
+
rowHtml,
|
|
877
|
+
scanGrid,
|
|
878
|
+
shown,
|
|
879
|
+
significantDigits,
|
|
880
|
+
tabDigest,
|
|
881
|
+
tabIndex,
|
|
882
|
+
tabJson,
|
|
883
|
+
tableHtml,
|
|
884
|
+
textEscape,
|
|
885
|
+
treeModel,
|
|
886
|
+
typed
|
|
887
|
+
};
|