v-code-diff 0.3.12 → 1.0.0-alpha.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/LICENSE +1 -1
- package/README.md +136 -92
- package/dist/v2/index.cjs.js +9 -0
- package/dist/v2/index.es.js +4526 -0
- package/dist/v2.7/index.cjs.js +9 -0
- package/dist/v2.7/index.es.js +4337 -0
- package/dist/v3/index.cjs.js +9 -0
- package/dist/v3/index.es.js +4315 -0
- package/package.json +44 -87
- package/scripts/postinstall.js +18 -0
- package/scripts/utils.js +36 -0
- package/src/CodeDiff.vue +57 -0
- package/src/highlight.ts +23 -0
- package/src/index.ts +15 -0
- package/src/split/SplitLine.vue +66 -0
- package/src/split/SplitViewer.vue +26 -0
- package/src/style.scss +114 -0
- package/src/types.ts +29 -0
- package/src/unified/UnifiedLine.vue +62 -0
- package/src/unified/UnifiedViewer.vue +20 -0
- package/src/utils.ts +418 -0
- package/src/var.scss +439 -0
- package/types/index.d.ts +14 -0
- package/dist/index.d.ts +0 -6
- package/dist/v-code-diff/index.d.ts +0 -2
- package/dist/v-code-diff/styles/index.d.ts +0 -3
- package/dist/v-code-diff/util.d.ts +0 -21
- package/dist/v-code-diff/v-code-diff.d.ts +0 -129
- package/dist/v-code-diff.cjs.js +0 -1
- package/dist/v-code-diff.esm.js +0 -1
- package/dist/v-code-diff.umd.js +0 -1
- package/src/lib/index.ts +0 -13
- package/src/lib/v-code-diff/index.ts +0 -3
- package/src/lib/v-code-diff/styles/highlight.scss +0 -84
- package/src/lib/v-code-diff/styles/index.ts +0 -3
- package/src/lib/v-code-diff/styles/style.scss +0 -36
- package/src/lib/v-code-diff/util.ts +0 -104
- package/src/lib/v-code-diff/v-code-diff.ts +0 -104
package/package.json
CHANGED
|
@@ -1,43 +1,44 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "v-code-diff",
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
"
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
"gh-pages": "vite build --base=/v-code-diff/ && gh-pages -d ./pages"
|
|
3
|
+
"version": "1.0.0-alpha.1",
|
|
4
|
+
"description": "template component for vue-demi, can dev and build",
|
|
5
|
+
"main": "dist/index.cjs",
|
|
6
|
+
"module": "dist/index.es.js",
|
|
7
|
+
"types": "./types/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.es.js",
|
|
11
|
+
"require": "./dist/index.cjs.js"
|
|
12
|
+
}
|
|
14
13
|
},
|
|
15
|
-
"main": "dist/v-code-diff.cjs.js",
|
|
16
|
-
"module": "dist/v-code-diff.esm.js",
|
|
17
|
-
"unpkg": "dist/v-code-diff.umd.js",
|
|
18
14
|
"files": [
|
|
15
|
+
"scripts",
|
|
19
16
|
"dist",
|
|
20
|
-
"src
|
|
21
|
-
|
|
22
|
-
"types": "dist/index.d.ts",
|
|
23
|
-
"keywords": [
|
|
24
|
-
"vue",
|
|
25
|
-
"vue3",
|
|
26
|
-
"code",
|
|
27
|
-
"diff"
|
|
17
|
+
"src",
|
|
18
|
+
"types"
|
|
28
19
|
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "npm run clean && run-s build:*",
|
|
22
|
+
"build:2": "vue-demi-switch 2 vue2 && pnpm --filter vue2-playground build",
|
|
23
|
+
"build:2.7": "vue-demi-switch 2.7 vue2 && pnpm --filter vue2.7-playground build",
|
|
24
|
+
"build:3": "vue-demi-switch 3 vue3 && pnpm --filter vue3-playground build",
|
|
25
|
+
"clean": "rimraf ./dist",
|
|
26
|
+
"dev:2": "vue-demi-switch 2 vue2 && pnpm --filter vue2-playground dev",
|
|
27
|
+
"dev:2.7": "vue-demi-switch 2.7 vue2 && pnpm --filter vue2.7-playground dev",
|
|
28
|
+
"dev:3": "vue-demi-switch 3 vue3 && pnpm --filter vue3-playground dev",
|
|
29
|
+
"lint:fix": "eslint . --ext .vue,.js,.jsx,.ts,.tsx --fix --ignore-path .gitignore",
|
|
30
|
+
"postinstall": "node scripts/postinstall.js",
|
|
31
|
+
"prepublishOnly": "npm run build",
|
|
32
|
+
"release": "bumpp --no-commit --no-push --no-tag --preid alpha && npm publish --tag alpha"
|
|
33
|
+
},
|
|
29
34
|
"author": "Shimada666<649940882@qq.com>",
|
|
30
35
|
"license": "MIT",
|
|
31
|
-
"bugs": {
|
|
32
|
-
"url": "https://github.com/Shimada666/v-code-diff/issues"
|
|
33
|
-
},
|
|
34
36
|
"repository": {
|
|
35
|
-
"type": "git"
|
|
36
|
-
"url": "git+https://github.com/Shimada666/v-code-diff.git"
|
|
37
|
+
"type": "git"
|
|
37
38
|
},
|
|
38
39
|
"peerDependencies": {
|
|
39
|
-
"@vue/composition-api": "^1.
|
|
40
|
-
"vue": "^2.
|
|
40
|
+
"@vue/composition-api": "^1.4.9",
|
|
41
|
+
"vue": "^2.6.0 || >=3.0.0"
|
|
41
42
|
},
|
|
42
43
|
"peerDependenciesMeta": {
|
|
43
44
|
"@vue/composition-api": {
|
|
@@ -46,67 +47,23 @@
|
|
|
46
47
|
},
|
|
47
48
|
"dependencies": {
|
|
48
49
|
"diff": "^5.0.0",
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"vue-demi": "^0.13.6"
|
|
50
|
+
"highlight.js": "^11.6.0",
|
|
51
|
+
"vue-demi": "latest"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
|
-
"@
|
|
55
|
-
"@commitlint/cli": "^8.2.0",
|
|
56
|
-
"@commitlint/config-conventional": "^8.2.0",
|
|
57
|
-
"@rollup/plugin-node-resolve": "^11.1.1",
|
|
54
|
+
"@antfu/eslint-config": "^0.34.0",
|
|
58
55
|
"@types/diff": "^5.0.0",
|
|
59
|
-
"@types/node": "^
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
"
|
|
66
|
-
"
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
"body-parser": "^1.19.0",
|
|
70
|
-
"commitizen": "^4.2.3",
|
|
71
|
-
"conventional-changelog-cli": "^2.1.1",
|
|
72
|
-
"cross-env": "^7.0.3",
|
|
73
|
-
"dotenv": "^8.2.0",
|
|
74
|
-
"eslint": "^7.22.0",
|
|
75
|
-
"eslint-plugin-import": "^2.22.1",
|
|
76
|
-
"eslint-plugin-vue": "^7.17.0",
|
|
77
|
-
"gh-pages": "^3.2.1",
|
|
78
|
-
"lint-staged": "^10.5.4",
|
|
79
|
-
"rollup": "^2.38.5",
|
|
80
|
-
"rollup-plugin-styles": "^3.14.1",
|
|
81
|
-
"rollup-plugin-terser": "^7.0.2",
|
|
82
|
-
"rollup-plugin-typescript2": "^0.29.0",
|
|
83
|
-
"rollup-plugin-vue": "^6.0.0",
|
|
84
|
-
"sass": "^1.35.1",
|
|
85
|
-
"stylelint": "^13.12.0",
|
|
86
|
-
"stylelint-config-prettier": "^8.0.2",
|
|
87
|
-
"stylelint-config-standard": "^21.0.0",
|
|
88
|
-
"stylelint-order": "^4.1.0",
|
|
89
|
-
"typescript": "^4.4.2",
|
|
90
|
-
"vite": "^2.5.6",
|
|
91
|
-
"vue": "^3.2.11",
|
|
92
|
-
"vue-eslint-parser": "^7.11.0",
|
|
93
|
-
"vue-tsc": "^0.3.0",
|
|
56
|
+
"@types/node": "^18.11.18",
|
|
57
|
+
"bumpp": "^8.2.1",
|
|
58
|
+
"eslint": "^8.31.0",
|
|
59
|
+
"npm-run-all": "^4.1.5",
|
|
60
|
+
"rimraf": "^3.0.2",
|
|
61
|
+
"sass": "^1.57.1",
|
|
62
|
+
"typescript": "~4.7.4",
|
|
63
|
+
"vite": "^4.0.4",
|
|
64
|
+
"vite-plugin-css-injected-by-js": "^2.4.0",
|
|
65
|
+
"vue-tsc": "^0.40.13",
|
|
94
66
|
"vue2": "npm:vue@2",
|
|
95
|
-
"
|
|
96
|
-
},
|
|
97
|
-
"gitHooks": {
|
|
98
|
-
"pre-commit": "lint-staged",
|
|
99
|
-
"commit-msg": "commitlint -e"
|
|
100
|
-
},
|
|
101
|
-
"config": {
|
|
102
|
-
"commitizen": {
|
|
103
|
-
"path": "cz-conventional-changelog"
|
|
104
|
-
}
|
|
105
|
-
},
|
|
106
|
-
"lint-staged": {
|
|
107
|
-
"*.{js,vue,ts}": [
|
|
108
|
-
"eslint --ext .ts,.vue,.tsx src",
|
|
109
|
-
"git add"
|
|
110
|
-
]
|
|
67
|
+
"vue3": "npm:vue@3"
|
|
111
68
|
}
|
|
112
69
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const { switchVersion, loadModule } = require('./utils')
|
|
2
|
+
|
|
3
|
+
const Vue = loadModule('vue')
|
|
4
|
+
|
|
5
|
+
if (!Vue || typeof Vue.version !== 'string')
|
|
6
|
+
console.warn('[vue-demi-sfc-component-template] Vue is not found. Please run "npm install vue" to install.')
|
|
7
|
+
|
|
8
|
+
else if (Vue.version.startsWith('2.7.'))
|
|
9
|
+
switchVersion('2.7')
|
|
10
|
+
|
|
11
|
+
else if (Vue.version.startsWith('2.'))
|
|
12
|
+
switchVersion('2')
|
|
13
|
+
|
|
14
|
+
else if (Vue.version.startsWith('3.'))
|
|
15
|
+
switchVersion('3')
|
|
16
|
+
|
|
17
|
+
else
|
|
18
|
+
console.warn(`[vue-demi-sfc-component-template] Vue version v${Vue.version} is not suppported.`)
|
package/scripts/utils.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
const fs = require('fs')
|
|
2
|
+
const path = require('path')
|
|
3
|
+
|
|
4
|
+
const dir = path.resolve(__dirname, '..', 'dist')
|
|
5
|
+
|
|
6
|
+
function loadModule(name) {
|
|
7
|
+
try {
|
|
8
|
+
return require(name)
|
|
9
|
+
}
|
|
10
|
+
catch (e) {
|
|
11
|
+
return undefined
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function copy(name, version, vue) {
|
|
16
|
+
vue = vue || 'vue'
|
|
17
|
+
const src = path.join(dir, `v${version}`, name)
|
|
18
|
+
const dest = path.join(dir, name)
|
|
19
|
+
let content = fs.readFileSync(src, 'utf-8')
|
|
20
|
+
content = content.replace(/'vue'/g, `'${vue}'`)
|
|
21
|
+
// unlink for pnpm, #92
|
|
22
|
+
try {
|
|
23
|
+
fs.unlinkSync(dest)
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
}
|
|
27
|
+
fs.writeFileSync(dest, content, 'utf-8')
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function switchVersion(version, vue) {
|
|
31
|
+
copy('index.es.js', version, vue)
|
|
32
|
+
copy('index.cjs.js', version, vue)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
module.exports.loadModule = loadModule
|
|
36
|
+
module.exports.switchVersion = switchVersion
|
package/src/CodeDiff.vue
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed } from 'vue-demi'
|
|
3
|
+
import { createSplitDiff, createUnifiedDiff } from './utils'
|
|
4
|
+
import UnifiedViewer from './unified/UnifiedViewer.vue'
|
|
5
|
+
import SplitViewer from './split/SplitViewer.vue'
|
|
6
|
+
|
|
7
|
+
import './style.scss'
|
|
8
|
+
import 'highlight.js/scss/vs.scss'
|
|
9
|
+
|
|
10
|
+
interface Props {
|
|
11
|
+
newString: string
|
|
12
|
+
oldString: string
|
|
13
|
+
language?: string
|
|
14
|
+
context?: number
|
|
15
|
+
diffStyle?: 'word' | 'char'
|
|
16
|
+
outputFormat?: 'line-by-line' | 'side-by-side'
|
|
17
|
+
trim?: boolean
|
|
18
|
+
noDiffLineFeed?: boolean
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
22
|
+
language: 'plaintext',
|
|
23
|
+
context: 10,
|
|
24
|
+
diffStyle: 'word',
|
|
25
|
+
outputFormat: 'line-by-line',
|
|
26
|
+
trim: false,
|
|
27
|
+
noDiffLineFeed: false,
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
const isUnifiedViewer = computed(() => props.outputFormat === 'line-by-line')
|
|
31
|
+
|
|
32
|
+
const oldString = computed(() => {
|
|
33
|
+
const value = props.trim ? props.oldString.trim() : props.oldString
|
|
34
|
+
return props.noDiffLineFeed ? value.replace(/(\r\n)/g, '\n') : value
|
|
35
|
+
})
|
|
36
|
+
const newString = computed(() => {
|
|
37
|
+
const value = props.trim ? props.newString.trim() : props.newString
|
|
38
|
+
return props.noDiffLineFeed ? value.replace(/(\r\n)/g, '\n') : value
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
const diffChange = computed(() =>
|
|
42
|
+
isUnifiedViewer.value
|
|
43
|
+
? createUnifiedDiff(oldString.value, newString.value, props.language, props.diffStyle, props.context)
|
|
44
|
+
: createSplitDiff(oldString.value, newString.value, props.language, props.diffStyle, props.context),
|
|
45
|
+
)
|
|
46
|
+
</script>
|
|
47
|
+
|
|
48
|
+
<template>
|
|
49
|
+
<div class="code-diff-view">
|
|
50
|
+
<UnifiedViewer v-if="isUnifiedViewer" :diff-change="diffChange" />
|
|
51
|
+
<SplitViewer v-else :diff-change="diffChange" />
|
|
52
|
+
</div>
|
|
53
|
+
</template>
|
|
54
|
+
|
|
55
|
+
<style lang="scss">
|
|
56
|
+
|
|
57
|
+
</style>
|
package/src/highlight.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import hljs from 'highlight.js/lib/core'
|
|
2
|
+
|
|
3
|
+
import xml from 'highlight.js/lib/languages/xml'
|
|
4
|
+
import javascript from 'highlight.js/lib/languages/javascript'
|
|
5
|
+
import json from 'highlight.js/lib/languages/json'
|
|
6
|
+
import yaml from 'highlight.js/lib/languages/yaml'
|
|
7
|
+
import plaintext from 'highlight.js/lib/languages/plaintext'
|
|
8
|
+
import python from 'highlight.js/lib/languages/python'
|
|
9
|
+
import java from 'highlight.js/lib/languages/java'
|
|
10
|
+
import bash from 'highlight.js/lib/languages/bash'
|
|
11
|
+
import sql from 'highlight.js/lib/languages/sql'
|
|
12
|
+
|
|
13
|
+
hljs.registerLanguage('xml', xml)
|
|
14
|
+
hljs.registerLanguage('javascript', javascript)
|
|
15
|
+
hljs.registerLanguage('json', json)
|
|
16
|
+
hljs.registerLanguage('yaml', yaml)
|
|
17
|
+
hljs.registerLanguage('plaintext', plaintext)
|
|
18
|
+
hljs.registerLanguage('python', python)
|
|
19
|
+
hljs.registerLanguage('java', java)
|
|
20
|
+
hljs.registerLanguage('bash', bash)
|
|
21
|
+
hljs.registerLanguage('sql', sql)
|
|
22
|
+
|
|
23
|
+
export default hljs
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { DiffType } from '../types'
|
|
3
|
+
import type { SplitDiffLine } from '../types'
|
|
4
|
+
|
|
5
|
+
const props = defineProps<{
|
|
6
|
+
splitLine: SplitDiffLine
|
|
7
|
+
}>()
|
|
8
|
+
|
|
9
|
+
const getCodeMarker = (type: DiffType) => {
|
|
10
|
+
if (type === DiffType.DELETE)
|
|
11
|
+
return '-'
|
|
12
|
+
if (type === DiffType.ADD)
|
|
13
|
+
return '+'
|
|
14
|
+
return ''
|
|
15
|
+
}
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<template>
|
|
19
|
+
<tr v-if="splitLine.fold">
|
|
20
|
+
<td class="blob-num blob-num-empty empty-cell" colspan="1">
|
|
21
|
+
>
|
|
22
|
+
</td>
|
|
23
|
+
<td class="blob-code blob-code-empty empty-cell" colspan="3" align="left">
|
|
24
|
+
⋯
|
|
25
|
+
</td>
|
|
26
|
+
</tr>
|
|
27
|
+
<tr v-else>
|
|
28
|
+
<template v-for="line in [splitLine.left, splitLine.right]">
|
|
29
|
+
<!-- eslint-disable -->
|
|
30
|
+
<template v-if="line.type === DiffType.EMPTY">
|
|
31
|
+
<td class="blob-num blob-num-empty empty-cell" />
|
|
32
|
+
<td class="blob-code blob-code-empty empty-cell" />
|
|
33
|
+
</template>
|
|
34
|
+
<template v-else>
|
|
35
|
+
<td
|
|
36
|
+
class="blob-num"
|
|
37
|
+
:class="{
|
|
38
|
+
'blob-num-deletion': line.type === DiffType.DELETE,
|
|
39
|
+
'blob-num-addition': line.type === DiffType.ADD,
|
|
40
|
+
'blob-num-context': line.type === DiffType.EQUAL,
|
|
41
|
+
}"
|
|
42
|
+
>
|
|
43
|
+
{{ line.num }}
|
|
44
|
+
</td>
|
|
45
|
+
<td
|
|
46
|
+
class="blob-code"
|
|
47
|
+
:class="{
|
|
48
|
+
'blob-code-deletion': line.type === DiffType.DELETE,
|
|
49
|
+
'blob-code-addition': line.type === DiffType.ADD,
|
|
50
|
+
'blob-code-context': line.type === DiffType.EQUAL,
|
|
51
|
+
}"
|
|
52
|
+
>
|
|
53
|
+
<span
|
|
54
|
+
class="blob-code-inner blob-code-marker"
|
|
55
|
+
:data-code-marker="getCodeMarker(line.type)"
|
|
56
|
+
v-html="line.code"
|
|
57
|
+
/>
|
|
58
|
+
</td>
|
|
59
|
+
</template>
|
|
60
|
+
<!-- eslint-enable -->
|
|
61
|
+
</template>
|
|
62
|
+
</tr>
|
|
63
|
+
</template>
|
|
64
|
+
|
|
65
|
+
<style lang="scss">
|
|
66
|
+
</style>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { SplitViewerChange } from '../types'
|
|
3
|
+
import SplitLine from './SplitLine.vue'
|
|
4
|
+
|
|
5
|
+
const props = defineProps<{
|
|
6
|
+
diffChange: SplitViewerChange
|
|
7
|
+
}>()
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
<template>
|
|
11
|
+
<div class="file">
|
|
12
|
+
<table class="file-diff-split diff-table">
|
|
13
|
+
<colgroup>
|
|
14
|
+
<col width="44">
|
|
15
|
+
<col>
|
|
16
|
+
<col width="44">
|
|
17
|
+
<col>
|
|
18
|
+
</colgroup>
|
|
19
|
+
<tbody>
|
|
20
|
+
<SplitLine v-for="(item, index) in diffChange" :key="index" :split-line="item" />
|
|
21
|
+
</tbody>
|
|
22
|
+
</table>
|
|
23
|
+
</div>
|
|
24
|
+
</template>
|
|
25
|
+
|
|
26
|
+
<style scoped></style>
|
package/src/style.scss
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
@import "./var";
|
|
2
|
+
|
|
3
|
+
.code-diff-view {
|
|
4
|
+
* {
|
|
5
|
+
position: static;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.file {
|
|
9
|
+
position: relative;
|
|
10
|
+
margin-top: 16px;
|
|
11
|
+
margin-bottom: 16px;
|
|
12
|
+
border: 1px solid var(--color-border-default, #ddd);
|
|
13
|
+
border-radius: 2px;
|
|
14
|
+
|
|
15
|
+
table {
|
|
16
|
+
border-spacing: 0;
|
|
17
|
+
}
|
|
18
|
+
.diff-table {
|
|
19
|
+
width: 100%;
|
|
20
|
+
|
|
21
|
+
.blob-num {
|
|
22
|
+
position: relative;
|
|
23
|
+
width: 1%;
|
|
24
|
+
min-width: 50px;
|
|
25
|
+
padding-right: 10px;
|
|
26
|
+
padding-left: 10px;
|
|
27
|
+
font-family: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace;
|
|
28
|
+
font-size: 12px;
|
|
29
|
+
line-height: 20px;
|
|
30
|
+
color: var(--color-fg-subtle);
|
|
31
|
+
text-align: right;
|
|
32
|
+
white-space: nowrap;
|
|
33
|
+
vertical-align: top;
|
|
34
|
+
cursor: pointer;
|
|
35
|
+
-webkit-user-select: none;
|
|
36
|
+
user-select: none;
|
|
37
|
+
}
|
|
38
|
+
.blob-num-deletion {
|
|
39
|
+
color: var(--color-diff-blob-deletion-num-text);
|
|
40
|
+
background-color: var(--color-diff-blob-deletion-num-bg);
|
|
41
|
+
border-color: var(--color-danger-emphasis);
|
|
42
|
+
}
|
|
43
|
+
.blob-num-addition {
|
|
44
|
+
color: var(--color-diff-blob-addition-num-text);
|
|
45
|
+
background-color: var(--color-diff-blob-addition-num-bg);
|
|
46
|
+
border-color: var(--color-success-emphasis);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.blob-code {
|
|
50
|
+
position: relative;
|
|
51
|
+
padding-right: 10px;
|
|
52
|
+
padding-left: 10px;
|
|
53
|
+
line-height: 20px;
|
|
54
|
+
vertical-align: top;
|
|
55
|
+
.blob-code-inner {
|
|
56
|
+
display: table-cell;
|
|
57
|
+
overflow: visible;
|
|
58
|
+
font-family: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace;
|
|
59
|
+
font-size: 12px;
|
|
60
|
+
color: var(--color-fg-default);
|
|
61
|
+
word-wrap: anywhere;
|
|
62
|
+
white-space: pre-wrap;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
.blob-code-deletion {
|
|
66
|
+
background-color: var(--color-diff-blob-deletion-line-bg);
|
|
67
|
+
outline: 1px dashed transparent;
|
|
68
|
+
|
|
69
|
+
.x {
|
|
70
|
+
color: var(--color-diff-blob-deletion-fg);
|
|
71
|
+
background-color: var(--color-diff-blob-deletion-word-bg);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
.blob-code-addition {
|
|
75
|
+
background-color: var(--color-diff-blob-addition-line-bg);
|
|
76
|
+
outline: 1px dotted transparent;
|
|
77
|
+
|
|
78
|
+
.x {
|
|
79
|
+
color: var(--color-diff-blob-addition-fg);
|
|
80
|
+
background-color: var(--color-diff-blob-addition-word-bg);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.blob-code-context,
|
|
85
|
+
.blob-code-addition,
|
|
86
|
+
.blob-code-deletion {
|
|
87
|
+
padding-left: 22px !important;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.blob-code-marker::before {
|
|
91
|
+
position: absolute;
|
|
92
|
+
top: 1px;
|
|
93
|
+
left: 8px;
|
|
94
|
+
padding-right: 8px;
|
|
95
|
+
content: attr(data-code-marker);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.file-diff-split {
|
|
100
|
+
table-layout: fixed;
|
|
101
|
+
|
|
102
|
+
.blob-code + .blob-num {
|
|
103
|
+
border-left: 1px solid var(--color-border-muted);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.empty-cell {
|
|
108
|
+
cursor: default;
|
|
109
|
+
background-color: var(--color-neutral-subtle);
|
|
110
|
+
border-right-color: var(--color-border-muted);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export const enum DiffType {
|
|
2
|
+
EQUAL = 'equal',
|
|
3
|
+
DELETE = 'removed',
|
|
4
|
+
ADD = 'added',
|
|
5
|
+
EMPTY = 'empty',
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface DiffLine {
|
|
9
|
+
type: DiffType
|
|
10
|
+
code?: string
|
|
11
|
+
num?: number
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface SplitDiffLine {
|
|
15
|
+
fold?: boolean
|
|
16
|
+
left: DiffLine
|
|
17
|
+
right: DiffLine
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface UnifiedLine {
|
|
21
|
+
fold?: boolean
|
|
22
|
+
type: DiffType
|
|
23
|
+
code: string
|
|
24
|
+
delNum?: number
|
|
25
|
+
addNum?: number
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export type SplitViewerChange = SplitDiffLine[]
|
|
29
|
+
export type UnifiedViewerChange = UnifiedLine[]
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import type { UnifiedLine } from '../types'
|
|
3
|
+
import { DiffType } from '../types'
|
|
4
|
+
|
|
5
|
+
const props = defineProps<{
|
|
6
|
+
line: UnifiedLine
|
|
7
|
+
}>()
|
|
8
|
+
|
|
9
|
+
const getCodeMarker = (type: DiffType) => {
|
|
10
|
+
if (type === DiffType.DELETE)
|
|
11
|
+
return '-'
|
|
12
|
+
if (type === DiffType.ADD)
|
|
13
|
+
return '+'
|
|
14
|
+
return ''
|
|
15
|
+
}
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<template>
|
|
19
|
+
<tr v-if="line.fold">
|
|
20
|
+
<td class="blob-num blob-num-empty empty-cell">
|
|
21
|
+
>
|
|
22
|
+
</td>
|
|
23
|
+
<td class="blob-num blob-num-empty empty-cell">
|
|
24
|
+
>
|
|
25
|
+
</td>
|
|
26
|
+
<td class="blob-code blob-code-empty empty-cell" align="left">
|
|
27
|
+
⋯
|
|
28
|
+
</td>
|
|
29
|
+
</tr>
|
|
30
|
+
<tr v-else>
|
|
31
|
+
<td
|
|
32
|
+
class="blob-num"
|
|
33
|
+
:class="{
|
|
34
|
+
'blob-num-deletion': line.type === DiffType.DELETE,
|
|
35
|
+
'blob-num-addition': line.type === DiffType.ADD,
|
|
36
|
+
'blob-num-context': line.type === DiffType.EQUAL,
|
|
37
|
+
}"
|
|
38
|
+
>
|
|
39
|
+
{{ line.delNum }}
|
|
40
|
+
</td>
|
|
41
|
+
<td
|
|
42
|
+
class="blob-num"
|
|
43
|
+
:class="{
|
|
44
|
+
'blob-num-deletion': line.type === DiffType.DELETE,
|
|
45
|
+
'blob-num-addition': line.type === DiffType.ADD,
|
|
46
|
+
'blob-num-context': line.type === DiffType.EQUAL,
|
|
47
|
+
}"
|
|
48
|
+
>
|
|
49
|
+
{{ line.addNum }}
|
|
50
|
+
</td>
|
|
51
|
+
<td
|
|
52
|
+
class="blob-code"
|
|
53
|
+
:class="{
|
|
54
|
+
'blob-code-deletion': line.type === DiffType.DELETE,
|
|
55
|
+
'blob-code-addition': line.type === DiffType.ADD,
|
|
56
|
+
'blob-code-context': line.type === DiffType.EQUAL,
|
|
57
|
+
}"
|
|
58
|
+
>
|
|
59
|
+
<span class="blob-code-inner blob-code-marker" :data-code-marker="getCodeMarker(line.type)" v-html="line.code" />
|
|
60
|
+
</td>
|
|
61
|
+
</tr>
|
|
62
|
+
</template>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { UnifiedViewerChange } from '../types'
|
|
3
|
+
import UnifiedLine from './UnifiedLine.vue'
|
|
4
|
+
|
|
5
|
+
const props = defineProps<{
|
|
6
|
+
diffChange: UnifiedViewerChange
|
|
7
|
+
}>()
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
<template>
|
|
11
|
+
<div class="file">
|
|
12
|
+
<table class="diff-table">
|
|
13
|
+
<tbody>
|
|
14
|
+
<UnifiedLine v-for="(item, index) in diffChange" :key="index" :line="item" />
|
|
15
|
+
</tbody>
|
|
16
|
+
</table>
|
|
17
|
+
</div>
|
|
18
|
+
</template>
|
|
19
|
+
|
|
20
|
+
<style scoped></style>
|