dsh-md-plus 0.4.0 → 0.4.2
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/CHANGELOG.md +23 -1
- package/README.md +4 -4
- package/lib/client.js +208 -39
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,28 @@
|
|
|
1
1
|
# 更新日志
|
|
2
2
|
|
|
3
|
-
## 0.4.
|
|
3
|
+
## 0.4.2 —— 未发布
|
|
4
|
+
|
|
5
|
+
- 修复鼠标悬浮表格或折叠内容时吞掉页面滚轮:移除表格容器的 `overscroll-behavior` containment,折叠态改为保留横向滚动、纵向 `overflow-y: clip`,并覆盖 DSH 宿主 `.tableScroll` 自带的横向 containment。
|
|
6
|
+
- 修复宽表横向滚动条出现 / 消失时鼠标移入移出表格造成的上下跳动:取消 hover 阶段的 padding 切换,固定底部留白。
|
|
7
|
+
- 修复宽表横向滚动时「展开 / 收起」按钮跟着表格内容移动:按钮中心固定跟随表格可视区域。
|
|
8
|
+
- 修复宽表横向滚动时右上角 CSV / Markdown 操作按钮跟表格内容移动:操作组固定在表格可视区域右上角。
|
|
9
|
+
- 新增 `docs/table-wheel-demo.html`:可直接检查短表、默认折叠长表(含横向滚动)和展开长表三种滚轮行为。
|
|
10
|
+
- 测试补到 73 条,新增表格和折叠内容不建立吞滚轮滚动容器的回归用例。
|
|
11
|
+
|
|
12
|
+
## 0.4.1 —— 2026-10-30
|
|
13
|
+
|
|
14
|
+
- 修复 DSH 代码块头部只显示占位文案时读不到真实围栏语言、补高亮失效的问题:现在会从宿主的 React fiber 读取真实 `lang`,读不到再退回正文嗅探,并把头部语言名显示成真实语言。
|
|
15
|
+
- 修复 `graph = nx.Graph()`、`pie = 3.14`、`timeline = []` 等普通代码被误判成 mermaid 图的问题:只嗅探第一行有效内容,并排除赋值和调用形态。
|
|
16
|
+
- 修复代码块折叠在 DSH 上不触发:DSH 的代码内容容器是 `display:contents`,插件没有可测量的盒子;现在给代码内容建立真实的块级盒模型。
|
|
17
|
+
- 修复表格吸顶:给表格容器增加纵向滚动上限,表头在容器内滚动时保持可见。
|
|
18
|
+
- 修复卸载/重载后高亮副本、折叠按钮和 `data-md-plus*` 属性残留,避免同一份代码显示两遍,重装后也能重新处理。
|
|
19
|
+
- 修复鼠标滚轮在 1 倍图表上拦截页面滚动:未放大且未按住 Ctrl/Meta 时放行;全屏查看仍可滚轮缩放。
|
|
20
|
+
- 修复切换主题后代码视图中的 mermaid 图不重画的问题。
|
|
21
|
+
- 修复设置面板「恢复默认」把折叠阈值写成 0、代码字号与宿主行高不匹配、字号输入越界后静默回退的问题。
|
|
22
|
+
- 修复 mermaid 渲染失败后仍显示无效缩放/全屏按钮的问题,失败块现在显示「重试」;运行时脚本加载失败也不再永久缓存失败结果。
|
|
23
|
+
- 测试补到 72 条,新增 React fiber 语言识别、mermaid 误判、代码折叠盒模型、卸载清理、滚轮放行、代码视图主题重画、设置默认值等回归用例。
|
|
24
|
+
|
|
25
|
+
## 0.4.0 —— 2026-10-28
|
|
4
26
|
|
|
5
27
|
- Mermaid 全屏工具栏新增「下载 SVG / 下载 PNG」,可以直接把图带进文档或演示文稿。
|
|
6
28
|
- 代码块、表格和 Mermaid 图卡增加长内容折叠:超过阈值显示「展开 / 收起」,避免长日志和长表格撑满聊天。
|
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
- **代码块**:统一成完整卡片,头部显示 `</>` 图标和语言名(无语言显示 `Plain text`),保留宿主原生的换行与复制按钮,顶栏与卡片同色。
|
|
10
10
|
- **Mermaid**:围栏渲染成 SVG,可在「图形 / 代码」间切换;支持全屏查看(滚轮缩放、拖拽、双击适应、Esc 关闭)、四套配色,以及下载 SVG / PNG。
|
|
11
11
|
- **长内容折叠**:代码块、表格、图表超过阈值自动折叠,底部出现「展开 / 收起」,长日志和长表格不会撑满聊天。
|
|
12
|
-
- **表格**:浅色 /
|
|
12
|
+
- **表格**:浅色 / 深色两套样式,表头吸顶,宽表支持表内横向滚动;每张表上方右侧有「CSV / Markdown」复制按钮。
|
|
13
13
|
- **图片放大**:只在旧宿主没有原生预览按钮时兜底,点击图片打开暗色预览,Esc 或点遮罩关闭;新版 DSH 的原生预览、头像、图标、代码块和链接里的图片都不接管。
|
|
14
14
|
- **设置面板**:右下角齿轮可调 Mermaid 配色、代码字号、图表默认视图和三类折叠阈值,阈值下方会注明按高度判断。设置存在 `localStorage`,界面文案跟随页面 `<html lang>` 切换中英文。
|
|
15
15
|
|
|
@@ -27,18 +27,18 @@ dsh plugin --profile desktop remove dsh-md-plus
|
|
|
27
27
|
```powershell
|
|
28
28
|
npm install # 顺带跑 prepare → build
|
|
29
29
|
npm run build # 产出 lib/ 下四个文件
|
|
30
|
-
npm run check # 语法检查 +
|
|
30
|
+
npm run check # 语法检查 + 73 条测试(先 build 再跑,check 不含 build)
|
|
31
31
|
npm run preview # 生成 preview.html(含真渲出来的 mermaid 图)
|
|
32
32
|
npm run shot # 用 headless Chrome 把 preview.html 截成 docs/preview.png
|
|
33
33
|
```
|
|
34
34
|
|
|
35
35
|
## 已知限制
|
|
36
36
|
|
|
37
|
-
- DSH 0.2.
|
|
37
|
+
- DSH 0.2.1-rc.4 的头部语言名由宿主决定:不认识的围栏只显示占位文案「代码块」。插件会从宿主的 React fiber 里兜底读取真实语言,读不到时才退回正文嗅探;宿主改 React 结构后这条兜底可能失效。
|
|
38
38
|
- `DSH_LANGS` 是 DSH 语言表的快照(108 条)。宿主加语言后这份快照会落后,落后只会多一次无效处理,不会出现双份高亮。
|
|
39
39
|
- mermaid 12 的新图种(`usecase-beta`、`agentflow-beta`)标识符只认字母数字下划线,中文得写进标签:`actor Customer("用户")` 可以,`actor 用户` 会解析失败。
|
|
40
40
|
- 高亮约 6.4 MB、mermaid 约 5.0 MB,按需下载,第一次用到时多花约 100ms 解析。
|
|
41
|
-
- 依赖宿主 `.md-code-block`、`[data-code-block-content]`、`[data-code-block-banner]`、`data-streaming`
|
|
41
|
+
- 依赖宿主 `.md-code-block`、`[data-code-block-content]`、`[data-code-block-banner]`、`data-streaming` 等钩子,以及 React fiber 里的 `lang`;DSH 改版后要同步调整 `src/client.js`。
|
|
42
42
|
|
|
43
43
|
目前只影响代码块、mermaid、表格、正文图片和显示设置,不改 Markdown 的解析结果。
|
|
44
44
|
|
package/lib/client.js
CHANGED
|
@@ -26,6 +26,7 @@ window.__ModuleLoader__.load({
|
|
|
26
26
|
var ZOOM_MIN_EPSILON = 1e-3;
|
|
27
27
|
var EXPAND_CLASS = "md-plus-expand";
|
|
28
28
|
var THEME_CLASS = "md-plus-theme";
|
|
29
|
+
var RETRY_CLASS = "md-plus-retry";
|
|
29
30
|
var THEME_KEY = "dsh-md-plus-mermaid-theme";
|
|
30
31
|
var THEME_ORDER = ["blue", "neutral", "forest", "contrast"];
|
|
31
32
|
var THEME_LABELS = {
|
|
@@ -56,6 +57,8 @@ window.__ModuleLoader__.load({
|
|
|
56
57
|
themePrefix: "\u914D\u8272\uFF1A",
|
|
57
58
|
foldOpen: "\u5C55\u5F00",
|
|
58
59
|
foldClose: "\u6536\u8D77",
|
|
60
|
+
retry: "\u91CD\u8BD5",
|
|
61
|
+
retryAria: "\u91CD\u65B0\u6E32\u67D3\u56FE\u8868",
|
|
59
62
|
renderFailed: "mermaid \u6E32\u67D3\u5931\u8D25\uFF1A",
|
|
60
63
|
diagram: "\u6D41\u7A0B\u56FE",
|
|
61
64
|
diagramAria: "\u6D41\u7A0B\u56FE\u5168\u5C4F\u67E5\u770B",
|
|
@@ -107,6 +110,8 @@ window.__ModuleLoader__.load({
|
|
|
107
110
|
themePrefix: "Theme: ",
|
|
108
111
|
foldOpen: "Expand",
|
|
109
112
|
foldClose: "Collapse",
|
|
113
|
+
retry: "Retry",
|
|
114
|
+
retryAria: "Retry diagram",
|
|
110
115
|
renderFailed: "Mermaid render failed: ",
|
|
111
116
|
diagram: "Diagram",
|
|
112
117
|
diagramAria: "Diagram fullscreen viewer",
|
|
@@ -207,8 +212,13 @@ window.__ModuleLoader__.load({
|
|
|
207
212
|
}
|
|
208
213
|
function applyCodeFontSize() {
|
|
209
214
|
var size = readSettings().codeFontSize;
|
|
210
|
-
if (size > 0)
|
|
211
|
-
|
|
215
|
+
if (size > 0) {
|
|
216
|
+
document.documentElement.style.setProperty("--md-plus-code-font-size", size + "px");
|
|
217
|
+
document.documentElement.style.setProperty("--md-plus-code-line-height", Math.round(size * 1.6) + "px");
|
|
218
|
+
} else {
|
|
219
|
+
document.documentElement.style.removeProperty("--md-plus-code-font-size");
|
|
220
|
+
document.documentElement.style.removeProperty("--md-plus-code-line-height");
|
|
221
|
+
}
|
|
212
222
|
}
|
|
213
223
|
var DSH_LANGS = /* @__PURE__ */ new Set([
|
|
214
224
|
"typescript",
|
|
@@ -321,7 +331,10 @@ window.__ModuleLoader__.load({
|
|
|
321
331
|
"gradle"
|
|
322
332
|
]);
|
|
323
333
|
var MMD_LANGS = /* @__PURE__ */ new Set(["mermaid", "mermaidjs", "mmd"]);
|
|
324
|
-
var
|
|
334
|
+
var MMD_FLOW = /^\s*(flowchart|graph)(?:\s+(?:TD|TB|BT|RL|LR))?\s*;?\s*$/i;
|
|
335
|
+
var MMD_PIE = /^\s*pie(?:\s+title\b.*)?\s*;?\s*$/i;
|
|
336
|
+
var MMD_GIT = /^\s*gitGraph(?:\s+(?:LR|TB|BT|RL))?:?\s*;?\s*$/i;
|
|
337
|
+
var MMD_SINGLE = /^\s*(sequenceDiagram|classDiagram|stateDiagram(?:-v2)?|erDiagram|journey|gantt|mindmap|timeline|quadrantChart|xychart-beta|sankey-beta|block-beta|packet-beta|architecture-beta|usecase-beta|agentflow-beta|C4Context|requirementDiagram|kanban|radar|treemap|venn|ishikawa|wardley|cynefin|treeView|zenuml)\s*;?\s*$/i;
|
|
325
338
|
function icon(paths) {
|
|
326
339
|
var svg = "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'>" + paths + "</svg>";
|
|
327
340
|
return 'url("data:image/svg+xml,' + encodeURIComponent(svg) + '")';
|
|
@@ -350,6 +363,9 @@ window.__ModuleLoader__.load({
|
|
|
350
363
|
var ICON_THEME = icon(
|
|
351
364
|
"<path d='M12 3s5 5.5 5 9a5 5 0 0 1-10 0c0-3.5 5-9 5-9z'/><path d='M9.5 12a2.5 2.5 0 0 0 5 0'/>"
|
|
352
365
|
);
|
|
366
|
+
var ICON_RETRY = icon(
|
|
367
|
+
"<path d='M20 11a8 8 0 1 0-2.34 5.66'/><path d='M20 4v7h-7'/>"
|
|
368
|
+
);
|
|
353
369
|
var ICON_GEAR = icon(
|
|
354
370
|
"<circle cx='12' cy='12' r='3'/><path d='M19.4 15a1.7 1.7 0 0 0 .34 1.87l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.7 1.7 0 0 0-1.87-.34 1.7 1.7 0 0 0-1 1.55V21a2 2 0 1 1-4 0v-.09a1.7 1.7 0 0 0-1.11-1.55 1.7 1.7 0 0 0-1.87.34l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06A1.7 1.7 0 0 0 4.6 15a1.7 1.7 0 0 0-1.55-1H3a2 2 0 1 1 0-4h.09a1.7 1.7 0 0 0 1.55-1.11 1.7 1.7 0 0 0-.34-1.87l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06A1.7 1.7 0 0 0 9 4.6a1.7 1.7 0 0 0 1-1.55V3a2 2 0 1 1 4 0v.09a1.7 1.7 0 0 0 1 1.55 1.7 1.7 0 0 0 1.87-.34l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06A1.7 1.7 0 0 0 19.4 9c.14.36.48.6.87.61H21a2 2 0 1 1 0 4h-.09a1.7 1.7 0 0 0-1.55 1z'/>"
|
|
355
371
|
);
|
|
@@ -358,7 +374,7 @@ window.__ModuleLoader__.load({
|
|
|
358
374
|
var TABLE_VARS_DARK = "--md-plus-tbl-line:#2f2f2f;--md-plus-tbl-head:#1f1f1f;--md-plus-tbl-head-fg:#f9fafb;--md-plus-tbl-hover:#1f1f1f";
|
|
359
375
|
var CSS = [
|
|
360
376
|
// ── 卡片:整块一个底色,顶栏不再是独立色带 ──────────────────────
|
|
361
|
-
".md-code-block{--md-plus-mmd-min-height:200px;--md-plus-icon:" + ICON_CODE + ";--md-plus-icon-copy:" + ICON_COPY + ";--md-plus-icon-nowrap:" + ICON_NOWRAP + ";--md-plus-icon-diagram:" + ICON_DIAGRAM + ";--md-plus-icon-zoom-in:" + ICON_ZOOM_IN + ";--md-plus-icon-zoom-out:" + ICON_ZOOM_OUT + ";--md-plus-icon-expand:" + ICON_EXPAND + ";--md-plus-icon-theme:" + ICON_THEME + "}",
|
|
377
|
+
".md-code-block{--md-plus-mmd-min-height:200px;--md-plus-icon:" + ICON_CODE + ";--md-plus-icon-copy:" + ICON_COPY + ";--md-plus-icon-nowrap:" + ICON_NOWRAP + ";--md-plus-icon-diagram:" + ICON_DIAGRAM + ";--md-plus-icon-zoom-in:" + ICON_ZOOM_IN + ";--md-plus-icon-zoom-out:" + ICON_ZOOM_OUT + ";--md-plus-icon-expand:" + ICON_EXPAND + ";--md-plus-icon-theme:" + ICON_THEME + ";--md-plus-icon-retry:" + ICON_RETRY + "}",
|
|
362
378
|
// bannerWrap 的原底色是 --dsw-alias-bg-base(#fff),会跟卡片灰拉开一条带
|
|
363
379
|
".md-code-block > div:has(> " + BANNER + "){background:transparent}",
|
|
364
380
|
// ── 头部:收紧,并把空着的左边填上 ─────────────────────────────
|
|
@@ -375,6 +391,9 @@ window.__ModuleLoader__.load({
|
|
|
375
391
|
// pre 的行高本身就在首行文字上方留了约半行空白;补 6px 后实测间距约 17px
|
|
376
392
|
// (原来给 0 时只有 11px,贴着看太挤)
|
|
377
393
|
".md-code-block pre{padding:6px 16px 16px;font-size:var(--md-plus-code-font-size,inherit)}",
|
|
394
|
+
".md-code-block pre{line-height:var(--md-plus-code-line-height,inherit)}",
|
|
395
|
+
// DSH 0.2.1 把内容容器设成 display:contents,折叠需要真实的盒子才能量高度和裁剪
|
|
396
|
+
".md-code-block > [data-code-block-content]{display:block}",
|
|
378
397
|
// ── 头部按钮:文字换成图标 ──────────────────────────────────────
|
|
379
398
|
".md-code-block " + BANNER + " button{display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px;padding:0;border:0;border-radius:6px;font-size:0;cursor:pointer;background:transparent;color:var(--dsw-alias-label-tertiary);transition:background-color .12s ease,color .12s ease}",
|
|
380
399
|
// font-size:0 只藏住「复制 / 已复制」的字面,可访问名仍在
|
|
@@ -393,6 +412,7 @@ window.__ModuleLoader__.load({
|
|
|
393
412
|
".md-code-block " + BANNER + " ." + ZOOM_OUT_CLASS + "::before{-webkit-mask:var(--md-plus-icon-zoom-out) center/contain no-repeat;mask:var(--md-plus-icon-zoom-out) center/contain no-repeat}",
|
|
394
413
|
".md-code-block " + BANNER + " ." + EXPAND_CLASS + "::before{-webkit-mask:var(--md-plus-icon-expand) center/contain no-repeat;mask:var(--md-plus-icon-expand) center/contain no-repeat}",
|
|
395
414
|
".md-code-block " + BANNER + " ." + THEME_CLASS + "::before{-webkit-mask:var(--md-plus-icon-theme) center/contain no-repeat;mask:var(--md-plus-icon-theme) center/contain no-repeat}",
|
|
415
|
+
".md-code-block " + BANNER + " ." + RETRY_CLASS + "::before{-webkit-mask:var(--md-plus-icon-retry) center/contain no-repeat;mask:var(--md-plus-icon-retry) center/contain no-repeat}",
|
|
396
416
|
"[" + MMD_ATTR + '="diagram"] .' + TOGGLE_CLASS + "{color:var(--dsw-alias-button-primary-fill,#4c6ef5);background:var(--dsw-alias-interactive-bg-active,rgb(76 110 245 / 12%))}",
|
|
397
417
|
// 已经到最小 / 最大时,对应那颗按钮变淡且不可点
|
|
398
418
|
"[" + ZOOM_ATTR + '="min"] .' + ZOOM_OUT_CLASS + ",[" + ZOOM_ATTR + '="max"] .' + ZOOM_IN_CLASS + "{opacity:.3;pointer-events:none}",
|
|
@@ -423,8 +443,9 @@ window.__ModuleLoader__.load({
|
|
|
423
443
|
"." + MODAL_CLASS + " svg{display:block}",
|
|
424
444
|
// ── 长内容折叠:代码块、表格、图表卡共用一套按钮 ───────────────
|
|
425
445
|
"." + FOLD_CLASS + "{position:relative}",
|
|
426
|
-
|
|
427
|
-
"." +
|
|
446
|
+
// 用 clip 而不是 hidden:hidden 会建立隐形滚动容器,鼠标在折叠内容上滚轮会被它吞掉。
|
|
447
|
+
"." + FOLD_CLASS + "[" + FOLD_ATTR + '="on"]{max-height:var(--md-plus-fold-max-height);overflow:clip}',
|
|
448
|
+
"." + FOLD_BTN_CLASS + "{display:block;white-space:nowrap;margin:8px auto 0;padding:4px 12px;border:1px solid var(--dsw-alias-border-secondary,rgb(127 127 127 / 22%));border-radius:999px;background:var(--dsw-alias-bg-base,#fff);color:var(--dsw-alias-label-primary);font:12px/18px var(--dsw-font-family-sans,system-ui,sans-serif);cursor:pointer;box-shadow:0 2px 8px rgb(0 0 0 / 12%);z-index:2}",
|
|
428
449
|
"." + FOLD_CLASS + "[" + FOLD_ATTR + '="on"] .' + FOLD_BTN_CLASS + "{position:absolute;left:50%;bottom:8px;transform:translateX(-50%);margin:0}",
|
|
429
450
|
// ── 图片点击放大 ────────────────────────────────────────────────
|
|
430
451
|
'[class*="_markdown_"] img{cursor:zoom-in}',
|
|
@@ -460,7 +481,10 @@ window.__ModuleLoader__.load({
|
|
|
460
481
|
// 抓手用结构选择器而不是 DSH 的哈希类名:外层是「唯一子元素是 table 的 div」。
|
|
461
482
|
// 前面挂 [class*="_markdown_"] 有两个作用——只认 markdown 渲染出来的表格,
|
|
462
483
|
// 同时把特异性顶到 (0,1,4),压过 DSH 自己的 .tableScroll th (0,1,1)。
|
|
463
|
-
|
|
484
|
+
// 不要加 overscroll-behavior-y:contain:宿主给表格的外层是 overflow-x:auto,
|
|
485
|
+
// 两轴滚动容器上加 contain 会让没有纵向滚动的短表也吞掉页面滚轮;宿主的
|
|
486
|
+
// overscroll-behavior-x:contain 同样要清掉,Chrome 下它也会连带吞掉纵向滚轮。
|
|
487
|
+
TABLE + "{position:relative;margin-block:16px;max-height:min(70vh,720px);overflow-y:auto;overscroll-behavior:auto;" + TABLE_VARS + "}",
|
|
464
488
|
"body[data-ds-dark-theme] " + TABLE + "{" + TABLE_VARS_DARK + "}",
|
|
465
489
|
// 整张表一个 1px 边框 + 小圆角。
|
|
466
490
|
// 注意必须是 separate:collapse 模式下 Chrome 会忽略单元格的圆角,
|
|
@@ -487,23 +511,24 @@ window.__ModuleLoader__.load({
|
|
|
487
511
|
// 长表往下滚时表头留在视口顶部;底色不透明才不会透出下面的行
|
|
488
512
|
TABLE + " > table thead th{position:sticky;top:0;z-index:1}",
|
|
489
513
|
// 复制按钮放在表尾右侧:不压住表头文字,表格折叠时也能随展开一起出现
|
|
490
|
-
TABLE + " > table > caption." + TABLE_TOOLS_CLASS + "{caption-side:top;text-align:right;
|
|
514
|
+
TABLE + " > table > caption." + TABLE_TOOLS_CLASS + "{caption-side:top;position:sticky;right:0;width:0;height:30px;margin-left:auto;padding:0;text-align:right;z-index:2}",
|
|
515
|
+
TABLE + " > table > caption." + TABLE_TOOLS_CLASS + " > span{position:absolute;right:0;top:0;display:flex;gap:0;white-space:nowrap}",
|
|
491
516
|
TABLE + " > table > caption." + TABLE_TOOLS_CLASS + " button{appearance:none;border:1px solid var(--md-plus-tbl-line);border-radius:5px;padding:2px 8px;margin-left:4px;background:transparent;color:var(--dsw-alias-label-secondary);font:11px/16px var(--dsw-font-family-sans,system-ui,sans-serif);cursor:pointer}",
|
|
492
517
|
TABLE + " > table > caption." + TABLE_TOOLS_CLASS + " button:hover{color:var(--dsw-alias-label-primary);background:var(--md-plus-tbl-hover)}",
|
|
493
518
|
// 宽表(≥4 列)不收着不行。宿主给这类表加了 .md-table-wide,并让它「出血」:
|
|
494
519
|
// 包裹层撑到面板宽,再用 padding-left 把表推到正文栏左侧。那个 padding 会吃掉
|
|
495
|
-
//
|
|
496
|
-
// 才出现——文字表落进这个区间就很难读。这里按回正文栏宽,超出改为表内横滚。
|
|
520
|
+
// 可用宽度,结果是表格比正文宽出一截、右边还被裁掉;这里按回正文栏宽,超出改为表内横滚。
|
|
497
521
|
// 特异性 (0,2,2),压得住宿主的 .Pg4CGa_body .md-table-wide (0,2,0)。
|
|
498
|
-
TABLE + ".md-table-wide{width:100%;max-width:100%;margin-inline:0;padding-inline:0;overflow-x:auto}",
|
|
522
|
+
TABLE + ".md-table-wide{width:100%;max-width:100%;margin-inline:0;padding-inline:0;padding-bottom:0;overflow-x:auto}",
|
|
499
523
|
// 塞得下就撑满正文栏,塞不下保持自然宽度让外面滚,不把列挤成一列一个字
|
|
500
524
|
TABLE + ".md-table-wide > table{width:100%;max-width:none;min-width:max-content}",
|
|
501
|
-
//
|
|
502
|
-
//
|
|
503
|
-
TABLE + ".
|
|
525
|
+
// 折叠态保留横向滚动,但纵向必须 clip;横向滚动容器只有在
|
|
526
|
+
// overscroll-behavior:auto 时才会把纵向滚轮交还给页面。
|
|
527
|
+
TABLE + "." + FOLD_CLASS + "[" + FOLD_ATTR + '="on"]{overflow-x:auto;overflow-y:clip}'
|
|
504
528
|
].join("\n");
|
|
505
529
|
var scripts = /* @__PURE__ */ new Map();
|
|
506
530
|
var pending = /* @__PURE__ */ new Set();
|
|
531
|
+
var foldSyncs = /* @__PURE__ */ new WeakMap();
|
|
507
532
|
var timer = null;
|
|
508
533
|
var rescanQueued = false;
|
|
509
534
|
var injected = /* @__PURE__ */ new Set();
|
|
@@ -524,30 +549,121 @@ window.__ModuleLoader__.load({
|
|
|
524
549
|
script.src = url;
|
|
525
550
|
script.async = true;
|
|
526
551
|
script.setAttribute(RUNTIME_ATTR, "1");
|
|
527
|
-
script.addEventListener(
|
|
528
|
-
|
|
552
|
+
script.addEventListener(
|
|
553
|
+
"load",
|
|
554
|
+
() => {
|
|
555
|
+
var api = window[globalName];
|
|
556
|
+
if (api === void 0) scripts.delete(url);
|
|
557
|
+
resolve(api ?? null);
|
|
558
|
+
},
|
|
559
|
+
{ once: true }
|
|
560
|
+
);
|
|
561
|
+
script.addEventListener(
|
|
562
|
+
"error",
|
|
563
|
+
() => {
|
|
564
|
+
scripts.delete(url);
|
|
565
|
+
script.remove();
|
|
566
|
+
resolve(null);
|
|
567
|
+
},
|
|
568
|
+
{ once: true }
|
|
569
|
+
);
|
|
529
570
|
document.head.appendChild(script);
|
|
530
571
|
});
|
|
531
572
|
scripts.set(url, promise);
|
|
532
573
|
return promise;
|
|
533
574
|
}
|
|
534
|
-
function
|
|
575
|
+
function readBannerLabel(block) {
|
|
535
576
|
var banner = block.querySelector(BANNER);
|
|
536
|
-
var info = banner?.firstElementChild;
|
|
577
|
+
var info = banner?.querySelector('[class*="_language_"]') ?? banner?.firstElementChild;
|
|
537
578
|
return (info?.textContent ?? "").trim().toLowerCase();
|
|
538
579
|
}
|
|
580
|
+
var PLACEHOLDER_LABELS = /* @__PURE__ */ new Set(["", "\u4EE3\u7801\u5757", "code block", "code", "plain text", "plaintext", "\u7EAF\u6587\u672C"]);
|
|
581
|
+
var FIBER_KEY = "__reactFiber$";
|
|
582
|
+
function isPlaceholderLabel(label) {
|
|
583
|
+
return PLACEHOLDER_LABELS.has(label);
|
|
584
|
+
}
|
|
585
|
+
function readFiberLang(block) {
|
|
586
|
+
var info = null;
|
|
587
|
+
var nodes = [block, block.querySelector(CONTENT)];
|
|
588
|
+
for (var node of nodes) {
|
|
589
|
+
if (node === null || node === void 0) continue;
|
|
590
|
+
var names;
|
|
591
|
+
try {
|
|
592
|
+
names = Object.getOwnPropertyNames(node);
|
|
593
|
+
} catch {
|
|
594
|
+
continue;
|
|
595
|
+
}
|
|
596
|
+
for (var name of names) {
|
|
597
|
+
if (name.lastIndexOf(FIBER_KEY, 0) !== 0) continue;
|
|
598
|
+
var fiber = node[name];
|
|
599
|
+
for (var depth = 0; fiber !== null && fiber !== void 0 && depth < 24; depth += 1) {
|
|
600
|
+
var props = fiber.memoizedProps;
|
|
601
|
+
if (props !== null && typeof props === "object" && Object.prototype.hasOwnProperty.call(props, "lang")) {
|
|
602
|
+
var value = typeof props.lang === "string" ? props.lang.trim().toLowerCase() : "";
|
|
603
|
+
info = { hasLang: value !== "", lang: value };
|
|
604
|
+
break;
|
|
605
|
+
}
|
|
606
|
+
fiber = fiber.return;
|
|
607
|
+
}
|
|
608
|
+
if (info !== null) break;
|
|
609
|
+
}
|
|
610
|
+
if (info !== null) break;
|
|
611
|
+
}
|
|
612
|
+
return info;
|
|
613
|
+
}
|
|
614
|
+
function readLang(block) {
|
|
615
|
+
var label = readBannerLabel(block);
|
|
616
|
+
if (!isPlaceholderLabel(label)) return label;
|
|
617
|
+
var info = readFiberLang(block);
|
|
618
|
+
return info === null ? "" : info.lang;
|
|
619
|
+
}
|
|
620
|
+
function paintLanguageLabel(block, lang) {
|
|
621
|
+
if (lang === "") return;
|
|
622
|
+
var banner = block.querySelector(BANNER);
|
|
623
|
+
var heading = banner?.firstElementChild;
|
|
624
|
+
if (heading === null || heading === void 0) return;
|
|
625
|
+
var target = banner.querySelector('[class*="_language_"]') ?? heading;
|
|
626
|
+
if ((target.textContent ?? "").trim().toLowerCase() === lang) return;
|
|
627
|
+
if (!target.hasAttribute("data-md-plus-original-label")) {
|
|
628
|
+
target.setAttribute("data-md-plus-original-label", target.textContent ?? "");
|
|
629
|
+
}
|
|
630
|
+
target.textContent = lang;
|
|
631
|
+
target.setAttribute("data-md-plus-lang", lang);
|
|
632
|
+
}
|
|
539
633
|
function sniffDiagramType(code) {
|
|
540
|
-
var
|
|
634
|
+
var lines = code.split("\n");
|
|
635
|
+
var start = 0;
|
|
636
|
+
while (start < lines.length) {
|
|
637
|
+
var line = lines[start].trim();
|
|
638
|
+
if (line === "" || line.startsWith("%%")) {
|
|
639
|
+
start += 1;
|
|
640
|
+
continue;
|
|
641
|
+
}
|
|
642
|
+
break;
|
|
643
|
+
}
|
|
644
|
+
var text = lines.slice(start).join("\n");
|
|
541
645
|
if (text.startsWith("---")) {
|
|
542
646
|
var blank = text.indexOf("\n");
|
|
543
647
|
var close = blank < 0 ? -1 : text.indexOf("\n---", blank);
|
|
544
648
|
text = close < 0 ? "" : text.slice(close + 4);
|
|
545
649
|
}
|
|
546
|
-
var
|
|
547
|
-
|
|
650
|
+
var first = text.split("\n").find((line2) => {
|
|
651
|
+
var value2 = line2.trim();
|
|
652
|
+
return value2 !== "" && !value2.startsWith("%%");
|
|
653
|
+
});
|
|
654
|
+
if (first === void 0) return null;
|
|
655
|
+
var value = first.trim();
|
|
656
|
+
var flow = MMD_FLOW.exec(value);
|
|
657
|
+
if (flow !== null) return flow[1];
|
|
658
|
+
if (MMD_PIE.test(value)) return "pie";
|
|
659
|
+
if (MMD_GIT.test(value)) return "gitGraph";
|
|
660
|
+
var single = MMD_SINGLE.exec(value);
|
|
661
|
+
return single === null ? null : single[1];
|
|
548
662
|
}
|
|
549
663
|
function diagramKind(block) {
|
|
550
|
-
|
|
664
|
+
var lang = readLang(block);
|
|
665
|
+
if (MMD_LANGS.has(lang)) return "diagram";
|
|
666
|
+
if (lang !== "") return null;
|
|
551
667
|
var pre = block.querySelector(CONTENT + " pre");
|
|
552
668
|
if (pre === null) return null;
|
|
553
669
|
return sniffDiagramType(pre.textContent ?? "") === null ? null : "diagram";
|
|
@@ -599,7 +715,8 @@ window.__ModuleLoader__.load({
|
|
|
599
715
|
}
|
|
600
716
|
}
|
|
601
717
|
function redrawDiagrams() {
|
|
602
|
-
for (const block of document.querySelectorAll("[" + MMD_ATTR +
|
|
718
|
+
for (const block of document.querySelectorAll("[" + MMD_ATTR + "]")) {
|
|
719
|
+
if (block.getAttribute(MMD_ATTR) === "failed") continue;
|
|
603
720
|
block.removeAttribute(KEY_ATTR);
|
|
604
721
|
pending.add(block);
|
|
605
722
|
}
|
|
@@ -646,6 +763,19 @@ window.__ModuleLoader__.load({
|
|
|
646
763
|
run: (block) => cycleMermaidTheme(block)
|
|
647
764
|
}
|
|
648
765
|
];
|
|
766
|
+
var FAILED_BUTTONS = [
|
|
767
|
+
{
|
|
768
|
+
cls: RETRY_CLASS,
|
|
769
|
+
titleKey: "retry",
|
|
770
|
+
ariaKey: "retryAria",
|
|
771
|
+
run: (block) => {
|
|
772
|
+
block.removeAttribute(KEY_ATTR);
|
|
773
|
+
block.removeAttribute(MMD_ATTR);
|
|
774
|
+
block.querySelector("." + MMD_CLASS + "-error")?.remove();
|
|
775
|
+
void enhance(block);
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
];
|
|
649
779
|
function findNativeWrap(buttons) {
|
|
650
780
|
if (buttons === void 0) return null;
|
|
651
781
|
for (const button of buttons) {
|
|
@@ -661,7 +791,10 @@ window.__ModuleLoader__.load({
|
|
|
661
791
|
var copy = nativeButtons === void 0 || nativeButtons.length === 0 ? null : nativeButtons[nativeButtons.length - 1];
|
|
662
792
|
var action = copy?.parentElement;
|
|
663
793
|
if (action === null || action === void 0) return;
|
|
664
|
-
var
|
|
794
|
+
var label = readBannerLabel(block);
|
|
795
|
+
var lang = readLang(block);
|
|
796
|
+
if (lang !== "" && isPlaceholderLabel(label)) paintLanguageLabel(block, lang);
|
|
797
|
+
var specs = block.getAttribute(MMD_ATTR) === "failed" ? FAILED_BUTTONS : diagramKind(block) !== null ? MMD_BUTTONS : findNativeWrap(nativeButtons) !== null ? [] : PLAIN_BUTTONS;
|
|
665
798
|
for (const existing of action.querySelectorAll("." + BTN_CLASS)) {
|
|
666
799
|
if (specs.some((spec) => existing.classList.contains(spec.cls))) continue;
|
|
667
800
|
existing.remove();
|
|
@@ -675,9 +808,9 @@ window.__ModuleLoader__.load({
|
|
|
675
808
|
created.title = t(spec.titleKey);
|
|
676
809
|
created.setAttribute("aria-label", t(spec.ariaKey));
|
|
677
810
|
if (spec.cls === THEME_CLASS) {
|
|
678
|
-
var
|
|
679
|
-
created.title =
|
|
680
|
-
created.setAttribute("aria-label",
|
|
811
|
+
var themeText = themeLabel(getMermaidTheme());
|
|
812
|
+
created.title = themeText;
|
|
813
|
+
created.setAttribute("aria-label", themeText);
|
|
681
814
|
}
|
|
682
815
|
created.addEventListener("click", () => spec.run(block));
|
|
683
816
|
action.insertBefore(created, copy);
|
|
@@ -702,11 +835,12 @@ window.__ModuleLoader__.load({
|
|
|
702
835
|
var pre = content.querySelector("pre");
|
|
703
836
|
if (pre === null || pre.classList.contains("shiki")) return;
|
|
704
837
|
var lang = readLang(block);
|
|
705
|
-
if (lang
|
|
838
|
+
if (lang !== "" && isPlaceholderLabel(readBannerLabel(block))) paintLanguageLabel(block, lang);
|
|
706
839
|
if (diagramKind(block) !== null) {
|
|
707
840
|
await renderDiagram(block, content, pre);
|
|
708
841
|
return;
|
|
709
842
|
}
|
|
843
|
+
if (lang === "") return;
|
|
710
844
|
if (DSH_LANGS.has(lang)) return;
|
|
711
845
|
var api = await loadScript(HL_URL, HL_GLOBAL);
|
|
712
846
|
if (api === null || !api.supports(lang)) return;
|
|
@@ -812,6 +946,7 @@ window.__ModuleLoader__.load({
|
|
|
812
946
|
zooms.delete(block);
|
|
813
947
|
paint(block);
|
|
814
948
|
scheduleFold(viewport, foldLimit("diagram"));
|
|
949
|
+
decorate(block);
|
|
815
950
|
}
|
|
816
951
|
var zooms = /* @__PURE__ */ new WeakMap();
|
|
817
952
|
function zoomState(block) {
|
|
@@ -862,11 +997,12 @@ window.__ModuleLoader__.load({
|
|
|
862
997
|
clampPan(block, state);
|
|
863
998
|
paint(block);
|
|
864
999
|
}
|
|
865
|
-
function bindViewport(block, viewport, resetView) {
|
|
1000
|
+
function bindViewport(block, viewport, resetView, alwaysZoom) {
|
|
866
1001
|
var drag = null;
|
|
867
1002
|
viewport.addEventListener(
|
|
868
1003
|
"wheel",
|
|
869
1004
|
(event) => {
|
|
1005
|
+
if (!alwaysZoom && !event.ctrlKey && !event.metaKey && zoomState(block).scale <= 1.001) return;
|
|
870
1006
|
event.preventDefault();
|
|
871
1007
|
zoomBy(block, event.deltaY < 0 ? ZOOM_STEP : 1 / ZOOM_STEP, event.clientX, event.clientY);
|
|
872
1008
|
},
|
|
@@ -914,6 +1050,12 @@ window.__ModuleLoader__.load({
|
|
|
914
1050
|
}
|
|
915
1051
|
function resetFold(target) {
|
|
916
1052
|
if (target === null) return;
|
|
1053
|
+
var sync = foldSyncs.get(target);
|
|
1054
|
+
if (sync !== void 0) {
|
|
1055
|
+
target.removeEventListener("scroll", sync);
|
|
1056
|
+
window.removeEventListener("resize", sync);
|
|
1057
|
+
foldSyncs.delete(target);
|
|
1058
|
+
}
|
|
917
1059
|
target.removeAttribute(FOLD_ATTR);
|
|
918
1060
|
target.classList.remove(FOLD_CLASS);
|
|
919
1061
|
target.style.removeProperty("--md-plus-fold-max-height");
|
|
@@ -946,13 +1088,23 @@ window.__ModuleLoader__.load({
|
|
|
946
1088
|
button.className = FOLD_BTN_CLASS;
|
|
947
1089
|
button.textContent = t("foldOpen");
|
|
948
1090
|
button.setAttribute("aria-expanded", "false");
|
|
1091
|
+
var sync = target.hasAttribute(TABLE_DONE_ATTR) ? () => {
|
|
1092
|
+
button.style.left = target.scrollLeft + target.clientWidth / 2 + "px";
|
|
1093
|
+
} : null;
|
|
1094
|
+
if (sync !== null) {
|
|
1095
|
+
foldSyncs.set(target, sync);
|
|
1096
|
+
target.addEventListener("scroll", sync, { passive: true });
|
|
1097
|
+
window.addEventListener("resize", sync);
|
|
1098
|
+
}
|
|
949
1099
|
button.addEventListener("click", () => {
|
|
950
1100
|
var folded = target.getAttribute(FOLD_ATTR) === "on";
|
|
951
1101
|
target.setAttribute(FOLD_ATTR, folded ? "off" : "on");
|
|
952
1102
|
button.textContent = folded ? t("foldClose") : t("foldOpen");
|
|
953
1103
|
button.setAttribute("aria-expanded", folded ? "true" : "false");
|
|
1104
|
+
sync?.();
|
|
954
1105
|
});
|
|
955
1106
|
target.appendChild(button);
|
|
1107
|
+
sync?.();
|
|
956
1108
|
});
|
|
957
1109
|
}
|
|
958
1110
|
function scanFolds() {
|
|
@@ -1022,6 +1174,8 @@ window.__ModuleLoader__.load({
|
|
|
1022
1174
|
table.setAttribute(TABLE_DONE_ATTR, "1");
|
|
1023
1175
|
var tools = document.createElement("caption");
|
|
1024
1176
|
tools.className = TABLE_TOOLS_CLASS;
|
|
1177
|
+
var group = document.createElement("span");
|
|
1178
|
+
group.className = TABLE_TOOLS_CLASS + "-group";
|
|
1025
1179
|
for (const [kind, label, titleKey, convert] of [
|
|
1026
1180
|
["csv", t("tableCsv"), "copyCsvTitle", tableToCsv],
|
|
1027
1181
|
["md", t("tableMd"), "copyMdTitle", tableToMarkdown]
|
|
@@ -1040,8 +1194,9 @@ window.__ModuleLoader__.load({
|
|
|
1040
1194
|
}
|
|
1041
1195
|
flashButton(button, ok ? t("copied") : t("copyFailed"));
|
|
1042
1196
|
});
|
|
1043
|
-
|
|
1197
|
+
group.appendChild(button);
|
|
1044
1198
|
}
|
|
1199
|
+
tools.appendChild(group);
|
|
1045
1200
|
dataTable.insertBefore(tools, dataTable.firstChild);
|
|
1046
1201
|
}
|
|
1047
1202
|
function openImage(source, alt) {
|
|
@@ -1214,21 +1369,26 @@ window.__ModuleLoader__.load({
|
|
|
1214
1369
|
closeSettings();
|
|
1215
1370
|
}
|
|
1216
1371
|
}
|
|
1217
|
-
function readNumber(input, fallback) {
|
|
1372
|
+
function readNumber(input, fallback, max) {
|
|
1373
|
+
var value = Number(input.value);
|
|
1374
|
+
return Number.isFinite(value) && value >= 0 ? Math.min(max ?? 4e3, Math.round(value)) : fallback;
|
|
1375
|
+
}
|
|
1376
|
+
function readFontSize(input) {
|
|
1218
1377
|
var value = Number(input.value);
|
|
1219
|
-
|
|
1378
|
+
if (!Number.isFinite(value) || value <= 0) return 0;
|
|
1379
|
+
return Math.min(20, Math.max(10, Math.round(value)));
|
|
1220
1380
|
}
|
|
1221
1381
|
resetButton.addEventListener("click", () => {
|
|
1222
1382
|
themeSelect.value = "blue";
|
|
1223
1383
|
fontInput.value = "";
|
|
1224
1384
|
viewSelect.value = DEFAULT_SETTINGS.diagramView;
|
|
1225
|
-
foldCode.value =
|
|
1226
|
-
foldTable.value =
|
|
1227
|
-
foldDiagram.value =
|
|
1385
|
+
foldCode.value = String(DEFAULT_SETTINGS.foldCode);
|
|
1386
|
+
foldTable.value = String(DEFAULT_SETTINGS.foldTable);
|
|
1387
|
+
foldDiagram.value = String(DEFAULT_SETTINGS.foldDiagram);
|
|
1228
1388
|
});
|
|
1229
1389
|
saveButton.addEventListener("click", () => {
|
|
1230
1390
|
saveSettings({
|
|
1231
|
-
codeFontSize:
|
|
1391
|
+
codeFontSize: readFontSize(fontInput),
|
|
1232
1392
|
diagramView: viewSelect.value === "code" ? "code" : "diagram",
|
|
1233
1393
|
foldCode: readNumber(foldCode, DEFAULT_SETTINGS.foldCode),
|
|
1234
1394
|
foldTable: readNumber(foldTable, DEFAULT_SETTINGS.foldTable),
|
|
@@ -1444,7 +1604,7 @@ window.__ModuleLoader__.load({
|
|
|
1444
1604
|
closeButton.addEventListener("click", closeViewer);
|
|
1445
1605
|
document.addEventListener("keydown", onKey, true);
|
|
1446
1606
|
zooms.set(overlay, { scale: 1, x: 0, y: 0, min: ZOOM_MIN_MODAL });
|
|
1447
|
-
bindViewport(overlay, viewport, reset);
|
|
1607
|
+
bindViewport(overlay, viewport, reset, true);
|
|
1448
1608
|
document.documentElement.style.overflow = "hidden";
|
|
1449
1609
|
document.body.appendChild(overlay);
|
|
1450
1610
|
closeButton.focus();
|
|
@@ -1460,6 +1620,7 @@ window.__ModuleLoader__.load({
|
|
|
1460
1620
|
content.appendChild(note);
|
|
1461
1621
|
block.setAttribute(KEY_ATTR, key);
|
|
1462
1622
|
block.setAttribute(MMD_ATTR, "failed");
|
|
1623
|
+
decorate(block);
|
|
1463
1624
|
console.warn("[dsh-md-plus] mermaid \u6E32\u67D3\u5931\u8D25", error);
|
|
1464
1625
|
}
|
|
1465
1626
|
function apply0(ctx) {
|
|
@@ -1484,10 +1645,17 @@ window.__ModuleLoader__.load({
|
|
|
1484
1645
|
document.removeEventListener("click", onDocumentClick, true);
|
|
1485
1646
|
for (const node of injected) node.remove();
|
|
1486
1647
|
injected.clear();
|
|
1648
|
+
for (const node of document.querySelectorAll("." + BTN_CLASS)) node.remove();
|
|
1649
|
+
for (const node of document.querySelectorAll("." + HOST_CLASS)) node.remove();
|
|
1650
|
+
for (const node of document.querySelectorAll("." + FOLD_BTN_CLASS)) node.remove();
|
|
1487
1651
|
for (const node of document.querySelectorAll("[" + FOLD_ATTR + "]")) resetFold(node);
|
|
1488
1652
|
for (const node of document.querySelectorAll("." + TABLE_TOOLS_CLASS)) node.remove();
|
|
1489
|
-
for (const
|
|
1490
|
-
|
|
1653
|
+
for (const attr of [DONE_ATTR, KEY_ATTR, WRAP_ATTR, MMD_ATTR, TABLE_DONE_ATTR, "data-md-plus-lang"]) {
|
|
1654
|
+
for (const node of document.querySelectorAll("[" + attr + "]")) node.removeAttribute(attr);
|
|
1655
|
+
}
|
|
1656
|
+
for (const node of document.querySelectorAll("[data-md-plus-original-label]")) {
|
|
1657
|
+
node.textContent = node.getAttribute("data-md-plus-original-label") ?? node.textContent;
|
|
1658
|
+
node.removeAttribute("data-md-plus-original-label");
|
|
1491
1659
|
}
|
|
1492
1660
|
for (const node of document.querySelectorAll(
|
|
1493
1661
|
"." + MMD_CLASS + ", ." + MMD_CLASS + "-error, ." + MODAL_CLASS + ", ." + IMG_MODAL_CLASS + ", ." + SETTINGS_BTN_CLASS + ", ." + SETTINGS_MODAL_CLASS
|
|
@@ -1496,6 +1664,7 @@ window.__ModuleLoader__.load({
|
|
|
1496
1664
|
}
|
|
1497
1665
|
document.documentElement.style.overflow = "";
|
|
1498
1666
|
document.documentElement.style.removeProperty("--md-plus-code-font-size");
|
|
1667
|
+
document.documentElement.style.removeProperty("--md-plus-code-line-height");
|
|
1499
1668
|
document.querySelector("style[" + STYLE_ATTR + "]")?.remove();
|
|
1500
1669
|
for (const script of document.querySelectorAll("script[" + RUNTIME_ATTR + "]")) {
|
|
1501
1670
|
script.remove();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-md-plus",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"description": "Markdown display enhancements for DeepSeek Harness Web: code block restyle, syntax highlighting for languages DSH does not ship, and built-in mermaid diagrams.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|