增加 xml <=> 编解码工具

This commit is contained in:
2026-03-27 08:44:50 +08:00
parent 1bf08a3698
commit c714f554ac
6 changed files with 150 additions and 73 deletions

View File

@@ -11,11 +11,11 @@ export {}
/* prettier-ignore */ /* prettier-ignore */
declare module 'vue' { declare module 'vue' {
export interface GlobalComponents { export interface GlobalComponents {
CoderBaseCard: typeof import('./src/components/CoderBaseCard.vue')['default']
CoderJson: typeof import('./src/components/CoderJson.vue')['default'] CoderJson: typeof import('./src/components/CoderJson.vue')['default']
CoderXml: typeof import('./src/components/CoderXml.vue')['default']
DetectedIDECard: typeof import('./src/components/DetectedIDECard.vue')['default'] DetectedIDECard: typeof import('./src/components/DetectedIDECard.vue')['default']
DetectedIDECardList: typeof import('./src/components/DetectedIDECardList.vue')['default'] DetectedIDECardList: typeof import('./src/components/DetectedIDECardList.vue')['default']
DetectedIDEVersionCard: typeof import('./src/components/DetectedIDEVersionCard.vue')['default']
DetectedIDEVersionCardList: typeof import('./src/components/DetectedIDEVersionCardList.vue')['default']
NAlert: typeof import('naive-ui')['NAlert'] NAlert: typeof import('naive-ui')['NAlert']
NButton: typeof import('naive-ui')['NButton'] NButton: typeof import('naive-ui')['NButton']
NCard: typeof import('naive-ui')['NCard'] NCard: typeof import('naive-ui')['NCard']

View File

@@ -3,9 +3,11 @@ import { darkTheme, dateZhCN, zhCN } from 'naive-ui'
import hljs from 'highlight.js' import hljs from 'highlight.js'
import javascript from 'highlight.js/lib/languages/javascript' import javascript from 'highlight.js/lib/languages/javascript'
import json from 'highlight.js/lib/languages/json' import json from 'highlight.js/lib/languages/json'
import xml from 'highlight.js/lib/languages/xml'
hljs.registerLanguage('javascript', javascript) hljs.registerLanguage('javascript', javascript)
hljs.registerLanguage('json', json) hljs.registerLanguage('json', json)
hljs.registerLanguage('xml', xml)
</script> </script>
<template> <template>

View File

@@ -0,0 +1,104 @@
<script lang="ts" setup>
import { computed, onMounted, ref } from 'vue'
import { useMessage } from 'naive-ui'
const message = useMessage()
const props = defineProps<{
cardTitle: string
defaultInput: string
// 人类友好格式的代码语言
codeLanguage1: 'json' | 'xml'
// 机器友好格式的代码语言
codeLanguage2: 'json' | 'xml'
// 转为人类友好格式
parser1: (input: string) => string
// 转为机器友好格式
parser2: (input: string) => string
// 转为人类友好格式别名
buttonText1?: string
// 转为机器友好格式别名
buttonText2?: string
}>()
const codingHumanFriendly = ref(true)
const inputValue = ref(props.defaultInput)
const displayValue = ref('')
const errorTip = ref('')
function generate(humanFriendly: boolean, showSuccessMessage: boolean = true): void {
try {
displayValue.value = humanFriendly
? props.parser1(inputValue.value)
: props.parser2(inputValue.value)
errorTip.value = ''
// 页面挂载时不显示成功提示
if (showSuccessMessage) {
message.success('没抱错,所以应该成功辽~')
}
} catch (error) {
if (error instanceof SyntaxError) {
message.error(error.name)
displayValue.value = ''
errorTip.value = error.name + ': ' + error.message
} else {
// TODO 还有什么可能的错误?
throw error
}
}
}
const codeLanguage = computed(() =>
codingHumanFriendly.value ? props.codeLanguage1 : props.codeLanguage2
)
onMounted(() => {
generate(true, false)
})
</script>
<template>
<n-card class="default-card" :title="cardTitle">
<template #header-extra>
<n-flex align="center" justify="center">
<n-switch v-model:value="codingHumanFriendly" size="large">
<template #checked> {{ buttonText1 ? buttonText1 : '转换为人类友好格式' }} </template>
<template #unchecked> {{ buttonText2 ? buttonText2 : '转换为机器友好格式' }} </template>
</n-switch>
<n-button secondary type="primary" @click="() => generate(codingHumanFriendly)"
>生成</n-button
>
<n-button
secondary
type="warning"
@click="
() => {
inputValue = defaultInput
codingHumanFriendly = true
generate(true)
}
"
>重置</n-button
>
<n-button secondary type="info">复制结果</n-button>
</n-flex>
</template>
<template #default>
<n-flex vertical>
<n-input v-model:value="inputValue" spellcheck="false" type="textarea" />
<div class="scrollarea code-area">
<n-code :code="displayValue" :language="codeLanguage" />
</div>
<n-alert v-if="errorTip !== ''" type="error">
{{ errorTip }}
</n-alert>
</n-flex>
</template>
</n-card>
</template>
<style scoped>
div.code-area {
max-height: 600px;
}
</style>

View File

@@ -1,77 +1,16 @@
<script lang="ts" setup> <script lang="ts" setup>
import { onMounted, ref } from 'vue' import CoderBaseCard from '@renderer/components/CoderBaseCard.vue'
import { useMessage } from 'naive-ui'
const message = useMessage()
const defaultInput =
'{"name":"Code Space","author":1,"url":"https://code.mangofanfan.cn","users":[{"name":"MangoFanFanw","age":18,"male":true}]}'
const codingHumanFriendly = ref(true)
const inputValue = ref(defaultInput)
const displayValue = ref('')
const errorTip = ref('')
function generate(humanFriendly: boolean): void {
try {
displayValue.value = JSON.stringify(JSON.parse(inputValue.value), null, humanFriendly ? 4 : 0)
errorTip.value = ''
} catch (error) {
if (error instanceof SyntaxError) {
message.error('JSON 解析错误,请复制完整并检查是否合法。')
displayValue.value = ''
errorTip.value = error.message
}
}
}
onMounted(() => {
generate(true)
})
</script> </script>
<template> <template>
<n-card class="default-card" title="json 格式化/压缩"> <CoderBaseCard
<template #header-extra> card-title="json 格式化/压缩"
<n-flex align="center" justify="center"> default-input='{"name":"Code Space","author":1,"url":"https://code.mangofanfan.cn","users":[{"name":"MangoFanFanw","age":18,"male":true}]}'
<n-switch v-model:value="codingHumanFriendly" size="large"> code-language1="json"
<template #checked> 转换为人类友好格式 </template> code-language2="json"
<template #unchecked> 转换为机器友好格式 </template> :parser1="(code: string) => JSON.stringify(JSON.parse(code), null, 4)"
</n-switch> :parser2="(code: string) => JSON.stringify(JSON.parse(code), null, 0)"
<n-button secondary type="primary" @click="() => generate(codingHumanFriendly)" />
>生成</n-button
>
<n-button
secondary
type="warning"
@click="
() => {
inputValue = defaultInput
codingHumanFriendly = true
generate(true)
}
"
>重置</n-button
>
<n-button secondary type="info">复制结果</n-button>
</n-flex>
</template>
<template #default>
<n-flex vertical>
<n-input v-model:value="inputValue" spellcheck="false" type="textarea" />
<div class="scrollarea code-area">
<n-code :code="displayValue" language="json" />
</div>
<n-alert v-if="errorTip !== ''" type="error">
{{ errorTip }}
</n-alert>
</n-flex>
</template>
</n-card>
</template> </template>
<style scoped> <style scoped></style>
div.code-area {
max-height: 600px;
}
</style>

View File

@@ -0,0 +1,30 @@
<script setup lang="ts">
import CoderBaseCard from '@renderer/components/CoderBaseCard.vue'
import { XMLBuilder, XMLParser } from 'fast-xml-parser'
const xmlParser = new XMLParser({ ignoreAttributes: false })
const xmlBuilder = new XMLBuilder({ format: true, indentBy: ' ', ignoreAttributes: false })
function parser1(code: string): string {
return JSON.stringify(xmlParser.parse(code), null, 4)
}
function parser2(code: string): string {
return xmlBuilder.build(JSON.parse(code))
}
</script>
<template>
<CoderBaseCard
card-title="xml <=> json"
default-input='<?xml version="1.0" encoding="UTF-8"?><bookstore><book category="cooking"><title lang="en">Everyday Italian</title><author>Giada De Laurentiis</author><year>2005</year><price>30.00</price></book><book category="children"><title lang="en">Harry Potter</title><author>J K. Rowling</author><year>2005</year><price>29.99</price></book></bookstore>'
code-language1="json"
code-language2="xml"
:parser1
:parser2
button-text1="xml => json"
button-text2="json => xml"
/>
</template>
<style scoped></style>

View File

@@ -1,5 +1,6 @@
<script lang="ts" setup> <script lang="ts" setup>
import CoderJson from '@renderer/components/CoderJson.vue' import CoderJson from '@renderer/components/CoderJson.vue'
import CoderXml from '@renderer/components/CoderXml.vue'
</script> </script>
<template> <template>
@@ -10,6 +11,7 @@ import CoderJson from '@renderer/components/CoderJson.vue'
</n-alert> </n-alert>
<CoderJson /> <CoderJson />
<CoderXml />
</template> </template>
<style scoped></style> <style scoped></style>