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

unicode 工具优化 #57

上级 80970141
......@@ -2,6 +2,10 @@
使用过程中的任何问题或者需要新的工具欢迎提交`Issue`,新工具如果可以提供实现代码就完美了O(∩_∩)O
## 先睹为快
![](https://cdn.jsdelivr.net/gh/baiy/Ctool@master/images/v2_1.png)
## chrome 安装
- 方法1: 在 [Chrome 应用商店](https://chrome.google.com/webstore/detail/ipfcebkfhpkjeikaammlkcnalknjahmh) 安装
......@@ -45,9 +49,9 @@ npm run build -adapter=[chrome|edge|utools|web]
|时间戳|双向转换|√|
|二维码|`生成`,`解析`|√|
|汉字转拼音|`声调`,`首字母`,`分隔符`|√|
|IP地址查询|`运营商`,`城市`|`×`|
|IP地址查询|`运营商`,`城市`|×|
|代码格式化|`js`, `html`, `css`, `xml`, `sql`, `压缩`|√|
|Unicode|双向转换|√|
|Unicode|`双向转换`,`emoji`,`html 实体`,`css 实体`|√|
|进制转换|2-64进制互转|√|
|正则表达式|字符匹配|√|
|随机字符生成器|`批量`,`特殊字符`|√|
......@@ -70,7 +74,6 @@ npm run build -adapter=[chrome|edge|utools|web]
项目诞生离不开这些优秀的开源程序
- [ajax-request](https://www.npmjs.com/package/ajax-request)
- [code-formatter](https://www.npmjs.com/package/code-formatter)
- [crypto-js](https://www.npmjs.com/package/crypto-js)
- [ipinyinjs](https://www.npmjs.com/package/ipinyinjs)
......@@ -102,9 +105,6 @@ npm run build -adapter=[chrome|edge|utools|web]
- [camelcaseplugin](https://github.com/netnexus/camelcaseplugin)
- [jwt-decode](https://www.npmjs.com/package/jwt-decode)
- [jian_fan](https://www.npmjs.com/package/jian_fan)
- [axios](https://www.npmjs.com/package/axios)
> 当然项目中还使用很多不知道姓名的大神的代码, 在这里就不一一感谢
## 先睹为快
![](https://cdn.jsdelivr.net/gh/baiy/Ctool@master/images/v2_1.png)
> 当然项目中还使用很多不知道姓名的大神的代码, 在这里就不一一感谢
\ No newline at end of file
{
"name": "c-tool",
"version": "1.6.5",
"version": "1.6.8",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
......@@ -1846,15 +1846,6 @@
"integrity": "sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA==",
"dev": true
},
"ajax-request": {
"version": "1.2.3",
"resolved": "https://registry.npm.taobao.org/ajax-request/download/ajax-request-1.2.3.tgz",
"integrity": "sha1-mfy+wdbSeS+F+pSVNTMr0U9fN5A=",
"requires": {
"file-system": "^2.1.1",
"utils-extend": "^1.0.7"
}
},
"ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
......@@ -2144,6 +2135,14 @@
"integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==",
"dev": true
},
"axios": {
"version": "0.21.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
"integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
"requires": {
"follow-redirects": "^1.10.0"
}
},
"babel-code-frame": {
"version": "6.26.0",
"resolved": "https://registry.npm.taobao.org/babel-code-frame/download/babel-code-frame-6.26.0.tgz",
......@@ -5222,23 +5221,6 @@
}
}
},
"file-match": {
"version": "1.0.2",
"resolved": "https://registry.npm.taobao.org/file-match/download/file-match-1.0.2.tgz",
"integrity": "sha1-ycrSZdLIrfOoFHWw30dYWQafrvc=",
"requires": {
"utils-extend": "^1.0.6"
}
},
"file-system": {
"version": "2.2.2",
"resolved": "https://registry.npm.taobao.org/file-system/download/file-system-2.2.2.tgz",
"integrity": "sha1-fWWDPjojR9zZVqgTxncVPtPt2Yc=",
"requires": {
"file-match": "^1.0.1",
"utils-extend": "^1.0.4"
}
},
"file-uri-to-path": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
......@@ -5406,8 +5388,7 @@
"follow-redirects": {
"version": "1.13.3",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.3.tgz",
"integrity": "sha512-DUgl6+HDzB0iEptNQEXLx/KhTmDb8tZUHSeLqpnjpknR70H0nC2t9N73BK6fN4hOvJ84pKlIQVQ4k5FFlBedKA==",
"dev": true
"integrity": "sha512-DUgl6+HDzB0iEptNQEXLx/KhTmDb8tZUHSeLqpnjpknR70H0nC2t9N73BK6fN4hOvJ84pKlIQVQ4k5FFlBedKA=="
},
"for-in": {
"version": "1.0.2",
......@@ -11833,11 +11814,6 @@
"integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=",
"dev": true
},
"utils-extend": {
"version": "1.0.8",
"resolved": "https://registry.npm.taobao.org/utils-extend/download/utils-extend-1.0.8.tgz",
"integrity": "sha1-zP17ZFQPjpDuIe7Fd2nQZRyril8="
},
"utils-merge": {
"version": "1.0.1",
"resolved": "http://registry.npm.taobao.org/utils-merge/download/utils-merge-1.0.1.tgz",
......
{
"name": "c-tool",
"version": "1.6.7",
"version": "1.6.8",
"private": true,
"scripts": {
"serve": "vue-cli-service serve --port 8081",
......@@ -8,7 +8,7 @@
"lint": "vue-cli-service lint"
},
"dependencies": {
"ajax-request": "^1.2.3",
"axios": "^0.21.1",
"babel-runtime": "^6.26.0",
"code-formatter": "0.0.1",
"cron-parser": "^2.16.3",
......
......@@ -16,7 +16,7 @@
</style>
</head>
<body>
<div id="page" style="width: 800px;height: 550px;margin: 0 auto;">
<div id="page" style="width: 800px;height: 580px;margin: 0 auto;">
<div style="text-align: center;padding-top: 200px;font-size: 16px;color: #666">加载中...</div>
</div>
<script src=/index.js></script>
......
......@@ -6,7 +6,7 @@
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>Ctool 程序开发常用工具</title>
</head>
<body>
<body style="padding-bottom: 30px">
<div id="page" style="width: 800px;height: 550px;margin: 0 auto;padding: 0 10px;overflow-y:auto;">
<div id="app"></div>
</div>
......
export const openUrl = (url) => {
// return chrome.tabs.create();
// return chrome.windows.create();
return window.open(url);
}
\ No newline at end of file
export const openUrl = (url) => {
if ("utools" in window && "shellOpenExternal" in window.utools) {
return window.utools.shellOpenExternal(url)
}
return window.open(url);
}
\ No newline at end of file
......@@ -6,10 +6,10 @@ const panel = {
chrome.windows.create({
url: chrome.runtime.getURL("tool.html"),
type: "popup",
width: 850,
width: 810,
left: 200,
top: 200,
height: 580,
height: 610,
}, (w) => {
cache.set(this.cacheName, w.id)
})
......
<template>
<div v-show="show" class="ctool-bottom">
<div class="ctool-bottom-block">
<notice-block/>
</div>
</div>
</template>
<script>
import Notice from './components/notice'
export default {
name: "bottom",
components: {
"notice-block": Notice
},
data() {
return {show: false}
},
methods: {
setShow() {
this.show = true
}
}
}
</script>
<style scoped>
.ctool-bottom {
width: 100%;
position: fixed;
z-index: 9999;
bottom: 0;
left: 0;
height: 30px;
overflow: hidden;
border-top: 1px solid #dcdee2;
background: #FFF;
}
.ctool-bottom-block {
height: 28px;
line-height: 28px;
overflow: hidden;
}
</style>
\ No newline at end of file
<template>
<div class="ctool-notice-block">
<ul class="ctool-notice-ul" :class="{'ctool-notice-animate-up': animateUp}">
<li v-for="(item, index) in listData" :key="index">
<Icon v-if="item.icon.length > 0" :type="item.icon"/>
<span v-html="item.text" @click="open(item)"></span>
</li>
</ul>
</div>
</template>
<script>
import {env, openUrl} from "../helper";
import instance from '../tool/instance'
import cache from "../tool/cache";
import user from "../tool/user";
import axios from "axios";
import _ from "lodash";
const CACHE_NAME = 'notice_item';
const CACHE_EXPIRY = 3600 * 24;
const NOTICE_TYPE = ['info', 'ad', 'hidden'];
const NOTICE_URL_TYPE = ['tool', 'web'];
const handleNoticeItems = ({code, data, info}) => {
if (code !== 0) {
throw new Error(info)
}
let items = [];
for (let item of data) {
if (
!('type' in item)
|| !('text' in item)
|| !('url' in item)
|| !('type' in item.url)
|| !('value' in item.url)
|| !NOTICE_TYPE.includes(item.type)
|| !NOTICE_URL_TYPE.includes(item.url.type)
|| item.text.trim().length < 1
) {
continue;
}
items.push({
type: item.type,
icon: 'icon' in item ? item.icon : "",
text: item.text.trim(),
url: {
type: item.url.type,
value: item.url.value,
},
})
}
return items;
}
const logError = (e) => {
// console.log(e)
}
export default {
name: "notice",
data() {
return {
animateUp: false,
// {icon,text,url:{type,value}},
listData: [],
timer: null
}
},
created() {
// 初始化数据
this.load();
},
methods: {
load() {
try {
// 加载缓存
let items = cache.get(CACHE_NAME)
if (items !== null) {
return this.init(items)
}
try {
// 远程加载
axios({
url: 'https://www.baiy.org/chrome_tool/notice/',
responseType: 'json',
params: {
v: env('version'),
p: env('platform'),
u: user.uid(),
r: Math.random()
}
}).then(({data}) => {
let notices = handleNoticeItems(data);
if (notices.length > 0) {
cache.set(CACHE_NAME, notices, CACHE_EXPIRY)
this.init(notices);
}
}).catch((error) => {
logError(error)
});
} catch (e) {
logError(e)
}
} catch (e) {
logError(e)
}
},
init(notices) {
this.listData = _.cloneDeep(notices.filter((item) => {
return item.type !== "hidden"
}))
if (this.listData.length > 1) {
this.timer = setInterval(this.scrollAnimate, 6000);
}
if (this.listData.length > 0) {
this.$parent['setShow']()
}
},
scrollAnimate() {
this.animateUp = true
setTimeout(() => {
this.listData.push(this.listData[0])
this.listData.shift()
this.animateUp = false
}, 500)
},
open(item) {
switch (item.url.type) {
case "tool":
instance.enter(item.url.value)
break;
case "web":
openUrl(item.url.value)
break;
}
}
},
destroyed() {
if (this.timer !== null) {
clearInterval(this.timer)
}
}
};
</script>
<style scoped>
.ctool-notice-block {
padding-left: 20px;
height: 28px;
border-radius: 20px;
margin: 0 auto;
overflow: hidden;
}
.ctool-notice-block .ctool-notice-ul li {
width: 100%;
height: 100%;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
list-style: none;
line-height: 28px;
/*text-align: right;*/
font-size: 14px;
color: #515a6e;
}
.ctool-notice-animate-up {
transition: all 0.5s ease-in-out;
transform: translateY(-28px);
}
.ctool-notice-block .ctool-notice-ul li span:hover {
font-weight: 400;
text-decoration: underline;
cursor: pointer;
}
.ctool-notice-block .ctool-notice-ul li i {
margin-right: 5px;
}
</style>
import {stringify as queryStringify} from "query-string"
import {v4 as uuidV4} from 'uuid';
import {openUrl as chromiumOpenUrl} from './adapter/chromium/helper';
import {openUrl as utoolsOpenUrl} from './adapter/utools/helper';
export const env = function (key) {
export const env = (key) => {
return process['ctool'][key] ? process['ctool'][key] : "";
};
......@@ -10,52 +12,16 @@ export const isChromium = !!env('isChromium')
export const isWeb = !!env('isWeb')
export const isUtools = !!env('isUtools')
export const trim = function (str, char, type) {
if (char) {
if (type === 'left') {
return str.replace(new RegExp('^\\' + char + '+', 'g'), '');
} else if (type === 'right') {
return str.replace(new RegExp('\\' + char + '+$', 'g'), '');
}
return str.replace(new RegExp('^\\' + char + '+|\\' + char + '+$', 'g'), '');
}
return str.replace(/^\s+|\s+$/g, '');
};
export const inArray = function (value, arr) {
return arr.findIndex((v) => {
return value === v
}) !== -1
};
export const uuid = () => {
return uuidV4().toLowerCase();
}
export const openTab = function (url) {
if (isChromium && chrome.tabs) {
return chrome.tabs.create({url: url, selected: true});
export const openUrl = (url) => {
if (isChromium) {
return chromiumOpenUrl(url)
}
if (isUtools && window.utools) {
return window.utools.shellOpenExternal(url)
if (isUtools) {
return utoolsOpenUrl(url)
}
return window.open(url);
};
export const stat = function (action, data = {}) {
setTimeout(function () {
try {
let img = new Image(1, 1);
img.src = 'https://www.baiy.org/chrome_tool/stat/?' + queryStringify(
Object.assign(
{
v: env('version'),
a: action,
p: env('platform'),
r: Math.random()
},
data
)
);
} catch (e) {
// todo
}
}, 3000)
};
};
\ No newline at end of file
......@@ -13,7 +13,7 @@ import {isUtools} from './helper'
const page = document.getElementById('page')
page.style.width = 'auto'
page.style.height = 'auto'
page.style.minHeight = '500px'
page.style.minHeight = '550px'
}
})()
......
import Vue from 'vue'
import Router from 'vue-router'
import { stat } from './helper'
import {env} from './helper'
import {stringify as queryStringify} from "query-string";
import user from "./tool/user";
Vue.use(Router)
export const stat = (action, data = {}) => {
setTimeout(() => {
try {
let img = new Image(1, 1);
img.src = 'https://www.baiy.org/chrome_tool/stat/?' + queryStringify({
v: env('version'),
a: action,
u: user.uid(),
p: env('platform'),
r: Math.random(),
...data
});
} catch (e) {
// todo
}
}, 3000)
};
// 路由配置
const routes = [
{
......@@ -116,12 +136,12 @@ const routes = [
}
]
const router = new Router({ routes })
const router = new Router({routes})
stat('index')
router.afterEach(to => {
stat('tool', { tool: to.path })
stat('tool', {tool: to.path})
})
export default router
\ No newline at end of file
......@@ -61,79 +61,82 @@
<Drawer title="设置" v-model="settingShow" :width="400">
<setting-block v-if="settingShow"></setting-block>
</Drawer>
<bottom-block/>
</div>
</template>
<script>
import config from './tool/config'
import instance from './tool/instance'
import BottomBlock from './bottom'
import settingBlock from "./views/setting/block"
import model from './tool/model'
import historyFactory from './tool/history'
import {setLoadHistoryIndex} from './tool/history'
import { openTab,isUtools } from './helper'
import historyFactory, {setLoadHistoryIndex} from './tool/history'
import {isUtools, openUrl} from './helper'
export default {
components: {
"setting-block": settingBlock
"setting-block": settingBlock,
"bottom-block": BottomBlock
},
data () {
data() {
return {
isRouterAlive:true,
isUtools:isUtools,
isRouterAlive: true,
isUtools: isUtools,
category: config.category,
currentCategory: '',
currentTool: '',
historyData: [],
settingShow:false,
settingShow: false,
historyShow: false,
historyColumns: [
{
title: '操作时间',
key: 'time',
width:180
width: 180
},
{
title: '数据',
slot: '_value',
ellipsis:true,
ellipsis: true,
},
{
title: '操作',
slot: '_op',
width:150
width: 150
}
],
}
},
computed: {
tools () {
tools() {
return config.getToolByCategory(this.currentCategory)
},
historyLength(){
historyLength() {
return historyFactory(this.currentTool).length()
},
historyTableHeight() {
// 设置表格高度
return window.innerHeight - 140
},
currentToolTitle(){
currentToolTitle() {
return config.getToolTitle(this.currentTool)
}
},
watch: {
currentTool (name) {
currentTool(name) {
model.setCurrentTool(name)
this.$router.push('/tool/' + name)
},
},
created () {
if (this.isUtools){
window.utools.onPluginEnter(({code,payload,type}) => {
created() {
if (this.isUtools) {
window.utools.onPluginEnter(({code, payload, type}) => {
let tool = "";
let feature = "";
if (code.indexOf('ctool-') !== -1) {
tool = code.replace(/ctool-/g, "")
if (tool.indexOf('-') !== -1){
if (tool.indexOf('-') !== -1) {
let temp = tool.split('-');
tool = temp[0]
feature = temp[1]
......@@ -141,11 +144,11 @@ export default {
}
// 写入正则匹配数据到固定数据数据
if (type === "regex" && payload){
if (type === "regex" && payload) {
model.setFixeInputData(payload)
}
if(feature){
if (feature) {
// 设置工具内功能
model.setToolCurrentFeature(feature)
}
......@@ -169,25 +172,27 @@ export default {
top: 150,
})
},
mounted () {},
mounted() {
instance.set(this)
},
methods: {
reload () {
reload() {
this.isRouterAlive = false
this.$nextTick(() => (this.isRouterAlive = true))
},
categorySelect (name) {
categorySelect(name) {
switch (name) {
case '_feedback':
openTab('https://github.com/baiy/Ctool/issues')
openUrl('https://github.com/baiy/Ctool/issues')
break
case '_about':
openTab('https://github.com/baiy/Ctool')
openUrl('https://github.com/baiy/Ctool')
break
case '_setting':
this.settingShow = true;
break
case '_new':
openTab(window.location.href)
openUrl(window.location.href)
break
case '_history':
this.history()
......@@ -199,7 +204,7 @@ export default {
break
}
},
history () {
history() {
let history = historyFactory(this.currentTool)
if (history.length() < 1) {
return this.$Message.error('暂无历史记录')
......@@ -207,53 +212,53 @@ export default {
this.historyData = history.all()
this.historyShow = true
},
historyValue (value) {
historyValue(value) {
return JSON.stringify(value)
},
historyView(index){
historyView(index) {
this.$Modal.info({
render: (h) => {
return h('Input', {
props: {
type:"textarea",
rows:10,
type: "textarea",
rows: 10,
value: JSON.stringify(historyFactory(this.currentTool).get(index), null, "\t"),
}
})
},
width:700,
okText:"关闭"
width: 700,
okText: "关闭"
})
},
historyClear(){
historyClear() {
historyFactory(this.currentTool).clear()
this.historyShow = false;
},
historyLoad(index){
historyLoad(index) {
setLoadHistoryIndex(index)
this.historyShow = false;
this.$router.push({
path:this.$router.currentRoute.fullPath,
query:{
t:Date.now(),
path: this.$router.currentRoute.fullPath,
query: {
t: Date.now(),
},
});
},
toolSelect (name) {
toolSelect(name) {
model.setToolHistory(this.currentCategory, name)
this.currentTool = name
},
badgeToolIsShow (tool) {
badgeToolIsShow(tool) {
return config.badgeToolIsShow(tool)
},
badgeCategoryIsShow (cat) {
badgeCategoryIsShow(cat) {
return config.badgeCategoryIsShow(cat)
},
},
}
</script>
<style scoped>
.drawer-footer{
.drawer-footer {
width: 100%;
position: absolute;
bottom: 0;
......
import {env, inArray} from '../helper'
import {env} from '../helper'
import cache from './cache'
const toolConfig = require('../config')
......@@ -84,16 +84,16 @@ export default {
getToolByCategory(cat) {
return tool.filter((t) => {
if (cat === 'common') {
return inArray(t.name, getUserCommon())
return getUserCommon().includes(t.name)
}
return inArray(cat, t.cat)
return t.cat.includes(cat);
})
},
getToolDefaultCategory,
badgeToolIsShow(tool) {
return badgeIsShow() && inArray(tool, BADGE_TOOL)
return badgeIsShow() && BADGE_TOOL.includes(tool)
},
badgeCategoryIsShow(cat) {
return badgeIsShow() && inArray(cat, BADGE_CATEGORY)
return badgeIsShow() && BADGE_CATEGORY.includes(cat)
},
}
\ No newline at end of file
import config from "./config";
let instance = null;
export default {
set(t) {
if (instance === null) {
instance = t
}
},
get() {
return instance
},
enter(name) {
if (instance !== null) {
let cat = config.getToolDefaultCategory(name);
if (cat) {
instance.categorySelect(cat)
}
instance.toolSelect(name)
}
}
}
\ No newline at end of file
import cache from './cache'
import {uuid} from '../helper'
const cache_name = "user_uuid"
export default {
uid() {
let id = cache.getNoVersion(cache_name);
if (id === null) {
id = uuid()
cache.setNoVersion(cache_name, id)
}
return id
}
}
\ No newline at end of file
......@@ -24,7 +24,7 @@
</template>
<script>
import {isChromium, isUtools, openTab} from '../../helper'
import {isChromium, isUtools, openUrl} from '../../helper'
import setting from '../../tool/setting'
import settingBlock from './setting'
......@@ -56,7 +56,7 @@ export default {
open(name) {
switch (name) {
case 'shortcuts':
openTab('chrome://extensions/shortcuts')
openUrl('chrome://extensions/shortcuts')
break
case 'setting':
this.settingShow = true
......
......@@ -20,7 +20,7 @@
</div>
</template>
<script>
import request from "ajax-request"
import axios from "axios"
import { codemirror } from 'vue-codemirror'
import 'codemirror/lib/codemirror.css'
import 'codemirror/mode/javascript/javascript.js'
......@@ -48,13 +48,17 @@
methods: {
handle() {
if (this.current.input) {
request({
url:"https://ifconfig.co/json",
data:this.current.input !== "localhost" ? {ip:this.current.input} : null,
},(err, res, result)=>{
if (err) return this.$Message.error("ip地址信息查询错误:"+err);
this.current.output = JSON.stringify(JSON.parse(result),null, 4);
this.$saveToolData(this.current);
axios({
url: 'https://ifconfig.co/json',
responseType: 'json',
params: this.current.input !== "localhost" ? {ip:this.current.input} : {}
}).then((response)=>{
console.log(response)
// if (err) return this.$Message.error("ip地址信息查询错误:"+err);
// this.current.output = JSON.stringify(JSON.parse(result),null, 4);
// this.$saveToolData(this.current);
}).catch((error)=>{
console.log(error)
});
}
},
......
......@@ -30,7 +30,9 @@
this.current = Object.assign(this.current, this.$getToolData('content'))
},
mounted(){
this.codemirror.setSize(null, window.innerHeight - 200)
setTimeout(()=>{
this.codemirror.setSize(null, window.innerHeight - 220)
},100)
},
computed: {
codemirror() {
......
const unicode_number = "unicode_number";
const html_entity_10 = "html_entity_10";
const html_entity_16 = "html_entity_16";
const unicode_point_default = "unicode_point_default";
const unicode_point_wide = "unicode_point_wide";
const unicode_point_wide_brace = "unicode_point_wide_brace";
const css_entitie = "css_entitie";
export default {
type: {
unicode_point_default,
unicode_point_wide,
unicode_point_wide_brace,
unicode_number,
html_entity_10,
html_entity_16,
css_entitie
},
decode(str, type) {
const errorListener = (item, callback) => {
try {
return callback && callback()
} catch (e) {
throw new Error(`${item} 解码异常:${e.message}`)
}
}
switch (type) {
case this.type.unicode_point_default:
return str.replace(/\\u[0-9a-fA-F]{4}/g, (item) => {
return errorListener(item, () => String.fromCodePoint(parseInt(`0x${item.toLowerCase().replace("\\u", "")}`)))
});
case this.type.unicode_point_wide:
return str.replace(/\\u[0-9a-fA-F]{1,6}/g, (item) => {
return errorListener(item, () => String.fromCodePoint(parseInt(`0x${item.toLowerCase().replace("\\u", "")}`)))
});
case this.type.unicode_point_wide_brace:
return str.replace(/\\u{[0-9a-fA-F]{1,6}}/g, (item) => {
return errorListener(item, () => String.fromCodePoint(parseInt(`0x${item.toLowerCase().replace("\\u", "").replace("{", "").replace("}", "")}`)))
});
case this.type.unicode_number:
return str.replace(/U\+[0-9a-fA-F]{1,6}/g, (item) => {
return errorListener(item, () => String.fromCodePoint(parseInt(`0x${item.replace("U", "").toLowerCase().replace("+", "")}`)))
});
case this.type.html_entity_10:
return str.replace(/&#[0-9]+;/g, (item) => {
return errorListener(item, () => String.fromCodePoint(parseInt(`${item.replace("&#", "").replace(";", "")}`)))
});
case this.type.html_entity_16:
return str.replace(/&#x[0-9a-fA-F]{1,6};/g, (item) => {
return errorListener(item, () => String.fromCodePoint(parseInt(`0x${item.replace("&#x", "").toLowerCase().replace(";", "")}`)))
});
case this.type.css_entitie:
return str.replace(/\\[0-9a-fA-F]{1,6}/g, (item) => {
return errorListener(item, () => String.fromCodePoint(parseInt(`0x${item.replace("\\", "").toLowerCase()}`)))
});
}
throw new Error("解码类型异常")
},
encode(string, type = unicode_point_default, ignore_ascii = false) {
let code = []
for (let s of string) {
let decimalStr = s.codePointAt(0).toString(10);
let hexStr = s.codePointAt(0).toString(16);
if (hexStr.length < 3 && ignore_ascii) {
// 忽略ascii字符
code.push(s)
continue;
}
// 补零
let hexRepairStr = this.repair(hexStr);
switch (type) {
case this.type.unicode_point_default:
if (hexStr.length > 4) {
// 宽字符处理
code.push(...this.charToUtf16(s).map((item) => `\\u${item}`))
} else {
code.push(`\\u${hexRepairStr}`);
}
break;
case this.type.unicode_point_wide:
code.push(`\\u${hexRepairStr}`);
break;
case this.type.unicode_point_wide_brace:
code.push(`\\u{${hexStr}}`);
break;
case this.type.unicode_number:
code.push(`U+${hexRepairStr.toUpperCase()}`);
break;
case this.type.html_entity_10:
code.push(`&#${decimalStr};`);
break;
case this.type.html_entity_16:
code.push(`&#x${hexStr};`);
break;
case this.type.css_entitie:
code.push(`\\${hexRepairStr}`);
break;
default:
throw new Error("编码类型异常")
}
}
return code.join("");
},
charToUtf16(str) {
let arr = []
for (let i = 0; i < str.length; i++) {
arr[i] = this.repair(str.charCodeAt(i).toString(16))
}
return arr
},
repair(str) {
return str.length > 3 ? str : `${'0'.repeat(4 - str.length)}${str}`;
}
}
\ No newline at end of file
......@@ -41,7 +41,6 @@
<script>
import generator from 'qrcode'
import qrcodeParser from 'qrcode-parser'
import { trim } from '../../helper'
import model from '../../tool/model'
export default {
......@@ -102,7 +101,7 @@
return false
},
substr (str) {
str = trim(str.replace(/[\r\n]/g, ''))
str = str.replace(/[\r\n]/g, '').trim()
const strLength = 100
return str.length > strLength ? str.substr(0, strLength) + '...' : str
},
......
......@@ -23,7 +23,6 @@
</template>
<script>
import moment from 'moment'
import { trim } from '../../helper'
let inputType = {
'normalSecond': 1,
......@@ -53,7 +52,7 @@
return inputType.unixMillisecond
}
return inputType.error
}(trim(this.current.input))
}(this.current.input.trim())
if (type === inputType.error) {
return this.$Message.error('输入时间格式错误')
}
......
......@@ -4,64 +4,68 @@
<option-block>
<FormItem>
<ButtonGroup>
<Button type="primary" @click="handle('string2unicode')">字符转Unicode</Button>
<Button type="primary" @click="handle('unicode2string')">Unicode转字符</Button>
<Button type="primary" @click="handle('encode')">字符转Unicode(编码)</Button>
<Button type="primary" @click="handle('decode')">Unicode转字符(解码)</Button>
</ButtonGroup>
</FormItem>
<FormItem>
<Select v-model="current.type" style="width:250px">
<Option value="unicode_point_default">Unicode 默认模式 \u[0-9a-f]{4}</Option>
<Option value="unicode_point_wide">Unicode 宽字符模式 \u[0-9a-f]{4,6}</Option>
<Option value="unicode_point_wide_brace">Unicode 宽字符模式(带大括号) \u{[0-9a-f]{4,6}}</Option>
<Option value="unicode_number">Unicode 编码模式 U+[0-9A-F]{4,6}</Option>
<Option value="html_entity_10">html 实体(10进制) &amp;#[0-9]+;</Option>
<Option value="html_entity_16">html 实体(16进制) &amp;#x[0-9a-f]{1,6};</Option>
<Option value="css_entitie">css 实体(16进制) \[0-9a-f]{4,6}</Option>
</Select>
</FormItem>
<FormItem v-if="!disable_ignore_ascii_select.includes(current.type)">
<Checkbox v-model="current.ignore_ascii">禁止 ASCII 字符编码</Checkbox>
</FormItem>
</option-block>
<Input v-model="current.output" :rows="7" type="textarea" placeholder="结果"></Input>
</div>
</template>
<script>
export default {
created() {
this.current = Object.assign(this.current, this.$getToolData("input"))
},
methods: {
handle(v) {
if (this.current.input) {
this.current.output = this[v](this.current.input);
this.current.operation = v;
this.$clipboardCopy(this.current.output);
this.$saveToolData(this.current);
}
},
string2unicode(string) {
let character = String(string).split("");
let ascii = "";
for (let i = 0; i < character.length; i++) {
let code = Number(character[i].charCodeAt(0));
if (code > 127) {
let charAscii = code.toString(16);
charAscii = String("0000").substring(charAscii.length, 4) + charAscii;
ascii += "\\u" + charAscii;
import Unicode from "./library/unicode"
export default {
created() {
this.current = Object.assign(this.current, this.$getToolData("input"))
},
methods: {
handle(operation) {
if (this.current.input) {
try {
if (operation === "encode") {
this.current.output = Unicode.encode(
this.current.input,
this.current.type,
this.disable_ignore_ascii_select.includes(this.current.type) ? false : this.current.ignore_ascii
);
} else {
ascii += character[i];
this.current.output = Unicode.decode(this.current.input, this.current.type);
}
} catch (e) {
return this.$Message.error(e.message)
}
return ascii;
},
unicode2string(unicode) {
let character = unicode.split("\\u");
let native = character[0];
for (let i = 1; i < character.length; i++) {
let code = character[i];
native += String.fromCharCode(parseInt("0x" + code.substring(0, 4)));
if (code.length > 4) {
native += code.substring(4, code.length);
}
}
return native;
this.current.operation = operation;
this.$clipboardCopy(this.current.output);
this.$saveToolData(this.current);
}
},
data() {
return {
current: {
input: "",
output: "",
operation: ""
}
}
},
}
}
},
data() {
return {
current: {
input: "",
output: "",
operation: "",
type: "unicode_point_default",
ignore_ascii: true,
},
disable_ignore_ascii_select: ['unicode_point_wide', 'unicode_number', 'css_entitie']
}
},
}
</script>
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册