@threadlabs/looma 0.29.11 → 0.29.13
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/EXPRESSIVE-MARKDOWN.md +90 -0
- package/README.md +6 -0
- package/components/ui-tabs/ui-tabs.html +2 -2
- package/components/ui-tabs/ui-tabs.js +14 -10
- package/dist/index.js +1 -1
- package/editor/chunks/extensions.js +80 -251
- package/editor/chunks/markdown.js +242 -0
- package/editor/expressmark.d.ts +31 -0
- package/editor/expressmark.js +942 -0
- package/editor/extensions/index.js +2 -1
- package/editor/extensions/table-of-contents.d.ts +1 -1
- package/editor/index.js +2 -1
- package/editor/node-views/image.d.ts +10 -0
- package/editor/node-views/table-of-contents.d.ts +1 -1
- package/package.json +12 -5
- package/styles/ui-action-bar.css +1 -1
- package/styles/ui-affordance-scope.css +1 -1
- package/styles/ui-avatar-group.css +1 -1
- package/styles/ui-avatar.css +1 -1
- package/styles/ui-badge.css +1 -1
- package/styles/ui-breadcrumb-item.css +1 -1
- package/styles/ui-breadcrumbs.css +1 -1
- package/styles/ui-button.css +1 -1
- package/styles/ui-callout.css +1 -1
- package/styles/ui-card.css +1 -1
- package/styles/ui-checkbox.css +1 -1
- package/styles/ui-cluster.css +1 -1
- package/styles/ui-combobox.css +1 -1
- package/styles/ui-container.css +1 -1
- package/styles/ui-context-menu.css +1 -1
- package/styles/ui-cover.css +1 -1
- package/styles/ui-description-item.css +1 -1
- package/styles/ui-description-list.css +1 -1
- package/styles/ui-dialog.css +1 -1
- package/styles/ui-disclosure.css +1 -1
- package/styles/ui-editable.css +1 -1
- package/styles/ui-editor-block-actions.css +1 -1
- package/styles/ui-editor-chip-editor.css +1 -1
- package/styles/ui-editor-code-language.css +1 -1
- package/styles/ui-editor-image-toolbar.css +1 -1
- package/styles/ui-editor-insert-table-grid.css +1 -1
- package/styles/ui-editor-link-card.css +1 -1
- package/styles/ui-editor-link-form.css +1 -1
- package/styles/ui-editor-mention-menu-item.css +1 -1
- package/styles/ui-editor-mention-menu.css +1 -1
- package/styles/ui-editor-slash-menu-group.css +1 -1
- package/styles/ui-editor-slash-menu-item.css +1 -1
- package/styles/ui-editor-slash-menu.css +1 -1
- package/styles/ui-editor-surface.css +1 -1
- package/styles/ui-editor-table-context-menu.css +1 -1
- package/styles/ui-editor-table-overlay.css +1 -1
- package/styles/ui-editor-table-toolbar.css +1 -1
- package/styles/ui-editor-toolbar.css +1 -1
- package/styles/ui-floating-action-button.css +1 -1
- package/styles/ui-form-field.css +1 -1
- package/styles/ui-grid.css +1 -1
- package/styles/ui-icon-button.css +1 -1
- package/styles/ui-icon.css +1 -1
- package/styles/ui-image.css +1 -1
- package/styles/ui-input-group.css +1 -1
- package/styles/ui-input.css +1 -1
- package/styles/ui-list-item.css +1 -1
- package/styles/ui-list.css +1 -1
- package/styles/ui-listbox.css +1 -1
- package/styles/ui-menu-group.css +1 -1
- package/styles/ui-menu-item.css +1 -1
- package/styles/ui-menu.css +1 -1
- package/styles/ui-meter.css +1 -1
- package/styles/ui-nav-item.css +1 -1
- package/styles/ui-page-header.css +1 -1
- package/styles/ui-popover.css +1 -1
- package/styles/ui-radio-group.css +1 -1
- package/styles/ui-radio.css +1 -1
- package/styles/ui-reel.css +1 -1
- package/styles/ui-scroll-area.css +1 -1
- package/styles/ui-search-result-row.css +1 -1
- package/styles/ui-search-shell.css +1 -1
- package/styles/ui-section.css +1 -1
- package/styles/ui-select.css +1 -1
- package/styles/ui-separator.css +1 -1
- package/styles/ui-sidebar.css +1 -1
- package/styles/ui-spinner.css +1 -1
- package/styles/ui-stack.css +1 -1
- package/styles/ui-status-message.css +1 -1
- package/styles/ui-swatch.css +1 -1
- package/styles/ui-switch.css +1 -1
- package/styles/ui-switcher.css +1 -1
- package/styles/ui-table.css +1 -1
- package/styles/ui-tabs.css +1 -1
- package/styles/ui-text.css +1 -1
- package/styles/ui-textarea.css +1 -1
- package/styles/ui-toast-region.css +1 -1
- package/styles/ui-toast.css +1 -1
- package/styles/ui-tooltip.css +1 -1
- package/styles/ui-top-bar.css +1 -1
- package/styles/ui-tree-item.css +1 -1
- package/styles/ui-tree.css +1 -1
- package/vanilla/UiActionBar.d.ts +1 -1
- package/vanilla/UiActionBar.js +1 -1
- package/vanilla/UiAffordanceScope.d.ts +1 -1
- package/vanilla/UiAffordanceScope.js +1 -1
- package/vanilla/UiAvatar.d.ts +1 -1
- package/vanilla/UiAvatar.js +1 -1
- package/vanilla/UiAvatarGroup.d.ts +1 -1
- package/vanilla/UiAvatarGroup.js +1 -1
- package/vanilla/UiBadge.d.ts +1 -1
- package/vanilla/UiBadge.js +1 -1
- package/vanilla/UiBreadcrumbItem.d.ts +1 -1
- package/vanilla/UiBreadcrumbItem.js +1 -1
- package/vanilla/UiBreadcrumbs.d.ts +1 -1
- package/vanilla/UiBreadcrumbs.js +1 -1
- package/vanilla/UiButton.d.ts +1 -1
- package/vanilla/UiButton.js +1 -1
- package/vanilla/UiCallout.d.ts +1 -1
- package/vanilla/UiCallout.js +1 -1
- package/vanilla/UiCard.d.ts +1 -1
- package/vanilla/UiCard.js +1 -1
- package/vanilla/UiCheckbox.d.ts +1 -1
- package/vanilla/UiCheckbox.js +1 -1
- package/vanilla/UiCluster.d.ts +1 -1
- package/vanilla/UiCluster.js +1 -1
- package/vanilla/UiCombobox.d.ts +1 -1
- package/vanilla/UiCombobox.js +1 -1
- package/vanilla/UiContainer.d.ts +1 -1
- package/vanilla/UiContainer.js +1 -1
- package/vanilla/UiContextMenu.d.ts +1 -1
- package/vanilla/UiContextMenu.js +1 -1
- package/vanilla/UiCover.d.ts +1 -1
- package/vanilla/UiCover.js +1 -1
- package/vanilla/UiDescriptionItem.d.ts +1 -1
- package/vanilla/UiDescriptionItem.js +1 -1
- package/vanilla/UiDescriptionList.d.ts +1 -1
- package/vanilla/UiDescriptionList.js +1 -1
- package/vanilla/UiDialog.d.ts +1 -1
- package/vanilla/UiDialog.js +1 -1
- package/vanilla/UiDisclosure.d.ts +1 -1
- package/vanilla/UiDisclosure.js +1 -1
- package/vanilla/UiEditable.d.ts +1 -1
- package/vanilla/UiEditable.js +1 -1
- package/vanilla/UiEditorBlockActions.d.ts +1 -1
- package/vanilla/UiEditorBlockActions.js +1 -1
- package/vanilla/UiEditorChipEditor.d.ts +1 -1
- package/vanilla/UiEditorChipEditor.js +1 -1
- package/vanilla/UiEditorCodeLanguage.d.ts +1 -1
- package/vanilla/UiEditorCodeLanguage.js +1 -1
- package/vanilla/UiEditorImageToolbar.d.ts +1 -1
- package/vanilla/UiEditorImageToolbar.js +1 -1
- package/vanilla/UiEditorInsertTableGrid.d.ts +1 -1
- package/vanilla/UiEditorInsertTableGrid.js +1 -1
- package/vanilla/UiEditorLinkCard.d.ts +1 -1
- package/vanilla/UiEditorLinkCard.js +1 -1
- package/vanilla/UiEditorLinkForm.d.ts +1 -1
- package/vanilla/UiEditorLinkForm.js +1 -1
- package/vanilla/UiEditorMentionMenu.d.ts +1 -1
- package/vanilla/UiEditorMentionMenu.js +1 -1
- package/vanilla/UiEditorMentionMenuItem.d.ts +1 -1
- package/vanilla/UiEditorMentionMenuItem.js +1 -1
- package/vanilla/UiEditorSlashMenu.d.ts +1 -1
- package/vanilla/UiEditorSlashMenu.js +1 -1
- package/vanilla/UiEditorSlashMenuGroup.d.ts +1 -1
- package/vanilla/UiEditorSlashMenuGroup.js +1 -1
- package/vanilla/UiEditorSlashMenuItem.d.ts +1 -1
- package/vanilla/UiEditorSlashMenuItem.js +1 -1
- package/vanilla/UiEditorSurface.d.ts +1 -1
- package/vanilla/UiEditorSurface.js +1 -1
- package/vanilla/UiEditorTableContextMenu.d.ts +1 -1
- package/vanilla/UiEditorTableContextMenu.js +1 -1
- package/vanilla/UiEditorTableOverlay.d.ts +1 -1
- package/vanilla/UiEditorTableOverlay.js +1 -1
- package/vanilla/UiEditorTableToolbar.d.ts +1 -1
- package/vanilla/UiEditorTableToolbar.js +1 -1
- package/vanilla/UiEditorToolbar.d.ts +1 -1
- package/vanilla/UiEditorToolbar.js +1 -1
- package/vanilla/UiFloatingActionButton.d.ts +1 -1
- package/vanilla/UiFloatingActionButton.js +1 -1
- package/vanilla/UiFormField.d.ts +1 -1
- package/vanilla/UiFormField.js +1 -1
- package/vanilla/UiGrid.d.ts +1 -1
- package/vanilla/UiGrid.js +1 -1
- package/vanilla/UiIcon.d.ts +1 -1
- package/vanilla/UiIcon.js +1 -1
- package/vanilla/UiIconButton.d.ts +1 -1
- package/vanilla/UiIconButton.js +1 -1
- package/vanilla/UiImage.d.ts +1 -1
- package/vanilla/UiImage.js +1 -1
- package/vanilla/UiInput.d.ts +1 -1
- package/vanilla/UiInput.js +1 -1
- package/vanilla/UiInputGroup.d.ts +1 -1
- package/vanilla/UiInputGroup.js +1 -1
- package/vanilla/UiList.d.ts +1 -1
- package/vanilla/UiList.js +1 -1
- package/vanilla/UiListItem.d.ts +1 -1
- package/vanilla/UiListItem.js +1 -1
- package/vanilla/UiListbox.d.ts +1 -1
- package/vanilla/UiListbox.js +1 -1
- package/vanilla/UiMenu.d.ts +1 -1
- package/vanilla/UiMenu.js +1 -1
- package/vanilla/UiMenuGroup.d.ts +1 -1
- package/vanilla/UiMenuGroup.js +1 -1
- package/vanilla/UiMenuItem.d.ts +1 -1
- package/vanilla/UiMenuItem.js +1 -1
- package/vanilla/UiMeter.d.ts +1 -1
- package/vanilla/UiMeter.js +1 -1
- package/vanilla/UiNavItem.d.ts +1 -1
- package/vanilla/UiNavItem.js +1 -1
- package/vanilla/UiPageHeader.d.ts +1 -1
- package/vanilla/UiPageHeader.js +1 -1
- package/vanilla/UiPopover.d.ts +1 -1
- package/vanilla/UiPopover.js +1 -1
- package/vanilla/UiRadio.d.ts +1 -1
- package/vanilla/UiRadio.js +1 -1
- package/vanilla/UiRadioGroup.d.ts +1 -1
- package/vanilla/UiRadioGroup.js +1 -1
- package/vanilla/UiReel.d.ts +1 -1
- package/vanilla/UiReel.js +1 -1
- package/vanilla/UiScrollArea.d.ts +1 -1
- package/vanilla/UiScrollArea.js +1 -1
- package/vanilla/UiSearchResultRow.d.ts +1 -1
- package/vanilla/UiSearchResultRow.js +1 -1
- package/vanilla/UiSearchShell.d.ts +1 -1
- package/vanilla/UiSearchShell.js +1 -1
- package/vanilla/UiSection.d.ts +1 -1
- package/vanilla/UiSection.js +1 -1
- package/vanilla/UiSelect.d.ts +1 -1
- package/vanilla/UiSelect.js +1 -1
- package/vanilla/UiSeparator.d.ts +1 -1
- package/vanilla/UiSeparator.js +1 -1
- package/vanilla/UiSidebar.d.ts +1 -1
- package/vanilla/UiSidebar.js +1 -1
- package/vanilla/UiSpinner.d.ts +1 -1
- package/vanilla/UiSpinner.js +1 -1
- package/vanilla/UiStack.d.ts +1 -1
- package/vanilla/UiStack.js +1 -1
- package/vanilla/UiStatusMessage.d.ts +1 -1
- package/vanilla/UiStatusMessage.js +1 -1
- package/vanilla/UiSwatch.d.ts +1 -1
- package/vanilla/UiSwatch.js +1 -1
- package/vanilla/UiSwitch.d.ts +1 -1
- package/vanilla/UiSwitch.js +1 -1
- package/vanilla/UiSwitcher.d.ts +1 -1
- package/vanilla/UiSwitcher.js +1 -1
- package/vanilla/UiTable.d.ts +1 -1
- package/vanilla/UiTable.js +1 -1
- package/vanilla/UiTabs.d.ts +1 -1
- package/vanilla/UiTabs.js +1 -1
- package/vanilla/UiText.d.ts +1 -1
- package/vanilla/UiText.js +1 -1
- package/vanilla/UiTextarea.d.ts +1 -1
- package/vanilla/UiTextarea.js +1 -1
- package/vanilla/UiToast.d.ts +1 -1
- package/vanilla/UiToast.js +1 -1
- package/vanilla/UiToastRegion.d.ts +1 -1
- package/vanilla/UiToastRegion.js +1 -1
- package/vanilla/UiTooltip.d.ts +1 -1
- package/vanilla/UiTooltip.js +1 -1
- package/vanilla/UiTopBar.d.ts +1 -1
- package/vanilla/UiTopBar.js +1 -1
- package/vanilla/UiTree.d.ts +1 -1
- package/vanilla/UiTree.js +1 -1
- package/vanilla/UiTreeItem.d.ts +1 -1
- package/vanilla/UiTreeItem.js +1 -1
- package/vue/UiActionBar.vue +1 -1
- package/vue/UiAffordanceScope.vue +1 -1
- package/vue/UiAvatar.vue +1 -1
- package/vue/UiAvatarGroup.vue +1 -1
- package/vue/UiBadge.vue +1 -1
- package/vue/UiBreadcrumbItem.vue +1 -1
- package/vue/UiBreadcrumbs.vue +1 -1
- package/vue/UiButton.vue +1 -1
- package/vue/UiCallout.vue +1 -1
- package/vue/UiCard.vue +1 -1
- package/vue/UiCheckbox.vue +1 -1
- package/vue/UiCluster.vue +1 -1
- package/vue/UiCombobox.vue +1 -1
- package/vue/UiContainer.vue +1 -1
- package/vue/UiContextMenu.vue +1 -1
- package/vue/UiCover.vue +1 -1
- package/vue/UiDescriptionItem.vue +1 -1
- package/vue/UiDescriptionList.vue +1 -1
- package/vue/UiDialog.vue +1 -1
- package/vue/UiDisclosure.vue +1 -1
- package/vue/UiEditable.vue +1 -1
- package/vue/UiEditorBlockActions.vue +1 -1
- package/vue/UiEditorChipEditor.vue +1 -1
- package/vue/UiEditorCodeLanguage.vue +1 -1
- package/vue/UiEditorImageToolbar.vue +1 -1
- package/vue/UiEditorInsertTableGrid.vue +1 -1
- package/vue/UiEditorLinkCard.vue +1 -1
- package/vue/UiEditorLinkForm.vue +1 -1
- package/vue/UiEditorMentionMenu.vue +1 -1
- package/vue/UiEditorMentionMenuItem.vue +1 -1
- package/vue/UiEditorSlashMenu.vue +1 -1
- package/vue/UiEditorSlashMenuGroup.vue +1 -1
- package/vue/UiEditorSlashMenuItem.vue +1 -1
- package/vue/UiEditorSurface.vue +1 -1
- package/vue/UiEditorTableContextMenu.vue +1 -1
- package/vue/UiEditorTableOverlay.vue +1 -1
- package/vue/UiEditorTableToolbar.vue +1 -1
- package/vue/UiEditorToolbar.vue +1 -1
- package/vue/UiFloatingActionButton.vue +1 -1
- package/vue/UiFormField.vue +1 -1
- package/vue/UiGrid.vue +1 -1
- package/vue/UiIcon.vue +1 -1
- package/vue/UiIconButton.vue +1 -1
- package/vue/UiImage.vue +1 -1
- package/vue/UiInput.vue +1 -1
- package/vue/UiInputGroup.vue +1 -1
- package/vue/UiList.vue +1 -1
- package/vue/UiListItem.vue +1 -1
- package/vue/UiListbox.vue +1 -1
- package/vue/UiMenu.vue +1 -1
- package/vue/UiMenuGroup.vue +1 -1
- package/vue/UiMenuItem.vue +1 -1
- package/vue/UiMeter.vue +1 -1
- package/vue/UiNavItem.vue +1 -1
- package/vue/UiPageHeader.vue +1 -1
- package/vue/UiPopover.vue +1 -1
- package/vue/UiRadio.vue +1 -1
- package/vue/UiRadioGroup.vue +1 -1
- package/vue/UiReel.vue +1 -1
- package/vue/UiScrollArea.vue +1 -1
- package/vue/UiSearchResultRow.vue +1 -1
- package/vue/UiSearchShell.vue +1 -1
- package/vue/UiSection.vue +1 -1
- package/vue/UiSelect.vue +1 -1
- package/vue/UiSeparator.vue +1 -1
- package/vue/UiSidebar.vue +1 -1
- package/vue/UiSpinner.vue +1 -1
- package/vue/UiStack.vue +1 -1
- package/vue/UiStatusMessage.vue +1 -1
- package/vue/UiSwatch.vue +1 -1
- package/vue/UiSwitch.vue +1 -1
- package/vue/UiSwitcher.vue +1 -1
- package/vue/UiTable.vue +1 -1
- package/vue/UiTabs.vue +3 -3
- package/vue/UiText.vue +1 -1
- package/vue/UiTextarea.vue +1 -1
- package/vue/UiToast.vue +1 -1
- package/vue/UiToastRegion.vue +1 -1
- package/vue/UiTooltip.vue +1 -1
- package/vue/UiTopBar.vue +1 -1
- package/vue/UiTree.vue +1 -1
- package/vue/UiTreeItem.vue +1 -1
- package/vue/chunks/UiActionBar.js +1 -1
- package/vue/chunks/UiAffordanceScope.js +1 -1
- package/vue/chunks/UiAvatar.js +1 -1
- package/vue/chunks/UiAvatarGroup.js +1 -1
- package/vue/chunks/UiBadge.js +1 -1
- package/vue/chunks/UiBreadcrumbItem.js +1 -1
- package/vue/chunks/UiBreadcrumbs.js +1 -1
- package/vue/chunks/UiButton.js +1 -1
- package/vue/chunks/UiCallout.js +1 -1
- package/vue/chunks/UiCard.js +1 -1
- package/vue/chunks/UiCheckbox.js +1 -1
- package/vue/chunks/UiCluster.js +1 -1
- package/vue/chunks/UiCombobox.js +1 -1
- package/vue/chunks/UiContainer.js +1 -1
- package/vue/chunks/UiContextMenu.js +1 -1
- package/vue/chunks/UiCover.js +1 -1
- package/vue/chunks/UiDescriptionItem.js +1 -1
- package/vue/chunks/UiDescriptionList.js +1 -1
- package/vue/chunks/UiDialog.js +1 -1
- package/vue/chunks/UiDisclosure.js +1 -1
- package/vue/chunks/UiEditable.js +1 -1
- package/vue/chunks/UiEditorInsertTableGrid.js +1 -1
- package/vue/chunks/UiEditorMentionMenu.js +1 -1
- package/vue/chunks/UiEditorMentionMenuItem.js +1 -1
- package/vue/chunks/UiEditorSlashMenu.js +1 -1
- package/vue/chunks/UiEditorSlashMenuGroup.js +1 -1
- package/vue/chunks/UiEditorSlashMenuItem.js +1 -1
- package/vue/chunks/UiEditorSurface.js +1 -1
- package/vue/chunks/UiEditorTableContextMenu.js +1 -1
- package/vue/chunks/UiEditorTableOverlay.js +1 -1
- package/vue/chunks/UiEditorTableToolbar.js +1 -1
- package/vue/chunks/UiEditorToolbar.js +1 -1
- package/vue/chunks/UiFloatingActionButton.js +1 -1
- package/vue/chunks/UiFormField.js +1 -1
- package/vue/chunks/UiGrid.js +1 -1
- package/vue/chunks/UiIcon.js +1 -1
- package/vue/chunks/UiIconButton.js +1 -1
- package/vue/chunks/UiImage.js +1 -1
- package/vue/chunks/UiInput.js +1 -1
- package/vue/chunks/UiInputGroup.js +1 -1
- package/vue/chunks/UiList.js +1 -1
- package/vue/chunks/UiListItem.js +1 -1
- package/vue/chunks/UiListbox.js +1 -1
- package/vue/chunks/UiMenu.js +1 -1
- package/vue/chunks/UiMenuGroup.js +1 -1
- package/vue/chunks/UiMenuItem.js +1 -1
- package/vue/chunks/UiMeter.js +1 -1
- package/vue/chunks/UiNavItem.js +1 -1
- package/vue/chunks/UiPageHeader.js +1 -1
- package/vue/chunks/UiPopover.js +1 -1
- package/vue/chunks/UiRadio.js +1 -1
- package/vue/chunks/UiRadioGroup.js +1 -1
- package/vue/chunks/UiReel.js +1 -1
- package/vue/chunks/UiScrollArea.js +1 -1
- package/vue/chunks/UiSearchResultRow.js +1 -1
- package/vue/chunks/UiSearchShell.js +1 -1
- package/vue/chunks/UiSection.js +1 -1
- package/vue/chunks/UiSelect.js +1 -1
- package/vue/chunks/UiSeparator.js +1 -1
- package/vue/chunks/UiSidebar.js +1 -1
- package/vue/chunks/UiSpinner.js +1 -1
- package/vue/chunks/UiStack.js +1 -1
- package/vue/chunks/UiStatusMessage.js +1 -1
- package/vue/chunks/UiSwatch.js +1 -1
- package/vue/chunks/UiSwitch.js +1 -1
- package/vue/chunks/UiSwitcher.js +1 -1
- package/vue/chunks/UiTable.js +1 -1
- package/vue/chunks/UiTabs.js +3 -3
- package/vue/chunks/UiText.js +1 -1
- package/vue/chunks/UiTextarea.js +1 -1
- package/vue/chunks/UiToast.js +1 -1
- package/vue/chunks/UiToastRegion.js +1 -1
- package/vue/chunks/UiTooltip.js +1 -1
- package/vue/chunks/UiTopBar.js +1 -1
- package/vue/chunks/UiTree.js +1 -1
- package/vue/chunks/UiTreeItem.js +1 -1
- package/vue/components.css +197 -37
- package/vue/editor/index.js +816 -313
- package/vue/host.ts +1 -1
- package/vue/editor/image.d.ts +0 -7
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { n as TABLE_CELL_BACKGROUND_PRESETS } from "./table-backgrounds.js";
|
|
2
|
+
import { a as assignLoomaHeadingIds, c as loomaContainerMarker, d as normalizeLoomaChipTone, f as parseLoomaAttributes, h as splitLoomaFrontmatter, i as applyLoomaCodeNotation, l as loomaHeadingSlug, m as readLoomaAttributes, n as LOOMA_CHIP_TONES, o as formatLoomaAttributes, p as parseLoomaFenceInfo, r as LOOMA_CONTAINER_NAMES, s as loomaCodeFence, u as normalizeLoomaCalloutTone } from "./markdown.js";
|
|
2
3
|
import { Extension, Mark, Node as Node$1, callOrReturn, canInsertNode, combineTransactionSteps, escapeForRegEx, findChildren, findChildrenInRange, findParentNodeClosestToPos, getAttributes, getChangedRanges, getExtensionField, getMarksBetween, getText, getTextSerializersFromSchema, isNodeEmpty, isNodeSelection, markInputRule, markPasteRule, mergeAttributes, nodeInputRule, textInputRule, textblockTypeInputRule, wrappingInputRule } from "@tiptap/core";
|
|
3
4
|
import { NodeSelection, Plugin, PluginKey, Selection, TextSelection } from "@tiptap/pm/state";
|
|
4
5
|
import { Decoration, DecorationSet } from "@tiptap/pm/view";
|
|
@@ -127,247 +128,6 @@ var LoomaActiveBlock = Extension.create({
|
|
|
127
128
|
}
|
|
128
129
|
});
|
|
129
130
|
//#endregion
|
|
130
|
-
//#region src/markdown/index.ts
|
|
131
|
-
/**
|
|
132
|
-
* Callout tones a document stores, in the order the editor offers them. The Callout component also
|
|
133
|
-
* takes `neutral` and `success`, which Markdown and the editor store as `note`.
|
|
134
|
-
*/
|
|
135
|
-
var LOOMA_CALLOUT_TONES = [
|
|
136
|
-
"note",
|
|
137
|
-
"tip",
|
|
138
|
-
"info",
|
|
139
|
-
"important",
|
|
140
|
-
"warning",
|
|
141
|
-
"danger"
|
|
142
|
-
];
|
|
143
|
-
/** Names that read as a stored tone: `caution` is `danger`, and `neutral` is the same muted aside as `note`. */
|
|
144
|
-
var LOOMA_CALLOUT_TONE_ALIASES = {
|
|
145
|
-
caution: "danger",
|
|
146
|
-
neutral: "note"
|
|
147
|
-
};
|
|
148
|
-
/**
|
|
149
|
-
* Maps a tone name or alias, in any case, onto a stored tone.
|
|
150
|
-
* @failure Unknown and non-string values become `note`.
|
|
151
|
-
*/
|
|
152
|
-
function normalizeLoomaCalloutTone(value) {
|
|
153
|
-
if (typeof value !== "string") return "note";
|
|
154
|
-
const tone = value.toLowerCase();
|
|
155
|
-
return LOOMA_CALLOUT_TONES.includes(tone) ? tone : LOOMA_CALLOUT_TONE_ALIASES[tone] ?? "note";
|
|
156
|
-
}
|
|
157
|
-
/** The hues chips and swatches take as their tone, written `:chip[Label]{tone=green}`. */
|
|
158
|
-
var LOOMA_CHIP_TONES = [
|
|
159
|
-
"neutral",
|
|
160
|
-
"blue",
|
|
161
|
-
"green",
|
|
162
|
-
"yellow",
|
|
163
|
-
"red",
|
|
164
|
-
"purple"
|
|
165
|
-
];
|
|
166
|
-
/**
|
|
167
|
-
* Keeps a chip tone within the palette.
|
|
168
|
-
* @failure Unknown values become `neutral`.
|
|
169
|
-
*/
|
|
170
|
-
function normalizeLoomaChipTone(value) {
|
|
171
|
-
return LOOMA_CHIP_TONES.includes(value) ? value : "neutral";
|
|
172
|
-
}
|
|
173
|
-
/**
|
|
174
|
-
* Names that open a `:::` container, matched without regard to case. A container with any other
|
|
175
|
-
* name is ordinary text.
|
|
176
|
-
*/
|
|
177
|
-
var LOOMA_CONTAINER_NAMES = /* @__PURE__ */ new Set([
|
|
178
|
-
...LOOMA_CALLOUT_TONES,
|
|
179
|
-
"caution",
|
|
180
|
-
"details",
|
|
181
|
-
"figure",
|
|
182
|
-
"tabs",
|
|
183
|
-
"code-group"
|
|
184
|
-
]);
|
|
185
|
-
var ATTRIBUTE_KEY = /[A-Za-z][\w-]*/y;
|
|
186
|
-
var ATTRIBUTE_ID = /#([\w-]+)/y;
|
|
187
|
-
var ATTRIBUTE_VALUE = /[^\s"'=<>`{}]+/y;
|
|
188
|
-
function sticky(pattern, source, index) {
|
|
189
|
-
pattern.lastIndex = index;
|
|
190
|
-
return pattern.exec(source);
|
|
191
|
-
}
|
|
192
|
-
/**
|
|
193
|
-
* Reads a brace attribute list starting at `source[start]`, which must be `{`.
|
|
194
|
-
* @contract Returns the attributes and the index just past the closing brace.
|
|
195
|
-
* @failure Returns null for anything that is not a complete, well-formed list, so the text stays literal.
|
|
196
|
-
*/
|
|
197
|
-
function readLoomaAttributes(source, start = 0) {
|
|
198
|
-
if (source[start] !== "{") return null;
|
|
199
|
-
const attributes = {};
|
|
200
|
-
let index = start + 1;
|
|
201
|
-
for (;;) {
|
|
202
|
-
while (source[index] === " " || source[index] === " ") index++;
|
|
203
|
-
if (source[index] === "}") return {
|
|
204
|
-
attributes,
|
|
205
|
-
end: index + 1
|
|
206
|
-
};
|
|
207
|
-
if (index > start + 1 && !/\s/.test(source[index - 1])) return null;
|
|
208
|
-
const id = sticky(ATTRIBUTE_ID, source, index);
|
|
209
|
-
if (id) {
|
|
210
|
-
attributes.id = id[1];
|
|
211
|
-
index += id[0].length;
|
|
212
|
-
continue;
|
|
213
|
-
}
|
|
214
|
-
const key = sticky(ATTRIBUTE_KEY, source, index);
|
|
215
|
-
if (!key) return null;
|
|
216
|
-
index += key[0].length;
|
|
217
|
-
if (source[index] !== "=") {
|
|
218
|
-
attributes[key[0]] = true;
|
|
219
|
-
continue;
|
|
220
|
-
}
|
|
221
|
-
index++;
|
|
222
|
-
const quote = source[index];
|
|
223
|
-
if (quote === "\"" || quote === "'") {
|
|
224
|
-
const close = source.indexOf(quote, index + 1);
|
|
225
|
-
if (close < 0) return null;
|
|
226
|
-
attributes[key[0]] = source.slice(index + 1, close);
|
|
227
|
-
index = close + 1;
|
|
228
|
-
continue;
|
|
229
|
-
}
|
|
230
|
-
const value = sticky(ATTRIBUTE_VALUE, source, index);
|
|
231
|
-
if (!value) return null;
|
|
232
|
-
attributes[key[0]] = value[0];
|
|
233
|
-
index += value[0].length;
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
/**
|
|
237
|
-
* Reads a whole string as one brace attribute list.
|
|
238
|
-
* @failure Returns null unless the string is exactly one well-formed list.
|
|
239
|
-
*/
|
|
240
|
-
function parseLoomaAttributes(source) {
|
|
241
|
-
const read = readLoomaAttributes(source);
|
|
242
|
-
return read && read.end === source.length ? read.attributes : null;
|
|
243
|
-
}
|
|
244
|
-
/**
|
|
245
|
-
* Writes attributes as a brace list, `id` first as `#id`, then the rest in order.
|
|
246
|
-
* @contract `true` writes a bare key; values are quoted only when they need it. `false`, null and
|
|
247
|
-
* undefined values are left out, and an empty set writes an empty string. An ID that `#` cannot
|
|
248
|
-
* carry, or any ID when `hashId` is false, is written `id=…`.
|
|
249
|
-
*/
|
|
250
|
-
function formatLoomaAttributes(attributes, { hashId = true } = {}) {
|
|
251
|
-
const items = [];
|
|
252
|
-
const { id, ...rest } = attributes;
|
|
253
|
-
const hashed = hashId && typeof id === "string" && /^[\w-]+$/.test(id);
|
|
254
|
-
if (hashed) items.push(`#${id}`);
|
|
255
|
-
for (const [key, value] of Object.entries(hashed ? rest : attributes)) if (value === true) items.push(key);
|
|
256
|
-
else if (value === false || value === null || value === void 0) continue;
|
|
257
|
-
else {
|
|
258
|
-
const text = String(value);
|
|
259
|
-
items.push(/^[^\s"'=<>`{}]+$/.test(text) ? `${key}=${text}` : text.includes("\"") ? `${key}='${text}'` : `${key}="${text}"`);
|
|
260
|
-
}
|
|
261
|
-
return items.length ? `{${items.join(" ")}}` : "";
|
|
262
|
-
}
|
|
263
|
-
/**
|
|
264
|
-
* The anchor a heading's text derives: NFC, lowercase, keeping letters, numbers and combining
|
|
265
|
-
* marks, with every other run of characters one hyphen.
|
|
266
|
-
* @failure Text with no letters or numbers, such as only emoji, derives `heading`.
|
|
267
|
-
*/
|
|
268
|
-
function loomaHeadingSlug(text) {
|
|
269
|
-
return text.normalize("NFC").toLowerCase().replace(/[^\p{L}\p{N}\p{M}]+/gu, "-").replace(/^-+|-+$/g, "") || "heading";
|
|
270
|
-
}
|
|
271
|
-
/**
|
|
272
|
-
* Gives every heading of a document its anchor, in document order.
|
|
273
|
-
* @contract A custom ID is kept unless an earlier heading already has it. Any other heading takes
|
|
274
|
-
* its slug, or the slug's first free suffix (`-1`, `-2`…), never one a later custom ID reserves.
|
|
275
|
-
*/
|
|
276
|
-
function assignLoomaHeadingIds(headings) {
|
|
277
|
-
const reserved = new Set(headings.map(({ id }) => id).filter((id) => Boolean(id)));
|
|
278
|
-
const used = /* @__PURE__ */ new Set();
|
|
279
|
-
return headings.map(({ text, id: custom }) => {
|
|
280
|
-
let id = custom || loomaHeadingSlug(text);
|
|
281
|
-
if (custom ? used.has(id) : used.has(id) || reserved.has(id)) {
|
|
282
|
-
const stem = id;
|
|
283
|
-
let suffix = 1;
|
|
284
|
-
while (used.has(`${stem}-${suffix}`) || reserved.has(`${stem}-${suffix}`)) suffix++;
|
|
285
|
-
id = `${stem}-${suffix}`;
|
|
286
|
-
}
|
|
287
|
-
used.add(id);
|
|
288
|
-
return id;
|
|
289
|
-
});
|
|
290
|
-
}
|
|
291
|
-
/** Reads a fence's info string: ```` ```ts title="a.ts" {1,3-5} :line-numbers ````. */
|
|
292
|
-
function parseLoomaFenceInfo(info) {
|
|
293
|
-
const source = info.trim();
|
|
294
|
-
const language = /^[^\s={:]+(?=[\s{:]|$)/.exec(source)?.[0];
|
|
295
|
-
const meta = (language ? source.slice(language.length) : source).trim();
|
|
296
|
-
const title = /(?:^|\s)title="([^"]*)"/.exec(meta)?.[1];
|
|
297
|
-
const rest = meta.replace(/(?:^|\s)title="[^"]*"/, "");
|
|
298
|
-
const lines = /* @__PURE__ */ new Set();
|
|
299
|
-
for (const range of /\{([\d\s,-]+)\}/.exec(rest)?.[1].split(",") ?? []) {
|
|
300
|
-
const [from = NaN, to = from] = range.split("-").map((part) => Number.parseInt(part, 10));
|
|
301
|
-
for (let line = from; line <= to; line++) lines.add(line);
|
|
302
|
-
}
|
|
303
|
-
const numbers = /:(no-)?line-numbers(?![\w-])/.exec(rest);
|
|
304
|
-
return {
|
|
305
|
-
...language ? { language } : {},
|
|
306
|
-
meta,
|
|
307
|
-
...title !== void 0 ? { title } : {},
|
|
308
|
-
lines: [...lines].sort((a, b) => a - b),
|
|
309
|
-
...numbers ? { lineNumbers: numbers[1] === void 0 } : {}
|
|
310
|
-
};
|
|
311
|
-
}
|
|
312
|
-
var MAPPING_KEY = /^(?:[^\s#:'"\-?,[\]{}&*!|>%@`][^:\n]*?|"[^"\n]*"|'[^'\n]*')[ \t]*:(?:[ \t]|$)/;
|
|
313
|
-
var NOTATION = /[ \t]*(?:\/\/|#|--|<!--|\{?\/\*)[ \t]*\[!code highlight(?::(\d+))?\][ \t]*(?:-->|\*\/\}?)?[ \t]*$/;
|
|
314
|
-
var ESCAPED_NOTATION = /\[\\(\\*!code highlight)/g;
|
|
315
|
-
/**
|
|
316
|
-
* Applies code notation: a line ending in a `[!code highlight]` comment is highlighted and loses
|
|
317
|
-
* the comment, `[!code highlight:3]` covers three lines, and a marker alone on its line is removed
|
|
318
|
-
* with the line and applies to the lines after it. A backslash between `[` and `!` escapes a
|
|
319
|
-
* marker, `[\!code highlight]`, which then shows as text with one backslash fewer and highlights
|
|
320
|
-
* nothing.
|
|
321
|
-
* @contract Returns the code a reader sees and its highlighted line numbers, from 1, ascending.
|
|
322
|
-
* ponytail: matched on source lines, so a string that ends in the marker counts too.
|
|
323
|
-
*/
|
|
324
|
-
function applyLoomaCodeNotation(code) {
|
|
325
|
-
const kept = [];
|
|
326
|
-
const lines = /* @__PURE__ */ new Set();
|
|
327
|
-
for (const line of code.split("\n")) {
|
|
328
|
-
const match = NOTATION.exec(line);
|
|
329
|
-
if (!match) {
|
|
330
|
-
kept.push(line);
|
|
331
|
-
continue;
|
|
332
|
-
}
|
|
333
|
-
const rest = line.slice(0, match.index);
|
|
334
|
-
const own = rest.trim() !== "";
|
|
335
|
-
if (own) kept.push(rest);
|
|
336
|
-
for (let count = 0; count < Number(match[1] ?? 1); count++) lines.add(kept.length + (own ? 0 : 1) + count);
|
|
337
|
-
}
|
|
338
|
-
return {
|
|
339
|
-
code: kept.join("\n").replace(ESCAPED_NOTATION, "[$1"),
|
|
340
|
-
lines: [...lines].sort((a, b) => a - b)
|
|
341
|
-
};
|
|
342
|
-
}
|
|
343
|
-
/**
|
|
344
|
-
* Splits YAML front matter from the start of a document.
|
|
345
|
-
* @contract Front matter opens with a `---` line at the very start and closes at a `---` or `...`
|
|
346
|
-
* line, and what lies between is a YAML mapping: its first line that is not blank or a comment
|
|
347
|
-
* starts with a key, whose value may be a scalar, a list or a mapping. `source` is the block as
|
|
348
|
-
* written, delimiters included.
|
|
349
|
-
* @failure Returns null when the document has none.
|
|
350
|
-
*/
|
|
351
|
-
function splitLoomaFrontmatter(document) {
|
|
352
|
-
const match = /^---[ \t]*\r?\n([\s\S]*?)\r?\n(?:---|\.\.\.)[ \t]*(?:\r?\n|$)/.exec(document.slice(0, 8192));
|
|
353
|
-
const first = match?.[1].split(/\r?\n/).find((line) => line.trim() && !line.trimStart().startsWith("#"));
|
|
354
|
-
if (!match || !first || !MAPPING_KEY.test(first)) return null;
|
|
355
|
-
return {
|
|
356
|
-
source: match[0].trimEnd(),
|
|
357
|
-
yaml: match[1],
|
|
358
|
-
body: document.slice(match[0].length)
|
|
359
|
-
};
|
|
360
|
-
}
|
|
361
|
-
/** The colons a container opens and closes with, given how deeply containers nest inside it. */
|
|
362
|
-
function loomaContainerMarker(nestedDepth) {
|
|
363
|
-
return ":".repeat(3 + Math.max(0, nestedDepth));
|
|
364
|
-
}
|
|
365
|
-
/** A backtick fence longer than any run of backticks in the code, and at least three long. */
|
|
366
|
-
function loomaCodeFence(code) {
|
|
367
|
-
const longest = Math.max(0, ...(code.match(/`+/g) ?? []).map((run) => run.length));
|
|
368
|
-
return "`".repeat(Math.max(3, longest + 1));
|
|
369
|
-
}
|
|
370
|
-
//#endregion
|
|
371
131
|
//#region src/editor/extensions/callout.ts
|
|
372
132
|
/**
|
|
373
133
|
* A durable block container for informational editor content, saved as Looma's Callout.
|
|
@@ -735,6 +495,24 @@ var LoomaTabs = Node$1.create({
|
|
|
735
495
|
parseHTML: (element) => element.getAttribute("group") ?? "",
|
|
736
496
|
renderHTML: (attributes) => attributes.group ? { group: attributes.group } : {}
|
|
737
497
|
},
|
|
498
|
+
defaultValue: {
|
|
499
|
+
default: null,
|
|
500
|
+
parseHTML: (element) => element.getAttribute("data-default-value"),
|
|
501
|
+
renderHTML: (attributes) => attributes.defaultValue === null ? {} : {
|
|
502
|
+
"data-default-value": attributes.defaultValue,
|
|
503
|
+
value: attributes.defaultValue
|
|
504
|
+
}
|
|
505
|
+
},
|
|
506
|
+
queryString: {
|
|
507
|
+
default: null,
|
|
508
|
+
parseHTML: (element) => element.getAttribute("data-query-string"),
|
|
509
|
+
renderHTML: (attributes) => attributes.queryString === null ? {} : { "data-query-string": attributes.queryString }
|
|
510
|
+
},
|
|
511
|
+
lazy: {
|
|
512
|
+
default: null,
|
|
513
|
+
parseHTML: (element) => element.hasAttribute("data-lazy") ? element.getAttribute("data-lazy") !== "false" : null,
|
|
514
|
+
renderHTML: (attributes) => attributes.lazy === null ? {} : { "data-lazy": String(attributes.lazy) }
|
|
515
|
+
},
|
|
738
516
|
codeGroup: {
|
|
739
517
|
default: false,
|
|
740
518
|
parseHTML: (element) => element.classList.contains("code-group"),
|
|
@@ -773,11 +551,18 @@ var LoomaTab = Node$1.create({
|
|
|
773
551
|
defining: true,
|
|
774
552
|
isolating: true,
|
|
775
553
|
addAttributes() {
|
|
776
|
-
return {
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
554
|
+
return {
|
|
555
|
+
value: {
|
|
556
|
+
default: null,
|
|
557
|
+
parseHTML: (element) => element.getAttribute("data-value"),
|
|
558
|
+
renderHTML: (attributes) => attributes.value === null ? {} : { "data-value": attributes.value }
|
|
559
|
+
},
|
|
560
|
+
label: {
|
|
561
|
+
default: "",
|
|
562
|
+
parseHTML: (element) => element.getAttribute("aria-label") ?? "",
|
|
563
|
+
renderHTML: (attributes) => ({ "aria-label": attributes.label })
|
|
564
|
+
}
|
|
565
|
+
};
|
|
781
566
|
},
|
|
782
567
|
parseHTML() {
|
|
783
568
|
return [{ tag: "ui-tabs > section" }];
|
|
@@ -975,14 +760,18 @@ async function navigateTableOfContents(editor, id) {
|
|
|
975
760
|
target.tabIndex = -1;
|
|
976
761
|
target.focus({ preventScroll: true });
|
|
977
762
|
}
|
|
763
|
+
function importAuthoredNavigation(element, schema) {
|
|
764
|
+
return DOMParser.fromSchema(schema).parse(element).content;
|
|
765
|
+
}
|
|
978
766
|
/**
|
|
979
|
-
* Automatic
|
|
767
|
+
* Automatic navigation, or an explicitly authored navigation body imported from a document.
|
|
980
768
|
* @ownership The schema owns configuration/anchors; node views derive entries.
|
|
981
769
|
* @lifecycle Headless views subscribe to transactions and unsubscribe on destroy.
|
|
982
770
|
*/
|
|
983
771
|
var LoomaTableOfContents = Node$1.create({
|
|
984
772
|
name: "loomaTableOfContents",
|
|
985
773
|
group: "block",
|
|
774
|
+
content: "block*",
|
|
986
775
|
atom: true,
|
|
987
776
|
selectable: true,
|
|
988
777
|
isolating: true,
|
|
@@ -1002,8 +791,25 @@ var LoomaTableOfContents = Node$1.create({
|
|
|
1002
791
|
}
|
|
1003
792
|
};
|
|
1004
793
|
},
|
|
1005
|
-
parseHTML: () => [{
|
|
794
|
+
parseHTML: () => [{
|
|
795
|
+
tag: "nav[data-looma-toc]",
|
|
796
|
+
getContent: (element, schema) => {
|
|
797
|
+
if (!(element instanceof HTMLElement) || !element.hasAttribute("data-authored-body")) return Fragment.empty;
|
|
798
|
+
return importAuthoredNavigation(element, schema);
|
|
799
|
+
}
|
|
800
|
+
}],
|
|
1006
801
|
renderHTML({ node }) {
|
|
802
|
+
if (node.childCount) return [
|
|
803
|
+
"nav",
|
|
804
|
+
{
|
|
805
|
+
"data-looma-toc": "",
|
|
806
|
+
"data-authored-body": "",
|
|
807
|
+
"data-format": node.attrs.format,
|
|
808
|
+
"data-depth": node.attrs.depth,
|
|
809
|
+
"aria-label": "Table of contents"
|
|
810
|
+
},
|
|
811
|
+
0
|
|
812
|
+
];
|
|
1007
813
|
return contentsHtml(this.editor?.view?.state.doc ?? node, normalizeTableOfContentsConfig(node.attrs));
|
|
1008
814
|
},
|
|
1009
815
|
addCommands() {
|
|
@@ -1019,8 +825,15 @@ var LoomaTableOfContents = Node$1.create({
|
|
|
1019
825
|
dom.contentEditable = "false";
|
|
1020
826
|
let current = node;
|
|
1021
827
|
const render = () => {
|
|
1022
|
-
|
|
1023
|
-
|
|
828
|
+
if (current.childCount) {
|
|
829
|
+
const nav = document.createElement("nav");
|
|
830
|
+
nav.setAttribute("aria-label", "Table of contents");
|
|
831
|
+
nav.append(DOMSerializer.fromSchema(editor.schema).serializeFragment(current.content));
|
|
832
|
+
dom.replaceChildren(nav);
|
|
833
|
+
} else {
|
|
834
|
+
const { dom: content } = DOMSerializer.renderSpec(document, contentsHtml(editor.state.doc, normalizeTableOfContentsConfig(current.attrs)));
|
|
835
|
+
dom.replaceChildren(content);
|
|
836
|
+
}
|
|
1024
837
|
};
|
|
1025
838
|
dom.addEventListener("click", (event) => {
|
|
1026
839
|
const anchor = event.target.closest("a");
|
|
@@ -10176,6 +9989,22 @@ function loomaMarkdownFromDoc(doc) {
|
|
|
10176
9989
|
const custom = customHeadingIds(doc);
|
|
10177
9990
|
let heading = 0;
|
|
10178
9991
|
const nodes = {
|
|
9992
|
+
loomaTableOfContents: (state, node, parent, index) => {
|
|
9993
|
+
if (node.childCount) {
|
|
9994
|
+
state.write(html(node));
|
|
9995
|
+
state.closeBlock(node);
|
|
9996
|
+
} else NODES.loomaTableOfContents(state, node, parent, index);
|
|
9997
|
+
},
|
|
9998
|
+
loomaTabs: (state, node, parent, index) => {
|
|
9999
|
+
if ([
|
|
10000
|
+
node.attrs.defaultValue,
|
|
10001
|
+
node.attrs.queryString,
|
|
10002
|
+
node.attrs.lazy
|
|
10003
|
+
].some((value) => value !== null && value !== void 0) || Array.from({ length: node.childCount }, (_, index) => node.child(index)).some((tab) => tab.attrs.value !== null && tab.attrs.value !== void 0)) {
|
|
10004
|
+
state.write(html(node));
|
|
10005
|
+
state.closeBlock(node);
|
|
10006
|
+
} else NODES.loomaTabs(state, node, parent, index);
|
|
10007
|
+
},
|
|
10179
10008
|
heading: (state, node) => {
|
|
10180
10009
|
state.write(`${"#".repeat(node.attrs.level)} `);
|
|
10181
10010
|
state.renderInline(node, false);
|
|
@@ -11955,4 +11784,4 @@ function createLoomaSlashCommandExtension(options = {}) {
|
|
|
11955
11784
|
});
|
|
11956
11785
|
}
|
|
11957
11786
|
//#endregion
|
|
11958
|
-
export {
|
|
11787
|
+
export { filterLoomaMentionItems as A, LoomaFigcaption as B, loomaMarkdownToHtml as C, createLoomaMentionExtension as D, LoomaMentionSuggestionPluginKey as E, LoomaTableOfContents as F, LoomaChip as G, LoomaExpand as H, getTableOfContentsEntries as I, LOOMA_ACTIVE_BLOCK_BLUR_GRACE_MS as J, normalizeLoomaChipColor as K, normalizeTableOfContentsConfig as L, LoomaImage as M, normalizeImageDimension as N, DEFAULT_MENTION_RESULT_LIMIT as O, normalizeImagePlacement as P, LoomaActiveBlockPluginKey as Q, LoomaTab as R, loomaMarkdownFromDoc as S, siteRelativeHref as T, revealLoomaExpandAt as U, LoomaFigure as V, LOOMA_CHIP_COLORS as W, LOOMA_ACTIVE_BLOCK_TYPING_IDLE_MS as X, LOOMA_ACTIVE_BLOCK_CLASS as Y, LoomaActiveBlock as Z, getActiveTableCellAlignment as _, getActiveTableUiState as a, setActiveTableCellBackground as b, insertTableAtRange as c, LoomaTableKit as d, getDefaultEditorExtensions as f, LoomaTableHeader as g, LoomaTableCell as h, getDefaultSlashCommands as i, normalizeMentionResultLimit as j, MAX_MENTION_RESULT_LIMIT as k, normalizeActiveTableColumnWidths as l, LoomaTable as m, createLoomaSlashCommandExtension as n, handleTableAction as o, getLoomaTableExtensions as p, LoomaCallout as q, filterLoomaSlashCommands as r, handleTableOverlayAction as s, LoomaSlashCommand as t, shouldShowTextFormattingToolbar as u, getActiveTableCellBackground as v, createSiteRelativeLinks as w, LoomaSmartPaste as x, setActiveTableCellAlignment as y, LoomaTabs as z };
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
//#region src/markdown/index.ts
|
|
2
|
+
/**
|
|
3
|
+
* Callout tones a document stores, in the order the editor offers them. The Callout component also
|
|
4
|
+
* takes `neutral` and `success`, which Markdown and the editor store as `note`.
|
|
5
|
+
*/
|
|
6
|
+
var LOOMA_CALLOUT_TONES = [
|
|
7
|
+
"note",
|
|
8
|
+
"tip",
|
|
9
|
+
"info",
|
|
10
|
+
"important",
|
|
11
|
+
"warning",
|
|
12
|
+
"danger"
|
|
13
|
+
];
|
|
14
|
+
/** Names that read as a stored tone: `caution` is `danger`, and `neutral` is the same muted aside as `note`. */
|
|
15
|
+
var LOOMA_CALLOUT_TONE_ALIASES = {
|
|
16
|
+
caution: "danger",
|
|
17
|
+
neutral: "note"
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Maps a tone name or alias, in any case, onto a stored tone.
|
|
21
|
+
* @failure Unknown and non-string values become `note`.
|
|
22
|
+
*/
|
|
23
|
+
function normalizeLoomaCalloutTone(value) {
|
|
24
|
+
if (typeof value !== "string") return "note";
|
|
25
|
+
const tone = value.toLowerCase();
|
|
26
|
+
return LOOMA_CALLOUT_TONES.includes(tone) ? tone : LOOMA_CALLOUT_TONE_ALIASES[tone] ?? "note";
|
|
27
|
+
}
|
|
28
|
+
/** The hues chips and swatches take as their tone, written `:chip[Label]{tone=green}`. */
|
|
29
|
+
var LOOMA_CHIP_TONES = [
|
|
30
|
+
"neutral",
|
|
31
|
+
"blue",
|
|
32
|
+
"green",
|
|
33
|
+
"yellow",
|
|
34
|
+
"red",
|
|
35
|
+
"purple"
|
|
36
|
+
];
|
|
37
|
+
/**
|
|
38
|
+
* Keeps a chip tone within the palette.
|
|
39
|
+
* @failure Unknown values become `neutral`.
|
|
40
|
+
*/
|
|
41
|
+
function normalizeLoomaChipTone(value) {
|
|
42
|
+
return LOOMA_CHIP_TONES.includes(value) ? value : "neutral";
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Names that open a `:::` container, matched without regard to case. A container with any other
|
|
46
|
+
* name is ordinary text.
|
|
47
|
+
*/
|
|
48
|
+
var LOOMA_CONTAINER_NAMES = /* @__PURE__ */ new Set([
|
|
49
|
+
...LOOMA_CALLOUT_TONES,
|
|
50
|
+
"caution",
|
|
51
|
+
"details",
|
|
52
|
+
"figure",
|
|
53
|
+
"tabs",
|
|
54
|
+
"code-group"
|
|
55
|
+
]);
|
|
56
|
+
var ATTRIBUTE_KEY = /[A-Za-z][\w-]*/y;
|
|
57
|
+
var ATTRIBUTE_ID = /#([\w-]+)/y;
|
|
58
|
+
var ATTRIBUTE_VALUE = /[^\s"'=<>`{}]+/y;
|
|
59
|
+
function sticky(pattern, source, index) {
|
|
60
|
+
pattern.lastIndex = index;
|
|
61
|
+
return pattern.exec(source);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Reads a brace attribute list starting at `source[start]`, which must be `{`.
|
|
65
|
+
* @contract Returns the attributes and the index just past the closing brace.
|
|
66
|
+
* @failure Returns null for anything that is not a complete, well-formed list, so the text stays literal.
|
|
67
|
+
*/
|
|
68
|
+
function readLoomaAttributes(source, start = 0) {
|
|
69
|
+
if (source[start] !== "{") return null;
|
|
70
|
+
const attributes = {};
|
|
71
|
+
let index = start + 1;
|
|
72
|
+
for (;;) {
|
|
73
|
+
while (source[index] === " " || source[index] === " ") index++;
|
|
74
|
+
if (source[index] === "}") return {
|
|
75
|
+
attributes,
|
|
76
|
+
end: index + 1
|
|
77
|
+
};
|
|
78
|
+
if (index > start + 1 && !/\s/.test(source[index - 1])) return null;
|
|
79
|
+
const id = sticky(ATTRIBUTE_ID, source, index);
|
|
80
|
+
if (id) {
|
|
81
|
+
attributes.id = id[1];
|
|
82
|
+
index += id[0].length;
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
const key = sticky(ATTRIBUTE_KEY, source, index);
|
|
86
|
+
if (!key) return null;
|
|
87
|
+
index += key[0].length;
|
|
88
|
+
if (source[index] !== "=") {
|
|
89
|
+
attributes[key[0]] = true;
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
index++;
|
|
93
|
+
const quote = source[index];
|
|
94
|
+
if (quote === "\"" || quote === "'") {
|
|
95
|
+
const close = source.indexOf(quote, index + 1);
|
|
96
|
+
if (close < 0) return null;
|
|
97
|
+
attributes[key[0]] = source.slice(index + 1, close);
|
|
98
|
+
index = close + 1;
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
const value = sticky(ATTRIBUTE_VALUE, source, index);
|
|
102
|
+
if (!value) return null;
|
|
103
|
+
attributes[key[0]] = value[0];
|
|
104
|
+
index += value[0].length;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Reads a whole string as one brace attribute list.
|
|
109
|
+
* @failure Returns null unless the string is exactly one well-formed list.
|
|
110
|
+
*/
|
|
111
|
+
function parseLoomaAttributes(source) {
|
|
112
|
+
const read = readLoomaAttributes(source);
|
|
113
|
+
return read && read.end === source.length ? read.attributes : null;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Writes attributes as a brace list, `id` first as `#id`, then the rest in order.
|
|
117
|
+
* @contract `true` writes a bare key; values are quoted only when they need it. `false`, null and
|
|
118
|
+
* undefined values are left out, and an empty set writes an empty string. An ID that `#` cannot
|
|
119
|
+
* carry, or any ID when `hashId` is false, is written `id=…`.
|
|
120
|
+
*/
|
|
121
|
+
function formatLoomaAttributes(attributes, { hashId = true } = {}) {
|
|
122
|
+
const items = [];
|
|
123
|
+
const { id, ...rest } = attributes;
|
|
124
|
+
const hashed = hashId && typeof id === "string" && /^[\w-]+$/.test(id);
|
|
125
|
+
if (hashed) items.push(`#${id}`);
|
|
126
|
+
for (const [key, value] of Object.entries(hashed ? rest : attributes)) if (value === true) items.push(key);
|
|
127
|
+
else if (value === false || value === null || value === void 0) continue;
|
|
128
|
+
else {
|
|
129
|
+
const text = String(value);
|
|
130
|
+
items.push(/^[^\s"'=<>`{}]+$/.test(text) ? `${key}=${text}` : text.includes("\"") ? `${key}='${text}'` : `${key}="${text}"`);
|
|
131
|
+
}
|
|
132
|
+
return items.length ? `{${items.join(" ")}}` : "";
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* The anchor a heading's text derives: NFC, lowercase, keeping letters, numbers and combining
|
|
136
|
+
* marks, with every other run of characters one hyphen.
|
|
137
|
+
* @failure Text with no letters or numbers, such as only emoji, derives `heading`.
|
|
138
|
+
*/
|
|
139
|
+
function loomaHeadingSlug(text) {
|
|
140
|
+
return text.normalize("NFC").toLowerCase().replace(/[^\p{L}\p{N}\p{M}]+/gu, "-").replace(/^-+|-+$/g, "") || "heading";
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Gives every heading of a document its anchor, in document order.
|
|
144
|
+
* @contract A custom ID is kept unless an earlier heading already has it. Any other heading takes
|
|
145
|
+
* its slug, or the slug's first free suffix (`-1`, `-2`…), never one a later custom ID reserves.
|
|
146
|
+
*/
|
|
147
|
+
function assignLoomaHeadingIds(headings) {
|
|
148
|
+
const reserved = new Set(headings.map(({ id }) => id).filter((id) => Boolean(id)));
|
|
149
|
+
const used = /* @__PURE__ */ new Set();
|
|
150
|
+
return headings.map(({ text, id: custom }) => {
|
|
151
|
+
let id = custom || loomaHeadingSlug(text);
|
|
152
|
+
if (custom ? used.has(id) : used.has(id) || reserved.has(id)) {
|
|
153
|
+
const stem = id;
|
|
154
|
+
let suffix = 1;
|
|
155
|
+
while (used.has(`${stem}-${suffix}`) || reserved.has(`${stem}-${suffix}`)) suffix++;
|
|
156
|
+
id = `${stem}-${suffix}`;
|
|
157
|
+
}
|
|
158
|
+
used.add(id);
|
|
159
|
+
return id;
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
/** Reads a fence's info string: ```` ```ts title="a.ts" {1,3-5} :line-numbers ````. */
|
|
163
|
+
function parseLoomaFenceInfo(info) {
|
|
164
|
+
const source = info.trim();
|
|
165
|
+
const language = /^[^\s={:]+(?=[\s{:]|$)/.exec(source)?.[0];
|
|
166
|
+
const meta = (language ? source.slice(language.length) : source).trim();
|
|
167
|
+
const title = /(?:^|\s)title="([^"]*)"/.exec(meta)?.[1];
|
|
168
|
+
const rest = meta.replace(/(?:^|\s)title="[^"]*"/, "");
|
|
169
|
+
const lines = /* @__PURE__ */ new Set();
|
|
170
|
+
for (const range of /\{([\d\s,-]+)\}/.exec(rest)?.[1].split(",") ?? []) {
|
|
171
|
+
const [from = NaN, to = from] = range.split("-").map((part) => Number.parseInt(part, 10));
|
|
172
|
+
for (let line = from; line <= to; line++) lines.add(line);
|
|
173
|
+
}
|
|
174
|
+
const numbers = /:(no-)?line-numbers(?![\w-])/.exec(rest);
|
|
175
|
+
return {
|
|
176
|
+
...language ? { language } : {},
|
|
177
|
+
meta,
|
|
178
|
+
...title !== void 0 ? { title } : {},
|
|
179
|
+
lines: [...lines].sort((a, b) => a - b),
|
|
180
|
+
...numbers ? { lineNumbers: numbers[1] === void 0 } : {}
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
var MAPPING_KEY = /^(?:[^\s#:'"\-?,[\]{}&*!|>%@`][^:\n]*?|"[^"\n]*"|'[^'\n]*')[ \t]*:(?:[ \t]|$)/;
|
|
184
|
+
var NOTATION = /[ \t]*(?:\/\/|#|--|<!--|\{?\/\*)[ \t]*\[!code highlight(?::(\d+))?\][ \t]*(?:-->|\*\/\}?)?[ \t]*$/;
|
|
185
|
+
var ESCAPED_NOTATION = /\[\\(\\*!code highlight)/g;
|
|
186
|
+
/**
|
|
187
|
+
* Applies code notation: a line ending in a `[!code highlight]` comment is highlighted and loses
|
|
188
|
+
* the comment, `[!code highlight:3]` covers three lines, and a marker alone on its line is removed
|
|
189
|
+
* with the line and applies to the lines after it. A backslash between `[` and `!` escapes a
|
|
190
|
+
* marker, `[\!code highlight]`, which then shows as text with one backslash fewer and highlights
|
|
191
|
+
* nothing.
|
|
192
|
+
* @contract Returns the code a reader sees and its highlighted line numbers, from 1, ascending.
|
|
193
|
+
* ponytail: matched on source lines, so a string that ends in the marker counts too.
|
|
194
|
+
*/
|
|
195
|
+
function applyLoomaCodeNotation(code) {
|
|
196
|
+
const kept = [];
|
|
197
|
+
const lines = /* @__PURE__ */ new Set();
|
|
198
|
+
for (const line of code.split("\n")) {
|
|
199
|
+
const match = NOTATION.exec(line);
|
|
200
|
+
if (!match) {
|
|
201
|
+
kept.push(line);
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
const rest = line.slice(0, match.index);
|
|
205
|
+
const own = rest.trim() !== "";
|
|
206
|
+
if (own) kept.push(rest);
|
|
207
|
+
for (let count = 0; count < Number(match[1] ?? 1); count++) lines.add(kept.length + (own ? 0 : 1) + count);
|
|
208
|
+
}
|
|
209
|
+
return {
|
|
210
|
+
code: kept.join("\n").replace(ESCAPED_NOTATION, "[$1"),
|
|
211
|
+
lines: [...lines].sort((a, b) => a - b)
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Splits YAML front matter from the start of a document.
|
|
216
|
+
* @contract Front matter opens with a `---` line at the very start and closes at a `---` or `...`
|
|
217
|
+
* line, and what lies between is a YAML mapping: its first line that is not blank or a comment
|
|
218
|
+
* starts with a key, whose value may be a scalar, a list or a mapping. `source` is the block as
|
|
219
|
+
* written, delimiters included.
|
|
220
|
+
* @failure Returns null when the document has none.
|
|
221
|
+
*/
|
|
222
|
+
function splitLoomaFrontmatter(document) {
|
|
223
|
+
const match = /^---[ \t]*\r?\n([\s\S]*?)\r?\n(?:---|\.\.\.)[ \t]*(?:\r?\n|$)/.exec(document.slice(0, 8192));
|
|
224
|
+
const first = match?.[1].split(/\r?\n/).find((line) => line.trim() && !line.trimStart().startsWith("#"));
|
|
225
|
+
if (!match || !first || !MAPPING_KEY.test(first)) return null;
|
|
226
|
+
return {
|
|
227
|
+
source: match[0].trimEnd(),
|
|
228
|
+
yaml: match[1],
|
|
229
|
+
body: document.slice(match[0].length)
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
/** The colons a container opens and closes with, given how deeply containers nest inside it. */
|
|
233
|
+
function loomaContainerMarker(nestedDepth) {
|
|
234
|
+
return ":".repeat(3 + Math.max(0, nestedDepth));
|
|
235
|
+
}
|
|
236
|
+
/** A backtick fence longer than any run of backticks in the code, and at least three long. */
|
|
237
|
+
function loomaCodeFence(code) {
|
|
238
|
+
const longest = Math.max(0, ...(code.match(/`+/g) ?? []).map((run) => run.length));
|
|
239
|
+
return "`".repeat(Math.max(3, longest + 1));
|
|
240
|
+
}
|
|
241
|
+
//#endregion
|
|
242
|
+
export { assignLoomaHeadingIds as a, loomaContainerMarker as c, normalizeLoomaChipTone as d, parseLoomaAttributes as f, splitLoomaFrontmatter as h, applyLoomaCodeNotation as i, loomaHeadingSlug as l, readLoomaAttributes as m, LOOMA_CHIP_TONES as n, formatLoomaAttributes as o, parseLoomaFenceInfo as p, LOOMA_CONTAINER_NAMES as r, loomaCodeFence as s, LOOMA_CALLOUT_TONES as t, normalizeLoomaCalloutTone as u };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { JSONContent } from "@tiptap/core";
|
|
2
|
+
import { type ConversionOptions, type Document } from "expressmark";
|
|
3
|
+
/**
|
|
4
|
+
* A conversion cannot faithfully represent the named input at this document location.
|
|
5
|
+
* @failure Callers retain the original document and can report the unsupported feature and path.
|
|
6
|
+
*/
|
|
7
|
+
export declare class EditorMarkdownConversionError extends Error {
|
|
8
|
+
readonly path: string;
|
|
9
|
+
readonly feature: string;
|
|
10
|
+
constructor(path: string, feature: string);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Maps an editor's saved JSON to the independent Expressive Markdown AST without DOM access.
|
|
14
|
+
* @contract Unsupported nodes, marks and durable attributes throw with their location; input is never mutated.
|
|
15
|
+
*/
|
|
16
|
+
export declare function editorDocumentToExpressmark(document: JSONContent, options?: ConversionOptions): Document;
|
|
17
|
+
/**
|
|
18
|
+
* Maps supported Expressive Markdown content into the Looma editor's saved JSON shape.
|
|
19
|
+
* @contract The editor schema cannot represent arbitrary format extensions; unsupported meanings fail explicitly.
|
|
20
|
+
*/
|
|
21
|
+
export declare function expressmarkToEditorDocument(document: Document): JSONContent;
|
|
22
|
+
/**
|
|
23
|
+
* Writes an editor document using Expressmark's shared parser/writer and safe HTML policy.
|
|
24
|
+
* @failure Unsupported editor data raises EditorMarkdownConversionError before any input is changed.
|
|
25
|
+
*/
|
|
26
|
+
export declare function editorDocumentToMarkdown(document: JSONContent, options?: ConversionOptions): string;
|
|
27
|
+
/**
|
|
28
|
+
* Parses Expressive Markdown into editable JSON for the supported editor schema.
|
|
29
|
+
* @failure Unsupported content or root metadata stops conversion instead of being silently flattened.
|
|
30
|
+
*/
|
|
31
|
+
export declare function markdownToEditorDocument(markdown: string, options?: ConversionOptions): JSONContent;
|