@tiptap/extension-unique-id 2.26.3 → 2.27.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/index.cjs CHANGED
@@ -41,6 +41,7 @@ const UniqueID = core.Extension.create({
41
41
  types: [],
42
42
  generateID: () => uuid.v4(),
43
43
  filterTransaction: null,
44
+ updateDocument: true,
44
45
  };
45
46
  },
46
47
  addGlobalAttributes() {
@@ -66,6 +67,9 @@ const UniqueID = core.Extension.create({
66
67
  },
67
68
  // check initial content for missing ids
68
69
  onCreate() {
70
+ if (!this.options.updateDocument) {
71
+ return;
72
+ }
69
73
  const collab = this.editor.extensionManager.extensions.find(ext => ext.name === 'collaboration');
70
74
  const provider = (collab === null || collab === void 0 ? void 0 : collab.options) ? collab.options.provider : undefined;
71
75
  const createIds = () => {
@@ -103,6 +107,9 @@ const UniqueID = core.Extension.create({
103
107
  }
104
108
  },
105
109
  addProseMirrorPlugins() {
110
+ if (!this.options.updateDocument) {
111
+ return [];
112
+ }
106
113
  let dragSourceElement = null;
107
114
  let transformPasted = false;
108
115
  return [
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","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":"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"}
1
+ {"version":3,"file":"index.cjs","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 * Whether to update the document by adding unique IDs to the nodes. Set this\n * property to `false` if the document is in `readonly` mode, is immutable, or\n * you don't want it to be modified.\n *\n * @default true\n */\n updateDocument: boolean\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 updateDocument: true,\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 if (!this.options.updateDocument) {\n return\n }\n\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 if (!this.options.updateDocument) {\n return []\n }\n\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":";;;;;;;;;AAAA;;;AAGG;AACG,SAAU,gBAAgB,CAAI,KAAU,EAAE,EAAE,GAAG,IAAI,CAAC,SAAS,EAAA;IACjE,MAAM,IAAI,GAAqB,EAAE;AAEjC,IAAA,OAAO,KAAK,CAAC,MAAM,CAAC,IAAI,IAAG;AACzB,QAAA,MAAM,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC;QAEpB,OAAO,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG;AACnD,cAAE;eACC,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;AACxB,KAAC,CAAC;AACJ;;ACZA;;AAEG;AACG,SAAU,cAAc,CAAC,KAAY,EAAA;IACzC,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,KAAK,KAAK,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,KAAK,CAAC;AACzE,IAAA,MAAM,UAAU,GAAG,gBAAgB,CAAC,QAAQ,CAAC;AAE7C,IAAA,OAAO,UAAU;AACnB;;ACkBa,MAAA,QAAQ,GAAGA,cAAS,CAAC,MAAM,CAAkB;AACxD,IAAA,IAAI,EAAE,UAAU;;;AAIhB,IAAA,QAAQ,EAAE,KAAK;IAEf,UAAU,GAAA;QACR,OAAO;AACL,YAAA,aAAa,EAAE,IAAI;AACnB,YAAA,KAAK,EAAE,EAAE;AACT,YAAA,UAAU,EAAE,MAAMC,OAAM,EAAE;AAC1B,YAAA,iBAAiB,EAAE,IAAI;AACvB,YAAA,cAAc,EAAE,IAAI;SACrB;KACF;IAED,mBAAmB,GAAA;QACjB,OAAO;AACL,YAAA;AACE,gBAAA,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK;AACzB,gBAAA,UAAU,EAAE;AACV,oBAAA,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,GAAG;AAC5B,wBAAA,OAAO,EAAE,IAAI;AACb,wBAAA,SAAS,EAAE,OAAO,IAAI,OAAO,CAAC,YAAY,CAAC,CAAA,KAAA,EAAQ,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;wBAChF,UAAU,EAAE,UAAU,IAAG;4BACvB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE;AAC3C,gCAAA,OAAO,EAAE;;4BAGX,OAAO;AACL,gCAAA,CAAC,QAAQ,IAAI,CAAC,OAAO,CAAC,aAAa,CAAE,CAAA,GAAG,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC;6BAC/E;yBACF;AACF,qBAAA;AACF,iBAAA;AACF,aAAA;SACF;KACF;;IAGD,QAAQ,GAAA;AACN,QAAA,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE;YAChC;;QAGF,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,KAAK,eAAe,CAAC;QAChG,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;QAEtE,MAAM,SAAS,GAAG,MAAK;YACrB,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,MAAM;AACnC,YAAA,MAAM,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,KAAK;YACzB,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC,OAAO;YACzD,MAAM,cAAc,GAAGC,iBAAY,CAAC,GAAG,EAAE,IAAI,IAAG;AAC9C,gBAAA,OAAO,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,KAAK,IAAI;AAC7E,aAAC,CAAC;YAEF,cAAc,CAAC,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,KAAI;AACvC,gBAAA,EAAE,CAAC,aAAa,CAAC,GAAG,EAAE,SAAS,EAAE;oBAC/B,GAAG,IAAI,CAAC,KAAK;AACb,oBAAA,CAAC,aAAa,GAAG,UAAU,EAAE;AAC9B,iBAAA,CAAC;AACJ,aAAC,CAAC;AAEF,YAAA,EAAE,CAAC,OAAO,CAAC,cAAc,EAAE,KAAK,CAAC;AAEjC,YAAA,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YAEjB,IAAI,QAAQ,EAAE;AACZ,gBAAA,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAC;;AAErC,SAAC;AAED;;;;AAIG;QACH,IAAI,MAAM,EAAE;YACV,IAAI,CAAC,QAAQ,EAAE;gBACb,OAAO,SAAS,EAAE;;AAGpB,YAAA,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,SAAS,CAAC;;aAC3B;YACL,OAAO,SAAS,EAAE;;KAErB;IAED,qBAAqB,GAAA;AACnB,QAAA,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE;AAChC,YAAA,OAAO,EAAE;;QAGX,IAAI,iBAAiB,GAAmB,IAAI;QAC5C,IAAI,eAAe,GAAG,KAAK;QAE3B,OAAO;AACL,YAAA,IAAIC,YAAM,CAAC;AACT,gBAAA,GAAG,EAAE,IAAIC,eAAS,CAAC,UAAU,CAAC;gBAE9B,iBAAiB,EAAE,CAAC,YAAY,EAAE,QAAQ,EAAE,QAAQ,KAAI;AACtD,oBAAA,MAAM,aAAa,GAAG,YAAY,CAAC,IAAI,CAAC,WAAW,IAAI,WAAW,CAAC,UAAU;2BACxE,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC;AACnC,oBAAA,MAAM,kBAAkB,GAAG,IAAI,CAAC,OAAO,CAAC;2BACnC,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;AAEnE,oBAAA,MAAM,mBAAmB,GAAG,YAAY,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;oBAE1E,IAAI,mBAAmB,EAAE;wBACvB;;AAGF,oBAAA,IAAI,CAAC,aAAa,IAAI,kBAAkB,EAAE;wBACxC;;AAGF,oBAAA,MAAM,EAAE,EAAE,EAAE,GAAG,QAAQ;oBAEvB,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC,OAAO;oBACzD,MAAM,SAAS,GAAGC,4BAAuB,CAAC,QAAQ,CAAC,GAAG,EAAE,YAA6B,CAAC;AACtF,oBAAA,MAAM,EAAE,OAAO,EAAE,GAAG,SAAS;;AAG7B,oBAAA,MAAM,OAAO,GAAGC,qBAAgB,CAAC,SAAS,CAAC;oBAE3C,OAAO,CAAC,OAAO,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAI;AAC/B,wBAAA,MAAM,QAAQ,GAAGC,wBAAmB,CAAC,QAAQ,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,IAAG;4BAClE,OAAO,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;AACvC,yBAAC,CAAC;wBAEF,MAAM,MAAM,GAAG;AACZ,6BAAA,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC;6BAC3C,MAAM,CAAC,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;AAE5B,wBAAA,QAAQ,CAAC,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC,KAAI;;;;;;AAKpC,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;AAEnD,4BAAA,IAAI,EAAE,KAAK,IAAI,EAAE;AACf,gCAAA,EAAE,CAAC,aAAa,CAAC,GAAG,EAAE,SAAS,EAAE;oCAC/B,GAAG,IAAI,CAAC,KAAK;AACb,oCAAA,CAAC,aAAa,GAAG,UAAU,EAAE;AAC9B,iCAAA,CAAC;gCAEF;;4BAGF,MAAM,QAAQ,GAAG,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC;4BAEhC,IAAI,QAAQ,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,EAAE;gCACvC,EAAE,CAAC,aAAa,CAAC,QAAQ,CAAC,GAAG,EAAE,SAAS,EAAE;AACxC,oCAAA,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK;oCACtB,CAAC,aAAa,GAAG,EAAE;AACpB,iCAAA,CAAC;AACF,gCAAA,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE;gCAElB,IAAI,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,EAAE;oCACtC;;AAGF,gCAAA,MAAM,WAAW,GAAG,UAAU,EAAE;AAEhC,gCAAA,EAAE,CAAC,aAAa,CAAC,GAAG,EAAE,SAAS,EAAE;oCAC/B,GAAG,IAAI,CAAC,KAAK;oCACb,CAAC,aAAa,GAAG,WAAW;AAC7B,iCAAA,CAAC;AACF,gCAAA,MAAM,CAAC,CAAC,CAAC,GAAG,WAAW;AAEvB,gCAAA,OAAO,EAAE;;AAGX,4BAAA,MAAM,gBAAgB,GAAG,cAAc,CAAC,MAAM,CAAC;;AAG/C,4BAAA,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC;4BAEnD,MAAM,OAAO,GAAG,OAAO,IAAI,gBAAgB,CAAC,QAAQ,CAAC,EAAE,CAAC;4BAExD,IAAI,OAAO,EAAE;AACX,gCAAA,EAAE,CAAC,aAAa,CAAC,GAAG,EAAE,SAAS,EAAE;oCAC/B,GAAG,IAAI,CAAC,KAAK;AACb,oCAAA,CAAC,aAAa,GAAG,UAAU,EAAE;AAC9B,iCAAA,CAAC;;AAEN,yBAAC,CAAC;AAEJ,qBAAC,CAAC;AAEF,oBAAA,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE;wBACpB;;;;oBAKF,EAAE,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,CAAC,WAAW,CAAC;AAE1C,oBAAA,OAAO,EAAE;iBACV;;AAGD,gBAAA,IAAI,CAAC,IAAI,EAAA;AACP,oBAAA,MAAM,eAAe,GAAG,CAAC,KAAgB,KAAI;;AAC3C,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;AAC3E,8BAAE,IAAI,CAAC,GAAG,CAAC;8BACT,IAAI;AACV,qBAAC;AAED,oBAAA,MAAM,CAAC,gBAAgB,CAAC,WAAW,EAAE,eAAe,CAAC;oBAErD,OAAO;wBACL,OAAO,GAAA;AACL,4BAAA,MAAM,CAAC,mBAAmB,CAAC,WAAW,EAAE,eAAe,CAAC;yBACzD;qBACF;iBACF;AAED,gBAAA,KAAK,EAAE;;;AAGL,oBAAA,eAAe,EAAE;;;;AAIf,wBAAA,IAAI,EAAE,CAAC,IAAI,EAAE,KAAK,KAAI;;AACpB,4BAAA,IACE,iBAAiB,KAAK,IAAI,CAAC,GAAG,CAAC;AAC5B,mCAAA,CAAA,MAAA,KAAK,CAAC,YAAY,MAAE,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,aAAa,MAAK;mCACtC,CAAA,CAAA,EAAA,GAAA,KAAK,CAAC,YAAY,0CAAE,aAAa,MAAK,MAAM,EAC/C;gCACA,iBAAiB,GAAG,IAAI;gCACxB,eAAe,GAAG,IAAI;;AAGxB,4BAAA,OAAO,KAAK;yBACb;;wBAED,KAAK,EAAE,MAAK;4BACV,eAAe,GAAG,IAAI;AAEtB,4BAAA,OAAO,KAAK;yBACb;AACF,qBAAA;;;oBAID,eAAe,EAAE,KAAK,IAAG;wBACvB,IAAI,CAAC,eAAe,EAAE;AACpB,4BAAA,OAAO,KAAK;;wBAGd,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC,OAAO;AAC7C,wBAAA,MAAM,QAAQ,GAAG,CAAC,QAAkB,KAAc;4BAChD,MAAM,IAAI,GAAsB,EAAE;AAElC,4BAAA,QAAQ,CAAC,OAAO,CAAC,IAAI,IAAG;;AAEtB,gCAAA,IAAI,IAAI,CAAC,MAAM,EAAE;AACf,oCAAA,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;oCAEf;;;AAIF,gCAAA,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;AACnC,oCAAA,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;oCAE5C;;;AAIF,gCAAA,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CACpC;oCACE,GAAG,IAAI,CAAC,KAAK;oCACb,CAAC,aAAa,GAAG,IAAI;iCACtB,EACD,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EACtB,IAAI,CAAC,KAAK,CACX;AAED,gCAAA,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC;AAC1B,6BAAC,CAAC;AAEF,4BAAA,OAAOC,cAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;AAC5B,yBAAC;;wBAGD,eAAe,GAAG,KAAK;AAEvB,wBAAA,OAAO,IAAIC,WAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC;qBAC1E;AACF,iBAAA;aACF,CAAC;SACH;KACF;AAEF,CAAA;;;;;"}
package/dist/index.js CHANGED
@@ -37,6 +37,7 @@ const UniqueID = Extension.create({
37
37
  types: [],
38
38
  generateID: () => v4(),
39
39
  filterTransaction: null,
40
+ updateDocument: true,
40
41
  };
41
42
  },
42
43
  addGlobalAttributes() {
@@ -62,6 +63,9 @@ const UniqueID = Extension.create({
62
63
  },
63
64
  // check initial content for missing ids
64
65
  onCreate() {
66
+ if (!this.options.updateDocument) {
67
+ return;
68
+ }
65
69
  const collab = this.editor.extensionManager.extensions.find(ext => ext.name === 'collaboration');
66
70
  const provider = (collab === null || collab === void 0 ? void 0 : collab.options) ? collab.options.provider : undefined;
67
71
  const createIds = () => {
@@ -99,6 +103,9 @@ const UniqueID = Extension.create({
99
103
  }
100
104
  },
101
105
  addProseMirrorPlugins() {
106
+ if (!this.options.updateDocument) {
107
+ return [];
108
+ }
102
109
  let dragSourceElement = null;
103
110
  let transformPasted = false;
104
111
  return [
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.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":["uuidv4"],"mappings":"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"}
1
+ {"version":3,"file":"index.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 * Whether to update the document by adding unique IDs to the nodes. Set this\n * property to `false` if the document is in `readonly` mode, is immutable, or\n * you don't want it to be modified.\n *\n * @default true\n */\n updateDocument: boolean\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 updateDocument: true,\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 if (!this.options.updateDocument) {\n return\n }\n\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 if (!this.options.updateDocument) {\n return []\n }\n\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":["uuidv4"],"mappings":"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"}
package/dist/index.umd.js CHANGED
@@ -38,6 +38,7 @@
38
38
  types: [],
39
39
  generateID: () => uuid.v4(),
40
40
  filterTransaction: null,
41
+ updateDocument: true,
41
42
  };
42
43
  },
43
44
  addGlobalAttributes() {
@@ -63,6 +64,9 @@
63
64
  },
64
65
  // check initial content for missing ids
65
66
  onCreate() {
67
+ if (!this.options.updateDocument) {
68
+ return;
69
+ }
66
70
  const collab = this.editor.extensionManager.extensions.find(ext => ext.name === 'collaboration');
67
71
  const provider = (collab === null || collab === void 0 ? void 0 : collab.options) ? collab.options.provider : undefined;
68
72
  const createIds = () => {
@@ -100,6 +104,9 @@
100
104
  }
101
105
  },
102
106
  addProseMirrorPlugins() {
107
+ if (!this.options.updateDocument) {
108
+ return [];
109
+ }
103
110
  let dragSourceElement = null;
104
111
  let transformPasted = false;
105
112
  return [
@@ -1 +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":"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"}
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 * Whether to update the document by adding unique IDs to the nodes. Set this\n * property to `false` if the document is in `readonly` mode, is immutable, or\n * you don't want it to be modified.\n *\n * @default true\n */\n updateDocument: boolean\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 updateDocument: true,\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 if (!this.options.updateDocument) {\n return\n }\n\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 if (!this.options.updateDocument) {\n return []\n }\n\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;;ACkBa,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;EACvB,YAAA,cAAc,EAAE,IAAI;WACrB;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;EACN,QAAA,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE;cAChC;;UAGF,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;EACnB,QAAA,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE;EAChC,YAAA,OAAO,EAAE;;UAGX,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;;;;;;;;;;;"}
@@ -5,6 +5,14 @@ export interface UniqueIDOptions {
5
5
  types: string[];
6
6
  generateID: () => any;
7
7
  filterTransaction: ((transaction: Transaction) => boolean) | null;
8
+ /**
9
+ * Whether to update the document by adding unique IDs to the nodes. Set this
10
+ * property to `false` if the document is in `readonly` mode, is immutable, or
11
+ * you don't want it to be modified.
12
+ *
13
+ * @default true
14
+ */
15
+ updateDocument: boolean;
8
16
  }
9
17
  export declare const UniqueID: Extension<UniqueIDOptions, any>;
10
18
  //# sourceMappingURL=unique-id.d.ts.map
@@ -1 +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"}
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;IAClE;;;;;;OAMG;IACH,cAAc,EAAE,OAAO,CAAA;CACxB;AAED,eAAO,MAAM,QAAQ,iCA2SnB,CAAA"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tiptap/extension-unique-id",
3
3
  "description": "unique id extension for tiptap",
4
- "version": "2.26.3",
4
+ "version": "2.27.0",
5
5
  "homepage": "https://tiptap.dev/api/extensions/unique-id",
6
6
  "keywords": [
7
7
  "tiptap",
@@ -36,8 +36,8 @@
36
36
  "uuid": "^10.0.0"
37
37
  },
38
38
  "devDependencies": {
39
- "@tiptap/core": "^2.26.3",
40
- "@tiptap/pm": "^2.26.3",
39
+ "@tiptap/core": "^2.27.0",
40
+ "@tiptap/pm": "^2.27.0",
41
41
  "@types/uuid": "^10.0.0"
42
42
  },
43
43
  "repository": {
package/src/unique-id.ts CHANGED
@@ -16,6 +16,14 @@ export interface UniqueIDOptions {
16
16
  types: string[],
17
17
  generateID: () => any,
18
18
  filterTransaction: ((transaction: Transaction) => boolean) | null,
19
+ /**
20
+ * Whether to update the document by adding unique IDs to the nodes. Set this
21
+ * property to `false` if the document is in `readonly` mode, is immutable, or
22
+ * you don't want it to be modified.
23
+ *
24
+ * @default true
25
+ */
26
+ updateDocument: boolean
19
27
  }
20
28
 
21
29
  export const UniqueID = Extension.create<UniqueIDOptions>({
@@ -31,6 +39,7 @@ export const UniqueID = Extension.create<UniqueIDOptions>({
31
39
  types: [],
32
40
  generateID: () => uuidv4(),
33
41
  filterTransaction: null,
42
+ updateDocument: true,
34
43
  }
35
44
  },
36
45
 
@@ -59,6 +68,10 @@ export const UniqueID = Extension.create<UniqueIDOptions>({
59
68
 
60
69
  // check initial content for missing ids
61
70
  onCreate() {
71
+ if (!this.options.updateDocument) {
72
+ return
73
+ }
74
+
62
75
  const collab = this.editor.extensionManager.extensions.find(ext => ext.name === 'collaboration')
63
76
  const provider = collab?.options ? collab.options.provider : undefined
64
77
 
@@ -103,6 +116,10 @@ export const UniqueID = Extension.create<UniqueIDOptions>({
103
116
  },
104
117
 
105
118
  addProseMirrorPlugins() {
119
+ if (!this.options.updateDocument) {
120
+ return []
121
+ }
122
+
106
123
  let dragSourceElement: Element | null = null
107
124
  let transformPasted = false
108
125