@yuhufe/wtool-vdiff 0.0.6 → 0.0.8

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.
Files changed (42) hide show
  1. package/README.md +140 -41
  2. package/dist/DiffFiles/DiffFiles.vue.d.ts +12 -0
  3. package/dist/DiffFiles/DiffList/DiffList.vue.d.ts +94 -0
  4. package/dist/DiffFiles/FileExplore/FileExplore.vue.d.ts +510 -0
  5. package/dist/DiffFiles/FileExplore/FileSearch.vue.d.ts +11 -0
  6. package/dist/DiffFiles/FileExplore/fileTree.d.ts +17 -0
  7. package/dist/DiffFiles/createDiffFiles.d.ts +13 -0
  8. package/dist/DiffFiles/index.d.ts +3 -0
  9. package/dist/DiffFiles/types.d.ts +12 -0
  10. package/dist/DiffFiles/useDiffFiles.d.ts +23 -0
  11. package/dist/DiffViewer/DiffViewer.vue.d.ts +15 -4
  12. package/dist/DiffViewer/MonacoDiffViewer.vue.d.ts +1 -1
  13. package/dist/DiffViewer/TopBar.vue.d.ts +2 -0
  14. package/dist/DiffViewer/const.d.ts +8 -0
  15. package/dist/DiffViewer/utils/autoHeight.d.ts +4 -1
  16. package/dist/DiffViewer/utils/patch2Pair.d.ts +9 -14
  17. package/dist/index.d.ts +1 -0
  18. package/dist/types.d.ts +16 -0
  19. package/dist/utils/patch.d.ts +20 -0
  20. package/dist/wtool-vdiff.cjs.js +45 -36
  21. package/dist/wtool-vdiff.es.js +9535 -5984
  22. package/package.json +10 -9
  23. package/src/DiffFiles/DiffFiles.vue +126 -0
  24. package/src/DiffFiles/DiffList/DiffList.vue +125 -0
  25. package/src/DiffFiles/FileExplore/FileExplore.vue +181 -0
  26. package/src/DiffFiles/FileExplore/FileSearch.vue +81 -0
  27. package/src/DiffFiles/FileExplore/fileTree.ts +102 -0
  28. package/src/DiffFiles/createDiffFiles.ts +70 -0
  29. package/src/DiffFiles/index.ts +11 -0
  30. package/src/DiffFiles/types.ts +15 -0
  31. package/src/DiffFiles/useDiffFiles.ts +56 -0
  32. package/src/DiffViewer/DiffViewer.vue +28 -7
  33. package/src/DiffViewer/MonacoDiffViewer.vue +21 -2
  34. package/src/DiffViewer/TopBar.vue +25 -6
  35. package/src/DiffViewer/const.ts +11 -0
  36. package/src/DiffViewer/utils/autoHeight.ts +159 -43
  37. package/src/DiffViewer/utils/patch2Pair.ts +37 -56
  38. package/src/assets/file.svg +4 -0
  39. package/src/assets/folder.svg +4 -0
  40. package/src/index.ts +1 -0
  41. package/src/types.ts +19 -0
  42. package/src/utils/patch.ts +74 -0
package/README.md CHANGED
@@ -2,17 +2,18 @@
2
2
 
3
3
  **Demo**: [https://defghy.github.io/web-toolkits/v-diff/](https://defghy.github.io/web-toolkits/v-diff/)
4
4
 
5
- 基于 Monaco DiffViewer **框架无关** —— 可直接集成到任何前端项目(React、Vue、原生 JS 等)中。
5
+ 基于 Monaco 的框架无关 DiffViewer,可集成到 React、Vue、原生 JS 等前端项目。
6
6
 
7
7
  ---
8
8
 
9
9
  ## 特性
10
10
 
11
- - **框架无关** :通过 Web Component 封装,函数调用即可挂载,无需 Vue 项目
12
- - **双模式输入** :支持 `diffPatch`(unified diff 字符串)与 `diffPair`(原始文件对)两种数据格式
13
- - **自适应高度** :根据实际变更行数自动计算编辑器高度,避免大量空白
14
- - **折叠未变更区域** :默认折叠无差异区域,仅保留变更附近的上下文行
15
- - **顶部工具栏** :内置文件名展示、增删行数统计、viewed 标记、raw 展开模式
11
+ - **框架无关** :通过 Web Component 封装,函数调用即可挂载
12
+ - **双模式输入** :支持 `diffPatch`(unified diff)和 `diffPair`(文件对)
13
+ - **自适应高度** :按变更行数计算编辑器高度,减少空白
14
+ - **折叠未变更区域** :默认折叠无差异区域,保留变更上下文
15
+ - **顶部工具栏** :提供文件名、增删行统计、viewed 标记和 raw 模式
16
+ - **文件列表 Diff** :通过文件数组生成可搜索的文件树,支持选择联动和虚拟滚动
16
17
 
17
18
  ---
18
19
 
@@ -28,7 +29,7 @@ pnpm add @yuhufe/wtool-vdiff
28
29
 
29
30
  ## 快速开始
30
31
 
31
- ### 方式一:`diffPatch` 模式(unified diff 字符串)
32
+ ### 方式一:`diffPatch`(unified diff
32
33
 
33
34
  ```typescript
34
35
  import { createDiffViewer } from '@yuhufe/wtool-vdiff'
@@ -44,14 +45,14 @@ const viewer = createDiffViewer(document.getElementById('diff-container')!, {
44
45
  export { foo }`,
45
46
  })
