├── .babelrc
├── .electron-vue
├── build.config.js
├── build.js
├── dev-client.js
├── dev-runner.js
├── webpack.main.config.js
├── webpack.renderer.config.js
└── webpack.web.config.js
├── .eslintignore
├── .eslintrc.js
├── .gitignore
├── README.md
├── README_CN.md
├── build
└── icons
│ ├── 256x256.png
│ ├── icon.icns
│ └── icon.ico
├── dist
├── electron
│ └── .gitkeep
└── web
│ └── .gitkeep
├── package-lock.json
├── package.json
├── src
├── index.ejs
├── main
│ ├── index.dev.js
│ └── index.js
└── renderer
│ ├── App.vue
│ ├── Sidebar.vue
│ ├── Tabs.vue
│ ├── assets
│ ├── .gitkeep
│ ├── IT-Tools-preview.gif
│ ├── alipay.gif
│ ├── logo.png
│ └── wechatpay.gif
│ ├── components
│ ├── ColorBoxPage.vue
│ ├── CronPage.vue
│ ├── CronPage
│ │ └── CronHelp.vue
│ ├── Image64Page.vue
│ ├── JsonPage.vue
│ ├── JsonPage
│ │ └── JsonResultHelp.vue
│ ├── LandingPage.vue
│ ├── LandingPage
│ │ └── Welcome.vue
│ ├── RegexPage.vue
│ ├── RegexPage
│ │ └── RegexHelp.vue
│ ├── TimestampPage.vue
│ └── TimestampPage
│ │ └── TstampHelp.vue
│ ├── i18n.js
│ ├── lang
│ ├── cn.js
│ ├── en.js
│ └── messages.js
│ ├── main.js
│ ├── router
│ └── index.js
│ └── store
│ ├── index.js
│ └── modules
│ ├── Color.js
│ ├── Cron.js
│ ├── Image64.js
│ ├── Json.js
│ ├── Menu.js
│ ├── Regex.js
│ ├── TStamp.js
│ └── index.js
├── static
└── .gitkeep
└── test
├── .eslintrc
├── e2e
├── index.js
├── specs
│ └── Launch.spec.js
└── utils.js
└── unit
├── index.js
├── karma.conf.js
└── specs
└── LandingPage.spec.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "comments": false,
3 | "env": {
4 | "test": {
5 | "presets": [
6 | ["env", {
7 | "targets": { "node": 7 }
8 | }],
9 | "stage-0"
10 | ],
11 | "plugins": ["istanbul"]
12 | },
13 | "main": {
14 | "presets": [
15 | ["env", {
16 | "targets": { "node": 7 }
17 | }],
18 | "stage-0"
19 | ]
20 | },
21 | "renderer": {
22 | "presets": [
23 | ["env", {
24 | "modules": false
25 | }],
26 | "stage-0"
27 | ]
28 | },
29 | "web": {
30 | "presets": [
31 | ["env", {
32 | "modules": false
33 | }],
34 | "stage-0"
35 | ]
36 | }
37 | },
38 | "plugins": ["transform-runtime"]
39 | }
40 |
--------------------------------------------------------------------------------
/.electron-vue/build.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 |
3 | /**
4 | * `electron-packager` options
5 | * https://simulatedgreg.gitbooks.io/electron-vue/content/en/using-electron-packager.html
6 | */
7 | module.exports = {
8 | arch: 'x64',
9 | asar: true,
10 | dir: path.join(__dirname, '../'),
11 | icon: path.join(__dirname, '../build/icons/icon'),
12 | ignore: /(^\/(src|test|\.[a-z]+|README|yarn|static|dist\/web))|\.gitkeep/,
13 | out: path.join(__dirname, '../build'),
14 | overwrite: true,
15 | platform: process.env.BUILD_TARGET || 'all'
16 | }
17 |
--------------------------------------------------------------------------------
/.electron-vue/build.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | process.env.NODE_ENV = 'production'
4 |
5 | const { say } = require('cfonts')
6 | const chalk = require('chalk')
7 | const del = require('del')
8 | const packager = require('electron-packager')
9 | const webpack = require('webpack')
10 | const Multispinner = require('multispinner')
11 |
12 | const buildConfig = require('./build.config')
13 | const mainConfig = require('./webpack.main.config')
14 | const rendererConfig = require('./webpack.renderer.config')
15 | const webConfig = require('./webpack.web.config')
16 |
17 | const doneLog = chalk.bgGreen.white(' DONE ') + ' '
18 | const errorLog = chalk.bgRed.white(' ERROR ') + ' '
19 | const okayLog = chalk.bgBlue.white(' OKAY ') + ' '
20 | const isCI = process.env.CI || false
21 |
22 | if (process.env.BUILD_TARGET === 'clean') clean()
23 | else if (process.env.BUILD_TARGET === 'web') web()
24 | else build()
25 |
26 | function clean () {
27 | del.sync(['build/*', '!build/icons', '!build/icons/icon.*'])
28 | console.log(`\n${doneLog}\n`)
29 | process.exit()
30 | }
31 |
32 | function build () {
33 | greeting()
34 |
35 | del.sync(['dist/electron/*', '!.gitkeep'])
36 |
37 | const tasks = ['main', 'renderer']
38 | const m = new Multispinner(tasks, {
39 | preText: 'building',
40 | postText: 'process'
41 | })
42 |
43 | let results = ''
44 |
45 | m.on('success', () => {
46 | process.stdout.write('\x1B[2J\x1B[0f')
47 | console.log(`\n\n${results}`)
48 | console.log(`${okayLog}take it away ${chalk.yellow('`electron-packager`')}\n`)
49 | bundleApp()
50 | })
51 |
52 | pack(mainConfig).then(result => {
53 | results += result + '\n\n'
54 | m.success('main')
55 | }).catch(err => {
56 | m.error('main')
57 | console.log(`\n ${errorLog}failed to build main process`)
58 | console.error(`\n${err}\n`)
59 | process.exit(1)
60 | })
61 |
62 | pack(rendererConfig).then(result => {
63 | results += result + '\n\n'
64 | m.success('renderer')
65 | }).catch(err => {
66 | m.error('renderer')
67 | console.log(`\n ${errorLog}failed to build renderer process`)
68 | console.error(`\n${err}\n`)
69 | process.exit(1)
70 | })
71 | }
72 |
73 | function pack (config) {
74 | return new Promise((resolve, reject) => {
75 | config.mode = 'production'
76 | webpack(config, (err, stats) => {
77 | if (err) reject(err.stack || err)
78 | else if (stats.hasErrors()) {
79 | let err = ''
80 |
81 | stats.toString({
82 | chunks: false,
83 | colors: true
84 | })
85 | .split(/\r?\n/)
86 | .forEach(line => {
87 | err += ` ${line}\n`
88 | })
89 |
90 | reject(err)
91 | } else {
92 | resolve(stats.toString({
93 | chunks: false,
94 | colors: true
95 | }))
96 | }
97 | })
98 | })
99 | }
100 |
101 | function bundleApp () {
102 | buildConfig.mode = 'production'
103 | packager(buildConfig, (err, appPaths) => {
104 | if (err) {
105 | console.log(`\n${errorLog}${chalk.yellow('`electron-packager`')} says...\n`)
106 | console.log(err + '\n')
107 | } else {
108 | console.log(`\n${doneLog}\n`)
109 | }
110 | })
111 | }
112 |
113 | function web () {
114 | del.sync(['dist/web/*', '!.gitkeep'])
115 | webConfig.mode = 'production'
116 | webpack(webConfig, (err, stats) => {
117 | if (err || stats.hasErrors()) console.log(err)
118 |
119 | console.log(stats.toString({
120 | chunks: false,
121 | colors: true
122 | }))
123 |
124 | process.exit()
125 | })
126 | }
127 |
128 | function greeting () {
129 | const cols = process.stdout.columns
130 | let text = ''
131 |
132 | if (cols > 85) text = 'lets-build'
133 | else if (cols > 60) text = 'lets-|build'
134 | else text = false
135 |
136 | if (text && !isCI) {
137 | say(text, {
138 | colors: ['yellow'],
139 | font: 'simple3d',
140 | space: false
141 | })
142 | } else console.log(chalk.yellow.bold('\n lets-build'))
143 | console.log()
144 | }
--------------------------------------------------------------------------------
/.electron-vue/dev-client.js:
--------------------------------------------------------------------------------
1 | const hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true')
2 |
3 | hotClient.subscribe(event => {
4 | /**
5 | * Reload browser when HTMLWebpackPlugin emits a new index.html
6 | *
7 | * Currently disabled until jantimon/html-webpack-plugin#680 is resolved.
8 | * https://github.com/SimulatedGREG/electron-vue/issues/437
9 | * https://github.com/jantimon/html-webpack-plugin/issues/680
10 | */
11 | // if (event.action === 'reload') {
12 | // window.location.reload()
13 | // }
14 |
15 | /**
16 | * Notify `mainWindow` when `main` process is compiling,
17 | * giving notice for an expected reload of the `electron` process
18 | */
19 | if (event.action === 'compiling') {
20 | document.body.innerHTML += `
21 |
34 |
35 |
36 | Compiling Main Process...
37 |
38 | `
39 | }
40 | })
41 |
--------------------------------------------------------------------------------
/.electron-vue/dev-runner.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const chalk = require('chalk')
4 | const electron = require('electron')
5 | const path = require('path')
6 | const { say } = require('cfonts')
7 | const { spawn } = require('child_process')
8 | const webpack = require('webpack')
9 | const WebpackDevServer = require('webpack-dev-server')
10 | const webpackHotMiddleware = require('webpack-hot-middleware')
11 |
12 | const mainConfig = require('./webpack.main.config')
13 | const rendererConfig = require('./webpack.renderer.config')
14 |
15 | let electronProcess = null
16 | let manualRestart = false
17 | let hotMiddleware
18 |
19 | function logStats (proc, data) {
20 | let log = ''
21 |
22 | log += chalk.yellow.bold(`┏ ${proc} Process ${new Array((19 - proc.length) + 1).join('-')}`)
23 | log += '\n\n'
24 |
25 | if (typeof data === 'object') {
26 | data.toString({
27 | colors: true,
28 | chunks: false
29 | }).split(/\r?\n/).forEach(line => {
30 | log += ' ' + line + '\n'
31 | })
32 | } else {
33 | log += ` ${data}\n`
34 | }
35 |
36 | log += '\n' + chalk.yellow.bold(`┗ ${new Array(28 + 1).join('-')}`) + '\n'
37 |
38 | console.log(log)
39 | }
40 |
41 | function startRenderer () {
42 | return new Promise((resolve, reject) => {
43 | rendererConfig.entry.renderer = [path.join(__dirname, 'dev-client')].concat(rendererConfig.entry.renderer)
44 | rendererConfig.mode = 'development'
45 | const compiler = webpack(rendererConfig)
46 | hotMiddleware = webpackHotMiddleware(compiler, {
47 | log: false,
48 | heartbeat: 2500
49 | })
50 |
51 | compiler.hooks.compilation.tap('compilation', compilation => {
52 | compilation.hooks.htmlWebpackPluginAfterEmit.tapAsync('html-webpack-plugin-after-emit', (data, cb) => {
53 | hotMiddleware.publish({ action: 'reload' })
54 | cb()
55 | })
56 | })
57 |
58 | compiler.hooks.done.tap('done', stats => {
59 | logStats('Renderer', stats)
60 | })
61 |
62 | const server = new WebpackDevServer(
63 | compiler,
64 | {
65 | contentBase: path.join(__dirname, '../'),
66 | quiet: true,
67 | before (app, ctx) {
68 | app.use(hotMiddleware)
69 | ctx.middleware.waitUntilValid(() => {
70 | resolve()
71 | })
72 | }
73 | }
74 | )
75 |
76 | server.listen(9080)
77 | })
78 | }
79 |
80 | function startMain () {
81 | return new Promise((resolve, reject) => {
82 | mainConfig.entry.main = [path.join(__dirname, '../src/main/index.dev.js')].concat(mainConfig.entry.main)
83 | mainConfig.mode = 'development'
84 | const compiler = webpack(mainConfig)
85 |
86 | compiler.hooks.watchRun.tapAsync('watch-run', (compilation, done) => {
87 | logStats('Main', chalk.white.bold('compiling...'))
88 | hotMiddleware.publish({ action: 'compiling' })
89 | done()
90 | })
91 |
92 | compiler.watch({}, (err, stats) => {
93 | if (err) {
94 | console.log(err)
95 | return
96 | }
97 |
98 | logStats('Main', stats)
99 |
100 | if (electronProcess && electronProcess.kill) {
101 | manualRestart = true
102 | process.kill(electronProcess.pid)
103 | electronProcess = null
104 | startElectron()
105 |
106 | setTimeout(() => {
107 | manualRestart = false
108 | }, 5000)
109 | }
110 |
111 | resolve()
112 | })
113 | })
114 | }
115 |
116 | function startElectron () {
117 | var args = [
118 | '--inspect=5858',
119 | path.join(__dirname, '../dist/electron/main.js')
120 | ]
121 |
122 | // detect yarn or npm and process commandline args accordingly
123 | if (process.env.npm_execpath.endsWith('yarn.js')) {
124 | args = args.concat(process.argv.slice(3))
125 | } else if (process.env.npm_execpath.endsWith('npm-cli.js')) {
126 | args = args.concat(process.argv.slice(2))
127 | }
128 |
129 | electronProcess = spawn(electron, args)
130 |
131 | electronProcess.stdout.on('data', data => {
132 | electronLog(data, 'blue')
133 | })
134 | electronProcess.stderr.on('data', data => {
135 | electronLog(data, 'red')
136 | })
137 |
138 | electronProcess.on('close', () => {
139 | if (!manualRestart) process.exit()
140 | })
141 | }
142 |
143 | function electronLog (data, color) {
144 | let log = ''
145 | data = data.toString().split(/\r?\n/)
146 | data.forEach(line => {
147 | log += ` ${line}\n`
148 | })
149 | if (/[0-9A-z]+/.test(log)) {
150 | console.log(
151 | chalk[color].bold('┏ Electron -------------------') +
152 | '\n\n' +
153 | log +
154 | chalk[color].bold('┗ ----------------------------') +
155 | '\n'
156 | )
157 | }
158 | }
159 |
160 | function greeting () {
161 | const cols = process.stdout.columns
162 | let text = ''
163 |
164 | if (cols > 104) text = 'electron-vue'
165 | else if (cols > 76) text = 'electron-|vue'
166 | else text = false
167 |
168 | if (text) {
169 | say(text, {
170 | colors: ['yellow'],
171 | font: 'simple3d',
172 | space: false
173 | })
174 | } else console.log(chalk.yellow.bold('\n electron-vue'))
175 | console.log(chalk.blue(' getting ready...') + '\n')
176 | }
177 |
178 | function init () {
179 | greeting()
180 |
181 | Promise.all([startRenderer(), startMain()])
182 | .then(() => {
183 | startElectron()
184 | })
185 | .catch(err => {
186 | console.error(err)
187 | })
188 | }
189 |
190 | init()
191 |
--------------------------------------------------------------------------------
/.electron-vue/webpack.main.config.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | process.env.BABEL_ENV = 'main'
4 |
5 | const path = require('path')
6 | const { dependencies } = require('../package.json')
7 | const webpack = require('webpack')
8 |
9 | const BabiliWebpackPlugin = require('babili-webpack-plugin')
10 |
11 | let mainConfig = {
12 | entry: {
13 | main: path.join(__dirname, '../src/main/index.js')
14 | },
15 | externals: [
16 | ...Object.keys(dependencies || {})
17 | ],
18 | module: {
19 | rules: [
20 | {
21 | test: /\.(js)$/,
22 | enforce: 'pre',
23 | exclude: /node_modules/,
24 | use: {
25 | loader: 'eslint-loader',
26 | options: {
27 | formatter: require('eslint-friendly-formatter')
28 | }
29 | }
30 | },
31 | {
32 | test: /\.js$/,
33 | use: 'babel-loader',
34 | exclude: /node_modules/
35 | },
36 | {
37 | test: /\.node$/,
38 | use: 'node-loader'
39 | }
40 | ]
41 | },
42 | node: {
43 | __dirname: process.env.NODE_ENV !== 'production',
44 | __filename: process.env.NODE_ENV !== 'production'
45 | },
46 | output: {
47 | filename: '[name].js',
48 | libraryTarget: 'commonjs2',
49 | path: path.join(__dirname, '../dist/electron')
50 | },
51 | plugins: [
52 | new webpack.NoEmitOnErrorsPlugin()
53 | ],
54 | resolve: {
55 | extensions: ['.js', '.json', '.node']
56 | },
57 | target: 'electron-main'
58 | }
59 |
60 | /**
61 | * Adjust mainConfig for development settings
62 | */
63 | if (process.env.NODE_ENV !== 'production') {
64 | mainConfig.plugins.push(
65 | new webpack.DefinePlugin({
66 | '__static': `"${path.join(__dirname, '../static').replace(/\\/g, '\\\\')}"`
67 | })
68 | )
69 | }
70 |
71 | /**
72 | * Adjust mainConfig for production settings
73 | */
74 | if (process.env.NODE_ENV === 'production') {
75 | mainConfig.plugins.push(
76 | new BabiliWebpackPlugin(),
77 | new webpack.DefinePlugin({
78 | 'process.env.NODE_ENV': '"production"'
79 | })
80 | )
81 | }
82 |
83 | module.exports = mainConfig
84 |
--------------------------------------------------------------------------------
/.electron-vue/webpack.renderer.config.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | process.env.BABEL_ENV = 'renderer'
4 |
5 | const path = require('path')
6 | const { dependencies } = require('../package.json')
7 | const webpack = require('webpack')
8 |
9 | const BabiliWebpackPlugin = require('babili-webpack-plugin')
10 | const CopyWebpackPlugin = require('copy-webpack-plugin')
11 | const MiniCssExtractPlugin = require('mini-css-extract-plugin')
12 | const HtmlWebpackPlugin = require('html-webpack-plugin')
13 | const { VueLoaderPlugin } = require('vue-loader')
14 |
15 | /**
16 | * List of node_modules to include in webpack bundle
17 | *
18 | * Required for specific packages like Vue UI libraries
19 | * that provide pure *.vue files that need compiling
20 | * https://simulatedgreg.gitbooks.io/electron-vue/content/en/webpack-configurations.html#white-listing-externals
21 | */
22 | let whiteListedModules = ['vue']
23 |
24 | let rendererConfig = {
25 | devtool: '#cheap-module-eval-source-map',
26 | entry: {
27 | renderer: path.join(__dirname, '../src/renderer/main.js')
28 | },
29 | externals: [
30 | ...Object.keys(dependencies || {}).filter(d => !whiteListedModules.includes(d))
31 | ],
32 | module: {
33 | rules: [
34 | {
35 | test: /\.(js|vue)$/,
36 | enforce: 'pre',
37 | exclude: /node_modules/,
38 | use: {
39 | loader: 'eslint-loader',
40 | options: {
41 | formatter: require('eslint-friendly-formatter')
42 | }
43 | }
44 | },
45 | {
46 | test: /\.scss$/,
47 | use: ['vue-style-loader', 'css-loader', 'sass-loader']
48 | },
49 | {
50 | test: /\.sass$/,
51 | use: ['vue-style-loader', 'css-loader', 'sass-loader?indentedSyntax']
52 | },
53 | {
54 | test: /\.less$/,
55 | use: ['vue-style-loader', 'css-loader', 'less-loader']
56 | },
57 | {
58 | test: /\.css$/,
59 | use: ['vue-style-loader', 'css-loader']
60 | },
61 | {
62 | test: /\.html$/,
63 | use: 'vue-html-loader'
64 | },
65 | {
66 | test: /\.js$/,
67 | use: 'babel-loader',
68 | exclude: /node_modules/
69 | },
70 | {
71 | test: /\.node$/,
72 | use: 'node-loader'
73 | },
74 | {
75 | test: /\.vue$/,
76 | use: {
77 | loader: 'vue-loader',
78 | options: {
79 | extractCSS: process.env.NODE_ENV === 'production',
80 | loaders: {
81 | sass: 'vue-style-loader!css-loader!sass-loader?indentedSyntax=1',
82 | scss: 'vue-style-loader!css-loader!sass-loader',
83 | less: 'vue-style-loader!css-loader!less-loader'
84 | }
85 | }
86 | }
87 | },
88 | {
89 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
90 | use: {
91 | loader: 'url-loader',
92 | query: {
93 | limit: 10000,
94 | name: 'imgs/[name]--[folder].[ext]'
95 | }
96 | }
97 | },
98 | {
99 | test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
100 | loader: 'url-loader',
101 | options: {
102 | limit: 10000,
103 | name: 'media/[name]--[folder].[ext]'
104 | }
105 | },
106 | {
107 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
108 | use: {
109 | loader: 'url-loader',
110 | query: {
111 | limit: 10000,
112 | name: 'fonts/[name]--[folder].[ext]'
113 | }
114 | }
115 | }
116 | ]
117 | },
118 | node: {
119 | __dirname: process.env.NODE_ENV !== 'production',
120 | __filename: process.env.NODE_ENV !== 'production'
121 | },
122 | plugins: [
123 | new VueLoaderPlugin(),
124 | new MiniCssExtractPlugin({filename: 'styles.css'}),
125 | new HtmlWebpackPlugin({
126 | filename: 'index.html',
127 | template: path.resolve(__dirname, '../src/index.ejs'),
128 | minify: {
129 | collapseWhitespace: true,
130 | removeAttributeQuotes: true,
131 | removeComments: true
132 | },
133 | nodeModules: process.env.NODE_ENV !== 'production'
134 | ? path.resolve(__dirname, '../node_modules')
135 | : false
136 | }),
137 | new webpack.HotModuleReplacementPlugin(),
138 | new webpack.NoEmitOnErrorsPlugin()
139 | ],
140 | output: {
141 | filename: '[name].js',
142 | libraryTarget: 'commonjs2',
143 | path: path.join(__dirname, '../dist/electron')
144 | },
145 | resolve: {
146 | alias: {
147 | '@': path.join(__dirname, '../src/renderer'),
148 | 'vue$': 'vue/dist/vue.esm.js'
149 | },
150 | extensions: ['.js', '.vue', '.json', '.css', '.node']
151 | },
152 | target: 'electron-renderer'
153 | }
154 |
155 | /**
156 | * Adjust rendererConfig for development settings
157 | */
158 | if (process.env.NODE_ENV !== 'production') {
159 | rendererConfig.plugins.push(
160 | new webpack.DefinePlugin({
161 | '__static': `"${path.join(__dirname, '../static').replace(/\\/g, '\\\\')}"`
162 | })
163 | )
164 | }
165 |
166 | /**
167 | * Adjust rendererConfig for production settings
168 | */
169 | if (process.env.NODE_ENV === 'production') {
170 | rendererConfig.devtool = ''
171 |
172 | rendererConfig.plugins.push(
173 | new BabiliWebpackPlugin(),
174 | new CopyWebpackPlugin([
175 | {
176 | from: path.join(__dirname, '../static'),
177 | to: path.join(__dirname, '../dist/electron/static'),
178 | ignore: ['.*']
179 | }
180 | ]),
181 | new webpack.DefinePlugin({
182 | 'process.env.NODE_ENV': '"production"'
183 | }),
184 | new webpack.LoaderOptionsPlugin({
185 | minimize: true
186 | })
187 | )
188 | }
189 |
190 | module.exports = rendererConfig
191 |
--------------------------------------------------------------------------------
/.electron-vue/webpack.web.config.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | process.env.BABEL_ENV = 'web'
4 |
5 | const path = require('path')
6 | const webpack = require('webpack')
7 |
8 | const BabiliWebpackPlugin = require('babili-webpack-plugin')
9 | const CopyWebpackPlugin = require('copy-webpack-plugin')
10 | const MiniCssExtractPlugin = require('mini-css-extract-plugin')
11 | const HtmlWebpackPlugin = require('html-webpack-plugin')
12 | const { VueLoaderPlugin } = require('vue-loader')
13 |
14 | let webConfig = {
15 | devtool: '#cheap-module-eval-source-map',
16 | entry: {
17 | web: path.join(__dirname, '../src/renderer/main.js')
18 | },
19 | module: {
20 | rules: [
21 | {
22 | test: /\.(js|vue)$/,
23 | enforce: 'pre',
24 | exclude: /node_modules/,
25 | use: {
26 | loader: 'eslint-loader',
27 | options: {
28 | formatter: require('eslint-friendly-formatter')
29 | }
30 | }
31 | },
32 | {
33 | test: /\.scss$/,
34 | use: ['vue-style-loader', 'css-loader', 'sass-loader']
35 | },
36 | {
37 | test: /\.sass$/,
38 | use: ['vue-style-loader', 'css-loader', 'sass-loader?indentedSyntax']
39 | },
40 | {
41 | test: /\.less$/,
42 | use: ['vue-style-loader', 'css-loader', 'less-loader']
43 | },
44 | {
45 | test: /\.css$/,
46 | use: ['vue-style-loader', 'css-loader']
47 | },
48 | {
49 | test: /\.html$/,
50 | use: 'vue-html-loader'
51 | },
52 | {
53 | test: /\.js$/,
54 | use: 'babel-loader',
55 | include: [ path.resolve(__dirname, '../src/renderer') ],
56 | exclude: /node_modules/
57 | },
58 | {
59 | test: /\.vue$/,
60 | use: {
61 | loader: 'vue-loader',
62 | options: {
63 | extractCSS: true,
64 | loaders: {
65 | sass: 'vue-style-loader!css-loader!sass-loader?indentedSyntax=1',
66 | scss: 'vue-style-loader!css-loader!sass-loader',
67 | less: 'vue-style-loader!css-loader!less-loader'
68 | }
69 | }
70 | }
71 | },
72 | {
73 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
74 | use: {
75 | loader: 'url-loader',
76 | query: {
77 | limit: 10000,
78 | name: 'imgs/[name].[ext]'
79 | }
80 | }
81 | },
82 | {
83 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
84 | use: {
85 | loader: 'url-loader',
86 | query: {
87 | limit: 10000,
88 | name: 'fonts/[name].[ext]'
89 | }
90 | }
91 | }
92 | ]
93 | },
94 | plugins: [
95 | new VueLoaderPlugin(),
96 | new MiniCssExtractPlugin({filename: 'styles.css'}),
97 | new HtmlWebpackPlugin({
98 | filename: 'index.html',
99 | template: path.resolve(__dirname, '../src/index.ejs'),
100 | minify: {
101 | collapseWhitespace: true,
102 | removeAttributeQuotes: true,
103 | removeComments: true
104 | },
105 | nodeModules: false
106 | }),
107 | new webpack.DefinePlugin({
108 | 'process.env.IS_WEB': 'true'
109 | }),
110 | new webpack.HotModuleReplacementPlugin(),
111 | new webpack.NoEmitOnErrorsPlugin()
112 | ],
113 | output: {
114 | filename: '[name].js',
115 | path: path.join(__dirname, '../dist/web')
116 | },
117 | resolve: {
118 | alias: {
119 | '@': path.join(__dirname, '../src/renderer'),
120 | 'vue$': 'vue/dist/vue.esm.js'
121 | },
122 | extensions: ['.js', '.vue', '.json', '.css']
123 | },
124 | target: 'web'
125 | }
126 |
127 | /**
128 | * Adjust webConfig for production settings
129 | */
130 | if (process.env.NODE_ENV === 'production') {
131 | webConfig.devtool = ''
132 |
133 | webConfig.plugins.push(
134 | new BabiliWebpackPlugin(),
135 | new CopyWebpackPlugin([
136 | {
137 | from: path.join(__dirname, '../static'),
138 | to: path.join(__dirname, '../dist/web/static'),
139 | ignore: ['.*']
140 | }
141 | ]),
142 | new webpack.DefinePlugin({
143 | 'process.env.NODE_ENV': '"production"'
144 | }),
145 | new webpack.LoaderOptionsPlugin({
146 | minimize: true
147 | })
148 | )
149 | }
150 |
151 | module.exports = webConfig
152 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | test/unit/coverage/**
2 | test/unit/*.js
3 | test/e2e/*.js
4 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | parser: 'babel-eslint',
4 | parserOptions: {
5 | sourceType: 'module'
6 | },
7 | env: {
8 | browser: true,
9 | node: true
10 | },
11 | extends: 'standard',
12 | globals: {
13 | __static: true
14 | },
15 | plugins: [
16 | 'html'
17 | ],
18 | 'rules': {
19 | // allow paren-less arrow functions
20 | 'arrow-parens': 0,
21 | // allow async-await
22 | 'generator-star-spacing': 0,
23 | // allow debugger during development
24 | 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | dist/electron/*
3 | dist/web/*
4 | build/*
5 | !build/icons
6 | coverage
7 | node_modules/
8 | npm-debug.log
9 | npm-debug.log.*
10 | thumbs.db
11 | !.gitkeep
12 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | A programing helper for developers built with Electron & Vue.js 🚀
10 |
11 |
12 |
13 | English | [简体中文 ]
14 |
15 |
16 |
17 | # it-tools
18 |
19 | > Help programers quickly solve problems.
20 | > To make life easy.
21 |
22 | Now this project including Regex Tool, Timestamp Converter, Color Box, Json Parser, Base64 Converter, Crontab Tool.
23 |
24 | ## Features
25 |
26 | - Regex Tool
27 | - Timestamp Converter
28 | - Color Box
29 | - JSON Parser
30 | - Base64 Converter
31 | - Crontab Tool
32 |
33 | ### Try It
34 | [Download](https://github.com/TsaiKoga/it-tools/releases)
35 |
36 | [Online Demo](https://tsaikoga.github.com/it-tools/web/index.html)
37 |
38 |
39 | ### Preview
40 |
41 | 
42 |
43 | ### Build Setup
44 |
45 | ``` bash
46 | # install dependencies
47 | npm install
48 |
49 | # serve with hot reload at localhost:9080
50 | npm run dev
51 |
52 | # build electron application for production
53 | npm run build
54 |
55 | # run unit & end-to-end tests
56 | npm test
57 |
58 |
59 | # lint all JS/Vue component files in `src/`
60 | npm run lint
61 |
62 | ```
63 |
64 | ### Donation
65 |
66 | If this project help you reduce time to develop, you can give me a cup of coffee :)
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 | Wechat Pay
78 | Ali Pay
79 | Paypal
80 |
81 |
82 |
83 |
84 | ---
85 |
86 | This project was generated with [electron-vue](https://github.com/SimulatedGREG/electron-vue)@[8fae476](https://github.com/SimulatedGREG/electron-vue/tree/8fae4763e9d225d3691b627e83b9e09b56f6c935) using [vue-cli](https://github.com/vuejs/vue-cli). Documentation about the original structure can be found [here](https://simulatedgreg.gitbooks.io/electron-vue/content/index.html).
87 |
--------------------------------------------------------------------------------
/README_CN.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | 这是由 Electron & Vue.js 编写的,为程序员服务的编程工具 🚀
10 |
11 |
12 |
13 | [ English] | 简体中文
14 |
15 |
16 |
17 | # it-tools
18 |
19 | > 旨在帮助程序员快速开发的小工具.
20 | > 让生活更加美好.
21 |
22 | 这个工具目前包括“正则表达式”、“时间戳转化”、“颜色盒子”、“Json转化”、“Base64转化“、“定时任务工具”
23 |
24 |
25 | ### 特点
26 |
27 | - 正则表达式
28 | - 时间戳转化
29 | - 颜色盒子
30 | - JSON 转化
31 | - Base64 转化
32 | - 定时任务
33 |
34 |
35 | ### 试一下
36 | [下载桌面应用](https://github.com/TsaiKoga/it-tools/releases)
37 |
38 | [在线演示](https://tsaikoga.github.com/it-tools/web/index.html)
39 |
40 |
41 | ### 预览
42 |
43 | 
44 |
45 | ### 构建步骤
46 |
47 | ``` bash
48 | # 安装依赖
49 | npm install
50 |
51 | # serve with hot reload at localhost:9080
52 | npm run dev
53 |
54 | # build electron application for production
55 | npm run build
56 |
57 | # run unit & end-to-end tests
58 | npm test
59 |
60 |
61 | # lint all JS/Vue component files in `src/`
62 | npm run lint
63 |
64 | ```
65 |
66 |
67 | ### 捐赠
68 |
69 |
70 |
71 | 如果觉您觉得项目对您有帮助,可否打赏我一杯咖啡喝:
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 | 微信
83 | 支付宝
84 | 贝宝
85 |
86 |
87 |
88 |
89 | 此项目由以下工具编写:
90 | [electron-vue](https://github.com/SimulatedGREG/electron-vue)@[8fae476](https://github.com/SimulatedGREG/electron-vue/tree/8fae4763e9d225d3691b627e83b9e09b56f6c935) using [vue-cli](https://github.com/vuejs/vue-cli). Documentation about the original structure can be found [here](https://simulatedgreg.gitbooks.io/electron-vue/content/index.html).
91 |
--------------------------------------------------------------------------------
/build/icons/256x256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TsaiKoga/it-tools/0df87d3c1e086106cc36f0cd0357812ea779aff2/build/icons/256x256.png
--------------------------------------------------------------------------------
/build/icons/icon.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TsaiKoga/it-tools/0df87d3c1e086106cc36f0cd0357812ea779aff2/build/icons/icon.icns
--------------------------------------------------------------------------------
/build/icons/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TsaiKoga/it-tools/0df87d3c1e086106cc36f0cd0357812ea779aff2/build/icons/icon.ico
--------------------------------------------------------------------------------
/dist/electron/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TsaiKoga/it-tools/0df87d3c1e086106cc36f0cd0357812ea779aff2/dist/electron/.gitkeep
--------------------------------------------------------------------------------
/dist/web/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TsaiKoga/it-tools/0df87d3c1e086106cc36f0cd0357812ea779aff2/dist/web/.gitkeep
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "IT-Tools",
3 | "productName": "IT Tools",
4 | "version": "1.5.1",
5 | "author": "TsaiKoga ",
6 | "description": "Help programers quickly solve problem.To be a life saver.",
7 | "license": "Apache-2.0",
8 | "main": "./dist/electron/main.js",
9 | "scripts": {
10 | "build": "node .electron-vue/build.js",
11 | "build:darwin": "cross-env BUILD_TARGET=darwin node .electron-vue/build.js",
12 | "build:linux": "cross-env BUILD_TARGET=linux node .electron-vue/build.js",
13 | "build:mas": "cross-env BUILD_TARGET=mas node .electron-vue/build.js",
14 | "build:win32": "cross-env BUILD_TARGET=win32 node .electron-vue/build.js",
15 | "build:clean": "cross-env BUILD_TARGET=clean node .electron-vue/build.js",
16 | "build:web": "cross-env BUILD_TARGET=web node .electron-vue/build.js",
17 | "dev": "node .electron-vue/dev-runner.js",
18 | "e2e": "npm run pack && mocha test/e2e",
19 | "lint": "eslint --ext .js,.vue -f ./node_modules/eslint-friendly-formatter src test",
20 | "lint:fix": "eslint --ext .js,.vue -f ./node_modules/eslint-friendly-formatter --fix src test",
21 | "pack": "npm run pack:main && npm run pack:renderer",
22 | "pack:main": "cross-env NODE_ENV=production webpack --progress --colors --config .electron-vue/webpack.main.config.js",
23 | "pack:renderer": "cross-env NODE_ENV=production webpack --progress --colors --config .electron-vue/webpack.renderer.config.js",
24 | "test": "npm run unit && npm run e2e",
25 | "unit": "karma start test/unit/karma.conf.js",
26 | "postinstall": "npm run lint:fix"
27 | },
28 | "dependencies": {
29 | "cron-parser": "^2.13.0",
30 | "moment": "^2.24.0",
31 | "node-sass": "^4.12.0",
32 | "vue": "^2.5.16",
33 | "vue-clipboard2": "^0.3.0",
34 | "vue-electron": "^1.0.6",
35 | "vue-i18n": "^8.10.0",
36 | "vue-router": "^3.0.1",
37 | "vuex": "^3.0.1",
38 | "vuex-electron": "^1.0.0"
39 | },
40 | "devDependencies": {
41 | "ajv": "^6.5.0",
42 | "babel-core": "^6.26.3",
43 | "babel-eslint": "^8.2.3",
44 | "babel-loader": "^7.1.4",
45 | "babel-plugin-istanbul": "^5.1.1",
46 | "babel-plugin-transform-runtime": "^6.23.0",
47 | "babel-preset-env": "^1.7.0",
48 | "babel-preset-stage-0": "^6.24.1",
49 | "babel-register": "^6.26.0",
50 | "babili-webpack-plugin": "^0.1.2",
51 | "cfonts": "^2.1.2",
52 | "chai": "^4.1.2",
53 | "chalk": "^2.4.1",
54 | "copy-webpack-plugin": "^4.5.1",
55 | "cross-env": "^5.1.6",
56 | "css-loader": "^0.28.11",
57 | "del": "^3.0.0",
58 | "devtron": "^1.4.0",
59 | "electron": "^2.0.4",
60 | "electron-debug": "^1.5.0",
61 | "electron-devtools-installer": "^2.2.4",
62 | "electron-packager": "^13.1.0",
63 | "electron-rebuild": "^1.8.1",
64 | "eslint": "^4.19.1",
65 | "eslint-config-standard": "^11.0.0",
66 | "eslint-friendly-formatter": "^4.0.1",
67 | "eslint-loader": "^2.0.0",
68 | "eslint-plugin-html": "^4.0.3",
69 | "eslint-plugin-import": "^2.12.0",
70 | "eslint-plugin-node": "^6.0.1",
71 | "eslint-plugin-promise": "^3.8.0",
72 | "eslint-plugin-standard": "^3.1.0",
73 | "file-loader": "^1.1.11",
74 | "html-webpack-plugin": "^3.2.0",
75 | "inject-loader": "^4.0.1",
76 | "karma": "^4.3.0",
77 | "karma-chai": "^0.1.0",
78 | "karma-coverage": "^1.1.2",
79 | "karma-electron": "^6.0.0",
80 | "karma-mocha": "^1.3.0",
81 | "karma-sourcemap-loader": "^0.3.7",
82 | "karma-spec-reporter": "^0.0.32",
83 | "karma-webpack": "^3.0.0",
84 | "mini-css-extract-plugin": "0.4.0",
85 | "mocha": "^5.2.0",
86 | "multispinner": "^0.2.1",
87 | "node-loader": "^0.6.0",
88 | "require-dir": "^1.0.0",
89 | "sass-loader": "^7.0.3",
90 | "spectron": "^3.8.0",
91 | "style-loader": "^0.21.0",
92 | "url-loader": "^1.0.1",
93 | "vue-html-loader": "^1.2.4",
94 | "vue-loader": "^15.2.4",
95 | "vue-style-loader": "^4.1.0",
96 | "vue-template-compiler": "^2.5.16",
97 | "webpack": "^4.15.1",
98 | "webpack-cli": "^3.0.8",
99 | "webpack-dev-server": "^3.1.4",
100 | "webpack-hot-middleware": "^2.22.2",
101 | "webpack-merge": "^4.1.3"
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/src/index.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | it-tools
6 | <% if (htmlWebpackPlugin.options.nodeModules) { %>
7 |
8 |
11 | <% } %>
12 |
13 |
14 |
15 |
16 | <% if (!process.browser) { %>
17 |
20 | <% } %>
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/main/index.dev.js:
--------------------------------------------------------------------------------
1 | /**
2 | * This file is used specifically and only for development. It installs
3 | * `electron-debug` & `vue-devtools`. There shouldn't be any need to
4 | * modify this file, but it can be used to extend your development
5 | * environment.
6 | */
7 |
8 | /* eslint-disable */
9 |
10 | // Install `electron-debug` with `devtron`
11 | require('electron-debug')({ showDevTools: true })
12 |
13 | // Install `vue-devtools`
14 | require('electron').app.on('ready', () => {
15 | let installExtension = require('electron-devtools-installer')
16 | installExtension.default(installExtension.VUEJS_DEVTOOLS)
17 | .then(() => {})
18 | .catch(err => {
19 | console.log('Unable to install `vue-devtools`: \n', err)
20 | })
21 | })
22 |
23 | // Require `main` process to boot app
24 | require('./index')
--------------------------------------------------------------------------------
/src/main/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | import { app, BrowserWindow, Menu } from 'electron'
4 |
5 | /**
6 | * Set `__static` path to static files in production
7 | * https://simulatedgreg.gitbooks.io/electron-vue/content/en/using-static-assets.html
8 | */
9 | if (process.env.NODE_ENV !== 'development') {
10 | global.__static = require('path').join(__dirname, '/static').replace(/\\/g, '\\\\')
11 | }
12 |
13 | let mainWindow
14 | const winURL = process.env.NODE_ENV === 'development'
15 | ? `http://localhost:9080`
16 | : `file://${__dirname}/index.html`
17 |
18 | function createWindow () {
19 | /**
20 | * Initial window options
21 | */
22 | mainWindow = new BrowserWindow({
23 | height: 650,
24 | width: 1100,
25 | 'minHeight': 650,
26 | 'minWidth': 1100,
27 | useContentSize: true,
28 | titleBarStyle: 'hiddenInset'
29 | })
30 |
31 | mainWindow.loadURL(winURL)
32 |
33 | mainWindow.on('closed', () => {
34 | mainWindow = null
35 | })
36 |
37 | const template = [{
38 | label: 'Application',
39 | submenu: [
40 | { label: 'About Application', selector: 'orderFrontStandardAboutPanel:' },
41 | { type: 'separator' },
42 | { label: 'Quit', accelerator: 'Command+Q', click: function () { app.quit() } }
43 | ]}, {
44 | label: 'Edit',
45 | submenu: [
46 | { label: 'Undo', accelerator: 'CmdOrCtrl+Z', selector: 'undo:' },
47 | { label: 'Redo', accelerator: 'Shift+CmdOrCtrl+Z', selector: 'redo:' },
48 | { type: 'separator' },
49 | { label: 'Cut', accelerator: 'CmdOrCtrl+X', selector: 'cut:' },
50 | { label: 'Copy', accelerator: 'CmdOrCtrl+C', selector: 'copy:' },
51 | { label: 'Paste', accelerator: 'CmdOrCtrl+V', selector: 'paste:' },
52 | { label: 'Select All', accelerator: 'CmdOrCtrl+A', selector: 'selectAll:' }
53 | ]}
54 | ]
55 |
56 | Menu.setApplicationMenu(Menu.buildFromTemplate(template))
57 | }
58 |
59 | app.on('ready', createWindow)
60 |
61 | app.on('window-all-closed', () => {
62 | if (process.platform !== 'darwin') {
63 | app.quit()
64 | }
65 | })
66 |
67 | app.on('activate', () => {
68 | if (mainWindow === null) {
69 | createWindow()
70 | }
71 | })
72 |
--------------------------------------------------------------------------------
/src/renderer/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
27 |
28 |
43 |
--------------------------------------------------------------------------------
/src/renderer/Sidebar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
35 |
36 |
68 |
69 |
70 |
71 |
96 |
97 |
178 |
--------------------------------------------------------------------------------
/src/renderer/Tabs.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
38 |
39 |
40 |
66 |
--------------------------------------------------------------------------------
/src/renderer/assets/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TsaiKoga/it-tools/0df87d3c1e086106cc36f0cd0357812ea779aff2/src/renderer/assets/.gitkeep
--------------------------------------------------------------------------------
/src/renderer/assets/IT-Tools-preview.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TsaiKoga/it-tools/0df87d3c1e086106cc36f0cd0357812ea779aff2/src/renderer/assets/IT-Tools-preview.gif
--------------------------------------------------------------------------------
/src/renderer/assets/alipay.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TsaiKoga/it-tools/0df87d3c1e086106cc36f0cd0357812ea779aff2/src/renderer/assets/alipay.gif
--------------------------------------------------------------------------------
/src/renderer/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TsaiKoga/it-tools/0df87d3c1e086106cc36f0cd0357812ea779aff2/src/renderer/assets/logo.png
--------------------------------------------------------------------------------
/src/renderer/assets/wechatpay.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TsaiKoga/it-tools/0df87d3c1e086106cc36f0cd0357812ea779aff2/src/renderer/assets/wechatpay.gif
--------------------------------------------------------------------------------
/src/renderer/components/ColorBoxPage.vue:
--------------------------------------------------------------------------------
1 |
2 |
96 |
97 |
98 |
147 |
148 |
406 |
--------------------------------------------------------------------------------
/src/renderer/components/CronPage.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | {{ $t('cron.yourCronExp') }}:
8 |
9 |
10 |
11 |
12 |
25 |
26 |
27 |
28 |
29 |
{{ $t('cron.nextExec') }}
30 |
31 |
{{ $t('cron.times') }}:
32 |
33 | {{ i + 1 }}: {{ item }}
34 | {{ cronResult['content'] }}
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | {{ term['symbol'] }}
43 | {{ term['explaination'] }}
44 |
45 |
46 |
47 |
48 | {{ cronResult['content'] }}
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
123 |
124 |
312 |
--------------------------------------------------------------------------------
/src/renderer/components/CronPage/CronHelp.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | {{ $t('cronHelp.minute') }}
11 | {{ $t('cronHelp.hour') }}
12 | {{ $t('cronHelp.day') }}
13 | {{ $t('cronHelp.month') }}
14 | {{ $t('cronHelp.day') }}
15 |
16 |
17 |
18 | * {{ $t('cronHelp.anyValue') }}
19 | * {{ $t('cronHelp.anyValue') }}
20 | * {{ $t('cronHelp.anyValue') }}
21 | * {{ $t('cronHelp.anyValue') }}
22 | * {{ $t('cronHelp.anyValue') }}
23 |
24 |
25 | , {{ $t('cronHelp.valueListSeparator') }}
26 | , {{ $t('cronHelp.valueListSeparator') }}
27 | , {{ $t('cronHelp.valueListSeparator') }}
28 | , {{ $t('cronHelp.valueListSeparator') }}
29 | , {{ $t('cronHelp.valueListSeparator') }}
30 |
31 |
32 | - {{ $t('cronHelp.rangeOfValues') }}
33 | - {{ $t('cronHelp.rangeOfValues') }}
34 | - {{ $t('cronHelp.rangeOfValues') }}
35 | - {{ $t('cronHelp.rangeOfValues') }}
36 | - {{ $t('cronHelp.rangeOfValues') }}
37 |
38 |
39 | / {{ $t('cronHelp.stepValues') }}
40 | / {{ $t('cronHelp.stepValues') }}
41 | / {{ $t('cronHelp.stepValues') }}
42 | / {{ $t('cronHelp.stepValues') }}
43 | / {{ $t('cronHelp.stepValues') }}
44 |
45 |
46 | 0-59 {{ $t('cronHelp.allowedValues') }}
47 | 0-23 {{ $t('cronHelp.allowedValues') }}
48 | 1-31 {{ $t('cronHelp.allowedValues') }}
49 | 1-12 {{ $t('cronHelp.allowedValues') }}
50 | 0-6 {{ $t('cronHelp.allowedValues') }}
51 |
52 |
53 |
54 |
55 |
56 | JAN-DEC {{ $t('cronHelp.alternativeSingleValues') }}
57 | SUN-SAT {{ $t('cronHelp.alternativeSingleValues') }}
58 |
59 |
60 |
61 |
62 |
63 |
64 | * * * * * *
65 | - - - - - -
66 | | | | | | |
67 | | | | | | + {{ $t('cronHelp.year') }} [{{ $t('cronHelp.optional') }}]
68 | | | | | +----- {{ $t('cronHelp.dayOfWeek') }} (0 - 7) (Sunday=0 or 7)
69 | | | | +---------- {{ $t('cronHelp.month') }} (1 - 12)
70 | | | +--------------- {{ $t('cronHelp.dayOfMonth' )}} (1 - 31)
71 | | +-------------------- {{ $t('cronHelp.hour') }} (0 - 23)
72 | +------------------------- {{ $t('cronHelp.minute') }} (0 - 59)
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
85 |
86 |
136 |
--------------------------------------------------------------------------------
/src/renderer/components/Image64Page.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
{{ $t('image64.dragImgHere') }}
7 |
8 |
9 |
10 |
11 |
{{ $t('image64.copy') }}
12 |
{{ $t('image64.clean') }}
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
70 |
71 |
194 |
--------------------------------------------------------------------------------
/src/renderer/components/JsonPage.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
49 |
50 |
138 |
--------------------------------------------------------------------------------
/src/renderer/components/JsonPage/JsonResultHelp.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
{{ $t('json.toXML') }}
5 |
{{ $t('json.toJSON') }}
6 |
{{ $t('json.reset') }}
7 |
{{ $t('json.copy') }}
8 |
9 |
10 |
11 |
12 |
13 |
14 |
79 |
80 |
191 |
--------------------------------------------------------------------------------
/src/renderer/components/LandingPage.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
18 |
19 |
32 |
--------------------------------------------------------------------------------
/src/renderer/components/LandingPage/Welcome.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{ appName }}
6 |
7 |
8 |
9 |
10 |
11 |
20 |
21 |
89 |
--------------------------------------------------------------------------------
/src/renderer/components/RegexPage.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | {{ $t('regex.yourRegexExp') }}:
8 |
9 |
10 |
/
11 |
12 |
13 |
14 |
15 |
/
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | {{ $t('regex.yourTestStr') }}:
26 |
27 |
28 |
29 |
30 | {{ regexResult['content'] }}
31 |
32 |
33 |
34 |
35 |
36 |
40 |
41 |
42 | {{ contArray }}
43 | {{ cont }}
44 |
45 |
46 |
47 |
48 | {{ $t('regex.matchGroups') }}:
49 |
50 |
51 |
52 |
{{ $t('regex.matchGroup') }} {{ index + 1 }}:
53 |
54 | {{ i }}: {{ item }}
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 | {{ regexResult['content'] }}
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
132 |
133 |
358 |
--------------------------------------------------------------------------------
/src/renderer/components/RegexPage/RegexHelp.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
{{ $t('regexHelp.title') }}
5 |
6 |
7 |
8 |
9 |
10 | [abc] {{ $t('regexHelp.squareBracket') }}
11 |
12 |
13 |
14 | [^abc] {{ $t('regexHelp.squareNot') }}
15 |
16 |
17 |
18 | [a-z] {{ $t('regexHelp.squareAny') }}
19 |
20 |
21 |
22 | [a-zA-Z] {{ $t('regexHelp.squareRange') }}
23 |
24 |
25 |
26 | ^ {{ $t('regexHelp.startOfLine') }}
27 |
28 |
29 |
30 | $ {{ $t('regexHelp.endOfLine') }}
31 |
32 |
33 |
34 | \A {{ $t('regexHelp.startOfStr') }}
35 |
36 |
37 |
38 | \z {{ $t('regexHelp.endOfStr') }}
39 |
40 |
41 |
42 | . {{ $t('regexHelp.anyChar') }}
43 |
44 |
45 |
46 | \s {{ $t('regexHelp.anyWSpace') }}
47 |
48 |
49 |
50 | \S {{ $t('regexHelp.anyNWSpace') }}
51 |
52 |
53 |
54 | \d {{ $t('regexHelp.anyDigit') }}
55 |
56 |
57 |
58 | a.+? {{ $t('regexHelp.stopAtFirstA') }}
59 |
60 |
61 |
62 | (?=Tom) {{ $t('regexHelp.matchBeforeTom') }}
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 | \D {{ $t('regexHelp.anyNDigit') }}
72 |
73 |
74 |
75 | \w {{ $t('regexHelp.anyWordChar') }}
76 |
77 |
78 |
79 | \W {{ $t('regexHelp.anyNWordChar') }}
80 |
81 |
82 |
83 | \b {{ $t('regexHelp.anyWordB') }}
84 |
85 |
86 |
87 | (...) {{ $t('regexHelp.capEnclosed') }}
88 |
89 |
90 |
91 | (a|b) {{ $t('regexHelp.or') }}
92 |
93 |
94 |
95 | a? {{ $t('regexHelp.zeroOne') }}
96 |
97 |
98 |
99 | a* {{ $t('regexHelp.moreThanZero') }}
100 |
101 |
102 |
103 | a+ {{ $t('regexHelp.moreThanOne') }}
104 |
105 |
106 |
107 | a{3} {{ $t('regexHelp.exactly3') }}
108 |
109 |
110 |
111 | a{3,} {{ $t('regexHelp.moreThan3') }}
112 |
113 |
114 |
115 | a{3,6} {{ $t('regexHelp.between') }}
116 |
117 |
118 |
119 | (?:Tom) {{ $t('regexHelp.matchTom') }}
120 |
121 |
122 |
123 | (?<=Tom) {{ $t('regexHelp.matchBehindTom') }}
124 |
125 |
126 |
127 |
128 |
129 |
130 |
{{ $t('regexHelp.options') }}:
131 |
132 | i
133 | {{ $t('regexHelp.caseI') }}
134 | u
135 | {{ $t('regexHelp.unicode') }}
136 |
137 | s
138 | {{ $t('regexHelp.newLine') }}
139 | y
140 | {{ $t('regexHelp.indexMatch') }}
141 |
142 |
143 |
144 |
145 |
146 |
147 |
152 |
153 |
193 |
--------------------------------------------------------------------------------
/src/renderer/components/TimestampPage.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
13 |
14 |
15 |
16 |
20 |
21 |
22 |
23 |
24 | {{ datetimeResult || $t('timestamp.datetimeResult') }}
25 |
26 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
40 |
41 | {{ timestampResult || $t('timestamp.timestampResult') }}
42 |
43 |
44 |
45 |
46 |
50 |
51 |
52 |
53 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
129 |
130 |
353 |
--------------------------------------------------------------------------------
/src/renderer/components/TimestampPage/TstampHelp.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Swift
10 |
11 | NSDate ().timeIntervalSince1970
12 |
13 |
14 |
15 |
16 | Go
17 |
18 | import ("time" )
19 | int32 (time .Now ().Unix ())
20 |
21 |
22 |
23 |
24 | Java
25 |
26 | (int ) (System .currentTimeMillis () / 1000 )
27 |
28 |
29 |
30 |
31 | (int ) (DateTime .now ().getMillis () / 1000 )
32 |
33 |
34 |
35 |
36 | Javascript
37 |
38 | Math .round (new Date () / 1000 )
39 |
40 |
41 |
42 |
43 | Objective-C
44 |
45 | [[NSDate date] timeIntervalSince1970 ]
46 |
47 |
48 |
49 |
50 | MySQL
51 |
52 | SELECT unix_timestamp (now ())
53 |
54 |
55 |
56 |
57 | PHP
58 |
59 | time ()
60 |
61 |
62 |
63 |
64 | Carbon ::now ()->timestamp
65 |
66 |
67 |
68 |
69 | Python
70 |
71 | import time
72 | time .time ()
73 |
74 |
75 |
76 |
77 | Ruby
78 |
79 | Time .now.to_i
80 |
81 |
82 |
83 |
84 | Shell
85 |
86 | date +%s
87 |
88 |
89 |
90 |
91 | Groovy
92 |
93 | (new Date ().time / 1000 ).intValue ()
94 |
95 |
96 |
97 |
98 | Lua
99 |
100 | os. time()
101 |
102 |
103 |
104 |
105 | .NET/C#
106 |
107 | (DateTime .Now.ToUniversalTime ().Ticks - 621355968000000000 ) / 10000000
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
121 |
122 |
179 |
--------------------------------------------------------------------------------
/src/renderer/i18n.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import VueI18n from 'vue-i18n'
3 | import { messages } from './lang/messages'
4 |
5 | Vue.use(VueI18n)
6 | if (!window.localStorage.getItem('locale')) {
7 | window.localStorage.setItem('locale', 'en')
8 | }
9 |
10 | const i18n = new VueI18n({
11 | locale: window.localStorage.getItem('locale'),
12 | messages: messages
13 | })
14 |
15 | export default i18n
16 |
--------------------------------------------------------------------------------
/src/renderer/lang/cn.js:
--------------------------------------------------------------------------------
1 | export const cn = {
2 | tabs: {
3 | home: '首页',
4 | help: '帮助'
5 | },
6 | // Sidebar
7 | sidebar: {
8 | regexTool: '正则表达式工具',
9 | timestampConverter: '时间戳转化',
10 | colorBox: '颜色盒子',
11 | jsonParser: 'JSON 转化',
12 | base64Converter: 'Base64 转化',
13 | cronTool: '定时任务工具',
14 | regex: '正',
15 | time: '时',
16 | color: '色',
17 | json: '键',
18 | image64: '图',
19 | cron: '定'
20 | },
21 | // Regex Tool
22 | regex: {
23 | yourRegexExp: '您的正则表达式',
24 | yourTestStr: '需要测试的字符串',
25 | clearFields: '清除所有输入',
26 | matchResult: '匹配结果',
27 | noMatches: '没有匹配到内容 ...',
28 | matchGroups: '匹配所有分组',
29 | matchGroup: '匹配分组',
30 | cleanFields: '清除输入框',
31 | heresResult: '这里显示结果。',
32 | uHaveAnUnmatchedPats: '您有一个括号缺少一边。',
33 | expError: '表达式错误',
34 | invalidOpt: '非法选项'
35 | },
36 | regexHelp: {
37 | title: '正则表达式速查表',
38 | squareBracket: '其中一个字符: a, b, 或 c',
39 | squareNot: '任意字符除了: a, b, 或 c',
40 | squareAny: 'a 到 z 中的任意字符',
41 | squareRange: 'a 到 z 或 A 到 Z 中的任意字符',
42 | startOfLine: '行开始符',
43 | endOfLine: '行结束符',
44 | startOfStr: '字符串开始符',
45 | endOfStr: '字符串结束符',
46 | anyChar: '任意一个字符',
47 | anyWSpace: '任意空白字符',
48 | anyNWSpace: '任意非空白字符',
49 | anyDigit: '任意数字',
50 | stopAtFirstA: '非贪婪:只在第一个 a 停止',
51 | matchBeforeTom: '匹配 Tom 前面的字符',
52 |
53 | anyNDigit: '任意非数字',
54 | anyWordChar: '任何词语字符 (字母, 数字, 下划线)',
55 | anyNWordChar: '任意非词语字符',
56 | anyWordB: '任意词语分界符',
57 | capEnclosed: '所有被括号包住的内容',
58 | or: 'a 或者 b',
59 | zeroOne: '0 或者 1 个 a',
60 | moreThanZero: '大于 0 个 a',
61 | moreThanOne: '大于 1 个 a',
62 | exactly3: '正好 3 个 a',
63 | moreThan3: '大于 3 个 a',
64 | between: '3 到 6 个 a',
65 | matchTom: '匹配 Tom',
66 | matchBehindTom: '匹配 Tom 后面的字符',
67 |
68 | options: '选项',
69 | caseI: '不区分大小写',
70 | unicode: '将规则做为 Unicode 序列',
71 | newLine: '允许用 . 匹配新行',
72 | indexMatch: '只匹配目标字符串中此正则表达式的 lastIndex 属性所指示的索引(不尝试匹配任何后续索引)'
73 | },
74 | // Timestamp Converter
75 | timestamp: {
76 | unitTimeChosen: '选择时间单位',
77 | sec: '秒',
78 | microSec: '毫秒',
79 | reset: '重置',
80 | inputTimestamp: '输入时间戳',
81 | datetimeResult: '日期时间结果',
82 | timestampResult: '时间戳结果',
83 | inputDatetime: '输入日期时间'
84 | },
85 | // Color box
86 | color: {
87 | currentColor: '当前颜色',
88 | copied: '已复制',
89 | inputHex: '输入十六进制',
90 | inputRGB: '输入 RGB',
91 | inputHSL: '输入 HSL'
92 | },
93 | // Json Parser
94 | json: {
95 | error: '错误',
96 | toXML: '转为 XML',
97 | toJSON: '转为 JSON',
98 | reset: '重置',
99 | copy: '复制',
100 | seems: '貌似',
101 | missing: '没有 ',
102 | missingComma: '没有逗号',
103 | missingKV: '在逗号后面没有键值对.',
104 | missingElemInArray: '数组中缺少元素',
105 | missingCommaInArray: '数组中缺少逗号',
106 | undefinedVal: '键值对的值未定义',
107 | undefinedKey: '键值对的键未定义.',
108 | near: '错误发生在',
109 | notBool: '错误: 非 Boolean 值',
110 | notNum: '非数值number...',
111 | notNull: '错误:非 null 值',
112 | moreBehind: '后面多了字符',
113 | inputJsonTip: '此处输入 JSON 字符串\n\n注意: 键值对要用双引号括起来'
114 | },
115 | // Image Converter
116 | image64: {
117 | copy: '复制',
118 | clean: '清除',
119 | dragImgHere: '拖动 😺 图片到此处,Base64 👉',
120 | inputBase64Here: '您也可以在这里输入 Base64 码,图片将会显示 👈'
121 | },
122 | cron: {
123 | yourCronExp: '您的定时任务表达式',
124 | heresResult: '这里显示结果',
125 | expError: '表达式错误',
126 | nextExec: '接下来执行如下的',
127 | times: '次',
128 | every: '每',
129 | at: '在',
130 | in: '在',
131 | on: '在',
132 | from: '从',
133 | through: '到',
134 | and: '和',
135 | of: '的'
136 | },
137 | cronHelp: {
138 | minute: '分钟',
139 | hour: '小时',
140 | day: '天',
141 | month: '月',
142 | year: '年',
143 | week: '周',
144 | dayOfWeekUnit: '周[按周区分的天]',
145 | dayOfMonthUnit: '号[按月区分的天]',
146 | dayOfMonth: '号',
147 | dayOfWeek: '周',
148 | sunday: '周日',
149 | monday: '周一',
150 | tuesday: '周二',
151 | wednesday: '周三',
152 | thursday: '周四',
153 | friday: '周五',
154 | saturday: '周六',
155 | yearly: '每年',
156 | annually: '每年一次',
157 | monthly: '每月',
158 | daily: '每天',
159 | hourly: '每小时',
160 | afterReboot: '重启后',
161 | optional: '可选',
162 | anyValue: '任一值',
163 | valueListSeparator: '分隔开的值',
164 | rangeOfValues: '范围内的值',
165 | stepValues: '阶步值',
166 | allowedValues: '允许的值',
167 | alternativeSingleValues: '可变的值',
168 | nonStandard: '非标准的',
169 | notWorkEveryCron: '并非所有定时任务都能生效',
170 | expNotComplete: '表达式不完善'
171 | }
172 | }
173 |
--------------------------------------------------------------------------------
/src/renderer/lang/en.js:
--------------------------------------------------------------------------------
1 | export const en = {
2 | tabs: {
3 | home: 'Home',
4 | help: 'Help'
5 | },
6 | // Sidebar
7 | sidebar: {
8 | regexTool: 'Regex Tool',
9 | timestampConverter: 'Timestamp Converter',
10 | colorBox: 'Color Box',
11 | jsonParser: 'Json Parser',
12 | base64Converter: 'Base64 Converter',
13 | cronTool: 'Crontab Tool',
14 | regex: 'Regex',
15 | time: 'Time',
16 | color: 'Color',
17 | json: 'Json',
18 | image64: 'Image',
19 | cron: 'Cron'
20 | },
21 | // Regex Tool
22 | regex: {
23 | yourRegexExp: 'Your regular expression',
24 | yourTestStr: 'Your test string',
25 | clearFields: 'Clear Fields',
26 | matchResult: 'Match Result',
27 | noMatches: 'No matches ...',
28 | matchGroups: 'Match Groups',
29 | matchGroup: 'Match Group',
30 | cleanFields: 'Clean Fields',
31 | heresResult: 'Here\'s result.',
32 | uHaveAnUnmatchedPats: 'You have an unmatched parenthesis.',
33 | expError: 'Expression Error',
34 | invalidOpt: 'Invalid Option'
35 | },
36 | regexHelp: {
37 | title: 'Regex quick reference',
38 | squareBracket: 'A single character of: a, b, or c',
39 | squareNot: 'Any single character except: a, b, or c',
40 | squareAny: 'Any single character in the range a-z',
41 | squareRange: 'Any single character in the range a-z or A-Z',
42 | startOfLine: 'Start of line',
43 | endOfLine: 'End of line',
44 | startOfStr: 'Start of string',
45 | endOfStr: 'End of string',
46 | anyChar: 'Any single character',
47 | anyWSpace: 'Any whitespace character',
48 | anyNWSpace: 'Any non-whitespace character',
49 | anyDigit: 'Any digit',
50 | stopAtFirstA: 'Not greedy: Stop at first a',
51 | matchBeforeTom: 'Match char before Tom',
52 |
53 | anyNDigit: 'Any non-digit',
54 | anyWordChar: 'Any word character (letter, number, underscore)',
55 | anyNWordChar: 'Any non-word character',
56 | anyWordB: 'Any word boundary',
57 | capEnclosed: 'Capture everything enclosed',
58 | or: 'a or b',
59 | zeroOne: 'Zero or one of a',
60 | moreThanZero: 'Zero or more of a',
61 | moreThanOne: 'One or more of a',
62 | exactly3: 'Exactly 3 of a',
63 | moreThan3: '3 or more of a',
64 | between: 'Between 3 and 6 of a',
65 | matchTom: 'Only match Tom',
66 | matchBehindTom: 'Match char behind Tom',
67 |
68 | options: 'Options',
69 | caseI: 'case insensitive',
70 | unicode: 'treat pattern as a sequence of Unicode code points',
71 | newLine: 'allows . to match newlines',
72 | indexMatch: 'matches only from the index indicated by the lastIndex property of this regular expression in the target string (and does not attempt to match from any later indexes)'
73 | },
74 | // Timestamp Converter
75 | timestamp: {
76 | unitTimeChosen: 'Choose the unit of time',
77 | sec: 'Second',
78 | microSec: 'Micro Second',
79 | reset: 'Reset',
80 | inputTimestamp: 'Input timestamp',
81 | datetimeResult: 'Datetime Result',
82 | timestampResult: 'Timestamp Result',
83 | inputDatetime: 'Input Datetime'
84 | },
85 | // Color box
86 | color: {
87 | currentColor: 'Current Color',
88 | copied: 'Copied',
89 | inputHex: 'Input Hex',
90 | inputRGB: 'Input RGB',
91 | inputHSL: 'Input HSL'
92 | },
93 | // Json Parser
94 | json: {
95 | error: 'Error',
96 | toXML: 'TO XML',
97 | toJSON: 'TO JSON',
98 | reset: 'Reset',
99 | copy: 'Copy',
100 | ps: 'PS:The Key Value must be enclosed in double quotation marks.',
101 | seems: 'It seems that ',
102 | missing: 'missing',
103 | missingComma: 'missing comma',
104 | missingKV: 'missing key-value after comma.',
105 | missingElemInArray: 'missing element in array.',
106 | missingCommaInArray: 'missing comma in array.',
107 | undefinedVal: 'the value is undefined.',
108 | undefinedKey: 'the Key is undefined.',
109 | near: 'This error occured near',
110 | notBool: 'Error: It\'s not Boolean',
111 | notNull: 'Error: It\'s not null',
112 | notNum: 'it\'s not number...',
113 | moreBehind: 'More character in the end',
114 | inputJsonTip: 'Input your Json here.\n\nPS:The Key Value must be enclosed in double quotation marks.'
115 | },
116 | // Image Converter
117 | image64: {
118 | copy: 'COPY',
119 | clean: 'CLEAN',
120 | dragImgHere: 'Drag your 😺 image here. Base64 👉',
121 | inputBase64Here: 'You can input Base64 code here, and the image will be shown 👈.'
122 | },
123 | // crontab
124 | cron: {
125 | yourCronExp: 'Your Crontab expression',
126 | heresResult: 'Here\'s result.',
127 | expError: 'Expression error.',
128 | nextExec: 'Execute like as follow next ',
129 | times: 'times',
130 | every: 'every',
131 | at: 'At',
132 | in: 'In',
133 | on: 'On',
134 | from: 'from',
135 | through: 'through',
136 | and: 'and',
137 | of: 'of'
138 | },
139 | cronHelp: {
140 | minute: 'minute',
141 | hour: 'hour',
142 | day: 'day',
143 | month: 'month',
144 | year: 'year',
145 | week: 'week',
146 | optional: 'optional',
147 | dayOfWeekUnit: 'day-of-month',
148 | dayOfMonthUnit: 'day-of-month',
149 | dayOfMonth: 'day-of-month',
150 | dayOfWeek: 'day-of-week',
151 | sunday: 'Sunday',
152 | monday: 'Monday',
153 | tuesday: 'Tuesday',
154 | wednesday: 'Wensday',
155 | thursday: 'Thursday',
156 | friday: 'Friday',
157 | saturday: 'Saturday',
158 | yearly: 'Yearly',
159 | annually: 'Annually',
160 | monthly: 'Monthly',
161 | daily: 'Daily',
162 | hourly: 'Hourly',
163 | afterReboot: 'After rebooting',
164 | anyValue: 'any value',
165 | valueListSeparator: 'value list separator',
166 | rangeOfValues: 'range of values',
167 | stepValues: 'step values',
168 | allowedValues: 'allowed values',
169 | alternativeSingleValues: 'alternative single values',
170 | nonStandard: 'non-standard',
171 | notWorkEveryCron: 'May not work with every cron',
172 | expNotComplete: 'The expression is not completed'
173 | }
174 | }
175 |
--------------------------------------------------------------------------------
/src/renderer/lang/messages.js:
--------------------------------------------------------------------------------
1 | import { cn } from './cn'
2 | import { en } from './en'
3 |
4 | export const messages = {
5 | en: en,
6 | cn: cn
7 | }
8 |
--------------------------------------------------------------------------------
/src/renderer/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import VueClipboard from 'vue-clipboard2'
3 |
4 | import App from './App'
5 | import router from './router'
6 | import store from './store'
7 | import i18n from './i18n'
8 |
9 | if (!process.env.IS_WEB) Vue.use(require('vue-electron'))
10 | Vue.config.productionTip = false
11 | Vue.use(VueClipboard)
12 |
13 | /* eslint-disable no-new */
14 | new Vue({
15 | components: { App },
16 | router,
17 | store,
18 | i18n,
19 | template: ' '
20 | }).$mount('#app')
21 |
--------------------------------------------------------------------------------
/src/renderer/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Router from 'vue-router'
3 |
4 | Vue.use(Router)
5 |
6 | export default new Router({
7 | routes: [
8 | {
9 | path: '/',
10 | name: 'landing-page',
11 | component: require('@/components/LandingPage').default
12 | },
13 | {
14 | path: '/regex-page',
15 | name: 'regex-page',
16 | component: require('@/components/RegexPage').default
17 | },
18 | {
19 | path: '/timestamp-page',
20 | name: 'timestamp-page',
21 | component: require('@/components/TimestampPage').default
22 | },
23 | {
24 | path: '/color-box-page',
25 | name: 'color-box-page',
26 | component: require('@/components/ColorBoxPage').default
27 | },
28 | {
29 | path: '/json-page',
30 | name: 'json-page',
31 | component: require('@/components/JsonPage').default
32 | },
33 | {
34 | path: '/image64-page',
35 | name: 'image64-page',
36 | component: require('@/components/Image64Page').default
37 | },
38 | {
39 | path: '/cron-page',
40 | name: 'cron-page',
41 | component: require('@/components/CronPage').default
42 | }
43 | ]
44 | })
45 |
--------------------------------------------------------------------------------
/src/renderer/store/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Vuex from 'vuex'
3 |
4 | // import { createPersistedState, createSharedMutations } from 'vuex-electron'
5 | // import { createPersistedState } from 'vuex-electron'
6 |
7 | import modules from './modules'
8 |
9 | Vue.use(Vuex)
10 |
11 | export default new Vuex.Store({
12 | modules,
13 | plugins: [
14 | // createPersistedState(),
15 | // createSharedMutations()
16 | // createPersistedState()
17 | ],
18 | strict: process.env.NODE_ENV !== 'production'
19 | })
20 |
--------------------------------------------------------------------------------
/src/renderer/store/modules/Color.js:
--------------------------------------------------------------------------------
1 | const state = {
2 | colorMatrix: [
3 | [{ hex: '#F9EBEA', rgb: '249,235,234', hsl: '6,54%,95%', anim: false, name: 'pomegranate' },
4 | { hex: '#F2D7D5', rgb: '242,215,213', hsl: '6,54%,89%', anim: false, name: 'pomegranate' },
5 | { hex: '#E6B0AA', rgb: '230,176,170', hsl: '6,54%,78%', anim: false, name: 'pomegranate' },
6 | { hex: '#D98880', rgb: '217,136,128', hsl: '6,54%,68%', anim: false, name: 'pomegranate' },
7 | { hex: '#CD6155', rgb: '205,97,85', hsl: '6,54%,57%', anim: false, name: 'pomegranate' },
8 | { hex: '#C0392B', rgb: '192,57,43', hsl: '6,63%,46%', anim: false, name: 'pomegranate' },
9 | { hex: '#A93226', rgb: '169,50,38', hsl: '6,63%,41%', anim: false, name: 'pomegranate' },
10 | { hex: '#922B21', rgb: '146,43,33', hsl: '6,63%,35%', anim: false, name: 'pomegranate' },
11 | { hex: '#7B241C', rgb: '123,36,28', hsl: '6,63%,29%', anim: false, name: 'pomegranate' },
12 | { hex: '#641E16', rgb: '100, 30, 22', hsl: '6, 63%, 24%', anim: false, name: 'pomegranate' }],
13 |
14 | [{ hex: '#FDEDEC', rgb: '253,237,236', hsl: '6,78%,96%', anim: false, name: 'alizarin' },
15 | { hex: '#FADBD8', rgb: '250,219,216', hsl: '6,78%,91%', anim: false, name: 'alizarin' },
16 | { hex: '#F5B7B1', rgb: '245,183,177', hsl: '6,78%,83%', anim: false, name: 'alizarin' },
17 | { hex: '#F1948A', rgb: '241,148,138', hsl: '6,78%,74%', anim: false, name: 'alizarin' },
18 | { hex: '#EC7063', rgb: '236,112,99', hsl: '6,78%,66%', anim: false, name: 'alizarin' },
19 | { hex: '#E74C3C', rgb: '231,76,60', hsl: '6,78%,57%', anim: false, name: 'alizarin' },
20 | { hex: '#CB4335', rgb: '203,67,53', hsl: '6,59%,50%', anim: false, name: 'alizarin' },
21 | { hex: '#B03A2E', rgb: '176,58,46', hsl: '6,59%,43%', anim: false, name: 'alizarin' },
22 | { hex: '#943126', rgb: '148,49,38', hsl: '6,59%,37%', anim: false, name: 'alizarin' },
23 | { hex: '#78281F', rgb: '120,40,31', hsl: '6,59%,30%', anim: false, name: 'alizarin' }],
24 |
25 | [{ hex: '#F5EEF8', rgb: '245, 238, 248', hsl: '283, 39%, 95%', anim: false, name: 'amethyst' },
26 | { hex: '#EBDEF0', rgb: '235, 222, 240', hsl: '283, 39%, 91%', anim: false, name: 'amethyst' },
27 | { hex: '#D7BDE2', rgb: '215, 189, 226', hsl: '283, 39%, 81%', anim: false, name: 'amethyst' },
28 | { hex: '#C39BD3', rgb: '195, 155, 211', hsl: '283, 39%, 72%', anim: false, name: 'amethyst' },
29 | { hex: '#AF7AC5', rgb: '175, 122, 197', hsl: '283, 39%, 63%', anim: false, name: 'amethyst' },
30 | { hex: '#9B59B6', rgb: '155, 89, 182', hsl: '283, 39%, 53%', anim: false, name: 'amethyst' },
31 | { hex: '#884EA0', rgb: '136, 78, 160', hsl: '283, 34%, 47%', anim: false, name: 'amethyst' },
32 | { hex: '#76448A', rgb: '118, 68, 138', hsl: '283, 34%, 40%', anim: false, name: 'amethyst' },
33 | { hex: '#633974', rgb: '99, 57, 116', hsl: '283, 34%, 34%', anim: false, name: 'amethyst' },
34 | { hex: '#512E5F', rgb: '81, 46, 95', hsl: '283, 34%, 28%', anim: false, name: 'amethyst' }],
35 |
36 | [{ hex: '#F4ECF7', rgb: '244, 236, 247', hsl: '282, 39%, 95%', anim: false, name: 'wisteria' },
37 | { hex: '#E8DAEF', rgb: '232, 218, 239', hsl: '282, 39%, 89%', anim: false, name: 'wisteria' },
38 | { hex: '#D2B4DE', rgb: '210, 180, 222', hsl: '282, 39%, 79%', anim: false, name: 'wisteria' },
39 | { hex: '#BB8FCE', rgb: '187, 143, 206', hsl: '282, 39%, 68%', anim: false, name: 'wisteria' },
40 | { hex: '#A569BD', rgb: '165, 105, 189', hsl: '282, 39%, 58%', anim: false, name: 'wisteria' },
41 | { hex: '#8E44AD', rgb: '142, 68, 173', hsl: '282, 44%, 47%', anim: false, name: 'wisteria' },
42 | { hex: '#7D3C98', rgb: '125, 60, 152', hsl: '282, 44%, 42%', anim: false, name: 'wisteria' },
43 | { hex: '#6C3483', rgb: '108, 52, 131', hsl: '282, 44%, 36%', anim: false, name: 'wisteria' },
44 | { hex: '#5B2C6F', rgb: '91, 44, 111', hsl: '282, 44%, 30%', anim: false, name: 'wisteria' },
45 | { hex: '#4A235A', rgb: '74, 35, 90', hsl: '282, 44%, 25%', anim: false, name: 'wisteria' }],
46 |
47 | [{ hex: '#EAF2F8', rgb: '234, 242, 248', hsl: '204, 51%, 94%', anim: false, name: 'belize hole' },
48 | { hex: '#D4E6F1', rgb: '212, 230, 241', hsl: '204, 51%, 89%', anim: false, name: 'belize hole' },
49 | { hex: '#A9CCE3', rgb: '169, 204, 227', hsl: '204, 51%, 78%', anim: false, name: 'belize hole' },
50 | { hex: '#7FB3D5', rgb: '127, 179, 213', hsl: '204, 51%, 67%', anim: false, name: 'belize hole' },
51 | { hex: '#5499C7', rgb: '84, 153, 199', hsl: '204, 51%, 55%', anim: false, name: 'belize hole' },
52 | { hex: '#2980B9', rgb: '41, 128, 185', hsl: '204, 64%, 44%', anim: false, name: 'belize hole' },
53 | { hex: '#2471A3', rgb: '36, 113, 163', hsl: '204, 64%, 39%', anim: false, name: 'belize hole' },
54 | { hex: '#1F618D', rgb: '31, 97, 141', hsl: '204, 64%, 34%', anim: false, name: 'belize hole' },
55 | { hex: '#1A5276', rgb: '26, 82, 118', hsl: '204, 64%, 28%', anim: false, name: 'belize hole' },
56 | { hex: '#154360', rgb: '21, 67, 96', hsl: '204, 64%, 23%', anim: false, name: 'belize hole' }],
57 |
58 | [{ hex: '#EBF5FB', rgb: '235, 245, 251', hsl: '204, 70%, 95%', anim: false, name: 'peter river' },
59 | { hex: '#D6EAF8', rgb: '214, 234, 248', hsl: '204, 70%, 91%', anim: false, name: 'peter river' },
60 | { hex: '#AED6F1', rgb: '174, 214, 241', hsl: '204, 70%, 81%', anim: false, name: 'peter river' },
61 | { hex: '#85C1E9', rgb: '133, 193, 233', hsl: '204, 70%, 72%', anim: false, name: 'peter river' },
62 | { hex: '#5DADE2', rgb: '93, 173, 226', hsl: '204, 70%, 63%', anim: false, name: 'peter river' },
63 | { hex: '#3498DB', rgb: '52, 152, 219', hsl: '204, 70%, 53%', anim: false, name: 'peter river' },
64 | { hex: '#2E86C1', rgb: '46, 134, 193', hsl: '204, 62%, 47%', anim: false, name: 'peter river' },
65 | { hex: '#2874A6', rgb: '40, 116, 166', hsl: '204, 62%, 40%', anim: false, name: 'peter river' },
66 | { hex: '#21618C', rgb: '33, 97, 140', hsl: '204, 62%, 34%', anim: false, name: 'peter river' },
67 | { hex: '#1B4F72', rgb: '27, 79, 114', hsl: '204, 62%, 28%', anim: false, name: 'peter river' }],
68 |
69 | [{ hex: '#E8F8F5', rgb: '232, 248, 245', hsl: '168, 55%, 94%', anim: false, name: 'turquoise' },
70 | { hex: '#D1F2EB', rgb: '209, 242, 235', hsl: '168, 55%, 88%', anim: false, name: 'turquoise' },
71 | { hex: '#A3E4D7', rgb: '163, 228, 215', hsl: '168, 55%, 77%', anim: false, name: 'turquoise' },
72 | { hex: '#76D7C4', rgb: '118, 215, 196', hsl: '168, 55%, 65%', anim: false, name: 'turquoise' },
73 | { hex: '#48C9B0', rgb: '72, 201, 176', hsl: '168, 55%, 54%', anim: false, name: 'turquoise' },
74 | { hex: '#1ABC9C', rgb: '26, 188, 156', hsl: '168, 76%, 42%', anim: false, name: 'turquoise' },
75 | { hex: '#17A589', rgb: '23, 165, 137', hsl: '168, 76%, 37%', anim: false, name: 'turquoise' },
76 | { hex: '#148F77', rgb: '20, 143, 119', hsl: '168, 76%, 32%', anim: false, name: 'turquoise' },
77 | { hex: '#117864', rgb: '17, 120, 100', hsl: '168, 76%, 27%', anim: false, name: 'turquoise' },
78 | { hex: '#0E6251', rgb: '14, 98, 81', hsl: '168, 76%, 22%', anim: false, name: 'turquoise' }],
79 |
80 | [{ hex: '#E8F6F3', rgb: '232, 246, 243', hsl: '168, 42%, 94%', anim: false, name: 'green sea' },
81 | { hex: '#D0ECE7', rgb: '208, 236, 231', hsl: '168, 42%, 87%', anim: false, name: 'green sea' },
82 | { hex: '#A2D9CE', rgb: '162, 217, 206', hsl: '168, 42%, 74%', anim: false, name: 'green sea' },
83 | { hex: '#73C6B6', rgb: '115, 198, 182', hsl: '168, 42%, 61%', anim: false, name: 'green sea' },
84 | { hex: '#45B39D', rgb: '69, 179, 157', hsl: '168, 45%, 49%', anim: false, name: 'green sea' },
85 | { hex: '#16A085', rgb: '22, 160, 133', hsl: '168, 76%, 36%', anim: false, name: 'green sea' },
86 | { hex: '#138D75', rgb: '19, 141, 117', hsl: '168, 76%, 31%', anim: false, name: 'green sea' },
87 | { hex: '#117A65', rgb: '17, 122, 101', hsl: '168, 76%, 27%', anim: false, name: 'green sea' },
88 | { hex: '#0E6655', rgb: '14, 102, 85', hsl: '168, 76%, 23%', anim: false, name: 'green sea' },
89 | { hex: '#0B5345', rgb: '11, 83, 69', hsl: '168, 76%, 19%', anim: false, name: 'green sea' }],
90 |
91 | [{ hex: '#E9F7EF', rgb: '233, 247, 239', hsl: '145, 45%, 94%', anim: false, name: 'nephritis' },
92 | { hex: '#D4EFDF', rgb: '212, 239, 223', hsl: '145, 45%, 88%', anim: false, name: 'nephritis' },
93 | { hex: '#A9DFBF', rgb: '169, 223, 191', hsl: '145, 45%, 77%', anim: false, name: 'nephritis' },
94 | { hex: '#7DCEA0', rgb: '125, 206, 160', hsl: '145, 45%, 65%', anim: false, name: 'nephritis' },
95 | { hex: '#52BE80', rgb: '82, 190, 128', hsl: '145, 45%, 53%', anim: false, name: 'nephritis' },
96 | { hex: '#27AE60', rgb: '39, 174, 96', hsl: '145, 63%, 42%', anim: false, name: 'nephritis' },
97 | { hex: '#229954', rgb: '34, 153, 84', hsl: '145, 63%, 37%', anim: false, name: 'nephritis' },
98 | { hex: '#1E8449', rgb: '30, 132, 73', hsl: '145, 63%, 32%', anim: false, name: 'nephritis' },
99 | { hex: '#196F3D', rgb: '25, 111, 61', hsl: '145, 63%, 27%', anim: false, name: 'nephritis' },
100 | { hex: '#145A32', rgb: '20, 90, 50', hsl: '145, 63%, 22%', anim: false, name: 'nephritis' }],
101 |
102 | [{ hex: '#EAFAF1', rgb: '234, 250, 241', hsl: '145, 61%, 95%', anim: false, name: 'emerald' },
103 | { hex: '#D5F5E3', rgb: '213, 245, 227', hsl: '145, 61%, 90%', anim: false, name: 'emerald' },
104 | { hex: '#ABEBC6', rgb: '171, 235, 198', hsl: '145, 61%, 80%', anim: false, name: 'emerald' },
105 | { hex: '#82E0AA', rgb: '130, 224, 170', hsl: '145, 61%, 69%', anim: false, name: 'emerald' },
106 | { hex: '#58D68D', rgb: '88, 214, 141', hsl: '145, 61%, 59%', anim: false, name: 'emerald' },
107 | { hex: '#2ECC71', rgb: '46, 204, 113', hsl: '145, 63%, 49%', anim: false, name: 'emerald' },
108 | { hex: '#28B463', rgb: '40, 180, 99', hsl: '145, 63%, 43%', anim: false, name: 'emerald' },
109 | { hex: '#239B56', rgb: '35, 155, 86', hsl: '145, 63%, 37%', anim: false, name: 'emerald' },
110 | { hex: '#1D8348', rgb: '29, 131, 72', hsl: '145, 63%, 31%', anim: false, name: 'emerald' },
111 | { hex: '#186A3B', rgb: '24, 106, 59', hsl: '145, 63%, 25%', anim: false, name: 'emerald' }],
112 |
113 | [{ hex: '#FEF9E7', rgb: '254, 249, 231', hsl: '48, 89%, 95%', anim: false, name: 'sunflower' },
114 | { hex: '#FCF3CF', rgb: '252, 243, 207', hsl: '48, 89%, 90%', anim: false, name: 'sunflower' },
115 | { hex: '#F9E79F', rgb: '249, 231, 159', hsl: '48, 89%, 80%', anim: false, name: 'sunflower' },
116 | { hex: '#F7DC6F', rgb: '247, 220, 111', hsl: '48, 89%, 70%', anim: false, name: 'sunflower' },
117 | { hex: '#F4D03F', rgb: '244, 208, 63', hsl: '48, 89%, 60%', anim: false, name: 'sunflower' },
118 | { hex: '#F1C40F', rgb: '241, 196, 15', hsl: '48, 89%, 50%', anim: false, name: 'sunflower' },
119 | { hex: '#D4AC0D', rgb: '212, 172, 13', hsl: '48, 88%, 44%', anim: false, name: 'sunflower' },
120 | { hex: '#B7950B', rgb: '183, 149, 11', hsl: '48, 88%, 38%', anim: false, name: 'sunflower' },
121 | { hex: '#9A7D0A', rgb: '154, 125, 10', hsl: '48, 88%, 32%', anim: false, name: 'sunflower' },
122 | { hex: '#7D6608', rgb: '125, 102, 8', hsl: '48, 88%, 26%', anim: false, name: 'sunflower' }],
123 |
124 | [{ hex: '#FEF5E7', rgb: '254, 245, 231', hsl: '37, 90%, 95%', anim: false, name: 'orange' },
125 | { hex: '#FDEBD0', rgb: '253, 235, 208', hsl: '37, 90%, 90%', anim: false, name: 'orange' },
126 | { hex: '#FAD7A0', rgb: '250, 215, 160', hsl: '37, 90%, 80%', anim: false, name: 'orange' },
127 | { hex: '#F8C471', rgb: '248, 196, 113', hsl: '37, 90%, 71%', anim: false, name: 'orange' },
128 | { hex: '#F5B041', rgb: '245, 176, 65', hsl: '37, 90%, 61%', anim: false, name: 'orange' },
129 | { hex: '#F39C12', rgb: '243, 156, 18', hsl: '37, 90%, 51%', anim: false, name: 'orange' },
130 | { hex: '#D68910', rgb: '214, 137, 16', hsl: '37, 86%, 45%', anim: false, name: 'orange' },
131 | { hex: '#B9770E', rgb: '185, 119, 14', hsl: '37, 86%, 39%', anim: false, name: 'orange' },
132 | { hex: '#9C640C', rgb: '156, 100, 12', hsl: '37, 86%, 33%', anim: false, name: 'orange' },
133 | { hex: '#7E5109', rgb: '126, 81, 9', hsl: '37, 86%, 27%', anim: false, name: 'orange' }],
134 |
135 | [{ hex: '#FDF2E9', rgb: '253, 242, 233', hsl: '28, 80%, 95%', anim: false, name: 'carrot' },
136 | { hex: '#FAE5D3', rgb: '250, 229, 211', hsl: '28, 80%, 90%', anim: false, name: 'carrot' },
137 | { hex: '#F5CBA7', rgb: '245, 203, 167', hsl: '28, 80%, 81%', anim: false, name: 'carrot' },
138 | { hex: '#F0B27A', rgb: '240, 178, 122', hsl: '28, 80%, 71%', anim: false, name: 'carrot' },
139 | { hex: '#EB984E', rgb: '235, 152, 78', hsl: '28, 80%, 61%', anim: false, name: 'carrot' },
140 | { hex: '#E67E22', rgb: '230, 126, 34', hsl: '28, 80%, 52%', anim: false, name: 'carrot' },
141 | { hex: '#CA6F1E', rgb: '202, 111, 30', hsl: '28, 74%, 46%', anim: false, name: 'carrot' },
142 | { hex: '#AF601A', rgb: '175, 96, 26', hsl: '28, 74%, 39%', anim: false, name: 'carrot' },
143 | { hex: '#935116', rgb: '147, 81, 22', hsl: '28, 74%, 33%', anim: false, name: 'carrot' },
144 | { hex: '#784212', rgb: '120, 66, 18', hsl: '28, 74%, 27%', anim: false, name: 'carrot' }],
145 |
146 | [{ hex: '#FBEEE6', rgb: '251, 238, 230', hsl: '24, 71%, 94%', anim: false, name: 'pumpkin' },
147 | { hex: '#F6DDCC', rgb: '246, 221, 204', hsl: '24, 71%, 88%', anim: false, name: 'pumpkin' },
148 | { hex: '#EDBB99', rgb: '237, 187, 153', hsl: '24, 71%, 77%', anim: false, name: 'pumpkin' },
149 | { hex: '#E59866', rgb: '229, 152, 102', hsl: '24, 71%, 65%', anim: false, name: 'pumpkin' },
150 | { hex: '#DC7633', rgb: '220, 118, 51', hsl: '24, 71%, 53%', anim: false, name: 'pumpkin' },
151 | { hex: '#D35400', rgb: '211, 84, 0', hsl: '24, 100%, 41%', anim: false, name: 'pumpkin' },
152 | { hex: '#BA4A00', rgb: '186, 74, 0', hsl: '24, 100%, 36%', anim: false, name: 'pumpkin' },
153 | { hex: '#A04000', rgb: '160, 64, 0', hsl: '24, 100%, 31%', anim: false, name: 'pumpkin' },
154 | { hex: '#873600', rgb: '135, 54, 0', hsl: '24, 100%, 26%', anim: false, name: 'pumpkin' },
155 | { hex: '#6E2C00', rgb: '110, 44, 0', hsl: '24, 100%, 22%', anim: false, name: 'pumpkin' }],
156 |
157 | [{ hex: '#FDFEFE', rgb: '253, 254, 254', hsl: '192, 15%, 99%', anim: false, name: 'clouds' },
158 | { hex: '#FBFCFC', rgb: '251, 252, 252', hsl: '192, 15%, 99%', anim: false, name: 'clouds' },
159 | { hex: '#F7F9F9', rgb: '247, 249, 249', hsl: '192, 15%, 97%', anim: false, name: 'clouds' },
160 | { hex: '#F4F6F7', rgb: '244, 246, 247', hsl: '192, 15%, 96%', anim: false, name: 'clouds' },
161 | { hex: '#F0F3F4', rgb: '240, 243, 244', hsl: '192, 15%, 95%', anim: false, name: 'clouds' },
162 | { hex: '#ECF0F1', rgb: '236, 240, 241', hsl: '192, 15%, 94%', anim: false, name: 'clouds' },
163 | { hex: '#D0D3D4', rgb: '208, 211, 212', hsl: '192, 5%, 82%', anim: false, name: 'clouds' },
164 | { hex: '#B3B6B7', rgb: '179, 182, 183', hsl: '192, 3%, 71%', anim: false, name: 'clouds' },
165 | { hex: '#979A9A', rgb: '151, 154, 154', hsl: '192, 2%, 60%', anim: false, name: 'clouds' },
166 | { hex: '#7B7D7D', rgb: '123, 125, 125', hsl: '192, 1%, 49%', anim: false, name: 'clouds' }],
167 |
168 | [{ hex: '#F8F9F9', rgb: '248, 249, 249', hsl: '204, 8%, 98%', anim: false, name: 'silver' },
169 | { hex: '#F2F3F4', rgb: '242, 243, 244', hsl: '204, 8%, 95%', anim: false, name: 'silver' },
170 | { hex: '#E5E7E9', rgb: '229, 231, 233', hsl: '204, 8%, 90%', anim: false, name: 'silver' },
171 | { hex: '#D7DBDD', rgb: '215, 219, 221', hsl: '204, 8%, 86%', anim: false, name: 'silver' },
172 | { hex: '#CACFD2', rgb: '202, 207, 210', hsl: '204, 8%, 81%', anim: false, name: 'silver' },
173 | { hex: '#BDC3C7', rgb: '189, 195, 199', hsl: '204, 8%, 76%', anim: false, name: 'silver' },
174 | { hex: '#A6ACAF', rgb: '166, 172, 175', hsl: '204, 5%, 67%', anim: false, name: 'silver' },
175 | { hex: '#909497', rgb: '144, 148, 151', hsl: '204, 4%, 58%', anim: false, name: 'silver' },
176 | { hex: '#797D7F', rgb: '121, 125, 127', hsl: '204, 3%, 49%', anim: false, name: 'silver' },
177 | { hex: '#626567', rgb: '98, 101, 103', hsl: '204, 3%, 40%', anim: false, name: 'silver' }],
178 |
179 | [{ hex: '#F4F6F6', rgb: '244, 246, 246', hsl: '184, 9%, 96%', anim: false, name: 'concrete' },
180 | { hex: '#EAEDED', rgb: '234, 237, 237', hsl: '184, 9%, 92%', anim: false, name: 'concrete' },
181 | { hex: '#D5DBDB', rgb: '213, 219, 219', hsl: '184, 9%, 85%', anim: false, name: 'concrete' },
182 | { hex: '#BFC9CA', rgb: '191, 201, 202', hsl: '184, 9%, 77%', anim: false, name: 'concrete' },
183 | { hex: '#AAB7B8', rgb: '170, 183, 184', hsl: '184, 9%, 69%', anim: false, name: 'concrete' },
184 | { hex: '#95A5A6', rgb: '149, 165, 166', hsl: '184, 9%, 62%', anim: false, name: 'concrete' },
185 | { hex: '#839192', rgb: '131, 145, 146', hsl: '184, 6%, 54%', anim: false, name: 'concrete' },
186 | { hex: '#717D7E', rgb: '113, 125, 126', hsl: '184, 5%, 47%', anim: false, name: 'concrete' },
187 | { hex: '#5F6A6A', rgb: '95, 106, 106', hsl: '184, 5%, 40%', anim: false, name: 'concrete' },
188 | { hex: '#4D5656', rgb: '77, 86, 86', hsl: '184, 5%, 32%', anim: false, name: 'concrete' }],
189 |
190 | [{ hex: '#F2F4F4', rgb: '242, 244, 244', hsl: '184, 6%, 95%', anim: false, name: 'asbestos' },
191 | { hex: '#E5E8E8', rgb: '229, 232, 232', hsl: '184, 6%, 91%', anim: false, name: 'asbestos' },
192 | { hex: '#CCD1D1', rgb: '204, 209, 209', hsl: '184, 6%, 81%', anim: false, name: 'asbestos' },
193 | { hex: '#B2BABB', rgb: '178, 186, 187', hsl: '184, 6%, 72%', anim: false, name: 'asbestos' },
194 | { hex: '#99A3A4', rgb: '153, 163, 164', hsl: '184, 6%, 62%', anim: false, name: 'asbestos' },
195 | { hex: '#7F8C8D', rgb: '127, 140, 141', hsl: '184, 6%, 53%', anim: false, name: 'asbestos' },
196 | { hex: '#707B7C', rgb: '112, 123, 124', hsl: '184, 5%, 46%', anim: false, name: 'asbestos' },
197 | { hex: '#616A6B', rgb: '97, 106, 107', hsl: '184, 5%, 40%', anim: false, name: 'asbestos' },
198 | { hex: '#515A5A', rgb: '81, 90, 90', hsl: '184, 5%, 34%', anim: false, name: 'asbestos' },
199 | { hex: '#424949', rgb: '66, 73, 73', hsl: '184, 5%, 27%', anim: false, name: 'asbestos' }],
200 |
201 | [{ hex: '#EBEDEF', rgb: '235, 237, 239', hsl: '210, 12%, 93%', anim: false, name: 'wet asphalt' },
202 | { hex: '#D6DBDF', rgb: '214, 219, 223', hsl: '210, 12%, 86%', anim: false, name: 'wet asphalt' },
203 | { hex: '#AEB6BF', rgb: '174, 182, 191', hsl: '210, 12%, 71%', anim: false, name: 'wet asphalt' },
204 | { hex: '#85929E', rgb: '133, 146, 158', hsl: '210, 12%, 57%', anim: false, name: 'wet asphalt' },
205 | { hex: '#5D6D7E', rgb: '93, 109, 126', hsl: '210, 15%, 43%', anim: false, name: 'wet asphalt' },
206 | { hex: '#34495E', rgb: '52, 73, 94', hsl: '210, 29%, 29%', anim: false, name: 'wet asphalt' },
207 | { hex: '#2E4053', rgb: '46, 64, 83', hsl: '210, 29%, 25%', anim: false, name: 'wet asphalt' },
208 | { hex: '#283747', rgb: '40, 55, 71', hsl: '210, 29%, 22%', anim: false, name: 'wet asphalt' },
209 | { hex: '#212F3C', rgb: '33, 47, 60', hsl: '210, 29%, 18%', anim: false, name: 'wet asphalt' },
210 | { hex: '#1B2631', rgb: '27, 38, 49', hsl: '210, 29%, 15%', anim: false, name: 'wet asphalt' }],
211 |
212 | [{ hex: '#EAECEE', rgb: '234, 236, 238', hsl: '210, 9%, 92%', anim: false, name: 'midnight blue' },
213 | { hex: '#D5D8DC', rgb: '213, 216, 220', hsl: '210, 9%, 85%', anim: false, name: 'midnight blue' },
214 | { hex: '#ABB2B9', rgb: '171, 178, 185', hsl: '210, 9%, 70%', anim: false, name: 'midnight blue' },
215 | { hex: '#808B96', rgb: '128, 139, 150', hsl: '210, 9%, 55%', anim: false, name: 'midnight blue' },
216 | { hex: '#566573', rgb: '86, 101, 115', hsl: '210, 14%, 39%', anim: false, name: 'midnight blue' },
217 | { hex: '#2C3E50', rgb: '44, 62, 80', hsl: '210, 29%, 24%', anim: false, name: 'midnight blue' },
218 | { hex: '#273746', rgb: '39, 55, 70', hsl: '210, 29%, 21%', anim: false, name: 'midnight blue' },
219 | { hex: '#212F3D', rgb: '33, 47, 61', hsl: '210, 29%, 18%', anim: false, name: 'midnight blue' },
220 | { hex: '#1C2833', rgb: '28, 40, 51', hsl: '210, 29%, 16%', anim: false, name: 'midnight blue' },
221 | { hex: '#17202A', rgb: '23, 32, 42', hsl: '210, 29%, 13%', anim: false, name: 'midnight blue' }]
222 | ],
223 | currentColor: { hex: '', rgb: '', hsl: '', name: '', index: 0 },
224 | toggleColorForm: false,
225 | colorHex: 'ffffff',
226 | colorRgb: '255,255,255',
227 | colorHsl: '0,0%,100%'
228 | }
229 |
230 | const mutations = {
231 | SET_CURRENT_COLOR (state, obj) {
232 | state.currentColor = obj
233 | },
234 | ACTIVE_COLOR (state, payload) {
235 | state.colorMatrix[payload.row][payload.col]['anim'] = true
236 | },
237 | DISACTIVE_COLOR (state, payload) {
238 | state.colorMatrix[payload.row][payload.col]['anim'] = false
239 | },
240 | TOGGLE_FORM (state) {
241 | state.toggleColorForm = !state.toggleColorForm
242 | },
243 | SET_HEX_COLOR (state, value) {
244 | function hexToRgb (hex) {
245 | // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
246 | let shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i
247 | hex = hex.replace(shorthandRegex, function (m, r, g, b) {
248 | return r + r + g + g + b + b
249 | })
250 |
251 | let result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)
252 | return result ? [
253 | parseInt(result[1], 16),
254 | parseInt(result[2], 16),
255 | parseInt(result[3], 16)
256 | ] : null
257 | }
258 |
259 | function rgb2hsl (r, g, b) {
260 | let a = Math.max(r, g, b)
261 | let n = a - Math.min(r, g, b)
262 | let f = (1 - Math.abs(a + a - n - 1))
263 | let h = n && ((a === r) ? (g - b) / n : ((a === g) ? 2 + (b - r) / n : 4 + (r - g) / n))
264 | return [60 * (h < 0 ? h + 6 : h), f ? n / f : 0, (a + a - n) / 2]
265 | }
266 |
267 | try {
268 | state.colorHex = value
269 | state.colorRgb = hexToRgb(state.colorHex).join(',')
270 | let rgbArrayBase = state.colorRgb.split(',').map((rgb) => rgb / 255)
271 | state.colorHsl = rgb2hsl(...rgbArrayBase).map((hsl, index) => {
272 | return index ? (hsl * 100).toFixed(0) + '%' : hsl.toFixed(0)
273 | }).join(',')
274 | } catch (err) {
275 | console.log(err.message)
276 | }
277 | },
278 |
279 | SET_RGB_COLOR (state, payload) {
280 | function rgb2hsl (r, g, b) {
281 | let a = Math.max(r, g, b)
282 | let n = a - Math.min(r, g, b)
283 | let f = (1 - Math.abs(a + a - n - 1))
284 | let h = n && ((a === r) ? (g - b) / n : ((a === g) ? 2 + (b - r) / n : 4 + (r - g) / n))
285 | return [60 * (h < 0 ? h + 6 : h), f ? n / f : 0, (a + a - n) / 2]
286 | }
287 | let rgb2hex = (r, g, b) => [r, g, b].map(x => Math.round(x * 255).toString(16).padStart(2, 0)).join('')
288 |
289 | try {
290 | let rgbArray = state.colorRgb.split(',')
291 | if (payload.sym === 'r') {
292 | rgbArray[0] = payload.value
293 | } else if (payload.sym === 'g') {
294 | rgbArray[1] = payload.value
295 | } else if (payload.sym === 'b') {
296 | rgbArray[2] = payload.value
297 | } else {
298 | rgbArray = [255, 255, 255]
299 | }
300 | let rgbArrayBase = rgbArray.map((rgb) => rgb / 255)
301 | state.colorRgb = rgbArray.join(',')
302 | state.colorHex = rgb2hex(...rgbArrayBase)
303 | state.colorHsl = rgb2hsl(...rgbArrayBase).map((hsl, index) => {
304 | return index ? (hsl * 100).toFixed(0) + '%' : hsl.toFixed(0)
305 | }).join(',')
306 | } catch (err) {
307 | console.log(err.message)
308 | }
309 | },
310 |
311 | SET_HSL_COLOR (state, payload) {
312 | let hsl2rgb = (h, s, l, a = s * Math.min(l, 1 - l), f = (n, k = (n + h / 30) % 12) => l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1)) => [f(0), f(8), f(4)]
313 | let rgb2hex = (r, g, b) => [r, g, b].map(x => Math.round(x * 255).toString(16).padStart(2, 0)).join('')
314 | try {
315 | let hslArray = state.colorHsl.split(',')
316 | let hslArrayBase = hslArray.map((hsl, i) => {
317 | return i ? (hsl.split('%')[0] / 100) : hsl
318 | })
319 | if (payload.sym === 'h') {
320 | hslArray[0] = payload.value
321 | hslArrayBase[0] = payload.value
322 | } else if (payload.sym === 's') {
323 | hslArray[1] = payload.value + '%'
324 | hslArrayBase[1] = payload.value / 100
325 | } else if (payload.sym === 'l') {
326 | hslArray[2] = payload.value + '%'
327 | hslArrayBase[2] = payload.value / 100
328 | } else {
329 | hslArray = ['0', '0%', '100%']
330 | }
331 | state.colorHsl = hslArray.join(',')
332 | state.colorRgb = hsl2rgb(...hslArrayBase).map(x => x * 255 | 0).join(',')
333 | let rgbArrayBase = state.colorRgb.split(',').map((rgb) => rgb / 255)
334 | state.colorHex = rgb2hex(...rgbArrayBase)
335 | } catch (err) {
336 | console.log(err.message)
337 | }
338 | }
339 | }
340 |
341 | const actions = {
342 | setCurrentColor ({ commit }, obj) {
343 | commit('SET_CURRENT_COLOR', obj)
344 | },
345 | activeColor ({ commit }, payload) {
346 | commit('ACTIVE_COLOR', payload)
347 | },
348 | disactiveColor ({ commit }, payload) {
349 | commit('DISACTIVE_COLOR', payload)
350 | },
351 | toggleForm ({ commit }) {
352 | commit('TOGGLE_FORM')
353 | },
354 | setHexColor ({ commit }, payload) {
355 | commit('SET_HEX_COLOR', payload.target.value)
356 | },
357 | setRgbColor ({ commit }, payload) {
358 | commit('SET_RGB_COLOR', payload)
359 | },
360 | setHslColor ({ commit }, payload) {
361 | commit('SET_HSL_COLOR', payload)
362 | }
363 | }
364 |
365 | export default {
366 | state,
367 | mutations,
368 | actions
369 | }
370 |
--------------------------------------------------------------------------------
/src/renderer/store/modules/Cron.js:
--------------------------------------------------------------------------------
1 | import i18n from './../../i18n'
2 | import * as moment from 'moment'
3 | import * as parser from 'cron-parser'
4 |
5 | const CRON_DATETIME_MAX_LIMIT = 200
6 | const CRON_DATETIME_DEFAULT_COUNT = 7
7 | const CRON_SPECIAL_TYPES = [ '@yearly', '@annually', '@monthly', '@daily', '@hourly', '@reboot' ]
8 | const CRON_SELECTED_UNIT = {
9 | 'min': false,
10 | 'hour': false,
11 | 'dayOfMonth': false,
12 | 'month': false,
13 | 'dayOfWeek': false
14 | }
15 | const CRON_OPTIONS = {
16 | currentDate: moment.utc().local().format('YYYY-MM-DD HH:mm:ss'),
17 | utc: true
18 | }
19 |
20 | const helpers = {
21 | getTermOptions () {
22 | return {
23 | default: [
24 | { symbol: '*', explaination: i18n.t('cronHelp.anyValue') },
25 | { symbol: ',', explaination: i18n.t('cronHelp.valueListSeparator') },
26 | { symbol: '-', explaination: i18n.t('cronHelp.rangeOfValues') },
27 | { symbol: '/', explaination: i18n.t('cronHelp.stepValues') },
28 | { symbol: '@yearly', explaination: i18n.t('cronHelp.nonStandard') },
29 | { symbol: '@annually', explaination: i18n.t('cronHelp.nonStandard') },
30 | { symbol: '@monthly', explaination: i18n.t('cronHelp.nonStandard') },
31 | { symbol: '@daily', explaination: i18n.t('cronHelp.nonStandard') },
32 | { symbol: '@hourly', explaination: i18n.t('cronHelp.nonStandard') },
33 | { symbol: '@reboot', explaination: i18n.t('cronHelp.nonStandard') }
34 | ],
35 | min: [
36 | { symbol: '*', explaination: i18n.t('cronHelp.anyValue') },
37 | { symbol: ',', explaination: i18n.t('cronHelp.valueListSeparator') },
38 | { symbol: '-', explaination: i18n.t('cronHelp.rangeOfValues') },
39 | { symbol: '/', explaination: i18n.t('cronHelp.stepValues') },
40 | { symbol: '0-59', explaination: i18n.t('cronHelp.allowedValues') }
41 | ],
42 | hour: [
43 | { symbol: '*', explaination: i18n.t('cronHelp.anyValue') },
44 | { symbol: ',', explaination: i18n.t('cronHelp.valueListSeparator') },
45 | { symbol: '-', explaination: i18n.t('cronHelp.rangeOfValues') },
46 | { symbol: '/', explaination: i18n.t('cronHelp.stepValues') },
47 | { symbol: '0-23', explaination: i18n.t('cronHelp.allowedValues') }
48 | ],
49 | dayOfMonth: [
50 | { symbol: '*', explaination: i18n.t('cronHelp.anyValue') },
51 | { symbol: ',', explaination: i18n.t('cronHelp.valueListSeparator') },
52 | { symbol: '-', explaination: i18n.t('cronHelp.rangeOfValues') },
53 | { symbol: '/', explaination: i18n.t('cronHelp.stepValues') },
54 | { symbol: '1-31', explaination: i18n.t('cronHelp.allowedValues') }
55 | ],
56 | month: [
57 | { symbol: '*', explaination: i18n.t('cronHelp.anyValue') },
58 | { symbol: ',', explaination: i18n.t('cronHelp.valueListSeparator') },
59 | { symbol: '-', explaination: i18n.t('cronHelp.rangeOfValues') },
60 | { symbol: '/', explaination: i18n.t('cronHelp.stepValues') },
61 | { symbol: '1-12', explaination: i18n.t('cronHelp.allowedValues') },
62 | { symbol: 'JAN-DEC', explaination: i18n.t('cronHelp.alternativeSingleValues') }
63 | ],
64 | dayOfWeek: [
65 | { symbol: '*', explaination: i18n.t('cronHelp.anyValue') },
66 | { symbol: ',', explaination: i18n.t('cronHelp.valueListSeparator') },
67 | { symbol: '-', explaination: i18n.t('cronHelp.rangeOfValues') },
68 | { symbol: '/', explaination: i18n.t('cronHelp.stepValues') },
69 | { symbol: '0-6', explaination: i18n.t('cronHelp.allowedValues') },
70 | { symbol: 'SUN-SAT', explaination: i18n.t('cronHelp.alternativeSingleValues') }
71 | ]
72 | }
73 | },
74 |
75 | translateSpecialWord () {
76 | if (state.cronExp === '@yearly') {
77 | state.cronResult['content'] = i18n.t('cronHelp.yearly')
78 | return true
79 | }
80 | if (state.cronExp === '@annually') {
81 | state.cronResult['content'] = i18n.t('cronHelp.annually')
82 | return true
83 | }
84 | if (state.cronExp === '@monthly') {
85 | state.cronResult['content'] = i18n.t('cronHelp.monthly')
86 | return true
87 | }
88 | if (state.cronExp === '@daily') {
89 | state.cronResult['content'] = i18n.t('cronHelp.daily')
90 | return true
91 | }
92 | if (state.cronExp === '@hourly') {
93 | state.cronResult['content'] = i18n.t('cronHelp.hourly')
94 | return true
95 | }
96 | if (state.cronExp === '@reboot') {
97 | state.cronResult['content'] = i18n.t('cronHelp.afterReboot')
98 | return true
99 | }
100 | return false
101 | },
102 |
103 | translateToLanguage (state) {
104 | if (this.translateSpecialWord()) return true
105 |
106 | let phrases = state.cronExp.split(/\s+/)
107 | switch (state.currentUnit) {
108 | case 'min':
109 | state.cronResult['content'] = i18n.t('cron.at') + ' ' + this.translateLanguageByMode(phrases[0], 'minute')
110 | break
111 | case 'hour':
112 | state.cronResult['content'] = i18n.t('cron.at') + ' ' + this.translateLanguageByMode(phrases[1], 'hour')
113 | break
114 | case 'dayOfMonth':
115 | state.cronResult['content'] = i18n.t('cron.on') + ' ' + this.translateLanguageByMode(phrases[2], 'dayOfMonth')
116 | break
117 | case 'month':
118 | state.cronResult['content'] = i18n.t('cron.in') + ' ' + this.translateLanguageByMode(phrases[3], 'month')
119 | break
120 | case 'dayOfWeek':
121 | state.cronResult['content'] = i18n.t('cron.on') + ' ' + this.translateLanguageByMode(phrases[4], 'dayOfWeek')
122 | break
123 | default:
124 | state.cronResult['content'] = ''
125 | break
126 | }
127 | if (i18n.locale === 'cn') state.cronResult['content'] = state.cronResult['content'].replace(/\s/g, '')
128 | },
129 |
130 | translateLanguageByMode (phrase, mode) {
131 | let terms = phrase.split(',')
132 | if (terms.length === 1) return this.translateEachTerm(terms[0], mode)
133 | if (terms.length > 1) {
134 | let lang = ''
135 | if (i18n.locale === 'en' && mode === 'dayOfMonth') lang += i18n.t('cronHelp.dayOfMonth')
136 | for (let i = 0; i < terms.length; i++) {
137 | if (i === (terms.length - 2)) {
138 | lang = lang + this.translateEachTerm(terms[i], mode) + ' ' + i18n.t('cron.and') + ' '
139 | } else if (i === (terms.length - 1)) {
140 | lang = lang + ' ' + this.translateEachTerm(terms[i], mode) + ' '
141 | } else {
142 | lang = lang + this.translateEachTerm(terms[i], mode) + ', '
143 | }
144 | }
145 | return lang
146 | } else {
147 | return ''
148 | }
149 | },
150 |
151 | translateEachTerm (term, mode, fromRange = false) {
152 | if (term === '*') {
153 | return this.translateEveryTerm(mode)
154 | } else if (term.match(/\//)) {
155 | let skip = term.split(/\//)
156 | let _range = this.translateRange(skip[0], mode, true)
157 | if (i18n.locale === 'cn') {
158 | return i18n.t('cron.every') + _range + i18n.t('cron.of') + i18n.t('cron.every') + this.translateOrdinalSuffix(skip[1], mode)
159 | } else {
160 | return i18n.t('cron.every') + ' ' + this.translateOrdinalSuffix(skip[1], mode) + ' ' + _range
161 | }
162 | } else if (term.match(/-/)) {
163 | return this.translateRange(term, mode)
164 | } else {
165 | if (mode === 'dayOfWeek') {
166 | return this.getDayOfWeek(term)
167 | } else if (mode === 'month') {
168 | return this.getMonthName(term)
169 | } else {
170 | return (i18n.locale === 'en' && (fromRange || mode === 'dayOfMonth')) ? term : (term + ' ' + i18n.t('cronHelp.' + mode))
171 | }
172 | }
173 | },
174 |
175 | translateEveryTerm (mode) {
176 | if (mode === 'dayOfWeek' && i18n.locale === 'cn') return '每周的每一天'
177 | if (mode === 'dayOfMonth' && i18n.locale === 'cn') return '每月的每一天'
178 | return i18n.t('cron.every') + ' ' + i18n.t('cronHelp.' + mode)
179 | },
180 |
181 | translateRange (term, mode, fromStep = false) {
182 | if (term === '*') {
183 | return ''
184 | } else if (term.match('-')) {
185 | let range = term.split(/-/)
186 | let rangeLang = i18n.t('cron.from') + ' ' + this.translateEachTerm(range[0], mode, true) + ' ' + i18n.t('cron.through') + ' ' + this.translateEachTerm(range[1], mode, true)
187 | return (i18n.locale === 'en' && !fromStep) ? (i18n.t('cronHelp.' + mode) + ' ' + rangeLang) : rangeLang
188 | } else if (fromStep === true) {
189 | let rangeLang = i18n.t('cron.from') + ' ' + this.translateEachTerm(term, mode, true) + ' ' + i18n.t('cron.through') + ' ' + this.translateEachTerm(this.getTheEndByMode(mode), mode, true)
190 | return (i18n.locale === 'en' && !fromStep) ? (i18n.t('cronHelp.' + mode) + ' ' + rangeLang) : rangeLang
191 | }
192 | },
193 |
194 | translateOrdinalSuffix (num, mode) {
195 | if (i18n.locale === 'en') {
196 | if (parseInt(num) === 1) return '1st' + ' ' + i18n.t('cronHelp.' + mode)
197 | if (parseInt(num) === 2) return '2nd' + ' ' + i18n.t('cronHelp.' + mode)
198 | if (parseInt(num) === 3) return '3rd' + ' ' + i18n.t('cronHelp.' + mode)
199 | if (parseInt(num) > 3) return num + 'th' + ' ' + i18n.t('cronHelp.' + mode)
200 | } else {
201 | let lang = '第' + num
202 | return (mode === 'dayOfWeek' || mode === 'dayOfMonth') ? lang + '天' : lang + i18n.t('cronHelp.' + mode)
203 | }
204 | },
205 |
206 | getDayOfWeek (num) {
207 | let dayOfWeek = [
208 | i18n.t('cronHelp.sunday'),
209 | i18n.t('cronHelp.monday'),
210 | i18n.t('cronHelp.tuesday'),
211 | i18n.t('cronHelp.wednesday'),
212 | i18n.t('cronHelp.thursday'),
213 | i18n.t('cronHelp.friday'),
214 | i18n.t('cronHelp.saturday')
215 | ]
216 | let aliases = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat']
217 | let numStr = String(num).toLowerCase()
218 | if (aliases.includes(numStr)) {
219 | num = aliases.findIndex(x => x === numStr)
220 | }
221 | return dayOfWeek[num]
222 | },
223 |
224 | getDayOfMonth (num) {
225 | return (state.locale === 'en') ? num : (num + i18n.t('cronHelp.dayOfMonth'))
226 | },
227 |
228 | getMonthName (num) {
229 | let dayOfMonth = {
230 | 1: 'January',
231 | 2: 'February',
232 | 3: 'March',
233 | 4: 'April',
234 | 5: 'May',
235 | 6: 'June',
236 | 7: 'July',
237 | 8: 'August',
238 | 9: 'September',
239 | 10: 'October',
240 | 11: 'November',
241 | 12: 'December'
242 | }
243 |
244 | let aliases = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec']
245 | let numStr = String(num).toLowerCase()
246 | if (aliases.includes(numStr)) {
247 | num = aliases.findIndex(x => x === numStr) + 1
248 | }
249 |
250 | return (i18n.locale === 'en') ? dayOfMonth[num] : (num + i18n.t('cronHelp.month'))
251 | },
252 |
253 | getTheEndByMode (mode) {
254 | if (mode === 'minute') return '59'
255 | if (mode === 'hour') return '23'
256 | if (mode === 'dayOfMonth') return '31'
257 | if (mode === 'month') return '12'
258 | if (mode === 'dayOfWeek') return '0'
259 | }
260 |
261 | }
262 |
263 | const state = {
264 | tabs: [
265 | { title: i18n.t('tabs.home'), isActive: true },
266 | { title: i18n.t('tabs.help'), isActive: false }
267 | ],
268 | currentTab: i18n.t('tabs.home'),
269 | cronExp: '* * * * *',
270 | dateMaxCount: CRON_DATETIME_DEFAULT_COUNT,
271 | cronResult: {
272 | status: 0,
273 | content: i18n.t('cron.heresResult'),
274 | list: []
275 | },
276 | termOptions: helpers.getTermOptions(),
277 | currentUnit: 'default'
278 | }
279 |
280 | const mutations = {
281 | SET_INIT_STATE (state, payload) {
282 | state.tabs = payload.tabs
283 | state.currentTab = payload.currentTab
284 | state.cronResult = { status: 0, content: i18n.t('cron.heresResult'), list: [] }
285 | state.termOptions = helpers.getTermOptions()
286 | },
287 |
288 | SET_NAV (state, payload) {
289 | state.tabs.forEach((tabs, i) => {
290 | if (i === payload.index) {
291 | state.tabs[payload.index]['isActive'] = true
292 | state.currentTab = payload.title
293 | } else {
294 | state.tabs[i]['isActive'] = false
295 | }
296 | })
297 | },
298 |
299 | CRON_MATCH (state, target) {
300 | if (target.name === 'cron-exp') {
301 | state.cronExp = target.value
302 | }
303 | if (target.name === 'max-count') {
304 | if (target.value >= 1 && target.value <= CRON_DATETIME_MAX_LIMIT) {
305 | state.dateMaxCount = parseInt(target.value)
306 | } else if (target.value > CRON_DATETIME_MAX_LIMIT) {
307 | state.dateMaxCount = CRON_DATETIME_MAX_LIMIT
308 | } else if (target.value === '') {
309 | state.dateMaxCount = ''
310 | return false
311 | } else {
312 | state.dateMaxCount = CRON_DATETIME_DEFAULT_COUNT
313 | }
314 | }
315 |
316 | try {
317 | let expTerms = state.cronExp.split(/\s+/)
318 | let terms = expTerms.filter((term) => term.length !== 0)
319 | state.cronResult = { status: -1, content: '', list: [] }
320 | if (terms.length < 5 && !CRON_SPECIAL_TYPES.includes(state.cronExp)) {
321 | target.classList.add('invalid')
322 | state.cronResult = { status: -1, content: i18n.t('cronHelp.expNotComplete'), list: [] }
323 | return false
324 | } else {
325 | target.classList.remove('invalid')
326 | if (state.cronExp === '@reboot') {
327 | state.cronResult = { status: 1, content: i18n.t('cronHelp.afterReboot'), list: [] }
328 | return false
329 | }
330 | }
331 | let interval = (state.cronExp === '@annually') ? parser.parseExpression('0 0 1 1 *', CRON_OPTIONS) : parser.parseExpression(state.cronExp, CRON_OPTIONS)
332 | Array(parseInt(state.dateMaxCount)).fill(1).forEach((_, i) => {
333 | state.cronResult['list'].push(interval.next()['_date'].format('YYYY-MM-DD HH:mm:ss dddd'))
334 | })
335 | state.cronResult['status'] = 1
336 | if (state.cronResult['status'] >= 0) helpers.translateToLanguage(state)
337 | } catch (err) {
338 | console.log('Error: ' + err.message)
339 | target.classList.add('invalid')
340 | state.cronResult = { status: -1, content: err.message, list: [] }
341 | return false
342 | }
343 | },
344 |
345 | SELECT_UNIT (state, target) {
346 | let children = target.currentTarget.parentNode.childNodes
347 | children.forEach((child, i) => {
348 | if (child.classList && child.classList.contains('tag')) {
349 | child.classList.remove('selected')
350 | }
351 | })
352 | target.currentTarget.classList.add('selected')
353 | selectTextInInput()
354 | if (state.cronResult['status'] >= 0) helpers.translateToLanguage(state)
355 |
356 | function selectTextInInput () {
357 | let expTerms = state.cronExp.split(' ')
358 | let terms = expTerms.filter((term) => term.length !== 0)
359 | if (terms.length === 5) {
360 | let cronInput = document.getElementsByName('cron-exp')[0]
361 | cronInput.focus()
362 | if (target.currentTarget.classList.contains('min')) {
363 | cronInput.setSelectionRange(0, terms[0].length)
364 | state.currentUnit = 'min'
365 | }
366 | if (target.currentTarget.classList.contains('hour')) {
367 | cronInput.setSelectionRange((terms[0].length + 1), (terms[1].length + terms[0].length + 1))
368 | state.currentUnit = 'hour'
369 | }
370 | if (target.currentTarget.classList.contains('dayOfMonth')) {
371 | let endTermLen = getStrLengthInArray(terms, 0, 3)
372 | let endPos = endTermLen + 2
373 | let startTermLen = getStrLengthInArray(terms, 0, 2)
374 | let startPos = startTermLen + 2
375 | cronInput.setSelectionRange(startPos, endPos)
376 | state.currentUnit = 'dayOfMonth'
377 | }
378 | if (target.currentTarget.classList.contains('month')) {
379 | let endTermLen = getStrLengthInArray(terms, 0, 4)
380 | let endPos = endTermLen + 3
381 | let startTermLen = getStrLengthInArray(terms, 0, 3)
382 | let startPos = startTermLen + 3
383 | cronInput.setSelectionRange(startPos, endPos)
384 | state.currentUnit = 'month'
385 | }
386 | if (target.currentTarget.classList.contains('dayOfWeek')) {
387 | let endTermLen = getStrLengthInArray(terms, 0, 5)
388 | let endPos = endTermLen + 4
389 | let startTermLen = getStrLengthInArray(terms, 0, 4)
390 | let startPos = startTermLen + 4
391 | cronInput.setSelectionRange(startPos, endPos)
392 | state.currentUnit = 'dayOfWeek'
393 | }
394 | }
395 |
396 | function getStrLengthInArray (array, start, end) {
397 | return array.slice(start, end).map((elem, i) => { return elem.length }).reduce((sum, x) => sum + x)
398 | }
399 | }
400 | },
401 |
402 | UNIT_BE_SELECTED (state, target) {
403 | let ctl = target.currentTarget
404 | let startPos = ctl.selectionStart
405 | let endPos = ctl.selectionEnd
406 |
407 | let expTerms = state.cronExp.split(' ')
408 | let terms = expTerms.filter((term) => term.length !== 0)
409 | if (terms.length === 5) {
410 | let ranges = getStrRange(terms)
411 | let unit = Object.keys(CRON_SELECTED_UNIT)
412 | let tagList = Array.from(document.getElementsByClassName('tag'))
413 | for (let tag of tagList) {
414 | tag.classList.remove('selected')
415 | }
416 | ranges.forEach((range, i) => {
417 | if (startPos >= range[0] && startPos <= range[1] && endPos >= range[0] && endPos <= range[1]) {
418 | document.getElementsByClassName(unit[i])[0].classList.add('selected')
419 | state.currentUnit = unit[i]
420 | if (state.cronResult['status'] >= 0) helpers.translateToLanguage(state)
421 | }
422 | })
423 | }
424 |
425 | if (CRON_SPECIAL_TYPES.includes(state.cronExp)) {
426 | state.currentUnit = 'default'
427 | }
428 |
429 | function getStrRange (array) {
430 | let pos = 0
431 | let ranges = array.map(function (elem, i) {
432 | let range = [pos, pos + elem.length]
433 | pos = pos + elem.length
434 | pos += 1 // add space
435 | return range
436 | })
437 | return ranges
438 | }
439 | }
440 | }
441 |
442 | const actions = {
443 | setInitState ({ commit }, payload) {
444 | commit('SET_INIT_STATE', payload)
445 | },
446 | setNav ({ commit }, payload) {
447 | commit('SET_NAV', payload)
448 | },
449 | cronMatch ({ commit }, payload) {
450 | commit('CRON_MATCH', payload.target)
451 | },
452 | selectUnit ({ commit }, payload) {
453 | commit('SELECT_UNIT', payload)
454 | },
455 | unitBeSelected ({ commit }, payload) {
456 | commit('UNIT_BE_SELECTED', payload)
457 | }
458 | }
459 |
460 | export default {
461 | state,
462 | mutations,
463 | actions
464 | }
465 |
--------------------------------------------------------------------------------
/src/renderer/store/modules/Image64.js:
--------------------------------------------------------------------------------
1 | const state = {
2 | base64: ''
3 | }
4 |
5 | const mutations = {
6 | SET_IMAGE (state, payload) {
7 | let image = payload
8 | state.base64 = image
9 | },
10 | RESET_ALL () {
11 | state.base64 = ''
12 | }
13 | }
14 |
15 | const actions = {
16 | setImage ({ commit }, payload) {
17 | commit('SET_IMAGE', payload)
18 | },
19 | resetAll ({ commit }) {
20 | commit('RESET_ALL')
21 | }
22 | }
23 |
24 | export default {
25 | state,
26 | mutations,
27 | actions
28 | }
29 |
--------------------------------------------------------------------------------
/src/renderer/store/modules/Json.js:
--------------------------------------------------------------------------------
1 | import i18n from './../../i18n'
2 |
3 | const state = {
4 | jsonStr: '',
5 | jsonResult: '',
6 | jsonHtml: '',
7 | error: { 'code': 0, 'msg': '' },
8 | isXML: false
9 | }
10 |
11 | const ESCAPE_SYM = [
12 | ['<', '<'],
13 | ['>', '>'],
14 | [' ', ' '],
15 | ['"', '"']
16 | ]
17 |
18 | const mutations = {
19 | SET_JSON_TEXT (state, value) {
20 | state.jsonStr = value
21 | },
22 |
23 | CONVERT_JSON (state) {
24 | let i = 0
25 | let indentInit = 0
26 | let indentSym = ' '
27 | let indentCount = 4
28 |
29 | state.error = { 'code': 0, 'msg': '' }
30 | state.jsonResult = parseValue()
31 | skipSpace()
32 | if (i < state.jsonStr.length) {
33 | state.jsonResult = errorTermination(i18n.t('json.moreBehind'))
34 | }
35 | state.jsonHtml = renderHtml(state.jsonResult, indentInit)
36 | state.isXML = false
37 |
38 | function escapeString (txt) {
39 | ESCAPE_SYM.forEach((symItem) => {
40 | let rex = new RegExp(symItem[0], 'g')
41 | txt = txt.replace(rex, symItem[1])
42 | })
43 | return txt
44 | }
45 |
46 | function unicodeToChinese (str) {
47 | return unescape(str.replace(/\\u/g, '%u'))
48 | }
49 |
50 | function renderHtml (result, indtIndx) {
51 | let rsltHtml = ''
52 | let indentI = indtIndx + 1
53 | if (state.error['code'] === -1) {
54 | rsltHtml = '' + i18n.t('json.error') + ':
' + state.error['msg'] + '
' + i18n.t('json.near') + '
' + state.error['posMsg'] + '
'
55 | } else if (Array.isArray(result)) {
56 | let arrayHtml = ''
57 | let arrayItemCount = 0
58 | result.forEach((item, index) => {
59 | arrayItemCount++
60 | let itemHtml = ''
61 | if (typeof item === 'number') {
62 | if (index < (result.length - 1)) {
63 | itemHtml = indentSym.repeat(indentCount * indentI) + '' + item + ' , '
64 | } else {
65 | itemHtml = indentSym.repeat(indentCount * indentI) + '' + item + ' '
66 | }
67 | } else if (typeof item === 'string') {
68 | if (index < (result.length - 1)) {
69 | itemHtml = indentSym.repeat(indentCount * indentI) + '"' + unicodeToChinese(item) + '" , '
70 | } else {
71 | itemHtml = indentSym.repeat(indentCount * indentI) + '"' + unicodeToChinese(item) + '" '
72 | }
73 | } else if (typeof item === 'boolean') {
74 | if (index < (result.length - 1)) {
75 | itemHtml = indentSym.repeat(indentCount * indentI) + '' + item + ' , '
76 | } else {
77 | itemHtml = indentSym.repeat(indentCount * indentI) + '' + item + ' '
78 | }
79 | } else if (item === null) {
80 | if (index < (result.length - 1)) {
81 | itemHtml = indentSym.repeat(indentCount * indentI) + '' + item + ' , '
82 | } else {
83 | itemHtml = indentSym.repeat(indentCount * indentI) + '' + item + ' '
84 | }
85 | } else {
86 | if (index < (result.length - 1)) {
87 | itemHtml = indentSym.repeat(indentCount * indentI) + renderHtml(item, indentI) + ', '
88 | } else {
89 | itemHtml = indentSym.repeat(indentCount * indentI) + renderHtml(item, indentI) + ' '
90 | }
91 | }
92 | arrayHtml += itemHtml
93 | })
94 | rsltHtml = '[ ' + arrayHtml + indentSym.repeat(indentCount * indtIndx) + '] [Array[' + arrayItemCount + '] ↔ ] '
95 | } else if (typeof result === 'object') {
96 | let resultKeyVal = ''
97 | for (let index = 0; index < Object.entries(result).length; index++) {
98 | // deal with key
99 | let keyval = Object.entries(result)[index]
100 | let resultKey
101 | // if (typeof keyval[0] === 'number' || (keyval[0] === '0')) {
102 | if (typeof keyval[0] === 'number') {
103 | return 'Error!'
104 | } else {
105 | resultKey = indentSym.repeat(indentCount * indentI) + '"' + unicodeToChinese(escapeString(keyval[0])) + '" :'
106 | }
107 |
108 | // deal with value
109 | let resultVal
110 | if (typeof keyval[1] === 'number') {
111 | if (index < (Object.entries(result).length - 1)) {
112 | resultVal = '' + keyval[1] + ' , '
113 | } else {
114 | resultVal = '' + keyval[1] + ' '
115 | }
116 | } else if (typeof keyval[1] === 'string') {
117 | if (index < (Object.entries(result).length - 1)) {
118 | resultVal = '"' + unicodeToChinese(escapeString(keyval[1])) + '" , '
119 | } else {
120 | resultVal = '"' + unicodeToChinese(escapeString(keyval[1])) + '" '
121 | }
122 | } else if (keyval[1] === null) {
123 | if (index < (Object.entries(result).length - 1)) {
124 | resultVal = 'null , '
125 | } else {
126 | resultVal = 'null '
127 | }
128 | } else {
129 | if (index < (Object.entries(result).length - 1)) {
130 | resultVal = renderHtml(keyval[1], indentI) + ', '
131 | } else {
132 | resultVal = renderHtml(keyval[1], indentI) + ' '
133 | }
134 | }
135 |
136 | // adding ',' if it's not the last key-val
137 | resultKeyVal += (resultKey + resultVal)
138 | }
139 | rsltHtml = '{ ' + resultKeyVal + indentSym.repeat(indentCount * indtIndx) + '} {Object ↔ } '
140 | } else if (typeof result === 'boolean') {
141 | rsltHtml = '' + result + ' '
142 | } else {
143 | return rsltHtml
144 | }
145 | return rsltHtml
146 | }
147 |
148 | function parseValue (isKey = false) {
149 | skipSpace()
150 | if (isKey) {
151 | if (state.jsonStr[i] === `"`) {
152 | i++
153 | return parseString()
154 | } else {
155 | return undefined
156 | }
157 | } else {
158 | for (; i < state.jsonStr.length; i++) {
159 | if (state.jsonStr[i] === `{`) {
160 | i++
161 | return parseObject()
162 | }
163 | if (state.jsonStr[i] === `[`) {
164 | i++
165 | return parseArray()
166 | }
167 | if (state.jsonStr[i] === `"`) {
168 | i++
169 | return parseString()
170 | }
171 | if (state.jsonStr[i] === `t` || state.jsonStr[i] === `f`) {
172 | return parseBoolean()
173 | }
174 | if (state.jsonStr[i] === `n`) {
175 | return parserNull()
176 | }
177 | if (/[0-9.e\-+]/i.test(state.jsonStr[i])) {
178 | return parseNumber()
179 | } else {
180 | return undefined
181 | }
182 | }
183 | }
184 | }
185 |
186 | function parseObject () {
187 | let res = {}
188 | let value
189 | skipSpace()
190 | while (state.jsonStr[i] !== `}` && i < state.jsonStr.length) {
191 | let comma = false
192 |
193 | let key = parseValue(true)
194 | if (key === undefined) return errorTermination(i18n.t('json.undefinedKey'))
195 | skipSpace()
196 | if (state.jsonStr[i] !== `:`) return errorTermination(i18n.t('json.missing') + ' : ')
197 | i++ // 跳过`:`
198 | value = parseValue()
199 | if (value === undefined) return errorTermination(i18n.t('json.undefinedVal'))
200 | res[key] = value
201 | skipSpace()
202 | while (/[ ,]/.test(state.jsonStr[i]) && i < state.jsonStr.length - 1) {
203 | comma = true
204 | i++ // 跳过`,`
205 | }
206 | skipSpace()
207 | if (state.jsonStr[i] === `}` && comma) return errorTermination(i18n.t('json.missingKV'))
208 | if (state.jsonStr[i] !== `}` && !comma) return errorTermination(i18n.t('json.missingComma') + ' : ,')
209 | }
210 |
211 | if (state.jsonStr[i] !== `}`) return errorTermination(i18n.t('json.missing') + ' } ...')
212 | i++ // 跳过“}”
213 | return res
214 | }
215 |
216 | function parseArray () {
217 | let res = []
218 | let value
219 | skipSpace()
220 | while (state.jsonStr[i] !== `]` && i < state.jsonStr.length - 1) {
221 | let comma = false
222 |
223 | value = parseValue()
224 | res.push(value)
225 | skipSpace()
226 | while (/[ ,]/.test(state.jsonStr[i]) && i < state.jsonStr.length - 1) {
227 | comma = true
228 | i++ // 跳过`,`
229 | }
230 | skipSpace()
231 | if (state.jsonStr[i] === `]` && comma) return errorTermination(i18n.t('json.missingElemInArray'))
232 | if (state.jsonStr[i] !== `]` && !comma) return errorTermination(i18n.t('json.missingCommaInArray'))
233 | if (/[ ,]/.test(state.jsonStr[i]) === false && value === undefined) return errorTermination('the element is undefined...')
234 | }
235 | if (state.jsonStr[i] !== `]`) return errorTermination(i18n.t('json.missing') + ' ] ...')
236 | i++ // 跳过结束“]”
237 | return res
238 | }
239 |
240 | function parseString () {
241 | /**
242 | * 直接获取到这串字符串 key 或 value
243 | */
244 | let res = ``
245 | let j = i
246 | while ((state.jsonStr[i] !== `"` || (state.jsonStr[i] === `"` && state.jsonStr[i - 1] === `\\`)) && i < state.jsonStr.length) {
247 | i++
248 | }
249 | res = state.jsonStr.slice(j, i)
250 | if (state.jsonStr[i] !== `"`) return errorTermination(i18n.t('json.missing') + ' " ')
251 | i++ // 跳过字符串结尾引号结束`"`
252 | return res
253 | }
254 |
255 | function parseBoolean () {
256 | if (state.jsonStr[i] === `t` && i < state.jsonStr.length) {
257 | if ((i + 3) < state.jsonStr.length && state.jsonStr[i + 1] === `r` && state.jsonStr[i + 2] === `u` && state.jsonStr[i + 3] === `e`) {
258 | i = i + 4
259 | return true
260 | } else {
261 | return i18n.t('json.notBool')
262 | }
263 | } else {
264 | if ((i + 4) < state.jsonStr.length && state.jsonStr[i + 1] === `a` && state.jsonStr[i + 2] === `l` && state.jsonStr[i + 3] === `s` && state.jsonStr[i + 4] === `e`) {
265 | i = i + 5
266 | return false
267 | } else {
268 | return i18n.t('json.notBool')
269 | }
270 | }
271 | }
272 |
273 | function parseNumber () {
274 | let res = ``
275 | let j = i
276 | while (/[0-9.e\-+]/i.test(state.jsonStr[i]) && i < state.jsonStr.length) {
277 | i++
278 | }
279 | res = Number(state.jsonStr.slice(j, i))
280 | if (isNaN(res)) return errorTermination(i18n.t('json.notNum'))
281 | return res
282 | }
283 |
284 | function parserNull () {
285 | if ((i + 3) < state.jsonStr.length && state.jsonStr[i] === `n` && state.jsonStr[i + 1] === `u` && state.jsonStr[i + 2] === `l` && state.jsonStr[i + 3] === `l`) {
286 | i = i + 4
287 | return null
288 | } else {
289 | return i18n.t('json.notNull')
290 | }
291 | }
292 |
293 | function skipSpace () {
294 | while (/[ \n\r\t\b]/.test(state.jsonStr[i]) && i < state.jsonStr.length) {
295 | i++ // 跳过空白
296 | }
297 | }
298 |
299 | function errorPosMsg () {
300 | let strPosMsg = state.jsonStr.slice(0, i)
301 | return strPosMsg
302 | }
303 |
304 | function errorTermination (msg) {
305 | state.error = {'code': -1, 'posMsg': errorPosMsg(), 'msg': i18n.t('json.seems') + msg}
306 | return state.error
307 | }
308 | },
309 |
310 | JSON_TO_XML (state) {
311 | let indentInit = 0
312 | let indentSym = ' '
313 | let indentCount = 2
314 | let result = state.jsonResult
315 |
316 | state.jsonHtml = '<?xml version="1.0" encoding="UTF-8" ?><root> '
317 | state.jsonHtml += renderXML(result, indentInit)
318 | state.jsonHtml += '</root>'
319 | state.isXML = true
320 |
321 | function renderXML (jsonResult, indtIndx) {
322 | let xmlResult = ''
323 | let indentI = indtIndx + 1
324 | if (Array.isArray(jsonResult)) {
325 | jsonResult.forEach((item, index) => {
326 | if (typeof item === 'object' || Array.isArray(item)) {
327 | xmlResult += (' ' + indentSym.repeat(indentCount * indentI) + '<' + index + '> ')
328 | xmlResult += renderXML(item, indentI)
329 | xmlResult += (indentSym.repeat(indentCount * indentI) + '</' + index + '> ')
330 | } else {
331 | xmlResult += (indentSym.repeat(indentCount * indentI) + '<' + index + '>')
332 | xmlResult += ('' + item + ' ')
333 | xmlResult += ('</' + index + '> ')
334 | }
335 | })
336 | } else if (typeof jsonResult === 'object') {
337 | for (let index = 0; index < Object.entries(jsonResult).length; index++) {
338 | let keyval = Object.entries(jsonResult)[index]
339 | xmlResult += (indentSym.repeat(indentCount * indentI) + '<' + keyval[0] + '>')
340 | if (typeof keyval[1] === 'object' || Array.isArray(keyval[1])) {
341 | xmlResult += ' '
342 | xmlResult += renderXML(keyval[1], indentI)
343 | xmlResult += (indentSym.repeat(indentCount * indentI) + '</' + keyval[0] + '> ')
344 | } else {
345 | xmlResult += ('' + keyval[1] + ' ')
346 | xmlResult += ('</' + keyval[0] + '> ')
347 | }
348 | }
349 | } else {
350 | xmlResult = jsonResult
351 | }
352 | return xmlResult
353 | }
354 | }
355 | }
356 |
357 | const actions = {
358 | setJsonText ({ commit }, value) {
359 | commit('SET_JSON_TEXT', value)
360 | },
361 | convertJson ({ commit }) {
362 | commit('CONVERT_JSON')
363 | },
364 | jsonToXML ({ commit }) {
365 | commit('JSON_TO_XML')
366 | }
367 | }
368 |
369 | export default {
370 | state,
371 | mutations,
372 | actions
373 | }
374 |
--------------------------------------------------------------------------------
/src/renderer/store/modules/Menu.js:
--------------------------------------------------------------------------------
1 | const state = {
2 | menuState: true,
3 | lang: 'en'
4 | }
5 |
6 | const mutations = {
7 | TOGGLE_MENU (state) {
8 | state.menuState = !state.menuState
9 | },
10 | TOGGLE_LANG (state, i18n) {
11 | if (i18n.locale === 'cn') {
12 | state.lang = 'en'
13 | } else {
14 | state.lang = 'cn'
15 | }
16 | i18n.locale = state.lang
17 | window.localStorage.setItem('locale', state.lang)
18 | }
19 | }
20 |
21 | const actions = {
22 | toggleMenu ({ commit }) {
23 | // do something async
24 | commit('TOGGLE_MENU')
25 | },
26 | toggleLang ({ commit }, i18n) {
27 | commit('TOGGLE_LANG', i18n)
28 | }
29 | }
30 |
31 | export default {
32 | state,
33 | mutations,
34 | actions
35 | }
36 |
--------------------------------------------------------------------------------
/src/renderer/store/modules/Regex.js:
--------------------------------------------------------------------------------
1 | import i18n from './../../i18n'
2 |
3 | const state = {
4 | tabs: [
5 | { title: i18n.t('tabs.home'), isActive: true },
6 | { title: i18n.t('tabs.help'), isActive: false }
7 | ],
8 | currentTab: i18n.t('tabs.home'),
9 | regexExp: '',
10 | regexOpt: '',
11 | regexCont: '',
12 | regexResult: { status: 0, content: i18n.t('regex.heresResult') }
13 | }
14 |
15 | const mutations = {
16 | SET_INIT_STATE (state, payload) {
17 | state.tabs = payload.tabs
18 | state.currentTab = payload.currentTab
19 | state.regexResult = payload.regexResult
20 | },
21 | SET_NAV (state, payload) {
22 | state.tabs.forEach((tabs, i) => {
23 | if (i === payload.index) {
24 | state.tabs[payload.index]['isActive'] = true
25 | state.currentTab = payload.title
26 | } else {
27 | state.tabs[i]['isActive'] = false
28 | }
29 | })
30 | },
31 | CLEAN_FIELDS (state) {
32 | state.regexExp = ''
33 | state.regexOpt = ''
34 | state.regexCont = ''
35 | state.regexResult = { status: 0, content: i18n.t('regex.heresResult') }
36 | },
37 | REGEX_MATCH (state, target) {
38 | if (target.name === 'regex-exp') {
39 | state.regexExp = target.value
40 | }
41 | if (target.name === 'regex-opt') {
42 | state.regexOpt = target.value
43 | }
44 | if (target.name === 'regex-content') {
45 | state.regexCont = target.value
46 | }
47 |
48 | // Main Match Method:
49 | function matchContext (regexGlobal, result, flag) {
50 | let matchedContext = []
51 | let matchedGroups = []
52 | let reGroup = []
53 | let beginPos = 0
54 | let preventingTag = 0
55 | while ((reGroup = regexGlobal.exec(result['input'])) !== null) {
56 | if (preventingTag > reGroup['index']) break
57 | matchedContext.push(reGroup['input'].slice(beginPos, reGroup['index']))
58 | matchedContext.push(reGroup[0])
59 | beginPos = reGroup['index'] + reGroup[0].length
60 | if (flag > 1) matchedGroups.push(reGroup)
61 | preventingTag++
62 | }
63 | if (beginPos !== result['input'].length) {
64 | matchedContext.push(result['input'].slice(beginPos, result['input'].length))
65 | }
66 | let regexResult = { status: 1, content: matchedGroups, matchedContext: matchedContext }
67 | return regexResult
68 | }
69 |
70 | // Do the Regex Match:
71 | function execMatchContent (state, regexCont) {
72 | let regexResult
73 | try {
74 | let re = new RegExp(state.regexExp, state.regexOpt)
75 | let reGb = new RegExp(state.regexExp, state.regexOpt + 'g')
76 | let result = regexCont.match(re)
77 |
78 | if (result === null) {
79 | regexResult = { status: -1, content: i18n.t('regex.noMatches'), matchedContext: regexCont }
80 | } else {
81 | if (state.regexExp === '()') {
82 | let matchedContext = []
83 | regexCont.split('').forEach((val, index) => {
84 | matchedContext.push(val)
85 | matchedContext.push('')
86 | })
87 | let matchedGroups = [...Array(regexCont.length)].map(() => [regexCont, ''])
88 | regexResult = { status: 1, content: matchedGroups, matchedContext: matchedContext }
89 | } else {
90 | regexResult = matchContext(reGb, result, result.length)
91 | }
92 | }
93 | } catch (err) {
94 | console.log(err.message)
95 | if (err.message.match(/expression/)) {
96 | if (err.message.match(/Unterminated\s+group/)) {
97 | regexResult = { status: -1, content: i18n.t('regex.uHaveAnUnmatchedPats'), matchedContext: regexCont }
98 | } else {
99 | regexResult = { status: -1, content: i18n.t('regex.expError'), matchedContext: regexCont }
100 | }
101 | } else if (err.message.match(/constructor/)) {
102 | regexResult = { status: -1, content: i18n.t('regex.invalidOpt'), matchedContext: regexCont }
103 | } else {
104 | regexResult = { status: -1, content: i18n.t('regex.noMatches'), matchedContext: regexCont }
105 | }
106 | }
107 | return regexResult
108 | }
109 |
110 | if (state.regexCont === '' || state.regexExp === '') {
111 | state.regexResult = { status: 0, content: i18n.t('regex.heresResult') }
112 | } else {
113 | let regexResults = []
114 | // loop more sample test content
115 | state.regexCont.split('\n').forEach((content) => {
116 | regexResults.push(execMatchContent(state, content))
117 | })
118 | let matchedContexts = []
119 | let contents = []
120 | let errorFlag = 1
121 | console.log(regexResults)
122 | regexResults.forEach((result) => {
123 | if (result['status'] === 1) {
124 | if (result['content'].length > 0) contents = contents.concat(result['content'])
125 | errorFlag = 0
126 | }
127 | matchedContexts.push(result['matchedContext'])
128 | })
129 | if (errorFlag === 0) {
130 | state.regexResult = { status: 1, content: contents, matchedContext: matchedContexts }
131 | } else {
132 | state.regexResult = regexResults[0]
133 | }
134 | console.log(state.regexResult)
135 | }
136 | }
137 | }
138 |
139 | const actions = {
140 | setInitState ({ commit }, payload) {
141 | commit('SET_INIT_STATE', payload)
142 | },
143 | setNav ({ commit }, payload) {
144 | commit('SET_NAV', payload)
145 | },
146 | cleanFields ({ commit }) {
147 | commit('CLEAN_FIELDS')
148 | },
149 | regexMatch ({ commit }, payload) {
150 | commit('REGEX_MATCH', payload.target)
151 | }
152 | }
153 |
154 | export default {
155 | state,
156 | mutations,
157 | actions
158 | }
159 |
--------------------------------------------------------------------------------
/src/renderer/store/modules/TStamp.js:
--------------------------------------------------------------------------------
1 | import * as moment from 'moment'
2 | import i18n from './../../i18n'
3 |
4 | const state = {
5 | tabs: [
6 | { title: i18n.t('tabs.home'), isActive: true },
7 | { title: i18n.t('tabs.help'), isActive: false }
8 | ],
9 | currentTab: i18n.t('tabs.home'),
10 | timestampField: '',
11 | datetimeField: '',
12 | unit: 1,
13 | datetimeResult: '',
14 | timestampResult: ''
15 | }
16 |
17 | const mutations = {
18 | SET_INIT_STATE (state, payload) {
19 | state.tabs = payload.tabs
20 | state.currentTab = payload.currentTab
21 | },
22 | SET_NAV (state, payload) {
23 | state.tabs.forEach((tabs, i) => {
24 | if (i === payload.index) {
25 | state.tabs[payload.index]['isActive'] = true
26 | state.currentTab = payload.title
27 | } else {
28 | state.tabs[i]['isActive'] = false
29 | }
30 | })
31 | },
32 |
33 | RESET_INPUT (state) {
34 | state.timestampField = ''
35 | state.datetimeField = ''
36 | state.datetimeResult = ''
37 | state.timestampResult = ''
38 | },
39 |
40 | SET_UNIT (state, value) {
41 | state.unit = value
42 | },
43 |
44 | TIMESTAMP_CONVERT (state, value) {
45 | if (value === '') {
46 | state.datetimeResult = ''
47 | } else {
48 | state.timestampField = value
49 | try {
50 | let timeStamp = state.timestampField
51 | if (typeof state.timestampField !== 'number') {
52 | timeStamp = Number(state.timestampField)
53 | }
54 | let result = moment.unix(timeStamp / state.unit).format('YYYY-MM-DD HH:mm:ss')
55 | state.datetimeResult = result
56 | } catch (err) {
57 | console.log(err.message)
58 | let result = 'Convert Error'
59 | state.datetimeResult = result
60 | }
61 | }
62 | },
63 |
64 | DATETIME_CONVERT (state, value) {
65 | if (value === '') {
66 | state.timestampResult = ''
67 | } else {
68 | state.datetimeField = value
69 | try {
70 | state.unit.toString() === '1000' ? state.timestampResult = moment(state.datetimeField).valueOf().toString() : state.timestampResult = moment(state.datetimeField).format('X')
71 | } catch (err) {
72 | console.log(err.message)
73 | let result = 'Convert Error'
74 | state.timestampResult = result
75 | }
76 | }
77 | }
78 | }
79 |
80 | const actions = {
81 | setInitState ({ commit }, payload) {
82 | commit('SET_INIT_STATE', payload)
83 | },
84 |
85 | setNav ({ commit }, payload) {
86 | commit('SET_NAV', payload)
87 | },
88 |
89 | resetInput ({ commit }) {
90 | commit('RESET_INPUT')
91 | },
92 |
93 | setUnit ({ commit }, payload) {
94 | commit('SET_UNIT', payload.target.value)
95 | },
96 |
97 | timestampConvert ({ commit }, payload) {
98 | commit('TIMESTAMP_CONVERT', payload.target.value)
99 | },
100 | datetimeConvert ({ commit }, payload) {
101 | commit('DATETIME_CONVERT', payload.target.value)
102 | }
103 | }
104 |
105 | export default {
106 | state,
107 | mutations,
108 | actions
109 | }
110 |
--------------------------------------------------------------------------------
/src/renderer/store/modules/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * The file enables `@/store/index.js` to import all vuex modules
3 | * in a one-shot manner. There should not be any reason to edit this file.
4 | */
5 |
6 | const files = require.context('.', false, /\.js$/)
7 | const modules = {}
8 |
9 | files.keys().forEach(key => {
10 | if (key === './index.js') return
11 | modules[key.replace(/(\.\/|\.js)/g, '')] = files(key).default
12 | modules[key.replace(/(\.\/|\.js)/g, '')]['namespaced'] = true
13 | })
14 |
15 | export default modules
16 |
--------------------------------------------------------------------------------
/static/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TsaiKoga/it-tools/0df87d3c1e086106cc36f0cd0357812ea779aff2/static/.gitkeep
--------------------------------------------------------------------------------
/test/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "mocha": true
4 | },
5 | "globals": {
6 | "assert": true,
7 | "expect": true,
8 | "should": true,
9 | "__static": true
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/test/e2e/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | // Set BABEL_ENV to use proper env config
4 | process.env.BABEL_ENV = 'test'
5 |
6 | // Enable use of ES6+ on required files
7 | require('babel-register')({
8 | ignore: /node_modules/
9 | })
10 |
11 | // Attach Chai APIs to global scope
12 | const { expect, should, assert } = require('chai')
13 | global.expect = expect
14 | global.should = should
15 | global.assert = assert
16 |
17 | // Require all JS files in `./specs` for Mocha to consume
18 | require('require-dir')('./specs')
19 |
--------------------------------------------------------------------------------
/test/e2e/specs/Launch.spec.js:
--------------------------------------------------------------------------------
1 | import utils from '../utils'
2 |
3 | describe('Launch', function () {
4 | beforeEach(utils.beforeEach)
5 | afterEach(utils.afterEach)
6 |
7 | it('shows the proper application title', function () {
8 | return this.app.client.getTitle()
9 | .then(title => {
10 | expect(title).to.equal('it-tools')
11 | })
12 | })
13 | })
14 |
--------------------------------------------------------------------------------
/test/e2e/utils.js:
--------------------------------------------------------------------------------
1 | import electron from 'electron'
2 | import { Application } from 'spectron'
3 |
4 | export default {
5 | afterEach () {
6 | this.timeout(10000)
7 |
8 | if (this.app && this.app.isRunning()) {
9 | return this.app.stop()
10 | }
11 | },
12 | beforeEach () {
13 | this.timeout(10000)
14 | this.app = new Application({
15 | path: electron,
16 | args: ['dist/electron/main.js'],
17 | startTimeout: 10000,
18 | waitTimeout: 10000
19 | })
20 |
21 | return this.app.start()
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/test/unit/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | Vue.config.devtools = false
3 | Vue.config.productionTip = false
4 |
5 | // require all test files (files that ends with .spec.js)
6 | const testsContext = require.context('./specs', true, /\.spec$/)
7 | testsContext.keys().forEach(testsContext)
8 |
9 | // require all src files except main.js for coverage.
10 | // you can also change this to match only the subset of files that
11 | // you want coverage for.
12 | const srcContext = require.context('../../src/renderer', true, /^\.\/(?!main(\.js)?$)/)
13 | srcContext.keys().forEach(srcContext)
14 |
--------------------------------------------------------------------------------
/test/unit/karma.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const path = require('path')
4 | const merge = require('webpack-merge')
5 | const webpack = require('webpack')
6 |
7 | const baseConfig = require('../../.electron-vue/webpack.renderer.config')
8 | const projectRoot = path.resolve(__dirname, '../../src/renderer')
9 |
10 | // Set BABEL_ENV to use proper preset config
11 | process.env.BABEL_ENV = 'test'
12 |
13 | let webpackConfig = merge(baseConfig, {
14 | devtool: '#inline-source-map',
15 | plugins: [
16 | new webpack.DefinePlugin({
17 | 'process.env.NODE_ENV': '"testing"'
18 | })
19 | ]
20 | })
21 |
22 | // don't treat dependencies as externals
23 | delete webpackConfig.entry
24 | delete webpackConfig.externals
25 | delete webpackConfig.output.libraryTarget
26 |
27 | // apply vue option to apply isparta-loader on js
28 | webpackConfig.module.rules
29 | .find(rule => rule.use.loader === 'vue-loader').use.options.loaders.js = 'babel-loader'
30 |
31 | module.exports = config => {
32 | config.set({
33 | browsers: ['visibleElectron'],
34 | client: {
35 | useIframe: false
36 | },
37 | coverageReporter: {
38 | dir: './coverage',
39 | reporters: [
40 | { type: 'lcov', subdir: '.' },
41 | { type: 'text-summary' }
42 | ]
43 | },
44 | customLaunchers: {
45 | 'visibleElectron': {
46 | base: 'Electron',
47 | flags: ['--show']
48 | }
49 | },
50 | frameworks: ['mocha', 'chai'],
51 | files: ['./index.js'],
52 | preprocessors: {
53 | './index.js': ['webpack', 'sourcemap']
54 | },
55 | reporters: ['spec', 'coverage'],
56 | singleRun: true,
57 | webpack: webpackConfig,
58 | webpackMiddleware: {
59 | noInfo: true
60 | }
61 | })
62 | }
63 |
--------------------------------------------------------------------------------
/test/unit/specs/LandingPage.spec.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import LandingPage from '@/components/LandingPage'
3 |
4 | describe('LandingPage.vue', () => {
5 | it('should render correct contents', () => {
6 | const vm = new Vue({
7 | el: document.createElement('div'),
8 | render: h => h(LandingPage)
9 | }).$mount()
10 |
11 | expect(vm.$el.querySelector('.g-container .g-view .g-text').textContent).to.contain('IT Tools')
12 | })
13 | })
14 |
--------------------------------------------------------------------------------