@tiptap/extension-unique-id 2.0.0-beta.3 → 2.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -0
- package/dist/helpers/findDuplicates.d.ts +5 -0
- package/dist/helpers/findDuplicates.d.ts.map +1 -0
- package/dist/helpers/removeDuplicates.d.ts +9 -0
- package/dist/helpers/removeDuplicates.d.ts.map +1 -0
- package/dist/{tiptap-extension-unique-id.cjs.js → index.cjs} +253 -280
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/{tiptap-extension-unique-id.esm.js → index.js} +253 -280
- package/dist/index.js.map +1 -0
- package/dist/{tiptap-extension-unique-id.umd.js → index.umd.js} +255 -281
- package/dist/index.umd.js.map +1 -0
- package/dist/{tiptap-pro/packages/extension-unique-id/src/unique-id.d.ts → unique-id.d.ts} +10 -9
- package/dist/unique-id.d.ts.map +1 -0
- package/package.json +31 -13
- package/src/helpers/findDuplicates.ts +2 -2
- package/src/helpers/removeDuplicates.ts +1 -1
- package/src/index.ts +2 -2
- package/src/unique-id.ts +104 -38
- package/dist/tiptap-extension-unique-id.cjs.js.map +0 -1
- package/dist/tiptap-extension-unique-id.esm.js.map +0 -1
- package/dist/tiptap-extension-unique-id.umd.js.map +0 -1
- package/dist/tiptap-pro/packages/extension-unique-id/src/helpers/combineTransactionSteps.d.ts +0 -7
- package/dist/tiptap-pro/packages/extension-unique-id/src/helpers/findDuplicates.d.ts +0 -4
- package/dist/tiptap-pro/packages/extension-unique-id/src/helpers/getChangedRanges.d.ts +0 -12
- package/dist/tiptap-pro/packages/extension-unique-id/src/helpers/removeDuplicates.d.ts +0 -8
- package/dist/tiptap-pro/packages/extension-unique-id/src/index.d.ts +0 -3
- package/src/helpers/arrayDifference.ts +0 -35
- package/src/helpers/combineTransactionSteps.ts +0 -18
- package/src/helpers/getChangedRanges.ts +0 -78
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.umd.js","sources":["../src/helpers/removeDuplicates.ts","../src/helpers/findDuplicates.ts","../src/unique-id.ts"],"sourcesContent":["/**\n * Removes duplicated values within an array.\n * Supports numbers, strings and objects.\n */\nexport function removeDuplicates<T>(array: T[], by = JSON.stringify): T[] {\n const seen: Record<any, any> = {}\n\n return array.filter(item => {\n const key = by(item)\n\n return Object.prototype.hasOwnProperty.call(seen, key)\n ? false\n : (seen[key] = true)\n })\n}\n","import { removeDuplicates } from './removeDuplicates.js'\n\n/**\n * Returns a list of duplicated items within an array.\n */\nexport function findDuplicates(items: any[]): any[] {\n const filtered = items.filter((el, index) => items.indexOf(el) !== index)\n const duplicates = removeDuplicates(filtered)\n\n return duplicates\n}\n","import {\n combineTransactionSteps,\n Extension,\n findChildren,\n findChildrenInRange,\n getChangedRanges,\n} from '@tiptap/core'\nimport { Fragment, Node as ProseMirrorNode, Slice } from '@tiptap/pm/model'\nimport { Plugin, PluginKey, Transaction } from '@tiptap/pm/state'\nimport { v4 as uuidv4 } from 'uuid'\n\nimport { findDuplicates } from './helpers/findDuplicates.js'\n\nexport interface UniqueIDOptions {\n attributeName: string,\n types: string[],\n generateID: () => any,\n filterTransaction: ((transaction: Transaction) => boolean) | null,\n}\n\nexport const UniqueID = Extension.create<UniqueIDOptions>({\n name: 'uniqueID',\n\n // we’ll set a very high priority to make sure this runs first\n // and is compatible with `appendTransaction` hooks of other extensions\n priority: 10000,\n\n addOptions() {\n return {\n attributeName: 'id',\n types: [],\n generateID: () => uuidv4(),\n filterTransaction: null,\n }\n },\n\n addGlobalAttributes() {\n return [\n {\n types: this.options.types,\n attributes: {\n [this.options.attributeName]: {\n default: null,\n parseHTML: element => element.getAttribute(`data-${this.options.attributeName}`),\n renderHTML: attributes => {\n if (!attributes[this.options.attributeName]) {\n return {}\n }\n\n return {\n [`data-${this.options.attributeName}`]: attributes[this.options.attributeName],\n }\n },\n },\n },\n },\n ]\n },\n\n // check initial content for missing ids\n onCreate() {\n const collab = this.editor.extensionManager.extensions.find(ext => ext.name === 'collaboration')\n const provider = collab?.options ? collab.options.provider : undefined\n\n const createIds = () => {\n const { view, state } = this.editor\n const { tr, doc } = state\n const { types, attributeName, generateID } = this.options\n const nodesWithoutId = findChildren(doc, node => {\n return types.includes(node.type.name) && node.attrs[attributeName] === null\n })\n\n nodesWithoutId.forEach(({ node, pos }) => {\n tr.setNodeMarkup(pos, undefined, {\n ...node.attrs,\n [attributeName]: generateID(),\n })\n })\n\n tr.setMeta('addToHistory', false)\n\n view.dispatch(tr)\n\n if (provider) {\n provider.off('synced', createIds)\n }\n }\n\n /**\n * We need to handle collaboration a bit different here\n * because we can't automatically add IDs when the provider is not yet synced\n * otherwise we end up with empty paragraphs\n */\n if (collab) {\n if (!provider) {\n return createIds()\n }\n\n provider.on('synced', createIds)\n } else {\n return createIds()\n }\n },\n\n addProseMirrorPlugins() {\n let dragSourceElement: Element | null = null\n let transformPasted = false\n\n return [\n new Plugin({\n key: new PluginKey('uniqueID'),\n\n appendTransaction: (transactions, oldState, newState) => {\n const hasDocChanges = transactions.some(transaction => transaction.docChanged)\n && !oldState.doc.eq(newState.doc)\n const filterTransactions = this.options.filterTransaction\n && transactions.some(tr => !this.options.filterTransaction?.(tr))\n\n const isCollabTransaction = transactions.find(tr => tr.getMeta('y-sync$'))\n\n if (isCollabTransaction) {\n return\n }\n\n if (!hasDocChanges || filterTransactions) {\n return\n }\n\n const { tr } = newState\n\n const { types, attributeName, generateID } = this.options\n const transform = combineTransactionSteps(oldState.doc, transactions as Transaction[])\n const { mapping } = transform\n\n // get changed ranges based on the old state\n const changes = getChangedRanges(transform)\n\n changes.forEach(({ newRange }) => {\n const newNodes = findChildrenInRange(newState.doc, newRange, node => {\n return types.includes(node.type.name)\n })\n\n const newIds = newNodes\n .map(({ node }) => node.attrs[attributeName])\n .filter(id => id !== null)\n\n newNodes.forEach(({ node, pos }, i) => {\n // instead of checking `node.attrs[attributeName]` directly\n // we look at the current state of the node within `tr.doc`.\n // this helps to prevent adding new ids to the same node\n // if the node changed multiple times within one transaction\n const id = tr.doc.nodeAt(pos)?.attrs[attributeName]\n\n if (id === null) {\n tr.setNodeMarkup(pos, undefined, {\n ...node.attrs,\n [attributeName]: generateID(),\n })\n\n return\n }\n\n const nextNode = newNodes[i + 1]\n\n if (nextNode && node.content.size === 0) {\n tr.setNodeMarkup(nextNode.pos, undefined, {\n ...nextNode.node.attrs,\n [attributeName]: id,\n })\n newIds[i + 1] = id\n\n if (nextNode.node.attrs[attributeName]) {\n return\n }\n\n const generatedId = generateID()\n\n tr.setNodeMarkup(pos, undefined, {\n ...node.attrs,\n [attributeName]: generatedId,\n })\n newIds[i] = generatedId\n\n return tr\n }\n\n const duplicatedNewIds = findDuplicates(newIds)\n\n // check if the node doesn’t exist in the old state\n const { deleted } = mapping.invert().mapResult(pos)\n\n const newNode = deleted && duplicatedNewIds.includes(id)\n\n if (newNode) {\n tr.setNodeMarkup(pos, undefined, {\n ...node.attrs,\n [attributeName]: generateID(),\n })\n }\n })\n\n })\n\n if (!tr.steps.length) {\n return\n }\n\n // `tr.setNodeMarkup` resets the stored marks\n // so we’ll restore them if they exist\n tr.setStoredMarks(newState.tr.storedMarks)\n\n return tr\n },\n\n // we register a global drag handler to track the current drag source element\n view(view) {\n const handleDragstart = (event: DragEvent) => {\n dragSourceElement = view.dom.parentElement?.contains(event.target as Element)\n ? view.dom.parentElement\n : null\n }\n\n window.addEventListener('dragstart', handleDragstart)\n\n return {\n destroy() {\n window.removeEventListener('dragstart', handleDragstart)\n },\n }\n },\n\n props: {\n // `handleDOMEvents` is called before `transformPasted`\n // so we can do some checks before\n handleDOMEvents: {\n // only create new ids for dropped content\n // or dropped content while holding `alt`\n // or content is dragged from another editor\n drop: (view, event) => {\n if (\n dragSourceElement !== view.dom.parentElement\n || event.dataTransfer?.effectAllowed === 'copyMove'\n || event.dataTransfer?.effectAllowed === 'copy'\n ) {\n dragSourceElement = null\n transformPasted = true\n }\n\n return false\n },\n // always create new ids on pasted content\n paste: () => {\n transformPasted = true\n\n return false\n },\n },\n\n // we’ll remove ids for every pasted node\n // so we can create a new one within `appendTransaction`\n transformPasted: slice => {\n if (!transformPasted) {\n return slice\n }\n\n const { types, attributeName } = this.options\n const removeId = (fragment: Fragment): Fragment => {\n const list: ProseMirrorNode[] = []\n\n fragment.forEach(node => {\n // don’t touch text nodes\n if (node.isText) {\n list.push(node)\n\n return\n }\n\n // check for any other child nodes\n if (!types.includes(node.type.name)) {\n list.push(node.copy(removeId(node.content)))\n\n return\n }\n\n // remove id\n const nodeWithoutId = node.type.create(\n {\n ...node.attrs,\n [attributeName]: null,\n },\n removeId(node.content),\n node.marks,\n )\n\n list.push(nodeWithoutId)\n })\n\n return Fragment.from(list)\n }\n\n // reset check\n transformPasted = false\n\n return new Slice(removeId(slice.content), slice.openStart, slice.openEnd)\n },\n },\n }),\n ]\n },\n\n})\n"],"names":["Extension","uuidv4","findChildren","Plugin","PluginKey","combineTransactionSteps","getChangedRanges","findChildrenInRange","Fragment","Slice"],"mappings":";;;;;;EAAA;;;EAGG;EACG,SAAU,gBAAgB,CAAI,KAAU,EAAE,EAAE,GAAG,IAAI,CAAC,SAAS,EAAA;MACjE,MAAM,IAAI,GAAqB,EAAE;EAEjC,IAAA,OAAO,KAAK,CAAC,MAAM,CAAC,IAAI,IAAG;EACzB,QAAA,MAAM,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC;UAEpB,OAAO,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG;EACnD,cAAE;iBACC,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;EACxB,KAAC,CAAC;EACJ;;ECZA;;EAEG;EACG,SAAU,cAAc,CAAC,KAAY,EAAA;MACzC,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,KAAK,KAAK,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,KAAK,CAAC;EACzE,IAAA,MAAM,UAAU,GAAG,gBAAgB,CAAC,QAAQ,CAAC;EAE7C,IAAA,OAAO,UAAU;EACnB;;ACUa,QAAA,QAAQ,GAAGA,cAAS,CAAC,MAAM,CAAkB;EACxD,IAAA,IAAI,EAAE,UAAU;;;EAIhB,IAAA,QAAQ,EAAE,KAAK;MAEf,UAAU,GAAA;UACR,OAAO;EACL,YAAA,aAAa,EAAE,IAAI;EACnB,YAAA,KAAK,EAAE,EAAE;EACT,YAAA,UAAU,EAAE,MAAMC,OAAM,EAAE;EAC1B,YAAA,iBAAiB,EAAE,IAAI;WACxB;OACF;MAED,mBAAmB,GAAA;UACjB,OAAO;EACL,YAAA;EACE,gBAAA,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK;EACzB,gBAAA,UAAU,EAAE;EACV,oBAAA,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,GAAG;EAC5B,wBAAA,OAAO,EAAE,IAAI;EACb,wBAAA,SAAS,EAAE,OAAO,IAAI,OAAO,CAAC,YAAY,CAAC,CAAA,KAAA,EAAQ,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;0BAChF,UAAU,EAAE,UAAU,IAAG;8BACvB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE;EAC3C,gCAAA,OAAO,EAAE;;8BAGX,OAAO;EACL,gCAAA,CAAC,QAAQ,IAAI,CAAC,OAAO,CAAC,aAAa,CAAE,CAAA,GAAG,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC;+BAC/E;2BACF;EACF,qBAAA;EACF,iBAAA;EACF,aAAA;WACF;OACF;;MAGD,QAAQ,GAAA;UACN,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,KAAK,eAAe,CAAC;UAChG,MAAM,QAAQ,GAAG,CAAA,MAAM,aAAN,MAAM,KAAA,KAAA,CAAA,GAAA,KAAA,CAAA,GAAN,MAAM,CAAE,OAAO,IAAG,MAAM,CAAC,OAAO,CAAC,QAAQ,GAAG,SAAS;UAEtE,MAAM,SAAS,GAAG,MAAK;cACrB,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,MAAM;EACnC,YAAA,MAAM,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,KAAK;cACzB,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC,OAAO;cACzD,MAAM,cAAc,GAAGC,iBAAY,CAAC,GAAG,EAAE,IAAI,IAAG;EAC9C,gBAAA,OAAO,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,KAAK,IAAI;EAC7E,aAAC,CAAC;cAEF,cAAc,CAAC,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,KAAI;EACvC,gBAAA,EAAE,CAAC,aAAa,CAAC,GAAG,EAAE,SAAS,EAAE;sBAC/B,GAAG,IAAI,CAAC,KAAK;EACb,oBAAA,CAAC,aAAa,GAAG,UAAU,EAAE;EAC9B,iBAAA,CAAC;EACJ,aAAC,CAAC;EAEF,YAAA,EAAE,CAAC,OAAO,CAAC,cAAc,EAAE,KAAK,CAAC;EAEjC,YAAA,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;cAEjB,IAAI,QAAQ,EAAE;EACZ,gBAAA,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAC;;EAErC,SAAC;EAED;;;;EAIG;UACH,IAAI,MAAM,EAAE;cACV,IAAI,CAAC,QAAQ,EAAE;kBACb,OAAO,SAAS,EAAE;;EAGpB,YAAA,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC;;eAC3B;cACL,OAAO,SAAS,EAAE;;OAErB;MAED,qBAAqB,GAAA;UACnB,IAAI,iBAAiB,GAAmB,IAAI;UAC5C,IAAI,eAAe,GAAG,KAAK;UAE3B,OAAO;EACL,YAAA,IAAIC,YAAM,CAAC;EACT,gBAAA,GAAG,EAAE,IAAIC,eAAS,CAAC,UAAU,CAAC;kBAE9B,iBAAiB,EAAE,CAAC,YAAY,EAAE,QAAQ,EAAE,QAAQ,KAAI;EACtD,oBAAA,MAAM,aAAa,GAAG,YAAY,CAAC,IAAI,CAAC,WAAW,IAAI,WAAW,CAAC,UAAU;6BACxE,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC;EACnC,oBAAA,MAAM,kBAAkB,GAAG,IAAI,CAAC,OAAO,CAAC;6BACnC,YAAY,CAAC,IAAI,CAAC,EAAE,IAAI,EAAA,IAAA,EAAA,EAAA,EAAA,CAAA,CAAA,OAAA,EAAC,CAAA,EAAA,GAAA,CAAA,EAAA,GAAA,IAAI,CAAC,OAAO,EAAC,iBAAiB,MAAG,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,IAAA,CAAA,EAAA,EAAA,EAAE,CAAC,CAAA,CAAA,EAAA,CAAC;EAEnE,oBAAA,MAAM,mBAAmB,GAAG,YAAY,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;sBAE1E,IAAI,mBAAmB,EAAE;0BACvB;;EAGF,oBAAA,IAAI,CAAC,aAAa,IAAI,kBAAkB,EAAE;0BACxC;;EAGF,oBAAA,MAAM,EAAE,EAAE,EAAE,GAAG,QAAQ;sBAEvB,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC,OAAO;sBACzD,MAAM,SAAS,GAAGC,4BAAuB,CAAC,QAAQ,CAAC,GAAG,EAAE,YAA6B,CAAC;EACtF,oBAAA,MAAM,EAAE,OAAO,EAAE,GAAG,SAAS;;EAG7B,oBAAA,MAAM,OAAO,GAAGC,qBAAgB,CAAC,SAAS,CAAC;sBAE3C,OAAO,CAAC,OAAO,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAI;EAC/B,wBAAA,MAAM,QAAQ,GAAGC,wBAAmB,CAAC,QAAQ,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,IAAG;8BAClE,OAAO,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;EACvC,yBAAC,CAAC;0BAEF,MAAM,MAAM,GAAG;EACZ,6BAAA,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC;+BAC3C,MAAM,CAAC,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;EAE5B,wBAAA,QAAQ,CAAC,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC,KAAI;;;;;;EAKpC,4BAAA,MAAM,EAAE,GAAG,CAAA,EAAA,GAAA,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,MAAE,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,KAAK,CAAC,aAAa,CAAC;EAEnD,4BAAA,IAAI,EAAE,KAAK,IAAI,EAAE;EACf,gCAAA,EAAE,CAAC,aAAa,CAAC,GAAG,EAAE,SAAS,EAAE;sCAC/B,GAAG,IAAI,CAAC,KAAK;EACb,oCAAA,CAAC,aAAa,GAAG,UAAU,EAAE;EAC9B,iCAAA,CAAC;kCAEF;;8BAGF,MAAM,QAAQ,GAAG,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC;8BAEhC,IAAI,QAAQ,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,EAAE;kCACvC,EAAE,CAAC,aAAa,CAAC,QAAQ,CAAC,GAAG,EAAE,SAAS,EAAE;EACxC,oCAAA,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK;sCACtB,CAAC,aAAa,GAAG,EAAE;EACpB,iCAAA,CAAC;EACF,gCAAA,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE;kCAElB,IAAI,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,EAAE;sCACtC;;EAGF,gCAAA,MAAM,WAAW,GAAG,UAAU,EAAE;EAEhC,gCAAA,EAAE,CAAC,aAAa,CAAC,GAAG,EAAE,SAAS,EAAE;sCAC/B,GAAG,IAAI,CAAC,KAAK;sCACb,CAAC,aAAa,GAAG,WAAW;EAC7B,iCAAA,CAAC;EACF,gCAAA,MAAM,CAAC,CAAC,CAAC,GAAG,WAAW;EAEvB,gCAAA,OAAO,EAAE;;EAGX,4BAAA,MAAM,gBAAgB,GAAG,cAAc,CAAC,MAAM,CAAC;;EAG/C,4BAAA,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC;8BAEnD,MAAM,OAAO,GAAG,OAAO,IAAI,gBAAgB,CAAC,QAAQ,CAAC,EAAE,CAAC;8BAExD,IAAI,OAAO,EAAE;EACX,gCAAA,EAAE,CAAC,aAAa,CAAC,GAAG,EAAE,SAAS,EAAE;sCAC/B,GAAG,IAAI,CAAC,KAAK;EACb,oCAAA,CAAC,aAAa,GAAG,UAAU,EAAE;EAC9B,iCAAA,CAAC;;EAEN,yBAAC,CAAC;EAEJ,qBAAC,CAAC;EAEF,oBAAA,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE;0BACpB;;;;sBAKF,EAAE,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,CAAC,WAAW,CAAC;EAE1C,oBAAA,OAAO,EAAE;mBACV;;EAGD,gBAAA,IAAI,CAAC,IAAI,EAAA;EACP,oBAAA,MAAM,eAAe,GAAG,CAAC,KAAgB,KAAI;;EAC3C,wBAAA,iBAAiB,GAAG,CAAA,CAAA,EAAA,GAAA,IAAI,CAAC,GAAG,CAAC,aAAa,MAAA,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAAE,QAAQ,CAAC,KAAK,CAAC,MAAiB,CAAC;EAC3E,8BAAE,IAAI,CAAC,GAAG,CAAC;gCACT,IAAI;EACV,qBAAC;EAED,oBAAA,MAAM,CAAC,gBAAgB,CAAC,WAAW,EAAE,eAAe,CAAC;sBAErD,OAAO;0BACL,OAAO,GAAA;EACL,4BAAA,MAAM,CAAC,mBAAmB,CAAC,WAAW,EAAE,eAAe,CAAC;2BACzD;uBACF;mBACF;EAED,gBAAA,KAAK,EAAE;;;EAGL,oBAAA,eAAe,EAAE;;;;EAIf,wBAAA,IAAI,EAAE,CAAC,IAAI,EAAE,KAAK,KAAI;;EACpB,4BAAA,IACE,iBAAiB,KAAK,IAAI,CAAC,GAAG,CAAC;EAC5B,mCAAA,CAAA,MAAA,KAAK,CAAC,YAAY,MAAE,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,aAAa,MAAK;qCACtC,CAAA,CAAA,EAAA,GAAA,KAAK,CAAC,YAAY,0CAAE,aAAa,MAAK,MAAM,EAC/C;kCACA,iBAAiB,GAAG,IAAI;kCACxB,eAAe,GAAG,IAAI;;EAGxB,4BAAA,OAAO,KAAK;2BACb;;0BAED,KAAK,EAAE,MAAK;8BACV,eAAe,GAAG,IAAI;EAEtB,4BAAA,OAAO,KAAK;2BACb;EACF,qBAAA;;;sBAID,eAAe,EAAE,KAAK,IAAG;0BACvB,IAAI,CAAC,eAAe,EAAE;EACpB,4BAAA,OAAO,KAAK;;0BAGd,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC,OAAO;EAC7C,wBAAA,MAAM,QAAQ,GAAG,CAAC,QAAkB,KAAc;8BAChD,MAAM,IAAI,GAAsB,EAAE;EAElC,4BAAA,QAAQ,CAAC,OAAO,CAAC,IAAI,IAAG;;EAEtB,gCAAA,IAAI,IAAI,CAAC,MAAM,EAAE;EACf,oCAAA,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;sCAEf;;;EAIF,gCAAA,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;EACnC,oCAAA,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;sCAE5C;;;EAIF,gCAAA,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CACpC;sCACE,GAAG,IAAI,CAAC,KAAK;sCACb,CAAC,aAAa,GAAG,IAAI;mCACtB,EACD,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EACtB,IAAI,CAAC,KAAK,CACX;EAED,gCAAA,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC;EAC1B,6BAAC,CAAC;EAEF,4BAAA,OAAOC,cAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;EAC5B,yBAAC;;0BAGD,eAAe,GAAG,KAAK;EAEvB,wBAAA,OAAO,IAAIC,WAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC;uBAC1E;EACF,iBAAA;eACF,CAAC;WACH;OACF;EAEF,CAAA;;;;;;;;;;;"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { Extension } from '@tiptap/core';
|
|
2
|
-
import { Transaction } from '
|
|
3
|
-
export interface UniqueIDOptions {
|
|
4
|
-
attributeName: string;
|
|
5
|
-
types: string[];
|
|
6
|
-
generateID: () => any;
|
|
7
|
-
filterTransaction: ((transaction: Transaction) => boolean) | null;
|
|
8
|
-
}
|
|
9
|
-
export declare const UniqueID: Extension<UniqueIDOptions>;
|
|
1
|
+
import { Extension } from '@tiptap/core';
|
|
2
|
+
import { Transaction } from '@tiptap/pm/state';
|
|
3
|
+
export interface UniqueIDOptions {
|
|
4
|
+
attributeName: string;
|
|
5
|
+
types: string[];
|
|
6
|
+
generateID: () => any;
|
|
7
|
+
filterTransaction: ((transaction: Transaction) => boolean) | null;
|
|
8
|
+
}
|
|
9
|
+
export declare const UniqueID: Extension<UniqueIDOptions, any>;
|
|
10
|
+
//# sourceMappingURL=unique-id.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unique-id.d.ts","sourceRoot":"","sources":["../src/unique-id.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,SAAS,EAIV,MAAM,cAAc,CAAA;AAErB,OAAO,EAAqB,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAKjE,MAAM,WAAW,eAAe;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,UAAU,EAAE,MAAM,GAAG,CAAC;IACtB,iBAAiB,EAAE,CAAC,CAAC,WAAW,EAAE,WAAW,KAAK,OAAO,CAAC,GAAG,IAAI,CAAC;CACnE;AAED,eAAO,MAAM,QAAQ,iCAkSnB,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tiptap/extension-unique-id",
|
|
3
3
|
"description": "unique id extension for tiptap",
|
|
4
|
-
"version": "2.
|
|
5
|
-
"homepage": "https://tiptap.dev",
|
|
4
|
+
"version": "2.22.0",
|
|
5
|
+
"homepage": "https://tiptap.dev/api/extensions/unique-id",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"tiptap",
|
|
8
8
|
"tiptap extension"
|
|
@@ -12,23 +12,41 @@
|
|
|
12
12
|
"type": "github",
|
|
13
13
|
"url": "https://github.com/sponsors/ueberdosis"
|
|
14
14
|
},
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
"type": "module",
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"import": "./dist/index.js",
|
|
20
|
+
"require": "./dist/index.cjs"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"main": "dist/index.cjs",
|
|
24
|
+
"module": "dist/index.js",
|
|
25
|
+
"umd": "dist/index.umd.js",
|
|
26
|
+
"types": "dist/index.d.ts",
|
|
19
27
|
"files": [
|
|
20
28
|
"src",
|
|
21
29
|
"dist"
|
|
22
30
|
],
|
|
23
31
|
"peerDependencies": {
|
|
24
|
-
"@tiptap/core": "^2.
|
|
32
|
+
"@tiptap/core": "^2.7.0",
|
|
33
|
+
"@tiptap/pm": "^2.7.0"
|
|
25
34
|
},
|
|
26
35
|
"dependencies": {
|
|
27
|
-
"
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
"
|
|
31
|
-
"
|
|
36
|
+
"uuid": "^10.0.0"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@tiptap/core": "^2.22.0",
|
|
40
|
+
"@tiptap/pm": "^2.22.0",
|
|
41
|
+
"@types/uuid": "^10.0.0"
|
|
42
|
+
},
|
|
43
|
+
"repository": {
|
|
44
|
+
"type": "git",
|
|
45
|
+
"url": "https://github.com/ueberdosis/tiptap",
|
|
46
|
+
"directory": "packages/extension-unique-id"
|
|
32
47
|
},
|
|
33
|
-
"
|
|
48
|
+
"scripts": {
|
|
49
|
+
"clean": "rm -rf dist",
|
|
50
|
+
"build": "npm run clean && rollup -c"
|
|
51
|
+
}
|
|
34
52
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import removeDuplicates from './removeDuplicates'
|
|
1
|
+
import { removeDuplicates } from './removeDuplicates.js'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Returns a list of duplicated items within an array.
|
|
5
5
|
*/
|
|
6
|
-
export
|
|
6
|
+
export function findDuplicates(items: any[]): any[] {
|
|
7
7
|
const filtered = items.filter((el, index) => items.indexOf(el) !== index)
|
|
8
8
|
const duplicates = removeDuplicates(filtered)
|
|
9
9
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Removes duplicated values within an array.
|
|
3
3
|
* Supports numbers, strings and objects.
|
|
4
4
|
*/
|
|
5
|
-
export
|
|
5
|
+
export function removeDuplicates<T>(array: T[], by = JSON.stringify): T[] {
|
|
6
6
|
const seen: Record<any, any> = {}
|
|
7
7
|
|
|
8
8
|
return array.filter(item => {
|
package/src/index.ts
CHANGED
package/src/unique-id.ts
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import {
|
|
2
|
+
combineTransactionSteps,
|
|
3
|
+
Extension,
|
|
4
|
+
findChildren,
|
|
5
|
+
findChildrenInRange,
|
|
6
|
+
getChangedRanges,
|
|
7
|
+
} from '@tiptap/core'
|
|
8
|
+
import { Fragment, Node as ProseMirrorNode, Slice } from '@tiptap/pm/model'
|
|
9
|
+
import { Plugin, PluginKey, Transaction } from '@tiptap/pm/state'
|
|
4
10
|
import { v4 as uuidv4 } from 'uuid'
|
|
5
|
-
|
|
6
|
-
import
|
|
7
|
-
import findDuplicates from './helpers/findDuplicates'
|
|
11
|
+
|
|
12
|
+
import { findDuplicates } from './helpers/findDuplicates.js'
|
|
8
13
|
|
|
9
14
|
export interface UniqueIDOptions {
|
|
10
15
|
attributeName: string,
|
|
@@ -20,11 +25,13 @@ export const UniqueID = Extension.create<UniqueIDOptions>({
|
|
|
20
25
|
// and is compatible with `appendTransaction` hooks of other extensions
|
|
21
26
|
priority: 10000,
|
|
22
27
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
addOptions() {
|
|
29
|
+
return {
|
|
30
|
+
attributeName: 'id',
|
|
31
|
+
types: [],
|
|
32
|
+
generateID: () => uuidv4(),
|
|
33
|
+
filterTransaction: null,
|
|
34
|
+
}
|
|
28
35
|
},
|
|
29
36
|
|
|
30
37
|
addGlobalAttributes() {
|
|
@@ -52,22 +59,47 @@ export const UniqueID = Extension.create<UniqueIDOptions>({
|
|
|
52
59
|
|
|
53
60
|
// check initial content for missing ids
|
|
54
61
|
onCreate() {
|
|
55
|
-
const
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
62
|
+
const collab = this.editor.extensionManager.extensions.find(ext => ext.name === 'collaboration')
|
|
63
|
+
const provider = collab?.options ? collab.options.provider : undefined
|
|
64
|
+
|
|
65
|
+
const createIds = () => {
|
|
66
|
+
const { view, state } = this.editor
|
|
67
|
+
const { tr, doc } = state
|
|
68
|
+
const { types, attributeName, generateID } = this.options
|
|
69
|
+
const nodesWithoutId = findChildren(doc, node => {
|
|
70
|
+
return types.includes(node.type.name) && node.attrs[attributeName] === null
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
nodesWithoutId.forEach(({ node, pos }) => {
|
|
74
|
+
tr.setNodeMarkup(pos, undefined, {
|
|
75
|
+
...node.attrs,
|
|
76
|
+
[attributeName]: generateID(),
|
|
77
|
+
})
|
|
67
78
|
})
|
|
68
|
-
})
|
|
69
79
|
|
|
70
|
-
|
|
80
|
+
tr.setMeta('addToHistory', false)
|
|
81
|
+
|
|
82
|
+
view.dispatch(tr)
|
|
83
|
+
|
|
84
|
+
if (provider) {
|
|
85
|
+
provider.off('synced', createIds)
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* We need to handle collaboration a bit different here
|
|
91
|
+
* because we can't automatically add IDs when the provider is not yet synced
|
|
92
|
+
* otherwise we end up with empty paragraphs
|
|
93
|
+
*/
|
|
94
|
+
if (collab) {
|
|
95
|
+
if (!provider) {
|
|
96
|
+
return createIds()
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
provider.on('synced', createIds)
|
|
100
|
+
} else {
|
|
101
|
+
return createIds()
|
|
102
|
+
}
|
|
71
103
|
},
|
|
72
104
|
|
|
73
105
|
addProseMirrorPlugins() {
|
|
@@ -79,29 +111,31 @@ export const UniqueID = Extension.create<UniqueIDOptions>({
|
|
|
79
111
|
key: new PluginKey('uniqueID'),
|
|
80
112
|
|
|
81
113
|
appendTransaction: (transactions, oldState, newState) => {
|
|
82
|
-
const
|
|
114
|
+
const hasDocChanges = transactions.some(transaction => transaction.docChanged)
|
|
83
115
|
&& !oldState.doc.eq(newState.doc)
|
|
84
116
|
const filterTransactions = this.options.filterTransaction
|
|
85
117
|
&& transactions.some(tr => !this.options.filterTransaction?.(tr))
|
|
86
118
|
|
|
87
|
-
|
|
119
|
+
const isCollabTransaction = transactions.find(tr => tr.getMeta('y-sync$'))
|
|
120
|
+
|
|
121
|
+
if (isCollabTransaction) {
|
|
122
|
+
return
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (!hasDocChanges || filterTransactions) {
|
|
88
126
|
return
|
|
89
127
|
}
|
|
90
128
|
|
|
91
129
|
const { tr } = newState
|
|
130
|
+
|
|
92
131
|
const { types, attributeName, generateID } = this.options
|
|
93
|
-
const transform = combineTransactionSteps(oldState.doc, transactions)
|
|
132
|
+
const transform = combineTransactionSteps(oldState.doc, transactions as Transaction[])
|
|
94
133
|
const { mapping } = transform
|
|
95
134
|
|
|
96
135
|
// get changed ranges based on the old state
|
|
97
136
|
const changes = getChangedRanges(transform)
|
|
98
137
|
|
|
99
|
-
changes.forEach(
|
|
100
|
-
const newRange = {
|
|
101
|
-
from: change.newStart,
|
|
102
|
-
to: change.newEnd,
|
|
103
|
-
}
|
|
104
|
-
|
|
138
|
+
changes.forEach(({ newRange }) => {
|
|
105
139
|
const newNodes = findChildrenInRange(newState.doc, newRange, node => {
|
|
106
140
|
return types.includes(node.type.name)
|
|
107
141
|
})
|
|
@@ -110,9 +144,7 @@ export const UniqueID = Extension.create<UniqueIDOptions>({
|
|
|
110
144
|
.map(({ node }) => node.attrs[attributeName])
|
|
111
145
|
.filter(id => id !== null)
|
|
112
146
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
newNodes.forEach(({ node, pos }) => {
|
|
147
|
+
newNodes.forEach(({ node, pos }, i) => {
|
|
116
148
|
// instead of checking `node.attrs[attributeName]` directly
|
|
117
149
|
// we look at the current state of the node within `tr.doc`.
|
|
118
150
|
// this helps to prevent adding new ids to the same node
|
|
@@ -128,8 +160,35 @@ export const UniqueID = Extension.create<UniqueIDOptions>({
|
|
|
128
160
|
return
|
|
129
161
|
}
|
|
130
162
|
|
|
163
|
+
const nextNode = newNodes[i + 1]
|
|
164
|
+
|
|
165
|
+
if (nextNode && node.content.size === 0) {
|
|
166
|
+
tr.setNodeMarkup(nextNode.pos, undefined, {
|
|
167
|
+
...nextNode.node.attrs,
|
|
168
|
+
[attributeName]: id,
|
|
169
|
+
})
|
|
170
|
+
newIds[i + 1] = id
|
|
171
|
+
|
|
172
|
+
if (nextNode.node.attrs[attributeName]) {
|
|
173
|
+
return
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const generatedId = generateID()
|
|
177
|
+
|
|
178
|
+
tr.setNodeMarkup(pos, undefined, {
|
|
179
|
+
...node.attrs,
|
|
180
|
+
[attributeName]: generatedId,
|
|
181
|
+
})
|
|
182
|
+
newIds[i] = generatedId
|
|
183
|
+
|
|
184
|
+
return tr
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const duplicatedNewIds = findDuplicates(newIds)
|
|
188
|
+
|
|
131
189
|
// check if the node doesn’t exist in the old state
|
|
132
190
|
const { deleted } = mapping.invert().mapResult(pos)
|
|
191
|
+
|
|
133
192
|
const newNode = deleted && duplicatedNewIds.includes(id)
|
|
134
193
|
|
|
135
194
|
if (newNode) {
|
|
@@ -146,6 +205,10 @@ export const UniqueID = Extension.create<UniqueIDOptions>({
|
|
|
146
205
|
return
|
|
147
206
|
}
|
|
148
207
|
|
|
208
|
+
// `tr.setNodeMarkup` resets the stored marks
|
|
209
|
+
// so we’ll restore them if they exist
|
|
210
|
+
tr.setStoredMarks(newState.tr.storedMarks)
|
|
211
|
+
|
|
149
212
|
return tr
|
|
150
213
|
},
|
|
151
214
|
|
|
@@ -170,11 +233,13 @@ export const UniqueID = Extension.create<UniqueIDOptions>({
|
|
|
170
233
|
// `handleDOMEvents` is called before `transformPasted`
|
|
171
234
|
// so we can do some checks before
|
|
172
235
|
handleDOMEvents: {
|
|
173
|
-
// only create new ids for dropped content
|
|
236
|
+
// only create new ids for dropped content
|
|
237
|
+
// or dropped content while holding `alt`
|
|
174
238
|
// or content is dragged from another editor
|
|
175
239
|
drop: (view, event) => {
|
|
176
240
|
if (
|
|
177
241
|
dragSourceElement !== view.dom.parentElement
|
|
242
|
+
|| event.dataTransfer?.effectAllowed === 'copyMove'
|
|
178
243
|
|| event.dataTransfer?.effectAllowed === 'copy'
|
|
179
244
|
) {
|
|
180
245
|
dragSourceElement = null
|
|
@@ -226,6 +291,7 @@ export const UniqueID = Extension.create<UniqueIDOptions>({
|
|
|
226
291
|
removeId(node.content),
|
|
227
292
|
node.marks,
|
|
228
293
|
)
|
|
294
|
+
|
|
229
295
|
list.push(nodeWithoutId)
|
|
230
296
|
})
|
|
231
297
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tiptap-extension-unique-id.cjs.js","sources":["../src/helpers/combineTransactionSteps.ts","../src/helpers/removeDuplicates.ts","../src/helpers/getChangedRanges.ts","../src/helpers/findDuplicates.ts","../src/unique-id.ts"],"sourcesContent":["import { Node as ProseMirrorNode } from 'prosemirror-model'\nimport { Transaction } from 'prosemirror-state'\nimport { Transform } from 'prosemirror-transform'\n\n/**\n * Returns a new `Transform` based on all steps of the passed transactions.\n */\nexport default function combineTransactionSteps(oldDoc: ProseMirrorNode, transactions: Transaction[]): Transform {\n const transform = new Transform(oldDoc)\n\n transactions.forEach(transaction => {\n transaction.steps.forEach(step => {\n transform.step(step)\n })\n })\n\n return transform\n}\n","/**\n * Removes duplicated values within an array.\n * Supports numbers, strings and objects.\n */\nexport default function removeDuplicates<T>(array: T[], by = JSON.stringify): T[] {\n const seen: Record<any, any> = {}\n\n return array.filter(item => {\n const key = by(item)\n\n return Object.prototype.hasOwnProperty.call(seen, key)\n ? false\n : (seen[key] = true)\n })\n}\n","import { Transform, Step } from 'prosemirror-transform'\nimport removeDuplicates from './removeDuplicates'\n\nexport type ChangedRange = {\n oldStart: number,\n oldEnd: number,\n newStart: number,\n newEnd: number,\n}\n\n/**\n * Removes duplicated ranges and ranges that are\n * fully captured by other ranges.\n */\nfunction simplifyChangedRanges(changes: ChangedRange[]): ChangedRange[] {\n const uniqueChanges = removeDuplicates(changes)\n\n return uniqueChanges.length === 1\n ? uniqueChanges\n : uniqueChanges.filter((change, index) => {\n const rest = uniqueChanges.filter((_, i) => i !== index)\n\n return !rest.some(otherChange => {\n return change.oldStart >= otherChange.oldStart\n && change.oldEnd <= otherChange.oldEnd\n && change.newStart >= otherChange.newStart\n && change.newEnd <= otherChange.newEnd\n })\n })\n}\n\n/**\n * Returns a list of changed ranges\n * based on the first and last state of all steps.\n */\nexport default function getChangedRanges(transform: Transform): ChangedRange[] {\n const { mapping, steps } = transform\n const changes: ChangedRange[] = []\n\n mapping.maps.forEach((stepMap, index) => {\n // This accounts for step changes where no range was actually altered\n // e.g. when setting a mark, node attribute, etc.\n // @ts-ignore\n if (!stepMap.ranges.length) {\n const step = steps[index] as Step & {\n from?: number,\n to?: number,\n }\n\n if (step.from === undefined || step.to === undefined) {\n return\n }\n\n changes.push({\n oldStart: step.from,\n oldEnd: step.to,\n newStart: step.from,\n newEnd: step.to,\n })\n } else {\n stepMap.forEach((from, to) => {\n const newStart = mapping.slice(index).map(from, -1)\n const newEnd = mapping.slice(index).map(to)\n const oldStart = mapping.invert().map(newStart, -1)\n const oldEnd = mapping.invert().map(newEnd)\n\n changes.push({\n oldStart,\n oldEnd,\n newStart,\n newEnd,\n })\n })\n }\n })\n\n return simplifyChangedRanges(changes)\n}\n","import removeDuplicates from './removeDuplicates'\n\n/**\n * Returns a list of duplicated items within an array.\n */\nexport default function findDuplicates(items: any[]): any[] {\n const filtered = items.filter((el, index) => items.indexOf(el) !== index)\n const duplicates = removeDuplicates(filtered)\n\n return duplicates\n}\n","import { Extension, findChildren, findChildrenInRange } from '@tiptap/core'\nimport { Plugin, PluginKey, Transaction } from 'prosemirror-state'\nimport { Slice, Fragment, Node as ProseMirrorNode } from 'prosemirror-model'\nimport { v4 as uuidv4 } from 'uuid'\nimport combineTransactionSteps from './helpers/combineTransactionSteps'\nimport getChangedRanges from './helpers/getChangedRanges'\nimport findDuplicates from './helpers/findDuplicates'\n\nexport interface UniqueIDOptions {\n attributeName: string,\n types: string[],\n generateID: () => any,\n filterTransaction: ((transaction: Transaction) => boolean) | null,\n}\n\nexport const UniqueID = Extension.create<UniqueIDOptions>({\n name: 'uniqueID',\n\n // we’ll set a very high priority to make sure this runs first\n // and is compatible with `appendTransaction` hooks of other extensions\n priority: 10000,\n\n defaultOptions: {\n attributeName: 'id',\n types: [],\n generateID: () => uuidv4(),\n filterTransaction: null,\n },\n\n addGlobalAttributes() {\n return [\n {\n types: this.options.types,\n attributes: {\n [this.options.attributeName]: {\n default: null,\n parseHTML: element => element.getAttribute(`data-${this.options.attributeName}`),\n renderHTML: attributes => {\n if (!attributes[this.options.attributeName]) {\n return {}\n }\n\n return {\n [`data-${this.options.attributeName}`]: attributes[this.options.attributeName],\n }\n },\n },\n },\n },\n ]\n },\n\n // check initial content for missing ids\n onCreate() {\n const { view, state } = this.editor\n const { tr, doc } = state\n const { types, attributeName, generateID } = this.options\n const nodesWithoutId = findChildren(doc, node => {\n return types.includes(node.type.name)\n && node.attrs[attributeName] === null\n })\n\n nodesWithoutId.forEach(({ node, pos }) => {\n tr.setNodeMarkup(pos, undefined, {\n ...node.attrs,\n [attributeName]: generateID(),\n })\n })\n\n view.dispatch(tr)\n },\n\n addProseMirrorPlugins() {\n let dragSourceElement: Element | null = null\n let transformPasted = false\n\n return [\n new Plugin({\n key: new PluginKey('uniqueID'),\n\n appendTransaction: (transactions, oldState, newState) => {\n const docChanges = transactions.some(transaction => transaction.docChanged)\n && !oldState.doc.eq(newState.doc)\n const filterTransactions = this.options.filterTransaction\n && transactions.some(tr => !this.options.filterTransaction?.(tr))\n\n if (!docChanges || filterTransactions) {\n return\n }\n\n const { tr } = newState\n const { types, attributeName, generateID } = this.options\n const transform = combineTransactionSteps(oldState.doc, transactions)\n const { mapping } = transform\n\n // get changed ranges based on the old state\n const changes = getChangedRanges(transform)\n\n changes.forEach(change => {\n const newRange = {\n from: change.newStart,\n to: change.newEnd,\n }\n\n const newNodes = findChildrenInRange(newState.doc, newRange, node => {\n return types.includes(node.type.name)\n })\n\n const newIds = newNodes\n .map(({ node }) => node.attrs[attributeName])\n .filter(id => id !== null)\n\n const duplicatedNewIds = findDuplicates(newIds)\n\n newNodes.forEach(({ node, pos }) => {\n // instead of checking `node.attrs[attributeName]` directly\n // we look at the current state of the node within `tr.doc`.\n // this helps to prevent adding new ids to the same node\n // if the node changed multiple times within one transaction\n const id = tr.doc.nodeAt(pos)?.attrs[attributeName]\n\n if (id === null) {\n tr.setNodeMarkup(pos, undefined, {\n ...node.attrs,\n [attributeName]: generateID(),\n })\n\n return\n }\n\n // check if the node doesn’t exist in the old state\n const { deleted } = mapping.invert().mapResult(pos)\n const newNode = deleted && duplicatedNewIds.includes(id)\n\n if (newNode) {\n tr.setNodeMarkup(pos, undefined, {\n ...node.attrs,\n [attributeName]: generateID(),\n })\n }\n })\n\n })\n\n if (!tr.steps.length) {\n return\n }\n\n return tr\n },\n\n // we register a global drag handler to track the current drag source element\n view(view) {\n const handleDragstart = (event: DragEvent) => {\n dragSourceElement = view.dom.parentElement?.contains(event.target as Element)\n ? view.dom.parentElement\n : null\n }\n\n window.addEventListener('dragstart', handleDragstart)\n\n return {\n destroy() {\n window.removeEventListener('dragstart', handleDragstart)\n },\n }\n },\n\n props: {\n // `handleDOMEvents` is called before `transformPasted`\n // so we can do some checks before\n handleDOMEvents: {\n // only create new ids for dropped content while holding `alt`\n // or content is dragged from another editor\n drop: (view, event) => {\n if (\n dragSourceElement !== view.dom.parentElement\n || event.dataTransfer?.effectAllowed === 'copy'\n ) {\n dragSourceElement = null\n transformPasted = true\n }\n\n return false\n },\n // always create new ids on pasted content\n paste: () => {\n transformPasted = true\n\n return false\n },\n },\n\n // we’ll remove ids for every pasted node\n // so we can create a new one within `appendTransaction`\n transformPasted: slice => {\n if (!transformPasted) {\n return slice\n }\n\n const { types, attributeName } = this.options\n const removeId = (fragment: Fragment): Fragment => {\n const list: ProseMirrorNode[] = []\n\n fragment.forEach(node => {\n // don’t touch text nodes\n if (node.isText) {\n list.push(node)\n\n return\n }\n\n // check for any other child nodes\n if (!types.includes(node.type.name)) {\n list.push(node.copy(removeId(node.content)))\n\n return\n }\n\n // remove id\n const nodeWithoutId = node.type.create(\n {\n ...node.attrs,\n [attributeName]: null,\n },\n removeId(node.content),\n node.marks,\n )\n list.push(nodeWithoutId)\n })\n\n return Fragment.from(list)\n }\n\n // reset check\n transformPasted = false\n\n return new Slice(removeId(slice.content), slice.openStart, slice.openEnd)\n },\n },\n }),\n ]\n },\n\n})\n"],"names":["Transform","Extension","uuidv4","findChildren","Plugin","PluginKey","findChildrenInRange","Fragment","Slice"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tiptap-extension-unique-id.esm.js","sources":["../src/helpers/combineTransactionSteps.ts","../src/helpers/removeDuplicates.ts","../src/helpers/getChangedRanges.ts","../src/helpers/findDuplicates.ts","../src/unique-id.ts"],"sourcesContent":["import { Node as ProseMirrorNode } from 'prosemirror-model'\nimport { Transaction } from 'prosemirror-state'\nimport { Transform } from 'prosemirror-transform'\n\n/**\n * Returns a new `Transform` based on all steps of the passed transactions.\n */\nexport default function combineTransactionSteps(oldDoc: ProseMirrorNode, transactions: Transaction[]): Transform {\n const transform = new Transform(oldDoc)\n\n transactions.forEach(transaction => {\n transaction.steps.forEach(step => {\n transform.step(step)\n })\n })\n\n return transform\n}\n","/**\n * Removes duplicated values within an array.\n * Supports numbers, strings and objects.\n */\nexport default function removeDuplicates<T>(array: T[], by = JSON.stringify): T[] {\n const seen: Record<any, any> = {}\n\n return array.filter(item => {\n const key = by(item)\n\n return Object.prototype.hasOwnProperty.call(seen, key)\n ? false\n : (seen[key] = true)\n })\n}\n","import { Transform, Step } from 'prosemirror-transform'\nimport removeDuplicates from './removeDuplicates'\n\nexport type ChangedRange = {\n oldStart: number,\n oldEnd: number,\n newStart: number,\n newEnd: number,\n}\n\n/**\n * Removes duplicated ranges and ranges that are\n * fully captured by other ranges.\n */\nfunction simplifyChangedRanges(changes: ChangedRange[]): ChangedRange[] {\n const uniqueChanges = removeDuplicates(changes)\n\n return uniqueChanges.length === 1\n ? uniqueChanges\n : uniqueChanges.filter((change, index) => {\n const rest = uniqueChanges.filter((_, i) => i !== index)\n\n return !rest.some(otherChange => {\n return change.oldStart >= otherChange.oldStart\n && change.oldEnd <= otherChange.oldEnd\n && change.newStart >= otherChange.newStart\n && change.newEnd <= otherChange.newEnd\n })\n })\n}\n\n/**\n * Returns a list of changed ranges\n * based on the first and last state of all steps.\n */\nexport default function getChangedRanges(transform: Transform): ChangedRange[] {\n const { mapping, steps } = transform\n const changes: ChangedRange[] = []\n\n mapping.maps.forEach((stepMap, index) => {\n // This accounts for step changes where no range was actually altered\n // e.g. when setting a mark, node attribute, etc.\n // @ts-ignore\n if (!stepMap.ranges.length) {\n const step = steps[index] as Step & {\n from?: number,\n to?: number,\n }\n\n if (step.from === undefined || step.to === undefined) {\n return\n }\n\n changes.push({\n oldStart: step.from,\n oldEnd: step.to,\n newStart: step.from,\n newEnd: step.to,\n })\n } else {\n stepMap.forEach((from, to) => {\n const newStart = mapping.slice(index).map(from, -1)\n const newEnd = mapping.slice(index).map(to)\n const oldStart = mapping.invert().map(newStart, -1)\n const oldEnd = mapping.invert().map(newEnd)\n\n changes.push({\n oldStart,\n oldEnd,\n newStart,\n newEnd,\n })\n })\n }\n })\n\n return simplifyChangedRanges(changes)\n}\n","import removeDuplicates from './removeDuplicates'\n\n/**\n * Returns a list of duplicated items within an array.\n */\nexport default function findDuplicates(items: any[]): any[] {\n const filtered = items.filter((el, index) => items.indexOf(el) !== index)\n const duplicates = removeDuplicates(filtered)\n\n return duplicates\n}\n","import { Extension, findChildren, findChildrenInRange } from '@tiptap/core'\nimport { Plugin, PluginKey, Transaction } from 'prosemirror-state'\nimport { Slice, Fragment, Node as ProseMirrorNode } from 'prosemirror-model'\nimport { v4 as uuidv4 } from 'uuid'\nimport combineTransactionSteps from './helpers/combineTransactionSteps'\nimport getChangedRanges from './helpers/getChangedRanges'\nimport findDuplicates from './helpers/findDuplicates'\n\nexport interface UniqueIDOptions {\n attributeName: string,\n types: string[],\n generateID: () => any,\n filterTransaction: ((transaction: Transaction) => boolean) | null,\n}\n\nexport const UniqueID = Extension.create<UniqueIDOptions>({\n name: 'uniqueID',\n\n // we’ll set a very high priority to make sure this runs first\n // and is compatible with `appendTransaction` hooks of other extensions\n priority: 10000,\n\n defaultOptions: {\n attributeName: 'id',\n types: [],\n generateID: () => uuidv4(),\n filterTransaction: null,\n },\n\n addGlobalAttributes() {\n return [\n {\n types: this.options.types,\n attributes: {\n [this.options.attributeName]: {\n default: null,\n parseHTML: element => element.getAttribute(`data-${this.options.attributeName}`),\n renderHTML: attributes => {\n if (!attributes[this.options.attributeName]) {\n return {}\n }\n\n return {\n [`data-${this.options.attributeName}`]: attributes[this.options.attributeName],\n }\n },\n },\n },\n },\n ]\n },\n\n // check initial content for missing ids\n onCreate() {\n const { view, state } = this.editor\n const { tr, doc } = state\n const { types, attributeName, generateID } = this.options\n const nodesWithoutId = findChildren(doc, node => {\n return types.includes(node.type.name)\n && node.attrs[attributeName] === null\n })\n\n nodesWithoutId.forEach(({ node, pos }) => {\n tr.setNodeMarkup(pos, undefined, {\n ...node.attrs,\n [attributeName]: generateID(),\n })\n })\n\n view.dispatch(tr)\n },\n\n addProseMirrorPlugins() {\n let dragSourceElement: Element | null = null\n let transformPasted = false\n\n return [\n new Plugin({\n key: new PluginKey('uniqueID'),\n\n appendTransaction: (transactions, oldState, newState) => {\n const docChanges = transactions.some(transaction => transaction.docChanged)\n && !oldState.doc.eq(newState.doc)\n const filterTransactions = this.options.filterTransaction\n && transactions.some(tr => !this.options.filterTransaction?.(tr))\n\n if (!docChanges || filterTransactions) {\n return\n }\n\n const { tr } = newState\n const { types, attributeName, generateID } = this.options\n const transform = combineTransactionSteps(oldState.doc, transactions)\n const { mapping } = transform\n\n // get changed ranges based on the old state\n const changes = getChangedRanges(transform)\n\n changes.forEach(change => {\n const newRange = {\n from: change.newStart,\n to: change.newEnd,\n }\n\n const newNodes = findChildrenInRange(newState.doc, newRange, node => {\n return types.includes(node.type.name)\n })\n\n const newIds = newNodes\n .map(({ node }) => node.attrs[attributeName])\n .filter(id => id !== null)\n\n const duplicatedNewIds = findDuplicates(newIds)\n\n newNodes.forEach(({ node, pos }) => {\n // instead of checking `node.attrs[attributeName]` directly\n // we look at the current state of the node within `tr.doc`.\n // this helps to prevent adding new ids to the same node\n // if the node changed multiple times within one transaction\n const id = tr.doc.nodeAt(pos)?.attrs[attributeName]\n\n if (id === null) {\n tr.setNodeMarkup(pos, undefined, {\n ...node.attrs,\n [attributeName]: generateID(),\n })\n\n return\n }\n\n // check if the node doesn’t exist in the old state\n const { deleted } = mapping.invert().mapResult(pos)\n const newNode = deleted && duplicatedNewIds.includes(id)\n\n if (newNode) {\n tr.setNodeMarkup(pos, undefined, {\n ...node.attrs,\n [attributeName]: generateID(),\n })\n }\n })\n\n })\n\n if (!tr.steps.length) {\n return\n }\n\n return tr\n },\n\n // we register a global drag handler to track the current drag source element\n view(view) {\n const handleDragstart = (event: DragEvent) => {\n dragSourceElement = view.dom.parentElement?.contains(event.target as Element)\n ? view.dom.parentElement\n : null\n }\n\n window.addEventListener('dragstart', handleDragstart)\n\n return {\n destroy() {\n window.removeEventListener('dragstart', handleDragstart)\n },\n }\n },\n\n props: {\n // `handleDOMEvents` is called before `transformPasted`\n // so we can do some checks before\n handleDOMEvents: {\n // only create new ids for dropped content while holding `alt`\n // or content is dragged from another editor\n drop: (view, event) => {\n if (\n dragSourceElement !== view.dom.parentElement\n || event.dataTransfer?.effectAllowed === 'copy'\n ) {\n dragSourceElement = null\n transformPasted = true\n }\n\n return false\n },\n // always create new ids on pasted content\n paste: () => {\n transformPasted = true\n\n return false\n },\n },\n\n // we’ll remove ids for every pasted node\n // so we can create a new one within `appendTransaction`\n transformPasted: slice => {\n if (!transformPasted) {\n return slice\n }\n\n const { types, attributeName } = this.options\n const removeId = (fragment: Fragment): Fragment => {\n const list: ProseMirrorNode[] = []\n\n fragment.forEach(node => {\n // don’t touch text nodes\n if (node.isText) {\n list.push(node)\n\n return\n }\n\n // check for any other child nodes\n if (!types.includes(node.type.name)) {\n list.push(node.copy(removeId(node.content)))\n\n return\n }\n\n // remove id\n const nodeWithoutId = node.type.create(\n {\n ...node.attrs,\n [attributeName]: null,\n },\n removeId(node.content),\n node.marks,\n )\n list.push(nodeWithoutId)\n })\n\n return Fragment.from(list)\n }\n\n // reset check\n transformPasted = false\n\n return new Slice(removeId(slice.content), slice.openStart, slice.openEnd)\n },\n },\n }),\n ]\n },\n\n})\n"],"names":["uuidv4"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tiptap-extension-unique-id.umd.js","sources":["../src/helpers/combineTransactionSteps.ts","../src/helpers/removeDuplicates.ts","../src/helpers/getChangedRanges.ts","../src/helpers/findDuplicates.ts","../src/unique-id.ts"],"sourcesContent":["import { Node as ProseMirrorNode } from 'prosemirror-model'\nimport { Transaction } from 'prosemirror-state'\nimport { Transform } from 'prosemirror-transform'\n\n/**\n * Returns a new `Transform` based on all steps of the passed transactions.\n */\nexport default function combineTransactionSteps(oldDoc: ProseMirrorNode, transactions: Transaction[]): Transform {\n const transform = new Transform(oldDoc)\n\n transactions.forEach(transaction => {\n transaction.steps.forEach(step => {\n transform.step(step)\n })\n })\n\n return transform\n}\n","/**\n * Removes duplicated values within an array.\n * Supports numbers, strings and objects.\n */\nexport default function removeDuplicates<T>(array: T[], by = JSON.stringify): T[] {\n const seen: Record<any, any> = {}\n\n return array.filter(item => {\n const key = by(item)\n\n return Object.prototype.hasOwnProperty.call(seen, key)\n ? false\n : (seen[key] = true)\n })\n}\n","import { Transform, Step } from 'prosemirror-transform'\nimport removeDuplicates from './removeDuplicates'\n\nexport type ChangedRange = {\n oldStart: number,\n oldEnd: number,\n newStart: number,\n newEnd: number,\n}\n\n/**\n * Removes duplicated ranges and ranges that are\n * fully captured by other ranges.\n */\nfunction simplifyChangedRanges(changes: ChangedRange[]): ChangedRange[] {\n const uniqueChanges = removeDuplicates(changes)\n\n return uniqueChanges.length === 1\n ? uniqueChanges\n : uniqueChanges.filter((change, index) => {\n const rest = uniqueChanges.filter((_, i) => i !== index)\n\n return !rest.some(otherChange => {\n return change.oldStart >= otherChange.oldStart\n && change.oldEnd <= otherChange.oldEnd\n && change.newStart >= otherChange.newStart\n && change.newEnd <= otherChange.newEnd\n })\n })\n}\n\n/**\n * Returns a list of changed ranges\n * based on the first and last state of all steps.\n */\nexport default function getChangedRanges(transform: Transform): ChangedRange[] {\n const { mapping, steps } = transform\n const changes: ChangedRange[] = []\n\n mapping.maps.forEach((stepMap, index) => {\n // This accounts for step changes where no range was actually altered\n // e.g. when setting a mark, node attribute, etc.\n // @ts-ignore\n if (!stepMap.ranges.length) {\n const step = steps[index] as Step & {\n from?: number,\n to?: number,\n }\n\n if (step.from === undefined || step.to === undefined) {\n return\n }\n\n changes.push({\n oldStart: step.from,\n oldEnd: step.to,\n newStart: step.from,\n newEnd: step.to,\n })\n } else {\n stepMap.forEach((from, to) => {\n const newStart = mapping.slice(index).map(from, -1)\n const newEnd = mapping.slice(index).map(to)\n const oldStart = mapping.invert().map(newStart, -1)\n const oldEnd = mapping.invert().map(newEnd)\n\n changes.push({\n oldStart,\n oldEnd,\n newStart,\n newEnd,\n })\n })\n }\n })\n\n return simplifyChangedRanges(changes)\n}\n","import removeDuplicates from './removeDuplicates'\n\n/**\n * Returns a list of duplicated items within an array.\n */\nexport default function findDuplicates(items: any[]): any[] {\n const filtered = items.filter((el, index) => items.indexOf(el) !== index)\n const duplicates = removeDuplicates(filtered)\n\n return duplicates\n}\n","import { Extension, findChildren, findChildrenInRange } from '@tiptap/core'\nimport { Plugin, PluginKey, Transaction } from 'prosemirror-state'\nimport { Slice, Fragment, Node as ProseMirrorNode } from 'prosemirror-model'\nimport { v4 as uuidv4 } from 'uuid'\nimport combineTransactionSteps from './helpers/combineTransactionSteps'\nimport getChangedRanges from './helpers/getChangedRanges'\nimport findDuplicates from './helpers/findDuplicates'\n\nexport interface UniqueIDOptions {\n attributeName: string,\n types: string[],\n generateID: () => any,\n filterTransaction: ((transaction: Transaction) => boolean) | null,\n}\n\nexport const UniqueID = Extension.create<UniqueIDOptions>({\n name: 'uniqueID',\n\n // we’ll set a very high priority to make sure this runs first\n // and is compatible with `appendTransaction` hooks of other extensions\n priority: 10000,\n\n defaultOptions: {\n attributeName: 'id',\n types: [],\n generateID: () => uuidv4(),\n filterTransaction: null,\n },\n\n addGlobalAttributes() {\n return [\n {\n types: this.options.types,\n attributes: {\n [this.options.attributeName]: {\n default: null,\n parseHTML: element => element.getAttribute(`data-${this.options.attributeName}`),\n renderHTML: attributes => {\n if (!attributes[this.options.attributeName]) {\n return {}\n }\n\n return {\n [`data-${this.options.attributeName}`]: attributes[this.options.attributeName],\n }\n },\n },\n },\n },\n ]\n },\n\n // check initial content for missing ids\n onCreate() {\n const { view, state } = this.editor\n const { tr, doc } = state\n const { types, attributeName, generateID } = this.options\n const nodesWithoutId = findChildren(doc, node => {\n return types.includes(node.type.name)\n && node.attrs[attributeName] === null\n })\n\n nodesWithoutId.forEach(({ node, pos }) => {\n tr.setNodeMarkup(pos, undefined, {\n ...node.attrs,\n [attributeName]: generateID(),\n })\n })\n\n view.dispatch(tr)\n },\n\n addProseMirrorPlugins() {\n let dragSourceElement: Element | null = null\n let transformPasted = false\n\n return [\n new Plugin({\n key: new PluginKey('uniqueID'),\n\n appendTransaction: (transactions, oldState, newState) => {\n const docChanges = transactions.some(transaction => transaction.docChanged)\n && !oldState.doc.eq(newState.doc)\n const filterTransactions = this.options.filterTransaction\n && transactions.some(tr => !this.options.filterTransaction?.(tr))\n\n if (!docChanges || filterTransactions) {\n return\n }\n\n const { tr } = newState\n const { types, attributeName, generateID } = this.options\n const transform = combineTransactionSteps(oldState.doc, transactions)\n const { mapping } = transform\n\n // get changed ranges based on the old state\n const changes = getChangedRanges(transform)\n\n changes.forEach(change => {\n const newRange = {\n from: change.newStart,\n to: change.newEnd,\n }\n\n const newNodes = findChildrenInRange(newState.doc, newRange, node => {\n return types.includes(node.type.name)\n })\n\n const newIds = newNodes\n .map(({ node }) => node.attrs[attributeName])\n .filter(id => id !== null)\n\n const duplicatedNewIds = findDuplicates(newIds)\n\n newNodes.forEach(({ node, pos }) => {\n // instead of checking `node.attrs[attributeName]` directly\n // we look at the current state of the node within `tr.doc`.\n // this helps to prevent adding new ids to the same node\n // if the node changed multiple times within one transaction\n const id = tr.doc.nodeAt(pos)?.attrs[attributeName]\n\n if (id === null) {\n tr.setNodeMarkup(pos, undefined, {\n ...node.attrs,\n [attributeName]: generateID(),\n })\n\n return\n }\n\n // check if the node doesn’t exist in the old state\n const { deleted } = mapping.invert().mapResult(pos)\n const newNode = deleted && duplicatedNewIds.includes(id)\n\n if (newNode) {\n tr.setNodeMarkup(pos, undefined, {\n ...node.attrs,\n [attributeName]: generateID(),\n })\n }\n })\n\n })\n\n if (!tr.steps.length) {\n return\n }\n\n return tr\n },\n\n // we register a global drag handler to track the current drag source element\n view(view) {\n const handleDragstart = (event: DragEvent) => {\n dragSourceElement = view.dom.parentElement?.contains(event.target as Element)\n ? view.dom.parentElement\n : null\n }\n\n window.addEventListener('dragstart', handleDragstart)\n\n return {\n destroy() {\n window.removeEventListener('dragstart', handleDragstart)\n },\n }\n },\n\n props: {\n // `handleDOMEvents` is called before `transformPasted`\n // so we can do some checks before\n handleDOMEvents: {\n // only create new ids for dropped content while holding `alt`\n // or content is dragged from another editor\n drop: (view, event) => {\n if (\n dragSourceElement !== view.dom.parentElement\n || event.dataTransfer?.effectAllowed === 'copy'\n ) {\n dragSourceElement = null\n transformPasted = true\n }\n\n return false\n },\n // always create new ids on pasted content\n paste: () => {\n transformPasted = true\n\n return false\n },\n },\n\n // we’ll remove ids for every pasted node\n // so we can create a new one within `appendTransaction`\n transformPasted: slice => {\n if (!transformPasted) {\n return slice\n }\n\n const { types, attributeName } = this.options\n const removeId = (fragment: Fragment): Fragment => {\n const list: ProseMirrorNode[] = []\n\n fragment.forEach(node => {\n // don’t touch text nodes\n if (node.isText) {\n list.push(node)\n\n return\n }\n\n // check for any other child nodes\n if (!types.includes(node.type.name)) {\n list.push(node.copy(removeId(node.content)))\n\n return\n }\n\n // remove id\n const nodeWithoutId = node.type.create(\n {\n ...node.attrs,\n [attributeName]: null,\n },\n removeId(node.content),\n node.marks,\n )\n list.push(nodeWithoutId)\n })\n\n return Fragment.from(list)\n }\n\n // reset check\n transformPasted = false\n\n return new Slice(removeId(slice.content), slice.openStart, slice.openEnd)\n },\n },\n }),\n ]\n },\n\n})\n"],"names":["Transform","Extension","uuidv4","findChildren","Plugin","PluginKey","findChildrenInRange","Fragment","Slice"],"mappings":"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"}
|
package/dist/tiptap-pro/packages/extension-unique-id/src/helpers/combineTransactionSteps.d.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { Node as ProseMirrorNode } from 'prosemirror-model';
|
|
2
|
-
import { Transaction } from 'prosemirror-state';
|
|
3
|
-
import { Transform } from 'prosemirror-transform';
|
|
4
|
-
/**
|
|
5
|
-
* Returns a new `Transform` based on all steps of the passed transactions.
|
|
6
|
-
*/
|
|
7
|
-
export default function combineTransactionSteps(oldDoc: ProseMirrorNode, transactions: Transaction[]): Transform;
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { Transform } from 'prosemirror-transform';
|
|
2
|
-
export declare type ChangedRange = {
|
|
3
|
-
oldStart: number;
|
|
4
|
-
oldEnd: number;
|
|
5
|
-
newStart: number;
|
|
6
|
-
newEnd: number;
|
|
7
|
-
};
|
|
8
|
-
/**
|
|
9
|
-
* Returns a list of changed ranges
|
|
10
|
-
* based on the first and last state of all steps.
|
|
11
|
-
*/
|
|
12
|
-
export default function getChangedRanges(transform: Transform): ChangedRange[];
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Removes duplicated values within an array.
|
|
3
|
-
* Supports numbers, strings and objects.
|
|
4
|
-
*/
|
|
5
|
-
export default function removeDuplicates<T>(array: T[], by?: {
|
|
6
|
-
(value: any, replacer?: ((this: any, key: string, value: any) => any) | undefined, space?: string | number | undefined): string;
|
|
7
|
-
(value: any, replacer?: (string | number)[] | null | undefined, space?: string | number | undefined): string;
|
|
8
|
-
}): T[];
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import removeDuplicates from './removeDuplicates'
|
|
2
|
-
|
|
3
|
-
export interface ArrayDifference {
|
|
4
|
-
added: any[],
|
|
5
|
-
removed: any[],
|
|
6
|
-
common: any[],
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Checks for added, removed and common items between two arrays.
|
|
11
|
-
*/
|
|
12
|
-
export default function arrayDifference(array1: any[], array2: any[]): ArrayDifference {
|
|
13
|
-
const uniqueCombinedArray = removeDuplicates([...array1, ...array2])
|
|
14
|
-
const data: ArrayDifference = {
|
|
15
|
-
added: [],
|
|
16
|
-
removed: [],
|
|
17
|
-
common: [],
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
uniqueCombinedArray.forEach(item => {
|
|
21
|
-
if (!array1.includes(item) && array2.includes(item)) {
|
|
22
|
-
data.added.push(item)
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
if (array1.includes(item) && !array2.includes(item)) {
|
|
26
|
-
data.removed.push(item)
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
if (array1.includes(item) && array2.includes(item)) {
|
|
30
|
-
data.common.push(item)
|
|
31
|
-
}
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
return data
|
|
35
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { Node as ProseMirrorNode } from 'prosemirror-model'
|
|
2
|
-
import { Transaction } from 'prosemirror-state'
|
|
3
|
-
import { Transform } from 'prosemirror-transform'
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Returns a new `Transform` based on all steps of the passed transactions.
|
|
7
|
-
*/
|
|
8
|
-
export default function combineTransactionSteps(oldDoc: ProseMirrorNode, transactions: Transaction[]): Transform {
|
|
9
|
-
const transform = new Transform(oldDoc)
|
|
10
|
-
|
|
11
|
-
transactions.forEach(transaction => {
|
|
12
|
-
transaction.steps.forEach(step => {
|
|
13
|
-
transform.step(step)
|
|
14
|
-
})
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
return transform
|
|
18
|
-
}
|