46
47
 
47
- // 动态更新内容
48
+ // 更新
48
49
  viewer.update({ diffPatch: newPatch })
49
50
 
50
51
  // 销毁
51
52
  viewer.destroy()
52
53
  ```
53
54
 
54
- ### 方式二:`diffPair` 模式(完整文件对)
55
+ ### 方式二:`diffPair`(文件对)
55
56
 
56
57
  ```typescript
57
58
  import { createDiffViewer } from '@yuhufe/wtool-vdiff'
@@ -67,9 +68,73 @@ const viewer = createDiffViewer(document.getElementById('diff-container')!, {
67
68
 
68
69
  ---
69
70
 
71
+ ## 文件列表 Diff
72
+
73
+ `createDiffFiles` 展示可搜索的文件树和虚拟滚动 Diff 列表,选择文件时自动滚动并高亮。
74
+
75
+ ```html
76
+ <div id="diff-files-container"></div>
77
+
78
+ <style>
79
+ #diff-files-container {
80
+ width: 100%;
81
+ height: 560px;
82
+ overflow: hidden;
83
+ }
84
+ </style>
85
+ ```
86
+
87
+ ```typescript
88
+ import { createDiffFiles, type DiffFile } from '@yuhufe/wtool-vdiff'
89
+
90
+ const diffFiles: DiffFile[] = [
91
+ {
92
+ diffPatch: `--- src/index.ts
93
+ +++ src/index.ts
94
+ @@ -1,2 +1,3 @@
95
+ import { foo } from './foo'
96
+ -export { foo }
97
+ +const version = 2
98
+ +export { foo, version }`,
99
+ },
100
+ {
101
+ diffPair: [
102
+ {
103
+ filename: 'src/utils/sum.ts',
104
+ content: 'export const sum = (a: number, b: number) => a + b',
105
+ },
106
+ {
107
+ filename: 'src/utils/sum.ts',
108
+ content: 'export function sum(a: number, b: number) {\n return a + b\n}',
109
+ },
110
+ ],
111
+ },
112
+ ]
113
+
114
+ const filesViewer = createDiffFiles(document.getElementById('diff-files-container')!, {
115
+ diffFiles,
116
+ viewerStyle: { maxHeight: '360px' },
117
+ })
118
+
119
+ // 销毁
120
+ filesViewer.destroy()
121
+ ```
122
+
123
+ > 组件根据 `fullPath` 构建目录树。外层容器需设置明确高度,且每个文件的最终 `fullPath` 必须唯一。文件内容通过 `diffPatch` 或 `diffPair` 提供。
124
+
125
+ 省略 `fullPath` 时,组件按以下顺序推导文件路径:
126
+
127
+ 1. 显式 `fullPath`
128
+ 2. `diffPair` 中修改后文件的 `filename`,其次为原文件
129
+ 3. `diffPatch` 的 `+++` 头部
130
+
131
+ `diffPatch` 中的文件名会原样保留,也可通过 `fullPath` 覆盖。无法确定路径时,组件会抛出带数组下标的 `TypeError`。
132
+
133
+ ---
134
+
70
135
  ## loader 配置
71
136
 
72
- 库内部通过 `@monaco-editor/loader` 按需加载 Monaco。默认走 jsDelivr CDN,生产环境建议改为本地 bundle。
137
+ 库通过 `@monaco-editor/loader` 按需加载 Monaco。默认使用 jsDelivr CDN,生产环境建议本地加载。
73
138
 
74
139
  **方式一:自定义 CDN 路径**
75
140
 
@@ -81,7 +146,7 @@ loader.config({
81
146
  })
82
147
  ```
83
148
 
84
- **方式二:从 node_modules 本地加载(Vite 项目推荐)**
149
+ **方式二:本地加载(Vite 推荐)**
85
150
 
86
151
  ```typescript
87
152
  import * as monaco from 'monaco-editor'
@@ -105,7 +170,7 @@ self.MonacoEnvironment = {
105
170
  loader.config({ monaco })
106
171
  ```
107
172
 
108
- > `loader.config` 必须在任意 `createDiffViewer` 调用之前执行。
173
+ > 请在首次调用 `createDiffViewer` 前配置 `loader`。
109
174
 
110
175
  ---
111
176
 
@@ -113,53 +178,87 @@ loader.config({ monaco })
113
178
 
114
179
  ### `createDiffViewer(target, props?)`
115
180
 
116
- 在目标元素内创建并挂载 diff 查看器,返回 `DiffViewerInstance` 实例。
181
+ 挂载 DiffViewer。
117
182
 
118
- | 参数 | 类型 | 必填 | 说明 |
119
- |------|------|------|------|
120
- | `target` | `HTMLElement` | ✅ | 挂载目标容器元素 |
121
- | `props` | `DiffViewerProps` | ❌ | 初始化属性(见下方 Props 说明) |
183
+ | 参数 | 类型 | 必填 | 说明 |
184
+ | -------- | ----------------- | ---- | -------- |
185
+ | `target` | `HTMLElement` | ✅ | 挂载容器 |
186
+ | `props` | `DiffViewerProps` | ❌ | 初始属性 |
122
187
 
123
188
  **返回值:`DiffViewerInstance`**
124
189
 
125
- | 方法 | 签名 | 说明 |
126
- |------|------|------|
127
- | `update` | `(props: Partial<DiffViewerProps>) => void` | 动态更新 props |
128
- | `destroy` | `() => void` | 销毁查看器并从 DOM 移除 |
190
+ | 方法 | 签名 | 说明 |
191
+ | --------- | ------------------------------------------- | ------------ |
192
+ | `update` | `(props: Partial<DiffViewerProps>) => void` | 更新 props |
193
+ | `destroy` | `() => void` | 销毁并从 DOM 移除 |
129
194
 
130
195
  ---
131
196
 
132
- ### Props(`DiffViewerProps`)
197
+ ### `createDiffFiles(target, props?)`
133
198
 
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` | — | 查看器外层样式(宽高) |
199
+ 挂载文件列表 Diff。
142
200
 
143
- ---
201
+ | 参数 | 类型 | 必填 | 说明 |
202
+ | -------- | ---------------- | ---- | -------- |
203
+ | `target` | `HTMLElement` | ✅ | 挂载容器 |
204
+ | `props` | `DiffFilesProps` | ❌ | 初始属性 |
144
205
 
145
- ### `WtoolDiffViewerStyle`
206
+ **返回值:`DiffFilesInstance`**
207
+
208
+ | 方法 | 签名 | 说明 |
209
+ | --------- | ------------------------------------------ | ------------ |
210
+ | `update` | `(props: Partial<DiffFilesProps>) => void` | 更新 props |
211
+ | `destroy` | `() => void` | 销毁并从 DOM 移除 |
212
+
213
+ ### `DiffFilesProps`
214
+
215
+ | 属性 | 类型 | 默认值 | 说明 |
216
+ | ------------- | ---------------------- | ------ | --------------------- |
217
+ | `diffFiles` | `DiffFile[]` | `[]` | 文件数组 |
218
+ | `viewerStyle` | `WtoolDiffViewerStyle` | `{}` | 单个 DiffViewer 的样式 |
219
+
220
+ ### `DiffFile`
146
221
 
147
- | 属性 | 类型 | 说明 |
148
- |------|------|------|
149
- | `width` | `string` | 查看器宽度,默认 `100%` |
150
- | `height` | `string` | 固定高度(设置后忽略自适应逻辑) |
151
- | `minHeight` | `string` | 自适应高度最小值,默认 `100px` |
152
- | `maxHeight` | `string` | 自适应高度最大值,默认 `250px` |
222
+ | 属性 | 类型 | 必填 | 说明 |
223
+ | ------------- | ------------------------------------------------- | ---- | -------------------------------------------------------- |
224
+ | `fullPath` | `string` | | 文件完整路径;省略时根据 `diffPair` 或 `diffPatch` 推导 |
225
+ | `diffPatch` | `string` | | Unified diff 字符串,与 `diffPair` 二选一 |
226
+ | `diffPair` | `{ filename: string; content: string \| null }[]` | ❌ | 原文件和修改后文件 |
153
227
 
154
- > 支持 `px` `vh` 单位。当 `height` 显式设置时,`minHeight` / `maxHeight` 无效。
228
+ > `FileTree` `DiffFile` 的废弃别名,建议迁移到 `DiffFile`。
155
229
 
156
230
  ---
157
231
 
158
- ### `DiffEditorOptions`(Monaco 透传)
232
+ ### `DiffViewerProps`
159
233
 
160
- 完整选项参考 [Monaco Editor 官方文档](https://microsoft.github.io/monaco-editor/docs.html)。
234
+ | 属性 | 类型 | 默认值 | 说明 |
235
+ | -------------- | ----------------------------------------- | ------------- | ----------------------------------------------------- |
236
+ | `diffPatch` | `string` | `''` | Unified diff 字符串,与 `diffPair` 二选一 |
237
+ | `diffPair` | `{ filename: string; content: string }[]` | `[]` | 原文件和修改后文件,与 `diffPatch` 二选一 |
238
+ | `language` | `string` | `'plaintext'` | Monaco 语言标识,如 `'typescript'`、`'python'` |
239
+ | `options` | `DiffEditorOptions` | `{}` | 透传至 Monaco Diff Editor |
240
+ | `modelOptions` | `ModelOptions` | `{}` | 透传至 Monaco 文本模型 |
241
+ | `viewerStyle` | `WtoolDiffViewerStyle` | — | 外层尺寸 |
161
242
 
162
243
  ---
163
244
 
245
+ ### `WtoolDiffViewerStyle`
246
+
247
+ | 属性 | 类型 | 说明 |
248
+ | ----------- | --------- | ------------------------------ |
249
+ | `width` | `string` | 宽度,默认 `100%` |
250
+ | `height` | `string` | 固定高度,优先于自适应高度 |
251
+ | `minHeight` | `string` | 最小高度,默认 `100px` |
252
+ | `maxHeight` | `string` | 最大高度,默认 `250px` |
253
+ | `viewed` | `boolean` | 是否已读的初始值,默认 `false` |
254
+ | `rawed` | `boolean` | 是否显示原始文件,默认 `false` |
164
255
 
256
+ > 尺寸支持 `px` 和 `vh`。
257
+
258
+ ---
165
259
 
260
+ ### `DiffEditorOptions`(Monaco 透传)
261
+
262
+ 选项见 [Monaco Editor 官方文档](https://microsoft.github.io/monaco-editor/docs.html)。
263
+
264
+ ---
@@ -0,0 +1,12 @@
1
+ import { WtoolDiffFilesProps } from '../types';
2
+ import { DiffFileSelection } from './FileExplore/fileTree';
3
+ declare const _default: import('../../node_modules/vue/dist/vue.esm-bundler.js').DefineComponent<WtoolDiffFilesProps, {}, {}, {}, {}, import('../../node_modules/vue/dist/vue.esm-bundler.js').ComponentOptionsMixin, import('../../node_modules/vue/dist/vue.esm-bundler.js').ComponentOptionsMixin, {
4
+ "select-file": (selection: DiffFileSelection) => any;
5
+ }, string, import('../../node_modules/vue/dist/vue.esm-bundler.js').PublicProps, Readonly<WtoolDiffFilesProps> & Readonly<{
6
+ "onSelect-file"?: ((selection: DiffFileSelection) => any) | undefined;
7
+ }>, {
8
+ viewerStyle: import('.').WtoolDiffViewerStyle;
9
+ diffFiles: import('.').DiffFile[];
10
+ fileOverScan: number;
11
+ }, {}, {}, {}, string, import('../../node_modules/vue/dist/vue.esm-bundler.js').ComponentProvideOptions, false, {}, HTMLDivElement>;
12
+ export default _default;
@@ -0,0 +1,94 @@
1
+ import { DiffFileState, FileItem } from '../types';
2
+ import { WtoolDiffViewerStyle } from '../../types';
3
+ type __VLS_Props = {
4
+ diffFiles: FileItem[];
5
+ fileOverScan?: number;
6
+ fileViewMap: Record<string, DiffFileState>;
7
+ viewerStyle?: WtoolDiffViewerStyle;
8
+ };
9
+ 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, {
10
+ "view-state-change": (file: FileItem, state: Partial<DiffFileState>) => any;
11
+ }, string, import('../../../node_modules/vue/dist/vue.esm-bundler.js').PublicProps, Readonly<__VLS_Props> & Readonly<{
12
+ "onView-state-change"?: ((file: FileItem, state: Partial<DiffFileState>) => any) | undefined;
13
+ }>, {
14
+ viewerStyle: WtoolDiffViewerStyle;
15
+ diffFiles: FileItem[];
16
+ fileOverScan: number;
17
+ fileViewMap: Record<string, DiffFileState>;
18
+ }, {}, {}, {}, string, import('../../../node_modules/vue/dist/vue.esm-bundler.js').ComponentProvideOptions, false, {
19
+ virtualScrollRef: import('../../../node_modules/vue/dist/vue.esm-bundler.js').CreateComponentPublicInstanceWithMixins<Readonly<import('../../../node_modules/vue/dist/vue.esm-bundler.js').ExtractPropTypes<{
20
+ items: {
21
+ required: true;
22
+ type: import('../../../node_modules/vue/dist/vue.esm-bundler.js').PropType<any[]>;
23
+ };
24
+ itemSize: {
25
+ required: true;
26
+ type: import('../../../node_modules/vue/dist/vue.esm-bundler.js').PropType<number | ((item: any, index: number) => number)>;
27
+ };
28
+ keyField: {
29
+ default: string;
30
+ type: StringConstructor;
31
+ };
32
+ overscan: {
33
+ default: number;
34
+ type: NumberConstructor;
35
+ };
36
+ }>> & Readonly<{}>, {
37
+ scrollCtn: import('../../../node_modules/vue/dist/vue.esm-bundler.js').Ref<HTMLElement, HTMLElement>;
38
+ onScroll: (evt: Event) => void;
39
+ totalHeight: import('../../../node_modules/vue/dist/vue.esm-bundler.js').ComputedRef<number>;
40
+ virtualItems: import('../../../node_modules/vue/dist/vue.esm-bundler.js').ComputedRef<{
41
+ key: any;
42
+ index: number;
43
+ start: number;
44
+ end: number;
45
+ size: number;
46
+ lane: number;
47
+ }[]>;
48
+ getVirtualer: () => import('@tanstack/vue-virtual').Virtualizer<HTMLElement, Element>;
49
+ }, {}, {}, {}, import('../../../node_modules/vue/dist/vue.esm-bundler.js').ComponentOptionsMixin, import('../../../node_modules/vue/dist/vue.esm-bundler.js').ComponentOptionsMixin, {}, import('../../../node_modules/vue/dist/vue.esm-bundler.js').PublicProps, {
50
+ keyField: string;
51
+ overscan: number;
52
+ }, true, {}, {}, import('../../../node_modules/vue/dist/vue.esm-bundler.js').GlobalComponents, import('../../../node_modules/vue/dist/vue.esm-bundler.js').GlobalDirectives, string, {}, any, import('../../../node_modules/vue/dist/vue.esm-bundler.js').ComponentProvideOptions, {
53
+ P: {};
54
+ B: {};
55
+ D: {};
56
+ C: {};
57
+ M: {};
58
+ Defaults: {};
59
+ }, Readonly<import('../../../node_modules/vue/dist/vue.esm-bundler.js').ExtractPropTypes<{
60
+ items: {
61
+ required: true;
62
+ type: import('../../../node_modules/vue/dist/vue.esm-bundler.js').PropType<any[]>;
63
+ };
64
+ itemSize: {
65
+ required: true;
66
+ type: import('../../../node_modules/vue/dist/vue.esm-bundler.js').PropType<number | ((item: any, index: number) => number)>;
67
+ };
68
+ keyField: {
69
+ default: string;
70
+ type: StringConstructor;
71
+ };
72
+ overscan: {
73
+ default: number;
74
+ type: NumberConstructor;
75
+ };
76
+ }>> & Readonly<{}>, {
77
+ scrollCtn: import('../../../node_modules/vue/dist/vue.esm-bundler.js').Ref<HTMLElement, HTMLElement>;
78
+ onScroll: (evt: Event) => void;
79
+ totalHeight: import('../../../node_modules/vue/dist/vue.esm-bundler.js').ComputedRef<number>;
80
+ virtualItems: import('../../../node_modules/vue/dist/vue.esm-bundler.js').ComputedRef<{
81
+ key: any;
82
+ index: number;
83
+ start: number;
84
+ end: number;
85
+ size: number;
86
+ lane: number;
87
+ }[]>;
88
+ getVirtualer: () => import('@tanstack/vue-virtual').Virtualizer<HTMLElement, Element>;
89
+ }, {}, {}, {}, {
90
+ keyField: string;
91
+ overscan: number;
92
+ }> | null;
93
+ }, any>;
94
+ export default _default;