tiptap-markdown-react 0.17.0 → 0.17.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/{ReportContent-CwcppHl8.js → ReportContent-MgbebxPV.js} +8 -8
- package/dist/{ReportContent-CwcppHl8.js.map → ReportContent-MgbebxPV.js.map} +1 -1
- package/dist/{extractToc-CheLC9kh.js → extractToc-BaR6LP1f.js} +42 -4
- package/dist/extractToc-BaR6LP1f.js.map +1 -0
- package/dist/index.js +14 -9
- package/dist/index.js.map +1 -1
- package/dist/placeholder.test.d.ts +1 -0
- package/dist/reader.js +2 -2
- package/dist/{scrollToTocHeading-CBvptTaQ.js → scrollToTocHeading-BTQWajGD.js} +2 -2
- package/dist/{scrollToTocHeading-CBvptTaQ.js.map → scrollToTocHeading-BTQWajGD.js.map} +1 -1
- package/dist/server.js +4 -4
- package/dist/style-inline.css +59 -56
- package/dist/style.css +59 -56
- package/dist/supSubMarkdown.test.d.ts +1 -0
- package/dist/supSubServer.test.d.ts +1 -0
- package/package.json +1 -1
- package/dist/extractToc-CheLC9kh.js.map +0 -1
package/dist/style.css
CHANGED
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
|
|
4
4
|
/* 编辑器最外层:查找替换浮动条的粘性范围就是它(超出编辑器范围后浮动条随之离场)。
|
|
5
5
|
正文的滚动容器仍是 .editorScroll(宿主传的 className 依然落在它身上,契约不变)。 */
|
|
6
|
-
.
|
|
6
|
+
._editorHost_1teg4_6 {
|
|
7
7
|
position: relative;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
/* 浮动条的粘性锚点:高度 0,不占布局、不推挤正文;sticky 让浮动条在「最近的滚动容器」
|
|
11
11
|
里粘住(宿主的外层滚动容器或页面本身),正文滚动时不会把条子卷上去。
|
|
12
12
|
注意:锚点必须在 DOM 里排在正文之前——排在后面的话它的自然位置在正文底部,粘性范围就错了。 */
|
|
13
|
-
.
|
|
13
|
+
._findBarAnchor_1teg4_13 {
|
|
14
14
|
position: sticky;
|
|
15
15
|
top: 0;
|
|
16
16
|
height: 0;
|
|
@@ -18,16 +18,16 @@
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
/* 浮动条本体:绝对定位浮在正文之上,具体落点由 findBarOffset 决定(默认右上 4px) */
|
|
21
|
-
.
|
|
21
|
+
._findBar_1teg4_13 {
|
|
22
22
|
position: absolute;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
.
|
|
25
|
+
._editorScroll_1teg4_5 {
|
|
26
26
|
margin-top: 24px;
|
|
27
27
|
position: relative;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
.
|
|
30
|
+
._editorContent_1teg4_30 {
|
|
31
31
|
outline: none;
|
|
32
32
|
padding: 0;
|
|
33
33
|
font-family: var(
|
|
@@ -49,8 +49,11 @@
|
|
|
49
49
|
min-height: var(--tmr-min-height, 420px);
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
/* placeholder
|
|
53
|
-
|
|
52
|
+
/* placeholder:空文档的当前文本块显示占位符。
|
|
53
|
+
属性由官方 Placeholder 扩展(组件里按 placeholder prop 注册)以节点装饰
|
|
54
|
+
打在段落 / 标题本身上,故此处 attr(data-placeholder) 取得到值。
|
|
55
|
+
不限定 p:空文档首块是空标题(敲 / 选 H1 后删空)时同样显示。 */
|
|
56
|
+
._editorContent_1teg4_30 .is-editor-empty:first-child::before {
|
|
54
57
|
content: attr(data-placeholder);
|
|
55
58
|
float: left;
|
|
56
59
|
height: 0;
|
|
@@ -58,7 +61,7 @@
|
|
|
58
61
|
pointer-events: none;
|
|
59
62
|
}
|
|
60
63
|
|
|
61
|
-
.
|
|
64
|
+
._editorContent_1teg4_30 h1 {
|
|
62
65
|
font-family: inherit;
|
|
63
66
|
font-size: 1.55em;
|
|
64
67
|
font-weight: 700;
|
|
@@ -66,7 +69,7 @@
|
|
|
66
69
|
line-height: 1.3;
|
|
67
70
|
}
|
|
68
71
|
|
|
69
|
-
.
|
|
72
|
+
._editorContent_1teg4_30 h2 {
|
|
70
73
|
font-family: inherit;
|
|
71
74
|
font-size: 1.3em;
|
|
72
75
|
font-weight: 700;
|
|
@@ -74,7 +77,7 @@
|
|
|
74
77
|
line-height: 1.3;
|
|
75
78
|
}
|
|
76
79
|
|
|
77
|
-
.
|
|
80
|
+
._editorContent_1teg4_30 h3 {
|
|
78
81
|
font-family: inherit;
|
|
79
82
|
font-size: 1.12em;
|
|
80
83
|
font-weight: 600;
|
|
@@ -82,21 +85,21 @@
|
|
|
82
85
|
}
|
|
83
86
|
|
|
84
87
|
/* h4-h6:延续 h1-h3 尺寸梯度递减;字号差变小后靠字重保持标题感,h6 字色稍弱。 */
|
|
85
|
-
.
|
|
88
|
+
._editorContent_1teg4_30 h4 {
|
|
86
89
|
font-family: inherit;
|
|
87
90
|
font-size: 1.05em;
|
|
88
91
|
font-weight: 600;
|
|
89
92
|
margin: 0.7em 0 0.3em;
|
|
90
93
|
}
|
|
91
94
|
|
|
92
|
-
.
|
|
95
|
+
._editorContent_1teg4_30 h5 {
|
|
93
96
|
font-family: inherit;
|
|
94
97
|
font-size: 0.95em;
|
|
95
98
|
font-weight: 600;
|
|
96
99
|
margin: 0.7em 0 0.3em;
|
|
97
100
|
}
|
|
98
101
|
|
|
99
|
-
.
|
|
102
|
+
._editorContent_1teg4_30 h6 {
|
|
100
103
|
font-family: inherit;
|
|
101
104
|
font-size: 0.88em;
|
|
102
105
|
font-weight: 600;
|
|
@@ -104,25 +107,25 @@
|
|
|
104
107
|
color: var(--tmr-muted, #777777);
|
|
105
108
|
}
|
|
106
109
|
|
|
107
|
-
.
|
|
110
|
+
._editorContent_1teg4_30 p {
|
|
108
111
|
margin: 0.7em 0;
|
|
109
112
|
}
|
|
110
113
|
|
|
111
|
-
.
|
|
112
|
-
.
|
|
114
|
+
._editorContent_1teg4_30 ul,
|
|
115
|
+
._editorContent_1teg4_30 ol {
|
|
113
116
|
padding-left: 1.5em;
|
|
114
117
|
margin: 0.7em 0;
|
|
115
118
|
}
|
|
116
119
|
|
|
117
|
-
.
|
|
120
|
+
._editorContent_1teg4_30 ul {
|
|
118
121
|
list-style: disc;
|
|
119
122
|
}
|
|
120
123
|
|
|
121
|
-
.
|
|
124
|
+
._editorContent_1teg4_30 ol {
|
|
122
125
|
list-style: decimal;
|
|
123
126
|
}
|
|
124
127
|
|
|
125
|
-
.
|
|
128
|
+
._editorContent_1teg4_30 blockquote {
|
|
126
129
|
border-left: 3px solid var(--tmr-accent, #ff6719);
|
|
127
130
|
padding-left: 1em;
|
|
128
131
|
margin: 0.9em 0;
|
|
@@ -130,13 +133,13 @@
|
|
|
130
133
|
font-style: italic;
|
|
131
134
|
}
|
|
132
135
|
|
|
133
|
-
.
|
|
136
|
+
._editorContent_1teg4_30 a {
|
|
134
137
|
color: var(--tmr-accent, #ff6719);
|
|
135
138
|
text-decoration: underline;
|
|
136
139
|
}
|
|
137
140
|
|
|
138
141
|
/* 仅行内代码加灰底;代码块内的 <code>(在 pre 内)由 NodeView 自管,排除掉 */
|
|
139
|
-
.
|
|
142
|
+
._editorContent_1teg4_30 code:not(pre code) {
|
|
140
143
|
background: var(--tmr-code-bg, #f4f4f4);
|
|
141
144
|
padding: 0.15em 0.4em;
|
|
142
145
|
border-radius: 4px;
|
|
@@ -151,13 +154,13 @@
|
|
|
151
154
|
);
|
|
152
155
|
}
|
|
153
156
|
|
|
154
|
-
.
|
|
157
|
+
._editorContent_1teg4_30 hr {
|
|
155
158
|
border: none;
|
|
156
159
|
border-top: 1px solid var(--tmr-border, #e6e6e6);
|
|
157
160
|
margin: 1.5em 0;
|
|
158
161
|
}
|
|
159
162
|
|
|
160
|
-
.
|
|
163
|
+
._editorContent_1teg4_30 img {
|
|
161
164
|
max-width: 100%;
|
|
162
165
|
height: auto;
|
|
163
166
|
border-radius: 6px;
|
|
@@ -166,21 +169,21 @@
|
|
|
166
169
|
}
|
|
167
170
|
|
|
168
171
|
/* 选中的图片高亮 */
|
|
169
|
-
.
|
|
172
|
+
._editorContent_1teg4_30 img.ProseMirror-selectednode {
|
|
170
173
|
outline: 2px solid var(--tmr-accent, #ff6719);
|
|
171
174
|
}
|
|
172
175
|
|
|
173
176
|
/* 表格:细边框、表头浅灰;外包 .tableWrapper(编辑器 NodeView + SSR renderWrapper)
|
|
174
177
|
* 桌面:width:100% + 允许换行,整表落在阅读列内(与改前一致)
|
|
175
178
|
* 窄屏:max-content + nowrap,避免列被挤扁,wrapper 内横滑 */
|
|
176
|
-
.
|
|
179
|
+
._editorContent_1teg4_30 .tableWrapper {
|
|
177
180
|
max-width: 100%;
|
|
178
181
|
overflow-x: auto;
|
|
179
182
|
-webkit-overflow-scrolling: touch;
|
|
180
183
|
margin: 1em 0;
|
|
181
184
|
}
|
|
182
185
|
|
|
183
|
-
.
|
|
186
|
+
._editorContent_1teg4_30 table {
|
|
184
187
|
border-collapse: collapse;
|
|
185
188
|
table-layout: auto;
|
|
186
189
|
width: 100%;
|
|
@@ -190,12 +193,12 @@
|
|
|
190
193
|
}
|
|
191
194
|
|
|
192
195
|
/* 无 wrapper 的遗留 HTML(旧缓存)仍给一点外边距 */
|
|
193
|
-
.
|
|
196
|
+
._editorContent_1teg4_30 :not(.tableWrapper) > table {
|
|
194
197
|
margin: 1em 0;
|
|
195
198
|
}
|
|
196
199
|
|
|
197
|
-
.
|
|
198
|
-
.
|
|
200
|
+
._editorContent_1teg4_30 table td,
|
|
201
|
+
._editorContent_1teg4_30 table th {
|
|
199
202
|
border: 1px solid var(--tmr-border, #e6e6e6);
|
|
200
203
|
padding: 8px 12px;
|
|
201
204
|
vertical-align: top;
|
|
@@ -206,27 +209,27 @@
|
|
|
206
209
|
word-break: break-word;
|
|
207
210
|
}
|
|
208
211
|
|
|
209
|
-
.
|
|
212
|
+
._editorContent_1teg4_30 table th {
|
|
210
213
|
background: var(--tmr-table-header-bg, #f7f7f7);
|
|
211
214
|
font-weight: 600;
|
|
212
215
|
}
|
|
213
216
|
|
|
214
217
|
@media (max-width: 640px) {
|
|
215
|
-
.
|
|
218
|
+
._editorContent_1teg4_30 table {
|
|
216
219
|
width: max-content;
|
|
217
220
|
min-width: 100%;
|
|
218
221
|
max-width: none;
|
|
219
222
|
}
|
|
220
223
|
|
|
221
|
-
.
|
|
222
|
-
.
|
|
224
|
+
._editorContent_1teg4_30 table td,
|
|
225
|
+
._editorContent_1teg4_30 table th {
|
|
223
226
|
white-space: nowrap;
|
|
224
227
|
word-break: normal;
|
|
225
228
|
}
|
|
226
229
|
}
|
|
227
230
|
|
|
228
231
|
/* 选中的单元格高亮 */
|
|
229
|
-
.
|
|
232
|
+
._editorContent_1teg4_30 table .selectedCell::after {
|
|
230
233
|
content: '';
|
|
231
234
|
position: absolute;
|
|
232
235
|
inset: 0;
|
|
@@ -235,7 +238,7 @@
|
|
|
235
238
|
}
|
|
236
239
|
|
|
237
240
|
/* 列宽拖拽手柄 */
|
|
238
|
-
.
|
|
241
|
+
._editorContent_1teg4_30 table .column-resize-handle {
|
|
239
242
|
position: absolute;
|
|
240
243
|
right: -2px;
|
|
241
244
|
top: 0;
|
|
@@ -248,30 +251,30 @@
|
|
|
248
251
|
/* 任务清单:复选框与首行文字在同一行高内垂直居中。
|
|
249
252
|
li 是 flex 容器,项内段落的外边距不会塌到 li 外(不像普通 ul/ol),只会把正文往下推,
|
|
250
253
|
所以项内段落清零外边距,项间距改由 li 按 ul/ol 的 0.7em 承担。 */
|
|
251
|
-
.
|
|
254
|
+
._editorContent_1teg4_30 ul[data-type='taskList'] {
|
|
252
255
|
list-style: none;
|
|
253
256
|
padding-left: 0.2em;
|
|
254
257
|
}
|
|
255
258
|
|
|
256
|
-
.
|
|
259
|
+
._editorContent_1teg4_30 ul[data-type='taskList'] li {
|
|
257
260
|
display: flex;
|
|
258
261
|
align-items: flex-start;
|
|
259
262
|
gap: 0.5em;
|
|
260
263
|
margin: 0.7em 0;
|
|
261
264
|
}
|
|
262
265
|
|
|
263
|
-
.
|
|
266
|
+
._editorContent_1teg4_30 ul[data-type='taskList'] li > div > p {
|
|
264
267
|
margin: 0;
|
|
265
268
|
}
|
|
266
269
|
|
|
267
270
|
/* 项内第二段起保留半档间距,避免多段任务项的段落粘成一片(首段仍不带外边距) */
|
|
268
|
-
.
|
|
271
|
+
._editorContent_1teg4_30 ul[data-type='taskList'] li > div > p + p {
|
|
269
272
|
margin-top: 0.35em;
|
|
270
273
|
}
|
|
271
274
|
|
|
272
275
|
/* label 撑满一行行高并居中,框心落在首行文字中线上;
|
|
273
276
|
1lh 即该元素当前行高,随 --tmr-line-height(数字或长度写法)一起变,不靠手调偏移。 */
|
|
274
|
-
.
|
|
277
|
+
._editorContent_1teg4_30 ul[data-type='taskList'] li > label {
|
|
275
278
|
display: flex;
|
|
276
279
|
align-items: center;
|
|
277
280
|
flex: 0 0 auto;
|
|
@@ -279,18 +282,18 @@
|
|
|
279
282
|
user-select: none;
|
|
280
283
|
}
|
|
281
284
|
|
|
282
|
-
.
|
|
285
|
+
._editorContent_1teg4_30 ul[data-type='taskList'] li > div {
|
|
283
286
|
flex: 1;
|
|
284
287
|
}
|
|
285
288
|
|
|
286
|
-
.
|
|
289
|
+
._editorContent_1teg4_30 ul[data-type='taskList'] input[type='checkbox'] {
|
|
287
290
|
margin: 0;
|
|
288
291
|
accent-color: var(--tmr-accent, #ff6719);
|
|
289
292
|
cursor: pointer;
|
|
290
293
|
}
|
|
291
294
|
|
|
292
295
|
/* 脚注/引文圆标:与正文字垂直居中;配色对齐工具栏 active(浅橙底 + accent 字) */
|
|
293
|
-
.
|
|
296
|
+
._editorContent_1teg4_30 span.citation-ref {
|
|
294
297
|
display: inline-flex;
|
|
295
298
|
align-items: center;
|
|
296
299
|
justify-content: center;
|
|
@@ -327,7 +330,7 @@
|
|
|
327
330
|
border-color 0.15s ease;
|
|
328
331
|
}
|
|
329
332
|
|
|
330
|
-
.
|
|
333
|
+
._editorContent_1teg4_30 span.citation-ref a {
|
|
331
334
|
color: inherit;
|
|
332
335
|
text-decoration: none;
|
|
333
336
|
display: flex;
|
|
@@ -339,26 +342,26 @@
|
|
|
339
342
|
pointer-events: none;
|
|
340
343
|
}
|
|
341
344
|
|
|
342
|
-
.
|
|
343
|
-
.
|
|
344
|
-
.
|
|
345
|
+
._editorContent_1teg4_30 span.citation-ref:hover,
|
|
346
|
+
._editorContent_1teg4_30 span.citation-ref:focus-within,
|
|
347
|
+
._editorContent_1teg4_30 span.citation-ref[data-tmr-citation-active] {
|
|
345
348
|
background: var(--tmr-citation-bg-hover, var(--tmr-accent, #ff6719));
|
|
346
349
|
border-color: var(--tmr-citation-bg-hover, var(--tmr-accent, #ff6719));
|
|
347
350
|
color: var(--tmr-citation-fg-hover, #ffffff);
|
|
348
351
|
}
|
|
349
352
|
|
|
350
|
-
.
|
|
353
|
+
._editorContent_1teg4_30 .tiptap-mathematics-render[data-type='inline-math'] {
|
|
351
354
|
display: inline;
|
|
352
355
|
}
|
|
353
356
|
|
|
354
|
-
.
|
|
357
|
+
._editorContent_1teg4_30 .tiptap-mathematics-render[data-type='block-math'] {
|
|
355
358
|
margin: 0.9em 0;
|
|
356
359
|
overflow-x: auto;
|
|
357
360
|
text-align: center;
|
|
358
361
|
}
|
|
359
362
|
|
|
360
363
|
/* 导入占位:进度写在光标处,不进 Markdown */
|
|
361
|
-
.
|
|
364
|
+
._editorContent_1teg4_30 .tmr-import-placeholder {
|
|
362
365
|
display: flex;
|
|
363
366
|
align-items: center;
|
|
364
367
|
gap: 0.5em;
|
|
@@ -368,16 +371,16 @@
|
|
|
368
371
|
user-select: none;
|
|
369
372
|
}
|
|
370
373
|
|
|
371
|
-
.
|
|
374
|
+
._editorContent_1teg4_30 .tmr-import-placeholder-spin {
|
|
372
375
|
width: 0.7em;
|
|
373
376
|
height: 0.7em;
|
|
374
377
|
border: 1.5px solid var(--tmr-border, #e6e6e6);
|
|
375
378
|
border-top-color: var(--tmr-accent, #ff6719);
|
|
376
379
|
border-radius: 50%;
|
|
377
|
-
animation: _tmr-import-
|
|
380
|
+
animation: _tmr-import-spin_1teg4_1 0.7s linear infinite;
|
|
378
381
|
}
|
|
379
382
|
|
|
380
|
-
@keyframes _tmr-import-
|
|
383
|
+
@keyframes _tmr-import-spin_1teg4_1 {
|
|
381
384
|
to {
|
|
382
385
|
transform: rotate(360deg);
|
|
383
386
|
}
|
|
@@ -385,7 +388,7 @@
|
|
|
385
388
|
|
|
386
389
|
/* 快捷键抽屉的悬浮入口:sticky-bottom——自然位置在编辑器底部,
|
|
387
390
|
内容滚动时保持悬浮在可视区右下;到内容末尾落位对齐右缘 */
|
|
388
|
-
.
|
|
391
|
+
._shortcutFab_1teg4_391 {
|
|
389
392
|
position: sticky;
|
|
390
393
|
bottom: 20px;
|
|
391
394
|
z-index: 6;
|
|
@@ -406,14 +409,14 @@
|
|
|
406
409
|
transition: box-shadow 0.15s, color 0.15s;
|
|
407
410
|
}
|
|
408
411
|
|
|
409
|
-
.
|
|
412
|
+
._shortcutFab_1teg4_391:hover {
|
|
410
413
|
color: var(--tmr-accent, #ff6719);
|
|
411
414
|
box-shadow: 0 8px 24px rgb(0 0 0 / 16%);
|
|
412
415
|
}
|
|
413
416
|
|
|
414
417
|
/* 宿主容器模式的悬浮键:定位归宿主(如叠在「回到顶部」按钮上方),
|
|
415
418
|
库只保留按钮本体视觉,不加粘性定位与右下角外边距 */
|
|
416
|
-
.
|
|
419
|
+
._shortcutFabHosted_1teg4_419 {
|
|
417
420
|
position: static;
|
|
418
421
|
margin: 0;
|
|
419
422
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tiptap-markdown-react",
|
|
3
|
-
"version": "0.17.
|
|
3
|
+
"version": "0.17.1",
|
|
4
4
|
"description": "A batteries-included, self-styled Markdown WYSIWYG editor and reader suite built on Tiptap v3. Markdown in/out, SSR/static rendering, table of contents, themeable via CSS variables, zero Ant Design.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"extractToc-CheLC9kh.js","sources":["../src/CitationRef.ts","../src/commentAnchor/CommentMark.ts","../src/commentAnchor/commentMapper.ts","../src/chart/ChartExtension.ts","../src/chart/codeBlockChartParse.ts","../src/math.ts","../src/extensions.ts","../src/chart/prepareChartMarkdown.ts","../src/toc/tocSlug.ts","../src/stabilizeMarkdown.ts","../src/toc/extractToc.ts"],"sourcesContent":["import { mergeAttributes, Node } from '@tiptap/core';\n\nexport interface CitationRefOptions {\n HTMLAttributes: Record<string, unknown>;\n}\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n citationRef: {\n insertCitationRef: (attrs: {\n index: string;\n url?: string | null;\n title?: string | null;\n }) => ReturnType;\n };\n }\n}\n\n/**\n * 脚注/引文引用——inline atom 节点。\n *\n * - 输入:`[^n]`(markdownTokenizer)或 `<span class=\"citation-ref\">`(parseHTML)\n * - 输出 HTML:居中圆形 pill(CSS `.citation-ref`),**不是**上下标\n * - 输出 markdown:`[^n]`\n *\n * Popover /「原文片段」由消费方通过 {@link createCitationRef} 的 `renderCitation`\n * 插槽完成;本节点只负责标记与默认圆标样式。\n */\nexport const CitationRef = Node.create<CitationRefOptions>({\n name: 'citationRef',\n\n group: 'inline',\n\n inline: true,\n\n atom: true,\n\n selectable: true,\n\n // 高于普通链接,确保 `[^1]` 不被拆成残缺 link\n priority: 1000,\n\n addOptions() {\n return { HTMLAttributes: {} };\n },\n\n addAttributes() {\n return {\n index: {\n default: null,\n parseHTML: (element) => element.getAttribute('data-index'),\n renderHTML: (attributes) => {\n if (!attributes.index) return {};\n return { 'data-index': attributes.index };\n },\n },\n url: {\n default: null,\n parseHTML: (element) => element.getAttribute('data-url'),\n renderHTML: (attributes) => {\n if (!attributes.url) return {};\n return { 'data-url': attributes.url };\n },\n },\n title: {\n default: null,\n parseHTML: (element) => element.getAttribute('data-title'),\n renderHTML: (attributes) => {\n if (!attributes.title) return {};\n return { 'data-title': attributes.title };\n },\n },\n };\n },\n\n parseHTML() {\n return [{ tag: 'span.citation-ref' }];\n },\n\n renderHTML({ node, HTMLAttributes }) {\n const index = String(node.attrs.index ?? '');\n const url = node.attrs.url as string | null;\n const title = (node.attrs.title as string | null) || '';\n const attrs = mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, {\n class: 'citation-ref',\n });\n\n if (url) {\n return [\n 'span',\n attrs,\n [\n 'a',\n {\n href: url,\n title,\n target: '_blank',\n rel: 'noopener noreferrer',\n },\n index,\n ],\n ];\n }\n\n return ['span', attrs, index];\n },\n\n renderMarkdown(node) {\n return `[^${node?.attrs?.index ?? ''}]`;\n },\n\n parseMarkdown: (token, helpers) => {\n return helpers.createNode('citationRef', {\n index: String(token.index ?? ''),\n url: token.url ?? null,\n title: token.title ?? null,\n });\n },\n\n markdownTokenizer: {\n name: 'citationRef',\n level: 'inline' as const,\n start(src: string) {\n const match = /\\[\\^\\d+\\]/.exec(src);\n return match?.index ?? -1;\n },\n tokenize(src) {\n const match = /^\\[\\^(\\d+)\\]/.exec(src);\n if (!match) return undefined;\n return {\n type: 'citationRef',\n raw: match[0],\n index: match[1],\n };\n },\n },\n\n addCommands() {\n return {\n insertCitationRef:\n (attrs) =>\n ({ commands }) =>\n commands.insertContent({\n type: this.name,\n attrs: {\n index: attrs.index,\n url: attrs.url ?? null,\n title: attrs.title ?? null,\n },\n }),\n };\n },\n});\n","import { Mark, mergeAttributes } from '@tiptap/core';\n\n/**\n * 评论锚定 mark —— 仅存在于编辑会话内,导出 markdown 时剥离。\n *\n * - attrs.commentIds:string[]。ProseMirror 同一文本节点不能挂两个同名\n * mark,重叠评论由 commentMapper 合并成「区间 + commentIds[]」后一次性铺入。\n * - renderMarkdown 返回空串 → getMarkdown() 输出纯文本,评论数据不落库。\n * - 粘贴/拖拽拦截与 gutter / active 装饰见 commentAnchorPlugin(客户端)。\n * 本模块保持纯 schema,server 入口可安全导入。\n */\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n commentAnchor: {\n /** 按互不相交的区间 + commentIds 数组铺评论 mark(区间由 mergeCommentIntervals 产出)。 */\n applyCommentAnchors: (intervals: CommentInterval[]) => ReturnType;\n /** 清空全文档评论 mark(comments 刷新 / 退出编辑态前调用)。 */\n clearCommentAnchors: () => ReturnType;\n };\n }\n}\n\nexport interface CommentInterval {\n from: number;\n to: number;\n commentIds: string[];\n}\n\nexport interface CommentMarkOptions {\n HTMLAttributes: Record<string, unknown>;\n}\n\nexport const CommentMark = Mark.create<CommentMarkOptions>({\n name: 'commentAnchor',\n\n // 评论是「引用快照」:光标在区间边界输入不应自动扩展高亮。\n inclusive: false,\n // 与加粗/斜体等格式可共存。\n excludes: '',\n\n addOptions() {\n return { HTMLAttributes: {} };\n },\n\n addAttributes() {\n return {\n commentIds: {\n default: [] as string[],\n parseHTML: (element) =>\n (element.getAttribute('data-comment-ids') ?? '')\n .split(' ')\n .filter(Boolean),\n renderHTML: (attributes) => {\n const ids = attributes.commentIds as string[];\n return ids?.length\n ? { 'data-comment-ids': Array.from(new Set(ids)).join(' ') }\n : {};\n },\n },\n };\n },\n\n parseHTML() {\n return [{ tag: 'mark[data-comment-ids]' }];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\n 'mark',\n mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, {\n class: 'tmr-comment',\n }),\n 0,\n ];\n },\n\n // 关键契约:markdown 输出剥离评论 mark,落库内容永远干净。\n // 注意:@tiptap/markdown 的 registerExtension 以扩展 name 注册 renderMarkdown,\n // 无需(也不支持)markdownName 字段。\n renderMarkdown() {\n return '';\n },\n\n addCommands() {\n return {\n applyCommentAnchors:\n (intervals) =>\n ({ tr, dispatch }) => {\n const intervals_ = (intervals ?? []).filter(\n (iv) => iv.from < iv.to && iv.commentIds.length > 0,\n );\n if (intervals_.length === 0) return false;\n let next = tr;\n for (const iv of intervals_) {\n next = next.addMark(\n iv.from,\n iv.to,\n this.type.create({ commentIds: iv.commentIds }),\n );\n }\n // 锚定是会话级 UI,不是用户内容:不进 undo 历史,避免 Ctrl+Z 把\n // 高亮全部撤掉。真编辑(改字)仍可正常 undo。\n next.setMeta('addToHistory', false);\n if (dispatch) dispatch(next);\n return true;\n },\n clearCommentAnchors:\n () =>\n ({ tr, dispatch }) => {\n const markType = this.type;\n const ranges: Array<{ from: number; to: number }> = [];\n tr.doc.descendants((node, pos) => {\n if (node.isText && node.marks.some((m) => m.type === markType)) {\n ranges.push({ from: pos, to: pos + node.nodeSize });\n }\n return true;\n });\n // 无 mark 时视为成功(no-op),保证 chain 后续命令继续执行。\n if (ranges.length === 0) return true;\n let next = tr;\n for (const r of ranges) next = next.removeMark(r.from, r.to, markType);\n next.setMeta('addToHistory', false);\n if (dispatch) dispatch(next);\n return true;\n },\n };\n },\n});\n","import type { Node } from '@tiptap/pm/model';\nimport type { CommentInterval } from './CommentMark';\n\n/**\n * SPIKE 原型:把评论的 ref_content segments 映射到 ProseMirror doc 上的文本区间。\n *\n * 与旧 DOM textContent 匹配的区别:\n * - 工作在文档模型上(无表格 wrapper 空白 / text node 碎片问题);\n * - 按顶层 block 作用域搜索,避免跨 block 误命中;\n * - fallback 链与既有 anchorCommentsInDom 一致:hash → context → exact → prefix → outdated。\n */\n\nexport interface CommentSegment {\n /** block 文本哈希(可选快路径;哈希算法见 blockTextHash,需与捕获端一致)。 */\n blockHash?: string;\n prefix?: string;\n exact: string;\n suffix?: string;\n}\n\nexport interface CommentAnchorInput {\n commentId: string;\n segments: CommentSegment[];\n}\n\nexport type CommentAnchorStatus = 'matched' | 'ambiguous' | 'partial' | 'outdated';\n\nexport interface CommentRange {\n from: number;\n to: number;\n}\n\nexport interface CommentAnchorResult {\n commentId: string;\n ranges: CommentRange[];\n status: CommentAnchorStatus;\n}\n\ninterface TextSlice {\n pos: number;\n text: string;\n}\n\ninterface TextIndex {\n slices: TextSlice[];\n offsets: number[];\n fullText: string;\n}\n\nconst PREFIX_FALLBACK_LEN = 20;\n\n/** 收集 [start, end) 内所有 text 节点 + 位置,拼成可搜索的 flat text。 */\nfunction collectText(doc: Node, start = 0, end = doc.content.size): TextIndex {\n const slices: TextSlice[] = [];\n const offsets: number[] = [];\n let cursor = 0;\n doc.nodesBetween(start, end, (node, pos) => {\n if (node.isText && node.text) {\n slices.push({ pos, text: node.text });\n offsets.push(cursor);\n cursor += node.text.length;\n }\n return true;\n });\n offsets.push(cursor);\n return {\n slices,\n offsets,\n fullText: slices.map((s) => s.text).join(''),\n };\n}\n\nfunction findAll(fullText: string, needle: string): number[] {\n if (!needle) return [];\n const hits: number[] = [];\n let from = 0;\n while (from <= fullText.length - needle.length) {\n const idx = fullText.indexOf(needle, from);\n if (idx < 0) break;\n hits.push(idx);\n from = idx + needle.length;\n }\n return hits;\n}\n\n/** 把 fullText 上的 [start, start+len) 映射回 doc 绝对位置。 */\nfunction rangeAt(index: TextIndex, start: number, len: number): CommentRange | null {\n if (len <= 0) return null;\n let startIdx = -1;\n let endIdx = -1;\n for (let i = 0; i < index.slices.length; i++) {\n if (index.offsets[i] <= start && start < index.offsets[i + 1]) startIdx = i;\n const end = start + len;\n if (index.offsets[i] < end && end <= index.offsets[i + 1]) endIdx = i;\n if (startIdx >= 0 && endIdx >= 0) break;\n }\n if (startIdx < 0 || endIdx < 0) return null;\n return {\n from: index.slices[startIdx].pos + (start - index.offsets[startIdx]),\n to: index.slices[endIdx].pos + (start + len - index.offsets[endIdx]),\n };\n}\n\n/** 顶层 block 边界(doc 直接子节点)。 */\nfunction blockBounds(doc: Node): Array<{ start: number; end: number }> {\n const bounds: Array<{ start: number; end: number }> = [];\n doc.forEach((child, offset) => {\n bounds.push({ start: offset, end: offset + child.nodeSize });\n });\n return bounds;\n}\n\n/** djb2 哈希(捕获端与消费端必须用同一个实现;invret 接入时对齐)。 */\nexport function blockTextHash(text: string): string {\n const normalized = text.replace(/\\s+/g, '');\n let hash = 5381;\n for (let i = 0; i < normalized.length; i++) {\n hash = (hash * 33) ^ normalized.charCodeAt(i);\n }\n return String(hash >>> 0);\n}\n\nfunction blockText(doc: Node, bound: { start: number; end: number }): string {\n return collectText(doc, bound.start, bound.end).fullText;\n}\n\n/** 在若干 block 内找 needle,返回命中区间;命中 >1 处标记 ambiguous。 */\nfunction matchInBlocks(\n doc: Node,\n bounds: Array<{ start: number; end: number }>,\n needle: string,\n markLen: number,\n markOffset: number,\n): { ranges: CommentRange[]; ambiguous: boolean } {\n const ranges: CommentRange[] = [];\n let hits = 0;\n for (const bound of bounds) {\n const index = collectText(doc, bound.start, bound.end);\n for (const start of findAll(index.fullText, needle)) {\n const range = rangeAt(index, start + markOffset, markLen);\n if (range) {\n ranges.push(range);\n hits += 1;\n }\n }\n }\n return { ranges, ambiguous: hits > 1 };\n}\n\n/** 单个 segment → doc 区间(fallback 链)。 */\nfunction matchSegment(doc: Node, seg: CommentSegment): {\n ranges: CommentRange[];\n ambiguous: boolean;\n} {\n const bounds = blockBounds(doc);\n\n // S1: blockHash 快路径\n if (seg.blockHash) {\n const ranges: CommentRange[] = [];\n let hits = 0;\n for (const bound of bounds) {\n if (blockTextHash(blockText(doc, bound)) !== seg.blockHash) continue;\n const index = collectText(doc, bound.start, bound.end);\n for (const start of findAll(index.fullText, seg.exact)) {\n const range = rangeAt(index, start, seg.exact.length);\n if (range) {\n ranges.push(range);\n hits += 1;\n }\n }\n }\n if (ranges.length > 0) return { ranges, ambiguous: hits > 1 };\n }\n\n // S2: 上下文(prefix+exact+suffix)定位\n if (seg.prefix || seg.suffix) {\n const composite = (seg.prefix ?? '') + seg.exact + (seg.suffix ?? '');\n const found = matchInBlocks(\n doc,\n bounds,\n composite,\n seg.exact.length,\n seg.prefix?.length ?? 0,\n );\n if (found.ranges.length > 0) return found;\n }\n\n // S3: block 内 exact\n const exact = matchInBlocks(doc, bounds, seg.exact, seg.exact.length, 0);\n if (exact.ranges.length > 0) return exact;\n\n // S4: 前缀降级(前 20 字)\n const prefix = seg.exact.slice(0, PREFIX_FALLBACK_LEN);\n if (prefix.length >= 4 && prefix !== seg.exact) {\n const fallback = matchInBlocks(doc, bounds, prefix, prefix.length, 0);\n if (fallback.ranges.length > 0) return fallback;\n }\n\n return { ranges: [], ambiguous: false };\n}\n\n/** 主入口:评论列表 → 每条的 doc 区间 + 状态。 */\nexport function mapCommentAnchors(\n doc: Node,\n comments: CommentAnchorInput[],\n): CommentAnchorResult[] {\n return comments.map((c) => {\n let matchedSegments = 0;\n let ambiguousSegments = 0;\n const ranges: CommentRange[] = [];\n for (const seg of c.segments) {\n const { ranges: segRanges, ambiguous } = matchSegment(doc, seg);\n if (segRanges.length > 0) {\n matchedSegments += 1;\n if (ambiguous) ambiguousSegments += 1;\n ranges.push(...segRanges);\n }\n }\n const status: CommentAnchorStatus =\n matchedSegments === 0\n ? 'outdated'\n : ambiguousSegments > 0\n ? 'ambiguous'\n : matchedSegments < c.segments.length\n ? 'partial'\n : 'matched';\n return { commentId: c.commentId, ranges, status };\n });\n}\n\n/** 把每条评论的区间合并成互不相交的 CommentInterval(重叠区间合并 commentIds)。 */\nexport function mergeCommentIntervals(\n entries: Array<{ commentId: string; ranges: CommentRange[] }>,\n): CommentInterval[] {\n interface Event {\n pos: number;\n delta: 1 | -1;\n id: string;\n }\n const events: Event[] = [];\n for (const e of entries) {\n // 先按评论合并相邻/接触区间(同一评论的多段 [0,2)+[2,4) 应视为连续覆盖),\n // 否则 sweep 会在接缝处错误地先关后开,产出多余分段。\n const sorted = e.ranges\n .filter((r) => r.from < r.to)\n .sort((a, b) => a.from - b.from || a.to - b.to);\n const merged: CommentRange[] = [];\n for (const r of sorted) {\n const last = merged[merged.length - 1];\n if (last && r.from <= last.to) {\n if (r.to > last.to) last.to = r.to;\n } else {\n merged.push({ from: r.from, to: r.to });\n }\n }\n for (const r of merged) {\n events.push({ pos: r.from, delta: 1, id: e.commentId });\n events.push({ pos: r.to, delta: -1, id: e.commentId });\n }\n }\n if (events.length === 0) return [];\n events.sort((a, b) => a.pos - b.pos || a.delta - b.delta);\n\n const intervals: CommentInterval[] = [];\n const active = new Set<string>();\n let prevPos = events[0].pos;\n for (const ev of events) {\n if (ev.pos > prevPos && active.size > 0) {\n intervals.push({\n from: prevPos,\n to: ev.pos,\n commentIds: Array.from(active),\n });\n }\n if (ev.delta === 1) active.add(ev.id);\n else active.delete(ev.id);\n prevPos = ev.pos;\n }\n return intervals;\n}\n","import { mergeAttributes, Node } from '@tiptap/core';\nimport { Plugin, PluginKey } from '@tiptap/pm/state';\nimport { CHART_FENCE_LANGS } from './codeBlockChartParse';\nimport {\n normalizeChartMarkdown,\n parseChartFenceBody,\n serializeChartPayload,\n} from './parse';\nimport type { ChartColumn, ChartConfig, ChartPayload } from './types';\n\nconst chartFenceUpgradeKey = new PluginKey('tmrChartFenceUpgrade');\n\nexport const CHART_NODE_NAME = 'chart';\n\nexport interface ChartNodeAttrs {\n config: ChartConfig[];\n columns: ChartColumn[];\n dataSource: Record<string, unknown>[];\n}\n\nfunction attrsToPayload(attrs: ChartNodeAttrs): ChartPayload {\n return {\n config: attrs.config ?? [],\n columns: attrs.columns ?? [],\n dataSource: attrs.dataSource ?? [],\n };\n}\n\nfunction encodePayload(payload: ChartPayload): string {\n return JSON.stringify(payload);\n}\n\nfunction decodePayloadAttr(raw: string | null): ChartPayload | null {\n if (!raw) return null;\n try {\n return parseChartFenceBody(raw) ?? (JSON.parse(raw) as ChartPayload);\n } catch {\n return null;\n }\n}\n\nexport interface ReportChartOptions {\n HTMLAttributes: Record<string, unknown>;\n}\n\n/**\n * Pure chart block node — safe for server / SSR.\n * Does not import chart.js or React. renderHTML emits a hydrate placeholder.\n */\nexport const reportChart = Node.create<ReportChartOptions>({\n name: CHART_NODE_NAME,\n\n group: 'block',\n\n atom: true,\n\n selectable: true,\n\n draggable: true,\n\n // Above default codeBlock so ```tmr-chart / ```chart bind here\n priority: 1000,\n\n addOptions() {\n return { HTMLAttributes: {} };\n },\n\n addAttributes() {\n return {\n config: {\n default: [],\n parseHTML: (element) => {\n const payload = decodePayloadAttr(element.getAttribute('data-chart'));\n return payload?.config ?? [];\n },\n },\n columns: {\n default: [],\n parseHTML: (element) => {\n const payload = decodePayloadAttr(element.getAttribute('data-chart'));\n return payload?.columns ?? [];\n },\n },\n dataSource: {\n default: [],\n parseHTML: (element) => {\n const payload = decodePayloadAttr(element.getAttribute('data-chart'));\n return payload?.dataSource ?? [];\n },\n },\n };\n },\n\n parseHTML() {\n return [{ tag: 'div[data-type=\"chart\"]' }];\n },\n\n renderHTML({ node, HTMLAttributes }) {\n const payload = attrsToPayload(node.attrs as ChartNodeAttrs);\n const title = payload.config[0]?.title;\n const height = payload.config[0]?.height ?? 320;\n const dataTime = payload.config[0]?.dataTime;\n\n return [\n 'div',\n mergeAttributes(this.options.HTMLAttributes, HTMLAttributes, {\n 'data-type': 'chart',\n 'data-chart': encodePayload(payload),\n class: 'tmr-chart',\n style: `min-height:${height}px`,\n }),\n title\n ? ['div', { class: 'tmr-chart-title' }, String(title)]\n : ['div', { class: 'tmr-chart-title tmr-chart-title--empty' }, ''],\n dataTime\n ? ['div', { class: 'tmr-chart-time' }, String(dataTime)]\n : ['div', { class: 'tmr-chart-time tmr-chart-time--empty' }, ''],\n [\n 'div',\n {\n class: 'tmr-chart-canvas-host tmr-chart-skeleton',\n 'aria-hidden': 'true',\n },\n ],\n ];\n },\n\n renderMarkdown(node) {\n const payload = attrsToPayload(node.attrs as ChartNodeAttrs);\n if (!payload.config.length) return '';\n return serializeChartPayload(payload);\n },\n\n parseMarkdown: (token, helpers) => {\n const body = String(token.content ?? token.text ?? token.raw ?? '');\n // Tokenizer may put JSON in `text` or leave fence body in content\n const json =\n typeof token.payload === 'string'\n ? token.payload\n : body.replace(/^```(?:tmr-chart|chart|json-chart)\\s*\\n?/i, '').replace(/\\n?```$/, '');\n const payload =\n parseChartFenceBody(typeof token.payload === 'string' ? token.payload : json) ??\n (token.payload && typeof token.payload === 'object'\n ? (token.payload as ChartPayload)\n : null);\n if (!payload) {\n return helpers.createNode('paragraph');\n }\n return helpers.createNode(CHART_NODE_NAME, {\n config: payload.config,\n columns: payload.columns,\n dataSource: payload.dataSource,\n });\n },\n\n markdownTokenizer: {\n name: CHART_NODE_NAME,\n level: 'block' as const,\n start(src: string) {\n const fence = src.match(/^```(?:tmr-chart|chart|json-chart)\\b/m);\n if (fence && fence.index !== undefined) return fence.index;\n return -1;\n },\n tokenize(src: string) {\n const match =\n /^```(tmr-chart|chart|json-chart)[^\\n]*\\n([\\s\\S]*?)```(?:\\r?\\n|$)/.exec(\n src,\n );\n if (!match) return undefined;\n const payload = parseChartFenceBody(match[2]);\n if (!payload) return undefined;\n return {\n type: CHART_NODE_NAME,\n raw: match[0],\n payload: JSON.stringify({\n config: payload.config,\n columns: payload.columns,\n dataSource: payload.dataSource,\n }),\n };\n },\n },\n\n /**\n * When the built-in `code` tokenizer wins, TipTap creates a codeBlock with\n * language=tmr-chart. Upgrade those nodes to chart (covers mid-column\n * CardMarkdownEditor + paste/setContent paths).\n */\n addProseMirrorPlugins() {\n const chartName = this.name;\n return [\n new Plugin({\n key: chartFenceUpgradeKey,\n appendTransaction(transactions, _oldState, newState) {\n if (!transactions.some((tr) => tr.docChanged)) return null;\n return buildChartFenceUpgradeTr(newState, chartName);\n },\n }),\n ];\n },\n});\n\nfunction buildChartFenceUpgradeTr(\n state: import('@tiptap/pm/state').EditorState,\n chartName: string,\n) {\n const chartType = state.schema.nodes[chartName];\n if (!chartType || !state.schema.nodes.codeBlock) return null;\n\n const replacements: { from: number; to: number; payload: ChartPayload }[] =\n [];\n state.doc.descendants((node, pos) => {\n if (node.type.name !== 'codeBlock') return;\n const lang = String(node.attrs.language ?? '')\n .trim()\n .toLowerCase();\n if (!CHART_FENCE_LANGS.has(lang)) return;\n const payload = parseChartFenceBody(node.textContent);\n if (!payload) return;\n replacements.push({\n from: pos,\n to: pos + node.nodeSize,\n payload,\n });\n });\n if (replacements.length === 0) return null;\n\n let tr = state.tr;\n for (let i = replacements.length - 1; i >= 0; i -= 1) {\n const { from, to, payload } = replacements[i];\n tr = tr.replaceWith(\n from,\n to,\n chartType.create({\n config: payload.config,\n columns: payload.columns,\n dataSource: payload.dataSource,\n }),\n );\n }\n return tr;\n}\n\n/** Re-export preprocess for parse pipelines. */\nexport { normalizeChartMarkdown };\n\n/** Pure chart extension alias for server / preview injection. */\nexport const pureChart = reportChart;\n","import type {\n JSONContent,\n MarkdownParseHelpers,\n MarkdownToken,\n} from '@tiptap/core';\nimport { CHART_NODE_NAME } from './ChartExtension';\nimport { parseChartFenceBody } from './parse';\n\n/** Fence languages that belong to chart nodes, not code blocks. */\nexport const CHART_FENCE_LANGS = new Set([\n 'tmr-chart',\n 'chart',\n 'json-chart',\n]);\n\n/**\n * TipTap's built-in `code` tokenizer often wins over custom chart fences.\n * When that happens, intercept CodeBlock.parseMarkdown and upgrade\n * ```tmr-chart / ```chart / ```json-chart into a chart node.\n */\nexport function parseCodeTokenAsChartOrCodeBlock(\n token: MarkdownToken,\n helpers: MarkdownParseHelpers,\n codeBlockName = 'codeBlock',\n): JSONContent | JSONContent[] {\n const lang = String(token.lang ?? '')\n .trim()\n .toLowerCase();\n if (CHART_FENCE_LANGS.has(lang)) {\n const payload = parseChartFenceBody(String(token.text ?? ''));\n if (payload) {\n return helpers.createNode(CHART_NODE_NAME, {\n config: payload.config,\n columns: payload.columns,\n dataSource: payload.dataSource,\n });\n }\n }\n\n if (\n token.raw?.startsWith('```') === false &&\n token.raw?.startsWith('~~~') === false &&\n token.codeBlockStyle !== 'indented'\n ) {\n return [];\n }\n\n return helpers.createNode(\n codeBlockName,\n { language: token.lang || null },\n token.text ? [helpers.createTextNode(token.text)] : [],\n );\n}\n","import { BlockMath, InlineMath } from '@tiptap/extension-mathematics';\nimport type { Node as PMNode } from '@tiptap/pm/model';\nimport katex from 'katex';\n\nconst KATEX_OPTIONS = { throwOnError: false as const };\n\nexport type MathKind = 'inline' | 'block';\n\nexport interface MathClickPayload {\n kind: MathKind;\n pos: number;\n latex: string;\n}\n\ntype MathClickListener = (payload: MathClickPayload) => void;\n\nlet mathClickListener: MathClickListener | null = null;\n\n/** 编辑器工具栏注册点击公式回调;未注册时点击无操作(预览 / SSR)。 */\nexport function subscribeMathClick(listener: MathClickListener): () => void {\n mathClickListener = listener;\n return () => {\n if (mathClickListener === listener) mathClickListener = null;\n };\n}\n\nfunction emitClick(kind: MathKind, node: PMNode, pos: number) {\n mathClickListener?.({\n kind,\n pos,\n latex: String(node.attrs.latex ?? ''),\n });\n}\n\nfunction escapeHtml(value: string): string {\n return value\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"');\n}\n\n/** KaTeX HTML 片段(SSR / 预览弹层)。失败时回退为转义原文。 */\nexport function renderMathHtml(latex: string, displayMode: boolean): string {\n try {\n return katex.renderToString(latex ?? '', {\n ...KATEX_OPTIONS,\n displayMode,\n });\n } catch {\n return escapeHtml(latex ?? '');\n }\n}\n\n/** 把公式画进已有节点(编辑态原地预览,避免再叠一份 overlay)。 */\nexport function renderMathInto(\n el: HTMLElement,\n latex: string,\n displayMode: boolean,\n): void {\n try {\n katex.render(latex ?? '', el, { ...KATEX_OPTIONS, displayMode });\n } catch {\n el.textContent = latex ?? '';\n }\n}\n\nexport function renderMathElementHtml(\n latex: string,\n displayMode: boolean,\n): string {\n const inner = renderMathHtml(latex, displayMode);\n const attr = escapeHtml(latex ?? '');\n if (displayMode) {\n return `<div data-type=\"block-math\" data-latex=\"${attr}\" class=\"tiptap-mathematics-render\">${inner}</div>`;\n }\n return `<span data-type=\"inline-math\" data-latex=\"${attr}\" class=\"tiptap-mathematics-render\">${inner}</span>`;\n}\n\n/**\n * 行内公式:markdown 为 `$$latex$$`(单行、无换行)。\n * 关掉官方 `$…$` tokenizer 与 `$$` input rule——手打 `$` / `$$` 当字。\n */\nexport const reportInlineMath = InlineMath.extend({\n addInputRules() {\n return [];\n },\n\n renderMarkdown(node: { attrs?: { latex?: string } }) {\n return `$$${node.attrs?.latex || ''}$$`;\n },\n\n markdownTokenizer: {\n name: 'inlineMath',\n level: 'inline' as const,\n start(src: string) {\n return src.indexOf('$$');\n },\n tokenize(src: string) {\n const match = /^\\$\\$([^$\\n]+?)\\$\\$/.exec(src);\n if (!match) return undefined;\n return {\n type: 'inlineMath',\n raw: match[0],\n latex: match[1].trim(),\n };\n },\n },\n}).configure({\n katexOptions: { ...KATEX_OPTIONS, displayMode: false },\n onClick: (node, pos) => emitClick('inline', node, pos),\n});\n\n/**\n * 块级公式:markdown 为带换行的 `$$\\nlatex\\n$$`。\n * 单行 `$$…$$` 不在这里匹配,交给行内。无 input rule。\n */\nexport const reportBlockMath = BlockMath.extend({\n addInputRules() {\n return [];\n },\n\n renderMarkdown(node: { attrs?: { latex?: string } }) {\n const latex = node.attrs?.latex || '';\n return `$$\\n${latex}\\n$$`;\n },\n\n markdownTokenizer: {\n name: 'blockMath',\n level: 'block' as const,\n start(src: string) {\n const match = /\\$\\$\\r?\\n/.exec(src);\n return match ? match.index : -1;\n },\n tokenize(src: string) {\n const match = /^\\$\\$\\r?\\n([\\s\\S]+?)\\r?\\n\\$\\$(?:\\r?\\n|$)/.exec(src);\n if (!match) return undefined;\n return {\n type: 'blockMath',\n raw: match[0],\n latex: match[1].trim(),\n };\n },\n },\n}).configure({\n katexOptions: { ...KATEX_OPTIONS, displayMode: true },\n onClick: (node, pos) => emitClick('block', node, pos),\n});\n","import Code from '@tiptap/extension-code';\nimport CodeBlockLowlight from '@tiptap/extension-code-block-lowlight';\nimport Highlight from '@tiptap/extension-highlight';\nimport Image from '@tiptap/extension-image';\nimport Subscript from '@tiptap/extension-subscript';\nimport Superscript from '@tiptap/extension-superscript';\nimport { TableKit } from '@tiptap/extension-table';\nimport TaskItem from '@tiptap/extension-task-item';\nimport TaskList from '@tiptap/extension-task-list';\nimport {\n Color,\n FontSize,\n TextStyle,\n} from '@tiptap/extension-text-style';\n// AnyExtension 从 @tiptap/react 取(它 re-export 自 core),避免新增 @tiptap/core 直接依赖\nimport type { AnyExtension } from '@tiptap/react';\nimport StarterKit from '@tiptap/starter-kit';\nimport { common, createLowlight } from 'lowlight';\nimport type { JSONContent } from '@tiptap/core';\nimport { parseCodeTokenAsChartOrCodeBlock } from './chart/codeBlockChartParse';\nimport { reportBlockMath, reportInlineMath } from './math';\n\n/**\n * StarterKit 默认 Code 的 excludes:'_' 禁止与任何其他 mark 共存。\n * CommonMark 允许 `**bold `code` bold**`;markdown 导入时会抛\n * RangeError: Invalid collection of marks for node text: bold,code。\n */\nconst InlineCode = Code.extend({\n excludes: '',\n});\n\n/**\n * 编辑器的「内容 schema 级」扩展集——纯节点/标记定义,不含任何 React NodeView\n * 或键盘交互绑定。三处共用:\n * 1. 编辑器(MarkdownWysiwygEditor):base + 交互增强版 CodeBlock/Image\n * 2. 只读预览(MarkdownPreview)\n * 3. server 端 markdown→HTML 渲染(renderReportHtml)\n *\n * 分层动机:交互增强依赖 @tiptap/react / 浏览器,会污染 server bundle(RSC)。\n * base 保持纯 schema,server import 它只引入节点定义,无 React 代码。\n *\n * 关键边界:CodeBlock / Image / CitationRef「会被客户端增强」,**不放进 base**——\n * 否则编辑器追加增强版会与 base 的纯版同名冲突(Tiptap 报 \"Duplicate extension names\")。\n * 改为:base 不含这三类,由调用方按需注入:\n * - 编辑器 / 预览注入「增强版」(React NodeView)\n * - server 注入「纯版」(pureCodeBlock / pureImage / CitationRef)\n */\n\n// lowlight 实例:代码块语法高亮。导出供编辑器增强版与 server 纯版共用同一实例。\nexport const lowlight = createLowlight(common);\n\n/**\n * 颜色 / 字号的 markdown 往返:markdown 没有原生颜色语法,序列化为行内 HTML\n * `<span style=\"...\">`(marked 支持行内 HTML,Tiptap 解析端经 parseHTML 还原成\n * TextStyle/Color/FontSize mark)。否则 getMarkdown() 会把这些 mark 静默剥掉,\n * 保存后再预览颜色丢失。\n *\n * 注意:Color / FontSize 通过 `types: [TextStyle.name]` 把 color / fontSize\n * 属性挂在 **textStyle** mark 的 attrs 上,文档里出现的 mark 类型名是\n * `textStyle`——所以 renderMarkdown 必须扩展在 TextStyle 上,序列化器才能按\n * mark 类型名查到 handler。\n */\nconst MarkdownTextStyle = TextStyle.extend({\n renderMarkdown(\n node: { attrs?: Record<string, unknown> },\n helpers: {\n renderChildren: (\n nodes: JSONContent | JSONContent[],\n separator?: string,\n ) => string;\n },\n ) {\n const { color, fontSize } = (node.attrs ?? {}) as {\n color?: string;\n fontSize?: string;\n };\n const styles: string[] = [];\n if (color) styles.push(`color:${color}`);\n if (fontSize) styles.push(`font-size:${fontSize}`);\n if (styles.length === 0) return '';\n // getMarkOpening 用占位符调用 renderChildren()(无需传节点),类型按签名兜底转换。\n const children = (helpers.renderChildren as () => string)();\n return `<span style=\"${styles.join(';')}\">${children}</span>`;\n },\n});\n\n/**\n * 纯版代码块(无 React 视图):server / 预览用。\n * 顺带把 ```tmr-chart 围栏升级为 chart 节点(内置 code tokenizer 抢先时)。\n */\nexport const pureCodeBlock = CodeBlockLowlight.extend({\n parseMarkdown: (token, helpers) =>\n parseCodeTokenAsChartOrCodeBlock(token, helpers, 'codeBlock'),\n}).configure({ lowlight });\n\n/**\n * 纯版块级图片(无删除快捷键):server / 预览用。\n * inline:false(官方默认)——研报里图片均为大图独占一行,块级图片可直接作为 doc\n * 顶层子节点,避免「inline image 裸挂 doc 顶层」被 generateTocIds 严格校验判非法。\n */\nexport const pureImage = Image.configure({ inline: false });\n\nexport { pureChart, reportChart } from './chart/ChartExtension';\n\n/**\n * 三处共用的纯 schema 扩展——**不含 CodeBlock / Image / CitationRef / Chart**(见上方边界说明)。\n * 编辑器:`[...baseExtensions, 增强CodeBlock, 增强Image, createCitationRef(), createChart(), Markdown]`\n * server/预览:`[...baseExtensions, pureCodeBlock, pureImage, CitationRef, pureChart, …]`\n */\nexport const baseExtensions: AnyExtension[] = [\n // 禁用 StarterKit 内置 codeBlock / code,统一改用 lowlight 代码块 + 可共存的 InlineCode\n StarterKit.configure({ codeBlock: false, code: false }),\n InlineCode,\n MarkdownTextStyle,\n Color.configure({ types: [TextStyle.name] }),\n // 正文字号:官方 FontSize(v3 起并入 text-style 包),以内联样式挂在 TextStyle\n // 的 <span> 上(如 style=\"font-size: 16px\"),与 Color 同基座,三端共用。\n FontSize.configure({ types: [TextStyle.name] }),\n Highlight.configure({ multicolor: true }),\n Superscript,\n Subscript,\n TableKit.configure({\n table: {\n resizable: true,\n // SSR/renderHTML 默认不包 wrapper;阅读页无 NodeView 时宽表会被挤扁。\n // 与编辑器 TableView 的 `.tableWrapper` 对齐,静态 HTML 也可 overflow-x。\n renderWrapper: true,\n },\n }),\n TaskList,\n TaskItem.configure({ nested: true }),\n reportInlineMath,\n reportBlockMath,\n];\n","import { normalizeChartMarkdown } from './parse';\n\n/**\n * Unwrap agentic-ui `<div data-card=\"true\">…</div>` so comment↔table\n * adjacency survives for normalizeChartMarkdown.\n */\nfunction unwrapDataCardDivs(markdown: string): string {\n return markdown.replace(\n /<div\\s+data-card=([\"']?)true\\1\\s*>\\s*([\\s\\S]*?)\\s*<\\/div>/gi,\n '\\n$2\\n',\n );\n}\n\n/**\n * Prepare markdown before TipTap / MarkdownManager parse:\n * unwrap data-card wrappers, then collapse `<!-- chart -->` + GFM table\n * pairs into ```tmr-chart fences.\n */\nexport function prepareChartMarkdown(markdown: string): string {\n return normalizeChartMarkdown(unwrapDataCardDivs(markdown ?? ''));\n}\n","/**\n * 目录锚点 id 生成——阅读页(SSR)与编辑页(editor)共用的**单一真源**,\n * 保证「创作预览的锚点 = 发布后阅读页的锚点」。\n *\n * 用 slug 而非官方默认 UUID:slug 跨 SSR / ISR revalidate 稳定(UUID 每次都变、\n * 分享的 #hash 会失效),且 `#introduction` 比 `#d4590f81-…` 可读、对 SEO 友好。\n *\n * slug 会重名(两个「细节」都 slug 成 `xi-jie`),故用闭包计数器去重:\n * 同名追加 -2 / -3(已实测:details / details-2 / details-3,HTML id 全唯一)。\n */\n\n/** 单个标题文本 → 基础 slug(保留中文,去标点,空白转连字符)。 */\nfunction baseSlug(text: string): string {\n return (\n text\n .toLowerCase()\n .trim()\n .replace(/\\s+/g, '-')\n // 保留字母/数字/下划线/中文/连字符,其余剔除\n .replace(/[^\\w一-龥-]/g, '')\n .replace(/^-+|-+$/g, '') || 'section'\n );\n}\n\n/**\n * 造一个带去重的 `getId`。每次生成新实例(闭包各自计数),传给\n * `TableOfContents.configure({ getId })` 或 `generateTocIds` 的扩展配置。\n */\nexport function makeTocGetId(): (content: string) => string {\n const seen = new Map<string, number>();\n return (content: string) => {\n const base = baseSlug(content);\n const n = (seen.get(base) ?? 0) + 1;\n seen.set(base, n);\n return n === 1 ? base : `${base}-${n}`;\n };\n}\n","/**\n * 给流式半成品 markdown 补闭合围栏,避免未结束的 ``` 把后文吞进 code。\n * 完整稿不要调用(ISR / 已落库卡)。\n */\nexport function stabilizeMarkdown(markdown: string): string {\n if (!markdown) return markdown;\n\n let inFence = false;\n let fenceChar = '`';\n let fenceLen = 3;\n\n for (const line of markdown.split('\\n')) {\n const match = line.match(/^(`{3,}|~{3,})/);\n if (!match) continue;\n const marker = match[1];\n const char = marker[0];\n if (!inFence) {\n inFence = true;\n fenceChar = char;\n fenceLen = marker.length;\n continue;\n }\n if (char === fenceChar && marker.length >= fenceLen && /^[`~]+\\s*$/.test(line)) {\n inFence = false;\n }\n }\n\n if (!inFence) return markdown;\n const closer = fenceChar.repeat(fenceLen);\n return markdown.endsWith('\\n') ? `${markdown}${closer}` : `${markdown}\\n${closer}`;\n}\n","/**\n * 最小 Tiptap JSON 节点结构(只取本模块用到的字段)。\n * 不从 `@tiptap/core` 引 `JSONContent`——core 是嵌套依赖、非直接依赖,\n * 直接 import 类型解析不到(与仓库既有做法一致,见 extensions.ts)。\n */\ninterface TocDocNode {\n type?: string;\n text?: string;\n attrs?: Record<string, unknown> | null;\n content?: TocDocNode[];\n}\n\n/** 目录项。 */\nexport interface TocItem {\n /** 锚点 id(= heading 的 data-toc-id / id,由 generateTocIds 注入)。 */\n id: string;\n /** 标题层级(1-6)。 */\n level: number;\n /** 标题纯文本。 */\n text: string;\n /** 付费墙锁住的章节(置灰不可点)。 */\n locked?: boolean;\n}\n\n/** 目录纳入的最大层级(h1-h6,全层级入目录)。 */\nconst MAX_LEVEL = 6;\n\n/** 取 heading 节点的纯文本(拼接其 text 子节点)。 */\nfunction headingText(node: TocDocNode): string {\n if (!node.content) return '';\n return node.content\n .map((c) => (c.type === 'text' ? c.text ?? '' : ''))\n .join('')\n .trim();\n}\n\n/**\n * 从已注入锚点 id 的 Tiptap JSON doc 提取 h1-h6 目录。\n *\n * 必须在 `generateTocIds` 之后调用(heading 的 attrs 里才有 `data-toc-id`)。\n * `lockedTitles`:被截断(锁住)章节标题,命中则标 `locked`——\n * 目录列全部章节,锁住项置灰不可点(付费墙钩子)。用 Set 便于去重命中。\n */\nexport function extractToc(\n doc: TocDocNode,\n lockedTitles: string[] = [],\n): TocItem[] {\n const locked = new Set(lockedTitles.map((t) => t.trim()));\n const items: TocItem[] = [];\n\n const walk = (node: TocDocNode) => {\n const level = node.attrs?.level;\n if (\n node.type === 'heading' &&\n typeof level === 'number' &&\n level <= MAX_LEVEL\n ) {\n const text = headingText(node);\n const id = (node.attrs?.['data-toc-id'] ?? node.attrs?.id) as\n | string\n | undefined;\n // 有文本 + 有锚点 id 才入目录(空标题 / 未注入 id 的跳过)。\n if (text && id) {\n items.push({\n id,\n level,\n text,\n locked: locked.has(text) || undefined,\n });\n }\n }\n node.content?.forEach(walk);\n };\n\n walk(doc);\n return items;\n}\n"],"names":[],"mappings":"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"}
|