代码块 CSS 代码 JS代码 迭代记录
作者: iTxGo |
发布于: 2026-01-12 21:07 |
更新于: 2026-01-17 10:10 |
分类: 笔记 |
浏览: 1425 |
🎨CSS 代码:
1. 🔄代码块 CSS 样式 - 2026年1月1日
/* ==========================================
代码块 - 需置于 文章详情页 样式下
========================================== */
.article-content {
--code-bg: #0f1724;
--code-text: #e6eef8;
--code-toolbar-bg: #151d27;
--code-border: rgba(255, 255, 255, 0.08);
--code-line-num: rgba(255, 255, 255, 0.28);
--code-btn-text: rgba(255, 255, 255, 0.68);
--code-btn-hover: rgba(255, 255, 255, 0.06);
--inline-code-bg: #0f1724;
--inline-code-text: #e6eef8;
--inline-code-hover: #252f3e;
}
/* 注意:折叠高度计算依赖以下值:
- 折叠时显示5行代码(由JS的CODE_CONFIG.COLLAPSE_LINES控制)
- 上边距:48px (工具栏高度38px + 10px间隔)
- 下边距:16px (--spacing-md)
- 行高:1.6 * 字体大小
*/
/* 字体渲染通用设置 */
.article-content pre,
.article-content code {
/* 字体栈:英文等宽 + 中文无衬线 */
font-family: var(--font-mono), var(--font-mono-cjk);
/* 字体平滑 */
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
/* 文本渲染质量 */
text-rendering: optimizeLegibility;
/* 禁用连字 */
font-feature-settings: "liga" off;
font-variant-ligatures: none;
}
/* 基础 pre 样式 */
.article-content pre {
position: relative;
background: var(--code-bg);
color: var(--code-text);
font-family: var(--font-mono);
font-size: 15px;
line-height: 1.6;
padding: 48px var(--spacing-md) var(--spacing-md) 54px;
border-radius: var(--radius-sm);
border: 1px solid var(--code-border);
margin: 1.2rem 0;
overflow: hidden; /* 初始为折叠状态 */
white-space: pre;
transition: max-height var(--transition-normal);
box-sizing: border-box;
}
/* 展开状态 */
.article-content pre.expanded {
overflow: auto;
max-height: none;
}
/* 折叠状态(由 JS 控制 maxHeight) */
.article-content pre.collapsed {
overflow: hidden;
}
/* 左侧行号列 */
.article-content pre::before {
content: attr(data-line-numbers);
position: absolute;
top: 48px;
left: 0;
width: 44px;
padding-right: 8px;
text-align: right;
font-size: 15px;
line-height: 1.6;
font-family: var(--font-mono);
color: var(--code-line-num);
white-space: pre;
user-select: none;
border-right: 1px solid rgba(255, 255, 255, 0.06);
box-sizing: border-box;
}
/* 顶部工具栏 */
.article-content pre .code-tools {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 38px;
padding: 0 var(--spacing-sm);
background: var(--code-toolbar-bg);
display: flex;
align-items: center;
justify-content: space-between;
border-top-left-radius: var(--radius-md);
border-top-right-radius: var(--radius-md);
box-sizing: border-box;
}
/* CODE 标题 */
.article-content pre .code-title {
font-size: 12px;
font-weight: 700;
color: rgba(255, 255, 255, 0.65);
letter-spacing: 1px;
user-select: none;
font-family: var(--font-primary);
}
/* 按钮样式 */
.article-content pre .code-btn {
background: transparent;
border: none;
color: var(--code-btn-text);
font-size: 13px;
cursor: pointer;
padding: 6px 8px;
border-radius: var(--radius-sm);
transition: all var(--transition-fast);
user-select: none;
-webkit-user-select: none;
}
.article-content pre .code-btn:hover:not(:disabled) {
color: var(--color-text-inverse);
background: var(--code-btn-hover);
}
.article-content pre .code-btn:active:not(:disabled) {
transform: scale(0.95);
}
.article-content pre .code-btn:disabled {
cursor: not-allowed;
opacity: 0.7;
color: #4ade80;
font-weight: bold;
}
/* 代码内容(code 元素) */
.article-content pre > code {
background: none;
border: none;
padding: 0;
margin: 0;
font-family: inherit;
font-size: inherit;
line-height: inherit;
display: block;
word-break: break-word;
}
/* 折叠遮罩 */
.article-content pre.collapsed::after {
content: "";
position: absolute;
left: 0;
right: 0;
bottom: 0;
height: 48px; /* 匹配下边距,创建渐变过渡效果 */
background: linear-gradient(to bottom, transparent, var(--code-bg));
pointer-events: none;
}
/* ==========================================
行内代码
========================================== */
.article-content code {
font-family: var(--font-mono);
background-color: var(--inline-code-bg);
color: var(--inline-code-text);
margin: 0 2px;
padding: 2px 5px;
border-radius: var(--radius-xs);
font-size: 0.94em;
transition: background-color var(--transition-fast);
}
2. ✅️代码块 CSS 样式 - AI风格 - 2026年1月12日
/* ==========================================
代码块 - 需置于 文章详情页 样式下
========================================== */
/* CSS变量 - 响应式浅色/深色主题 */
:root {
/* 浅色主题 */
--itxgo-code-bg-light: var(--color-bg-light);
--itxgo-code-text-light: #24292f;
--itxgo-border-light: #d1d9e0;
--itxgo-btn-text-light: #57606a;
--itxgo-code-label-light: #6e7781;
--itxgo-scrollbar-thumb-light: #afb8c1;
/* 深色主题 */
--itxgo-code-bg-dark: #30302e;
--itxgo-code-text-dark: #e6edf3;
--itxgo-border-dark: #30363d;
--itxgo-btn-text-dark: #c9d1d9;
--itxgo-code-label-dark: #8b949e;
--itxgo-scrollbar-thumb-dark: #484f58;
/* 默认使用浅色主题 */
--itxgo-code-bg: var(--itxgo-code-bg-light);
--itxgo-code-text: var(--itxgo-code-text-light);
--itxgo-border: var(--itxgo-border-light);
--itxgo-btn-text: var(--itxgo-btn-text-light);
--itxgo-code-label: var(--itxgo-code-label-light);
--itxgo-scrollbar-thumb: var(--itxgo-scrollbar-thumb-light);
}
/* 深色主题切换 */
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) {
--itxgo-code-bg: var(--itxgo-code-bg-dark);
--itxgo-code-text: var(--itxgo-code-text-dark);
--itxgo-border: var(--itxgo-border-dark);
--itxgo-btn-text: var(--itxgo-btn-text-dark);
--itxgo-code-label: var(--itxgo-code-label-dark);
--itxgo-scrollbar-thumb: var(--itxgo-scrollbar-thumb-dark);
}
}
[data-theme="dark"],
.dark-mode,
.dark {
--itxgo-code-bg: var(--itxgo-code-bg-dark);
--itxgo-code-text: var(--itxgo-code-text-dark);
--itxgo-border: var(--itxgo-border-dark);
--itxgo-btn-text: var(--itxgo-btn-text-dark);
--itxgo-code-label: var(--itxgo-code-label-dark);
--itxgo-scrollbar-thumb: var(--itxgo-scrollbar-thumb-dark);
}
/* 代码块容器 */
.article-content pre.itxgo-code-block {
position: relative;
background: var(--itxgo-code-bg);
color: var(--itxgo-code-text);
font-family: Cascadia Code;
font-size: 14px;
line-height: 1.4286;
padding: 40px 16px 12px;
border-radius: var(--radius-md);
margin: 1rem 0;
overflow: hidden;
transition: max-height 0.3s ease-out, background-color 0.3s ease;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
border: 1px solid #6e7781;
}
.article-content pre.itxgo-code-block > code {
font-family: inherit;
background: none;
border: none;
padding: 0;
margin: 0;
display: block;
word-break: break-word;
white-space: pre-wrap;
tab-size: 2;
}
/* 展开/折叠状态 */
.article-content pre.itxgo-expanded {
overflow: auto;
max-height: none;
}
.article-content pre.itxgo-collapsed {
overflow: hidden;
cursor: pointer;
}
.article-content pre.itxgo-collapsed::after {
content: "︾";
position: absolute;
left: 0;
right: 0;
bottom: 0;
height: 40px;
background: linear-gradient(to bottom, transparent, var(--itxgo-code-bg) 70%);
display: flex;
align-items: flex-end;
justify-content: center;
padding-bottom: 6px;
color: var(--itxgo-code-label);
font-size: 18px;
font-weight: normal;
font-family: system-ui, -apple-system, sans-serif;
pointer-events: none;
border-radius: 6px;
}
/* 工具栏 */
.article-content pre .itxgo-code-tools {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 38px;
padding: 0 16px;
background: var(--itxgo-code-bg);
display: flex;
align-items: center;
justify-content: space-between;
border-radius: 6px 6px 0 0;
transition: background-color 0.3s ease;
z-index: 10;
cursor: default;
}
.article-content pre .itxgo-code-header {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
gap: 12px;
}
.article-content pre .itxgo-code-label {
font-family: Cascadia Code;
font-size: 12px;
font-weight: 600;
color: var(--itxgo-code-label);
letter-spacing: 0.5px;
user-select: none;
text-transform: uppercase;
transition: color 0.3s ease;
cursor: default;
}
.article-content pre .itxgo-code-actions {
display: flex;
align-items: center;
gap: 6px;
}
/* 按钮样式 */
.article-content pre .itxgo-code-btn {
display: flex;
align-items: center;
gap: 6px;
background: transparent;
border: 1px solid transparent;
color: var(--itxgo-btn-text);
font-size: 12px;
cursor: pointer;
padding: 4px 10px;
border-radius: 6px;
transition: all 0.2s ease;
user-select: none;
font-family: Cascadia Code;
font-weight: 500;
height: 28px;
}
.article-content pre .itxgo-code-btn:disabled {
cursor: not-allowed;
opacity: 0.7;
}
.article-content pre .itxgo-copy .copy-icon {
flex-shrink: 0;
stroke-width: 2;
}
.article-content pre .itxgo-copy .copy-text {
font-size: 12px;
}
.article-content pre .itxgo-toggle {
width: 28px;
min-width: 28px;
padding: 0;
justify-content: center;
font-size: 12px;
}
/* 滚动条 */
.article-content pre.itxgo-code-block::-webkit-scrollbar {
width: 8px;
height: 8px;
}
.article-content pre.itxgo-code-block::-webkit-scrollbar-track {
background: transparent;
border-radius: 6px;
}
.article-content pre.itxgo-code-block::-webkit-scrollbar-thumb {
background: var(--itxgo-scrollbar-thumb);
border-radius: 4px;
}
.article-content pre.itxgo-code-block::-webkit-scrollbar-thumb:hover {
background: color-mix(in srgb, var(--itxgo-scrollbar-thumb) 80%, var(--itxgo-code-text));
}
/* 行内代码 */
.article-content code:not(pre > code) {
font-family: Cascadia Code;
background-color: rgba(88, 166, 255, 0.1);
color: #58a6ff;
margin: 0 1px;
padding: 2px 6px;
border-radius: 4px;
font-size: 0.88em;
transition: all 0.2s ease;
}
.article-content code:not(pre > code):hover {
background-color: rgba(88, 166, 255, 0.15);
}
/* 响应式 */
@media (max-width: 768px) {
.article-content pre.itxgo-code-block {
font-size: 13px;
padding: 36px 12px 10px;
margin: 0.8rem -8px;
border-radius: 0;
}
.article-content pre .itxgo-code-tools {
height: 34px;
padding: 0 12px;
}
.article-content pre .itxgo-code-btn {
padding: 3px 8px;
font-size: 11px;
height: 26px;
}
.article-content pre .itxgo-toggle {
width: 26px;
min-width: 26px;
}
.article-content pre .itxgo-code-label {
font-size: 11px;
}
}
3. ✅️代码块 CSS 样式 - AI风格 新增右下折叠按钮 - 2026年1月12日
/* ==========================================
代码块 - 需置于 文章详情页 样式下
========================================== */
/* CSS变量 - 响应式浅色/深色主题 */
:root {
/* 浅色主题 */
--itxgo-code-bg-light: var(--color-bg-light);
--itxgo-code-text-light: #24292f;
--itxgo-border-light: #d1d9e0;
--itxgo-btn-text-light: #57606a;
--itxgo-code-label-light: #6e7781;
--itxgo-scrollbar-thumb-light: #afb8c1;
/* 深色主题 */
--itxgo-code-bg-dark: #30302e;
--itxgo-code-text-dark: #e6edf3;
--itxgo-border-dark: #30363d;
--itxgo-btn-text-dark: #c9d1d9;
--itxgo-code-label-dark: #8b949e;
--itxgo-scrollbar-thumb-dark: #484f58;
/* 默认使用浅色主题 */
--itxgo-code-bg: var(--itxgo-code-bg-light);
--itxgo-code-text: var(--itxgo-code-text-light);
--itxgo-border: var(--itxgo-border-light);
--itxgo-btn-text: var(--itxgo-btn-text-light);
--itxgo-code-label: var(--itxgo-code-label-light);
--itxgo-scrollbar-thumb: var(--itxgo-scrollbar-thumb-light);
}
/* 深色主题切换 */
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) {
--itxgo-code-bg: var(--itxgo-code-bg-dark);
--itxgo-code-text: var(--itxgo-code-text-dark);
--itxgo-border: var(--itxgo-border-dark);
--itxgo-btn-text: var(--itxgo-btn-text-dark);
--itxgo-code-label: var(--itxgo-code-label-dark);
--itxgo-scrollbar-thumb: var(--itxgo-scrollbar-thumb-dark);
}
}
[data-theme="dark"],
.dark-mode,
.dark {
--itxgo-code-bg: var(--itxgo-code-bg-dark);
--itxgo-code-text: var(--itxgo-code-text-dark);
--itxgo-border: var(--itxgo-border-dark);
--itxgo-btn-text: var(--itxgo-btn-text-dark);
--itxgo-code-label: var(--itxgo-code-label-dark);
--itxgo-scrollbar-thumb: var(--itxgo-scrollbar-thumb-dark);
}
/* 代码块容器 */
.article-content pre.itxgo-code-block {
position: relative;
background: var(--itxgo-code-bg);
color: var(--itxgo-code-text);
font-family: Cascadia Code;
font-size: 14px;
line-height: 1.4286;
padding: 40px 16px 12px;
border-radius: var(--radius-md);
margin: 1rem 0;
overflow: hidden;
transition: max-height 0.3s ease-out, background-color 0.3s ease;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
border: 1px solid #6e7781;
}
.article-content pre.itxgo-code-block > code {
font-family: inherit;
background: none;
border: none;
padding: 0;
margin: 0;
display: block;
word-break: break-word;
white-space: pre-wrap;
tab-size: 2;
}
/* 展开/折叠状态 */
.article-content pre.itxgo-expanded {
overflow: auto;
max-height: none;
}
.article-content pre.itxgo-collapsed {
overflow: hidden;
cursor: pointer;
}
.article-content pre.itxgo-collapsed::after {
content: "︾";
position: absolute;
left: 0;
right: 0;
bottom: 0;
height: 40px;
background: linear-gradient(to bottom, transparent, var(--itxgo-code-bg) 70%);
display: flex;
align-items: flex-end;
justify-content: center;
padding-bottom: 6px;
color: var(--itxgo-code-label);
font-size: 18px;
font-weight: normal;
font-family: system-ui, -apple-system, sans-serif;
pointer-events: none;
border-radius: 6px;
}
/* 工具栏 */
.article-content pre .itxgo-code-tools {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 38px;
padding: 0 16px;
background: var(--itxgo-code-bg);
display: flex;
align-items: center;
justify-content: space-between;
border-radius: 6px 6px 0 0;
transition: background-color 0.3s ease;
z-index: 10;
cursor: default;
}
.article-content pre .itxgo-code-header {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
gap: 12px;
}
.article-content pre .itxgo-code-label {
font-family: Cascadia Code;
font-size: 12px;
font-weight: 600;
color: var(--itxgo-code-label);
letter-spacing: 0.5px;
user-select: none;
text-transform: uppercase;
transition: color 0.3s ease;
cursor: default;
}
.article-content pre .itxgo-code-actions {
display: flex;
align-items: center;
gap: 6px;
}
/* 按钮样式 */
.article-content pre .itxgo-code-btn {
display: flex;
align-items: center;
gap: 6px;
background: transparent;
border: 1px solid transparent;
color: var(--itxgo-btn-text);
font-size: 12px;
cursor: pointer;
padding: 4px 10px;
border-radius: 6px;
transition: all 0.2s ease;
user-select: none;
font-family: Cascadia Code;
font-weight: 500;
height: 28px;
}
.article-content pre .itxgo-code-btn:disabled {
cursor: not-allowed;
opacity: 0.7;
}
.article-content pre .itxgo-copy .copy-icon {
flex-shrink: 0;
stroke-width: 2;
}
.article-content pre .itxgo-copy .copy-text {
font-size: 12px;
}
.article-content pre .itxgo-toggle {
width: 28px;
min-width: 28px;
padding: 0;
justify-content: center;
font-size: 12px;
}
/* 右下角折叠按钮 */
.article-content pre .itxgo-collapse-corner-btn {
display: none;
position: absolute;
bottom: 12px;
right: 12px;
z-index: 20;
background: transparent;
border: none;
font-size: 18px;
color: var(--itxgo-code-label);
cursor: pointer;
}
/* 仅在展开状态显示 */
.article-content pre.itxgo-expanded .itxgo-collapse-corner-btn {
display: block;
}
.article-content pre .itxgo-collapse-corner-btn:hover {
opacity: 1;
}
/* 滚动条 */
.article-content pre.itxgo-code-block::-webkit-scrollbar {
width: 8px;
height: 8px;
}
.article-content pre.itxgo-code-block::-webkit-scrollbar-track {
background: transparent;
border-radius: 6px;
}
.article-content pre.itxgo-code-block::-webkit-scrollbar-thumb {
background: var(--itxgo-scrollbar-thumb);
border-radius: 4px;
}
.article-content pre.itxgo-code-block::-webkit-scrollbar-thumb:hover {
background: color-mix(in srgb, var(--itxgo-scrollbar-thumb) 80%, var(--itxgo-code-text));
}
/* 行内代码 */
.article-content code:not(pre > code) {
font-family: Cascadia Code;
background-color: rgba(88, 166, 255, 0.1);
color: #58a6ff;
margin: 0 1px;
padding: 2px 6px;
border-radius: 4px;
font-size: 0.88em;
transition: all 0.2s ease;
}
.article-content code:not(pre > code):hover {
background-color: rgba(88, 166, 255, 0.15);
}
/* 响应式 */
@media (max-width: 768px) {
.article-content pre.itxgo-code-block {
font-size: 13px;
padding: 36px 12px 10px;
margin: 0.8rem -8px;
border-radius: 0;
}
.article-content pre .itxgo-code-tools {
height: 34px;
padding: 0 12px;
}
.article-content pre .itxgo-code-btn {
padding: 3px 8px;
font-size: 11px;
height: 26px;
}
.article-content pre .itxgo-toggle {
width: 26px;
min-width: 26px;
}
.article-content pre .itxgo-code-label {
font-size: 11px;
}
}
4. ✅️代码块 CSS 样式 - AI风格 代码高亮版 - GitHub 配色 - 2026年1月13日
/* ==========================================
代码块 - 需置于 文章详情页 样式下
========================================== */
/* CSS变量 - 响应式浅色/深色主题 */
:root {
/* 浅色主题 */
--itxgo-code-bg-light: var(--color-bg-light);
--itxgo-code-text-light: #24292f;
--itxgo-border-light: #d1d9e0;
--itxgo-btn-text-light: #57606a;
--itxgo-code-label-light: #6e7781;
--itxgo-scrollbar-thumb-light: #afb8c1;
/* 深色主题 */
--itxgo-code-bg-dark: #30302e;
--itxgo-code-text-dark: #e6edf3;
--itxgo-border-dark: #30363d;
--itxgo-btn-text-dark: #c9d1d9;
--itxgo-code-label-dark: #8b949e;
--itxgo-scrollbar-thumb-dark: #484f58;
/* 默认使用浅色主题 */
--itxgo-code-bg: var(--itxgo-code-bg-light);
--itxgo-code-text: var(--itxgo-code-text-light);
--itxgo-border: var(--itxgo-border-light);
--itxgo-btn-text: var(--itxgo-btn-text-light);
--itxgo-code-label: var(--itxgo-code-label-light);
--itxgo-scrollbar-thumb: var(--itxgo-scrollbar-thumb-light);
}
/* 深色主题切换 */
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) {
--itxgo-code-bg: var(--itxgo-code-bg-dark);
--itxgo-code-text: var(--itxgo-code-text-dark);
--itxgo-border: var(--itxgo-border-dark);
--itxgo-btn-text: var(--itxgo-btn-text-dark);
--itxgo-code-label: var(--itxgo-code-label-dark);
--itxgo-scrollbar-thumb: var(--itxgo-scrollbar-thumb-dark);
}
}
[data-theme="dark"],
.dark-mode,
.dark {
--itxgo-code-bg: var(--itxgo-code-bg-dark);
--itxgo-code-text: var(--itxgo-code-text-dark);
--itxgo-border: var(--itxgo-border-dark);
--itxgo-btn-text: var(--itxgo-btn-text-dark);
--itxgo-code-label: var(--itxgo-code-label-dark);
--itxgo-scrollbar-thumb: var(--itxgo-scrollbar-thumb-dark);
}
/* 代码块容器 */
.article-content pre.itxgo-code-block {
position: relative;
background: var(--itxgo-code-bg);
color: var(--itxgo-code-text);
font-family: Cascadia Code;
font-size: 14px;
line-height: 1.4286;
padding: 40px 16px 12px;
border-radius: var(--radius-md);
margin: 1rem 0;
overflow: hidden;
transition: max-height 0.3s ease-out, background-color 0.3s ease;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
border: 1px solid #6e7781;
}
.article-content pre.itxgo-code-block > code {
font-family: inherit;
background: none;
border: none;
padding: 0;
margin: 0;
display: block;
word-break: break-word;
white-space: pre-wrap;
tab-size: 2;
}
/* ==========================================
Prism.js 语法高亮样式 - 浅色主题
========================================== */
.article-content pre.itxgo-code-block code[class*="language-"] .token.comment,
.article-content pre.itxgo-code-block code[class*="language-"] .token.prolog,
.article-content pre.itxgo-code-block code[class*="language-"] .token.doctype,
.article-content pre.itxgo-code-block code[class*="language-"] .token.cdata {
color: #6a737d;
font-style: italic;
}
.article-content pre.itxgo-code-block code[class*="language-"] .token.punctuation {
color: #24292f;
}
.article-content pre.itxgo-code-block code[class*="language-"] .token.property,
.article-content pre.itxgo-code-block code[class*="language-"] .token.tag,
.article-content pre.itxgo-code-block code[class*="language-"] .token.boolean,
.article-content pre.itxgo-code-block code[class*="language-"] .token.number,
.article-content pre.itxgo-code-block code[class*="language-"] .token.constant,
.article-content pre.itxgo-code-block code[class*="language-"] .token.symbol,
.article-content pre.itxgo-code-block code[class*="language-"] .token.deleted {
color: #005cc5;
}
.article-content pre.itxgo-code-block code[class*="language-"] .token.selector,
.article-content pre.itxgo-code-block code[class*="language-"] .token.attr-name,
.article-content pre.itxgo-code-block code[class*="language-"] .token.string,
.article-content pre.itxgo-code-block code[class*="language-"] .token.char,
.article-content pre.itxgo-code-block code[class*="language-"] .token.builtin,
.article-content pre.itxgo-code-block code[class*="language-"] .token.inserted {
color: #032f62;
}
.article-content pre.itxgo-code-block code[class*="language-"] .token.operator,
.article-content pre.itxgo-code-block code[class*="language-"] .token.entity,
.article-content pre.itxgo-code-block code[class*="language-"] .token.url,
.article-content pre.itxgo-code-block code[class*="language-"] .language-css .token.string,
.article-content pre.itxgo-code-block code[class*="language-"] .style .token.string {
color: #d73a49;
}
.article-content pre.itxgo-code-block code[class*="language-"] .token.atrule,
.article-content pre.itxgo-code-block code[class*="language-"] .token.attr-value,
.article-content pre.itxgo-code-block code[class*="language-"] .token.keyword {
color: #d73a49;
}
.article-content pre.itxgo-code-block code[class*="language-"] .token.function,
.article-content pre.itxgo-code-block code[class*="language-"] .token.class-name {
color: #6f42c1;
}
.article-content pre.itxgo-code-block code[class*="language-"] .token.regex,
.article-content pre.itxgo-code-block code[class*="language-"] .token.important,
.article-content pre.itxgo-code-block code[class*="language-"] .token.variable {
color: #e36209;
}
/* ==========================================
Prism.js 语法高亮样式 - 深色主题
========================================== */
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.comment,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.prolog,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.doctype,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.cdata {
color: #8b949e;
}
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.punctuation {
color: #c9d1d9;
}
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.property,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.tag,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.boolean,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.number,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.constant,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.symbol,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.deleted {
color: #79c0ff;
}
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.selector,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.attr-name,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.string,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.char,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.builtin,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.inserted {
color: #a5d6ff;
}
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.operator,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.entity,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.url,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .language-css .token.string,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .style .token.string {
color: #ff7b72;
}
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.atrule,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.attr-value,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.keyword {
color: #ff7b72;
}
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.function,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.class-name {
color: #d2a8ff;
}
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.regex,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.important,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.variable {
color: #ffa657;
}
}
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.comment,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.prolog,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.doctype,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.cdata,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.comment,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.prolog,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.doctype,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.cdata,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.comment,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.prolog,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.doctype,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.cdata {
color: #8b949e;
}
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.punctuation,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.punctuation,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.punctuation {
color: #c9d1d9;
}
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.property,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.tag,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.boolean,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.number,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.constant,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.symbol,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.deleted,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.property,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.tag,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.boolean,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.number,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.constant,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.symbol,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.deleted,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.property,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.tag,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.boolean,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.number,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.constant,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.symbol,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.deleted {
color: #79c0ff;
}
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.selector,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.attr-name,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.string,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.char,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.builtin,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.inserted,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.selector,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.attr-name,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.string,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.char,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.builtin,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.inserted,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.selector,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.attr-name,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.string,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.char,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.builtin,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.inserted {
color: #a5d6ff;
}
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.operator,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.entity,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.url,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .language-css .token.string,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .style .token.string,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.operator,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.entity,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.url,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .language-css .token.string,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .style .token.string,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.operator,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.entity,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.url,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .language-css .token.string,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .style .token.string {
color: #ff7b72;
}
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.atrule,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.attr-value,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.keyword,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.atrule,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.attr-value,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.keyword,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.atrule,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.attr-value,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.keyword {
color: #ff7b72;
}
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.function,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.class-name,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.function,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.class-name,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.function,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.class-name {
color: #d2a8ff;
}
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.regex,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.important,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.variable,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.regex,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.important,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.variable,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.regex,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.important,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.variable {
color: #ffa657;
}
/* 展开/折叠状态 */
.article-content pre.itxgo-expanded {
overflow: auto;
max-height: none;
}
.article-content pre.itxgo-collapsed {
overflow: hidden;
cursor: pointer;
}
.article-content pre.itxgo-collapsed::after {
content: "︾";
position: absolute;
left: 0;
right: 0;
bottom: 0;
height: 40px;
background: linear-gradient(to bottom, transparent, var(--itxgo-code-bg) 70%);
display: flex;
align-items: flex-end;
justify-content: center;
padding-bottom: 6px;
color: var(--itxgo-code-label);
font-size: 18px;
font-weight: normal;
font-family: system-ui, -apple-system, sans-serif;
pointer-events: none;
border-radius: 6px;
}
/* 工具栏 */
.article-content pre .itxgo-code-tools {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 38px;
padding: 0 16px;
background: var(--itxgo-code-bg);
display: flex;
align-items: center;
justify-content: space-between;
border-radius: 6px 6px 0 0;
transition: background-color 0.3s ease;
z-index: 10;
cursor: default;
}
.article-content pre .itxgo-code-header {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
gap: 12px;
}
.article-content pre .itxgo-code-label {
font-family: Cascadia Code;
font-size: 12px;
font-weight: 600;
color: var(--itxgo-code-label);
letter-spacing: 0.5px;
user-select: none;
text-transform: uppercase;
transition: color 0.3s ease;
cursor: default;
}
.article-content pre .itxgo-code-actions {
display: flex;
align-items: center;
gap: 6px;
}
/* 按钮样式 */
.article-content pre .itxgo-code-btn {
display: flex;
align-items: center;
gap: 6px;
background: transparent;
border: 1px solid transparent;
color: var(--itxgo-btn-text);
font-size: 12px;
cursor: pointer;
padding: 4px 10px;
border-radius: 6px;
transition: all 0.2s ease;
user-select: none;
font-family: Cascadia Code;
font-weight: 500;
height: 28px;
}
.article-content pre .itxgo-code-btn:disabled {
cursor: not-allowed;
opacity: 0.7;
}
.article-content pre .itxgo-copy .copy-icon {
flex-shrink: 0;
stroke-width: 2;
}
.article-content pre .itxgo-copy .copy-text {
font-size: 12px;
}
.article-content pre .itxgo-toggle {
width: 28px;
min-width: 28px;
padding: 0;
justify-content: center;
font-size: 12px;
}
/* 右下角折叠按钮 */
.article-content pre .itxgo-collapse-corner-btn {
display: none;
position: absolute;
bottom: 12px;
right: 12px;
z-index: 20;
background: transparent;
border: none;
font-size: 18px;
color: var(--itxgo-code-label);
cursor: pointer;
}
/* 仅在展开状态显示 */
.article-content pre.itxgo-expanded .itxgo-collapse-corner-btn {
display: block;
}
.article-content pre .itxgo-collapse-corner-btn:hover {
opacity: 1;
}
/* 滚动条 */
.article-content pre.itxgo-code-block::-webkit-scrollbar {
width: 8px;
height: 8px;
}
.article-content pre.itxgo-code-block::-webkit-scrollbar-track {
background: transparent;
border-radius: 6px;
}
.article-content pre.itxgo-code-block::-webkit-scrollbar-thumb {
background: var(--itxgo-scrollbar-thumb);
border-radius: 4px;
}
.article-content pre.itxgo-code-block::-webkit-scrollbar-thumb:hover {
background: color-mix(in srgb, var(--itxgo-scrollbar-thumb) 80%, var(--itxgo-code-text));
}
/* 重置代码块内部元素样式 */
.article-content pre.itxgo-code-block code,
.article-content pre.itxgo-code-block code * {
background: transparent;
padding: 0;
margin: 0;
border: none;
border-radius: 0;
}
/* 行内代码 */
.article-content code:not(pre > code) {
font-family: Cascadia Code;
background-color: rgba(88, 166, 255, 0.1);
color: #58a6ff;
margin: 0 1px;
padding: 2px 6px;
border-radius: 4px;
font-size: 0.88em;
transition: all 0.2s ease;
}
.article-content code:not(pre > code):hover {
background-color: rgba(88, 166, 255, 0.15);
}
/* 响应式 */
@media (max-width: 768px) {
.article-content pre.itxgo-code-block {
font-size: 13px;
padding: 36px 12px 10px;
margin: 0.8rem -8px;
border-radius: 0;
}
.article-content pre .itxgo-code-tools {
height: 34px;
padding: 0 12px;
}
.article-content pre .itxgo-code-btn {
padding: 3px 8px;
font-size: 11px;
height: 26px;
}
.article-content pre .itxgo-toggle {
width: 26px;
min-width: 26px;
}
.article-content pre .itxgo-code-label {
font-size: 11px;
}
}
4-1. ✅️代码块 CSS 样式 - AI风格 代码高亮版 - DeepSeek 配色 - 2026年1月13日
/* ==========================================
代码块 - 需置于 文章详情页 样式下
========================================== */
/* CSS变量 - 响应式浅色/深色主题 */
:root {
/* 浅色主题 */
--itxgo-code-bg-light: var(--color-bg-light);
--itxgo-code-text-light: #24292f;
--itxgo-border-light: #d1d9e0;
--itxgo-btn-text-light: #57606a;
--itxgo-code-label-light: #6e7781;
--itxgo-scrollbar-thumb-light: #afb8c1;
/* 深色主题 */
--itxgo-code-bg-dark: #30302e;
--itxgo-code-text-dark: #e6edf3;
--itxgo-border-dark: #30363d;
--itxgo-btn-text-dark: #c9d1d9;
--itxgo-code-label-dark: #8b949e;
--itxgo-scrollbar-thumb-dark: #484f58;
/* 默认使用浅色主题 */
--itxgo-code-bg: var(--itxgo-code-bg-light);
--itxgo-code-text: var(--itxgo-code-text-light);
--itxgo-border: var(--itxgo-border-light);
--itxgo-btn-text: var(--itxgo-btn-text-light);
--itxgo-code-label: var(--itxgo-code-label-light);
--itxgo-scrollbar-thumb: var(--itxgo-scrollbar-thumb-light);
}
/* 深色主题切换 */
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) {
--itxgo-code-bg: var(--itxgo-code-bg-dark);
--itxgo-code-text: var(--itxgo-code-text-dark);
--itxgo-border: var(--itxgo-border-dark);
--itxgo-btn-text: var(--itxgo-btn-text-dark);
--itxgo-code-label: var(--itxgo-code-label-dark);
--itxgo-scrollbar-thumb: var(--itxgo-scrollbar-thumb-dark);
}
}
[data-theme="dark"],
.dark-mode,
.dark {
--itxgo-code-bg: var(--itxgo-code-bg-dark);
--itxgo-code-text: var(--itxgo-code-text-dark);
--itxgo-border: var(--itxgo-border-dark);
--itxgo-btn-text: var(--itxgo-btn-text-dark);
--itxgo-code-label: var(--itxgo-code-label-dark);
--itxgo-scrollbar-thumb: var(--itxgo-scrollbar-thumb-dark);
}
/* 未初始化的代码块使用 display:none 完全隐藏 */
.article-content pre:not(.itxgo-initialized):not(.itxgo-code-block) {
display: none;
}
/* 代码块容器 */
.article-content pre.itxgo-code-block {
position: relative;
background: var(--itxgo-code-bg);
color: var(--itxgo-code-text);
font-family: Cascadia Code;
font-size: 14px;
line-height: 1.4286;
padding: 40px 16px 12px;
border-radius: var(--radius-md);
margin: 1rem 0;
overflow: hidden;
transition: max-height 0.3s ease-out, background-color 0.3s ease;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
border: 1px solid #6e7781;
}
.article-content pre.itxgo-code-block > code {
font-family: inherit;
background: none;
border: none;
padding: 0;
margin: 0;
display: block;
word-break: break-word;
white-space: pre-wrap;
tab-size: 2;
}
/* ==========================================
Prism.js 语法高亮样式 - DeepSeek 配色
========================================== */
/* 浅色主题 */
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.comment,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.prolog,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.doctype,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.cdata {
color: #6b7280;
font-style: italic;
}
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.punctuation {
color: #374151;
}
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.property,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.tag,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.boolean,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.number,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.constant,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.symbol,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.deleted {
color: #0284c7;
}
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.selector,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.attr-name,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.string,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.char,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.builtin,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.inserted {
color: #059669;
}
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.operator,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.entity,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.url,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .language-css .token.string,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .style .token.string {
color: #dc2626;
}
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.atrule,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.attr-value,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.keyword {
color: #7c3aed;
}
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.function,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.class-name {
color: #2563eb;
}
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.regex,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.important,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.variable {
color: #ea580c;
}
/* 深色主题 - 媒体查询 */
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.comment,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.prolog,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.doctype,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.cdata {
color: #94a3b8;
font-style: italic;
}
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.punctuation {
color: #e2e8f0;
}
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.property,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.tag,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.boolean,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.number,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.constant,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.symbol,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.deleted {
color: #38bdf8;
}
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.selector,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.attr-name,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.string,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.char,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.builtin,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.inserted {
color: #4ade80;
}
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.operator,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.entity,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.url,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .language-css .token.string,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .style .token.string {
color: #f87171;
}
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.atrule,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.attr-value,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.keyword {
color: #a78bfa;
}
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.function,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.class-name {
color: #60a5fa;
}
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.regex,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.important,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.variable {
color: #fb923c;
}
}
/* 深色主题 - 显式指定 */
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.comment,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.prolog,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.doctype,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.cdata,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.comment,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.prolog,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.doctype,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.cdata,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.comment,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.prolog,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.doctype,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.cdata {
color: #94a3b8;
font-style: italic;
}
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.punctuation,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.punctuation,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.punctuation {
color: #e2e8f0;
}
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.property,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.tag,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.boolean,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.number,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.constant,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.symbol,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.deleted,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.property,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.tag,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.boolean,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.number,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.constant,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.symbol,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.deleted,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.property,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.tag,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.boolean,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.number,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.constant,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.symbol,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.deleted {
color: #38bdf8;
}
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.selector,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.attr-name,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.string,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.char,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.builtin,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.inserted,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.selector,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.attr-name,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.string,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.char,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.builtin,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.inserted,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.selector,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.attr-name,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.string,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.char,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.builtin,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.inserted {
color: #4ade80;
}
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.operator,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.entity,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.url,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .language-css .token.string,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .style .token.string,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.operator,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.entity,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.url,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .language-css .token.string,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .style .token.string,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.operator,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.entity,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.url,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .language-css .token.string,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .style .token.string {
color: #f87171;
}
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.atrule,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.attr-value,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.keyword,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.atrule,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.attr-value,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.keyword,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.atrule,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.attr-value,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.keyword {
color: #a78bfa;
}
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.function,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.class-name,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.function,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.class-name,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.function,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.class-name {
color: #60a5fa;
}
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.regex,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.important,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.variable,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.regex,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.important,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.variable,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.regex,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.important,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.variable {
color: #fb923c;
}
/* 展开/折叠状态 */
.article-content pre.itxgo-expanded {
overflow: auto;
max-height: none;
}
.article-content pre.itxgo-collapsed {
overflow: hidden;
cursor: pointer;
}
.article-content pre.itxgo-collapsed::after {
content: "︾";
position: absolute;
left: 0;
right: 0;
bottom: 0;
height: 40px;
background: linear-gradient(to bottom, transparent, var(--itxgo-code-bg) 70%);
display: flex;
align-items: flex-end;
justify-content: center;
padding-bottom: 6px;
color: var(--itxgo-code-label);
font-size: 18px;
font-weight: normal;
font-family: system-ui, -apple-system, sans-serif;
pointer-events: none;
border-radius: 6px;
}
/* 工具栏 */
.article-content pre .itxgo-code-tools {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 38px;
padding: 0 16px;
background: var(--itxgo-code-bg);
display: flex;
align-items: center;
justify-content: space-between;
border-radius: 6px 6px 0 0;
transition: background-color 0.3s ease;
z-index: 10;
cursor: default;
}
.article-content pre .itxgo-code-header {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
gap: 12px;
}
.article-content pre .itxgo-code-label {
font-family: Cascadia Code;
font-size: 12px;
font-weight: 600;
color: var(--itxgo-code-label);
letter-spacing: 0.5px;
user-select: none;
text-transform: uppercase;
transition: color 0.3s ease;
cursor: default;
}
.article-content pre .itxgo-code-actions {
display: flex;
align-items: center;
gap: 6px;
}
/* 按钮样式 */
.article-content pre .itxgo-code-btn {
display: flex;
align-items: center;
gap: 6px;
background: transparent;
border: 1px solid transparent;
color: var(--itxgo-btn-text);
font-size: 12px;
cursor: pointer;
padding: 4px 0 4px 4px;
border-radius: 6px;
transition: all 0.2s ease;
user-select: none;
font-family: Cascadia Code;
font-weight: 500;
height: 28px;
}
.article-content pre .itxgo-code-btn:disabled {
cursor: not-allowed;
opacity: 0.7;
}
.article-content pre .itxgo-copy .copy-icon {
flex-shrink: 0;
stroke-width: 2;
}
.article-content pre .itxgo-copy .copy-text {
font-size: 12px;
}
.article-content pre .itxgo-toggle {
width: 28px;
min-width: 28px;
padding: 0;
justify-content: center;
font-size: 12px;
}
/* 右下角折叠按钮 */
.article-content pre .itxgo-collapse-corner-btn {
display: none;
position: absolute;
bottom: 12px;
right: 12px;
z-index: 20;
background: transparent;
border: none;
font-size: 18px;
color: var(--itxgo-code-label);
cursor: pointer;
}
/* 仅在展开状态显示 */
.article-content pre.itxgo-expanded .itxgo-collapse-corner-btn {
display: block;
}
.article-content pre .itxgo-collapse-corner-btn:hover {
opacity: 1;
}
/* 滚动条 */
.article-content pre.itxgo-code-block::-webkit-scrollbar {
width: 8px;
height: 8px;
}
.article-content pre.itxgo-code-block::-webkit-scrollbar-track {
background: transparent;
border-radius: 6px;
}
.article-content pre.itxgo-code-block::-webkit-scrollbar-thumb {
background: var(--itxgo-scrollbar-thumb);
border-radius: 4px;
}
.article-content pre.itxgo-code-block::-webkit-scrollbar-thumb:hover {
background: color-mix(in srgb, var(--itxgo-scrollbar-thumb) 80%, var(--itxgo-code-text));
}
/* 重置代码块内部元素样式 */
.article-content pre.itxgo-code-block code,
.article-content pre.itxgo-code-block code * {
background: transparent;
padding: 0;
margin: 0;
border: none;
border-radius: 0;
}
/* 行内代码 */
.article-content code:not(pre > code) {
font-family: Cascadia Code;
background-color: rgba(88, 166, 255, 0.1);
color: #58a6ff;
margin: 0 1px;
padding: 2px 6px;
border-radius: 4px;
font-size: 0.88em;
transition: all 0.2s ease;
}
.article-content code:not(pre > code):hover {
background-color: rgba(88, 166, 255, 0.15);
}
/* 响应式 */
@media (max-width: 768px) {
.article-content pre.itxgo-code-block {
font-size: 13px;
padding: 36px 12px 10px;
margin: 0.8rem -8px;
border-radius: 0;
}
.article-content pre .itxgo-code-tools {
height: 34px;
padding: 0 12px;
}
.article-content pre .itxgo-code-btn {
padding: 3px 8px;
font-size: 11px;
height: 26px;
}
.article-content pre .itxgo-toggle {
width: 26px;
min-width: 26px;
}
.article-content pre .itxgo-code-label {
font-size: 11px;
}
}
5 ✅️代码块 CSS 样式 - 终版 - 2026年1月15日
:root {
/* 代码块 浅色主题 */
--itxgo-code-bg-light: var(--color-bg-light);
--itxgo-code-text-light: #24292f;
--itxgo-border-light: #d1d9e0;
--itxgo-btn-text-light: #57606a;
--itxgo-code-label-light: #6e7781;
--itxgo-scrollbar-thumb-light: #afb8c1;
/* 代码块 深色主题 */
--itxgo-code-bg-dark: #30302e;
--itxgo-code-text-dark: #e6edf3;
--itxgo-border-dark: #30363d;
--itxgo-btn-text-dark: #c9d1d9;
--itxgo-code-label-dark: #8b949e;
--itxgo-scrollbar-thumb-dark: #484f58;
/* 代码块 默认使用浅色主题 */
--itxgo-code-bg: var(--itxgo-code-bg-light);
--itxgo-code-text: var(--itxgo-code-text-light);
--itxgo-border: var(--itxgo-border-light);
--itxgo-btn-text: var(--itxgo-btn-text-light);
--itxgo-code-label: var(--itxgo-code-label-light);
--itxgo-scrollbar-thumb: var(--itxgo-scrollbar-thumb-light);
}
/* ==========================================
代码块 - 需置于 文章详情页 样式下
========================================== */
/* 深色主题切换 */
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) {
--itxgo-code-bg: var(--itxgo-code-bg-dark);
--itxgo-code-text: var(--itxgo-code-text-dark);
--itxgo-border: var(--itxgo-border-dark);
--itxgo-btn-text: var(--itxgo-btn-text-dark);
--itxgo-code-label: var(--itxgo-code-label-dark);
--itxgo-scrollbar-thumb: var(--itxgo-scrollbar-thumb-dark);
}
}
[data-theme="dark"],
.dark-mode,
.dark {
--itxgo-code-bg: var(--itxgo-code-bg-dark);
--itxgo-code-text: var(--itxgo-code-text-dark);
--itxgo-border: var(--itxgo-border-dark);
--itxgo-btn-text: var(--itxgo-btn-text-dark);
--itxgo-code-label: var(--itxgo-code-label-dark);
--itxgo-scrollbar-thumb: var(--itxgo-scrollbar-thumb-dark);
}
/* 防止页面加载瞬间出现横向滚动条 对 pre 标签生效 */
.article-content pre {
max-width: 100%;
width: 100%;
box-sizing: border-box;
white-space: pre-wrap;
overflow-wrap: break-word;
word-break: break-word;
visibility: hidden;
opacity: 0;
position: relative;
z-index: 0;
}
.article-content pre > code {
display: block;
width: 100%;
white-space: pre-wrap;
word-break: break-word;
}
/* 初始化完成后的淡入动画 */
@keyframes itxgo-fade-in {
from { opacity: 0; }
to { opacity: 1; }
}
.article-content pre.itxgo-initialized {
visibility: visible;
animation: itxgo-fade-in 0.4s ease-out forwards;
}
/* 代码块容器 */
.article-content pre.itxgo-code-block {
position: relative;
background: var(--itxgo-code-bg);
color: var(--itxgo-code-text);
font-family: Cascadia Code;
font-size: 14px;
line-height: 1.4286;
padding: 40px 16px 12px;
border-radius: var(--radius-md);
margin: 1rem 0;
overflow: hidden;
transition: max-height 0.3s ease-out, background-color 0.3s ease;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
border: 1px solid #e9ecef;
}
.article-content pre.itxgo-code-block > code {
font-family: inherit;
background: none;
border: none;
padding: 0;
margin: 0;
tab-size: 2;
}
/* ==========================================
Prism.js 语法高亮样式 - DeepSeek 配色
========================================== */
/* 浅色主题 */
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.comment,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.prolog,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.doctype,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.cdata {
color: #6b7280;
font-style: italic;
}
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.punctuation {
color: #374151;
}
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.property,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.tag,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.boolean,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.number,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.constant,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.symbol,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.deleted {
color: #0284c7;
}
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.selector,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.attr-name,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.string,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.char,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.builtin,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.inserted {
color: #059669;
}
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.operator,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.entity,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.url,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .language-css .token.string,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .style .token.string {
color: #dc2626;
}
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.atrule,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.attr-value,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.keyword {
color: #7c3aed;
}
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.function,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.class-name {
color: #2563eb;
}
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.regex,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.important,
:root:not([data-theme="dark"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.variable {
color: #ea580c;
}
/* 深色主题 - 媒体查询 */
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.comment,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.prolog,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.doctype,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.cdata {
color: #94a3b8;
font-style: italic;
}
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.punctuation {
color: #e2e8f0;
}
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.property,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.tag,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.boolean,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.number,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.constant,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.symbol,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.deleted {
color: #38bdf8;
}
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.selector,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.attr-name,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.string,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.char,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.builtin,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.inserted {
color: #4ade80;
}
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.operator,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.entity,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.url,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .language-css .token.string,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .style .token.string {
color: #f87171;
}
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.atrule,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.attr-value,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.keyword {
color: #a78bfa;
}
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.function,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.class-name {
color: #60a5fa;
}
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.regex,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.important,
:root:not([data-theme="light"]) .article-content pre.itxgo-code-block code[class*="language-"] .token.variable {
color: #fb923c;
}
}
/* 深色主题 - 显式指定 */
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.comment,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.prolog,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.doctype,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.cdata,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.comment,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.prolog,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.doctype,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.cdata,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.comment,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.prolog,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.doctype,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.cdata {
color: #94a3b8;
font-style: italic;
}
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.punctuation,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.punctuation,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.punctuation {
color: #e2e8f0;
}
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.property,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.tag,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.boolean,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.number,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.constant,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.symbol,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.deleted,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.property,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.tag,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.boolean,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.number,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.constant,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.symbol,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.deleted,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.property,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.tag,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.boolean,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.number,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.constant,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.symbol,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.deleted {
color: #38bdf8;
}
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.selector,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.attr-name,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.string,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.char,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.builtin,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.inserted,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.selector,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.attr-name,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.string,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.char,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.builtin,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.inserted,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.selector,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.attr-name,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.string,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.char,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.builtin,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.inserted {
color: #4ade80;
}
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.operator,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.entity,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.url,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .language-css .token.string,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .style .token.string,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.operator,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.entity,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.url,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .language-css .token.string,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .style .token.string,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.operator,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.entity,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.url,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .language-css .token.string,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .style .token.string {
color: #f87171;
}
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.atrule,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.attr-value,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.keyword,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.atrule,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.attr-value,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.keyword,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.atrule,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.attr-value,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.keyword {
color: #a78bfa;
}
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.function,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.class-name,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.function,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.class-name,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.function,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.class-name {
color: #60a5fa;
}
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.regex,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.important,
[data-theme="dark"] .article-content pre.itxgo-code-block code[class*="language-"] .token.variable,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.regex,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.important,
.dark-mode .article-content pre.itxgo-code-block code[class*="language-"] .token.variable,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.regex,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.important,
.dark .article-content pre.itxgo-code-block code[class*="language-"] .token.variable {
color: #fb923c;
}
/* 展开/折叠状态 */
.article-content pre.itxgo-expanded {
overflow: auto;
max-height: none;
}
.article-content pre.itxgo-collapsed {
overflow: hidden;
cursor: pointer;
}
.article-content pre.itxgo-collapsed::after {
content: "︾";
position: absolute;
left: 0;
right: 0;
bottom: 0;
height: 40px;
background: linear-gradient(to bottom, transparent, var(--itxgo-code-bg) 70%);
display: flex;
align-items: flex-end;
justify-content: center;
padding-bottom: 6px;
color: var(--itxgo-code-label);
font-size: 18px;
font-weight: normal;
font-family: system-ui, -apple-system, sans-serif;
pointer-events: none;
border-radius: 6px;
}
/* 工具栏 */
.article-content pre .itxgo-code-tools {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 38px;
padding: 0 16px;
background: var(--itxgo-code-bg);
display: flex;
align-items: center;
justify-content: space-between;
border-radius: 6px 6px 0 0;
transition: background-color 0.3s ease;
z-index: 10;
cursor: default;
}
.article-content pre .itxgo-code-header {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
gap: 12px;
}
.article-content pre .itxgo-code-label {
font-family: Cascadia Code;
font-size: 12px;
font-weight: 600;
color: var(--itxgo-code-label);
letter-spacing: 0.5px;
user-select: none;
text-transform: uppercase;
transition: color 0.3s ease;
cursor: default;
}
.article-content pre .itxgo-code-actions {
display: flex;
align-items: center;
gap: 6px;
}
/* 按钮样式 */
.article-content pre .itxgo-code-btn {
display: flex;
align-items: center;
gap: 6px;
background: transparent;
border: 1px solid transparent;
color: var(--itxgo-btn-text);
font-size: 12px;
cursor: pointer;
padding: 4px 0 4px 4px;
border-radius: 6px;
transition: all 0.2s ease;
user-select: none;
font-family: Cascadia Code;
font-weight: 500;
height: 28px;
}
.article-content pre .itxgo-code-btn:disabled {
cursor: not-allowed;
opacity: 0.7;
}
.article-content pre .itxgo-copy .copy-icon {
flex-shrink: 0;
stroke-width: 2;
}
.article-content pre .itxgo-copy .copy-text {
font-size: 12px;
}
.article-content pre .itxgo-toggle {
width: 28px;
min-width: 28px;
padding: 0;
justify-content: center;
font-size: 12px;
}
/* 右下角折叠按钮 */
.article-content pre .itxgo-collapse-corner-btn {
display: none;
position: absolute;
bottom: 12px;
right: 12px;
z-index: 20;
background: transparent;
border: none;
font-size: 18px;
color: var(--itxgo-code-label);
cursor: pointer;
}
/* 仅在展开状态显示 */
.article-content pre.itxgo-expanded .itxgo-collapse-corner-btn {
display: block;
}
.article-content pre .itxgo-collapse-corner-btn:hover {
opacity: 1;
}
/* 滚动条 */
.article-content pre.itxgo-code-block::-webkit-scrollbar {
width: 8px;
height: 8px;
}
.article-content pre.itxgo-code-block::-webkit-scrollbar-track {
background: transparent;
border-radius: 6px;
}
.article-content pre.itxgo-code-block::-webkit-scrollbar-thumb {
background: var(--itxgo-scrollbar-thumb);
border-radius: 4px;
}
.article-content pre.itxgo-code-block::-webkit-scrollbar-thumb:hover {
background: color-mix(in srgb, var(--itxgo-scrollbar-thumb) 80%, var(--itxgo-code-text));
}
/* 重置代码块内部元素样式 */
.article-content pre.itxgo-code-block code,
.article-content pre.itxgo-code-block code * {
background: transparent;
padding: 0;
margin: 0;
border: none;
border-radius: 0;
}
/* 行内代码 */
.article-content code:not(pre > code) {
font-family: Cascadia Code;
background-color: rgba(88, 166, 255, 0.1);
color: #58a6ff;
margin: 0 1px;
padding: 2px 6px;
border-radius: 4px;
font-size: 0.88em;
transition: all 0.2s ease;
}
.article-content code:not(pre > code):hover {
background-color: rgba(88, 166, 255, 0.15);
}
/* 响应式 */
@media (max-width: 768px) {
.article-content pre.itxgo-code-block {
font-size: 13px;
padding: 36px 12px 10px;
margin: 0.8rem -16px;
max-width: 100vw;
border-radius: 0;
}
.article-content pre .itxgo-code-tools {
height: 34px;
padding: 0 12px;
}
.article-content pre .itxgo-code-btn {
padding: 3px 8px;
font-size: 11px;
height: 26px;
}
.article-content pre .itxgo-toggle {
width: 26px;
min-width: 26px;
}
.article-content pre .itxgo-code-label {
font-size: 11px;
}
}
6 ✅️代码块 CSS 样式 - 终版简化版 - 2026年1月17日
:root {
/* 代码块 UI 变量 - 浅色 */
--itxgo-code-bg-light: var(--color-bg-light);
--itxgo-code-text-light: #24292f;
--itxgo-border-light: #e9ecef;
--itxgo-btn-text-light: #57606a;
--itxgo-code-label-light: #6e7781;
--itxgo-scrollbar-thumb-light: #afb8c1;
/* 代码块 UI 变量 - 深色 */
--itxgo-code-bg-dark: #30302e;
--itxgo-code-text-dark: #e6edf3;
--itxgo-border-dark: #30363d;
--itxgo-btn-text-dark: #c9d1d9;
--itxgo-code-label-dark: #8b949e;
--itxgo-scrollbar-thumb-dark: #484f58;
/* 语法高亮颜色变量 - 浅色 */
--token-comment: #6b7280;
--token-punctuation: #374151;
--token-property: #0284c7;
--token-selector: #059669;
--token-operator: #dc2626;
--token-keyword: #7c3aed;
--token-function: #2563eb;
--token-variable: #ea580c;
/* 默认应用浅色变量 */
--itxgo-code-bg: var(--itxgo-code-bg-light);
--itxgo-code-text: var(--itxgo-code-text-light);
--itxgo-border: var(--itxgo-border-light);
--itxgo-btn-text: var(--itxgo-btn-text-light);
--itxgo-code-label: var(--itxgo-code-label-light);
--itxgo-scrollbar-thumb: var(--itxgo-scrollbar-thumb-light);
}
/* ==========================================
代码块 - 需置于 文章详情页 样式下
========================================== */
/* 深色主题 - 媒体查询 */
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) {
/* UI 变量覆盖 */
--itxgo-code-bg: var(--itxgo-code-bg-dark);
--itxgo-code-text: var(--itxgo-code-text-dark);
--itxgo-border: var(--itxgo-border-dark);
--itxgo-btn-text: var(--itxgo-btn-text-dark);
--itxgo-code-label: var(--itxgo-code-label-dark);
--itxgo-scrollbar-thumb: var(--itxgo-scrollbar-thumb-dark);
/* 语法变量覆盖 - 深色配色 */
--token-comment: #94a3b8;
--token-punctuation: #e2e8f0;
--token-property: #38bdf8;
--token-selector: #4ade80;
--token-operator: #f87171;
--token-keyword: #a78bfa;
--token-function: #60a5fa;
--token-variable: #fb923c;
}
}
/* 深色主题 - 显式指定类名/属性 */
[data-theme="dark"],
.dark-mode,
.dark {
/* UI 变量覆盖 */
--itxgo-code-bg: var(--itxgo-code-bg-dark);
--itxgo-code-text: var(--itxgo-code-text-dark);
--itxgo-border: var(--itxgo-border-dark);
--itxgo-btn-text: var(--itxgo-btn-text-dark);
--itxgo-code-label: var(--itxgo-code-label-dark);
--itxgo-scrollbar-thumb: var(--itxgo-scrollbar-thumb-dark);
/* 语法变量覆盖 - 深色配色 */
--token-comment: #94a3b8;
--token-punctuation: #e2e8f0;
--token-property: #38bdf8;
--token-selector: #4ade80;
--token-operator: #f87171;
--token-keyword: #a78bfa;
--token-function: #60a5fa;
--token-variable: #fb923c;
}
/* ===== 基础布局与容器 ===== */
/* 防止页面加载瞬间出现横向滚动条 */
.article-content pre {
max-width: 100%;
width: 100%;
box-sizing: border-box;
white-space: pre-wrap;
overflow-wrap: break-word;
word-break: break-word;
visibility: hidden;
opacity: 0;
position: relative;
z-index: 0;
}
.article-content pre > code {
display: block;
width: 100%;
white-space: pre-wrap;
word-break: break-word;
}
/* 初始化完成后的淡入动画 */
@keyframes itxgo-fade-in {
from { opacity: 0; }
to { opacity: 1; }
}
.article-content pre.itxgo-initialized {
visibility: visible;
animation: itxgo-fade-in 0.4s ease-out forwards;
}
/* 代码块容器 */
.article-content pre.itxgo-code-block {
position: relative;
background: var(--itxgo-code-bg);
color: var(--itxgo-code-text);
font-family: Cascadia Code;
font-size: 14px;
line-height: 1.4286;
padding: 40px 16px 12px;
border-radius: var(--radius-md);
margin: 1rem 0;
overflow: hidden;
transition: max-height 0.3s ease-out, background-color 0.3s ease;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
/* 使用变量边框,确保深色模式下正确 */
border: 1px solid var(--itxgo-border);
}
.article-content pre.itxgo-code-block > code {
font-family: inherit;
background: none;
border: none;
padding: 0;
margin: 0;
tab-size: 2;
}
/* ===== Prism.js 语法高亮 ===== */
.article-content pre.itxgo-code-block .token.comment,
.article-content pre.itxgo-code-block .token.prolog,
.article-content pre.itxgo-code-block .token.doctype,
.article-content pre.itxgo-code-block .token.cdata {
color: var(--token-comment);
font-style: italic;
}
.article-content pre.itxgo-code-block .token.punctuation {
color: var(--token-punctuation);
}
.article-content pre.itxgo-code-block .token.property,
.article-content pre.itxgo-code-block .token.tag,
.article-content pre.itxgo-code-block .token.boolean,
.article-content pre.itxgo-code-block .token.number,
.article-content pre.itxgo-code-block .token.constant,
.article-content pre.itxgo-code-block .token.symbol,
.article-content pre.itxgo-code-block .token.deleted {
color: var(--token-property);
}
.article-content pre.itxgo-code-block .token.selector,
.article-content pre.itxgo-code-block .token.attr-name,
.article-content pre.itxgo-code-block .token.string,
.article-content pre.itxgo-code-block .token.char,
.article-content pre.itxgo-code-block .token.builtin,
.article-content pre.itxgo-code-block .token.inserted {
color: var(--token-selector);
}
.article-content pre.itxgo-code-block .token.operator,
.article-content pre.itxgo-code-block .token.entity,
.article-content pre.itxgo-code-block .token.url,
.article-content pre.itxgo-code-block .language-css .token.string,
.article-content pre.itxgo-code-block .style .token.string {
color: var(--token-operator);
}
.article-content pre.itxgo-code-block .token.atrule,
.article-content pre.itxgo-code-block .token.attr-value,
.article-content pre.itxgo-code-block .token.keyword {
color: var(--token-keyword);
}
.article-content pre.itxgo-code-block .token.function,
.article-content pre.itxgo-code-block .token.class-name {
color: var(--token-function);
}
.article-content pre.itxgo-code-block .token.regex,
.article-content pre.itxgo-code-block .token.important,
.article-content pre.itxgo-code-block .token.variable {
color: var(--token-variable);
}
/* ===== 交互组件 (Toolbar, 展开/折叠, 滚动条) ===== */
/* 展开/折叠状态 */
.article-content pre.itxgo-expanded {
overflow: auto;
max-height: none;
}
.article-content pre.itxgo-collapsed {
overflow: hidden;
cursor: pointer;
}
.article-content pre.itxgo-collapsed::after {
content: "︾";
position: absolute;
left: 0;
right: 0;
bottom: 0;
height: 40px;
background: linear-gradient(to bottom, transparent, var(--itxgo-code-bg) 70%);
display: flex;
align-items: flex-end;
justify-content: center;
padding-bottom: 6px;
color: var(--itxgo-code-label);
font-size: 18px;
font-weight: normal;
font-family: system-ui, -apple-system, sans-serif;
pointer-events: none;
border-radius: 6px;
}
/* 工具栏 */
.article-content pre .itxgo-code-tools {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 38px;
padding: 0 16px;
background: var(--itxgo-code-bg);
display: flex;
align-items: center;
justify-content: space-between;
border-radius: 6px 6px 0 0;
transition: background-color 0.3s ease;
z-index: 10;
cursor: default;
}
.article-content pre .itxgo-code-header {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
gap: 12px;
}
.article-content pre .itxgo-code-label {
font-family: Cascadia Code;
font-size: 12px;
font-weight: 600;
color: var(--itxgo-code-label);
letter-spacing: 0.5px;
user-select: none;
text-transform: uppercase;
transition: color 0.3s ease;
cursor: default;
}
.article-content pre .itxgo-code-actions {
display: flex;
align-items: center;
gap: 6px;
}
/* 按钮样式 */
.article-content pre .itxgo-code-btn {
display: flex;
align-items: center;
gap: 6px;
background: transparent;
border: 1px solid transparent;
color: var(--itxgo-btn-text);
font-size: 12px;
cursor: pointer;
padding: 4px 0 4px 4px;
border-radius: 6px;
transition: all 0.2s ease;
user-select: none;
font-family: Cascadia Code;
font-weight: 500;
height: 28px;
}
.article-content pre .itxgo-code-btn:disabled {
cursor: not-allowed;
opacity: 0.7;
}
.article-content pre .itxgo-copy .copy-icon { flex-shrink: 0; stroke-width: 2; }
.article-content pre .itxgo-copy .copy-text { font-size: 12px; }
.article-content pre .itxgo-toggle {
width: 28px;
min-width: 28px;
padding: 0;
justify-content: center;
font-size: 12px;
}
/* 右下角折叠按钮 */
.article-content pre .itxgo-collapse-corner-btn {
display: none;
position: absolute;
bottom: 12px;
right: 12px;
z-index: 20;
background: transparent;
border: none;
font-size: 18px;
color: var(--itxgo-code-label);
cursor: pointer;
}
.article-content pre.itxgo-expanded .itxgo-collapse-corner-btn { display: block; }
.article-content pre .itxgo-collapse-corner-btn:hover { opacity: 1; }
/* 滚动条 */
.article-content pre.itxgo-code-block::-webkit-scrollbar { width: 8px; height: 8px; }
.article-content pre.itxgo-code-block::-webkit-scrollbar-track { background: transparent; border-radius: 6px; }
.article-content pre.itxgo-code-block::-webkit-scrollbar-thumb {
background: var(--itxgo-scrollbar-thumb);
border-radius: 4px;
}
.article-content pre.itxgo-code-block::-webkit-scrollbar-thumb:hover {
background: color-mix(in srgb, var(--itxgo-scrollbar-thumb) 80%, var(--itxgo-code-text));
}
/* 重置代码块内部元素样式 */
.article-content pre.itxgo-code-block code,
.article-content pre.itxgo-code-block code * {
background: transparent; padding: 0; margin: 0; border: none; border-radius: 0;
}
/* 行内代码 */
.article-content code:not(pre > code) {
font-family: Cascadia Code;
background-color: rgba(88, 166, 255, 0.1);
color: #58a6ff;
margin: 0 1px;
padding: 2px 6px;
border-radius: 4px;
font-size: 0.88em;
transition: all 0.2s ease;
}
.article-content code:not(pre > code):hover { background-color: rgba(88, 166, 255, 0.15); }
/* 响应式 */
@media (max-width: 768px) {
.article-content pre.itxgo-code-block {
font-size: 13px;
padding: 36px 12px 10px;
margin: 0.8rem -16px;
max-width: 100vw;
border-radius: 0;
}
.article-content pre .itxgo-code-tools { height: 34px; padding: 0 12px; }
.article-content pre .itxgo-code-btn { padding: 3px 8px; font-size: 11px; height: 26px; }
.article-content pre .itxgo-toggle { width: 26px; min-width: 26px; }
.article-content pre .itxgo-code-label { font-size: 11px; }
}
⚡️JS 代码:
1. 🔄代码块 JS 函数代码 - 2026年1月1日
// =============================
// 7. 代码块功能
// =============================
const CODE_CONFIG = {
COLLAPSE_LINE_THRESHOLD: 5,
COLLAPSE_LINES: 5,
COPY_FEEDBACK_DURATION: 1200,
RESIZE_DEBOUNCE_DELAY: 150,
};
async function initCodeBlocks() {
requestAnimationFrame(async () => {
if (document.fonts && document.fonts.ready) {
try {
await document.fonts.ready;
} catch (e) {
console.warn("Fonts ready failed", e);
}
}
const blocks = document.querySelectorAll(".article-content pre");
if (blocks.length === 0) return;
for (let i = 0; i < blocks.length; i++) {
await processBlock(blocks[i], i);
}
});
// Resize 处理
let resizeTimer = null;
window.addEventListener(
"resize",
() => {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(() => {
document
.querySelectorAll(".article-content pre.collapsed")
.forEach((pre) => {
const codeEl = pre.querySelector("code") || pre;
const cs = getComputedStyle(codeEl);
const fs = parseFloat(cs.fontSize) || 15;
const lh = parseFloat(cs.lineHeight) || fs * 1.6;
const ps = getComputedStyle(pre);
const pt = parseFloat(ps.paddingTop) || 48;
const pb = parseFloat(ps.paddingBottom) || 16;
const newHeight = Math.ceil(
pt + lh * CODE_CONFIG.COLLAPSE_LINES + pb
);
pre._collapsedHeight = newHeight;
pre.style.maxHeight = newHeight + "px";
});
}, CODE_CONFIG.RESIZE_DEBOUNCE_DELAY);
},
{ passive: true }
);
}
// 代码块处理逻辑分离
async function processBlock(pre, index) {
// 分片处理,避免在主线程阻塞太久(Safari 尤其敏感)
if (index > 0 && index % 5 === 0) {
await new Promise((resolve) => setTimeout(resolve, 0));
}
const codeEl = pre.querySelector("code") || pre;
// 使用 textContent 避免 innerText 触发重排
let raw = (codeEl.textContent || "")
.replace(/^\n+|\n+$/g, "")
.replace(/\r\n/g, "\n");
const lines = raw ? raw.split("\n") : [];
// ==================== 生成行号 ====================
if (!pre.hasAttribute("data-line-numbers")) {
const lineNumbersText = lines.map((_, i) => i + 1).join("\n");
pre.setAttribute("data-line-numbers", lineNumbersText);
}
// ==================== 工具栏 ====================
if (!pre.querySelector(".code-tools")) {
const shouldCollapse = lines.length > CODE_CONFIG.COLLAPSE_LINE_THRESHOLD;
const toggleBtnHTML = shouldCollapse
? '<button class="code-btn code-toggle" type="button">展开</button>'
: "";
const tools = document.createElement("div");
tools.className = "code-tools";
tools.innerHTML = `
<span class="code-title">CODE - iTxGo™️</span>
<div style="display:flex; gap:8px; align-items:center;">
${toggleBtnHTML}
<button class="code-btn code-copy" type="button" style="width:43px; min-width:43px; text-align:center;">复制</button>
</div>
`;
pre.insertBefore(tools, pre.firstChild);
}
// ==================== 复制功能 ====================
const copyBtn = pre.querySelector(".code-copy");
if (copyBtn && !copyBtn.hasListener) {
copyBtn.hasListener = true;
// Safari 下使用 touchstart 或确保 click 有效
copyBtn.addEventListener("click", async () => {
try {
await navigator.clipboard.writeText(raw);
showCopyFeedback(copyBtn);
} catch (e) {
// 降级处理
if (copyWithFallback(raw)) showCopyFeedback(copyBtn);
else showCopyError(copyBtn, "复制失败");
}
});
}
// ==================== 折叠功能 ====================
const shouldCollapse = lines.length > CODE_CONFIG.COLLAPSE_LINE_THRESHOLD;
if (!shouldCollapse) {
pre.classList.add("expanded");
pre.classList.remove("collapsed");
return;
}
// 计算折叠高度
const cs = getComputedStyle(codeEl);
const fontSize = parseFloat(cs.fontSize) || 15;
const lineHeight = parseFloat(cs.lineHeight) || fontSize * 1.6;
const ps = getComputedStyle(pre);
const paddingTop = parseFloat(ps.paddingTop) || 48;
const paddingBottom = parseFloat(ps.paddingBottom) || 16;
const collapsedHeight = Math.ceil(
paddingTop + lineHeight * CODE_CONFIG.COLLAPSE_LINES + paddingBottom
);
pre._collapsedHeight = collapsedHeight;
pre.style.maxHeight = collapsedHeight + "px";
pre.classList.add("collapsed");
pre.classList.remove("expanded");
// ==================== 折叠按钮事件 ====================
const toggleBtn = pre.querySelector(".code-toggle");
if (toggleBtn && !toggleBtn.hasListener) {
toggleBtn.hasListener = true;
toggleBtn.addEventListener("click", () => {
const isCollapsed = pre.classList.contains("collapsed");
if (isCollapsed) {
pre.classList.replace("collapsed", "expanded");
pre.style.maxHeight = "none";
toggleBtn.textContent = "折叠";
} else {
pre.classList.replace("expanded", "collapsed");
pre.style.maxHeight = pre._collapsedHeight + "px";
toggleBtn.textContent = "展开";
}
});
}
}
function copyWithFallback(text) {
try {
const textarea = document.createElement("textarea");
textarea.value = text;
// 防止 iOS 缩放和滚动
textarea.style.position = "fixed";
textarea.style.left = "-9999px";
textarea.style.top = "0";
document.body.appendChild(textarea);
textarea.select();
textarea.setSelectionRange(0, 99999); // 移动端兼容
const success = document.execCommand("copy");
document.body.removeChild(textarea);
return success;
} catch (err) {
return false;
}
}
function showCopyFeedback(btn) {
const originalText = btn.textContent;
btn.textContent = "✓";
btn.disabled = true;
btn.style.color = "#4ade80";
setTimeout(() => {
btn.textContent = originalText;
btn.disabled = false;
btn.style.color = "";
}, CODE_CONFIG.COPY_FEEDBACK_DURATION);
}
function showCopyError(btn, message) {
const originalText = btn.textContent;
btn.textContent = "失败";
btn.disabled = true;
btn.style.color = "#ef4444";
setTimeout(() => {
btn.textContent = originalText;
btn.disabled = false;
btn.style.color = "";
}, CODE_CONFIG.COPY_FEEDBACK_DURATION);
}
2. ✅️代码块 JS 函数代码 - AI风格 - 2026年1月12日
// =============================
// 7. 代码块功能
// =============================
const ITXGO_CODE_CONFIG = {
COLLAPSE_LINE_THRESHOLD: 10,
COLLAPSE_LINES: 10,
COPY_FEEDBACK_DURATION: 1200,
RESIZE_DEBOUNCE_DELAY: 150,
};
async function initItxgoCodeBlocks() {
// 观察DOM变化
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
mutation.addedNodes.forEach((node) => {
if (node.nodeType === 1) {
const newBlocks = node.querySelectorAll?.(".article-content pre:not(.itxgo-initialized)") || [];
newBlocks.forEach((block, index) => setTimeout(() => processItxgoBlock(block), index * 10));
}
});
});
});
observer.observe(document.body, { childList: true, subtree: true });
// 处理现有代码块
requestAnimationFrame(async () => {
if (document.fonts?.ready) {
try { await document.fonts.ready; } catch (e) {}
}
const blocks = document.querySelectorAll(".article-content pre:not(.itxgo-initialized)");
for (let i = 0; i < blocks.length; i++) {
await processItxgoBlock(blocks[i]);
}
});
// Resize 处理
let resizeTimer;
window.addEventListener("resize", () => {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(() => {
document.querySelectorAll(".article-content pre.itxgo-collapsed").forEach((pre) => {
const codeEl = pre.querySelector("code") || pre;
const cs = getComputedStyle(codeEl);
const fs = parseFloat(cs.fontSize) || 14;
const lh = parseFloat(cs.lineHeight) || fs * 1.4286;
const ps = getComputedStyle(pre);
const pt = parseFloat(ps.paddingTop) || 40;
const pb = parseFloat(ps.paddingBottom) || 12;
const newHeight = Math.ceil(pt + lh * ITXGO_CODE_CONFIG.COLLAPSE_LINES + pb);
pre._itxgoCollapsedHeight = newHeight;
pre.style.maxHeight = newHeight + "px";
});
}, ITXGO_CODE_CONFIG.RESIZE_DEBOUNCE_DELAY);
}, { passive: true });
}
async function processItxgoBlock(pre) {
if (pre.classList.contains('itxgo-initialized')) return;
pre.classList.add('itxgo-initialized', 'itxgo-code-block');
const codeEl = pre.querySelector("code") || pre;
const raw = (codeEl.textContent || "").replace(/^\n+|\n+$/g, "").replace(/\r\n/g, "\n");
const lines = raw.split("\n");
const shouldCollapse = lines.length > ITXGO_CODE_CONFIG.COLLAPSE_LINE_THRESHOLD;
// 添加工具栏
if (!pre.querySelector(".itxgo-code-tools")) {
const tools = document.createElement("div");
tools.className = "itxgo-code-tools";
tools.innerHTML = `
<div class="itxgo-code-header">
<span class="itxgo-code-label">CODE</span>
<div class="itxgo-code-actions">
${shouldCollapse ? '<button class="itxgo-code-btn itxgo-toggle" type="button" aria-label="展开代码">展开</button>' : ''}
<button class="itxgo-code-btn itxgo-copy" type="button" aria-label="复制代码">
<svg class="copy-icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
</svg>
<span class="copy-text">复制</span>
</button>
</div>
</div>
`;
pre.insertBefore(tools, pre.firstChild);
// 复制功能
const copyBtn = tools.querySelector(".itxgo-copy");
copyBtn.addEventListener("click", async (e) => {
e.stopPropagation();
try {
await navigator.clipboard.writeText(raw);
showFeedback(copyBtn, true);
} catch (e) {
showFeedback(copyBtn, copyWithFallback(raw));
}
});
// 折叠功能
if (shouldCollapse) {
const toggleBtn = tools.querySelector(".itxgo-toggle");
const cs = getComputedStyle(codeEl);
const fontSize = parseFloat(cs.fontSize) || 14;
const lineHeight = parseFloat(cs.lineHeight) || fontSize * 1.4286;
const ps = getComputedStyle(pre);
const paddingTop = parseFloat(ps.paddingTop) || 40;
const paddingBottom = parseFloat(ps.paddingBottom) || 12;
const collapsedHeight = Math.ceil(paddingTop + lineHeight * ITXGO_CODE_CONFIG.COLLAPSE_LINES + paddingBottom);
pre._itxgoCollapsedHeight = collapsedHeight;
pre.style.maxHeight = collapsedHeight + "px";
pre.classList.add("itxgo-collapsed");
const toggle = () => {
const isCollapsed = pre.classList.contains("itxgo-collapsed");
if (isCollapsed) {
pre.classList.replace("itxgo-collapsed", "itxgo-expanded");
pre.style.maxHeight = "none";
toggleBtn.textContent = '折叠';
toggleBtn.setAttribute('aria-label', '折叠代码');
} else {
pre.classList.replace("itxgo-expanded", "itxgo-collapsed");
pre.style.maxHeight = collapsedHeight + "px";
toggleBtn.textContent = '展开';
toggleBtn.setAttribute('aria-label', '展开代码');
}
};
toggleBtn.addEventListener("click", (e) => {
e.stopPropagation();
toggle();
});
pre.addEventListener('click', (e) => {
if (!e.target.closest('.itxgo-code-tools') && pre.classList.contains('itxgo-collapsed')) {
toggle();
}
});
} else {
pre.classList.add("itxgo-expanded");
}
}
}
function showFeedback(btn, success) {
const copyText = btn.querySelector('.copy-text');
const svgIcon = btn.querySelector('.copy-icon');
const originalText = copyText.textContent;
const originalSVG = svgIcon.innerHTML;
if (success) {
copyText.textContent = '复制';
svgIcon.innerHTML = '<path d="M20 6L9 17l-5-5" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>';
} else {
copyText.textContent = '复制失败';
}
setTimeout(() => {
copyText.textContent = originalText;
svgIcon.innerHTML = originalSVG;
}, ITXGO_CODE_CONFIG.COPY_FEEDBACK_DURATION);
}
function copyWithFallback(text) {
try {
const textarea = document.createElement("textarea");
textarea.value = text;
textarea.style.cssText = "position:fixed;left:-9999px;top:0";
document.body.appendChild(textarea);
textarea.select();
textarea.setSelectionRange(0, 99999);
const success = document.execCommand("copy");
document.body.removeChild(textarea);
return success;
} catch {
return false;
}
}
// 初始化
function initCodeBlocks() {
initItxgoCodeBlocks();
}
3. ✅️代码块 JS 函数代码 - AI风格 新增右下折叠按钮 - 2026年1月12日
// =============================
// 7. 代码块功能
// =============================
const ITXGO_CODE_CONFIG = {
COLLAPSE_LINE_THRESHOLD: 10,
COLLAPSE_LINES: 10,
COPY_FEEDBACK_DURATION: 1200,
RESIZE_DEBOUNCE_DELAY: 150,
};
async function initItxgoCodeBlocks() {
// 观察DOM变化
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
mutation.addedNodes.forEach((node) => {
if (node.nodeType === 1) {
const newBlocks = node.querySelectorAll?.(".article-content pre:not(.itxgo-initialized)") || [];
newBlocks.forEach((block, index) => setTimeout(() => processItxgoBlock(block), index * 10));
}
});
});
});
observer.observe(document.body, { childList: true, subtree: true });
// 处理现有代码块
requestAnimationFrame(async () => {
if (document.fonts?.ready) {
try { await document.fonts.ready; } catch (e) {}
}
const blocks = document.querySelectorAll(".article-content pre:not(.itxgo-initialized)");
for (let i = 0; i < blocks.length; i++) {
await processItxgoBlock(blocks[i]);
}
});
// Resize 处理
let resizeTimer;
window.addEventListener("resize", () => {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(() => {
document.querySelectorAll(".article-content pre.itxgo-collapsed").forEach((pre) => {
const codeEl = pre.querySelector("code") || pre;
const cs = getComputedStyle(codeEl);
const fs = parseFloat(cs.fontSize) || 14;
const lh = parseFloat(cs.lineHeight) || fs * 1.4286;
const ps = getComputedStyle(pre);
const pt = parseFloat(ps.paddingTop) || 40;
const pb = parseFloat(ps.paddingBottom) || 12;
const newHeight = Math.ceil(pt + lh * ITXGO_CODE_CONFIG.COLLAPSE_LINES + pb);
pre._itxgoCollapsedHeight = newHeight;
pre.style.maxHeight = newHeight + "px";
});
}, ITXGO_CODE_CONFIG.RESIZE_DEBOUNCE_DELAY);
}, { passive: true });
}
async function processItxgoBlock(pre) {
if (pre.classList.contains('itxgo-initialized')) return;
pre.classList.add('itxgo-initialized', 'itxgo-code-block');
const codeEl = pre.querySelector("code") || pre;
const raw = (codeEl.textContent || "").replace(/^\n+|\n+$/g, "").replace(/\r\n/g, "\n");
const lines = raw.split("\n");
const shouldCollapse = lines.length > ITXGO_CODE_CONFIG.COLLAPSE_LINE_THRESHOLD;
// 添加工具栏
if (!pre.querySelector(".itxgo-code-tools")) {
const tools = document.createElement("div");
tools.className = "itxgo-code-tools";
tools.innerHTML = `
<div class="itxgo-code-header">
<span class="itxgo-code-label">CODE</span>
<div class="itxgo-code-actions">
${shouldCollapse ? '<button class="itxgo-code-btn itxgo-toggle" type="button" aria-label="展开代码">展开</button>' : ''}
<button class="itxgo-code-btn itxgo-copy" type="button" aria-label="复制代码">
<svg class="copy-icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
</svg>
<span class="copy-text">复制</span>
</button>
</div>
</div>
`;
pre.insertBefore(tools, pre.firstChild);
// 复制功能
const copyBtn = tools.querySelector(".itxgo-copy");
copyBtn.addEventListener("click", async (e) => {
e.stopPropagation();
try {
await navigator.clipboard.writeText(raw);
showFeedback(copyBtn, true);
} catch (e) {
showFeedback(copyBtn, copyWithFallback(raw));
}
});
// 折叠功能
if (shouldCollapse) {
const toggleBtn = tools.querySelector(".itxgo-toggle");
// 右下角折叠按钮
const cornerBtn = document.createElement("button");
cornerBtn.className = "itxgo-collapse-corner-btn";
cornerBtn.type = "button";
cornerBtn.innerHTML = "︽";
cornerBtn.setAttribute('aria-label', '折叠代码');
// 仅用于折叠 展开由原有toggleBtn或点击pre处理
cornerBtn.addEventListener("click", (e) => {
e.stopPropagation();
// 只有在展开状态下才有效
if (!pre.classList.contains("itxgo-collapsed")) {
pre.classList.replace("itxgo-expanded", "itxgo-collapsed");
pre.style.maxHeight = pre._itxgoCollapsedHeight + "px";
// 同步更新原有工具栏按钮状态
if(toggleBtn) {
toggleBtn.textContent = '展开';
toggleBtn.setAttribute('aria-label', '展开代码');
}
}
});
pre.appendChild(cornerBtn);
// 计算折叠高度
const cs = getComputedStyle(codeEl);
const fontSize = parseFloat(cs.fontSize) || 14;
const lineHeight = parseFloat(cs.lineHeight) || fontSize * 1.4286;
const ps = getComputedStyle(pre);
const paddingTop = parseFloat(ps.paddingTop) || 40;
const paddingBottom = parseFloat(ps.paddingBottom) || 12;
const collapsedHeight = Math.ceil(paddingTop + lineHeight * ITXGO_CODE_CONFIG.COLLAPSE_LINES + paddingBottom);
pre._itxgoCollapsedHeight = collapsedHeight;
pre.style.maxHeight = collapsedHeight + "px";
pre.classList.add("itxgo-collapsed");
const toggle = () => {
const isCollapsed = pre.classList.contains("itxgo-collapsed");
if (isCollapsed) {
pre.classList.replace("itxgo-collapsed", "itxgo-expanded");
pre.style.maxHeight = "none";
toggleBtn.textContent = '折叠';
toggleBtn.setAttribute('aria-label', '折叠代码');
} else {
pre.classList.replace("itxgo-expanded", "itxgo-collapsed");
pre.style.maxHeight = collapsedHeight + "px";
toggleBtn.textContent = '展开';
toggleBtn.setAttribute('aria-label', '展开代码');
}
};
// 工具栏按钮点击事件
toggleBtn.addEventListener("click", (e) => {
e.stopPropagation();
toggle();
});
// 点击代码块空白处展开事件
pre.addEventListener('click', (e) => {
if (!e.target.closest('.itxgo-code-tools') && pre.classList.contains('itxgo-collapsed')) {
toggle();
}
});
} else {
pre.classList.add("itxgo-expanded");
}
}
}
function showFeedback(btn, success) {
const copyText = btn.querySelector('.copy-text');
const svgIcon = btn.querySelector('.copy-icon');
const originalText = copyText.textContent;
const originalSVG = svgIcon.innerHTML;
if (success) {
copyText.textContent = '复制';
svgIcon.innerHTML = '<path d="M20 6L9 17l-5-5" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>';
} else {
copyText.textContent = '复制失败';
}
setTimeout(() => {
copyText.textContent = originalText;
svgIcon.innerHTML = originalSVG;
}, ITXGO_CODE_CONFIG.COPY_FEEDBACK_DURATION);
}
function copyWithFallback(text) {
try {
const textarea = document.createElement("textarea");
textarea.value = text;
textarea.style.cssText = "position:fixed;left:-9999px;top:0";
document.body.appendChild(textarea);
textarea.select();
textarea.setSelectionRange(0, 99999);
const success = document.execCommand("copy");
document.body.removeChild(textarea);
return success;
} catch {
return false;
}
}
// 初始化
function initCodeBlocks() {
initItxgoCodeBlocks();
}
4. ✅️代码块 JS 函数代码 - AI风格 代码高亮版 - 2026年1月13日
// =============================
// 代码块功能(含自动语法高亮识别)
// =============================
const ITXGO_CODE_CONFIG = {
COLLAPSE_LINE_THRESHOLD: 10,
COLLAPSE_LINES: 10,
COPY_FEEDBACK_DURATION: 1200,
RESIZE_DEBOUNCE_DELAY: 150,
PRISM_CDN: 'https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/prism.min.js',
// 常用语言组件映射
LANGUAGE_COMPONENTS: {
'javascript': 'prism-javascript',
'js': 'prism-javascript',
'typescript': 'prism-typescript',
'ts': 'prism-typescript',
'python': 'prism-python',
'py': 'prism-python',
'java': 'prism-java',
'cpp': 'prism-cpp',
'c': 'prism-c',
'csharp': 'prism-csharp',
'cs': 'prism-csharp',
'php': 'prism-php',
'ruby': 'prism-ruby',
'go': 'prism-go',
'rust': 'prism-rust',
'sql': 'prism-sql',
'bash': 'prism-bash',
'shell': 'prism-bash',
'json': 'prism-json',
'yaml': 'prism-yaml',
'xml': 'prism-markup',
'html': 'prism-markup',
'css': 'prism-css',
'scss': 'prism-scss',
'markdown': 'prism-markdown',
'md': 'prism-markdown'
}
};
// 加载 Prism.js 及语言组件
let prismLoaded = false;
let prismLoading = false;
const loadedLanguages = new Set(['markup', 'css', 'clike', 'javascript']); // Prism 核心包含的语言
async function loadPrism() {
if (prismLoaded) return true;
if (prismLoading) {
return new Promise((resolve) => {
const check = setInterval(() => {
if (prismLoaded) {
clearInterval(check);
resolve(true);
}
}, 100);
});
}
prismLoading = true;
return new Promise((resolve, reject) => {
const script = document.createElement('script');
script.src = ITXGO_CODE_CONFIG.PRISM_CDN;
script.onload = () => {
prismLoaded = true;
prismLoading = false;
if (window.Prism) {
window.Prism.manual = true;
}
resolve(true);
};
script.onerror = () => {
prismLoading = false;
console.error('Failed to load Prism.js');
reject(false);
};
document.head.appendChild(script);
});
}
// 加载特定语言的组件
async function loadLanguageComponent(language) {
if (!language || loadedLanguages.has(language)) return true;
const componentName = ITXGO_CODE_CONFIG.LANGUAGE_COMPONENTS[language.toLowerCase()];
if (!componentName) return true;
return new Promise((resolve) => {
const script = document.createElement('script');
script.src = `https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/${componentName}.min.js`;
script.onload = () => {
loadedLanguages.add(language);
resolve(true);
};
script.onerror = () => {
console.warn(`Failed to load Prism component: ${componentName}`);
resolve(false);
};
document.head.appendChild(script);
});
}
// 自动检测代码语言
function autoDetectLanguage(code) {
const trimmed = code.trim();
// JavaScript/TypeScript 特征
if (/^(import|export|const|let|var|function|class)\s/.test(trimmed) ||
/=>\s*{/.test(trimmed) ||
/\bconsole\.(log|error|warn)/.test(trimmed) ||
/(async|await)\s/.test(trimmed)) {
if (/:\s*(string|number|boolean|any)\s*[;=)]/.test(trimmed) || /interface\s+\w+/.test(trimmed)) {
return 'typescript';
}
return 'javascript';
}
// Python 特征
if (/^(def|class|import|from|if __name__|print\()\s/.test(trimmed) ||
/:\s*$/.test(trimmed.split('\n')[0]) ||
/\bself\.\w+/.test(trimmed)) {
return 'python';
}
// HTML 特征
if (/^<!DOCTYPE html>|^<html|^<\!--/.test(trimmed) ||
/<(div|span|p|h[1-6]|body|head|meta|link)[\s>]/.test(trimmed)) {
return 'html';
}
// CSS 特征
if (/^[.#]?[\w-]+\s*{/.test(trimmed) ||
/@(media|keyframes|import)\s/.test(trimmed) ||
/:\s*[^;]+;/.test(trimmed.split('\n')[0])) {
return 'css';
}
// Java 特征
if (/^(public|private|protected|class|interface)\s/.test(trimmed) ||
/System\.(out|err)\.print/.test(trimmed) ||
/\bpublic static void main\(/.test(trimmed)) {
return 'java';
}
// PHP 特征
if (/^<\?php/.test(trimmed) || /\$\w+\s*=/.test(trimmed)) {
return 'php';
}
// C/C++ 特征
if (/#include\s*</.test(trimmed) ||
/^(int|void|char|float|double)\s+\w+\s*\(/.test(trimmed)) {
if (/std::|iostream|vector|string/.test(trimmed)) {
return 'cpp';
}
return 'c';
}
// JSON 特征
if (/^\s*[{\[]/.test(trimmed) && /[}\]]\s*$/.test(trimmed)) {
try {
JSON.parse(trimmed);
return 'json';
} catch (e) {
// 不是有效的JSON
}
}
// SQL 特征
if (/^(SELECT|INSERT|UPDATE|DELETE|CREATE|ALTER|DROP)\s+/i.test(trimmed)) {
return 'sql';
}
// Bash/Shell 特征
if (/^#!\/bin\/(bash|sh)/.test(trimmed) ||
/^(echo|cd|ls|mkdir|rm|cp|mv|grep|cat)\s/.test(trimmed) ||
/\$\{?\w+\}?/.test(trimmed)) {
return 'bash';
}
// YAML 特征
if (/^\w+:\s*$/.test(trimmed.split('\n')[0]) && !/[{}]/.test(trimmed)) {
return 'yaml';
}
return null; // 无法识别
}
// 检测代码块语言(优先使用标记的语言)
function detectLanguage(codeElement) {
// 从 class 中检测 language-xxx
const classes = codeElement.className.split(' ');
for (const cls of classes) {
if (cls.startsWith('language-')) {
return cls.replace('language-', '');
}
}
// 从父元素 pre 检测
const pre = codeElement.closest('pre');
if (pre) {
const preClasses = pre.className.split(' ');
for (const cls of preClasses) {
if (cls.startsWith('language-')) {
return cls.replace('language-', '');
}
}
}
// 如果没有标记,尝试自动检测
const code = codeElement.textContent || '';
return autoDetectLanguage(code);
}
// 应用语法高亮
async function applyHighlight(codeElement, language) {
if (!window.Prism || !language) return false;
try {
await loadLanguageComponent(language);
if (!codeElement.classList.contains(`language-${language}`)) {
codeElement.classList.add(`language-${language}`);
}
window.Prism.highlightElement(codeElement);
return true;
} catch (e) {
console.error('Highlight error:', e);
return false;
}
}
async function initItxgoCodeBlocks() {
// 预加载 Prism.js
loadPrism().catch(() => {
console.warn('Prism.js not available, syntax highlighting disabled');
});
// 观察DOM变化
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
mutation.addedNodes.forEach((node) => {
if (node.nodeType === 1) {
const newBlocks = node.querySelectorAll?.(".article-content pre:not(.itxgo-initialized)") || [];
newBlocks.forEach((block, index) => setTimeout(() => processItxgoBlock(block), index * 10));
}
});
});
});
observer.observe(document.body, { childList: true, subtree: true });
// 处理现有代码块
requestAnimationFrame(async () => {
if (document.fonts?.ready) {
try { await document.fonts.ready; } catch (e) {}
}
const blocks = document.querySelectorAll(".article-content pre:not(.itxgo-initialized)");
for (let i = 0; i < blocks.length; i++) {
await processItxgoBlock(blocks[i]);
}
});
// Resize 处理
let resizeTimer;
window.addEventListener("resize", () => {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(() => {
document.querySelectorAll(".article-content pre.itxgo-collapsed").forEach((pre) => {
const codeEl = pre.querySelector("code") || pre;
const cs = getComputedStyle(codeEl);
const fs = parseFloat(cs.fontSize) || 14;
const lh = parseFloat(cs.lineHeight) || fs * 1.4286;
const ps = getComputedStyle(pre);
const pt = parseFloat(ps.paddingTop) || 40;
const pb = parseFloat(ps.paddingBottom) || 12;
const newHeight = Math.ceil(pt + lh * ITXGO_CODE_CONFIG.COLLAPSE_LINES + pb);
pre._itxgoCollapsedHeight = newHeight;
pre.style.maxHeight = newHeight + "px";
});
}, ITXGO_CODE_CONFIG.RESIZE_DEBOUNCE_DELAY);
}, { passive: true });
}
async function processItxgoBlock(pre) {
if (pre.classList.contains('itxgo-initialized')) return;
pre.classList.add('itxgo-initialized', 'itxgo-code-block');
const codeEl = pre.querySelector("code") || pre;
const raw = (codeEl.textContent || "").replace(/^\n+|\n+$/g, "").replace(/\r\n/g, "\n");
const lines = raw.split("\n");
const shouldCollapse = lines.length > ITXGO_CODE_CONFIG.COLLAPSE_LINE_THRESHOLD;
// 检测语言并应用高亮
const language = detectLanguage(codeEl);
if (prismLoaded && language) {
await applyHighlight(codeEl, language);
} else if (!prismLoaded && language) {
loadPrism().then(() => {
applyHighlight(codeEl, language);
});
}
// 更新工具栏语言标签
const languageLabel = language ? language.toUpperCase() : 'CODE';
// 添加工具栏
if (!pre.querySelector(".itxgo-code-tools")) {
const tools = document.createElement("div");
tools.className = "itxgo-code-tools";
tools.innerHTML = `
<div class="itxgo-code-header">
<span class="itxgo-code-label">${languageLabel}</span>
<div class="itxgo-code-actions">
${shouldCollapse ? '<button class="itxgo-code-btn itxgo-toggle" type="button" aria-label="展开代码">展开</button>' : ''}
<button class="itxgo-code-btn itxgo-copy" type="button" aria-label="复制代码">
<svg class="copy-icon" width="15" height="15" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill="currentColor" d="M6.149 4.02c.963 0 1.73-.002 2.347.055.626.057 1.163.176 1.646.456.58.334 1.06.815 1.395 1.394.279.484.398 1.02.455 1.646.056.616.055 1.384.055 2.346 0 .963.002 1.73-.055 2.347-.057.626-.176 1.163-.456 1.646-.334.58-.815 1.06-1.394 1.395-.484.279-1.02.398-1.646.455-.616.056-1.384.055-2.347.055-.962 0-1.73.002-2.346-.055-.626-.057-1.163-.176-1.646-.456-.58-.334-1.06-.815-1.394-1.394-.28-.484-.4-1.02-.456-1.646-.056-.616-.056-1.384-.056-2.347 0-.962-.002-1.73.055-2.346.057-.626.177-1.163.456-1.646.335-.58.816-1.06 1.395-1.394.484-.28 1.02-.4 1.646-.456.616-.056 1.384-.056 2.347-.056Zm0 1.358c-.987 0-1.683.002-2.224.049-.53.048-.846.139-1.089.279-.373.215-.682.525-.898.897-.14.243-.231.559-.279 1.09-.049.54-.049 1.236-.049 2.224 0 .987-.002 1.683.049 2.224.048.53.139.846.279 1.089.215.372.525.682.897.897.243.14.559.231 1.09.279.54.049 1.236.049 2.224.049.987 0 1.683-.002 2.224-.049.53-.048.846-.139 1.089-.279.372-.215.682-.525.897-.897.14-.243.231-.559.279-1.09.049-.54.049-1.236.049-2.224 0-.987.002-1.683-.049-2.224-.048-.53-.139-.846-.279-1.089-.215-.373-.525-.682-.897-.897-.243-.14-.559-.231-1.09-.279-.54-.049-1.236-.049-2.224-.049Zm3.652-5.01c.963 0 1.73-.002 2.346.056.625.057 1.162.175 1.646.455.578.334 1.059.815 1.393 1.394.28.484.4 1.02.456 1.646.056.616.055 1.384.055 2.346v1.566c0 .462.002.76-.032 1.018-.199 1.504-1.265 2.725-2.682 3.15V11c.714-.356 1.227-1.05 1.336-1.875.019-.148.021-.336.021-.842V6.264c0-.987-.002-1.683-.049-2.224-.048-.53-.139-.846-.279-1.089-.215-.372-.525-.682-.897-.897-.243-.14-.559-.231-1.09-.279-.54-.049-1.236-.049-2.224-.049H7.715c-.959.002-1.788.553-2.192 1.355H4.07c.472-1.568 1.923-2.71 3.645-2.711h2.087Z"/></svg>
<span class="copy-text">复制</span>
</button>
</div>
</div>
`;
pre.insertBefore(tools, pre.firstChild);
// 复制功能
const copyBtn = tools.querySelector(".itxgo-copy");
copyBtn.addEventListener("click", async (e) => {
e.stopPropagation();
try {
await navigator.clipboard.writeText(raw);
showFeedback(copyBtn, true);
} catch (e) {
showFeedback(copyBtn, copyWithFallback(raw));
}
});
// 折叠功能
if (shouldCollapse) {
const toggleBtn = tools.querySelector(".itxgo-toggle");
const cornerBtn = document.createElement("button");
cornerBtn.className = "itxgo-collapse-corner-btn";
cornerBtn.type = "button";
cornerBtn.innerHTML = `<svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="currentColor"><g stroke="currentColor" stroke-width="20" stroke-linecap="round" stroke-linejoin="round"><path d="M125.3 176.1h742.4c15.8 0 28.7-10.6 28.7-23.6s-12.9-23.6-28.7-23.6H125.3c-15.8 0-28.7 10.6-28.7 23.6 0 13 12.9 23.6 28.7 23.6z"/><path d="M492.5 385.2H125.3c-15.4 0-28.1 10.6-28.1 23.6 0 12.9 12.7 23.6 28.1 23.6h367.2c15.4 0 28.1-10.7 28.1-23.6 0-12.9-12.7-23.6-28.1-23.6z"/><path d="M492.5 594.3H125.3c-15.4 0-28.1 10.6-28.1 23.6 0 13.1 12.7 23.6 28.1 23.6h367.2c15.4 0 28.1-10.7 28.1-23.6 0-13.1-12.7-23.6-28.1-23.6z"/><path d="M492.1 803.4H126c-15.8 0-28.7 10.6-28.7 23.6 0 13.1 12.7 23.6 28.7 23.6h366.2c15.8 0 28.7-10.7 28.7-23.6 0-13.1-12.9-23.6-28.7-23.6z"/><path d="M926.31 502.17c1.02-2.25-0.2-9.22-7.78-18.64L819.2 359.42c-8.19-10.24-18.64-15.77-29.49-15.77-10.85 0-21.5 5.53-29.49 15.77L661.09 483.33c-7.78 9.63-9.01 16.59-7.99 18.64 1.43 2.66 8.19 6.35 22.53 6.35h90.52v306.38c0 15.36 10.44 28.06 23.55 28.06s23.55-12.7 23.55-28.06V508.31h90.52c14.34 0 21.5-3.69 22.53-6.14z"/></g></svg>`;
cornerBtn.setAttribute('aria-label', '折叠代码');
cornerBtn.title = "折叠";
cornerBtn.addEventListener("click", (e) => {
e.stopPropagation();
if (!pre.classList.contains("itxgo-collapsed")) {
pre.classList.replace("itxgo-expanded", "itxgo-collapsed");
pre.style.maxHeight = pre._itxgoCollapsedHeight + "px";
if(toggleBtn) {
toggleBtn.textContent = '展开';
toggleBtn.setAttribute('aria-label', '展开代码');
}
}
});
pre.appendChild(cornerBtn);
const cs = getComputedStyle(codeEl);
const fontSize = parseFloat(cs.fontSize) || 14;
const lineHeight = parseFloat(cs.lineHeight) || fontSize * 1.4286;
const ps = getComputedStyle(pre);
const paddingTop = parseFloat(ps.paddingTop) || 40;
const paddingBottom = parseFloat(ps.paddingBottom) || 12;
const collapsedHeight = Math.ceil(paddingTop + lineHeight * ITXGO_CODE_CONFIG.COLLAPSE_LINES + paddingBottom);
pre._itxgoCollapsedHeight = collapsedHeight;
pre.style.maxHeight = collapsedHeight + "px";
pre.classList.add("itxgo-collapsed");
const toggle = () => {
const isCollapsed = pre.classList.contains("itxgo-collapsed");
if (isCollapsed) {
pre.classList.replace("itxgo-collapsed", "itxgo-expanded");
pre.style.maxHeight = "none";
toggleBtn.textContent = '折叠';
toggleBtn.setAttribute('aria-label', '折叠代码');
} else {
pre.classList.replace("itxgo-expanded", "itxgo-collapsed");
pre.style.maxHeight = collapsedHeight + "px";
toggleBtn.textContent = '展开';
toggleBtn.setAttribute('aria-label', '展开代码');
}
};
toggleBtn.addEventListener("click", (e) => {
e.stopPropagation();
toggle();
});
pre.addEventListener('click', (e) => {
if (!e.target.closest('.itxgo-code-tools') && pre.classList.contains('itxgo-collapsed')) {
toggle();
}
});
} else {
pre.classList.add("itxgo-expanded");
}
}
}
function showFeedback(btn, success) {
const copyText = btn.querySelector('.copy-text');
const svgIcon = btn.querySelector('.copy-icon');
const originalText = copyText.textContent;
const originalSVG = svgIcon.innerHTML;
if (success) {
copyText.textContent = '复制';
svgIcon.innerHTML = '<path d="M3 8.5L6 11.5L12 5.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>';
} else {
copyText.textContent = '复制失败';
}
setTimeout(() => {
copyText.textContent = originalText;
svgIcon.innerHTML = originalSVG;
}, ITXGO_CODE_CONFIG.COPY_FEEDBACK_DURATION);
}
function copyWithFallback(text) {
try {
const textarea = document.createElement("textarea");
textarea.value = text;
textarea.style.cssText = "position:fixed;left:-9999px;top:0";
document.body.appendChild(textarea);
textarea.select();
textarea.setSelectionRange(0, 99999);
const success = document.execCommand("copy");
document.body.removeChild(textarea);
return success;
} catch {
return false;
}
}
// 初始化
function initCodeBlocks() {
initItxgoCodeBlocks();
}
5. ✅️代码块 JS 函数代码 - 终版 - 2026年1月15日
// =============================
// 7. 代码块功能 - chat.z.ai
// =============================
const ITXGO_CODE_CONFIG = {
COLLAPSE_LINES: 10,
THRESHOLD: 10,
COPY_DURATION: 1000,
RESIZE_DELAY: 150,
BASE_CDN: 'https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/',
CHUNK_SIZE: 2
};
// 常量管理
const ICONS = {
COPY: `<svg class="copy-icon" width="15" height="15" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill="currentColor" d="M6.149 4.02c.963 0 1.73-.002 2.347.055.626.057 1.163.176 1.646.456.58.334 1.06.815 1.395 1.394.279.484.398 1.02.455 1.646.056.616.055 1.384.055 2.346 0 .963.002 1.73-.055 2.347-.057.626-.176 1.163-.456 1.646-.334.58-.815 1.06-1.394 1.395-.484.279-1.02.398-1.646.455-.616.056-1.384.055-2.347.055-.962 0-1.73.002-2.346-.055-.626-.057-1.163-.176-1.646-.456-.58-.334-1.06-.815-1.394-1.394-.28-.484-.4-1.02-.456-1.646-.056-.616-.056-1.384-.056-2.347 0-.962-.002-1.73.055-2.346.057-.626.177-1.163.456-1.646.335-.58.816-1.06 1.395-1.394.484-.28 1.02-.4 1.646-.456.616-.056 1.384-.056 2.347-.056Zm0 1.358c-.987 0-1.683.002-2.224.049-.53.048-.846.139-1.089.279-.373.215-.682.525-.898.897-.14.243-.231.559-.279 1.09-.049.54-.049 1.236-.049 2.224 0 .987-.002 1.683.049 2.224.048.53.139.846.279 1.089.215.372.525.682.897.897.243.14.559.231 1.09.279.54.049 1.236.049 2.224.049.987 0 1.683-.002 2.224-.049.53-.048.846-.139 1.089-.279.372-.215.682-.525.897-.897.14-.243.231-.559.279-1.09.049-.54.049-1.236.049-2.224 0-.987.002-1.683-.049-2.224-.048-.53-.139-.846-.279-1.089-.215-.373-.525-.682-.897-.897-.243-.14-.559-.231-1.09-.279-.54-.049-1.236-.049-2.224-.049Zm3.652-5.01c.963 0 1.73-.002 2.346.056.625.057 1.162.175 1.646.455.578.334 1.059.815 1.393 1.394.28.484.4 1.02.456 1.646.056.616.055 1.384.055 2.346v1.566c0 .462.002.76-.032 1.018-.199 1.504-1.265 2.725-2.682 3.15V11c.714-.356 1.227-1.05 1.336-1.875.019-.148.021-.336.021-.842V6.264c0-.987-.002-1.683-.049-2.224-.048-.53-.139-.846-.279-1.089-.215-.372-.525-.682-.897-.897-.243-.14-.559-.231-1.09-.279-.54-.049-1.236-.049-2.224-.049H7.715c-.959.002-1.788.553-2.192 1.355H4.07c.472-1.568 1.923-2.71 3.645-2.711h2.087Z"/></svg>`,
COLLAPSE: `<svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="currentColor"><g stroke="currentColor" stroke-width="20" stroke-linecap="round" stroke-linejoin="round"><path d="M125.3 176.1h742.4c15.8 0 28.7-10.6 28.7-23.6s-12.9-23.6-28.7-23.6H125.3c-15.8 0-28.7 10.6-28.7 23.6 0 13 12.9 23.6 28.7 23.6z"/><path d="M492.5 385.2H125.3c-15.4 0-28.1 10.6-28.1 23.6 0 12.9 12.7 23.6 28.1 23.6h367.2c15.4 0 28.1-10.7 28.1-23.6 0-12.9-12.7-23.6-28.1-23.6z"/><path d="M492.5 594.3H125.3c-15.4 0-28.1 10.6-28.1 23.6 0 13.1 12.7 23.6 28.1 23.6h367.2c15.4 0 28.1-10.7 28.1-23.6 0-13.1-12.7-23.6-28.1-23.6z"/><path d="M492.1 803.4H126c-15.8 0-28.7 10.6-28.7 23.6 0 13.1 12.7 23.6 28.7 23.6h366.2c15.8 0 28.7-10.7 28.7-23.6 0-13.1-12.9-23.6-28.7-23.6z"/><path d="M926.31 502.17c1.02-2.25-0.2-9.22-7.78-18.64L819.2 359.42c-8.19-10.24-18.64-15.77-29.49-15.77-10.85 0-21.5 5.53-29.49 15.77L661.09 483.33c-7.78 9.63-9.01 16.59-7.99 18.64 1.43 2.66 8.19 6.35 22.53 6.35h90.52v306.38c0 15.36 10.44 28.06 23.55 28.06s23.55-12.7 23.55-28.06V508.31h90.52c14.34 0 21.5-3.69 22.53-6.14z"/></g></svg>`
};
let prismLoaded = false, prismLoading = false;
const loadedLanguages = new Set(['markup', 'css', 'clike', 'javascript']);
const LANG_MAP = { js: 'javascript', ts: 'typescript', py: 'python', rb: 'ruby', cs: 'csharp', sh: 'bash', md: 'markdown', yaml: 'yaml' };
// ===== 异步加载 =====
function loadScript(src) {
return new Promise((resolve, reject) => {
const s = document.createElement('script');
s.src = src; s.onload = resolve; s.onerror = reject;
document.head.appendChild(s);
});
}
async function loadPrism() {
if (prismLoaded) return true;
if (prismLoading) return new Promise(r => setTimeout(r, 50)); // 异步等待 不阻塞
prismLoading = true;
try {
await loadScript(ITXGO_CODE_CONFIG.BASE_CDN + 'prism.min.js');
prismLoaded = true;
if (window.Prism) Prism.manual = true;
} catch (e) { console.warn('Prism load failed'); }
finally { prismLoading = false; }
return prismLoaded;
}
async function loadLangComp(lang) {
if (lang === 'html' || lang === 'markup') {
if (loadedLanguages.has('markup')) return true;
loadedLanguages.add('markup');
return true;
}
if (!lang || loadedLanguages.has(lang)) return true;
const key = LANG_MAP[lang] || lang;
if (!key) return true;
if (key === 'markup') {
loadedLanguages.add('markup');
return true;
}
return new Promise(resolve => {
const s = document.createElement('script');
s.src = `${ITXGO_CODE_CONFIG.BASE_CDN}components/prism-${key}.min.js`;
s.onload = () => {
loadedLanguages.add(lang);
resolve(true);
};
s.onerror = () => {
resolve(false);
};
document.head.appendChild(s);
});
}
async function runInChunks(items, processFn) {
const { CHUNK_SIZE } = ITXGO_CODE_CONFIG;
for (let i = 0; i < items.length; i += CHUNK_SIZE) {
const chunk = items.slice(i, i + CHUNK_SIZE);
chunk.forEach(processFn);
applyCollapseHeights(chunk);
// 标记代码块准备就绪,触发淡入动画
chunk.forEach(pre => {
if (!pre.classList.contains('itxgo-ready')) {
pre.classList.add('itxgo-ready');
}
});
if (i + CHUNK_SIZE < items.length) await new Promise(r => requestAnimationFrame(r));
}
}
// ===== 代码语言判断核心逻辑 =====
function getLanguage(el) {
const classMatch = (e) => e && (e.className || '').match(/language-(\w+)/);
let m = classMatch(el) || classMatch(el.closest('pre'));
if (m) return m[1];
const text = (el.textContent || '').trim();
const sample = text.slice(0, 500);
const RULES = {
css: {
threshold: 15,
score: [
[/--[\w-]+\s*:/, 10],
[/@media|@keyframes|@import|@font-face|:root|@supports/, 10],
[/([.#]?[\w-]+\s*,?\s*[{])/, 5],
[/(display|color|background|margin|padding|border|font-size|position)\s*:\s*[^;]+;/, 5],
],
},
javascript: {
threshold: 10,
score: [
[/\b(const|let|async|await|import|export)\b/, 10],
[/\bvar\s+[a-zA-Z_$]/, 10],
[/\b(function|class)\s+[a-zA-Z_$][\w$]*\s*\(/, 10],
[/=>\s*[{(]/, 8],
[/\b(console|document|window|JSON)\./, 8],
[/\.then\(|\.catch\(|new Promise\(/, 8],
],
postDetect: (s) =>
/\b(interface|type|enum|implements|: string|: number|: any)\b/.test(s)
? 'typescript'
: null,
},
html: {
threshold: 10,
score: [
[/^<!DOCTYPE|<html|<head|<body|<div|<span|<p\s/i, 15],
[/<\/[\w]+>/, 10],
],
result: 'markup',
},
};
// 统一打分
const scores = {};
for (const lang in RULES) {
let total = 0;
for (const [regex, weight] of RULES[lang].score) {
if (regex.test(sample)) total += weight;
}
scores[lang] = total;
}
// 选择最高得分
let winner = null;
let maxScore = 0;
for (const lang in scores) {
if (scores[lang] > maxScore) {
maxScore = scores[lang];
winner = lang;
}
}
if (winner && maxScore >= RULES[winner].threshold) {
const rule = RULES[winner];
if (rule.postDetect) {
const refined = rule.postDetect(sample);
if (refined) return refined;
}
return rule.result || winner;
}
// --- 特殊语言判定(确定性规则) ---
// JSON (需要完整的 text)
try {
if (/^\s*[{[]/.test(text) && /[}\]]\s*$/.test(text)) {
JSON.parse(text);
return 'json';
}
} catch (e) {}
// Python (使用 /m 修饰符以支持多行检测)
if (/^(def |class |import |from |if __name__|print\(|self\.|try:|except:)/m.test(sample)) return 'python';
if (/^(public|private|protected|class|interface|enum|package)\s|System\.out\.print|@Override/m.test(sample)) return 'java';
if (/^<\?php|\$\w+\s*=|namespace\s+|use\s+[\w\\]+;/m.test(sample)) return 'php';
if (/#include <|(int|void|char|float|double|bool)\s+\w+\s*[\(\{]|std::|cout|cin|endl/.test(sample))
return /std::|vector|namespace|class\s+\w+/.test(sample) ? 'cpp' : 'c';
if (/^(SELECT|INSERT|UPDATE|DELETE|CREATE|ALTER|DROP|TRUNCATE|GRANT|REVOKE)\s+/i.test(sample)) return 'sql';
if (/^#!\/(bin\/bash|bin\/sh|usr\/bin\/env)|^(echo|cd|ls|mkdir|rm|cp|mv|grep|sudo|npm|git|docker|curl|wget)\b/m.test(sample))
return 'bash';
if (/^package\s+main|func\s+\w+\(|go\s+func|import\s+\(/.test(sample)) return 'go';
if (/^require\s|def\s+\w+|end$|puts\s|class\s+\w+/m.test(sample)) return 'ruby';
if (/^fn\s+main|let\s+mut\b|use\s+std::|impl\s+\w+/.test(sample)) return 'rust';
if (/^import\s+(Foundation|UIKit|Swift)|func\s+\w+|@IBOutlet/.test(sample)) return 'swift';
if (/^fun\s+|val\s+\w+|class\s+\w+:/m.test(sample)) return 'kotlin';
if (/^[\w-]+:\s*\n|^\s+-\s+/.test(sample)) return 'yaml';
if (/^#{1,6}\s|^\*{3,}$|^\-{3,}$|^\[.*\]\(.*\)|^\d+\.\s|^\>\s/.test(sample)) return 'markdown';
// --- 最终兜底 ---
if (/[{}]\s*;/.test(sample) && (scores.javascript || 0) < 5) return 'css';
return 'plaintext';
}
async function applyHighlight(el, lang) {
if (!window.Prism || !lang) return;
await loadLangComp(lang);
el.classList.add(`language-${lang}`);
Prism.highlightElement(el); // 同步执行 在 processBlock 中未 await 故不阻塞主线程
}
// ===== UI 与 交互 =====
function processBlock(pre) {
if (pre.classList.contains('itxgo-initialized')) return;
pre.classList.add('itxgo-initialized', 'itxgo-code-block');
const codeEl = pre.querySelector('code') || pre;
const raw = codeEl.textContent.replace(/^\n+|\n+$/g, '').replace(/\r\n/g, '\n');
const lang = getLanguage(codeEl);
const shouldCollapse = raw.split('\n').length > ITXGO_CODE_CONFIG.THRESHOLD;
// 不使用 await 允许高亮在后台异步进行 避免长任务
if (prismLoaded) applyHighlight(codeEl, lang);
else loadPrism().then(() => applyHighlight(codeEl, lang));
buildUI(pre, lang, shouldCollapse, raw);
}
function buildUI(pre, lang, shouldCollapse, raw) {
const tools = document.createElement('div');
tools.className = 'itxgo-code-tools';
tools.innerHTML = `
<div class="itxgo-code-header">
<span class="itxgo-code-label">${lang.toUpperCase()}</span>
<div class="itxgo-code-actions">
${shouldCollapse ? '<button class="itxgo-code-btn itxgo-toggle" type="button">展开</button>' : ''}
<button class="itxgo-code-btn itxgo-copy" type="button">
${ICONS.COPY}<span class="copy-text">复制</span>
</button>
</div>
</div>`;
pre.insertBefore(tools, pre.firstChild);
const copyBtn = tools.querySelector('.itxgo-copy');
copyBtn.onclick = async (e) => {
e.stopPropagation();
let ok = false;
try { await navigator.clipboard.writeText(raw); ok = true; }
catch {
const t = document.createElement('textarea');
t.value = raw; t.style.cssText = "position:fixed;left:-9999px";
document.body.appendChild(t); t.select();
ok = document.execCommand('copy');
document.body.removeChild(t);
}
const icon = copyBtn.querySelector('.copy-icon'), txt = copyBtn.querySelector('.copy-text');
const oldH = icon.innerHTML, oldT = txt.textContent;
icon.innerHTML = '<path d="M3 8.5L6 11.5L12 5.5" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>';
txt.textContent = ok ? '复制' : '失败';
setTimeout(() => { icon.innerHTML = oldH; txt.textContent = oldT; }, ITXGO_CODE_CONFIG.COPY_DURATION);
};
if (shouldCollapse) {
const toggleBtn = tools.querySelector('.itxgo-toggle');
const cornerBtn = document.createElement('button');
cornerBtn.className = 'itxgo-collapse-corner-btn';
cornerBtn.title = "折叠";
cornerBtn.setAttribute('aria-label', '折叠');
cornerBtn.innerHTML = ICONS.COLLAPSE;
Object.assign(cornerBtn.style, { opacity: 0, pointerEvents: 'none', transition: 'opacity 0.2s' });
const toggle = (forceState) => {
const isCollapsed = pre.classList.contains('itxgo-collapsed');
const shouldExpand = forceState !== undefined ? forceState : isCollapsed;
if (shouldExpand) {
pre.classList.replace('itxgo-collapsed', 'itxgo-expanded');
pre.style.maxHeight = 'none';
toggleBtn.textContent = '折叠';
cornerBtn.style.opacity = 1; cornerBtn.style.pointerEvents = 'auto';
} else {
pre.classList.replace('itxgo-expanded', 'itxgo-collapsed');
pre.style.maxHeight = pre._itxgoCollapsedHeight + 'px';
toggleBtn.textContent = '展开';
cornerBtn.style.opacity = 0; cornerBtn.style.pointerEvents = 'none';
}
};
toggleBtn.onclick = (e) => { e.stopPropagation(); toggle(); };
pre.onclick = (e) => {
if (pre.classList.contains('itxgo-collapsed') && !e.target.closest('.itxgo-code-tools')) toggle(true);
};
cornerBtn.onclick = (e) => {
e.stopPropagation();
const preRect = pre.getBoundingClientRect();
const offset = 170;
window.scrollTo(0, Math.max(0, window.scrollY + preRect.top - offset));
toggle(false);
};
pre.appendChild(cornerBtn);
}
}
// ===== 性能关键:批量高度计算 =====
function applyCollapseHeights(pres) {
const targets = Array.from(pres).filter(pre => {
if (pre.classList.contains('itxgo-expanded')) return false;
if (pre._itxgoCollapsedHeight) return false;
return pre.querySelector('.itxgo-toggle');
});
if (targets.length === 0) return;
// Batch Read & Write
const metrics = targets.map(pre => {
const code = pre.querySelector('code') || pre;
const cs = getComputedStyle(code), ps = getComputedStyle(pre);
const fs = parseFloat(cs.fontSize) || 14;
const lh = parseFloat(cs.lineHeight);
const pt = parseFloat(ps.paddingTop) || 40;
const pb = parseFloat(ps.paddingBottom) || 12;
return { pre, height: Math.ceil(pt + lh * ITXGO_CODE_CONFIG.COLLAPSE_LINES + pb) };
});
metrics.forEach(({ pre, height }) => {
pre._itxgoCollapsedHeight = height;
pre.style.maxHeight = height + 'px';
pre.classList.add('itxgo-collapsed');
});
}
// ===== 初始化 =====
function initCodeBlocks() {
loadPrism();
const processObserverBlocks = async (blocks) => {
if (!blocks.length) return;
if (document.fonts) await document.fonts.ready; // 增加字体等待 防止计算抖动
runInChunks(Array.from(blocks), processBlock);
};
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => processObserverBlocks(document.querySelectorAll(".article-content pre:not(.itxgo-initialized)")));
} else {
// 保持延迟 确保环境就绪
setTimeout(() => processObserverBlocks(document.querySelectorAll(".article-content pre:not(.itxgo-initialized)")), 350);
}
const observer = new MutationObserver(mutations => {
const newBlocks = [];
mutations.forEach(m => m.addedNodes.forEach(n => {
if (n.nodeType === 1) {
if (n.matches && n.matches(".article-content pre:not(.itxgo-initialized)")) newBlocks.push(n);
const found = n.querySelectorAll?.(".article-content pre:not(.itxgo-initialized)");
if (found) newBlocks.push(...found);
}
}));
if (newBlocks.length) runInChunks(newBlocks, processBlock);
});
observer.observe(document.body, { childList: true, subtree: true });
let resizeTimer;
window.addEventListener("resize", () => {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(() => {
applyCollapseHeights(document.querySelectorAll('.article-content pre.itxgo-collapsed'));
}, ITXGO_CODE_CONFIG.RESIZE_DELAY);
}, { passive: true });
}
6. ✅️代码块 JS 函数代码 - 终版语言判断简化版 - 2026年1月17日
// =============================
// 7. 代码块功能 - chat.z.ai
// =============================
const ITXGO_CODE_CONFIG = {
COLLAPSE_LINES: 10,
THRESHOLD: 10,
COPY_DURATION: 1000,
RESIZE_DELAY: 150,
BASE_CDN: 'https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/',
CHUNK_SIZE: 2
};
// 常量管理
const ICONS = {
COPY: `<svg class="copy-icon" width="15" height="15" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill="currentColor" d="M6.149 4.02c.963 0 1.73-.002 2.347.055.626.057 1.163.176 1.646.456.58.334 1.06.815 1.395 1.394.279.484.398 1.02.455 1.646.056.616.055 1.384.055 2.346 0 .963.002 1.73-.055 2.347-.057.626-.176 1.163-.456 1.646-.334.58-.815 1.06-1.394 1.395-.484.279-1.02.398-1.646.455-.616.056-1.384.055-2.347.055-.962 0-1.73.002-2.346-.055-.626-.057-1.163-.176-1.646-.456-.58-.334-1.06-.815-1.394-1.394-.28-.484-.4-1.02-.456-1.646-.056-.616-.056-1.384-.056-2.347 0-.962-.002-1.73.055-2.346.057-.626.177-1.163.456-1.646.335-.58.816-1.06 1.395-1.394.484-.28 1.02-.4 1.646-.456.616-.056 1.384-.056 2.347-.056Zm0 1.358c-.987 0-1.683.002-2.224.049-.53.048-.846.139-1.089.279-.373.215-.682.525-.898.897-.14.243-.231.559-.279 1.09-.049.54-.049 1.236-.049 2.224 0 .987-.002 1.683.049 2.224.048.53.139.846.279 1.089.215.372.525.682.897.897.243.14.559.231 1.09.279.54.049 1.236.049 2.224.049.987 0 1.683-.002 2.224-.049.53-.048.846-.139 1.089-.279.372-.215.682-.525.897-.897.14-.243.231-.559.279-1.09.049-.54.049-1.236.049-2.224 0-.987.002-1.683-.049-2.224-.048-.53-.139-.846-.279-1.089-.215-.373-.525-.682-.897-.897-.243-.14-.559-.231-1.09-.279-.54-.049-1.236-.049-2.224-.049Zm3.652-5.01c.963 0 1.73-.002 2.346.056.625.057 1.162.175 1.646.455.578.334 1.059.815 1.393 1.394.28.484.4 1.02.456 1.646.056.616.055 1.384.055 2.346v1.566c0 .462.002.76-.032 1.018-.199 1.504-1.265 2.725-2.682 3.15V11c.714-.356 1.227-1.05 1.336-1.875.019-.148.021-.336.021-.842V6.264c0-.987-.002-1.683-.049-2.224-.048-.53-.139-.846-.279-1.089-.215-.372-.525-.682-.897-.897-.243-.14-.559-.231-1.09-.279-.54-.049-1.236-.049-2.224-.049H7.715c-.959.002-1.788.553-2.192 1.355H4.07c.472-1.568 1.923-2.71 3.645-2.711h2.087Z"/></svg>`,
COLLAPSE: `<svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="currentColor"><g stroke="currentColor" stroke-width="20" stroke-linecap="round" stroke-linejoin="round"><path d="M125.3 176.1h742.4c15.8 0 28.7-10.6 28.7-23.6s-12.9-23.6-28.7-23.6H125.3c-15.8 0-28.7 10.6-28.7 23.6 0 13 12.9 23.6 28.7 23.6z"/><path d="M492.5 385.2H125.3c-15.4 0-28.1 10.6-28.1 23.6 0 12.9 12.7 23.6 28.1 23.6h367.2c15.4 0 28.1-10.7 28.1-23.6 0-12.9-12.7-23.6-28.1-23.6z"/><path d="M492.5 594.3H125.3c-15.4 0-28.1 10.6-28.1 23.6 0 13.1 12.7 23.6 28.1 23.6h367.2c15.4 0 28.1-10.7 28.1-23.6 0-13.1-12.7-23.6-28.1-23.6z"/><path d="M492.1 803.4H126c-15.8 0-28.7 10.6-28.7 23.6 0 13.1 12.7 23.6 28.7 23.6h366.2c15.8 0 28.7-10.7 28.7-23.6 0-13.1-12.9-23.6-28.7-23.6z"/><path d="M926.31 502.17c1.02-2.25-0.2-9.22-7.78-18.64L819.2 359.42c-8.19-10.24-18.64-15.77-29.49-15.77-10.85 0-21.5 5.53-29.49 15.77L661.09 483.33c-7.78 9.63-9.01 16.59-7.99 18.64 1.43 2.66 8.19 6.35 22.53 6.35h90.52v306.38c0 15.36 10.44 28.06 23.55 28.06s23.55-12.7 23.55-28.06V508.31h90.52c14.34 0 21.5-3.69 22.53-6.14z"/></g></svg>`
};
let prismLoaded = false, prismLoading = false;
const loadedLanguages = new Set(['markup', 'css', 'clike', 'javascript']);
const LANG_MAP = { js: 'javascript', ts: 'typescript', py: 'python', rb: 'ruby', cs: 'csharp', sh: 'bash', md: 'markdown', yaml: 'yaml' };
// ===== 异步加载 =====
function loadScript(src) {
return new Promise((resolve, reject) => {
const s = document.createElement('script');
s.src = src; s.onload = resolve; s.onerror = reject;
document.head.appendChild(s);
});
}
async function loadPrism() {
if (prismLoaded) return true;
if (prismLoading) return new Promise(r => setTimeout(r, 50)); // 异步等待 不阻塞
prismLoading = true;
try {
await loadScript(ITXGO_CODE_CONFIG.BASE_CDN + 'prism.min.js');
prismLoaded = true;
if (window.Prism) Prism.manual = true;
} catch (e) { console.warn('Prism load failed'); }
finally { prismLoading = false; }
return prismLoaded;
}
async function loadLangComp(lang) {
if (lang === 'html' || lang === 'markup') {
if (loadedLanguages.has('markup')) return true;
loadedLanguages.add('markup');
return true;
}
if (!lang || loadedLanguages.has(lang)) return true;
const key = LANG_MAP[lang] || lang;
if (!key) return true;
if (key === 'markup') {
loadedLanguages.add('markup');
return true;
}
return new Promise(resolve => {
const s = document.createElement('script');
s.src = `${ITXGO_CODE_CONFIG.BASE_CDN}components/prism-${key}.min.js`;
s.onload = () => {
loadedLanguages.add(lang);
resolve(true);
};
s.onerror = () => {
resolve(false);
};
document.head.appendChild(s);
});
}
async function runInChunks(items, processFn) {
const { CHUNK_SIZE } = ITXGO_CODE_CONFIG;
for (let i = 0; i < items.length; i += CHUNK_SIZE) {
const chunk = items.slice(i, i + CHUNK_SIZE);
chunk.forEach(processFn);
applyCollapseHeights(chunk);
// 标记代码块准备就绪,触发淡入动画
chunk.forEach(pre => {
if (!pre.classList.contains('itxgo-ready')) {
pre.classList.add('itxgo-ready');
}
});
if (i + CHUNK_SIZE < items.length) await new Promise(r => requestAnimationFrame(r));
}
}
// ===== 代码语言判断核心逻辑 =====
function getLanguage(el) {
// 第 1 层:上帝视角
const findClass = (e) => {
if (!e) return null;
const match = e.className && e.className.match(/(?:^|\s)language-(\w+)(?:\s|$)/);
return match ? match[1] : null;
};
const lang = findClass(el) || findClass(el.closest('pre'));
if (lang) return lang;
const text = (el.textContent || '').trim();
const sample = text.slice(0, 300);
// 第 2 层:硬核结构解析
// 1. JSON
try {
if (/^[\[{]/.test(text) && /[\]}]$/.test(text)) {
JSON.parse(text);
return 'json';
}
} catch (e) {}
// 2. HTML
if (/<([a-zA-Z][a-zA-Z0-9]*)[^>]*>.*<\/\1>|<!DOCTYPE|<xml/i.test(sample)) {
return 'markup';
}
// 第 3 层:JS/TS
if (
/=>|const\s+\w+\s*=|let\s+\w+\s*=|var\s+\w+\s*=/.test(sample) ||
/function\s+\(|async\s+function|console\.log\|document\.|window\./i.test(sample) ||
/import\s+.*from\s+|export\s+|interface\s+\w+/.test(sample)
) {
return 'javascript';
}
// 4. SQL
if (/\b(SELECT|UPDATE|INSERT|CREATE|ALTER|DELETE)\b.*\b(FROM|INTO|TABLE|SET)\b/i.test(sample)) {
return 'sql';
}
// 5. PHP
if (/<\?php|<\?(?!xml)|\$[a-zA-Z_]\w+\s*=/i.test(sample)) {
return 'php';
}
// 6. C / C++
if (/#include\s*<[^>]+>|#define\s+\w+/i.test(sample)) {
return 'cpp';
}
// 7. Java
if (/\b(System\.out\.println|package\s+\w+|public\s+static\s+void\s+main)\b/i.test(sample)) {
return 'java';
}
// 8. Python
if (/def\s+\w+\s*\(|import\s+\w+|print\s*\(/i.test(sample) && !/{/.test(sample.slice(0, 500))) {
return 'python';
}
// 第 4 层:CSS
const hasSelector = /(\.[\w-]+\s*\{|#[\w-]+\s*\{|:\w+\s*\{|@\w+[^\{]*\{)/i;
const hasCssStyle = /(px|em|rem|%|vh|deg|s|ms)\s*;|!important|url\s*\(|rgba?\s*\(|var\s*\(|calc\s*\(:root/i;
if (hasSelector.test(sample) && hasCssStyle.test(sample)) {
return 'css';
}
// 第 5 层:兜底
if (/\b(fn\s+|use\s+std\s*::)\b/i.test(sample)) return 'rust';
if (/\b(package\s+main|func\s+\(|import\s*\()\b/i.test(sample)) return 'go';
if (/(^#|^!\/bin\/bash|\-eq|\-ne|echo\s+\$\w+)/m.test(sample)) return 'bash';
return 'plaintext';
}
async function applyHighlight(el, lang) {
if (!window.Prism || !lang) return;
await loadLangComp(lang);
el.classList.add(`language-${lang}`);
Prism.highlightElement(el); // 同步执行 在 processBlock 中未 await 故不阻塞主线程
}
// ===== UI 与 交互 =====
function processBlock(pre) {
if (pre.classList.contains('itxgo-initialized')) return;
pre.classList.add('itxgo-initialized', 'itxgo-code-block');
const codeEl = pre.querySelector('code') || pre;
const raw = codeEl.textContent.replace(/^\n+|\n+$/g, '').replace(/\r\n/g, '\n');
const lang = getLanguage(codeEl);
const shouldCollapse = raw.split('\n').length > ITXGO_CODE_CONFIG.THRESHOLD;
// 不使用 await 允许高亮在后台异步进行 避免长任务
if (prismLoaded) applyHighlight(codeEl, lang);
else loadPrism().then(() => applyHighlight(codeEl, lang));
buildUI(pre, lang, shouldCollapse, raw);
}
function buildUI(pre, lang, shouldCollapse, raw) {
const tools = document.createElement('div');
tools.className = 'itxgo-code-tools';
tools.innerHTML = `
<div class="itxgo-code-header">
<span class="itxgo-code-label">${lang.toUpperCase()}</span>
<div class="itxgo-code-actions">
${shouldCollapse ? '<button class="itxgo-code-btn itxgo-toggle" type="button">展开</button>' : ''}
<button class="itxgo-code-btn itxgo-copy" type="button">
${ICONS.COPY}<span class="copy-text">复制</span>
</button>
</div>
</div>`;
pre.insertBefore(tools, pre.firstChild);
const copyBtn = tools.querySelector('.itxgo-copy');
copyBtn.onclick = async (e) => {
e.stopPropagation();
let ok = false;
try { await navigator.clipboard.writeText(raw); ok = true; }
catch {
const t = document.createElement('textarea');
t.value = raw; t.style.cssText = "position:fixed;left:-9999px";
document.body.appendChild(t); t.select();
ok = document.execCommand('copy');
document.body.removeChild(t);
}
const icon = copyBtn.querySelector('.copy-icon'), txt = copyBtn.querySelector('.copy-text');
const oldH = icon.innerHTML, oldT = txt.textContent;
icon.innerHTML = '<path d="M3 8.5L6 11.5L12 5.5" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>';
txt.textContent = ok ? '复制' : '失败';
setTimeout(() => { icon.innerHTML = oldH; txt.textContent = oldT; }, ITXGO_CODE_CONFIG.COPY_DURATION);
};
if (shouldCollapse) {
const toggleBtn = tools.querySelector('.itxgo-toggle');
const cornerBtn = document.createElement('button');
cornerBtn.className = 'itxgo-collapse-corner-btn';
cornerBtn.title = "折叠";
cornerBtn.setAttribute('aria-label', '折叠');
cornerBtn.innerHTML = ICONS.COLLAPSE;
Object.assign(cornerBtn.style, { opacity: 0, pointerEvents: 'none', transition: 'opacity 0.2s' });
const toggle = (forceState) => {
const isCollapsed = pre.classList.contains('itxgo-collapsed');
const shouldExpand = forceState !== undefined ? forceState : isCollapsed;
if (shouldExpand) {
pre.classList.replace('itxgo-collapsed', 'itxgo-expanded');
pre.style.maxHeight = 'none';
toggleBtn.textContent = '折叠';
cornerBtn.style.opacity = 1; cornerBtn.style.pointerEvents = 'auto';
} else {
pre.classList.replace('itxgo-expanded', 'itxgo-collapsed');
pre.style.maxHeight = pre._itxgoCollapsedHeight + 'px';
toggleBtn.textContent = '展开';
cornerBtn.style.opacity = 0; cornerBtn.style.pointerEvents = 'none';
}
};
toggleBtn.onclick = (e) => { e.stopPropagation(); toggle(); };
pre.onclick = (e) => {
if (pre.classList.contains('itxgo-collapsed') && !e.target.closest('.itxgo-code-tools')) toggle(true);
};
cornerBtn.onclick = (e) => {
e.stopPropagation();
const preRect = pre.getBoundingClientRect();
const offset = 170;
window.scrollTo(0, Math.max(0, window.scrollY + preRect.top - offset));
toggle(false);
};
pre.appendChild(cornerBtn);
}
}
// ===== 性能关键:批量高度计算 =====
function applyCollapseHeights(pres) {
const targets = Array.from(pres).filter(pre => {
if (pre.classList.contains('itxgo-expanded')) return false;
if (pre._itxgoCollapsedHeight) return false;
return pre.querySelector('.itxgo-toggle');
});
if (targets.length === 0) return;
// Batch Read & Write
const metrics = targets.map(pre => {
const code = pre.querySelector('code') || pre;
const cs = getComputedStyle(code), ps = getComputedStyle(pre);
const fs = parseFloat(cs.fontSize) || 14;
const lh = parseFloat(cs.lineHeight);
const pt = parseFloat(ps.paddingTop) || 40;
const pb = parseFloat(ps.paddingBottom) || 12;
return { pre, height: Math.ceil(pt + lh * ITXGO_CODE_CONFIG.COLLAPSE_LINES + pb) };
});
metrics.forEach(({ pre, height }) => {
pre._itxgoCollapsedHeight = height;
pre.style.maxHeight = height + 'px';
pre.classList.add('itxgo-collapsed');
});
}
// ===== 初始化 =====
function initCodeBlocks() {
loadPrism();
const processObserverBlocks = async (blocks) => {
if (!blocks.length) return;
if (document.fonts) await document.fonts.ready; // 增加字体等待 防止计算抖动
runInChunks(Array.from(blocks), processBlock);
};
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => processObserverBlocks(document.querySelectorAll(".article-content pre:not(.itxgo-initialized)")));
} else {
// 保持延迟 确保环境就绪
setTimeout(() => processObserverBlocks(document.querySelectorAll(".article-content pre:not(.itxgo-initialized)")), 350);
}
const observer = new MutationObserver(mutations => {
const newBlocks = [];
mutations.forEach(m => m.addedNodes.forEach(n => {
if (n.nodeType === 1) {
if (n.matches && n.matches(".article-content pre:not(.itxgo-initialized)")) newBlocks.push(n);
const found = n.querySelectorAll?.(".article-content pre:not(.itxgo-initialized)");
if (found) newBlocks.push(...found);
}
}));
if (newBlocks.length) runInChunks(newBlocks, processBlock);
});
observer.observe(document.body, { childList: true, subtree: true });
let resizeTimer;
window.addEventListener("resize", () => {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(() => {
applyCollapseHeights(document.querySelectorAll('.article-content pre.itxgo-collapsed'));
}, ITXGO_CODE_CONFIG.RESIZE_DELAY);
}, { passive: true });
}
6-1. ✅️代码块 JS 函数代码 - 终版语言判断简化版 - 2026年1月17日
// =============================
// 7. 代码块功能 - claude.ai
// =============================
const ITXGO_CODE_CONFIG = {
COLLAPSE_LINES: 10,
THRESHOLD: 10,
COPY_DURATION: 1000,
RESIZE_DELAY: 150,
BASE_CDN: 'https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/',
CHUNK_SIZE: 2
};
// 常量管理
const ICONS = {
COPY: `<svg class="copy-icon" width="15" height="15" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill="currentColor" d="M6.149 4.02c.963 0 1.73-.002 2.347.055.626.057 1.163.176 1.646.456.58.334 1.06.815 1.395 1.394.279.484.398 1.02.455 1.646.056.616.055 1.384.055 2.346 0 .963.002 1.73-.055 2.347-.057.626-.176 1.163-.456 1.646-.334.58-.815 1.06-1.394 1.395-.484.279-1.02.398-1.646.455-.616.056-1.384.055-2.347.055-.962 0-1.73.002-2.346-.055-.626-.057-1.163-.176-1.646-.456-.58-.334-1.06-.815-1.394-1.394-.28-.484-.4-1.02-.456-1.646-.056-.616-.056-1.384-.056-2.347 0-.962-.002-1.73.055-2.346.057-.626.177-1.163.456-1.646.335-.58.816-1.06 1.395-1.394.484-.28 1.02-.4 1.646-.456.616-.056 1.384-.056 2.347-.056Zm0 1.358c-.987 0-1.683.002-2.224.049-.53.048-.846.139-1.089.279-.373.215-.682.525-.898.897-.14.243-.231.559-.279 1.09-.049.54-.049 1.236-.049 2.224 0 .987-.002 1.683.049 2.224.048.53.139.846.279 1.089.215.372.525.682.897.897.243.14.559.231 1.09.279.54.049 1.236.049 2.224.049.987 0 1.683-.002 2.224-.049.53-.048.846-.139 1.089-.279.372-.215.682-.525.897-.897.14-.243.231-.559.279-1.09.049-.54.049-1.236.049-2.224 0-.987.002-1.683-.049-2.224-.048-.53-.139-.846-.279-1.089-.215-.373-.525-.682-.897-.897-.243-.14-.559-.231-1.09-.279-.54-.049-1.236-.049-2.224-.049Zm3.652-5.01c.963 0 1.73-.002 2.346.056.625.057 1.162.175 1.646.455.578.334 1.059.815 1.393 1.394.28.484.4 1.02.456 1.646.056.616.055 1.384.055 2.346v1.566c0 .462.002.76-.032 1.018-.199 1.504-1.265 2.725-2.682 3.15V11c.714-.356 1.227-1.05 1.336-1.875.019-.148.021-.336.021-.842V6.264c0-.987-.002-1.683-.049-2.224-.048-.53-.139-.846-.279-1.089-.215-.372-.525-.682-.897-.897-.243-.14-.559-.231-1.09-.279-.54-.049-1.236-.049-2.224-.049H7.715c-.959.002-1.788.553-2.192 1.355H4.07c.472-1.568 1.923-2.71 3.645-2.711h2.087Z"/></svg>`,
COLLAPSE: `<svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="currentColor"><g stroke="currentColor" stroke-width="20" stroke-linecap="round" stroke-linejoin="round"><path d="M125.3 176.1h742.4c15.8 0 28.7-10.6 28.7-23.6s-12.9-23.6-28.7-23.6H125.3c-15.8 0-28.7 10.6-28.7 23.6 0 13 12.9 23.6 28.7 23.6z"/><path d="M492.5 385.2H125.3c-15.4 0-28.1 10.6-28.1 23.6 0 12.9 12.7 23.6 28.1 23.6h367.2c15.4 0 28.1-10.7 28.1-23.6 0-12.9-12.7-23.6-28.1-23.6z"/><path d="M492.5 594.3H125.3c-15.4 0-28.1 10.6-28.1 23.6 0 13.1 12.7 23.6 28.1 23.6h367.2c15.4 0 28.1-10.7 28.1-23.6 0-13.1-12.7-23.6-28.1-23.6z"/><path d="M492.1 803.4H126c-15.8 0-28.7 10.6-28.7 23.6 0 13.1 12.7 23.6 28.7 23.6h366.2c15.8 0 28.7-10.7 28.7-23.6 0-13.1-12.9-23.6-28.7-23.6z"/><path d="M926.31 502.17c1.02-2.25-0.2-9.22-7.78-18.64L819.2 359.42c-8.19-10.24-18.64-15.77-29.49-15.77-10.85 0-21.5 5.53-29.49 15.77L661.09 483.33c-7.78 9.63-9.01 16.59-7.99 18.64 1.43 2.66 8.19 6.35 22.53 6.35h90.52v306.38c0 15.36 10.44 28.06 23.55 28.06s23.55-12.7 23.55-28.06V508.31h90.52c14.34 0 21.5-3.69 22.53-6.14z"/></g></svg>`
};
let prismLoaded = false, prismLoading = false;
const loadedLanguages = new Set(['markup', 'css', 'clike', 'javascript']);
const LANG_MAP = { js: 'javascript', ts: 'typescript', py: 'python', rb: 'ruby', cs: 'csharp', sh: 'bash', md: 'markdown', yaml: 'yaml' };
// ===== 异步加载 =====
function loadScript(src) {
return new Promise((resolve, reject) => {
const s = document.createElement('script');
s.src = src; s.onload = resolve; s.onerror = reject;
document.head.appendChild(s);
});
}
async function loadPrism() {
if (prismLoaded) return true;
if (prismLoading) return new Promise(r => setTimeout(r, 50)); // 异步等待 不阻塞
prismLoading = true;
try {
await loadScript(ITXGO_CODE_CONFIG.BASE_CDN + 'prism.min.js');
prismLoaded = true;
if (window.Prism) Prism.manual = true;
} catch (e) { console.warn('Prism load failed'); }
finally { prismLoading = false; }
return prismLoaded;
}
async function loadLangComp(lang) {
if (lang === 'html' || lang === 'markup') {
if (loadedLanguages.has('markup')) return true;
loadedLanguages.add('markup');
return true;
}
if (!lang || loadedLanguages.has(lang)) return true;
const key = LANG_MAP[lang] || lang;
if (!key) return true;
if (key === 'markup') {
loadedLanguages.add('markup');
return true;
}
return new Promise(resolve => {
const s = document.createElement('script');
s.src = `${ITXGO_CODE_CONFIG.BASE_CDN}components/prism-${key}.min.js`;
s.onload = () => {
loadedLanguages.add(lang);
resolve(true);
};
s.onerror = () => {
resolve(false);
};
document.head.appendChild(s);
});
}
async function runInChunks(items, processFn) {
const { CHUNK_SIZE } = ITXGO_CODE_CONFIG;
for (let i = 0; i < items.length; i += CHUNK_SIZE) {
const chunk = items.slice(i, i + CHUNK_SIZE);
chunk.forEach(processFn);
applyCollapseHeights(chunk);
// 标记代码块准备就绪,触发淡入动画
chunk.forEach(pre => {
if (!pre.classList.contains('itxgo-ready')) {
pre.classList.add('itxgo-ready');
}
});
if (i + CHUNK_SIZE < items.length) await new Promise(r => requestAnimationFrame(r));
}
}
// ===== 代码语言判断核心逻辑 =====
function getLanguage(el) {
// 1. 优先级最高:显式标记
const cls = el.className || el.closest('pre')?.className || '';
const match = cls.match(/(?:^|\s)language-(\w+)/);
if (match) return match[1];
const text = (el.textContent || '').trim();
const head = text.slice(0, 500); // 只检测前 500 字符
// 2. 结构性语言
if (/^[\[{][\s\S]*[\]}]$/.test(text)) {
try { JSON.parse(text); return 'json'; } catch {}
}
// HTML/XML
if (/<([a-z][\w-]*)[^>]*>[\s\S]*<\/\1>|<!DOCTYPE|<\?xml/i.test(head)) {
return 'markup';
}
// 3. 编程语言特征
// JavaScript/TypeScript
if (
/\bconst\s+\w+\s*=|let\s+\w+\s*=|var\s+\w+/.test(head) ||
/\bfunction\s*\(|=>\s*[{(]|console\.(log|error)|export\s+(default|const)/.test(head) ||
/import\s+.+from\s+['"]|interface\s+\w+\s*\{/.test(head)
) {
return 'javascript';
}
// Python
if (
/\b(def|class)\s+\w+\s*[(:]|import\s+\w+|print\s*\(/.test(head) &&
!/\bfunction\s*\(|=>\s*/.test(head)
) {
return 'python';
}
// SQL
if (/\b(SELECT|INSERT|UPDATE|DELETE|CREATE)\s+.+\b(FROM|INTO|TABLE|SET)\b/i.test(head)) {
return 'sql';
}
// PHP
if (/<\?php|<\?=|\$\w+\s*=/.test(head)) return 'php';
// C/C++
if (/#include\s*<|#define\s+\w+|int\s+main\s*\(/.test(head)) return 'cpp';
// Java
if (/\b(public\s+class|System\.out|package\s+[\w.]+)/.test(head)) return 'java';
// 4. CSS
if (
/[.#][\w-]+\s*\{|@\w+[^{]*\{|:\w+\s*\{/.test(head) &&
/(px|em|rem|%|vh|vw|deg|ms|s)\s*;|:\s*#[\da-f]{3,8}|rgba?\(|url\(/.test(head)
) {
return 'css';
}
// 5. 其他语言
if (/\bfn\s+\w+|use\s+std::/.test(head)) return 'rust';
if (/\bpackage\s+main|func\s+\w+\s*\(/.test(head)) return 'go';
if (/^#!/m.test(head) || /\becho\s+\$|\[\s*-[a-z]\s/.test(head)) return 'bash';
return 'plaintext';
}
async function applyHighlight(el, lang) {
if (!window.Prism || !lang) return;
await loadLangComp(lang);
el.classList.add(`language-${lang}`);
Prism.highlightElement(el); // 同步执行 在 processBlock 中未 await 故不阻塞主线程
}
// ===== UI 与 交互 =====
function processBlock(pre) {
if (pre.classList.contains('itxgo-initialized')) return;
pre.classList.add('itxgo-initialized', 'itxgo-code-block');
const codeEl = pre.querySelector('code') || pre;
const raw = codeEl.textContent.replace(/^\n+|\n+$/g, '').replace(/\r\n/g, '\n');
const lang = getLanguage(codeEl);
const shouldCollapse = raw.split('\n').length > ITXGO_CODE_CONFIG.THRESHOLD;
// 不使用 await 允许高亮在后台异步进行 避免长任务
if (prismLoaded) applyHighlight(codeEl, lang);
else loadPrism().then(() => applyHighlight(codeEl, lang));
buildUI(pre, lang, shouldCollapse, raw);
}
function buildUI(pre, lang, shouldCollapse, raw) {
const tools = document.createElement('div');
tools.className = 'itxgo-code-tools';
tools.innerHTML = `
<div class="itxgo-code-header">
<span class="itxgo-code-label">${lang.toUpperCase()}</span>
<div class="itxgo-code-actions">
${shouldCollapse ? '<button class="itxgo-code-btn itxgo-toggle" type="button">展开</button>' : ''}
<button class="itxgo-code-btn itxgo-copy" type="button">
${ICONS.COPY}<span class="copy-text">复制</span>
</button>
</div>
</div>`;
pre.insertBefore(tools, pre.firstChild);
const copyBtn = tools.querySelector('.itxgo-copy');
copyBtn.onclick = async (e) => {
e.stopPropagation();
let ok = false;
try { await navigator.clipboard.writeText(raw); ok = true; }
catch {
const t = document.createElement('textarea');
t.value = raw; t.style.cssText = "position:fixed;left:-9999px";
document.body.appendChild(t); t.select();
ok = document.execCommand('copy');
document.body.removeChild(t);
}
const icon = copyBtn.querySelector('.copy-icon'), txt = copyBtn.querySelector('.copy-text');
const oldH = icon.innerHTML, oldT = txt.textContent;
icon.innerHTML = '<path d="M3 8.5L6 11.5L12 5.5" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>';
txt.textContent = ok ? '复制' : '失败';
setTimeout(() => { icon.innerHTML = oldH; txt.textContent = oldT; }, ITXGO_CODE_CONFIG.COPY_DURATION);
};
if (shouldCollapse) {
const toggleBtn = tools.querySelector('.itxgo-toggle');
const cornerBtn = document.createElement('button');
cornerBtn.className = 'itxgo-collapse-corner-btn';
cornerBtn.title = "折叠";
cornerBtn.setAttribute('aria-label', '折叠');
cornerBtn.innerHTML = ICONS.COLLAPSE;
Object.assign(cornerBtn.style, { opacity: 0, pointerEvents: 'none', transition: 'opacity 0.2s' });
const toggle = (forceState) => {
const isCollapsed = pre.classList.contains('itxgo-collapsed');
const shouldExpand = forceState !== undefined ? forceState : isCollapsed;
if (shouldExpand) {
pre.classList.replace('itxgo-collapsed', 'itxgo-expanded');
pre.style.maxHeight = 'none';
toggleBtn.textContent = '折叠';
cornerBtn.style.opacity = 1; cornerBtn.style.pointerEvents = 'auto';
} else {
pre.classList.replace('itxgo-expanded', 'itxgo-collapsed');
pre.style.maxHeight = pre._itxgoCollapsedHeight + 'px';
toggleBtn.textContent = '展开';
cornerBtn.style.opacity = 0; cornerBtn.style.pointerEvents = 'none';
}
};
toggleBtn.onclick = (e) => { e.stopPropagation(); toggle(); };
pre.onclick = (e) => {
if (pre.classList.contains('itxgo-collapsed') && !e.target.closest('.itxgo-code-tools')) toggle(true);
};
cornerBtn.onclick = (e) => {
e.stopPropagation();
const preRect = pre.getBoundingClientRect();
const offset = 170;
window.scrollTo(0, Math.max(0, window.scrollY + preRect.top - offset));
toggle(false);
};
pre.appendChild(cornerBtn);
}
}
// ===== 性能关键:批量高度计算 =====
function applyCollapseHeights(pres) {
const targets = Array.from(pres).filter(pre => {
if (pre.classList.contains('itxgo-expanded')) return false;
if (pre._itxgoCollapsedHeight) return false;
return pre.querySelector('.itxgo-toggle');
});
if (targets.length === 0) return;
// Batch Read & Write
const metrics = targets.map(pre => {
const code = pre.querySelector('code') || pre;
const cs = getComputedStyle(code), ps = getComputedStyle(pre);
const fs = parseFloat(cs.fontSize) || 14;
const lh = parseFloat(cs.lineHeight);
const pt = parseFloat(ps.paddingTop) || 40;
const pb = parseFloat(ps.paddingBottom) || 12;
return { pre, height: Math.ceil(pt + lh * ITXGO_CODE_CONFIG.COLLAPSE_LINES + pb) };
});
metrics.forEach(({ pre, height }) => {
pre._itxgoCollapsedHeight = height;
pre.style.maxHeight = height + 'px';
pre.classList.add('itxgo-collapsed');
});
}
// ===== 初始化 =====
function initCodeBlocks() {
loadPrism();
const processObserverBlocks = async (blocks) => {
if (!blocks.length) return;
if (document.fonts) await document.fonts.ready; // 增加字体等待 防止计算抖动
runInChunks(Array.from(blocks), processBlock);
};
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => processObserverBlocks(document.querySelectorAll(".article-content pre:not(.itxgo-initialized)")));
} else {
// 保持延迟 确保环境就绪
setTimeout(() => processObserverBlocks(document.querySelectorAll(".article-content pre:not(.itxgo-initialized)")), 350);
}
const observer = new MutationObserver(mutations => {
const newBlocks = [];
mutations.forEach(m => m.addedNodes.forEach(n => {
if (n.nodeType === 1) {
if (n.matches && n.matches(".article-content pre:not(.itxgo-initialized)")) newBlocks.push(n);
const found = n.querySelectorAll?.(".article-content pre:not(.itxgo-initialized)");
if (found) newBlocks.push(...found);
}
}));
if (newBlocks.length) runInChunks(newBlocks, processBlock);
});
observer.observe(document.body, { childList: true, subtree: true });
let resizeTimer;
window.addEventListener("resize", () => {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(() => {
applyCollapseHeights(document.querySelectorAll('.article-content pre.itxgo-collapsed'));
}, ITXGO_CODE_CONFIG.RESIZE_DELAY);
}, { passive: true });
}