@ctzhian/tiptap 2.3.2-beta.5 → 2.3.2-beta.7
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/extension/node/TableOfContents/index.js +6 -87
- package/dist/extension/node/TableOfContents/plugin.d.ts +6 -0
- package/dist/extension/node/TableOfContents/plugin.js +58 -0
- package/dist/extension/node/TableOfContents/tableOfContents.d.ts +8 -0
- package/dist/extension/node/TableOfContents/tableOfContents.js +313 -0
- package/package.json +1 -1
|
@@ -4,100 +4,19 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
|
|
|
4
4
|
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
5
5
|
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
|
|
6
6
|
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
7
|
-
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
|
|
8
|
-
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
9
|
-
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
10
|
-
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
|
|
11
|
-
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
|
|
12
|
-
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
|
13
|
-
// @ts-nocheck
|
|
14
|
-
|
|
15
7
|
import { getHierarchicalIndexes, TableOfContents } from '@tiptap/extension-table-of-contents';
|
|
16
8
|
import { Plugin, PluginKey } from '@tiptap/pm/state';
|
|
9
|
+
import { TableOfContentsPlugin } from "./plugin";
|
|
17
10
|
export var TableOfContentsExtension = function TableOfContentsExtension(_ref) {
|
|
18
11
|
var onTocUpdate = _ref.onTocUpdate,
|
|
19
12
|
tableOfContentsOptions = _ref.tableOfContentsOptions;
|
|
20
13
|
return TableOfContents.extend({
|
|
21
|
-
onCreate: function onCreate() {
|
|
22
|
-
var _lastChild$content$fi,
|
|
23
|
-
_this = this;
|
|
24
|
-
// 检查文档结构,避免在特定结构下触发错误
|
|
25
|
-
var doc = this.editor.state.doc;
|
|
26
|
-
var lastChild = doc.lastChild;
|
|
27
|
-
var hasProblematicStructure = lastChild && lastChild.type.name === 'paragraph' && lastChild.content.childCount === 1 && ((_lastChild$content$fi = lastChild.content.firstChild) === null || _lastChild$content$fi === void 0 ? void 0 : _lastChild$content$fi.type.name) === 'image';
|
|
28
|
-
|
|
29
|
-
// 如果有问题的结构,跳过父类的 onCreate,避免触发 contentMatchAt 错误
|
|
30
|
-
if (hasProblematicStructure) {
|
|
31
|
-
console.warn('TableOfContents: 检测到文档结构问题(图片单独成段),跳过 onCreate 以避免 contentMatchAt 错误');
|
|
32
|
-
// 仍然需要初始化 storage 和 scroll handler
|
|
33
|
-
this.storage.scrollHandler = function () {
|
|
34
|
-
if (!_this.options.scrollParent) return;
|
|
35
|
-
var scrollParent = typeof _this.options.scrollParent === 'function' ? _this.options.scrollParent() : _this.options.scrollParent;
|
|
36
|
-
var scrollPosition = scrollParent instanceof HTMLElement ? scrollParent.scrollTop : scrollParent.scrollY;
|
|
37
|
-
_this.storage.scrollPosition = scrollPosition || 0;
|
|
38
|
-
};
|
|
39
|
-
if (this.options.scrollParent) {
|
|
40
|
-
var scrollParent = typeof this.options.scrollParent === 'function' ? this.options.scrollParent() : this.options.scrollParent;
|
|
41
|
-
if (scrollParent) {
|
|
42
|
-
scrollParent.addEventListener('scroll', this.storage.scrollHandler);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// 正常结构,调用父类的 onCreate,使用 try-catch 包装
|
|
49
|
-
try {
|
|
50
|
-
if (this.parent) {
|
|
51
|
-
this.parent();
|
|
52
|
-
}
|
|
53
|
-
} catch (error) {
|
|
54
|
-
// 捕获 onCreate 中的错误,特别是 contentMatchAt 错误
|
|
55
|
-
if (error instanceof Error && error.message.includes('contentMatchAt')) {
|
|
56
|
-
console.warn('TableOfContents: onCreate 中检测到 contentMatchAt 错误,已跳过', error);
|
|
57
|
-
// 即使出错,也初始化必要的部分
|
|
58
|
-
this.storage.scrollHandler = function () {
|
|
59
|
-
if (!_this.options.scrollParent) return;
|
|
60
|
-
var scrollParent = typeof _this.options.scrollParent === 'function' ? _this.options.scrollParent() : _this.options.scrollParent;
|
|
61
|
-
var scrollPosition = scrollParent instanceof HTMLElement ? scrollParent.scrollTop : scrollParent.scrollY;
|
|
62
|
-
_this.storage.scrollPosition = scrollPosition || 0;
|
|
63
|
-
};
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
// 其他错误继续抛出
|
|
67
|
-
throw error;
|
|
68
|
-
}
|
|
69
|
-
},
|
|
70
14
|
addProseMirrorPlugins: function addProseMirrorPlugins() {
|
|
71
|
-
var _this$parent;
|
|
72
15
|
var imeCompositionPluginKey = new PluginKey('imeComposition');
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
key: new PluginKey('tableOfContentsProtection'),
|
|
78
|
-
appendTransaction: function appendTransaction(transactions, oldState, newState) {
|
|
79
|
-
try {
|
|
80
|
-
var _lastChild$content$fi2;
|
|
81
|
-
// 检查文档结构
|
|
82
|
-
var doc = newState.doc;
|
|
83
|
-
var lastChild = doc.lastChild;
|
|
84
|
-
var hasProblematicStructure = lastChild && lastChild.type.name === 'paragraph' && lastChild.content.childCount === 1 && ((_lastChild$content$fi2 = lastChild.content.firstChild) === null || _lastChild$content$fi2 === void 0 ? void 0 : _lastChild$content$fi2.type.name) === 'image';
|
|
85
|
-
|
|
86
|
-
// 如果有问题的结构,不执行任何操作
|
|
87
|
-
if (hasProblematicStructure) {
|
|
88
|
-
return null;
|
|
89
|
-
}
|
|
90
|
-
} catch (error) {
|
|
91
|
-
// 捕获任何错误,避免崩溃
|
|
92
|
-
if (error instanceof Error && error.message.includes('contentMatchAt')) {
|
|
93
|
-
console.warn('TableOfContents: 保护插件中检测到 contentMatchAt 错误', error);
|
|
94
|
-
return null;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
return null;
|
|
98
|
-
}
|
|
99
|
-
});
|
|
100
|
-
return [protectionPlugin].concat(_toConsumableArray(parentPlugins), [new Plugin({
|
|
16
|
+
return [TableOfContentsPlugin({
|
|
17
|
+
getId: this.options.getId,
|
|
18
|
+
anchorTypes: this.options.anchorTypes
|
|
19
|
+
}), new Plugin({
|
|
101
20
|
key: new PluginKey('tableOfContentImeFix'),
|
|
102
21
|
appendTransaction: function appendTransaction(transactions, _oldState, newState) {
|
|
103
22
|
if (transactions.some(function (tr) {
|
|
@@ -111,7 +30,7 @@ export var TableOfContentsExtension = function TableOfContentsExtension(_ref) {
|
|
|
111
30
|
}
|
|
112
31
|
return null;
|
|
113
32
|
}
|
|
114
|
-
})]
|
|
33
|
+
})];
|
|
115
34
|
}
|
|
116
35
|
}).configure(_objectSpread(_objectSpread({
|
|
117
36
|
getIndex: getHierarchicalIndexes
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { NodeType } from '@tiptap/pm/model';
|
|
2
|
+
import { Plugin } from '@tiptap/pm/state';
|
|
3
|
+
export declare const TableOfContentsPlugin: ({ getId, anchorTypes, }: {
|
|
4
|
+
getId?: ((textContent: string) => string) | undefined;
|
|
5
|
+
anchorTypes?: (string | NodeType)[] | undefined;
|
|
6
|
+
}) => Plugin<any>;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
2
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
3
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
4
|
+
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
5
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
|
|
6
|
+
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
7
|
+
import { Plugin, PluginKey } from '@tiptap/pm/state';
|
|
8
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
9
|
+
export var TableOfContentsPlugin = function TableOfContentsPlugin(_ref) {
|
|
10
|
+
var getId = _ref.getId,
|
|
11
|
+
_ref$anchorTypes = _ref.anchorTypes,
|
|
12
|
+
anchorTypes = _ref$anchorTypes === void 0 ? ['heading'] : _ref$anchorTypes;
|
|
13
|
+
return new Plugin({
|
|
14
|
+
key: new PluginKey('tableOfContent'),
|
|
15
|
+
appendTransaction: function appendTransaction(transactions, oldState, newState) {
|
|
16
|
+
var _view;
|
|
17
|
+
// 若处于组合输入,完全避免在此事务中写入 id,交由扩展层异步生成
|
|
18
|
+
if ((_view = newState.view) !== null && _view !== void 0 && _view.composing || typeof document !== 'undefined' && document.composing || typeof window !== 'undefined' && window.compositionState) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// 检查是否有任何事务包含组合相关的变化
|
|
23
|
+
var hasCompositionChanges = transactions.some(function (tr) {
|
|
24
|
+
return tr.getMeta('composition') || tr.getMeta('compositionend') || tr.getMeta('compositionstart');
|
|
25
|
+
});
|
|
26
|
+
if (hasCompositionChanges) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
var tr = newState.tr;
|
|
30
|
+
var modified = false;
|
|
31
|
+
if (transactions.some(function (transaction) {
|
|
32
|
+
return transaction.docChanged;
|
|
33
|
+
}) && !oldState.doc.eq(newState.doc)) {
|
|
34
|
+
var existingIds = [];
|
|
35
|
+
newState.doc.descendants(function (node, pos) {
|
|
36
|
+
var nodeId = node.attrs.id;
|
|
37
|
+
if (!anchorTypes.includes(node.type.name) || node.textContent.length === 0) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (nodeId === null || nodeId === undefined || existingIds.includes(nodeId)) {
|
|
41
|
+
var id = '';
|
|
42
|
+
if (getId) {
|
|
43
|
+
id = getId(node.textContent);
|
|
44
|
+
} else {
|
|
45
|
+
id = uuidv4();
|
|
46
|
+
}
|
|
47
|
+
tr.setNodeMarkup(pos, undefined, _objectSpread(_objectSpread({}, node.attrs), {}, {
|
|
48
|
+
id: id
|
|
49
|
+
}));
|
|
50
|
+
modified = true;
|
|
51
|
+
}
|
|
52
|
+
existingIds.push(nodeId);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
return modified ? tr : null;
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { TocList } from "../../../type";
|
|
2
|
+
import { Extension } from '@tiptap/core';
|
|
3
|
+
import { TableOfContentsOptions, TableOfContentsStorage } from '@tiptap/extension-table-of-contents';
|
|
4
|
+
export declare const TableOfContentsExtension: Extension<TableOfContentsOptions, TableOfContentsStorage>;
|
|
5
|
+
export declare const TableOfContents: ({ onTocUpdate }: {
|
|
6
|
+
onTocUpdate?: ((toc: TocList) => void) | undefined;
|
|
7
|
+
}) => Extension<TableOfContentsOptions, TableOfContentsStorage>;
|
|
8
|
+
export default TableOfContents;
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
2
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
3
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
4
|
+
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
5
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
|
|
6
|
+
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
7
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
8
|
+
|
|
9
|
+
import { Extension } from '@tiptap/core';
|
|
10
|
+
import { getHeadlineLevel, getHierarchicalIndexes, getLinearIndexes } from '@tiptap/extension-table-of-contents';
|
|
11
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
12
|
+
import { TableOfContentsPlugin } from "./plugin";
|
|
13
|
+
var addTocActiveStatesAndGetItems = function addTocActiveStatesAndGetItems(content, options) {
|
|
14
|
+
var editor = options.editor;
|
|
15
|
+
var headlines = [];
|
|
16
|
+
var scrolledOverIds = [];
|
|
17
|
+
var activeId = null;
|
|
18
|
+
if (editor.isDestroyed) {
|
|
19
|
+
return content;
|
|
20
|
+
}
|
|
21
|
+
editor.state.doc.descendants(function (node, pos) {
|
|
22
|
+
var _options$anchorTypes;
|
|
23
|
+
var isValidType = (_options$anchorTypes = options.anchorTypes) === null || _options$anchorTypes === void 0 ? void 0 : _options$anchorTypes.includes(node.type.name);
|
|
24
|
+
if (!isValidType) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
headlines.push({
|
|
28
|
+
node: node,
|
|
29
|
+
pos: pos
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
headlines.forEach(function (headline) {
|
|
33
|
+
var domElement = editor.view.domAtPos(headline.pos + 1).node;
|
|
34
|
+
var scrolledOver = options.storage.scrollPosition >= domElement.offsetTop;
|
|
35
|
+
if (scrolledOver) {
|
|
36
|
+
activeId = headline.node.attrs.id;
|
|
37
|
+
scrolledOverIds.push(headline.node.attrs.id);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
return content.map(function (heading) {
|
|
41
|
+
return _objectSpread(_objectSpread({}, heading), {}, {
|
|
42
|
+
isActive: heading.id === activeId,
|
|
43
|
+
isScrolledOver: scrolledOverIds.includes(heading.id)
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
};
|
|
47
|
+
var setTocData = function setTocData(options) {
|
|
48
|
+
var editor = options.editor,
|
|
49
|
+
onUpdate = options.onUpdate;
|
|
50
|
+
if (editor.isDestroyed) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
var headlines = [];
|
|
54
|
+
var anchors = [];
|
|
55
|
+
var anchorEls = [];
|
|
56
|
+
editor.state.doc.descendants(function (node, pos) {
|
|
57
|
+
var _options$anchorTypes2;
|
|
58
|
+
var isValidType = (_options$anchorTypes2 = options.anchorTypes) === null || _options$anchorTypes2 === void 0 ? void 0 : _options$anchorTypes2.includes(node.type.name);
|
|
59
|
+
if (!isValidType) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
headlines.push({
|
|
63
|
+
node: node,
|
|
64
|
+
pos: pos
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
headlines.forEach(function (headline) {
|
|
68
|
+
if (headline.node.textContent.length === 0) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
var domElement = editor.view.domAtPos(headline.pos + 1).node;
|
|
72
|
+
var scrolledOver = options.storage.scrollPosition >= domElement.offsetTop;
|
|
73
|
+
anchorEls.push(domElement);
|
|
74
|
+
var originalLevel = headline.node.attrs.level;
|
|
75
|
+
var level = options.getLevelFn(headline, anchors);
|
|
76
|
+
var itemIndex = options.getIndexFn(headline, anchors, level);
|
|
77
|
+
anchors.push({
|
|
78
|
+
itemIndex: itemIndex,
|
|
79
|
+
id: headline.node.attrs.id || options.getId(headline.node.textContent),
|
|
80
|
+
originalLevel: originalLevel,
|
|
81
|
+
level: level,
|
|
82
|
+
textContent: headline.node.textContent,
|
|
83
|
+
pos: headline.pos,
|
|
84
|
+
editor: editor,
|
|
85
|
+
isActive: false,
|
|
86
|
+
isScrolledOver: scrolledOver,
|
|
87
|
+
node: headline.node,
|
|
88
|
+
dom: domElement
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// 计算 active 和 scrolledOver 状态
|
|
93
|
+
anchors = addTocActiveStatesAndGetItems(anchors, {
|
|
94
|
+
editor: options.editor,
|
|
95
|
+
anchorTypes: options.anchorTypes,
|
|
96
|
+
storage: options.storage
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// 更新存储
|
|
100
|
+
options.storage.anchors = anchorEls;
|
|
101
|
+
options.storage.content = anchors;
|
|
102
|
+
|
|
103
|
+
// 调用回调
|
|
104
|
+
if (onUpdate) {
|
|
105
|
+
var isInitialCreation = options.storage.content.length === 0;
|
|
106
|
+
onUpdate(anchors, isInitialCreation);
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
export var TableOfContentsExtension = Extension.create({
|
|
110
|
+
name: 'tableOfContents',
|
|
111
|
+
addStorage: function addStorage() {
|
|
112
|
+
return {
|
|
113
|
+
content: [],
|
|
114
|
+
anchors: [],
|
|
115
|
+
scrollHandler: function scrollHandler() {
|
|
116
|
+
return null;
|
|
117
|
+
},
|
|
118
|
+
scrollPosition: 0
|
|
119
|
+
};
|
|
120
|
+
},
|
|
121
|
+
addGlobalAttributes: function addGlobalAttributes() {
|
|
122
|
+
return [{
|
|
123
|
+
types: this.options.anchorTypes || ['heading'],
|
|
124
|
+
attributes: {
|
|
125
|
+
id: {
|
|
126
|
+
default: null,
|
|
127
|
+
renderHTML: function renderHTML(attributes) {
|
|
128
|
+
return {
|
|
129
|
+
id: attributes.id
|
|
130
|
+
};
|
|
131
|
+
},
|
|
132
|
+
parseHTML: function parseHTML(element) {
|
|
133
|
+
return element.id || null;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}];
|
|
138
|
+
},
|
|
139
|
+
addOptions: function addOptions() {
|
|
140
|
+
var defaultScrollParent = typeof window !== 'undefined' ? function () {
|
|
141
|
+
return window;
|
|
142
|
+
} : undefined;
|
|
143
|
+
return {
|
|
144
|
+
// eslint-disable-next-line
|
|
145
|
+
onUpdate: function onUpdate() {},
|
|
146
|
+
// eslint-disable-next-line
|
|
147
|
+
getId: function getId(_textContent) {
|
|
148
|
+
return uuidv4();
|
|
149
|
+
},
|
|
150
|
+
scrollParent: defaultScrollParent,
|
|
151
|
+
anchorTypes: ['heading']
|
|
152
|
+
};
|
|
153
|
+
},
|
|
154
|
+
addCommands: function addCommands() {
|
|
155
|
+
var _this = this;
|
|
156
|
+
return {
|
|
157
|
+
updateTableOfContents: function updateTableOfContents() {
|
|
158
|
+
return function (_ref) {
|
|
159
|
+
var dispatch = _ref.dispatch;
|
|
160
|
+
if (dispatch) {
|
|
161
|
+
var _this$options$onUpdat;
|
|
162
|
+
setTocData({
|
|
163
|
+
editor: _this.editor,
|
|
164
|
+
storage: _this.storage,
|
|
165
|
+
onUpdate: (_this$options$onUpdat = _this.options.onUpdate) === null || _this$options$onUpdat === void 0 ? void 0 : _this$options$onUpdat.bind(_this),
|
|
166
|
+
getIndexFn: _this.options.getIndex || getLinearIndexes,
|
|
167
|
+
getLevelFn: _this.options.getLevel || getHeadlineLevel,
|
|
168
|
+
anchorTypes: _this.options.anchorTypes,
|
|
169
|
+
getId: _this.options.getId || function (textContent) {
|
|
170
|
+
return uuidv4();
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
return true;
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
},
|
|
179
|
+
onTransaction: function onTransaction(_ref2) {
|
|
180
|
+
var transaction = _ref2.transaction;
|
|
181
|
+
if (transaction.docChanged && !transaction.getMeta('toc')) {
|
|
182
|
+
var _this$options$onUpdat2;
|
|
183
|
+
setTocData({
|
|
184
|
+
editor: this.editor,
|
|
185
|
+
storage: this.storage,
|
|
186
|
+
onUpdate: (_this$options$onUpdat2 = this.options.onUpdate) === null || _this$options$onUpdat2 === void 0 ? void 0 : _this$options$onUpdat2.bind(this),
|
|
187
|
+
getIndexFn: this.options.getIndex || getLinearIndexes,
|
|
188
|
+
getLevelFn: this.options.getLevel || getHeadlineLevel,
|
|
189
|
+
anchorTypes: this.options.anchorTypes,
|
|
190
|
+
getId: this.options.getId || function (textContent) {
|
|
191
|
+
return uuidv4();
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
onCreate: function onCreate() {
|
|
197
|
+
var _this2 = this;
|
|
198
|
+
var tr = this.editor.state.tr;
|
|
199
|
+
var existingIds = [];
|
|
200
|
+
if (this.options.scrollParent && typeof this.options.scrollParent !== 'function') {
|
|
201
|
+
console.warn("[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.");
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// 异步处理初始 ID 分配,避免与初始输入竞争
|
|
205
|
+
requestAnimationFrame(function () {
|
|
206
|
+
_this2.editor.state.doc.descendants(function (node, pos) {
|
|
207
|
+
var _this2$options$anchor;
|
|
208
|
+
var nodeId = node.attrs.id;
|
|
209
|
+
var isValidType = (_this2$options$anchor = _this2.options.anchorTypes) === null || _this2$options$anchor === void 0 ? void 0 : _this2$options$anchor.includes(node.type.name);
|
|
210
|
+
if (!isValidType || node.textContent.length === 0) {
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
if (nodeId === null || nodeId === undefined || existingIds.includes(nodeId)) {
|
|
214
|
+
var id = '';
|
|
215
|
+
if (_this2.options.getId) {
|
|
216
|
+
id = _this2.options.getId(node.textContent);
|
|
217
|
+
} else {
|
|
218
|
+
id = uuidv4();
|
|
219
|
+
}
|
|
220
|
+
tr.setNodeMarkup(pos, undefined, _objectSpread(_objectSpread({}, node.attrs), {}, {
|
|
221
|
+
id: id
|
|
222
|
+
}));
|
|
223
|
+
}
|
|
224
|
+
existingIds.push(nodeId);
|
|
225
|
+
});
|
|
226
|
+
_this2.editor.view.dispatch(tr);
|
|
227
|
+
|
|
228
|
+
// 延迟初始化 TOC 数据
|
|
229
|
+
setTimeout(function () {
|
|
230
|
+
var _this2$options$onUpda;
|
|
231
|
+
setTocData({
|
|
232
|
+
editor: _this2.editor,
|
|
233
|
+
storage: _this2.storage,
|
|
234
|
+
onUpdate: (_this2$options$onUpda = _this2.options.onUpdate) === null || _this2$options$onUpda === void 0 ? void 0 : _this2$options$onUpda.bind(_this2),
|
|
235
|
+
getIndexFn: _this2.options.getIndex || getLinearIndexes,
|
|
236
|
+
getLevelFn: _this2.options.getLevel || getHeadlineLevel,
|
|
237
|
+
anchorTypes: _this2.options.anchorTypes,
|
|
238
|
+
getId: _this2.options.getId || function (textContent) {
|
|
239
|
+
return uuidv4();
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
}, 100);
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
// 防抖的 scroll handler,避免滚动期间频繁触发回调
|
|
246
|
+
var scrollTimer = null;
|
|
247
|
+
this.storage.scrollHandler = function () {
|
|
248
|
+
if (!_this2.options.scrollParent) {
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
var scrollParent = typeof _this2.options.scrollParent === 'function' ? _this2.options.scrollParent() : _this2.options.scrollParent;
|
|
252
|
+
var scrollPosition = scrollParent instanceof HTMLElement ? scrollParent.scrollTop : scrollParent.scrollY;
|
|
253
|
+
_this2.storage.scrollPosition = scrollPosition || 0;
|
|
254
|
+
if (scrollTimer) clearTimeout(scrollTimer);
|
|
255
|
+
scrollTimer = setTimeout(function () {
|
|
256
|
+
var _this2$options$onUpda2, _this2$options;
|
|
257
|
+
var updatedItems = addTocActiveStatesAndGetItems(_this2.storage.content, {
|
|
258
|
+
editor: _this2.editor,
|
|
259
|
+
anchorTypes: _this2.options.anchorTypes,
|
|
260
|
+
storage: _this2.storage
|
|
261
|
+
});
|
|
262
|
+
_this2.storage.content = updatedItems;
|
|
263
|
+
// 调用 onUpdate 回调
|
|
264
|
+
(_this2$options$onUpda2 = (_this2$options = _this2.options).onUpdate) === null || _this2$options$onUpda2 === void 0 || _this2$options$onUpda2.call(_this2$options, updatedItems, false);
|
|
265
|
+
}, 100);
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
// 添加滚动监听
|
|
269
|
+
if (this.options.scrollParent) {
|
|
270
|
+
var scrollParent = typeof this.options.scrollParent === 'function' ? this.options.scrollParent() : this.options.scrollParent;
|
|
271
|
+
if (scrollParent) {
|
|
272
|
+
scrollParent.addEventListener('scroll', this.storage.scrollHandler);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
},
|
|
276
|
+
onDestroy: function onDestroy() {
|
|
277
|
+
if (this.options.scrollParent) {
|
|
278
|
+
var scrollParent = typeof this.options.scrollParent === 'function' ? this.options.scrollParent() : this.options.scrollParent;
|
|
279
|
+
if (scrollParent) {
|
|
280
|
+
scrollParent.removeEventListener('scroll', this.storage.scrollHandler);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
},
|
|
284
|
+
addProseMirrorPlugins: function addProseMirrorPlugins() {
|
|
285
|
+
return [TableOfContentsPlugin({
|
|
286
|
+
getId: this.options.getId,
|
|
287
|
+
anchorTypes: this.options.anchorTypes
|
|
288
|
+
})];
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
export var TableOfContents = function TableOfContents(_ref3) {
|
|
292
|
+
var onTocUpdate = _ref3.onTocUpdate;
|
|
293
|
+
return TableOfContentsExtension.configure({
|
|
294
|
+
getIndex: getHierarchicalIndexes,
|
|
295
|
+
onUpdate: function onUpdate(data) {
|
|
296
|
+
setTimeout(function () {
|
|
297
|
+
onTocUpdate === null || onTocUpdate === void 0 || onTocUpdate(data.map(function (content) {
|
|
298
|
+
return {
|
|
299
|
+
id: content.id,
|
|
300
|
+
isActive: content.isActive,
|
|
301
|
+
isScrolledOver: content.isScrolledOver,
|
|
302
|
+
itemIndex: content.itemIndex,
|
|
303
|
+
level: content.level,
|
|
304
|
+
originalLevel: content.originalLevel,
|
|
305
|
+
pos: content.pos,
|
|
306
|
+
textContent: content.textContent
|
|
307
|
+
};
|
|
308
|
+
}));
|
|
309
|
+
}, 0);
|
|
310
|
+
}
|
|
311
|
+
});
|
|
312
|
+
};
|
|
313
|
+
export default TableOfContents;
|