@tiptap/extension-table-of-contents 3.12.1 → 3.14.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
@@ -48,6 +48,9 @@ var TableOfContentsPlugin = ({
48
48
  if (typeof window === "undefined") {
49
49
  return null;
50
50
  }
51
+ if (transactions.some((tr2) => tr2.getMeta("composition"))) {
52
+ return;
53
+ }
51
54
  const tr = newState.tr;
52
55
  let modified = false;
53
56
  if (transactions.some((transaction) => transaction.docChanged)) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/tableOfContents.ts","../src/plugin.ts","../src/utils.ts"],"sourcesContent":["import { TableOfContents } from './tableOfContents.js'\n\nexport * from './plugin.js'\nexport * from './tableOfContents.js'\nexport * from './utils.js'\n\nexport default TableOfContents\n","import type { Editor } from '@tiptap/core'\nimport { Extension } from '@tiptap/core'\nimport type { Node as TiptapNode } from '@tiptap/pm/model'\nimport { v4 as uuidv4 } from 'uuid'\n\nimport { TableOfContentsPlugin } from './plugin.js'\nimport type {\n GetTableOfContentIndexFunction,\n GetTableOfContentLevelFunction,\n TableOfContentData,\n TableOfContentDataItem,\n TableOfContentsOptions,\n TableOfContentsStorage,\n} from './types.js'\nimport { getHeadlineLevel, getLinearIndexes } from './utils.js'\n\nexport * from './types.js'\n\nconst addTocActiveStatesAndGetItems = (\n content: TableOfContentDataItem[],\n options: {\n editor: Editor\n anchorTypes: Array<string> | undefined\n storage: TableOfContentsStorage\n onUpdate?: (data: TableOfContentData, isCreate?: boolean) => void | undefined\n },\n) => {\n const { editor } = options\n const headlines: Array<{ node: TiptapNode; pos: number }> = []\n const scrolledOverIds: string[] = []\n let activeId: string | null = null\n\n if (editor.isDestroyed) {\n return content\n }\n\n editor.state.doc.descendants((node, pos) => {\n const isValidType = options.anchorTypes?.includes(node.type.name)\n\n if (!isValidType) {\n return\n }\n\n headlines.push({ node, pos })\n })\n\n headlines.forEach(headline => {\n const domElement = editor.view.domAtPos(headline.pos + 1).node as HTMLHeadingElement | HTMLElement\n const scrolledOver = options.storage.scrollPosition >= domElement.offsetTop\n\n if (scrolledOver) {\n activeId = headline.node.attrs['data-toc-id']\n scrolledOverIds.push(headline.node.attrs['data-toc-id'])\n }\n })\n\n content = content.map(heading => ({\n ...heading,\n isActive: heading.id === activeId,\n isScrolledOver: scrolledOverIds.includes(heading.id),\n }))\n\n if (options.onUpdate) {\n const isInitialCreation = options.storage.content.length === 0\n\n options.onUpdate(content, isInitialCreation)\n }\n\n return content\n}\n\nconst setTocData = (options: {\n editor: Editor\n anchorTypes: Array<string> | undefined\n getIndexFn: GetTableOfContentIndexFunction\n getLevelFn: GetTableOfContentLevelFunction\n storage: TableOfContentsStorage\n onUpdate?: (data: TableOfContentData, isCreate?: boolean) => void | undefined\n}) => {\n const { editor, onUpdate } = options\n\n if (editor.isDestroyed) {\n return\n }\n\n const headlines: Array<{ node: TiptapNode; pos: number }> = []\n\n let anchors: TableOfContentDataItem[] = []\n const anchorEls: Array<HTMLHeadingElement | HTMLElement> = []\n\n editor.state.doc.descendants((node, pos) => {\n const isValidType = options.anchorTypes?.includes(node.type.name)\n\n if (!isValidType) {\n return\n }\n\n headlines.push({ node, pos })\n })\n\n headlines.forEach((headline, i) => {\n if (headline.node.textContent.length === 0) {\n return\n }\n\n const domElement = editor.view.domAtPos(headline.pos + 1).node as HTMLHeadingElement\n const scrolledOver = options.storage.scrollPosition >= domElement.offsetTop\n\n anchorEls.push(domElement)\n\n const originalLevel = headline.node.attrs.level\n\n const prevHeadline = headlines[i - 1]\n\n const level = options.getLevelFn(headline, anchors)\n const itemIndex = options.getIndexFn(headline, anchors, level)\n\n if (!prevHeadline) {\n anchors = [\n ...anchors,\n {\n itemIndex,\n id: headline.node.attrs['data-toc-id'],\n originalLevel,\n level,\n textContent: headline.node.textContent,\n pos: headline.pos,\n editor,\n isActive: false,\n isScrolledOver: scrolledOver,\n node: headline.node,\n dom: domElement,\n },\n ]\n\n return\n }\n\n anchors = [\n ...anchors,\n {\n itemIndex,\n id: headline.node.attrs['data-toc-id'],\n originalLevel,\n level,\n textContent: headline.node.textContent,\n pos: headline.pos,\n editor,\n isActive: false,\n isScrolledOver: false,\n node: headline.node,\n dom: domElement,\n },\n ]\n })\n\n anchors = addTocActiveStatesAndGetItems(anchors, options)\n\n if (onUpdate) {\n const isInitialCreation = options.storage.content.length === 0\n\n onUpdate(anchors, isInitialCreation)\n }\n\n options.storage.anchors = anchorEls\n options.storage.content = anchors\n editor.state.tr.setMeta('toc', anchors)\n editor.view.dispatch(editor.state.tr)\n}\n\nexport const TableOfContents = Extension.create<TableOfContentsOptions, TableOfContentsStorage>({\n name: 'tableOfContents',\n\n addStorage() {\n return {\n content: [],\n anchors: [],\n scrollHandler: () => null,\n scrollPosition: 0,\n }\n },\n\n addGlobalAttributes() {\n return [\n {\n types: (this.options.anchorTypes as string[]) || ['headline'],\n attributes: {\n id: {\n default: null,\n renderHTML: attributes => {\n return {\n id: attributes.id,\n }\n },\n parseHTML: element => {\n return element.id || null\n },\n },\n 'data-toc-id': {\n default: null,\n renderHTML: attributes => {\n return {\n 'data-toc-id': attributes['data-toc-id'],\n }\n },\n parseHTML: element => {\n return element.dataset.tocId || null\n },\n },\n },\n },\n ]\n },\n\n addOptions() {\n const defaultScrollParent = typeof window !== 'undefined' ? () => window : undefined\n\n return {\n // eslint-disable-next-line\n onUpdate: () => {},\n // eslint-disable-next-line\n getId: _textContent => uuidv4(),\n\n scrollParent: defaultScrollParent,\n\n anchorTypes: ['heading'],\n }\n },\n\n addCommands() {\n return {\n updateTableOfContents:\n () =>\n ({ dispatch }) => {\n if (dispatch) {\n setTocData({\n editor: this.editor,\n storage: this.storage,\n onUpdate: this.options.onUpdate?.bind(this),\n getIndexFn: this.options.getIndex || getLinearIndexes,\n getLevelFn: this.options.getLevel || getHeadlineLevel,\n anchorTypes: this.options.anchorTypes,\n })\n }\n\n return true\n },\n }\n },\n\n onTransaction({ transaction }) {\n if (transaction.docChanged && !transaction.getMeta('toc')) {\n setTocData({\n editor: this.editor,\n storage: this.storage,\n onUpdate: this.options.onUpdate?.bind(this),\n getIndexFn: this.options.getIndex || getLinearIndexes,\n getLevelFn: this.options.getLevel || getHeadlineLevel,\n anchorTypes: this.options.anchorTypes,\n })\n }\n },\n\n onCreate() {\n // Avoid mutating the document during server-side rendering.\n if (typeof window === 'undefined' || !this.editor.view) {\n return\n }\n\n const { tr } = this.editor.state\n const existingIds: string[] = []\n\n if (this.options.scrollParent && typeof this.options.scrollParent !== 'function') {\n console.warn(\n \"[Tiptap Table of Contents Deprecation Notice]: The 'scrollParent' option must now be provided as a callback function that returns the 'scrollParent' element. The ability to pass this option directly will be deprecated in future releases.\",\n )\n }\n\n this.editor.state.doc.descendants((node, pos) => {\n const nodeId = node.attrs['data-toc-id']\n const isValidType = this.options.anchorTypes?.includes(node.type.name)\n\n if (!isValidType || node.textContent.length === 0) {\n return\n }\n\n if (nodeId === null || nodeId === undefined || existingIds.includes(nodeId)) {\n let id = ''\n\n if (this.options.getId) {\n id = this.options.getId(node.textContent)\n } else {\n id = uuidv4()\n }\n\n tr.setNodeMarkup(pos, undefined, {\n ...node.attrs,\n 'data-toc-id': id,\n id,\n })\n }\n\n existingIds.push(nodeId)\n })\n\n this.editor.view.dispatch(tr)\n\n setTocData({\n editor: this.editor,\n storage: this.storage,\n onUpdate: this.options.onUpdate?.bind(this),\n getIndexFn: this.options.getIndex || getLinearIndexes,\n getLevelFn: this.options.getLevel || getHeadlineLevel,\n anchorTypes: this.options.anchorTypes,\n })\n\n this.storage.scrollHandler = () => {\n if (!this.options.scrollParent) {\n return\n }\n\n // if scrollParent is HTML Element, use scrollTop - otherwise use scrollY\n const scrollParent =\n typeof this.options.scrollParent === 'function' ? this.options.scrollParent() : this.options.scrollParent\n\n const scrollPosition = scrollParent instanceof HTMLElement ? scrollParent.scrollTop : scrollParent.scrollY\n\n this.storage.scrollPosition = scrollPosition || 0\n\n const updatedItems = addTocActiveStatesAndGetItems(this.storage.content, {\n editor: this.editor,\n anchorTypes: this.options.anchorTypes,\n storage: this.storage,\n onUpdate: this.options.onUpdate?.bind(this),\n })\n\n this.storage.content = updatedItems\n }\n\n if (!this.options.scrollParent) {\n return\n }\n\n const scrollParent =\n typeof this.options.scrollParent === 'function' ? this.options.scrollParent() : this.options.scrollParent\n\n if (scrollParent) {\n scrollParent.addEventListener('scroll', this.storage.scrollHandler)\n }\n },\n\n onDestroy() {\n if (!this.options.scrollParent) {\n return\n }\n\n const scrollParent =\n typeof this.options.scrollParent === 'function' ? this.options.scrollParent() : this.options.scrollParent\n\n if (scrollParent) {\n scrollParent.removeEventListener('scroll', this.storage.scrollHandler)\n }\n },\n\n addProseMirrorPlugins() {\n return [TableOfContentsPlugin({ getId: this.options.getId, anchorTypes: this.options.anchorTypes })]\n },\n})\n","import type { NodeType } from '@tiptap/pm/model'\nimport { Plugin, PluginKey } from '@tiptap/pm/state'\nimport { v4 as uuidv4 } from 'uuid'\n\nexport const TableOfContentsPlugin = ({\n getId,\n anchorTypes = ['heading'],\n}: {\n getId?: (textContent: string) => string\n anchorTypes?: Array<string | NodeType>\n}) => {\n return new Plugin({\n key: new PluginKey('tableOfContent'),\n\n appendTransaction(transactions, _oldState, newState) {\n // Avoid running on the server where `window` / DOM is not available.\n if (typeof window === 'undefined') {\n return null\n }\n\n const tr = newState.tr\n let modified = false\n\n if (transactions.some(transaction => transaction.docChanged)) {\n const existingIds: string[] = []\n\n newState.doc.descendants((node, pos) => {\n const nodeId = node.attrs['data-toc-id']\n\n if (!anchorTypes.includes(node.type.name) || node.textContent.length === 0) {\n return\n }\n\n if (nodeId === null || nodeId === undefined || existingIds.includes(nodeId)) {\n let id = ''\n\n if (getId) {\n id = getId(node.textContent)\n } else {\n id = uuidv4()\n }\n\n tr.setNodeMarkup(pos, undefined, {\n ...node.attrs,\n 'data-toc-id': id,\n id,\n })\n\n modified = true\n }\n\n existingIds.push(nodeId)\n })\n }\n\n return modified ? tr : null\n },\n })\n}\n","import type { GetTableOfContentIndexFunction, GetTableOfContentLevelFunction, TableOfContentDataItem } from './types.js'\n\nexport const getLastHeadingOnLevel = (\n headings: TableOfContentDataItem[],\n level: number,\n): TableOfContentDataItem | undefined => {\n let heading = headings.filter(currentHeading => currentHeading.level === level).pop()\n\n if (level === 0) {\n return undefined\n }\n\n if (!heading) {\n heading = getLastHeadingOnLevel(headings, level - 1)\n }\n\n return heading\n}\n\nexport const getHeadlineLevel: GetTableOfContentLevelFunction = (headline, previousItems) => {\n let level = 1\n\n const previousHeadline = previousItems.at(-1)\n const highestHeadlineAbove = [...previousItems].reverse().find(h => h.originalLevel <= headline.node.attrs.level)\n\n const highestLevelAbove = highestHeadlineAbove?.level || 1\n\n if (headline.node.attrs.level > (previousHeadline?.originalLevel || 1)) {\n level = (previousHeadline?.level || 1) + 1\n } else if (headline.node.attrs.level < (previousHeadline?.originalLevel || 1)) {\n level = highestLevelAbove\n } else {\n level = previousHeadline?.level || 1\n }\n\n return level\n}\n\nexport const getLinearIndexes: GetTableOfContentIndexFunction = (_headline, previousHeadlines) => {\n const previousHeadline = previousHeadlines.at(-1)\n\n if (!previousHeadline) {\n return 1\n }\n\n return (previousHeadline?.itemIndex || 1) + 1\n}\n\nexport const getHierarchicalIndexes: GetTableOfContentIndexFunction = (headline, previousHeadlines, currentLevel) => {\n const level = currentLevel || headline.node.attrs.level || 1\n let itemIndex = 1\n\n const previousHeadlinesOnLevelOrBelow = previousHeadlines.filter(h => h.level <= level)\n\n if (previousHeadlinesOnLevelOrBelow.at(-1)?.level === level) {\n itemIndex = (previousHeadlinesOnLevelOrBelow.at(-1)?.itemIndex || 1) + 1\n } else {\n itemIndex = 1\n }\n\n return itemIndex\n}\n\nexport function debounce(func: (...args: any[]) => void, wait: number) {\n let timeout: ReturnType<typeof setTimeout> | null = null\n\n return (...args: any[]) => {\n if (timeout) {\n clearTimeout(timeout)\n }\n timeout = setTimeout(() => {\n func(...args)\n }, wait)\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACCA,kBAA0B;AAE1B,IAAAA,eAA6B;;;ACF7B,mBAAkC;AAClC,kBAA6B;AAEtB,IAAM,wBAAwB,CAAC;AAAA,EACpC;AAAA,EACA,cAAc,CAAC,SAAS;AAC1B,MAGM;AACJ,SAAO,IAAI,oBAAO;AAAA,IAChB,KAAK,IAAI,uBAAU,gBAAgB;AAAA,IAEnC,kBAAkB,cAAc,WAAW,UAAU;AAEnD,UAAI,OAAO,WAAW,aAAa;AACjC,eAAO;AAAA,MACT;AAEA,YAAM,KAAK,SAAS;AACpB,UAAI,WAAW;AAEf,UAAI,aAAa,KAAK,iBAAe,YAAY,UAAU,GAAG;AAC5D,cAAM,cAAwB,CAAC;AAE/B,iBAAS,IAAI,YAAY,CAAC,MAAM,QAAQ;AACtC,gBAAM,SAAS,KAAK,MAAM,aAAa;AAEvC,cAAI,CAAC,YAAY,SAAS,KAAK,KAAK,IAAI,KAAK,KAAK,YAAY,WAAW,GAAG;AAC1E;AAAA,UACF;AAEA,cAAI,WAAW,QAAQ,WAAW,UAAa,YAAY,SAAS,MAAM,GAAG;AAC3E,gBAAI,KAAK;AAET,gBAAI,OAAO;AACT,mBAAK,MAAM,KAAK,WAAW;AAAA,YAC7B,OAAO;AACL,uBAAK,YAAAC,IAAO;AAAA,YACd;AAEA,eAAG,cAAc,KAAK,QAAW;AAAA,cAC/B,GAAG,KAAK;AAAA,cACR,eAAe;AAAA,cACf;AAAA,YACF,CAAC;AAED,uBAAW;AAAA,UACb;AAEA,sBAAY,KAAK,MAAM;AAAA,QACzB,CAAC;AAAA,MACH;AAEA,aAAO,WAAW,KAAK;AAAA,IACzB;AAAA,EACF,CAAC;AACH;;;ACxDO,IAAM,wBAAwB,CACnC,UACA,UACuC;AACvC,MAAI,UAAU,SAAS,OAAO,oBAAkB,eAAe,UAAU,KAAK,EAAE,IAAI;AAEpF,MAAI,UAAU,GAAG;AACf,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,SAAS;AACZ,cAAU,sBAAsB,UAAU,QAAQ,CAAC;AAAA,EACrD;AAEA,SAAO;AACT;AAEO,IAAM,mBAAmD,CAAC,UAAU,kBAAkB;AAC3F,MAAI,QAAQ;AAEZ,QAAM,mBAAmB,cAAc,GAAG,EAAE;AAC5C,QAAM,uBAAuB,CAAC,GAAG,aAAa,EAAE,QAAQ,EAAE,KAAK,OAAK,EAAE,iBAAiB,SAAS,KAAK,MAAM,KAAK;AAEhH,QAAM,qBAAoB,6DAAsB,UAAS;AAEzD,MAAI,SAAS,KAAK,MAAM,UAAS,qDAAkB,kBAAiB,IAAI;AACtE,cAAS,qDAAkB,UAAS,KAAK;AAAA,EAC3C,WAAW,SAAS,KAAK,MAAM,UAAS,qDAAkB,kBAAiB,IAAI;AAC7E,YAAQ;AAAA,EACV,OAAO;AACL,aAAQ,qDAAkB,UAAS;AAAA,EACrC;AAEA,SAAO;AACT;AAEO,IAAM,mBAAmD,CAAC,WAAW,sBAAsB;AAChG,QAAM,mBAAmB,kBAAkB,GAAG,EAAE;AAEhD,MAAI,CAAC,kBAAkB;AACrB,WAAO;AAAA,EACT;AAEA,WAAQ,qDAAkB,cAAa,KAAK;AAC9C;AAEO,IAAM,yBAAyD,CAAC,UAAU,mBAAmB,iBAAiB;AAhDrH;AAiDE,QAAM,QAAQ,gBAAgB,SAAS,KAAK,MAAM,SAAS;AAC3D,MAAI,YAAY;AAEhB,QAAM,kCAAkC,kBAAkB,OAAO,OAAK,EAAE,SAAS,KAAK;AAEtF,QAAI,qCAAgC,GAAG,EAAE,MAArC,mBAAwC,WAAU,OAAO;AAC3D,mBAAa,qCAAgC,GAAG,EAAE,MAArC,mBAAwC,cAAa,KAAK;AAAA,EACzE,OAAO;AACL,gBAAY;AAAA,EACd;AAEA,SAAO;AACT;AAEO,SAAS,SAAS,MAAgC,MAAc;AACrE,MAAI,UAAgD;AAEpD,SAAO,IAAI,SAAgB;AACzB,QAAI,SAAS;AACX,mBAAa,OAAO;AAAA,IACtB;AACA,cAAU,WAAW,MAAM;AACzB,WAAK,GAAG,IAAI;AAAA,IACd,GAAG,IAAI;AAAA,EACT;AACF;;;AFxDA,IAAM,gCAAgC,CACpC,SACA,YAMG;AACH,QAAM,EAAE,OAAO,IAAI;AACnB,QAAM,YAAsD,CAAC;AAC7D,QAAM,kBAA4B,CAAC;AACnC,MAAI,WAA0B;AAE9B,MAAI,OAAO,aAAa;AACtB,WAAO;AAAA,EACT;AAEA,SAAO,MAAM,IAAI,YAAY,CAAC,MAAM,QAAQ;AApC9C;AAqCI,UAAM,eAAc,aAAQ,gBAAR,mBAAqB,SAAS,KAAK,KAAK;AAE5D,QAAI,CAAC,aAAa;AAChB;AAAA,IACF;AAEA,cAAU,KAAK,EAAE,MAAM,IAAI,CAAC;AAAA,EAC9B,CAAC;AAED,YAAU,QAAQ,cAAY;AAC5B,UAAM,aAAa,OAAO,KAAK,SAAS,SAAS,MAAM,CAAC,EAAE;AAC1D,UAAM,eAAe,QAAQ,QAAQ,kBAAkB,WAAW;AAElE,QAAI,cAAc;AAChB,iBAAW,SAAS,KAAK,MAAM,aAAa;AAC5C,sBAAgB,KAAK,SAAS,KAAK,MAAM,aAAa,CAAC;AAAA,IACzD;AAAA,EACF,CAAC;AAED,YAAU,QAAQ,IAAI,cAAY;AAAA,IAChC,GAAG;AAAA,IACH,UAAU,QAAQ,OAAO;AAAA,IACzB,gBAAgB,gBAAgB,SAAS,QAAQ,EAAE;AAAA,EACrD,EAAE;AAEF,MAAI,QAAQ,UAAU;AACpB,UAAM,oBAAoB,QAAQ,QAAQ,QAAQ,WAAW;AAE7D,YAAQ,SAAS,SAAS,iBAAiB;AAAA,EAC7C;AAEA,SAAO;AACT;AAEA,IAAM,aAAa,CAAC,YAOd;AACJ,QAAM,EAAE,QAAQ,SAAS,IAAI;AAE7B,MAAI,OAAO,aAAa;AACtB;AAAA,EACF;AAEA,QAAM,YAAsD,CAAC;AAE7D,MAAI,UAAoC,CAAC;AACzC,QAAM,YAAqD,CAAC;AAE5D,SAAO,MAAM,IAAI,YAAY,CAAC,MAAM,QAAQ;AA1F9C;AA2FI,UAAM,eAAc,aAAQ,gBAAR,mBAAqB,SAAS,KAAK,KAAK;AAE5D,QAAI,CAAC,aAAa;AAChB;AAAA,IACF;AAEA,cAAU,KAAK,EAAE,MAAM,IAAI,CAAC;AAAA,EAC9B,CAAC;AAED,YAAU,QAAQ,CAAC,UAAU,MAAM;AACjC,QAAI,SAAS,KAAK,YAAY,WAAW,GAAG;AAC1C;AAAA,IACF;AAEA,UAAM,aAAa,OAAO,KAAK,SAAS,SAAS,MAAM,CAAC,EAAE;AAC1D,UAAM,eAAe,QAAQ,QAAQ,kBAAkB,WAAW;AAElE,cAAU,KAAK,UAAU;AAEzB,UAAM,gBAAgB,SAAS,KAAK,MAAM;AAE1C,UAAM,eAAe,UAAU,IAAI,CAAC;AAEpC,UAAM,QAAQ,QAAQ,WAAW,UAAU,OAAO;AAClD,UAAM,YAAY,QAAQ,WAAW,UAAU,SAAS,KAAK;AAE7D,QAAI,CAAC,cAAc;AACjB,gBAAU;AAAA,QACR,GAAG;AAAA,QACH;AAAA,UACE;AAAA,UACA,IAAI,SAAS,KAAK,MAAM,aAAa;AAAA,UACrC;AAAA,UACA;AAAA,UACA,aAAa,SAAS,KAAK;AAAA,UAC3B,KAAK,SAAS;AAAA,UACd;AAAA,UACA,UAAU;AAAA,UACV,gBAAgB;AAAA,UAChB,MAAM,SAAS;AAAA,UACf,KAAK;AAAA,QACP;AAAA,MACF;AAEA;AAAA,IACF;AAEA,cAAU;AAAA,MACR,GAAG;AAAA,MACH;AAAA,QACE;AAAA,QACA,IAAI,SAAS,KAAK,MAAM,aAAa;AAAA,QACrC;AAAA,QACA;AAAA,QACA,aAAa,SAAS,KAAK;AAAA,QAC3B,KAAK,SAAS;AAAA,QACd;AAAA,QACA,UAAU;AAAA,QACV,gBAAgB;AAAA,QAChB,MAAM,SAAS;AAAA,QACf,KAAK;AAAA,MACP;AAAA,IACF;AAAA,EACF,CAAC;AAED,YAAU,8BAA8B,SAAS,OAAO;AAExD,MAAI,UAAU;AACZ,UAAM,oBAAoB,QAAQ,QAAQ,QAAQ,WAAW;AAE7D,aAAS,SAAS,iBAAiB;AAAA,EACrC;AAEA,UAAQ,QAAQ,UAAU;AAC1B,UAAQ,QAAQ,UAAU;AAC1B,SAAO,MAAM,GAAG,QAAQ,OAAO,OAAO;AACtC,SAAO,KAAK,SAAS,OAAO,MAAM,EAAE;AACtC;AAEO,IAAM,kBAAkB,sBAAU,OAAuD;AAAA,EAC9F,MAAM;AAAA,EAEN,aAAa;AACX,WAAO;AAAA,MACL,SAAS,CAAC;AAAA,MACV,SAAS,CAAC;AAAA,MACV,eAAe,MAAM;AAAA,MACrB,gBAAgB;AAAA,IAClB;AAAA,EACF;AAAA,EAEA,sBAAsB;AACpB,WAAO;AAAA,MACL;AAAA,QACE,OAAQ,KAAK,QAAQ,eAA4B,CAAC,UAAU;AAAA,QAC5D,YAAY;AAAA,UACV,IAAI;AAAA,YACF,SAAS;AAAA,YACT,YAAY,gBAAc;AACxB,qBAAO;AAAA,gBACL,IAAI,WAAW;AAAA,cACjB;AAAA,YACF;AAAA,YACA,WAAW,aAAW;AACpB,qBAAO,QAAQ,MAAM;AAAA,YACvB;AAAA,UACF;AAAA,UACA,eAAe;AAAA,YACb,SAAS;AAAA,YACT,YAAY,gBAAc;AACxB,qBAAO;AAAA,gBACL,eAAe,WAAW,aAAa;AAAA,cACzC;AAAA,YACF;AAAA,YACA,WAAW,aAAW;AACpB,qBAAO,QAAQ,QAAQ,SAAS;AAAA,YAClC;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,aAAa;AACX,UAAM,sBAAsB,OAAO,WAAW,cAAc,MAAM,SAAS;AAE3E,WAAO;AAAA;AAAA,MAEL,UAAU,MAAM;AAAA,MAAC;AAAA;AAAA,MAEjB,OAAO,sBAAgB,aAAAC,IAAO;AAAA,MAE9B,cAAc;AAAA,MAEd,aAAa,CAAC,SAAS;AAAA,IACzB;AAAA,EACF;AAAA,EAEA,cAAc;AACZ,WAAO;AAAA,MACL,uBACE,MACA,CAAC,EAAE,SAAS,MAAM;AAzO1B;AA0OU,YAAI,UAAU;AACZ,qBAAW;AAAA,YACT,QAAQ,KAAK;AAAA,YACb,SAAS,KAAK;AAAA,YACd,WAAU,UAAK,QAAQ,aAAb,mBAAuB,KAAK;AAAA,YACtC,YAAY,KAAK,QAAQ,YAAY;AAAA,YACrC,YAAY,KAAK,QAAQ,YAAY;AAAA,YACrC,aAAa,KAAK,QAAQ;AAAA,UAC5B,CAAC;AAAA,QACH;AAEA,eAAO;AAAA,MACT;AAAA,IACJ;AAAA,EACF;AAAA,EAEA,cAAc,EAAE,YAAY,GAAG;AA1PjC;AA2PI,QAAI,YAAY,cAAc,CAAC,YAAY,QAAQ,KAAK,GAAG;AACzD,iBAAW;AAAA,QACT,QAAQ,KAAK;AAAA,QACb,SAAS,KAAK;AAAA,QACd,WAAU,UAAK,QAAQ,aAAb,mBAAuB,KAAK;AAAA,QACtC,YAAY,KAAK,QAAQ,YAAY;AAAA,QACrC,YAAY,KAAK,QAAQ,YAAY;AAAA,QACrC,aAAa,KAAK,QAAQ;AAAA,MAC5B,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,WAAW;AAvQb;AAyQI,QAAI,OAAO,WAAW,eAAe,CAAC,KAAK,OAAO,MAAM;AACtD;AAAA,IACF;AAEA,UAAM,EAAE,GAAG,IAAI,KAAK,OAAO;AAC3B,UAAM,cAAwB,CAAC;AAE/B,QAAI,KAAK,QAAQ,gBAAgB,OAAO,KAAK,QAAQ,iBAAiB,YAAY;AAChF,cAAQ;AAAA,QACN;AAAA,MACF;AAAA,IACF;AAEA,SAAK,OAAO,MAAM,IAAI,YAAY,CAAC,MAAM,QAAQ;AAtRrD,UAAAC;AAuRM,YAAM,SAAS,KAAK,MAAM,aAAa;AACvC,YAAM,eAAcA,MAAA,KAAK,QAAQ,gBAAb,gBAAAA,IAA0B,SAAS,KAAK,KAAK;AAEjE,UAAI,CAAC,eAAe,KAAK,YAAY,WAAW,GAAG;AACjD;AAAA,MACF;AAEA,UAAI,WAAW,QAAQ,WAAW,UAAa,YAAY,SAAS,MAAM,GAAG;AAC3E,YAAI,KAAK;AAET,YAAI,KAAK,QAAQ,OAAO;AACtB,eAAK,KAAK,QAAQ,MAAM,KAAK,WAAW;AAAA,QAC1C,OAAO;AACL,mBAAK,aAAAD,IAAO;AAAA,QACd;AAEA,WAAG,cAAc,KAAK,QAAW;AAAA,UAC/B,GAAG,KAAK;AAAA,UACR,eAAe;AAAA,UACf;AAAA,QACF,CAAC;AAAA,MACH;AAEA,kBAAY,KAAK,MAAM;AAAA,IACzB,CAAC;AAED,SAAK,OAAO,KAAK,SAAS,EAAE;AAE5B,eAAW;AAAA,MACT,QAAQ,KAAK;AAAA,MACb,SAAS,KAAK;AAAA,MACd,WAAU,UAAK,QAAQ,aAAb,mBAAuB,KAAK;AAAA,MACtC,YAAY,KAAK,QAAQ,YAAY;AAAA,MACrC,YAAY,KAAK,QAAQ,YAAY;AAAA,MACrC,aAAa,KAAK,QAAQ;AAAA,IAC5B,CAAC;AAED,SAAK,QAAQ,gBAAgB,MAAM;AA5TvC,UAAAC;AA6TM,UAAI,CAAC,KAAK,QAAQ,cAAc;AAC9B;AAAA,MACF;AAGA,YAAMC,gBACJ,OAAO,KAAK,QAAQ,iBAAiB,aAAa,KAAK,QAAQ,aAAa,IAAI,KAAK,QAAQ;AAE/F,YAAM,iBAAiBA,yBAAwB,cAAcA,cAAa,YAAYA,cAAa;AAEnG,WAAK,QAAQ,iBAAiB,kBAAkB;AAEhD,YAAM,eAAe,8BAA8B,KAAK,QAAQ,SAAS;AAAA,QACvE,QAAQ,KAAK;AAAA,QACb,aAAa,KAAK,QAAQ;AAAA,QAC1B,SAAS,KAAK;AAAA,QACd,WAAUD,MAAA,KAAK,QAAQ,aAAb,gBAAAA,IAAuB,KAAK;AAAA,MACxC,CAAC;AAED,WAAK,QAAQ,UAAU;AAAA,IACzB;AAEA,QAAI,CAAC,KAAK,QAAQ,cAAc;AAC9B;AAAA,IACF;AAEA,UAAM,eACJ,OAAO,KAAK,QAAQ,iBAAiB,aAAa,KAAK,QAAQ,aAAa,IAAI,KAAK,QAAQ;AAE/F,QAAI,cAAc;AAChB,mBAAa,iBAAiB,UAAU,KAAK,QAAQ,aAAa;AAAA,IACpE;AAAA,EACF;AAAA,EAEA,YAAY;AACV,QAAI,CAAC,KAAK,QAAQ,cAAc;AAC9B;AAAA,IACF;AAEA,UAAM,eACJ,OAAO,KAAK,QAAQ,iBAAiB,aAAa,KAAK,QAAQ,aAAa,IAAI,KAAK,QAAQ;AAE/F,QAAI,cAAc;AAChB,mBAAa,oBAAoB,UAAU,KAAK,QAAQ,aAAa;AAAA,IACvE;AAAA,EACF;AAAA,EAEA,wBAAwB;AACtB,WAAO,CAAC,sBAAsB,EAAE,OAAO,KAAK,QAAQ,OAAO,aAAa,KAAK,QAAQ,YAAY,CAAC,CAAC;AAAA,EACrG;AACF,CAAC;;;ADzWD,IAAO,gBAAQ;","names":["import_uuid","uuidv4","uuidv4","_a","scrollParent"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/tableOfContents.ts","../src/plugin.ts","../src/utils.ts"],"sourcesContent":["import { TableOfContents } from './tableOfContents.js'\n\nexport * from './plugin.js'\nexport * from './tableOfContents.js'\nexport * from './utils.js'\n\nexport default TableOfContents\n","import type { Editor } from '@tiptap/core'\nimport { Extension } from '@tiptap/core'\nimport type { Node as TiptapNode } from '@tiptap/pm/model'\nimport { v4 as uuidv4 } from 'uuid'\n\nimport { TableOfContentsPlugin } from './plugin.js'\nimport type {\n GetTableOfContentIndexFunction,\n GetTableOfContentLevelFunction,\n TableOfContentData,\n TableOfContentDataItem,\n TableOfContentsOptions,\n TableOfContentsStorage,\n} from './types.js'\nimport { getHeadlineLevel, getLinearIndexes } from './utils.js'\n\nexport * from './types.js'\n\nconst addTocActiveStatesAndGetItems = (\n content: TableOfContentDataItem[],\n options: {\n editor: Editor\n anchorTypes: Array<string> | undefined\n storage: TableOfContentsStorage\n onUpdate?: (data: TableOfContentData, isCreate?: boolean) => void | undefined\n },\n) => {\n const { editor } = options\n const headlines: Array<{ node: TiptapNode; pos: number }> = []\n const scrolledOverIds: string[] = []\n let activeId: string | null = null\n\n if (editor.isDestroyed) {\n return content\n }\n\n editor.state.doc.descendants((node, pos) => {\n const isValidType = options.anchorTypes?.includes(node.type.name)\n\n if (!isValidType) {\n return\n }\n\n headlines.push({ node, pos })\n })\n\n headlines.forEach(headline => {\n const domElement = editor.view.domAtPos(headline.pos + 1).node as HTMLHeadingElement | HTMLElement\n const scrolledOver = options.storage.scrollPosition >= domElement.offsetTop\n\n if (scrolledOver) {\n activeId = headline.node.attrs['data-toc-id']\n scrolledOverIds.push(headline.node.attrs['data-toc-id'])\n }\n })\n\n content = content.map(heading => ({\n ...heading,\n isActive: heading.id === activeId,\n isScrolledOver: scrolledOverIds.includes(heading.id),\n }))\n\n if (options.onUpdate) {\n const isInitialCreation = options.storage.content.length === 0\n\n options.onUpdate(content, isInitialCreation)\n }\n\n return content\n}\n\nconst setTocData = (options: {\n editor: Editor\n anchorTypes: Array<string> | undefined\n getIndexFn: GetTableOfContentIndexFunction\n getLevelFn: GetTableOfContentLevelFunction\n storage: TableOfContentsStorage\n onUpdate?: (data: TableOfContentData, isCreate?: boolean) => void | undefined\n}) => {\n const { editor, onUpdate } = options\n\n if (editor.isDestroyed) {\n return\n }\n\n const headlines: Array<{ node: TiptapNode; pos: number }> = []\n\n let anchors: TableOfContentDataItem[] = []\n const anchorEls: Array<HTMLHeadingElement | HTMLElement> = []\n\n editor.state.doc.descendants((node, pos) => {\n const isValidType = options.anchorTypes?.includes(node.type.name)\n\n if (!isValidType) {\n return\n }\n\n headlines.push({ node, pos })\n })\n\n headlines.forEach((headline, i) => {\n if (headline.node.textContent.length === 0) {\n return\n }\n\n const domElement = editor.view.domAtPos(headline.pos + 1).node as HTMLHeadingElement\n const scrolledOver = options.storage.scrollPosition >= domElement.offsetTop\n\n anchorEls.push(domElement)\n\n const originalLevel = headline.node.attrs.level\n\n const prevHeadline = headlines[i - 1]\n\n const level = options.getLevelFn(headline, anchors)\n const itemIndex = options.getIndexFn(headline, anchors, level)\n\n if (!prevHeadline) {\n anchors = [\n ...anchors,\n {\n itemIndex,\n id: headline.node.attrs['data-toc-id'],\n originalLevel,\n level,\n textContent: headline.node.textContent,\n pos: headline.pos,\n editor,\n isActive: false,\n isScrolledOver: scrolledOver,\n node: headline.node,\n dom: domElement,\n },\n ]\n\n return\n }\n\n anchors = [\n ...anchors,\n {\n itemIndex,\n id: headline.node.attrs['data-toc-id'],\n originalLevel,\n level,\n textContent: headline.node.textContent,\n pos: headline.pos,\n editor,\n isActive: false,\n isScrolledOver: false,\n node: headline.node,\n dom: domElement,\n },\n ]\n })\n\n anchors = addTocActiveStatesAndGetItems(anchors, options)\n\n if (onUpdate) {\n const isInitialCreation = options.storage.content.length === 0\n\n onUpdate(anchors, isInitialCreation)\n }\n\n options.storage.anchors = anchorEls\n options.storage.content = anchors\n editor.state.tr.setMeta('toc', anchors)\n editor.view.dispatch(editor.state.tr)\n}\n\nexport const TableOfContents = Extension.create<TableOfContentsOptions, TableOfContentsStorage>({\n name: 'tableOfContents',\n\n addStorage() {\n return {\n content: [],\n anchors: [],\n scrollHandler: () => null,\n scrollPosition: 0,\n }\n },\n\n addGlobalAttributes() {\n return [\n {\n types: (this.options.anchorTypes as string[]) || ['headline'],\n attributes: {\n id: {\n default: null,\n renderHTML: attributes => {\n return {\n id: attributes.id,\n }\n },\n parseHTML: element => {\n return element.id || null\n },\n },\n 'data-toc-id': {\n default: null,\n renderHTML: attributes => {\n return {\n 'data-toc-id': attributes['data-toc-id'],\n }\n },\n parseHTML: element => {\n return element.dataset.tocId || null\n },\n },\n },\n },\n ]\n },\n\n addOptions() {\n const defaultScrollParent = typeof window !== 'undefined' ? () => window : undefined\n\n return {\n // eslint-disable-next-line\n onUpdate: () => {},\n // eslint-disable-next-line\n getId: _textContent => uuidv4(),\n\n scrollParent: defaultScrollParent,\n\n anchorTypes: ['heading'],\n }\n },\n\n addCommands() {\n return {\n updateTableOfContents:\n () =>\n ({ dispatch }) => {\n if (dispatch) {\n setTocData({\n editor: this.editor,\n storage: this.storage,\n onUpdate: this.options.onUpdate?.bind(this),\n getIndexFn: this.options.getIndex || getLinearIndexes,\n getLevelFn: this.options.getLevel || getHeadlineLevel,\n anchorTypes: this.options.anchorTypes,\n })\n }\n\n return true\n },\n }\n },\n\n onTransaction({ transaction }) {\n if (transaction.docChanged && !transaction.getMeta('toc')) {\n setTocData({\n editor: this.editor,\n storage: this.storage,\n onUpdate: this.options.onUpdate?.bind(this),\n getIndexFn: this.options.getIndex || getLinearIndexes,\n getLevelFn: this.options.getLevel || getHeadlineLevel,\n anchorTypes: this.options.anchorTypes,\n })\n }\n },\n\n onCreate() {\n // Avoid mutating the document during server-side rendering.\n if (typeof window === 'undefined' || !this.editor.view) {\n return\n }\n\n const { tr } = this.editor.state\n const existingIds: string[] = []\n\n if (this.options.scrollParent && typeof this.options.scrollParent !== 'function') {\n console.warn(\n \"[Tiptap Table of Contents Deprecation Notice]: The 'scrollParent' option must now be provided as a callback function that returns the 'scrollParent' element. The ability to pass this option directly will be deprecated in future releases.\",\n )\n }\n\n this.editor.state.doc.descendants((node, pos) => {\n const nodeId = node.attrs['data-toc-id']\n const isValidType = this.options.anchorTypes?.includes(node.type.name)\n\n if (!isValidType || node.textContent.length === 0) {\n return\n }\n\n if (nodeId === null || nodeId === undefined || existingIds.includes(nodeId)) {\n let id = ''\n\n if (this.options.getId) {\n id = this.options.getId(node.textContent)\n } else {\n id = uuidv4()\n }\n\n tr.setNodeMarkup(pos, undefined, {\n ...node.attrs,\n 'data-toc-id': id,\n id,\n })\n }\n\n existingIds.push(nodeId)\n })\n\n this.editor.view.dispatch(tr)\n\n setTocData({\n editor: this.editor,\n storage: this.storage,\n onUpdate: this.options.onUpdate?.bind(this),\n getIndexFn: this.options.getIndex || getLinearIndexes,\n getLevelFn: this.options.getLevel || getHeadlineLevel,\n anchorTypes: this.options.anchorTypes,\n })\n\n this.storage.scrollHandler = () => {\n if (!this.options.scrollParent) {\n return\n }\n\n // if scrollParent is HTML Element, use scrollTop - otherwise use scrollY\n const scrollParent =\n typeof this.options.scrollParent === 'function' ? this.options.scrollParent() : this.options.scrollParent\n\n const scrollPosition = scrollParent instanceof HTMLElement ? scrollParent.scrollTop : scrollParent.scrollY\n\n this.storage.scrollPosition = scrollPosition || 0\n\n const updatedItems = addTocActiveStatesAndGetItems(this.storage.content, {\n editor: this.editor,\n anchorTypes: this.options.anchorTypes,\n storage: this.storage,\n onUpdate: this.options.onUpdate?.bind(this),\n })\n\n this.storage.content = updatedItems\n }\n\n if (!this.options.scrollParent) {\n return\n }\n\n const scrollParent =\n typeof this.options.scrollParent === 'function' ? this.options.scrollParent() : this.options.scrollParent\n\n if (scrollParent) {\n scrollParent.addEventListener('scroll', this.storage.scrollHandler)\n }\n },\n\n onDestroy() {\n if (!this.options.scrollParent) {\n return\n }\n\n const scrollParent =\n typeof this.options.scrollParent === 'function' ? this.options.scrollParent() : this.options.scrollParent\n\n if (scrollParent) {\n scrollParent.removeEventListener('scroll', this.storage.scrollHandler)\n }\n },\n\n addProseMirrorPlugins() {\n return [TableOfContentsPlugin({ getId: this.options.getId, anchorTypes: this.options.anchorTypes })]\n },\n})\n","import type { NodeType } from '@tiptap/pm/model'\nimport { Plugin, PluginKey } from '@tiptap/pm/state'\nimport { v4 as uuidv4 } from 'uuid'\n\nexport const TableOfContentsPlugin = ({\n getId,\n anchorTypes = ['heading'],\n}: {\n getId?: (textContent: string) => string\n anchorTypes?: Array<string | NodeType>\n}) => {\n return new Plugin({\n key: new PluginKey('tableOfContent'),\n\n appendTransaction(transactions, _oldState, newState) {\n // Avoid running on the server where `window` / DOM is not available.\n if (typeof window === 'undefined') {\n return null\n }\n\n // Skip updating table of contents during IME composition\n // to avoid interfering with input method editor\n if (transactions.some(tr => tr.getMeta('composition'))) {\n return\n }\n\n const tr = newState.tr\n let modified = false\n\n if (transactions.some(transaction => transaction.docChanged)) {\n const existingIds: string[] = []\n\n newState.doc.descendants((node, pos) => {\n const nodeId = node.attrs['data-toc-id']\n\n if (!anchorTypes.includes(node.type.name) || node.textContent.length === 0) {\n return\n }\n\n if (nodeId === null || nodeId === undefined || existingIds.includes(nodeId)) {\n let id = ''\n\n if (getId) {\n id = getId(node.textContent)\n } else {\n id = uuidv4()\n }\n\n tr.setNodeMarkup(pos, undefined, {\n ...node.attrs,\n 'data-toc-id': id,\n id,\n })\n\n modified = true\n }\n\n existingIds.push(nodeId)\n })\n }\n\n return modified ? tr : null\n },\n })\n}\n","import type { GetTableOfContentIndexFunction, GetTableOfContentLevelFunction, TableOfContentDataItem } from './types.js'\n\nexport const getLastHeadingOnLevel = (\n headings: TableOfContentDataItem[],\n level: number,\n): TableOfContentDataItem | undefined => {\n let heading = headings.filter(currentHeading => currentHeading.level === level).pop()\n\n if (level === 0) {\n return undefined\n }\n\n if (!heading) {\n heading = getLastHeadingOnLevel(headings, level - 1)\n }\n\n return heading\n}\n\nexport const getHeadlineLevel: GetTableOfContentLevelFunction = (headline, previousItems) => {\n let level = 1\n\n const previousHeadline = previousItems.at(-1)\n const highestHeadlineAbove = [...previousItems].reverse().find(h => h.originalLevel <= headline.node.attrs.level)\n\n const highestLevelAbove = highestHeadlineAbove?.level || 1\n\n if (headline.node.attrs.level > (previousHeadline?.originalLevel || 1)) {\n level = (previousHeadline?.level || 1) + 1\n } else if (headline.node.attrs.level < (previousHeadline?.originalLevel || 1)) {\n level = highestLevelAbove\n } else {\n level = previousHeadline?.level || 1\n }\n\n return level\n}\n\nexport const getLinearIndexes: GetTableOfContentIndexFunction = (_headline, previousHeadlines) => {\n const previousHeadline = previousHeadlines.at(-1)\n\n if (!previousHeadline) {\n return 1\n }\n\n return (previousHeadline?.itemIndex || 1) + 1\n}\n\nexport const getHierarchicalIndexes: GetTableOfContentIndexFunction = (headline, previousHeadlines, currentLevel) => {\n const level = currentLevel || headline.node.attrs.level || 1\n let itemIndex = 1\n\n const previousHeadlinesOnLevelOrBelow = previousHeadlines.filter(h => h.level <= level)\n\n if (previousHeadlinesOnLevelOrBelow.at(-1)?.level === level) {\n itemIndex = (previousHeadlinesOnLevelOrBelow.at(-1)?.itemIndex || 1) + 1\n } else {\n itemIndex = 1\n }\n\n return itemIndex\n}\n\nexport function debounce(func: (...args: any[]) => void, wait: number) {\n let timeout: ReturnType<typeof setTimeout> | null = null\n\n return (...args: any[]) => {\n if (timeout) {\n clearTimeout(timeout)\n }\n timeout = setTimeout(() => {\n func(...args)\n }, wait)\n }\n}\n"],"mappings":"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","names":["import_uuid","tr","uuidv4","uuidv4","_a","scrollParent"]}
package/dist/index.js CHANGED
@@ -15,6 +15,9 @@ var TableOfContentsPlugin = ({
15
15
  if (typeof window === "undefined") {
16
16
  return null;
17
17
  }
18
+ if (transactions.some((tr2) => tr2.getMeta("composition"))) {
19
+ return;
20
+ }
18
21
  const tr = newState.tr;
19
22
  let modified = false;
20
23
  if (transactions.some((transaction) => transaction.docChanged)) {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/tableOfContents.ts","../src/plugin.ts","../src/utils.ts","../src/index.ts"],"sourcesContent":["import type { Editor } from '@tiptap/core'\nimport { Extension } from '@tiptap/core'\nimport type { Node as TiptapNode } from '@tiptap/pm/model'\nimport { v4 as uuidv4 } from 'uuid'\n\nimport { TableOfContentsPlugin } from './plugin.js'\nimport type {\n GetTableOfContentIndexFunction,\n GetTableOfContentLevelFunction,\n TableOfContentData,\n TableOfContentDataItem,\n TableOfContentsOptions,\n TableOfContentsStorage,\n} from './types.js'\nimport { getHeadlineLevel, getLinearIndexes } from './utils.js'\n\nexport * from './types.js'\n\nconst addTocActiveStatesAndGetItems = (\n content: TableOfContentDataItem[],\n options: {\n editor: Editor\n anchorTypes: Array<string> | undefined\n storage: TableOfContentsStorage\n onUpdate?: (data: TableOfContentData, isCreate?: boolean) => void | undefined\n },\n) => {\n const { editor } = options\n const headlines: Array<{ node: TiptapNode; pos: number }> = []\n const scrolledOverIds: string[] = []\n let activeId: string | null = null\n\n if (editor.isDestroyed) {\n return content\n }\n\n editor.state.doc.descendants((node, pos) => {\n const isValidType = options.anchorTypes?.includes(node.type.name)\n\n if (!isValidType) {\n return\n }\n\n headlines.push({ node, pos })\n })\n\n headlines.forEach(headline => {\n const domElement = editor.view.domAtPos(headline.pos + 1).node as HTMLHeadingElement | HTMLElement\n const scrolledOver = options.storage.scrollPosition >= domElement.offsetTop\n\n if (scrolledOver) {\n activeId = headline.node.attrs['data-toc-id']\n scrolledOverIds.push(headline.node.attrs['data-toc-id'])\n }\n })\n\n content = content.map(heading => ({\n ...heading,\n isActive: heading.id === activeId,\n isScrolledOver: scrolledOverIds.includes(heading.id),\n }))\n\n if (options.onUpdate) {\n const isInitialCreation = options.storage.content.length === 0\n\n options.onUpdate(content, isInitialCreation)\n }\n\n return content\n}\n\nconst setTocData = (options: {\n editor: Editor\n anchorTypes: Array<string> | undefined\n getIndexFn: GetTableOfContentIndexFunction\n getLevelFn: GetTableOfContentLevelFunction\n storage: TableOfContentsStorage\n onUpdate?: (data: TableOfContentData, isCreate?: boolean) => void | undefined\n}) => {\n const { editor, onUpdate } = options\n\n if (editor.isDestroyed) {\n return\n }\n\n const headlines: Array<{ node: TiptapNode; pos: number }> = []\n\n let anchors: TableOfContentDataItem[] = []\n const anchorEls: Array<HTMLHeadingElement | HTMLElement> = []\n\n editor.state.doc.descendants((node, pos) => {\n const isValidType = options.anchorTypes?.includes(node.type.name)\n\n if (!isValidType) {\n return\n }\n\n headlines.push({ node, pos })\n })\n\n headlines.forEach((headline, i) => {\n if (headline.node.textContent.length === 0) {\n return\n }\n\n const domElement = editor.view.domAtPos(headline.pos + 1).node as HTMLHeadingElement\n const scrolledOver = options.storage.scrollPosition >= domElement.offsetTop\n\n anchorEls.push(domElement)\n\n const originalLevel = headline.node.attrs.level\n\n const prevHeadline = headlines[i - 1]\n\n const level = options.getLevelFn(headline, anchors)\n const itemIndex = options.getIndexFn(headline, anchors, level)\n\n if (!prevHeadline) {\n anchors = [\n ...anchors,\n {\n itemIndex,\n id: headline.node.attrs['data-toc-id'],\n originalLevel,\n level,\n textContent: headline.node.textContent,\n pos: headline.pos,\n editor,\n isActive: false,\n isScrolledOver: scrolledOver,\n node: headline.node,\n dom: domElement,\n },\n ]\n\n return\n }\n\n anchors = [\n ...anchors,\n {\n itemIndex,\n id: headline.node.attrs['data-toc-id'],\n originalLevel,\n level,\n textContent: headline.node.textContent,\n pos: headline.pos,\n editor,\n isActive: false,\n isScrolledOver: false,\n node: headline.node,\n dom: domElement,\n },\n ]\n })\n\n anchors = addTocActiveStatesAndGetItems(anchors, options)\n\n if (onUpdate) {\n const isInitialCreation = options.storage.content.length === 0\n\n onUpdate(anchors, isInitialCreation)\n }\n\n options.storage.anchors = anchorEls\n options.storage.content = anchors\n editor.state.tr.setMeta('toc', anchors)\n editor.view.dispatch(editor.state.tr)\n}\n\nexport const TableOfContents = Extension.create<TableOfContentsOptions, TableOfContentsStorage>({\n name: 'tableOfContents',\n\n addStorage() {\n return {\n content: [],\n anchors: [],\n scrollHandler: () => null,\n scrollPosition: 0,\n }\n },\n\n addGlobalAttributes() {\n return [\n {\n types: (this.options.anchorTypes as string[]) || ['headline'],\n attributes: {\n id: {\n default: null,\n renderHTML: attributes => {\n return {\n id: attributes.id,\n }\n },\n parseHTML: element => {\n return element.id || null\n },\n },\n 'data-toc-id': {\n default: null,\n renderHTML: attributes => {\n return {\n 'data-toc-id': attributes['data-toc-id'],\n }\n },\n parseHTML: element => {\n return element.dataset.tocId || null\n },\n },\n },\n },\n ]\n },\n\n addOptions() {\n const defaultScrollParent = typeof window !== 'undefined' ? () => window : undefined\n\n return {\n // eslint-disable-next-line\n onUpdate: () => {},\n // eslint-disable-next-line\n getId: _textContent => uuidv4(),\n\n scrollParent: defaultScrollParent,\n\n anchorTypes: ['heading'],\n }\n },\n\n addCommands() {\n return {\n updateTableOfContents:\n () =>\n ({ dispatch }) => {\n if (dispatch) {\n setTocData({\n editor: this.editor,\n storage: this.storage,\n onUpdate: this.options.onUpdate?.bind(this),\n getIndexFn: this.options.getIndex || getLinearIndexes,\n getLevelFn: this.options.getLevel || getHeadlineLevel,\n anchorTypes: this.options.anchorTypes,\n })\n }\n\n return true\n },\n }\n },\n\n onTransaction({ transaction }) {\n if (transaction.docChanged && !transaction.getMeta('toc')) {\n setTocData({\n editor: this.editor,\n storage: this.storage,\n onUpdate: this.options.onUpdate?.bind(this),\n getIndexFn: this.options.getIndex || getLinearIndexes,\n getLevelFn: this.options.getLevel || getHeadlineLevel,\n anchorTypes: this.options.anchorTypes,\n })\n }\n },\n\n onCreate() {\n // Avoid mutating the document during server-side rendering.\n if (typeof window === 'undefined' || !this.editor.view) {\n return\n }\n\n const { tr } = this.editor.state\n const existingIds: string[] = []\n\n if (this.options.scrollParent && typeof this.options.scrollParent !== 'function') {\n console.warn(\n \"[Tiptap Table of Contents Deprecation Notice]: The 'scrollParent' option must now be provided as a callback function that returns the 'scrollParent' element. The ability to pass this option directly will be deprecated in future releases.\",\n )\n }\n\n this.editor.state.doc.descendants((node, pos) => {\n const nodeId = node.attrs['data-toc-id']\n const isValidType = this.options.anchorTypes?.includes(node.type.name)\n\n if (!isValidType || node.textContent.length === 0) {\n return\n }\n\n if (nodeId === null || nodeId === undefined || existingIds.includes(nodeId)) {\n let id = ''\n\n if (this.options.getId) {\n id = this.options.getId(node.textContent)\n } else {\n id = uuidv4()\n }\n\n tr.setNodeMarkup(pos, undefined, {\n ...node.attrs,\n 'data-toc-id': id,\n id,\n })\n }\n\n existingIds.push(nodeId)\n })\n\n this.editor.view.dispatch(tr)\n\n setTocData({\n editor: this.editor,\n storage: this.storage,\n onUpdate: this.options.onUpdate?.bind(this),\n getIndexFn: this.options.getIndex || getLinearIndexes,\n getLevelFn: this.options.getLevel || getHeadlineLevel,\n anchorTypes: this.options.anchorTypes,\n })\n\n this.storage.scrollHandler = () => {\n if (!this.options.scrollParent) {\n return\n }\n\n // if scrollParent is HTML Element, use scrollTop - otherwise use scrollY\n const scrollParent =\n typeof this.options.scrollParent === 'function' ? this.options.scrollParent() : this.options.scrollParent\n\n const scrollPosition = scrollParent instanceof HTMLElement ? scrollParent.scrollTop : scrollParent.scrollY\n\n this.storage.scrollPosition = scrollPosition || 0\n\n const updatedItems = addTocActiveStatesAndGetItems(this.storage.content, {\n editor: this.editor,\n anchorTypes: this.options.anchorTypes,\n storage: this.storage,\n onUpdate: this.options.onUpdate?.bind(this),\n })\n\n this.storage.content = updatedItems\n }\n\n if (!this.options.scrollParent) {\n return\n }\n\n const scrollParent =\n typeof this.options.scrollParent === 'function' ? this.options.scrollParent() : this.options.scrollParent\n\n if (scrollParent) {\n scrollParent.addEventListener('scroll', this.storage.scrollHandler)\n }\n },\n\n onDestroy() {\n if (!this.options.scrollParent) {\n return\n }\n\n const scrollParent =\n typeof this.options.scrollParent === 'function' ? this.options.scrollParent() : this.options.scrollParent\n\n if (scrollParent) {\n scrollParent.removeEventListener('scroll', this.storage.scrollHandler)\n }\n },\n\n addProseMirrorPlugins() {\n return [TableOfContentsPlugin({ getId: this.options.getId, anchorTypes: this.options.anchorTypes })]\n },\n})\n","import type { NodeType } from '@tiptap/pm/model'\nimport { Plugin, PluginKey } from '@tiptap/pm/state'\nimport { v4 as uuidv4 } from 'uuid'\n\nexport const TableOfContentsPlugin = ({\n getId,\n anchorTypes = ['heading'],\n}: {\n getId?: (textContent: string) => string\n anchorTypes?: Array<string | NodeType>\n}) => {\n return new Plugin({\n key: new PluginKey('tableOfContent'),\n\n appendTransaction(transactions, _oldState, newState) {\n // Avoid running on the server where `window` / DOM is not available.\n if (typeof window === 'undefined') {\n return null\n }\n\n const tr = newState.tr\n let modified = false\n\n if (transactions.some(transaction => transaction.docChanged)) {\n const existingIds: string[] = []\n\n newState.doc.descendants((node, pos) => {\n const nodeId = node.attrs['data-toc-id']\n\n if (!anchorTypes.includes(node.type.name) || node.textContent.length === 0) {\n return\n }\n\n if (nodeId === null || nodeId === undefined || existingIds.includes(nodeId)) {\n let id = ''\n\n if (getId) {\n id = getId(node.textContent)\n } else {\n id = uuidv4()\n }\n\n tr.setNodeMarkup(pos, undefined, {\n ...node.attrs,\n 'data-toc-id': id,\n id,\n })\n\n modified = true\n }\n\n existingIds.push(nodeId)\n })\n }\n\n return modified ? tr : null\n },\n })\n}\n","import type { GetTableOfContentIndexFunction, GetTableOfContentLevelFunction, TableOfContentDataItem } from './types.js'\n\nexport const getLastHeadingOnLevel = (\n headings: TableOfContentDataItem[],\n level: number,\n): TableOfContentDataItem | undefined => {\n let heading = headings.filter(currentHeading => currentHeading.level === level).pop()\n\n if (level === 0) {\n return undefined\n }\n\n if (!heading) {\n heading = getLastHeadingOnLevel(headings, level - 1)\n }\n\n return heading\n}\n\nexport const getHeadlineLevel: GetTableOfContentLevelFunction = (headline, previousItems) => {\n let level = 1\n\n const previousHeadline = previousItems.at(-1)\n const highestHeadlineAbove = [...previousItems].reverse().find(h => h.originalLevel <= headline.node.attrs.level)\n\n const highestLevelAbove = highestHeadlineAbove?.level || 1\n\n if (headline.node.attrs.level > (previousHeadline?.originalLevel || 1)) {\n level = (previousHeadline?.level || 1) + 1\n } else if (headline.node.attrs.level < (previousHeadline?.originalLevel || 1)) {\n level = highestLevelAbove\n } else {\n level = previousHeadline?.level || 1\n }\n\n return level\n}\n\nexport const getLinearIndexes: GetTableOfContentIndexFunction = (_headline, previousHeadlines) => {\n const previousHeadline = previousHeadlines.at(-1)\n\n if (!previousHeadline) {\n return 1\n }\n\n return (previousHeadline?.itemIndex || 1) + 1\n}\n\nexport const getHierarchicalIndexes: GetTableOfContentIndexFunction = (headline, previousHeadlines, currentLevel) => {\n const level = currentLevel || headline.node.attrs.level || 1\n let itemIndex = 1\n\n const previousHeadlinesOnLevelOrBelow = previousHeadlines.filter(h => h.level <= level)\n\n if (previousHeadlinesOnLevelOrBelow.at(-1)?.level === level) {\n itemIndex = (previousHeadlinesOnLevelOrBelow.at(-1)?.itemIndex || 1) + 1\n } else {\n itemIndex = 1\n }\n\n return itemIndex\n}\n\nexport function debounce(func: (...args: any[]) => void, wait: number) {\n let timeout: ReturnType<typeof setTimeout> | null = null\n\n return (...args: any[]) => {\n if (timeout) {\n clearTimeout(timeout)\n }\n timeout = setTimeout(() => {\n func(...args)\n }, wait)\n }\n}\n","import { TableOfContents } from './tableOfContents.js'\n\nexport * from './plugin.js'\nexport * from './tableOfContents.js'\nexport * from './utils.js'\n\nexport default TableOfContents\n"],"mappings":"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","names":["uuidv4","uuidv4","_a","scrollParent"]}
1
+ {"version":3,"sources":["../src/tableOfContents.ts","../src/plugin.ts","../src/utils.ts","../src/index.ts"],"sourcesContent":["import type { Editor } from '@tiptap/core'\nimport { Extension } from '@tiptap/core'\nimport type { Node as TiptapNode } from '@tiptap/pm/model'\nimport { v4 as uuidv4 } from 'uuid'\n\nimport { TableOfContentsPlugin } from './plugin.js'\nimport type {\n GetTableOfContentIndexFunction,\n GetTableOfContentLevelFunction,\n TableOfContentData,\n TableOfContentDataItem,\n TableOfContentsOptions,\n TableOfContentsStorage,\n} from './types.js'\nimport { getHeadlineLevel, getLinearIndexes } from './utils.js'\n\nexport * from './types.js'\n\nconst addTocActiveStatesAndGetItems = (\n content: TableOfContentDataItem[],\n options: {\n editor: Editor\n anchorTypes: Array<string> | undefined\n storage: TableOfContentsStorage\n onUpdate?: (data: TableOfContentData, isCreate?: boolean) => void | undefined\n },\n) => {\n const { editor } = options\n const headlines: Array<{ node: TiptapNode; pos: number }> = []\n const scrolledOverIds: string[] = []\n let activeId: string | null = null\n\n if (editor.isDestroyed) {\n return content\n }\n\n editor.state.doc.descendants((node, pos) => {\n const isValidType = options.anchorTypes?.includes(node.type.name)\n\n if (!isValidType) {\n return\n }\n\n headlines.push({ node, pos })\n })\n\n headlines.forEach(headline => {\n const domElement = editor.view.domAtPos(headline.pos + 1).node as HTMLHeadingElement | HTMLElement\n const scrolledOver = options.storage.scrollPosition >= domElement.offsetTop\n\n if (scrolledOver) {\n activeId = headline.node.attrs['data-toc-id']\n scrolledOverIds.push(headline.node.attrs['data-toc-id'])\n }\n })\n\n content = content.map(heading => ({\n ...heading,\n isActive: heading.id === activeId,\n isScrolledOver: scrolledOverIds.includes(heading.id),\n }))\n\n if (options.onUpdate) {\n const isInitialCreation = options.storage.content.length === 0\n\n options.onUpdate(content, isInitialCreation)\n }\n\n return content\n}\n\nconst setTocData = (options: {\n editor: Editor\n anchorTypes: Array<string> | undefined\n getIndexFn: GetTableOfContentIndexFunction\n getLevelFn: GetTableOfContentLevelFunction\n storage: TableOfContentsStorage\n onUpdate?: (data: TableOfContentData, isCreate?: boolean) => void | undefined\n}) => {\n const { editor, onUpdate } = options\n\n if (editor.isDestroyed) {\n return\n }\n\n const headlines: Array<{ node: TiptapNode; pos: number }> = []\n\n let anchors: TableOfContentDataItem[] = []\n const anchorEls: Array<HTMLHeadingElement | HTMLElement> = []\n\n editor.state.doc.descendants((node, pos) => {\n const isValidType = options.anchorTypes?.includes(node.type.name)\n\n if (!isValidType) {\n return\n }\n\n headlines.push({ node, pos })\n })\n\n headlines.forEach((headline, i) => {\n if (headline.node.textContent.length === 0) {\n return\n }\n\n const domElement = editor.view.domAtPos(headline.pos + 1).node as HTMLHeadingElement\n const scrolledOver = options.storage.scrollPosition >= domElement.offsetTop\n\n anchorEls.push(domElement)\n\n const originalLevel = headline.node.attrs.level\n\n const prevHeadline = headlines[i - 1]\n\n const level = options.getLevelFn(headline, anchors)\n const itemIndex = options.getIndexFn(headline, anchors, level)\n\n if (!prevHeadline) {\n anchors = [\n ...anchors,\n {\n itemIndex,\n id: headline.node.attrs['data-toc-id'],\n originalLevel,\n level,\n textContent: headline.node.textContent,\n pos: headline.pos,\n editor,\n isActive: false,\n isScrolledOver: scrolledOver,\n node: headline.node,\n dom: domElement,\n },\n ]\n\n return\n }\n\n anchors = [\n ...anchors,\n {\n itemIndex,\n id: headline.node.attrs['data-toc-id'],\n originalLevel,\n level,\n textContent: headline.node.textContent,\n pos: headline.pos,\n editor,\n isActive: false,\n isScrolledOver: false,\n node: headline.node,\n dom: domElement,\n },\n ]\n })\n\n anchors = addTocActiveStatesAndGetItems(anchors, options)\n\n if (onUpdate) {\n const isInitialCreation = options.storage.content.length === 0\n\n onUpdate(anchors, isInitialCreation)\n }\n\n options.storage.anchors = anchorEls\n options.storage.content = anchors\n editor.state.tr.setMeta('toc', anchors)\n editor.view.dispatch(editor.state.tr)\n}\n\nexport const TableOfContents = Extension.create<TableOfContentsOptions, TableOfContentsStorage>({\n name: 'tableOfContents',\n\n addStorage() {\n return {\n content: [],\n anchors: [],\n scrollHandler: () => null,\n scrollPosition: 0,\n }\n },\n\n addGlobalAttributes() {\n return [\n {\n types: (this.options.anchorTypes as string[]) || ['headline'],\n attributes: {\n id: {\n default: null,\n renderHTML: attributes => {\n return {\n id: attributes.id,\n }\n },\n parseHTML: element => {\n return element.id || null\n },\n },\n 'data-toc-id': {\n default: null,\n renderHTML: attributes => {\n return {\n 'data-toc-id': attributes['data-toc-id'],\n }\n },\n parseHTML: element => {\n return element.dataset.tocId || null\n },\n },\n },\n },\n ]\n },\n\n addOptions() {\n const defaultScrollParent = typeof window !== 'undefined' ? () => window : undefined\n\n return {\n // eslint-disable-next-line\n onUpdate: () => {},\n // eslint-disable-next-line\n getId: _textContent => uuidv4(),\n\n scrollParent: defaultScrollParent,\n\n anchorTypes: ['heading'],\n }\n },\n\n addCommands() {\n return {\n updateTableOfContents:\n () =>\n ({ dispatch }) => {\n if (dispatch) {\n setTocData({\n editor: this.editor,\n storage: this.storage,\n onUpdate: this.options.onUpdate?.bind(this),\n getIndexFn: this.options.getIndex || getLinearIndexes,\n getLevelFn: this.options.getLevel || getHeadlineLevel,\n anchorTypes: this.options.anchorTypes,\n })\n }\n\n return true\n },\n }\n },\n\n onTransaction({ transaction }) {\n if (transaction.docChanged && !transaction.getMeta('toc')) {\n setTocData({\n editor: this.editor,\n storage: this.storage,\n onUpdate: this.options.onUpdate?.bind(this),\n getIndexFn: this.options.getIndex || getLinearIndexes,\n getLevelFn: this.options.getLevel || getHeadlineLevel,\n anchorTypes: this.options.anchorTypes,\n })\n }\n },\n\n onCreate() {\n // Avoid mutating the document during server-side rendering.\n if (typeof window === 'undefined' || !this.editor.view) {\n return\n }\n\n const { tr } = this.editor.state\n const existingIds: string[] = []\n\n if (this.options.scrollParent && typeof this.options.scrollParent !== 'function') {\n console.warn(\n \"[Tiptap Table of Contents Deprecation Notice]: The 'scrollParent' option must now be provided as a callback function that returns the 'scrollParent' element. The ability to pass this option directly will be deprecated in future releases.\",\n )\n }\n\n this.editor.state.doc.descendants((node, pos) => {\n const nodeId = node.attrs['data-toc-id']\n const isValidType = this.options.anchorTypes?.includes(node.type.name)\n\n if (!isValidType || node.textContent.length === 0) {\n return\n }\n\n if (nodeId === null || nodeId === undefined || existingIds.includes(nodeId)) {\n let id = ''\n\n if (this.options.getId) {\n id = this.options.getId(node.textContent)\n } else {\n id = uuidv4()\n }\n\n tr.setNodeMarkup(pos, undefined, {\n ...node.attrs,\n 'data-toc-id': id,\n id,\n })\n }\n\n existingIds.push(nodeId)\n })\n\n this.editor.view.dispatch(tr)\n\n setTocData({\n editor: this.editor,\n storage: this.storage,\n onUpdate: this.options.onUpdate?.bind(this),\n getIndexFn: this.options.getIndex || getLinearIndexes,\n getLevelFn: this.options.getLevel || getHeadlineLevel,\n anchorTypes: this.options.anchorTypes,\n })\n\n this.storage.scrollHandler = () => {\n if (!this.options.scrollParent) {\n return\n }\n\n // if scrollParent is HTML Element, use scrollTop - otherwise use scrollY\n const scrollParent =\n typeof this.options.scrollParent === 'function' ? this.options.scrollParent() : this.options.scrollParent\n\n const scrollPosition = scrollParent instanceof HTMLElement ? scrollParent.scrollTop : scrollParent.scrollY\n\n this.storage.scrollPosition = scrollPosition || 0\n\n const updatedItems = addTocActiveStatesAndGetItems(this.storage.content, {\n editor: this.editor,\n anchorTypes: this.options.anchorTypes,\n storage: this.storage,\n onUpdate: this.options.onUpdate?.bind(this),\n })\n\n this.storage.content = updatedItems\n }\n\n if (!this.options.scrollParent) {\n return\n }\n\n const scrollParent =\n typeof this.options.scrollParent === 'function' ? this.options.scrollParent() : this.options.scrollParent\n\n if (scrollParent) {\n scrollParent.addEventListener('scroll', this.storage.scrollHandler)\n }\n },\n\n onDestroy() {\n if (!this.options.scrollParent) {\n return\n }\n\n const scrollParent =\n typeof this.options.scrollParent === 'function' ? this.options.scrollParent() : this.options.scrollParent\n\n if (scrollParent) {\n scrollParent.removeEventListener('scroll', this.storage.scrollHandler)\n }\n },\n\n addProseMirrorPlugins() {\n return [TableOfContentsPlugin({ getId: this.options.getId, anchorTypes: this.options.anchorTypes })]\n },\n})\n","import type { NodeType } from '@tiptap/pm/model'\nimport { Plugin, PluginKey } from '@tiptap/pm/state'\nimport { v4 as uuidv4 } from 'uuid'\n\nexport const TableOfContentsPlugin = ({\n getId,\n anchorTypes = ['heading'],\n}: {\n getId?: (textContent: string) => string\n anchorTypes?: Array<string | NodeType>\n}) => {\n return new Plugin({\n key: new PluginKey('tableOfContent'),\n\n appendTransaction(transactions, _oldState, newState) {\n // Avoid running on the server where `window` / DOM is not available.\n if (typeof window === 'undefined') {\n return null\n }\n\n // Skip updating table of contents during IME composition\n // to avoid interfering with input method editor\n if (transactions.some(tr => tr.getMeta('composition'))) {\n return\n }\n\n const tr = newState.tr\n let modified = false\n\n if (transactions.some(transaction => transaction.docChanged)) {\n const existingIds: string[] = []\n\n newState.doc.descendants((node, pos) => {\n const nodeId = node.attrs['data-toc-id']\n\n if (!anchorTypes.includes(node.type.name) || node.textContent.length === 0) {\n return\n }\n\n if (nodeId === null || nodeId === undefined || existingIds.includes(nodeId)) {\n let id = ''\n\n if (getId) {\n id = getId(node.textContent)\n } else {\n id = uuidv4()\n }\n\n tr.setNodeMarkup(pos, undefined, {\n ...node.attrs,\n 'data-toc-id': id,\n id,\n })\n\n modified = true\n }\n\n existingIds.push(nodeId)\n })\n }\n\n return modified ? tr : null\n },\n })\n}\n","import type { GetTableOfContentIndexFunction, GetTableOfContentLevelFunction, TableOfContentDataItem } from './types.js'\n\nexport const getLastHeadingOnLevel = (\n headings: TableOfContentDataItem[],\n level: number,\n): TableOfContentDataItem | undefined => {\n let heading = headings.filter(currentHeading => currentHeading.level === level).pop()\n\n if (level === 0) {\n return undefined\n }\n\n if (!heading) {\n heading = getLastHeadingOnLevel(headings, level - 1)\n }\n\n return heading\n}\n\nexport const getHeadlineLevel: GetTableOfContentLevelFunction = (headline, previousItems) => {\n let level = 1\n\n const previousHeadline = previousItems.at(-1)\n const highestHeadlineAbove = [...previousItems].reverse().find(h => h.originalLevel <= headline.node.attrs.level)\n\n const highestLevelAbove = highestHeadlineAbove?.level || 1\n\n if (headline.node.attrs.level > (previousHeadline?.originalLevel || 1)) {\n level = (previousHeadline?.level || 1) + 1\n } else if (headline.node.attrs.level < (previousHeadline?.originalLevel || 1)) {\n level = highestLevelAbove\n } else {\n level = previousHeadline?.level || 1\n }\n\n return level\n}\n\nexport const getLinearIndexes: GetTableOfContentIndexFunction = (_headline, previousHeadlines) => {\n const previousHeadline = previousHeadlines.at(-1)\n\n if (!previousHeadline) {\n return 1\n }\n\n return (previousHeadline?.itemIndex || 1) + 1\n}\n\nexport const getHierarchicalIndexes: GetTableOfContentIndexFunction = (headline, previousHeadlines, currentLevel) => {\n const level = currentLevel || headline.node.attrs.level || 1\n let itemIndex = 1\n\n const previousHeadlinesOnLevelOrBelow = previousHeadlines.filter(h => h.level <= level)\n\n if (previousHeadlinesOnLevelOrBelow.at(-1)?.level === level) {\n itemIndex = (previousHeadlinesOnLevelOrBelow.at(-1)?.itemIndex || 1) + 1\n } else {\n itemIndex = 1\n }\n\n return itemIndex\n}\n\nexport function debounce(func: (...args: any[]) => void, wait: number) {\n let timeout: ReturnType<typeof setTimeout> | null = null\n\n return (...args: any[]) => {\n if (timeout) {\n clearTimeout(timeout)\n }\n timeout = setTimeout(() => {\n func(...args)\n }, wait)\n }\n}\n","import { TableOfContents } from './tableOfContents.js'\n\nexport * from './plugin.js'\nexport * from './tableOfContents.js'\nexport * from './utils.js'\n\nexport default TableOfContents\n"],"mappings":";AACA,SAAS,iBAAiB;AAE1B,SAAS,MAAMA,eAAc;;;ACF7B,SAAS,QAAQ,iBAAiB;AAClC,SAAS,MAAM,cAAc;AAEtB,IAAM,wBAAwB,CAAC;AAAA,EACpC;AAAA,EACA,cAAc,CAAC,SAAS;AAC1B,MAGM;AACJ,SAAO,IAAI,OAAO;AAAA,IAChB,KAAK,IAAI,UAAU,gBAAgB;AAAA,IAEnC,kBAAkB,cAAc,WAAW,UAAU;AAEnD,UAAI,OAAO,WAAW,aAAa;AACjC,eAAO;AAAA,MACT;AAIA,UAAI,aAAa,KAAK,CAAAC,QAAMA,IAAG,QAAQ,aAAa,CAAC,GAAG;AACtD;AAAA,MACF;AAEA,YAAM,KAAK,SAAS;AACpB,UAAI,WAAW;AAEf,UAAI,aAAa,KAAK,iBAAe,YAAY,UAAU,GAAG;AAC5D,cAAM,cAAwB,CAAC;AAE/B,iBAAS,IAAI,YAAY,CAAC,MAAM,QAAQ;AACtC,gBAAM,SAAS,KAAK,MAAM,aAAa;AAEvC,cAAI,CAAC,YAAY,SAAS,KAAK,KAAK,IAAI,KAAK,KAAK,YAAY,WAAW,GAAG;AAC1E;AAAA,UACF;AAEA,cAAI,WAAW,QAAQ,WAAW,UAAa,YAAY,SAAS,MAAM,GAAG;AAC3E,gBAAI,KAAK;AAET,gBAAI,OAAO;AACT,mBAAK,MAAM,KAAK,WAAW;AAAA,YAC7B,OAAO;AACL,mBAAK,OAAO;AAAA,YACd;AAEA,eAAG,cAAc,KAAK,QAAW;AAAA,cAC/B,GAAG,KAAK;AAAA,cACR,eAAe;AAAA,cACf;AAAA,YACF,CAAC;AAED,uBAAW;AAAA,UACb;AAEA,sBAAY,KAAK,MAAM;AAAA,QACzB,CAAC;AAAA,MACH;AAEA,aAAO,WAAW,KAAK;AAAA,IACzB;AAAA,EACF,CAAC;AACH;;;AC9DO,IAAM,wBAAwB,CACnC,UACA,UACuC;AACvC,MAAI,UAAU,SAAS,OAAO,oBAAkB,eAAe,UAAU,KAAK,EAAE,IAAI;AAEpF,MAAI,UAAU,GAAG;AACf,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,SAAS;AACZ,cAAU,sBAAsB,UAAU,QAAQ,CAAC;AAAA,EACrD;AAEA,SAAO;AACT;AAEO,IAAM,mBAAmD,CAAC,UAAU,kBAAkB;AAC3F,MAAI,QAAQ;AAEZ,QAAM,mBAAmB,cAAc,GAAG,EAAE;AAC5C,QAAM,uBAAuB,CAAC,GAAG,aAAa,EAAE,QAAQ,EAAE,KAAK,OAAK,EAAE,iBAAiB,SAAS,KAAK,MAAM,KAAK;AAEhH,QAAM,qBAAoB,6DAAsB,UAAS;AAEzD,MAAI,SAAS,KAAK,MAAM,UAAS,qDAAkB,kBAAiB,IAAI;AACtE,cAAS,qDAAkB,UAAS,KAAK;AAAA,EAC3C,WAAW,SAAS,KAAK,MAAM,UAAS,qDAAkB,kBAAiB,IAAI;AAC7E,YAAQ;AAAA,EACV,OAAO;AACL,aAAQ,qDAAkB,UAAS;AAAA,EACrC;AAEA,SAAO;AACT;AAEO,IAAM,mBAAmD,CAAC,WAAW,sBAAsB;AAChG,QAAM,mBAAmB,kBAAkB,GAAG,EAAE;AAEhD,MAAI,CAAC,kBAAkB;AACrB,WAAO;AAAA,EACT;AAEA,WAAQ,qDAAkB,cAAa,KAAK;AAC9C;AAEO,IAAM,yBAAyD,CAAC,UAAU,mBAAmB,iBAAiB;AAhDrH;AAiDE,QAAM,QAAQ,gBAAgB,SAAS,KAAK,MAAM,SAAS;AAC3D,MAAI,YAAY;AAEhB,QAAM,kCAAkC,kBAAkB,OAAO,OAAK,EAAE,SAAS,KAAK;AAEtF,QAAI,qCAAgC,GAAG,EAAE,MAArC,mBAAwC,WAAU,OAAO;AAC3D,mBAAa,qCAAgC,GAAG,EAAE,MAArC,mBAAwC,cAAa,KAAK;AAAA,EACzE,OAAO;AACL,gBAAY;AAAA,EACd;AAEA,SAAO;AACT;AAEO,SAAS,SAAS,MAAgC,MAAc;AACrE,MAAI,UAAgD;AAEpD,SAAO,IAAI,SAAgB;AACzB,QAAI,SAAS;AACX,mBAAa,OAAO;AAAA,IACtB;AACA,cAAU,WAAW,MAAM;AACzB,WAAK,GAAG,IAAI;AAAA,IACd,GAAG,IAAI;AAAA,EACT;AACF;;;AFxDA,IAAM,gCAAgC,CACpC,SACA,YAMG;AACH,QAAM,EAAE,OAAO,IAAI;AACnB,QAAM,YAAsD,CAAC;AAC7D,QAAM,kBAA4B,CAAC;AACnC,MAAI,WAA0B;AAE9B,MAAI,OAAO,aAAa;AACtB,WAAO;AAAA,EACT;AAEA,SAAO,MAAM,IAAI,YAAY,CAAC,MAAM,QAAQ;AApC9C;AAqCI,UAAM,eAAc,aAAQ,gBAAR,mBAAqB,SAAS,KAAK,KAAK;AAE5D,QAAI,CAAC,aAAa;AAChB;AAAA,IACF;AAEA,cAAU,KAAK,EAAE,MAAM,IAAI,CAAC;AAAA,EAC9B,CAAC;AAED,YAAU,QAAQ,cAAY;AAC5B,UAAM,aAAa,OAAO,KAAK,SAAS,SAAS,MAAM,CAAC,EAAE;AAC1D,UAAM,eAAe,QAAQ,QAAQ,kBAAkB,WAAW;AAElE,QAAI,cAAc;AAChB,iBAAW,SAAS,KAAK,MAAM,aAAa;AAC5C,sBAAgB,KAAK,SAAS,KAAK,MAAM,aAAa,CAAC;AAAA,IACzD;AAAA,EACF,CAAC;AAED,YAAU,QAAQ,IAAI,cAAY;AAAA,IAChC,GAAG;AAAA,IACH,UAAU,QAAQ,OAAO;AAAA,IACzB,gBAAgB,gBAAgB,SAAS,QAAQ,EAAE;AAAA,EACrD,EAAE;AAEF,MAAI,QAAQ,UAAU;AACpB,UAAM,oBAAoB,QAAQ,QAAQ,QAAQ,WAAW;AAE7D,YAAQ,SAAS,SAAS,iBAAiB;AAAA,EAC7C;AAEA,SAAO;AACT;AAEA,IAAM,aAAa,CAAC,YAOd;AACJ,QAAM,EAAE,QAAQ,SAAS,IAAI;AAE7B,MAAI,OAAO,aAAa;AACtB;AAAA,EACF;AAEA,QAAM,YAAsD,CAAC;AAE7D,MAAI,UAAoC,CAAC;AACzC,QAAM,YAAqD,CAAC;AAE5D,SAAO,MAAM,IAAI,YAAY,CAAC,MAAM,QAAQ;AA1F9C;AA2FI,UAAM,eAAc,aAAQ,gBAAR,mBAAqB,SAAS,KAAK,KAAK;AAE5D,QAAI,CAAC,aAAa;AAChB;AAAA,IACF;AAEA,cAAU,KAAK,EAAE,MAAM,IAAI,CAAC;AAAA,EAC9B,CAAC;AAED,YAAU,QAAQ,CAAC,UAAU,MAAM;AACjC,QAAI,SAAS,KAAK,YAAY,WAAW,GAAG;AAC1C;AAAA,IACF;AAEA,UAAM,aAAa,OAAO,KAAK,SAAS,SAAS,MAAM,CAAC,EAAE;AAC1D,UAAM,eAAe,QAAQ,QAAQ,kBAAkB,WAAW;AAElE,cAAU,KAAK,UAAU;AAEzB,UAAM,gBAAgB,SAAS,KAAK,MAAM;AAE1C,UAAM,eAAe,UAAU,IAAI,CAAC;AAEpC,UAAM,QAAQ,QAAQ,WAAW,UAAU,OAAO;AAClD,UAAM,YAAY,QAAQ,WAAW,UAAU,SAAS,KAAK;AAE7D,QAAI,CAAC,cAAc;AACjB,gBAAU;AAAA,QACR,GAAG;AAAA,QACH;AAAA,UACE;AAAA,UACA,IAAI,SAAS,KAAK,MAAM,aAAa;AAAA,UACrC;AAAA,UACA;AAAA,UACA,aAAa,SAAS,KAAK;AAAA,UAC3B,KAAK,SAAS;AAAA,UACd;AAAA,UACA,UAAU;AAAA,UACV,gBAAgB;AAAA,UAChB,MAAM,SAAS;AAAA,UACf,KAAK;AAAA,QACP;AAAA,MACF;AAEA;AAAA,IACF;AAEA,cAAU;AAAA,MACR,GAAG;AAAA,MACH;AAAA,QACE;AAAA,QACA,IAAI,SAAS,KAAK,MAAM,aAAa;AAAA,QACrC;AAAA,QACA;AAAA,QACA,aAAa,SAAS,KAAK;AAAA,QAC3B,KAAK,SAAS;AAAA,QACd;AAAA,QACA,UAAU;AAAA,QACV,gBAAgB;AAAA,QAChB,MAAM,SAAS;AAAA,QACf,KAAK;AAAA,MACP;AAAA,IACF;AAAA,EACF,CAAC;AAED,YAAU,8BAA8B,SAAS,OAAO;AAExD,MAAI,UAAU;AACZ,UAAM,oBAAoB,QAAQ,QAAQ,QAAQ,WAAW;AAE7D,aAAS,SAAS,iBAAiB;AAAA,EACrC;AAEA,UAAQ,QAAQ,UAAU;AAC1B,UAAQ,QAAQ,UAAU;AAC1B,SAAO,MAAM,GAAG,QAAQ,OAAO,OAAO;AACtC,SAAO,KAAK,SAAS,OAAO,MAAM,EAAE;AACtC;AAEO,IAAM,kBAAkB,UAAU,OAAuD;AAAA,EAC9F,MAAM;AAAA,EAEN,aAAa;AACX,WAAO;AAAA,MACL,SAAS,CAAC;AAAA,MACV,SAAS,CAAC;AAAA,MACV,eAAe,MAAM;AAAA,MACrB,gBAAgB;AAAA,IAClB;AAAA,EACF;AAAA,EAEA,sBAAsB;AACpB,WAAO;AAAA,MACL;AAAA,QACE,OAAQ,KAAK,QAAQ,eAA4B,CAAC,UAAU;AAAA,QAC5D,YAAY;AAAA,UACV,IAAI;AAAA,YACF,SAAS;AAAA,YACT,YAAY,gBAAc;AACxB,qBAAO;AAAA,gBACL,IAAI,WAAW;AAAA,cACjB;AAAA,YACF;AAAA,YACA,WAAW,aAAW;AACpB,qBAAO,QAAQ,MAAM;AAAA,YACvB;AAAA,UACF;AAAA,UACA,eAAe;AAAA,YACb,SAAS;AAAA,YACT,YAAY,gBAAc;AACxB,qBAAO;AAAA,gBACL,eAAe,WAAW,aAAa;AAAA,cACzC;AAAA,YACF;AAAA,YACA,WAAW,aAAW;AACpB,qBAAO,QAAQ,QAAQ,SAAS;AAAA,YAClC;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,aAAa;AACX,UAAM,sBAAsB,OAAO,WAAW,cAAc,MAAM,SAAS;AAE3E,WAAO;AAAA;AAAA,MAEL,UAAU,MAAM;AAAA,MAAC;AAAA;AAAA,MAEjB,OAAO,kBAAgBC,QAAO;AAAA,MAE9B,cAAc;AAAA,MAEd,aAAa,CAAC,SAAS;AAAA,IACzB;AAAA,EACF;AAAA,EAEA,cAAc;AACZ,WAAO;AAAA,MACL,uBACE,MACA,CAAC,EAAE,SAAS,MAAM;AAzO1B;AA0OU,YAAI,UAAU;AACZ,qBAAW;AAAA,YACT,QAAQ,KAAK;AAAA,YACb,SAAS,KAAK;AAAA,YACd,WAAU,UAAK,QAAQ,aAAb,mBAAuB,KAAK;AAAA,YACtC,YAAY,KAAK,QAAQ,YAAY;AAAA,YACrC,YAAY,KAAK,QAAQ,YAAY;AAAA,YACrC,aAAa,KAAK,QAAQ;AAAA,UAC5B,CAAC;AAAA,QACH;AAEA,eAAO;AAAA,MACT;AAAA,IACJ;AAAA,EACF;AAAA,EAEA,cAAc,EAAE,YAAY,GAAG;AA1PjC;AA2PI,QAAI,YAAY,cAAc,CAAC,YAAY,QAAQ,KAAK,GAAG;AACzD,iBAAW;AAAA,QACT,QAAQ,KAAK;AAAA,QACb,SAAS,KAAK;AAAA,QACd,WAAU,UAAK,QAAQ,aAAb,mBAAuB,KAAK;AAAA,QACtC,YAAY,KAAK,QAAQ,YAAY;AAAA,QACrC,YAAY,KAAK,QAAQ,YAAY;AAAA,QACrC,aAAa,KAAK,QAAQ;AAAA,MAC5B,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,WAAW;AAvQb;AAyQI,QAAI,OAAO,WAAW,eAAe,CAAC,KAAK,OAAO,MAAM;AACtD;AAAA,IACF;AAEA,UAAM,EAAE,GAAG,IAAI,KAAK,OAAO;AAC3B,UAAM,cAAwB,CAAC;AAE/B,QAAI,KAAK,QAAQ,gBAAgB,OAAO,KAAK,QAAQ,iBAAiB,YAAY;AAChF,cAAQ;AAAA,QACN;AAAA,MACF;AAAA,IACF;AAEA,SAAK,OAAO,MAAM,IAAI,YAAY,CAAC,MAAM,QAAQ;AAtRrD,UAAAC;AAuRM,YAAM,SAAS,KAAK,MAAM,aAAa;AACvC,YAAM,eAAcA,MAAA,KAAK,QAAQ,gBAAb,gBAAAA,IAA0B,SAAS,KAAK,KAAK;AAEjE,UAAI,CAAC,eAAe,KAAK,YAAY,WAAW,GAAG;AACjD;AAAA,MACF;AAEA,UAAI,WAAW,QAAQ,WAAW,UAAa,YAAY,SAAS,MAAM,GAAG;AAC3E,YAAI,KAAK;AAET,YAAI,KAAK,QAAQ,OAAO;AACtB,eAAK,KAAK,QAAQ,MAAM,KAAK,WAAW;AAAA,QAC1C,OAAO;AACL,eAAKD,QAAO;AAAA,QACd;AAEA,WAAG,cAAc,KAAK,QAAW;AAAA,UAC/B,GAAG,KAAK;AAAA,UACR,eAAe;AAAA,UACf;AAAA,QACF,CAAC;AAAA,MACH;AAEA,kBAAY,KAAK,MAAM;AAAA,IACzB,CAAC;AAED,SAAK,OAAO,KAAK,SAAS,EAAE;AAE5B,eAAW;AAAA,MACT,QAAQ,KAAK;AAAA,MACb,SAAS,KAAK;AAAA,MACd,WAAU,UAAK,QAAQ,aAAb,mBAAuB,KAAK;AAAA,MACtC,YAAY,KAAK,QAAQ,YAAY;AAAA,MACrC,YAAY,KAAK,QAAQ,YAAY;AAAA,MACrC,aAAa,KAAK,QAAQ;AAAA,IAC5B,CAAC;AAED,SAAK,QAAQ,gBAAgB,MAAM;AA5TvC,UAAAC;AA6TM,UAAI,CAAC,KAAK,QAAQ,cAAc;AAC9B;AAAA,MACF;AAGA,YAAMC,gBACJ,OAAO,KAAK,QAAQ,iBAAiB,aAAa,KAAK,QAAQ,aAAa,IAAI,KAAK,QAAQ;AAE/F,YAAM,iBAAiBA,yBAAwB,cAAcA,cAAa,YAAYA,cAAa;AAEnG,WAAK,QAAQ,iBAAiB,kBAAkB;AAEhD,YAAM,eAAe,8BAA8B,KAAK,QAAQ,SAAS;AAAA,QACvE,QAAQ,KAAK;AAAA,QACb,aAAa,KAAK,QAAQ;AAAA,QAC1B,SAAS,KAAK;AAAA,QACd,WAAUD,MAAA,KAAK,QAAQ,aAAb,gBAAAA,IAAuB,KAAK;AAAA,MACxC,CAAC;AAED,WAAK,QAAQ,UAAU;AAAA,IACzB;AAEA,QAAI,CAAC,KAAK,QAAQ,cAAc;AAC9B;AAAA,IACF;AAEA,UAAM,eACJ,OAAO,KAAK,QAAQ,iBAAiB,aAAa,KAAK,QAAQ,aAAa,IAAI,KAAK,QAAQ;AAE/F,QAAI,cAAc;AAChB,mBAAa,iBAAiB,UAAU,KAAK,QAAQ,aAAa;AAAA,IACpE;AAAA,EACF;AAAA,EAEA,YAAY;AACV,QAAI,CAAC,KAAK,QAAQ,cAAc;AAC9B;AAAA,IACF;AAEA,UAAM,eACJ,OAAO,KAAK,QAAQ,iBAAiB,aAAa,KAAK,QAAQ,aAAa,IAAI,KAAK,QAAQ;AAE/F,QAAI,cAAc;AAChB,mBAAa,oBAAoB,UAAU,KAAK,QAAQ,aAAa;AAAA,IACvE;AAAA,EACF;AAAA,EAEA,wBAAwB;AACtB,WAAO,CAAC,sBAAsB,EAAE,OAAO,KAAK,QAAQ,OAAO,aAAa,KAAK,QAAQ,YAAY,CAAC,CAAC;AAAA,EACrG;AACF,CAAC;;;AGzWD,IAAO,gBAAQ;","names":["uuidv4","tr","uuidv4","_a","scrollParent"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tiptap/extension-table-of-contents",
3
3
  "description": "table of contents extension for Tiptap",
4
- "version": "3.12.1",
4
+ "version": "3.14.0",
5
5
  "homepage": "https://tiptap.dev/docs/editor/extensions/functionality/table-of-contents",
6
6
  "keywords": [
7
7
  "tiptap",
@@ -40,12 +40,12 @@
40
40
  },
41
41
  "devDependencies": {
42
42
  "@types/uuid": "^10.0.0",
43
- "@tiptap/core": "^3.12.1",
44
- "@tiptap/pm": "^3.12.1"
43
+ "@tiptap/core": "^3.14.0",
44
+ "@tiptap/pm": "^3.14.0"
45
45
  },
46
46
  "peerDependencies": {
47
- "@tiptap/core": "^3.12.1",
48
- "@tiptap/pm": "^3.12.1"
47
+ "@tiptap/pm": "^3.14.0",
48
+ "@tiptap/core": "^3.14.0"
49
49
  },
50
50
  "scripts": {
51
51
  "build": "tsup",
package/src/plugin.ts CHANGED
@@ -18,6 +18,12 @@ export const TableOfContentsPlugin = ({
18
18
  return null
19
19
  }
20
20
 
21
+ // Skip updating table of contents during IME composition
22
+ // to avoid interfering with input method editor
23
+ if (transactions.some(tr => tr.getMeta('composition'))) {
24
+ return
25
+ }
26
+
21
27
  const tr = newState.tr
22
28
  let modified = false
23
29