dsh-codinput 0.3.6 → 0.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/lib/client.js +159 -40
- package/package.json +2 -1
- package/src/client/components/AttachmentRail.tsx +3 -3
- package/src/client/components/StatsRow.tsx +17 -17
- package/src/client/components/UserMessageMarkdown.tsx +591 -0
- package/src/client/i18n.ts +16 -0
- package/src/client/index.tsx +41 -0
- package/src/client/prefs.ts +3 -0
- package/src/client/settings.tsx +7 -0
- package/src/client/styles.ts +118 -0
package/src/client/prefs.ts
CHANGED
|
@@ -17,6 +17,8 @@ export type CodinputMode = 'normal' | 'float' | 'side';
|
|
|
17
17
|
export interface CodinputPrefs {
|
|
18
18
|
/** 启用接管:关闭即恢复官方输入框(卸载遮蔽条目)。 */
|
|
19
19
|
enabled: boolean;
|
|
20
|
+
/** 用户消息 Markdown 渲染(键控座 conversation.chat.node 的 user/steering 遮蔽)。 */
|
|
21
|
+
userMarkdown: boolean;
|
|
20
22
|
/** 显示行号(当前行与行号高亮常开)。 */
|
|
21
23
|
lineNumbers: boolean;
|
|
22
24
|
/** 编辑器字体(默认 JetBrains Mono)。 */
|
|
@@ -43,6 +45,7 @@ export interface CodinputPrefs {
|
|
|
43
45
|
|
|
44
46
|
export const DEFAULT_PREFS: CodinputPrefs = {
|
|
45
47
|
enabled: true,
|
|
48
|
+
userMarkdown: true,
|
|
46
49
|
lineNumbers: true,
|
|
47
50
|
fontFamily: "'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace",
|
|
48
51
|
sendHotkey: 'mod+enter',
|
package/src/client/settings.tsx
CHANGED
|
@@ -176,6 +176,13 @@ export function CodinputSettingsSection(): JSX.Element {
|
|
|
176
176
|
<Row title={t("set.enabled")} desc={t("set.enabledDesc")}>
|
|
177
177
|
<Switch on={prefs.enabled} label={t("set.enabled")} onToggle={() => update({ enabled: !prefs.enabled })} />
|
|
178
178
|
</Row>
|
|
179
|
+
<Row title={t("set.userMarkdown")} desc={t("set.userMarkdownDesc")}>
|
|
180
|
+
<Switch
|
|
181
|
+
on={prefs.userMarkdown}
|
|
182
|
+
label={t("set.userMarkdown")}
|
|
183
|
+
onToggle={() => update({ userMarkdown: !prefs.userMarkdown })}
|
|
184
|
+
/>
|
|
185
|
+
</Row>
|
|
179
186
|
<Row title={t("set.lineNumbers")} desc={t("set.lineNumbersDesc")}>
|
|
180
187
|
<Switch on={prefs.lineNumbers} label={t("set.lineNumbers")} onToggle={() => update({ lineNumbers: !prefs.lineNumbers })} />
|
|
181
188
|
</Row>
|
package/src/client/styles.ts
CHANGED
|
@@ -537,6 +537,124 @@ button.dci-attach-body { color: inherit; font: inherit; text-align: left; backgr
|
|
|
537
537
|
.dci-btn-primary:hover:not(:disabled) { background: var(--dsw-alias-button-primary-hover, currentColor); }
|
|
538
538
|
.dci-btn-cancel { min-width: 72px; }
|
|
539
539
|
.dci-btn-confirm { min-width: 136px; }
|
|
540
|
+
|
|
541
|
+
/* ===== 用户消息 Markdown(chat.node 键控座遮蔽条目)=====
|
|
542
|
+
气泡/操作行/附件行取值逐条移植官方 MessageItem.module.css 与
|
|
543
|
+
MessageIconActions.module.css;Markdown 排版逐条移植官方
|
|
544
|
+
MarkdownText.module.css;引用 chip 逐条移植官方 user-text.module.css。
|
|
545
|
+
官方走 --dsw-* token 的取值这里同样走 token(换肤全盘跟随)。 */
|
|
546
|
+
.dci-umsg-row { flex-direction: column; align-items: flex-end; gap: 6px; display: flex; }
|
|
547
|
+
.dci-umsg-stack { min-width: 0; max-width: min(calc(var(--dsh-chat-content-width, 748px) * 0.702), 82%);
|
|
548
|
+
flex-direction: column; align-items: flex-end; gap: 8px; display: flex; }
|
|
549
|
+
.dci-umsg-bubble { background: var(--dsw-specific-bubble); border-radius: var(--dsw-radius-xl); max-width: 100%;
|
|
550
|
+
font-size: var(--dsh-content-font-size, 14px); line-height: calc(22px + var(--dsh-content-font-delta, 0px));
|
|
551
|
+
color: var(--dsw-alias-label-primary); white-space: pre-wrap; word-break: break-word; padding: 10px 16px; }
|
|
552
|
+
.dci-umsg-refsum { color: var(--dsw-alias-label-tertiary);
|
|
553
|
+
font-size: var(--dsh-content-font-size-secondary, 13px); line-height: calc(18px + var(--dsh-content-font-delta-secondary, 0px)); }
|
|
554
|
+
.dci-umsg-attrow { flex-wrap: wrap; justify-content: flex-end; gap: 8px; max-width: 100%; display: flex; }
|
|
555
|
+
.dci-umsg-file { border: 0.5px solid var(--dsw-alias-border-l2, #0000001f); border-radius: var(--dsw-radius-xl);
|
|
556
|
+
background: var(--dsw-specific-input-major, transparent); box-sizing: border-box; flex: 0 0 240px;
|
|
557
|
+
align-items: center; gap: 10px; width: 240px; min-height: 64px; padding: 8px 12px; display: inline-flex; }
|
|
558
|
+
.dci-umsg-fileglyph { flex: none; width: 28px; height: 28px; }
|
|
559
|
+
.dci-umsg-filecontent { flex-direction: column; flex: 1; min-width: 0; display: flex; }
|
|
560
|
+
.dci-umsg-filename { white-space: nowrap; text-overflow: ellipsis; color: var(--dsw-alias-label-primary);
|
|
561
|
+
font-size: 14px; font-weight: 500; line-height: 22px; overflow: hidden; }
|
|
562
|
+
.dci-umsg-filemeta { white-space: nowrap; text-overflow: ellipsis; color: var(--dsw-alias-label-tertiary, #00000073);
|
|
563
|
+
font-size: 12px; line-height: 15px; overflow: hidden; }
|
|
564
|
+
.dci-umsg-actions { height: calc(28px + var(--dsh-content-font-delta, 0px)); align-items: center; gap: 8px; display: flex; }
|
|
565
|
+
.dci-umsg-time { font-size: var(--dsh-content-font-size-secondary, 13px);
|
|
566
|
+
line-height: calc(24px + var(--dsh-content-font-delta, 0px)); color: var(--dsw-alias-label-tertiary); white-space: nowrap; padding-right: 12px; }
|
|
567
|
+
.dci-umsg-action { width: calc(28px + var(--dsh-content-font-delta, 0px)); height: calc(28px + var(--dsh-content-font-delta, 0px));
|
|
568
|
+
border-radius: var(--dsw-radius-sm); color: var(--dsw-alias-label-tertiary); cursor: pointer; background: 0 0;
|
|
569
|
+
border: none; justify-content: center; align-items: center; padding: 6px; display: inline-flex; }
|
|
570
|
+
.dci-umsg-action svg { width: calc(15px + var(--dsh-content-font-delta, 0px)); height: calc(15px + var(--dsh-content-font-delta, 0px)); }
|
|
571
|
+
.dci-umsg-action:hover { background: var(--dsw-alias-interactive-bg-hover); color: var(--dsw-alias-label-secondary); }
|
|
572
|
+
/* 悬停显形(官方同款 data 属性面:chat 根的 data-actions-reveal 与 flowItem 的
|
|
573
|
+
data-chat-flow-kind 都在宿主 DOM 上,这里只换目标类)。 */
|
|
574
|
+
@media (hover: hover) {
|
|
575
|
+
[data-actions-reveal="hover"] .dci-umsg-actions,
|
|
576
|
+
:is([data-chat-flow-kind="user"], [data-chat-flow-kind="steering"]):has(~ :is([data-chat-flow-kind="user"], [data-chat-flow-kind="steering"])) .dci-umsg-actions { opacity: 0; transition: opacity 80ms; }
|
|
577
|
+
[data-actions-reveal="hover"]:hover .dci-umsg-actions,
|
|
578
|
+
[data-actions-reveal="hover"]:focus-within .dci-umsg-actions,
|
|
579
|
+
:is([data-chat-flow-kind="user"], [data-chat-flow-kind="steering"]):hover .dci-umsg-actions,
|
|
580
|
+
:is([data-chat-flow-kind="user"], [data-chat-flow-kind="steering"]):focus-within .dci-umsg-actions { opacity: 1; }
|
|
581
|
+
}
|
|
582
|
+
.dci-umsg-extra { margin: 8px 0 0; padding: 8px; border: 0.5px solid var(--dsw-alias-border-l2);
|
|
583
|
+
border-radius: var(--dsw-radius-sm); font-family: var(--ds-font-family-code); font-size: 12px; line-height: 18px;
|
|
584
|
+
overflow: auto; max-height: 200px; white-space: pre; }
|
|
585
|
+
|
|
586
|
+
/* Markdown 排版(官方 MarkdownText.module.css 逐条移植,.markdown → 本根)。 */
|
|
587
|
+
.dci-umsg-md { min-width: 0; overflow-wrap: anywhere; font: var(--dsw-font-markdown-base);
|
|
588
|
+
color: var(--dsw-alias-label-primary); white-space: normal; }
|
|
589
|
+
.dci-umsg-md strong { font-weight: 600; }
|
|
590
|
+
.dci-umsg-md h1 { font: var(--dsw-font-markdown-h1); margin: 32px 0 16px; }
|
|
591
|
+
.dci-umsg-md h2 { font: var(--dsw-font-markdown-h2); margin: 32px 0 16px; }
|
|
592
|
+
.dci-umsg-md h3 { font: var(--dsw-font-markdown-h3); margin: 32px 0 16px; }
|
|
593
|
+
.dci-umsg-md h4 { font: var(--dsw-font-markdown-h4); margin: 16px 0; }
|
|
594
|
+
.dci-umsg-md :where(h5, h6) { font: var(--dsw-font-markdown-base-strong); margin: 16px 0; }
|
|
595
|
+
.dci-umsg-md :where(h1, h2, h3, h4, h5, h6) strong { font-weight: inherit; }
|
|
596
|
+
.dci-umsg-md p { margin: 16px 0; }
|
|
597
|
+
.dci-umsg-md :where(h4, h5, h6) + :where(ul, ol) { margin-top: 8px; }
|
|
598
|
+
.dci-umsg-md :where(h4, h5, h6):has(+ :where(ul, ol)) { margin-bottom: 8px; }
|
|
599
|
+
.dci-umsg-md a { color: var(--dsw-alias-link); font-weight: 500;
|
|
600
|
+
transition: box-shadow var(--ds-transition-duration) var(--ds-ease-in-out); position: relative; text-decoration: none;
|
|
601
|
+
border-left: 3px solid rgb(255 255 255 / 0); border-right: 3px solid rgb(255 255 255 / 0);
|
|
602
|
+
border-top: 2px solid rgb(255 255 255 / 0); border-bottom: 2px solid rgb(255 255 255 / 0);
|
|
603
|
+
margin-left: -3px; margin-right: -3px; }
|
|
604
|
+
.dci-umsg-md a:hover, .dci-umsg-md a:focus { outline: none; text-decoration: underline dotted var(--dsw-alias-link); text-underline-offset: 3px; }
|
|
605
|
+
.dci-umsg-md a:focus-visible { box-shadow: 0 0 0 2px var(--dsw-focus-ring-color, var(--dsw-alias-state-business-primary)); }
|
|
606
|
+
.dci-umsg-md :where(ul, ol) { margin: 16px 0; padding-left: 18px; }
|
|
607
|
+
.dci-umsg-md li:not(:first-child) { margin-top: 6px; }
|
|
608
|
+
.dci-umsg-md li > :where(ul, ol) { margin-top: 4px; }
|
|
609
|
+
.dci-umsg-md li::marker { line-height: 24px; color: var(--dsw-alias-label-secondary); }
|
|
610
|
+
.dci-umsg-md :where(ul, ol) ol { list-style-position: inside; padding-left: 0; }
|
|
611
|
+
.dci-umsg-md :where(ul, ol) ol li p { display: inline; }
|
|
612
|
+
.dci-umsg-md li > p { margin: 8px 0; }
|
|
613
|
+
.dci-umsg-md li > *:first-child { margin-top: 0; }
|
|
614
|
+
.dci-umsg-md hr { display: block; border: none; height: 0.5px; margin: 32px 0; background: var(--dsw-alias-border-l2); }
|
|
615
|
+
.dci-umsg-md blockquote { border-left: 2px solid var(--dsw-alias-label-caption); margin: 16px 0 0; padding-left: 14px; }
|
|
616
|
+
/* 围栏代码块:官方 CodeBlock.module.css 的 .block :where(pre) 逐值——底色/圆角/
|
|
617
|
+
字体走官方 token(换肤跟随),气泡内靠底色与气泡面区分。语言横幅仍不做
|
|
618
|
+
(组件头注释的已知边界)。 */
|
|
619
|
+
.dci-umsg-md pre { margin: 16px 0; padding: 16px; font: var(--dsw-font-markdown-code-block, var(--ds-font-family-code));
|
|
620
|
+
background: var(--dsw-alias-markdown-code-block, color-mix(in srgb, currentColor 6%, transparent));
|
|
621
|
+
color: var(--dsw-alias-label-primary); white-space: pre-wrap; word-break: break-all; overflow-x: auto;
|
|
622
|
+
border-radius: var(--dsw-radius-lg); }
|
|
623
|
+
.dci-umsg-md pre code { font: inherit; background: none; padding: 0; }
|
|
624
|
+
.dci-umsg-md :not(pre) > code { display: inline-flex; align-items: center; box-sizing: border-box;
|
|
625
|
+
font: var(--dsw-font-markdown-code); font-family: var(--ds-font-family-code); font-size: 0.875em !important;
|
|
626
|
+
/* 底色与围栏代码块同一 token(--dsw-alias-markdown-code-block,产品决策 2026-10-29:
|
|
627
|
+
两种代码面同色)。官方 --dsw-alias-markdown-inline-code 对页面底设计(深色
|
|
628
|
+
rgb(41,41,41)),进用户气泡(深色 rgb(44,44,46))只差 3/255 不可辨,故不取它。 */
|
|
629
|
+
background-color: var(--dsw-alias-markdown-code-block, color-mix(in srgb, currentColor 6%, transparent));
|
|
630
|
+
border: 0.5px solid var(--dsw-alias-border-l1);
|
|
631
|
+
border-radius: var(--dsw-radius-sm); padding: 0 5px; }
|
|
632
|
+
.dci-umsg-md :where(h1, h2, h3, h4, h5, h6) code { font: inherit; font-family: var(--ds-font-family-code); }
|
|
633
|
+
.dci-umsg-md input[type='checkbox'] { margin: 0 8px 0 0; accent-color: var(--dsw-alias-label-secondary); }
|
|
634
|
+
.dci-umsg-md img { display: block; width: auto; max-width: 100%; height: auto; margin: 0;
|
|
635
|
+
border-radius: var(--dsw-radius-md); background: var(--dsw-alias-bg-base); object-fit: contain; }
|
|
636
|
+
.dci-umsg-tscroll { max-width: 100%; overflow-x: auto; overscroll-behavior-x: contain; }
|
|
637
|
+
.dci-umsg-tscroll table { border-collapse: collapse; width: max-content; max-width: max-content; }
|
|
638
|
+
.dci-umsg-tscroll th { text-align: start; padding: 10px 16px; border-bottom: 0.5px solid var(--dsw-alias-border-l3);
|
|
639
|
+
border-top: none; font: var(--dsw-font-markdown-table-head); max-width: min(30vw, 320px); min-width: 100px; }
|
|
640
|
+
.dci-umsg-tscroll td { padding: 10px 16px; border-bottom: 0.5px solid var(--dsw-alias-border-l2);
|
|
641
|
+
font: var(--dsw-font-markdown-table); max-width: min(30vw, 320px); min-width: 100px; }
|
|
642
|
+
.dci-umsg-tscroll th:first-child, .dci-umsg-tscroll td:first-child { padding-left: 0; }
|
|
643
|
+
.dci-umsg-tscroll td:last-child { padding-right: 0; }
|
|
644
|
+
.dci-umsg-tscroll table code { font-size: 11px; }
|
|
645
|
+
.dci-umsg-md > :first-child, .dci-umsg-md p:first-child { margin-top: 0 !important; }
|
|
646
|
+
.dci-umsg-md > :last-child, .dci-umsg-md p:last-child { margin-bottom: 0 !important; }
|
|
647
|
+
|
|
648
|
+
/* 引用 chip(官方 user-text.module.css 逐条移植):inline 走消费方基线,
|
|
649
|
+
可点 chip 用官方 fileMention 的链接语言。 */
|
|
650
|
+
.dci-umsg-chip { display: inline; max-width: 100%; margin: 0 2px; color: var(--dsw-alias-state-business-primary);
|
|
651
|
+
font-weight: 500; white-space: inherit; overflow-wrap: anywhere; text-align: inherit; }
|
|
652
|
+
button.dci-umsg-chip { margin: 0; padding: 0; border: none; background: none; font: inherit;
|
|
653
|
+
color: var(--dsw-alias-link); text-decoration: none; cursor: pointer; }
|
|
654
|
+
button.dci-umsg-chip:hover, button.dci-umsg-chip:focus { outline: none; text-decoration: underline dotted var(--dsw-alias-link); text-underline-offset: 3px; }
|
|
655
|
+
button.dci-umsg-chip:focus-visible { box-shadow: 0 0 0 2px var(--dsw-focus-ring-color, var(--dsw-alias-state-business-primary)); }
|
|
656
|
+
.dci-umsg-chip[data-chip="slash"] { font-family: var(--dsw-font-markdown-code-font-family); }
|
|
657
|
+
.dci-umsg-chipicon { width: 1em; height: 1em; margin-right: 4px; vertical-align: -0.125em; }
|
|
540
658
|
`;
|
|
541
659
|
|
|
542
660
|
export function injectStyles(): void {
|