xfy 1fa1984703 feat(editor): 点语言标签编辑可运行代码块的语言与配置
openRunnableModal 新增编辑模式(editPos + currentInfo):
- 回填当前块的 lang + overrides(解析 info string)
- 标题改「编辑」、按钮改「保存」
- 确认用 setNodeMarkup 原地更新 language 属性(保留块内代码)

CodeBlockNodeView 的语言标签在 runnable 块上可点击(绿字 hover 提示),
点击触发编辑模式(getPos 传 NodeView)。update() 在 language 变化时同步
刷新 <code> 的 class,让高亮按新语言重算。

补 4 个编辑模式用例(回填/标题/保存走 setNodeMarkup/改语言写入)。
Playwright 验证:python→node 编辑后 lang 标签与 code class 同步更新。
2026-07-07 16:12:11 +08:00

1071 lines
22 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* Tiptap Editor - Typora-inspired, theme-aware */
.tiptap-editor {
position: relative;
width: 100%;
height: 100%;
font-family:
-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
font-size: 16px;
line-height: 1.75;
/* Catppuccin Latte text */
color: #4c4f69;
outline: none;
}
.tiptap-editor .ProseMirror {
width: 100%;
height: 100%;
padding: 24px 32px;
outline: none;
overflow-y: auto;
}
.tiptap-editor .ProseMirror-focused {
outline: none;
}
/* Placeholder - shown when document has only one empty paragraph */
.tiptap-editor .ProseMirror
p:first-child:last-child:has(br.ProseMirror-trailingBreak:only-child)::before {
content: '在此输入内容...';
float: left;
/* Latte overlay0 */
color: #9ca0b0;
pointer-events: none;
height: 0;
}
/* Typography */
.tiptap-editor h1 {
font-size: 2em;
font-weight: 700;
margin: 1.2em 0 0.6em;
line-height: 1.3;
/* Latte text */
color: #4c4f69;
}
.tiptap-editor h2 {
font-size: 1.5em;
font-weight: 600;
margin: 1em 0 0.5em;
line-height: 1.35;
color: #4c4f69;
}
.tiptap-editor h3 {
font-size: 1.25em;
font-weight: 600;
margin: 0.8em 0 0.4em;
color: #4c4f69;
}
.tiptap-editor p {
margin: 0.6em 0;
}
.tiptap-editor p:first-child {
margin-top: 0;
}
.tiptap-editor strong {
font-weight: 700;
color: #4c4f69;
}
.tiptap-editor em {
font-style: italic;
}
.tiptap-editor s {
text-decoration: line-through;
opacity: 0.7;
}
.tiptap-editor code {
font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, monospace;
font-size: 0.875em;
/* Latte surface0 / red */
background: #ccd0da;
padding: 0.15em 0.4em;
border-radius: 3px;
color: #d20f39;
}
.tiptap-editor pre {
/* Latte crust */
background: #dce0e8;
border-radius: 6px;
padding: 16px;
overflow-x: auto;
margin: 1em 0;
}
.tiptap-editor pre code {
background: none;
padding: 0;
color: #4c4f69;
font-size: 0.85em;
line-height: 1.6;
}
.tiptap-editor blockquote {
/* Latte surface1 / subtext0 */
border-left: 4px solid #bcc0cc;
padding-left: 16px;
margin: 1em 0;
color: #6c6f85;
font-style: italic;
}
.tiptap-editor ul {
list-style-type: disc;
margin: 0.6em 0;
padding-left: 2em;
}
.tiptap-editor ol {
list-style-type: decimal;
margin: 0.6em 0;
padding-left: 2em;
}
.tiptap-editor li {
margin: 0.2em 0;
}
.tiptap-editor li > p {
margin: 0.2em 0;
}
.tiptap-editor hr {
/* Latte surface1 */
border: none;
border-top: 1px solid #bcc0cc;
margin: 1.5em 0;
}
/* Selection */
.tiptap-editor .ProseMirror ::selection {
/* Latte surface0 */
background: #ccd0da;
}
/* Cursor */
.tiptap-editor .ProseMirror-focused .ProseMirror-gapcursor {
display: none;
}
/* ========== Dark Theme (Catppuccin Mocha) ========== */
.dark .tiptap-editor {
/* Mocha text */
color: #cdd6f4;
}
.dark .tiptap-editor h1,
.dark .tiptap-editor h2,
.dark .tiptap-editor h3,
.dark .tiptap-editor strong {
color: #cdd6f4;
}
.dark .tiptap-editor .ProseMirror p.is-editor-empty:first-child::before {
/* Mocha overlay0 */
color: #6c7086;
}
.dark .tiptap-editor code {
/* Mocha surface0 / red */
background: #313244;
color: #f38ba8;
}
.dark .tiptap-editor pre {
background: #313244;
}
.dark .tiptap-editor pre code {
color: #cdd6f4;
}
.dark .tiptap-editor blockquote {
/* Mocha surface1 / subtext0 */
border-left-color: #45475a;
color: #a6adc8;
}
.dark .tiptap-editor hr {
border-top-color: #45475a;
}
.dark .tiptap-editor a {
/* Mocha blue */
color: #89b4fa;
}
.dark .tiptap-editor .ProseMirror ::selection {
background: rgba(30, 102, 245, 0.3);
}
/* ========== Link ========== */
.tiptap-editor a {
/* Latte blue */
color: #1e66f5;
text-decoration: none;
}
.tiptap-editor a:hover {
text-decoration: underline;
}
/* ========== Table ========== */
.tiptap-editor table {
border-collapse: collapse;
table-layout: fixed;
width: 100%;
margin: 1em 0;
overflow: hidden;
/* Latte surface1 */
border: 1px solid #bcc0cc;
border-radius: 6px;
}
.tiptap-editor table td,
.tiptap-editor table th {
min-width: 80px;
border: 1px solid #bcc0cc;
padding: 8px 12px;
position: relative;
vertical-align: top;
box-sizing: border-box;
}
.tiptap-editor table th {
/* Latte crust */
background: #dce0e8;
font-weight: 600;
text-align: left;
}
.tiptap-editor table .selectedCell {
/* Latte surface0 */
background: #ccd0da;
}
.tiptap-editor table .column-resize-handle {
position: absolute;
right: -2px;
top: 0;
bottom: -2px;
width: 4px;
/* Latte blue */
background-color: #1e66f5;
pointer-events: none;
}
.tiptap-editor .tableWrapper {
padding: 1rem 0;
overflow-x: auto;
}
.tiptap-editor .resize-cursor {
cursor: ew-resize;
cursor: col-resize;
}
/* ========== Slash Command ========== */
.slash-command {
position: fixed;
z-index: 9999;
/* Latte mantle */
background: #e6e9ef;
border: 1px solid #bcc0cc;
border-radius: 8px;
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.12);
padding: 4px;
min-width: 260px;
max-height: 320px;
overflow-y: auto;
font-family:
-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}
.slash-command-list {
display: flex;
flex-direction: column;
}
.slash-command-item {
display: flex;
align-items: center;
gap: 10px;
padding: 8px 12px;
border-radius: 6px;
cursor: pointer;
transition: background 0.15s;
}
.slash-command-item:hover,
.slash-command-item.is-selected {
/* Latte surface0 */
background: #ccd0da;
}
.slash-command-item-icon {
flex-shrink: 0;
width: 36px;
height: 36px;
display: flex;
align-items: center;
justify-content: center;
background: #ccd0da;
border-radius: 6px;
font-size: 13px;
font-weight: 600;
/* Latte subtext1 */
color: #5c5f77;
}
.slash-command-item-text {
flex: 1;
min-width: 0;
}
.slash-command-item-title {
font-size: 14px;
font-weight: 500;
color: #4c4f69;
line-height: 1.3;
}
.slash-command-item-desc {
font-size: 12px;
/* Latte overlay0 */
color: #9ca0b0;
line-height: 1.3;
}
.slash-command-empty {
padding: 12px 16px;
font-size: 13px;
/* Latte overlay0 */
color: #9ca0b0;
text-align: center;
}
.dark .slash-command-empty {
/* Mocha overlay0 */
color: #6c7086;
}
/* ========== Task List (Enhanced) ========== */
.tiptap-editor ul[data-type='taskList'] {
list-style: none;
padding-left: 0;
}
.tiptap-editor ul[data-type='taskList'] li {
display: flex;
align-items: center;
gap: 0.5em;
margin: 0.3em 0;
}
.tiptap-editor ul[data-type='taskList'] li > label {
flex-shrink: 0;
cursor: pointer;
user-select: none;
/* label 默认 inline,内部 checkbox 是 inline-block 会受 line-height 撑出
基线间距导致 checkbox 在 label 内偏上。用 flex 居中并清零行高,
让 checkbox 严格在 label 盒子中心。 */
display: flex;
align-items: center;
line-height: 0;
}
.tiptap-editor ul[data-type='taskList'] li > label input[type='checkbox'] {
width: 16px;
height: 16px;
/* 主强调色 Latte green */
accent-color: #40a02b;
cursor: pointer;
}
.tiptap-editor ul[data-type='taskList'] li > div {
flex: 1;
}
/* task list 项内的段落去掉上下 margin.tiptap-editor p 默认 .6em 0
否则 margin 会撑高 div使 checkbox 与文本垂直中线错位、项间距过大。 */
.tiptap-editor ul[data-type='taskList'] li > div > p {
margin: 0;
}
.tiptap-editor ul[data-type='taskList'] li[data-checked='true'] > div {
text-decoration: line-through;
opacity: 0.6;
}
/* ========== Image ========== */
.tiptap-editor img {
max-width: 100%;
height: auto;
border-radius: 6px;
margin: 1em 0;
display: block;
}
.tiptap-editor img.ProseMirror-selectednode {
/* 主强调色 Latte green */
outline: 2px solid #40a02b;
border-radius: 6px;
}
/* ========== Upload Image Placeholder NodeView ========== */
.upload-image-container {
position: relative;
display: inline-block;
max-width: 100%;
}
.upload-image-container img {
max-width: 100%;
height: auto;
border-radius: 6px;
margin: 1em 0;
display: block;
/* blur/grayscale 出现与消失的过渡(上传中→成功/失败的 filter 切换) */
transition: filter 0.2s ease;
}
.upload-image-container.is-error img {
opacity: 0.5;
filter: grayscale(0.5);
}
/* 上传中图片高斯模糊遮罩文字spinner/"上传中…")在独立 overlay 层不受影响 */
.upload-image-container.is-uploading {
overflow: hidden;
}
.upload-image-container.is-uploading img {
filter: blur(8px);
}
.upload-image-overlay {
position: absolute;
inset: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 8px;
border-radius: 6px;
pointer-events: none;
}
.upload-image-container.is-error .upload-image-overlay {
background: rgba(0, 0, 0, 0.35);
pointer-events: auto;
}
.upload-spinner {
width: 28px;
height: 28px;
border: 3px solid rgba(255, 255, 255, 0.4);
border-top-color: #fff;
border-radius: 50%;
animation: upload-spin 0.8s linear infinite;
}
@keyframes upload-spin {
to {
transform: rotate(360deg);
}
}
.upload-overlay-text {
color: #fff;
font-size: 13px;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
}
.upload-error-icon {
color: #fff;
font-size: 22px;
line-height: 1;
}
.upload-error-msg {
color: #fff;
font-size: 13px;
text-align: center;
padding: 0 12px;
max-width: 90%;
word-break: break-word;
}
.upload-error-actions {
display: flex;
gap: 8px;
}
.upload-btn {
padding: 3px 12px;
font-size: 12px;
border-radius: 4px;
border: 1px solid rgba(255, 255, 255, 0.6);
background: rgba(255, 255, 255, 0.15);
color: #fff;
cursor: pointer;
}
.upload-btn:hover {
background: rgba(255, 255, 255, 0.3);
}
.upload-btn-remove {
border-color: rgba(254, 202, 202, 0.7);
color: #fecaca;
}
.upload-btn-remove:hover {
background: rgba(239, 68, 68, 0.3);
}
/* ========== Dark Theme: Table (Mocha) ========== */
.dark .tiptap-editor table {
/* Mocha surface1 */
border-color: #45475a;
}
.dark .tiptap-editor table td,
.dark .tiptap-editor table th {
border-color: #45475a;
color: #cdd6f4;
}
.dark .tiptap-editor table th {
/* Mocha surface0 */
background: #313244;
}
.dark .tiptap-editor table .selectedCell {
background: rgba(30, 102, 245, 0.25);
}
/* ========== Dark Theme: Slash Command (Mocha) ========== */
.dark .slash-command {
/* Mocha mantle */
background: #181825;
border-color: #45475a;
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.4);
}
.dark .slash-command-item:hover,
.dark .slash-command-item.is-selected {
background: #313244;
}
.dark .slash-command-item-icon {
background: #313244;
color: #cdd6f4;
}
.dark .slash-command-item-title {
color: #cdd6f4;
}
.dark .slash-command-item-desc {
/* Mocha overlay0 */
color: #6c7086;
}
/* ========== Dark Theme: Image (Mocha) ========== */
.dark .tiptap-editor img.ProseMirror-selectednode {
/* 主强调色 Mocha green */
outline-color: #a6e3a1;
}
.dark .upload-image-container.is-error img {
opacity: 0.45;
}
.dark .upload-btn {
border-color: rgba(200, 200, 200, 0.4);
}
.dark .upload-btn-remove {
border-color: rgba(239, 68, 68, 0.5);
}
/* ========== Dark Theme: Task List (Mocha) ========== */
.dark .tiptap-editor ul[data-type='taskList'] li > label input[type='checkbox'] {
/* 主强调色 Mocha green */
accent-color: #a6e3a1;
}
/* ========== Source Toggle Button ========== */
.tiptap-toggle-btn {
position: absolute;
top: 12px;
right: 12px;
z-index: 10;
width: 30px;
height: 30px;
display: flex;
align-items: center;
justify-content: center;
border: none;
border-radius: 6px;
/* Latte text 半透明底 */
background: rgba(76, 79, 105, 0.05);
color: #6c6f85;
font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, monospace;
font-size: 13px;
font-weight: 600;
line-height: 1;
cursor: pointer;
opacity: 0.55;
transition:
opacity 0.15s,
background 0.15s;
}
.tiptap-toggle-btn:hover {
opacity: 1;
background: rgba(76, 79, 105, 0.1);
}
.dark .tiptap-toggle-btn {
/* Mocha text 半透明底 */
background: rgba(205, 214, 244, 0.06);
color: #6c7086;
}
.dark .tiptap-toggle-btn:hover {
background: rgba(205, 214, 244, 0.12);
}
/* ========== Source Textarea ========== */
.tiptap-source-textarea {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
padding: 24px 32px;
box-sizing: border-box;
border: none;
background: transparent;
/* Latte text */
color: #4c4f69;
font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, monospace;
font-size: 14px;
line-height: 1.7;
resize: none;
outline: none;
overflow-y: auto;
z-index: 5;
}
.tiptap-source-textarea::placeholder {
/* Latte overlay0 */
color: #9ca0b0;
}
.dark .tiptap-source-textarea {
/* Mocha text */
color: #cdd6f4;
}
.dark .tiptap-source-textarea::placeholder {
/* Mocha overlay0 */
color: #6c7086;
}
/* ========== Runnable Code Block Modal ========== */
.tiptap-runnable-modal-mask {
position: fixed;
inset: 0;
z-index: 10000;
display: flex;
align-items: center;
justify-content: center;
background: rgba(0, 0, 0, 0.3);
}
.tiptap-runnable-modal {
/* Latte mantle —— 复用 .slash-command 配色 */
background: #e6e9ef;
border: 1px solid #bcc0cc;
border-radius: 8px;
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.12);
padding: 16px;
min-width: 320px;
max-width: 90vw;
font-family:
-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}
.tiptap-runnable-modal-title {
font-size: 15px;
font-weight: 600;
/* Latte text */
color: #4c4f69;
margin-bottom: 12px;
}
.tiptap-runnable-field {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 8px;
font-size: 13px;
/* Latte subtext0 */
color: #6c6f85;
}
.tiptap-runnable-field input[type='number'],
.tiptap-runnable-field select {
flex: 1;
padding: 4px 8px;
border: 1px solid #bcc0cc;
border-radius: 4px;
background: #fff;
/* Latte text */
color: #4c4f69;
font-size: 13px;
font-family: inherit;
outline: none;
}
.tiptap-runnable-field input[type='checkbox'] {
accent-color: #40a02b;
}
.tiptap-runnable-preview {
margin: 12px 0;
padding: 8px;
/* Latte surface0 */
background: #ccd0da;
border-radius: 4px;
font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, monospace;
font-size: 12px;
/* Latte subtext1 */
color: #5c5f77;
word-break: break-all;
}
.tiptap-runnable-actions {
display: flex;
justify-content: flex-end;
gap: 8px;
}
.tiptap-runnable-actions button {
padding: 6px 16px;
border: none;
border-radius: 4px;
font-size: 13px;
cursor: pointer;
}
.tiptap-runnable-actions .cancel {
/* Latte surface0 */
background: #ccd0da;
/* Latte text */
color: #4c4f69;
}
.tiptap-runnable-actions .insert {
/* Catppuccin green —— 与 Code Runner 运行按钮主色一致 */
background: #40a02b;
color: #fff;
}
.tiptap-runnable-actions .insert:disabled {
opacity: 0.5;
cursor: not-allowed;
}
/* ========== Dark Theme: Runnable Modal (Mocha) ========== */
.dark .tiptap-runnable-modal {
/* Mocha mantle */
background: #181825;
border-color: #45475a;
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.4);
}
.dark .tiptap-runnable-modal-title {
/* Mocha text */
color: #cdd6f4;
}
.dark .tiptap-runnable-field {
/* Mocha subtext0 */
color: #a6adc8;
}
.dark .tiptap-runnable-field input[type='number'],
.dark .tiptap-runnable-field select {
border-color: #45475a;
/* Mocha base */
background: #1e1e2e;
/* Mocha text */
color: #cdd6f4;
}
.dark .tiptap-runnable-field input[type='checkbox'] {
/* Mocha green */
accent-color: #a6e3a1;
}
.dark .tiptap-runnable-preview {
/* Mocha surface0 */
background: #313244;
/* Mocha subtext1 */
color: #bac2de;
}
.dark .tiptap-runnable-actions .cancel {
/* Mocha surface0 */
background: #313244;
/* Mocha text */
color: #cdd6f4;
}
.dark .tiptap-runnable-actions .insert {
/* Mocha green */
background: #a6e3a1;
/* Mocha base */
color: #1e1e2e;
}
/* ========== Code Block Syntax Highlighting (Catppuccin Latte) ========== */
/* 色值取自 @catppuccin/highlightjs@1.0.1,与读者侧 public/highlight.css(syntect Catppuccin)同一 palette。
scope 到 .tiptap-editor pre code,避免污染全站 code 元素。
基础文字色/背景由现有 .tiptap-editor pre code 规则覆盖,未命中 token 回退到基础色。 */
.tiptap-editor pre code .hljs-keyword {
color: #8839ef;
}
.tiptap-editor pre code .hljs-string,
.tiptap-editor pre code .hljs-char.escape_ {
color: #40a02b;
}
.tiptap-editor pre code .hljs-comment {
color: #7c7f93;
font-style: italic;
}
.tiptap-editor pre code .hljs-number,
.tiptap-editor pre code .hljs-literal {
color: #fe640b;
}
.tiptap-editor pre code .hljs-title,
.tiptap-editor pre code .hljs-title.function_ {
color: #1e66f5;
}
.tiptap-editor pre code .hljs-type,
.tiptap-editor pre code .hljs-title.class_ {
color: #df8e1d;
}
.tiptap-editor pre code .hljs-built_in,
.tiptap-editor pre code .hljs-doctag {
color: #d20f39;
}
.tiptap-editor pre code .hljs-operator {
color: #04a5e5;
}
.tiptap-editor pre code .hljs-property,
.tiptap-editor pre code .hljs-tag {
color: #179299;
}
.tiptap-editor pre code .hljs-regexp,
.tiptap-editor pre code .hljs-meta {
color: #ea76cb;
}
.tiptap-editor pre code .hljs-variable,
.tiptap-editor pre code .hljs-symbol {
color: #dd7878;
}
.tiptap-editor pre code .hljs-attr,
.tiptap-editor pre code .hljs-attribute {
color: #1e66f5;
}
.tiptap-editor pre code .hljs-addition {
color: #40a02b;
background: rgba(64, 160, 43, 0.15);
}
.tiptap-editor pre code .hljs-deletion {
color: #d20f39;
background: rgba(210, 15, 57, 0.15);
}
/* ========== Dark Theme: Code Block Syntax Highlighting (Catppuccin Mocha) ========== */
.dark .tiptap-editor pre code .hljs-keyword {
color: #cba6f7;
}
.dark .tiptap-editor pre code .hljs-string,
.dark .tiptap-editor pre code .hljs-char.escape_ {
color: #a6e3a1;
}
.dark .tiptap-editor pre code .hljs-comment {
color: #9399b2;
font-style: italic;
}
.dark .tiptap-editor pre code .hljs-number,
.dark .tiptap-editor pre code .hljs-literal {
color: #fab387;
}
.dark .tiptap-editor pre code .hljs-title,
.dark .tiptap-editor pre code .hljs-title.function_ {
color: #89b4fa;
}
.dark .tiptap-editor pre code .hljs-type,
.dark .tiptap-editor pre code .hljs-title.class_ {
color: #f9e2af;
}
.dark .tiptap-editor pre code .hljs-built_in,
.dark .tiptap-editor pre code .hljs-doctag {
color: #f38ba8;
}
.dark .tiptap-editor pre code .hljs-operator {
color: #89dceb;
}
.dark .tiptap-editor pre code .hljs-property,
.dark .tiptap-editor pre code .hljs-tag {
color: #94e2d5;
}
.dark .tiptap-editor pre code .hljs-regexp,
.dark .tiptap-editor pre code .hljs-meta {
color: #f5c2e7;
}
.dark .tiptap-editor pre code .hljs-variable,
.dark .tiptap-editor pre code .hljs-symbol {
color: #f2cdcd;
}
.dark .tiptap-editor pre code .hljs-attr,
.dark .tiptap-editor pre code .hljs-attribute {
color: #89b4fa;
}
.dark .tiptap-editor pre code .hljs-addition {
color: #a6e3a1;
background: rgba(166, 227, 161, 0.15);
}
.dark .tiptap-editor pre code .hljs-deletion {
color: #f38ba8;
background: rgba(243, 139, 168, 0.15);
}
/* ========== Code Block NodeView (toolbar + result) ========== */
.tiptap-codeblock {
position: relative;
margin: 1em 0;
}
.tiptap-codeblock-toolbar {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
padding: 4px 12px;
/* Latte crust与 pre 背景协调) */
background: #dce0e8;
border-radius: 6px 6px 0 0;
font-size: 12px;
font-family:
-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}
/* pre 紧贴 toolbar 下方,合并圆角 */
.tiptap-codeblock > pre {
margin: 0;
border-radius: 0 0 6px 6px;
}
/* runnable 块绿条移到容器左侧(避免与 pre padding 冲突) */
.tiptap-codeblock:has(code[class*='runnable']) {
border-left: 3px solid #40a02b;
padding-left: 0;
}
.tiptap-codeblock:has(code[class*='runnable']) > pre {
padding-left: 13px;
}
.tiptap-codeblock-lang {
/* Latte subtext0 */
color: #6c6f85;
font-weight: 500;
text-transform: lowercase;
}
/* runnable 块的语言标签可点击(触发编辑模态框) */
.tiptap-codeblock-lang-editable {
cursor: pointer;
padding: 1px 6px;
border-radius: 3px;
}
.tiptap-codeblock-lang-editable:hover {
/* Latte surface0 */
background: #ccd0da;
/* Catppuccin green暗示可改 */
color: #40a02b;
}
.dark .tiptap-codeblock-lang-editable:hover {
/* Mocha surface0 / green */
background: #313244;
color: #a6e3a1;
}
.tiptap-codeblock-run {
border: none;
border-radius: 4px;
padding: 2px 10px;
font-size: 12px;
cursor: pointer;
/* Catppuccin green */
background: #40a02b;
color: #fff;
}
.tiptap-codeblock-run:hover:not(:disabled) {
background: #3a8f26;
}
.tiptap-codeblock-run:disabled {
opacity: 0.6;
cursor: wait;
}
.tiptap-codeblock-result {
margin-top: 4px;
padding: 8px 12px;
border-radius: 6px;
/* Latte surface0 */
background: #ccd0da;
font-family: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, monospace;
font-size: 12px;
/* Latte text */
color: #4c4f69;
white-space: pre-wrap;
word-break: break-all;
max-height: 300px;
overflow-y: auto;
}
/* ========== Dark Theme: Code Block NodeView (Mocha) ========== */
.dark .tiptap-codeblock-toolbar {
/* Mocha crust */
background: #11111b;
}
.dark .tiptap-codeblock:has(code[class*='runnable']) {
border-left-color: #a6e3a1;
}
.dark .tiptap-codeblock-lang {
/* Mocha subtext0 */
color: #a6adc8;
}
.dark .tiptap-codeblock-run {
/* Mocha green */
background: #a6e3a1;
/* Mocha base */
color: #1e1e2e;
}
.dark .tiptap-codeblock-run:hover:not(:disabled) {
background: #95d88f;
}
.dark .tiptap-codeblock-result {
/* Mocha surface0 */
background: #313244;
/* Mocha text */
color: #cdd6f4;
}