Compare commits
134 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d87091b23f | ||
|
|
b65b69dd97 | ||
|
|
5bd5d2c2f3 | ||
|
|
55dffa5635 | ||
|
|
baee5e6656 | ||
|
|
df5804c71d | ||
|
|
8e99a0a783 | ||
|
|
6e22b12494 | ||
|
|
aaa154d0b8 | ||
|
|
37b28c8d21 | ||
|
|
06aac238b2 | ||
|
|
a282c526c1 | ||
|
|
19eafdbe37 | ||
|
|
635552fbce | ||
|
|
7f8404645d | ||
|
|
66c569f886 | ||
|
|
f02a816eaa | ||
|
|
f0d8a3ad26 | ||
|
|
f91a2a1343 | ||
|
|
845d106927 | ||
|
|
25bbf9b5f3 | ||
|
|
853e24ca75 | ||
|
|
41fadc7334 | ||
|
|
19ab6d06c3 | ||
|
|
d92c46c60b | ||
|
|
ed176c7b8c | ||
|
|
e152651a4b | ||
|
|
a20858dfb8 | ||
|
|
b75603f311 | ||
|
|
d27c133a66 | ||
|
|
bd64eb9dbe | ||
|
|
ac54250e8a | ||
|
|
e0e7715ce6 | ||
|
|
aa3a424f10 | ||
|
|
03e073d4f0 | ||
|
|
cb0e3f91db | ||
|
|
c8c0dceb21 | ||
|
|
ba5e07d063 | ||
|
|
9e94a985ca | ||
|
|
a14a7338f8 | ||
|
|
b65472ce96 | ||
|
|
87f269a792 | ||
|
|
27f957a098 | ||
|
|
551738f559 | ||
|
|
8f7b7f628e | ||
|
|
46514cf71b | ||
|
|
78157b4cb5 | ||
|
|
bf4260f926 | ||
|
|
9fc566e55a | ||
|
|
507d961cd8 | ||
|
|
0631a7f750 | ||
|
|
99ffe08d01 | ||
|
|
fcc1335f97 | ||
|
|
3988d33218 | ||
|
|
ecb4b1bb7b | ||
|
|
b63c4b5415 | ||
|
|
26bda68f41 | ||
|
|
f9f80b4e3a | ||
|
|
f50c5cb91b | ||
|
|
da1da1d269 | ||
|
|
4129169e2b | ||
|
|
cffbfe3e39 | ||
|
|
583ce878d2 | ||
|
|
c179f6a800 | ||
|
|
7944fd9f17 | ||
|
|
84763e1d5f | ||
|
|
ab56a3b598 | ||
|
|
b7d7454df5 | ||
|
|
b730c1d1b4 | ||
|
|
f6da2a44e5 | ||
|
|
89713c4986 | ||
|
|
3401fa4cf1 | ||
|
|
2a7abceba1 | ||
|
|
cd9a2318fd | ||
|
|
0ebe60e21e | ||
|
|
634147f0b3 | ||
|
|
318691837e | ||
|
|
17f3e7de35 | ||
|
|
aa4fb5ffff | ||
|
|
e51a37844a | ||
|
|
6d8db0a5d5 | ||
|
|
84e727a43a | ||
|
|
6f7c399823 | ||
|
|
3777eb941d | ||
|
|
dd41bdc57c | ||
|
|
48d0815524 | ||
|
|
efe62bb3cf | ||
|
|
48376c17b2 | ||
|
|
458309c563 | ||
|
|
fba0701df2 | ||
|
|
b013903c41 | ||
|
|
432ac7dd1c | ||
|
|
12a0d93c85 | ||
|
|
8c16d5f691 | ||
|
|
3c0c2bd14f | ||
|
|
f729eacdc5 | ||
|
|
b46ae1a89e | ||
|
|
45112d1b33 | ||
|
|
0bf13326c8 | ||
|
|
e5ffb4b946 | ||
|
|
a110a6b212 | ||
|
|
596753ce42 | ||
|
|
803dabece3 | ||
|
|
f15ae7c959 | ||
|
|
6dca9bb1bf | ||
|
|
9486c71d2b | ||
|
|
42864770d7 | ||
|
|
8fab4264b8 | ||
|
|
d7e0c4a16f | ||
|
|
ea4c87f6f3 | ||
|
|
360faf285e | ||
|
|
db48322ec3 | ||
|
|
c4bfad764c | ||
|
|
4801519b9f | ||
|
|
5ec4c26f01 | ||
|
|
b3d63734f0 | ||
|
|
9f4a257599 | ||
|
|
3e5a26c54c | ||
|
|
332cd33196 | ||
|
|
44c9157cec | ||
|
|
40b2695c8d | ||
|
|
55668ea312 | ||
|
|
77a6f20b2b | ||
|
|
407669def2 | ||
|
|
8c78e8ad77 | ||
|
|
85587beb0d | ||
|
|
805716910a | ||
|
|
e67e4cf547 | ||
|
|
716cfb69e3 | ||
|
|
d9f6c55a79 | ||
|
|
ee4eb30ca2 | ||
|
|
5a06d89bcc | ||
|
|
d1db2c8601 | ||
|
|
1fba5c42e1 |
38
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: "[BUG] My bug title"
|
||||
labels: bug
|
||||
assignees: CorentinTh
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Desktop (please complete the following information):**
|
||||
- OS: [e.g. iOS]
|
||||
- Browser [e.g. chrome, safari]
|
||||
- Version [e.g. 22]
|
||||
|
||||
**Smartphone (please complete the following information):**
|
||||
- Device: [e.g. iPhone6]
|
||||
- OS: [e.g. iOS8.1]
|
||||
- Browser [e.g. stock browser, safari]
|
||||
- Version [e.g. 22]
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
54
CHANGELOG.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## Next
|
||||
- [feat] [Crontab friendly generator](https://it-tools.tech/crontab-generator)
|
||||
|
||||
## 1.6.0
|
||||
- [feat] [BIP39 generator](https://it-tools.tech/bip39-generator)
|
||||
- [feat] [Base 64 converter](https://it-tools.tech/base64-string-converter)
|
||||
|
||||
## 1.5.2
|
||||
- [feat] [humans.txt](https://it-tools.tech/humans.txt)
|
||||
- [feat] pwa auto update on new changes
|
||||
|
||||
## 1.5.1
|
||||
- [feat] switched back to history mode (no more '#' in url)
|
||||
|
||||
## 1.5.0
|
||||
- [feat] added [qr-code generator](https://it-tools.tech/qrcode-generator)
|
||||
|
||||
## 1.4.0
|
||||
- [ui] condensed + colored sidenav
|
||||
- [feat] added [git memo](https://it-tools.tech/git-memo)
|
||||
- [refactor] changed app title
|
||||
|
||||
## 1.3.0
|
||||
- [fix] [GithubContributors] ordered contributors by contribution count
|
||||
- [refactor] used vue-typecasting for number inputs
|
||||
- [feat] lazy loading tools routes
|
||||
- [feat] added [markdown editor](https://it-tools.tech/markdown-editor)
|
||||
- [feat] added [lorem ipsum generator](https://it-tools.tech/lorem-ipsum-generator)
|
||||
|
||||
## 1.2.1
|
||||
- [fix] [UuidGenerator] added quantity validation rules
|
||||
- [refactor] better isInt checker
|
||||
|
||||
## 1.2.0
|
||||
- [feat] [UuidGenerator] can generate multiple uuids
|
||||
|
||||
## 1.1.0
|
||||
- [feat] 404 route + page
|
||||
- [feat] changelog in the About page
|
||||
- [feat] contributors list in the About page
|
||||
- [fix] [ColorConverter] color picker now updates fields
|
||||
|
||||
## 1.0.1
|
||||
- [chore] added changelog
|
||||
- [fix] [BaseConverter] prevented non-integer bases
|
||||
- [fix] remove history move (incompatible with vercel.com)
|
||||
|
||||
## 1.0.0
|
||||
- First release
|
||||
45
README.md
@@ -2,7 +2,7 @@
|
||||
|
||||
Aggregated set of useful tools that every developer may need once in a while. Available [here](https://it-tools.tech).
|
||||
|
||||
## Functionality/roadmap
|
||||
## Functionalities roadmap
|
||||
Here is an unordered list of the current functionalities, and some that may come.
|
||||
|
||||
- [x] Token generator
|
||||
@@ -15,13 +15,23 @@ Here is an unordered list of the current functionalities, and some that may come
|
||||
- [x] Url encoder
|
||||
- [x] Base 64 generator
|
||||
- [x] Text information
|
||||
- [ ] Lorem ipsum text generator
|
||||
- [x] Markdown editor
|
||||
- [x] Lorem ipsum text generator
|
||||
- [x] Git memo (cheat sheet)
|
||||
- [x] QR code generator
|
||||
- [x] Bip39 pass-phrase generator
|
||||
- [x] Base 64 string converter
|
||||
- [x] Crontab friendly generator
|
||||
- [ ] CSS memo (cheat sheet)
|
||||
- [ ] REGEX memo (cheat sheet) + tester?
|
||||
- [ ] Minify/un-minify
|
||||
- [ ] Image exif editor/remover
|
||||
- [ ] QR code generator
|
||||
- [ ] Bip39 pass-phrase generator
|
||||
- [ ] Crontab friendly generator
|
||||
- [ ] Image format converter?
|
||||
- [ ] Image cropper
|
||||
- [ ] Image resizer
|
||||
- [ ] HTTP client (w/ axios + cors proxy)
|
||||
- [ ] Math expression evaluator
|
||||
- [ ] Math expression graph
|
||||
|
||||
You have an idea of a tool? Submit a feature request!
|
||||
|
||||
@@ -44,10 +54,33 @@ npm run lint
|
||||
## Contribute
|
||||
**Pull requests are welcome !** Feel free to contribute.
|
||||
|
||||
### Add a tool
|
||||
To add a tool you just have to create a vue component in [src/routes/tools](./src/routes/tools), example:
|
||||
```vue
|
||||
<template>
|
||||
<v-card class="single-card">
|
||||
<v-card-title>My component</v-card-title>
|
||||
<v-card-text>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</v-card-text>
|
||||
</v-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "My component"
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
</style>
|
||||
```
|
||||
|
||||
Then, update the file [router.js](./src/router.js) specifying info of the component.
|
||||
Use [fontawesome 5](https://fontawesome.com/icons?d=gallery&m=free) for icons.
|
||||
|
||||
## Credits
|
||||
Coded with ❤️ by [Corentin Thomasset](//corentin-thomasset.fr).
|
||||
|
||||
This project is continuously deployed using [vercel.com](https://vercel.com).
|
||||
|
||||
## License
|
||||
This project is under the [MIT license](LICENSE).
|
||||
This project is under the [MIT license](LICENSE).
|
||||
|
||||
112
package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "it-tools",
|
||||
"version": "1.0.0",
|
||||
"version": "1.7.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@@ -2483,6 +2483,24 @@
|
||||
"file-uri-to-path": "1.0.0"
|
||||
}
|
||||
},
|
||||
"bip39": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/bip39/-/bip39-3.0.2.tgz",
|
||||
"integrity": "sha512-J4E1r2N0tUylTKt07ibXvhpT2c5pyAFgvuA5q1H9uDy6dEGpjV8jmymh3MTYJDLCNbIVClSB9FbND49I6N24MQ==",
|
||||
"requires": {
|
||||
"@types/node": "11.11.6",
|
||||
"create-hash": "^1.1.0",
|
||||
"pbkdf2": "^3.0.9",
|
||||
"randombytes": "^2.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/node": {
|
||||
"version": "11.11.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-11.11.6.tgz",
|
||||
"integrity": "sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"bluebird": {
|
||||
"version": "3.7.2",
|
||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
|
||||
@@ -3023,7 +3041,6 @@
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
|
||||
"integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"inherits": "^2.0.1",
|
||||
"safe-buffer": "^5.0.1"
|
||||
@@ -3139,6 +3156,12 @@
|
||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||
"dev": true
|
||||
},
|
||||
"highlight.js": {
|
||||
"version": "9.18.1",
|
||||
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.18.1.tgz",
|
||||
"integrity": "sha512-OrVKYz70LHsnCgmbXctv/bfuvntIKDz177h0Co37DQ5jamGZLVmoCVMtjMtNZY3X9DrCcKfklHPNeA0uPZhSJg==",
|
||||
"dev": true
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
|
||||
@@ -3676,7 +3699,6 @@
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
|
||||
"integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"cipher-base": "^1.0.1",
|
||||
"inherits": "^2.0.1",
|
||||
@@ -3689,7 +3711,6 @@
|
||||
"version": "1.1.7",
|
||||
"resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
|
||||
"integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"cipher-base": "^1.0.3",
|
||||
"create-hash": "^1.1.0",
|
||||
@@ -3699,6 +3720,16 @@
|
||||
"sha.js": "^2.4.8"
|
||||
}
|
||||
},
|
||||
"cron-validator": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/cron-validator/-/cron-validator-1.1.1.tgz",
|
||||
"integrity": "sha512-vfZb05w/wezuwPZBDvdIBmJp2BvuJExHeyKRa5oBqD2ZDXR61hb3QgPc/3ZhBEQJlAy8Jlnn5XC/JCT3IDqxwg=="
|
||||
},
|
||||
"cronstrue": {
|
||||
"version": "1.96.0",
|
||||
"resolved": "https://registry.npmjs.org/cronstrue/-/cronstrue-1.96.0.tgz",
|
||||
"integrity": "sha512-kNuuN0AXqspm+jlpwiecFSFBrG5dYBaL5EaW5MEjGAh4IFT/jbKwKCNhzWb8N5NulKQUHEDN7w98GjoAm6PmMg=="
|
||||
},
|
||||
"cross-spawn": {
|
||||
"version": "6.0.5",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
|
||||
@@ -4373,6 +4404,11 @@
|
||||
"domelementtype": "1"
|
||||
}
|
||||
},
|
||||
"dompurify": {
|
||||
"version": "2.0.11",
|
||||
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.0.11.tgz",
|
||||
"integrity": "sha512-qVoGPjIW9IqxRij7klDQQ2j6nSe4UNWANBhZNLnsS7ScTtLb+3YdxkRY8brNTpkUiTtcXsCJO+jS0UCDfenLuA=="
|
||||
},
|
||||
"domutils": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz",
|
||||
@@ -6214,7 +6250,6 @@
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz",
|
||||
"integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"inherits": "^2.0.1",
|
||||
"safe-buffer": "^5.0.1"
|
||||
@@ -6253,12 +6288,6 @@
|
||||
"integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==",
|
||||
"dev": true
|
||||
},
|
||||
"highlight.js": {
|
||||
"version": "9.18.1",
|
||||
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.18.1.tgz",
|
||||
"integrity": "sha512-OrVKYz70LHsnCgmbXctv/bfuvntIKDz177h0Co37DQ5jamGZLVmoCVMtjMtNZY3X9DrCcKfklHPNeA0uPZhSJg==",
|
||||
"dev": true
|
||||
},
|
||||
"hmac-drbg": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
|
||||
@@ -6628,8 +6657,7 @@
|
||||
"inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
},
|
||||
"inquirer": {
|
||||
"version": "7.1.0",
|
||||
@@ -7913,9 +7941,9 @@
|
||||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.15",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
|
||||
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
|
||||
"version": "4.17.19",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
|
||||
"integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
|
||||
"dev": true
|
||||
},
|
||||
"lodash._reinterpolate": {
|
||||
@@ -8103,11 +8131,15 @@
|
||||
"object-visit": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"marked": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/marked/-/marked-1.1.0.tgz",
|
||||
"integrity": "sha512-EkE7RW6KcXfMHy2PA7Jg0YJE1l8UPEZE8k45tylzmZM30/r1M1MUXWQfJlrSbsTeh7m/XTwHbWUENvAJZpp1YA=="
|
||||
},
|
||||
"md5.js": {
|
||||
"version": "1.3.5",
|
||||
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
|
||||
"integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"hash-base": "^3.0.0",
|
||||
"inherits": "^2.0.1",
|
||||
@@ -9084,7 +9116,6 @@
|
||||
"version": "3.0.17",
|
||||
"resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz",
|
||||
"integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"create-hash": "^1.1.2",
|
||||
"create-hmac": "^1.1.4",
|
||||
@@ -9980,6 +10011,11 @@
|
||||
"integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=",
|
||||
"dev": true
|
||||
},
|
||||
"qrcode.vue": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/qrcode.vue/-/qrcode.vue-1.7.0.tgz",
|
||||
"integrity": "sha512-R7t6Y3fDDtcU7L4rtqwGUDP9xD64gJhIwpfjhRCTKmBoYF6SS49PIJHRJ048cse6OI7iwTwgyy2C46N9Ygoc6g=="
|
||||
},
|
||||
"qs": {
|
||||
"version": "6.5.2",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
|
||||
@@ -10018,7 +10054,6 @@
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
||||
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.1.0"
|
||||
}
|
||||
@@ -10051,6 +10086,29 @@
|
||||
"unpipe": "1.0.0"
|
||||
}
|
||||
},
|
||||
"raw-loader": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-4.0.1.tgz",
|
||||
"integrity": "sha512-baolhQBSi3iNh1cglJjA0mYzga+wePk7vdEX//1dTFd+v4TsQlQE0jitJSNF1OIP82rdYulH7otaVmdlDaJ64A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"loader-utils": "^2.0.0",
|
||||
"schema-utils": "^2.6.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"loader-utils": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
|
||||
"integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"big.js": "^5.2.2",
|
||||
"emojis-list": "^3.0.0",
|
||||
"json5": "^2.1.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"read-pkg": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz",
|
||||
@@ -10428,7 +10486,6 @@
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz",
|
||||
"integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"hash-base": "^3.0.0",
|
||||
"inherits": "^2.0.1"
|
||||
@@ -10475,8 +10532,7 @@
|
||||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
||||
"dev": true
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
||||
},
|
||||
"safe-regex": {
|
||||
"version": "1.1.0",
|
||||
@@ -10737,7 +10793,6 @@
|
||||
"version": "2.4.11",
|
||||
"resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
|
||||
"integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"inherits": "^2.0.1",
|
||||
"safe-buffer": "^5.0.1"
|
||||
@@ -12117,6 +12172,11 @@
|
||||
"resolved": "https://registry.npmjs.org/vue/-/vue-2.6.11.tgz",
|
||||
"integrity": "sha512-VfPwgcGABbGAue9+sfrD4PuwFar7gPb1yl1UK1MwXoQPAw0BKSqWfoYCT/ThFrdEVWoI51dBuyCoiNU9bZDZxQ=="
|
||||
},
|
||||
"vue-analytics": {
|
||||
"version": "5.22.1",
|
||||
"resolved": "https://registry.npmjs.org/vue-analytics/-/vue-analytics-5.22.1.tgz",
|
||||
"integrity": "sha512-HPKQMN7gfcUqS5SxoO0VxqLRRSPkG1H1FqglsHccz6BatBatNtm/Vyy8brApktZxNCfnAkrSVDpxg3/FNDeOgQ=="
|
||||
},
|
||||
"vue-cli-plugin-vuetify": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/vue-cli-plugin-vuetify/-/vue-cli-plugin-vuetify-2.0.5.tgz",
|
||||
@@ -12713,9 +12773,9 @@
|
||||
}
|
||||
},
|
||||
"websocket-extensions": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz",
|
||||
"integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==",
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz",
|
||||
"integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==",
|
||||
"dev": true
|
||||
},
|
||||
"which": {
|
||||
|
||||
10
package.json
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "it-tools",
|
||||
"description": "",
|
||||
"version": "1.0.0",
|
||||
"version": "1.7.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
@@ -10,12 +10,19 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^0.19.2",
|
||||
"bip39": "^3.0.2",
|
||||
"color-convert": "^2.0.1",
|
||||
"color-name": "^1.1.4",
|
||||
"core-js": "^3.6.4",
|
||||
"cron-validator": "^1.1.1",
|
||||
"cronstrue": "^1.96.0",
|
||||
"dompurify": "^2.0.11",
|
||||
"marked": "^1.1.0",
|
||||
"qrcode.vue": "^1.7.0",
|
||||
"register-service-worker": "^1.7.1",
|
||||
"roboto-fontface": "*",
|
||||
"vue": "^2.6.11",
|
||||
"vue-analytics": "^5.22.1",
|
||||
"vue-cryptojs": "^2.1.4",
|
||||
"vue-headful": "^2.1.0",
|
||||
"vue-router": "^3.1.6",
|
||||
@@ -35,6 +42,7 @@
|
||||
"less": "^3.0.4",
|
||||
"less-loader": "^5.0.0",
|
||||
"lint-staged": "^9.5.0",
|
||||
"raw-loader": "^4.0.1",
|
||||
"sass": "^1.19.0",
|
||||
"sass-loader": "^8.0.0",
|
||||
"vue-cli-plugin-vuetify": "~2.0.5",
|
||||
|
||||
9
public/browserconfig.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<browserconfig>
|
||||
<msapplication>
|
||||
<tile>
|
||||
<square150x150logo src="./img/icons/mstile-150x150.png"/>
|
||||
<TileColor>#2d89ef</TileColor>
|
||||
</tile>
|
||||
</msapplication>
|
||||
</browserconfig>
|
||||
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 15 KiB |
5
public/humans.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
/* TEAM */
|
||||
Developer: Corentin Thomasset
|
||||
Site: https://github.com/CorentinTh
|
||||
Twitter: @cthmsst
|
||||
|
||||
|
Before Width: | Height: | Size: 9.2 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 6.3 KiB |
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 799 B After Width: | Height: | Size: 862 B |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 3.4 KiB |
@@ -2,148 +2,50 @@
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||
width="16.000000pt" height="16.000000pt" viewBox="0 0 16.000000 16.000000"
|
||||
width="1024.000000pt" height="1024.000000pt" viewBox="0 0 1024.000000 1024.000000"
|
||||
preserveAspectRatio="xMidYMid meet">
|
||||
<metadata>
|
||||
Created by potrace 1.11, written by Peter Selinger 2001-2013
|
||||
</metadata>
|
||||
<g transform="translate(0.000000,16.000000) scale(0.000320,-0.000320)"
|
||||
<g transform="translate(0.000000,1024.000000) scale(0.100000,-0.100000)"
|
||||
fill="#000000" stroke="none">
|
||||
<path d="M18 46618 c45 -75 122 -207 122 -211 0 -2 25 -45 55 -95 30 -50 55
|
||||
-96 55 -102 0 -5 5 -10 10 -10 6 0 10 -4 10 -9 0 -5 73 -135 161 -288 89 -153
|
||||
173 -298 187 -323 14 -25 32 -57 41 -72 88 -149 187 -324 189 -335 2 -7 8 -13
|
||||
13 -13 5 0 9 -4 9 -10 0 -5 46 -89 103 -187 175 -302 490 -846 507 -876 8 -16
|
||||
20 -36 25 -45 28 -46 290 -498 339 -585 13 -23 74 -129 136 -236 61 -107 123
|
||||
-215 137 -240 14 -25 29 -50 33 -56 5 -5 23 -37 40 -70 18 -33 38 -67 44 -75
|
||||
11 -16 21 -33 63 -109 14 -25 29 -50 33 -56 4 -5 21 -35 38 -65 55 -100 261
|
||||
-455 269 -465 4 -5 14 -21 20 -35 15 -29 41 -75 103 -180 24 -41 52 -88 60
|
||||
-105 9 -16 57 -100 107 -185 112 -193 362 -626 380 -660 8 -14 23 -38 33 -55
|
||||
11 -16 23 -37 27 -45 4 -8 26 -46 48 -85 23 -38 53 -90 67 -115 46 -81 64
|
||||
-113 178 -310 62 -107 121 -210 132 -227 37 -67 56 -99 85 -148 16 -27 32 -57
|
||||
36 -65 4 -8 15 -27 25 -42 9 -15 53 -89 96 -165 44 -76 177 -307 296 -513 120
|
||||
-206 268 -463 330 -570 131 -227 117 -203 200 -348 36 -62 73 -125 82 -140 10
|
||||
-15 21 -34 25 -42 4 -8 20 -37 36 -65 17 -27 38 -65 48 -82 49 -85 64 -111 87
|
||||
-153 13 -25 28 -49 32 -55 4 -5 78 -134 165 -285 87 -151 166 -288 176 -305
|
||||
10 -16 26 -43 35 -59 9 -17 125 -217 257 -445 132 -229 253 -441 270 -471 17
|
||||
-30 45 -79 64 -108 18 -29 33 -54 33 -57 0 -2 20 -37 44 -77 24 -40 123 -212
|
||||
221 -383 97 -170 190 -330 205 -355 16 -25 39 -65 53 -90 13 -25 81 -144 152
|
||||
-265 70 -121 137 -238 150 -260 12 -22 37 -65 55 -95 18 -30 43 -73 55 -95 12
|
||||
-22 48 -85 80 -140 77 -132 163 -280 190 -330 13 -22 71 -123 130 -225 59
|
||||
-102 116 -199 126 -217 10 -17 29 -50 43 -72 15 -22 26 -43 26 -45 0 -2 27
|
||||
-50 60 -106 33 -56 60 -103 60 -105 0 -2 55 -98 90 -155 8 -14 182 -316 239
|
||||
-414 13 -22 45 -79 72 -124 27 -46 49 -86 49 -89 0 -2 14 -24 30 -48 16 -24
|
||||
30 -46 30 -49 0 -5 74 -135 100 -176 5 -8 24 -42 43 -75 50 -88 58 -101 262
|
||||
-455 104 -179 199 -345 213 -370 14 -25 28 -49 32 -55 4 -5 17 -26 28 -45 10
|
||||
-19 62 -109 114 -200 114 -197 133 -230 170 -295 16 -27 33 -57 38 -65 17 -28
|
||||
96 -165 103 -180 4 -8 16 -28 26 -45 10 -16 77 -131 148 -255 72 -124 181
|
||||
-313 243 -420 62 -107 121 -209 131 -227 35 -62 323 -560 392 -678 38 -66 83
|
||||
-145 100 -175 16 -30 33 -59 37 -65 4 -5 17 -27 29 -47 34 -61 56 -100 90
|
||||
-156 17 -29 31 -55 31 -57 0 -2 17 -32 39 -67 21 -35 134 -229 251 -433 117
|
||||
-203 235 -407 261 -451 27 -45 49 -85 49 -88 0 -4 8 -19 19 -34 15 -21 200
|
||||
-341 309 -533 10 -19 33 -58 51 -87 17 -29 31 -54 31 -56 0 -2 25 -44 55 -94
|
||||
30 -50 55 -95 55 -98 0 -4 6 -15 14 -23 7 -9 27 -41 43 -71 17 -30 170 -297
|
||||
342 -594 171 -296 311 -542 311 -547 0 -5 5 -9 10 -9 6 0 10 -4 10 -10 0 -5
|
||||
22 -47 49 -92 27 -46 58 -99 68 -118 24 -43 81 -140 93 -160 5 -8 66 -114 135
|
||||
-235 69 -121 130 -227 135 -235 12 -21 259 -447 283 -490 10 -19 28 -47 38
|
||||
-62 11 -14 19 -29 19 -32 0 -3 37 -69 83 -148 99 -170 305 -526 337 -583 13
|
||||
-22 31 -53 41 -70 11 -16 22 -37 26 -45 7 -14 82 -146 103 -180 14 -24 181
|
||||
-311 205 -355 13 -22 46 -80 75 -130 29 -49 64 -110 78 -135 14 -25 51 -88 82
|
||||
-140 31 -52 59 -102 63 -110 4 -8 18 -33 31 -55 205 -353 284 -489 309 -535
|
||||
17 -30 45 -78 62 -106 18 -28 36 -60 39 -72 4 -12 12 -22 17 -22 5 0 9 -4 9
|
||||
-10 0 -5 109 -197 241 -427 133 -230 250 -431 259 -448 51 -90 222 -385 280
|
||||
-485 37 -63 78 -135 92 -160 14 -25 67 -117 118 -205 51 -88 101 -175 111
|
||||
-193 34 -58 55 -95 149 -257 51 -88 101 -173 110 -190 9 -16 76 -131 147 -255
|
||||
72 -124 140 -241 151 -260 61 -108 281 -489 355 -615 38 -66 77 -133 87 -150
|
||||
35 -63 91 -161 100 -175 14 -23 99 -169 128 -220 54 -97 135 -235 142 -245 4
|
||||
-5 20 -32 35 -60 26 -48 238 -416 276 -480 10 -16 26 -46 37 -65 30 -53 382
|
||||
-661 403 -695 10 -16 22 -37 26 -45 4 -8 26 -48 50 -88 24 -41 43 -75 43 -77
|
||||
0 -2 22 -40 50 -85 27 -45 50 -84 50 -86 0 -3 38 -69 83 -147 84 -142 302
|
||||
-520 340 -587 10 -19 34 -60 52 -90 18 -30 44 -75 57 -100 14 -25 45 -79 70
|
||||
-120 25 -41 56 -96 70 -121 14 -25 77 -133 138 -240 62 -107 122 -210 132
|
||||
-229 25 -43 310 -535 337 -581 11 -19 26 -45 34 -59 17 -32 238 -414 266 -460
|
||||
11 -19 24 -41 28 -49 3 -7 75 -133 160 -278 84 -146 153 -269 153 -274 0 -5 5
|
||||
-9 10 -9 6 0 10 -4 10 -10 0 -5 82 -150 181 -322 182 -314 201 -346 240 -415
|
||||
12 -21 80 -139 152 -263 71 -124 141 -245 155 -270 14 -25 28 -49 32 -55 6 -8
|
||||
145 -248 220 -380 37 -66 209 -362 229 -395 11 -19 24 -42 28 -49 4 -8 67
|
||||
-118 140 -243 73 -125 133 -230 133 -233 0 -2 15 -28 33 -57 19 -29 47 -78 64
|
||||
-108 17 -30 53 -93 79 -139 53 -90 82 -141 157 -272 82 -142 115 -199 381
|
||||
-659 142 -245 268 -463 281 -485 12 -22 71 -125 132 -230 60 -104 172 -298
|
||||
248 -430 76 -132 146 -253 156 -270 11 -16 22 -36 26 -44 3 -8 30 -54 60 -103
|
||||
29 -49 53 -91 53 -93 0 -3 18 -34 40 -70 22 -36 40 -67 40 -69 0 -2 37 -66 81
|
||||
-142 45 -77 98 -168 119 -204 20 -36 47 -81 58 -100 12 -19 27 -47 33 -62 6
|
||||
-16 15 -28 20 -28 5 0 9 -4 9 -9 0 -6 63 -118 140 -251 77 -133 140 -243 140
|
||||
-245 0 -2 18 -33 41 -70 22 -37 49 -83 60 -101 10 -19 29 -51 40 -71 25 -45
|
||||
109 -189 126 -218 7 -11 17 -29 22 -40 6 -11 22 -38 35 -60 14 -22 37 -62 52
|
||||
-90 14 -27 35 -62 45 -77 11 -14 19 -29 19 -32 0 -3 18 -35 40 -71 22 -36 40
|
||||
-67 40 -69 0 -2 19 -35 42 -72 23 -38 55 -94 72 -124 26 -47 139 -244 171
|
||||
-298 6 -9 21 -36 34 -60 28 -48 37 -51 51 -19 6 12 19 36 29 52 10 17 27 46
|
||||
38 65 11 19 104 181 208 360 103 179 199 345 213 370 14 25 42 74 64 109 21
|
||||
34 38 65 38 67 0 2 18 33 40 69 22 36 40 67 40 69 0 3 177 310 199 346 16 26
|
||||
136 234 140 244 2 5 25 44 52 88 27 44 49 81 49 84 0 2 18 34 40 70 22 36 40
|
||||
67 40 69 0 2 20 36 43 77 35 58 169 289 297 513 9 17 50 86 90 155 40 69 86
|
||||
150 103 180 16 30 35 62 41 70 6 8 16 24 22 35 35 64 72 129 167 293 59 100
|
||||
116 199 127 220 11 20 30 53 41 72 43 72 1070 1850 1121 1940 14 25 65 113
|
||||
113 195 48 83 96 166 107 185 10 19 28 50 38 68 11 18 73 124 137 235 64 111
|
||||
175 303 246 427 71 124 173 299 225 390 52 91 116 202 143 248 27 45 49 85 49
|
||||
89 0 4 6 14 14 22 7 9 28 43 46 76 26 47 251 436 378 655 11 19 29 51 40 70
|
||||
11 19 101 176 201 348 99 172 181 317 181 323 0 5 5 9 10 9 6 0 10 5 10 11 0
|
||||
6 8 23 18 37 11 15 32 52 49 82 16 30 130 228 253 440 122 212 234 405 248
|
||||
430 13 25 39 70 57 100 39 65 69 117 130 225 25 44 50 87 55 95 12 19 78 134
|
||||
220 380 61 107 129 224 150 260 161 277 222 382 246 425 15 28 47 83 71 123
|
||||
24 41 43 78 43 83 0 5 4 9 8 9 4 0 13 12 19 28 7 15 23 45 36 67 66 110 277
|
||||
478 277 483 0 3 6 13 14 21 7 9 27 41 43 71 17 30 45 80 63 110 34 57 375 649
|
||||
394 685 6 11 16 27 22 35 6 8 26 42 44 75 18 33 41 74 51 90 10 17 24 41 32
|
||||
55 54 97 72 128 88 152 11 14 19 28 19 30 0 3 79 141 175 308 96 167 175 305
|
||||
175 308 0 3 6 13 14 21 7 9 26 39 41 66 33 60 276 483 338 587 24 40 46 80 50
|
||||
88 4 8 13 24 20 35 14 23 95 163 125 215 11 19 52 91 92 160 40 69 80 139 90
|
||||
155 9 17 103 179 207 360 105 182 200 346 211 365 103 181 463 802 489 845 7
|
||||
11 15 27 19 35 4 8 29 51 55 95 64 110 828 1433 848 1470 9 17 24 41 33 55 9
|
||||
14 29 48 45 77 15 28 52 93 82 145 30 51 62 107 71 123 17 30 231 398 400 690
|
||||
51 88 103 179 115 202 12 23 26 48 32 55 6 7 24 38 40 68 17 30 61 107 98 170
|
||||
37 63 84 144 103 180 19 36 41 72 48 81 8 8 14 18 14 21 0 4 27 51 59 106 32
|
||||
55 72 124 89 154 16 29 71 125 122 213 51 88 104 180 118 205 13 25 28 50 32
|
||||
55 4 6 17 26 28 45 11 19 45 80 77 135 31 55 66 116 77 135 11 19 88 152 171
|
||||
295 401 694 620 1072 650 1125 11 19 87 152 170 295 83 143 158 273 166 288 9
|
||||
16 21 36 26 45 6 9 31 52 55 96 25 43 54 94 66 115 11 20 95 164 186 321 91
|
||||
157 173 299 182 315 9 17 26 46 37 65 12 19 66 114 121 210 56 96 108 186 117
|
||||
200 8 14 24 40 34 59 24 45 383 664 412 713 5 9 17 29 26 45 15 28 120 210
|
||||
241 419 36 61 68 117 72 125 4 8 12 23 19 34 35 57 245 420 262 453 11 20 35
|
||||
61 53 90 17 29 32 54 32 56 0 3 28 51 62 108 33 57 70 119 80 138 10 19 23 42
|
||||
28 50 5 8 32 53 59 100 27 47 149 258 271 470 122 212 234 405 248 430 30 53
|
||||
62 108 80 135 6 11 15 27 19 35 4 8 85 150 181 315 96 165 187 323 202 350 31
|
||||
56 116 202 130 225 5 8 25 42 43 75 19 33 92 159 162 280 149 257 157 271 202
|
||||
350 19 33 38 67 43 75 9 14 228 392 275 475 12 22 55 96 95 165 40 69 80 139
|
||||
90 155 24 42 202 350 221 383 9 15 27 47 41 72 14 25 75 131 136 236 61 106
|
||||
121 210 134 232 99 172 271 470 279 482 5 8 23 40 40 70 18 30 81 141 142 245
|
||||
60 105 121 210 135 235 14 25 71 124 127 220 56 96 143 247 194 335 51 88 96
|
||||
167 102 175 14 24 180 311 204 355 23 43 340 590 356 615 5 8 50 87 101 175
|
||||
171 301 517 898 582 1008 25 43 46 81 46 83 0 2 12 23 27 47 14 23 40 67 56
|
||||
97 16 30 35 62 42 70 7 8 15 22 18 30 4 8 20 38 37 65 16 28 33 57 37 65 6 12
|
||||
111 196 143 250 5 8 55 95 112 193 57 98 113 195 126 215 12 20 27 46 32 57 6
|
||||
11 14 27 20 35 5 8 76 130 156 270 80 140 165 287 187 325 23 39 52 90 66 115
|
||||
13 25 30 52 37 61 8 8 14 18 14 21 0 4 41 77 92 165 50 87 175 302 276 478
|
||||
101 176 208 360 236 408 28 49 67 117 86 152 19 35 41 70 48 77 6 6 12 15 12
|
||||
19 0 7 124 224 167 291 12 21 23 40 23 42 0 2 21 40 46 83 26 43 55 92 64 109
|
||||
54 95 327 568 354 614 19 30 45 75 59 100 71 128 82 145 89 148 4 2 8 8 8 13
|
||||
0 5 42 82 94 172 311 538 496 858 518 897 14 25 40 70 58 100 18 30 42 71 53
|
||||
90 10 19 79 139 152 265 73 127 142 246 153 265 10 19 43 76 72 125 29 50 63
|
||||
108 75 130 65 116 80 140 87 143 4 2 8 8 8 12 0 8 114 212 140 250 6 8 14 24
|
||||
20 35 5 11 54 97 108 190 l100 170 -9611 3 c-5286 1 -9614 -1 -9618 -5 -5 -6
|
||||
-419 -719 -619 -1068 -89 -155 -267 -463 -323 -560 -38 -66 -81 -140 -95 -165
|
||||
-31 -56 -263 -457 -526 -910 -110 -190 -224 -388 -254 -440 -29 -52 -61 -109
|
||||
-71 -125 -23 -39 -243 -420 -268 -465 -11 -19 -204 -352 -428 -740 -224 -388
|
||||
-477 -826 -563 -975 -85 -148 -185 -322 -222 -385 -37 -63 -120 -207 -185
|
||||
-320 -65 -113 -177 -306 -248 -430 -72 -124 -172 -297 -222 -385 -51 -88 -142
|
||||
-245 -202 -350 -131 -226 -247 -427 -408 -705 -65 -113 -249 -432 -410 -710
|
||||
-160 -278 -388 -673 -506 -877 -118 -205 -216 -373 -219 -373 -3 0 -52 82
|
||||
-109 183 -58 100 -144 250 -192 332 -95 164 -402 696 -647 1120 -85 149 -228
|
||||
396 -317 550 -212 365 -982 1700 -1008 1745 -10 19 -43 76 -72 125 -29 50 -64
|
||||
110 -77 135 -14 25 -63 110 -110 190 -47 80 -96 165 -110 190 -14 25 -99 171
|
||||
-188 325 -89 154 -174 300 -188 325 -13 25 -64 113 -112 195 -48 83 -140 242
|
||||
-205 355 -65 113 -183 317 -263 454 -79 137 -152 264 -163 282 -50 89 -335
|
||||
583 -354 614 -12 19 -34 58 -50 85 -15 28 -129 226 -253 440 -124 215 -235
|
||||
408 -247 430 -12 22 -69 121 -127 220 -58 99 -226 389 -373 645 -148 256 -324
|
||||
561 -392 678 -67 117 -134 232 -147 255 -13 23 -33 59 -46 80 l-22 37 -9615 0
|
||||
-9615 0 20 -32z"/>
|
||||
<path d="M4368 10130 c-61 -11 -108 -40 -141 -87 -28 -42 -61 -135 -71 -203
|
||||
-4 -25 -22 -126 -41 -225 -18 -99 -38 -220 -43 -270 -17 -154 -83 -600 -90
|
||||
-606 -11 -10 -563 -242 -576 -242 -6 0 -210 157 -452 349 -242 193 -457 361
|
||||
-478 374 -104 63 -210 33 -351 -100 -33 -31 -96 -83 -140 -116 -93 -69 -300
|
||||
-273 -544 -537 -327 -355 -390 -449 -377 -565 8 -65 32 -104 156 -252 104
|
||||
-125 402 -513 518 -677 l73 -102 -76 -144 c-53 -102 -90 -189 -125 -300 -50
|
||||
-153 -50 -155 -82 -161 -18 -3 -287 -44 -598 -91 -311 -47 -583 -92 -605 -101
|
||||
-54 -21 -72 -39 -109 -109 l-31 -60 0 -790 0 -790 30 -44 c60 -88 68 -90 742
|
||||
-193 329 -50 600 -92 601 -94 2 -1 14 -45 28 -96 34 -135 64 -212 156 -396
|
||||
l81 -163 -35 -37 c-19 -20 -75 -89 -123 -152 -49 -63 -139 -178 -200 -255 -61
|
||||
-77 -131 -169 -155 -205 -24 -36 -75 -102 -113 -147 -52 -62 -74 -98 -88 -144
|
||||
-41 -132 -20 -197 118 -369 189 -235 897 -930 1030 -1011 48 -29 65 -33 115
|
||||
-32 73 1 65 -4 620 429 l427 334 150 -74 c82 -42 209 -98 282 -126 73 -28 134
|
||||
-52 136 -53 1 -2 45 -268 98 -592 52 -325 103 -614 113 -644 14 -44 28 -63 74
|
||||
-102 53 -44 61 -48 130 -54 40 -3 393 -5 783 -3 l710 3 55 32 c31 17 65 42 77
|
||||
55 32 34 70 178 88 334 9 76 17 140 19 143 9 15 75 435 81 516 7 95 33 306 38
|
||||
311 2 2 70 28 153 58 82 30 215 86 297 124 l147 71 438 -348 c240 -191 457
|
||||
-361 482 -377 25 -17 63 -34 85 -37 50 -8 130 15 165 47 14 13 61 47 105 76
|
||||
44 29 130 101 190 159 61 59 131 122 156 141 25 19 64 59 85 88 21 30 64 77
|
||||
94 104 88 80 287 297 338 368 25 36 67 88 92 115 76 82 102 130 108 201 4 54
|
||||
1 69 -24 118 -15 31 -52 84 -82 118 -30 34 -72 87 -95 117 -113 157 -345 461
|
||||
-378 498 -21 23 -52 66 -68 96 -17 29 -46 71 -64 92 l-34 39 48 101 c41 86
|
||||
137 325 185 461 l15 41 612 92 c337 51 623 99 637 106 33 18 100 116 111 163
|
||||
11 46 11 1502 0 1558 -4 23 -26 65 -50 96 -39 53 -46 57 -109 72 -37 9 -317
|
||||
54 -622 102 -305 47 -558 89 -562 92 -3 4 -40 93 -82 197 -41 105 -100 246
|
||||
-130 314 l-55 125 38 45 c20 25 52 73 70 106 19 33 57 87 85 120 29 33 77 96
|
||||
108 140 31 44 97 130 148 190 51 61 105 135 120 165 15 30 43 69 60 85 72 67
|
||||
107 156 92 237 -6 29 -28 70 -69 125 -34 45 -75 106 -92 135 -53 93 -905 937
|
||||
-1010 1003 -59 36 -178 21 -231 -29 -28 -27 -649 -508 -871 -674 l-56 -42
|
||||
-139 63 c-76 35 -204 90 -284 122 -80 32 -149 61 -153 65 -4 4 -51 290 -103
|
||||
636 l-95 629 -32 33 c-18 18 -54 47 -82 65 l-50 32 -740 2 c-407 0 -761 -3
|
||||
-787 -7z m1022 -3360 c119 -22 329 -88 441 -139 143 -65 424 -286 520 -408 29
|
||||
-38 74 -90 100 -118 72 -77 123 -170 188 -342 100 -265 131 -417 131 -638 0
|
||||
-239 -32 -394 -138 -671 -58 -151 -105 -232 -208 -361 -162 -202 -379 -381
|
||||
-609 -501 -67 -35 -301 -102 -440 -126 -118 -21 -395 -21 -501 -1 -147 28
|
||||
-377 97 -453 135 -195 98 -474 328 -622 514 -86 108 -219 386 -276 579 l-28
|
||||
92 0 325 c0 324 0 325 28 427 30 111 89 258 169 416 85 171 303 398 553 576
|
||||
89 64 135 88 240 129 262 101 398 129 626 131 127 1 192 -4 279 -19z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 3.3 KiB |
@@ -5,17 +5,20 @@
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||
<meta itemprop="name">
|
||||
<meta property="og:title">
|
||||
<meta name="twitter:title">
|
||||
<meta name="description"/>
|
||||
<meta itemprop="description">
|
||||
<meta property="og:description">
|
||||
<meta name="twitter:description">
|
||||
<meta itemprop="image">
|
||||
<meta property="og:image">
|
||||
<meta name="twitter:image">
|
||||
<title>IT Tools - Set of handy developer tools</title>
|
||||
<link rel="canonical" href="https://it-tools.tech">
|
||||
<meta itemprop="name" content="IT-Tools">
|
||||
<meta property="og:title" content="IT-Tools">
|
||||
<meta name="twitter:title" content="IT-Tools">
|
||||
<meta name="description" content="Aggregated set of useful tools that every developer may need once in a while.">
|
||||
<meta itemprop="description" content="Aggregated set of useful tools that every developer may need once in a while.">
|
||||
<meta property="og:description" content="Aggregated set of useful tools that every developer may need once in a while.">
|
||||
<meta name="twitter:description" content="Aggregated set of useful tools that every developer may need once in a while.">
|
||||
<meta itemprop="image" content="/img/banner.png">
|
||||
<meta property="og:image" content="/img/banner.png">
|
||||
<meta name="twitter:image" content="/img/banner.png">
|
||||
<link rel="author" href="humans.txt" />
|
||||
<meta name="robots" content="noindex">
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
|
||||
19
public/manifest.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "IT Tools",
|
||||
"short_name": "IT Tools",
|
||||
"icons": [
|
||||
{
|
||||
"src": "./img/icons/android-chrome-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "./img/icons/android-chrome-512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
}
|
||||
],
|
||||
"theme_color": "#4bae50",
|
||||
"background_color": "#121212",
|
||||
"display": "standalone"
|
||||
}
|
||||
@@ -1,2 +1,2 @@
|
||||
User-agent: *
|
||||
Disallow:
|
||||
Disallow: *
|
||||
|
||||
72
src/App.vue
@@ -1,23 +1,24 @@
|
||||
<template>
|
||||
<v-app id="inspire">
|
||||
<vue-headful
|
||||
:title="currentRoute ? `${currentRoute.text} - IT-Tools` : 'IT-Tools'"
|
||||
:description="currentRoute ? currentRoute.description: 'Aggregated set of useful tools that every developer may need once in a while.'"
|
||||
:keywords="currentRoute ? currentRoute.keywords: null"
|
||||
image="/img/banner.png"
|
||||
:title="currentRoute ? `${currentRoute.text} - IT Tools` : 'IT Tools - Set of handy developer tools'"
|
||||
:description="currentRoute ? currentRoute.description: 'Aggregated set of useful tools that every developer may need once in a while.'"
|
||||
:keywords="currentRoute ? currentRoute.keywords: null"
|
||||
image="/img/banner.png"
|
||||
/>
|
||||
<v-navigation-drawer v-model="drawer" app clipped>
|
||||
<template v-slot:prepend>
|
||||
<SearchBar class="hidden-sm-and-up"/>
|
||||
</template>
|
||||
|
||||
<SearchBar class="hidden-sm-and-up" />
|
||||
|
||||
<v-list dense>
|
||||
<v-list dense id="navigation-list">
|
||||
|
||||
<div v-for="section in items" :key="section.title">
|
||||
<v-subheader class="mt-4 pl-4">{{section.title}}</v-subheader>
|
||||
|
||||
<v-list-item v-for="item in section.child" :key="item.text" :to="item.path">
|
||||
<v-list-item-action>
|
||||
<v-icon>{{ item.icon }}</v-icon>
|
||||
<v-icon style="width: 1.25em">{{ item.icon }}</v-icon>
|
||||
</v-list-item-action>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>
|
||||
@@ -99,7 +100,7 @@
|
||||
appVersion: 'v' + process.env.APPLICATION_VERSION,
|
||||
drawer: null,
|
||||
items: toolsComponents,
|
||||
currentRoute:{}
|
||||
currentRoute: {}
|
||||
}),
|
||||
mounted() {
|
||||
this.setTitle()
|
||||
@@ -107,14 +108,14 @@
|
||||
created() {
|
||||
this.$vuetify.theme.dark = true
|
||||
},
|
||||
methods:{
|
||||
setTitle(){
|
||||
methods: {
|
||||
setTitle() {
|
||||
const path = this.$router.currentRoute.path;
|
||||
this.currentRoute = toolsComponents.map(p => p.child).flat().find(p => p.path === path)
|
||||
}
|
||||
},
|
||||
watch:{
|
||||
'$route'(){
|
||||
watch: {
|
||||
'$route'() {
|
||||
this.setTitle()
|
||||
}
|
||||
}
|
||||
@@ -125,6 +126,51 @@
|
||||
html {
|
||||
overflow-y: auto !important;
|
||||
}
|
||||
code{
|
||||
background-color: rgba(0, 0, 0, 0.15) !important;
|
||||
box-shadow: none !important;
|
||||
color: #9a9a9a !important;
|
||||
font-weight: normal !important;
|
||||
}
|
||||
.pretty-scrollbar{
|
||||
&::-webkit-scrollbar {
|
||||
width: 5px!important;
|
||||
height: 5px !important;
|
||||
}
|
||||
|
||||
/* Track */
|
||||
&::-webkit-scrollbar-track {
|
||||
opacity: 0 !important;
|
||||
}
|
||||
|
||||
/* Handle */
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: rgba(241, 241, 241, 0.10) !important;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
/* Handle on hover */
|
||||
&::-webkit-scrollbar-thumb:hover {
|
||||
background: rgba(241, 241, 241, 0.20)!important;
|
||||
}
|
||||
}
|
||||
|
||||
#navigation-list{
|
||||
div:first-child .v-subheader{
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
|
||||
.v-list-item__action{
|
||||
margin: 8px 25px 8px 0;
|
||||
.v-icon{
|
||||
color: #4CAF50 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.v-navigation-drawer__content{
|
||||
.pretty-scrollbar;
|
||||
}
|
||||
|
||||
.single-card {
|
||||
width: 100%;
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
<p class="text-justify">
|
||||
Welcome to <strong>IT-Tools</strong>! This wonderful website, originally created with ❤ by
|
||||
<a href="//corentin-thomasset.fr">Corentin Thomasset</a>, aggregate a set of useful tools
|
||||
that every developer may need once in a while.
|
||||
that every developer may need once in a while. And don't forget to add <strong>IT-Tools</strong> to your
|
||||
shortcut bar (press <code>{{ isMacOS ? 'Cmd' : 'Ctrl' }} +
|
||||
D</code>).
|
||||
</p>
|
||||
|
||||
|
||||
@@ -30,7 +32,10 @@
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "Abstract"
|
||||
name: "Abstract",
|
||||
data: () => ({
|
||||
isMacOS: navigator.platform.toUpperCase().indexOf('MAC') >= 0
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
58
src/components/ColorInput.vue
Normal file
@@ -0,0 +1,58 @@
|
||||
<template>
|
||||
<v-text-field v-model="color" hide-details class="ma-0 pa-0" outlined :label="label" v-on:input="$emit('input', color)">
|
||||
<template v-slot:append>
|
||||
<v-menu v-model="menu" top nudge-bottom="101" nudge-left="16" :close-on-content-click="false">
|
||||
<template v-slot:activator="{ on }">
|
||||
<div :style="swatchStyle" v-on="on" />
|
||||
</template>
|
||||
<v-card>
|
||||
<v-card-text class="pa-0">
|
||||
<v-color-picker v-model="color" flat v-on:input="$emit('input', color)"/>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-menu>
|
||||
</template>
|
||||
</v-text-field>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// From: https://codepen.io/JamieCurnow/pen/KKPjraK
|
||||
|
||||
export default {
|
||||
name: "ColorInput",
|
||||
props:{
|
||||
value: {
|
||||
type: String,
|
||||
default: '#FFFFFF'
|
||||
},
|
||||
label:String
|
||||
},
|
||||
data: () => ({
|
||||
menu: false,
|
||||
color:''
|
||||
}),
|
||||
mounted() {
|
||||
this.color = this.value
|
||||
},
|
||||
computed: {
|
||||
swatchStyle() {
|
||||
const { color, menu } = this
|
||||
return {
|
||||
backgroundColor: color,
|
||||
cursor: 'pointer',
|
||||
height: '30px',
|
||||
width: '30px',
|
||||
borderRadius: menu ? '50%' : '4px',
|
||||
transition: 'border-radius 200ms ease-in-out'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
::v-deep .v-input__append-inner{
|
||||
margin-top: 13px;
|
||||
}
|
||||
|
||||
</style>
|
||||
43
src/components/CopyableCodeContent.vue
Normal file
@@ -0,0 +1,43 @@
|
||||
<template>
|
||||
<div class="copyable-code-content" @click="copy($slots.default[0].text)">
|
||||
<pre class="pretty-scrollbar"><slot></slot></pre>
|
||||
<v-icon>far fa-copy</v-icon>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {copyable} from "../mixins/copyable.mixin";
|
||||
|
||||
export default {
|
||||
name: "CopyableCodeContent",
|
||||
mixins: [copyable]
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.copyable-code-content {
|
||||
cursor: pointer;
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
border-radius: 4px;
|
||||
padding: 8px 15px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
pre {
|
||||
flex: 1;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.v-icon {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.v-icon {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
49
src/components/GithubContributors.vue
Normal file
@@ -0,0 +1,49 @@
|
||||
<template>
|
||||
<div class="github-contributor">
|
||||
|
||||
<div v-if="loading" class="text-center pt-3 pb-3">
|
||||
<v-progress-circular indeterminate />
|
||||
</div>
|
||||
|
||||
<v-list v-else class="pa-0">
|
||||
<v-list-item v-for="(contributor, i) in contributors" :key="i" :href="contributor.html_url">
|
||||
<v-list-item-avatar>
|
||||
<v-img :src="contributor.avatar_url"></v-img>
|
||||
</v-list-item-avatar>
|
||||
<v-list-item-content>
|
||||
{{contributor.login}}
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
const baseUrl = 'https://api.github.com/repos/$repo$/contributors'
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
name: "GithubContributors",
|
||||
props: ['repo'],
|
||||
data: () => ({
|
||||
contributors: [],
|
||||
loading: true,
|
||||
hasError: false
|
||||
}),
|
||||
mounted() {
|
||||
const url = baseUrl.replace('$repo$', this.repo)
|
||||
|
||||
axios
|
||||
.get(url)
|
||||
.then(({data}) => {
|
||||
this.contributors = data.sort((a, b) => b.contributions - a.contributions)
|
||||
this.loading = false
|
||||
})
|
||||
.catch(() => this.hasError = true)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
73
src/components/MemoViewer.vue
Normal file
@@ -0,0 +1,73 @@
|
||||
<template>
|
||||
<div class="memo-viewer" v-bind:style="{ columns: `auto ${colWidth}` }">
|
||||
<div class="section" v-for="(group,i) in memo" :key="i">
|
||||
<h2>{{group.section}}</h2>
|
||||
|
||||
<div class="tip" v-for="(tips,i) in group.child" :key="i">
|
||||
<v-card>
|
||||
<v-card-text>
|
||||
<template v-for="tip in (Array.isArray(tips) ? tips : [tips])">
|
||||
<p :key="tip.text">{{tip.text}}</p>
|
||||
<CopyableCodeContent class="code" :key="tip.code">{{tip.code}}</CopyableCodeContent>
|
||||
</template>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CopyableCodeContent from "./CopyableCodeContent";
|
||||
|
||||
export default {
|
||||
name: "MemoViewer",
|
||||
props: {
|
||||
memo: Array,
|
||||
colWidth: {
|
||||
type: String,
|
||||
default: '400px'
|
||||
}
|
||||
},
|
||||
components: {
|
||||
CopyableCodeContent
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.memo-viewer {
|
||||
column-gap: 30px;
|
||||
column-rule: 1px solid #37373961;
|
||||
column-fill: auto;
|
||||
|
||||
}
|
||||
.section {
|
||||
break-inside: avoid-column;
|
||||
display: inline-block;
|
||||
margin-bottom: 20px;
|
||||
width: 100%;
|
||||
|
||||
h2 {
|
||||
margin: 25px 0 15px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.tip {
|
||||
margin: 20px 0;
|
||||
|
||||
.v-card{
|
||||
background-color: rgba(47, 46, 46, 0.44);
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 10px;
|
||||
|
||||
&:not(:first-child){
|
||||
margin-top: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -8,6 +8,7 @@ import '@fortawesome/fontawesome-free/css/all.css'
|
||||
import './plugins/crypto-js'
|
||||
import './plugins/toast-snackbar'
|
||||
import './plugins/vue-headful'
|
||||
import './plugins/vue-analytics'
|
||||
|
||||
Vue.config.productionTip = false
|
||||
|
||||
|
||||
10
src/mixins/copyable.mixin.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import {copyToClipboard} from "../utils/helpers";
|
||||
|
||||
export const copyable = {
|
||||
methods: {
|
||||
copy(text, toastText = 'Copied to clipboard !'){
|
||||
copyToClipboard(text);
|
||||
this.$toast.success(toastText)
|
||||
}
|
||||
}
|
||||
}
|
||||
16
src/plugins/vue-analytics.js
Normal file
@@ -0,0 +1,16 @@
|
||||
import Vue from 'vue'
|
||||
import VueAnalytics from 'vue-analytics'
|
||||
import router from "../router";
|
||||
|
||||
if(process.env.VUE_APP_GANALYTICS){
|
||||
Vue.use(VueAnalytics, {
|
||||
id: process.env.VUE_APP_GANALYTICS,
|
||||
router,
|
||||
set:[
|
||||
{
|
||||
field: 'dimension1',
|
||||
value: process.env.APPLICATION_VERSION
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
@@ -20,7 +20,8 @@ if (process.env.NODE_ENV === 'production') {
|
||||
console.log('New content is downloading.')
|
||||
},
|
||||
updated () {
|
||||
console.log('New content is available; please refresh.')
|
||||
console.log('New content is available; hard refresh.');
|
||||
window.location.reload(true);
|
||||
},
|
||||
offline () {
|
||||
console.log('No internet connection found. App is running in offline mode.')
|
||||
|
||||
106
src/router.js
@@ -1,20 +1,9 @@
|
||||
import Vue from 'vue'
|
||||
import VueRouter from 'vue-router'
|
||||
import Home from './routes/Home.vue'
|
||||
import TokenGenerator from "./routes/tools/TokenGenerator";
|
||||
import Hash from "./routes/tools/Hash";
|
||||
import DateConverter from "./routes/tools/DateConverter";
|
||||
import UrlEncoder from "./routes/tools/UrlEncoder";
|
||||
import FileToBase64 from "./routes/tools/FileToBase64";
|
||||
import TextCypher from "./routes/tools/TextCypher";
|
||||
import TextStats from "./routes/tools/TextStats";
|
||||
import BaseConverter from "./routes/tools/BaseConverter";
|
||||
import UuidGenerator from "./routes/tools/UuidGenerator";
|
||||
import ColorConverter from "./routes/tools/ColorConverter";
|
||||
|
||||
Vue.use(VueRouter)
|
||||
|
||||
|
||||
const toolsComponents = [
|
||||
{
|
||||
title: 'Crypto',
|
||||
@@ -23,7 +12,7 @@ const toolsComponents = [
|
||||
icon: 'fa-key',
|
||||
text: 'Token generator',
|
||||
path: '/token-generator',
|
||||
component: TokenGenerator,
|
||||
component: () => import('./routes/tools/TokenGenerator'),
|
||||
keywords: ['token', 'random', 'string', 'alphanumeric'],
|
||||
description: 'Generate random tokens.'
|
||||
},
|
||||
@@ -31,14 +20,14 @@ const toolsComponents = [
|
||||
icon: 'fa-fingerprint',
|
||||
text: 'Uuid generator',
|
||||
path: '/uuid-generator',
|
||||
component: UuidGenerator,
|
||||
component: () => import('./routes/tools/UuidGenerator'),
|
||||
keywords: ['token', 'v4', 'string', 'alphanumeric']
|
||||
},
|
||||
{
|
||||
icon: 'fa-font',
|
||||
text: 'Hash text',
|
||||
path: '/hash',
|
||||
component: Hash,
|
||||
component: () => import('./routes/tools/Hash'),
|
||||
keywords: ['md5', 'sha1', 'sha256', 'sha224', 'sha512', 'sha384', 'sha3', 'ripemd160', 'random']
|
||||
|
||||
},
|
||||
@@ -46,9 +35,16 @@ const toolsComponents = [
|
||||
icon: 'fa-lock',
|
||||
text: 'Cypher/uncypher text',
|
||||
path: '/cypher',
|
||||
component: TextCypher,
|
||||
component: () => import('./routes/tools/TextCypher'),
|
||||
keywords: ['aes', 'tripledes', 'rabbit', 'rabbitlegacy', 'rc4']
|
||||
},
|
||||
{
|
||||
icon: 'fa-file-word',
|
||||
text: 'BIP39 passphrase generator',
|
||||
path: '/bip39-generator',
|
||||
component: () => import('./routes/tools/BIP39Generator'),
|
||||
keywords: []
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -58,21 +54,21 @@ const toolsComponents = [
|
||||
icon: 'fa-calendar',
|
||||
text: 'Date/Time converter',
|
||||
path: '/date-converter',
|
||||
component: DateConverter,
|
||||
component: () => import('./routes/tools/DateConverter'),
|
||||
keywords: ['locale', 'format', 'iso 8601', 'utc', 'timestamp', 'unix', 'year', 'month', 'day', 'hours', 'minutes', 'seconds']
|
||||
},
|
||||
{
|
||||
icon: 'fa-exchange-alt',
|
||||
text: 'Base converter',
|
||||
path: '/base-converter',
|
||||
component: BaseConverter,
|
||||
component: () => import('./routes/tools/BaseConverter'),
|
||||
keywords: ['binary', 'hexadecimal', 'decimal']
|
||||
},
|
||||
{
|
||||
icon: 'fa-palette',
|
||||
text: 'Color picker/converter',
|
||||
path: '/color-picker-converter',
|
||||
component: ColorConverter,
|
||||
component: () => import('./routes/tools/ColorConverter'),
|
||||
keywords: ['rgb', 'rgba', 'hexadecimal', 'hsla', 'red', 'green', 'blue', 'alpha']
|
||||
},
|
||||
],
|
||||
@@ -84,28 +80,79 @@ const toolsComponents = [
|
||||
icon: 'fa-link',
|
||||
text: 'URL encode/decode',
|
||||
path: '/url-encoder',
|
||||
component: UrlEncoder,
|
||||
component: () => import('./routes/tools/UrlEncoder'),
|
||||
keywords: ['%20']
|
||||
},
|
||||
{
|
||||
icon: 'fa-file-export',
|
||||
text: 'File to Base64',
|
||||
path: '/file-to-base64',
|
||||
component: FileToBase64
|
||||
component: () => import('./routes/tools/FileToBase64')
|
||||
},
|
||||
{
|
||||
icon: 'fa-file-alt',
|
||||
text: 'Base64 string converter',
|
||||
path: '/base64-string-converter',
|
||||
component: () => import('./routes/tools/StringToBase64')
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Text',
|
||||
child: [
|
||||
{
|
||||
icon: 'fa-align-left',
|
||||
text: 'Text stats',
|
||||
path: '/text-stats',
|
||||
component: () => import('./routes/tools/TextStats'),
|
||||
keywords: ['word', 'count', 'size', 'bytes', 'length']
|
||||
},
|
||||
{
|
||||
icon: 'fab fa-markdown',
|
||||
text: 'Markdown editor',
|
||||
path: '/markdown-editor',
|
||||
component: () => import('./routes/tools/MarkdownEditor'),
|
||||
keywords: ['text', 'html', 'markdown']
|
||||
},
|
||||
{
|
||||
icon: 'fa-align-justify',
|
||||
text: 'Lorem ipsum generator',
|
||||
path: '/lorem-ipsum-generator',
|
||||
component: () => import('./routes/tools/LoremIpsumGenerator'),
|
||||
keywords: ['text', 'dolor', 'sit', 'placeholder', 'fill', 'dummy']
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Memos',
|
||||
child: [
|
||||
{
|
||||
text: 'Git memo',
|
||||
path: '/git-memo',
|
||||
icon: 'fa-code-branch',
|
||||
component: () => import('./routes/tools/GitMemo'),
|
||||
keywords: ['git', 'push', 'rebase', 'merge', 'tag', 'commit', 'checkout']
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: 'Miscellaneous',
|
||||
child: [
|
||||
{
|
||||
icon: 'fa-align-left\n',
|
||||
text: 'Text stats',
|
||||
path: '/text-stats',
|
||||
component: TextStats,
|
||||
keywords: ['word', 'count', 'size', 'bytes', 'length']
|
||||
text: 'Crontab generator',
|
||||
path: '/crontab-generator',
|
||||
icon: 'fa-clock',
|
||||
component: () => import('./routes/tools/CrontabGenerator'),
|
||||
keywords: ['Cron', 'Schedule']
|
||||
},
|
||||
],
|
||||
{
|
||||
text: 'QR Code generator',
|
||||
path: '/qrcode-generator',
|
||||
icon: 'fa-qrcode',
|
||||
component: () => import('./routes/tools/QRCodeGenerator'),
|
||||
keywords: []
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
@@ -121,12 +168,17 @@ const routes = [
|
||||
path: '/about',
|
||||
name: 'About',
|
||||
component: () => import('./routes/About.vue')
|
||||
},
|
||||
{
|
||||
path: '*',
|
||||
name: '404',
|
||||
component: () => import('./routes/NotFound.vue')
|
||||
}
|
||||
]
|
||||
|
||||
const router = new VueRouter({
|
||||
mode: 'history',
|
||||
base: process.env.BASE_URL,
|
||||
mode: 'history',
|
||||
routes
|
||||
});
|
||||
|
||||
|
||||
@@ -1,19 +1,63 @@
|
||||
<template>
|
||||
<v-card class="single-card">
|
||||
<v-card-title>About</v-card-title>
|
||||
<v-card-text>
|
||||
<Abstract />
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
<div>
|
||||
<v-row justify="center" align="center">
|
||||
<v-col cols="12" xl="12">
|
||||
<v-card class="single-card">
|
||||
<v-card-title>About</v-card-title>
|
||||
<v-card-text>
|
||||
<Abstract/>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
|
||||
</v-row>
|
||||
<v-row justify="center">
|
||||
<v-col cols="12" md="5" sm="12">
|
||||
<v-card>
|
||||
<v-card-title>Contributors</v-card-title>
|
||||
<github-contributors repo="CorentinTh/it-tools"/>
|
||||
</v-card>
|
||||
</v-col>
|
||||
<v-col cols="12" md="7" sm="12">
|
||||
<v-card>
|
||||
<v-card-title>Changelog</v-card-title>
|
||||
<v-card-text>
|
||||
<div v-html="changelog" class="changelog">
|
||||
</div>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Abstract from "../components/Abstract";
|
||||
import Abstract from "../components/Abstract";
|
||||
import GithubContributors from "../components/GithubContributors";
|
||||
import changelog from "../../CHANGELOG.md"
|
||||
import marked from 'marked'
|
||||
import DOMPurify from 'dompurify';
|
||||
|
||||
export default {
|
||||
name: "About",
|
||||
components : {
|
||||
Abstract
|
||||
},
|
||||
}
|
||||
</script>
|
||||
export default {
|
||||
name: "About",
|
||||
data: () => ({
|
||||
changelog: []
|
||||
}),
|
||||
mounted() {
|
||||
this.changelog = DOMPurify.sanitize(marked('##' + changelog.replace(/^(.*?)##/s, '')));
|
||||
},
|
||||
components: {
|
||||
Abstract,
|
||||
GithubContributors
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
::v-deep {
|
||||
.changelog {
|
||||
h2 {
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -9,9 +9,7 @@
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-row justify="center" align="center">
|
||||
<v-col cols="12" lg="8" md="12">
|
||||
<v-col cols="12" lg="5" md="12">
|
||||
<v-card class="card-auto">
|
||||
<v-card-text>
|
||||
<div class="card-wrapper ">
|
||||
@@ -56,7 +54,7 @@
|
||||
flex-wrap: wrap;
|
||||
|
||||
div {
|
||||
flex: 0 1 20%;
|
||||
flex: 0 1 33%;
|
||||
|
||||
@media only screen and (max-width: 800px) {
|
||||
flex: 0 1 33%;
|
||||
|
||||
54
src/routes/NotFound.vue
Normal file
@@ -0,0 +1,54 @@
|
||||
<template>
|
||||
<div class="e404">
|
||||
<div class="e404-image">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 100 511.999 300" xml:space="preserve">
|
||||
<g><path d="M140.61,273.063h-5.956v-22.69c0-11.623-10.593-19.433-26.358-19.433s-26.357,7.81-26.357,19.433v22.69H65.571 l25.677-100.707c1.101-2.746,1.194-5.749,1.186-8.392l-0.001-0.284c0-15.632-22.966-20.737-30.881-20.737 c-10.132,0-18.414,5.148-22.723,14.123c-0.199,0.415-0.359,0.847-0.481,1.29C0,298.98,0,300.981,0,302.305 c0,12.096,8.537,20.876,20.297,20.876H33.97c4.2,0,7.604-3.405,7.604-7.604c0-4.199-3.404-7.604-7.604-7.604H20.297 c-3.184,0-4.887-1.694-5.072-5.04c1.954-8.608,23.256-87.252,37.593-139.831c1.785-3.288,4.721-4.954,8.734-4.954 c5.289,0,14.355,3.338,15.673,5.732l0.001,0.128c0.001,0.584,0.006,2.084-0.132,2.756c-0.178,0.397-0.321,0.809-0.43,1.231 L48.417,278.788c-0.58,2.275-0.076,4.69,1.365,6.544c1.44,1.854,3.656,2.938,6.004,2.938h33.757c4.2,0,7.604-3.405,7.604-7.604 v-30.294c0-2.528,5.766-4.225,11.149-4.225c5.481,0,11.15,1.581,11.15,4.225v30.294c0,4.199,3.404,7.604,7.604,7.604h13.56 c2.252,0,4.226,4.671,4.226,9.996c0,5.013-3.022,9.171-4.382,9.708H127.05c-4.2,0-7.604,3.405-7.604,7.604v34.045 c0,1.954-4.872,4.225-11.15,4.225c-6.467,0-11.149-2.523-11.149-4.225v-34.045c0-4.199-3.404-7.604-7.604-7.604H59.318 c-4.2,0-7.604,3.405-7.604,7.604c0,4.199,3.404,7.604,7.604,7.604h22.621v26.441c0,11.26,11.086,19.433,26.357,19.433 c15.52,0,26.358-7.991,26.358-19.433v-26.441h5.956c9.192,0,19.434-10.232,19.434-24.916 C160.043,283.663,151.87,273.063,140.61,273.063z"/></g>
|
||||
<g><path d="M492.566,273.063h-5.956v-22.69c0-11.623-10.593-19.433-26.358-19.433s-26.357,7.81-26.357,19.433v22.69h-16.368 l25.679-100.708c1.1-2.745,1.193-5.75,1.185-8.393l-0.001-0.281c0-15.632-22.966-20.737-30.881-20.737 c-10.132,0-18.415,5.148-22.724,14.123c-0.199,0.415-0.359,0.847-0.481,1.29c0,0-4.869,17.852-11.125,40.898 c0,0.001,0,0.002-0.001,0.003l-7.879,29.071c-19.345,71.527-19.345,72.449-19.345,73.978c0,12.096,8.537,20.876,20.298,20.876 h61.64v26.441c0,11.26,11.085,19.433,26.357,19.433c15.52,0,26.358-7.991,26.358-19.433v-26.441h5.956 c9.192,0,19.434-10.232,19.434-24.915C512,283.663,503.826,273.063,492.566,273.063z M492.41,307.974h-13.404 c-4.2,0-7.604,3.405-7.604,7.604v34.045c0,1.954-4.872,4.225-11.15,4.225c-6.467,0-11.149-2.523-11.149-4.225v-34.045 c0-4.199-3.404-7.604-7.604-7.604h-69.244c-3.183,0-4.887-1.694-5.073-5.037c0.677-2.966,4.201-16.655,18.801-70.634l7.877-29.064 c5.504-20.276,9.934-36.53,10.916-40.133c1.785-3.288,4.721-4.954,8.735-4.954c5.289,0,14.354,3.338,15.673,5.732l0.001,0.124 c0.001,0.585,0.006,2.09-0.133,2.762c-0.177,0.396-0.32,0.808-0.429,1.23l-28.249,110.79c-0.58,2.275-0.076,4.69,1.365,6.544 c1.44,1.854,3.656,2.938,6.004,2.938H441.5c4.2,0,7.604-3.405,7.604-7.604v-30.294c0-2.528,5.766-4.225,11.149-4.225 c5.481,0,11.15,1.581,11.15,4.225v30.294c0,4.199,3.404,7.604,7.604,7.604h13.56c2.252,0,4.226,4.671,4.226,9.996 C496.792,303.281,493.769,307.437,492.41,307.974z"/></g>
|
||||
<g><path d="M330.892,206.939c-2.512-3.363-7.279-4.051-10.642-1.536c-3.362,2.515-4.05,7.281-1.535,10.643 c10.168,13.597,15.542,29.786,15.542,46.818c0,43.149-35.104,78.252-78.252,78.252c-43.15,0-78.253-35.104-78.253-78.252 c0-43.149,35.104-78.253,78.253-78.253c17.152,0,33.434,5.444,47.083,15.744c3.353,2.53,8.122,1.863,10.651-1.49 c2.529-3.352,1.862-8.12-1.49-10.65c-16.311-12.307-35.76-18.812-56.245-18.812c-51.534,0-93.461,41.927-93.461,93.461 s41.927,93.46,93.461,93.46c51.534,0,93.46-41.926,93.46-93.46C349.464,242.523,343.042,223.185,330.892,206.939z"/></g>
|
||||
<g><path d="M296.624,292.726l-29.863-29.863L296.624,233c2.968-2.969,2.968-7.783-0.002-10.753c-2.971-2.97-7.784-2.97-10.754,0 l-29.863,29.863l-29.863-29.863c-2.971-2.97-7.784-2.97-10.754,0c-2.97,2.97-2.97,7.784,0,10.753l29.863,29.863l-29.863,29.863 c-2.97,2.97-2.97,7.784,0,10.753c1.485,1.484,3.432,2.227,5.378,2.227c1.946,0,3.892-0.742,5.377-2.227l29.863-29.863 l29.863,29.863c1.485,1.484,3.432,2.227,5.377,2.227s3.892-0.742,5.378-2.227C299.593,300.51,299.593,295.695,296.624,292.726z"/></g>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="separator"></div>
|
||||
<div class="e404-description">
|
||||
Page not found, sorry.
|
||||
</div>
|
||||
<v-btn color="primary" @click="$router.go(-1)">Back</v-btn>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "404.vue"
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.e404 {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.e404-image {
|
||||
width: 200px;
|
||||
|
||||
svg {
|
||||
fill: #ffffff;
|
||||
opacity: 0.3;
|
||||
}
|
||||
}
|
||||
|
||||
.separator {
|
||||
width: 60px;
|
||||
height: 3px;
|
||||
border-radius: 5px;
|
||||
background-color: #4CAF50;
|
||||
}
|
||||
|
||||
.e404-description {
|
||||
font-size: 30px;
|
||||
opacity: 0.9;
|
||||
margin: 15px 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
99
src/routes/tools/BIP39Generator.vue
Normal file
@@ -0,0 +1,99 @@
|
||||
<template>
|
||||
<v-card class="single-card">
|
||||
<v-card-title>BIP39 passphrase generator</v-card-title>
|
||||
<v-card-text>
|
||||
<v-select
|
||||
outlined
|
||||
label="Language"
|
||||
@change="languageChanged"
|
||||
:items="languageList"
|
||||
v-model="language"
|
||||
/>
|
||||
<v-text-field
|
||||
outlined
|
||||
v-model="entropy"
|
||||
label="Entropy"
|
||||
append-icon="fa-clipboard"
|
||||
@click:append="copy(entropy)"
|
||||
:rules="rules.entropy"
|
||||
ref="entropy"
|
||||
/>
|
||||
<v-text-field
|
||||
outlined
|
||||
v-model="passphrase"
|
||||
label="Passphrase"
|
||||
append-icon="fa-clipboard"
|
||||
@click:append="copy(passphrase)"
|
||||
:rules="rules.passphrase"
|
||||
ref="passphrase"
|
||||
/>
|
||||
<div class="text-center">
|
||||
<v-btn @click="refresh">refresh</v-btn>
|
||||
</div>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as bip39 from "bip39";
|
||||
import {copyable} from "../../mixins/copyable.mixin";
|
||||
|
||||
const shuffle = (str) => str.split('').sort(() => 0.5 - Math.random()).join('');
|
||||
|
||||
const getRandomBuffer = () => {
|
||||
return Buffer.from(shuffle('0123456789abcdef'.repeat(16)).substring(0, 32), 'hex');
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'BIP39Generator',
|
||||
mixins: [copyable],
|
||||
data: () => ({
|
||||
buffer: getRandomBuffer(),
|
||||
languageList: Object.keys(bip39.wordlists).filter(k => !k.match(/[A-Z]{2}/)).map(k => ({text: k.split('_').map(k => k.charAt(0).toUpperCase() + k.slice(1)).join(' '), value:k})),
|
||||
language: 'english',
|
||||
rules: {
|
||||
passphrase: [
|
||||
v => (!!v && bip39.validateMnemonic(v)) || 'Invalid mnemonic.'
|
||||
],
|
||||
entropy: [
|
||||
v => (!!v && !!v.match(/[0-9a-fA-F]{32}/)) || 'Invalid entropy.'
|
||||
]
|
||||
}
|
||||
}),
|
||||
methods:{
|
||||
refresh(){
|
||||
this.buffer = getRandomBuffer();
|
||||
},
|
||||
languageChanged(){
|
||||
bip39.setDefaultWordlist(this.language);
|
||||
this.passphrase = bip39.entropyToMnemonic(this.buffer)
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
entropy: {
|
||||
get() {
|
||||
return this.buffer.toString('hex')
|
||||
},
|
||||
set(value) {
|
||||
if(this.$refs.entropy.validate()) {
|
||||
this.buffer = Buffer.from(value, 'hex')
|
||||
}
|
||||
}
|
||||
},
|
||||
passphrase: {
|
||||
get() {
|
||||
return bip39.entropyToMnemonic(this.buffer)
|
||||
},
|
||||
set(value) {
|
||||
if(this.$refs.passphrase.validate()){
|
||||
this.buffer = Buffer.from(bip39.mnemonicToEntropy(value), 'hex')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -8,7 +8,8 @@
|
||||
label="Input base"
|
||||
outlined
|
||||
type="number"
|
||||
v-model="inputBase"
|
||||
v-model.number="inputBase"
|
||||
ref="inputBase"
|
||||
hide-details="auto"
|
||||
:rules="baseRules"
|
||||
/>
|
||||
@@ -32,7 +33,8 @@
|
||||
label="Output base"
|
||||
outlined
|
||||
type="number"
|
||||
v-model="outputBase"
|
||||
v-model.number="outputBase"
|
||||
ref="outputBase"
|
||||
:rules="baseRules"
|
||||
/>
|
||||
</v-col>
|
||||
@@ -54,7 +56,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {copyToClipboard} from "../../utils/helpers";
|
||||
import {copyToClipboard, isInt} from "../../utils/helpers";
|
||||
|
||||
const convertBase = (value, fromBase, toBase) => {
|
||||
const range = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/'.split('');
|
||||
@@ -83,12 +85,17 @@
|
||||
inputBase: 10,
|
||||
outputBase: 16,
|
||||
baseRules: [
|
||||
v => isInt(v) || 'Base should be an integer',
|
||||
v => !!v || 'Required',
|
||||
v => v > 1 || 'Base should be > 1',
|
||||
v => v <= 64 || 'Base should be <= 64',
|
||||
v => v <= 64 || 'Base should be <= 64'
|
||||
],
|
||||
isMounted: false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.isMounted = true;
|
||||
},
|
||||
methods: {
|
||||
copy() {
|
||||
copyToClipboard(this.outputNumber);
|
||||
@@ -97,10 +104,14 @@
|
||||
},
|
||||
computed: {
|
||||
outputNumber() {
|
||||
try{
|
||||
return convertBase(this.inputNumber, this.inputBase, this.outputBase)
|
||||
}catch (e) {
|
||||
return e.message;
|
||||
if(this.isMounted && this.$refs.inputBase.validate() && this.$refs.outputBase.validate()){
|
||||
try{
|
||||
return convertBase(this.inputNumber, this.inputBase, this.outputBase)
|
||||
}catch (e) {
|
||||
return e.message;
|
||||
}
|
||||
}else {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
hide-inputs
|
||||
mode="rgba"
|
||||
v-model="rgbPicker"
|
||||
@input="(v) => updateColors(v, 'picker')"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="6" align="center">
|
||||
@@ -116,7 +117,7 @@
|
||||
this.keyword = convert.rgb.keyword(r, g, b);
|
||||
},
|
||||
updateColors(value, fromType) {
|
||||
if (this.$refs[fromType].validate()) {
|
||||
if (fromType === 'picker' || this.$refs[fromType].validate()) {
|
||||
if (fromType === 'rgb') {
|
||||
const [r, g, b] = value.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/).slice(1).map(v => parseInt(v));
|
||||
this.rgbPicker = {r, g, b}
|
||||
@@ -150,6 +151,13 @@
|
||||
} catch (ignored) {
|
||||
// ignored
|
||||
}
|
||||
} else if (fromType === 'picker') {
|
||||
const {r, g, b} = value;
|
||||
|
||||
this.setRGB(r, g, b);
|
||||
this.setHEX(r, g, b);
|
||||
this.setHSL(r, g, b);
|
||||
this.setKeyword(r, g, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
221
src/routes/tools/CrontabGenerator.vue
Normal file
@@ -0,0 +1,221 @@
|
||||
<template>
|
||||
<v-row justify="center" align="center">
|
||||
<v-col cols="12" xl="5" lg="5" md="12">
|
||||
<v-card>
|
||||
<v-card-title>Crontab generator</v-card-title>
|
||||
<v-card-text>
|
||||
<div class="result">{{cronString}}</div>
|
||||
<v-text-field
|
||||
ref="cron"
|
||||
class="cron-wrapper"
|
||||
outlined
|
||||
v-model="cron"
|
||||
label="Cron"
|
||||
append-icon="fa-copy"
|
||||
@click:append="copy(cron)"
|
||||
:rules="[isCronValid]"
|
||||
hide-details="auto"
|
||||
/>
|
||||
|
||||
<v-checkbox
|
||||
hide-details
|
||||
label="Verbose"
|
||||
v-model="cronstrueConfig.verbose"
|
||||
/>
|
||||
<v-checkbox
|
||||
hide-details
|
||||
label="Use 24 hour time format"
|
||||
v-model="cronstrueConfig.use24HourTimeFormat"
|
||||
/>
|
||||
<v-checkbox
|
||||
hide-details
|
||||
label="Day of the week start a index 0"
|
||||
v-model="cronstrueConfig.dayOfWeekStartIndexZero"
|
||||
/>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
<v-col cols="12" xl="6" lg="7" md="12">
|
||||
<v-card>
|
||||
<v-card-title>Crontab helper</v-card-title>
|
||||
<v-card-text>
|
||||
<div class="text-center">
|
||||
<pre>
|
||||
┌────────── day of week (0 - 6, sunday=0) OR sun,mon ...
|
||||
| ┌──────── month (1 - 12) OR jan,feb,mar,apr ...
|
||||
| | ┌────── day of month (1 - 31)
|
||||
| | | ┌──── hour (0 - 23)
|
||||
| | | | ┌── minute (0 - 59)
|
||||
| | | | |
|
||||
* * * * * command
|
||||
</pre>
|
||||
</div>
|
||||
<br>
|
||||
<v-simple-table dense>
|
||||
<template v-slot:default>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-left">Symbol</th>
|
||||
<th class="text-left">Meaning</th>
|
||||
<th class="text-left">Example</th>
|
||||
<th class="text-left">Equivalent</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>*</td>
|
||||
<td>Any value</td>
|
||||
<td>
|
||||
<pre>* * * *</pre>
|
||||
</td>
|
||||
<td>Every minute</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>-</td>
|
||||
<td>Range of values</td>
|
||||
<td>
|
||||
<pre>1-10 * * *</pre>
|
||||
</td>
|
||||
<td>Minutes 1 through 10</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>,</td>
|
||||
<td>List of values</td>
|
||||
<td>
|
||||
<pre>1,10 * * *</pre>
|
||||
</td>
|
||||
<td>At minutes 1 and 10</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>/</td>
|
||||
<td>Step values</td>
|
||||
<td>
|
||||
<pre>*/10 * * *</pre>
|
||||
</td>
|
||||
<td>Every 10 minutes</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>@yearly</td>
|
||||
<td>Once every year at midnight of 1 January</td>
|
||||
<td>
|
||||
<pre>@yearly</pre>
|
||||
</td>
|
||||
<td>0 0 1 1 *</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>@annually</td>
|
||||
<td>Same as @yearly</td>
|
||||
<td>
|
||||
<pre>@annually</pre>
|
||||
</td>
|
||||
<td>0 0 1 1 *</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>@monthly</td>
|
||||
<td>Once a month at midnight on the first day</td>
|
||||
<td>
|
||||
<pre>@monthly</pre>
|
||||
</td>
|
||||
<td>0 0 1 * *</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>@weekly</td>
|
||||
<td>Once a week at midnight on Sunday morning</td>
|
||||
<td>
|
||||
<pre>@weekly</pre>
|
||||
</td>
|
||||
<td>0 0 * * 0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>@daily</td>
|
||||
<td>Once a day at midnight</td>
|
||||
<td>
|
||||
<pre>@daily</pre>
|
||||
</td>
|
||||
<td>0 0 * * *</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>@midnight</td>
|
||||
<td>Same as @daily</td>
|
||||
<td>
|
||||
<pre>@midnight</pre>
|
||||
</td>
|
||||
<td>0 0 * * *</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>@hourly</td>
|
||||
<td>Once an hour at the beginning of the hour</td>
|
||||
<td>
|
||||
<pre>@hourly</pre>
|
||||
</td>
|
||||
<td>0 * * * *</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>@reboot</td>
|
||||
<td>Run at startup</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</template>
|
||||
</v-simple-table>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {copyable} from "../../mixins/copyable.mixin";
|
||||
import cronstrue from 'cronstrue';
|
||||
import * as CronValidator from 'cron-validator'
|
||||
|
||||
export default {
|
||||
name: "CrontabGenerator",
|
||||
mixins: [copyable],
|
||||
data: () => ({
|
||||
cron: '* * * * *',
|
||||
cronstrueConfig: {
|
||||
verbose: true,
|
||||
dayOfWeekStartIndexZero: true,
|
||||
use24HourTimeFormat: true,
|
||||
throwExceptionOnParseError: true
|
||||
}
|
||||
}),
|
||||
methods: {
|
||||
isCronValid(v) {
|
||||
return CronValidator.isValidCron(v, {allowBlankDay: true, alias: true});
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
cronString() {
|
||||
if (this.isCronValid(this.cron)) {
|
||||
return cronstrue.toString(this.cron, this.cronstrueConfig)
|
||||
} else {
|
||||
return ' '
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
::v-deep .cron-wrapper input {
|
||||
text-align: center;
|
||||
font-size: 22px;
|
||||
font-family: Consolas, monospace;
|
||||
}
|
||||
|
||||
.result {
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
margin-bottom: 22px;
|
||||
}
|
||||
|
||||
.text-center{
|
||||
pre{
|
||||
display: inline-block;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
150
src/routes/tools/GitMemo.vue
Normal file
@@ -0,0 +1,150 @@
|
||||
<template>
|
||||
<v-row>
|
||||
<v-col cols="12" xl="12">
|
||||
<v-card>
|
||||
<v-card-title>Git Memo</v-card-title>
|
||||
<v-card-text>
|
||||
<MemoViewer :memo="tips"/>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MemoViewer from "../../components/MemoViewer";
|
||||
|
||||
export default {
|
||||
name: "GitMemo",
|
||||
data: () => ({
|
||||
tips: [
|
||||
{
|
||||
section: 'Get started',
|
||||
child: [
|
||||
{
|
||||
text: 'Create a git repo',
|
||||
code: 'git init'
|
||||
},
|
||||
{
|
||||
text: 'Clone an existing repository',
|
||||
code: 'git clone [repo url]'
|
||||
},
|
||||
{
|
||||
text: 'Add current files to next commit',
|
||||
code: 'git add .'
|
||||
},
|
||||
{
|
||||
text: 'Commit tracked files changes',
|
||||
code: 'git commit -am "[commit message]"'
|
||||
},
|
||||
{
|
||||
text: 'List files that has changed',
|
||||
code: 'git status'
|
||||
},
|
||||
{
|
||||
text: 'List changes in tracked files',
|
||||
code: 'git diff'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
section: 'Basic configuration',
|
||||
child: [
|
||||
{
|
||||
text: 'Set the name that will be associated to every operation',
|
||||
code: 'git config --global user.name "[nom]"'
|
||||
},
|
||||
{
|
||||
text: 'Set the email address that will be associated to every operation',
|
||||
code: 'git config --global user.email "[email]"'
|
||||
},
|
||||
{
|
||||
text: 'Tell git to always push tags',
|
||||
code: 'git config --global push.followTags true'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
section: 'I\'ve made a mistake',
|
||||
child: [
|
||||
{
|
||||
text: 'Change last commit message',
|
||||
code: 'git commit --amend'
|
||||
},
|
||||
{
|
||||
text: 'Undo most recent commit and keep changes',
|
||||
code: 'git reset HEAD~1'
|
||||
},
|
||||
{
|
||||
text: 'Undo most recent commit and get rid of changes',
|
||||
code: 'git reset HEAD~1 --hard'
|
||||
},
|
||||
{
|
||||
text: 'Reset branch to remote state',
|
||||
code: 'git fetch origin\ngit reset --hard origin/[branch-name]'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
section: 'Setup SSH',
|
||||
child: [
|
||||
[
|
||||
{
|
||||
text: '1). Generate an SSH key.',
|
||||
code: 'ssh-keygen -t rsa -b 4096 -C "[email]"'
|
||||
},
|
||||
{
|
||||
text: '2). Start the ssh-agent in the background.',
|
||||
code: 'eval "$(ssh-agent -s)"'
|
||||
},
|
||||
{
|
||||
text: '3). Add your SSH private key to the ssh-agent.',
|
||||
code: 'ssh-add ~/.ssh/id_rsa'
|
||||
},
|
||||
{
|
||||
text: '4). Add your SSH public key to your git server (for github: Settings -> SSH and GPG keys)',
|
||||
code: 'cat ~/.ssh/id_rsa.pub'
|
||||
},
|
||||
{
|
||||
text: '5). (Optional) Testing your SSH connection',
|
||||
code: 'ssh -T git@github.com'
|
||||
},
|
||||
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
section: 'Merge and rebase',
|
||||
child: [
|
||||
{
|
||||
text: 'Merge a branch into the current',
|
||||
code: 'git merge [branch]'
|
||||
},
|
||||
{
|
||||
text: 'Abort merge (conflicts)',
|
||||
code: 'git merge --abort'
|
||||
},
|
||||
{
|
||||
text: 'Continue merge after resolving conflicts',
|
||||
code: 'git merge --continue'
|
||||
},
|
||||
{
|
||||
text: 'Rebase a branch into the current',
|
||||
code: 'git rebase [branch]'
|
||||
},
|
||||
{
|
||||
text: 'Continue rebase after resolving conflicts',
|
||||
code: 'git rebase --continue'
|
||||
},
|
||||
]
|
||||
},
|
||||
]
|
||||
}),
|
||||
components: {
|
||||
MemoViewer
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
</style>
|
||||
94
src/routes/tools/LoremIpsumGenerator.vue
Normal file
@@ -0,0 +1,94 @@
|
||||
<template>
|
||||
<v-row justify="center" align="center" class="lorem-ipsum-generator">
|
||||
<v-col cols="12" xl="5" lg="6" md="12">
|
||||
<v-card>
|
||||
<v-card-title>Lorem ipsum generator</v-card-title>
|
||||
<v-card-text>
|
||||
<v-slider v-model="paragraphs" min="1" max="20" label="Paragraphs" thumb-label/>
|
||||
<v-range-slider v-model="sentencePerParagraph" min="1" max="50" label="Sentences per paragraph"
|
||||
thumb-label/>
|
||||
<v-range-slider v-model="wordPerSentence" min="1" max="50" label="Words per sentence" thumb-label hide-details/>
|
||||
<v-checkbox v-model="startWithLoremIpsum" label="Start with 'Lorem ipsum ...'" hide-details/>
|
||||
<v-checkbox v-model="asHTML" label="As HTML" hide-details/>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
<v-col cols="12" xl="5" lg="6" md="12">
|
||||
<v-card>
|
||||
<v-card-text>
|
||||
<v-textarea outlined readonly hide-details="auto" v-model="loremIpsum" rows="15"
|
||||
class="text-justify"></v-textarea>
|
||||
<div class="text-center mt-4">
|
||||
<v-btn depressed @click="copy()">Copy</v-btn>
|
||||
</div>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {copyToClipboard, randFromArray, randIntFromInterval} from "../../utils/helpers";
|
||||
|
||||
const vocabulary = ['a', 'ac', 'accumsan', 'ad', 'adipiscing', 'aenean', 'aliquam', 'aliquet', 'amet', 'ante', 'aptent', 'arcu', 'at', 'auctor', 'bibendum', 'blandit', 'class', 'commodo', 'condimentum', 'congue', 'consectetur', 'consequat', 'conubia', 'convallis', 'cras', 'cubilia', 'cum', 'curabitur', 'curae', 'dapibus', 'diam', 'dictum', 'dictumst', 'dignissim', 'dolor', 'donec', 'dui', 'duis', 'egestas', 'eget', 'eleifend', 'elementum', 'elit', 'enim', 'erat', 'eros', 'est', 'et', 'etiam', 'eu', 'euismod', 'facilisi', 'faucibus', 'felis', 'fermentum', 'feugiat', 'fringilla', 'fusce', 'gravida', 'habitant', 'habitasse', 'hac', 'hendrerit', 'himenaeos', 'iaculis', 'id', 'imperdiet', 'in', 'inceptos', 'integer', 'interdum', 'ipsum', 'justo', 'lacinia', 'lacus', 'laoreet', 'lectus', 'leo', 'ligula', 'litora', 'lobortis', 'lorem', 'luctus', 'maecenas', 'magna', 'magnis', 'malesuada', 'massa', 'mattis', 'mauris', 'metus', 'mi', 'molestie', 'mollis', 'montes', 'morbi', 'mus', 'nam', 'nascetur', 'natoque', 'nec', 'neque', 'netus', 'nisi', 'nisl', 'non', 'nostra', 'nulla', 'nullam', 'nunc', 'odio', 'orci', 'ornare', 'parturient', 'pellentesque', 'penatibus', 'per', 'pharetra', 'phasellus', 'placerat', 'platea', 'porta', 'porttitor', 'posuere', 'potenti', 'praesent', 'pretium', 'primis', 'proin', 'pulvinar', 'purus', 'quam', 'quis', 'quisque', 'rhoncus', 'ridiculus', 'risus', 'rutrum', 'sagittis', 'sapien', 'scelerisque', 'sed', 'sem', 'semper', 'senectus', 'sit', 'sociis', 'sociosqu', 'sodales', 'sollicitudin', 'suscipit', 'suspendisse', 'taciti', 'tellus', 'tempor', 'tempus', 'tincidunt', 'torquent', 'tortor', 'turpis', 'ullamcorper', 'ultrices', 'ultricies', 'urna', 'varius', 'vehicula', 'vel', 'velit', 'venenatis', 'vestibulum', 'vitae', 'vivamus', 'viverra', 'volutpat', 'vulputate'];
|
||||
const firstSentence = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';
|
||||
|
||||
const generateSentence = (length) => {
|
||||
let sentence = Array.from({length}).map(() => randFromArray(vocabulary)).join(' ')
|
||||
sentence = sentence.charAt(0).toUpperCase() + sentence.slice(1) + '.'
|
||||
return sentence
|
||||
}
|
||||
|
||||
|
||||
export default {
|
||||
name: "LoremIpsumGenerator",
|
||||
data: () => ({
|
||||
paragraphs: 1,
|
||||
sentencePerParagraph: [3, 8],
|
||||
wordPerSentence: [8, 15],
|
||||
startWithLoremIpsum: true,
|
||||
asHTML: false
|
||||
}),
|
||||
methods:{
|
||||
copy(){
|
||||
copyToClipboard(this.loremIpsum)
|
||||
this.$toast.success('Copied to clipboard.')
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
loremIpsum: function () {
|
||||
const lorem = Array
|
||||
.from({length: this.paragraphs})
|
||||
.map(() => {
|
||||
const length = randIntFromInterval(...this.sentencePerParagraph);
|
||||
|
||||
return Array.from({length}).map(() => {
|
||||
const wordCount = randIntFromInterval(...this.wordPerSentence);
|
||||
return generateSentence(wordCount);
|
||||
})
|
||||
});
|
||||
|
||||
if (this.startWithLoremIpsum) {
|
||||
lorem[0][0] = firstSentence
|
||||
}
|
||||
|
||||
let result;
|
||||
if(this.asHTML){
|
||||
result = `<p>${lorem.map(s => s.join(' ')).join('</p>\n\n<p>')}</p>`
|
||||
}else{
|
||||
result = lorem.map(s => s.join(' ')).join('\n\n')
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
::v-deep {
|
||||
.v-label{
|
||||
min-width: 200px !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
71
src/routes/tools/MarkdownEditor.vue
Normal file
@@ -0,0 +1,71 @@
|
||||
<template>
|
||||
<v-row justify="center" align="center">
|
||||
<v-col cols="12" xl="5" lg="6" md="12">
|
||||
<v-card>
|
||||
<v-card-text>
|
||||
<v-textarea v-model="markdown" auto-grow outlined label="Markdown editor"/>
|
||||
<div class="text-center">
|
||||
<v-btn @click="copy(markdown)">copy markdown</v-btn>
|
||||
</div>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
<v-col cols="12" xl="5" lg="6" md="12">
|
||||
<v-card>
|
||||
<v-card-text >
|
||||
<div class="preview" v-html="html"></div>
|
||||
<div class="text-center">
|
||||
<v-divider />
|
||||
<br>
|
||||
<v-btn @click="copy(html)">copy html</v-btn>
|
||||
</div>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// import {debounce} from "../../utils/helpers";
|
||||
import marked from 'marked'
|
||||
import DOMPurify from 'dompurify';
|
||||
import {copyToClipboard} from "../../utils/helpers";
|
||||
|
||||
export default {
|
||||
name: "MarkdownEditor",
|
||||
data: () => ({
|
||||
markdown: '# Hello, World!\nLorem ipsum **dolor** sit *amet*, consectetur adipisicing elit. A aspernatur commodi consequuntur distinctio dolore doloribus eaque earum est ipsum nobis numquam pariatur perspiciatis quasi quis, sed, sunt tempore tenetur, veniam!\n',
|
||||
}),
|
||||
methods: {
|
||||
copy(text){
|
||||
copyToClipboard(text)
|
||||
this.$toast.success('Copied to clipboard.')
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
html() {
|
||||
return DOMPurify.sanitize(marked(this.markdown))
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
::v-deep {
|
||||
.preview {
|
||||
padding: 20px;
|
||||
|
||||
h1{
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
pre {
|
||||
width: 100%;
|
||||
|
||||
code {
|
||||
width: 100% !important;
|
||||
padding: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
137
src/routes/tools/QRCodeGenerator.vue
Normal file
@@ -0,0 +1,137 @@
|
||||
<template>
|
||||
<v-card class="single-card">
|
||||
<v-card-title>QR-code generator</v-card-title>
|
||||
<v-card-text>
|
||||
<v-row justify="center" align="center">
|
||||
<v-col cols="12" lg="6" sm="12">
|
||||
<v-text-field
|
||||
outlined
|
||||
v-model="value"
|
||||
label="Data"
|
||||
:rules="rules.value"
|
||||
/>
|
||||
<v-slider v-model="size" min="100" max="1920" label="Size (preview will not change): " thumb-label/>
|
||||
<v-select
|
||||
outlined
|
||||
v-model="level"
|
||||
:items="levels"
|
||||
label="Error resistance"
|
||||
/>
|
||||
<v-row>
|
||||
<v-col cols="12" md="6" sm="12">
|
||||
<ColorInput v-model="fgcolor" label="Foreground color"/>
|
||||
</v-col>
|
||||
<v-col cols="12" md="6" sm="12">
|
||||
<ColorInput v-model="bgcolor" label="Background color"/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
</v-col>
|
||||
|
||||
<v-col cols="12" lg="6" sm="12" class="text-center">
|
||||
<qrcode-vue
|
||||
:value="input"
|
||||
:size="size"
|
||||
:level="level"
|
||||
:background="bgcolor"
|
||||
:foreground="fgcolor"
|
||||
render-as="svg"
|
||||
class-name="qrcode-wrapper"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<div class="text-center mt-3 mb-sm-2">
|
||||
<v-btn @click="download('png')" class="mr-1" color="primary">download as png</v-btn>
|
||||
<v-btn @click="download('svg')" class="ml-1" color="primary">download as svg</v-btn>
|
||||
</div>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import QrcodeVue from 'qrcode.vue'
|
||||
import colors from "color-name";
|
||||
import ColorInput from "../../components/ColorInput";
|
||||
import {downloadBase64File} from "../../utils/helpers";
|
||||
|
||||
export default {
|
||||
name: "QRCodeGenerator",
|
||||
data: () => ({
|
||||
value: 'https://it-tools.tech',
|
||||
size: 300,
|
||||
level: 'M',
|
||||
bgcolor: '#ffffff',
|
||||
fgcolor: '#000000',
|
||||
levels: [
|
||||
{text: 'Low', value: 'L'},
|
||||
{text: 'Medium', value: 'M'},
|
||||
{text: 'Quartile', value: 'Q'},
|
||||
{text: 'High', value: 'H'}
|
||||
],
|
||||
rules: {
|
||||
value: [
|
||||
v => v.length > 0 || 'Value is needed'
|
||||
],
|
||||
color: [
|
||||
v => {
|
||||
v = v.trim()
|
||||
const isFFFFFF = /^#(?:[0-9a-fA-F]{6})$/.test(v);
|
||||
const isFFF = /^#(?:[0-9a-fA-F]{3})$/.test(v);
|
||||
const isRGB = /^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/.test(v);
|
||||
const isHSL = /^hsl\((\d+),\s*(\d+)%,\s*(\d+)%\)$/.test(v);
|
||||
const isKeyword = v in colors;
|
||||
const isTransparent = v === 'transparent';
|
||||
|
||||
return isFFFFFF || isFFF || isKeyword || isTransparent || isRGB || isHSL || 'Incorrect color.'
|
||||
}
|
||||
]
|
||||
}
|
||||
}),
|
||||
methods: {
|
||||
download(type) {
|
||||
const svgEl = this.$el.querySelector('.qrcode-wrapper svg');
|
||||
const svgString = new XMLSerializer().serializeToString(svgEl);
|
||||
const svgUrl = `data:image/svg+xml;base64,${btoa(svgString)}`;
|
||||
|
||||
if (type === 'png') {
|
||||
const canvas = document.createElement("canvas");
|
||||
canvas.width = this.size;
|
||||
canvas.height = this.size;
|
||||
const ctx = canvas.getContext("2d");
|
||||
|
||||
const image = new Image();
|
||||
image.onload = function () {
|
||||
ctx.drawImage(image, 0, 0);
|
||||
const result = canvas.toDataURL();
|
||||
|
||||
downloadBase64File(result, 'qr-code');
|
||||
};
|
||||
image.src = svgUrl;
|
||||
} else {
|
||||
downloadBase64File(svgUrl, 'qr-code');
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
input() {
|
||||
return this.value
|
||||
|
||||
}
|
||||
},
|
||||
components: {
|
||||
QrcodeVue,
|
||||
ColorInput
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
::v-deep .qrcode-wrapper {
|
||||
& > * {
|
||||
width: 300px !important;
|
||||
height: 300px !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
66
src/routes/tools/StringToBase64.vue
Normal file
@@ -0,0 +1,66 @@
|
||||
<template>
|
||||
<v-card class="single-card">
|
||||
<v-card-title>Base64 string converter</v-card-title>
|
||||
<v-card-text>
|
||||
<v-textarea
|
||||
outlined
|
||||
v-model="clear"
|
||||
label="Clear text"
|
||||
></v-textarea>
|
||||
|
||||
<v-textarea
|
||||
outlined
|
||||
v-model="base64"
|
||||
label="Base64 text"
|
||||
:rules="rules.base64"
|
||||
ref="base64"
|
||||
></v-textarea>
|
||||
<div class="text-center">
|
||||
<v-btn class="mr-1" depressed @click="copy(clear)">Copy clear</v-btn>
|
||||
<v-btn class="ml-1" depressed @click="copy(base64)">Copy base64</v-btn>
|
||||
</div>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {copyable} from "../../mixins/copyable.mixin";
|
||||
|
||||
export default {
|
||||
name: "StringToBase64",
|
||||
mixins: [copyable],
|
||||
data() {
|
||||
return {
|
||||
clear: 'Lorem ipsum dolor sit amet.',
|
||||
rules:{
|
||||
base64: [
|
||||
v => {
|
||||
try{
|
||||
return btoa(atob(v)) === v || 'Input is not base64.'
|
||||
}catch (e) {
|
||||
return 'Input is not base64.'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
base64: {
|
||||
get(){
|
||||
return btoa(this.clear)
|
||||
},
|
||||
set(value){
|
||||
if(this.$refs.base64.validate()){
|
||||
this.clear = atob(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -3,27 +3,52 @@
|
||||
<v-card-title>Uuid v4 generator</v-card-title>
|
||||
|
||||
<v-card-text>
|
||||
<v-text-field outlined v-model="token" class="centered-input"/>
|
||||
<v-text-field
|
||||
outlined
|
||||
v-model.number="quantity"
|
||||
ref="quantity"
|
||||
type="number"
|
||||
label="Quantity"
|
||||
dense
|
||||
class="quantity"
|
||||
:rules="rules.quantity"
|
||||
/>
|
||||
<v-textarea outlined v-model="token" class="centered-input" :rows="quantity <= 10 ? quantity : 10"
|
||||
readonly/>
|
||||
|
||||
<div class="text-center">
|
||||
<v-btn @click="refreshBool = !refreshBool" depressed class="mr-4">Refresh</v-btn>
|
||||
<v-btn @click="copyToken()" depressed>Copy token</v-btn>
|
||||
<v-btn @click="copyToken()" depressed>Copy uuid{{ quantity > 1 ? 's' : ''}}</v-btn>
|
||||
</div>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {copyToClipboard} from "../../utils/helpers";
|
||||
import {copyToClipboard, isInt} from "../../utils/helpers";
|
||||
|
||||
const noop = () => {
|
||||
};
|
||||
|
||||
const generateUuid = () => ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16));
|
||||
|
||||
export default {
|
||||
name: "UuidGenerator",
|
||||
data: () => ({
|
||||
refreshBool: true
|
||||
refreshBool: true,
|
||||
quantity: 1,
|
||||
rules: {
|
||||
quantity: [
|
||||
v => !!v || 'Quantity is required',
|
||||
v => (v > 0 && v <= 50 ) || 'Quantity should be > 0 and <= 50',
|
||||
v => isInt(v) || 'Quantity should be an integer'
|
||||
]
|
||||
},
|
||||
isMounted:false
|
||||
}),
|
||||
mounted() {
|
||||
this.isMounted = true;
|
||||
},
|
||||
methods: {
|
||||
copyToken() {
|
||||
copyToClipboard(this.token);
|
||||
@@ -32,16 +57,32 @@
|
||||
},
|
||||
computed: {
|
||||
token() {
|
||||
if (this.refreshBool) noop(); // To force recomputation
|
||||
if (this.isMounted && this.$refs.quantity.validate()) {
|
||||
if (this.refreshBool) noop(); // To force recomputation
|
||||
|
||||
return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16));
|
||||
return Array.from({length: this.quantity}, generateUuid).join('\n');
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
::v-deep .centered-input input {
|
||||
text-align: center
|
||||
<style scoped lang="less">
|
||||
.quantity {
|
||||
width: 100px;
|
||||
margin: auto;
|
||||
text-align: center;
|
||||
|
||||
::v-deep input {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep .centered-input textarea {
|
||||
text-align: center;
|
||||
margin-top: 13px !important;
|
||||
font-family: Consolas, monospace;
|
||||
}
|
||||
</style>
|
||||
@@ -24,8 +24,37 @@ const formatBytes = (bytes, decimals = 2) => {
|
||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
|
||||
}
|
||||
|
||||
const isInt = (value) => {
|
||||
return Number.isInteger(value);
|
||||
}
|
||||
|
||||
const debounce = (callback, delay = 300) => {
|
||||
let timer;
|
||||
|
||||
return function(...args) {
|
||||
clearTimeout(timer);
|
||||
timer = setTimeout(() => callback(...args), delay);
|
||||
}
|
||||
}
|
||||
|
||||
const randFromArray = (array) => array[Math.floor(Math.random() * array.length)];
|
||||
|
||||
const randIntFromInterval = (min, max) => Math.floor(Math.random() * (max - min) + min)
|
||||
|
||||
const downloadBase64File = (dataUrl, name = 'file') => {
|
||||
const a = document.createElement("a");
|
||||
a.href = dataUrl;
|
||||
a.download = name;
|
||||
a.click();
|
||||
}
|
||||
|
||||
export {
|
||||
copyToClipboard,
|
||||
fileIsImage,
|
||||
formatBytes
|
||||
formatBytes,
|
||||
isInt,
|
||||
debounce,
|
||||
randFromArray,
|
||||
randIntFromInterval,
|
||||
downloadBase64File
|
||||
}
|
||||
7
vercel.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"version": 2,
|
||||
"routes": [
|
||||
{ "handle": "filesystem" },
|
||||
{ "src": "/.*", "dest": "/index.html" }
|
||||
]
|
||||
}
|
||||
@@ -6,6 +6,11 @@ module.exports = {
|
||||
],
|
||||
configureWebpack: () => {
|
||||
return {
|
||||
module:{
|
||||
rules: [
|
||||
{ test: /\.md$/, use: 'raw-loader' }
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': {
|
||||
@@ -14,5 +19,11 @@ module.exports = {
|
||||
})
|
||||
]
|
||||
}
|
||||
},
|
||||
pwa: {
|
||||
workboxOptions: {
|
||||
skipWaiting: true,
|
||||
clientsClaim: true,
|
||||
}
|
||||
}
|
||||
}
|
||||