v-code-diff 1.10.0 → 1.12.0
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 +19 -18
- package/dist/v2/index.cjs.js +17 -17
- package/dist/v2/index.es.js +1368 -1238
- package/dist/v2/index.umd.js +17 -17
- package/dist/v2.7/index.cjs.js +18 -18
- package/dist/v2.7/index.es.js +1246 -1200
- package/dist/v2.7/index.umd.js +18 -18
- package/dist/v3/index.cjs.js +16 -16
- package/dist/v3/index.es.js +1405 -1330
- package/dist/v3/index.umd.js +17 -17
- package/package.json +3 -2
- package/src/CodeDiff.vue +51 -2
- package/src/icons/DownArrowIcon.vue +11 -0
- package/src/icons/UpArrowIcon.vue +11 -0
- package/src/style.scss +27 -2
- package/src/utils.ts +6 -4
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "v-code-diff",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.12.0",
|
|
5
5
|
"description": "template component for vue-demi, can dev and build",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"exports": {
|
|
@@ -53,7 +53,8 @@
|
|
|
53
53
|
"diff": "^5.1.0",
|
|
54
54
|
"diff-match-patch": "^1.0.5",
|
|
55
55
|
"highlight.js": "^11.9.0",
|
|
56
|
-
"vue-demi": "^0.14.6"
|
|
56
|
+
"vue-demi": "^0.14.6",
|
|
57
|
+
"vue-i18n": "9"
|
|
57
58
|
},
|
|
58
59
|
"devDependencies": {
|
|
59
60
|
"@antfu/eslint-config": "^2.4.5",
|
package/src/CodeDiff.vue
CHANGED
|
@@ -3,6 +3,8 @@ import { computed, ref, watch } from 'vue-demi'
|
|
|
3
3
|
import { createSplitDiff, createUnifiedDiff } from './utils'
|
|
4
4
|
import UnifiedViewer from './unified/UnifiedViewer.vue'
|
|
5
5
|
import SplitViewer from './split/SplitViewer.vue'
|
|
6
|
+
import DownArrowIcon from './icons/DownArrowIcon.vue'
|
|
7
|
+
import UpArrowIcon from './icons/UpArrowIcon.vue'
|
|
6
8
|
|
|
7
9
|
import './style.scss'
|
|
8
10
|
|
|
@@ -12,6 +14,7 @@ interface Props {
|
|
|
12
14
|
language?: string
|
|
13
15
|
context?: number
|
|
14
16
|
diffStyle?: 'word' | 'char'
|
|
17
|
+
forceInlineComparison?: boolean
|
|
15
18
|
outputFormat?: 'line-by-line' | 'side-by-side'
|
|
16
19
|
trim?: boolean
|
|
17
20
|
noDiffLineFeed?: boolean
|
|
@@ -29,6 +32,7 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
29
32
|
language: 'plaintext',
|
|
30
33
|
context: 10,
|
|
31
34
|
diffStyle: 'word',
|
|
35
|
+
forceInlineComparison: false,
|
|
32
36
|
outputFormat: 'line-by-line',
|
|
33
37
|
trim: false,
|
|
34
38
|
noDiffLineFeed: false,
|
|
@@ -70,12 +74,41 @@ const newString = computed(() => {
|
|
|
70
74
|
|
|
71
75
|
const raw = computed(() =>
|
|
72
76
|
isUnifiedViewer.value
|
|
73
|
-
? createUnifiedDiff(oldString.value, newString.value, props.language, props.diffStyle, props.context, props.ignoreMatchingLines)
|
|
74
|
-
: createSplitDiff(oldString.value, newString.value, props.language, props.diffStyle, props.context, props.ignoreMatchingLines),
|
|
77
|
+
? createUnifiedDiff(oldString.value, newString.value, props.language, props.diffStyle, props.forceInlineComparison, props.context, props.ignoreMatchingLines)
|
|
78
|
+
: createSplitDiff(oldString.value, newString.value, props.language, props.diffStyle, props.forceInlineComparison, props.context, props.ignoreMatchingLines),
|
|
75
79
|
)
|
|
76
80
|
const diffChange = ref(raw.value)
|
|
77
81
|
const isNotChanged = computed(() => diffChange.value.stat.additionsNum === 0 && diffChange.value.stat.deletionsNum === 0)
|
|
78
82
|
|
|
83
|
+
const currentDiffIndex = ref(-1)
|
|
84
|
+
|
|
85
|
+
function goToNextDiff() {
|
|
86
|
+
const diffs = document.querySelectorAll('.blob-code-addition')
|
|
87
|
+
if (currentDiffIndex.value < diffs.length - 1) {
|
|
88
|
+
currentDiffIndex.value++
|
|
89
|
+
updateCurrentDiffHighlight(diffs)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function goToPrevDiff() {
|
|
94
|
+
const diffs = document.querySelectorAll('.blob-code-addition')
|
|
95
|
+
if (currentDiffIndex.value > 0) {
|
|
96
|
+
currentDiffIndex.value--
|
|
97
|
+
updateCurrentDiffHighlight(diffs)
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function updateCurrentDiffHighlight(diffs: NodeListOf<Element>) {
|
|
102
|
+
diffs.forEach((diff: { classList: { remove: (arg0: string) => any } }) => diff.classList.remove('current-diff'))
|
|
103
|
+
|
|
104
|
+
const currentDiff = diffs[currentDiffIndex.value]
|
|
105
|
+
|
|
106
|
+
if (currentDiff) {
|
|
107
|
+
currentDiff.classList.add('current-diff')
|
|
108
|
+
currentDiff.scrollIntoView({ behavior: 'smooth', block: 'center' })
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
79
112
|
watch(() => props, () => {
|
|
80
113
|
diffChange.value = raw.value
|
|
81
114
|
emits('diff', {
|
|
@@ -97,6 +130,14 @@ watch(() => props, () => {
|
|
|
97
130
|
<div class="info-left">{{ filename }}</div>
|
|
98
131
|
<div class="info-left">{{ newFilename }}</div>
|
|
99
132
|
</span>
|
|
133
|
+
<span class="diff-commandbar">
|
|
134
|
+
<button class="command-item-button" title="Next Change" @click="goToNextDiff">
|
|
135
|
+
<DownArrowIcon />
|
|
136
|
+
</button>
|
|
137
|
+
<button class="command-item-button" title="Previous Change" @click="goToPrevDiff">
|
|
138
|
+
<UpArrowIcon />
|
|
139
|
+
</button>
|
|
140
|
+
</span>
|
|
100
141
|
<span v-if="!hideStat" class="diff-stat">
|
|
101
142
|
<slot name="stat" :stat="diffChange.stat">
|
|
102
143
|
<span class="diff-stat-added">+{{ diffChange.stat.additionsNum }} additions</span>
|
|
@@ -109,6 +150,14 @@ watch(() => props, () => {
|
|
|
109
150
|
<span class="info-left">{{ filename }}</span>
|
|
110
151
|
<span class="info-right">
|
|
111
152
|
<span style="margin-left: 20px;">{{ newFilename }}</span>
|
|
153
|
+
<span class="diff-commandbar">
|
|
154
|
+
<button class="command-item-button" title="Next Change" @click="goToNextDiff">
|
|
155
|
+
<DownArrowIcon />
|
|
156
|
+
</button>
|
|
157
|
+
<button class="command-item-button" title="Previous Change" @click="goToPrevDiff">
|
|
158
|
+
<UpArrowIcon />
|
|
159
|
+
</button>
|
|
160
|
+
</span>
|
|
112
161
|
<span v-if="!hideStat" class="diff-stat">
|
|
113
162
|
<slot name="stat" :stat="diffChange.stat">
|
|
114
163
|
<span class="diff-stat-added">+{{ diffChange.stat.additionsNum }} additions</span>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
export default {
|
|
3
|
+
name: 'DownArrowIcon',
|
|
4
|
+
}
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<template>
|
|
8
|
+
<svg width="1rem" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg">
|
|
9
|
+
<path d="M383.6,322.7L278.6,423c-5.8,6-13.7,9-22.4,9c-8.7,0-16.5-3-22.4-9L128.4,322.7c-12.5-11.9-12.5-31.3,0-43.2 c12.5-11.9,32.7-11.9,45.2,0l50.4,48.2v-217c0-16.9,14.3-30.6,32-30.6c17.7,0,32,13.7,32,30.6v217l50.4-48.2 c12.5-11.9,32.7-11.9,45.2,0C396.1,291.4,396.1,310.7,383.6,322.7z" />
|
|
10
|
+
</svg>
|
|
11
|
+
</template>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
export default {
|
|
3
|
+
name: 'UpArrowIcon',
|
|
4
|
+
}
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
<template>
|
|
8
|
+
<svg width="1rem" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg">
|
|
9
|
+
<path d="M128.4,189.3L233.4,89c5.8-6,13.7-9,22.4-9c8.7,0,16.5,3,22.4,9l105.4,100.3c12.5,11.9,12.5,31.3,0,43.2 c-12.5,11.9-32.7,11.9-45.2,0L288,184.4v217c0,16.9-14.3,30.6-32,30.6c-17.7,0-32-13.7-32-30.6v-217l-50.4,48.2 c-12.5,11.9-32.7,11.9-45.2,0C115.9,220.6,115.9,201.3,128.4,189.3z" />
|
|
10
|
+
</svg>
|
|
11
|
+
</template>
|
package/src/style.scss
CHANGED
|
@@ -15,12 +15,14 @@
|
|
|
15
15
|
overflow-y: auto;
|
|
16
16
|
|
|
17
17
|
.file-header {
|
|
18
|
+
position: sticky;
|
|
19
|
+
top: 0;
|
|
20
|
+
z-index: 1;
|
|
18
21
|
background-color: var(--color-canvas-subtle);
|
|
19
22
|
border-bottom: 1px solid var(--color-border-default);
|
|
20
23
|
padding: 8px 16px;
|
|
21
24
|
font-size: 12px;
|
|
22
|
-
font-family: ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace;
|
|
23
|
-
|
|
25
|
+
font-family: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace;
|
|
24
26
|
.file-info {
|
|
25
27
|
display: flex;
|
|
26
28
|
justify-content: space-between;
|
|
@@ -51,6 +53,25 @@
|
|
|
51
53
|
color: var(--color-fg-subtle);
|
|
52
54
|
}
|
|
53
55
|
}
|
|
56
|
+
|
|
57
|
+
.diff-commandbar {
|
|
58
|
+
margin-left: auto;
|
|
59
|
+
margin-right: 1rem;
|
|
60
|
+
|
|
61
|
+
.command-item-button {
|
|
62
|
+
background-color: transparent;
|
|
63
|
+
color: var(--color-fg-subtle);
|
|
64
|
+
border: none;
|
|
65
|
+
|
|
66
|
+
svg {
|
|
67
|
+
fill: var(--color-fg-subtle);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.command-item-button:hover {
|
|
72
|
+
background-color: var(--color-btn-outline-hover-border);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
54
75
|
}
|
|
55
76
|
}
|
|
56
77
|
|
|
@@ -122,6 +143,10 @@
|
|
|
122
143
|
background-color: var(--color-diff-blob-addition-word-bg);
|
|
123
144
|
}
|
|
124
145
|
}
|
|
146
|
+
|
|
147
|
+
.current-diff {
|
|
148
|
+
border: 1px solid var(--color-border-muted);
|
|
149
|
+
}
|
|
125
150
|
|
|
126
151
|
.blob-code-context,
|
|
127
152
|
.blob-code-addition,
|
package/src/utils.ts
CHANGED
|
@@ -170,6 +170,7 @@ export function createSplitDiff(
|
|
|
170
170
|
newString: string,
|
|
171
171
|
language = 'plaintext',
|
|
172
172
|
diffStyle = 'word',
|
|
173
|
+
forceInlineComparison = false,
|
|
173
174
|
context = 10,
|
|
174
175
|
ignoreMatchingLines?: string,
|
|
175
176
|
): SplitViewerChange {
|
|
@@ -270,9 +271,9 @@ export function createSplitDiff(
|
|
|
270
271
|
addNum++
|
|
271
272
|
|
|
272
273
|
const [curLine, nextLine] = [curLines[j], nextLines[j]]
|
|
273
|
-
|
|
274
|
-
const leftLine =
|
|
275
|
-
const rightLine =
|
|
274
|
+
const shouldRenderWords = forceInlineComparison || curLines.length === nextLines.length
|
|
275
|
+
const leftLine = shouldRenderWords ? renderWords(nextLine, curLine, diffStyle) : curLine
|
|
276
|
+
const rightLine = shouldRenderWords ? renderWords(curLine, nextLine, diffStyle) : nextLine
|
|
276
277
|
|
|
277
278
|
// 忽略匹配的行等价于相等
|
|
278
279
|
const leftDiffType = ignoreRegex?.test(curLine) ? DiffType.EQUAL : DiffType.DELETE
|
|
@@ -361,6 +362,7 @@ export function createUnifiedDiff(
|
|
|
361
362
|
newString: string,
|
|
362
363
|
language = 'plaintext',
|
|
363
364
|
diffStyle = 'word',
|
|
365
|
+
forceInlineComparison = false,
|
|
364
366
|
context = 10,
|
|
365
367
|
ignoreMatchingLines?: string,
|
|
366
368
|
): UnifiedViewerChange {
|
|
@@ -430,7 +432,7 @@ export function createUnifiedDiff(
|
|
|
430
432
|
// 处理当前 diff 为删除的情况
|
|
431
433
|
if (curType === DiffType.DELETE) {
|
|
432
434
|
// 下一处差异为新增,且删除与新增行数相同时,对每行依次 diff
|
|
433
|
-
if (nextType === DiffType.ADD && curLines.length === nextLines.length) {
|
|
435
|
+
if (nextType === DiffType.ADD && (curLines.length === nextLines.length || forceInlineComparison)) {
|
|
434
436
|
for (let j = 0; j < curLines.length; j++) {
|
|
435
437
|
const curLine = curLines[j]
|
|
436
438
|
const nextLine = nextLines[j]
|