Skip to content
This repository was archived by the owner on Feb 10, 2025. It is now read-only.

Commit 4493899

Browse files
committed
chore: development
1 parent c1c3f59 commit 4493899

File tree

13 files changed

+251
-118
lines changed

13 files changed

+251
-118
lines changed

.eslintrc.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@ module.exports = {
1919
overrides: [
2020
{
2121
files: [
22-
'**/__tests__/*.{j,t}s?(x)',
23-
'**/tests/unit/**/*.spec.{j,t}s?(x)'
22+
'**/__tests__/*.{j,t}s?(x)'
2423
],
2524
env: {
2625
jest: true

__tests__/index.spec.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { mount } from '@vue/test-utils'
2+
import VueDiff from '../src/index'
3+
4+
describe('Plugin and component', () => {
5+
it('Install plugin', () => {
6+
const wrapper = mount({
7+
template: `
8+
<Diff />
9+
`
10+
}, {
11+
global: {
12+
plugins: [
13+
[VueDiff]
14+
]
15+
}
16+
})
17+
expect(wrapper.find('.vue-diff-wrapper')).toBeTruthy()
18+
expect(wrapper.find('.vue-diff-mode-split')).toBeTruthy()
19+
expect(wrapper.find('.vue-diff-theme-dark')).toBeTruthy()
20+
})
21+
22+
it('Set plugin options', () => {
23+
const wrapper = mount({
24+
template: `
25+
<VueDiff />
26+
`
27+
}, {
28+
global: {
29+
plugins: [
30+
[VueDiff, {
31+
componentName: 'VueDiff'
32+
}]
33+
]
34+
}
35+
})
36+
expect(wrapper.find('.vue-diff-wrapper')).toBeTruthy()
37+
expect(wrapper.find('.vue-diff-mode-split')).toBeTruthy()
38+
expect(wrapper.find('.vue-diff-theme-dark')).toBeTruthy()
39+
})
40+
41+
it('Set component property', () => {
42+
const wrapper = mount({
43+
template: `
44+
<Diff
45+
mode="unified"
46+
theme="light"
47+
/>
48+
`
49+
}, {
50+
global: {
51+
plugins: [
52+
[VueDiff]
53+
]
54+
}
55+
})
56+
expect(wrapper.find('.vue-diff-wrapper')).toBeTruthy()
57+
expect(wrapper.find('.vue-diff-mode-unified')).toBeTruthy()
58+
expect(wrapper.find('.vue-diff-theme-light')).toBeTruthy()
59+
})
60+
})

__tests__/utils.spec.ts

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import { ref } from 'Vue'
2+
import { MODIFIED_START_TAG, MODIFIED_CLOSE_TAG, getDiffType, getSplitLines, getUnifiedLines, renderLines, renderWords, setHighlightCode } from '../src/utils'
3+
4+
describe('Utils unit', () => {
5+
const added = {
6+
count: 1,
7+
added: true,
8+
removed: undefined,
9+
value: ''
10+
}
11+
12+
const removed = {
13+
count: 1,
14+
added: undefined,
15+
removed: true,
16+
value: ''
17+
}
18+
19+
const equal = {
20+
count: 1,
21+
added: undefined,
22+
removed: undefined,
23+
value: ''
24+
}
25+
26+
const disabled = {
27+
value: ''
28+
}
29+
30+
const prev = 'a\nb'
31+
const curr = 'c'
32+
33+
const diffsMap = [
34+
[
35+
{
36+
count: 2,
37+
added: undefined,
38+
removed: true,
39+
value: prev
40+
},
41+
{
42+
count: 1,
43+
added: true,
44+
removed: undefined,
45+
value: curr
46+
}
47+
]
48+
]
49+
50+
it('getDiffType', () => {
51+
expect(getDiffType(added)).toBe('added')
52+
expect(getDiffType(removed)).toBe('removed')
53+
expect(getDiffType(equal)).toBe('equal')
54+
expect(getDiffType(disabled)).toBe('disabled')
55+
})
56+
57+
it('getSplitLines', () => {
58+
const result = getSplitLines(diffsMap)
59+
expect(result.length).toBe(2)
60+
expect(result[0][0].type).toBe('removed')
61+
expect(result[0][0].lineNum).toBe(1)
62+
expect(result[0][0].value).toBe('a')
63+
expect(result[0][0].chkWords).toBe(false)
64+
})
65+
66+
it('getUnifiedLines', () => {
67+
const result = getUnifiedLines(diffsMap)
68+
expect(result.length).toBe(3)
69+
expect(result[0][0].type).toBe('removed')
70+
expect(result[0][0].lineNum).toBe(undefined)
71+
expect(result[0][0].value).toBe('a')
72+
expect(result[1][0].type).toBe('removed')
73+
expect(result[1][0].lineNum).toBe(undefined)
74+
expect(result[1][0].value).toBe('b')
75+
expect(result[2][0].type).toBe('added')
76+
expect(result[2][0].lineNum).toBe(1)
77+
expect(result[2][0].value).toBe('c')
78+
})
79+
80+
it('getUnifiedLines', () => {
81+
const split = renderLines('split', prev, curr)
82+
const unified = renderLines('unified', prev, curr)
83+
expect(split.length).toBe(2)
84+
expect(unified.length).toBe(3)
85+
})
86+
87+
it('renderWords', () => {
88+
expect(renderWords('abc', 'abc')).toBe('abc')
89+
expect(renderWords('abc', 'acc')).toBe(`${MODIFIED_START_TAG}acc${MODIFIED_CLOSE_TAG}`)
90+
expect(renderWords('a b c', 'a c c')).toBe(`a ${MODIFIED_START_TAG}c${MODIFIED_CLOSE_TAG} c`)
91+
})
92+
93+
it('setHighlightCode', () => {
94+
const highlightCode = ref('')
95+
96+
setHighlightCode({
97+
highlightCode,
98+
language: 'plaintext',
99+
code: `a ${MODIFIED_START_TAG}c${MODIFIED_CLOSE_TAG} c`
100+
})
101+
102+
expect(highlightCode.value).toBe('a <span class="modified">c</span> c')
103+
})
104+
})

dev/App.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ import template from './template'
4848
export default defineComponent({
4949
setup () {
5050
const modes = ref(['split', 'unified'])
51-
const mode = ref('split')
51+
const mode = ref('unified')
5252
const languages = ref(['javascript', 'html', 'css'])
5353
const language = ref('javascript')
5454
const themes = ref(['dark', 'light'])

index.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@
88
</head>
99
<body class="bg-gray-900">
1010
<div class="p-12">
11-
<h1 class="text-3xl font-extrabold text-gray-100 flex items-center">
12-
<span class="mr-4">Vue Diff</span>
11+
<h1 class="text-3xl font-extrabold text-gray-100">
12+
Vue Diff
1313
<!-- Place this tag where you want the button to render. -->
14-
<span class="mt-2">
14+
<span style="display: inline-block; line-height: 0; margin: -4px 0 0 10px; vertical-align: middle; font-size: 0;">
1515
<a class="github-button" href="https://github.com/hoiheart/vue-diff" data-color-scheme="no-preference: dark; light: dark; dark: dark;" data-size="large" data-show-count="true" aria-label="Star hoiheart/vue-diff on GitHub">Star</a>
1616
</span>
1717
</h1>

package-lock.json

Lines changed: 0 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
"scripts": {
1212
"dev": "vite",
1313
"build": "vite build",
14-
"test:unit": "vue-cli-service test:unit",
15-
"test:e2e": "vue-cli-service test:e2e",
14+
"test": "vue-cli-service test:unit",
15+
"test:watch": "vue-cli-service test:unit --watch",
1616
"lint": "vue-cli-service lint"
1717
},
1818
"dependencies": {
@@ -48,7 +48,6 @@
4848
"sass-loader": "^8.0.2",
4949
"typescript": "~3.9.3",
5050
"vite": "^1.0.0-rc.13",
51-
"vue-github-button": "^1.3.0",
5251
"vue-jest": "^5.0.0-0"
5352
},
5453
"_id": "vue-diff@0.0.0",

src/Code.vue

Lines changed: 1 addition & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -3,83 +3,8 @@
33
</template>
44

55
<script lang="ts">
6-
import { highlight } from 'highlight.js'
76
import { defineComponent, ref, onMounted, watch } from 'vue'
8-
import { MODIFIED_START_TAG, MODIFIED_CLOSE_TAG } from './utils'
9-
10-
import type { Ref } from 'vue'
11-
12-
/**
13-
* Set hightlight code
14-
* This function must calling at client only (use DOM)
15-
*/
16-
const setHighlightCode = ({ highlightCode, language, code }: { highlightCode: Ref; language: string; code: string }) => {
17-
const hasModifiedTags = code.match(new RegExp(`(${MODIFIED_START_TAG}|${MODIFIED_CLOSE_TAG})`, 'g'))
18-
19-
if (!hasModifiedTags) {
20-
highlightCode.value = highlight(language, code).value
21-
return
22-
}
23-
24-
/**
25-
* Explore highlight DOM extracted from pure code and compare the text with the original code code to generate the highlight code
26-
*/
27-
let originalCode = code // original code with modified tags
28-
const pureCode = code.replace(new RegExp(`(${MODIFIED_START_TAG}|${MODIFIED_CLOSE_TAG})`, 'g'), '') // Without modified tags
29-
let pureElement = document.createElement('div')
30-
pureElement.innerHTML = highlight(language, pureCode).value // Highlight DOM without modified tags
31-
32-
const diffElements = (node: HTMLElement) => {
33-
node.childNodes.forEach(child => {
34-
if (child.nodeType === 1) {
35-
diffElements(child as HTMLElement)
36-
}
37-
38-
// Compare text nodes and check changed text
39-
if (child.nodeType === 3) {
40-
if (!child.textContent) return
41-
42-
let oldContent = child.textContent
43-
let newContent = ''
44-
45-
while (oldContent.length) {
46-
if (originalCode.startsWith(MODIFIED_START_TAG)) { // Add modified start tag
47-
originalCode = originalCode.slice(MODIFIED_START_TAG.length)
48-
newContent = newContent + MODIFIED_START_TAG
49-
continue
50-
}
51-
if (originalCode.startsWith(MODIFIED_CLOSE_TAG)) { // Add modified close tag
52-
originalCode = originalCode.slice(MODIFIED_CLOSE_TAG.length)
53-
newContent = newContent + MODIFIED_CLOSE_TAG
54-
continue
55-
}
56-
57-
// Add words before modified tag
58-
const hasModifiedTag = originalCode.match(new RegExp(`(${MODIFIED_START_TAG}|${MODIFIED_CLOSE_TAG})`))
59-
const originalCodeDiffLength = hasModifiedTag && hasModifiedTag.index ? hasModifiedTag.index : originalCode.length
60-
const nextDiffsLength = Math.min(originalCodeDiffLength, oldContent.length)
61-
62-
newContent = newContent + originalCode.substring(0, nextDiffsLength)
63-
originalCode = originalCode.slice(nextDiffsLength)
64-
oldContent = oldContent.slice(nextDiffsLength)
65-
}
66-
67-
child.textContent = newContent // put as entity code because change textContent
68-
}
69-
})
70-
}
71-
diffElements(pureElement)
72-
73-
const startEntity = MODIFIED_START_TAG.replace('<', '&lt;').replace('>', '&gt;')
74-
const closeEntity = MODIFIED_CLOSE_TAG.replace('<', '&lt;').replace('>', '&gt;')
75-
76-
highlightCode.value = pureElement.innerHTML
77-
.replace(new RegExp(startEntity, 'g'), '<span class="modified">')
78-
.replace(new RegExp(closeEntity, 'g'), '</span>')
79-
80-
// @ts-ignore
81-
pureElement = null
82-
}
7+
import { setHighlightCode } from './utils'
838
849
export default defineComponent({
8510
props: {

src/Diff.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,15 @@ export default defineComponent({
3030
props: {
3131
mode: {
3232
type: String as PropType<Mode>,
33-
required: true
33+
default: 'split'
3434
},
3535
theme: {
3636
type: String as PropType<Theme>,
3737
default: 'dark'
3838
},
3939
language: {
4040
type: String,
41-
default: ''
41+
default: 'plaintext'
4242
},
4343
prev: {
4444
type: String,

src/Line.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
<td class="code" :class="`vue-diff-cell-${data[0].type}`">
2424
<Code
2525
:language="language"
26-
:code="setCode(line)"
26+
:code="setCode(data[0])"
2727
/>
2828
</td>
2929
</tr>

0 commit comments

Comments
 (0)