提交 26f3694e 编写于 作者: B baiy 提交者: ninecents

1.9.3 update

上级 434f7dc5
...@@ -12,13 +12,7 @@ ...@@ -12,13 +12,7 @@
## chrome 安装 ## chrome 安装
- 方法1: 在 [Chrome 应用商店](https://chrome.google.com/webstore/detail/ipfcebkfhpkjeikaammlkcnalknjahmh) 安装 -[Chrome 应用商店](https://chrome.google.com/webstore/detail/ipfcebkfhpkjeikaammlkcnalknjahmh) 安装
- 方法2: [下载 .crx 安装包](https://github.com/baiy/Ctool/releases/latest)
- 方法3: [百度网盘下载](https://pan.baidu.com/s/1mhWbqWC) 安装方法和方法2一致
> 方法2 / 方法3 不定期维护 仅供网络环境特别恶劣的同学使用
>
> [猛戳这里查看手动安装`.crx`教程](http://www.cnplugins.com/tool/outline-install-crx-file.html)
## 微软 Edge 安装 ## 微软 Edge 安装
...@@ -30,9 +24,7 @@ ...@@ -30,9 +24,7 @@
## utools 安装 ## utools 安装
### 插件中心安装 - [utools](https://u.tools/) 插件中心 搜索 `ctool`
> 插件中心搜索 `ctool`
## 开发 ## 开发
...@@ -54,15 +46,15 @@ npm run build -adapter=[chrome|edge|utools|firefox|web] ...@@ -54,15 +46,15 @@ npm run build -adapter=[chrome|edge|utools|firefox|web]
|加密/解密|`AES`,`DES`,`RC4`,`Rabbit`,`TripleDes`,`sm2`|√| |加密/解密|`AES`,`DES`,`RC4`,`Rabbit`,`TripleDes`,`sm2`|√|
|BASE64编码|`加密`,`解密`,`支持文件`|√| |BASE64编码|`加密`,`解密`,`支持文件`|√|
|URL编码|`编码`,`解码`|√| |URL编码|`编码`,`解码`|√|
|时间戳|双向转换|√| |时间戳|`双向转换`,`毫秒`|√|
|二维码|`生成`,`解析`|√| |二维码|`生成`,`解析`|√|
|条形码|`生成`|√| |条形码|`生成`|√|
|汉字转拼音|`声调`,`首字母`,`分隔符`|√| |汉字转拼音|`声调`,`首字母`,`分隔符`|√|
|IP地址查询|`运营商`,`城市`|×| |IP地址查询|`运营商`,`城市`|×|
|代码格式化|`js`, `ts`, `html`, `css`, `less`, `scss`, `graphql`, `vue`, `angular`, `markdown`, `json5`, `xml`, `yaml`, `sql`, `压缩`|√| |代码格式化|`js`, `ts`, `html`, `css`, `less`, `scss`, `graphql`, `vue`, `angular`, `markdown`, `json5`, `xml`, `yaml`, `sql`, `压缩`|√|
|Unicode|`双向转换`,`emoji`,`html 实体`,`css 实体`|√| |Unicode|`双向转换`,`emoji`,`html 实体`,`css 实体`|√|
|进制转换|2-64进制互转|√| |进制转换|`2-64进制`|√|
|正则表达式|字符匹配|√| |正则表达式|`匹配`,`查找`,`替换`|√|
|随机字符生成器|`批量`,`特殊字符`|√| |随机字符生成器|`批量`,`特殊字符`|√|
|序列化转换|`json`, `xml`, `yaml`, `phpArray`, `phpSerialize`, `properties`|√| |序列化转换|`json`, `xml`, `yaml`, `phpArray`, `phpSerialize`, `properties`|√|
|文本差异化对比|`行`,`单词`,`css`|√| |文本差异化对比|`行`,`单词`,`css`|√|
...@@ -78,8 +70,9 @@ npm run build -adapter=[chrome|edge|utools|firefox|web] ...@@ -78,8 +70,9 @@ npm run build -adapter=[chrome|edge|utools|firefox|web]
|jwt解码|`header`, `payload`|√| |jwt解码|`header`, `payload`|√|
|Hex/String转换|`hex to string`, `string to hex`, `十六进制转字符串`, `字符串转十六进制`|√| |Hex/String转换|`hex to string`, `string to hex`, `十六进制转字符串`, `字符串转十六进制`|√|
|文本处理|`大小写转换`, `中英文标点转换`, `简繁转换`, `替换`, `字符统计`, `行去重`, `添加行号`, `行排序`, `过滤行首尾不可见字符`,`过滤空行`|√| |文本处理|`大小写转换`, `中英文标点转换`, `简繁转换`, `替换`, `字符统计`, `行去重`, `添加行号`, `行排序`, `过滤行首尾不可见字符`,`过滤空行`|√|
|html编码|`html编码`|√| |html编码|-|√|
|签名/验签|`签名`,`验签`,`RSA`|√| |原码/反码/补码|`生成`|√|
|ARM/HEX|`互转`|×|
## 第三方开源库 ## 第三方开源库
......
此差异已折叠。
{ {
"name": "c-tool", "name": "c-tool",
"version": "1.9.2", "version": "1.9.3",
"private": true, "private": true,
"scripts": { "scripts": {
"serve": "vue-cli-service serve --port 8081", "serve": "vue-cli-service serve --port 8081",
...@@ -17,14 +17,15 @@ ...@@ -17,14 +17,15 @@
"babel-runtime": "^6.26.0", "babel-runtime": "^6.26.0",
"bignumber.js": "^9.0.1", "bignumber.js": "^9.0.1",
"code-formatter": "0.0.1", "code-formatter": "0.0.1",
"codemirror": "^5.63.3", "codemirror": "^5.64.0",
"codemirror-graphql": "^1.1.0", "codemirror-graphql": "^1.2.4",
"cosmiconfig": "^7.0.1",
"cron-parser": "^2.16.3", "cron-parser": "^2.16.3",
"cronstrue": "^1.122.0", "cronstrue": "^1.122.0",
"crypto-js": "^3.3.0", "crypto-js": "^3.3.0",
"diff-match-patch": "^1.0.5", "diff-match-patch": "^1.0.5",
"file": "^0.2.2", "file": "^0.2.2",
"graphql": "15.5.0", "graphql": "15.7.2",
"ipinyinjs": "^1.0.0", "ipinyinjs": "^1.0.0",
"jian_fan": "^1.0.3", "jian_fan": "^1.0.3",
"jimp": "^0.16.1", "jimp": "^0.16.1",
...@@ -35,7 +36,7 @@ ...@@ -35,7 +36,7 @@
"json-to-properties": "^1.1.3", "json-to-properties": "^1.1.3",
"json5": "^2.2.0", "json5": "^2.2.0",
"jsonlint": "^1.6.3", "jsonlint": "^1.6.3",
"jsrsasign": "^10.4.1", "jsrsasign": "^10.5.0",
"jsrsasign-util": "^1.0.5", "jsrsasign-util": "^1.0.5",
"jwt-decode": "^3.1.2", "jwt-decode": "^3.1.2",
"lodash": "^4.17.21", "lodash": "^4.17.21",
...@@ -43,13 +44,13 @@ ...@@ -43,13 +44,13 @@
"moment": "^2.29.1", "moment": "^2.29.1",
"php-array-reader": "^1.3.2", "php-array-reader": "^1.3.2",
"phparr": "^0.2.0", "phparr": "^0.2.0",
"postcss": "^8.3.11", "postcss": "^8.4.4",
"postcss-less": "^5.0.0", "postcss-less": "^5.0.0",
"postcss-scss": "^4.0.2", "postcss-scss": "^4.0.2",
"prettier": "^2.4.1", "prettier": "^2.5.0",
"prettier-plugin-sql": "^0.3.0", "prettier-plugin-sql": "^0.3.0",
"properties-to-json": "^0.1.7", "properties-to-json": "^0.1.7",
"qrcode": "^1.4.4", "qrcode": "^1.5.0",
"qrcode-parser": "^1.2.0", "qrcode-parser": "^1.2.0",
"query-string": "^6.14.1", "query-string": "^6.14.1",
"serialize-php": "^1.1.2", "serialize-php": "^1.1.2",
......
...@@ -70,5 +70,6 @@ ...@@ -70,5 +70,6 @@
"tool_binary": "trueForm/inverse/complement", "tool_binary": "trueForm/inverse/complement",
"tool_armConverter": "ARM/HEX", "tool_armConverter": "ARM/HEX",
// other // other
"css_main_category_item_style": "padding: 0 10px" "css_main_category_item_style": "padding: 0 10px",
"editor_line_wrapping": "Line Wrapping"
} }
...@@ -54,15 +54,15 @@ ...@@ -54,15 +54,15 @@
"tool_regex": "正则表达式", "tool_regex": "正则表达式",
"tool_randomString": "随机字符生成", "tool_randomString": "随机字符生成",
"tool_serializeConversion": "序列化转换", "tool_serializeConversion": "序列化转换",
"tool_diffs": "文本差异化对比", "tool_diffs": "文本比对",
"tool_crontab": "crontab校验", "tool_crontab": "crontab",
"tool_websocket": "websocket调试", "tool_websocket": "websocket",
"tool_unit": "单位换算", "tool_unit": "单位换算",
"tool_time": "时间计算器", "tool_time": "时间计算器",
"tool_uuid": "UUID生成", "tool_uuid": "UUID生成",
"tool_jsonToObject": "JSON转实体类", "tool_jsonToObject": "JSON转实体类",
"tool_ascii": "ASCII转换", "tool_ascii": "ASCII",
"tool_variableConversion": "变量名转换", "tool_variableConversion": "变量名",
"tool_jwt": "JWT解码", "tool_jwt": "JWT解码",
"tool_hexString": "Hex/String", "tool_hexString": "Hex/String",
"tool_text": "文本处理", "tool_text": "文本处理",
...@@ -70,5 +70,6 @@ ...@@ -70,5 +70,6 @@
"tool_binary": "原码/反码/补码", "tool_binary": "原码/反码/补码",
"tool_armConverter": "ARM/HEX", "tool_armConverter": "ARM/HEX",
// 其他 // 其他
"css_main_category_item_style": "padding: 0 20px" "css_main_category_item_style": "padding: 0 20px",
"editor_line_wrapping": "自动换行"
} }
...@@ -3,6 +3,7 @@ import clipboard from './clipboard' ...@@ -3,6 +3,7 @@ import clipboard from './clipboard'
import setting from './setting' import setting from './setting'
import cache from './cache' import cache from './cache'
import history from './history.js' import history from './history.js'
import _ from "lodash";
let fixeInputData; let fixeInputData;
let toolCurrentFeature = ""; let toolCurrentFeature = "";
...@@ -44,40 +45,107 @@ const model = { ...@@ -44,40 +45,107 @@ const model = {
} }
} }
// 保存历史记录防抖
let debounceSaveToolData = {};
const debounceSaveToolDataMethod = _.debounce(function () {
return history(debounceSaveToolData['tool']).push(debounceSaveToolData['data'])
}, 1000)
const appendData = async function (check = "") {
const result = (data = "") => {
if (data) {
if (
!check
|| (_.isFunction(check) && check(data)) // 函数校验
) {
return data
}
}
return ""
}
return new Promise(async (resolve) => {
try {
// 使用固定输入数据
if (fixeInputData) {
let temp = fixeInputData
fixeInputData = ""
return resolve(result(temp))
}
if (setting.autoReadCopy()) {
let paste = (await clipboard.paste()).trim()
if (paste) {
resolve(result(paste))
}
}
resolve(result())
} catch {
resolve(result())
}
});
}
export const plugin = { export const plugin = {
install: function (Vue) { install: function (Vue) {
Vue.prototype.$getToolData = function (clipboardField = '') { Vue.prototype.$initToolData = function (input = "", inputCheck = "", field = "current", isLoadHistory = true) {
let data = history(model.getCurrentTool()).current() let current = _.cloneDeep(this[field])
if (clipboardField) { let inputHistory = ""
if (fixeInputData) { // 使用固定输入数据 let inputDefault = ""
data[clipboardField] = fixeInputData let inputAppend = ""
fixeInputData = "" // 默认数据
} else if (setting.autoReadCopy()) { if (input && (input in current) && current[input]) {
let paste = clipboard.paste() inputDefault = current[input];
if (!data[clipboardField] && paste) { }
if (setting.autoReadCopyFilter()){ // 历史数据
paste = paste.trim() if (isLoadHistory) {
} let history = this.$getToolData()
data[clipboardField] = paste if (input && (input in history)) {
} inputHistory = history[input]
delete history[input]
} }
Object.assign(current, this.$getToolData())
}
if (!input) {
this[field] = current
return;
} }
return data
// 追加剪贴板等数据
appendData(inputCheck).then((append) => {
inputAppend = append
this[field] = Object.assign(
current,
{
// 历史数据 > 追加数据 > 默认数据
[input]: inputHistory ? inputHistory : (inputAppend ? inputAppend : inputDefault)
}
)
})
} }
Vue.prototype.$saveToolData = function (data) { Vue.prototype.$getToolData = function () {
return history(model.getCurrentTool()).push(data) return _.cloneDeep(history(model.getCurrentTool()).current())
} }
Vue.prototype.$clipboardCopy = function (data) { Vue.prototype.$saveToolData = function (data, ignoreDebounce = false) {
if (!setting.autoSaveCopy() || !data) return if (ignoreDebounce) {
clipboard.copy(data,()=>{ return history(model.getCurrentTool()).push(_.cloneDeep(data))
this.$Message.success('结果已复制 ^o^') }
}) debounceSaveToolData = {tool: model.getCurrentTool(), data: _.cloneDeep(data)}
debounceSaveToolDataMethod()
} }
Vue.prototype.$clipboardCopyImages = function (data) { Vue.prototype.$clipboardCopy = function (data, force = false) {
if (!setting.autoSaveCopy() || !data) return if ((setting.autoSaveCopy() || force) && data) {
clipboard.copyImage(data,()=>{ clipboard.copy(data, () => {
this.$Message.success('图片已复制 ^o^') this.$Message.success(this.$t('main_ui_copy_text_ok').toString())
}) })
}
}
Vue.prototype.$clipboardCopyImages = function (data, force = false) {
if ((setting.autoSaveCopy() || force) && data) {
clipboard.copyImage(data, () => {
this.$Message.success(this.$t('main_ui_copy_image_ok').toString())
})
}
} }
}, },
} }
......
<template> <template>
<div> <div>
<div style="border: 1px solid #dcdee2; border-radius: 4px"> <heightResize :append="['.page-option-block']">
<code-editor ref="editor" v-model="current.content" :auto-height="220" :language="this.current.lang"></code-editor> <code-editor ref="editor" showLineWrappingSet="no" v-model="current.content" :language="this.current.lang"></code-editor>
</div> </heightResize>
<option-block> <option-block class="page-option-block">
<FormItem> <FormItem>
<ButtonGroup> <ButtonGroup>
<Button <Button
...@@ -16,53 +16,63 @@ ...@@ -16,53 +16,63 @@
</ButtonGroup> </ButtonGroup>
</FormItem> </FormItem>
<FormItem> <FormItem>
<Select placeholder="更多语言" @on-change="(value)=>{handle(value)}"> <Select :placeholder="$t('code_more')" @on-change="(value)=>{handle(value)}">
<Option v-for="item in lang" :value="item" :key="item">{{ item }}</Option> <Option v-for="item in lang" :value="item" :key="item">{{ item }}</Option>
</Select> </Select>
</FormItem> </FormItem>
<FormItem> <FormItem>
<Select placeholder="代码缩进" v-model="current.tab"> <Select :placeholder="$t('code_indent')" v-model="current.tab">
<Option :value="2">缩进 Tab 2</Option> <Option :value="2">{{ $t('code_indent_width',[2]) }}</Option>
<Option :value="4">缩进 Tab 4</Option> <Option :value="4">{{ $t('code_indent_width',[4]) }}</Option>
<Option :value="6">缩进 Tab 6</Option> <Option :value="6">{{ $t('code_indent_width',[6]) }}</Option>
<Option :value="8">缩进 Tab 8</Option> <Option :value="8">{{ $t('code_indent_width',[8]) }}</Option>
</Select> </Select>
</FormItem> </FormItem>
<FormItem>
<Checkbox v-model="current.isCompress">{{ $t('code_compress') }}</Checkbox>
</FormItem>
</option-block> </option-block>
</div> </div>
</template> </template>
<script> <script>
import _ from "lodash"; import _ from "lodash";
import codeEditor from "./components/codeEditor"; import codeEditor from "./components/codeEditor";
import heightResize from "./components/heightResize";
export default { export default {
components: { components: {
codeEditor, codeEditor,
heightResize
}, },
computed:{ computed: {
buttonLang(){ buttonLang() {
let data = _.slice(this.lang,0,8) let data = _.slice(this.lang, 0, 7)
if (this.current.lang && !data.includes(this.current.lang)){ if (this.current.lang && !data.includes(this.current.lang)) {
data.push(this.current.lang) data.push(this.current.lang)
} }
return data return data
} }
}, },
created() { created() {
this.current = Object.assign(this.current, this.$getToolData("content")) this.$initToolData('content')
}, },
methods: { methods: {
handle(language) { handle(language) {
if (this.current.content) { if (this.current.content) {
try { try {
this.current.lang = language; this.current.lang = language;
this.$refs.editor.format(language,{tab:this.current.tab}); if (!this.current.isCompress) {
let option = {tab: this.current.tab}
this.$refs.editor.format(language, option);
} else {
this.$refs.editor.compress(language);
}
this.$saveToolData(this.current); this.$saveToolData(this.current);
return this.$Message.success('格式化完成'); return this.$Message.success(this.$t('code_complete').toString());
} } catch (e) {
catch (e) { console.log(e)
return this.$Modal.error({ return this.$Modal.error({
title:"格式化错误", title: this.$t('code_error_prompt').toString(),
content:`${e.message}` content: `${e.message}`
}); });
} }
} }
...@@ -72,19 +82,20 @@ export default { ...@@ -72,19 +82,20 @@ export default {
return { return {
current: { current: {
content: "", content: "",
isCompress: false,
lang: "", lang: "",
tab:4, tab: 4,
}, },
lang: [ lang: [
"html", "html",
"js",
"css",
"xml",
"json", "json",
"sql",
"yaml", "yaml",
"php", "php",
"xml", "ts",
"sql",
"javascript",
"css",
"typescript",
"java", "java",
"scss", "scss",
"less", "less",
......
<template> <template>
<div ref="container" class="code-editor" :style="`height:${containerHeight};width:${width}`"></div> <input-block right="5px" bottom="5px" :style="style">
<div ref="container" class="code-editor" :style="`height:100%;width:${width}`"></div>
<template slot="extra">
<Checkbox v-if="showLineWrappingSet !== 'null'" v-model="lineWrapping">{{ $t('main_editor_line_wrapping') }}</Checkbox>
</template>
</input-block>
</template> </template>
<script> <script>
import formatter from "../library/formatter"; import {format} from "../library/formatter";
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api'; import {create} from "../library/editor";
const allowFormatterLanguage = {
html: "html",
typescript: "ts",
javascript: "js",
json: "json",
graphql: "graphql",
java: "java",
markdown: "markdown",
php: "php",
css: "css",
scss: "scss",
less: "less",
sql: "sql",
xml: "xml",
yaml: "yaml",
vue: "vue",
angular: "angular",
}
export default { export default {
name: 'codeEditor', name: 'codeEditor',
...@@ -34,97 +20,109 @@ export default { ...@@ -34,97 +20,109 @@ export default {
type: String, type: String,
default: "" default: ""
}, },
autoHeight: { enableBorder: {
type: Number, type: Boolean,
default: 0 default: true
}, },
theme: { placeholder: {
type: String, type: String,
default: 'vs' default: ""
}, },
roundedSelection: { showLineWrappingSet: {
type: Boolean, type: String,
default: true default: "null"
}, },
height: { height: {
type: String, type: String,
default: "350px" default: "100%"
},
hideLineNumbers: {
type: Boolean,
default: false
}, },
width: { width: {
type: String, type: String,
default: "100%" 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: { watch: {
value(newValue) { value(newValue) {
if (this.editor !== null && this.editor.getValue() !== newValue) { if (this.editor !== null && this.editor.getValue() !== newValue) {
this.editor.pushUndoStop(); this.editor.setValue(newValue)
this.editor.getModel().pushEditOperations(
[],
[
{
range: this.editor.getModel().getFullModelRange(),
text: newValue,
},
]
);
this.editor.pushUndoStop();
} }
}, },
language(newValue) { language(newValue) {
if (this.editor !== null) { if (this.editor !== null) {
monaco.editor.setModelLanguage(this.editor.getModel(), newValue) this.editor.customSetEditorLanguage(newValue);
} }
}, },
theme(newValue) { lineWrapping(newValue) {
if (this.editor !== null) { if (this.editor !== null) {
monaco.editor.setTheme(newValue) this.editor.setOption("lineWrapping", newValue);
} }
} }
}, },
created() {
if (this.autoHeight > 0) {
this.containerHeight = (window.innerHeight - this.autoHeight) + "px"
} else {
this.containerHeight = this.height
}
},
mounted() { mounted() {
this.initEditor() this.initEditor()
}, },
data() { data() {
return { return {
editor: null, editor: null,
containerHeight: "" lineWrapping: true,
}
},
created() {
if (this.showLineWrappingSet !== 'null') {
this.lineWrapping = this.showLineWrappingSet === 'yes'
} }
}, },
methods: { methods: {
initEditor() { initEditor() {
this.$refs.container.innerHTML = '' this.editor = create(
this.editor = monaco.editor.create(this.$refs.container, { this.$refs.container,
value: this.value, this.language,
language: this.language, {
theme: this.theme, lineNumbers: !this.hideLineNumbers,
roundedSelection: this.roundedSelection, lineWrapping: this.lineWrapping,
automaticLayout: true placeholder: this.placeholder
}) }
this.editor.onDidChangeModelContent(() => { );
if (this.value !== this.editor.getValue()){ this.editor.setValue(this.value)
this.$emit('input', this.editor.getValue()) this.editor.on('change', editor => {
if (this.value !== editor.getValue()) {
this.$emit('input', editor.getValue())
} }
}) })
}, },
/** @return monaco.editor.IStandaloneCodeEditor*/
getEditor() { getEditor() {
return this.editor return this.editor
}, },
format(lang,option = {}) { format(lang, option = {}) {
if (!(lang in allowFormatterLanguage)){ this.$emit('input', format(this.editor.getValue(), lang, false, option))
throw new Error("当前代码无法格式化"); },
} compress(lang) {
this.$emit('input', formatter(this.editor.getValue(), allowFormatterLanguage[lang],option)) this.$emit('input', format(this.editor.getValue(), lang, true))
} }
} }
}; };
</script> </script>
<style>
.CodeMirror {
height: 100%;
}
.CodeMirror pre.CodeMirror-placeholder {
color: #999;
}
</style>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册