v-code-diff 1.4.0 → 1.5.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 +3 -111
- package/dist/v2/index.cjs.js +13 -13
- package/dist/v2/index.es.js +557 -485
- package/dist/v2/index.umd.js +13 -13
- package/dist/v2.7/index.cjs.js +15 -15
- package/dist/v2.7/index.es.js +703 -662
- package/dist/v2.7/index.umd.js +15 -15
- package/dist/v3/index.cjs.js +13 -13
- package/dist/v3/index.es.js +559 -512
- package/dist/v3/index.umd.js +13 -13
- package/package.json +1 -1
- package/src/CodeDiff.vue +17 -11
- package/src/split/SplitLine.vue +21 -26
- package/src/split/SplitViewer.vue +11 -2
- package/src/types.ts +17 -0
- package/src/unified/UnifiedLine.vue +7 -6
- package/src/unified/UnifiedViewer.vue +12 -3
- package/src/utils.ts +50 -10
package/src/CodeDiff.vue
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { computed } from 'vue-demi'
|
|
2
|
+
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'
|
|
@@ -34,19 +34,27 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
34
34
|
const isUnifiedViewer = computed(() => props.outputFormat === 'line-by-line')
|
|
35
35
|
|
|
36
36
|
const oldString = computed(() => {
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
let value = props.oldString || ''
|
|
38
|
+
value = props.trim ? value.trim() : value
|
|
39
|
+
value = props.noDiffLineFeed ? value.replace(/(\r\n)/g, '\n') : value
|
|
40
|
+
return value
|
|
39
41
|
})
|
|
40
42
|
const newString = computed(() => {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
+
let value = props.newString || ''
|
|
44
|
+
value = props.trim ? value.trim() : value
|
|
45
|
+
value = props.noDiffLineFeed ? value.replace(/(\r\n)/g, '\n') : value
|
|
46
|
+
return value
|
|
43
47
|
})
|
|
44
48
|
|
|
45
|
-
const
|
|
49
|
+
const raw = computed(() =>
|
|
46
50
|
isUnifiedViewer.value
|
|
47
51
|
? createUnifiedDiff(oldString.value, newString.value, props.language, props.diffStyle, props.context)
|
|
48
52
|
: createSplitDiff(oldString.value, newString.value, props.language, props.diffStyle, props.context),
|
|
49
53
|
)
|
|
54
|
+
const diffChange = ref(raw.value)
|
|
55
|
+
watch(() => props, () => {
|
|
56
|
+
diffChange.value = raw.value
|
|
57
|
+
}, { deep: true })
|
|
50
58
|
</script>
|
|
51
59
|
|
|
52
60
|
<template>
|
|
@@ -60,11 +68,9 @@ const diffChange = computed(() =>
|
|
|
60
68
|
</span>
|
|
61
69
|
</div>
|
|
62
70
|
</div>
|
|
63
|
-
<UnifiedViewer v-if="isUnifiedViewer" :diff-change="diffChange
|
|
64
|
-
<SplitViewer v-else :diff-change="diffChange
|
|
71
|
+
<UnifiedViewer v-if="isUnifiedViewer" :diff-change="diffChange" />
|
|
72
|
+
<SplitViewer v-else :diff-change="diffChange" />
|
|
65
73
|
</div>
|
|
66
74
|
</template>
|
|
67
75
|
|
|
68
|
-
<style lang="scss">
|
|
69
|
-
|
|
70
|
-
</style>
|
|
76
|
+
<style lang="scss"></style>
|
package/src/split/SplitLine.vue
CHANGED
|
@@ -5,6 +5,7 @@ import type { SplitLineChange } from '../types'
|
|
|
5
5
|
const props = defineProps<{
|
|
6
6
|
splitLine: SplitLineChange
|
|
7
7
|
}>()
|
|
8
|
+
const emit = defineEmits(['expand'])
|
|
8
9
|
|
|
9
10
|
const getCodeMarker = (type: DiffType) => {
|
|
10
11
|
if (type === DiffType.DELETE)
|
|
@@ -16,15 +17,15 @@ const getCodeMarker = (type: DiffType) => {
|
|
|
16
17
|
</script>
|
|
17
18
|
|
|
18
19
|
<template>
|
|
19
|
-
<tr v-if="splitLine.
|
|
20
|
-
<td class="blob-num blob-num-hunk" colspan="1">
|
|
20
|
+
<tr v-if="splitLine.hideIndex !== undefined && splitLine.hide">
|
|
21
|
+
<td class="blob-num blob-num-hunk" colspan="1" @click="emit('expand', splitLine)">
|
|
21
22
|
>
|
|
22
23
|
</td>
|
|
23
24
|
<td class="blob-code blob-code-inner blob-code-hunk" colspan="3" align="left">
|
|
24
25
|
⋯
|
|
25
26
|
</td>
|
|
26
27
|
</tr>
|
|
27
|
-
<tr v-else>
|
|
28
|
+
<tr v-else-if="!splitLine.hide">
|
|
28
29
|
<template v-for="line in [splitLine.left, splitLine.right]">
|
|
29
30
|
<!-- eslint-disable -->
|
|
30
31
|
<template v-if="line.type === DiffType.EMPTY">
|
|
@@ -32,29 +33,24 @@ const getCodeMarker = (type: DiffType) => {
|
|
|
32
33
|
<td class="blob-code blob-code-empty empty-cell" />
|
|
33
34
|
</template>
|
|
34
35
|
<template v-else>
|
|
35
|
-
<td
|
|
36
|
-
|
|
37
|
-
:
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
>
|
|
36
|
+
<td class="blob-num" :class="{
|
|
37
|
+
'blob-num-deletion': line.type === DiffType.DELETE,
|
|
38
|
+
'blob-num-addition': line.type === DiffType.ADD,
|
|
39
|
+
'blob-num-context': line.type === DiffType.EQUAL,
|
|
40
|
+
'blob-num-hunk': splitLine.hide !== undefined,
|
|
41
|
+
|
|
42
|
+
}">
|
|
43
43
|
{{ line.num }}
|
|
44
44
|
</td>
|
|
45
|
-
<td
|
|
46
|
-
|
|
47
|
-
:
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
class="blob-code-inner blob-code-marker"
|
|
55
|
-
:data-code-marker="getCodeMarker(line.type)"
|
|
56
|
-
v-html="line.code"
|
|
57
|
-
/>
|
|
45
|
+
<td class="blob-code" :class="{
|
|
46
|
+
'blob-code-deletion': line.type === DiffType.DELETE,
|
|
47
|
+
'blob-code-addition': line.type === DiffType.ADD,
|
|
48
|
+
'blob-code-context': line.type === DiffType.EQUAL,
|
|
49
|
+
'blob-code-hunk': splitLine.hide !== undefined,
|
|
50
|
+
|
|
51
|
+
}">
|
|
52
|
+
<span class="blob-code-inner blob-code-marker" :data-code-marker="getCodeMarker(line.type)"
|
|
53
|
+
v-html="line.code" />
|
|
58
54
|
</td>
|
|
59
55
|
</template>
|
|
60
56
|
<!-- eslint-enable -->
|
|
@@ -62,5 +58,4 @@ const getCodeMarker = (type: DiffType) => {
|
|
|
62
58
|
</tr>
|
|
63
59
|
</template>
|
|
64
60
|
|
|
65
|
-
<style lang="scss">
|
|
66
|
-
</style>
|
|
61
|
+
<style lang="scss"></style>
|
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import type { SplitViewerChange } from '../types'
|
|
2
|
+
import type { SplitLineChange, SplitViewerChange } from '../types'
|
|
3
3
|
import SplitLine from './SplitLine.vue'
|
|
4
4
|
|
|
5
5
|
const props = defineProps<{
|
|
6
6
|
diffChange: SplitViewerChange
|
|
7
7
|
}>()
|
|
8
|
+
|
|
9
|
+
function expandHandler({ hideIndex }: SplitLineChange) {
|
|
10
|
+
if (hideIndex === undefined)
|
|
11
|
+
return
|
|
12
|
+
props.diffChange.collector[hideIndex!].lines.forEach((line) => {
|
|
13
|
+
line.hide = false
|
|
14
|
+
line.fold = false
|
|
15
|
+
})
|
|
16
|
+
}
|
|
8
17
|
</script>
|
|
9
18
|
|
|
10
19
|
<template>
|
|
@@ -16,7 +25,7 @@ const props = defineProps<{
|
|
|
16
25
|
<col>
|
|
17
26
|
</colgroup>
|
|
18
27
|
<tbody>
|
|
19
|
-
<SplitLine v-for="(item, index) in diffChange" :key="index" :split-line="item" />
|
|
28
|
+
<SplitLine v-for="(item, index) in diffChange?.changes" :key="index" :split-line="item" @expand="expandHandler" />
|
|
20
29
|
</tbody>
|
|
21
30
|
</table>
|
|
22
31
|
</template>
|
package/src/types.ts
CHANGED
|
@@ -5,6 +5,16 @@ export const enum DiffType {
|
|
|
5
5
|
EMPTY = 'empty',
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
+
export interface UnifiedLineUnchanges {
|
|
9
|
+
lines: UnifiedLineChange[]
|
|
10
|
+
fold: boolean
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface SplitLineUnchanges {
|
|
14
|
+
lines: SplitLineChange[]
|
|
15
|
+
fold: boolean
|
|
16
|
+
}
|
|
17
|
+
|
|
8
18
|
export interface DiffLine {
|
|
9
19
|
type: DiffType
|
|
10
20
|
code?: string
|
|
@@ -15,6 +25,8 @@ export interface SplitLineChange {
|
|
|
15
25
|
fold?: boolean
|
|
16
26
|
left: DiffLine
|
|
17
27
|
right: DiffLine
|
|
28
|
+
hide?: boolean
|
|
29
|
+
hideIndex?: number
|
|
18
30
|
}
|
|
19
31
|
|
|
20
32
|
export interface UnifiedLineChange {
|
|
@@ -23,18 +35,23 @@ export interface UnifiedLineChange {
|
|
|
23
35
|
code: string
|
|
24
36
|
delNum?: number
|
|
25
37
|
addNum?: number
|
|
38
|
+
hide?: boolean
|
|
39
|
+
hideIndex?: number
|
|
26
40
|
}
|
|
27
41
|
|
|
28
42
|
export interface DiffStat {
|
|
29
43
|
additionsNum: number
|
|
30
44
|
deletionsNum: number
|
|
31
45
|
}
|
|
46
|
+
|
|
32
47
|
export interface SplitViewerChange {
|
|
33
48
|
changes: SplitLineChange[]
|
|
49
|
+
collector: SplitLineUnchanges[]
|
|
34
50
|
stat: DiffStat
|
|
35
51
|
}
|
|
36
52
|
|
|
37
53
|
export interface UnifiedViewerChange {
|
|
38
54
|
changes: UnifiedLineChange[]
|
|
55
|
+
collector: UnifiedLineUnchanges[]
|
|
39
56
|
stat: DiffStat
|
|
40
57
|
}
|
|
@@ -5,6 +5,7 @@ import { DiffType } from '../types'
|
|
|
5
5
|
const props = defineProps<{
|
|
6
6
|
line: UnifiedLineChange
|
|
7
7
|
}>()
|
|
8
|
+
const emit = defineEmits(['expand'])
|
|
8
9
|
|
|
9
10
|
const getCodeMarker = (type: DiffType) => {
|
|
10
11
|
if (type === DiffType.DELETE)
|
|
@@ -16,24 +17,22 @@ const getCodeMarker = (type: DiffType) => {
|
|
|
16
17
|
</script>
|
|
17
18
|
|
|
18
19
|
<template>
|
|
19
|
-
<tr v-if="line.
|
|
20
|
-
<td class="blob-num blob-num-hunk">
|
|
21
|
-
>
|
|
22
|
-
</td>
|
|
23
|
-
<td class="blob-num blob-num-hunk">
|
|
20
|
+
<tr v-if="line.hideIndex !== undefined && line.hide">
|
|
21
|
+
<td class="blob-num blob-num-hunk text-center" colspan="2" @click="emit('expand', line)">
|
|
24
22
|
>
|
|
25
23
|
</td>
|
|
26
24
|
<td class="blob-code blob-code-hunk" align="left">
|
|
27
25
|
⋯
|
|
28
26
|
</td>
|
|
29
27
|
</tr>
|
|
30
|
-
<tr v-else>
|
|
28
|
+
<tr v-else-if="!line.hide">
|
|
31
29
|
<td
|
|
32
30
|
class="blob-num"
|
|
33
31
|
:class="{
|
|
34
32
|
'blob-num-deletion': line.type === DiffType.DELETE,
|
|
35
33
|
'blob-num-addition': line.type === DiffType.ADD,
|
|
36
34
|
'blob-num-context': line.type === DiffType.EQUAL,
|
|
35
|
+
'blob-num-hunk': line.hide !== undefined,
|
|
37
36
|
}"
|
|
38
37
|
>
|
|
39
38
|
{{ line.delNum }}
|
|
@@ -44,6 +43,7 @@ const getCodeMarker = (type: DiffType) => {
|
|
|
44
43
|
'blob-num-deletion': line.type === DiffType.DELETE,
|
|
45
44
|
'blob-num-addition': line.type === DiffType.ADD,
|
|
46
45
|
'blob-num-context': line.type === DiffType.EQUAL,
|
|
46
|
+
'blob-num-hunk': line.hide !== undefined,
|
|
47
47
|
}"
|
|
48
48
|
>
|
|
49
49
|
{{ line.addNum }}
|
|
@@ -54,6 +54,7 @@ const getCodeMarker = (type: DiffType) => {
|
|
|
54
54
|
'blob-code-deletion': line.type === DiffType.DELETE,
|
|
55
55
|
'blob-code-addition': line.type === DiffType.ADD,
|
|
56
56
|
'blob-code-context': line.type === DiffType.EQUAL,
|
|
57
|
+
'blob-code-hunk': line.hide !== undefined,
|
|
57
58
|
}"
|
|
58
59
|
>
|
|
59
60
|
<span class="blob-code-inner blob-code-marker" :data-code-marker="getCodeMarker(line.type)" v-html="line.code" />
|
|
@@ -1,16 +1,25 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import type { UnifiedLineChange } from '../types'
|
|
2
|
+
import type { UnifiedLineChange, UnifiedViewerChange } from '../types'
|
|
3
3
|
import UnifiedLine from './UnifiedLine.vue'
|
|
4
4
|
|
|
5
5
|
const props = defineProps<{
|
|
6
|
-
diffChange:
|
|
6
|
+
diffChange: UnifiedViewerChange
|
|
7
7
|
}>()
|
|
8
|
+
|
|
9
|
+
function expandHandler({ hideIndex }: UnifiedLineChange) {
|
|
10
|
+
if (hideIndex === undefined)
|
|
11
|
+
return
|
|
12
|
+
props.diffChange.collector[hideIndex!].lines.forEach((line) => {
|
|
13
|
+
line.hide = false
|
|
14
|
+
line.fold = false
|
|
15
|
+
})
|
|
16
|
+
}
|
|
8
17
|
</script>
|
|
9
18
|
|
|
10
19
|
<template>
|
|
11
20
|
<table class="diff-table">
|
|
12
21
|
<tbody>
|
|
13
|
-
<UnifiedLine v-for="(item, index) in diffChange" :key="index" :line="item" />
|
|
22
|
+
<UnifiedLine v-for="(item, index) in diffChange?.changes" :key="index" :line="item" @expand="expandHandler" />
|
|
14
23
|
</tbody>
|
|
15
24
|
</table>
|
|
16
25
|
</template>
|
package/src/utils.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { Change } from 'diff'
|
|
|
3
3
|
import { DIFF_DELETE, DIFF_INSERT, diff_match_patch as DiffMatchPatch } from 'diff-match-patch'
|
|
4
4
|
import hljs from './highlight'
|
|
5
5
|
import { DiffType } from './types'
|
|
6
|
-
import type { DiffLine, DiffStat, SplitLineChange, SplitViewerChange, UnifiedLineChange, UnifiedViewerChange } from './types'
|
|
6
|
+
import type { DiffLine, DiffStat, SplitLineChange, SplitLineUnchanges, SplitViewerChange, UnifiedLineChange, UnifiedLineUnchanges, UnifiedViewerChange } from './types'
|
|
7
7
|
|
|
8
8
|
const MODIFIED_START_TAG = '<code-diff-modified>'
|
|
9
9
|
const MODIFIED_CLOSE_TAG = '</code-diff-modified>'
|
|
@@ -168,6 +168,7 @@ export function createSplitDiff(
|
|
|
168
168
|
const rawChanges: SplitLineChange[] = []
|
|
169
169
|
const result: SplitViewerChange = {
|
|
170
170
|
changes: rawChanges,
|
|
171
|
+
collector: [],
|
|
171
172
|
stat: calcDiffStat(changes),
|
|
172
173
|
}
|
|
173
174
|
|
|
@@ -208,7 +209,6 @@ export function createSplitDiff(
|
|
|
208
209
|
left = newEmptySplitDiff()
|
|
209
210
|
right = newSplitDiff(DiffType.ADD, addNum, highlightCode)
|
|
210
211
|
}
|
|
211
|
-
|
|
212
212
|
rawChanges.push({ left, right })
|
|
213
213
|
}
|
|
214
214
|
break
|
|
@@ -300,17 +300,35 @@ export function createSplitDiff(
|
|
|
300
300
|
line.fold = true
|
|
301
301
|
}
|
|
302
302
|
|
|
303
|
-
const processedChanges = []
|
|
303
|
+
const processedChanges: SplitViewerChange['changes'] = []
|
|
304
|
+
let unchanges: SplitLineUnchanges['lines'] = [] // collector for unchanged lines.
|
|
305
|
+
|
|
304
306
|
for (let i = 0; i < rawChanges.length; i++) {
|
|
305
307
|
const line = rawChanges[i]
|
|
306
308
|
if (line.fold === false) {
|
|
309
|
+
if (unchanges.length) {
|
|
310
|
+
unchanges[0].hideIndex = result.collector.length
|
|
311
|
+
result.collector.push({
|
|
312
|
+
lines: unchanges,
|
|
313
|
+
fold: true,
|
|
314
|
+
})
|
|
315
|
+
unchanges = []
|
|
316
|
+
}
|
|
307
317
|
processedChanges.push(line)
|
|
308
318
|
continue
|
|
309
319
|
}
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
320
|
+
|
|
321
|
+
line.hide = true
|
|
322
|
+
unchanges.push(line)
|
|
323
|
+
processedChanges.push(line)
|
|
324
|
+
}
|
|
325
|
+
if (unchanges.length) {
|
|
326
|
+
unchanges[0].hideIndex = result.collector.length
|
|
327
|
+
result.collector.push({
|
|
328
|
+
lines: unchanges,
|
|
329
|
+
fold: true,
|
|
330
|
+
})
|
|
331
|
+
unchanges = []
|
|
314
332
|
}
|
|
315
333
|
result.changes = processedChanges
|
|
316
334
|
|
|
@@ -333,6 +351,7 @@ export function createUnifiedDiff(
|
|
|
333
351
|
const rawChanges: UnifiedLineChange[] = []
|
|
334
352
|
const result: UnifiedViewerChange = {
|
|
335
353
|
changes: rawChanges,
|
|
354
|
+
collector: [],
|
|
336
355
|
stat: calcDiffStat(changes),
|
|
337
356
|
}
|
|
338
357
|
|
|
@@ -449,16 +468,37 @@ export function createUnifiedDiff(
|
|
|
449
468
|
}
|
|
450
469
|
|
|
451
470
|
const processedChanges = []
|
|
471
|
+
let unchanges: UnifiedLineUnchanges['lines'] = [] // collector for unchanged lines.
|
|
472
|
+
|
|
452
473
|
for (let i = 0; i < rawChanges.length; i++) {
|
|
453
474
|
const line = rawChanges[i]
|
|
454
475
|
if (line.fold === false) {
|
|
476
|
+
if (unchanges.length) {
|
|
477
|
+
unchanges[0].hideIndex = result.collector.length
|
|
478
|
+
// Keeps "hideIndex" in first element of collector
|
|
479
|
+
// for delegating lines to expand.
|
|
480
|
+
result.collector.push({
|
|
481
|
+
lines: unchanges,
|
|
482
|
+
fold: true,
|
|
483
|
+
})
|
|
484
|
+
unchanges = []
|
|
485
|
+
}
|
|
455
486
|
processedChanges.push(line)
|
|
456
487
|
continue
|
|
457
488
|
}
|
|
458
|
-
if (line.
|
|
459
|
-
|
|
460
|
-
|
|
489
|
+
if (line.type === 'equal') {
|
|
490
|
+
line.hide = true
|
|
491
|
+
unchanges.push(line)
|
|
461
492
|
}
|
|
493
|
+
processedChanges.push(line)
|
|
494
|
+
}
|
|
495
|
+
if (unchanges.length) {
|
|
496
|
+
unchanges[0].hideIndex = result.collector.length
|
|
497
|
+
result.collector.push({
|
|
498
|
+
lines: unchanges,
|
|
499
|
+
fold: true,
|
|
500
|
+
})
|
|
501
|
+
unchanges = []
|
|
462
502
|
}
|
|
463
503
|
result.changes = processedChanges
|
|
464
504
|
|