@prolibu-suite/cobalt-core 0.10.4 → 0.11.1
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 +12 -5
- package/custom-elements.json +7034 -1203
- package/dist/cjs/co-accordion.cjs.entry.js +3 -3
- package/dist/cjs/co-action-bar.cjs.entry.js +3 -3
- package/dist/cjs/co-app-shell.cjs.entry.js +3 -3
- package/dist/cjs/co-audio-player.cjs.entry.js +4 -4
- package/dist/cjs/co-autocomplete.cjs.entry.js +12 -5
- package/dist/cjs/co-avatar-group.cjs.entry.js +3 -3
- package/dist/cjs/co-avatar.cjs.entry.js +7 -4
- package/dist/cjs/co-badge.cjs.entry.js +2 -2
- package/dist/cjs/co-bottom-sheet.cjs.entry.js +5 -5
- package/dist/cjs/co-breadcrumb-item.cjs.entry.js +3 -3
- package/dist/cjs/co-breadcrumb.cjs.entry.js +2 -2
- package/dist/cjs/co-button-group.cjs.entry.js +4 -3
- package/dist/cjs/co-button.cjs.entry.js +9 -7
- package/dist/cjs/co-calendar-month_2.cjs.entry.js +16 -4
- package/dist/cjs/co-calendar_3.cjs.entry.js +76 -27
- package/dist/cjs/co-card.cjs.entry.js +3 -3
- package/dist/cjs/co-carousel-item.cjs.entry.js +2 -2
- package/dist/cjs/co-carousel.cjs.entry.js +6 -3
- package/dist/cjs/co-checkbox-group.cjs.entry.js +4 -4
- package/dist/cjs/co-checkbox.cjs.entry.js +13 -5
- package/dist/cjs/co-chip_2.cjs.entry.js +20 -7
- package/dist/cjs/co-color-area.cjs.entry.js +169 -0
- package/dist/cjs/co-color-picker.cjs.entry.js +5 -5
- package/dist/cjs/co-color-slider.cjs.entry.js +189 -0
- package/dist/cjs/co-column-picker.cjs.entry.js +23 -3
- package/dist/cjs/co-combobox.cjs.entry.js +5 -5
- package/dist/cjs/co-command-search.cjs.entry.js +5 -5
- package/dist/cjs/co-data-table-pagination.cjs.entry.js +5 -5
- package/dist/cjs/co-data-table.cjs.entry.js +3 -3
- package/dist/cjs/co-date-picker.cjs.entry.js +10 -2
- package/dist/cjs/co-date-range-picker.cjs.entry.js +11 -2
- package/dist/cjs/co-date-range.cjs.entry.js +8 -2
- package/dist/cjs/co-date-time-picker.cjs.entry.js +11 -4
- package/dist/cjs/co-document-editor.cjs.entry.js +1167 -0
- package/dist/cjs/co-drive-card.cjs.entry.js +2 -2
- package/dist/cjs/co-drop-zone.cjs.entry.js +2 -2
- package/dist/cjs/co-emoji-picker.cjs.entry.js +3 -3
- package/dist/cjs/co-empty-state.cjs.entry.js +3 -3
- package/dist/cjs/co-event-calendar.cjs.entry.js +5 -3
- package/dist/cjs/co-event-popover.cjs.entry.js +7 -3
- package/dist/cjs/co-fab.cjs.entry.js +7 -3
- package/dist/cjs/co-file-field.cjs.entry.js +12 -8
- package/dist/cjs/co-file-type-tile.cjs.entry.js +3 -3
- package/dist/cjs/co-gradient-bar.cjs.entry.js +220 -0
- package/dist/cjs/co-helper-text.cjs.entry.js +3 -3
- package/dist/cjs/co-icon-button.cjs.entry.js +48 -9
- package/dist/cjs/co-icon.cjs.entry.js +3 -3
- package/dist/cjs/co-input.cjs.entry.js +14 -8
- package/dist/cjs/co-json-field.cjs.entry.js +10 -5
- package/dist/cjs/{co-tooltip.cjs.entry.js → co-kbd_2.cjs.entry.js} +194 -6
- package/dist/cjs/co-lightbox.cjs.entry.js +5 -5
- package/dist/cjs/co-list-footer.cjs.entry.js +2 -2
- package/dist/cjs/co-list-item.cjs.entry.js +5 -5
- package/dist/cjs/co-loader.cjs.entry.js +1 -1
- package/dist/cjs/co-media-thumb.cjs.entry.js +3 -3
- package/dist/cjs/co-menu-divider.cjs.entry.js +3 -3
- package/dist/cjs/co-menu-item.cjs.entry.js +41 -43
- package/dist/cjs/co-menu.cjs.entry.js +81 -5
- package/dist/cjs/co-modal.cjs.entry.js +350 -7
- package/dist/cjs/co-navbar.cjs.entry.js +3 -3
- package/dist/cjs/co-number-field.cjs.entry.js +11 -5
- package/dist/cjs/co-overlay.cjs.entry.js +8 -4
- package/dist/cjs/co-page-header.cjs.entry.js +2 -2
- package/dist/cjs/co-phone-field.cjs.entry.js +3 -3
- package/dist/cjs/co-popover.cjs.entry.js +69 -6
- package/dist/cjs/co-progress-bar.cjs.entry.js +3 -3
- package/dist/cjs/co-progress-circle.cjs.entry.js +3 -3
- package/dist/cjs/co-provider-logo_2.cjs.entry.js +2 -2
- package/dist/cjs/co-radio-group.cjs.entry.js +4 -4
- package/dist/cjs/co-radio.cjs.entry.js +4 -4
- package/dist/cjs/co-rating.cjs.entry.js +11 -4
- package/dist/cjs/co-ref-field.cjs.entry.js +14 -5
- package/dist/cjs/co-rich-text-editor.cjs.entry.js +40 -92
- package/dist/cjs/co-rich-text-toolbar.cjs.entry.js +80 -20
- package/dist/cjs/co-rich-text-viewer.cjs.entry.js +9 -2
- package/dist/cjs/co-row.cjs.entry.js +3 -3
- package/dist/cjs/co-segmented-bar.cjs.entry.js +3 -3
- package/dist/cjs/co-select.cjs.entry.js +171 -29
- package/dist/cjs/co-separator.cjs.entry.js +2 -2
- package/dist/cjs/co-sidebar-nav.cjs.entry.js +20 -5
- package/dist/cjs/co-sidebar.cjs.entry.js +3 -3
- package/dist/cjs/co-slider.cjs.entry.js +209 -23
- package/dist/cjs/co-swatch-grid.cjs.entry.js +121 -0
- package/dist/cjs/co-switch.cjs.entry.js +5 -5
- package/dist/cjs/co-tab-group.cjs.entry.js +113 -4
- package/dist/cjs/co-tab.cjs.entry.js +15 -5
- package/dist/cjs/co-tags-field.cjs.entry.js +13 -8
- package/dist/cjs/co-textarea.cjs.entry.js +6 -6
- package/dist/cjs/co-tile.cjs.entry.js +61 -0
- package/dist/cjs/co-time-field.cjs.entry.js +5 -2
- package/dist/cjs/co-toast.cjs.entry.js +3 -3
- package/dist/cjs/co-toggle-button-group.cjs.entry.js +29 -5
- package/dist/cjs/co-toggle-button.cjs.entry.js +70 -6
- package/dist/cjs/co-transfer-list.cjs.entry.js +7 -3
- package/dist/cjs/co-tree-item.cjs.entry.js +110 -0
- package/dist/cjs/co-video.cjs.entry.js +11 -3
- package/dist/cjs/cobalt.cjs.js +2 -2
- package/dist/cjs/{color-CML2Cfdh.js → color-DQVrQGi0.js} +10 -5
- package/dist/cjs/{fieldChip-B6YIGU1V.js → fieldChip-C7MxxBVO.js} +1 -1
- package/dist/cjs/gradientStops-CMpH4fB_.js +153 -0
- package/dist/cjs/hsv-DpfSF3M2.js +95 -0
- package/dist/cjs/{index-MDAnKsze.js → index-bHoidDwv.js} +67 -27
- package/dist/cjs/index-oMHzCXm6.js +144 -0
- package/dist/cjs/loader.cjs.js +2 -2
- package/dist/cjs/{index-2kMmd5-a.js → pagination-DV43TRj9.js} +1780 -297
- package/dist/cjs/{positioning-CyatXeT_.js → positioning-CILo5esi.js} +45 -18
- package/dist/cjs/{requiredMark-D-t-IPN0.js → requiredMark-21yHvvZS.js} +1 -1
- package/dist/cjs/rich-text-host-ueFSfW-6.js +119 -0
- package/dist/cjs/{richTextI18n-B28uAhh4.js → richTextI18n-DXGIv5w1.js} +45 -0
- package/dist/cjs/submenu-RlaX6irw.js +65 -0
- package/dist/cjs/{toolbar-config-CYACt9hh.js → toolbar-config-DczL6C4W.js} +32 -0
- package/dist/cobalt/cobalt.css +1 -1
- package/dist/cobalt/cobalt.esm.js +1 -1
- package/dist/cobalt/{p-76249983.entry.js → p-019eed8e.entry.js} +1 -1
- package/dist/cobalt/p-04e3e1f6.entry.js +1 -0
- package/dist/cobalt/p-06689166.entry.js +1 -0
- package/dist/cobalt/p-0d046d98.entry.js +1 -0
- package/dist/cobalt/{p-28764b8e.entry.js → p-0e4c2234.entry.js} +1 -1
- package/dist/cobalt/{p-b90d41e4.entry.js → p-1348d5ca.entry.js} +1 -1
- package/dist/cobalt/{p-49834b8e.entry.js → p-13e5b724.entry.js} +1 -1
- package/dist/cobalt/p-1a5bec8c.entry.js +1 -0
- package/dist/cobalt/p-21b4a830.entry.js +1 -0
- package/dist/cobalt/p-2231bacc.entry.js +1 -0
- package/dist/cobalt/{p-b437eff6.entry.js → p-26cbdc33.entry.js} +1 -1
- package/dist/cobalt/{p-aa9400bf.entry.js → p-28cf05f3.entry.js} +1 -1
- package/dist/cobalt/{p-eadfd661.entry.js → p-358a6c2a.entry.js} +1 -1
- package/dist/cobalt/p-3b5024ce.entry.js +1 -0
- package/dist/cobalt/p-3b6efb79.entry.js +1 -0
- package/dist/cobalt/p-3d1a48e5.entry.js +1 -0
- package/dist/cobalt/p-47eca182.entry.js +1 -0
- package/dist/cobalt/{p-eb82358d.entry.js → p-4bcdd422.entry.js} +1 -1
- package/dist/cobalt/{p-17244412.entry.js → p-4d743628.entry.js} +1 -1
- package/dist/cobalt/{p-011dc80b.entry.js → p-4e81e580.entry.js} +1 -1
- package/dist/cobalt/{p-ee9a623d.entry.js → p-53a251ca.entry.js} +1 -1
- package/dist/cobalt/{p-11c5ce78.entry.js → p-56176aa0.entry.js} +1 -1
- package/dist/cobalt/{p-a32b20eb.entry.js → p-58ebb303.entry.js} +1 -1
- package/dist/cobalt/{p-4592ca00.entry.js → p-5a32b9a2.entry.js} +1 -1
- package/dist/cobalt/{p-2636b7eb.entry.js → p-5e678e88.entry.js} +1 -1
- package/dist/cobalt/{p-996f4e38.entry.js → p-60f948c4.entry.js} +1 -1
- package/dist/cobalt/p-63908a8d.entry.js +1 -0
- package/dist/cobalt/p-65c191aa.entry.js +1 -0
- package/dist/cobalt/{p-c2ebf0ec.entry.js → p-65d44da2.entry.js} +1 -1
- package/dist/cobalt/p-67a024dd.entry.js +1 -0
- package/dist/cobalt/{p-ee149fd2.entry.js → p-6974df59.entry.js} +1 -1
- package/dist/cobalt/{p-000a15b8.entry.js → p-69ecc933.entry.js} +1 -1
- package/dist/cobalt/p-6c1992c9.entry.js +1 -0
- package/dist/cobalt/{p-b821d9de.entry.js → p-6d4a660c.entry.js} +1 -1
- package/dist/cobalt/{p-f57dffca.entry.js → p-713637f2.entry.js} +1 -1
- package/dist/cobalt/{p-292b0389.entry.js → p-71ae1551.entry.js} +1 -1
- package/dist/cobalt/{p-91e73a92.entry.js → p-71dc8e4a.entry.js} +1 -1
- package/dist/cobalt/{p-aaca6dab.entry.js → p-71ee36a8.entry.js} +1 -1
- package/dist/cobalt/p-71fe35c4.entry.js +1 -0
- package/dist/cobalt/{p-08e42e00.entry.js → p-73313cbe.entry.js} +1 -1
- package/dist/cobalt/{p-7b5c555c.entry.js → p-763698b3.entry.js} +1 -1
- package/dist/cobalt/p-77e0d401.entry.js +1 -0
- package/dist/cobalt/{p-c91d4fc6.entry.js → p-78412feb.entry.js} +1 -1
- package/dist/cobalt/p-7beface1.entry.js +1 -0
- package/dist/cobalt/{p-f4e1c3c3.entry.js → p-7d1718ed.entry.js} +1 -1
- package/dist/cobalt/{p-826ee074.entry.js → p-7df18a52.entry.js} +1 -1
- package/dist/cobalt/p-7e678cbd.entry.js +1 -0
- package/dist/cobalt/{p-d0b2c418.entry.js → p-7fabd8ba.entry.js} +1 -1
- package/dist/cobalt/{p-23ab0cc5.entry.js → p-848f5ca4.entry.js} +1 -1
- package/dist/cobalt/{p-623cc195.entry.js → p-8680559b.entry.js} +1 -1
- package/dist/cobalt/p-87de5469.entry.js +1 -0
- package/dist/cobalt/p-87e62e2b.entry.js +1 -0
- package/dist/cobalt/{p-1861fe41.entry.js → p-8a2a2b6c.entry.js} +1 -1
- package/dist/cobalt/p-903237f9.entry.js +1 -0
- package/dist/cobalt/{p-2c9dba2f.entry.js → p-95f2ebb1.entry.js} +1 -1
- package/dist/cobalt/{p-24196410.entry.js → p-99df434b.entry.js} +1 -1
- package/dist/cobalt/{p-290066ef.entry.js → p-9adbab95.entry.js} +1 -1
- package/dist/cobalt/p-9dc01092.entry.js +1 -0
- package/dist/cobalt/p-9ee5bef3.entry.js +1 -0
- package/dist/cobalt/p-B1JT7us1.js +1 -0
- package/dist/cobalt/{p-BRbgGqLw.js → p-BVGGRfNG.js} +1 -1
- package/dist/cobalt/p-BmdKHBZP.js +1 -0
- package/dist/cobalt/p-BtliEQAT.js +1 -0
- package/dist/cobalt/p-COJdaKBU.js +1 -0
- package/dist/cobalt/{p-BAYo-RBt.js → p-CRxTFT_z.js} +1 -1
- package/dist/cobalt/p-CYN5B3IQ.js +1 -0
- package/dist/cobalt/p-DJkaRtbb.js +2 -0
- package/dist/cobalt/p-DU-KOQ8L.js +1 -0
- package/dist/cobalt/p-DXLeDZvr.js +1 -0
- package/dist/cobalt/{p-D_zA1Pv4.js → p-DgJovDdy.js} +1 -1
- package/dist/cobalt/p-RVQJEYxa.js +1 -0
- package/dist/cobalt/{p-ee2023da.entry.js → p-a27013e6.entry.js} +1 -1
- package/dist/cobalt/{p-2f9cbbd5.entry.js → p-a4eb298c.entry.js} +1 -1
- package/dist/cobalt/p-a56bd4a8.entry.js +1 -0
- package/dist/cobalt/{p-59963937.entry.js → p-a5eabecb.entry.js} +1 -1
- package/dist/cobalt/p-a5ee1fc2.entry.js +1 -0
- package/dist/cobalt/{p-fb2d1144.entry.js → p-a7cd61ce.entry.js} +1 -1
- package/dist/cobalt/{p-39a50e7f.entry.js → p-ad752791.entry.js} +1 -1
- package/dist/cobalt/{p-07416e31.entry.js → p-ae999b94.entry.js} +1 -1
- package/dist/cobalt/{p-4d65e713.entry.js → p-aed832d5.entry.js} +1 -1
- package/dist/cobalt/p-b2457431.entry.js +1 -0
- package/dist/cobalt/{p-6dd220e0.entry.js → p-b39a4999.entry.js} +1 -1
- package/dist/cobalt/p-b5dabdc3.entry.js +1 -0
- package/dist/cobalt/{p-8471abe2.entry.js → p-b67fb616.entry.js} +1 -1
- package/dist/cobalt/{p-f7eb1a40.entry.js → p-b9b73dcb.entry.js} +1 -1
- package/dist/cobalt/{p-f9a7b7c6.entry.js → p-ba39a965.entry.js} +1 -1
- package/dist/cobalt/{p-58d9b650.entry.js → p-be520bd5.entry.js} +1 -1
- package/dist/cobalt/{p-1dc55e43.entry.js → p-bee30373.entry.js} +1 -1
- package/dist/cobalt/{p-44c4e4a3.entry.js → p-c220362c.entry.js} +1 -1
- package/dist/cobalt/p-c4c997f3.entry.js +1 -0
- package/dist/cobalt/{p-a2462d7a.entry.js → p-c5464a98.entry.js} +1 -1
- package/dist/cobalt/p-c567533e.entry.js +1 -0
- package/dist/cobalt/{p-c30b4cb5.entry.js → p-cf5b91be.entry.js} +1 -1
- package/dist/cobalt/p-cfaaa684.entry.js +1 -0
- package/dist/cobalt/p-d00c3894.entry.js +1 -0
- package/dist/cobalt/p-d1e83525.entry.js +1 -0
- package/dist/cobalt/{p-44ea675f.entry.js → p-d5d8fa8b.entry.js} +1 -1
- package/dist/cobalt/p-d6215d80.entry.js +1 -0
- package/dist/cobalt/p-d6e7c258.entry.js +1 -0
- package/dist/cobalt/p-dabcbba7.entry.js +1 -0
- package/dist/cobalt/p-db623519.entry.js +1 -0
- package/dist/cobalt/{p-c7d7d7f7.entry.js → p-df529110.entry.js} +1 -1
- package/dist/cobalt/{p-1cc818ca.entry.js → p-ea24eea8.entry.js} +1 -1
- package/dist/cobalt/{p-d29bb0fa.entry.js → p-efb3cbb0.entry.js} +1 -1
- package/dist/cobalt/{p-f6691108.entry.js → p-f0898e21.entry.js} +1 -1
- package/dist/cobalt/{p-0c004735.entry.js → p-f2fa2ac0.entry.js} +1 -1
- package/dist/cobalt/p-f403eeec.entry.js +1 -0
- package/dist/cobalt/{p-e4264532.entry.js → p-f69804a6.entry.js} +1 -1
- package/dist/cobalt/p-xnrKkNWQ.js +1 -0
- package/dist/collection/collection-manifest.json +8 -0
- package/dist/collection/components/co-accordion/co-accordion.js +12 -2
- package/dist/collection/components/co-action-bar/co-action-bar.css +6 -0
- package/dist/collection/components/co-action-bar/co-action-bar.js +3 -2
- package/dist/collection/components/co-app-shell/co-app-shell.css +6 -0
- package/dist/collection/components/co-app-shell/co-app-shell.js +13 -2
- package/dist/collection/components/co-audio-player/co-audio-player.js +19 -7
- package/dist/collection/components/co-autocomplete/co-autocomplete.js +30 -17
- package/dist/collection/components/co-avatar/co-avatar.css +16 -2
- package/dist/collection/components/co-avatar/co-avatar.js +14 -4
- package/dist/collection/components/co-avatar-group/co-avatar-group.css +4 -0
- package/dist/collection/components/co-avatar-group/co-avatar-group.js +8 -3
- package/dist/collection/components/co-badge/co-badge.js +8 -1
- package/dist/collection/components/co-bottom-sheet/co-bottom-sheet.js +13 -4
- package/dist/collection/components/co-breadcrumb/co-breadcrumb.js +5 -1
- package/dist/collection/components/co-breadcrumb-item/co-breadcrumb-item.js +8 -2
- package/dist/collection/components/co-button/co-button.css +81 -6
- package/dist/collection/components/co-button/co-button.js +39 -11
- package/dist/collection/components/co-button-group/co-button-group.js +10 -3
- package/dist/collection/components/co-calendar/calendarMarks.js +40 -0
- package/dist/collection/components/co-calendar/co-calendar.css +19 -1
- package/dist/collection/components/co-calendar/co-calendar.js +84 -20
- package/dist/collection/components/co-calendar-month/co-calendar-month.js +1 -1
- package/dist/collection/components/co-calendar-timegrid/co-calendar-timegrid.js +36 -19
- package/dist/collection/components/co-card/co-card.js +11 -2
- package/dist/collection/components/co-carousel/co-carousel.css +10 -0
- package/dist/collection/components/co-carousel/co-carousel.js +17 -5
- package/dist/collection/components/co-carousel-item/co-carousel-item.js +1 -1
- package/dist/collection/components/co-checkbox/co-checkbox.css +43 -1
- package/dist/collection/components/co-checkbox/co-checkbox.js +39 -3
- package/dist/collection/components/co-checkbox-group/co-checkbox-group.js +9 -4
- package/dist/collection/components/co-chip/co-chip.css +9 -0
- package/dist/collection/components/co-chip/co-chip.js +15 -2
- package/dist/collection/components/co-color-area/co-color-area.css +87 -0
- package/dist/collection/components/co-color-area/co-color-area.js +342 -0
- package/dist/collection/components/co-color-picker/co-color-picker.js +4 -2
- package/dist/collection/components/co-color-slider/co-color-slider.css +115 -0
- package/dist/collection/components/co-color-slider/co-color-slider.js +354 -0
- package/dist/collection/components/co-column-picker/co-column-picker.js +51 -25
- package/dist/collection/components/co-combobox/co-combobox.js +18 -4
- package/dist/collection/components/co-command-search/co-command-search.js +19 -8
- package/dist/collection/components/co-data-table/co-data-table.js +8 -3
- package/dist/collection/components/co-data-table-pagination/co-data-table-pagination.js +16 -4
- package/dist/collection/components/co-date-field/co-date-field.js +19 -13
- package/dist/collection/components/co-date-picker/co-date-picker.js +38 -25
- package/dist/collection/components/co-date-range/co-date-range.js +19 -10
- package/dist/collection/components/co-date-range-picker/co-date-range-picker.js +44 -30
- package/dist/collection/components/co-date-time-picker/co-date-time-picker.js +31 -22
- package/dist/collection/components/co-document-editor/change-throttle.js +30 -0
- package/dist/collection/components/co-document-editor/co-document-editor.css +438 -0
- package/dist/collection/components/co-document-editor/co-document-editor.js +1549 -0
- package/dist/collection/components/co-document-editor/document-props.js +40 -0
- package/dist/collection/components/co-document-editor/header-tools.js +11 -0
- package/dist/collection/components/co-document-editor/image-bar.js +66 -0
- package/dist/collection/components/co-document-editor/page-styles.js +90 -0
- package/dist/collection/components/co-document-editor/zoom.js +45 -0
- package/dist/collection/components/co-drawer/co-drawer.css +5 -0
- package/dist/collection/components/co-drawer/co-drawer.js +13 -0
- package/dist/collection/components/co-drive-card/co-drive-card.js +14 -1
- package/dist/collection/components/co-drop-zone/co-drop-zone.js +7 -2
- package/dist/collection/components/co-emoji-picker/co-emoji-picker.css +4 -0
- package/dist/collection/components/co-emoji-picker/co-emoji-picker.js +11 -2
- package/dist/collection/components/co-empty-state/co-empty-state.js +4 -2
- package/dist/collection/components/co-event-calendar/co-event-calendar.js +16 -4
- package/dist/collection/components/co-event-popover/co-event-popover.js +18 -6
- package/dist/collection/components/co-fab/co-fab.css +8 -0
- package/dist/collection/components/co-fab/co-fab.js +17 -8
- package/dist/collection/components/co-file-field/co-file-field.js +16 -11
- package/dist/collection/components/co-file-type-tile/co-file-type-tile.js +9 -2
- package/dist/collection/components/co-gradient-bar/co-gradient-bar.css +143 -0
- package/dist/collection/components/co-gradient-bar/co-gradient-bar.js +412 -0
- package/dist/collection/components/co-helper-text/co-helper-text.js +4 -2
- package/dist/collection/components/co-icon/co-icon.js +6 -2
- package/dist/collection/components/co-icon-button/co-icon-button.css +104 -19
- package/dist/collection/components/co-icon-button/co-icon-button.js +125 -10
- package/dist/collection/components/co-input/co-input.css +125 -0
- package/dist/collection/components/co-input/co-input.js +48 -11
- package/dist/collection/components/co-json-field/co-json-field.js +19 -12
- package/dist/collection/components/co-kbd/co-kbd.css +99 -0
- package/dist/collection/components/co-kbd/co-kbd.js +298 -0
- package/dist/collection/components/co-lightbox/co-lightbox.js +4 -4
- package/dist/collection/components/co-list-footer/co-list-footer.js +4 -1
- package/dist/collection/components/co-list-item/co-list-item.js +7 -4
- package/dist/collection/components/co-loader/co-loader.js +5 -0
- package/dist/collection/components/co-media-thumb/co-media-thumb.js +9 -2
- package/dist/collection/components/co-menu/co-menu.css +70 -0
- package/dist/collection/components/co-menu/co-menu.js +146 -6
- package/dist/collection/components/co-menu-divider/co-menu-divider.css +21 -0
- package/dist/collection/components/co-menu-divider/co-menu-divider.js +2 -1
- package/dist/collection/components/co-menu-item/co-menu-item.css +56 -6
- package/dist/collection/components/co-menu-item/co-menu-item.js +60 -4
- package/dist/collection/components/co-modal/co-modal.css +218 -1
- package/dist/collection/components/co-modal/co-modal.js +354 -12
- package/dist/collection/components/co-navbar/co-navbar.css +7 -0
- package/dist/collection/components/co-navbar/co-navbar.js +4 -2
- package/dist/collection/components/co-number-field/co-number-field.js +29 -15
- package/dist/collection/components/co-option-list/co-option-list.css +102 -21
- package/dist/collection/components/co-option-list/co-option-list.js +37 -16
- package/dist/collection/components/co-overlay/co-overlay.css +4 -0
- package/dist/collection/components/co-overlay/co-overlay.js +17 -3
- package/dist/collection/components/co-page-header/co-page-header.js +4 -1
- package/dist/collection/components/co-phone-field/co-phone-field.js +1 -1
- package/dist/collection/components/co-popover/co-popover.css +20 -2
- package/dist/collection/components/co-popover/co-popover.js +148 -10
- package/dist/collection/components/co-progress-bar/co-progress-bar.js +5 -2
- package/dist/collection/components/co-progress-circle/co-progress-circle.js +5 -2
- package/dist/collection/components/co-provider-logo/co-provider-logo.js +3 -0
- package/dist/collection/components/co-radio/co-radio.js +11 -3
- package/dist/collection/components/co-radio-group/co-radio-group.js +9 -4
- package/dist/collection/components/co-rating/co-rating.js +25 -13
- package/dist/collection/components/co-ref-field/co-ref-field.css +14 -0
- package/dist/collection/components/co-ref-field/co-ref-field.js +55 -27
- package/dist/collection/components/co-rich-text-editor/co-rich-text-editor.js +66 -111
- package/dist/collection/components/co-rich-text-toolbar/co-rich-text-toolbar.css +12 -0
- package/dist/collection/components/co-rich-text-toolbar/co-rich-text-toolbar.js +127 -19
- package/dist/collection/components/co-rich-text-viewer/co-rich-text-viewer.js +16 -1
- package/dist/collection/components/co-row/co-row.js +5 -2
- package/dist/collection/components/co-segmented-bar/co-segmented-bar.js +9 -3
- package/dist/collection/components/co-select/co-select.css +207 -11
- package/dist/collection/components/co-select/co-select.js +198 -48
- package/dist/collection/components/co-select/virtualRows.js +57 -0
- package/dist/collection/components/co-separator/co-separator.js +8 -1
- package/dist/collection/components/co-sidebar/co-sidebar.js +10 -2
- package/dist/collection/components/co-sidebar-nav/co-sidebar-nav.css +15 -0
- package/dist/collection/components/co-sidebar-nav/co-sidebar-nav.js +20 -4
- package/dist/collection/components/co-skeleton/co-skeleton.js +4 -1
- package/dist/collection/components/co-slider/co-slider.css +155 -5
- package/dist/collection/components/co-slider/co-slider.js +263 -32
- package/dist/collection/components/co-swatch-grid/co-swatch-grid.css +56 -0
- package/dist/collection/components/co-swatch-grid/co-swatch-grid.js +293 -0
- package/dist/collection/components/co-switch/co-switch.css +4 -0
- package/dist/collection/components/co-switch/co-switch.js +12 -3
- package/dist/collection/components/co-tab/co-tab.css +60 -0
- package/dist/collection/components/co-tab/co-tab.js +44 -6
- package/dist/collection/components/co-tab-group/co-tab-group.css +24 -0
- package/dist/collection/components/co-tab-group/co-tab-group.js +133 -2
- package/dist/collection/components/co-tab-group/revealTab.js +26 -0
- package/dist/collection/components/co-tags-field/co-tags-field.js +21 -14
- package/dist/collection/components/co-textarea/co-textarea.js +4 -4
- package/dist/collection/components/co-tile/co-tile.css +63 -0
- package/dist/collection/components/co-tile/co-tile.js +167 -0
- package/dist/collection/components/co-time-field/co-time-field.js +9 -4
- package/dist/collection/components/co-toast/co-toast.css +11 -0
- package/dist/collection/components/co-toast/co-toast.js +13 -4
- package/dist/collection/components/co-toggle-button/co-toggle-button.css +106 -0
- package/dist/collection/components/co-toggle-button/co-toggle-button.js +91 -15
- package/dist/collection/components/co-toggle-button-group/co-toggle-button-group.css +21 -0
- package/dist/collection/components/co-toggle-button-group/co-toggle-button-group.js +41 -11
- package/dist/collection/components/co-tooltip/co-tooltip.css +36 -0
- package/dist/collection/components/co-tooltip/co-tooltip.js +61 -3
- package/dist/collection/components/co-transfer-list/co-transfer-list.js +19 -10
- package/dist/collection/components/co-tree-item/co-tree-item.css +235 -0
- package/dist/collection/components/co-tree-item/co-tree-item.js +355 -0
- package/dist/collection/components/co-tree-item/treeItemI18n.js +16 -0
- package/dist/collection/components/co-video/co-video.css +11 -0
- package/dist/collection/components/co-video/co-video.js +41 -22
- package/dist/collection/utils/color.js +9 -5
- package/dist/collection/utils/dragMove.js +95 -0
- package/dist/collection/utils/gradientBarI18n.js +24 -0
- package/dist/collection/utils/gradientStops.js +142 -0
- package/dist/collection/utils/hsv.js +114 -0
- package/dist/collection/utils/kbdI18n.js +29 -0
- package/dist/collection/utils/positioning.js +44 -18
- package/dist/collection/utils/rich-text-host.js +109 -0
- package/dist/collection/utils/richTextI18n.js +45 -0
- package/dist/collection/utils/submenu.js +23 -3
- package/dist/collection/utils/swatchGridI18n.js +14 -0
- package/dist/collection/utils/test/fake-block-layout.js +41 -0
- package/dist/collection/utils/test/prosemirror-dom-shim.js +17 -0
- package/dist/collection/utils/test/shared-contract-css.js +9 -0
- package/dist/components/co-accordion.js +1 -1
- package/dist/components/co-action-bar.js +1 -1
- package/dist/components/co-app-shell.js +1 -1
- package/dist/components/co-audio-player.js +1 -1
- package/dist/components/co-autocomplete.js +1 -1
- package/dist/components/co-avatar-group.js +1 -1
- package/dist/components/co-avatar.js +1 -1
- package/dist/components/co-badge.js +1 -1
- package/dist/components/co-bottom-sheet.js +1 -1
- package/dist/components/co-breadcrumb-item.js +1 -1
- package/dist/components/co-breadcrumb.js +1 -1
- package/dist/components/co-button-group.js +1 -1
- package/dist/components/co-button.js +1 -1
- package/dist/components/co-calendar-month.js +1 -1
- package/dist/components/co-calendar-timegrid.js +1 -1
- package/dist/components/co-calendar.js +1 -1
- package/dist/components/co-card.js +1 -1
- package/dist/components/co-carousel-item.js +1 -1
- package/dist/components/co-carousel.js +1 -1
- package/dist/components/co-checkbox-group.js +1 -1
- package/dist/components/co-checkbox.js +1 -1
- package/dist/components/co-chip.js +1 -1
- package/dist/components/co-color-area.d.ts +11 -0
- package/dist/components/co-color-area.js +1 -0
- package/dist/components/co-color-picker.js +1 -1
- package/dist/components/co-color-slider.d.ts +11 -0
- package/dist/components/co-color-slider.js +1 -0
- package/dist/components/co-column-picker.js +1 -1
- package/dist/components/co-combobox.js +1 -1
- package/dist/components/co-command-search.js +1 -1
- package/dist/components/co-data-table-pagination.js +1 -1
- package/dist/components/co-data-table.js +1 -1
- package/dist/components/co-date-field.js +1 -1
- package/dist/components/co-date-picker.js +1 -1
- package/dist/components/co-date-range-picker.js +1 -1
- package/dist/components/co-date-range.js +1 -1
- package/dist/components/co-date-time-picker.js +1 -1
- package/dist/components/co-document-editor.d.ts +11 -0
- package/dist/components/co-document-editor.js +1 -0
- package/dist/components/co-drawer.js +1 -1
- package/dist/components/co-drive-card.js +1 -1
- package/dist/components/co-drop-zone.js +1 -1
- package/dist/components/co-emoji-picker.js +1 -1
- package/dist/components/co-empty-state.js +1 -1
- package/dist/components/co-event-calendar.js +1 -1
- package/dist/components/co-event-popover.js +1 -1
- package/dist/components/co-fab.js +1 -1
- package/dist/components/co-file-field.js +1 -1
- package/dist/components/co-file-type-tile.js +1 -1
- package/dist/components/co-gradient-bar.d.ts +11 -0
- package/dist/components/co-gradient-bar.js +1 -0
- package/dist/components/co-helper-text.js +1 -1
- package/dist/components/co-icon-button.js +1 -1
- package/dist/components/co-icon.js +1 -1
- package/dist/components/co-input.js +1 -1
- package/dist/components/co-json-field.js +1 -1
- package/dist/components/co-kbd.d.ts +11 -0
- package/dist/components/co-kbd.js +1 -0
- package/dist/components/co-lightbox.js +1 -1
- package/dist/components/co-list-footer.js +1 -1
- package/dist/components/co-list-item.js +1 -1
- package/dist/components/co-media-thumb.js +1 -1
- package/dist/components/co-menu-divider.js +1 -1
- package/dist/components/co-menu-item.js +1 -1
- package/dist/components/co-menu.js +1 -1
- package/dist/components/co-modal.js +1 -1
- package/dist/components/co-navbar.js +1 -1
- package/dist/components/co-number-field.js +1 -1
- package/dist/components/co-option-list.js +1 -1
- package/dist/components/co-overlay.js +1 -1
- package/dist/components/co-page-header.js +1 -1
- package/dist/components/co-phone-field.js +1 -1
- package/dist/components/co-popover.js +1 -1
- package/dist/components/co-progress-bar.js +1 -1
- package/dist/components/co-progress-circle.js +1 -1
- package/dist/components/co-radio-group.js +1 -1
- package/dist/components/co-radio.js +1 -1
- package/dist/components/co-rating.js +1 -1
- package/dist/components/co-ref-field.js +1 -1
- package/dist/components/co-rich-text-editor.js +1 -1
- package/dist/components/co-rich-text-toolbar.js +1 -1
- package/dist/components/co-rich-text-viewer.js +1 -1
- package/dist/components/co-row.js +1 -1
- package/dist/components/co-segmented-bar.js +1 -1
- package/dist/components/co-select.js +1 -1
- package/dist/components/co-separator.js +1 -1
- package/dist/components/co-sidebar-nav.js +1 -1
- package/dist/components/co-sidebar.js +1 -1
- package/dist/components/co-skeleton.js +1 -1
- package/dist/components/co-slider.js +1 -1
- package/dist/components/co-swatch-grid.d.ts +11 -0
- package/dist/components/co-swatch-grid.js +1 -0
- package/dist/components/co-switch.js +1 -1
- package/dist/components/co-tab-group.js +1 -1
- package/dist/components/co-tab.js +1 -1
- package/dist/components/co-tags-field.js +1 -1
- package/dist/components/co-textarea.js +1 -1
- package/dist/components/co-tile.d.ts +11 -0
- package/dist/components/co-tile.js +1 -0
- package/dist/components/co-time-field.js +1 -1
- package/dist/components/co-toast.js +1 -1
- package/dist/components/co-toggle-button-group.js +1 -1
- package/dist/components/co-toggle-button.js +1 -1
- package/dist/components/co-tooltip.js +1 -1
- package/dist/components/co-transfer-list.js +1 -1
- package/dist/components/co-tree-item.d.ts +11 -0
- package/dist/components/co-tree-item.js +1 -0
- package/dist/components/co-video.js +1 -1
- package/dist/components/index.js +1 -1
- package/dist/components/p-8XzG8pzY.js +1 -0
- package/dist/components/p-9VoFSbIH.js +1 -0
- package/dist/components/p-B1JT7us1.js +1 -0
- package/dist/components/{p-Dc_Kbari.js → p-B3Egz082.js} +1 -1
- package/dist/components/p-B9wdMd_0.js +1 -0
- package/dist/components/p-BRZci8B3.js +1 -0
- package/dist/components/{p-BRbgGqLw.js → p-BVGGRfNG.js} +1 -1
- package/dist/components/{p-B56LX2SH.js → p-BVdCvEza.js} +1 -1
- package/dist/components/p-BdmzslA5.js +1 -0
- package/dist/components/p-BmdKHBZP.js +1 -0
- package/dist/components/p-BtliEQAT.js +1 -0
- package/dist/components/{p-CT2enQ6h.js → p-Bw_b_czs.js} +1 -1
- package/dist/components/{p-NNxjElcX.js → p-C4sZjIDj.js} +1 -1
- package/dist/components/{p-Nt4JJxbL.js → p-C6WHpL5X.js} +1 -1
- package/dist/components/p-COJdaKBU.js +1 -0
- package/dist/components/p-COozgrEk.js +1 -0
- package/dist/components/{p-BAYo-RBt.js → p-CRxTFT_z.js} +1 -1
- package/dist/components/{p-uxdXViMV.js → p-CiYPJW0B.js} +1 -1
- package/dist/components/p-Cnfd6Zze.js +1 -0
- package/dist/components/{p-BhCVadcA.js → p-CxWo3qDo.js} +1 -1
- package/dist/components/p-D4XP17VP.js +1 -0
- package/dist/components/{p-e5KibEs8.js → p-DJ468fPu.js} +1 -1
- package/dist/components/p-DU-KOQ8L.js +1 -0
- package/dist/components/p-DXLeDZvr.js +1 -0
- package/dist/components/{p-DvR45CLa.js → p-Dn2wblrA.js} +1 -1
- package/dist/components/p-Dnz99Ox_.js +1 -0
- package/dist/components/p-DsuFNmTI.js +1 -0
- package/dist/components/{p-Du_CgT5E.js → p-Du8EpQb-.js} +1 -1
- package/dist/components/{p-DFlJMEJ-.js → p-DymSqdlK.js} +1 -1
- package/dist/components/p-Hi57w2_2.js +1 -0
- package/dist/components/{p-DNJAIVfI.js → p-KK2vAKs-.js} +1 -1
- package/dist/components/p-RVQJEYxa.js +1 -0
- package/dist/components/p-TGRbLkLz.js +1 -0
- package/dist/components/p-VcrjNCew.js +1 -0
- package/dist/components/{p-Dxa7c4Ap.js → p-dnaee7fS.js} +1 -1
- package/dist/components/p-nrwDl_gx.js +1 -0
- package/dist/components/{p-P4HlMBlL.js → p-zJ3pjFzW.js} +1 -1
- package/dist/esm/co-accordion.entry.js +3 -3
- package/dist/esm/co-action-bar.entry.js +3 -3
- package/dist/esm/co-app-shell.entry.js +3 -3
- package/dist/esm/co-audio-player.entry.js +4 -4
- package/dist/esm/co-autocomplete.entry.js +12 -5
- package/dist/esm/co-avatar-group.entry.js +3 -3
- package/dist/esm/co-avatar.entry.js +7 -4
- package/dist/esm/co-badge.entry.js +2 -2
- package/dist/esm/co-bottom-sheet.entry.js +5 -5
- package/dist/esm/co-breadcrumb-item.entry.js +3 -3
- package/dist/esm/co-breadcrumb.entry.js +2 -2
- package/dist/esm/co-button-group.entry.js +4 -3
- package/dist/esm/co-button.entry.js +9 -7
- package/dist/esm/co-calendar-month_2.entry.js +16 -4
- package/dist/esm/co-calendar_3.entry.js +76 -27
- package/dist/esm/co-card.entry.js +3 -3
- package/dist/esm/co-carousel-item.entry.js +2 -2
- package/dist/esm/co-carousel.entry.js +6 -3
- package/dist/esm/co-checkbox-group.entry.js +4 -4
- package/dist/esm/co-checkbox.entry.js +13 -5
- package/dist/esm/co-chip_2.entry.js +20 -7
- package/dist/esm/co-color-area.entry.js +167 -0
- package/dist/esm/co-color-picker.entry.js +5 -5
- package/dist/esm/co-color-slider.entry.js +187 -0
- package/dist/esm/co-column-picker.entry.js +23 -3
- package/dist/esm/co-combobox.entry.js +5 -5
- package/dist/esm/co-command-search.entry.js +5 -5
- package/dist/esm/co-data-table-pagination.entry.js +5 -5
- package/dist/esm/co-data-table.entry.js +3 -3
- package/dist/esm/co-date-picker.entry.js +10 -2
- package/dist/esm/co-date-range-picker.entry.js +11 -2
- package/dist/esm/co-date-range.entry.js +8 -2
- package/dist/esm/co-date-time-picker.entry.js +11 -4
- package/dist/esm/co-document-editor.entry.js +1165 -0
- package/dist/esm/co-drive-card.entry.js +2 -2
- package/dist/esm/co-drop-zone.entry.js +2 -2
- package/dist/esm/co-emoji-picker.entry.js +3 -3
- package/dist/esm/co-empty-state.entry.js +3 -3
- package/dist/esm/co-event-calendar.entry.js +5 -3
- package/dist/esm/co-event-popover.entry.js +7 -3
- package/dist/esm/co-fab.entry.js +7 -3
- package/dist/esm/co-file-field.entry.js +12 -8
- package/dist/esm/co-file-type-tile.entry.js +3 -3
- package/dist/esm/co-gradient-bar.entry.js +218 -0
- package/dist/esm/co-helper-text.entry.js +3 -3
- package/dist/esm/co-icon-button.entry.js +48 -9
- package/dist/esm/co-icon.entry.js +3 -3
- package/dist/esm/co-input.entry.js +14 -8
- package/dist/esm/co-json-field.entry.js +10 -5
- package/dist/esm/{co-tooltip.entry.js → co-kbd_2.entry.js} +194 -7
- package/dist/esm/co-lightbox.entry.js +5 -5
- package/dist/esm/co-list-footer.entry.js +2 -2
- package/dist/esm/co-list-item.entry.js +5 -5
- package/dist/esm/co-loader.entry.js +1 -1
- package/dist/esm/co-media-thumb.entry.js +3 -3
- package/dist/esm/co-menu-divider.entry.js +3 -3
- package/dist/esm/co-menu-item.entry.js +39 -41
- package/dist/esm/co-menu.entry.js +81 -5
- package/dist/esm/co-modal.entry.js +350 -7
- package/dist/esm/co-navbar.entry.js +3 -3
- package/dist/esm/co-number-field.entry.js +11 -5
- package/dist/esm/co-overlay.entry.js +8 -4
- package/dist/esm/co-page-header.entry.js +2 -2
- package/dist/esm/co-phone-field.entry.js +3 -3
- package/dist/esm/co-popover.entry.js +69 -6
- package/dist/esm/co-progress-bar.entry.js +3 -3
- package/dist/esm/co-progress-circle.entry.js +3 -3
- package/dist/esm/co-provider-logo_2.entry.js +2 -2
- package/dist/esm/co-radio-group.entry.js +4 -4
- package/dist/esm/co-radio.entry.js +4 -4
- package/dist/esm/co-rating.entry.js +11 -4
- package/dist/esm/co-ref-field.entry.js +14 -5
- package/dist/esm/co-rich-text-editor.entry.js +40 -92
- package/dist/esm/co-rich-text-toolbar.entry.js +80 -20
- package/dist/esm/co-rich-text-viewer.entry.js +9 -2
- package/dist/esm/co-row.entry.js +3 -3
- package/dist/esm/co-segmented-bar.entry.js +3 -3
- package/dist/esm/co-select.entry.js +171 -29
- package/dist/esm/co-separator.entry.js +2 -2
- package/dist/esm/co-sidebar-nav.entry.js +20 -5
- package/dist/esm/co-sidebar.entry.js +3 -3
- package/dist/esm/co-slider.entry.js +209 -23
- package/dist/esm/co-swatch-grid.entry.js +119 -0
- package/dist/esm/co-switch.entry.js +5 -5
- package/dist/esm/co-tab-group.entry.js +113 -4
- package/dist/esm/co-tab.entry.js +15 -5
- package/dist/esm/co-tags-field.entry.js +13 -8
- package/dist/esm/co-textarea.entry.js +6 -6
- package/dist/esm/co-tile.entry.js +59 -0
- package/dist/esm/co-time-field.entry.js +5 -2
- package/dist/esm/co-toast.entry.js +3 -3
- package/dist/esm/co-toggle-button-group.entry.js +29 -5
- package/dist/esm/co-toggle-button.entry.js +70 -6
- package/dist/esm/co-transfer-list.entry.js +7 -3
- package/dist/esm/co-tree-item.entry.js +108 -0
- package/dist/esm/co-video.entry.js +11 -3
- package/dist/esm/cobalt.js +3 -3
- package/dist/esm/{color-BRbgGqLw.js → color-BVGGRfNG.js} +10 -6
- package/dist/esm/{fieldChip-uyggU8VV.js → fieldChip-B2ctp2m6.js} +1 -1
- package/dist/esm/gradientStops-DDK0y8ra.js +145 -0
- package/dist/esm/hsv-COJdaKBU.js +90 -0
- package/dist/esm/index-Cpo8HTwr.js +142 -0
- package/dist/esm/{index-DH5lfRNj.js → index-DJkaRtbb.js} +67 -28
- package/dist/esm/loader.js +3 -3
- package/dist/esm/{index-BBIYyvq-.js → pagination-D9OfZUnY.js} +1728 -297
- package/dist/esm/{positioning-DFHRS9cJ.js → positioning-BtliEQAT.js} +45 -19
- package/dist/esm/{requiredMark-BCJUuZvC.js → requiredMark-D5C5NzOE.js} +1 -1
- package/dist/esm/rich-text-host-BmdKHBZP.js +111 -0
- package/dist/esm/{richTextI18n-BYKAgwq3.js → richTextI18n-xnrKkNWQ.js} +45 -0
- package/dist/esm/submenu-DU-KOQ8L.js +57 -0
- package/dist/esm/{toolbar-config-BAYo-RBt.js → toolbar-config-CRxTFT_z.js} +32 -0
- package/dist/types/components/co-accordion/co-accordion.d.ts +10 -0
- package/dist/types/components/co-action-bar/co-action-bar.d.ts +1 -0
- package/dist/types/components/co-app-shell/co-app-shell.d.ts +11 -0
- package/dist/types/components/co-audio-player/co-audio-player.d.ts +16 -0
- package/dist/types/components/co-autocomplete/co-autocomplete.d.ts +21 -0
- package/dist/types/components/co-avatar/co-avatar.d.ts +11 -2
- package/dist/types/components/co-avatar-group/co-avatar-group.d.ts +5 -0
- package/dist/types/components/co-badge/co-badge.d.ts +7 -0
- package/dist/types/components/co-bottom-sheet/co-bottom-sheet.d.ts +9 -0
- package/dist/types/components/co-breadcrumb/co-breadcrumb.d.ts +4 -0
- package/dist/types/components/co-breadcrumb-item/co-breadcrumb-item.d.ts +6 -0
- package/dist/types/components/co-button/co-button.d.ts +12 -4
- package/dist/types/components/co-button-group/co-button-group.d.ts +7 -0
- package/dist/types/components/co-calendar/calendarMarks.d.ts +15 -0
- package/dist/types/components/co-calendar/co-calendar.d.ts +18 -0
- package/dist/types/components/co-calendar-timegrid/co-calendar-timegrid.d.ts +23 -0
- package/dist/types/components/co-card/co-card.d.ts +9 -0
- package/dist/types/components/co-carousel/co-carousel.d.ts +12 -0
- package/dist/types/components/co-checkbox/co-checkbox.d.ts +15 -0
- package/dist/types/components/co-checkbox-group/co-checkbox-group.d.ts +5 -0
- package/dist/types/components/co-chip/co-chip.d.ts +13 -0
- package/dist/types/components/co-color-area/co-color-area.d.ts +65 -0
- package/dist/types/components/co-color-picker/co-color-picker.d.ts +2 -0
- package/dist/types/components/co-color-slider/co-color-slider.d.ts +62 -0
- package/dist/types/components/co-column-picker/co-column-picker.d.ts +32 -0
- package/dist/types/components/co-combobox/co-combobox.d.ts +14 -0
- package/dist/types/components/co-command-search/co-command-search.d.ts +15 -0
- package/dist/types/components/co-data-table/co-data-table.d.ts +5 -0
- package/dist/types/components/co-data-table-pagination/co-data-table-pagination.d.ts +12 -0
- package/dist/types/components/co-date-field/co-date-field.d.ts +11 -0
- package/dist/types/components/co-date-picker/co-date-picker.d.ts +30 -0
- package/dist/types/components/co-date-range/co-date-range.d.ts +12 -0
- package/dist/types/components/co-date-range-picker/co-date-range-picker.d.ts +33 -0
- package/dist/types/components/co-date-time-picker/co-date-time-picker.d.ts +22 -1
- package/dist/types/components/co-document-editor/change-throttle.d.ts +9 -0
- package/dist/types/components/co-document-editor/co-document-editor.d.ts +284 -0
- package/dist/types/components/co-document-editor/document-props.d.ts +6 -0
- package/dist/types/components/co-document-editor/header-tools.d.ts +11 -0
- package/dist/types/components/co-document-editor/image-bar.d.ts +50 -0
- package/dist/types/components/co-document-editor/page-styles.d.ts +1 -0
- package/dist/types/components/co-document-editor/zoom.d.ts +26 -0
- package/dist/types/components/co-drawer/co-drawer.d.ts +13 -0
- package/dist/types/components/co-drive-card/co-drive-card.d.ts +13 -0
- package/dist/types/components/co-drop-zone/co-drop-zone.d.ts +6 -1
- package/dist/types/components/co-emoji-picker/co-emoji-picker.d.ts +9 -0
- package/dist/types/components/co-empty-state/co-empty-state.d.ts +2 -0
- package/dist/types/components/co-event-calendar/co-event-calendar.d.ts +12 -16
- package/dist/types/components/co-event-popover/co-event-popover.d.ts +13 -0
- package/dist/types/components/co-fab/co-fab.d.ts +11 -0
- package/dist/types/components/co-file-field/co-file-field.d.ts +6 -0
- package/dist/types/components/co-file-type-tile/co-file-type-tile.d.ts +7 -0
- package/dist/types/components/co-gradient-bar/co-gradient-bar.d.ts +77 -0
- package/dist/types/components/co-helper-text/co-helper-text.d.ts +2 -0
- package/dist/types/components/co-icon/co-icon.d.ts +4 -0
- package/dist/types/components/co-icon-button/co-icon-button.d.ts +39 -2
- package/dist/types/components/co-input/co-input.d.ts +25 -5
- package/dist/types/components/co-json-field/co-json-field.d.ts +11 -0
- package/dist/types/components/co-kbd/co-kbd.d.ts +50 -0
- package/dist/types/components/co-list-footer/co-list-footer.d.ts +3 -0
- package/dist/types/components/co-list-item/co-list-item.d.ts +3 -0
- package/dist/types/components/co-loader/co-loader.d.ts +5 -0
- package/dist/types/components/co-media-thumb/co-media-thumb.d.ts +7 -0
- package/dist/types/components/co-menu/co-menu.d.ts +42 -1
- package/dist/types/components/co-menu-divider/co-menu-divider.d.ts +1 -0
- package/dist/types/components/co-menu-item/co-menu-item.d.ts +19 -0
- package/dist/types/components/co-modal/co-modal.d.ts +126 -5
- package/dist/types/components/co-navbar/co-navbar.d.ts +2 -0
- package/dist/types/components/co-number-field/co-number-field.d.ts +20 -0
- package/dist/types/components/co-option-list/co-option-list.d.ts +29 -1
- package/dist/types/components/co-option-list/optionListLogic.d.ts +3 -0
- package/dist/types/components/co-overlay/co-overlay.d.ts +10 -0
- package/dist/types/components/co-page-header/co-page-header.d.ts +3 -0
- package/dist/types/components/co-popover/co-popover.d.ts +51 -0
- package/dist/types/components/co-progress-bar/co-progress-bar.d.ts +3 -0
- package/dist/types/components/co-progress-circle/co-progress-circle.d.ts +3 -0
- package/dist/types/components/co-provider-logo/co-provider-logo.d.ts +3 -0
- package/dist/types/components/co-radio/co-radio.d.ts +8 -0
- package/dist/types/components/co-radio-group/co-radio-group.d.ts +5 -0
- package/dist/types/components/co-rating/co-rating.d.ts +15 -0
- package/dist/types/components/co-ref-field/co-ref-field.d.ts +42 -0
- package/dist/types/components/co-rich-text-editor/co-rich-text-editor.d.ts +31 -5
- package/dist/types/components/co-rich-text-toolbar/co-rich-text-toolbar.d.ts +20 -2
- package/dist/types/components/co-rich-text-viewer/co-rich-text-viewer.d.ts +8 -0
- package/dist/types/components/co-row/co-row.d.ts +3 -0
- package/dist/types/components/co-segmented-bar/co-segmented-bar.d.ts +6 -0
- package/dist/types/components/co-select/co-select.d.ts +73 -5
- package/dist/types/components/co-select/virtualRows.d.ts +44 -0
- package/dist/types/components/co-separator/co-separator.d.ts +7 -0
- package/dist/types/components/co-sidebar/co-sidebar.d.ts +8 -0
- package/dist/types/components/co-sidebar-nav/co-sidebar-nav.d.ts +1 -0
- package/dist/types/components/co-skeleton/co-skeleton.d.ts +3 -0
- package/dist/types/components/co-slider/co-slider.d.ts +160 -1
- package/dist/types/components/co-swatch-grid/co-swatch-grid.d.ts +38 -0
- package/dist/types/components/co-switch/co-switch.d.ts +9 -0
- package/dist/types/components/co-tab/co-tab.d.ts +20 -2
- package/dist/types/components/co-tab-group/co-tab-group.d.ts +46 -0
- package/dist/types/components/co-tab-group/revealTab.d.ts +29 -0
- package/dist/types/components/co-tags-field/co-tags-field.d.ts +11 -0
- package/dist/types/components/co-tile/co-tile.d.ts +45 -0
- package/dist/types/components/co-time-field/co-time-field.d.ts +5 -0
- package/dist/types/components/co-toast/co-toast.d.ts +9 -0
- package/dist/types/components/co-toggle-button/co-toggle-button.d.ts +45 -2
- package/dist/types/components/co-toggle-button-group/co-toggle-button-group.d.ts +30 -2
- package/dist/types/components/co-tooltip/co-tooltip.d.ts +22 -0
- package/dist/types/components/co-transfer-list/co-transfer-list.d.ts +12 -0
- package/dist/types/components/co-tree-item/co-tree-item.d.ts +75 -0
- package/dist/types/components/co-tree-item/treeItemI18n.d.ts +6 -0
- package/dist/types/components/co-video/co-video.d.ts +31 -0
- package/dist/types/components.d.ts +3905 -85
- package/dist/types/utils/color.d.ts +9 -1
- package/dist/types/utils/dragMove.d.ts +63 -0
- package/dist/types/utils/gradientBarI18n.d.ts +8 -0
- package/dist/types/utils/gradientStops.d.ts +63 -0
- package/dist/types/utils/hsv.d.ts +44 -0
- package/dist/types/utils/kbdI18n.d.ts +25 -0
- package/dist/types/utils/positioning.d.ts +24 -0
- package/dist/types/utils/rich-text-host.d.ts +41 -0
- package/dist/types/utils/richTextI18n.d.ts +15 -0
- package/dist/types/utils/submenu.d.ts +16 -2
- package/dist/types/utils/swatchGridI18n.d.ts +6 -0
- package/dist/types/utils/test/fake-block-layout.d.ts +7 -0
- package/dist/types/utils/test/prosemirror-dom-shim.d.ts +1 -0
- package/dist/types/utils/test/shared-contract-css.d.ts +9 -0
- package/package.json +5 -5
- package/dist/cobalt/p-0678c797.entry.js +0 -1
- package/dist/cobalt/p-1d3a79af.entry.js +0 -1
- package/dist/cobalt/p-216a63ee.entry.js +0 -1
- package/dist/cobalt/p-3d31c575.entry.js +0 -1
- package/dist/cobalt/p-416795f5.entry.js +0 -1
- package/dist/cobalt/p-56551580.entry.js +0 -1
- package/dist/cobalt/p-58137c9e.entry.js +0 -1
- package/dist/cobalt/p-5a3e4c81.entry.js +0 -1
- package/dist/cobalt/p-5c756787.entry.js +0 -1
- package/dist/cobalt/p-67f3b9d6.entry.js +0 -1
- package/dist/cobalt/p-6a4f3179.entry.js +0 -1
- package/dist/cobalt/p-71cbc53c.entry.js +0 -1
- package/dist/cobalt/p-72e52af7.entry.js +0 -1
- package/dist/cobalt/p-8530ad16.entry.js +0 -1
- package/dist/cobalt/p-8a74bf7d.entry.js +0 -1
- package/dist/cobalt/p-8e05b979.entry.js +0 -1
- package/dist/cobalt/p-8ebc0c12.entry.js +0 -1
- package/dist/cobalt/p-8f2199ff.entry.js +0 -1
- package/dist/cobalt/p-9246e09c.entry.js +0 -1
- package/dist/cobalt/p-99a655f6.entry.js +0 -1
- package/dist/cobalt/p-BYKAgwq3.js +0 -1
- package/dist/cobalt/p-CJW9H3Gi.js +0 -1
- package/dist/cobalt/p-DFHRS9cJ.js +0 -1
- package/dist/cobalt/p-DH5lfRNj.js +0 -2
- package/dist/cobalt/p-a1b422ca.entry.js +0 -1
- package/dist/cobalt/p-ade07307.entry.js +0 -1
- package/dist/cobalt/p-b0762fd8.entry.js +0 -1
- package/dist/cobalt/p-b698188c.entry.js +0 -1
- package/dist/cobalt/p-bde32f8b.entry.js +0 -1
- package/dist/cobalt/p-d375014b.entry.js +0 -1
- package/dist/cobalt/p-db805569.entry.js +0 -1
- package/dist/cobalt/p-e3aae282.entry.js +0 -1
- package/dist/cobalt/p-e49a564c.entry.js +0 -1
- package/dist/cobalt/p-ef301976.entry.js +0 -1
- package/dist/cobalt/p-fMqVDypp.js +0 -1
- package/dist/components/p-2EOI1nrz.js +0 -1
- package/dist/components/p-7TncUlLN.js +0 -1
- package/dist/components/p-B4NCaKrR.js +0 -1
- package/dist/components/p-BGDqldEg.js +0 -1
- package/dist/components/p-BJh68Jqe.js +0 -1
- package/dist/components/p-BrAFTkAn.js +0 -1
- package/dist/components/p-Bsh0JMGf.js +0 -1
- package/dist/components/p-CJW9H3Gi.js +0 -1
- package/dist/components/p-CWCYYQrF.js +0 -1
- package/dist/components/p-D9T7zKeL.js +0 -1
- package/dist/components/p-DFHRS9cJ.js +0 -1
- package/dist/components/p-DTPYZwaZ.js +0 -1
- package/dist/components/p-Dcg4krSX.js +0 -1
- package/dist/components/p-Dh8ffSjK.js +0 -1
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var purify_es = require('./purify.es-DX41ZWS2.js');
|
|
4
|
-
var toolbarConfig = require('./toolbar-config-CYACt9hh.js');
|
|
5
4
|
|
|
6
5
|
// ::- Persistent data structure representing an ordered mapping from
|
|
7
6
|
// strings to values, with some convenient update methods.
|
|
@@ -2657,7 +2656,7 @@ A DOM parser represents a strategy for parsing DOM content into a
|
|
|
2657
2656
|
ProseMirror document conforming to a given schema. Its behavior is
|
|
2658
2657
|
defined by an array of [rules](https://prosemirror.net/docs/ref/#model.ParseRule).
|
|
2659
2658
|
*/
|
|
2660
|
-
class DOMParser {
|
|
2659
|
+
let DOMParser$1 = class DOMParser {
|
|
2661
2660
|
/**
|
|
2662
2661
|
Create a parser that targets the given schema, using the given
|
|
2663
2662
|
parsing rules.
|
|
@@ -2808,7 +2807,7 @@ class DOMParser {
|
|
|
2808
2807
|
return schema.cached.domParser ||
|
|
2809
2808
|
(schema.cached.domParser = new DOMParser(schema, DOMParser.schemaRules(schema)));
|
|
2810
2809
|
}
|
|
2811
|
-
}
|
|
2810
|
+
};
|
|
2812
2811
|
const blockTags = {
|
|
2813
2812
|
address: true, article: true, aside: true, blockquote: true, canvas: true,
|
|
2814
2813
|
dd: true, div: true, dl: true, fieldset: true, figcaption: true, figure: true,
|
|
@@ -10007,7 +10006,7 @@ function skipIgnoredNodesBefore(view) {
|
|
|
10007
10006
|
break;
|
|
10008
10007
|
}
|
|
10009
10008
|
}
|
|
10010
|
-
else if (isBlockNode(node)) {
|
|
10009
|
+
else if (isBlockNode$1(node)) {
|
|
10011
10010
|
break;
|
|
10012
10011
|
}
|
|
10013
10012
|
else {
|
|
@@ -10055,7 +10054,7 @@ function skipIgnoredNodesAfter(view) {
|
|
|
10055
10054
|
else
|
|
10056
10055
|
break;
|
|
10057
10056
|
}
|
|
10058
|
-
else if (isBlockNode(node)) {
|
|
10057
|
+
else if (isBlockNode$1(node)) {
|
|
10059
10058
|
break;
|
|
10060
10059
|
}
|
|
10061
10060
|
else {
|
|
@@ -10081,7 +10080,7 @@ function skipIgnoredNodesAfter(view) {
|
|
|
10081
10080
|
if (moveNode)
|
|
10082
10081
|
setSelFocus(view, moveNode, moveOffset);
|
|
10083
10082
|
}
|
|
10084
|
-
function isBlockNode(dom) {
|
|
10083
|
+
function isBlockNode$1(dom) {
|
|
10085
10084
|
let desc = dom.pmViewDesc;
|
|
10086
10085
|
return desc && desc.node && desc.node.isBlock;
|
|
10087
10086
|
}
|
|
@@ -10361,7 +10360,7 @@ function parseFromClipboard(view, text, html, plainText, $context) {
|
|
|
10361
10360
|
dom = child;
|
|
10362
10361
|
}
|
|
10363
10362
|
if (!slice) {
|
|
10364
|
-
let parser = view.someProp("clipboardParser") || view.someProp("domParser") || DOMParser.fromSchema(view.state.schema);
|
|
10363
|
+
let parser = view.someProp("clipboardParser") || view.someProp("domParser") || DOMParser$1.fromSchema(view.state.schema);
|
|
10365
10364
|
slice = parser.parseSlice(dom, {
|
|
10366
10365
|
preserveWhitespace: !!(asText || sliceData),
|
|
10367
10366
|
context: $context,
|
|
@@ -12462,7 +12461,7 @@ function parseBetween(view, from_, to_) {
|
|
|
12462
12461
|
}
|
|
12463
12462
|
}
|
|
12464
12463
|
let startDoc = view.state.doc;
|
|
12465
|
-
let parser = view.someProp("domParser") || DOMParser.fromSchema(view.state.schema);
|
|
12464
|
+
let parser = view.someProp("domParser") || DOMParser$1.fromSchema(view.state.schema);
|
|
12466
12465
|
let $from = startDoc.resolve(from);
|
|
12467
12466
|
let sel = null, doc = parser.parse(parent, {
|
|
12468
12467
|
topNode: $from.parent,
|
|
@@ -14324,12 +14323,12 @@ function createNodeFromContent(content, schema, options) {
|
|
|
14324
14323
|
})
|
|
14325
14324
|
});
|
|
14326
14325
|
if (options.slice) {
|
|
14327
|
-
DOMParser.fromSchema(contentCheckSchema).parseSlice(
|
|
14326
|
+
DOMParser$1.fromSchema(contentCheckSchema).parseSlice(
|
|
14328
14327
|
elementFromString(content),
|
|
14329
14328
|
options.parseOptions
|
|
14330
14329
|
);
|
|
14331
14330
|
} else {
|
|
14332
|
-
DOMParser.fromSchema(contentCheckSchema).parse(
|
|
14331
|
+
DOMParser$1.fromSchema(contentCheckSchema).parse(
|
|
14333
14332
|
elementFromString(content),
|
|
14334
14333
|
options.parseOptions
|
|
14335
14334
|
);
|
|
@@ -14340,7 +14339,7 @@ function createNodeFromContent(content, schema, options) {
|
|
|
14340
14339
|
});
|
|
14341
14340
|
}
|
|
14342
14341
|
}
|
|
14343
|
-
const parser = DOMParser.fromSchema(schema);
|
|
14342
|
+
const parser = DOMParser$1.fromSchema(schema);
|
|
14344
14343
|
if (options.slice) {
|
|
14345
14344
|
return parser.parseSlice(elementFromString(content), options.parseOptions).content;
|
|
14346
14345
|
}
|
|
@@ -34996,6 +34995,799 @@ var Subscript = Mark.create({
|
|
|
34996
34995
|
}
|
|
34997
34996
|
});
|
|
34998
34997
|
|
|
34998
|
+
function sanitizeFieldName(raw) {
|
|
34999
|
+
return String(raw ?? '')
|
|
35000
|
+
.trim()
|
|
35001
|
+
.replace(/\s+/g, '_')
|
|
35002
|
+
.replace(/[^\p{L}\p{N}_.]/gu, '_');
|
|
35003
|
+
}
|
|
35004
|
+
/** Admite un grupo `[…]` al final del contenido (enum en JSON). Nueva instancia por llamada (flag g). */
|
|
35005
|
+
function fieldTokenRegex() {
|
|
35006
|
+
return /\[\[\s*([^[\]]+?(?:\[[^[\]]*\])?)\s*\]\]/g;
|
|
35007
|
+
}
|
|
35008
|
+
function parseFieldToken(inner) {
|
|
35009
|
+
const parts = String(inner ?? '').split('|').map((p) => p.trim());
|
|
35010
|
+
let raw = parts[0] ?? '';
|
|
35011
|
+
const required = raw.endsWith('*');
|
|
35012
|
+
if (required)
|
|
35013
|
+
raw = raw.slice(0, -1);
|
|
35014
|
+
const name = sanitizeFieldName(raw);
|
|
35015
|
+
if (!name)
|
|
35016
|
+
return null;
|
|
35017
|
+
const type = parts[1] || 'string';
|
|
35018
|
+
let values = null;
|
|
35019
|
+
if (parts[2]?.startsWith('enum:')) {
|
|
35020
|
+
const rawEnum = parts[2].slice(5).trim();
|
|
35021
|
+
try {
|
|
35022
|
+
const parsed = JSON.parse(rawEnum);
|
|
35023
|
+
values = Array.isArray(parsed) ? parsed.map(String) : null;
|
|
35024
|
+
}
|
|
35025
|
+
catch {
|
|
35026
|
+
values = rawEnum.split(',').map((v) => v.trim()).filter(Boolean);
|
|
35027
|
+
}
|
|
35028
|
+
}
|
|
35029
|
+
return { name, required, type, enum: values };
|
|
35030
|
+
}
|
|
35031
|
+
|
|
35032
|
+
/** Meta de las transacciones que escribe el HOST (valores): no son edición del usuario. */
|
|
35033
|
+
const FIELD_SYNC_META = 'coFieldSync';
|
|
35034
|
+
function parseEnumAttr(raw) {
|
|
35035
|
+
if (!raw)
|
|
35036
|
+
return null;
|
|
35037
|
+
try {
|
|
35038
|
+
const v = JSON.parse(raw);
|
|
35039
|
+
return Array.isArray(v) ? v.map(String) : null;
|
|
35040
|
+
}
|
|
35041
|
+
catch {
|
|
35042
|
+
return null;
|
|
35043
|
+
}
|
|
35044
|
+
}
|
|
35045
|
+
/** Lista de campos en orden de primera aparición (sin repetidos). Acepta un doc de ProseMirror o su JSON. */
|
|
35046
|
+
function collectFields(doc, into = []) {
|
|
35047
|
+
const index = new Map(into.map((f, i) => [f.name, i]));
|
|
35048
|
+
const visit = (attrs) => {
|
|
35049
|
+
const name = attrs?.name;
|
|
35050
|
+
if (!name)
|
|
35051
|
+
return;
|
|
35052
|
+
const at = index.get(name);
|
|
35053
|
+
if (at === undefined) {
|
|
35054
|
+
index.set(name, into.length);
|
|
35055
|
+
into.push({ name, required: !!attrs.required, type: attrs.type || 'string', enum: attrs.enum ?? null });
|
|
35056
|
+
}
|
|
35057
|
+
else if (attrs.required) {
|
|
35058
|
+
into[at].required = true;
|
|
35059
|
+
}
|
|
35060
|
+
};
|
|
35061
|
+
if (typeof doc.descendants === 'function') {
|
|
35062
|
+
doc.descendants((node) => {
|
|
35063
|
+
if (node.type.name === 'mergeField') {
|
|
35064
|
+
visit(node.attrs);
|
|
35065
|
+
return false;
|
|
35066
|
+
}
|
|
35067
|
+
return true;
|
|
35068
|
+
});
|
|
35069
|
+
}
|
|
35070
|
+
else {
|
|
35071
|
+
const walk = (node) => {
|
|
35072
|
+
if (!node)
|
|
35073
|
+
return;
|
|
35074
|
+
if (node.type === 'mergeField')
|
|
35075
|
+
visit(node.attrs ?? {});
|
|
35076
|
+
node.content?.forEach(walk);
|
|
35077
|
+
};
|
|
35078
|
+
walk(doc);
|
|
35079
|
+
}
|
|
35080
|
+
return into;
|
|
35081
|
+
}
|
|
35082
|
+
/** Textblocks tocados por las transacciones (para no recorrer todo el doc por tecla). */
|
|
35083
|
+
function touchedTextblocks(transactions, state) {
|
|
35084
|
+
let ranges = [];
|
|
35085
|
+
transactions.forEach((tr) => {
|
|
35086
|
+
// Lo tocado por transacciones anteriores se lleva a las posiciones de ésta.
|
|
35087
|
+
ranges = ranges.map(([a, b]) => [tr.mapping.map(a, -1), tr.mapping.map(b, 1)]);
|
|
35088
|
+
if (!tr.docChanged)
|
|
35089
|
+
return;
|
|
35090
|
+
tr.mapping.maps.forEach((map, i) => {
|
|
35091
|
+
map.forEach((_oldStart, _oldEnd, newStart, newEnd) => {
|
|
35092
|
+
const rest = tr.mapping.slice(i + 1);
|
|
35093
|
+
ranges.push([rest.map(newStart, -1), rest.map(newEnd, 1)]);
|
|
35094
|
+
});
|
|
35095
|
+
});
|
|
35096
|
+
});
|
|
35097
|
+
const out = new Set();
|
|
35098
|
+
const size = state.doc.content.size;
|
|
35099
|
+
ranges.forEach(([from, to]) => {
|
|
35100
|
+
state.doc.nodesBetween(Math.max(0, from), Math.min(size, to), (node, pos) => {
|
|
35101
|
+
if (node.isTextblock) {
|
|
35102
|
+
out.add(pos);
|
|
35103
|
+
return false;
|
|
35104
|
+
}
|
|
35105
|
+
return true;
|
|
35106
|
+
});
|
|
35107
|
+
});
|
|
35108
|
+
return Array.from(out);
|
|
35109
|
+
}
|
|
35110
|
+
const MergeField = Node3.create({
|
|
35111
|
+
name: 'mergeField',
|
|
35112
|
+
group: 'inline',
|
|
35113
|
+
inline: true,
|
|
35114
|
+
atom: true,
|
|
35115
|
+
selectable: true,
|
|
35116
|
+
addOptions() {
|
|
35117
|
+
return { renameLabel: 'Field name' };
|
|
35118
|
+
},
|
|
35119
|
+
addAttributes() {
|
|
35120
|
+
return {
|
|
35121
|
+
name: { default: '', parseHTML: (el) => el.getAttribute('data-variable') || '', rendered: false },
|
|
35122
|
+
value: { default: '', parseHTML: (el) => el.getAttribute('data-value') ?? '', rendered: false },
|
|
35123
|
+
required: { default: false, parseHTML: (el) => el.getAttribute('data-required') === 'true', rendered: false },
|
|
35124
|
+
type: { default: 'string', parseHTML: (el) => el.getAttribute('data-type') || 'string', rendered: false },
|
|
35125
|
+
enum: { default: null, parseHTML: (el) => parseEnumAttr(el.getAttribute('data-enum')), rendered: false },
|
|
35126
|
+
};
|
|
35127
|
+
},
|
|
35128
|
+
// Prioridad 100: gana a las marcas `span[style]` (color/tamaño), como en V1.
|
|
35129
|
+
parseHTML() {
|
|
35130
|
+
return [{ tag: 'span[data-variable]', priority: 100 }];
|
|
35131
|
+
},
|
|
35132
|
+
// Forma canónica (spec §3.4): SIN estilos (D9), atributos en orden fijo.
|
|
35133
|
+
renderHTML({ node }) {
|
|
35134
|
+
const { name, value, type, required } = node.attrs;
|
|
35135
|
+
const attrs = {
|
|
35136
|
+
class: 'variable-node',
|
|
35137
|
+
'data-variable': name,
|
|
35138
|
+
'data-value': value ?? '',
|
|
35139
|
+
'data-type': type || 'string',
|
|
35140
|
+
'data-required': required ? 'true' : 'false',
|
|
35141
|
+
};
|
|
35142
|
+
if (node.attrs.enum)
|
|
35143
|
+
attrs['data-enum'] = JSON.stringify(node.attrs.enum);
|
|
35144
|
+
attrs.contenteditable = 'false';
|
|
35145
|
+
return ['span', attrs, value || `[[${name}]]`];
|
|
35146
|
+
},
|
|
35147
|
+
renderText({ node }) {
|
|
35148
|
+
return node.attrs.value || `[[${node.attrs.name}]]`;
|
|
35149
|
+
},
|
|
35150
|
+
addNodeView() {
|
|
35151
|
+
const renameLabel = this.options.renameLabel;
|
|
35152
|
+
return ({ node, getPos, editor }) => {
|
|
35153
|
+
const dom = document.createElement('span');
|
|
35154
|
+
dom.className = 'co-doc-field';
|
|
35155
|
+
dom.contentEditable = 'false';
|
|
35156
|
+
let current = node;
|
|
35157
|
+
let editing = false;
|
|
35158
|
+
const paint = (n) => {
|
|
35159
|
+
dom.textContent = n.attrs.value || `[[${n.attrs.name}]]`;
|
|
35160
|
+
dom.classList.toggle('co-doc-field--empty', !n.attrs.value);
|
|
35161
|
+
dom.classList.toggle('co-doc-field--required', !!n.attrs.required);
|
|
35162
|
+
dom.setAttribute('data-variable', n.attrs.name);
|
|
35163
|
+
};
|
|
35164
|
+
const startRename = () => {
|
|
35165
|
+
if (editing || !editor.isEditable)
|
|
35166
|
+
return;
|
|
35167
|
+
editing = true;
|
|
35168
|
+
const input = document.createElement('input');
|
|
35169
|
+
input.className = 'co-doc-field__input';
|
|
35170
|
+
input.value = current.attrs.name;
|
|
35171
|
+
input.setAttribute('aria-label', renameLabel);
|
|
35172
|
+
dom.textContent = '';
|
|
35173
|
+
dom.appendChild(input);
|
|
35174
|
+
input.focus();
|
|
35175
|
+
input.select();
|
|
35176
|
+
let done = false;
|
|
35177
|
+
const finish = (commit) => {
|
|
35178
|
+
if (done)
|
|
35179
|
+
return;
|
|
35180
|
+
done = true;
|
|
35181
|
+
editing = false;
|
|
35182
|
+
const next = sanitizeFieldName(input.value);
|
|
35183
|
+
const pos = typeof getPos === 'function' ? getPos() : undefined;
|
|
35184
|
+
if (commit && next && next !== current.attrs.name && typeof pos === 'number') {
|
|
35185
|
+
// Como V1: el campo renombrado arranca vacío (solo ESTE nodo).
|
|
35186
|
+
editor.view.dispatch(editor.state.tr.setNodeMarkup(pos, undefined, { ...current.attrs, name: next, value: '' }));
|
|
35187
|
+
}
|
|
35188
|
+
else {
|
|
35189
|
+
paint(current);
|
|
35190
|
+
}
|
|
35191
|
+
};
|
|
35192
|
+
input.addEventListener('keydown', (ev) => {
|
|
35193
|
+
ev.stopPropagation(); // Esc no debe cerrar el overlay del host
|
|
35194
|
+
if (ev.key === 'Enter') {
|
|
35195
|
+
ev.preventDefault();
|
|
35196
|
+
finish(true);
|
|
35197
|
+
}
|
|
35198
|
+
else if (ev.key === 'Escape') {
|
|
35199
|
+
ev.preventDefault();
|
|
35200
|
+
finish(false);
|
|
35201
|
+
}
|
|
35202
|
+
});
|
|
35203
|
+
input.addEventListener('blur', () => finish(false));
|
|
35204
|
+
};
|
|
35205
|
+
dom.addEventListener('dblclick', (ev) => {
|
|
35206
|
+
ev.preventDefault();
|
|
35207
|
+
startRename();
|
|
35208
|
+
});
|
|
35209
|
+
paint(node);
|
|
35210
|
+
return {
|
|
35211
|
+
dom,
|
|
35212
|
+
update(next) {
|
|
35213
|
+
if (next.type.name !== 'mergeField')
|
|
35214
|
+
return false;
|
|
35215
|
+
current = next;
|
|
35216
|
+
if (!editing)
|
|
35217
|
+
paint(next);
|
|
35218
|
+
return true;
|
|
35219
|
+
},
|
|
35220
|
+
stopEvent: (ev) => ev.target instanceof HTMLInputElement,
|
|
35221
|
+
ignoreMutation: () => true,
|
|
35222
|
+
};
|
|
35223
|
+
};
|
|
35224
|
+
},
|
|
35225
|
+
addCommands() {
|
|
35226
|
+
return {
|
|
35227
|
+
insertField: (name, opts = {}) => ({ commands }) => {
|
|
35228
|
+
const clean = sanitizeFieldName(name);
|
|
35229
|
+
if (!clean)
|
|
35230
|
+
return false;
|
|
35231
|
+
return commands.insertContent({
|
|
35232
|
+
type: this.name,
|
|
35233
|
+
attrs: {
|
|
35234
|
+
name: clean,
|
|
35235
|
+
value: opts.value ?? '',
|
|
35236
|
+
required: !!opts.required,
|
|
35237
|
+
type: opts.type || 'string',
|
|
35238
|
+
enum: opts.enum ?? null,
|
|
35239
|
+
},
|
|
35240
|
+
});
|
|
35241
|
+
},
|
|
35242
|
+
setFieldValues: (values) => ({ tr, state, dispatch }) => {
|
|
35243
|
+
let changed = false;
|
|
35244
|
+
state.doc.descendants((node, pos) => {
|
|
35245
|
+
if (node.type.name !== this.name)
|
|
35246
|
+
return true;
|
|
35247
|
+
if (!Object.prototype.hasOwnProperty.call(values, node.attrs.name))
|
|
35248
|
+
return false;
|
|
35249
|
+
const next = String(values[node.attrs.name] ?? '');
|
|
35250
|
+
if (next !== node.attrs.value) {
|
|
35251
|
+
changed = true;
|
|
35252
|
+
if (dispatch)
|
|
35253
|
+
tr.setNodeMarkup(pos, undefined, { ...node.attrs, value: next });
|
|
35254
|
+
}
|
|
35255
|
+
return false;
|
|
35256
|
+
});
|
|
35257
|
+
if (!changed)
|
|
35258
|
+
return false;
|
|
35259
|
+
if (dispatch) {
|
|
35260
|
+
tr.setMeta(FIELD_SYNC_META, true);
|
|
35261
|
+
tr.setMeta('addToHistory', false);
|
|
35262
|
+
}
|
|
35263
|
+
return true;
|
|
35264
|
+
},
|
|
35265
|
+
renameField: (from, to) => ({ tr, state, dispatch }) => {
|
|
35266
|
+
const clean = sanitizeFieldName(to);
|
|
35267
|
+
if (!clean || clean === from)
|
|
35268
|
+
return false; // renombrar a sí mismo borraría los valores
|
|
35269
|
+
let changed = false;
|
|
35270
|
+
state.doc.descendants((node, pos) => {
|
|
35271
|
+
if (node.type.name !== this.name)
|
|
35272
|
+
return true;
|
|
35273
|
+
if (node.attrs.name === from) {
|
|
35274
|
+
changed = true;
|
|
35275
|
+
if (dispatch)
|
|
35276
|
+
tr.setNodeMarkup(pos, undefined, { ...node.attrs, name: clean, value: '' });
|
|
35277
|
+
}
|
|
35278
|
+
return false;
|
|
35279
|
+
});
|
|
35280
|
+
return changed;
|
|
35281
|
+
},
|
|
35282
|
+
};
|
|
35283
|
+
},
|
|
35284
|
+
addProseMirrorPlugins() {
|
|
35285
|
+
const type = this.type;
|
|
35286
|
+
return [
|
|
35287
|
+
new Plugin({
|
|
35288
|
+
key: new PluginKey('coMergeFieldTokens'),
|
|
35289
|
+
// Convierte `[[…]]` escritos o pegados en campos, solo en los textblocks tocados.
|
|
35290
|
+
appendTransaction: (transactions, _old, state) => {
|
|
35291
|
+
if (!transactions.some((t) => t.docChanged && !t.getMeta(FIELD_SYNC_META)))
|
|
35292
|
+
return null;
|
|
35293
|
+
const blocks = touchedTextblocks(transactions, state);
|
|
35294
|
+
if (!blocks.length)
|
|
35295
|
+
return null;
|
|
35296
|
+
const hits = [];
|
|
35297
|
+
blocks.forEach((blockPos) => {
|
|
35298
|
+
const block = state.doc.nodeAt(blockPos);
|
|
35299
|
+
if (!block || block.type.spec.code)
|
|
35300
|
+
return;
|
|
35301
|
+
block.forEach((child, offset) => {
|
|
35302
|
+
if (!child.isText || !child.text || !child.text.includes('[['))
|
|
35303
|
+
return;
|
|
35304
|
+
const re = fieldTokenRegex();
|
|
35305
|
+
let m;
|
|
35306
|
+
while ((m = re.exec(child.text)) !== null) {
|
|
35307
|
+
const def = parseFieldToken(m[1]);
|
|
35308
|
+
if (!def)
|
|
35309
|
+
continue;
|
|
35310
|
+
const from = blockPos + 1 + offset + m.index;
|
|
35311
|
+
hits.push({ from, to: from + m[0].length, def });
|
|
35312
|
+
}
|
|
35313
|
+
});
|
|
35314
|
+
});
|
|
35315
|
+
if (!hits.length)
|
|
35316
|
+
return null;
|
|
35317
|
+
const tr = state.tr;
|
|
35318
|
+
hits
|
|
35319
|
+
.sort((a, b) => b.from - a.from)
|
|
35320
|
+
.forEach(({ from, to, def }) => {
|
|
35321
|
+
tr.replaceWith(from, to, type.create({ ...def, value: '' }));
|
|
35322
|
+
});
|
|
35323
|
+
return tr;
|
|
35324
|
+
},
|
|
35325
|
+
}),
|
|
35326
|
+
];
|
|
35327
|
+
},
|
|
35328
|
+
});
|
|
35329
|
+
|
|
35330
|
+
/**
|
|
35331
|
+
* Marcador de firma `⟦sig:N⟧`. La forma canónica es la de V1
|
|
35332
|
+
* (tiptap-editor-html/utils/normalizeSignatureSlots.js) byte a byte: pdf.js lee
|
|
35333
|
+
* el token transparente de la capa de texto del PDF y deriva la posición.
|
|
35334
|
+
* Con font-size:1px Chromium colapsaba glifos: el token va a 8px y transparente.
|
|
35335
|
+
*
|
|
35336
|
+
* ⚠️ `editor.getHTML()` NO es la forma canónica: el DOMSerializer de ProseMirror
|
|
35337
|
+
* escribe `style` por CSSOM (`top:0` → `top: 0px;`). La forma exacta sale de
|
|
35338
|
+
* `signatureSlotHtml()` o de un serializador que escriba `style` con `setAttribute`
|
|
35339
|
+
* (`serializePrintHtml`).
|
|
35340
|
+
*/
|
|
35341
|
+
const signatureToken = (n) => `⟦sig:${n}⟧`;
|
|
35342
|
+
const SIGNATURE_TOKEN_STYLE = 'position:absolute;top:0;left:0;color:transparent;font-size:8px;line-height:1;white-space:nowrap;pointer-events:none;user-select:none';
|
|
35343
|
+
const signatureBoxStyle = (w, h) => `display:inline-block;position:relative;width:${w}px;height:${h}px;vertical-align:top`;
|
|
35344
|
+
const SIGNATURE_DEFAULT_W = 150;
|
|
35345
|
+
const SIGNATURE_DEFAULT_H = 50;
|
|
35346
|
+
function nextFreeSlot(used = []) {
|
|
35347
|
+
const taken = new Set(used);
|
|
35348
|
+
let n = 1;
|
|
35349
|
+
while (taken.has(n))
|
|
35350
|
+
n += 1;
|
|
35351
|
+
return n;
|
|
35352
|
+
}
|
|
35353
|
+
/** Spec de la forma canónica (orden de atributos = el de V1). Lo usa `renderHTML`. */
|
|
35354
|
+
function signatureSlotSpec({ slot, w, h }) {
|
|
35355
|
+
return [
|
|
35356
|
+
'span',
|
|
35357
|
+
{
|
|
35358
|
+
'data-sig-slot': String(slot),
|
|
35359
|
+
'data-w': String(w),
|
|
35360
|
+
'data-h': String(h),
|
|
35361
|
+
contenteditable: 'false',
|
|
35362
|
+
style: signatureBoxStyle(w, h),
|
|
35363
|
+
},
|
|
35364
|
+
['span', { style: SIGNATURE_TOKEN_STYLE }, signatureToken(slot)],
|
|
35365
|
+
];
|
|
35366
|
+
}
|
|
35367
|
+
/**
|
|
35368
|
+
* La forma canónica como string, armada del MISMO spec que `renderHTML` y sin pasar
|
|
35369
|
+
* por CSSOM. Los valores son números y constantes propias: no hay nada que escapar.
|
|
35370
|
+
*/
|
|
35371
|
+
function signatureSlotHtml(attrs) {
|
|
35372
|
+
const [tag, boxAttrs, [innerTag, innerAttrs, text]] = signatureSlotSpec(attrs);
|
|
35373
|
+
const attrsOf = (a) => Object.entries(a)
|
|
35374
|
+
.map(([k, v]) => ` ${k}="${v}"`)
|
|
35375
|
+
.join('');
|
|
35376
|
+
return `<${tag}${attrsOf(boxAttrs)}><${innerTag}${attrsOf(innerAttrs)}>${text}</${innerTag}></${tag}>`;
|
|
35377
|
+
}
|
|
35378
|
+
const toInt = (v, fallback) => {
|
|
35379
|
+
const n = parseInt(v ?? '', 10);
|
|
35380
|
+
return Number.isFinite(n) && n > 0 ? n : fallback;
|
|
35381
|
+
};
|
|
35382
|
+
const SignatureSlot = Node3.create({
|
|
35383
|
+
name: 'signatureSlot',
|
|
35384
|
+
group: 'inline',
|
|
35385
|
+
inline: true,
|
|
35386
|
+
atom: true,
|
|
35387
|
+
selectable: true,
|
|
35388
|
+
addOptions() {
|
|
35389
|
+
return { label: (slot) => `Signature ${slot}` };
|
|
35390
|
+
},
|
|
35391
|
+
addAttributes() {
|
|
35392
|
+
return {
|
|
35393
|
+
slot: { default: 1, parseHTML: (el) => toInt(el.getAttribute('data-sig-slot'), 1), rendered: false },
|
|
35394
|
+
w: { default: SIGNATURE_DEFAULT_W, parseHTML: (el) => toInt(el.getAttribute('data-w'), SIGNATURE_DEFAULT_W), rendered: false },
|
|
35395
|
+
h: { default: SIGNATURE_DEFAULT_H, parseHTML: (el) => toInt(el.getAttribute('data-h'), SIGNATURE_DEFAULT_H), rendered: false },
|
|
35396
|
+
};
|
|
35397
|
+
},
|
|
35398
|
+
parseHTML() {
|
|
35399
|
+
return [{ tag: 'span[data-sig-slot]', priority: 100 }];
|
|
35400
|
+
},
|
|
35401
|
+
renderHTML({ node }) {
|
|
35402
|
+
return signatureSlotSpec(node.attrs);
|
|
35403
|
+
},
|
|
35404
|
+
renderText({ node }) {
|
|
35405
|
+
return signatureToken(node.attrs.slot);
|
|
35406
|
+
},
|
|
35407
|
+
addNodeView() {
|
|
35408
|
+
const label = this.options.label;
|
|
35409
|
+
return ({ node }) => {
|
|
35410
|
+
const dom = document.createElement('span');
|
|
35411
|
+
dom.className = 'co-doc-signature';
|
|
35412
|
+
dom.contentEditable = 'false';
|
|
35413
|
+
const paint = (n) => {
|
|
35414
|
+
dom.style.width = `${n.attrs.w}px`;
|
|
35415
|
+
dom.style.height = `${n.attrs.h}px`;
|
|
35416
|
+
dom.textContent = label(n.attrs.slot);
|
|
35417
|
+
dom.setAttribute('data-sig-slot', String(n.attrs.slot));
|
|
35418
|
+
};
|
|
35419
|
+
paint(node);
|
|
35420
|
+
return {
|
|
35421
|
+
dom,
|
|
35422
|
+
update(next) {
|
|
35423
|
+
if (next.type.name !== 'signatureSlot')
|
|
35424
|
+
return false;
|
|
35425
|
+
paint(next);
|
|
35426
|
+
return true;
|
|
35427
|
+
},
|
|
35428
|
+
ignoreMutation: () => true,
|
|
35429
|
+
};
|
|
35430
|
+
};
|
|
35431
|
+
},
|
|
35432
|
+
addCommands() {
|
|
35433
|
+
return {
|
|
35434
|
+
insertSignatureSlot: (size = {}) => ({ state, commands }) => {
|
|
35435
|
+
const used = [];
|
|
35436
|
+
state.doc.descendants((n) => {
|
|
35437
|
+
if (n.type.name === this.name)
|
|
35438
|
+
used.push(n.attrs.slot);
|
|
35439
|
+
});
|
|
35440
|
+
return commands.insertContent({
|
|
35441
|
+
type: this.name,
|
|
35442
|
+
attrs: { slot: nextFreeSlot(used), w: size.w ?? SIGNATURE_DEFAULT_W, h: size.h ?? SIGNATURE_DEFAULT_H },
|
|
35443
|
+
});
|
|
35444
|
+
},
|
|
35445
|
+
};
|
|
35446
|
+
},
|
|
35447
|
+
});
|
|
35448
|
+
|
|
35449
|
+
/** Tamaño base del cuerpo de impresión (SharedContractUtils: 14px/1.5). */
|
|
35450
|
+
const BASE_FONT_PX = 14;
|
|
35451
|
+
/** Valor crudo de una propiedad del atributo style (conserva `#hex`; `el.style.color` lo pasaría a rgb). */
|
|
35452
|
+
function rawStyleValue(el, prop) {
|
|
35453
|
+
const style = el.getAttribute('style') || '';
|
|
35454
|
+
for (const decl of style.split(';')) {
|
|
35455
|
+
const i = decl.indexOf(':');
|
|
35456
|
+
if (i <= 0)
|
|
35457
|
+
continue;
|
|
35458
|
+
if (decl.slice(0, i).trim().toLowerCase() === prop) {
|
|
35459
|
+
const v = decl.slice(i + 1).trim();
|
|
35460
|
+
return v || null;
|
|
35461
|
+
}
|
|
35462
|
+
}
|
|
35463
|
+
return null;
|
|
35464
|
+
}
|
|
35465
|
+
/** V1 pasaba mal las unidades (12pt → 12px, 1.5em → 1px). Acá se convierten a px de verdad. */
|
|
35466
|
+
function normalizeFontSizePx(v) {
|
|
35467
|
+
if (v == null)
|
|
35468
|
+
return null;
|
|
35469
|
+
const m = /^\s*(\d+(?:\.\d+)?)\s*(px|pt|em|rem|%)?\s*$/i.exec(String(v));
|
|
35470
|
+
if (!m)
|
|
35471
|
+
return null;
|
|
35472
|
+
const n = parseFloat(m[1]);
|
|
35473
|
+
const unit = (m[2] || 'px').toLowerCase();
|
|
35474
|
+
const px = unit === 'px' ? n : unit === 'pt' ? (n * 4) / 3 : unit === '%' ? (n / 100) * BASE_FONT_PX : n * BASE_FONT_PX;
|
|
35475
|
+
const r = Math.round(px);
|
|
35476
|
+
return r >= 1 && r <= 400 ? `${r}px` : null;
|
|
35477
|
+
}
|
|
35478
|
+
/**
|
|
35479
|
+
* Color de texto en la forma de V1: `<span class="editor-text-style" style="color: X">`,
|
|
35480
|
+
* SIEMPRE por fuera del tamaño (un span con color + tamaño pierde el color en V1).
|
|
35481
|
+
* Se llama `textStyle` para que la barra lea `getAttributes('textStyle').color`.
|
|
35482
|
+
* Prioridad alta = marca más externa (link 1003 > color 1002 > tamaño 1001 > resto 100).
|
|
35483
|
+
*
|
|
35484
|
+
* La regla de parse queda con la prioridad por defecto (50): la firma
|
|
35485
|
+
* (`span[data-sig-slot]`) y el campo (`span[data-variable]`) van a 100 y le ganan
|
|
35486
|
+
* aunque lleven `style` inline.
|
|
35487
|
+
*/
|
|
35488
|
+
const PrintTextColor = Mark.create({
|
|
35489
|
+
name: 'textStyle',
|
|
35490
|
+
priority: 1002,
|
|
35491
|
+
addAttributes() {
|
|
35492
|
+
return {
|
|
35493
|
+
color: { default: null, parseHTML: (el) => rawStyleValue(el, 'color'), rendered: false },
|
|
35494
|
+
};
|
|
35495
|
+
},
|
|
35496
|
+
parseHTML() {
|
|
35497
|
+
return [{ tag: 'span', consuming: false, getAttrs: (el) => (rawStyleValue(el, 'color') ? {} : false) }];
|
|
35498
|
+
},
|
|
35499
|
+
renderHTML({ mark }) {
|
|
35500
|
+
return ['span', { class: 'editor-text-style', style: `color: ${mark.attrs.color}` }, 0];
|
|
35501
|
+
},
|
|
35502
|
+
addCommands() {
|
|
35503
|
+
return {
|
|
35504
|
+
setColor: (color) => ({ commands }) => commands.setMark(this.name, { color }),
|
|
35505
|
+
unsetColor: () => ({ commands }) => commands.unsetMark(this.name),
|
|
35506
|
+
};
|
|
35507
|
+
},
|
|
35508
|
+
});
|
|
35509
|
+
/** Tamaño en px como marca APARTE, anidada dentro del color: `<span style="font-size: Npx">`. */
|
|
35510
|
+
const PrintFontSize = Mark.create({
|
|
35511
|
+
name: 'printFontSize',
|
|
35512
|
+
priority: 1001,
|
|
35513
|
+
addAttributes() {
|
|
35514
|
+
return {
|
|
35515
|
+
size: { default: null, parseHTML: (el) => normalizeFontSizePx(rawStyleValue(el, 'font-size')), rendered: false },
|
|
35516
|
+
};
|
|
35517
|
+
},
|
|
35518
|
+
parseHTML() {
|
|
35519
|
+
return [{ tag: 'span', consuming: false, getAttrs: (el) => (normalizeFontSizePx(rawStyleValue(el, 'font-size')) ? {} : false) }];
|
|
35520
|
+
},
|
|
35521
|
+
renderHTML({ mark }) {
|
|
35522
|
+
return ['span', { style: `font-size: ${mark.attrs.size}` }, 0];
|
|
35523
|
+
},
|
|
35524
|
+
addCommands() {
|
|
35525
|
+
return {
|
|
35526
|
+
setFontSize: (size) => ({ commands }) => {
|
|
35527
|
+
const px = normalizeFontSizePx(size);
|
|
35528
|
+
return px ? commands.setMark(this.name, { size: px }) : false;
|
|
35529
|
+
},
|
|
35530
|
+
unsetFontSize: () => ({ commands }) => commands.unsetMark(this.name),
|
|
35531
|
+
};
|
|
35532
|
+
},
|
|
35533
|
+
});
|
|
35534
|
+
|
|
35535
|
+
const IMAGE_LAYOUT_MODES = ['inline', 'wrap-left', 'wrap-right', 'break'];
|
|
35536
|
+
const MODE_PROPS = new Set(['float', 'clear', 'display', 'padding-left', 'padding-right']);
|
|
35537
|
+
const MODE_STYLES = {
|
|
35538
|
+
inline: { wrapper: ['display: inline-block'], container: ['display: inline-block'] },
|
|
35539
|
+
'wrap-left': { wrapper: ['display: inline-block', 'float: left'], container: ['display: inline-block', 'float: left', 'padding-right: 8px'] },
|
|
35540
|
+
'wrap-right': { wrapper: ['display: inline-block', 'float: right'], container: ['display: inline-block', 'float: right', 'padding-left: 8px'] },
|
|
35541
|
+
break: { wrapper: ['display: block'], container: ['display: block'] },
|
|
35542
|
+
};
|
|
35543
|
+
/** Una imagen nueva nace en línea (ruling del ledger); al leer una de V1 manda su wrapperstyle. */
|
|
35544
|
+
const DEFAULT_WRAPPER_STYLE = 'display: inline-block;';
|
|
35545
|
+
const DEFAULT_CONTAINER_STYLE = 'height: auto; cursor: pointer; display: inline-block;';
|
|
35546
|
+
function stripModeProps(style) {
|
|
35547
|
+
return String(style || '')
|
|
35548
|
+
.split(';')
|
|
35549
|
+
.map((d) => d.trim())
|
|
35550
|
+
.filter((d) => d.includes(':'))
|
|
35551
|
+
.filter((d) => !MODE_PROPS.has(d.slice(0, d.indexOf(':')).trim().toLowerCase()));
|
|
35552
|
+
}
|
|
35553
|
+
function applyImageLayoutMode(mode, { wrapperStyle = '', containerStyle = '' } = {}) {
|
|
35554
|
+
const preset = MODE_STYLES[mode];
|
|
35555
|
+
if (!preset)
|
|
35556
|
+
return { wrapperStyle: wrapperStyle || '', containerStyle: containerStyle || '' };
|
|
35557
|
+
const join = (mods, rest) => [...mods, ...rest].join('; ').replace(/;?\s*$/, ';');
|
|
35558
|
+
return {
|
|
35559
|
+
wrapperStyle: join(preset.wrapper, stripModeProps(wrapperStyle || '')),
|
|
35560
|
+
containerStyle: join(preset.container, stripModeProps(containerStyle || '')),
|
|
35561
|
+
};
|
|
35562
|
+
}
|
|
35563
|
+
function getImageLayoutMode({ wrapperStyle = '', containerStyle = '' } = {}) {
|
|
35564
|
+
const style = `${containerStyle || ''};${wrapperStyle || ''}`.toLowerCase();
|
|
35565
|
+
if (/float:\s*left/.test(style))
|
|
35566
|
+
return 'wrap-left';
|
|
35567
|
+
if (/float:\s*right/.test(style))
|
|
35568
|
+
return 'wrap-right';
|
|
35569
|
+
if (/display:\s*block\b/.test(style))
|
|
35570
|
+
return 'break';
|
|
35571
|
+
return 'inline';
|
|
35572
|
+
}
|
|
35573
|
+
const HEADER_IMG_MAX = { w: 400, h: 40 };
|
|
35574
|
+
/** Ancho que entra en la banda del encabezado (port de headerContainerStyle de V1). */
|
|
35575
|
+
function headerImageWidth(dims, max = HEADER_IMG_MAX) {
|
|
35576
|
+
if (!dims || !dims.w || !dims.h)
|
|
35577
|
+
return null;
|
|
35578
|
+
const scale = Math.min(1, max.h / dims.h, max.w / dims.w);
|
|
35579
|
+
return Math.max(1, Math.round(dims.w * scale));
|
|
35580
|
+
}
|
|
35581
|
+
/**
|
|
35582
|
+
* `width:` anclado a inicio de declaración: sin el ancla, `min-width`/`max-width` también
|
|
35583
|
+
* matchean y se leía (y se pisaba) el ancho equivocado de un `containerstyle` de V1.
|
|
35584
|
+
*/
|
|
35585
|
+
const WIDTH_DECL = /(^|;)(\s*)width:\s*([0-9.]+)px/i;
|
|
35586
|
+
function withWidth(style, width) {
|
|
35587
|
+
if (!width)
|
|
35588
|
+
return style;
|
|
35589
|
+
const decl = `width: ${width}px`;
|
|
35590
|
+
return WIDTH_DECL.test(style)
|
|
35591
|
+
? style.replace(WIDTH_DECL, (_m, sep, ws) => `${sep}${ws}${decl}`)
|
|
35592
|
+
: `${decl}; ${style}`.trim();
|
|
35593
|
+
}
|
|
35594
|
+
function parseWidth(el) {
|
|
35595
|
+
const attr = parseInt(el.getAttribute('width') || '', 10);
|
|
35596
|
+
if (attr > 0)
|
|
35597
|
+
return attr;
|
|
35598
|
+
const m = WIDTH_DECL.exec(el.getAttribute('containerstyle') || el.getAttribute('style') || '');
|
|
35599
|
+
return m ? Math.round(parseFloat(m[3])) : null;
|
|
35600
|
+
}
|
|
35601
|
+
/**
|
|
35602
|
+
* H10: el node view de resize de Tiptap solo copia los atributos RENDERIZADOS, y
|
|
35603
|
+
* `wrapperStyle`/`containerStyle` no lo son → en el editor toda imagen se veía en línea.
|
|
35604
|
+
* Se lleva el modo al contenedor (`[data-resize-container]`) para que la hoja pagine
|
|
35605
|
+
* como el PDF. `inline-flex`/`flex` (no `inline-block`/`block`): el contenedor de
|
|
35606
|
+
* resize los necesita para ubicar las manijas.
|
|
35607
|
+
*/
|
|
35608
|
+
function syncImageModeToContainer(container, node) {
|
|
35609
|
+
const mode = getImageLayoutMode(node.attrs);
|
|
35610
|
+
container.dataset.imageLayout = mode;
|
|
35611
|
+
container.style.float = mode === 'wrap-left' ? 'left' : mode === 'wrap-right' ? 'right' : '';
|
|
35612
|
+
container.style.paddingLeft = mode === 'wrap-right' ? '8px' : '';
|
|
35613
|
+
container.style.paddingRight = mode === 'wrap-left' ? '8px' : '';
|
|
35614
|
+
container.style.display = mode === 'break' ? 'flex' : 'inline-flex';
|
|
35615
|
+
}
|
|
35616
|
+
const PrintImage = Image.extend({
|
|
35617
|
+
name: 'image',
|
|
35618
|
+
addOptions() {
|
|
35619
|
+
return { ...this.parent?.(), header: false };
|
|
35620
|
+
},
|
|
35621
|
+
addAttributes() {
|
|
35622
|
+
return {
|
|
35623
|
+
...this.parent?.(),
|
|
35624
|
+
width: { default: null, parseHTML: (el) => parseWidth(el), rendered: false },
|
|
35625
|
+
dataFileId: { default: null, parseHTML: (el) => el.getAttribute('data-file-id'), rendered: false },
|
|
35626
|
+
containerStyle: { default: null, parseHTML: (el) => el.getAttribute('containerstyle'), rendered: false },
|
|
35627
|
+
wrapperStyle: { default: null, parseHTML: (el) => el.getAttribute('wrapperstyle'), rendered: false },
|
|
35628
|
+
};
|
|
35629
|
+
},
|
|
35630
|
+
parseHTML() {
|
|
35631
|
+
return [{ tag: this.options.allowBase64 ? 'img[src]' : 'img[src]:not([src^="data:"])', priority: 100 }];
|
|
35632
|
+
},
|
|
35633
|
+
renderHTML({ node }) {
|
|
35634
|
+
const a = node.attrs;
|
|
35635
|
+
const width = a.width ? Math.round(Number(a.width)) : null;
|
|
35636
|
+
const wrapper = a.wrapperStyle || DEFAULT_WRAPPER_STYLE;
|
|
35637
|
+
const container = withWidth(a.containerStyle || DEFAULT_CONTAINER_STYLE, width);
|
|
35638
|
+
const img = { src: a.src };
|
|
35639
|
+
if (a.alt)
|
|
35640
|
+
img.alt = a.alt;
|
|
35641
|
+
if (a.title)
|
|
35642
|
+
img.title = a.title;
|
|
35643
|
+
if (a.dataFileId)
|
|
35644
|
+
img['data-file-id'] = String(a.dataFileId);
|
|
35645
|
+
if (width) {
|
|
35646
|
+
img.width = String(width);
|
|
35647
|
+
img.style = this.options.header ? `width: ${width}px; height: auto;` : `width: ${width}px;`;
|
|
35648
|
+
}
|
|
35649
|
+
img.containerstyle = container;
|
|
35650
|
+
img.wrapperstyle = wrapper;
|
|
35651
|
+
return ['span', { style: wrapper }, ['img', img]];
|
|
35652
|
+
},
|
|
35653
|
+
addNodeView() {
|
|
35654
|
+
const parent = this.parent?.();
|
|
35655
|
+
if (!parent)
|
|
35656
|
+
return null;
|
|
35657
|
+
return (props) => {
|
|
35658
|
+
const view = parent(props);
|
|
35659
|
+
const container = view.dom;
|
|
35660
|
+
syncImageModeToContainer(container, props.node);
|
|
35661
|
+
const update = view.update?.bind(view);
|
|
35662
|
+
view.update = (node, decorations, inner) => {
|
|
35663
|
+
const ok = update ? update(node, decorations, inner) : node.type === props.node.type;
|
|
35664
|
+
if (ok)
|
|
35665
|
+
syncImageModeToContainer(container, node);
|
|
35666
|
+
return ok;
|
|
35667
|
+
};
|
|
35668
|
+
return view;
|
|
35669
|
+
};
|
|
35670
|
+
},
|
|
35671
|
+
addCommands() {
|
|
35672
|
+
return {
|
|
35673
|
+
...this.parent?.(),
|
|
35674
|
+
setImageLayoutMode: (mode) => ({ state, tr, dispatch }) => {
|
|
35675
|
+
const sel = state.selection;
|
|
35676
|
+
if (!(sel instanceof NodeSelection) || sel.node.type.name !== this.name)
|
|
35677
|
+
return false;
|
|
35678
|
+
if (dispatch) {
|
|
35679
|
+
const next = applyImageLayoutMode(mode, {
|
|
35680
|
+
wrapperStyle: sel.node.attrs.wrapperStyle || DEFAULT_WRAPPER_STYLE,
|
|
35681
|
+
containerStyle: withWidth(sel.node.attrs.containerStyle || DEFAULT_CONTAINER_STYLE, sel.node.attrs.width),
|
|
35682
|
+
});
|
|
35683
|
+
tr.setNodeMarkup(sel.from, undefined, { ...sel.node.attrs, ...next });
|
|
35684
|
+
// H7: la NodeSelection no sobrevive al reemplazo de la hoja; sin esto la barra de imagen se cierra.
|
|
35685
|
+
tr.setSelection(NodeSelection.create(tr.doc, sel.from));
|
|
35686
|
+
}
|
|
35687
|
+
return true;
|
|
35688
|
+
},
|
|
35689
|
+
};
|
|
35690
|
+
},
|
|
35691
|
+
});
|
|
35692
|
+
|
|
35693
|
+
/** Validación de V1 (tiptap-editor-html/extensions/index.js): exige un `.`, rechaza `/` y `./`. */
|
|
35694
|
+
const printLinkAllowed = (url, ctx) => ctx.defaultValidate(url) && !url.startsWith('./') && !url.startsWith('/') && url.includes('.');
|
|
35695
|
+
/** Autolink APAGADO: generaba `<a>` dentro de `{{ }}` y rompía Handlebars. Prioridad 1003 = marca más externa. */
|
|
35696
|
+
const PrintLink = Link.extend({ inclusive: () => false, priority: 1003 }).configure({
|
|
35697
|
+
autolink: false,
|
|
35698
|
+
openOnClick: false,
|
|
35699
|
+
defaultProtocol: 'https',
|
|
35700
|
+
protocols: ['mailto', { scheme: 'tel', optionalSlashes: true }],
|
|
35701
|
+
HTMLAttributes: { target: '_blank', rel: 'noopener noreferrer', class: 'editor-link' },
|
|
35702
|
+
isAllowedUri: printLinkAllowed,
|
|
35703
|
+
});
|
|
35704
|
+
|
|
35705
|
+
/** Resalta `{{ … }}` con una DECORACIÓN: no toca el documento ni se serializa. */
|
|
35706
|
+
const HB_RE = /\{\{[^}]*\}\}/g;
|
|
35707
|
+
function build(doc) {
|
|
35708
|
+
const decos = [];
|
|
35709
|
+
doc.descendants((node, pos) => {
|
|
35710
|
+
if (!node.isText || !node.text)
|
|
35711
|
+
return true;
|
|
35712
|
+
HB_RE.lastIndex = 0;
|
|
35713
|
+
let m;
|
|
35714
|
+
while ((m = HB_RE.exec(node.text)) !== null) {
|
|
35715
|
+
decos.push(Decoration.inline(pos + m.index, pos + m.index + m[0].length, { class: 'co-doc-hb' }));
|
|
35716
|
+
}
|
|
35717
|
+
return true;
|
|
35718
|
+
});
|
|
35719
|
+
return DecorationSet.create(doc, decos);
|
|
35720
|
+
}
|
|
35721
|
+
const HandlebarsHighlight = Extension.create({
|
|
35722
|
+
name: 'handlebarsHighlight',
|
|
35723
|
+
addProseMirrorPlugins() {
|
|
35724
|
+
const key = new PluginKey('coHandlebarsHighlight');
|
|
35725
|
+
return [
|
|
35726
|
+
new Plugin({
|
|
35727
|
+
key,
|
|
35728
|
+
state: {
|
|
35729
|
+
init: (_config, { doc }) => build(doc),
|
|
35730
|
+
apply: (tr, old) => (tr.docChanged ? build(tr.doc) : old),
|
|
35731
|
+
},
|
|
35732
|
+
props: {
|
|
35733
|
+
decorations(state) {
|
|
35734
|
+
return key.getState(state);
|
|
35735
|
+
},
|
|
35736
|
+
},
|
|
35737
|
+
}),
|
|
35738
|
+
];
|
|
35739
|
+
},
|
|
35740
|
+
});
|
|
35741
|
+
|
|
35742
|
+
/**
|
|
35743
|
+
* Presets `print` (cuerpo) y `print-header` (banda). Paridad ESTRICTA de
|
|
35744
|
+
* funciones de V1 (spec §3.5/§3.6, D7): sin subrayado, familia, peso,
|
|
35745
|
+
* interlineado, espaciado ni sangría; autolink apagado; sin nodo `variable`
|
|
35746
|
+
* (comparte selector `span[data-variable]` con el campo). `trailingNode` apagado:
|
|
35747
|
+
* V1 no lo tenía y una tabla al final sumaría una línea vacía al PDF.
|
|
35748
|
+
* Las etiquetas (`labels`) las localiza el host; sin ellas quedan en inglés.
|
|
35749
|
+
*/
|
|
35750
|
+
function getPrintExtensions(preset, opts = {}) {
|
|
35751
|
+
const header = preset === 'print-header';
|
|
35752
|
+
const { features = {}, labels = {} } = opts;
|
|
35753
|
+
const starter = { underline: false, link: false, trailingNode: false };
|
|
35754
|
+
if (header) {
|
|
35755
|
+
Object.assign(starter, {
|
|
35756
|
+
heading: false, bulletList: false, orderedList: false, listItem: false, listKeymap: false,
|
|
35757
|
+
blockquote: false, codeBlock: false, horizontalRule: false,
|
|
35758
|
+
});
|
|
35759
|
+
}
|
|
35760
|
+
else {
|
|
35761
|
+
starter.heading = { levels: [1, 2, 3, 4] };
|
|
35762
|
+
}
|
|
35763
|
+
const exts = [
|
|
35764
|
+
StarterKit.configure(starter),
|
|
35765
|
+
PrintTextColor,
|
|
35766
|
+
PrintFontSize,
|
|
35767
|
+
Highlight.configure({ multicolor: true }),
|
|
35768
|
+
TextAlign.configure({ types: header ? ['paragraph'] : ['heading', 'paragraph'] }),
|
|
35769
|
+
HandlebarsHighlight,
|
|
35770
|
+
];
|
|
35771
|
+
if (!header) {
|
|
35772
|
+
exts.push(PrintLink, Table.configure({ resizable: true, renderWrapper: true }), TableRow, TableHeader, TableCell);
|
|
35773
|
+
}
|
|
35774
|
+
exts.push(PrintImage.configure({
|
|
35775
|
+
inline: true,
|
|
35776
|
+
allowBase64: true,
|
|
35777
|
+
header,
|
|
35778
|
+
resize: header
|
|
35779
|
+
? false
|
|
35780
|
+
: { enabled: true, directions: ['left', 'right', 'bottom-left', 'bottom-right'], minWidth: 50, minHeight: 20, alwaysPreserveAspectRatio: true },
|
|
35781
|
+
}));
|
|
35782
|
+
if (features.fields !== false) {
|
|
35783
|
+
exts.push(MergeField.configure({ renameLabel: labels.fieldName ?? 'Field name' }));
|
|
35784
|
+
}
|
|
35785
|
+
if (!header && features.signatureSlots !== false) {
|
|
35786
|
+
exts.push(labels.signature ? SignatureSlot.configure({ label: labels.signature }) : SignatureSlot);
|
|
35787
|
+
}
|
|
35788
|
+
return exts;
|
|
35789
|
+
}
|
|
35790
|
+
|
|
34999
35791
|
/** Shared link configuration — never auto-opens inside the editor, safe rel. */
|
|
35000
35792
|
const LINK_CONFIG = {
|
|
35001
35793
|
openOnClick: false,
|
|
@@ -35074,6 +35866,8 @@ const PRESET_TOOLBAR = {
|
|
|
35074
35866
|
email: 'full',
|
|
35075
35867
|
document: 'full',
|
|
35076
35868
|
'block-email': 'basic',
|
|
35869
|
+
print: 'document',
|
|
35870
|
+
'print-header': 'document',
|
|
35077
35871
|
};
|
|
35078
35872
|
/** Suggested max length per preset (null = no limit). */
|
|
35079
35873
|
const PRESET_MAXLENGTH = {
|
|
@@ -35083,10 +35877,22 @@ const PRESET_MAXLENGTH = {
|
|
|
35083
35877
|
email: null,
|
|
35084
35878
|
document: null,
|
|
35085
35879
|
'block-email': null,
|
|
35880
|
+
print: null,
|
|
35881
|
+
'print-header': null,
|
|
35086
35882
|
};
|
|
35087
35883
|
/** Build the ordered extension array for a preset. */
|
|
35088
35884
|
function getExtensions(preset = 'task', options = {}) {
|
|
35089
|
-
const { placeholder, maxLength, features = {}, includeUiExtensions = true } = options;
|
|
35885
|
+
const { placeholder, maxLength, features = {}, includeUiExtensions = true, labels } = options;
|
|
35886
|
+
// Presets de impresión: schema propio (spec contracts-v2-contract-editor §3.5/§3.6).
|
|
35887
|
+
if (preset === 'print' || preset === 'print-header') {
|
|
35888
|
+
const exts = getPrintExtensions(preset, {
|
|
35889
|
+
features: { fields: features.fields, signatureSlots: features.signatureSlots },
|
|
35890
|
+
labels,
|
|
35891
|
+
});
|
|
35892
|
+
if (includeUiExtensions && placeholder)
|
|
35893
|
+
exts.push(Placeholder.configure({ placeholder }));
|
|
35894
|
+
return exts;
|
|
35895
|
+
}
|
|
35090
35896
|
const config = STARTERKIT_CONFIG[preset] ?? STARTERKIT_CONFIG.task;
|
|
35091
35897
|
const exts = [StarterKit.configure(config), CobaltLink];
|
|
35092
35898
|
// Color requires TextStyle to be registered first. Only presets that keep
|
|
@@ -35184,7 +35990,573 @@ function defaultToolbarForPreset(preset = 'task') {
|
|
|
35184
35990
|
function maxLengthForPreset(preset = 'task') {
|
|
35185
35991
|
return PRESET_MAXLENGTH[preset] ?? null;
|
|
35186
35992
|
}
|
|
35187
|
-
const PRESETS = ['comment', 'task', 'notes', 'email', 'document', 'block-email'];
|
|
35993
|
+
const PRESETS = ['comment', 'task', 'notes', 'email', 'document', 'block-email', 'print', 'print-header'];
|
|
35994
|
+
|
|
35995
|
+
// src/generateHTML.ts
|
|
35996
|
+
function getHTMLFromFragment(doc, schema, options) {
|
|
35997
|
+
if (typeof window === "undefined") {
|
|
35998
|
+
throw new Error(
|
|
35999
|
+
"getHTMLFromFragment can only be used in a browser environment\nIf you want to use this in a Node environment, use the `@tiptap/html/server` import instead."
|
|
36000
|
+
);
|
|
36001
|
+
}
|
|
36002
|
+
const wrap = window.document.createElement("div");
|
|
36003
|
+
DOMSerializer.fromSchema(schema).serializeFragment(
|
|
36004
|
+
doc.content,
|
|
36005
|
+
{
|
|
36006
|
+
document: window.document
|
|
36007
|
+
},
|
|
36008
|
+
wrap
|
|
36009
|
+
);
|
|
36010
|
+
return wrap.innerHTML;
|
|
36011
|
+
}
|
|
36012
|
+
|
|
36013
|
+
// src/generateHTML.ts
|
|
36014
|
+
function generateHTML(doc, extensions) {
|
|
36015
|
+
if (typeof window === "undefined") {
|
|
36016
|
+
throw new Error(
|
|
36017
|
+
"generateHTML can only be used in a browser environment\nIf you want to use this in a Node environment, use the `@tiptap/html/server` import instead."
|
|
36018
|
+
);
|
|
36019
|
+
}
|
|
36020
|
+
const schema = getSchema(extensions);
|
|
36021
|
+
const contentNode = Node$1.fromJSON(schema, doc);
|
|
36022
|
+
return getHTMLFromFragment(contentNode, schema);
|
|
36023
|
+
}
|
|
36024
|
+
function generateJSON(html, extensions, options) {
|
|
36025
|
+
if (typeof window === "undefined") {
|
|
36026
|
+
throw new Error(
|
|
36027
|
+
"generateJSON can only be used in a browser environment\nIf you want to use this in a Node environment, use the `@tiptap/html/server` import instead."
|
|
36028
|
+
);
|
|
36029
|
+
}
|
|
36030
|
+
const schema = getSchema(extensions);
|
|
36031
|
+
const doc = new window.DOMParser().parseFromString(html, "text/html");
|
|
36032
|
+
if (!doc) {
|
|
36033
|
+
throw new Error("Failed to parse HTML string");
|
|
36034
|
+
}
|
|
36035
|
+
return DOMParser$1.fromSchema(schema).parse(doc.body, options).toJSON();
|
|
36036
|
+
}
|
|
36037
|
+
|
|
36038
|
+
const BASE_INLINE = ['p', 'br', 'strong', 'em', 'a', 'span'];
|
|
36039
|
+
const BASE_ATTR = ['href', 'target', 'rel', 'data-mention-id', 'data-mention-label'];
|
|
36040
|
+
const SANITIZE_CONFIGS = {
|
|
36041
|
+
// Más ancho que su schema A PROPÓSITO (única excepción al lock-step): el
|
|
36042
|
+
// editor `comment` no puede autorar listas ni headings (STARTERKIT_CONFIG los
|
|
36043
|
+
// apaga y ProseMirror descarta esos nodos al parsear el paste), pero el
|
|
36044
|
+
// VIEWER tiene que pintarlos cuando el HTML entra por API — una nota de
|
|
36045
|
+
// enriquecimiento (Apollo.io) trae <ul>/<li>/<h4> y con KEEP_CONTENT el
|
|
36046
|
+
// texto se hoisteaba al padre: lista corrida, heading fundido en el cuerpo.
|
|
36047
|
+
// Espejo inline en core/co-rich-text-viewer.tsx (ALLOWED_TAGS.comment).
|
|
36048
|
+
comment: {
|
|
36049
|
+
ALLOWED_TAGS: [...BASE_INLINE, 'ul', 'ol', 'li', 'h1', 'h2', 'h3', 'h4'],
|
|
36050
|
+
ALLOWED_ATTR: [...BASE_ATTR],
|
|
36051
|
+
ALLOW_DATA_ATTR: false,
|
|
36052
|
+
},
|
|
36053
|
+
task: {
|
|
36054
|
+
ALLOWED_TAGS: [...BASE_INLINE, 'u', 's', 'code', 'ul', 'ol', 'li', 'blockquote', 'input', 'label'],
|
|
36055
|
+
ALLOWED_ATTR: [...BASE_ATTR, 'type', 'checked', 'disabled', 'data-type', 'data-checked', 'data-variant'],
|
|
36056
|
+
ALLOW_DATA_ATTR: false,
|
|
36057
|
+
},
|
|
36058
|
+
// Lock-step con getExtensions('notes'): task sin checklists + TextStyle/Color
|
|
36059
|
+
// (`style` capado a STYLE_ALLOWED_PROPS) + Highlight multicolor (`mark` con
|
|
36060
|
+
// `data-color`).
|
|
36061
|
+
notes: {
|
|
36062
|
+
ALLOWED_TAGS: [...BASE_INLINE, 'u', 's', 'code', 'ul', 'ol', 'li', 'blockquote', 'mark'],
|
|
36063
|
+
ALLOWED_ATTR: [...BASE_ATTR, 'style', 'data-color'],
|
|
36064
|
+
ALLOW_DATA_ATTR: false,
|
|
36065
|
+
},
|
|
36066
|
+
email: {
|
|
36067
|
+
ALLOWED_TAGS: [
|
|
36068
|
+
...BASE_INLINE, 'u', 's', 'code', 'ul', 'ol', 'li', 'blockquote',
|
|
36069
|
+
'h2', 'h3', 'div', 'img',
|
|
36070
|
+
],
|
|
36071
|
+
ALLOWED_ATTR: [...BASE_ATTR, 'style', 'data-variable', 'data-transform', 'data-fallback', 'src', 'alt', 'width', 'height', 'data-file-id', 'data-image-layout'],
|
|
36072
|
+
ALLOW_DATA_ATTR: false,
|
|
36073
|
+
},
|
|
36074
|
+
document: {
|
|
36075
|
+
ALLOWED_TAGS: [
|
|
36076
|
+
...BASE_INLINE, 'u', 's', 'code', 'ul', 'ol', 'li', 'blockquote',
|
|
36077
|
+
'h1', 'h2', 'h3', 'h4', 'hr', 'div', 'mark', 'img',
|
|
36078
|
+
'table', 'thead', 'tbody', 'tr', 'th', 'td',
|
|
36079
|
+
'input', 'label', 'iframe',
|
|
36080
|
+
],
|
|
36081
|
+
ALLOWED_ATTR: [...BASE_ATTR, 'style', 'data-variable', 'colspan', 'rowspan', 'src', 'alt', 'width', 'height', 'type', 'checked', 'disabled', 'allowfullscreen', 'frameborder', 'allow', 'loading'],
|
|
36082
|
+
ALLOW_DATA_ATTR: true,
|
|
36083
|
+
},
|
|
36084
|
+
'block-email': {
|
|
36085
|
+
ALLOWED_TAGS: [...BASE_INLINE, 'u', 's', 'code', 'ul', 'ol', 'li', 'blockquote', 'h2', 'h3', 'div', 'img'],
|
|
36086
|
+
ALLOWED_ATTR: [...BASE_ATTR, 'style', 'data-variable', 'data-transform', 'data-fallback', 'src', 'alt', 'width', 'height', 'data-file-id', 'data-image-layout', 'data-type', 'data-label', 'data-href', 'data-bg', 'data-color', 'data-height'],
|
|
36087
|
+
ALLOW_DATA_ATTR: false,
|
|
36088
|
+
},
|
|
36089
|
+
// Espejo de getPrintExtensions('print'): cuerpo del documento de impresión.
|
|
36090
|
+
// `class` y data-* son parte de la forma que V1 re-parsea (editor-text-style,
|
|
36091
|
+
// variable-node, editor-link, tableWrapper, trailingBreak, data-variable…).
|
|
36092
|
+
print: {
|
|
36093
|
+
ALLOWED_TAGS: [
|
|
36094
|
+
'p', 'br', 'strong', 'em', 's', 'code', 'a', 'span', 'mark',
|
|
36095
|
+
'h1', 'h2', 'h3', 'h4', 'ul', 'ol', 'li', 'blockquote', 'pre', 'hr', 'img', 'div',
|
|
36096
|
+
'table', 'colgroup', 'col', 'thead', 'tbody', 'tr', 'th', 'td',
|
|
36097
|
+
],
|
|
36098
|
+
ALLOWED_ATTR: [
|
|
36099
|
+
'href', 'target', 'rel', 'class', 'style', 'src', 'alt', 'title', 'width', 'height',
|
|
36100
|
+
'colspan', 'rowspan', 'colwidth', 'start', 'contenteditable', 'containerstyle', 'wrapperstyle',
|
|
36101
|
+
],
|
|
36102
|
+
ALLOW_DATA_ATTR: true,
|
|
36103
|
+
ADD_URI_SAFE_ATTR: ['containerstyle', 'wrapperstyle'],
|
|
36104
|
+
},
|
|
36105
|
+
// Espejo de getPrintExtensions('print-header'): la banda del encabezado.
|
|
36106
|
+
'print-header': {
|
|
36107
|
+
ALLOWED_TAGS: ['p', 'br', 'strong', 'em', 's', 'code', 'span', 'mark', 'img'],
|
|
36108
|
+
ALLOWED_ATTR: ['class', 'style', 'src', 'alt', 'title', 'width', 'height', 'contenteditable', 'containerstyle', 'wrapperstyle'],
|
|
36109
|
+
ALLOW_DATA_ATTR: true,
|
|
36110
|
+
ADD_URI_SAFE_ATTR: ['containerstyle', 'wrapperstyle'],
|
|
36111
|
+
},
|
|
36112
|
+
};
|
|
36113
|
+
/**
|
|
36114
|
+
* `<iframe>`s are permitted only with an `https:` source (blocks javascript:,
|
|
36115
|
+
* data:, and plain http: embeds). This is what makes allowing iframes safe-ish
|
|
36116
|
+
* for a trusted-author document; YouTube embeds satisfy it too.
|
|
36117
|
+
*/
|
|
36118
|
+
const SAFE_IFRAME_SRC_RE = /^https:\/\/[^\s"'<>]+$/i;
|
|
36119
|
+
/** Tags forbidden in every preset, regardless of the allow-list. */
|
|
36120
|
+
const FORBID_TAGS = ['script', 'object', 'embed', 'form', 'textarea', 'style'];
|
|
36121
|
+
/** Attributes forbidden in every preset (event handlers handled by DOMPurify itself). */
|
|
36122
|
+
const FORBID_ATTR = ['onerror', 'onload', 'onclick'];
|
|
36123
|
+
/**
|
|
36124
|
+
* Resolve the effective config for a preset + feature overrides. Features can
|
|
36125
|
+
* only ADD capabilities (mirroring `getExtensions`, where they register extra
|
|
36126
|
+
* nodes); they never narrow a preset's base whitelist.
|
|
36127
|
+
*/
|
|
36128
|
+
function configFor(preset, features) {
|
|
36129
|
+
const cfg = SANITIZE_CONFIGS[preset] ?? SANITIZE_CONFIGS.task;
|
|
36130
|
+
if (!features)
|
|
36131
|
+
return cfg;
|
|
36132
|
+
const tags = new Set(cfg.ALLOWED_TAGS);
|
|
36133
|
+
const attr = new Set(cfg.ALLOWED_ATTR);
|
|
36134
|
+
if (features.image) {
|
|
36135
|
+
tags.add('img');
|
|
36136
|
+
['src', 'alt', 'width', 'height'].forEach((a) => attr.add(a));
|
|
36137
|
+
}
|
|
36138
|
+
if (features.variables)
|
|
36139
|
+
attr.add('data-variable');
|
|
36140
|
+
if (features.mentions) {
|
|
36141
|
+
// data-mention-id/label ya están en BASE_ATTR. Los attrs del markup V1
|
|
36142
|
+
// (quill-mention) se suman porque el BACKEND los parsea para notificar —
|
|
36143
|
+
// re-editar una nota no debe destruirlos.
|
|
36144
|
+
// Espejo inline en core/co-rich-text-viewer.tsx (el viewer no importa este módulo para no cargar el engine) — si cambias esta lista, cambia la del viewer.
|
|
36145
|
+
['data-id', 'data-value', 'data-denotation-char', 'data-index'].forEach((a) => attr.add(a));
|
|
36146
|
+
}
|
|
36147
|
+
return { ...cfg, ALLOWED_TAGS: [...tags], ALLOWED_ATTR: [...attr] };
|
|
36148
|
+
}
|
|
36149
|
+
/**
|
|
36150
|
+
* `style` is only allowed in notes/email/document, and even there we cap it to
|
|
36151
|
+
* the properties our extensions actually emit (TextStyle/Color/TextAlign,
|
|
36152
|
+
* ListStyleExtension's `list-style-type`). Everything else — position,
|
|
36153
|
+
* background-image url(), etc. — is UI-redressing/tracking surface.
|
|
36154
|
+
*/
|
|
36155
|
+
const STYLE_ALLOWED_PROPS = new Set(['color', 'background-color', 'text-align', 'list-style-type']);
|
|
36156
|
+
const UNSAFE_STYLE_VALUE = /url\s*\(|expression\s*\(/i;
|
|
36157
|
+
const DEFAULT_STYLE_POLICY = {
|
|
36158
|
+
attrs: new Set(['style']),
|
|
36159
|
+
allows: (prop) => STYLE_ALLOWED_PROPS.has(prop),
|
|
36160
|
+
keepOriginalWhenClean: false,
|
|
36161
|
+
};
|
|
36162
|
+
const COLOR_VALUE = /^(#[0-9a-f]{3,8}|rgba?\([\d.\s,%]+\)|hsla?\([\d.\s,%deg]+\)|[a-z]+)$/i;
|
|
36163
|
+
const LENGTH_TOKEN = /^(-?\d+(\.\d+)?(px|pt|em|rem|%|mm|cm|in)?|auto)$/i;
|
|
36164
|
+
const lengths = (v) => v.split(/\s+/).every((t) => LENGTH_TOKEN.test(t));
|
|
36165
|
+
const oneOf = (re) => (v) => re.test(v);
|
|
36166
|
+
/** Lo que emiten las extensiones del preset print y la firma canónica (spec §3.4, §4.1). */
|
|
36167
|
+
const PRINT_STYLE_RULES = {
|
|
36168
|
+
color: oneOf(COLOR_VALUE),
|
|
36169
|
+
'background-color': oneOf(COLOR_VALUE),
|
|
36170
|
+
'text-align': oneOf(/^(left|center|right|justify)$/i),
|
|
36171
|
+
'font-size': oneOf(/^\d+(\.\d+)?(px|pt|em|rem|%)$/i),
|
|
36172
|
+
width: lengths,
|
|
36173
|
+
height: lengths,
|
|
36174
|
+
'min-width': lengths,
|
|
36175
|
+
'max-width': lengths,
|
|
36176
|
+
display: oneOf(/^(inline-block|inline|block|flex|inline-flex)$/i),
|
|
36177
|
+
float: oneOf(/^(left|right|none)$/i),
|
|
36178
|
+
margin: lengths,
|
|
36179
|
+
'margin-top': lengths,
|
|
36180
|
+
'margin-right': lengths,
|
|
36181
|
+
'margin-bottom': lengths,
|
|
36182
|
+
'margin-left': lengths,
|
|
36183
|
+
padding: lengths,
|
|
36184
|
+
'padding-top': lengths,
|
|
36185
|
+
'padding-right': lengths,
|
|
36186
|
+
'padding-bottom': lengths,
|
|
36187
|
+
'padding-left': lengths,
|
|
36188
|
+
'vertical-align': oneOf(/^(top|middle|bottom|baseline|text-top|text-bottom)$/i),
|
|
36189
|
+
position: oneOf(/^(relative|absolute)$/i),
|
|
36190
|
+
top: lengths,
|
|
36191
|
+
left: lengths,
|
|
36192
|
+
'line-height': oneOf(/^\d+(\.\d+)?(px)?$/i),
|
|
36193
|
+
'white-space': oneOf(/^(nowrap|normal|pre-wrap)$/i),
|
|
36194
|
+
'pointer-events': oneOf(/^none$/i),
|
|
36195
|
+
'user-select': oneOf(/^none$/i),
|
|
36196
|
+
cursor: oneOf(/^(pointer|default)$/i),
|
|
36197
|
+
};
|
|
36198
|
+
const PRINT_STYLE_POLICY = {
|
|
36199
|
+
// containerstyle/wrapperstyle son CSS que V1 aplica inline a la imagen (H2).
|
|
36200
|
+
attrs: new Set(['style', 'containerstyle', 'wrapperstyle']),
|
|
36201
|
+
allows: (prop, value) => Object.prototype.hasOwnProperty.call(PRINT_STYLE_RULES, prop) && PRINT_STYLE_RULES[prop](value),
|
|
36202
|
+
keepOriginalWhenClean: true,
|
|
36203
|
+
};
|
|
36204
|
+
const STYLE_POLICIES = {
|
|
36205
|
+
print: PRINT_STYLE_POLICY,
|
|
36206
|
+
'print-header': PRINT_STYLE_POLICY,
|
|
36207
|
+
};
|
|
36208
|
+
/**
|
|
36209
|
+
* Sanitize an HTML string for the given preset (+ feature overrides — pass the
|
|
36210
|
+
* same `features` you gave `getExtensions`/`createEditor` so the whitelist
|
|
36211
|
+
* stays in lock-step with the schema). Always strips script/object/embed/style/
|
|
36212
|
+
* form/event-handlers and `javascript:` URLs (DOMPurify default). `<iframe>` is
|
|
36213
|
+
* allowed ONLY for the document preset and ONLY with an `https:` source
|
|
36214
|
+
* (YouTube, Vimeo, Loom, Slides, … survive save/render; unsafe embeds are
|
|
36215
|
+
* dropped). `style` is capped to color/background-color/text-align.
|
|
36216
|
+
*/
|
|
36217
|
+
function sanitize(html, preset = 'task', features) {
|
|
36218
|
+
if (!html)
|
|
36219
|
+
return '';
|
|
36220
|
+
const cfg = configFor(preset, features);
|
|
36221
|
+
purify_es.purify.addHook('uponSanitizeElement', (node, data) => {
|
|
36222
|
+
// Only allow <input type="checkbox"> (task list checkboxes); strip others.
|
|
36223
|
+
if (data.tagName === 'input' && node.type !== 'checkbox') {
|
|
36224
|
+
node.parentNode?.removeChild(node);
|
|
36225
|
+
}
|
|
36226
|
+
// Allow only https iframes (YouTube and other embeds); drop anything else.
|
|
36227
|
+
if (data.tagName === 'iframe') {
|
|
36228
|
+
const src = node.getAttribute('src') || '';
|
|
36229
|
+
if (!SAFE_IFRAME_SRC_RE.test(src))
|
|
36230
|
+
node.parentNode?.removeChild(node);
|
|
36231
|
+
}
|
|
36232
|
+
});
|
|
36233
|
+
// Cap `style` (and, in print, the image's containerstyle/wrapperstyle) to
|
|
36234
|
+
// the properties the preset's extensions actually emit; strip the rest
|
|
36235
|
+
// (position:fixed, background-image url(), expression(), …). Drop the attr
|
|
36236
|
+
// entirely when nothing survives. The default policy is the pre-print rule
|
|
36237
|
+
// verbatim (guarded by sanitizer.presets.snapshot.test.ts).
|
|
36238
|
+
const policy = STYLE_POLICIES[preset] ?? DEFAULT_STYLE_POLICY;
|
|
36239
|
+
purify_es.purify.addHook('uponSanitizeAttribute', (_node, data) => {
|
|
36240
|
+
if (!policy.attrs.has(data.attrName))
|
|
36241
|
+
return;
|
|
36242
|
+
const decls = data.attrValue.split(';').map((d) => d.trim()).filter(Boolean);
|
|
36243
|
+
const safe = decls.filter((d) => {
|
|
36244
|
+
const colon = d.indexOf(':');
|
|
36245
|
+
if (colon <= 0)
|
|
36246
|
+
return false;
|
|
36247
|
+
const prop = d.slice(0, colon).trim().toLowerCase();
|
|
36248
|
+
const value = d.slice(colon + 1).trim();
|
|
36249
|
+
return !UNSAFE_STYLE_VALUE.test(d) && policy.allows(prop, value);
|
|
36250
|
+
});
|
|
36251
|
+
if (policy.keepOriginalWhenClean && safe.length === decls.length && safe.length > 0)
|
|
36252
|
+
return;
|
|
36253
|
+
data.attrValue = safe.join('; ');
|
|
36254
|
+
if (!data.attrValue)
|
|
36255
|
+
data.keepAttr = false;
|
|
36256
|
+
});
|
|
36257
|
+
try {
|
|
36258
|
+
const clean = purify_es.purify.sanitize(html, {
|
|
36259
|
+
ALLOWED_TAGS: cfg.ALLOWED_TAGS,
|
|
36260
|
+
ALLOWED_ATTR: cfg.ALLOWED_ATTR,
|
|
36261
|
+
ALLOW_DATA_ATTR: cfg.ALLOW_DATA_ATTR ?? false,
|
|
36262
|
+
FORBID_TAGS,
|
|
36263
|
+
FORBID_ATTR,
|
|
36264
|
+
ADD_ATTR: ['target', 'allowfullscreen', 'frameborder', 'allow'],
|
|
36265
|
+
...(cfg.ADD_URI_SAFE_ATTR ? { ADD_URI_SAFE_ATTR: cfg.ADD_URI_SAFE_ATTR } : {}),
|
|
36266
|
+
});
|
|
36267
|
+
return clean;
|
|
36268
|
+
}
|
|
36269
|
+
finally {
|
|
36270
|
+
purify_es.purify.removeHook('uponSanitizeElement');
|
|
36271
|
+
purify_es.purify.removeHook('uponSanitizeAttribute');
|
|
36272
|
+
}
|
|
36273
|
+
}
|
|
36274
|
+
|
|
36275
|
+
/**
|
|
36276
|
+
* Lector tolerante del HTML de impresión (spec contracts-v2-contract-editor §3.3).
|
|
36277
|
+
* Entrada: lo que guardó V1 (documento completo con CSS, fragmento que dejó
|
|
36278
|
+
* cheerio en el backend, cuerpo compilado de generateFromDeal) o lo que escribe
|
|
36279
|
+
* el serializador canónico. Salida: SOLO el cuerpo, sin restos de edición.
|
|
36280
|
+
* No usa schema: el parse lo hace readPrintHtml (print/io.ts).
|
|
36281
|
+
*/
|
|
36282
|
+
const EDITING_CLASSES = ['ProseMirror-selectednode', 'variable-node--editing', 'selectedCell'];
|
|
36283
|
+
const BLOCK_TAGS = new Set(['P', 'DIV', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'UL', 'OL', 'LI', 'TABLE', 'BLOCKQUOTE', 'PRE', 'HR']);
|
|
36284
|
+
const INLINE_CONTENT_TAGS = new Set(['P', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6']);
|
|
36285
|
+
const HEAD_ONLY = 'style, script, meta, title, link, base';
|
|
36286
|
+
function normalizePrintHtml(html) {
|
|
36287
|
+
if (!html || !html.trim())
|
|
36288
|
+
return '';
|
|
36289
|
+
const doc = new DOMParser().parseFromString(html, 'text/html');
|
|
36290
|
+
const root = doc.querySelector('.tiptap.ProseMirror, .ProseMirror') ?? doc.body;
|
|
36291
|
+
root.querySelectorAll('#document-metadata').forEach((el) => el.remove());
|
|
36292
|
+
root.querySelectorAll(HEAD_ONLY).forEach((el) => el.remove());
|
|
36293
|
+
// prosemirror-model convierte estos br en saltos REALES al re-parsear: fuera todos.
|
|
36294
|
+
root.querySelectorAll('br.ProseMirror-trailingBreak, img.ProseMirror-separator').forEach((el) => el.remove());
|
|
36295
|
+
// V1 serializa por error la decoración de {{ }}.
|
|
36296
|
+
root.querySelectorAll('span.hb-token').forEach(unwrap);
|
|
36297
|
+
Array.from(root.querySelectorAll('*')).forEach(cleanEditingResidue);
|
|
36298
|
+
cleanCellStyles(root);
|
|
36299
|
+
rebuildSplitImages(root);
|
|
36300
|
+
// Tras desenvolver hb-token y quitar breaks quedan textos adyacentes: un token repartido entre ellos no matchearía.
|
|
36301
|
+
root.normalize();
|
|
36302
|
+
tokensToFieldSpans(root);
|
|
36303
|
+
return root.innerHTML;
|
|
36304
|
+
}
|
|
36305
|
+
function unwrap(el) {
|
|
36306
|
+
el.replaceWith(...Array.from(el.childNodes));
|
|
36307
|
+
}
|
|
36308
|
+
function cleanEditingResidue(el) {
|
|
36309
|
+
Array.from(el.attributes).forEach((a) => {
|
|
36310
|
+
if (a.name.startsWith('data-v-') || a.name === 'data-node-view-wrapper')
|
|
36311
|
+
el.removeAttribute(a.name);
|
|
36312
|
+
});
|
|
36313
|
+
EDITING_CLASSES.forEach((c) => el.classList.remove(c));
|
|
36314
|
+
if (el.getAttribute('class') === '')
|
|
36315
|
+
el.removeAttribute('class');
|
|
36316
|
+
}
|
|
36317
|
+
function cleanCellStyles(root) {
|
|
36318
|
+
root.querySelectorAll('td[style], th[style]').forEach((cell) => {
|
|
36319
|
+
const kept = (cell.getAttribute('style') || '')
|
|
36320
|
+
.split(';')
|
|
36321
|
+
.map((d) => d.trim())
|
|
36322
|
+
.filter((d) => {
|
|
36323
|
+
const i = d.indexOf(':');
|
|
36324
|
+
if (i <= 0)
|
|
36325
|
+
return false;
|
|
36326
|
+
const v = d.slice(i + 1).trim().toLowerCase();
|
|
36327
|
+
return v !== '' && v !== 'null' && v !== 'undefined';
|
|
36328
|
+
});
|
|
36329
|
+
if (kept.length)
|
|
36330
|
+
cell.setAttribute('style', kept.join('; '));
|
|
36331
|
+
else
|
|
36332
|
+
cell.removeAttribute('style');
|
|
36333
|
+
});
|
|
36334
|
+
}
|
|
36335
|
+
const isBlockNode = (n) => n.nodeType === 1 && BLOCK_TAGS.has(n.tagName);
|
|
36336
|
+
const isBlankText = (n) => n.nodeType === 3 && !(n.textContent ?? '').trim();
|
|
36337
|
+
/**
|
|
36338
|
+
* V1 guarda la imagen como `<div wrapper><div container><img></div></div>`
|
|
36339
|
+
* DENTRO del `<p>`; el parser HTML5 parte el párrafo en `<p>antes</p><div>…</div>después<p></p>`.
|
|
36340
|
+
* Se vuelve a juntar en un solo párrafo, con los estilos del wrapper y del
|
|
36341
|
+
* container copiados al `<img>` (así los lee el nodo image del preset print).
|
|
36342
|
+
*/
|
|
36343
|
+
function rebuildSplitImages(root) {
|
|
36344
|
+
const doc = root.ownerDocument;
|
|
36345
|
+
Array.from(root.querySelectorAll('img')).forEach((img) => {
|
|
36346
|
+
const container = img.parentElement;
|
|
36347
|
+
// `container !== root`: un <img> suelto al tope del cuerpo no es una imagen partida.
|
|
36348
|
+
if (!container || container === root || container.tagName !== 'DIV' || container.firstElementChild !== img)
|
|
36349
|
+
return;
|
|
36350
|
+
const parent = container.parentElement;
|
|
36351
|
+
const wrapper = parent && parent.tagName === 'DIV' && parent.firstElementChild === container && parent !== root ? parent : null;
|
|
36352
|
+
const containerCss = container.getAttribute('style');
|
|
36353
|
+
if (containerCss && !img.hasAttribute('containerstyle'))
|
|
36354
|
+
img.setAttribute('containerstyle', containerCss);
|
|
36355
|
+
const wrapperCss = wrapper?.getAttribute('style');
|
|
36356
|
+
if (wrapperCss && !img.hasAttribute('wrapperstyle'))
|
|
36357
|
+
img.setAttribute('wrapperstyle', wrapperCss);
|
|
36358
|
+
const outer = wrapper ?? container;
|
|
36359
|
+
// El parser HTML5 solo parte <p>: dentro de un título (o de un <p> que no se
|
|
36360
|
+
// partió) la imagen queda en su lugar, sin recomponer hermanos ni crear <p>.
|
|
36361
|
+
if (outer.parentElement && INLINE_CONTENT_TAGS.has(outer.parentElement.tagName)) {
|
|
36362
|
+
outer.replaceWith(img);
|
|
36363
|
+
return;
|
|
36364
|
+
}
|
|
36365
|
+
const before = [];
|
|
36366
|
+
let prev = outer.previousSibling;
|
|
36367
|
+
while (prev && !isBlockNode(prev)) {
|
|
36368
|
+
before.unshift(prev);
|
|
36369
|
+
prev = prev.previousSibling;
|
|
36370
|
+
}
|
|
36371
|
+
const after = [];
|
|
36372
|
+
let next = outer.nextSibling;
|
|
36373
|
+
while (next && !isBlockNode(next)) {
|
|
36374
|
+
after.push(next);
|
|
36375
|
+
next = next.nextSibling;
|
|
36376
|
+
}
|
|
36377
|
+
// El `</p>` original quedó huérfano: el parser lo convierte en un <p></p> vacío.
|
|
36378
|
+
if (next && next.nodeName === 'P' && !next.hasChildNodes())
|
|
36379
|
+
next.remove();
|
|
36380
|
+
let target;
|
|
36381
|
+
if (before.every(isBlankText) && prev && prev.nodeName === 'P') {
|
|
36382
|
+
before.forEach((n) => n.parentNode?.removeChild(n));
|
|
36383
|
+
target = prev;
|
|
36384
|
+
}
|
|
36385
|
+
else {
|
|
36386
|
+
target = doc.createElement('p');
|
|
36387
|
+
outer.before(target);
|
|
36388
|
+
before.forEach((n) => target.appendChild(n));
|
|
36389
|
+
}
|
|
36390
|
+
target.appendChild(img);
|
|
36391
|
+
after.forEach((n) => target.appendChild(n));
|
|
36392
|
+
outer.remove();
|
|
36393
|
+
});
|
|
36394
|
+
}
|
|
36395
|
+
function tokensToFieldSpans(root) {
|
|
36396
|
+
const doc = root.ownerDocument;
|
|
36397
|
+
const walker = doc.createTreeWalker(root, NodeFilter.SHOW_TEXT);
|
|
36398
|
+
const targets = [];
|
|
36399
|
+
let n;
|
|
36400
|
+
while ((n = walker.nextNode())) {
|
|
36401
|
+
const t = n;
|
|
36402
|
+
if (!t.data.includes('[['))
|
|
36403
|
+
continue;
|
|
36404
|
+
if (t.parentElement?.closest('[data-variable], [data-sig-slot], pre, code'))
|
|
36405
|
+
continue;
|
|
36406
|
+
targets.push(t);
|
|
36407
|
+
}
|
|
36408
|
+
targets.forEach((t) => {
|
|
36409
|
+
const text = t.data;
|
|
36410
|
+
const re = fieldTokenRegex();
|
|
36411
|
+
const frag = doc.createDocumentFragment();
|
|
36412
|
+
let last = 0;
|
|
36413
|
+
let any = false;
|
|
36414
|
+
let m;
|
|
36415
|
+
while ((m = re.exec(text)) !== null) {
|
|
36416
|
+
const def = parseFieldToken(m[1]);
|
|
36417
|
+
if (!def)
|
|
36418
|
+
continue;
|
|
36419
|
+
any = true;
|
|
36420
|
+
if (m.index > last)
|
|
36421
|
+
frag.appendChild(doc.createTextNode(text.slice(last, m.index)));
|
|
36422
|
+
const span = doc.createElement('span');
|
|
36423
|
+
span.setAttribute('data-variable', def.name);
|
|
36424
|
+
span.setAttribute('data-value', '');
|
|
36425
|
+
span.setAttribute('data-type', def.type);
|
|
36426
|
+
span.setAttribute('data-required', def.required ? 'true' : 'false');
|
|
36427
|
+
if (def.enum)
|
|
36428
|
+
span.setAttribute('data-enum', JSON.stringify(def.enum));
|
|
36429
|
+
span.textContent = `[[${def.name}]]`;
|
|
36430
|
+
frag.appendChild(span);
|
|
36431
|
+
last = m.index + m[0].length;
|
|
36432
|
+
}
|
|
36433
|
+
if (!any)
|
|
36434
|
+
return;
|
|
36435
|
+
if (last < text.length)
|
|
36436
|
+
frag.appendChild(doc.createTextNode(text.slice(last)));
|
|
36437
|
+
t.replaceWith(frag);
|
|
36438
|
+
});
|
|
36439
|
+
}
|
|
36440
|
+
|
|
36441
|
+
/**
|
|
36442
|
+
* Serializador canónico del preset print (spec contracts-v2-contract-editor §3.4).
|
|
36443
|
+
* Escribe desde el DOCUMENTO (renderHTML del schema), nunca desde el DOM de
|
|
36444
|
+
* pantalla: así no se cuelan NodeViews, decoraciones ni los hacks de
|
|
36445
|
+
* prosemirror-view que V1 guardaba con innerHTML.
|
|
36446
|
+
*
|
|
36447
|
+
* H1: `DOMSerializer` escribe `style` por CSSOM (`dom.style.cssText = …`), que
|
|
36448
|
+
* normaliza el string (`#ff0000` → `rgb(255, 0, 0)`, `top:0` → `top: 0px;`) y
|
|
36449
|
+
* rompe la forma byte a byte de V1 (firma, color, tamaño, imagen). Por eso se
|
|
36450
|
+
* serializa con un `document` sustituto cuyos elementos no exponen `style`:
|
|
36451
|
+
* ProseMirror cae a `setAttribute` y conserva el string crudo. `editor.getHTML()`
|
|
36452
|
+
* NO es la forma canónica.
|
|
36453
|
+
*/
|
|
36454
|
+
const TRAILING_BREAK_CLASS = 'ProseMirror-trailingBreak';
|
|
36455
|
+
const TRAILING_MARKER = 'data-co-trailing-break';
|
|
36456
|
+
/**
|
|
36457
|
+
* Como prosemirror-view, el trailingBreak se decide por el NODO: textblock vacío o
|
|
36458
|
+
* cuyo último hijo es un hardBreak (aunque el <br> quede dentro de un mark).
|
|
36459
|
+
*/
|
|
36460
|
+
function needsTrailingBreak(node) {
|
|
36461
|
+
if (!node.isTextblock)
|
|
36462
|
+
return false;
|
|
36463
|
+
return node.childCount === 0 || node.lastChild.type.name === 'hardBreak';
|
|
36464
|
+
}
|
|
36465
|
+
/**
|
|
36466
|
+
* Marca el elemento de bloque (spec `[tag, attrs?, 0]`, hueco directo en el
|
|
36467
|
+
* elemento: p/h*) para que el <br> vaya como su ÚLTIMO hijo, fuera de los marks.
|
|
36468
|
+
*/
|
|
36469
|
+
function withTrailingMarker(spec) {
|
|
36470
|
+
if (!Array.isArray(spec) || spec[spec.length - 1] !== 0)
|
|
36471
|
+
return spec;
|
|
36472
|
+
const attrs = spec[1];
|
|
36473
|
+
if (attrs && typeof attrs === 'object' && !Array.isArray(attrs) && !('nodeType' in attrs)) {
|
|
36474
|
+
return [spec[0], { ...attrs, [TRAILING_MARKER]: '' }, ...spec.slice(2)];
|
|
36475
|
+
}
|
|
36476
|
+
return [spec[0], { [TRAILING_MARKER]: '' }, ...spec.slice(1)];
|
|
36477
|
+
}
|
|
36478
|
+
function rawStyleDocument(real) {
|
|
36479
|
+
return {
|
|
36480
|
+
createElement: (tag) => {
|
|
36481
|
+
const el = real.createElement(tag);
|
|
36482
|
+
Object.defineProperty(el, 'style', { value: null });
|
|
36483
|
+
return el;
|
|
36484
|
+
},
|
|
36485
|
+
createElementNS: (ns, tag) => {
|
|
36486
|
+
const el = real.createElementNS(ns, tag);
|
|
36487
|
+
Object.defineProperty(el, 'style', { value: null });
|
|
36488
|
+
return el;
|
|
36489
|
+
},
|
|
36490
|
+
createTextNode: real.createTextNode.bind(real),
|
|
36491
|
+
createDocumentFragment: real.createDocumentFragment.bind(real),
|
|
36492
|
+
};
|
|
36493
|
+
}
|
|
36494
|
+
function printSerializer(schema) {
|
|
36495
|
+
const base = DOMSerializer.fromSchema(schema);
|
|
36496
|
+
const nodes = {};
|
|
36497
|
+
Object.entries(base.nodes).forEach(([name, render]) => {
|
|
36498
|
+
nodes[name] = (node) => {
|
|
36499
|
+
const spec = render(node);
|
|
36500
|
+
return needsTrailingBreak(node) ? withTrailingMarker(spec) : spec;
|
|
36501
|
+
};
|
|
36502
|
+
});
|
|
36503
|
+
return new DOMSerializer(nodes, base.marks);
|
|
36504
|
+
}
|
|
36505
|
+
function serializePrintHtml(doc) {
|
|
36506
|
+
const container = document.createElement('div');
|
|
36507
|
+
const fragment = printSerializer(doc.type.schema).serializeFragment(doc.content, {
|
|
36508
|
+
document: rawStyleDocument(document),
|
|
36509
|
+
});
|
|
36510
|
+
container.appendChild(fragment);
|
|
36511
|
+
// Sin el trailingBreak la línea vacía o final no ocupa alto en el PDF
|
|
36512
|
+
// (.tiptap p{margin:0}). El lector lo quita al volver.
|
|
36513
|
+
container.querySelectorAll(`[${TRAILING_MARKER}]`).forEach((el) => {
|
|
36514
|
+
el.removeAttribute(TRAILING_MARKER);
|
|
36515
|
+
const br = document.createElement('br');
|
|
36516
|
+
br.className = TRAILING_BREAK_CLASS;
|
|
36517
|
+
el.appendChild(br);
|
|
36518
|
+
});
|
|
36519
|
+
return container.innerHTML;
|
|
36520
|
+
}
|
|
36521
|
+
|
|
36522
|
+
function isPrintPreset(p) {
|
|
36523
|
+
return p === 'print' || p === 'print-header';
|
|
36524
|
+
}
|
|
36525
|
+
function schemaExtensions(preset, features) {
|
|
36526
|
+
return getExtensions(preset, { includeUiExtensions: false, features });
|
|
36527
|
+
}
|
|
36528
|
+
/** HTML de impresión (el de V1 incluido) → JSON: lector tolerante → limpieza del preset → parse. */
|
|
36529
|
+
function readPrintHtml(html, preset = 'print', features) {
|
|
36530
|
+
const clean = sanitize(normalizePrintHtml(html ?? ''), preset, features);
|
|
36531
|
+
return generateJSON(clean, schemaExtensions(preset, features));
|
|
36532
|
+
}
|
|
36533
|
+
/**
|
|
36534
|
+
* Documento → forma canónica (spec §3.4), pasada por la limpieza del preset.
|
|
36535
|
+
* Es la ÚNICA forma canónica: `editor.getHTML()` de Tiptap normaliza los `style`
|
|
36536
|
+
* (H1) y no sirve para guardar.
|
|
36537
|
+
*/
|
|
36538
|
+
function writePrintHtml(doc, preset = 'print', features) {
|
|
36539
|
+
if (!doc)
|
|
36540
|
+
return '';
|
|
36541
|
+
const node = doc instanceof Node$1
|
|
36542
|
+
? doc
|
|
36543
|
+
: Node$1.fromJSON(getSchema(schemaExtensions(preset, features)), doc);
|
|
36544
|
+
return sanitize(serializePrintHtml(node), preset, features);
|
|
36545
|
+
}
|
|
36546
|
+
/** Aplica valores a los campos de un HTML sin montar un editor (encabezado fuera de edición). */
|
|
36547
|
+
function setFieldValuesInHtml(html, values, preset = 'print-header', features) {
|
|
36548
|
+
if (!html)
|
|
36549
|
+
return '';
|
|
36550
|
+
const json = readPrintHtml(html, preset, features);
|
|
36551
|
+
const apply = (n) => {
|
|
36552
|
+
if (n.type === 'mergeField' && n.attrs && Object.prototype.hasOwnProperty.call(values, n.attrs.name)) {
|
|
36553
|
+
n.attrs = { ...n.attrs, value: String(values[n.attrs.name] ?? '') };
|
|
36554
|
+
}
|
|
36555
|
+
n.content?.forEach(apply);
|
|
36556
|
+
};
|
|
36557
|
+
apply(json);
|
|
36558
|
+
return writePrintHtml(json, preset, features);
|
|
36559
|
+
}
|
|
35188
36560
|
|
|
35189
36561
|
/**
|
|
35190
36562
|
* ProseMirror editorProps that insert pasted/dropped images optimistically
|
|
@@ -35310,6 +36682,11 @@ function autolinkTrailing(editor) {
|
|
|
35310
36682
|
editor.view.dispatch(tr);
|
|
35311
36683
|
return changed;
|
|
35312
36684
|
}
|
|
36685
|
+
/** El autolink al perder foco solo corre si el link del schema lo tiene activo (print lo apaga). */
|
|
36686
|
+
function autolinkEnabled(editor) {
|
|
36687
|
+
const link = editor.extensionManager.extensions.find((ext) => ext.name === 'link');
|
|
36688
|
+
return !!(link && link.options.autolink);
|
|
36689
|
+
}
|
|
35313
36690
|
/**
|
|
35314
36691
|
* Create a configured Tiptap v3 editor for a Cobalt preset.
|
|
35315
36692
|
*
|
|
@@ -35318,9 +36695,9 @@ function autolinkTrailing(editor) {
|
|
|
35318
36695
|
* always false — Cobalt owns every style.
|
|
35319
36696
|
*/
|
|
35320
36697
|
function createEditor(options = {}) {
|
|
35321
|
-
const { preset = 'task', element = null, content = null, editable = true, placeholder, maxLength, features, customExtensions = [], bubbleMenuElement, imageUpload, onUpdate, onSelectionUpdate, onFocus, onBlur, onCreate, onDestroy, onContentError, } = options;
|
|
36698
|
+
const { preset = 'task', element = null, content = null, editable = true, placeholder, maxLength, features, labels, customExtensions = [], bubbleMenuElement, imageUpload, onUpdate, onSelectionUpdate, onFocus, onBlur, onCreate, onDestroy, onContentError, } = options;
|
|
35322
36699
|
const extensions = [
|
|
35323
|
-
...getExtensions(preset, { placeholder, maxLength, features }),
|
|
36700
|
+
...getExtensions(preset, { placeholder, maxLength, features, labels }),
|
|
35324
36701
|
...customExtensions,
|
|
35325
36702
|
];
|
|
35326
36703
|
let editor;
|
|
@@ -35377,11 +36754,13 @@ function createEditor(options = {}) {
|
|
|
35377
36754
|
},
|
|
35378
36755
|
}));
|
|
35379
36756
|
}
|
|
36757
|
+
// En print, un string es HTML de impresión (quizá de V1): pasa por el lector tolerante.
|
|
36758
|
+
const initialContent = isPrintPreset(preset) && typeof content === 'string' ? readPrintHtml(content, preset, features) : content;
|
|
35380
36759
|
editor = new Editor({
|
|
35381
36760
|
...(element ? { element } : {}),
|
|
35382
36761
|
...(imageUpload ? { editorProps: imageDropPaste(imageUpload) } : {}),
|
|
35383
36762
|
extensions,
|
|
35384
|
-
content:
|
|
36763
|
+
content: initialContent ?? '',
|
|
35385
36764
|
editable,
|
|
35386
36765
|
injectCSS: false,
|
|
35387
36766
|
// `enableContentCheck: true` makes tiptap THROW on invalid content from
|
|
@@ -35396,304 +36775,408 @@ function createEditor(options = {}) {
|
|
|
35396
36775
|
onUpdate: ({ editor: e }) => onUpdate?.(e),
|
|
35397
36776
|
onSelectionUpdate: ({ editor: e }) => onSelectionUpdate?.(e),
|
|
35398
36777
|
onFocus: ({ editor: e }) => onFocus?.(e),
|
|
35399
|
-
onBlur: ({ editor: e }) => {
|
|
36778
|
+
onBlur: ({ editor: e }) => { if (autolinkEnabled(e))
|
|
36779
|
+
autolinkTrailing(e); onBlur?.(e); },
|
|
35400
36780
|
onDestroy: () => onDestroy?.(),
|
|
35401
36781
|
});
|
|
35402
36782
|
return editor;
|
|
35403
36783
|
}
|
|
35404
36784
|
|
|
35405
|
-
|
|
35406
|
-
|
|
35407
|
-
|
|
35408
|
-
|
|
35409
|
-
|
|
35410
|
-
|
|
35411
|
-
|
|
35412
|
-
|
|
35413
|
-
|
|
35414
|
-
|
|
35415
|
-
|
|
35416
|
-
|
|
35417
|
-
|
|
35418
|
-
|
|
35419
|
-
|
|
35420
|
-
|
|
35421
|
-
|
|
35422
|
-
|
|
35423
|
-
|
|
35424
|
-
|
|
35425
|
-
|
|
35426
|
-
|
|
35427
|
-
|
|
35428
|
-
|
|
35429
|
-
|
|
35430
|
-
|
|
35431
|
-
|
|
35432
|
-
|
|
35433
|
-
|
|
35434
|
-
|
|
35435
|
-
|
|
35436
|
-
throw new Error(
|
|
35437
|
-
"generateJSON can only be used in a browser environment\nIf you want to use this in a Node environment, use the `@tiptap/html/server` import instead."
|
|
35438
|
-
);
|
|
35439
|
-
}
|
|
35440
|
-
const schema = getSchema(extensions);
|
|
35441
|
-
const doc = new window.DOMParser().parseFromString(html, "text/html");
|
|
35442
|
-
if (!doc) {
|
|
35443
|
-
throw new Error("Failed to parse HTML string");
|
|
35444
|
-
}
|
|
35445
|
-
return DOMParser.fromSchema(schema).parse(doc.body, options).toJSON();
|
|
35446
|
-
}
|
|
35447
|
-
|
|
35448
|
-
const BASE_INLINE = ['p', 'br', 'strong', 'em', 'a', 'span'];
|
|
35449
|
-
const BASE_ATTR = ['href', 'target', 'rel', 'data-mention-id', 'data-mention-label'];
|
|
35450
|
-
const SANITIZE_CONFIGS = {
|
|
35451
|
-
// Más ancho que su schema A PROPÓSITO (única excepción al lock-step): el
|
|
35452
|
-
// editor `comment` no puede autorar listas ni headings (STARTERKIT_CONFIG los
|
|
35453
|
-
// apaga y ProseMirror descarta esos nodos al parsear el paste), pero el
|
|
35454
|
-
// VIEWER tiene que pintarlos cuando el HTML entra por API — una nota de
|
|
35455
|
-
// enriquecimiento (Apollo.io) trae <ul>/<li>/<h4> y con KEEP_CONTENT el
|
|
35456
|
-
// texto se hoisteaba al padre: lista corrida, heading fundido en el cuerpo.
|
|
35457
|
-
// Espejo inline en core/co-rich-text-viewer.tsx (ALLOWED_TAGS.comment).
|
|
35458
|
-
comment: {
|
|
35459
|
-
ALLOWED_TAGS: [...BASE_INLINE, 'ul', 'ol', 'li', 'h1', 'h2', 'h3', 'h4'],
|
|
35460
|
-
ALLOWED_ATTR: [...BASE_ATTR],
|
|
35461
|
-
ALLOW_DATA_ATTR: false,
|
|
35462
|
-
},
|
|
35463
|
-
task: {
|
|
35464
|
-
ALLOWED_TAGS: [...BASE_INLINE, 'u', 's', 'code', 'ul', 'ol', 'li', 'blockquote', 'input', 'label'],
|
|
35465
|
-
ALLOWED_ATTR: [...BASE_ATTR, 'type', 'checked', 'disabled', 'data-type', 'data-checked', 'data-variant'],
|
|
35466
|
-
ALLOW_DATA_ATTR: false,
|
|
35467
|
-
},
|
|
35468
|
-
// Lock-step con getExtensions('notes'): task sin checklists + TextStyle/Color
|
|
35469
|
-
// (`style` capado a STYLE_ALLOWED_PROPS) + Highlight multicolor (`mark` con
|
|
35470
|
-
// `data-color`).
|
|
35471
|
-
notes: {
|
|
35472
|
-
ALLOWED_TAGS: [...BASE_INLINE, 'u', 's', 'code', 'ul', 'ol', 'li', 'blockquote', 'mark'],
|
|
35473
|
-
ALLOWED_ATTR: [...BASE_ATTR, 'style', 'data-color'],
|
|
35474
|
-
ALLOW_DATA_ATTR: false,
|
|
35475
|
-
},
|
|
35476
|
-
email: {
|
|
35477
|
-
ALLOWED_TAGS: [
|
|
35478
|
-
...BASE_INLINE, 'u', 's', 'code', 'ul', 'ol', 'li', 'blockquote',
|
|
35479
|
-
'h2', 'h3', 'div', 'img',
|
|
35480
|
-
],
|
|
35481
|
-
ALLOWED_ATTR: [...BASE_ATTR, 'style', 'data-variable', 'data-transform', 'data-fallback', 'src', 'alt', 'width', 'height', 'data-file-id', 'data-image-layout'],
|
|
35482
|
-
ALLOW_DATA_ATTR: false,
|
|
35483
|
-
},
|
|
35484
|
-
document: {
|
|
35485
|
-
ALLOWED_TAGS: [
|
|
35486
|
-
...BASE_INLINE, 'u', 's', 'code', 'ul', 'ol', 'li', 'blockquote',
|
|
35487
|
-
'h1', 'h2', 'h3', 'h4', 'hr', 'div', 'mark', 'img',
|
|
35488
|
-
'table', 'thead', 'tbody', 'tr', 'th', 'td',
|
|
35489
|
-
'input', 'label', 'iframe',
|
|
35490
|
-
],
|
|
35491
|
-
ALLOWED_ATTR: [...BASE_ATTR, 'style', 'data-variable', 'colspan', 'rowspan', 'src', 'alt', 'width', 'height', 'type', 'checked', 'disabled', 'allowfullscreen', 'frameborder', 'allow', 'loading'],
|
|
35492
|
-
ALLOW_DATA_ATTR: true,
|
|
35493
|
-
},
|
|
35494
|
-
'block-email': {
|
|
35495
|
-
ALLOWED_TAGS: [...BASE_INLINE, 'u', 's', 'code', 'ul', 'ol', 'li', 'blockquote', 'h2', 'h3', 'div', 'img'],
|
|
35496
|
-
ALLOWED_ATTR: [...BASE_ATTR, 'style', 'data-variable', 'data-transform', 'data-fallback', 'src', 'alt', 'width', 'height', 'data-file-id', 'data-image-layout', 'data-type', 'data-label', 'data-href', 'data-bg', 'data-color', 'data-height'],
|
|
35497
|
-
ALLOW_DATA_ATTR: false,
|
|
35498
|
-
},
|
|
35499
|
-
};
|
|
35500
|
-
/**
|
|
35501
|
-
* `<iframe>`s are permitted only with an `https:` source (blocks javascript:,
|
|
35502
|
-
* data:, and plain http: embeds). This is what makes allowing iframes safe-ish
|
|
35503
|
-
* for a trusted-author document; YouTube embeds satisfy it too.
|
|
35504
|
-
*/
|
|
35505
|
-
const SAFE_IFRAME_SRC_RE = /^https:\/\/[^\s"'<>]+$/i;
|
|
35506
|
-
/** Tags forbidden in every preset, regardless of the allow-list. */
|
|
35507
|
-
const FORBID_TAGS = ['script', 'object', 'embed', 'form', 'textarea', 'style'];
|
|
35508
|
-
/** Attributes forbidden in every preset (event handlers handled by DOMPurify itself). */
|
|
35509
|
-
const FORBID_ATTR = ['onerror', 'onload', 'onclick'];
|
|
35510
|
-
/**
|
|
35511
|
-
* Resolve the effective config for a preset + feature overrides. Features can
|
|
35512
|
-
* only ADD capabilities (mirroring `getExtensions`, where they register extra
|
|
35513
|
-
* nodes); they never narrow a preset's base whitelist.
|
|
35514
|
-
*/
|
|
35515
|
-
function configFor(preset, features) {
|
|
35516
|
-
const cfg = SANITIZE_CONFIGS[preset] ?? SANITIZE_CONFIGS.task;
|
|
35517
|
-
if (!features)
|
|
35518
|
-
return cfg;
|
|
35519
|
-
const tags = new Set(cfg.ALLOWED_TAGS);
|
|
35520
|
-
const attr = new Set(cfg.ALLOWED_ATTR);
|
|
35521
|
-
if (features.image) {
|
|
35522
|
-
tags.add('img');
|
|
35523
|
-
['src', 'alt', 'width', 'height'].forEach((a) => attr.add(a));
|
|
35524
|
-
}
|
|
35525
|
-
if (features.variables)
|
|
35526
|
-
attr.add('data-variable');
|
|
35527
|
-
if (features.mentions) {
|
|
35528
|
-
// data-mention-id/label ya están en BASE_ATTR. Los attrs del markup V1
|
|
35529
|
-
// (quill-mention) se suman porque el BACKEND los parsea para notificar —
|
|
35530
|
-
// re-editar una nota no debe destruirlos.
|
|
35531
|
-
// Espejo inline en core/co-rich-text-viewer.tsx (el viewer no importa este módulo para no cargar el engine) — si cambias esta lista, cambia la del viewer.
|
|
35532
|
-
['data-id', 'data-value', 'data-denotation-char', 'data-index'].forEach((a) => attr.add(a));
|
|
36785
|
+
function computePageBreaks(atoms, pageContentHeight) {
|
|
36786
|
+
const breaks = [];
|
|
36787
|
+
if (!atoms.length || !(pageContentHeight > 0))
|
|
36788
|
+
return { breaks, pageCount: 1 };
|
|
36789
|
+
let page = 1;
|
|
36790
|
+
let start = 0;
|
|
36791
|
+
let pageTop = atoms[0].top;
|
|
36792
|
+
let i = 0;
|
|
36793
|
+
while (i < atoms.length) {
|
|
36794
|
+
const atom = atoms[i];
|
|
36795
|
+
const bottom = atom.top + atom.height;
|
|
36796
|
+
if (bottom - pageTop <= pageContentHeight) {
|
|
36797
|
+
i += 1;
|
|
36798
|
+
continue;
|
|
36799
|
+
}
|
|
36800
|
+
if (i === start) {
|
|
36801
|
+
// Más alto que una hoja: ocupa las que necesite; no hay frontera adentro.
|
|
36802
|
+
const extra = Math.ceil((bottom - pageTop) / pageContentHeight) - 1;
|
|
36803
|
+
page += extra;
|
|
36804
|
+
pageTop += extra * pageContentHeight;
|
|
36805
|
+
i += 1;
|
|
36806
|
+
continue;
|
|
36807
|
+
}
|
|
36808
|
+
let b = i;
|
|
36809
|
+
while (b - 1 > start && atoms[b - 1].keepWithNext)
|
|
36810
|
+
b -= 1;
|
|
36811
|
+
page += 1;
|
|
36812
|
+
breaks.push({ pos: atoms[b].pos, page });
|
|
36813
|
+
start = b;
|
|
36814
|
+
pageTop = atoms[b].top;
|
|
36815
|
+
i = b;
|
|
35533
36816
|
}
|
|
35534
|
-
return {
|
|
36817
|
+
return { breaks, pageCount: page };
|
|
35535
36818
|
}
|
|
35536
36819
|
/**
|
|
35537
|
-
*
|
|
35538
|
-
*
|
|
35539
|
-
* ListStyleExtension's `list-style-type`). Everything else — position,
|
|
35540
|
-
* background-image url(), etc. — is UI-redressing/tracking surface.
|
|
36820
|
+
* Resta a cada átomo la altura de las bandas de salto que ya están dibujadas
|
|
36821
|
+
* por encima (V1 medía con las bandas viejas en el flujo y cortaba antes).
|
|
35541
36822
|
*/
|
|
35542
|
-
|
|
35543
|
-
|
|
35544
|
-
|
|
35545
|
-
|
|
35546
|
-
|
|
35547
|
-
|
|
35548
|
-
|
|
35549
|
-
|
|
35550
|
-
|
|
35551
|
-
|
|
35552
|
-
|
|
35553
|
-
if (!html)
|
|
35554
|
-
return '';
|
|
35555
|
-
const cfg = configFor(preset, features);
|
|
35556
|
-
purify_es.purify.addHook('uponSanitizeElement', (node, data) => {
|
|
35557
|
-
// Only allow <input type="checkbox"> (task list checkboxes); strip others.
|
|
35558
|
-
if (data.tagName === 'input' && node.type !== 'checkbox') {
|
|
35559
|
-
node.parentNode?.removeChild(node);
|
|
35560
|
-
}
|
|
35561
|
-
// Allow only https iframes (YouTube and other embeds); drop anything else.
|
|
35562
|
-
if (data.tagName === 'iframe') {
|
|
35563
|
-
const src = node.getAttribute('src') || '';
|
|
35564
|
-
if (!SAFE_IFRAME_SRC_RE.test(src))
|
|
35565
|
-
node.parentNode?.removeChild(node);
|
|
36823
|
+
function stripBandOffsets(atoms, bands) {
|
|
36824
|
+
if (!bands.length)
|
|
36825
|
+
return atoms;
|
|
36826
|
+
const sorted = [...bands].sort((a, b) => a.top - b.top);
|
|
36827
|
+
return atoms.map((atom) => {
|
|
36828
|
+
let shift = 0;
|
|
36829
|
+
for (const band of sorted) {
|
|
36830
|
+
if (band.top < atom.top)
|
|
36831
|
+
shift += band.height;
|
|
36832
|
+
else
|
|
36833
|
+
break;
|
|
35566
36834
|
}
|
|
36835
|
+
return shift ? { ...atom, top: atom.top - shift } : atom;
|
|
35567
36836
|
});
|
|
35568
|
-
|
|
35569
|
-
|
|
35570
|
-
|
|
35571
|
-
|
|
35572
|
-
|
|
35573
|
-
|
|
35574
|
-
|
|
35575
|
-
|
|
35576
|
-
|
|
35577
|
-
|
|
35578
|
-
|
|
35579
|
-
|
|
35580
|
-
|
|
35581
|
-
|
|
35582
|
-
|
|
35583
|
-
|
|
35584
|
-
|
|
35585
|
-
|
|
35586
|
-
|
|
36837
|
+
}
|
|
36838
|
+
const ATOM_TYPES = new Set(['listItem', 'tableRow']);
|
|
36839
|
+
const CONTAINER_TYPES = new Set(['bulletList', 'orderedList', 'table']);
|
|
36840
|
+
function classifyPaginationNode(node) {
|
|
36841
|
+
const name = node?.type?.name;
|
|
36842
|
+
if (!name || name === 'doc')
|
|
36843
|
+
return 'skip';
|
|
36844
|
+
if (CONTAINER_TYPES.has(name))
|
|
36845
|
+
return 'container';
|
|
36846
|
+
if (ATOM_TYPES.has(name))
|
|
36847
|
+
return 'atom';
|
|
36848
|
+
if (node?.isBlock)
|
|
36849
|
+
return 'atom';
|
|
36850
|
+
return 'skip';
|
|
36851
|
+
}
|
|
36852
|
+
function isKeepWithNext(node) {
|
|
36853
|
+
return node.type.name === 'heading' && Number(node.attrs?.level) >= 2;
|
|
36854
|
+
}
|
|
36855
|
+
/** Columnas de una tabla = suma de colspan de su primera fila (banda-fila que cruza la tabla). */
|
|
36856
|
+
function tableColumnCount(tableNode) {
|
|
36857
|
+
const firstRow = tableNode && typeof tableNode.child === 'function' ? tableNode.child(0) : null;
|
|
36858
|
+
if (!firstRow || typeof firstRow.forEach !== 'function')
|
|
36859
|
+
return 1;
|
|
36860
|
+
let cols = 0;
|
|
36861
|
+
firstRow.forEach((cell) => {
|
|
36862
|
+
cols += cell?.attrs?.colspan || 1;
|
|
35587
36863
|
});
|
|
35588
|
-
|
|
35589
|
-
const clean = purify_es.purify.sanitize(html, {
|
|
35590
|
-
ALLOWED_TAGS: cfg.ALLOWED_TAGS,
|
|
35591
|
-
ALLOWED_ATTR: cfg.ALLOWED_ATTR,
|
|
35592
|
-
ALLOW_DATA_ATTR: cfg.ALLOW_DATA_ATTR ?? false,
|
|
35593
|
-
FORBID_TAGS,
|
|
35594
|
-
FORBID_ATTR,
|
|
35595
|
-
ADD_ATTR: ['target', 'allowfullscreen', 'frameborder', 'allow'],
|
|
35596
|
-
});
|
|
35597
|
-
return clean;
|
|
35598
|
-
}
|
|
35599
|
-
finally {
|
|
35600
|
-
purify_es.purify.removeHook('uponSanitizeElement');
|
|
35601
|
-
purify_es.purify.removeHook('uponSanitizeAttribute');
|
|
35602
|
-
}
|
|
36864
|
+
return cols || 1;
|
|
35603
36865
|
}
|
|
35604
36866
|
|
|
35605
|
-
/**
|
|
35606
|
-
|
|
35607
|
-
|
|
35608
|
-
}
|
|
35609
|
-
|
|
35610
|
-
|
|
35611
|
-
|
|
35612
|
-
|
|
35613
|
-
|
|
35614
|
-
|
|
35615
|
-
|
|
35616
|
-
|
|
35617
|
-
|
|
35618
|
-
|
|
35619
|
-
|
|
35620
|
-
|
|
35621
|
-
|
|
35622
|
-
|
|
35623
|
-
return sanitize(html, preset, features);
|
|
35624
|
-
}
|
|
35625
|
-
/** HTML string → ProseMirror JSON (tolerant; unknown nodes are dropped by the schema). */
|
|
35626
|
-
function htmlToJson(html, preset = 'task', features) {
|
|
35627
|
-
const safe = sanitize(html ?? '', preset, features);
|
|
35628
|
-
return generateJSON(safe, schemaExtensions(preset, features));
|
|
36867
|
+
/** px a 96 dpi. */
|
|
36868
|
+
const PAGE_SIZES = {
|
|
36869
|
+
letter: { width: 816, height: 1056 },
|
|
36870
|
+
a4: { width: 794, height: 1123 },
|
|
36871
|
+
legal: { width: 816, height: 1344 },
|
|
36872
|
+
};
|
|
36873
|
+
/** Separación visual entre hojas (no existe en el PDF). */
|
|
36874
|
+
const PAGE_GAP_PX = 24;
|
|
36875
|
+
const PAGINATION_META = 'coPagination';
|
|
36876
|
+
function resolvePageSize(page) {
|
|
36877
|
+
if (!page)
|
|
36878
|
+
return PAGE_SIZES.letter;
|
|
36879
|
+
if (typeof page === 'string')
|
|
36880
|
+
return PAGE_SIZES[page] ?? PAGE_SIZES.letter;
|
|
36881
|
+
return { width: Number(page.width), height: Number(page.height) };
|
|
36882
|
+
}
|
|
36883
|
+
function pageContentHeight(o) {
|
|
36884
|
+
return o.page.height - o.margins.top - o.margins.bottom - o.header.height - o.footer.height;
|
|
35629
36885
|
}
|
|
35630
36886
|
/**
|
|
35631
|
-
*
|
|
35632
|
-
*
|
|
36887
|
+
* Top relativo a `root` sumando `offsetTop` por la cadena de offsetParent.
|
|
36888
|
+
* `root` tiene que ser posicionado (la extensión le pone `position: relative`).
|
|
36889
|
+
* Son px de LAYOUT: un `transform: scale()` de zoom no los altera.
|
|
35633
36890
|
*/
|
|
35634
|
-
function
|
|
35635
|
-
|
|
35636
|
-
|
|
35637
|
-
|
|
35638
|
-
|
|
35639
|
-
|
|
35640
|
-
|
|
35641
|
-
|
|
35642
|
-
|
|
35643
|
-
|
|
35644
|
-
|
|
35645
|
-
|
|
35646
|
-
|
|
35647
|
-
|
|
35648
|
-
|
|
35649
|
-
|
|
35650
|
-
|
|
35651
|
-
|
|
35652
|
-
}
|
|
35653
|
-
|
|
35654
|
-
|
|
35655
|
-
|
|
35656
|
-
}
|
|
35657
|
-
if (node.type === 'hardBreak') {
|
|
35658
|
-
out.push('\n');
|
|
35659
|
-
return;
|
|
35660
|
-
}
|
|
35661
|
-
if (Array.isArray(node.content))
|
|
35662
|
-
node.content.forEach(walk);
|
|
35663
|
-
if (BLOCK.has(node.type))
|
|
35664
|
-
out.push('\n');
|
|
36891
|
+
function layoutBox(el, root) {
|
|
36892
|
+
let top = 0;
|
|
36893
|
+
let node = el;
|
|
36894
|
+
while (node && node !== root) {
|
|
36895
|
+
top += node.offsetTop;
|
|
36896
|
+
node = node.offsetParent;
|
|
36897
|
+
}
|
|
36898
|
+
return { top, height: el.offsetHeight };
|
|
36899
|
+
}
|
|
36900
|
+
const defaultSchedule = (cb) => {
|
|
36901
|
+
if (typeof requestAnimationFrame === 'function')
|
|
36902
|
+
requestAnimationFrame(() => cb());
|
|
36903
|
+
else
|
|
36904
|
+
setTimeout(cb, 16);
|
|
36905
|
+
};
|
|
36906
|
+
function toLayoutOptions(o) {
|
|
36907
|
+
return {
|
|
36908
|
+
page: resolvePageSize(o.page),
|
|
36909
|
+
margins: { ...o.margins },
|
|
36910
|
+
header: { height: o.header?.height ?? 0 },
|
|
36911
|
+
footer: { height: o.footer?.height ?? 0 },
|
|
36912
|
+
gap: o.gap ?? PAGE_GAP_PX,
|
|
35665
36913
|
};
|
|
35666
|
-
|
|
35667
|
-
|
|
35668
|
-
|
|
35669
|
-
|
|
35670
|
-
|
|
35671
|
-
|
|
35672
|
-
|
|
35673
|
-
|
|
35674
|
-
|
|
35675
|
-
|
|
35676
|
-
|
|
35677
|
-
|
|
35678
|
-
|
|
35679
|
-
|
|
35680
|
-
|
|
35681
|
-
|
|
35682
|
-
|
|
35683
|
-
|
|
35684
|
-
|
|
35685
|
-
|
|
35686
|
-
|
|
35687
|
-
|
|
35688
|
-
|
|
35689
|
-
|
|
35690
|
-
|
|
35691
|
-
|
|
35692
|
-
|
|
35693
|
-
|
|
35694
|
-
|
|
35695
|
-
|
|
35696
|
-
|
|
36914
|
+
}
|
|
36915
|
+
/**
|
|
36916
|
+
* Banda de salto: margen inferior (+ pie) de la hoja que termina, separación
|
|
36917
|
+
* entre hojas y margen superior (+ encabezado) de la que empieza. Dentro de una
|
|
36918
|
+
* tabla va envuelta en una fila con el colspan de la tabla (un div entre `tr`
|
|
36919
|
+
* lo expulsaría el navegador).
|
|
36920
|
+
*/
|
|
36921
|
+
function buildPageGap(page, pageCount, o, header, cols = 0) {
|
|
36922
|
+
const foot = o.margins.bottom + o.footer.height;
|
|
36923
|
+
const head = o.margins.top + o.header.height;
|
|
36924
|
+
const band = document.createElement('div');
|
|
36925
|
+
band.className = 'co-doc-page-gap';
|
|
36926
|
+
band.setAttribute('contenteditable', 'false');
|
|
36927
|
+
band.style.height = `${foot + o.gap + head}px`;
|
|
36928
|
+
const bottom = document.createElement('div');
|
|
36929
|
+
bottom.className = 'co-doc-page-gap__foot';
|
|
36930
|
+
bottom.style.height = `${foot}px`;
|
|
36931
|
+
const between = document.createElement('div');
|
|
36932
|
+
between.className = 'co-doc-page-gap__between';
|
|
36933
|
+
between.style.height = `${o.gap}px`;
|
|
36934
|
+
const top = document.createElement('div');
|
|
36935
|
+
top.className = 'co-doc-page-gap__head';
|
|
36936
|
+
top.style.height = `${head}px`;
|
|
36937
|
+
top.style.paddingTop = `${o.margins.top}px`;
|
|
36938
|
+
top.style.boxSizing = 'border-box';
|
|
36939
|
+
if (header)
|
|
36940
|
+
top.appendChild(header);
|
|
36941
|
+
band.append(bottom, between, top);
|
|
36942
|
+
band.setAttribute('data-page', String(page));
|
|
36943
|
+
band.setAttribute('data-page-count', String(pageCount));
|
|
36944
|
+
if (!cols) {
|
|
36945
|
+
band.setAttribute('data-co-page-gap', String(page));
|
|
36946
|
+
return band;
|
|
36947
|
+
}
|
|
36948
|
+
const tr = document.createElement('tr');
|
|
36949
|
+
tr.className = 'co-doc-page-gap-row';
|
|
36950
|
+
tr.setAttribute('contenteditable', 'false');
|
|
36951
|
+
tr.setAttribute('data-co-page-gap', String(page));
|
|
36952
|
+
const td = document.createElement('td');
|
|
36953
|
+
td.setAttribute('colspan', String(cols));
|
|
36954
|
+
td.appendChild(band);
|
|
36955
|
+
tr.appendChild(td);
|
|
36956
|
+
return tr;
|
|
36957
|
+
}
|
|
36958
|
+
function measureLayout(view, opts, measure) {
|
|
36959
|
+
const root = view.dom;
|
|
36960
|
+
const atoms = [];
|
|
36961
|
+
view.state.doc.descendants((node, pos) => {
|
|
36962
|
+
const kind = classifyPaginationNode(node);
|
|
36963
|
+
if (kind === 'container')
|
|
36964
|
+
return true;
|
|
36965
|
+
if (kind === 'skip')
|
|
36966
|
+
return false;
|
|
36967
|
+
const dom = view.nodeDOM(pos);
|
|
36968
|
+
if (!(dom instanceof HTMLElement))
|
|
36969
|
+
return false;
|
|
36970
|
+
const box = measure(dom, root);
|
|
36971
|
+
if (box.height > 0)
|
|
36972
|
+
atoms.push({ pos, top: box.top, height: box.height, keepWithNext: isKeepWithNext(node) });
|
|
36973
|
+
return false;
|
|
36974
|
+
});
|
|
36975
|
+
const bands = Array.from(root.querySelectorAll('[data-co-page-gap]')).map((el) => measure(el, root));
|
|
36976
|
+
return computePageBreaks(stripBandOffsets(atoms, bands), pageContentHeight(opts));
|
|
36977
|
+
}
|
|
36978
|
+
const paginationKey = new PluginKey('coPagination');
|
|
36979
|
+
const Pagination = Extension.create({
|
|
36980
|
+
name: 'pagination',
|
|
36981
|
+
addOptions() {
|
|
36982
|
+
return {
|
|
36983
|
+
page: 'letter',
|
|
36984
|
+
margins: { top: 38, right: 38, bottom: 38, left: 38 },
|
|
36985
|
+
header: { height: 0 },
|
|
36986
|
+
footer: { height: 0 },
|
|
36987
|
+
gap: PAGE_GAP_PX,
|
|
36988
|
+
renderHeader: null,
|
|
36989
|
+
onPagesChange: null,
|
|
36990
|
+
measure: layoutBox,
|
|
36991
|
+
schedule: defaultSchedule,
|
|
36992
|
+
};
|
|
36993
|
+
},
|
|
36994
|
+
addStorage() {
|
|
36995
|
+
return { pageCount: 1 };
|
|
36996
|
+
},
|
|
36997
|
+
addCommands() {
|
|
36998
|
+
return {
|
|
36999
|
+
setPaginationOptions: (patch) => ({ tr, dispatch }) => {
|
|
37000
|
+
if (dispatch)
|
|
37001
|
+
tr.setMeta(PAGINATION_META, { patch });
|
|
37002
|
+
return true;
|
|
37003
|
+
},
|
|
37004
|
+
remeasurePages: () => ({ tr, dispatch }) => {
|
|
37005
|
+
if (dispatch)
|
|
37006
|
+
tr.setMeta(PAGINATION_META, { remeasure: true });
|
|
37007
|
+
return true;
|
|
37008
|
+
},
|
|
37009
|
+
};
|
|
37010
|
+
},
|
|
37011
|
+
addProseMirrorPlugins() {
|
|
37012
|
+
const options = this.options;
|
|
37013
|
+
const storage = this.storage;
|
|
37014
|
+
let lastEmitted = 0;
|
|
37015
|
+
const decorationsFor = (state, st) => {
|
|
37016
|
+
const decos = [];
|
|
37017
|
+
for (const br of st.layout.breaks) {
|
|
37018
|
+
if (br.pos < 0 || br.pos > state.doc.content.size)
|
|
37019
|
+
continue;
|
|
37020
|
+
// Nunca un widget de bloque dentro de contenido inline.
|
|
37021
|
+
if (state.doc.resolve(br.pos).parent.inlineContent)
|
|
37022
|
+
continue;
|
|
37023
|
+
const node = state.doc.nodeAt(br.pos);
|
|
37024
|
+
const cols = node?.type.name === 'tableRow' ? tableColumnCount(state.doc.resolve(br.pos).parent) : 0;
|
|
37025
|
+
decos.push(Decoration.widget(br.pos, () => buildPageGap(br.page, st.layout.pageCount, st.opts, options.renderHeader?.(br.page, st.layout.pageCount) ?? null, cols), { side: -1, key: `co-pg-${br.page}-${st.layout.pageCount}-v${st.version}-c${cols}` }));
|
|
37026
|
+
}
|
|
37027
|
+
return DecorationSet.create(state.doc, decos);
|
|
37028
|
+
};
|
|
37029
|
+
return [
|
|
37030
|
+
new Plugin({
|
|
37031
|
+
key: paginationKey,
|
|
37032
|
+
state: {
|
|
37033
|
+
init: () => ({ layout: { breaks: [], pageCount: 1 }, opts: toLayoutOptions(options), version: 0, dirty: true }),
|
|
37034
|
+
apply(tr, prev) {
|
|
37035
|
+
const meta = tr.getMeta(PAGINATION_META);
|
|
37036
|
+
let next = prev;
|
|
37037
|
+
if (tr.docChanged) {
|
|
37038
|
+
next = {
|
|
37039
|
+
...next,
|
|
37040
|
+
dirty: true,
|
|
37041
|
+
// Un salto cuya frontera se borró (p. ej. unir párrafos en el borde de una hoja)
|
|
37042
|
+
// se descarta: mapearlo lo dejaría dentro de un textblock. La medición siguiente
|
|
37043
|
+
// lo recalcula.
|
|
37044
|
+
layout: {
|
|
37045
|
+
...next.layout,
|
|
37046
|
+
breaks: next.layout.breaks.flatMap((b) => {
|
|
37047
|
+
const r = tr.mapping.mapResult(b.pos);
|
|
37048
|
+
return r.deleted ? [] : [{ ...b, pos: r.pos }];
|
|
37049
|
+
}),
|
|
37050
|
+
},
|
|
37051
|
+
};
|
|
37052
|
+
}
|
|
37053
|
+
if (meta?.patch) {
|
|
37054
|
+
const merged = toLayoutOptions({ ...next.opts, ...meta.patch, page: meta.patch.page ?? next.opts.page });
|
|
37055
|
+
next = { ...next, opts: merged, version: next.version + 1, dirty: true };
|
|
37056
|
+
}
|
|
37057
|
+
if (meta?.remeasure)
|
|
37058
|
+
next = { ...next, dirty: true };
|
|
37059
|
+
if (meta?.layout)
|
|
37060
|
+
next = { ...next, layout: meta.layout, dirty: false };
|
|
37061
|
+
return next;
|
|
37062
|
+
},
|
|
37063
|
+
},
|
|
37064
|
+
props: {
|
|
37065
|
+
decorations(state) {
|
|
37066
|
+
const st = paginationKey.getState(state);
|
|
37067
|
+
return st ? decorationsFor(state, st) : DecorationSet.empty;
|
|
37068
|
+
},
|
|
37069
|
+
},
|
|
37070
|
+
view(view) {
|
|
37071
|
+
const root = view.dom;
|
|
37072
|
+
if (!root.style.position)
|
|
37073
|
+
root.style.position = 'relative';
|
|
37074
|
+
let scheduled = false;
|
|
37075
|
+
let alive = true;
|
|
37076
|
+
const run = () => {
|
|
37077
|
+
scheduled = false;
|
|
37078
|
+
if (!alive || view.isDestroyed)
|
|
37079
|
+
return;
|
|
37080
|
+
const st = paginationKey.getState(view.state);
|
|
37081
|
+
if (!st)
|
|
37082
|
+
return;
|
|
37083
|
+
const layout = measureLayout(view, st.opts, options.measure);
|
|
37084
|
+
storage.pageCount = layout.pageCount;
|
|
37085
|
+
view.dispatch(view.state.tr.setMeta(PAGINATION_META, { layout }));
|
|
37086
|
+
if (layout.pageCount !== lastEmitted) {
|
|
37087
|
+
lastEmitted = layout.pageCount;
|
|
37088
|
+
options.onPagesChange?.(layout.pageCount);
|
|
37089
|
+
}
|
|
37090
|
+
};
|
|
37091
|
+
const maybeSchedule = () => {
|
|
37092
|
+
const st = paginationKey.getState(view.state);
|
|
37093
|
+
if (!st?.dirty || scheduled)
|
|
37094
|
+
return;
|
|
37095
|
+
scheduled = true;
|
|
37096
|
+
options.schedule(run);
|
|
37097
|
+
};
|
|
37098
|
+
const remeasure = () => {
|
|
37099
|
+
if (alive && !view.isDestroyed) {
|
|
37100
|
+
view.dispatch(view.state.tr.setMeta(PAGINATION_META, { remeasure: true }));
|
|
37101
|
+
}
|
|
37102
|
+
};
|
|
37103
|
+
// Imágenes que cargan tarde cambian alturas (las de las bandas no: tienen alto fijo).
|
|
37104
|
+
const onLoad = (e) => {
|
|
37105
|
+
const t = e.target;
|
|
37106
|
+
if (!t || t.tagName !== 'IMG' || t.closest('[data-co-page-gap]'))
|
|
37107
|
+
return;
|
|
37108
|
+
remeasure();
|
|
37109
|
+
};
|
|
37110
|
+
root.addEventListener('load', onLoad, true);
|
|
37111
|
+
const fonts = document.fonts;
|
|
37112
|
+
fonts?.ready?.then(remeasure).catch(() => { });
|
|
37113
|
+
// Fuentes que cargan después (un peso o familia aplicado por primera vez).
|
|
37114
|
+
fonts?.addEventListener?.('loadingdone', remeasure);
|
|
37115
|
+
maybeSchedule();
|
|
37116
|
+
return {
|
|
37117
|
+
update: () => maybeSchedule(),
|
|
37118
|
+
destroy: () => {
|
|
37119
|
+
alive = false;
|
|
37120
|
+
root.removeEventListener('load', onLoad, true);
|
|
37121
|
+
fonts?.removeEventListener?.('loadingdone', remeasure);
|
|
37122
|
+
},
|
|
37123
|
+
};
|
|
37124
|
+
},
|
|
37125
|
+
}),
|
|
37126
|
+
];
|
|
37127
|
+
},
|
|
35697
37128
|
});
|
|
35698
37129
|
|
|
35699
|
-
exports.
|
|
37130
|
+
exports.CalloutNode = CalloutNode;
|
|
37131
|
+
exports.CobaltTaskItem = CobaltTaskItem;
|
|
37132
|
+
exports.CobaltTaskList = CobaltTaskList;
|
|
37133
|
+
exports.FIELD_SYNC_META = FIELD_SYNC_META;
|
|
37134
|
+
exports.FontFamilyExtension = FontFamilyExtension;
|
|
37135
|
+
exports.FontSizeExtension = FontSizeExtension;
|
|
37136
|
+
exports.FontWeightExtension = FontWeightExtension;
|
|
37137
|
+
exports.IMAGE_LAYOUT_MODES = IMAGE_LAYOUT_MODES;
|
|
37138
|
+
exports.IndentExtension = IndentExtension;
|
|
37139
|
+
exports.LetterSpacingExtension = LetterSpacingExtension;
|
|
37140
|
+
exports.LineHeightExtension = LineHeightExtension;
|
|
37141
|
+
exports.ListStyleExtension = ListStyleExtension;
|
|
37142
|
+
exports.MentionNode = MentionNode;
|
|
37143
|
+
exports.MergeField = MergeField;
|
|
37144
|
+
exports.PAGE_GAP_PX = PAGE_GAP_PX;
|
|
37145
|
+
exports.PAGE_SIZES = PAGE_SIZES;
|
|
37146
|
+
exports.PAGINATION_META = PAGINATION_META;
|
|
37147
|
+
exports.PRESETS = PRESETS;
|
|
37148
|
+
exports.Pagination = Pagination;
|
|
37149
|
+
exports.SANITIZE_CONFIGS = SANITIZE_CONFIGS;
|
|
37150
|
+
exports.SIGNATURE_TOKEN_STYLE = SIGNATURE_TOKEN_STYLE;
|
|
37151
|
+
exports.SignatureSlot = SignatureSlot;
|
|
37152
|
+
exports.TRAILING_BREAK_CLASS = TRAILING_BREAK_CLASS;
|
|
37153
|
+
exports.VariableNode = VariableNode;
|
|
37154
|
+
exports.applyImageLayoutMode = applyImageLayoutMode;
|
|
37155
|
+
exports.collectFields = collectFields;
|
|
37156
|
+
exports.computePageBreaks = computePageBreaks;
|
|
37157
|
+
exports.createEditor = createEditor;
|
|
37158
|
+
exports.defaultToolbarForPreset = defaultToolbarForPreset;
|
|
37159
|
+
exports.generateHTML = generateHTML;
|
|
37160
|
+
exports.generateJSON = generateJSON;
|
|
37161
|
+
exports.getExtensions = getExtensions;
|
|
37162
|
+
exports.getImageLayoutMode = getImageLayoutMode;
|
|
37163
|
+
exports.getPrintExtensions = getPrintExtensions;
|
|
37164
|
+
exports.headerImageWidth = headerImageWidth;
|
|
37165
|
+
exports.isPrintPreset = isPrintPreset;
|
|
37166
|
+
exports.layoutBox = layoutBox;
|
|
37167
|
+
exports.maxLengthForPreset = maxLengthForPreset;
|
|
37168
|
+
exports.nextFreeSlot = nextFreeSlot;
|
|
37169
|
+
exports.normalizePrintHtml = normalizePrintHtml;
|
|
37170
|
+
exports.pageContentHeight = pageContentHeight;
|
|
37171
|
+
exports.parseFieldToken = parseFieldToken;
|
|
37172
|
+
exports.readPrintHtml = readPrintHtml;
|
|
37173
|
+
exports.resolvePageSize = resolvePageSize;
|
|
37174
|
+
exports.sanitize = sanitize;
|
|
37175
|
+
exports.sanitizeFieldName = sanitizeFieldName;
|
|
37176
|
+
exports.serializePrintHtml = serializePrintHtml;
|
|
37177
|
+
exports.setFieldValuesInHtml = setFieldValuesInHtml;
|
|
37178
|
+
exports.signatureBoxStyle = signatureBoxStyle;
|
|
37179
|
+
exports.signatureSlotHtml = signatureSlotHtml;
|
|
37180
|
+
exports.signatureToken = signatureToken;
|
|
37181
|
+
exports.stripBandOffsets = stripBandOffsets;
|
|
37182
|
+
exports.writePrintHtml = writePrintHtml;
|