regexptester/src/components/RegExp.vue

196 lines
5.4 KiB
Vue

<template>
<div class="regexp-tester">
<h1>正则表达式测试器</h1>
<el-input v-model="regex" placeholder="请输入正则表达式" clearable class="regex-input" />
<el-input v-model="testString" placeholder="请输入测试字符串" clearable class="test-input" />
<el-button type="primary" @click="testRegex" class="test-button">测试</el-button>
<el-button type="default" @click="saveRegex" class="test-button" :disabled="shouldDisableSaveButton">保存</el-button>
<!-- 添加匹配示意图 -->
<div class="match-diagram">
<h2>匹配示意图</h2>
<div class="diagram-content" ref="myDiagram">
<!-- <pre v-html="generateMatchDiagram()"></pre> -->
</div>
</div>
<div class="results">
<h2>匹配结果</h2>
<div v-if="results.length === 0" class="result-item">
<p>未找到匹配项</p>
</div>
<div v-for="(result, index) in results" :key="index" class="result-item">
<p>匹配内容: {{ result.match }}</p>
<p>匹配位置: {{ result.index }}</p>
<div v-if="result.groups && result.groups.length > 0">
<p>捕获组:</p>
<ul>
<li v-for="(group, groupIndex) in result.groups" :key="groupIndex">
组 {{ groupIndex + 1 }}: {{ group }}
</li>
</ul>
</div>
</div>
</div>
</div>
<el-dialog v-model="dialogVisible" :modal="false">
<el-input placeholder="保存为" v-model="regxname" />
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="saveRegex">保存</el-button>
</el-dialog>
</template>
<script setup lang="ts">
import { ref, onMounted,computed } from 'vue'
import { ElInput, ElButton } from 'element-plus'
// 在你的组件文件中
let vscode: any = null
// 现在你可以在这个文件中使用 window.vizregx 而不会得到 TypeScript 的错误
const regex = ref('')
const testString = ref('')
const dialogVisible = ref(false)
const regxname = ref('')
const results = ref<{ match: string; index: number; groups: string[] }[]>([])
const myDiagram = ref<HTMLElement | null>(null)
const testRegex = () => {
try {
// 确保正则表达式带有全局标志 'g'
const regexPattern = new RegExp(regex.value, 'g')
const matches = testString.value.matchAll(regexPattern)
results.value = Array.from(matches, (match) => ({
match: match[0],
index: match.index || 0,
groups: match.slice(1), // 捕获组结果
}))
if (myDiagram.value && typeof window.vizregx !== 'undefined') {
//先删除之前的匹配示意图
myDiagram.value.innerHTML = ''
window.vizregx(myDiagram.value, regex.value)
}
} catch (error) {
console.error('Invalid regex:', error)
results.value = []
}
}
const isInVscode = () => {
return typeof window.acquireVsCodeApi !== 'undefined'
}
const shouldDisableSaveButton = computed(() => {
return !regex.value || !testString.value
})
const saveRegex = () => {
// show a dialog to ask for a name
if (!dialogVisible.value) {
dialogVisible.value = true
} else {
dialogVisible.value = false
if (isInVscode()) {
if(!vscode) vscode = window.acquireVsCodeApi()
vscode.postMessage({ command: 'regex.save', name:regxname.value, regexp: regex.value, teststr: testString.value })
}
}
}
onMounted(() => {
// 此时 myDiagram.value 应该已经被设置为对应的 DOM
if (isInVscode()) {
window.addEventListener('message', (event) => {
const message = event.data
if (message.command === 'regex.show') {
regex.value = message.regexp
testString.value = message.teststr
testRegex()
}
})
}
})
// // 生成匹配示意图
// const generateMatchDiagram = () => {
// let diagram = testString.value
// results.value.forEach((result) => {
// const start = result.index
// const end = start + result.match.length
// diagram =
// diagram.slice(0, start) +
// `<span class="highlight">${diagram.slice(start, end)}</span>` +
// diagram.slice(end)
// })
// return diagram
// }
</script>
<style scoped>
.regexp-tester {
padding: 20px;
max-width: 600px;
margin: 0 auto;
/* background-color: #1e1e1e; /* 暗色背景 */
border-radius: 8px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
h1,
h2 {
text-align: center;
/* color: #ffffff; /* 白色文字 */
}
.regex-input,
.test-input {
margin-bottom: 15px;
}
.test-button {
width: 100%;
margin-bottom: 15px;
margin-left: 0px;
}
.results {
margin-top: 20px;
padding: 15px;
/* background-color: #2d2d2d; /* 暗色背景 */
border-radius: 8px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
.result-item {
/* border: 1px solid #444444; /* 暗色边框 */
padding: 10px;
margin-bottom: 10px;
border-radius: 4px;
/* background-color: #333333; /* 暗色背景 */
}
.result-item p {
margin: 5px 0;
/*color: #cccccc; /* 浅灰色文字 */
}
/* 匹配示意图样式 */
.match-diagram {
margin-top: 20px;
padding: 15px;
/*background-color: #2d2d2d; /* 暗色背景 */
border-radius: 8px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
.diagram-content {
padding: 10px;
/*background-color: #333333; /* 暗色背景 */
/* border: 1px solid #444444; /* 暗色边框 */
border-radius: 4px;
}
.diagram-content pre {
margin: 0;
/* color: #cccccc; /* 浅灰色文字 */
}
.highlight {
/* background-color: #ffeb3b; /* 高亮颜色 */
padding: 2px 4px;
border-radius: 3px;
}
</style>