@bikdotai/bik-component-library 0.0.806 → 0.0.807-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/editor/BikEditor.styles.js +8 -2
- package/dist/cjs/editor/BikEditor.styles.js.map +1 -1
- package/dist/cjs/editor/BikEditor.utils.js +1 -1
- package/dist/cjs/editor/BikEditor.utils.js.map +1 -1
- package/dist/cjs/editor/extensions/buildExtensions.js +1 -1
- package/dist/cjs/editor/extensions/buildExtensions.js.map +1 -1
- package/dist/cjs/editor/extensions/mention/MentionExtension.js +1 -1
- package/dist/cjs/editor/extensions/mention/MentionExtension.js.map +1 -1
- package/dist/cjs/editor/extensions/plainClipboard/ClipboardNormalizationExtension.js +2 -0
- package/dist/cjs/editor/extensions/plainClipboard/ClipboardNormalizationExtension.js.map +1 -0
- package/dist/cjs/editor/extensions/plainClipboard/PlainClipboardExtension.js +1 -1
- package/dist/cjs/editor/extensions/plainClipboard/PlainClipboardExtension.js.map +1 -1
- package/dist/cjs/editor/extensions/plainClipboard/pasteUtils.js +2 -0
- package/dist/cjs/editor/extensions/plainClipboard/pasteUtils.js.map +1 -0
- package/dist/cjs/editor/extensions/slashCommand/SlashCommandExtension.js +1 -1
- package/dist/cjs/editor/extensions/slashCommand/SlashCommandExtension.js.map +1 -1
- package/dist/cjs/editor/serializers/toWhatsAppText.js +1 -1
- package/dist/cjs/editor/serializers/toWhatsAppText.js.map +1 -1
- package/dist/cjs/src/components/QueryBuilder/Triggers/EVENTS/components/EventsTrigger.d.ts +1 -1
- package/dist/cjs/src/components/QueryBuilder/Triggers/EVENTS/selectors/useIGTriggerNameCacheSelector.d.ts +1 -1
- package/dist/cjs/src/components/QueryBuilder/Triggers/IG/components/IGTrigger.d.ts +1 -1
- package/dist/cjs/src/components/QueryBuilder/Triggers/IG/selectors/useIGTriggerNameCacheSelector.d.ts +1 -1
- package/dist/cjs/src/components/QueryBuilder/Triggers/components/BaseTriggerQueryBuilderNode.d.ts +2 -2
- package/dist/cjs/src/editor/BikEditor.utils.d.ts +15 -10
- package/dist/cjs/src/editor/extensions/plainClipboard/ClipboardNormalizationExtension.d.ts +7 -0
- package/dist/cjs/src/editor/extensions/plainClipboard/pasteUtils.d.ts +21 -0
- package/dist/cjs/src/editor/serializers/toWhatsAppText.d.ts +2 -2
- package/dist/esm/editor/BikEditor.styles.js +6 -0
- package/dist/esm/editor/BikEditor.styles.js.map +1 -1
- package/dist/esm/editor/BikEditor.utils.js +1 -1
- package/dist/esm/editor/BikEditor.utils.js.map +1 -1
- package/dist/esm/editor/extensions/buildExtensions.js +1 -1
- package/dist/esm/editor/extensions/buildExtensions.js.map +1 -1
- package/dist/esm/editor/extensions/mention/MentionExtension.js +1 -1
- package/dist/esm/editor/extensions/mention/MentionExtension.js.map +1 -1
- package/dist/esm/editor/extensions/plainClipboard/ClipboardNormalizationExtension.js +2 -0
- package/dist/esm/editor/extensions/plainClipboard/ClipboardNormalizationExtension.js.map +1 -0
- package/dist/esm/editor/extensions/plainClipboard/PlainClipboardExtension.js +1 -1
- package/dist/esm/editor/extensions/plainClipboard/PlainClipboardExtension.js.map +1 -1
- package/dist/esm/editor/extensions/plainClipboard/pasteUtils.js +2 -0
- package/dist/esm/editor/extensions/plainClipboard/pasteUtils.js.map +1 -0
- package/dist/esm/editor/extensions/slashCommand/SlashCommandExtension.js +1 -1
- package/dist/esm/editor/extensions/slashCommand/SlashCommandExtension.js.map +1 -1
- package/dist/esm/editor/serializers/toWhatsAppText.js +1 -1
- package/dist/esm/editor/serializers/toWhatsAppText.js.map +1 -1
- package/dist/esm/src/components/QueryBuilder/Triggers/EVENTS/components/EventsTrigger.d.ts +1 -1
- package/dist/esm/src/components/QueryBuilder/Triggers/EVENTS/selectors/useIGTriggerNameCacheSelector.d.ts +1 -1
- package/dist/esm/src/components/QueryBuilder/Triggers/IG/components/IGTrigger.d.ts +1 -1
- package/dist/esm/src/components/QueryBuilder/Triggers/IG/selectors/useIGTriggerNameCacheSelector.d.ts +1 -1
- package/dist/esm/src/components/QueryBuilder/Triggers/components/BaseTriggerQueryBuilderNode.d.ts +2 -2
- package/dist/esm/src/editor/BikEditor.utils.d.ts +15 -10
- package/dist/esm/src/editor/extensions/plainClipboard/ClipboardNormalizationExtension.d.ts +7 -0
- package/dist/esm/src/editor/extensions/plainClipboard/pasteUtils.d.ts +21 -0
- package/dist/esm/src/editor/serializers/toWhatsAppText.d.ts +2 -2
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("styled-components"),t=require("../constants/Theme.js");function o(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}const
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("styled-components"),t=require("../constants/Theme.js");function o(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}const r=o(e).default.div`
|
|
2
2
|
position: relative;
|
|
3
3
|
width: 100%;
|
|
4
4
|
|
|
@@ -17,6 +17,12 @@
|
|
|
17
17
|
padding: 0;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
/* Enter = new paragraph → visible gap. Shift+Enter = <br> inside
|
|
21
|
+
the same paragraph → no gap. Matches Google Docs / Word behavior. */
|
|
22
|
+
p + p {
|
|
23
|
+
margin-top: 4px;
|
|
24
|
+
}
|
|
25
|
+
|
|
20
26
|
ul,
|
|
21
27
|
ol {
|
|
22
28
|
margin: 0;
|
|
@@ -58,5 +64,5 @@
|
|
|
58
64
|
text-decoration-color: #6366f1;
|
|
59
65
|
}
|
|
60
66
|
}
|
|
61
|
-
`;exports.BikEditorShell=
|
|
67
|
+
`;exports.BikEditorShell=r;
|
|
62
68
|
//# sourceMappingURL=BikEditor.styles.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BikEditor.styles.js","sources":["../../../src/editor/BikEditor.styles.ts"],"sourcesContent":["import styled from 'styled-components';\nimport { COLORS } from '../constants/Theme';\n\nexport const BikEditorShell = styled.div<{\n\tminHeight?: string;\n\tmaxHeight?: string;\n}>`\n\tposition: relative;\n\twidth: 100%;\n\n\t.ProseMirror {\n\t\tmin-height: ${({ minHeight }) => minHeight ?? '80px'};\n\t\tmax-height: ${({ maxHeight }) => maxHeight ?? 'none'};\n\t\toverflow-y: auto;\n\t\toutline: none;\n\t\tpadding: 8px 12px;\n\t\tfont-size: 14px;\n\t\tline-height: 1.5;\n\t\tword-break: break-word;\n\n\t\tp {\n\t\t\tmargin: 0;\n\t\t\tpadding: 0;\n\t\t}\n\n\t\tul,\n\t\tol {\n\t\t\tmargin: 0;\n\t\t\tpadding-left: 1.5em;\n\t\t}\n\n\t\tli + li {\n\t\t\tmargin-top: 2px;\n\t\t}\n\n\t\tp.is-editor-empty:first-child::before {\n\t\t\tcontent: attr(data-placeholder);\n\t\t\tfloat: left;\n\t\t\tcolor: #adb5bd;\n\t\t\tpointer-events: none;\n\t\t\theight: 0;\n\t\t}\n\t}\n\n\t.bik-mention {\n\t\tcolor: ${COLORS.content.brand};\n\t\tpadding: 1px 4px;\n\t}\n\t.bik-mention--team {\n\t\tcolor: ${COLORS.content.brand};\n\t}\n\t.bik-variable {\n\t}\n\n\ta,\n\t.bik-link {\n\t\tcolor: #4f46e5;\n\t\ttext-decoration: underline;\n\t\ttext-decoration-color: #a5b4fc;\n\t\ttext-underline-offset: 2px;\n\t\tcursor: pointer;\n\t\t&:hover {\n\t\t\tcolor: #3730a3;\n\t\t\ttext-decoration-color: #6366f1;\n\t\t}\n\t}\n`;\n"],"names":["BikEditorShell","div","_ref","minHeight","_ref2","maxHeight","COLORS","content","brand"],"mappings":"kNAGaA,MAAAA,OAAuB,QAACC,GAGnC;;;;;gBAKcC,IAAA,IAACC,UAAEA,GAAWD,EAAA,OAAKC,QAAAA,EAAa,MAAM;gBACtCC,IAAA,IAACC,UAAEA,GAAWD,EAAA,OAAKC,QAAAA,EAAa,MAAM
|
|
1
|
+
{"version":3,"file":"BikEditor.styles.js","sources":["../../../src/editor/BikEditor.styles.ts"],"sourcesContent":["import styled from 'styled-components';\nimport { COLORS } from '../constants/Theme';\n\nexport const BikEditorShell = styled.div<{\n\tminHeight?: string;\n\tmaxHeight?: string;\n}>`\n\tposition: relative;\n\twidth: 100%;\n\n\t.ProseMirror {\n\t\tmin-height: ${({ minHeight }) => minHeight ?? '80px'};\n\t\tmax-height: ${({ maxHeight }) => maxHeight ?? 'none'};\n\t\toverflow-y: auto;\n\t\toutline: none;\n\t\tpadding: 8px 12px;\n\t\tfont-size: 14px;\n\t\tline-height: 1.5;\n\t\tword-break: break-word;\n\n\t\tp {\n\t\t\tmargin: 0;\n\t\t\tpadding: 0;\n\t\t}\n\n\t\t/* Enter = new paragraph → visible gap. Shift+Enter = <br> inside\n\t\t the same paragraph → no gap. Matches Google Docs / Word behavior. */\n\t\tp + p {\n\t\t\tmargin-top: 4px;\n\t\t}\n\n\t\tul,\n\t\tol {\n\t\t\tmargin: 0;\n\t\t\tpadding-left: 1.5em;\n\t\t}\n\n\t\tli + li {\n\t\t\tmargin-top: 2px;\n\t\t}\n\n\t\tp.is-editor-empty:first-child::before {\n\t\t\tcontent: attr(data-placeholder);\n\t\t\tfloat: left;\n\t\t\tcolor: #adb5bd;\n\t\t\tpointer-events: none;\n\t\t\theight: 0;\n\t\t}\n\t}\n\n\t.bik-mention {\n\t\tcolor: ${COLORS.content.brand};\n\t\tpadding: 1px 4px;\n\t}\n\t.bik-mention--team {\n\t\tcolor: ${COLORS.content.brand};\n\t}\n\t.bik-variable {\n\t}\n\n\ta,\n\t.bik-link {\n\t\tcolor: #4f46e5;\n\t\ttext-decoration: underline;\n\t\ttext-decoration-color: #a5b4fc;\n\t\ttext-underline-offset: 2px;\n\t\tcursor: pointer;\n\t\t&:hover {\n\t\t\tcolor: #3730a3;\n\t\t\ttext-decoration-color: #6366f1;\n\t\t}\n\t}\n`;\n"],"names":["BikEditorShell","div","_ref","minHeight","_ref2","maxHeight","COLORS","content","brand"],"mappings":"kNAGaA,MAAAA,OAAuB,QAACC,GAGnC;;;;;gBAKcC,IAAA,IAACC,UAAEA,GAAWD,EAAA,OAAKC,QAAAA,EAAa,MAAM;gBACtCC,IAAA,IAACC,UAAEA,GAAWD,EAAA,OAAKC,QAAAA,EAAa,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAuC3CC,EAAMA,OAACC,QAAQC;;;;WAIfF,EAAMA,OAACC,QAAQC;;;;;;;;;;;;;;;;;"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var t=require("../node_modules/prosemirror-model/dist/index.js");function e(t){return t.replace(
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var t=require("../node_modules/prosemirror-model/dist/index.js");function e(t){return t.replace(/<\/?span[^>]*>/gi,"").replace(/(<p[^>]*>)\s*<br\s*\/?>\s*(<\/p>)/gi,"$1$2")}function n(t){return t.replace(/<p><\/p>/g,"<p><br></p>")}const i=t=>`<div data-section-divider="${t}" style="display:none;height:0;line-height:0;overflow:hidden;"></div>`;function r(t){var e;if(!t)return"";return null!==(e=o(t).get("body"))&&void 0!==e?e:t}function o(t){const e=new Map,n=/<div[^>]*data-section-divider="([^"]*)[^>]*>\s*<\/div>/g,i=[];let r;for(;null!==(r=n.exec(t));)i.push({id:r[1],index:r.index,endIndex:r.index+r[0].length});if(0===i.length)return e.set("body",t),e;e.set("body",t.slice(0,i[0].index));for(let n=0;n<i.length;n++){const r=i[n].endIndex,o=n+1<i.length?i[n+1].index:t.length;e.set(i[n].id,t.slice(r,o))}return e}function s(e,i){var r;const o=c(e,i);if(-1===o)return{html:"",text:"",isEmpty:!0,characterCount:0};const s=l(e,i),d=e.state.doc.slice(o,s),u=document.createElement("div"),a=t.DOMSerializer.fromSchema(e.schema);u.appendChild(a.serializeFragment(d.content));const f=n(u.innerHTML),p=null!==(r=u.textContent)&&void 0!==r?r:"";return{html:f,text:p,isEmpty:!p.trim(),characterCount:p.length}}function c(t,e){if("body"===e)return 1;let n=-1;return t.state.doc.descendants(((t,i)=>{if(-1!==n)return!1;"sectionDivider"===t.type.name&&t.attrs.sectionId===e&&(n=i+t.nodeSize)})),n}function l(t,e){const n=t.state.doc,i=n.content.size;if("body"===e){let t=-1;return n.descendants(((e,n)=>{if(-1!==t)return!1;"sectionDivider"===e.type.name&&(t=n)})),-1!==t?t:i}let r=!1,o=-1;return n.descendants(((t,n)=>-1===o&&(r?void("sectionDivider"===t.type.name&&(o=n)):("sectionDivider"===t.type.name&&t.attrs.sectionId===e&&(r=!0),!1)))),-1!==o?o:i}exports.SECTION_DIVIDER_HTML=i,exports.buildSectionedContent=function(t,e){let n=t;for(const t of e)n+=i(t.id)+t.content;return n},exports.extractActiveFormats=function(t){var e,n,i,r;return{bold:t.isActive("bold"),italic:t.isActive("italic"),underline:t.isActive("underline"),strike:t.isActive("strike"),bulletList:t.isActive("bulletList"),orderedList:t.isActive("orderedList"),blockquote:t.isActive("blockquote"),codeBlock:t.isActive("codeBlock"),link:(()=>{var e,n,i;if(t.isActive("link"))return{href:null!==(e=t.getAttributes("link").href)&&void 0!==e?e:""};const{$from:r}=t.state.selection;if(r.pos>0){const t=r.doc.resolve(r.pos).marks().find((t=>"link"===t.type.name));if(t)return{href:null!==(i=t.attrs.href)&&void 0!==i?i:""};{const t=r.nodeBefore,e=null==t?void 0:t.marks.find((t=>"link"===t.type.name));if(e)return{href:null!==(n=e.attrs.href)&&void 0!==n?n:""}}}return null})(),textAlign:t.isActive({textAlign:"center"})?"center":t.isActive({textAlign:"right"})?"right":t.isActive({textAlign:"justify"})?"justify":t.isActive({textAlign:"left"})?"left":null,fontFamily:null!==(e=t.getAttributes("textStyle").fontFamily)&&void 0!==e?e:null,fontSize:null!==(n=t.getAttributes("textStyle").fontSize)&&void 0!==n?n:null,color:null!==(i=t.getAttributes("textStyle").color)&&void 0!==i?i:null,highlight:t.isActive("highlight")?null!==(r=t.getAttributes("highlight").color)&&void 0!==r?r:"default":null,superscript:t.isActive("superscript"),subscript:t.isActive("subscript")}},exports.extractAllSectionsFromHtml=o,exports.extractBodyContent=function(t){return s(t,"body")},exports.extractContent=function(t){var e,i,r;return{html:n(t.getHTML()),text:t.getText(),isEmpty:t.isEmpty,characterCount:null!==(r=null===(i=null===(e=t.storage.characterCount)||void 0===e?void 0:e.characters)||void 0===i?void 0:i.call(e))&&void 0!==r?r:t.getText().length}},exports.extractSectionContent=s,exports.findSectionEndPos=l,exports.findSectionStartPos=c,exports.getBodyHtml=r,exports.getSectionsHtml=function(t){if(!t)return"";const e=r(t);return t.substring(e.length)},exports.insertInlineHtml=function(n,i){const r=e(i),o=document.createElement("div");o.innerHTML=r;const s=t.DOMParser.fromSchema(n.schema).parseSlice(o);if(0===s.size)return;const{from:c,to:l}=n.state.selection,d=n.state.tr.replaceRange(c,l,s);n.view.dispatch(d)},exports.normalizeHtml=e,exports.setSectionContentInEditor=function(e,n,r){const o=c(e,n);if(-1===o){const t=e.state.doc.content.size,o=i(n)+r;return void e.commands.insertContentAt(t,o,{updateSelection:!1})}const s=l(e,n),d=function(e,n){const i=document.createElement("div");return i.innerHTML=n,t.DOMParser.fromSchema(e.schema).parse(i).content}(e,r),{tr:u}=e.state,a="body"===n?0:o;u.replaceWith(a,s,d),u.setMeta("addToHistory",!1),e.view.dispatch(u)},exports.toPortableHtml=n;
|
|
2
2
|
//# sourceMappingURL=BikEditor.utils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BikEditor.utils.js","sources":["../../../src/editor/BikEditor.utils.ts"],"sourcesContent":["import { Editor } from '@tiptap/core';\nimport { DOMParser, DOMSerializer } from 'prosemirror-model';\nimport { EditorSnapshot, FormatState } from './BikEditor.types';\n\n// ---------------------------------------------------------------------------\n// HTML normalisation\n// ---------------------------------------------------------------------------\n\n/**\n * Normalise HTML before passing it to TipTap.\n *\n * Problem: Quill uses `<p><br></p>` as a blank-line separator. TipTap's\n * HardBreak extension parses that `<br>` as a real `hard_break` node.\n * ProseMirror then also appends `<br class=\"ProseMirror-trailingBreak\">` as a\n * cursor-position decoration, making the empty paragraph render at **2× line\n * height** instead of 1×.\n *\n * Fix: replace `<p><br></p>` → `<p></p>` so TipTap stores a truly empty\n * paragraph. ProseMirror adds only the trailing decoration, giving the correct\n * 1× line height. The WA text output is unchanged (`\\n` either way after\n * surrounding-newline collapse in `toWhatsAppText`).\n */\nexport function normalizeHtml(html: string): string {\n\treturn html\n\t\t.replace(/<p>\\s*<br\\s*\\/?>\\s*<\\/p>/gi, '<p></p>')\n\t\t.replace(/<\\/?span[^>]*>/gi, '');\n}\n\n// ---------------------------------------------------------------------------\n// Inline content insertion\n// ---------------------------------------------------------------------------\n\n/**\n * Insert HTML at the current cursor position, merging the first paragraph\n * inline while preserving the block structure of subsequent paragraphs/lists.\n *\n * Uses `parseSlice` which returns an open-ended Slice — the first block merges\n * at the cursor, middle blocks stay intact, and the last block merges with any\n * text that follows the cursor.\n */\nexport function insertInlineHtml(editor: Editor, html: string): void {\n\tconst normalised = normalizeHtml(html);\n\tconst dom = document.createElement('div');\n\tdom.innerHTML = normalised;\n\tconst slice = DOMParser.fromSchema(editor.schema).parseSlice(dom);\n\n\tif (slice.size === 0) return;\n\n\tconst { from, to } = editor.state.selection;\n\tconst tr = editor.state.tr.replaceRange(from, to, slice);\n\teditor.view.dispatch(tr);\n}\n\n// ---------------------------------------------------------------------------\n// Section divider HTML\n// ---------------------------------------------------------------------------\n\nexport const SECTION_DIVIDER_HTML = (id: string) =>\n\t`<div data-section-divider=\"${id}\" style=\"display:none;height:0;line-height:0;overflow:hidden;\"></div>`;\n\n/**\n * Build initial HTML for an editor with one or more named sections below the body.\n * Each section is separated by an invisible divider node.\n *\n * @example\n * buildSectionedContent('<p>Body</p>', [\n * { id: 'signature', content: '<p>Alice</p>' },\n * { id: 'forwarded', content: '<p>--- fwd ---</p>' },\n * ])\n */\nexport function buildSectionedContent(\n\tbody: string,\n\tsections: Array<{ id: string; content: string }>,\n): string {\n\tlet html = body;\n\tfor (const s of sections) {\n\t\thtml += SECTION_DIVIDER_HTML(s.id) + s.content;\n\t}\n\treturn html;\n}\n\n// ---------------------------------------------------------------------------\n// Section extraction\n// ---------------------------------------------------------------------------\n\n/**\n * Parse the editor HTML into a Map of sectionId → raw HTML string.\n * The special key `'body'` always holds the content before the first divider.\n * Map iteration order matches document order.\n */\nexport function extractAllSections(editor: Editor): Map<string, string> {\n\treturn extractAllSectionsFromHtml(editor.getHTML());\n}\n\n/**\n * Extract just the body portion (everything before the first section divider)\n * from an HTML string produced by BikEditor. Safe to call on plain HTML too —\n * returns the full string when no dividers are present.\n */\nexport function getBodyHtml(html: string): string {\n\tif (!html) return '';\n\tconst sections = extractAllSectionsFromHtml(html);\n\treturn sections.get('body') ?? html;\n}\n\n/**\n * Extract everything from the first section divider onward (dividers + their\n * content). Returns an empty string when there are no sections.\n */\nexport function getSectionsHtml(html: string): string {\n\tif (!html) return '';\n\tconst body = getBodyHtml(html);\n\treturn html.substring(body.length);\n}\n\nexport function extractAllSectionsFromHtml(html: string): Map<string, string> {\n\tconst sections = new Map<string, string>();\n\tconst dividerRegex =\n\t\t/<div[^>]*data-section-divider=\"([^\"]*)[^>]*>\\s*<\\/div>/g;\n\tconst dividers: Array<{ id: string; index: number; endIndex: number }> = [];\n\n\tlet match: RegExpExecArray | null;\n\twhile ((match = dividerRegex.exec(html)) !== null) {\n\t\tdividers.push({\n\t\t\tid: match[1],\n\t\t\tindex: match.index,\n\t\t\tendIndex: match.index + match[0].length,\n\t\t});\n\t}\n\n\tif (dividers.length === 0) {\n\t\tsections.set('body', html);\n\t\treturn sections;\n\t}\n\n\tsections.set('body', html.slice(0, dividers[0].index));\n\tfor (let i = 0; i < dividers.length; i++) {\n\t\tconst start = dividers[i].endIndex;\n\t\tconst end = i + 1 < dividers.length ? dividers[i + 1].index : html.length;\n\t\tsections.set(dividers[i].id, html.slice(start, end));\n\t}\n\n\treturn sections;\n}\n\n/** Returns BikEditorContent for a single named section (or 'body'). */\nexport function extractSectionContent(\n\teditor: Editor,\n\tid: string,\n): EditorSnapshot {\n\tconst startPos = findSectionStartPos(editor, id);\n\tif (startPos === -1)\n\t\treturn { html: '', text: '', isEmpty: true, characterCount: 0 };\n\tconst endPos = findSectionEndPos(editor, id);\n\tconst slice = editor.state.doc.slice(startPos, endPos);\n\tconst container = document.createElement('div');\n\tconst serializer = DOMSerializer.fromSchema(editor.schema);\n\tcontainer.appendChild(serializer.serializeFragment(slice.content));\n\tconst html = container.innerHTML;\n\tconst text = container.textContent ?? '';\n\treturn { html, text, isEmpty: !text.trim(), characterCount: text.length };\n}\n\n/**\n * Parse an HTML string into ProseMirror nodes using the editor's schema.\n */\nfunction parseHtmlToNodes(editor: Editor, html: string) {\n\tconst container = document.createElement('div');\n\tcontainer.innerHTML = html;\n\treturn DOMParser.fromSchema(editor.schema).parse(container).content;\n}\n\n/**\n * Replace the content of a single named section without touching others.\n * Uses a ProseMirror transaction to replace only the target range,\n * preserving undo history and other sections' state.\n * If the section doesn't exist yet, it is appended at the end of the document.\n */\nexport function setSectionContentInEditor(\n\teditor: Editor,\n\tid: string,\n\thtml: string,\n): void {\n\tconst startPos = findSectionStartPos(editor, id);\n\tif (startPos === -1) {\n\t\tconst endPos = editor.state.doc.content.size;\n\t\tconst dividerHtml = SECTION_DIVIDER_HTML(id) + html;\n\t\teditor.commands.insertContentAt(endPos, dividerHtml, {\n\t\t\tupdateSelection: false,\n\t\t});\n\t\treturn;\n\t}\n\tconst endPos = findSectionEndPos(editor, id);\n\tconst fragment = parseHtmlToNodes(editor, html);\n\tconst { tr } = editor.state;\n\t// For body, replace from position 0 (before the first paragraph's opening\n\t// boundary) so ProseMirror swaps entire block nodes cleanly. Position 1\n\t// (inside the paragraph) would force ProseMirror to close the open paragraph\n\t// first, creating a ghost empty <p></p>.\n\tconst replaceFrom = id === 'body' ? 0 : startPos;\n\ttr.replaceWith(replaceFrom, endPos, fragment);\n\ttr.setMeta('addToHistory', false);\n\teditor.view.dispatch(tr);\n}\n\n// ---------------------------------------------------------------------------\n// Convenience shorthands (body = first section)\n// ---------------------------------------------------------------------------\n\n/** Extract BikEditorContent for just the body (before the first divider). */\nexport function extractBodyContent(editor: Editor): EditorSnapshot {\n\treturn extractSectionContent(editor, 'body');\n}\n\n// ---------------------------------------------------------------------------\n// Active formats\n// ---------------------------------------------------------------------------\n\nexport function extractActiveFormats(editor: Editor): FormatState {\n\treturn {\n\t\tbold: editor.isActive('bold'),\n\t\titalic: editor.isActive('italic'),\n\t\tunderline: editor.isActive('underline'),\n\t\tstrike: editor.isActive('strike'),\n\t\tbulletList: editor.isActive('bulletList'),\n\t\torderedList: editor.isActive('orderedList'),\n\t\tblockquote: editor.isActive('blockquote'),\n\t\tcodeBlock: editor.isActive('codeBlock'),\n\t\tlink: (() => {\n\t\t\tif (editor.isActive('link')) {\n\t\t\t\treturn { href: editor.getAttributes('link')['href'] ?? '' };\n\t\t\t}\n\t\t\tconst { $from } = editor.state.selection;\n\t\t\tif ($from.pos > 0) {\n\t\t\t\tconst before = $from.doc.resolve($from.pos);\n\t\t\t\tconst linkMark = before.marks().find((m) => m.type.name === 'link');\n\t\t\t\tif (!linkMark) {\n\t\t\t\t\tconst nodeBefore = $from.nodeBefore;\n\t\t\t\t\tconst markOnPrev = nodeBefore?.marks.find(\n\t\t\t\t\t\t(m) => m.type.name === 'link',\n\t\t\t\t\t);\n\t\t\t\t\tif (markOnPrev) {\n\t\t\t\t\t\treturn { href: markOnPrev.attrs['href'] ?? '' };\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\treturn { href: linkMark.attrs['href'] ?? '' };\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t})(),\n\t\ttextAlign: editor.isActive({ textAlign: 'center' })\n\t\t\t? 'center'\n\t\t\t: editor.isActive({ textAlign: 'right' })\n\t\t\t? 'right'\n\t\t\t: editor.isActive({ textAlign: 'justify' })\n\t\t\t? 'justify'\n\t\t\t: editor.isActive({ textAlign: 'left' })\n\t\t\t? 'left'\n\t\t\t: null,\n\t\tfontFamily: editor.getAttributes('textStyle')['fontFamily'] ?? null,\n\t\tfontSize: editor.getAttributes('textStyle')['fontSize'] ?? null,\n\t\tcolor: editor.getAttributes('textStyle')['color'] ?? null,\n\t\thighlight: editor.isActive('highlight')\n\t\t\t? editor.getAttributes('highlight')['color'] ?? 'default'\n\t\t\t: null,\n\t\tsuperscript: editor.isActive('superscript'),\n\t\tsubscript: editor.isActive('subscript'),\n\t};\n}\n\nexport function extractContent(editor: Editor): EditorSnapshot {\n\treturn {\n\t\thtml: editor.getHTML(),\n\t\ttext: editor.getText(),\n\t\tisEmpty: editor.isEmpty,\n\t\tcharacterCount:\n\t\t\teditor.storage.characterCount?.characters?.() ?? editor.getText().length,\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// Section position helpers (used by insertAtSectionStart/End and appendBodyContent)\n// ---------------------------------------------------------------------------\n\n/**\n * Returns the ProseMirror position immediately after a section's opening divider\n * (i.e. the start of the section's own content).\n * For `'body'`, returns 1 (beginning of the document).\n * Returns -1 if the named section's divider is not found.\n */\nexport function findSectionStartPos(editor: Editor, sectionId: string): number {\n\tif (sectionId === 'body') return 1;\n\tlet startPos = -1;\n\teditor.state.doc.descendants((node, pos) => {\n\t\tif (startPos !== -1) return false;\n\t\tif (\n\t\t\tnode.type.name === 'sectionDivider' &&\n\t\t\tnode.attrs['sectionId'] === sectionId\n\t\t) {\n\t\t\tstartPos = pos + node.nodeSize; // position right after the divider\n\t\t}\n\t});\n\treturn startPos;\n}\n\n/**\n * Returns the ProseMirror position at the end of a named section's content:\n * - For `'body'`: position of the first section divider, or end of document.\n * - For a named section: position of the next divider, or end of document.\n */\nexport function findSectionEndPos(editor: Editor, sectionId: string): number {\n\tconst doc = editor.state.doc;\n\tconst docSize = doc.content.size;\n\n\tif (sectionId === 'body') {\n\t\tlet firstDividerPos = -1;\n\t\tdoc.descendants((node, pos) => {\n\t\t\tif (firstDividerPos !== -1) return false;\n\t\t\tif (node.type.name === 'sectionDivider') {\n\t\t\t\tfirstDividerPos = pos;\n\t\t\t}\n\t\t});\n\t\treturn firstDividerPos !== -1 ? firstDividerPos : docSize;\n\t}\n\n\tlet passedSection = false;\n\tlet nextDividerPos = -1;\n\tdoc.descendants((node, pos) => {\n\t\tif (nextDividerPos !== -1) return false;\n\t\tif (!passedSection) {\n\t\t\tif (\n\t\t\t\tnode.type.name === 'sectionDivider' &&\n\t\t\t\tnode.attrs['sectionId'] === sectionId\n\t\t\t) {\n\t\t\t\tpassedSection = true;\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\t\tif (node.type.name === 'sectionDivider') {\n\t\t\tnextDividerPos = pos;\n\t\t}\n\t});\n\treturn nextDividerPos !== -1 ? nextDividerPos : docSize;\n}\n"],"names":["normalizeHtml","html","replace","SECTION_DIVIDER_HTML","id","getBodyHtml","_a","extractAllSectionsFromHtml","get","sections","Map","dividerRegex","dividers","match","exec","push","index","endIndex","length","set","slice","i","start","end","extractSectionContent","editor","startPos","findSectionStartPos","text","isEmpty","characterCount","endPos","findSectionEndPos","state","doc","container","document","createElement","serializer","DOMSerializer","fromSchema","schema","appendChild","serializeFragment","content","innerHTML","textContent","trim","sectionId","descendants","node","pos","type","name","attrs","nodeSize","docSize","size","firstDividerPos","passedSection","nextDividerPos","body","s","bold","isActive","italic","underline","strike","bulletList","orderedList","blockquote","codeBlock","link","href","getAttributes","$from","selection","linkMark","resolve","marks","find","m","_c","nodeBefore","markOnPrev","_b","textAlign","fontFamily","fontSize","color","highlight","_d","superscript","subscript","getHTML","getText","storage","characters","substring","normalised","dom","DOMParser","parseSlice","from","to","tr","replaceRange","view","dispatch","dividerHtml","commands","insertContentAt","updateSelection","fragment","parse","parseHtmlToNodes","replaceFrom","replaceWith","setMeta"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"BikEditor.utils.js","sources":["../../../src/editor/BikEditor.utils.ts"],"sourcesContent":["import { Editor } from '@tiptap/core';\nimport { DOMParser, DOMSerializer } from 'prosemirror-model';\nimport { EditorSnapshot, FormatState } from './BikEditor.types';\n\n// ---------------------------------------------------------------------------\n// HTML normalisation\n// ---------------------------------------------------------------------------\n\n/**\n * Normalise HTML before passing it to TipTap.\n *\n * 1. Strip all `<span>` tags first (keeps inner content). This exposes\n * bare `<br>` inside otherwise-empty paragraphs like Quill's\n * `<p><span class=\"ql-cursor\"><br></span></p>`.\n * 2. Then convert `<p><br></p>` → `<p></p>`. ProseMirror parses `<p></p>`\n * as an empty paragraph node and adds its own DOM `<br>` for cursor\n * positioning — one blank line, correct height. Leaving the `<br>`\n * would create a `hard_break` child AND the cursor `<br>`, producing\n * double-height blank lines.\n */\nexport function normalizeHtml(html: string): string {\n\treturn html\n\t\t.replace(/<\\/?span[^>]*>/gi, '')\n\t\t.replace(/(<p[^>]*>)\\s*<br\\s*\\/?>\\s*(<\\/p>)/gi, '$1$2');\n}\n\n/**\n * Convert ProseMirror's `<p></p>` empty paragraphs to the universally\n * rendered `<p><br></p>` format before the HTML leaves the editor.\n * Email clients, chat bubbles, and every renderer understand `<p><br></p>`\n * as a visible blank line, whereas `<p></p>` collapses to zero height.\n */\nexport function toPortableHtml(html: string): string {\n\treturn html.replace(/<p><\\/p>/g, '<p><br></p>');\n}\n\n// ---------------------------------------------------------------------------\n// Inline content insertion\n// ---------------------------------------------------------------------------\n\n/**\n * Insert HTML at the current cursor position, merging the first paragraph\n * inline while preserving the block structure of subsequent paragraphs/lists.\n *\n * Uses `parseSlice` which returns an open-ended Slice — the first block merges\n * at the cursor, middle blocks stay intact, and the last block merges with any\n * text that follows the cursor.\n */\nexport function insertInlineHtml(editor: Editor, html: string): void {\n\tconst normalised = normalizeHtml(html);\n\tconst dom = document.createElement('div');\n\tdom.innerHTML = normalised;\n\tconst slice = DOMParser.fromSchema(editor.schema).parseSlice(dom);\n\n\tif (slice.size === 0) return;\n\n\tconst { from, to } = editor.state.selection;\n\tconst tr = editor.state.tr.replaceRange(from, to, slice);\n\teditor.view.dispatch(tr);\n}\n\n// ---------------------------------------------------------------------------\n// Section divider HTML\n// ---------------------------------------------------------------------------\n\nexport const SECTION_DIVIDER_HTML = (id: string) =>\n\t`<div data-section-divider=\"${id}\" style=\"display:none;height:0;line-height:0;overflow:hidden;\"></div>`;\n\n/**\n * Build initial HTML for an editor with one or more named sections below the body.\n * Each section is separated by an invisible divider node.\n *\n * @example\n * buildSectionedContent('<p>Body</p>', [\n * { id: 'signature', content: '<p>Alice</p>' },\n * { id: 'forwarded', content: '<p>--- fwd ---</p>' },\n * ])\n */\nexport function buildSectionedContent(\n\tbody: string,\n\tsections: Array<{ id: string; content: string }>,\n): string {\n\tlet html = body;\n\tfor (const s of sections) {\n\t\thtml += SECTION_DIVIDER_HTML(s.id) + s.content;\n\t}\n\treturn html;\n}\n\n// ---------------------------------------------------------------------------\n// Section extraction\n// ---------------------------------------------------------------------------\n\n/**\n * Parse the editor HTML into a Map of sectionId → raw HTML string.\n * The special key `'body'` always holds the content before the first divider.\n * Map iteration order matches document order.\n */\nexport function extractAllSections(editor: Editor): Map<string, string> {\n\treturn extractAllSectionsFromHtml(editor.getHTML());\n}\n\n/**\n * Extract just the body portion (everything before the first section divider)\n * from an HTML string produced by BikEditor. Safe to call on plain HTML too —\n * returns the full string when no dividers are present.\n */\nexport function getBodyHtml(html: string): string {\n\tif (!html) return '';\n\tconst sections = extractAllSectionsFromHtml(html);\n\treturn sections.get('body') ?? html;\n}\n\n/**\n * Extract everything from the first section divider onward (dividers + their\n * content). Returns an empty string when there are no sections.\n */\nexport function getSectionsHtml(html: string): string {\n\tif (!html) return '';\n\tconst body = getBodyHtml(html);\n\treturn html.substring(body.length);\n}\n\nexport function extractAllSectionsFromHtml(html: string): Map<string, string> {\n\tconst sections = new Map<string, string>();\n\tconst dividerRegex =\n\t\t/<div[^>]*data-section-divider=\"([^\"]*)[^>]*>\\s*<\\/div>/g;\n\tconst dividers: Array<{ id: string; index: number; endIndex: number }> = [];\n\n\tlet match: RegExpExecArray | null;\n\twhile ((match = dividerRegex.exec(html)) !== null) {\n\t\tdividers.push({\n\t\t\tid: match[1],\n\t\t\tindex: match.index,\n\t\t\tendIndex: match.index + match[0].length,\n\t\t});\n\t}\n\n\tif (dividers.length === 0) {\n\t\tsections.set('body', html);\n\t\treturn sections;\n\t}\n\n\tsections.set('body', html.slice(0, dividers[0].index));\n\tfor (let i = 0; i < dividers.length; i++) {\n\t\tconst start = dividers[i].endIndex;\n\t\tconst end = i + 1 < dividers.length ? dividers[i + 1].index : html.length;\n\t\tsections.set(dividers[i].id, html.slice(start, end));\n\t}\n\n\treturn sections;\n}\n\n/** Returns BikEditorContent for a single named section (or 'body'). */\nexport function extractSectionContent(\n\teditor: Editor,\n\tid: string,\n): EditorSnapshot {\n\tconst startPos = findSectionStartPos(editor, id);\n\tif (startPos === -1)\n\t\treturn { html: '', text: '', isEmpty: true, characterCount: 0 };\n\tconst endPos = findSectionEndPos(editor, id);\n\tconst slice = editor.state.doc.slice(startPos, endPos);\n\tconst container = document.createElement('div');\n\tconst serializer = DOMSerializer.fromSchema(editor.schema);\n\tcontainer.appendChild(serializer.serializeFragment(slice.content));\n\tconst html = toPortableHtml(container.innerHTML);\n\tconst text = container.textContent ?? '';\n\treturn { html, text, isEmpty: !text.trim(), characterCount: text.length };\n}\n\n/**\n * Parse an HTML string into ProseMirror nodes using the editor's schema.\n */\nfunction parseHtmlToNodes(editor: Editor, html: string) {\n\tconst container = document.createElement('div');\n\tcontainer.innerHTML = html;\n\treturn DOMParser.fromSchema(editor.schema).parse(container).content;\n}\n\n/**\n * Replace the content of a single named section without touching others.\n * Uses a ProseMirror transaction to replace only the target range,\n * preserving undo history and other sections' state.\n * If the section doesn't exist yet, it is appended at the end of the document.\n */\nexport function setSectionContentInEditor(\n\teditor: Editor,\n\tid: string,\n\thtml: string,\n): void {\n\tconst startPos = findSectionStartPos(editor, id);\n\tif (startPos === -1) {\n\t\tconst endPos = editor.state.doc.content.size;\n\t\tconst dividerHtml = SECTION_DIVIDER_HTML(id) + html;\n\t\teditor.commands.insertContentAt(endPos, dividerHtml, {\n\t\t\tupdateSelection: false,\n\t\t});\n\t\treturn;\n\t}\n\tconst endPos = findSectionEndPos(editor, id);\n\tconst fragment = parseHtmlToNodes(editor, html);\n\tconst { tr } = editor.state;\n\t// For body, replace from position 0 (before the first paragraph's opening\n\t// boundary) so ProseMirror swaps entire block nodes cleanly. Position 1\n\t// (inside the paragraph) would force ProseMirror to close the open paragraph\n\t// first, creating a ghost empty <p></p>.\n\tconst replaceFrom = id === 'body' ? 0 : startPos;\n\ttr.replaceWith(replaceFrom, endPos, fragment);\n\ttr.setMeta('addToHistory', false);\n\teditor.view.dispatch(tr);\n}\n\n// ---------------------------------------------------------------------------\n// Convenience shorthands (body = first section)\n// ---------------------------------------------------------------------------\n\n/** Extract BikEditorContent for just the body (before the first divider). */\nexport function extractBodyContent(editor: Editor): EditorSnapshot {\n\treturn extractSectionContent(editor, 'body');\n}\n\n// ---------------------------------------------------------------------------\n// Active formats\n// ---------------------------------------------------------------------------\n\nexport function extractActiveFormats(editor: Editor): FormatState {\n\treturn {\n\t\tbold: editor.isActive('bold'),\n\t\titalic: editor.isActive('italic'),\n\t\tunderline: editor.isActive('underline'),\n\t\tstrike: editor.isActive('strike'),\n\t\tbulletList: editor.isActive('bulletList'),\n\t\torderedList: editor.isActive('orderedList'),\n\t\tblockquote: editor.isActive('blockquote'),\n\t\tcodeBlock: editor.isActive('codeBlock'),\n\t\tlink: (() => {\n\t\t\tif (editor.isActive('link')) {\n\t\t\t\treturn { href: editor.getAttributes('link')['href'] ?? '' };\n\t\t\t}\n\t\t\tconst { $from } = editor.state.selection;\n\t\t\tif ($from.pos > 0) {\n\t\t\t\tconst before = $from.doc.resolve($from.pos);\n\t\t\t\tconst linkMark = before.marks().find((m) => m.type.name === 'link');\n\t\t\t\tif (!linkMark) {\n\t\t\t\t\tconst nodeBefore = $from.nodeBefore;\n\t\t\t\t\tconst markOnPrev = nodeBefore?.marks.find(\n\t\t\t\t\t\t(m) => m.type.name === 'link',\n\t\t\t\t\t);\n\t\t\t\t\tif (markOnPrev) {\n\t\t\t\t\t\treturn { href: markOnPrev.attrs['href'] ?? '' };\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\treturn { href: linkMark.attrs['href'] ?? '' };\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t})(),\n\t\ttextAlign: editor.isActive({ textAlign: 'center' })\n\t\t\t? 'center'\n\t\t\t: editor.isActive({ textAlign: 'right' })\n\t\t\t? 'right'\n\t\t\t: editor.isActive({ textAlign: 'justify' })\n\t\t\t? 'justify'\n\t\t\t: editor.isActive({ textAlign: 'left' })\n\t\t\t? 'left'\n\t\t\t: null,\n\t\tfontFamily: editor.getAttributes('textStyle')['fontFamily'] ?? null,\n\t\tfontSize: editor.getAttributes('textStyle')['fontSize'] ?? null,\n\t\tcolor: editor.getAttributes('textStyle')['color'] ?? null,\n\t\thighlight: editor.isActive('highlight')\n\t\t\t? editor.getAttributes('highlight')['color'] ?? 'default'\n\t\t\t: null,\n\t\tsuperscript: editor.isActive('superscript'),\n\t\tsubscript: editor.isActive('subscript'),\n\t};\n}\n\nexport function extractContent(editor: Editor): EditorSnapshot {\n\treturn {\n\t\thtml: toPortableHtml(editor.getHTML()),\n\t\ttext: editor.getText(),\n\t\tisEmpty: editor.isEmpty,\n\t\tcharacterCount:\n\t\t\teditor.storage.characterCount?.characters?.() ?? editor.getText().length,\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// Section position helpers (used by insertAtSectionStart/End and appendBodyContent)\n// ---------------------------------------------------------------------------\n\n/**\n * Returns the ProseMirror position immediately after a section's opening divider\n * (i.e. the start of the section's own content).\n * For `'body'`, returns 1 (beginning of the document).\n * Returns -1 if the named section's divider is not found.\n */\nexport function findSectionStartPos(editor: Editor, sectionId: string): number {\n\tif (sectionId === 'body') return 1;\n\tlet startPos = -1;\n\teditor.state.doc.descendants((node, pos) => {\n\t\tif (startPos !== -1) return false;\n\t\tif (\n\t\t\tnode.type.name === 'sectionDivider' &&\n\t\t\tnode.attrs['sectionId'] === sectionId\n\t\t) {\n\t\t\tstartPos = pos + node.nodeSize; // position right after the divider\n\t\t}\n\t});\n\treturn startPos;\n}\n\n/**\n * Returns the ProseMirror position at the end of a named section's content:\n * - For `'body'`: position of the first section divider, or end of document.\n * - For a named section: position of the next divider, or end of document.\n */\nexport function findSectionEndPos(editor: Editor, sectionId: string): number {\n\tconst doc = editor.state.doc;\n\tconst docSize = doc.content.size;\n\n\tif (sectionId === 'body') {\n\t\tlet firstDividerPos = -1;\n\t\tdoc.descendants((node, pos) => {\n\t\t\tif (firstDividerPos !== -1) return false;\n\t\t\tif (node.type.name === 'sectionDivider') {\n\t\t\t\tfirstDividerPos = pos;\n\t\t\t}\n\t\t});\n\t\treturn firstDividerPos !== -1 ? firstDividerPos : docSize;\n\t}\n\n\tlet passedSection = false;\n\tlet nextDividerPos = -1;\n\tdoc.descendants((node, pos) => {\n\t\tif (nextDividerPos !== -1) return false;\n\t\tif (!passedSection) {\n\t\t\tif (\n\t\t\t\tnode.type.name === 'sectionDivider' &&\n\t\t\t\tnode.attrs['sectionId'] === sectionId\n\t\t\t) {\n\t\t\t\tpassedSection = true;\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\t\tif (node.type.name === 'sectionDivider') {\n\t\t\tnextDividerPos = pos;\n\t\t}\n\t});\n\treturn nextDividerPos !== -1 ? nextDividerPos : docSize;\n}\n"],"names":["normalizeHtml","html","replace","toPortableHtml","SECTION_DIVIDER_HTML","id","getBodyHtml","_a","extractAllSectionsFromHtml","get","sections","Map","dividerRegex","dividers","match","exec","push","index","endIndex","length","set","slice","i","start","end","extractSectionContent","editor","startPos","findSectionStartPos","text","isEmpty","characterCount","endPos","findSectionEndPos","state","doc","container","document","createElement","serializer","DOMSerializer","fromSchema","schema","appendChild","serializeFragment","content","innerHTML","textContent","trim","sectionId","descendants","node","pos","type","name","attrs","nodeSize","docSize","size","firstDividerPos","passedSection","nextDividerPos","body","s","bold","isActive","italic","underline","strike","bulletList","orderedList","blockquote","codeBlock","link","href","getAttributes","$from","selection","linkMark","resolve","marks","find","m","_c","nodeBefore","markOnPrev","_b","textAlign","fontFamily","fontSize","color","highlight","_d","superscript","subscript","getHTML","getText","storage","characters","substring","normalised","dom","DOMParser","parseSlice","from","to","tr","replaceRange","view","dispatch","dividerHtml","commands","insertContentAt","updateSelection","fragment","parse","parseHtmlToNodes","replaceFrom","replaceWith","setMeta"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@tiptap/extension-character-count"),n=require("@tiptap/extension-color"),t=require("@tiptap/extension-font-family"),i=require("@tiptap/extension-highlight"),o=require("@tiptap/extension-image"),r=require("@tiptap/extension-link"),a=require("@tiptap/extension-placeholder"),s=require("@tiptap/extension-subscript"),l=require("@tiptap/extension-superscript"),d=require("@tiptap/extension-text-align"),u=require("@tiptap/extension-text-style"),p=require("@tiptap/extension-underline"),c=require("@tiptap/starter-kit"),x=require("./FontSizeExtension.js"),m=require("./mention/MentionExtension.js"),f=require("./paste/PasteExtension.js"),h=require("./plainClipboard/
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@tiptap/extension-character-count"),n=require("@tiptap/extension-color"),t=require("@tiptap/extension-font-family"),i=require("@tiptap/extension-highlight"),o=require("@tiptap/extension-image"),r=require("@tiptap/extension-link"),a=require("@tiptap/extension-placeholder"),s=require("@tiptap/extension-subscript"),l=require("@tiptap/extension-superscript"),d=require("@tiptap/extension-text-align"),u=require("@tiptap/extension-text-style"),p=require("@tiptap/extension-underline"),c=require("@tiptap/starter-kit"),x=require("./FontSizeExtension.js"),m=require("./mention/MentionExtension.js"),f=require("./paste/PasteExtension.js"),h=require("./plainClipboard/ClipboardNormalizationExtension.js"),S=require("./plainClipboard/PlainClipboardExtension.js"),q=require("./sectionDivider/SectionDividerNode.js"),v=require("./sendShortcut/SendShortcutExtension.js"),b=require("./slashCommand/SlashCommandExtension.js"),g=require("./variable/VariableDecorationExtension.js");function E(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var C=E(e),M=E(n),j=E(t),k=E(i),P=E(o),y=E(r),D=E(a),T=E(s),w=E(l),z=E(d),I=E(p),N=E(c);exports.buildExtensions=function(e){var n,t,i,o,r,a,s,l,d;const p=null!==(t=null===(n=e.features)||void 0===n?void 0:n.richPaste)&&void 0!==t&&t,c=null!==(o=null===(i=e.features)||void 0===i?void 0:i.richTypography)&&void 0!==o&&o,E=null===(r=e.features)||void 0===r?void 0:r.allowedMarks,O=e=>!E||E.includes(e);return[...[N.default.configure({link:!1,underline:!1,bold:!!O("bold")&&{},italic:!!O("italic")&&{},strike:!!O("strike")&&{},code:!!O("code")&&{}}),...O("underline")?[I.default]:[],y.default.extend({addPasteRules:()=>[],addInputRules:()=>[]}).configure({openOnClick:!1,autolink:!1,linkOnPaste:!1,HTMLAttributes:{rel:"noopener noreferrer",class:"bik-link"}}),u.TextStyle,D.default.configure({placeholder:null!==(a=e.placeholder)&&void 0!==a?a:"Type a message..."}),...e.onPaste?[f.PasteExtension.configure({onPaste:e.onPaste})]:[],...p?[h.ClipboardNormalizationExtension]:[S.PlainClipboardExtension],v.SendShortcutExtension.configure({onSend:e.onSend,sendShortcut:e.sendShortcut,extraShortcuts:null!==(s=e.shortcuts)&&void 0!==s?s:[]}),g.VariableDecorationExtension,...e.maxCharacters?[C.default.configure({limit:e.maxCharacters})]:[],q.SectionDividerNode],...[...(null===(l=e.mentions)||void 0===l?void 0:l.agents)?[m.buildAgentMentionExtension(e.mentions.agents,e.onMentionSelected,e.renderMentionItem,e.renderMentionDropdown)]:[],...(null===(d=e.mentions)||void 0===d?void 0:d.teams)?[m.buildTeamMentionExtension(e.mentions.teams,e.onMentionSelected,e.renderMentionItem,e.renderMentionDropdown)]:[],...e.slashCommands?[b.buildSlashCommandExtension(e.slashCommands,e.onSlashCommandSelected,e.renderSlashCommandItem,e.renderSlashCommandDropdown)]:[]],...c?[M.default,k.default.configure({multicolor:!0}),j.default,x.FontSizeExtension,z.default.configure({types:["heading","paragraph"]}),T.default,w.default,P.default]:[M.default]]};
|
|
2
2
|
//# sourceMappingURL=buildExtensions.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildExtensions.js","sources":["../../../../src/editor/extensions/buildExtensions.ts"],"sourcesContent":["import CharacterCount from '@tiptap/extension-character-count';\nimport Color from '@tiptap/extension-color';\nimport FontFamily from '@tiptap/extension-font-family';\nimport Highlight from '@tiptap/extension-highlight';\nimport Image from '@tiptap/extension-image';\nimport Link from '@tiptap/extension-link';\nimport Placeholder from '@tiptap/extension-placeholder';\nimport Subscript from '@tiptap/extension-subscript';\nimport Superscript from '@tiptap/extension-superscript';\nimport TextAlign from '@tiptap/extension-text-align';\nimport { TextStyle } from '@tiptap/extension-text-style';\nimport Underline from '@tiptap/extension-underline';\nimport StarterKit from '@tiptap/starter-kit';\nimport type { ReactNode } from 'react';\nimport type {\n\tEditorFeatures,\n\tEditorSnapshot,\n\tKeyboardShortcut,\n\tMentionDropdownRenderProps,\n\tMentionItem,\n\tPasteData,\n\tSlashCommandDropdownRenderProps,\n\tSlashCommandItem,\n} from '../BikEditor.types';\nimport { FontSizeExtension } from './FontSizeExtension';\nimport {\n\tbuildAgentMentionExtension,\n\tbuildTeamMentionExtension,\n} from './mention/MentionExtension';\nimport { PasteExtension } from './paste/PasteExtension';\nimport { PlainClipboardExtension } from './plainClipboard/PlainClipboardExtension';\nimport { SectionDividerNode } from './sectionDivider/SectionDividerNode';\nimport { SendShortcutExtension } from './sendShortcut/SendShortcutExtension';\nimport { buildSlashCommandExtension } from './slashCommand/SlashCommandExtension';\nimport { VariableDecorationExtension } from './variable/VariableDecorationExtension';\n\ninterface ExtensionConfig {\n\tfeatures?: EditorFeatures;\n\tplaceholder?: string;\n\tmaxCharacters?: number;\n\thasSections?: boolean;\n\tmentions?: {\n\t\tagents?: { current: MentionItem[] };\n\t\tteams?: { current: MentionItem[] };\n\t};\n\tslashCommands?: { current: SlashCommandItem[] };\n\tonPaste?: (data: PasteData) => boolean | void;\n\tonSend?: (content: EditorSnapshot) => void;\n\tsendShortcut?:\n\t\t| { key: string; modifiers?: Array<'mod' | 'ctrl' | 'shift' | 'alt'> }\n\t\t| Array<{\n\t\t\t\tkey: string;\n\t\t\t\tmodifiers?: Array<'mod' | 'ctrl' | 'shift' | 'alt'>;\n\t\t }>;\n\tshortcuts?: KeyboardShortcut[];\n\tonMentionSelected?: (item: MentionItem, char: '@' | '#') => void;\n\tonSlashCommandSelected?: (command: SlashCommandItem) => void;\n\trenderMentionItem?: (item: MentionItem, isActive: boolean) => ReactNode;\n\trenderMentionDropdown?: (props: MentionDropdownRenderProps) => ReactNode;\n\trenderSlashCommandItem?: (\n\t\titem: SlashCommandItem,\n\t\tisActive: boolean,\n\t) => ReactNode;\n\trenderSlashCommandDropdown?: (\n\t\tprops: SlashCommandDropdownRenderProps,\n\t) => ReactNode;\n}\n\nexport function buildExtensions(config: ExtensionConfig) {\n\tconst hasRichPaste = config.features?.richPaste ?? false;\n\tconst hasRichTypography = config.features?.richTypography ?? false;\n\n\t// When allowedMarks is specified only those marks are registered in the schema.\n\t// This disables rendering, keyboard shortcuts AND paste-preservation for the\n\t// excluded marks — all three come for free when the extension is absent.\n\tconst allowedMarks = config.features?.allowedMarks;\n\tconst isMark = (m: 'bold' | 'italic' | 'strike' | 'underline' | 'code') =>\n\t\t!allowedMarks || allowedMarks.includes(m);\n\n\tconst base = [\n\t\t// Exclude Link and Underline from StarterKit — TipTap v3 bundles both.\n\t\t// Without this, two copies of each are registered and the StarterKit copy's\n\t\t// click handler calls window.open even when openOnClick: false is set.\n\t\tStarterKit.configure({\n\t\t\tlink: false,\n\t\t\tunderline: false,\n\t\t\tbold: isMark('bold') ? {} : false,\n\t\t\titalic: isMark('italic') ? {} : false,\n\t\t\tstrike: isMark('strike') ? {} : false,\n\t\t\tcode: isMark('code') ? {} : false,\n\t\t}),\n\t\t...(isMark('underline') ? [Underline] : []),\n\t\t// Extend Link to strip addPasteRules() and addInputRules() so pasting a\n\t\t// URL never creates a hyperlink regardless of autolink/linkOnPaste values.\n\t\tLink.extend({\n\t\t\taddPasteRules: () => [],\n\t\t\taddInputRules: () => [],\n\t\t}).configure({\n\t\t\topenOnClick: false,\n\t\t\tautolink: false,\n\t\t\tlinkOnPaste: false,\n\t\t\tHTMLAttributes: {\n\t\t\t\trel: 'noopener noreferrer',\n\t\t\t\tclass: 'bik-link',\n\t\t\t},\n\t\t}),\n\t\tTextStyle,\n\t\tPlaceholder.configure({\n\t\t\tplaceholder: config.placeholder ?? 'Type a message...',\n\t\t}),\n\t\t// Consumer paste callback runs first. If it returns true the event is\n\t\t// consumed and neither PlainClipboardExtension nor the editor's default\n\t\t// paste handling will run for that event.\n\t\t...(config.onPaste\n\t\t\t? [PasteExtension.configure({ onPaste: config.onPaste })]\n\t\t\t: []),\n\t\t//
|
|
1
|
+
{"version":3,"file":"buildExtensions.js","sources":["../../../../src/editor/extensions/buildExtensions.ts"],"sourcesContent":["import CharacterCount from '@tiptap/extension-character-count';\nimport Color from '@tiptap/extension-color';\nimport FontFamily from '@tiptap/extension-font-family';\nimport Highlight from '@tiptap/extension-highlight';\nimport Image from '@tiptap/extension-image';\nimport Link from '@tiptap/extension-link';\nimport Placeholder from '@tiptap/extension-placeholder';\nimport Subscript from '@tiptap/extension-subscript';\nimport Superscript from '@tiptap/extension-superscript';\nimport TextAlign from '@tiptap/extension-text-align';\nimport { TextStyle } from '@tiptap/extension-text-style';\nimport Underline from '@tiptap/extension-underline';\nimport StarterKit from '@tiptap/starter-kit';\nimport type { ReactNode } from 'react';\nimport type {\n\tEditorFeatures,\n\tEditorSnapshot,\n\tKeyboardShortcut,\n\tMentionDropdownRenderProps,\n\tMentionItem,\n\tPasteData,\n\tSlashCommandDropdownRenderProps,\n\tSlashCommandItem,\n} from '../BikEditor.types';\nimport { FontSizeExtension } from './FontSizeExtension';\nimport {\n\tbuildAgentMentionExtension,\n\tbuildTeamMentionExtension,\n} from './mention/MentionExtension';\nimport { PasteExtension } from './paste/PasteExtension';\nimport { ClipboardNormalizationExtension } from './plainClipboard/ClipboardNormalizationExtension';\nimport { PlainClipboardExtension } from './plainClipboard/PlainClipboardExtension';\nimport { SectionDividerNode } from './sectionDivider/SectionDividerNode';\nimport { SendShortcutExtension } from './sendShortcut/SendShortcutExtension';\nimport { buildSlashCommandExtension } from './slashCommand/SlashCommandExtension';\nimport { VariableDecorationExtension } from './variable/VariableDecorationExtension';\n\ninterface ExtensionConfig {\n\tfeatures?: EditorFeatures;\n\tplaceholder?: string;\n\tmaxCharacters?: number;\n\thasSections?: boolean;\n\tmentions?: {\n\t\tagents?: { current: MentionItem[] };\n\t\tteams?: { current: MentionItem[] };\n\t};\n\tslashCommands?: { current: SlashCommandItem[] };\n\tonPaste?: (data: PasteData) => boolean | void;\n\tonSend?: (content: EditorSnapshot) => void;\n\tsendShortcut?:\n\t\t| { key: string; modifiers?: Array<'mod' | 'ctrl' | 'shift' | 'alt'> }\n\t\t| Array<{\n\t\t\t\tkey: string;\n\t\t\t\tmodifiers?: Array<'mod' | 'ctrl' | 'shift' | 'alt'>;\n\t\t }>;\n\tshortcuts?: KeyboardShortcut[];\n\tonMentionSelected?: (item: MentionItem, char: '@' | '#') => void;\n\tonSlashCommandSelected?: (command: SlashCommandItem) => void;\n\trenderMentionItem?: (item: MentionItem, isActive: boolean) => ReactNode;\n\trenderMentionDropdown?: (props: MentionDropdownRenderProps) => ReactNode;\n\trenderSlashCommandItem?: (\n\t\titem: SlashCommandItem,\n\t\tisActive: boolean,\n\t) => ReactNode;\n\trenderSlashCommandDropdown?: (\n\t\tprops: SlashCommandDropdownRenderProps,\n\t) => ReactNode;\n}\n\nexport function buildExtensions(config: ExtensionConfig) {\n\tconst hasRichPaste = config.features?.richPaste ?? false;\n\tconst hasRichTypography = config.features?.richTypography ?? false;\n\n\t// When allowedMarks is specified only those marks are registered in the schema.\n\t// This disables rendering, keyboard shortcuts AND paste-preservation for the\n\t// excluded marks — all three come for free when the extension is absent.\n\tconst allowedMarks = config.features?.allowedMarks;\n\tconst isMark = (m: 'bold' | 'italic' | 'strike' | 'underline' | 'code') =>\n\t\t!allowedMarks || allowedMarks.includes(m);\n\n\tconst base = [\n\t\t// Exclude Link and Underline from StarterKit — TipTap v3 bundles both.\n\t\t// Without this, two copies of each are registered and the StarterKit copy's\n\t\t// click handler calls window.open even when openOnClick: false is set.\n\t\tStarterKit.configure({\n\t\t\tlink: false,\n\t\t\tunderline: false,\n\t\t\tbold: isMark('bold') ? {} : false,\n\t\t\titalic: isMark('italic') ? {} : false,\n\t\t\tstrike: isMark('strike') ? {} : false,\n\t\t\tcode: isMark('code') ? {} : false,\n\t\t}),\n\t\t...(isMark('underline') ? [Underline] : []),\n\t\t// Extend Link to strip addPasteRules() and addInputRules() so pasting a\n\t\t// URL never creates a hyperlink regardless of autolink/linkOnPaste values.\n\t\tLink.extend({\n\t\t\taddPasteRules: () => [],\n\t\t\taddInputRules: () => [],\n\t\t}).configure({\n\t\t\topenOnClick: false,\n\t\t\tautolink: false,\n\t\t\tlinkOnPaste: false,\n\t\t\tHTMLAttributes: {\n\t\t\t\trel: 'noopener noreferrer',\n\t\t\t\tclass: 'bik-link',\n\t\t\t},\n\t\t}),\n\t\tTextStyle,\n\t\tPlaceholder.configure({\n\t\t\tplaceholder: config.placeholder ?? 'Type a message...',\n\t\t}),\n\t\t// Consumer paste callback runs first. If it returns true the event is\n\t\t// consumed and neither PlainClipboardExtension nor the editor's default\n\t\t// paste handling will run for that event.\n\t\t...(config.onPaste\n\t\t\t? [PasteExtension.configure({ onPaste: config.onPaste })]\n\t\t\t: []),\n\t\t// Non-rich editors: strip rich marks + normalize blanks on paste.\n\t\t// Rich editors (email): only normalize blanks (fix Google Docs spacing).\n\t\t...(!hasRichPaste\n\t\t\t? [PlainClipboardExtension]\n\t\t\t: [ClipboardNormalizationExtension]),\n\t\tSendShortcutExtension.configure({\n\t\t\tonSend: config.onSend,\n\t\t\tsendShortcut: config.sendShortcut,\n\t\t\textraShortcuts: config.shortcuts ?? [],\n\t\t}),\n\t\tVariableDecorationExtension,\n\t\t...(config.maxCharacters\n\t\t\t? [CharacterCount.configure({ limit: config.maxCharacters })]\n\t\t\t: []),\n\t\t// Always register SectionDividerNode so the custom <div data-section-divider>\n\t\t// node is part of the schema in every editor instance. This means imperative\n\t\t// callers (setBodyAndSections / setSectionContent) work even when no\n\t\t// `sections` prop was provided at mount time.\n\t\tSectionDividerNode,\n\t];\n\n\tconst mentionExtensions = [\n\t\t...(config.mentions?.agents\n\t\t\t? [\n\t\t\t\t\tbuildAgentMentionExtension(\n\t\t\t\t\t\tconfig.mentions.agents,\n\t\t\t\t\t\tconfig.onMentionSelected,\n\t\t\t\t\t\tconfig.renderMentionItem,\n\t\t\t\t\t\tconfig.renderMentionDropdown,\n\t\t\t\t\t),\n\t\t\t ]\n\t\t\t: []),\n\t\t...(config.mentions?.teams\n\t\t\t? [\n\t\t\t\t\tbuildTeamMentionExtension(\n\t\t\t\t\t\tconfig.mentions.teams,\n\t\t\t\t\t\tconfig.onMentionSelected,\n\t\t\t\t\t\tconfig.renderMentionItem,\n\t\t\t\t\t\tconfig.renderMentionDropdown,\n\t\t\t\t\t),\n\t\t\t ]\n\t\t\t: []),\n\t\t...(config.slashCommands\n\t\t\t? [\n\t\t\t\t\tbuildSlashCommandExtension(\n\t\t\t\t\t\tconfig.slashCommands,\n\t\t\t\t\t\tconfig.onSlashCommandSelected,\n\t\t\t\t\t\tconfig.renderSlashCommandItem,\n\t\t\t\t\t\tconfig.renderSlashCommandDropdown,\n\t\t\t\t\t),\n\t\t\t ]\n\t\t\t: []),\n\t];\n\n\tconst richExtensions = hasRichTypography\n\t\t? [\n\t\t\t\tColor,\n\t\t\t\tHighlight.configure({ multicolor: true }),\n\t\t\t\tFontFamily,\n\t\t\t\tFontSizeExtension,\n\t\t\t\tTextAlign.configure({ types: ['heading', 'paragraph'] }),\n\t\t\t\tSubscript,\n\t\t\t\tSuperscript,\n\t\t\t\tImage,\n\t\t ]\n\t\t: [Color];\n\n\treturn [...base, ...mentionExtensions, ...richExtensions];\n}\n"],"names":["config","hasRichPaste","_b","_a","features","richPaste","hasRichTypography","_d","_c","richTypography","allowedMarks","_e","isMark","m","includes","StarterKit","configure","link","underline","bold","italic","strike","code","Underline","Link","extend","addPasteRules","addInputRules","openOnClick","autolink","linkOnPaste","HTMLAttributes","rel","class","TextStyle","Placeholder","placeholder","_f","onPaste","PasteExtension","ClipboardNormalizationExtension","PlainClipboardExtension","SendShortcutExtension","onSend","sendShortcut","extraShortcuts","_g","shortcuts","VariableDecorationExtension","maxCharacters","CharacterCount","limit","SectionDividerNode","_h","mentions","agents","buildAgentMentionExtension","onMentionSelected","renderMentionItem","renderMentionDropdown","_j","teams","buildTeamMentionExtension","slashCommands","buildSlashCommandExtension","onSlashCommandSelected","renderSlashCommandItem","renderSlashCommandDropdown","Color","Highlight","multicolor","FontFamily","FontSizeExtension","TextAlign","types","Subscript","Superscript","Image"],"mappings":"mtCAqEM,SAA0BA,yBAC/B,MAAMC,EAA6C,QAA9BC,EAAiB,QAAjBC,EAAAH,EAAOI,gBAAU,IAAAD,OAAA,EAAAA,EAAAE,iBAAa,IAAAH,GAAAA,EAC7CI,EAAuD,QAAnCC,EAAiB,QAAjBC,EAAAR,EAAOI,gBAAU,IAAAI,OAAA,EAAAA,EAAAC,sBAAkB,IAAAF,GAAAA,EAKvDG,EAA8B,QAAfC,EAAAX,EAAOI,gBAAQ,IAAAO,OAAA,EAAAA,EAAED,aAChCE,EAAUC,IACdH,GAAgBA,EAAaI,SAASD,GA0GxC,MAAO,IAxGM,CAIZE,EAAAA,QAAWC,UAAU,CACpBC,MAAM,EACNC,WAAW,EACXC,OAAMP,EAAO,SAAU,CAAE,EACzBQ,SAAQR,EAAO,WAAY,CAAE,EAC7BS,SAAQT,EAAO,WAAY,CAAE,EAC7BU,OAAMV,EAAO,SAAU,CAAE,OAEtBA,EAAO,aAAe,CAACW,EAAAA,SAAa,GAGxCC,EAAAA,QAAKC,OAAO,CACXC,cAAeA,IAAM,GACrBC,cAAeA,IAAM,KACnBX,UAAU,CACZY,aAAa,EACbC,UAAU,EACVC,aAAa,EACbC,eAAgB,CACfC,IAAK,sBACLC,MAAO,cAGTC,EAAAA,UACAC,EAAW,QAACnB,UAAU,CACrBoB,oBAAaC,EAAArC,EAAOoC,2BAAe,yBAKhCpC,EAAOsC,QACR,CAACC,EAAAA,eAAevB,UAAU,CAAEsB,QAAStC,EAAOsC,WAC5C,MAGErC,EAEF,CAACuC,EAAAA,iCADD,CAACC,2BAEJC,EAAqBA,sBAAC1B,UAAU,CAC/B2B,OAAQ3C,EAAO2C,OACfC,aAAc5C,EAAO4C,aACrBC,uBAAgBC,EAAA9C,EAAO+C,yBAAa,KAErCC,EAA2BA,+BACvBhD,EAAOiD,cACR,CAACC,EAAc,QAAClC,UAAU,CAAEmC,MAAOnD,EAAOiD,iBAC1C,GAKHG,EAAAA,uBAGyB,aACrBC,EAAArD,EAAOsD,+BAAUC,QAClB,CACAC,6BACCxD,EAAOsD,SAASC,OAChBvD,EAAOyD,kBACPzD,EAAO0D,kBACP1D,EAAO2D,wBAGR,eACCC,EAAA5D,EAAOsD,+BAAUO,OAClB,CACAC,EAAyBA,0BACxB9D,EAAOsD,SAASO,MAChB7D,EAAOyD,kBACPzD,EAAO0D,kBACP1D,EAAO2D,wBAGR,MACC3D,EAAO+D,cACR,CACAC,EAAAA,2BACChE,EAAO+D,cACP/D,EAAOiE,uBACPjE,EAAOkE,uBACPlE,EAAOmE,6BAGR,OAGmB7D,EACpB,CACA8D,EAAAA,QACAC,EAAAA,QAAUrD,UAAU,CAAEsD,YAAY,IAClCC,EAAU,QACVC,oBACAC,EAAAA,QAAUzD,UAAU,CAAE0D,MAAO,CAAC,UAAW,eACzCC,EAAS,QACTC,EAAW,QACXC,EAAK,SAEL,CAACT,EAAK,SAGV"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("../../../node_modules/@tiptap/core/dist/index.js"),t=require("@tiptap/extension-mention"),n=require("@tiptap/react"),r=require("../suggestionPopup.js"),o=require("./MentionDropdown.js");function i(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var s=i(t);function a(e){let t=arguments.length>2?arguments[2]:void 0,i=arguments.length>3?arguments[3]:void 0;return()=>{let e,s;return{onStart:a=>{e=new n.ReactRenderer(o.MentionDropdown,{props:Object.assign(Object.assign({},a),{renderItem:t,renderDropdown:i}),editor:a.editor}),s=r.createSuggestionPopup(e.element,a.clientRect)},onUpdate:n=>{var r;e.updateProps(Object.assign(Object.assign({},n),{renderItem:t,renderDropdown:i})),(null===(r=n.items)||void 0===r?void 0:r.length)?(s.show(),s.updatePosition(n.clientRect)):s.hide()},onKeyDown:t=>{var n,r;return"Escape"===t.event.key?(s.hide(),!0):null!==(r=null===(n=e.ref)||void 0===n?void 0:n.onKeyDown(t))&&void 0!==r&&r},onExit:()=>{s.destroy(),e.destroy()}}}}exports.buildAgentMentionExtension=function(t,n,r,o){return s.default.extend({name:"mentionAgent"}).configure({HTMLAttributes:{class:"bik-mention bik-mention--agent"},renderText:e=>{let{options:t,node:n}=e;return`${t.suggestion.char}${n.attrs.label}`},renderHTML:t=>{let{options:n,node:r}=t;return["span",e.mergeAttributes(n.HTMLAttributes),`${n.suggestion.char}${r.attrs.label}`]},suggestion:{char:"@",items:e=>{let{query:n}=e;return t.current.filter((e=>e.label.toLowerCase().includes(n.toLowerCase())))},command:e=>{let{editor:t,range:r,props:o}=e;t.chain().focus().deleteRange(r).insertContent({type:"mentionAgent",attrs:{id:o.id,label:o.label}}).run(),null==n||n(o,"@")},render:a(n,"@",r,o)}})},exports.buildTeamMentionExtension=function(t,n,r,o){return s.default.extend({name:"mentionTeam"}).configure({HTMLAttributes:{class:"bik-mention bik-mention--team"},renderText:e=>{let{options:t,node:n}=e;return`${t.suggestion.char}${n.attrs.label}`},renderHTML:t=>{let{options:n,node:r}=t;return["span",e.mergeAttributes(n.HTMLAttributes),`${n.suggestion.char}${r.attrs.label}`]},suggestion:{char:"#",items:e=>{let{query:n}=e;return t.current.filter((e=>e.label.toLowerCase().includes(n.toLowerCase())))},command:e=>{let{editor:t,range:r,props:o}=e;t.chain().focus().deleteRange(r).insertContent({type:"mentionTeam",attrs:{id:o.id,label:o.label}}).run(),null==n||n(o,"#")},render:a(n,"#",r,o)}})};
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("../../../node_modules/@tiptap/core/dist/index.js"),t=require("@tiptap/extension-mention"),n=require("@tiptap/react"),r=require("../suggestionPopup.js"),o=require("./MentionDropdown.js");function i(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var s=i(t);function a(e){let t=arguments.length>2?arguments[2]:void 0,i=arguments.length>3?arguments[3]:void 0;return()=>{let e,s;return{onStart:a=>{e=new n.ReactRenderer(o.MentionDropdown,{props:Object.assign(Object.assign({},a),{renderItem:t,renderDropdown:i}),editor:a.editor}),s=r.createSuggestionPopup(e.element,a.clientRect)},onUpdate:n=>{var r;e.updateProps(Object.assign(Object.assign({},n),{renderItem:t,renderDropdown:i})),(null===(r=n.items)||void 0===r?void 0:r.length)?(s.show(),s.updatePosition(n.clientRect)):s.hide()},onKeyDown:t=>{var n,r;return"Escape"===t.event.key?(s.hide(),!0):null!==(r=null===(n=e.ref)||void 0===n?void 0:n.onKeyDown(t))&&void 0!==r&&r},onExit:()=>{s.destroy(),e.destroy()}}}}exports.buildAgentMentionExtension=function(t,n,r,o){return s.default.extend({name:"mentionAgent"}).configure({HTMLAttributes:{class:"bik-mention bik-mention--agent"},renderText:e=>{let{options:t,node:n}=e;return`${t.suggestion.char}${n.attrs.label}`},renderHTML:t=>{let{options:n,node:r}=t;return["span",e.mergeAttributes(n.HTMLAttributes),`${n.suggestion.char}${r.attrs.label}`]},suggestion:{char:"@",allowSpaces:!0,items:e=>{let{query:n}=e;return t.current.filter((e=>e.label.toLowerCase().includes(n.toLowerCase())))},command:e=>{let{editor:t,range:r,props:o}=e;t.chain().focus().deleteRange(r).insertContent({type:"mentionAgent",attrs:{id:o.id,label:o.label}}).run(),null==n||n(o,"@")},render:a(n,"@",r,o)}})},exports.buildTeamMentionExtension=function(t,n,r,o){return s.default.extend({name:"mentionTeam"}).configure({HTMLAttributes:{class:"bik-mention bik-mention--team"},renderText:e=>{let{options:t,node:n}=e;return`${t.suggestion.char}${n.attrs.label}`},renderHTML:t=>{let{options:n,node:r}=t;return["span",e.mergeAttributes(n.HTMLAttributes),`${n.suggestion.char}${r.attrs.label}`]},suggestion:{char:"#",allowSpaces:!0,items:e=>{let{query:n}=e;return t.current.filter((e=>e.label.toLowerCase().includes(n.toLowerCase())))},command:e=>{let{editor:t,range:r,props:o}=e;t.chain().focus().deleteRange(r).insertContent({type:"mentionTeam",attrs:{id:o.id,label:o.label}}).run(),null==n||n(o,"#")},render:a(n,"#",r,o)}})};
|
|
2
2
|
//# sourceMappingURL=MentionExtension.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MentionExtension.js","sources":["../../../../../src/editor/extensions/mention/MentionExtension.ts"],"sourcesContent":["import { mergeAttributes } from '@tiptap/core';\nimport Mention from '@tiptap/extension-mention';\nimport { ReactRenderer } from '@tiptap/react';\nimport type { ReactNode } from 'react';\nimport type {\n\tMentionDropdownRenderProps,\n\tMentionItem,\n} from '../../BikEditor.types';\nimport {\n\tcreateSuggestionPopup,\n\ttype SuggestionPopup,\n} from '../suggestionPopup';\nimport { MentionDropdown } from './MentionDropdown';\n\nfunction buildRender(\n\tonSelect?: (item: MentionItem, char: '@' | '#') => void,\n\tchar: '@' | '#' = '@',\n\trenderItem?: (item: MentionItem, isActive: boolean) => ReactNode,\n\trenderDropdown?: (props: MentionDropdownRenderProps) => ReactNode,\n) {\n\treturn () => {\n\t\tlet component: ReactRenderer;\n\t\tlet popup: SuggestionPopup;\n\n\t\treturn {\n\t\t\tonStart: (props: any) => {\n\t\t\t\tcomponent = new ReactRenderer(MentionDropdown, {\n\t\t\t\t\tprops: { ...props, renderItem, renderDropdown },\n\t\t\t\t\teditor: props.editor,\n\t\t\t\t});\n\t\t\t\tpopup = createSuggestionPopup(component.element, props.clientRect);\n\t\t\t},\n\t\t\tonUpdate: (props: any) => {\n\t\t\t\tcomponent.updateProps({ ...props, renderItem, renderDropdown });\n\t\t\t\tif (!props.items?.length) {\n\t\t\t\t\tpopup.hide();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tpopup.show();\n\t\t\t\tpopup.updatePosition(props.clientRect);\n\t\t\t},\n\t\t\tonKeyDown: (props: any) => {\n\t\t\t\tif (props.event.key === 'Escape') {\n\t\t\t\t\tpopup.hide();\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\treturn (component.ref as any)?.onKeyDown(props) ?? false;\n\t\t\t},\n\t\t\tonExit: () => {\n\t\t\t\tpopup.destroy();\n\t\t\t\tcomponent.destroy();\n\t\t\t},\n\t\t};\n\t};\n}\n\nexport function buildAgentMentionExtension(\n\tagentsRef: { current: MentionItem[] },\n\tonSelect?: (item: MentionItem, char: '@' | '#') => void,\n\trenderItem?: (item: MentionItem, isActive: boolean) => ReactNode,\n\trenderDropdown?: (props: MentionDropdownRenderProps) => ReactNode,\n) {\n\treturn Mention.extend({ name: 'mentionAgent' }).configure({\n\t\tHTMLAttributes: { class: 'bik-mention bik-mention--agent' },\n\t\trenderText: ({ options, node }) =>\n\t\t\t`${options.suggestion.char}${node.attrs['label']}`,\n\t\trenderHTML: ({ options, node }) => [\n\t\t\t'span',\n\t\t\tmergeAttributes(options.HTMLAttributes),\n\t\t\t`${options.suggestion.char}${node.attrs['label']}`,\n\t\t],\n\t\tsuggestion: {\n\t\t\tchar: '@',\n\t\t\titems: ({ query }: { query: string }) =>\n\t\t\t\tagentsRef.current.filter((a) =>\n\t\t\t\t\ta.label.toLowerCase().includes(query.toLowerCase()),\n\t\t\t\t),\n\t\t\tcommand: ({ editor, range, props }: any) => {\n\t\t\t\teditor\n\t\t\t\t\t.chain()\n\t\t\t\t\t.focus()\n\t\t\t\t\t.deleteRange(range)\n\t\t\t\t\t.insertContent({\n\t\t\t\t\t\ttype: 'mentionAgent',\n\t\t\t\t\t\tattrs: { id: props.id, label: props.label },\n\t\t\t\t\t})\n\t\t\t\t\t.run();\n\t\t\t\tonSelect?.(props, '@');\n\t\t\t},\n\t\t\trender: buildRender(onSelect, '@', renderItem, renderDropdown),\n\t\t},\n\t});\n}\n\nexport function buildTeamMentionExtension(\n\tteamsRef: { current: MentionItem[] },\n\tonSelect?: (item: MentionItem, char: '@' | '#') => void,\n\trenderItem?: (item: MentionItem, isActive: boolean) => ReactNode,\n\trenderDropdown?: (props: MentionDropdownRenderProps) => ReactNode,\n) {\n\treturn Mention.extend({ name: 'mentionTeam' }).configure({\n\t\tHTMLAttributes: { class: 'bik-mention bik-mention--team' },\n\t\trenderText: ({ options, node }) =>\n\t\t\t`${options.suggestion.char}${node.attrs['label']}`,\n\t\trenderHTML: ({ options, node }) => [\n\t\t\t'span',\n\t\t\tmergeAttributes(options.HTMLAttributes),\n\t\t\t`${options.suggestion.char}${node.attrs['label']}`,\n\t\t],\n\t\tsuggestion: {\n\t\t\tchar: '#',\n\t\t\titems: ({ query }: { query: string }) =>\n\t\t\t\tteamsRef.current.filter((t) =>\n\t\t\t\t\tt.label.toLowerCase().includes(query.toLowerCase()),\n\t\t\t\t),\n\t\t\tcommand: ({ editor, range, props }: any) => {\n\t\t\t\teditor\n\t\t\t\t\t.chain()\n\t\t\t\t\t.focus()\n\t\t\t\t\t.deleteRange(range)\n\t\t\t\t\t.insertContent({\n\t\t\t\t\t\ttype: 'mentionTeam',\n\t\t\t\t\t\tattrs: { id: props.id, label: props.label },\n\t\t\t\t\t})\n\t\t\t\t\t.run();\n\t\t\t\tonSelect?.(props, '#');\n\t\t\t},\n\t\t\trender: buildRender(onSelect, '#', renderItem, renderDropdown),\n\t\t},\n\t});\n}\n"],"names":["buildRender","onSelect","renderItem","arguments","length","undefined","renderDropdown","component","popup","onStart","props","ReactRenderer","MentionDropdown","editor","createSuggestionPopup","element","clientRect","onUpdate","updateProps","Object","assign","_a","items","show","updatePosition","hide","onKeyDown","event","key","_b","ref","onExit","destroy","agentsRef","Mention","extend","name","configure","HTMLAttributes","class","renderText","_ref","options","node","suggestion","char","attrs","renderHTML","_ref2","mergeAttributes","_ref3","query","current","filter","a","label","toLowerCase","includes","command","_ref4","range","chain","focus","deleteRange","insertContent","type","id","run","render","teamsRef","_ref5","_ref6","_ref7","t","_ref8"],"mappings":"gWAcA,SAASA,EACRC,GACqB,IACrBC,EAAgEC,UAAAC,OAAAD,EAAAA,kBAAAE,EAChEC,EAAiEH,UAAAC,OAAAD,EAAAA,kBAAAE,EAEjE,MAAO,KACN,IAAIE,EACAC,EAEJ,MAAO,CACNC,QAAUC,IACTH,EAAY,IAAII,EAAaA,cAACC,kBAAiB,CAC9CF,qCAAYA,GAAK,CAAER,aAAYI,mBAC/BO,OAAQH,EAAMG,SAEfL,EAAQM,EAAqBA,sBAACP,EAAUQ,QAASL,EAAMM,WAAW,EAEnEC,SAAWP,UACVH,EAAUW,YAAiBC,OAAAC,OAAAD,OAAAC,OAAA,CAAA,EAAAV,IAAOR,aAAYI,qBAC9B,QAAXe,EAAAX,EAAMY,aAAK,IAAAD,OAAA,EAAAA,EAAEjB,SAIlBI,EAAMe,OACNf,EAAMgB,eAAed,EAAMM,aAJ1BR,EAAMiB,MAI+B,EAEvCC,UAAYhB,YACX,MAAwB,WAApBA,EAAMiB,MAAMC,KACfpB,EAAMiB,QACC,GAE2C,QAA5CI,EAAsB,QAAtBR,EAACd,EAAUuB,WAAW,IAAAT,OAAA,EAAAA,EAAEK,UAAUhB,UAAU,IAAAmB,GAAAA,CAAK,EAEzDE,OAAQA,KACPvB,EAAMwB,UACNzB,EAAUyB,SAAS,EAEpB,CAEH,oCAEM,SACLC,EACAhC,EACAC,EACAI,GAEA,OAAO4B,EAAAA,QAAQC,OAAO,CAAEC,KAAM,iBAAkBC,UAAU,CACzDC,eAAgB,CAAEC,MAAO,kCACzBC,WAAYC,IAAA,IAACC,QAAEA,EAAOC,KAAEA,GAAMF,EAAA,MAC7B,GAAGC,EAAQE,WAAWC,OAAOF,EAAKG,MAAa,OAAG,EACnDC,WAAYC,IAAA,IAACN,QAAEA,EAAOC,KAAEA,GAAMK,EAAA,MAAK,CAClC,OACAC,EAAeA,gBAACP,EAAQJ,gBACxB,GAAGI,EAAQE,WAAWC,OAAOF,EAAKG,MAAa,QAC/C,EACDF,WAAY,CACXC,KAAM,
|
|
1
|
+
{"version":3,"file":"MentionExtension.js","sources":["../../../../../src/editor/extensions/mention/MentionExtension.ts"],"sourcesContent":["import { mergeAttributes } from '@tiptap/core';\nimport Mention from '@tiptap/extension-mention';\nimport { ReactRenderer } from '@tiptap/react';\nimport type { ReactNode } from 'react';\nimport type {\n\tMentionDropdownRenderProps,\n\tMentionItem,\n} from '../../BikEditor.types';\nimport {\n\tcreateSuggestionPopup,\n\ttype SuggestionPopup,\n} from '../suggestionPopup';\nimport { MentionDropdown } from './MentionDropdown';\n\nfunction buildRender(\n\tonSelect?: (item: MentionItem, char: '@' | '#') => void,\n\tchar: '@' | '#' = '@',\n\trenderItem?: (item: MentionItem, isActive: boolean) => ReactNode,\n\trenderDropdown?: (props: MentionDropdownRenderProps) => ReactNode,\n) {\n\treturn () => {\n\t\tlet component: ReactRenderer;\n\t\tlet popup: SuggestionPopup;\n\n\t\treturn {\n\t\t\tonStart: (props: any) => {\n\t\t\t\tcomponent = new ReactRenderer(MentionDropdown, {\n\t\t\t\t\tprops: { ...props, renderItem, renderDropdown },\n\t\t\t\t\teditor: props.editor,\n\t\t\t\t});\n\t\t\t\tpopup = createSuggestionPopup(component.element, props.clientRect);\n\t\t\t},\n\t\t\tonUpdate: (props: any) => {\n\t\t\t\tcomponent.updateProps({ ...props, renderItem, renderDropdown });\n\t\t\t\tif (!props.items?.length) {\n\t\t\t\t\tpopup.hide();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tpopup.show();\n\t\t\t\tpopup.updatePosition(props.clientRect);\n\t\t\t},\n\t\t\tonKeyDown: (props: any) => {\n\t\t\t\tif (props.event.key === 'Escape') {\n\t\t\t\t\tpopup.hide();\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\treturn (component.ref as any)?.onKeyDown(props) ?? false;\n\t\t\t},\n\t\t\tonExit: () => {\n\t\t\t\tpopup.destroy();\n\t\t\t\tcomponent.destroy();\n\t\t\t},\n\t\t};\n\t};\n}\n\nexport function buildAgentMentionExtension(\n\tagentsRef: { current: MentionItem[] },\n\tonSelect?: (item: MentionItem, char: '@' | '#') => void,\n\trenderItem?: (item: MentionItem, isActive: boolean) => ReactNode,\n\trenderDropdown?: (props: MentionDropdownRenderProps) => ReactNode,\n) {\n\treturn Mention.extend({ name: 'mentionAgent' }).configure({\n\t\tHTMLAttributes: { class: 'bik-mention bik-mention--agent' },\n\t\trenderText: ({ options, node }) =>\n\t\t\t`${options.suggestion.char}${node.attrs['label']}`,\n\t\trenderHTML: ({ options, node }) => [\n\t\t\t'span',\n\t\t\tmergeAttributes(options.HTMLAttributes),\n\t\t\t`${options.suggestion.char}${node.attrs['label']}`,\n\t\t],\n\t\tsuggestion: {\n\t\t\tchar: '@',\n\t\t\tallowSpaces: true,\n\t\t\titems: ({ query }: { query: string }) =>\n\t\t\t\tagentsRef.current.filter((a) =>\n\t\t\t\t\ta.label.toLowerCase().includes(query.toLowerCase()),\n\t\t\t\t),\n\t\t\tcommand: ({ editor, range, props }: any) => {\n\t\t\t\teditor\n\t\t\t\t\t.chain()\n\t\t\t\t\t.focus()\n\t\t\t\t\t.deleteRange(range)\n\t\t\t\t\t.insertContent({\n\t\t\t\t\t\ttype: 'mentionAgent',\n\t\t\t\t\t\tattrs: { id: props.id, label: props.label },\n\t\t\t\t\t})\n\t\t\t\t\t.run();\n\t\t\t\tonSelect?.(props, '@');\n\t\t\t},\n\t\t\trender: buildRender(onSelect, '@', renderItem, renderDropdown),\n\t\t},\n\t});\n}\n\nexport function buildTeamMentionExtension(\n\tteamsRef: { current: MentionItem[] },\n\tonSelect?: (item: MentionItem, char: '@' | '#') => void,\n\trenderItem?: (item: MentionItem, isActive: boolean) => ReactNode,\n\trenderDropdown?: (props: MentionDropdownRenderProps) => ReactNode,\n) {\n\treturn Mention.extend({ name: 'mentionTeam' }).configure({\n\t\tHTMLAttributes: { class: 'bik-mention bik-mention--team' },\n\t\trenderText: ({ options, node }) =>\n\t\t\t`${options.suggestion.char}${node.attrs['label']}`,\n\t\trenderHTML: ({ options, node }) => [\n\t\t\t'span',\n\t\t\tmergeAttributes(options.HTMLAttributes),\n\t\t\t`${options.suggestion.char}${node.attrs['label']}`,\n\t\t],\n\t\tsuggestion: {\n\t\t\tchar: '#',\n\t\t\tallowSpaces: true,\n\t\t\titems: ({ query }: { query: string }) =>\n\t\t\t\tteamsRef.current.filter((t) =>\n\t\t\t\t\tt.label.toLowerCase().includes(query.toLowerCase()),\n\t\t\t\t),\n\t\t\tcommand: ({ editor, range, props }: any) => {\n\t\t\t\teditor\n\t\t\t\t\t.chain()\n\t\t\t\t\t.focus()\n\t\t\t\t\t.deleteRange(range)\n\t\t\t\t\t.insertContent({\n\t\t\t\t\t\ttype: 'mentionTeam',\n\t\t\t\t\t\tattrs: { id: props.id, label: props.label },\n\t\t\t\t\t})\n\t\t\t\t\t.run();\n\t\t\t\tonSelect?.(props, '#');\n\t\t\t},\n\t\t\trender: buildRender(onSelect, '#', renderItem, renderDropdown),\n\t\t},\n\t});\n}\n"],"names":["buildRender","onSelect","renderItem","arguments","length","undefined","renderDropdown","component","popup","onStart","props","ReactRenderer","MentionDropdown","editor","createSuggestionPopup","element","clientRect","onUpdate","updateProps","Object","assign","_a","items","show","updatePosition","hide","onKeyDown","event","key","_b","ref","onExit","destroy","agentsRef","Mention","extend","name","configure","HTMLAttributes","class","renderText","_ref","options","node","suggestion","char","attrs","renderHTML","_ref2","mergeAttributes","allowSpaces","_ref3","query","current","filter","a","label","toLowerCase","includes","command","_ref4","range","chain","focus","deleteRange","insertContent","type","id","run","render","teamsRef","_ref5","_ref6","_ref7","t","_ref8"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("../../../node_modules/@tiptap/core/dist/index.js"),t=require("@tiptap/pm/model"),r=require("@tiptap/pm/state"),i=require("./pasteUtils.js");const a=e.Extension.create({name:"clipboardNormalization",addProseMirrorPlugins:()=>[new r.Plugin({props:{handlePaste(e,r){var a,n,o;if(null===(n=null===(a=r.clipboardData)||void 0===a?void 0:a.files)||void 0===n?void 0:n.length)return!1;const l=null===(o=r.clipboardData)||void 0===o?void 0:o.getData("text/html");if(!l)return!1;if(l.includes("data-pm-slice"))return!1;const s=document.createElement("div");if(s.innerHTML=l,!s.querySelector(i.BLOCK_SELECTOR))return!1;i.cleanBlockBrs(s);const c=e.state.schema,d=t.DOMParser.fromSchema(c).parseSlice(s),p=i.normalizeBlanks(d.content),u=new t.Slice(p,d.openStart,d.openEnd);return e.dispatch(e.state.tr.replaceSelection(u)),!0}}})]});exports.ClipboardNormalizationExtension=a;
|
|
2
|
+
//# sourceMappingURL=ClipboardNormalizationExtension.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClipboardNormalizationExtension.js","sources":["../../../../../src/editor/extensions/plainClipboard/ClipboardNormalizationExtension.ts"],"sourcesContent":["import { Extension } from '@tiptap/core';\nimport { DOMParser as ProseMirrorDOMParser, Slice } from '@tiptap/pm/model';\nimport { Plugin } from '@tiptap/pm/state';\nimport { BLOCK_SELECTOR, cleanBlockBrs, normalizeBlanks } from './pasteUtils';\n\n/**\n * Lightweight paste normalizer for rich-paste editors (email).\n * Fixes Google Docs' standalone `<br>` between paragraphs and collapses\n * consecutive empty paragraphs — but keeps ALL formatting marks intact.\n */\nexport const ClipboardNormalizationExtension = Extension.create({\n\tname: 'clipboardNormalization',\n\taddProseMirrorPlugins() {\n\t\treturn [\n\t\t\tnew Plugin({\n\t\t\t\tprops: {\n\t\t\t\t\thandlePaste(_view, event) {\n\t\t\t\t\t\tif (event.clipboardData?.files?.length) return false;\n\t\t\t\t\t\tconst html = event.clipboardData?.getData('text/html');\n\t\t\t\t\t\tif (!html) return false;\n\t\t\t\t\t\tif (html.includes('data-pm-slice')) return false;\n\n\t\t\t\t\t\tconst container = document.createElement('div');\n\t\t\t\t\t\tcontainer.innerHTML = html;\n\t\t\t\t\t\tif (!container.querySelector(BLOCK_SELECTOR)) return false;\n\n\t\t\t\t\t\tcleanBlockBrs(container);\n\t\t\t\t\t\tconst schema = _view.state.schema;\n\t\t\t\t\t\tconst parsed =\n\t\t\t\t\t\t\tProseMirrorDOMParser.fromSchema(schema).parseSlice(container);\n\t\t\t\t\t\tconst cleaned = normalizeBlanks(parsed.content);\n\t\t\t\t\t\tconst slice = new Slice(cleaned, parsed.openStart, parsed.openEnd);\n\t\t\t\t\t\t_view.dispatch(_view.state.tr.replaceSelection(slice));\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}),\n\t\t];\n\t},\n});\n"],"names":["ClipboardNormalizationExtension","Extension","create","name","addProseMirrorPlugins","Plugin","props","handlePaste","_view","event","_b","clipboardData","_a","files","length","html","_c","getData","includes","container","document","createElement","innerHTML","querySelector","BLOCK_SELECTOR","cleanBlockBrs","schema","state","parsed","ProseMirrorDOMParser","fromSchema","parseSlice","cleaned","normalizeBlanks","content","slice","Slice","openStart","openEnd","dispatch","tr","replaceSelection"],"mappings":"qOAUaA,EAAkCC,EAASA,UAACC,OAAO,CAC/DC,KAAM,yBACNC,sBAAqBA,IACb,CACN,IAAIC,EAAAA,OAAO,CACVC,MAAO,CACNC,YAAYC,EAAOC,aAClB,WAAIC,EAAqB,UAArBD,EAAME,qBAAe,IAAAC,OAAA,EAAAA,EAAAC,4BAAOC,OAAQ,OAAO,EAC/C,MAAMC,EAA0B,QAAnBC,EAAAP,EAAME,qBAAa,IAAAK,OAAA,EAAAA,EAAEC,QAAQ,aAC1C,IAAKF,EAAM,OAAO,EAClB,GAAIA,EAAKG,SAAS,iBAAkB,OAAO,EAE3C,MAAMC,EAAYC,SAASC,cAAc,OAEzC,GADAF,EAAUG,UAAYP,GACjBI,EAAUI,cAAcC,EAAAA,gBAAiB,OAAO,EAErDC,EAAaA,cAACN,GACd,MAAMO,EAASlB,EAAMmB,MAAMD,OACrBE,EACLC,EAAAA,UAAqBC,WAAWJ,GAAQK,WAAWZ,GAC9Ca,EAAUC,EAAAA,gBAAgBL,EAAOM,SACjCC,EAAQ,IAAIC,EAAAA,MAAMJ,EAASJ,EAAOS,UAAWT,EAAOU,SAE1D,OADA9B,EAAM+B,SAAS/B,EAAMmB,MAAMa,GAAGC,iBAAiBN,KACxC,CACR"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("../../../node_modules/@tiptap/core/dist/index.js"),t=require("@tiptap/pm/model"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("../../../node_modules/@tiptap/core/dist/index.js"),t=require("@tiptap/pm/model"),r=require("@tiptap/pm/state"),a=require("./pasteUtils.js");const i=e.Extension.create({name:"plainClipboard",addProseMirrorPlugins:()=>[new r.Plugin({props:{handlePaste(e,r){var i,n,l,o;if(null===(n=null===(i=r.clipboardData)||void 0===i?void 0:i.files)||void 0===n?void 0:n.length)return!1;const s=null===(l=r.clipboardData)||void 0===l?void 0:l.getData("text/html"),p=null===(o=r.clipboardData)||void 0===o?void 0:o.getData("text/plain");if(!p)return!1;if(null==s?void 0:s.includes("data-pm-slice"))return!1;const c=e.state.schema;if(s){const r=document.createElement("div");r.innerHTML=s;if(r.querySelector(a.BLOCK_SELECTOR)){a.cleanBlockBrs(r);const i=t.DOMParser.fromSchema(c).parseSlice(r),n=a.normalizeBlanks(a.stripRichMarks(i.content)),l=new t.Slice(n,i.openStart,i.openEnd);return e.dispatch(e.state.tr.replaceSelection(l)),!0}}const d=p.split("\n").map((e=>c.node("paragraph",null,e?[c.text(e)]:[]))),u=new t.Slice(t.Fragment.fromArray(d),1,1);return e.dispatch(e.state.tr.replaceSelection(u)),!0}}})]});exports.PlainClipboardExtension=i;
|
|
2
2
|
//# sourceMappingURL=PlainClipboardExtension.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlainClipboardExtension.js","sources":["../../../../../src/editor/extensions/plainClipboard/PlainClipboardExtension.ts"],"sourcesContent":["import { Extension } from '@tiptap/core';\nimport {
|
|
1
|
+
{"version":3,"file":"PlainClipboardExtension.js","sources":["../../../../../src/editor/extensions/plainClipboard/PlainClipboardExtension.ts"],"sourcesContent":["import { Extension } from '@tiptap/core';\nimport {\n\tFragment,\n\tDOMParser as ProseMirrorDOMParser,\n\tSlice,\n} from '@tiptap/pm/model';\nimport { Plugin } from '@tiptap/pm/state';\nimport {\n\tBLOCK_SELECTOR,\n\tcleanBlockBrs,\n\tnormalizeBlanks,\n\tstripRichMarks,\n} from './pasteUtils';\n\nexport const PlainClipboardExtension = Extension.create({\n\tname: 'plainClipboard',\n\taddProseMirrorPlugins() {\n\t\treturn [\n\t\t\tnew Plugin({\n\t\t\t\tprops: {\n\t\t\t\t\thandlePaste(_view, event) {\n\t\t\t\t\t\tif (event.clipboardData?.files?.length) return false;\n\t\t\t\t\t\tconst html = event.clipboardData?.getData('text/html');\n\t\t\t\t\t\tconst text = event.clipboardData?.getData('text/plain');\n\t\t\t\t\t\tif (!text) return false;\n\n\t\t\t\t\t\tif (html?.includes('data-pm-slice')) return false;\n\n\t\t\t\t\t\tconst schema = _view.state.schema;\n\n\t\t\t\t\t\tif (html) {\n\t\t\t\t\t\t\tconst container = document.createElement('div');\n\t\t\t\t\t\t\tcontainer.innerHTML = html;\n\t\t\t\t\t\t\tconst hasBlocks = container.querySelector(BLOCK_SELECTOR);\n\t\t\t\t\t\t\tif (hasBlocks) {\n\t\t\t\t\t\t\t\tcleanBlockBrs(container);\n\t\t\t\t\t\t\t\tconst parsed =\n\t\t\t\t\t\t\t\t\tProseMirrorDOMParser.fromSchema(schema).parseSlice(container);\n\t\t\t\t\t\t\t\tconst cleaned = normalizeBlanks(stripRichMarks(parsed.content));\n\t\t\t\t\t\t\t\tconst slice = new Slice(\n\t\t\t\t\t\t\t\t\tcleaned,\n\t\t\t\t\t\t\t\t\tparsed.openStart,\n\t\t\t\t\t\t\t\t\tparsed.openEnd,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t_view.dispatch(_view.state.tr.replaceSelection(slice));\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst paragraphs = text\n\t\t\t\t\t\t\t.split('\\n')\n\t\t\t\t\t\t\t.map((line) =>\n\t\t\t\t\t\t\t\tschema.node('paragraph', null, line ? [schema.text(line)] : []),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\tconst slice = new Slice(Fragment.fromArray(paragraphs), 1, 1);\n\t\t\t\t\t\t_view.dispatch(_view.state.tr.replaceSelection(slice));\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}),\n\t\t];\n\t},\n});\n"],"names":["PlainClipboardExtension","Extension","create","name","addProseMirrorPlugins","Plugin","props","handlePaste","_view","event","_b","clipboardData","_a","files","length","html","_c","getData","text","_d","includes","schema","state","container","document","createElement","innerHTML","querySelector","BLOCK_SELECTOR","cleanBlockBrs","parsed","ProseMirrorDOMParser","fromSchema","parseSlice","cleaned","normalizeBlanks","stripRichMarks","content","slice","Slice","openStart","openEnd","dispatch","tr","replaceSelection","paragraphs","split","map","line","node","Fragment","fromArray"],"mappings":"qOAcaA,EAA0BC,EAASA,UAACC,OAAO,CACvDC,KAAM,iBACNC,sBAAqBA,IACb,CACN,IAAIC,EAAAA,OAAO,CACVC,MAAO,CACNC,YAAYC,EAAOC,eAClB,WAAIC,EAAqB,UAArBD,EAAME,qBAAe,IAAAC,OAAA,EAAAA,EAAAC,4BAAOC,OAAQ,OAAO,EAC/C,MAAMC,EAA0B,QAAnBC,EAAAP,EAAME,qBAAa,IAAAK,OAAA,EAAAA,EAAEC,QAAQ,aACpCC,EAA0B,QAAnBC,EAAAV,EAAME,qBAAa,IAAAQ,OAAA,EAAAA,EAAEF,QAAQ,cAC1C,IAAKC,EAAM,OAAO,EAElB,GAAIH,aAAI,EAAJA,EAAMK,SAAS,iBAAkB,OAAO,EAE5C,MAAMC,EAASb,EAAMc,MAAMD,OAE3B,GAAIN,EAAM,CACT,MAAMQ,EAAYC,SAASC,cAAc,OACzCF,EAAUG,UAAYX,EAEtB,GADkBQ,EAAUI,cAAcC,EAAcA,gBACzC,CACdC,EAAaA,cAACN,GACd,MAAMO,EACLC,EAAAA,UAAqBC,WAAWX,GAAQY,WAAWV,GAC9CW,EAAUC,EAAAA,gBAAgBC,EAAAA,eAAeN,EAAOO,UAChDC,EAAQ,IAAIC,EAAAA,MACjBL,EACAJ,EAAOU,UACPV,EAAOW,SAGR,OADAjC,EAAMkC,SAASlC,EAAMc,MAAMqB,GAAGC,iBAAiBN,KACxC,CACP,CACD,CAED,MAAMO,EAAa3B,EACjB4B,MAAM,MACNC,KAAKC,GACL3B,EAAO4B,KAAK,YAAa,KAAMD,EAAO,CAAC3B,EAAOH,KAAK8B,IAAS,MAExDV,EAAQ,IAAIC,EAAAA,MAAMW,EAAQA,SAACC,UAAUN,GAAa,EAAG,GAE3D,OADArC,EAAMkC,SAASlC,EAAMc,MAAMqB,GAAGC,iBAAiBN,KACxC,CACR"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@tiptap/pm/model");const t=new Set(["P","LI","H1","H2","H3","H4","H5","H6","TD","TH","PRE"]),r=new Set(["bold","italic","strike","underline","code"]);exports.BLOCK_SELECTOR="p,div,h1,h2,h3,h4,h5,h6,ul,ol,li,blockquote,table,pre",exports.TEXTBLOCK_TAGS=t,exports.cleanBlockBrs=function(e){const r=Array.from(e.querySelectorAll("br"));for(const n of r){let r=!1,o=n.parentElement;for(;o&&o!==e;){if(t.has(o.tagName)){r=!0;break}o=o.parentElement}r||n.parentElement.replaceChild(document.createElement("p"),n)}},exports.normalizeBlanks=function t(r){const n=[];let o=!1;return r.forEach((e=>{var r;if("paragraph"===e.type.name&&1===e.childCount&&"hardBreak"===(null===(r=e.firstChild)||void 0===r?void 0:r.type.name))return o||n.push(e.type.create(e.attrs)),void(o=!0);const a="paragraph"===e.type.name&&0===e.childCount;a&&o||(o=a,e.isBlock&&!e.isLeaf?n.push(e.copy(t(e.content))):n.push(e))})),e.Fragment.from(n)},exports.stripRichMarks=function t(n){const o=[];return n.forEach((e=>{if(e.isText){const t=e.marks.filter((e=>r.has(e.type.name)));o.push(t.length===e.marks.length?e:e.mark(t))}else o.push(e.copy(t(e.content)))})),e.Fragment.from(o)};
|
|
2
|
+
//# sourceMappingURL=pasteUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pasteUtils.js","sources":["../../../../../src/editor/extensions/plainClipboard/pasteUtils.ts"],"sourcesContent":["import { Fragment, Node as PMNode } from '@tiptap/pm/model';\n\nexport const TEXTBLOCK_TAGS = new Set([\n\t'P',\n\t'LI',\n\t'H1',\n\t'H2',\n\t'H3',\n\t'H4',\n\t'H5',\n\t'H6',\n\t'TD',\n\t'TH',\n\t'PRE',\n]);\n\nexport const BLOCK_SELECTOR =\n\t'p,div,h1,h2,h3,h4,h5,h6,ul,ol,li,blockquote,table,pre';\n\nconst BASIC_MARKS = new Set(['bold', 'italic', 'strike', 'underline', 'code']);\n\n/**\n * Replace `<br>` elements that sit at block level (not inside a textblock\n * like `<p>`, `<li>`, etc.) with empty `<p></p>` elements. Google Docs\n * puts standalone `<br>` tags between paragraphs to represent blank lines.\n * Without this, ProseMirror parses them as top-level hardBreak nodes.\n */\nexport function cleanBlockBrs(container: HTMLElement): void {\n\tconst brs = Array.from(container.querySelectorAll('br'));\n\tfor (const br of brs) {\n\t\tlet insideTextblock = false;\n\t\tlet el = br.parentElement;\n\t\twhile (el && el !== container) {\n\t\t\tif (TEXTBLOCK_TAGS.has(el.tagName)) {\n\t\t\t\tinsideTextblock = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tel = el.parentElement;\n\t\t}\n\t\tif (!insideTextblock) {\n\t\t\tbr.parentElement!.replaceChild(document.createElement('p'), br);\n\t\t}\n\t}\n}\n\n/**\n * 1. Convert paragraphs containing only a hard_break into empty paragraphs.\n * 2. Collapse consecutive empty paragraphs into one.\n */\nexport function normalizeBlanks(fragment: Fragment): Fragment {\n\tconst nodes: PMNode[] = [];\n\tlet prevEmpty = false;\n\tfragment.forEach((node) => {\n\t\tconst isHardBreakOnly =\n\t\t\tnode.type.name === 'paragraph' &&\n\t\t\tnode.childCount === 1 &&\n\t\t\tnode.firstChild?.type.name === 'hardBreak';\n\t\tif (isHardBreakOnly) {\n\t\t\tif (!prevEmpty) nodes.push(node.type.create(node.attrs));\n\t\t\tprevEmpty = true;\n\t\t\treturn;\n\t\t}\n\t\tconst isEmpty = node.type.name === 'paragraph' && node.childCount === 0;\n\t\tif (isEmpty && prevEmpty) return;\n\t\tprevEmpty = isEmpty;\n\t\tif (node.isBlock && !node.isLeaf) {\n\t\t\tnodes.push(node.copy(normalizeBlanks(node.content)));\n\t\t} else {\n\t\t\tnodes.push(node);\n\t\t}\n\t});\n\treturn Fragment.from(nodes);\n}\n\n/**\n * Strip only \"rich\" marks (link, textStyle, highlight, etc.) while keeping\n * basic formatting marks (bold, italic, strike, underline, code) that\n * messaging channels can represent.\n */\nexport function stripRichMarks(fragment: Fragment): Fragment {\n\tconst nodes: PMNode[] = [];\n\tfragment.forEach((node) => {\n\t\tif (node.isText) {\n\t\t\tconst kept = node.marks.filter((m) => BASIC_MARKS.has(m.type.name));\n\t\t\tnodes.push(kept.length === node.marks.length ? node : node.mark(kept));\n\t\t} else {\n\t\t\tnodes.push(node.copy(stripRichMarks(node.content)));\n\t\t}\n\t});\n\treturn Fragment.from(nodes);\n}\n"],"names":["TEXTBLOCK_TAGS","Set","BASIC_MARKS","container","brs","Array","from","querySelectorAll","br","insideTextblock","el","parentElement","has","tagName","replaceChild","document","createElement","normalizeBlanks","fragment","nodes","prevEmpty","forEach","node","type","name","childCount","_a","firstChild","push","create","attrs","isEmpty","isBlock","isLeaf","copy","content","Fragment","stripRichMarks","isText","kept","marks","filter","m","length","mark"],"mappings":"sGAEaA,MAAAA,EAAiB,IAAIC,IAAI,CACrC,IACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,KACA,QAMKC,EAAc,IAAID,IAAI,CAAC,OAAQ,SAAU,SAAU,YAAa,gCAFrE,uGAUK,SAAwBE,GAC7B,MAAMC,EAAMC,MAAMC,KAAKH,EAAUI,iBAAiB,OAClD,IAAK,MAAMC,KAAMJ,EAAK,CACrB,IAAIK,GAAkB,EAClBC,EAAKF,EAAGG,cACZ,KAAOD,GAAMA,IAAOP,GAAW,CAC9B,GAAIH,EAAeY,IAAIF,EAAGG,SAAU,CACnCJ,GAAkB,EAClB,KACA,CACDC,EAAKA,EAAGC,aACR,CACIF,GACJD,EAAGG,cAAeG,aAAaC,SAASC,cAAc,KAAMR,EAE7D,CACF,0BAMM,SAAUS,EAAgBC,GAC/B,MAAMC,EAAkB,GACxB,IAAIC,GAAY,EAoBhB,OAnBAF,EAASG,SAASC,UAKjB,GAHoB,cAAnBA,EAAKC,KAAKC,MACU,IAApBF,EAAKG,YAC0B,eAAhB,QAAfC,EAAAJ,EAAKK,kBAAU,IAAAD,OAAA,EAAAA,EAAEH,KAAKC,MAItB,OAFKJ,GAAWD,EAAMS,KAAKN,EAAKC,KAAKM,OAAOP,EAAKQ,aACjDV,GAAY,GAGb,MAAMW,EAA6B,cAAnBT,EAAKC,KAAKC,MAA4C,IAApBF,EAAKG,WACnDM,GAAWX,IACfA,EAAYW,EACRT,EAAKU,UAAYV,EAAKW,OACzBd,EAAMS,KAAKN,EAAKY,KAAKjB,EAAgBK,EAAKa,WAE1ChB,EAAMS,KAAKN,GACX,IAEKc,EAAQA,SAAC9B,KAAKa,EACtB,yBAOM,SAAUkB,EAAenB,GAC9B,MAAMC,EAAkB,GASxB,OARAD,EAASG,SAASC,IACjB,GAAIA,EAAKgB,OAAQ,CAChB,MAAMC,EAAOjB,EAAKkB,MAAMC,QAAQC,GAAMxC,EAAYU,IAAI8B,EAAEnB,KAAKC,QAC7DL,EAAMS,KAAKW,EAAKI,SAAWrB,EAAKkB,MAAMG,OAASrB,EAAOA,EAAKsB,KAAKL,GAChE,MACApB,EAAMS,KAAKN,EAAKY,KAAKG,EAAef,EAAKa,UACzC,IAEKC,EAAQA,SAAC9B,KAAKa,EACtB"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("../../../node_modules/@tiptap/core/dist/index.js"),r=require("@tiptap/react"),t=require("@tiptap/suggestion"),n=require("../suggestionPopup.js"),o=require("./SlashCommandMenu.js");function i(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var s=i(t);exports.buildSlashCommandExtension=function(t,i,d
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("../../../node_modules/@tiptap/core/dist/index.js"),r=require("@tiptap/react"),t=require("@tiptap/suggestion"),n=require("../suggestionPopup.js"),o=require("./SlashCommandMenu.js");function i(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var s=i(t);exports.buildSlashCommandExtension=function(t,i,a,d){return e.Extension.create({name:"slashCommand",addProseMirrorPlugins(){return[s.default({editor:this.editor,char:"/",allowSpaces:!0,items:e=>{let{query:r}=e;return t.current.filter((e=>e.label.toLowerCase().includes(r.toLowerCase()))).slice(0,20)},command:e=>{let{editor:r,range:t,props:n}=e;r.chain().focus().deleteRange(t).run(),null==i||i(n)},render:()=>{let e,t;return{onStart:i=>{e=new r.ReactRenderer(o.SlashCommandMenu,{props:Object.assign(Object.assign({},i),{renderItem:a,renderDropdown:d}),editor:i.editor}),t=n.createSuggestionPopup(e.element,i.clientRect)},onUpdate:r=>{var n;e.updateProps(Object.assign(Object.assign({},r),{renderItem:a,renderDropdown:d})),(null===(n=r.items)||void 0===n?void 0:n.length)?(t.show(),t.updatePosition(r.clientRect)):t.hide()},onKeyDown:r=>{var n,o;return"Escape"===r.event.key?(t.hide(),!0):null!==(o=null===(n=e.ref)||void 0===n?void 0:n.onKeyDown(r))&&void 0!==o&&o},onExit:()=>{t.destroy(),e.destroy()}}}})]}})};
|
|
2
2
|
//# sourceMappingURL=SlashCommandExtension.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SlashCommandExtension.js","sources":["../../../../../src/editor/extensions/slashCommand/SlashCommandExtension.ts"],"sourcesContent":["import { Extension } from '@tiptap/core';\nimport { ReactRenderer } from '@tiptap/react';\nimport Suggestion from '@tiptap/suggestion';\nimport type { ReactNode } from 'react';\nimport type {\n\tSlashCommandDropdownRenderProps,\n\tSlashCommandItem,\n} from '../../BikEditor.types';\nimport {\n\tcreateSuggestionPopup,\n\ttype SuggestionPopup,\n} from '../suggestionPopup';\nimport { SlashCommandMenu } from './SlashCommandMenu';\n\nexport function buildSlashCommandExtension(\n\tcommandsRef: { current: SlashCommandItem[] },\n\tonSelect?: (command: SlashCommandItem) => void,\n\trenderItem?: (item: SlashCommandItem, isActive: boolean) => ReactNode,\n\trenderDropdown?: (props: SlashCommandDropdownRenderProps) => ReactNode,\n) {\n\treturn Extension.create({\n\t\tname: 'slashCommand',\n\t\taddProseMirrorPlugins() {\n\t\t\treturn [\n\t\t\t\tSuggestion({\n\t\t\t\t\teditor: this.editor,\n\t\t\t\t\tchar: '/',\n\t\t\t\t\titems: ({ query }: any) =>\n\t\t\t\t\t\tcommandsRef.current\n\t\t\t\t\t\t\t.filter((c) =>\n\t\t\t\t\t\t\t\tc.label.toLowerCase().includes(query.toLowerCase()),\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.slice(0, 20),\n\t\t\t\t\tcommand: ({ editor, range, props }: any) => {\n\t\t\t\t\t\teditor.chain().focus().deleteRange(range).run();\n\t\t\t\t\t\tonSelect?.(props);\n\t\t\t\t\t},\n\t\t\t\t\trender: () => {\n\t\t\t\t\t\tlet component: ReactRenderer;\n\t\t\t\t\t\tlet popup: SuggestionPopup;\n\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tonStart: (props: any) => {\n\t\t\t\t\t\t\t\tcomponent = new ReactRenderer(SlashCommandMenu, {\n\t\t\t\t\t\t\t\t\tprops: { ...props, renderItem, renderDropdown },\n\t\t\t\t\t\t\t\t\teditor: props.editor,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tpopup = createSuggestionPopup(\n\t\t\t\t\t\t\t\t\tcomponent.element,\n\t\t\t\t\t\t\t\t\tprops.clientRect,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tonUpdate: (props: any) => {\n\t\t\t\t\t\t\t\tcomponent.updateProps({ ...props, renderItem, renderDropdown });\n\t\t\t\t\t\t\t\tif (!props.items?.length) {\n\t\t\t\t\t\t\t\t\tpopup.hide();\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tpopup.show();\n\t\t\t\t\t\t\t\tpopup.updatePosition(props.clientRect);\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tonKeyDown: (props: any) => {\n\t\t\t\t\t\t\t\tif (props.event.key === 'Escape') {\n\t\t\t\t\t\t\t\t\tpopup.hide();\n\t\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\treturn (component.ref as any)?.onKeyDown(props) ?? false;\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tonExit: () => {\n\t\t\t\t\t\t\t\tpopup.destroy();\n\t\t\t\t\t\t\t\tcomponent.destroy();\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t};\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t];\n\t\t},\n\t});\n}\n"],"names":["commandsRef","onSelect","renderItem","renderDropdown","Extension","create","name","addProseMirrorPlugins","Suggestion","editor","this","char","items","_ref","query","current","filter","c","label","toLowerCase","includes","slice","command","_ref2","range","props","chain","focus","deleteRange","run","render","component","popup","onStart","ReactRenderer","SlashCommandMenu","createSuggestionPopup","element","clientRect","onUpdate","updateProps","Object","assign","_a","length","show","updatePosition","hide","onKeyDown","event","key","_b","ref","onExit","destroy"],"mappings":"6XAcM,SACLA,EACAC,EACAC,EACAC,GAEA,OAAOC,EAAAA,UAAUC,OAAO,CACvBC,KAAM,eACNC,wBACC,MAAO,CACNC,EAAAA,QAAW,CACVC,OAAQC,KAAKD,OACbE,KAAM,IACNC,MAAOC,IAAA,IAACC,MAAEA,GAAYD,EAAA,
|
|
1
|
+
{"version":3,"file":"SlashCommandExtension.js","sources":["../../../../../src/editor/extensions/slashCommand/SlashCommandExtension.ts"],"sourcesContent":["import { Extension } from '@tiptap/core';\nimport { ReactRenderer } from '@tiptap/react';\nimport Suggestion from '@tiptap/suggestion';\nimport type { ReactNode } from 'react';\nimport type {\n\tSlashCommandDropdownRenderProps,\n\tSlashCommandItem,\n} from '../../BikEditor.types';\nimport {\n\tcreateSuggestionPopup,\n\ttype SuggestionPopup,\n} from '../suggestionPopup';\nimport { SlashCommandMenu } from './SlashCommandMenu';\n\nexport function buildSlashCommandExtension(\n\tcommandsRef: { current: SlashCommandItem[] },\n\tonSelect?: (command: SlashCommandItem) => void,\n\trenderItem?: (item: SlashCommandItem, isActive: boolean) => ReactNode,\n\trenderDropdown?: (props: SlashCommandDropdownRenderProps) => ReactNode,\n) {\n\treturn Extension.create({\n\t\tname: 'slashCommand',\n\t\taddProseMirrorPlugins() {\n\t\t\treturn [\n\t\t\t\tSuggestion({\n\t\t\t\t\teditor: this.editor,\n\t\t\t\t\tchar: '/',\n\t\t\t\t\tallowSpaces: true,\n\t\t\t\t\titems: ({ query }: any) =>\n\t\t\t\t\t\tcommandsRef.current\n\t\t\t\t\t\t\t.filter((c) =>\n\t\t\t\t\t\t\t\tc.label.toLowerCase().includes(query.toLowerCase()),\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.slice(0, 20),\n\t\t\t\t\tcommand: ({ editor, range, props }: any) => {\n\t\t\t\t\t\teditor.chain().focus().deleteRange(range).run();\n\t\t\t\t\t\tonSelect?.(props);\n\t\t\t\t\t},\n\t\t\t\t\trender: () => {\n\t\t\t\t\t\tlet component: ReactRenderer;\n\t\t\t\t\t\tlet popup: SuggestionPopup;\n\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tonStart: (props: any) => {\n\t\t\t\t\t\t\t\tcomponent = new ReactRenderer(SlashCommandMenu, {\n\t\t\t\t\t\t\t\t\tprops: { ...props, renderItem, renderDropdown },\n\t\t\t\t\t\t\t\t\teditor: props.editor,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tpopup = createSuggestionPopup(\n\t\t\t\t\t\t\t\t\tcomponent.element,\n\t\t\t\t\t\t\t\t\tprops.clientRect,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tonUpdate: (props: any) => {\n\t\t\t\t\t\t\t\tcomponent.updateProps({ ...props, renderItem, renderDropdown });\n\t\t\t\t\t\t\t\tif (!props.items?.length) {\n\t\t\t\t\t\t\t\t\tpopup.hide();\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tpopup.show();\n\t\t\t\t\t\t\t\tpopup.updatePosition(props.clientRect);\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tonKeyDown: (props: any) => {\n\t\t\t\t\t\t\t\tif (props.event.key === 'Escape') {\n\t\t\t\t\t\t\t\t\tpopup.hide();\n\t\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\treturn (component.ref as any)?.onKeyDown(props) ?? false;\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tonExit: () => {\n\t\t\t\t\t\t\t\tpopup.destroy();\n\t\t\t\t\t\t\t\tcomponent.destroy();\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t};\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t];\n\t\t},\n\t});\n}\n"],"names":["commandsRef","onSelect","renderItem","renderDropdown","Extension","create","name","addProseMirrorPlugins","Suggestion","editor","this","char","allowSpaces","items","_ref","query","current","filter","c","label","toLowerCase","includes","slice","command","_ref2","range","props","chain","focus","deleteRange","run","render","component","popup","onStart","ReactRenderer","SlashCommandMenu","createSuggestionPopup","element","clientRect","onUpdate","updateProps","Object","assign","_a","length","show","updatePosition","hide","onKeyDown","event","key","_b","ref","onExit","destroy"],"mappings":"6XAcM,SACLA,EACAC,EACAC,EACAC,GAEA,OAAOC,EAAAA,UAAUC,OAAO,CACvBC,KAAM,eACNC,wBACC,MAAO,CACNC,EAAAA,QAAW,CACVC,OAAQC,KAAKD,OACbE,KAAM,IACNC,aAAa,EACbC,MAAOC,IAAA,IAACC,MAAEA,GAAYD,EAAA,OACrBd,EAAYgB,QACVC,QAAQC,GACRA,EAAEC,MAAMC,cAAcC,SAASN,EAAMK,iBAErCE,MAAM,EAAG,GAAG,EACfC,QAASC,IAAkC,IAAjCf,OAAEA,EAAMgB,MAAEA,EAAKC,MAAEA,GAAYF,EACtCf,EAAOkB,QAAQC,QAAQC,YAAYJ,GAAOK,MAC1C7B,SAAAA,EAAWyB,EAAM,EAElBK,OAAQA,KACP,IAAIC,EACAC,EAEJ,MAAO,CACNC,QAAUR,IACTM,EAAY,IAAIG,EAAaA,cAACC,mBAAkB,CAC/CV,qCAAYA,GAAK,CAAExB,aAAYC,mBAC/BM,OAAQiB,EAAMjB,SAEfwB,EAAQI,EAAqBA,sBAC5BL,EAAUM,QACVZ,EAAMa,WACN,EAEFC,SAAWd,UACVM,EAAUS,YAAiBC,OAAAC,OAAAD,OAAAC,OAAA,CAAA,EAAAjB,IAAOxB,aAAYC,qBAC9B,QAAXyC,EAAAlB,EAAMb,aAAK,IAAA+B,OAAA,EAAAA,EAAEC,SAIlBZ,EAAMa,OACNb,EAAMc,eAAerB,EAAMa,aAJ1BN,EAAMe,MAI+B,EAEvCC,UAAYvB,YACX,MAAwB,WAApBA,EAAMwB,MAAMC,KACflB,EAAMe,QACC,GAE2C,QAA5CI,EAAsB,QAAtBR,EAACZ,EAAUqB,WAAW,IAAAT,OAAA,EAAAA,EAAEK,UAAUvB,UAAU,IAAA0B,GAAAA,CAAK,EAEzDE,OAAQA,KACPrB,EAAMsB,UACNvB,EAAUuB,SAAS,EAEpB,IAIL,GAEF"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";function e(r){var n
|
|
1
|
+
"use strict";function e(r){var n;if(r.nodeType===Node.TEXT_NODE)return null!==(n=r.textContent)&&void 0!==n?n:"";if(r.nodeType!==Node.ELEMENT_NODE)return"";const a=r,c=a.tagName.toLowerCase(),t=function(r){return Array.from(r.childNodes).map(e).join("")}(a);switch(c){case"strong":case"b":return t?`*${t}*`:"";case"em":case"i":return t?`_${t}_`:"";case"s":case"del":case"strike":return t?`~${t}~`:"";case"code":return t?`\`${t}\``:"";case"pre":return t?`\`\`\`${t}\`\`\``:"";case"a":case"ul":case"ol":case"body":default:return t;case"br":return"\n";case"p":case"div":return t?`${t}\n`:"\n";case"h1":case"h2":case"h3":case"h4":case"h5":case"h6":return t?`*${t}*\n`:"\n";case"li":return`• ${t.trimEnd()}\n`;case"blockquote":return t.split("\n").map((e=>e?`> ${e}`:"")).join("\n")+"\n"}}Object.defineProperty(exports,"__esModule",{value:!0}),exports.toWhatsAppText=function(r){if(!r)return"";if("undefined"!=typeof document){return e((new DOMParser).parseFromString(r,"text/html").body).replace(/\n{3,}/g,"\n\n").trim()}return function(e){return e.replace(/<strong[^>]*>([\s\S]*?)<\/strong>/gi,"*$1*").replace(/<b[^>]*>([\s\S]*?)<\/b>/gi,"*$1*").replace(/<em[^>]*>([\s\S]*?)<\/em>/gi,"_$1_").replace(/<i[^>]*>([\s\S]*?)<\/i>/gi,"_$1_").replace(/<s[^>]*>([\s\S]*?)<\/s>/gi,"~$1~").replace(/<del[^>]*>([\s\S]*?)<\/del>/gi,"~$1~").replace(/<code[^>]*>([\s\S]*?)<\/code>/gi,"`$1`").replace(/<a[^>]*>([\s\S]*?)<\/a>/gi,"$1").replace(/<br\s*\/?>/gi,"\n").replace(/<\/p>/gi,"\n").replace(/<\/div>/gi,"\n").replace(/<\/h[1-6]>/gi,"\n").replace(/<li[^>]*>/gi,"• ").replace(/<\/li>/gi,"\n").replace(/<[^>]+>/g,"").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/ /g," ").replace(/\n{3,}/g,"\n\n").trim()}(r)};
|
|
2
2
|
//# sourceMappingURL=toWhatsAppText.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toWhatsAppText.js","sources":["../../../../src/editor/serializers/toWhatsAppText.ts"],"sourcesContent":["/**\n * Converts TipTap HTML to WhatsApp-flavoured markdown text.\n *\n * WhatsApp formatting:\n * *bold* _italic_ ~strikethrough~ ```monospace```\n *\n * Links: WhatsApp does not support
|
|
1
|
+
{"version":3,"file":"toWhatsAppText.js","sources":["../../../../src/editor/serializers/toWhatsAppText.ts"],"sourcesContent":["/**\n * Converts TipTap HTML to WhatsApp-flavoured markdown text.\n *\n * WhatsApp formatting:\n * *bold* _italic_ ~strikethrough~ ```monospace```\n *\n * Links: WhatsApp does not support hyperlinks.\n * <a href=\"https://…\">Visit us</a> → Visit us (display text kept, href dropped)\n *\n * @example\n * const { html } = ref.current?.getContent();\n * const waText = toWhatsAppText(html);\n * sendWhatsApp({ text: waText });\n */\nexport function toWhatsAppText(html: string): string {\n\tif (!html) return '';\n\n\tif (typeof document !== 'undefined') {\n\t\tconst doc = new DOMParser().parseFromString(html, 'text/html');\n\t\treturn serializeNode(doc.body)\n\t\t\t.replace(/\\n{3,}/g, '\\n\\n')\n\t\t\t.trim();\n\t}\n\n\t// SSR / Node.js fallback — handles simple non-nested markup\n\treturn ssrFallback(html);\n}\n\n// ---------------------------------------------------------------------------\n// Browser path — DOM-based, handles nested marks correctly\n// ---------------------------------------------------------------------------\n\nfunction serializeNode(node: Node): string {\n\tif (node.nodeType === Node.TEXT_NODE) {\n\t\treturn node.textContent ?? '';\n\t}\n\tif (node.nodeType !== Node.ELEMENT_NODE) return '';\n\n\tconst el = node as Element;\n\tconst tag = el.tagName.toLowerCase();\n\tconst inner = serializeChildren(el);\n\n\tswitch (tag) {\n\t\tcase 'strong':\n\t\tcase 'b':\n\t\t\treturn inner ? `*${inner}*` : '';\n\n\t\tcase 'em':\n\t\tcase 'i':\n\t\t\treturn inner ? `_${inner}_` : '';\n\n\t\tcase 's':\n\t\tcase 'del':\n\t\tcase 'strike':\n\t\t\treturn inner ? `~${inner}~` : '';\n\n\t\tcase 'code':\n\t\t\treturn inner ? `\\`${inner}\\`` : '';\n\n\t\tcase 'pre':\n\t\t\treturn inner ? `\\`\\`\\`${inner}\\`\\`\\`` : '';\n\n\t\tcase 'a':\n\t\t\treturn inner;\n\n\t\tcase 'br':\n\t\t\treturn '\\n';\n\n\t\tcase 'p':\n\t\tcase 'div':\n\t\t\treturn inner ? `${inner}\\n` : '\\n';\n\n\t\tcase 'h1':\n\t\tcase 'h2':\n\t\tcase 'h3':\n\t\tcase 'h4':\n\t\tcase 'h5':\n\t\tcase 'h6':\n\t\t\treturn inner ? `*${inner}*\\n` : '\\n';\n\n\t\tcase 'ul':\n\t\tcase 'ol':\n\t\t\treturn inner;\n\n\t\tcase 'li':\n\t\t\treturn `• ${inner.trimEnd()}\\n`;\n\n\t\tcase 'blockquote':\n\t\t\treturn (\n\t\t\t\tinner\n\t\t\t\t\t.split('\\n')\n\t\t\t\t\t.map((l) => (l ? `> ${l}` : ''))\n\t\t\t\t\t.join('\\n') + '\\n'\n\t\t\t);\n\n\t\tcase 'body':\n\t\tdefault:\n\t\t\treturn inner;\n\t}\n}\n\nfunction serializeChildren(el: Element): string {\n\treturn Array.from(el.childNodes).map(serializeNode).join('');\n}\n\n// ---------------------------------------------------------------------------\n// SSR fallback — regex-based, best-effort for simple markup\n// ---------------------------------------------------------------------------\n\nfunction ssrFallback(html: string): string {\n\treturn html\n\t\t.replace(/<strong[^>]*>([\\s\\S]*?)<\\/strong>/gi, '*$1*')\n\t\t.replace(/<b[^>]*>([\\s\\S]*?)<\\/b>/gi, '*$1*')\n\t\t.replace(/<em[^>]*>([\\s\\S]*?)<\\/em>/gi, '_$1_')\n\t\t.replace(/<i[^>]*>([\\s\\S]*?)<\\/i>/gi, '_$1_')\n\t\t.replace(/<s[^>]*>([\\s\\S]*?)<\\/s>/gi, '~$1~')\n\t\t.replace(/<del[^>]*>([\\s\\S]*?)<\\/del>/gi, '~$1~')\n\t\t.replace(/<code[^>]*>([\\s\\S]*?)<\\/code>/gi, '`$1`')\n\t\t.replace(/<a[^>]*>([\\s\\S]*?)<\\/a>/gi, '$1')\n\t\t.replace(/<br\\s*\\/?>/gi, '\\n')\n\t\t.replace(/<\\/p>/gi, '\\n')\n\t\t.replace(/<\\/div>/gi, '\\n')\n\t\t.replace(/<\\/h[1-6]>/gi, '\\n')\n\t\t.replace(/<li[^>]*>/gi, '• ')\n\t\t.replace(/<\\/li>/gi, '\\n')\n\t\t.replace(/<[^>]+>/g, '')\n\t\t.replace(/&/g, '&')\n\t\t.replace(/</g, '<')\n\t\t.replace(/>/g, '>')\n\t\t.replace(/ /g, ' ')\n\t\t.replace(/\\n{3,}/g, '\\n\\n')\n\t\t.trim();\n}\n"],"names":["serializeNode","node","nodeType","Node","TEXT_NODE","textContent","_a","ELEMENT_NODE","el","tag","tagName","toLowerCase","inner","Array","from","childNodes","map","join","serializeChildren","trimEnd","split","l","html","document","DOMParser","parseFromString","body","replace","trim","ssrFallback"],"mappings":"aAgCA,SAASA,EAAcC,SACtB,GAAIA,EAAKC,WAAaC,KAAKC,UAC1B,OAAuB,UAAhBH,EAAKI,mBAAW,IAAAC,EAAAA,EAAI,GAE5B,GAAIL,EAAKC,WAAaC,KAAKI,aAAc,MAAO,GAEhD,MAAMC,EAAKP,EACLQ,EAAMD,EAAGE,QAAQC,cACjBC,EA6DP,SAA2BJ,GAC1B,OAAOK,MAAMC,KAAKN,EAAGO,YAAYC,IAAIhB,GAAeiB,KAAK,GAC1D,CA/DeC,CAAkBV,GAEhC,OAAQC,GACP,IAAK,SACL,IAAK,IACJ,OAAOG,EAAQ,IAAIA,KAAW,GAE/B,IAAK,KACL,IAAK,IACJ,OAAOA,EAAQ,IAAIA,KAAW,GAE/B,IAAK,IACL,IAAK,MACL,IAAK,SACJ,OAAOA,EAAQ,IAAIA,KAAW,GAE/B,IAAK,OACJ,OAAOA,EAAQ,KAAKA,MAAY,GAEjC,IAAK,MACJ,OAAOA,EAAQ,SAASA,UAAgB,GAEzC,IAAK,IAkBL,IAAK,KACL,IAAK,KAcL,IAAK,OACL,QACC,OAAOA,EAhCR,IAAK,KACJ,MAAO,KAER,IAAK,IACL,IAAK,MACJ,OAAOA,EAAQ,GAAGA,MAAY,KAE/B,IAAK,KACL,IAAK,KACL,IAAK,KACL,IAAK,KACL,IAAK,KACL,IAAK,KACJ,OAAOA,EAAQ,IAAIA,OAAa,KAMjC,IAAK,KACJ,WAAYA,EAAMO,cAEnB,IAAK,aACJ,OACCP,EACEQ,MAAM,MACNJ,KAAKK,GAAOA,EAAI,KAAKA,IAAM,KAC3BJ,KAAK,MAAQ,KAOnB,+EArFM,SAAyBK,GAC9B,IAAKA,EAAM,MAAO,GAElB,GAAwB,oBAAbC,SAA0B,CAEpC,OAAOvB,GADK,IAAIwB,WAAYC,gBAAgBH,EAAM,aACzBI,MACvBC,QAAQ,UAAW,QACnBC,MACF,CAGD,OAoFD,SAAqBN,GACpB,OAAOA,EACLK,QAAQ,sCAAuC,QAC/CA,QAAQ,4BAA6B,QACrCA,QAAQ,8BAA+B,QACvCA,QAAQ,4BAA6B,QACrCA,QAAQ,4BAA6B,QACrCA,QAAQ,gCAAiC,QACzCA,QAAQ,kCAAmC,QAC3CA,QAAQ,4BAA6B,MACrCA,QAAQ,eAAgB,MACxBA,QAAQ,UAAW,MACnBA,QAAQ,YAAa,MACrBA,QAAQ,eAAgB,MACxBA,QAAQ,cAAe,MACvBA,QAAQ,WAAY,MACpBA,QAAQ,WAAY,IACpBA,QAAQ,SAAU,KAClBA,QAAQ,QAAS,KACjBA,QAAQ,QAAS,KACjBA,QAAQ,UAAW,KACnBA,QAAQ,UAAW,QACnBC,MACH,CA3GQC,CAAYP,EACpB"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { QueryBuilderNodeProps } from "../../../
|
|
2
|
+
import { QueryBuilderNodeProps } from "../../../Types/QueryBuilderNodeProps.type";
|
|
3
3
|
declare const EventsTrigger: React.FC<QueryBuilderNodeProps>;
|
|
4
4
|
export default EventsTrigger;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { QueryBuilderAPIData } from "../../../
|
|
1
|
+
import { QueryBuilderAPIData } from "../../../Types/QueryBuilderAPI.type";
|
|
2
2
|
export declare const useIGTriggerNameCacheSelector: () => QueryBuilderAPIData[];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { QueryBuilderNodeProps } from "../../../
|
|
2
|
+
import { QueryBuilderNodeProps } from "../../../Types/QueryBuilderNodeProps.type";
|
|
3
3
|
declare const IGTrigger: React.FC<QueryBuilderNodeProps>;
|
|
4
4
|
export default IGTrigger;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { QueryBuilderAPIData } from "../../../
|
|
1
|
+
import { QueryBuilderAPIData } from "../../../Types/QueryBuilderAPI.type";
|
|
2
2
|
export declare const useIGTriggerNameCacheSelector: () => QueryBuilderAPIData[];
|
package/dist/cjs/src/components/QueryBuilder/Triggers/components/BaseTriggerQueryBuilderNode.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { DropdownOption } from "../../../dropdown/type";
|
|
3
|
-
import { QueryBuilderProperty } from "../../
|
|
4
|
-
import { QueryBuilderNodeProps } from "../../
|
|
3
|
+
import { QueryBuilderProperty } from "../../Types/QueryBuilder.type";
|
|
4
|
+
import { QueryBuilderNodeProps } from "../../Types/QueryBuilderNodeProps.type";
|
|
5
5
|
declare const BaseTriggerQueryBuilderNode: React.FC<QueryBuilderNodeProps & {
|
|
6
6
|
cacheKey: string;
|
|
7
7
|
propertyAddBtnText: string;
|
|
@@ -3,18 +3,23 @@ import { EditorSnapshot, FormatState } from './BikEditor.types';
|
|
|
3
3
|
/**
|
|
4
4
|
* Normalise HTML before passing it to TipTap.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* 1× line height. The WA text output is unchanged (`\n` either way after
|
|
15
|
-
* surrounding-newline collapse in `toWhatsAppText`).
|
|
6
|
+
* 1. Strip all `<span>` tags first (keeps inner content). This exposes
|
|
7
|
+
* bare `<br>` inside otherwise-empty paragraphs like Quill's
|
|
8
|
+
* `<p><span class="ql-cursor"><br></span></p>`.
|
|
9
|
+
* 2. Then convert `<p><br></p>` → `<p></p>`. ProseMirror parses `<p></p>`
|
|
10
|
+
* as an empty paragraph node and adds its own DOM `<br>` for cursor
|
|
11
|
+
* positioning — one blank line, correct height. Leaving the `<br>`
|
|
12
|
+
* would create a `hard_break` child AND the cursor `<br>`, producing
|
|
13
|
+
* double-height blank lines.
|
|
16
14
|
*/
|
|
17
15
|
export declare function normalizeHtml(html: string): string;
|
|
16
|
+
/**
|
|
17
|
+
* Convert ProseMirror's `<p></p>` empty paragraphs to the universally
|
|
18
|
+
* rendered `<p><br></p>` format before the HTML leaves the editor.
|
|
19
|
+
* Email clients, chat bubbles, and every renderer understand `<p><br></p>`
|
|
20
|
+
* as a visible blank line, whereas `<p></p>` collapses to zero height.
|
|
21
|
+
*/
|
|
22
|
+
export declare function toPortableHtml(html: string): string;
|
|
18
23
|
/**
|
|
19
24
|
* Insert HTML at the current cursor position, merging the first paragraph
|
|
20
25
|
* inline while preserving the block structure of subsequent paragraphs/lists.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Extension } from '@tiptap/core';
|
|
2
|
+
/**
|
|
3
|
+
* Lightweight paste normalizer for rich-paste editors (email).
|
|
4
|
+
* Fixes Google Docs' standalone `<br>` between paragraphs and collapses
|
|
5
|
+
* consecutive empty paragraphs — but keeps ALL formatting marks intact.
|
|
6
|
+
*/
|
|
7
|
+
export declare const ClipboardNormalizationExtension: Extension<any, any>;
|