提交 f6d0012c 编写于 作者: B baiy 提交者: ninecents

代码编辑器重写

上级 270b4da0
.DS_Store
/node_modules
/temp_release
/desktop/node_modules
/dist
/public/manifest.json
......
此差异已折叠。
......@@ -9,13 +9,15 @@
},
"dependencies": {
"@babel/parser": "^7.15.8",
"@typescript-eslint/typescript-estree": "^5.0.0",
"@prettier/plugin-php": "^0.17.5",
"@prettier/plugin-xml": "^1.1.0",
"@typescript-eslint/typescript-estree": "^5.1.0",
"angular-html-parser": "^1.8.0",
"axios": "^0.21.4",
"babel-runtime": "^6.26.0",
"code-formatter": "0.0.1",
"cron-parser": "^2.16.3",
"cronstrue": "^1.117.0",
"cronstrue": "^1.122.0",
"crypto-js": "^3.3.0",
"diff": "^4.0.2",
"file": "^0.2.2",
......@@ -29,13 +31,17 @@
"jsonlint": "^1.6.3",
"jwt-decode": "^3.1.2",
"lodash": "^4.17.21",
"mime-types": "^2.1.32",
"mime-types": "^2.1.33",
"moment": "^2.29.1",
"monaco-editor": "^0.29.1",
"monaco-editor-webpack-plugin": "^5.0.0",
"php-array-reader": "^1.3.0",
"phparr": "^0.2.0",
"postcss-less": "^5.0.0",
"postcss-scss": "^4.0.1",
"prettier": "^2.4.1",
"prettier-plugin-java": "^1.5.0",
"prettier-plugin-sql": "^0.3.0",
"properties-to-json": "^0.1.7",
"qrcode": "^1.4.4",
"qrcode-parser": "^1.2.0",
......@@ -46,10 +52,8 @@
"uuid": "^8.3.2",
"view-design": "^4.6.1",
"vue": "^2.6.14",
"vue-codemirror": "^4.0.6",
"vue-router": "^3.5.2",
"x2js": "github:abdolence/x2js",
"xml-formatter": "^2.4.1"
"x2js": "github:abdolence/x2js"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^3.12.1",
......@@ -60,7 +64,7 @@
"eslint-plugin-vue": "^5.2.3",
"less": "^2.7.3",
"less-loader": "^5.0.0",
"utools-api-types": "^2.0.6",
"utools-api-types": "^2.3.0",
"vue-cli-plugin-iview": "^1.0.6",
"vue-template-compiler": "^2.6.14"
},
......@@ -97,4 +101,4 @@
"last 2 versions",
"not ie <= 8"
]
}
\ No newline at end of file
}
......@@ -4,6 +4,7 @@ import './statics/theme.less'
import router from './tool.router'
import optionBlock from './components/optionBlock'
import {plugin as modelPlugin} from './tool/model'
import codeEditor from "./views/tool/components/codeEditor";
import cache from './tool/cache'
import setting from './tool/setting'
import App from './tool.vue'
......@@ -18,6 +19,7 @@ const run = () => {
Vue.use(ViewUI)
Vue.use(modelPlugin)
Vue.component('option-block', optionBlock);
Vue.component('code-editor', codeEditor);
new Vue({
router,
......
......@@ -3,7 +3,7 @@ const _ = require('lodash');
const fs = require('fs');
// 运行平台适配
let platform = process.env.hasOwnProperty('npm_config_adapter') ? process.env.npm_config_adapter : "";
platform = ["chrome", 'utools', 'edge', 'firefox'].includes(platform) ? platform : "web"
platform = ['chrome', 'utools', 'edge', 'firefox','web'].includes(platform) ? platform : "web"
const IS_CHROME = "chrome" === platform
const IS_EDGE = "edge" === platform
......
<template>
<div>
<div style="border: 1px solid #dcdee2; border-radius: 4px">
<codemirror
ref="code"
v-model="current.content"
:options="options"
></codemirror>
<div>
<div style="border: 1px solid #dcdee2; border-radius: 4px">
<code-editor ref="editor" v-model="current.content" auto-height="220" :language="this.current.lang"></code-editor>
</div>
<option-block>
<FormItem>
<ButtonGroup>
<Button
:type="current.lang !== item ? 'primary' : 'error'"
@click="handle(item)"
v-for="item in buttonLang"
:key="item"
>{{ item }}
</Button>
</ButtonGroup>
</FormItem>
<FormItem>
<Select placeholder="更多语言/格式" @on-change="(value)=>{handle(value)}">
<Option v-for="item in lang" :value="item" :key="item">{{ item }}</Option>
</Select>
</FormItem>
</option-block>
</div>
<option-block>
<FormItem>
<ButtonGroup>
<Button
type="primary"
@click="handle(k, v)"
v-for="(v, k) in lang"
:key="k"
>{{ k }}</Button
>
</ButtonGroup>
</FormItem>
<FormItem>
<Checkbox v-model="current.isCompress">压缩</Checkbox>
</FormItem>
</option-block>
</div>
</template>
<script>
import { codemirror } from "vue-codemirror";
import formatter from "./library/formatter";
import "codemirror/lib/codemirror.css";
import "codemirror/mode/javascript/javascript.js";
import "codemirror/mode/htmlmixed/htmlmixed.js";
import "codemirror/mode/css/css.js";
import "codemirror/mode/xml/xml.js";
import "codemirror/mode/sql/sql.js";
import "codemirror/addon/fold/foldcode.js";
import "codemirror/addon/fold/foldgutter.js";
import "codemirror/addon/fold/brace-fold.js";
import "codemirror/addon/fold/comment-fold.js";
import "codemirror/addon/fold/foldgutter.css";
import _ from "lodash";
export default {
components: {
codemirror,
},
created() {
this.current = Object.assign(this.current, this.$getToolData("content"));
},
mounted() {
this.codemirror.setSize(null, 350);
if (this.current.lang) {
this.codemirror.setOption("mode", this.options[this.current.lang]);
}
},
computed: {
codemirror() {
return this.$refs.code.codemirror;
computed:{
buttonLang(){
let data = _.slice(this.lang,0,8)
if (this.current.lang && !data.includes(this.current.lang)){
data.push(this.current.lang)
}
return data
}
},
},
methods: {
handle(lang, mode) {
if (this.current.content) {
this.current.content = formatter(
this.current.content,
lang,
this.current.isCompress
);
this.codemirror.setOption("mode", mode);
this.current.lang = lang;
this.$saveToolData(this.current);
}
methods: {
handle(language) {
this.current.lang = language;
setTimeout(()=>{
if (this.current.content) {
let oldContent = this.current.content;
this.$refs.editor.getEditor().getAction('editor.action.formatDocument').run();
setTimeout(()=>{
if (oldContent !== this.current.content){
this.$saveToolData(this.current);
return this.$Message.success('格式化完成');
}
},300)
}
},200)
},
},
data() {
return {
current: {
content: "",
lang: "",
},
lang: [
"html",
"json",
"yaml",
"php",
"xml",
"sql",
"javascript",
"css",
"typescript",
"java",
"scss",
"less",
"graphql",
"markdown",
],
};
},
},
data() {
return {
current: {
content: "",
lang: "",
isCompress: false,
},
options: {
mode: null,
lineNumbers: true,
lineWrapping: false,
foldGutter: true,
indentUnit: 4,
gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"],
},
lang: {
js: "text/javascript",
ts: "text/typescript",
css: "text/css",
scss: "text/scss",
less: "text/less",
json5: "text/json5",
graphql: "text/graphql",
markdown: "text/markdown",
html: "text/html",
xml: "application/xml",
sql: "text/x-mysql",
vue: "text/vue",
angular: "text/angular",
},
};
},
};
</script>
\ No newline at end of file
</script>
<template>
<div :style="style">
<div ref="container" class="code-editor" :style="`height:100%;width:${width}`"></div>
<div ref="container" class="monaco-editor"
:style="`height:${containerHeight};width:${width}`">
</div>
</template>
<script>
import {format} from "../library/formatter";
import {create} from "../library/editor";
import formatter from "../library/formatter";
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
// 注册文本格式化服务
// html/typescript/javascript/json 使用内置服务
const allowFormatterLanguage = [
{id: "css", format: "css"},
{id: "graphql", format: "graphql"},
{id: "java", format: "java"},
{id: "markdown", format: "markdown"},
{id: "php", format: "php"},
{id: "scss", format: "scss"},
{id: "sql", format: "sql"},
{id: "xml", format: "xml"},
{id: "yaml", format: "yaml"},
]
for (let lang of allowFormatterLanguage) {
monaco.languages.registerDocumentFormattingEditProvider(lang.id, {
provideDocumentFormattingEdits(model) {
return [
{
range: model.getFullModelRange(),
text: formatter(model.getValue(), lang.format),
},
];
}
});
}
export default {
name: 'codeEditor',
......@@ -17,37 +43,27 @@ export default {
type: String,
default: ""
},
enableBorder: {
theme: {
type: String,
default: 'vs'
},
roundedSelection: {
type: Boolean,
default: true
},
placeholder: {
type: String,
default: ""
autoHeight: {
type: Number,
default: 0
},
height: {
type: String,
default: "100%"
},
hideLineNumbers: {
type: Boolean,
default: false
default: "350px"
},
width: {
type: String,
default: "100%"
},
},
computed: {
style() {
let css = [`height:${this.height}`];
if (this.enableBorder) {
css.push("border: 1px solid #dcdee2")
css.push("border-radius: 4px")
}
return css.join(";")
}
},
watch: {
value(newValue) {
if (this.editor !== null && this.editor.getValue() !== newValue) {
......@@ -56,53 +72,50 @@ export default {
},
language(newValue) {
if (this.editor !== null) {
this.editor.customSetEditorLanguage(newValue);
monaco.editor.setModelLanguage(this.editor.getModel(), newValue)
}
},
theme(newValue) {
if (this.editor !== null) {
monaco.editor.setTheme(newValue)
}
}
},
created() {
if (this.autoHeight > 0) {
this.containerHeight = (window.innerHeight - this.autoHeight) + "px"
} else {
this.containerHeight = this.height
}
},
mounted() {
this.initEditor()
},
data() {
return {
editor: null,
containerHeight: ""
}
},
methods: {
initEditor() {
this.editor = create(
this.$refs.container,
this.language,
{
lineNumbers: !this.hideLineNumbers,
placeholder: this.placeholder
}
);
this.editor.setValue(this.value)
this.editor.on('change', editor => {
if (this.value !== editor.getValue()) {
this.$emit('input', editor.getValue())
}
this.$refs.container.innerHTML = ''
this.editor = monaco.editor.create(this.$refs.container, {
value: this.value,
language: this.language,
theme: this.theme,
roundedSelection: this.roundedSelection,
automaticLayout: true
})
this.editor.onDidChangeModelContent(() => {
this.$emit('input', this.editor.getValue())
})
},
/** @return monaco.editor.IStandaloneCodeEditor*/
getEditor() {
return this.editor
},
format(lang, option = {}) {
this.$emit('input', format(this.editor.getValue(), lang, false, option))
},
compress(lang) {
this.$emit('input', format(this.editor.getValue(), lang, true))
}
}
};
</script>
<style>
.CodeMirror {
height: 100%;
}
.CodeMirror pre.CodeMirror-placeholder {
color: #999;
}
</style>
......@@ -15,37 +15,18 @@
</FormItem>
</option-block>
<div style="border: 1px solid #dcdee2;border-radius: 4px;">
<codemirror ref="code" v-model="current.output" :options="options"></codemirror>
<code-editor v-model="current.output" language="json"></code-editor>
</div>
</div>
</template>
<script>
import axios from "axios"
import _ from "lodash"
import {codemirror} from 'vue-codemirror'
import 'codemirror/lib/codemirror.css'
import 'codemirror/mode/javascript/javascript.js'
import 'codemirror/addon/fold/foldcode.js'
import 'codemirror/addon/fold/foldgutter.js'
import 'codemirror/addon/fold/brace-fold.js'
import 'codemirror/addon/fold/comment-fold.js'
import 'codemirror/addon/fold/foldgutter.css'
export default {
components: {
codemirror,
},
created() {
this.current = Object.assign(this.current, this.$getToolData("input"))
},
mounted() {
this.codemirror.setSize(null, 350)
},
computed: {
codemirror() {
return this.$refs.code.codemirror
}
},
methods: {
handle() {
if (this.current.input) {
......@@ -70,14 +51,6 @@ export default {
current: {
input: "",
output: "",
},
options: {
mode: 'application/json',
lineNumbers: true,
lineWrapping: false,
foldGutter: true,
indentUnit: 4,
gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'],
}
}
},
......
<template>
<div>
<div style="border: 1px solid #dcdee2;border-radius: 4px;">
<codemirror ref="code" v-model="current.content" :options="options"></codemirror>
<code-editor v-model="current.content" :auto-height="220" language="json"></code-editor>
</div>
<option-block :style="{textAlign:'center'}">
<FormItem>
......@@ -13,33 +13,18 @@
</div>
</template>
<script>
import { codemirror } from 'vue-codemirror'
import 'codemirror/lib/codemirror.css'
import 'codemirror/mode/javascript/javascript.js'
import 'codemirror/addon/fold/foldcode.js'
import 'codemirror/addon/fold/foldgutter.js'
import 'codemirror/addon/fold/brace-fold.js'
import 'codemirror/addon/fold/comment-fold.js'
import 'codemirror/addon/fold/foldgutter.css'
import Unicode from "./library/unicode"
export default {
components: {
codemirror,
},
created () {
this.current = Object.assign(this.current, this.$getToolData('content'))
},
mounted(){
setTimeout(()=>{
this.codemirror.setSize(null, window.innerHeight - 220)
this.editorHeight = (window.innerHeight - 220) + "px"
console.log(this.editorHeight)
},100)
},
computed: {
codemirror() {
return this.$refs.code.codemirror
}
},
methods: {
handle (v) {
if (this.current.content) {
......@@ -136,14 +121,6 @@
current: {
content: '',
},
options: {
mode: 'application/json',
lineNumbers: true,
lineWrapping: false,
foldGutter: true,
indentUnit: 4,
gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'],
},
type: {
'format': '格式化/校验',
'compress': '压缩',
......@@ -157,4 +134,4 @@
}
},
}
</script>
\ No newline at end of file
</script>
......@@ -3,7 +3,7 @@
<Col span="10">
<Card :padding="0">
<p slot="title">JSON内容</p>
<codemirror ref="json" v-model="current.json" :options="options('Json')"></codemirror>
<code-editor v-model="current.json" auto-height="330" language="json"></code-editor>
</Card>
<option-block>
<FormItem>
......@@ -28,8 +28,7 @@
@click="handle(item)">{{ item }}
</Button>
</template>
<codemirror ref="output" v-model="current.output"
:options="options(this.current.type)"></codemirror>
<code-editor v-model="current.output" auto-height="220" :language="languages[current.type]"></code-editor>
</Card>
</Col>
</Row>
......@@ -39,29 +38,11 @@ import json2Go from './library/json2Go'
import json2CSharp from './library/json2CSharp'
import json2Java from './library/json2Java'
import json2Dart from './library/json2Dart'
import {codemirror} from 'vue-codemirror'
import 'codemirror/lib/codemirror.css'
import 'codemirror/mode/javascript/javascript.js'
import 'codemirror/mode/go/go.js'
import 'codemirror/mode/dart/dart'
import 'codemirror/mode/clike/clike.js'
import 'codemirror/addon/fold/foldcode.js'
import 'codemirror/addon/fold/foldgutter.js'
import 'codemirror/addon/fold/brace-fold.js'
import 'codemirror/addon/fold/comment-fold.js'
import 'codemirror/addon/fold/foldgutter.css'
export default {
components: {
codemirror,
},
created() {
this.current = Object.assign(this.current, this.$getToolData())
},
mounted() {
this.$refs.json.codemirror.setSize(null, window.innerHeight - 330)
this.$refs.output.codemirror.setSize(null, window.innerHeight - 230)
},
methods: {
handle(type) {
try {
......@@ -93,15 +74,6 @@ export default {
return
}
this.$saveToolData(this.current)
},
options(mode) {
return {
mode: this.codemirrorMode[mode],
lineWrapping: false,
foldGutter: true,
indentUnit: 4,
gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'],
}
}
},
data() {
......@@ -114,14 +86,13 @@ export default {
output: "",
},
type: ["Java", "C#", "Go",'Dart'],
codemirrorMode: {
"Json": "application/json",
"Java": "text/x-java",
"Dart": "application/dart",
"C#": "text/x-csharp",
"Go": "text/x-go"
languages: {
"Java": "java",
"Dart": "dart",
"C#": "csharp",
"Go": "go"
},
}
},
}
</script>
\ No newline at end of file
</script>
import codeFormatter from "code-formatter";
import xmlFormatter from "xml-formatter";
import prettier from "prettier/standalone";
import parser from "prettier/parser-babel";
import parserJson5 from "prettier/parser-babel";
import parserTypeScript from "prettier/parser-typescript";
import parserGraphql from "prettier/parser-graphql";
import parserMarkdown from "prettier/parser-markdown";
import parserCss from "prettier/parser-postcss";
import parserYaml from "prettier/parser-yaml";
import parserHtml from "prettier/parser-html";
import parserJson5 from "prettier/parser-babel";
import parserJava from "prettier-plugin-java";
import parserSql from "prettier-plugin-sql";
import parserPhp from "@prettier/plugin-php";
import parserXml from "@prettier/plugin-xml";
//https://github.com/prettier/prettier/issues/6264#issuecomment-507535391
const options = {
js: { parser: "babel", plugins: [parser] },
ts: { parser: "typescript", plugins: [parserTypeScript] },
vue: { parser: "vue", plugins: [parserHtml] },
graphql: { parser: "graphql", plugins: [parserGraphql] },
markdown: { parser: "markdown", plugins: [parserMarkdown] },
css: { parser: "css", plugins: [parserCss] },
less: { parser: "less", plugins: [parserCss] },
scss: { parser: "scss", plugins: [parserCss] },
yaml: { parser: "yaml", plugins: [parserYaml] },
html: { parser: "html", plugins: [parserHtml] },
angular: { parser: "angular", plugins: [parserHtml] },
json5: { parser: "json5", plugins: [parserJson5] },
js: {parser: "babel", plugins: [parser]},
ts: {parser: "typescript", plugins: [parserTypeScript]},
vue: {parser: "vue", plugins: [parserHtml]},
graphql: {parser: "graphql", plugins: [parserGraphql]},
markdown: {parser: "markdown", plugins: [parserMarkdown]},
css: {parser: "css", plugins: [parserCss]},
less: {parser: "less", plugins: [parserCss]},
scss: {parser: "scss", plugins: [parserCss]},
yaml: {parser: "yaml", plugins: [parserYaml]},
html: {parser: "html", plugins: [parserHtml]},
angular: {parser: "angular", plugins: [parserHtml]},
json: {parser: "json5", plugins: [parserJson5]},
xml: {parser: "xml", plugins: [parserXml]},
sql: {parser: "sql", plugins: [parserSql]},
php: {parser: "php", plugins: [parserPhp]},
java: {parser: "java", plugins: [parserJava]},
};
export default (code, type, isCompress = false) => {
if (type === "xml") {
return xmlFormatter(code, {
indentation: isCompress ? "" : " ",
collapseContent: true,
lineSeparator: isCompress ? "" : "\n",
});
} else if (type === "sql") {
return codeFormatter(code, {
method: isCompress ? type + "min" : type,
});
} else {
return prettier.format(code, options[type]);
}
export default (code, lang) => {
if (!(lang in options)) {
throw new Error(`${lang} can't format`);
}
return prettier.format(code, options[lang]);
};
let adapter = require('./src/tool/adapter');
let pages = {}
pages.tool = {
entry: 'src/tool.js',
template: 'public/tool.html',
};
const adapter = require('./src/tool/adapter');
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin')
const pages = {
tool: {
entry: 'src/tool.js',
template: 'public/tool.html',
}
}
const config = {
productionSourceMap: false,
publicPath: "./",
......@@ -24,6 +25,7 @@ const config = {
});
return args
})
config.plugin('monaco-editor').use(MonacoWebpackPlugin)
},
};
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册