Files
UI/packages/skin/ui/src/diffView.ts
T

42 lines
2.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { h } from '@ui-arch/frame';
import { diffLines } from './diffKit.js';
import type { DiffViewProps } from './types.js';
/*** 文本差异对比:行级对齐 + 增删着色 + 双行号列,超限时退化为整段替换(只影响精度不影响语义) ***/
export function diffView(props: DiffViewProps): HTMLElement {
const ignore = props.ignoreWhitespace === true; // 只在显式开启时归一行内空白
const ops = diffLines(props.before, props.after, ignore); // 纯逻辑在 diffKit:这里只负责把它画出来
const added = ops.filter((o) => o.type === 'add').length; // 新增行数:统计条与读屏共用
const removed = ops.filter((o) => o.type === 'del').length; // 删除行数
let oldNo = 0;
let newNo = 0;
const rows = ops.map((op) => {
if (op.type !== 'add') oldNo += 1; // same 与 del 占旧行号
if (op.type !== 'del') newNo += 1; // same 与 add 占新行号
const sign = op.type === 'add' ? '+' : op.type === 'del' ? '−' : ' ';
return h(
'div',
{ class: `ua-diff-row is-${op.type}` },
h('span', { class: 'ua-diff-no' }, op.type === 'add' ? '' : String(oldNo)),
h('span', { class: 'ua-diff-no' }, op.type === 'del' ? '' : String(newNo)),
h('span', { class: 'ua-diff-sign', 'aria-hidden': 'true' }, sign),
h('span', { class: 'ua-diff-text' }, op.text || ' '),
);
});
const stats = props.showStats === false
? null
: h(
'div',
{ class: 'ua-diff-stats' },
h('span', { class: 'ua-diff-add' }, `+${added}`),
h('span', { class: 'ua-diff-del' }, `−${removed}`),
ignore ? h('span', { class: 'ua-diff-note' }, '已忽略行内空白差异') : null, // 归一口径必须写在脸上,否则「为什么不报这几行」说不清
);
return h(
'div',
{ class: 'ua-diff', role: 'group', 'aria-label': props.ariaLabel ?? `文本差异:新增 ${added} 行,删除 ${removed} 行` },
stats,
h('div', { class: 'ua-diff-body' }, ...rows),
);
}