iter(g270): 新增代码块组件
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
import { h } from '@ui-arch/frame';
|
||||
import { copyButton } from './copyButton.js';
|
||||
import type { CodeBlockProps } from './types.js';
|
||||
|
||||
/*** 代码块:等宽渲染多行代码,可选行号列与标题行(语言 / 文件名),右上角一键复制原文;只做展示不做高亮 ***/
|
||||
export function codeBlock(props: CodeBlockProps): HTMLElement {
|
||||
const lines = props.code.replace(/\r?\n$/, '').split(/\r?\n/); // 末尾换行不生成空行:复制走原文,显示不多一行
|
||||
const showNo = props.lineNumbers !== false && lines.length > 1; // 单行代码给行号只是噪音
|
||||
const body = h(
|
||||
'div',
|
||||
{ class: 'ua-code-body' },
|
||||
...lines.map((text, i) => h(
|
||||
'div',
|
||||
{ class: 'ua-code-line' },
|
||||
showNo ? h('span', { class: 'ua-code-no', 'aria-hidden': 'true' }, String(i + 1)) : null, // 行号是装饰,读屏跳过
|
||||
h('span', { class: 'ua-code-text' }, text || ' '), // 空行补一个空格,撑住行高
|
||||
)),
|
||||
);
|
||||
if (props.maxHeight !== undefined) body.style.maxHeight = `${props.maxHeight}px`; // 只在给了上限时限高,超出内部滚动
|
||||
const title = props.title ?? props.lang; // 标题优先用文件名,其次语言名
|
||||
const head = props.copyable === false && !title
|
||||
? null // 既无标题也不可复制:整个头部省掉,不留空条
|
||||
: h(
|
||||
'div',
|
||||
{ class: 'ua-code-head' },
|
||||
title ? h('span', { class: 'ua-code-title' }, title) : h('span', null, ''),
|
||||
props.copyable === false ? null : copyButton({ text: props.code, label: '复制', size: 'sm', variant: 'ghost', onCopied: props.onCopy }),
|
||||
);
|
||||
return h('div', { class: 'ua-code', role: 'group', 'aria-label': props.ariaLabel ?? '代码块' }, head, body);
|
||||
}
|
||||
@@ -79,3 +79,4 @@ export { inputTag } from './inputTag.js';
|
||||
export { layout } from './layout.js';
|
||||
export { jsonViewer } from './jsonViewer.js';
|
||||
export { diffView } from './diffView.js';
|
||||
export { codeBlock } from './codeBlock.js';
|
||||
|
||||
@@ -1038,3 +1038,15 @@ export interface DiffViewProps {
|
||||
showStats?: boolean; // 是否在顶部显示 +N / −N 统计条;缺省 true
|
||||
ariaLabel?: string; // 可访问名;缺省自动播报「新增 N 行,删除 M 行」
|
||||
}
|
||||
|
||||
/*** 代码块入参 ***/
|
||||
export interface CodeBlockProps {
|
||||
code: string; // 代码原文:显示与复制都用它(不读 DOM,避免行号混进剪贴板)
|
||||
lang?: string; // 语言名(如 ts / css);无 title 时作头部标题
|
||||
title?: string; // 头部标题(如文件名);优先于 lang
|
||||
lineNumbers?: boolean; // 是否显示行号列;缺省 true(单行代码自动省略)
|
||||
maxHeight?: number; // 代码区最高高度(px),超出在框内滚动;缺省不限高
|
||||
copyable?: boolean; // 右上角是否出现复制按钮;缺省 true
|
||||
onCopy?: (text: string) => void; // 复制成功回调(参数为实际写入剪贴板的内容)
|
||||
ariaLabel?: string; // 可访问名;缺省「代码块」
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user