Skip to content

Commit

Permalink
feat(xmlFormatter): 添加xml格式化
Browse files Browse the repository at this point in the history
  • Loading branch information
ZvonimirSun committed Dec 17, 2023
1 parent ee7cfe2 commit 5665f60
Show file tree
Hide file tree
Showing 7 changed files with 271 additions and 6 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@
"vanilla-jsoneditor": "^0.18.13",
"vue": "^3.3.8",
"vue-router": "^4.2.5",
"vue3-ace-editor": "^2.2.4"
"vue3-ace-editor": "^2.2.4",
"xml-formatter": "^3.6.0"
},
"devDependencies": {
"@algolia/client-search": "^4.20.0",
Expand Down
15 changes: 15 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ declare module 'vue' {
ElTree: typeof import('element-plus/es')['ElTree']
ElUpload: typeof import('element-plus/es')['ElUpload']
FixedWidgets: typeof import('./components/fixed-widgets.vue')['default']
FormatTransformer: typeof import('./components/FormatTransformer.vue')['default']
Hue: typeof import('./components/color-picker/hue.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
Expand Down
101 changes: 101 additions & 0 deletions src/components/FormatTransformer.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<script setup lang="ts">
import { identity } from 'lodash-es'
import type { FormInstance, FormItemRule, FormRules } from 'element-plus'
const props = withDefaults(
defineProps<{
transformer?:(v: string) => string
inputValidationRules?: FormItemRule[]
inputLabel?: string
inputPlaceholder?: string
inputDefault?: string
outputLabel?: string
}>(),
{
transformer: identity,
inputValidationRules: () => [],
inputLabel: '输入',
inputDefault: '',
inputPlaceholder: '输入...',
outputLabel: '输出'
}
)
const { transformer, inputValidationRules, inputLabel, outputLabel, inputPlaceholder, inputDefault } = toRefs(props)
const emits = defineEmits<{(e: 'format', data: string): void}>()
const ruleFormRef = ref<FormInstance>()
const form = reactive({
input: inputDefault.value
})
watch(inputDefault, (val) => {
form.input = val
})
const output = computed(() => transformer.value(form.input))
const rules = reactive<FormRules<typeof form>>({
input: inputValidationRules.value
})
onMounted(() => {
emits('format', output.value)
})
watch(output, () => {
emits('format', output.value)
})
</script>

<template>
<div class="formatter-container">
<el-form
ref="ruleFormRef"
:model="form"
label-position="top"
:rules="rules"
>
<el-form-item
:label="inputLabel"
prop="input"
>
<el-input
v-model="form.input"
:placeholder="inputPlaceholder"
:rows="20"
type="textarea"
/>
</el-form-item>
<el-form-item
:label="outputLabel"
>
<el-input
:model-value="output"
:rows="20"
type="textarea"
readonly
/>
</el-form-item>
</el-form>
</div>
</template>

<style scoped lang="scss">
.formatter-container {
display: flex;
gap: .8rem;
.el-form {
width: 100%;
display: flex;
gap: .8rem;
.el-form-item {
width: 50%;
}
}
}
</style>
8 changes: 4 additions & 4 deletions src/tools.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,6 @@
"name": "CSS编辑器",
"link": "/cssFormatter"
},
{
"name": "XML编辑器",
"link": "/xmlEditor"
},
{
"name": "TinyEditor",
"link": "/tinyEditor"
Expand All @@ -72,6 +68,10 @@
"type": "开发工具",
"icon": "i-icon-park-outline-code",
"children": [
{
"name": "XML格式化",
"link": "/xmlEditor"
},
{
"name": "Mock工具",
"link": "/mock",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
</div>
<div class="ace-container">
<v-ace-editor
v-model="code"
v-model:value="code"
lang="xml"
:theme="theme"
style="height: 100%;"
Expand Down Expand Up @@ -106,6 +106,15 @@ import workerXmlUrl from 'ace-builds/src-noconflict/worker-xml?url'
ace.config.setModuleUrl('ace/mode/xml_worker', workerXmlUrl)
const beautify = ace.require('ace/ext/beautify')
const props = defineProps({
value: {
type: String,
default: ''
}
})
const emits = defineEmits(['change'])
let aceEditor = null
const code = ref('')
const cursor = ref({
Expand All @@ -130,6 +139,14 @@ watch(isDark, (val) => {
}
})
watch(code, (val) => {
emits('change', val)
})
onBeforeMount(() => {
code.value = props.value
})
function editorInit (editor) {
aceEditor = editor
aceEditor.getSession().setTabSize(2)
Expand Down
130 changes: 130 additions & 0 deletions src/views/xmlEditor/xmlEditor.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
<template>
<div class="code-container">
<el-switch
:model-value="advancedMode"
size="large"
inactive-text="简易模式"
active-text="高级模式"
@change="toggleMode"
/>
<div
v-if="!advancedMode"
flex
gap-4
flex-col
w-full
items-center
>
<div
flex
gap-4
items-center
>
<el-switch
v-model="collapseContent"
size="large"
inactive-text="折叠内容"
/>
<span>
缩进大小
</span>
<el-input-number
v-model="indentValue"
:min="0"
:max="10"
:step="1"
:step-strictly="true"
/>
</div>
<FormatTransformer
w-full
input-label="你的XML内容"
input-placeholder="在这里粘贴XML内容..."
output-label="格式化后的XML内容"
:input-default="value"
:transformer="transformer"
:input-validation-rules="rules"
@format="formattedValue = $event"
/>
</div>
<full-editor
v-else
:value="value"
@change="updateValue"
/>
</div>
</template>

<script setup lang="ts">
import xmlFormat from 'xml-formatter'
import type { Ref } from 'vue'
import FullEditor from './child/fullEditor.vue'
const advancedMode: Ref<boolean> = ref(false)
const value: Ref<string> = ref('<hello><world>foo</world><world>bar</world></hello>')
const formattedValue: Ref<string> = ref('')
const collapseContent: Ref<boolean> = ref(true)
const indentValue: Ref<number> = ref(2)
const rules = [{
validator: (rule: any, val: string, callback: any) => {
if (!isValidXML(val)) {
callback(new Error('请输入正确的XML内容'))
} else {
callback()
}
},
trigger: 'change'
}]
function toggleMode () {
value.value = formattedValue.value || value.value
advancedMode.value = !advancedMode.value
}
function updateValue (val: string) {
formattedValue.value = val
}
function transformer (value: string) {
try {
return xmlFormat(value.trim(), {
collapseContent: collapseContent.value,
indentation: ' '.repeat(indentValue.value),
lineSeparator: '\n'
})
} catch (e) {
return ''
}
}
function isValidXML (val: string) {
const tmp = val.trim()
if (!tmp) {
return true
}
try {
xmlFormat(tmp)
return true
} catch (e) {
return false
}
}
</script>

<style scoped lang="scss">
.code-container {
height: 100%;
width: 100%;
display: flex;
flex-direction: column;
align-items: flex-start;
gap: .8rem;
& > :last-child {
flex: 1;
width: 100%;
}
}
</style>

0 comments on commit 5665f60

Please sign in to comment.