@yuhufe/wtool-vdiff 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +165 -0
- package/dist/DiffViewer/DiffViewer.vue.d.ts +12 -0
- package/dist/DiffViewer/MonacoDiffViewer.vue.d.ts +24 -0
- package/dist/DiffViewer/TopBar.vue.d.ts +13 -0
- package/dist/DiffViewer/createDiffViewer.d.ts +10 -0
- package/dist/DiffViewer/index.d.ts +1 -0
- package/dist/DiffViewer/useDiffView.d.ts +27 -0
- package/dist/DiffViewer/utils/autoHeight.d.ts +9 -0
- package/dist/DiffViewer/utils/patch2Pair.d.ts +27 -0
- package/dist/index.d.ts +2 -0
- package/dist/types.d.ts +20 -0
- package/dist/wtool-vdiff.cjs.js +48 -0
- package/dist/wtool-vdiff.css +1 -0
- package/dist/wtool-vdiff.es.d.ts +2 -0
- package/dist/wtool-vdiff.es.js +13026 -0
- package/package.json +53 -0
- package/src/DiffViewer/DiffViewer.vue +143 -0
- package/src/DiffViewer/MonacoDiffViewer.vue +178 -0
- package/src/DiffViewer/TopBar.vue +121 -0
- package/src/DiffViewer/createDiffViewer.ts +49 -0
- package/src/DiffViewer/index.ts +8 -0
- package/src/DiffViewer/useDiffView.ts +16 -0
- package/src/DiffViewer/utils/autoHeight.ts +149 -0
- package/src/DiffViewer/utils/patch2Pair.ts +121 -0
- package/src/index.ts +2 -0
- package/src/types.ts +20 -0
- package/src/vite-env.d.ts +7 -0
package/README.md
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# @yuhufe/wtool-vdiff
|
|
2
|
+
|
|
3
|
+
**Demo**: [https://defghy.github.io/web-toolkits/v-diff/](https://defghy.github.io/web-toolkits/v-diff/)
|
|
4
|
+
|
|
5
|
+
基于 Monaco 的 DiffViewer。 **框架无关** —— 可直接集成到任何前端项目(React、Vue、原生 JS 等)中。
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 特性
|
|
10
|
+
|
|
11
|
+
- **框架无关** :通过 Web Component 封装,函数调用即可挂载,无需 Vue 项目
|
|
12
|
+
- **双模式输入** :支持 `diffPatch`(unified diff 字符串)与 `diffPair`(原始文件对)两种数据格式
|
|
13
|
+
- **自适应高度** :根据实际变更行数自动计算编辑器高度,避免大量空白
|
|
14
|
+
- **折叠未变更区域** :默认折叠无差异区域,仅保留变更附近的上下文行
|
|
15
|
+
- **顶部工具栏** :内置文件名展示、增删行数统计、viewed 标记、raw 展开模式
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 安装
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install @yuhufe/wtool-vdiff
|
|
23
|
+
# 或
|
|
24
|
+
pnpm add @yuhufe/wtool-vdiff
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## 快速开始
|
|
30
|
+
|
|
31
|
+
### 方式一:`diffPatch` 模式(unified diff 字符串)
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
import { createDiffViewer } from '@yuhufe/wtool-vdiff'
|
|
35
|
+
|
|
36
|
+
const viewer = createDiffViewer(document.getElementById('diff-container')!, {
|
|
37
|
+
diffPatch: `--- a/src/index.ts
|
|
38
|
+
+++ b/src/index.ts
|
|
39
|
+
@@ -1,5 +1,6 @@
|
|
40
|
+
import { foo } from './foo'
|
|
41
|
+
-const x = 1
|
|
42
|
+
+const x = 2
|
|
43
|
+
+const y = 3
|
|
44
|
+
export { foo }`,
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
// 动态更新内容
|
|
48
|
+
viewer.update({ diffPatch: newPatch })
|
|
49
|
+
|
|
50
|
+
// 销毁
|
|
51
|
+
viewer.destroy()
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### 方式二:`diffPair` 模式(完整文件对)
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
import { createDiffViewer } from '@yuhufe/wtool-vdiff'
|
|
58
|
+
|
|
59
|
+
const viewer = createDiffViewer(document.getElementById('diff-container')!, {
|
|
60
|
+
diffPair: [
|
|
61
|
+
{ filename: 'src/index.ts', content: 'const x = 1\nexport { foo }' },
|
|
62
|
+
{ filename: 'src/index.ts', content: 'const x = 2\nconst y = 3\nexport { foo }' },
|
|
63
|
+
],
|
|
64
|
+
language: 'typescript',
|
|
65
|
+
})
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## loader 配置
|
|
71
|
+
|
|
72
|
+
库内部通过 `@monaco-editor/loader` 按需加载 Monaco。默认走 jsDelivr CDN,生产环境建议改为本地 bundle。
|
|
73
|
+
|
|
74
|
+
**方式一:自定义 CDN 路径**
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
import { loader } from '@yuhufe/wtool-vdiff'
|
|
78
|
+
|
|
79
|
+
loader.config({
|
|
80
|
+
paths: { vs: 'https://your-cdn.example.com/monaco-editor/0.53.0/min/vs' },
|
|
81
|
+
})
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**方式二:从 node_modules 本地加载(Vite 项目推荐)**
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
import * as monaco from 'monaco-editor'
|
|
88
|
+
import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker'
|
|
89
|
+
import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker'
|
|
90
|
+
import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker'
|
|
91
|
+
import cssWorker from 'monaco-editor/esm/vs/language/css/css.worker?worker'
|
|
92
|
+
import htmlWorker from 'monaco-editor/esm/vs/language/html/html.worker?worker'
|
|
93
|
+
import { loader } from '@yuhufe/wtool-vdiff'
|
|
94
|
+
|
|
95
|
+
self.MonacoEnvironment = {
|
|
96
|
+
getWorker(_, label) {
|
|
97
|
+
if (label === 'json') return new jsonWorker()
|
|
98
|
+
if (label === 'css' || label === 'scss' || label === 'less') return new cssWorker()
|
|
99
|
+
if (label === 'html' || label === 'handlebars' || label === 'razor') return new htmlWorker()
|
|
100
|
+
if (label === 'typescript' || label === 'javascript') return new tsWorker()
|
|
101
|
+
return new editorWorker()
|
|
102
|
+
},
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
loader.config({ monaco })
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
> `loader.config` 必须在任意 `createDiffViewer` 调用之前执行。
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## API
|
|
113
|
+
|
|
114
|
+
### `createDiffViewer(target, props?)`
|
|
115
|
+
|
|
116
|
+
在目标元素内创建并挂载 diff 查看器,返回 `DiffViewerInstance` 实例。
|
|
117
|
+
|
|
118
|
+
| 参数 | 类型 | 必填 | 说明 |
|
|
119
|
+
|------|------|------|------|
|
|
120
|
+
| `target` | `HTMLElement` | ✅ | 挂载目标容器元素 |
|
|
121
|
+
| `props` | `DiffViewerProps` | ❌ | 初始化属性(见下方 Props 说明) |
|
|
122
|
+
|
|
123
|
+
**返回值:`DiffViewerInstance`**
|
|
124
|
+
|
|
125
|
+
| 方法 | 签名 | 说明 |
|
|
126
|
+
|------|------|------|
|
|
127
|
+
| `update` | `(props: Partial<DiffViewerProps>) => void` | 动态更新 props |
|
|
128
|
+
| `destroy` | `() => void` | 销毁查看器并从 DOM 移除 |
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
### Props(`DiffViewerProps`)
|
|
133
|
+
|
|
134
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
135
|
+
|------|------|--------|------|
|
|
136
|
+
| `diffPatch` | `string` | `''` | Unified diff 格式字符串(与 `diffPair` 二选一) |
|
|
137
|
+
| `diffPair` | `{ filename: string; content: string }[]` | `[]` | 原始文件对,数组长度为 2,分别为原始文件与修改后文件(与 `diffPatch` 二选一) |
|
|
138
|
+
| `language` | `string` | `'plaintext'` | Monaco 语言标识,影响语法高亮(如 `'typescript'`、`'python'`) |
|
|
139
|
+
| `options` | `DiffEditorOptions` | `{}` | Monaco `IStandaloneDiffEditorConstructionOptions`,透传给 Monaco 编辑器 |
|
|
140
|
+
| `modelOptions` | `ModelOptions` | `{}` | Monaco `ITextModelUpdateOptions`,透传给文本模型 |
|
|
141
|
+
| `viewerStyle` | `WtoolDiffViewerStyle` | — | 查看器外层样式(宽高) |
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
### `WtoolDiffViewerStyle`
|
|
146
|
+
|
|
147
|
+
| 属性 | 类型 | 说明 |
|
|
148
|
+
|------|------|------|
|
|
149
|
+
| `width` | `string` | 查看器宽度,默认 `100%` |
|
|
150
|
+
| `height` | `string` | 固定高度(设置后忽略自适应逻辑) |
|
|
151
|
+
| `minHeight` | `string` | 自适应高度最小值,默认 `100px` |
|
|
152
|
+
| `maxHeight` | `string` | 自适应高度最大值,默认 `250px` |
|
|
153
|
+
|
|
154
|
+
> 支持 `px` 和 `vh` 单位。当 `height` 显式设置时,`minHeight` / `maxHeight` 无效。
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
### `DiffEditorOptions`(Monaco 透传)
|
|
159
|
+
|
|
160
|
+
完整选项参考 [Monaco Editor 官方文档](https://microsoft.github.io/monaco-editor/docs.html)。
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { DiffEditorOptions, WtoolDiffViewerProps, ModelOptions } from '../types';
|
|
2
|
+
declare const _default: import('../../node_modules/vue/dist/vue.esm-bundler.js').DefineComponent<WtoolDiffViewerProps, {}, {}, {}, {}, import('../../node_modules/vue/dist/vue.esm-bundler.js').ComponentOptionsMixin, import('../../node_modules/vue/dist/vue.esm-bundler.js').ComponentOptionsMixin, {}, string, import('../../node_modules/vue/dist/vue.esm-bundler.js').PublicProps, Readonly<WtoolDiffViewerProps> & Readonly<{}>, {
|
|
3
|
+
language: string;
|
|
4
|
+
options: DiffEditorOptions;
|
|
5
|
+
modelOptions: ModelOptions;
|
|
6
|
+
diffPair: {
|
|
7
|
+
filename: string;
|
|
8
|
+
content: string;
|
|
9
|
+
}[];
|
|
10
|
+
diffPatch: string;
|
|
11
|
+
}, {}, {}, {}, string, import('../../node_modules/vue/dist/vue.esm-bundler.js').ComponentProvideOptions, false, {}, HTMLDivElement>;
|
|
12
|
+
export default _default;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type * as Monaco from 'monaco-editor';
|
|
2
|
+
type DiffEditorOptions = Monaco.editor.IStandaloneDiffEditorConstructionOptions;
|
|
3
|
+
type ModelOptions = Monaco.editor.ITextModelUpdateOptions;
|
|
4
|
+
type __VLS_Props = {
|
|
5
|
+
originalCode?: string;
|
|
6
|
+
modifiedCode?: string;
|
|
7
|
+
language?: string;
|
|
8
|
+
options?: DiffEditorOptions;
|
|
9
|
+
modelOptions?: ModelOptions;
|
|
10
|
+
};
|
|
11
|
+
declare const _default: import('../../node_modules/vue/dist/vue.esm-bundler.js').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('../../node_modules/vue/dist/vue.esm-bundler.js').ComponentOptionsMixin, import('../../node_modules/vue/dist/vue.esm-bundler.js').ComponentOptionsMixin, {
|
|
12
|
+
renderComplete: () => any;
|
|
13
|
+
}, string, import('../../node_modules/vue/dist/vue.esm-bundler.js').PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
14
|
+
onRenderComplete?: (() => any) | undefined;
|
|
15
|
+
}>, {
|
|
16
|
+
originalCode: string;
|
|
17
|
+
modifiedCode: string;
|
|
18
|
+
language: string;
|
|
19
|
+
options: DiffEditorOptions;
|
|
20
|
+
modelOptions: ModelOptions;
|
|
21
|
+
}, {}, {}, {}, string, import('../../node_modules/vue/dist/vue.esm-bundler.js').ComponentProvideOptions, false, {
|
|
22
|
+
containerEl: HTMLDivElement;
|
|
23
|
+
}, HTMLDivElement>;
|
|
24
|
+
export default _default;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
type __VLS_Props = {
|
|
2
|
+
diffPair?: {
|
|
3
|
+
filename: string;
|
|
4
|
+
content: string;
|
|
5
|
+
}[];
|
|
6
|
+
};
|
|
7
|
+
declare const _default: import('../../node_modules/vue/dist/vue.esm-bundler.js').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('../../node_modules/vue/dist/vue.esm-bundler.js').ComponentOptionsMixin, import('../../node_modules/vue/dist/vue.esm-bundler.js').ComponentOptionsMixin, {}, string, import('../../node_modules/vue/dist/vue.esm-bundler.js').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
8
|
+
diffPair: {
|
|
9
|
+
filename: string;
|
|
10
|
+
content: string;
|
|
11
|
+
}[];
|
|
12
|
+
}, {}, {}, {}, string, import('../../node_modules/vue/dist/vue.esm-bundler.js').ComponentProvideOptions, false, {}, HTMLDivElement>;
|
|
13
|
+
export default _default;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { WtoolDiffViewerProps } from '../types';
|
|
2
|
+
export type DiffViewerProps = WtoolDiffViewerProps;
|
|
3
|
+
export declare const WTOOL_DIFF_VIEWER_TAG = "wtool-diff-viewer";
|
|
4
|
+
export declare const WtoolDiffViewer: import('../../node_modules/vue/dist/vue.esm-bundler.js').VueElementConstructor<WtoolDiffViewerProps>;
|
|
5
|
+
export declare function register(tagName?: string): void;
|
|
6
|
+
export interface DiffViewerInstance {
|
|
7
|
+
update(props: Partial<DiffViewerProps>): void;
|
|
8
|
+
destroy(): void;
|
|
9
|
+
}
|
|
10
|
+
export declare function createDiffViewer(target: HTMLElement, initialProps?: DiffViewerProps): DiffViewerInstance;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { WTOOL_DIFF_VIEWER_TAG, WtoolDiffViewer, register as registerDiffViewer, createDiffViewer, type DiffViewerProps, type DiffViewerInstance, } from './createDiffViewer';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Ref } from '../../node_modules/vue/dist/vue.esm-bundler.js';
|
|
2
|
+
export declare const useDiffViewer: ({ isMaster }?: {
|
|
3
|
+
isMaster?: boolean | undefined;
|
|
4
|
+
}) => {
|
|
5
|
+
funcs: {
|
|
6
|
+
viewed: Ref<boolean>;
|
|
7
|
+
rawed: Ref<boolean>;
|
|
8
|
+
updateViewed: (viewed: boolean) => any;
|
|
9
|
+
updateRawed: (args: boolean) => any;
|
|
10
|
+
updateChangedLines: (args: {
|
|
11
|
+
added: number;
|
|
12
|
+
removed: number;
|
|
13
|
+
}) => any;
|
|
14
|
+
canUnchangeVisible: Ref<boolean>;
|
|
15
|
+
};
|
|
16
|
+
registerFunc: (funcList: Partial<{
|
|
17
|
+
viewed: Ref<boolean>;
|
|
18
|
+
rawed: Ref<boolean>;
|
|
19
|
+
updateViewed: (viewed: boolean) => any;
|
|
20
|
+
updateRawed: (args: boolean) => any;
|
|
21
|
+
updateChangedLines: (args: {
|
|
22
|
+
added: number;
|
|
23
|
+
removed: number;
|
|
24
|
+
}) => any;
|
|
25
|
+
canUnchangeVisible: Ref<boolean>;
|
|
26
|
+
}>) => void;
|
|
27
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { WtoolDiffViewerProps } from '../../types';
|
|
2
|
+
export declare const autoHeight: ({ patch, pair, maxHeight, minHeight, unchangedVisiable, unchangedCtxLineNum, }: {
|
|
3
|
+
patch?: string;
|
|
4
|
+
pair?: WtoolDiffViewerProps["diffPair"];
|
|
5
|
+
maxHeight: string;
|
|
6
|
+
minHeight: string;
|
|
7
|
+
unchangedVisiable: boolean;
|
|
8
|
+
unchangedCtxLineNum: number;
|
|
9
|
+
}) => number;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export interface FilePair {
|
|
2
|
+
filename: string;
|
|
3
|
+
content: string;
|
|
4
|
+
}
|
|
5
|
+
export interface Hunk {
|
|
6
|
+
origStart: number;
|
|
7
|
+
origCount: number;
|
|
8
|
+
modStart: number;
|
|
9
|
+
modCount: number;
|
|
10
|
+
lines: string[];
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* 解析 unified diff patch,提取文件名与所有 hunk
|
|
14
|
+
*/
|
|
15
|
+
export declare function parseHunks(patch: string): {
|
|
16
|
+
origFilename: string;
|
|
17
|
+
modFilename: string;
|
|
18
|
+
hunks: Hunk[];
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* 将 unified diff patch 转换为 [original, modified] 文件对。
|
|
22
|
+
*
|
|
23
|
+
* Monaco diff editor 需要两个完整文件内容,而 patch 只记录变更片段。
|
|
24
|
+
* 未改动的行(hunk 之外)用空行填充,使两侧行号与 hunk 声明的起始位置对齐,
|
|
25
|
+
* 从而让 Monaco 能在正确的行号位置渲染增删差异。
|
|
26
|
+
*/
|
|
27
|
+
export declare const patch2Pair: (patch: string) => FilePair[];
|
package/dist/index.d.ts
ADDED
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type * as Monaco from 'monaco-editor';
|
|
2
|
+
export type DiffEditorOptions = Monaco.editor.IStandaloneDiffEditorConstructionOptions;
|
|
3
|
+
export type ModelOptions = Monaco.editor.ITextModelUpdateOptions;
|
|
4
|
+
export interface WtoolDiffViewerProps {
|
|
5
|
+
diffPair?: {
|
|
6
|
+
filename: string;
|
|
7
|
+
content: string;
|
|
8
|
+
}[];
|
|
9
|
+
diffPatch?: string;
|
|
10
|
+
language?: string;
|
|
11
|
+
options?: DiffEditorOptions;
|
|
12
|
+
modelOptions?: ModelOptions;
|
|
13
|
+
viewerStyle?: WtoolDiffViewerStyle;
|
|
14
|
+
}
|
|
15
|
+
export interface WtoolDiffViewerStyle {
|
|
16
|
+
width?: string;
|
|
17
|
+
height?: string;
|
|
18
|
+
minHeight?: string;
|
|
19
|
+
maxHeight?: string;
|
|
20
|
+
}
|