minecodex 2.0.50 → 2.0.52
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/features/composer-expand/src/injection-source.mjs +3 -3
- package/features/composer-expand/src/native.mjs +23 -1
- package/features/file-navigation/src/adapters/codex/modules.mjs +23 -2
- package/features/file-navigation/src/injection-source.mjs +3 -3
- package/features/images/src/adapters/codex/native-image-modules.mjs +11 -4
- package/features/images/src/adapters/codex/rspack-modules.mjs +148 -0
- package/features/images/src/library-prompt-source.mjs +3 -2
- package/features/markdown-reading/src/adapters/codex/links.mjs +10 -1
- package/features/markdown-reading/src/adapters/codex/rich-text.mjs +12 -0
- package/features/markdown-reading/src/injection-source.mjs +6 -4
- package/features/mermaid-diagrams/src/injection-source.mjs +4 -3
- package/features/model-slider/src/adapters/codex/controller.mjs +57 -2
- package/features/model-slider/src/frontend/install.mjs +49 -43
- package/features/quick-chat/src/frontend/entry.mjs +9 -5
- package/features/session-status/src/session-status.mjs +9 -3
- package/features/sites/src/adapters/codex/renderer.mjs +2 -2
- package/package.json +1 -1
- package/packages/cli/src/control-server.mjs +4 -5
- package/packages/cli/src/npm-adapter.mjs +4 -4
- package/packages/codex-adapter/src/markdown/block-actions.mjs +4 -1
- package/packages/codex-adapter/src/markdown/editor-api.mjs +26 -1
- package/packages/codex-adapter/src/markdown/rspack.mjs +75 -0
- package/packages/codex-adapter/src/markdown/toc-native.mjs +4 -1
- package/packages/codex-adapter/src/renderer/modules.mjs +61 -0
- package/packages/plugin/assets/app.js +2 -2
- package/packages/plugin/assets/prompts.js +1 -1
|
@@ -16,6 +16,11 @@ export function installModelSlider(signal, { feature, ui, createIcon, requestRef
|
|
|
16
16
|
const modelSelectorOriginalToggleLabels = new Map();
|
|
17
17
|
const modelSelectorGenericContainers = new Map();
|
|
18
18
|
const modelSelectorNativeToggleHandlers = new Map();
|
|
19
|
+
// 原生 CSS 模块类名:26.1029 起改用不带下划线的 Name-hash 形式。
|
|
20
|
+
function hasNativeClass(element, name) {
|
|
21
|
+
const tokens = String(element?.className ?? "").split(/\s+/);
|
|
22
|
+
return tokens.some((token) => token.startsWith(`_${name}_`) || token.startsWith(`${name}-`));
|
|
23
|
+
}
|
|
19
24
|
const modelSelectorPositionObservers = new Map();
|
|
20
25
|
const modelSelectorMenuSizeFrames = new Map();
|
|
21
26
|
const modelSelectorOpeningFrames = new Map();
|
|
@@ -63,15 +68,15 @@ export function installModelSlider(signal, { feature, ui, createIcon, requestRef
|
|
|
63
68
|
max-height: var(--codex-model-slider-menu-max-height) !important;
|
|
64
69
|
overflow-y: auto;
|
|
65
70
|
}
|
|
66
|
-
[data-codex-model-slider-trigger] [class*="
|
|
71
|
+
[data-codex-model-slider-trigger] [class*="ModelPickerTriggerModelLabel"] {
|
|
67
72
|
min-width: 0; max-width: 110px; flex-shrink: 1; overflow: hidden; text-overflow: ellipsis;
|
|
68
73
|
}
|
|
69
|
-
[data-codex-model-slider-trigger] [class*="
|
|
74
|
+
[data-codex-model-slider-trigger] [class*="ModelPickerTriggerModelText"] {
|
|
70
75
|
min-width: 0; max-width: 110px; overflow: hidden; text-overflow: ellipsis;
|
|
71
76
|
}
|
|
72
77
|
html[data-codex-model-slider-catalog-ready]
|
|
73
78
|
[data-codex-model-slider-trigger]
|
|
74
|
-
[class*="
|
|
79
|
+
[class*="ModelPickerTriggerModelText"]:not([data-codex-model-slider-trigger-label]):has(+ [data-codex-model-slider-trigger-label]) {
|
|
75
80
|
display: none !important;
|
|
76
81
|
}
|
|
77
82
|
[data-codex-model-slider-trigger-label] {
|
|
@@ -83,26 +88,26 @@ export function installModelSlider(signal, { feature, ui, createIcon, requestRef
|
|
|
83
88
|
[data-codex-model-slider-trigger]:not([data-codex-model-slider-trigger-placeholder]) [data-codex-model-slider-trigger-label] {
|
|
84
89
|
max-width: none; overflow: visible; text-overflow: clip; flex-shrink: 0;
|
|
85
90
|
}
|
|
86
|
-
[data-codex-model-slider-trigger]:not([data-codex-model-slider-trigger-placeholder]) [class*="
|
|
91
|
+
[data-codex-model-slider-trigger]:not([data-codex-model-slider-trigger-placeholder]) [class*="ModelPickerTriggerModelLabel"] {
|
|
87
92
|
max-width: none; overflow: visible; flex-shrink: 0;
|
|
88
93
|
}
|
|
89
|
-
[data-codex-model-slider-trigger]:not([data-codex-model-slider-trigger-placeholder]) [class*="
|
|
94
|
+
[data-codex-model-slider-trigger]:not([data-codex-model-slider-trigger-placeholder]) [class*="ModelPickerTriggerContent"] {
|
|
90
95
|
max-width: none !important;
|
|
91
96
|
}
|
|
92
|
-
[data-codex-model-slider-trigger][data-codex-model-slider-trigger-placeholder] [class*="
|
|
97
|
+
[data-codex-model-slider-trigger][data-codex-model-slider-trigger-placeholder] [class*="ModelPickerTriggerContent"] {
|
|
93
98
|
width: 160px; min-width: 160px !important; max-width: 160px;
|
|
94
99
|
}
|
|
95
100
|
/* 打开时先完成占位态,避免原生 crossfade 的宽度动画带动弹层。 */
|
|
96
|
-
[data-codex-model-slider-trigger][data-state="open"][data-codex-model-slider-trigger-placeholder] [class*="
|
|
101
|
+
[data-codex-model-slider-trigger][data-state="open"][data-codex-model-slider-trigger-placeholder] [class*="ModelPickerTriggerContent"] > span:has(> span > [class*="ModelPickerTriggerPlaceholder"]) {
|
|
97
102
|
width: 160px !important;
|
|
98
103
|
}
|
|
99
|
-
[data-codex-model-slider-trigger][data-state="open"][data-codex-model-slider-trigger-placeholder] span:has(> [class*="
|
|
104
|
+
[data-codex-model-slider-trigger][data-state="open"][data-codex-model-slider-trigger-placeholder] span:has(> [class*="ModelPickerTriggerPlaceholder"]) {
|
|
100
105
|
opacity: 1 !important;
|
|
101
106
|
}
|
|
102
|
-
[data-codex-model-slider-trigger][data-state="open"][data-codex-model-slider-trigger-placeholder] [class*="
|
|
107
|
+
[data-codex-model-slider-trigger][data-state="open"][data-codex-model-slider-trigger-placeholder] [class*="ModelPickerTriggerLabel"] {
|
|
103
108
|
visibility: hidden;
|
|
104
109
|
}
|
|
105
|
-
[data-codex-model-slider-trigger] [class*="
|
|
110
|
+
[data-codex-model-slider-trigger] [class*="ModelPickerTriggerEffortLabel"] {
|
|
106
111
|
display: inline-flex; align-items: center; align-self: center;
|
|
107
112
|
}
|
|
108
113
|
html[data-codex-model-slider-selecting-effort] [role="menu"][data-state="open"]:not(:has([data-reasoning-slider])) {
|
|
@@ -185,12 +190,13 @@ export function installModelSlider(signal, { feature, ui, createIcon, requestRef
|
|
|
185
190
|
}
|
|
186
191
|
|
|
187
192
|
function nativeCssModuleClass(tokenName, root = document) {
|
|
188
|
-
|
|
189
|
-
const
|
|
193
|
+
// 26.1029 起原生类名改为 Name-hash,旧版带下划线包裹。
|
|
194
|
+
const pattern = new RegExp(`^(?:_${tokenName}_|${tokenName}-)[A-Za-z0-9_-]+$`);
|
|
195
|
+
const live = Array.from(root.querySelectorAll(`[class*="_${tokenName}_"], [class*="${tokenName}-"]`))
|
|
190
196
|
.flatMap((element) => Array.from(element.classList))
|
|
191
197
|
.find((name) => pattern.test(name));
|
|
192
198
|
if (live) return live;
|
|
193
|
-
const selectorPattern = new RegExp(`\\.(_${tokenName}_[A-Za-z0-9_-]+)`);
|
|
199
|
+
const selectorPattern = new RegExp(`\\.((?:_${tokenName}_|${tokenName}-)[A-Za-z0-9_-]+)`);
|
|
194
200
|
const find = (rules) => {
|
|
195
201
|
for (const rule of rules ?? []) {
|
|
196
202
|
const match = String(rule.selectorText ?? "").match(selectorPattern);
|
|
@@ -296,9 +302,9 @@ export function installModelSlider(signal, { feature, ui, createIcon, requestRef
|
|
|
296
302
|
|
|
297
303
|
function captureNativeFastIcon() {
|
|
298
304
|
// 原生控件每次只渲染当前状态;状态切换后按控件本身更新缓存。
|
|
299
|
-
const nativeContent = Array.from(document.querySelectorAll('[class*="_FastModeToggleContent_"]'))
|
|
305
|
+
const nativeContent = Array.from(document.querySelectorAll(':is([class*="_FastModeToggleContent_"], [class*="FastModeToggleContent-"])'))
|
|
300
306
|
.find((content) => !content.closest("[data-codex-model-slider-generic]"));
|
|
301
|
-
const toggle = nativeContent?.closest('[class*="_FastModeToggle_"]');
|
|
307
|
+
const toggle = nativeContent?.closest(':is([class*="_FastModeToggle_"], [class*="FastModeToggle-"])');
|
|
302
308
|
const state = toggle?.getAttribute("data-fast-mode-enabled") === "true" ? "active" : "inactive";
|
|
303
309
|
const svg = nativeContent?.querySelector("svg");
|
|
304
310
|
const current = modelSelectorNativeFastIcons?.[state];
|
|
@@ -341,11 +347,11 @@ export function installModelSlider(signal, { feature, ui, createIcon, requestRef
|
|
|
341
347
|
// 直接读取已就绪的图标存储(启动时由 bundle/持久化填充,运行期由
|
|
342
348
|
// captureNativeFastIcon 升级为 DOM 克隆),避免再次触发捕获造成递归。
|
|
343
349
|
// 优先克隆当前面板的图标;切换瞬间使用缓存时,也沿用原生图标尺寸。
|
|
344
|
-
const nativeContents = Array.from(document.querySelectorAll('[class*="_FastModeToggleContent_"]'))
|
|
350
|
+
const nativeContents = Array.from(document.querySelectorAll(':is([class*="_FastModeToggleContent_"], [class*="FastModeToggleContent-"])'))
|
|
345
351
|
.filter((content) => !content.closest("[data-codex-model-slider-generic]"));
|
|
346
352
|
const nativeContent = nativeContents.find((content) => (
|
|
347
353
|
(content.getAttribute("data-fast-mode-enabled")
|
|
348
|
-
?? content.closest('[class*="_FastModeToggle_"]')?.getAttribute("data-fast-mode-enabled")) === String(active)
|
|
354
|
+
?? content.closest(':is([class*="_FastModeToggle_"], [class*="FastModeToggle-"])')?.getAttribute("data-fast-mode-enabled")) === String(active)
|
|
349
355
|
));
|
|
350
356
|
const nativeSvg = nativeContent?.querySelector("svg") ?? nativeContents[0]?.querySelector("svg");
|
|
351
357
|
const template = nativeContent?.querySelector("svg")
|
|
@@ -458,7 +464,7 @@ export function installModelSlider(signal, { feature, ui, createIcon, requestRef
|
|
|
458
464
|
|
|
459
465
|
function nativeModelValue(menu) {
|
|
460
466
|
const toggle = menu?.querySelector("[data-model-picker-view-toggle]");
|
|
461
|
-
const toggleModelLabel = toggle?.querySelector('[class*="_ViewToggleModelLabel_"]');
|
|
467
|
+
const toggleModelLabel = toggle?.querySelector(':is([class*="_ViewToggleModelLabel_"], [class*="ViewToggleModelLabel-"])');
|
|
462
468
|
const toggleValues = String(
|
|
463
469
|
toggle?.hasAttribute("data-model-picker-view-toggle")
|
|
464
470
|
? (toggleModelLabel?.textContent ?? toggle.innerText)
|
|
@@ -1113,7 +1119,7 @@ export function installModelSlider(signal, { feature, ui, createIcon, requestRef
|
|
|
1113
1119
|
if (!record) return false;
|
|
1114
1120
|
if (record.closing && !immediate) return true;
|
|
1115
1121
|
record.reveal?.cancel();
|
|
1116
|
-
const placeholder = record.trigger?.querySelector('[class*="
|
|
1122
|
+
const placeholder = record.trigger?.querySelector('[class*="ModelPickerTriggerPlaceholder"]');
|
|
1117
1123
|
const placeholderNode = placeholder && firstVisibleTextNode(placeholder);
|
|
1118
1124
|
if (placeholderNode && record.placeholderText != null) {
|
|
1119
1125
|
placeholderNode.nodeValue = record.placeholderText;
|
|
@@ -1297,7 +1303,7 @@ export function installModelSlider(signal, { feature, ui, createIcon, requestRef
|
|
|
1297
1303
|
renderEnhancedModelMenu(menu, selector);
|
|
1298
1304
|
|
|
1299
1305
|
const trigger = nativeComposerTrigger();
|
|
1300
|
-
const placeholder = trigger?.querySelector('[class*="
|
|
1306
|
+
const placeholder = trigger?.querySelector('[class*="ModelPickerTriggerPlaceholder"]');
|
|
1301
1307
|
const placeholderNode = placeholder && firstVisibleTextNode(placeholder);
|
|
1302
1308
|
const placeholderText = placeholderNode?.nodeValue ?? null;
|
|
1303
1309
|
// 保留产品行为:模型列表打开时 chip 显示 Select model。只能原地更新
|
|
@@ -1446,7 +1452,7 @@ export function installModelSlider(signal, { feature, ui, createIcon, requestRef
|
|
|
1446
1452
|
const edgeCorrection = correction * Math.max(0, edgeScale);
|
|
1447
1453
|
nativeRange.style.transform = `translateX(calc(${progress - 100}% + ${edgeCorrection}px))`;
|
|
1448
1454
|
nativeThumb.style.left = `calc(${progress}% + ${correction}px)`;
|
|
1449
|
-
const particleClip = rail.querySelector('[class*="_FastParticleClip_"]');
|
|
1455
|
+
const particleClip = rail.querySelector(':is([class*="_FastParticleClip_"], [class*="FastParticleClip-"])');
|
|
1450
1456
|
if (particleClip) particleClip.style.clipPath = `inset(0 calc(${100 - progress}% - ${edgeCorrection}px) 0 0)`;
|
|
1451
1457
|
}
|
|
1452
1458
|
rail.style.setProperty("--codex-model-slider-progress", `${progress}%`);
|
|
@@ -1462,7 +1468,7 @@ export function installModelSlider(signal, { feature, ui, createIcon, requestRef
|
|
|
1462
1468
|
rail?.setAttribute("data-max", value);
|
|
1463
1469
|
effortText?.setAttribute("data-maximum", value);
|
|
1464
1470
|
fastButton?.setAttribute("data-max-power-selection", value);
|
|
1465
|
-
const maxEffects = rail?.querySelector('[class*="_MaxEffects_"]');
|
|
1471
|
+
const maxEffects = rail?.querySelector(':is([class*="_MaxEffects_"], [class*="MaxEffects-"])');
|
|
1466
1472
|
if (maxEffects) {
|
|
1467
1473
|
maxEffects.style.opacity = maximum ? "1" : "0";
|
|
1468
1474
|
if (maximum) maxEffects.style.transform = "translateX(0)";
|
|
@@ -1493,9 +1499,9 @@ export function installModelSlider(signal, { feature, ui, createIcon, requestRef
|
|
|
1493
1499
|
}
|
|
1494
1500
|
|
|
1495
1501
|
function syncNativeFastParticles(rail, enabled, entering = false) {
|
|
1496
|
-
const track = Array.from(rail.children).find((element) =>
|
|
1502
|
+
const track = Array.from(rail.children).find((element) => hasNativeClass(element, "Track"));
|
|
1497
1503
|
if (!track) return;
|
|
1498
|
-
const staticParticles = rail.querySelector('[class*="_ParticleTransition_"]');
|
|
1504
|
+
const staticParticles = rail.querySelector(':is([class*="_ParticleTransition_"], [class*="ParticleTransition-"])');
|
|
1499
1505
|
if (staticParticles && !matchMedia("(prefers-reduced-motion: reduce)").matches) {
|
|
1500
1506
|
staticParticles.__codexStaticParticleFade?.cancel();
|
|
1501
1507
|
staticParticles.style.opacity = enabled ? "0" : "1";
|
|
@@ -1507,7 +1513,7 @@ export function installModelSlider(signal, { feature, ui, createIcon, requestRef
|
|
|
1507
1513
|
);
|
|
1508
1514
|
}
|
|
1509
1515
|
}
|
|
1510
|
-
track.querySelectorAll('[class*="_FastParticleClip_"]').forEach((element) => element.remove());
|
|
1516
|
+
track.querySelectorAll(':is([class*="_FastParticleClip_"], [class*="FastParticleClip-"])').forEach((element) => element.remove());
|
|
1511
1517
|
if (!enabled || matchMedia("(prefers-reduced-motion: reduce)").matches) return;
|
|
1512
1518
|
const clipClass = nativeCssModuleClass("FastParticleClip");
|
|
1513
1519
|
const particlesClass = nativeCssModuleClass("FastTrackParticles");
|
|
@@ -1540,7 +1546,7 @@ export function installModelSlider(signal, { feature, ui, createIcon, requestRef
|
|
|
1540
1546
|
return path;
|
|
1541
1547
|
}));
|
|
1542
1548
|
clip.append(particles);
|
|
1543
|
-
const tickRail = Array.from(track.children).find((element) =>
|
|
1549
|
+
const tickRail = Array.from(track.children).find((element) => hasNativeClass(element, "TickRail"));
|
|
1544
1550
|
track.insertBefore(clip, tickRail ?? null);
|
|
1545
1551
|
// 重建粒子层后按当前档位恢复裁剪,避免重开面板时覆盖整条滑轨。
|
|
1546
1552
|
setGenericSliderVisual(rail, valueNow, valueMax + 1);
|
|
@@ -1615,13 +1621,13 @@ export function installModelSlider(signal, { feature, ui, createIcon, requestRef
|
|
|
1615
1621
|
root.setAttribute("data-max", "false");
|
|
1616
1622
|
root.setAttribute("data-endpoint-labels-visible", "false");
|
|
1617
1623
|
const range = Array.from(root.querySelectorAll("span")).find((element) => (
|
|
1618
|
-
|
|
1624
|
+
hasNativeClass(element, "Range")
|
|
1619
1625
|
));
|
|
1620
1626
|
const thumbScale = Array.from(root.querySelectorAll("span")).find((element) => (
|
|
1621
|
-
|
|
1627
|
+
hasNativeClass(element, "ThumbScale")
|
|
1622
1628
|
));
|
|
1623
1629
|
const tickRail = Array.from(root.querySelectorAll("div")).find((element) => (
|
|
1624
|
-
|
|
1630
|
+
hasNativeClass(element, "TickRail")
|
|
1625
1631
|
));
|
|
1626
1632
|
const tickTemplate = tickRail?.querySelector("span");
|
|
1627
1633
|
if (!range || !thumbScale || !tickRail || !tickTemplate) return null;
|
|
@@ -1680,29 +1686,29 @@ export function installModelSlider(signal, { feature, ui, createIcon, requestRef
|
|
|
1680
1686
|
copyCanvas();
|
|
1681
1687
|
canvasTimer = setInterval(copyCanvas, 80);
|
|
1682
1688
|
}
|
|
1683
|
-
const sourceEffects = source.querySelector('[class*="_MaxEffects_"]');
|
|
1684
|
-
const cloneEffects = clone.querySelector('[class*="_MaxEffects_"]');
|
|
1689
|
+
const sourceEffects = source.querySelector(':is([class*="_MaxEffects_"], [class*="MaxEffects-"])');
|
|
1690
|
+
const cloneEffects = clone.querySelector(':is([class*="_MaxEffects_"], [class*="MaxEffects-"])');
|
|
1685
1691
|
if (!sourceEffects || !cloneEffects) return { disconnect };
|
|
1686
1692
|
const sync = () => {
|
|
1687
1693
|
if (!source.isConnected || !shell.isConnected) {
|
|
1688
1694
|
disconnect();
|
|
1689
1695
|
return;
|
|
1690
1696
|
}
|
|
1691
|
-
const sourceTransition = sourceEffects.querySelector('[class*="_ParticleTransition_"]');
|
|
1692
|
-
let cloneTransition = cloneEffects.querySelector('[class*="_ParticleTransition_"]');
|
|
1697
|
+
const sourceTransition = sourceEffects.querySelector(':is([class*="_ParticleTransition_"], [class*="ParticleTransition-"])');
|
|
1698
|
+
let cloneTransition = cloneEffects.querySelector(':is([class*="_ParticleTransition_"], [class*="ParticleTransition-"])');
|
|
1693
1699
|
if (!sourceTransition) {
|
|
1694
1700
|
if (clone.querySelector("[data-fast-mode]")?.getAttribute("data-fast-mode") !== "true") {
|
|
1695
1701
|
cloneTransition?.remove();
|
|
1696
1702
|
}
|
|
1697
1703
|
return;
|
|
1698
1704
|
}
|
|
1699
|
-
const sourceParticles = sourceTransition.querySelectorAll('[class*="_TrackParticle_"]');
|
|
1700
|
-
let cloneParticles = cloneTransition?.querySelectorAll('[class*="_TrackParticle_"]');
|
|
1705
|
+
const sourceParticles = sourceTransition.querySelectorAll(':is([class*="_TrackParticle_"], [class*="TrackParticle-"])');
|
|
1706
|
+
let cloneParticles = cloneTransition?.querySelectorAll(':is([class*="_TrackParticle_"], [class*="TrackParticle-"])');
|
|
1701
1707
|
if (!cloneTransition || sourceParticles.length !== cloneParticles.length) {
|
|
1702
1708
|
cloneTransition?.remove();
|
|
1703
1709
|
cloneTransition = sourceTransition.cloneNode(true);
|
|
1704
1710
|
cloneEffects.append(cloneTransition);
|
|
1705
|
-
cloneParticles = cloneTransition.querySelectorAll('[class*="_TrackParticle_"]');
|
|
1711
|
+
cloneParticles = cloneTransition.querySelectorAll(':is([class*="_TrackParticle_"], [class*="TrackParticle-"])');
|
|
1706
1712
|
}
|
|
1707
1713
|
cloneTransition.setAttribute("style", sourceTransition.getAttribute("style") ?? "");
|
|
1708
1714
|
sourceParticles.forEach((particle, index) => {
|
|
@@ -1862,7 +1868,7 @@ export function installModelSlider(signal, { feature, ui, createIcon, requestRef
|
|
|
1862
1868
|
viewControls.append(modelButton);
|
|
1863
1869
|
}
|
|
1864
1870
|
|
|
1865
|
-
const nativeReset = parentMenu.firstElementChild?.querySelector('[class*="_ResetToDefault_"]');
|
|
1871
|
+
const nativeReset = parentMenu.firstElementChild?.querySelector(':is([class*="_ResetToDefault_"], [class*="ResetToDefault-"])');
|
|
1866
1872
|
if (nativeReset) {
|
|
1867
1873
|
const reset = nativeReset.cloneNode(true);
|
|
1868
1874
|
reset.setAttribute("role", "button");
|
|
@@ -1870,7 +1876,7 @@ export function installModelSlider(signal, { feature, ui, createIcon, requestRef
|
|
|
1870
1876
|
reset.setAttribute("data-codex-model-slider-reset", "");
|
|
1871
1877
|
reset.removeAttribute("data-radix-collection-item");
|
|
1872
1878
|
reset.addEventListener("click", () => {
|
|
1873
|
-
const currentReset = parentMenu.firstElementChild?.querySelector('[class*="_ResetToDefault_"]');
|
|
1879
|
+
const currentReset = parentMenu.firstElementChild?.querySelector(':is([class*="_ResetToDefault_"], [class*="ResetToDefault-"])');
|
|
1874
1880
|
invokeNativeMenuItemSelect(currentReset);
|
|
1875
1881
|
queueEnsure();
|
|
1876
1882
|
});
|
|
@@ -2092,7 +2098,7 @@ export function installModelSlider(signal, { feature, ui, createIcon, requestRef
|
|
|
2092
2098
|
const existing = parentMenu.querySelector(":scope > [data-codex-model-slider-generic]");
|
|
2093
2099
|
const nativeTemplateReady = Boolean(
|
|
2094
2100
|
parentMenu.firstElementChild
|
|
2095
|
-
?.querySelector("[data-model-picker-power-slider] [class*='_TickRail_'] > span"),
|
|
2101
|
+
?.querySelector("[data-model-picker-power-slider] :is([class*='_TickRail_'], [class*='TickRail-']) > span"),
|
|
2096
2102
|
);
|
|
2097
2103
|
const templateWaitCount = Number(parentMenu.getAttribute("data-codex-model-slider-template-wait") ?? 0);
|
|
2098
2104
|
if (nativeModel?.slug.toLowerCase().startsWith("gpt-") && !nativeTemplateReady && templateWaitCount < 3) {
|
|
@@ -2212,8 +2218,8 @@ export function installModelSlider(signal, { feature, ui, createIcon, requestRef
|
|
|
2212
2218
|
if (trigger.querySelector("[data-codex-model-slider-trigger-label]")) return;
|
|
2213
2219
|
const raw = trigger.getAttribute("data-codex-model-slider-trigger-raw");
|
|
2214
2220
|
if (!raw) return;
|
|
2215
|
-
const anchor = trigger.querySelector('[class*="
|
|
2216
|
-
?? trigger.querySelector('[class*="
|
|
2221
|
+
const anchor = trigger.querySelector('[class*="ModelPickerTriggerLabel"]')
|
|
2222
|
+
?? trigger.querySelector('[class*="ModelPickerTriggerContent"]');
|
|
2217
2223
|
if (!anchor) return;
|
|
2218
2224
|
const displayLabel = document.createElement("span");
|
|
2219
2225
|
displayLabel.setAttribute("data-codex-model-slider-trigger-label", "");
|
|
@@ -2235,14 +2241,14 @@ export function installModelSlider(signal, { feature, ui, createIcon, requestRef
|
|
|
2235
2241
|
modelSelectorTriggerObservers.set(trigger, observer);
|
|
2236
2242
|
}
|
|
2237
2243
|
const openPlaceholder = trigger.getAttribute("data-state") === "open"
|
|
2238
|
-
&& trigger.querySelector('[class*="
|
|
2244
|
+
&& trigger.querySelector('[class*="ModelPickerTriggerPlaceholder"]');
|
|
2239
2245
|
if (openPlaceholder && modelSelectorControllerMenu?.trigger === trigger && !modelSelectorControllerMenu.closing) {
|
|
2240
2246
|
const textNode = firstVisibleTextNode(openPlaceholder);
|
|
2241
2247
|
const label = locale === "zh-CN" ? "选择模型" : "Select model";
|
|
2242
2248
|
if (textNode && textNode.nodeValue !== label) textNode.nodeValue = label;
|
|
2243
2249
|
}
|
|
2244
2250
|
const nativeLabels = Array.from(trigger.querySelectorAll(
|
|
2245
|
-
'[class*="
|
|
2251
|
+
'[class*="ModelPickerTriggerModelText"]:not([data-codex-model-slider-trigger-label])',
|
|
2246
2252
|
));
|
|
2247
2253
|
if (!nativeLabels.length) {
|
|
2248
2254
|
trigger.setAttribute("data-codex-model-slider-trigger", "");
|
|
@@ -10,9 +10,13 @@ style.textContent = `
|
|
|
10
10
|
[data-mcx-quick-chat-history]>svg,[data-mcx-quick-chat-close]>svg{width:16px;height:16px}
|
|
11
11
|
[data-mcx-quick-chat-close]{margin-inline-end:0}
|
|
12
12
|
[data-mcx-quick-chat-minimize]{border-radius:calc(infinity * 1px)}
|
|
13
|
-
/*
|
|
14
|
-
[data-mcx-quick-chat
|
|
15
|
-
|
|
13
|
+
/* footer 底部对齐;编辑器与按钮共用高度,避免文字中线偏高。 */
|
|
14
|
+
[data-mcx-quick-chat] [data-composer-input][data-composer-layout="single-line"]:has(>[data-composer-input-layout="single-line"]){--composer-editor-single-line-height:var(--spacing-token-button-composer,calc(var(--spacing,4px)*9));margin-block:0}
|
|
15
|
+
/* 保留原生横条总高度,移除不对称留白,让整组内容在 wrapper 内居中。 */
|
|
16
|
+
[data-mcx-quick-chat] [data-composer-rows="inline"][data-composer-layout="single-line"]:not([data-dictation-view]):has([data-composer-input-layout="single-line"]){height:auto;min-block-size:calc(var(--composer-editor-single-line-height,calc(var(--spacing,4px)*9)) + var(--padding-composer-single-line-footer-block,0px) + var(--spacing-composer-footer-bottom,0px));padding-block:0;margin-block:0;align-items:center}
|
|
17
|
+
@media (width>=40rem){
|
|
18
|
+
[data-mcx-quick-chat] [data-composer-rows="responsive"][data-composer-layout="single-line"]:not([data-dictation-view]):has([data-composer-input-layout="single-line"]){height:auto;min-block-size:calc(var(--composer-editor-single-line-height,calc(var(--spacing,4px)*9)) + var(--padding-composer-single-line-footer-block,0px) + var(--spacing-composer-footer-bottom,0px));padding-block:0;margin-block:0;align-items:center}
|
|
19
|
+
}
|
|
16
20
|
[data-mcx-quick-chat-project-rail]{display:none!important}
|
|
17
21
|
/* 隐藏唯一的项目栏时,一并收起原生 rail 的圆角留白与负 margin。 */
|
|
18
22
|
[data-composer-rail]:has(>[data-mcx-quick-chat-project-rail]):not(:has(>:not([data-mcx-quick-chat-project-rail]):not(:empty))){display:none!important}
|
|
@@ -25,7 +29,7 @@ function releaseBackground(instance) {
|
|
|
25
29
|
instance.background = null;
|
|
26
30
|
}
|
|
27
31
|
function releaseProjectRail(instance) { instance.projectRail?.removeAttribute('data-mcx-quick-chat-project-rail'); instance.projectRail = null; }
|
|
28
|
-
function remove(instance) { instance.surface?.removeAttribute('data-mcx-quick-chat
|
|
32
|
+
function remove(instance) { instance.surface?.removeAttribute('data-mcx-quick-chat'); releaseBackground(instance); releaseProjectRail(instance); instance.minimize?.removeAttribute('data-mcx-quick-chat-minimize'); instance.unsubscribe(); instance.button?.remove(); instance.tracker.clear(); instance.historyTracker.clear(); }
|
|
29
33
|
function sync() {
|
|
30
34
|
if (disposed) return;
|
|
31
35
|
shortcut.sync();
|
|
@@ -43,7 +47,7 @@ function sync() {
|
|
|
43
47
|
}
|
|
44
48
|
if (selected || instance.tracker.accepted(snapshot)) snapshot.expand();
|
|
45
49
|
instance.historyTracker.open(snapshot);
|
|
46
|
-
snapshot.surface.
|
|
50
|
+
snapshot.surface.setAttribute('data-mcx-quick-chat', '');
|
|
47
51
|
if (instance.projectRail !== snapshot.projectRail) {
|
|
48
52
|
releaseProjectRail(instance);
|
|
49
53
|
instance.projectRail = snapshot.projectRail;
|
|
@@ -269,6 +269,7 @@ collapse.innerHTML = '<svg aria-hidden="true" viewBox="0 0 24 24" fill="none" st
|
|
|
269
269
|
collapse.addEventListener("click", () => { setGlobalExpanded(false); trigger.focus(); hideTooltip(); }, { signal });
|
|
270
270
|
root.append(collapse);
|
|
271
271
|
let snapshot = null;
|
|
272
|
+
let logSnapshot = null;
|
|
272
273
|
// 统计刷新会重建浮窗,复用图标节点以保留 tooltip 的悬浮锚点。
|
|
273
274
|
const tpsInfo = document.createElement("button");
|
|
274
275
|
tpsInfo.type = "button";
|
|
@@ -499,7 +500,8 @@ function ensurePosition() {
|
|
|
499
500
|
activeThreadId = threadId;
|
|
500
501
|
nativeContext = emptyNativeContext();
|
|
501
502
|
// 会话建立后先展示占位,不让日志落盘速度决定状态栏是否出现。
|
|
502
|
-
|
|
503
|
+
logSnapshot = threadId ? { threadId } : null;
|
|
504
|
+
snapshot = logSnapshot;
|
|
503
505
|
closePanel();
|
|
504
506
|
render();
|
|
505
507
|
requestRefresh();
|
|
@@ -532,8 +534,12 @@ function ensurePosition() {
|
|
|
532
534
|
}
|
|
533
535
|
syncVisibility(composer);
|
|
534
536
|
}
|
|
537
|
+
// 原生上下文不可用时保留日志口径,避免环退化为占位。
|
|
538
|
+
function withNativeContext(current, native) {
|
|
539
|
+
return !current || native.contextPercent == null ? current : { ...current, ...native };
|
|
540
|
+
}
|
|
535
541
|
function render() {
|
|
536
|
-
|
|
542
|
+
snapshot = withNativeContext(logSnapshot, nativeContext);
|
|
537
543
|
syncVisibility(findComposer());
|
|
538
544
|
if (root.hidden) return;
|
|
539
545
|
trigger.querySelector("[data-context-progress]").setAttribute("stroke-dashoffset", String(100 - (snapshot.contextPercent ?? 0)));
|
|
@@ -587,7 +593,7 @@ const receiver = {
|
|
|
587
593
|
if (revision <= lastRevision) return;
|
|
588
594
|
lastRevision = revision;
|
|
589
595
|
}
|
|
590
|
-
|
|
596
|
+
logSnapshot = value;
|
|
591
597
|
render();
|
|
592
598
|
scheduleRefresh();
|
|
593
599
|
},
|
|
@@ -31,8 +31,8 @@ function pageInfo() {
|
|
|
31
31
|
if (!visible(content)) return null;
|
|
32
32
|
const native = nativeProps(list || content.querySelector("button") || content.querySelector("p") || content.lastElementChild?.lastElementChild, p => "viewMode" in p && "shared" in p);
|
|
33
33
|
const grid = native ? native.viewMode === "grid" : !!page.querySelector('button[aria-label="Grid view"][aria-pressed="true"],button[aria-label="网格视图"][aria-pressed="true"]');
|
|
34
|
-
const ownershipTabs=[...page.querySelectorAll('[role="tablist"]')].find(node=>!node.closest(`[${owned}]`)&&nativeProps(node,p=>p.tabs?.some(tab=>tab.key==="owned")&&p.tabs?.some(tab=>tab.key
|
|
35
|
-
const ownership=ownershipTabs&&nativeProps(ownershipTabs,p=>p.tabs?.some(tab=>tab.key==="owned")&&p.tabs?.some(tab=>tab.key
|
|
34
|
+
const ownershipTabs=[...page.querySelectorAll('[role="tablist"]')].find(node=>!node.closest(`[${owned}]`)&&nativeProps(node,p=>p.tabs?.some(tab=>tab.key==="owned")&&p.tabs?.some(tab=>["shared","pinned"].includes(tab.key))));
|
|
35
|
+
const ownership=ownershipTabs&&nativeProps(ownershipTabs,p=>p.tabs?.some(tab=>tab.key==="owned")&&p.tabs?.some(tab=>["shared","pinned"].includes(tab.key)));
|
|
36
36
|
const shared = ownership ? ownership.selectedKey === "shared" : native ? !!native.shared : [...page.querySelectorAll("button[aria-pressed=true]")].some(b => /Shared with you|与你共享|與你共用/.test(b.textContent));
|
|
37
37
|
const create = [...(plus ? page : page.firstElementChild).querySelectorAll("button")].find(b => visible(b) && (plus ? /^(Create Site|创建站点|创建新站点|建立網站)$/ : /^(New|新建|新增)$/).test(b.textContent.trim()) && !b.hasAttribute(owned));
|
|
38
38
|
codex.report("sites-page",true);
|
package/package.json
CHANGED
|
@@ -8,6 +8,7 @@ import { fileURLToPath } from "node:url";
|
|
|
8
8
|
import { BrowserExchangeStore } from "./browser-exchange.mjs";
|
|
9
9
|
import { FEATURE_IDS, readConfig, updateFeature } from "./config.mjs";
|
|
10
10
|
import { normalizeRuntimeReady } from "./runtime-manager.mjs";
|
|
11
|
+
import { createNpmAdapter } from "./npm-adapter.mjs";
|
|
11
12
|
|
|
12
13
|
import { createDataTransfer, MAX_TRANSFER_BYTES } from "./data-transfer/service.mjs";
|
|
13
14
|
|
|
@@ -327,11 +328,9 @@ export async function createControlServer({
|
|
|
327
328
|
return;
|
|
328
329
|
}
|
|
329
330
|
if (request.method === "GET" && url.pathname === "/api/update") {
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
});
|
|
333
|
-
if (!registryResponse.ok) throw Object.assign(new Error("Update check failed"), { statusCode: 502 });
|
|
334
|
-
const latest = String((await registryResponse.json()).version ?? "");
|
|
331
|
+
// 与 mcx update 共用 npm 配置,保留用户的 registry、代理和证书设置。
|
|
332
|
+
const latest = await createNpmAdapter().viewLatestVersion();
|
|
333
|
+
if (!latest) throw Object.assign(new Error("Update check failed"), { statusCode: 502 });
|
|
335
334
|
json(response, 200, {
|
|
336
335
|
current: packageMetadata.version,
|
|
337
336
|
latest,
|
|
@@ -7,17 +7,17 @@ import { promisify } from "node:util";
|
|
|
7
7
|
const defaultExecFile = promisify(execFileCallback);
|
|
8
8
|
|
|
9
9
|
export function createNpmAdapter({ execFile = defaultExecFile, tempRoot = os.tmpdir(), platform = process.platform } = {}) {
|
|
10
|
-
function runNpm(args) {
|
|
11
|
-
if (platform !== "win32") return execFile("npm", args);
|
|
10
|
+
function runNpm(args, options = {}) {
|
|
11
|
+
if (platform !== "win32") return execFile("npm", args, options);
|
|
12
12
|
// npm.cmd 需要命令解释器;字面量参数经编码传递,避免路径被当成脚本。
|
|
13
13
|
const quote = (value) => "'" + String(value).replaceAll("'", "''") + "'";
|
|
14
14
|
const script = "[Console]::OutputEncoding=[Text.Encoding]::UTF8; $ErrorActionPreference='Stop'; & npm.cmd "
|
|
15
15
|
+ args.map(quote).join(" ") + "; exit $LASTEXITCODE";
|
|
16
|
-
return execFile("powershell.exe", ["-NoProfile", "-NonInteractive", "-EncodedCommand", Buffer.from(script, "utf16le").toString("base64")]);
|
|
16
|
+
return execFile("powershell.exe", ["-NoProfile", "-NonInteractive", "-EncodedCommand", Buffer.from(script, "utf16le").toString("base64")], options);
|
|
17
17
|
}
|
|
18
18
|
return {
|
|
19
19
|
async viewLatestVersion() {
|
|
20
|
-
const { stdout } = await runNpm(["view", "minecodex", "version"]);
|
|
20
|
+
const { stdout } = await runNpm(["view", "minecodex", "version", "--fetch-retries=0", "--fetch-timeout=8000"], { timeout: 12_000 });
|
|
21
21
|
return stdout.trim();
|
|
22
22
|
},
|
|
23
23
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {loadRspackMarkdownTableActions} from './rspack.mjs';
|
|
2
|
+
import { findCodexModule, codexModuleRegistry } from '../renderer/modules.mjs';
|
|
2
3
|
import { loadNativeMarkdownRenderer } from './markdown-native.mjs';
|
|
3
4
|
|
|
4
5
|
export function markdownExportAlias(source, name) {
|
|
@@ -14,6 +15,8 @@ export function markdownExportAlias(source, name) {
|
|
|
14
15
|
|
|
15
16
|
// 从 Chat Markdown 的公开组件发现悬浮操作栏和控件,不绑定构建 hash。
|
|
16
17
|
export async function loadNativeMarkdownTableActions(native) {
|
|
18
|
+
const registry=await codexModuleRegistry();
|
|
19
|
+
if(registry)return loadRspackMarkdownTableActions(registry,native);
|
|
17
20
|
const url = await findCodexModule('app-initial');
|
|
18
21
|
if (!url) throw new Error('native-table-actions-module-unavailable');
|
|
19
22
|
const response = await fetch(url);
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { findCodexModule } from '../renderer/modules.mjs';
|
|
1
|
+
import { findCodexModule, codexModuleRegistry } from '../renderer/modules.mjs';
|
|
2
2
|
// 使用当前编辑器所属的原生 CodeMirror 实例,避免引入第二套编辑器依赖。
|
|
3
3
|
export async function loadMarkdownListAPI(view) {
|
|
4
|
+
const registry=await codexModuleRegistry();
|
|
5
|
+
if (registry) return loadRspackMarkdownListAPI(registry,view);
|
|
4
6
|
const urls=await findCodexModule('dist',{all:true});
|
|
5
7
|
for (const url of urls) {
|
|
6
8
|
const exports = Object.values(await import(url));
|
|
@@ -24,3 +26,26 @@ export async function loadMarkdownListAPI(view) {
|
|
|
24
26
|
}
|
|
25
27
|
throw new Error('native-markdown-list-api-unavailable');
|
|
26
28
|
}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
export function loadRspackMarkdownListAPI(registry,view) {
|
|
32
|
+
const values=[...new Set(registry.entries.flatMap(entry=>{
|
|
33
|
+
let exports;
|
|
34
|
+
try {exports=Object.values(registry.exports(entry));} catch {return [];}
|
|
35
|
+
return exports.includes(view.constructor)||exports.includes(view.state.constructor)?exports:[];
|
|
36
|
+
}))];
|
|
37
|
+
const requireRole=(predicate,role)=>{
|
|
38
|
+
const matches=values.filter(predicate);
|
|
39
|
+
if(matches.length!==1)throw new Error(`native-codemirror-${role}-unavailable`);
|
|
40
|
+
return matches[0];
|
|
41
|
+
};
|
|
42
|
+
return {
|
|
43
|
+
Decoration:requireRole(value=>value?.line&&value?.replace&&value?.mark,'decoration'),
|
|
44
|
+
ViewPlugin:requireRole(value=>value?.fromClass&&value?.define,'view-plugin'),
|
|
45
|
+
StateEffect:requireRole(value=>value?.appendConfig&&value?.reconfigure,'state-effect'),
|
|
46
|
+
Compartment:requireRole(value=>value?.prototype?.reconfigure&&value?.prototype?.of&&value?.prototype?.get,'compartment'),
|
|
47
|
+
WidgetType:requireRole(value=>value?.prototype?.eq&&value?.prototype?.ignoreEvent&&value?.prototype?.updateDOM,'widget'),
|
|
48
|
+
StateField:requireRole(value=>value?.define&&value?.prototype?.slot&&value?.prototype?.init&&value?.prototype?.create,'state-field'),
|
|
49
|
+
Prec:requireRole(value=>value?.highest&&value?.lowest&&value?.high,'precedence'),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// Markdown 共用原生角色;只沿已注册模块与原生 lazy 声明绑定依赖。
|
|
2
|
+
export async function loadRspackMarkdownToc(registry) {
|
|
3
|
+
if (!registry.entries.some(entry=>entry.source.includes('data-heading-preview'))) {
|
|
4
|
+
const page=registry.module(source=>source.includes(').PageEditorContent'),'Pages content loader');
|
|
5
|
+
await registry.lazy(page,'PageEditorContent');
|
|
6
|
+
}
|
|
7
|
+
const owner=registry.module(source=>source.includes('data-heading-preview')&&source.includes('page-table-of-contents'),'Pages table of contents');
|
|
8
|
+
const body=marker=>{
|
|
9
|
+
const at=owner.source.indexOf(marker),start=owner.source.lastIndexOf('function ',at);
|
|
10
|
+
const end=owner.source.indexOf('}function ',at);
|
|
11
|
+
if(at<0||start<0)throw new Error('native-page-toc-component-unavailable');
|
|
12
|
+
return owner.source.slice(start,end<0?owner.source.length:end+1);
|
|
13
|
+
};
|
|
14
|
+
const requireMatch=(source,pattern)=>{
|
|
15
|
+
const match=source.match(pattern);
|
|
16
|
+
if(!match)throw new Error('native-page-toc-contract-changed');
|
|
17
|
+
return match[1];
|
|
18
|
+
};
|
|
19
|
+
const rail=body('"data-floating-navigation-rail-list"'),list=body('"data-heading-preview"');
|
|
20
|
+
const React=registry.binding(owner,requireMatch(rail,/\(0,([\w$]+)\.useState\)/));
|
|
21
|
+
const roots=[...new Set(registry.entries.filter(entry=>/\.createRoot=/.test(entry.source)).map(entry=>registry.exports(entry)).filter(value=>typeof value.createRoot==='function'))];
|
|
22
|
+
if(roots.length!==1)throw new Error('native-markdown-react-root-unavailable');
|
|
23
|
+
const marker=requireMatch(rail,/\.jsx\)\(([\w$]+\.[\w$]+),\{hierarchyLevel:/);
|
|
24
|
+
const layout=registry.binding(owner,marker.split('.')[0]);
|
|
25
|
+
const panels=Object.values(layout).filter(value=>typeof value==='function'&®istry.sourceOf(value).includes('shadow-xl-spread'));
|
|
26
|
+
if(panels.length!==1)throw new Error('native-page-toc-panel-unavailable');
|
|
27
|
+
const tooltip=requireMatch(owner.source,/\.jsx\)\(([\w$]+\.[\w$]+),\{align:"center",delayOpen:!0,interactive:!0,side:"right",sideOffset:0,skipDelayKey:"page-table-of-contents"/);
|
|
28
|
+
const indent=requireMatch(list,/"block",([\w$]+)\[e\.level\]/);
|
|
29
|
+
const array=requireMatch(owner.source,new RegExp(`(?:^|[^\\w$])${indent}=(\\[[^\\]]+\\])`));
|
|
30
|
+
if(!/^\[(?:void 0|"ms-\d+"|,)+\]$/.test(array))throw new Error('native-page-toc-indent-unavailable');
|
|
31
|
+
return {React,ReactDOM:roots[0],Marker:registry.binding(owner,marker),Panel:panels[0],Tooltip:registry.binding(owner,tooltip),
|
|
32
|
+
classes:{
|
|
33
|
+
rail:requireMatch(rail,/ref:[\w$]+,className:"([^"]+)","data-floating-navigation-rail-list"/),
|
|
34
|
+
railButton:requireMatch(rail,/className:"([^"]+)","aria-current"/),
|
|
35
|
+
menu:requireMatch(list,/ref:[\w$]+,className:"([^"]+)",variant:"viewer"/),
|
|
36
|
+
menuButton:requireMatch(list,/className:\(0,[\w$]+\.[\w$]+\)\("([^"]+)"/),
|
|
37
|
+
nav:requireMatch(body('skipDelayKey:"page-table-of-contents"'),/\.jsx\)\("nav",\{"aria-label":[\w$]+,className:"([^"]+)"/),
|
|
38
|
+
},indentation:array.slice(1,-1).split(',').map(value=>value==='void 0'?'':value.slice(1,-1))};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function loadRspackMarkdownRenderer(registry) {
|
|
42
|
+
const owner=registry.module((source,entry)=>/\{getDefaultComponents:[\w$]+,\.\.\./.test(source)&&Object.values(registry.exports(entry)).some(value=>typeof value==='function'&&/\{getDefaultComponents:[\w$]+,\.\.\./.test(registry.sourceOf(value))),'Markdown component');
|
|
43
|
+
const Markdown=registry.value(owner,(value,source)=>typeof value==='function'&&source.includes('getDefaultComponents:'),'Markdown renderer');
|
|
44
|
+
const parser=registry.module(source=>/tokens:\(0,[\w$]+\.[\w$]+\)\([\w$]+,void 0\)/.test(source),'Markdown token parser');
|
|
45
|
+
const ref=parser.source.match(/tokens:\(0,([\w$]+\.[\w$]+)\)\([\w$]+,void 0\)/)[1];
|
|
46
|
+
const lexer=registry.binding(parser,ref);
|
|
47
|
+
if(typeof lexer!=='function')throw new Error('native-markdown-lexer-unavailable');
|
|
48
|
+
return {Markdown,lexer};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function loadRspackMarkdownTableActions(registry,native) {
|
|
52
|
+
const owner=registry.module(source=>source.includes('id:"markdown.expandTable"'),'Markdown table controls');
|
|
53
|
+
const bind=pattern=>{
|
|
54
|
+
const ref=owner.source.match(pattern)?.[1];
|
|
55
|
+
if(!ref)throw new Error('native-table-actions-contract-changed');
|
|
56
|
+
return registry.binding(owner,ref);
|
|
57
|
+
};
|
|
58
|
+
const actions=registry.module(source=>source.includes('"data-block-actions":!0'),'block action bar');
|
|
59
|
+
const Actions=registry.value(actions,(value,source)=>typeof value==='function'&&source.includes('data-block-actions'),'block action bar');
|
|
60
|
+
const code=registry.module((source,entry)=>source.includes('id:"codeSnippet.wrap.disable"')&&Object.values(registry.exports(entry)).some(value=>typeof value==='function'&®istry.sourceOf(value).includes('id:"codeSnippet.wrap.disable"')),'code wrap controls');
|
|
61
|
+
const pair=code.source.match(/\?\(0,[\w$]+\.jsx\)\(([\w$]+\.[\w$]+),\{\}\):\(0,[\w$]+\.jsx\)\(([\w$]+\.[\w$]+),\{\}\)/);
|
|
62
|
+
if(!pair)throw new Error('native-code-wrap-icons-unavailable');
|
|
63
|
+
const icon=owner.source.match(/children:\(0,[\w$]+\.jsx\)\(([\w$]+\.[\w$]+),\{icon:\{16:([\w$]+\.[\w$]+),20:([\w$]+\.[\w$]+)\}\}\)/);
|
|
64
|
+
if(!icon)throw new Error('native-table-expand-icon-unavailable');
|
|
65
|
+
const [Icon,small,medium]=icon.slice(1).map(ref=>registry.binding(owner,ref));
|
|
66
|
+
return {...native,...loadRspackMarkdownRenderer(registry),rspack:registry,Actions,
|
|
67
|
+
Button:bind(/\.jsx\)\(([\w$]+\.[\w$]+),\{"aria-label":[\w$]+,"aria-expanded"/),
|
|
68
|
+
CopyButton:bind(/\.jsx\)\(([\w$]+\.[\w$]+),\{ariaLabel:[\w$]+,buttonText:/),
|
|
69
|
+
TablePreview:bind(/\.jsx\)\(([\w$]+\.[\w$]+),\{src:"",alt:/),
|
|
70
|
+
Table:bind(/\.jsx\)\(([\w$]+\.[\w$]+),\{className:[\w$]+,children:[\w$]+\}/),
|
|
71
|
+
tableClasses:bind(/([\w$]+\.[\w$]+)\.MarkdownTablePreview/),
|
|
72
|
+
ExpandIcon:()=>native.React.createElement(Icon,{icon:{16:small,20:medium}}),
|
|
73
|
+
wrapIcons:{disable:registry.binding(code,pair[1]),enable:registry.binding(code,pair[2])},
|
|
74
|
+
};
|
|
75
|
+
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {loadRspackMarkdownToc} from './rspack.mjs';
|
|
2
|
+
import { findCodexModule, codexModuleStyles, codexModuleRegistry } from '../renderer/modules.mjs';
|
|
2
3
|
// 直接导入原生 Marker、目录浮层和 Tooltip;仅按源码调用关系发现公开角色。
|
|
3
4
|
export async function loadNativeMarkdownToc() {
|
|
5
|
+
const registry=await codexModuleRegistry();
|
|
6
|
+
if(registry)return loadRspackMarkdownToc(registry);
|
|
4
7
|
const urls = [...document.querySelectorAll('link[rel="modulepreload"],script[src]')].map(
|
|
5
8
|
(n) => n.href || n.src,
|
|
6
9
|
);
|