@tiptap/extension-table-of-contents 3.11.1 → 3.12.1
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 +6 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
- package/src/plugin.ts +5 -0
- package/src/tableOfContents.ts +5 -0
package/dist/index.cjs
CHANGED
|
@@ -45,6 +45,9 @@ var TableOfContentsPlugin = ({
|
|
|
45
45
|
return new import_state.Plugin({
|
|
46
46
|
key: new import_state.PluginKey("tableOfContent"),
|
|
47
47
|
appendTransaction(transactions, _oldState, newState) {
|
|
48
|
+
if (typeof window === "undefined") {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
48
51
|
const tr = newState.tr;
|
|
49
52
|
let modified = false;
|
|
50
53
|
if (transactions.some((transaction) => transaction.docChanged)) {
|
|
@@ -327,6 +330,9 @@ var TableOfContents = import_core.Extension.create({
|
|
|
327
330
|
},
|
|
328
331
|
onCreate() {
|
|
329
332
|
var _a;
|
|
333
|
+
if (typeof window === "undefined" || !this.editor.view) {
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
330
336
|
const { tr } = this.editor.state;
|
|
331
337
|
const existingIds = [];
|
|
332
338
|
if (this.options.scrollParent && typeof this.options.scrollParent !== "function") {
|
package/dist/index.cjs.map
CHANGED
|
@@ -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 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 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","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 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"]}
|
package/dist/index.js
CHANGED
|
@@ -12,6 +12,9 @@ var TableOfContentsPlugin = ({
|
|
|
12
12
|
return new Plugin({
|
|
13
13
|
key: new PluginKey("tableOfContent"),
|
|
14
14
|
appendTransaction(transactions, _oldState, newState) {
|
|
15
|
+
if (typeof window === "undefined") {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
15
18
|
const tr = newState.tr;
|
|
16
19
|
let modified = false;
|
|
17
20
|
if (transactions.some((transaction) => transaction.docChanged)) {
|
|
@@ -294,6 +297,9 @@ var TableOfContents = Extension.create({
|
|
|
294
297
|
},
|
|
295
298
|
onCreate() {
|
|
296
299
|
var _a;
|
|
300
|
+
if (typeof window === "undefined" || !this.editor.view) {
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
297
303
|
const { tr } = this.editor.state;
|
|
298
304
|
const existingIds = [];
|
|
299
305
|
if (this.options.scrollParent && typeof this.options.scrollParent !== "function") {
|
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 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 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 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"]}
|
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.
|
|
4
|
+
"version": "3.12.1",
|
|
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.
|
|
44
|
-
"@tiptap/pm": "^3.
|
|
43
|
+
"@tiptap/core": "^3.12.1",
|
|
44
|
+
"@tiptap/pm": "^3.12.1"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
47
|
-
"@tiptap/core": "^3.
|
|
48
|
-
"@tiptap/pm": "^3.
|
|
47
|
+
"@tiptap/core": "^3.12.1",
|
|
48
|
+
"@tiptap/pm": "^3.12.1"
|
|
49
49
|
},
|
|
50
50
|
"scripts": {
|
|
51
51
|
"build": "tsup",
|
package/src/plugin.ts
CHANGED
|
@@ -13,6 +13,11 @@ export const TableOfContentsPlugin = ({
|
|
|
13
13
|
key: new PluginKey('tableOfContent'),
|
|
14
14
|
|
|
15
15
|
appendTransaction(transactions, _oldState, newState) {
|
|
16
|
+
// Avoid running on the server where `window` / DOM is not available.
|
|
17
|
+
if (typeof window === 'undefined') {
|
|
18
|
+
return null
|
|
19
|
+
}
|
|
20
|
+
|
|
16
21
|
const tr = newState.tr
|
|
17
22
|
let modified = false
|
|
18
23
|
|
package/src/tableOfContents.ts
CHANGED
|
@@ -262,6 +262,11 @@ export const TableOfContents = Extension.create<TableOfContentsOptions, TableOfC
|
|
|
262
262
|
},
|
|
263
263
|
|
|
264
264
|
onCreate() {
|
|
265
|
+
// Avoid mutating the document during server-side rendering.
|
|
266
|
+
if (typeof window === 'undefined' || !this.editor.view) {
|
|
267
|
+
return
|
|
268
|
+
}
|
|
269
|
+
|
|
265
270
|
const { tr } = this.editor.state
|
|
266
271
|
const existingIds: string[] = []
|
|
267
272
|
|