text-compare-vue3
Version:
A powerful text comparison plugin for Vue.js with character-level diff support
86 lines (76 loc) • 2.46 kB
text/typescript
import { computed, ref, Ref } from 'vue'
import { getDiffParts } from '../utils/diff'
import type { DiffPart } from '../types'
export interface TextComparisonOptions {
customColors?: {
commonColor?: string
removedColor?: string
addedColor?: string
}
}
export interface DiffStyles {
common: { color: string }
removed: { backgroundColor: string; color: string }
added: { backgroundColor: string; color: string }
}
export function useTextComparison(
initialText1: string | Ref<string>,
initialText2: string | Ref<string>,
options: TextComparisonOptions = {}
) {
// 确保文本是响应式的
const oldText = ref(initialText1 instanceof Object ? initialText1.value : initialText1)
const newText = ref(initialText2 instanceof Object ? initialText2.value : initialText2)
// 计算差异
const diffResult = computed(() => {
try {
return getDiffParts(oldText.value || '', newText.value || '', true)
} catch (error) {
console.error('Error computing diff:', error)
return {
oldParts: [{ value: oldText.value || '', removed: false }],
newParts: [{ value: newText.value || '', added: false }]
}
}
})
// 计算相似度
const similarity = computed(() => {
try {
const total = (oldText.value || '').length + (newText.value || '').length
if (total === 0) return 100
if (oldText.value.length === 0 || newText.value.length === 0) return 0
const commonParts = diffResult.value.oldParts.filter((part: DiffPart) => !part.removed)
const commonLength = commonParts.reduce((sum: number, part: DiffPart) => sum + part.value.length, 0) * 2
return (commonLength / total) * 100
} catch (error) {
console.error('Error computing similarity:', error)
return 0
}
})
// 生成样式
const styles = computed<DiffStyles>(() => {
const { customColors = {} } = options
return {
common: { color: customColors.commonColor || 'inherit' },
removed: {
backgroundColor: '#ffeef0',
color: customColors.removedColor || '#f56c6c'
},
added: {
backgroundColor: '#e6ffed',
color: customColors.addedColor || '#28a745'
}
}
})
// 更新文本
const updateTexts = (newText1: string, newText2: string) => {
oldText.value = newText1 || ''
newText.value = newText2 || ''
}
return {
diffResult,
similarity,
styles,
updateTexts
}
}