Compare commits
77 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
fce9240221 | ||
|
e6a7397493 | ||
|
a099485382 | ||
|
181c9f9874 | ||
|
21e9890b65 | ||
|
e894125001 | ||
|
ffe25b87d2 | ||
|
eb4363244b | ||
|
58372b0d06 | ||
|
096bebf093 | ||
|
9f83534046 | ||
|
c1dafd09b7 | ||
|
cc1ac8398b | ||
|
24fd5e7aaf | ||
|
94cb74d434 | ||
|
08aae49aa3 | ||
|
c727e150f7 | ||
|
8158f29d62 | ||
|
830c11f2a8 | ||
|
c484715c3e | ||
|
0812385ada | ||
|
f6d8dc41e6 | ||
|
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.
|
BIN
.github/logo.png
vendored
Normal file
After Width: | Height: | Size: 7.8 KiB |
32
CHANGELOG.md
Normal file
@@ -0,0 +1,32 @@
|
||||
# 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
|
||||
- [fix] [GithubContributors] ordered contributors by contribution count
|
||||
- [refactor] used vue-typecasting for number inputs
|
||||
- [feat] lazy loading tools routes
|
||||
- [feat] added [markdown editor](/#/markdown-editor)
|
||||
- [feat] added [lorem ipsum generator](/#/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
|
76
CODE_OF_CONDUCT.md
Normal file
@@ -0,0 +1,76 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to making participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, sex characteristics, gender identity and expression,
|
||||
level of experience, education, socio-economic status, nationality, personal
|
||||
appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment
|
||||
include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or
|
||||
advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic
|
||||
address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable
|
||||
behavior and are expected to take appropriate and fair corrective action in
|
||||
response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or
|
||||
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||
permanently any contributor for other behaviors that they deem inappropriate,
|
||||
threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces
|
||||
when an individual is representing the project or its community. Examples of
|
||||
representing a project or community include using an official project e-mail
|
||||
address, posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event. Representation of a project may be
|
||||
further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported by contacting the project team at contact@corentin-thomasset.fr. All
|
||||
complaints will be reviewed and investigated and will result in a response that
|
||||
is deemed necessary and appropriate to the circumstances. The project team is
|
||||
obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||
Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||
faith may face temporary or permanent repercussions as determined by other
|
||||
members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
||||
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
For answers to common questions about this code of conduct, see
|
||||
https://www.contributor-covenant.org/faq
|
92
CONTRIBUTING.md
Normal file
@@ -0,0 +1,92 @@
|
||||
# Contributing
|
||||
|
||||
When contributing to this repository, please first discuss the change you wish to make via issue,
|
||||
email, or any other method with the owners of this repository before making a change.
|
||||
|
||||
Please note we have a code of conduct, please follow it in all your interactions with the project.
|
||||
|
||||
## Pull Request Process
|
||||
|
||||
1. Ensure any install or build dependencies are removed before the end of the layer when doing a
|
||||
build.
|
||||
2. Update the README.md with details of changes to the interface, this includes new environment
|
||||
variables, exposed ports, useful file locations and container parameters.
|
||||
3. Increase the version numbers in any examples files and the README.md to the new version that this
|
||||
Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/).
|
||||
4. You may merge the Pull Request in once you have the sign-off of two other developers, or if you
|
||||
do not have permission to do that, you may request the second reviewer to merge it for you.
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
### Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to making participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, gender identity and expression, level of experience,
|
||||
nationality, personal appearance, race, religion, or sexual identity and
|
||||
orientation.
|
||||
|
||||
### Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment
|
||||
include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or
|
||||
advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic
|
||||
address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
### Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable
|
||||
behavior and are expected to take appropriate and fair corrective action in
|
||||
response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or
|
||||
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||
permanently any contributor for other behaviors that they deem inappropriate,
|
||||
threatening, offensive, or harmful.
|
||||
|
||||
### Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces
|
||||
when an individual is representing the project or its community. Examples of
|
||||
representing a project or community include using an official project e-mail
|
||||
address, posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event. Representation of a project may be
|
||||
further defined and clarified by project maintainers.
|
||||
|
||||
### Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported by contacting the project team at contact@corentin-thomasset.fr. All
|
||||
complaints will be reviewed and investigated and will result in a response that
|
||||
is deemed necessary and appropriate to the circumstances. The project team is
|
||||
obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||
Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||
faith may face temporary or permanent repercussions as determined by other
|
||||
members of the project's leadership.
|
||||
|
||||
### Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
||||
available at [http://contributor-covenant.org/version/1/4][version]
|
||||
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Corentin THOMASSET
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
60
README.md
@@ -1,24 +1,58 @@
|
||||
# it-tools
|
||||

|
||||
|
||||
Aggregated set of useful tools that every developer may need once in a while. Available [here](https://it-tools.tech).
|
||||
|
||||
## Functionalities roadmap
|
||||
Here is an unordered list of the current functionalities, and some that may come.
|
||||
|
||||
- [x] Token generator
|
||||
- [x] Uuid generator
|
||||
- [x] String hash
|
||||
- [x] Text encryption
|
||||
- [x] Date format converter
|
||||
- [x] Int base converter
|
||||
- [x] Color format converter
|
||||
- [x] Url encoder
|
||||
- [x] Base 64 generator
|
||||
- [x] Text information
|
||||
- [x] Markdown editor
|
||||
- [x] Lorem ipsum text generator
|
||||
- [ ] 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)
|
||||
- [ ] Math expression evaluator
|
||||
- [ ] Math expression graph
|
||||
|
||||
You have an idea of a tool? Submit a feature request!
|
||||
|
||||
## Project setup
|
||||
```
|
||||
Install dependencies by running the following command:
|
||||
```shell
|
||||
npm install
|
||||
```
|
||||
|
||||
### Compiles and hot-reloads for development
|
||||
```
|
||||
Then compiles and hot-reloads for development:
|
||||
```shell
|
||||
npm run serve
|
||||
```
|
||||
|
||||
### Compiles and minifies for production
|
||||
```
|
||||
npm run build
|
||||
```
|
||||
|
||||
### Lints and fixes files
|
||||
```
|
||||
And to lint and fixe files, run:
|
||||
```shell
|
||||
npm run lint
|
||||
```
|
||||
|
||||
### Customize configuration
|
||||
See [Configuration Reference](https://cli.vuejs.org/config/).
|
||||
## Contribute
|
||||
**Pull requests are welcome !** Feel free to contribute.
|
||||
|
||||
## 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).
|
592
package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "it-tools",
|
||||
"version": "0.1.0",
|
||||
"version": "1.3.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@@ -972,6 +972,12 @@
|
||||
"to-fast-properties": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"@fortawesome/fontawesome-free": {
|
||||
"version": "5.13.0",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.13.0.tgz",
|
||||
"integrity": "sha512-xKOeQEl5O47GPZYIMToj6uuA2syyFlq9EMSl2ui0uytjY9xbe8XS0pexNWmxrdcCyNGyDmLyYw5FtKsalBUeOg==",
|
||||
"dev": true
|
||||
},
|
||||
"@hapi/address": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.1.4.tgz",
|
||||
@@ -1987,6 +1993,25 @@
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-convert": "^1.9.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"color-convert": {
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-name": "1.1.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"color-name": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"any-observable": {
|
||||
@@ -2220,6 +2245,37 @@
|
||||
"integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==",
|
||||
"dev": true
|
||||
},
|
||||
"axios": {
|
||||
"version": "0.19.2",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz",
|
||||
"integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==",
|
||||
"requires": {
|
||||
"follow-redirects": "1.5.10"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
|
||||
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"follow-redirects": {
|
||||
"version": "1.5.10",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz",
|
||||
"integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==",
|
||||
"requires": {
|
||||
"debug": "=3.1.0"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||
}
|
||||
}
|
||||
},
|
||||
"babel-eslint": {
|
||||
"version": "10.1.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz",
|
||||
@@ -3083,6 +3139,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",
|
||||
@@ -3195,6 +3257,17 @@
|
||||
"integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=",
|
||||
"dev": true
|
||||
},
|
||||
"clone-deep": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz",
|
||||
"integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-plain-object": "^2.0.4",
|
||||
"kind-of": "^6.0.2",
|
||||
"shallow-clone": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"coa": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz",
|
||||
@@ -3230,22 +3303,46 @@
|
||||
"requires": {
|
||||
"color-convert": "^1.9.1",
|
||||
"color-string": "^1.5.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"color-convert": {
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-name": "1.1.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"color-name": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||
"dev": true,
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"requires": {
|
||||
"color-name": "1.1.3"
|
||||
"color-name": "~1.1.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
|
||||
"dev": true
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
||||
},
|
||||
"color-string": {
|
||||
"version": "1.5.3",
|
||||
@@ -3640,6 +3737,11 @@
|
||||
"randomfill": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"crypto-js": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.3.0.tgz",
|
||||
"integrity": "sha512-DIT51nX0dCfKltpRiXV+/TVZq+Qq2NgF4644+K7Ttnla7zEzqc+kjJyiB96BHNyUTBxyjzRcZYpUdZa+QAqi6Q=="
|
||||
},
|
||||
"css-color-names": {
|
||||
"version": "0.0.4",
|
||||
"resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz",
|
||||
@@ -4277,6 +4379,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",
|
||||
@@ -4751,9 +4858,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"eventemitter3": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.0.tgz",
|
||||
"integrity": "sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg==",
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.4.tgz",
|
||||
"integrity": "sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ==",
|
||||
"dev": true
|
||||
},
|
||||
"events": {
|
||||
@@ -6146,18 +6253,17 @@
|
||||
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
|
||||
"dev": true
|
||||
},
|
||||
"headful": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/headful/-/headful-1.0.3.tgz",
|
||||
"integrity": "sha512-vF9Vfddn1QWmziliht2mji6ayI78+hUuSC+Kt0GEqLw/51zWgi1KF7oLtIQf3nlkg8sQQOlznkkIaF4W9lIt9w=="
|
||||
},
|
||||
"hex-color-regex": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz",
|
||||
"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",
|
||||
@@ -6212,9 +6318,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"html-entities": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz",
|
||||
"integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=",
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.3.1.tgz",
|
||||
"integrity": "sha512-rhE/4Z3hIhzHAUKbW8jVcCyuT5oJCXXqhN/6mXXVCpzTmvJnoH2HL/bt3EZ6p55jbFJBeAe1ZNpL5BugLujxNA==",
|
||||
"dev": true
|
||||
},
|
||||
"html-minifier": {
|
||||
@@ -6363,16 +6469,10 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"http-parser-js": {
|
||||
"version": "0.4.10",
|
||||
"resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.10.tgz",
|
||||
"integrity": "sha1-ksnBN0w1CF912zWexWzCV8u5P6Q=",
|
||||
"dev": true
|
||||
},
|
||||
"http-proxy": {
|
||||
"version": "1.18.0",
|
||||
"resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.0.tgz",
|
||||
"integrity": "sha512-84I2iJM/n1d4Hdgc6y2+qY5mDaz2PUVjlg9znE9byl+q0uC3DeByqBGReQu5tpLK0TAqTIXScRUV+dg7+bUPpQ==",
|
||||
"version": "1.18.1",
|
||||
"resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz",
|
||||
"integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"eventemitter3": "^4.0.0",
|
||||
@@ -6665,6 +6765,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"interpret": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz",
|
||||
"integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==",
|
||||
"dev": true
|
||||
},
|
||||
"invariant": {
|
||||
"version": "2.2.4",
|
||||
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
|
||||
@@ -6674,12 +6780,6 @@
|
||||
"loose-envify": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"invert-kv": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz",
|
||||
"integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==",
|
||||
"dev": true
|
||||
},
|
||||
"ip": {
|
||||
"version": "1.1.5",
|
||||
"resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
|
||||
@@ -7213,15 +7313,6 @@
|
||||
"launch-editor": "^2.2.1"
|
||||
}
|
||||
},
|
||||
"lcid": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz",
|
||||
"integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"invert-kv": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"less": {
|
||||
"version": "3.11.1",
|
||||
"resolved": "https://registry.npmjs.org/less/-/less-3.11.1.tgz",
|
||||
@@ -7963,9 +8054,9 @@
|
||||
}
|
||||
},
|
||||
"loglevel": {
|
||||
"version": "1.6.7",
|
||||
"resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.7.tgz",
|
||||
"integrity": "sha512-cY2eLFrQSAfVPhCgH1s7JI73tMbg9YC3v3+ZHVW67sBS7UxWzNEk/ZBbSfLykBWHp33dqqtOv82gjhKEi81T/A==",
|
||||
"version": "1.6.8",
|
||||
"resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.8.tgz",
|
||||
"integrity": "sha512-bsU7+gc9AJ2SqpzxwU3+1fedl8zAntbtC5XYlt3s2j1hJcn2PsXSmgN8TaLG/J1/2mod4+cE/3vNL70/c1RNCA==",
|
||||
"dev": true
|
||||
},
|
||||
"loose-envify": {
|
||||
@@ -8002,15 +8093,6 @@
|
||||
"semver": "^5.6.0"
|
||||
}
|
||||
},
|
||||
"map-age-cleaner": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz",
|
||||
"integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"p-defer": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"map-cache": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
|
||||
@@ -8026,6 +8108,11 @@
|
||||
"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",
|
||||
@@ -8049,25 +8136,6 @@
|
||||
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=",
|
||||
"dev": true
|
||||
},
|
||||
"mem": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz",
|
||||
"integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"map-age-cleaner": "^0.1.1",
|
||||
"mimic-fn": "^2.0.0",
|
||||
"p-is-promise": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"mimic-fn": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
|
||||
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"memory-fs": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
|
||||
@@ -8623,10 +8691,14 @@
|
||||
"dev": true
|
||||
},
|
||||
"object-is": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.2.tgz",
|
||||
"integrity": "sha512-Epah+btZd5wrrfjkJZq1AOB9O6OxUQto45hzFd7lXGrpHPGE0W1k+426yrZV+k6NJOzLNNW/nVsmZdIWsAqoOQ==",
|
||||
"dev": true
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.2.tgz",
|
||||
"integrity": "sha512-5lHCz+0uufF6wZ7CRFWJN3hp8Jqblpgve06U5CMQ3f//6iDjPr2PEo9MWCjEssDsa+UZEL4PkFpr+BMop6aKzQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"define-properties": "^1.1.3",
|
||||
"es-abstract": "^1.17.5"
|
||||
}
|
||||
},
|
||||
"object-keys": {
|
||||
"version": "1.1.1",
|
||||
@@ -8803,41 +8875,18 @@
|
||||
"integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=",
|
||||
"dev": true
|
||||
},
|
||||
"os-locale": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz",
|
||||
"integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"execa": "^1.0.0",
|
||||
"lcid": "^2.0.0",
|
||||
"mem": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"os-tmpdir": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
|
||||
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
|
||||
"dev": true
|
||||
},
|
||||
"p-defer": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz",
|
||||
"integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=",
|
||||
"dev": true
|
||||
},
|
||||
"p-finally": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
|
||||
"integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=",
|
||||
"dev": true
|
||||
},
|
||||
"p-is-promise": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz",
|
||||
"integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==",
|
||||
"dev": true
|
||||
},
|
||||
"p-limit": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
|
||||
@@ -10012,6 +10061,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",
|
||||
@@ -10050,6 +10122,15 @@
|
||||
"readable-stream": "^2.0.2"
|
||||
}
|
||||
},
|
||||
"rechoir": {
|
||||
"version": "0.6.2",
|
||||
"resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
|
||||
"integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"resolve": "^1.1.6"
|
||||
}
|
||||
},
|
||||
"regenerate": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz",
|
||||
@@ -10386,6 +10467,11 @@
|
||||
"inherits": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"roboto-fontface": {
|
||||
"version": "0.10.0",
|
||||
"resolved": "https://registry.npmjs.org/roboto-fontface/-/roboto-fontface-0.10.0.tgz",
|
||||
"integrity": "sha512-OlwfYEgA2RdboZohpldlvJ1xngOins5d7ejqnIBWr9KaMxsnBqotpptRXTyfNRLnFpqzX6sTDt+X+a+6udnU8g=="
|
||||
},
|
||||
"run-async": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.0.tgz",
|
||||
@@ -10440,6 +10526,36 @@
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
||||
"dev": true
|
||||
},
|
||||
"sass": {
|
||||
"version": "1.26.3",
|
||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.26.3.tgz",
|
||||
"integrity": "sha512-5NMHI1+YFYw4sN3yfKjpLuV9B5l7MqQ6FlkTcC4FT+oHbBRUZoSjHrrt/mE0nFXJyY2kQtU9ou9HxvFVjLFuuw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chokidar": ">=2.0.0 <4.0.0"
|
||||
}
|
||||
},
|
||||
"sass-loader": {
|
||||
"version": "8.0.2",
|
||||
"resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-8.0.2.tgz",
|
||||
"integrity": "sha512-7o4dbSK8/Ol2KflEmSco4jTjQoV988bM82P9CZdmo9hR3RLnvNc0ufMNdMrB0caq38JQ/FgF4/7RcbcfKzxoFQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"clone-deep": "^4.0.1",
|
||||
"loader-utils": "^1.2.3",
|
||||
"neo-async": "^2.6.1",
|
||||
"schema-utils": "^2.6.1",
|
||||
"semver": "^6.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"semver": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"sax": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
|
||||
@@ -10660,6 +10776,15 @@
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"shallow-clone": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz",
|
||||
"integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"kind-of": "^6.0.2"
|
||||
}
|
||||
},
|
||||
"shebang-command": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
|
||||
@@ -10681,6 +10806,17 @@
|
||||
"integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==",
|
||||
"dev": true
|
||||
},
|
||||
"shelljs": {
|
||||
"version": "0.8.3",
|
||||
"resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.3.tgz",
|
||||
"integrity": "sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"glob": "^7.0.0",
|
||||
"interpret": "^1.0.0",
|
||||
"rechoir": "^0.6.2"
|
||||
}
|
||||
},
|
||||
"signal-exit": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
|
||||
@@ -10852,13 +10988,14 @@
|
||||
}
|
||||
},
|
||||
"sockjs": {
|
||||
"version": "0.3.19",
|
||||
"resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.19.tgz",
|
||||
"integrity": "sha512-V48klKZl8T6MzatbLlzzRNhMepEys9Y4oGFpypBFFn1gLI/QQ9HtLLyWJNbPlwGLelOVOEijUbTTJeLLI59jLw==",
|
||||
"version": "0.3.20",
|
||||
"resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.20.tgz",
|
||||
"integrity": "sha512-SpmVOVpdq0DJc0qArhF3E5xsxvaiqGNb73XfgBpK1y3UD5gs8DSo8aCTsuT5pX8rssdc2NDIzANwP9eCAiSdTA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"faye-websocket": "^0.10.0",
|
||||
"uuid": "^3.0.1"
|
||||
"uuid": "^3.4.0",
|
||||
"websocket-driver": "0.6.5"
|
||||
}
|
||||
},
|
||||
"sockjs-client": {
|
||||
@@ -12013,6 +12150,37 @@
|
||||
"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",
|
||||
"integrity": "sha512-jtxcidjLT5f1H9QLYKLFjo/ZG42ud4pI9bK3WNO5DXyhiMDMTwSZ7b3NcJVRH7tKYbv5/ty0VPdDGlf4w22AMA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"semver": "^7.1.2",
|
||||
"shelljs": "^0.8.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"semver": {
|
||||
"version": "7.2.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.2.1.tgz",
|
||||
"integrity": "sha512-aHhm1pD02jXXkyIpq25qBZjr3CQgg8KST8uX0OWXch3xE6jw+1bfbWnCjzMwojsTquroUmKFHNzU6x26mEiRxw==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"vue-cryptojs": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/vue-cryptojs/-/vue-cryptojs-2.1.4.tgz",
|
||||
"integrity": "sha512-AmJ5HAbvW81X4DLzq5Q3YlFbFIr1vSAmjXcr5SxyJCJeoH/2R+HHuU6D21pI2pAv4LCqfRpakWMWs6Cl8XvtAA==",
|
||||
"requires": {
|
||||
"crypto-js": "^3.3.0"
|
||||
}
|
||||
},
|
||||
"vue-eslint-parser": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-7.0.0.tgz",
|
||||
@@ -12039,6 +12207,14 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"vue-headful": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/vue-headful/-/vue-headful-2.1.0.tgz",
|
||||
"integrity": "sha512-HXMdJfVDgD3eoh8qk9Laz2wGraPVGYDbvfXd7+i1MVziWMXGHUm8gpRC2p11ugYYXKRAcaS2g6ycq4Pr+eqb7g==",
|
||||
"requires": {
|
||||
"headful": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"vue-hot-reload-api": {
|
||||
"version": "2.3.4",
|
||||
"resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz",
|
||||
@@ -12105,6 +12281,25 @@
|
||||
"integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==",
|
||||
"dev": true
|
||||
},
|
||||
"vuetify": {
|
||||
"version": "2.2.20",
|
||||
"resolved": "https://registry.npmjs.org/vuetify/-/vuetify-2.2.20.tgz",
|
||||
"integrity": "sha512-tiij3ammBiG7QrdwRBJxW917AyDLcMekRtLosdyVshDKHA5CpKrru8Ljn1gAmeUyhYZyUw4gz3XbrrIJ++TP7w=="
|
||||
},
|
||||
"vuetify-loader": {
|
||||
"version": "1.4.3",
|
||||
"resolved": "https://registry.npmjs.org/vuetify-loader/-/vuetify-loader-1.4.3.tgz",
|
||||
"integrity": "sha512-fS0wRil682Ebsj2as+eruBoMPKaQYDhu/fDAndnTItzSY4RK4LOEIsssVL4vD6QY8dvUgoGL84SUQ6vGr777CA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"loader-utils": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"vuetify-toast-snackbar": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/vuetify-toast-snackbar/-/vuetify-toast-snackbar-0.6.1.tgz",
|
||||
"integrity": "sha512-F2bLPMXiw7qQgX68adSu0zQrMTKODN5JAzCP8AP/HGhz/Bz1z24QbvYcX0fyHnG/yP6PAPkpMCXsLQSq6HV0Ag=="
|
||||
},
|
||||
"watchpack": {
|
||||
"version": "1.6.1",
|
||||
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.1.tgz",
|
||||
@@ -12231,9 +12426,9 @@
|
||||
}
|
||||
},
|
||||
"webpack-dev-server": {
|
||||
"version": "3.10.3",
|
||||
"resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.10.3.tgz",
|
||||
"integrity": "sha512-e4nWev8YzEVNdOMcNzNeCN947sWJNd43E5XvsJzbAL08kGc2frm1tQ32hTJslRS+H65LCb/AaUCYU7fjHCpDeQ==",
|
||||
"version": "3.11.0",
|
||||
"resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.11.0.tgz",
|
||||
"integrity": "sha512-PUxZ+oSTxogFQgkTtFndEtJIPNmml7ExwufBZ9L2/Xyyd5PnOL5UreWe5ZT7IU25DSdykL9p1MLQzmLh2ljSeg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-html": "0.0.7",
|
||||
@@ -12244,31 +12439,31 @@
|
||||
"debug": "^4.1.1",
|
||||
"del": "^4.1.1",
|
||||
"express": "^4.17.1",
|
||||
"html-entities": "^1.2.1",
|
||||
"html-entities": "^1.3.1",
|
||||
"http-proxy-middleware": "0.19.1",
|
||||
"import-local": "^2.0.0",
|
||||
"internal-ip": "^4.3.0",
|
||||
"ip": "^1.1.5",
|
||||
"is-absolute-url": "^3.0.3",
|
||||
"killable": "^1.0.1",
|
||||
"loglevel": "^1.6.6",
|
||||
"loglevel": "^1.6.8",
|
||||
"opn": "^5.5.0",
|
||||
"p-retry": "^3.0.1",
|
||||
"portfinder": "^1.0.25",
|
||||
"portfinder": "^1.0.26",
|
||||
"schema-utils": "^1.0.0",
|
||||
"selfsigned": "^1.10.7",
|
||||
"semver": "^6.3.0",
|
||||
"serve-index": "^1.9.1",
|
||||
"sockjs": "0.3.19",
|
||||
"sockjs": "0.3.20",
|
||||
"sockjs-client": "1.4.0",
|
||||
"spdy": "^4.0.1",
|
||||
"spdy": "^4.0.2",
|
||||
"strip-ansi": "^3.0.1",
|
||||
"supports-color": "^6.1.0",
|
||||
"url": "^0.11.0",
|
||||
"webpack-dev-middleware": "^3.7.2",
|
||||
"webpack-log": "^2.0.0",
|
||||
"ws": "^6.2.1",
|
||||
"yargs": "12.0.5"
|
||||
"yargs": "^13.3.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-regex": {
|
||||
@@ -12278,33 +12473,39 @@
|
||||
"dev": true
|
||||
},
|
||||
"cliui": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz",
|
||||
"integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==",
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
|
||||
"integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"string-width": "^2.1.1",
|
||||
"strip-ansi": "^4.0.0",
|
||||
"wrap-ansi": "^2.0.0"
|
||||
"string-width": "^3.1.0",
|
||||
"strip-ansi": "^5.2.0",
|
||||
"wrap-ansi": "^5.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-regex": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
|
||||
"integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
|
||||
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
|
||||
"dev": true
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
|
||||
"integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
|
||||
"integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-regex": "^3.0.0"
|
||||
"ansi-regex": "^4.1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"emoji-regex": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
|
||||
"integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
|
||||
"dev": true
|
||||
},
|
||||
"find-up": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
|
||||
@@ -12314,12 +12515,6 @@
|
||||
"locate-path": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"get-caller-file": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
|
||||
"integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==",
|
||||
"dev": true
|
||||
},
|
||||
"is-absolute-url": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz",
|
||||
@@ -12366,11 +12561,27 @@
|
||||
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
|
||||
"dev": true
|
||||
},
|
||||
"require-main-filename": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
|
||||
"integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=",
|
||||
"dev": true
|
||||
"portfinder": {
|
||||
"version": "1.0.26",
|
||||
"resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.26.tgz",
|
||||
"integrity": "sha512-Xi7mKxJHHMI3rIUrnm/jjUgwhbYMkp/XKEcZX3aG4BrumLpq3nmoQMX+ClYnDZnZ/New7IatC1no5RX0zo1vXQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"async": "^2.6.2",
|
||||
"debug": "^3.1.1",
|
||||
"mkdirp": "^0.5.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
"version": "3.2.6",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
|
||||
"integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ms": "^2.1.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"schema-utils": {
|
||||
"version": "1.0.0",
|
||||
@@ -12390,28 +12601,29 @@
|
||||
"dev": true
|
||||
},
|
||||
"string-width": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
|
||||
"integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
|
||||
"integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"emoji-regex": "^7.0.1",
|
||||
"is-fullwidth-code-point": "^2.0.0",
|
||||
"strip-ansi": "^4.0.0"
|
||||
"strip-ansi": "^5.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-regex": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
|
||||
"integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
|
||||
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
|
||||
"dev": true
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
|
||||
"integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
|
||||
"integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-regex": "^3.0.0"
|
||||
"ansi-regex": "^4.1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12435,61 +12647,55 @@
|
||||
}
|
||||
},
|
||||
"wrap-ansi": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
|
||||
"integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
|
||||
"integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"string-width": "^1.0.1",
|
||||
"strip-ansi": "^3.0.1"
|
||||
"ansi-styles": "^3.2.0",
|
||||
"string-width": "^3.0.0",
|
||||
"strip-ansi": "^5.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"is-fullwidth-code-point": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
|
||||
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
}
|
||||
"ansi-regex": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
|
||||
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
|
||||
"dev": true
|
||||
},
|
||||
"string-width": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
|
||||
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
|
||||
"strip-ansi": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
|
||||
"integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"code-point-at": "^1.0.0",
|
||||
"is-fullwidth-code-point": "^1.0.0",
|
||||
"strip-ansi": "^3.0.0"
|
||||
"ansi-regex": "^4.1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"yargs": {
|
||||
"version": "12.0.5",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz",
|
||||
"integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==",
|
||||
"version": "13.3.2",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz",
|
||||
"integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"cliui": "^4.0.0",
|
||||
"decamelize": "^1.2.0",
|
||||
"cliui": "^5.0.0",
|
||||
"find-up": "^3.0.0",
|
||||
"get-caller-file": "^1.0.1",
|
||||
"os-locale": "^3.0.0",
|
||||
"get-caller-file": "^2.0.1",
|
||||
"require-directory": "^2.1.1",
|
||||
"require-main-filename": "^1.0.1",
|
||||
"require-main-filename": "^2.0.0",
|
||||
"set-blocking": "^2.0.0",
|
||||
"string-width": "^2.0.0",
|
||||
"string-width": "^3.0.0",
|
||||
"which-module": "^2.0.0",
|
||||
"y18n": "^3.2.1 || ^4.0.0",
|
||||
"yargs-parser": "^11.1.1"
|
||||
"y18n": "^4.0.0",
|
||||
"yargs-parser": "^13.1.2"
|
||||
}
|
||||
},
|
||||
"yargs-parser": {
|
||||
"version": "11.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz",
|
||||
"integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==",
|
||||
"version": "13.1.2",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz",
|
||||
"integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"camelcase": "^5.0.0",
|
||||
@@ -12536,20 +12742,18 @@
|
||||
}
|
||||
},
|
||||
"websocket-driver": {
|
||||
"version": "0.7.3",
|
||||
"resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.3.tgz",
|
||||
"integrity": "sha512-bpxWlvbbB459Mlipc5GBzzZwhoZgGEZLuqPaR0INBGnPAY1vdBX6hPnoFXiw+3yWxDuHyQjO2oXTMyS8A5haFg==",
|
||||
"version": "0.6.5",
|
||||
"resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.6.5.tgz",
|
||||
"integrity": "sha1-XLJVbOuF9Dc8bYI4qmkchFThOjY=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"http-parser-js": ">=0.4.0 <0.4.11",
|
||||
"safe-buffer": ">=5.1.0",
|
||||
"websocket-extensions": ">=0.1.1"
|
||||
}
|
||||
},
|
||||
"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": {
|
||||
|
24
package.json
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"name": "it-tools",
|
||||
"version": "0.1.0",
|
||||
"description": "",
|
||||
"version": "1.3.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
@@ -8,12 +9,24 @@
|
||||
"lint": "vue-cli-service lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^0.19.2",
|
||||
"color-convert": "^2.0.1",
|
||||
"color-name": "^1.1.4",
|
||||
"core-js": "^3.6.4",
|
||||
"dompurify": "^2.0.11",
|
||||
"marked": "^1.1.0",
|
||||
"register-service-worker": "^1.7.1",
|
||||
"roboto-fontface": "*",
|
||||
"vue": "^2.6.11",
|
||||
"vue-router": "^3.1.6"
|
||||
"vue-analytics": "^5.22.1",
|
||||
"vue-cryptojs": "^2.1.4",
|
||||
"vue-headful": "^2.1.0",
|
||||
"vue-router": "^3.1.6",
|
||||
"vuetify": "^2.2.11",
|
||||
"vuetify-toast-snackbar": "^0.6.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@fortawesome/fontawesome-free": "^5.13.0",
|
||||
"@vue/cli-plugin-babel": "~4.3.0",
|
||||
"@vue/cli-plugin-eslint": "~4.3.0",
|
||||
"@vue/cli-plugin-pwa": "~4.3.0",
|
||||
@@ -25,7 +38,12 @@
|
||||
"less": "^3.0.4",
|
||||
"less-loader": "^5.0.0",
|
||||
"lint-staged": "^9.5.0",
|
||||
"vue-template-compiler": "^2.6.11"
|
||||
"raw-loader": "^4.0.1",
|
||||
"sass": "^1.19.0",
|
||||
"sass-loader": "^8.0.0",
|
||||
"vue-cli-plugin-vuetify": "~2.0.5",
|
||||
"vue-template-compiler": "^2.6.11",
|
||||
"vuetify-loader": "^1.3.0"
|
||||
},
|
||||
"gitHooks": {
|
||||
"pre-commit": "lint-staged"
|
||||
|
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 |
BIN
public/img/banner.png
Normal file
After Width: | Height: | Size: 64 KiB |
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 |
@@ -6,6 +6,16 @@
|
||||
<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" 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">
|
||||
</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"
|
||||
}
|
245
src/App.vue
@@ -1,32 +1,223 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<div id="nav">
|
||||
<router-link to="/">Home</router-link> |
|
||||
<router-link to="/about">About</router-link>
|
||||
</div>
|
||||
<router-view/>
|
||||
</div>
|
||||
<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"
|
||||
/>
|
||||
<v-navigation-drawer v-model="drawer" app clipped>
|
||||
<template v-slot:prepend>
|
||||
<SearchBar class="hidden-sm-and-up"/>
|
||||
</template>
|
||||
|
||||
<v-list dense>
|
||||
|
||||
<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 style="width: 1.25em">{{ item.icon }}</v-icon>
|
||||
</v-list-item-action>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>
|
||||
{{ item.text }}
|
||||
</v-list-item-title>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
</div>
|
||||
|
||||
</v-list>
|
||||
|
||||
<template v-slot:append>
|
||||
<v-divider></v-divider>
|
||||
|
||||
<div class="pa-5">
|
||||
<div>
|
||||
IT-Tools <a v-bind:href="'https://github.com/CorentinTh/it-tools/tree/'+appVersion"
|
||||
target="_blank">{{appVersion}}</a>
|
||||
|
||||
</div>
|
||||
<div>© {{new Date().getFullYear()}} <a href="//corentin-thomasset.fr" class="footer-link">Corentin
|
||||
Thomasset</a></div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</template>
|
||||
</v-navigation-drawer>
|
||||
|
||||
<v-app-bar app clipped-left color="green">
|
||||
<v-app-bar-nav-icon @click.stop="drawer = !drawer"/>
|
||||
<v-toolbar-title class="mr-12 align-center">
|
||||
<router-link to="/" class="title">IT Tools</router-link>
|
||||
</v-toolbar-title>
|
||||
|
||||
<v-spacer></v-spacer>
|
||||
<v-row
|
||||
align="center"
|
||||
style="max-width: 650px"
|
||||
class="hidden-sm-and-down"
|
||||
>
|
||||
<SearchBar/>
|
||||
</v-row>
|
||||
<v-spacer></v-spacer>
|
||||
|
||||
<div class="right-links">
|
||||
<router-link to="/about">About</router-link>
|
||||
|
||||
<a href="https://github.com/CorentinTh/it-tools" target="_blank" class="navbar-link">
|
||||
<v-icon>fab fa-github</v-icon>
|
||||
</a>
|
||||
</div>
|
||||
</v-app-bar>
|
||||
|
||||
<v-content>
|
||||
<v-row class="fill-height pa-4" justify="center" align="center" no-gutters>
|
||||
<router-view></router-view>
|
||||
</v-row>
|
||||
</v-content>
|
||||
|
||||
<!-- <v-footer app>-->
|
||||
<!-- <span>© {{new Date().getFullYear()}} <a href="//corentin-thomasset.fr" class="footer-link">Corentin Thomasset</a></span>-->
|
||||
<!-- <span>A bug ? A feature request ? Stuff happens <a href="https://github.com/CorentinTh/it-tools/issues"-->
|
||||
<!-- target="_blank" class="footer-link">here</a>.</span>-->
|
||||
<!-- </v-footer>-->
|
||||
</v-app>
|
||||
</template>
|
||||
|
||||
<style lang="less">
|
||||
#app {
|
||||
font-family: Avenir, Helvetica, Arial, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
text-align: center;
|
||||
color: #2c3e50;
|
||||
}
|
||||
<script>
|
||||
import SearchBar from "./components/SearchBar";
|
||||
import {toolsComponents} from "./router";
|
||||
|
||||
#nav {
|
||||
padding: 30px;
|
||||
|
||||
a {
|
||||
font-weight: bold;
|
||||
color: #2c3e50;
|
||||
|
||||
&.router-link-exact-active {
|
||||
color: #42b983;
|
||||
export default {
|
||||
props: {
|
||||
source: String,
|
||||
},
|
||||
components: {SearchBar},
|
||||
data: () => ({
|
||||
appVersion: 'v' + process.env.APPLICATION_VERSION,
|
||||
drawer: null,
|
||||
items: toolsComponents,
|
||||
currentRoute: {}
|
||||
}),
|
||||
mounted() {
|
||||
this.setTitle()
|
||||
},
|
||||
created() {
|
||||
this.$vuetify.theme.dark = true
|
||||
},
|
||||
methods: {
|
||||
setTitle() {
|
||||
const path = this.$router.currentRoute.path;
|
||||
this.currentRoute = toolsComponents.map(p => p.child).flat().find(p => p.path === path)
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'$route'() {
|
||||
this.setTitle()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
html {
|
||||
overflow-y: auto !important;
|
||||
}
|
||||
|
||||
.pretty-scrollbar{
|
||||
&::-webkit-scrollbar {
|
||||
width: 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.v-navigation-drawer__content{
|
||||
.pretty-scrollbar;
|
||||
}
|
||||
|
||||
.single-card {
|
||||
width: 100%;
|
||||
max-width: 700px !important;
|
||||
}
|
||||
|
||||
.v-card__title {
|
||||
justify-content: center;
|
||||
font-size: 30px !important;
|
||||
line-height: 30px !important;
|
||||
padding: 30px 0 !important;
|
||||
font-weight: 300 !important;
|
||||
}
|
||||
|
||||
.title {
|
||||
text-decoration: none;
|
||||
color: #fff !important;
|
||||
|
||||
&:hover {
|
||||
border-bottom: 1px dashed;
|
||||
}
|
||||
}
|
||||
|
||||
.right-links {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
|
||||
a:not(:last-child) {
|
||||
margin-right: 20px;
|
||||
text-decoration: none;
|
||||
color: #fff;
|
||||
|
||||
&:hover {
|
||||
border-bottom: 1px dashed;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.navbar-link {
|
||||
text-decoration: none;
|
||||
|
||||
.v-icon {
|
||||
font-size: 37px !important;
|
||||
|
||||
&:hover {
|
||||
color: #363636;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.v-navigation-drawer__append {
|
||||
text-align: center;
|
||||
color: rgba(255, 255, 255, 0.52) !important;
|
||||
|
||||
a {
|
||||
border-bottom: 1px dashed;
|
||||
text-decoration: none;
|
||||
color: rgba(255, 255, 255, 0.52) !important;
|
||||
|
||||
&:hover {
|
||||
color: #4CAF50 !important;
|
||||
border-bottom: 1px solid;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
Before Width: | Height: | Size: 6.7 KiB |
48
src/components/Abstract.vue
Normal file
@@ -0,0 +1,48 @@
|
||||
<template>
|
||||
<div>
|
||||
<h2>Hello, World!</h2>
|
||||
<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.
|
||||
</p>
|
||||
|
||||
|
||||
<v-row>
|
||||
<v-col cols="12" lg="6" md="12">
|
||||
<h2>A tool is missing?</h2>
|
||||
<p class="text-justify">
|
||||
If you need a tool that is not currently not present here, and you think can be
|
||||
relevant, you are welcome to submit a feature request <a
|
||||
href="//github.com/CorentinTh/it-tools/issues/new?assignees=CorentinTh&labels=enhancement&template=feature_request.md&title=%5BFEAT%5D%20My%20feature">here</a>.
|
||||
</p>
|
||||
</v-col>
|
||||
<v-col cols="12" lg="6" md="12">
|
||||
<h2>Found a bug?</h2>
|
||||
<p class="text-justify">
|
||||
If you found a bug, or something broken that doesn't work as expected, please fill a bug report here <a
|
||||
href="//github.com/CorentinTh/it-tools/issues/new?assignees=CorentinTh&labels=bug&template=bug_report.md&title=%5BBUG%5D%20My%20bug">here</a>.
|
||||
</p>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "Abstract"
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
a {
|
||||
border-bottom: 1px dashed rgba(255, 255, 255, 0.2);
|
||||
text-decoration: none;
|
||||
color: inherit !important;
|
||||
|
||||
&:hover {
|
||||
color: #4CAF50 !important;
|
||||
border-bottom: 1px solid;
|
||||
}
|
||||
}
|
||||
</style>
|
148
src/components/FileUploader.vue
Normal file
@@ -0,0 +1,148 @@
|
||||
<template>
|
||||
<div
|
||||
class="drop-area pa-4 text-center"
|
||||
:class="{'drag-over':dragging, 'pb-0':!loading}"
|
||||
@dragover.prevent
|
||||
@drop.prevent="imageDropped"
|
||||
@dragenter="dragEnter()"
|
||||
@dragend="dragEnd()"
|
||||
@dragleave="dragLeave()"
|
||||
@dragexit="dragExit()"
|
||||
>
|
||||
<div v-if="loading">
|
||||
<v-progress-circular
|
||||
indeterminate
|
||||
color="primary"
|
||||
|
||||
/>
|
||||
</div>
|
||||
<div v-else>
|
||||
<p>Drag & drop a file here</p>
|
||||
<p class="or">or</p>
|
||||
<v-btn depressed @click="manualUploadClicked">select a file</v-btn>
|
||||
<input ref="uploadInput" type="file" hidden @change="(e) => handleFiles(e.target.files[0])">
|
||||
|
||||
<div v-if="allowUrl">
|
||||
<p class="or">or</p>
|
||||
<v-text-field
|
||||
ref="urlInput"
|
||||
@click:append="urlFilled(url)"
|
||||
@keypress.enter="urlFilled(url)"
|
||||
v-model="url"
|
||||
append-icon="fa-arrow-right"
|
||||
dense
|
||||
label="Paste the file url"
|
||||
outlined
|
||||
:error-messages="urlErrors"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as axios from "axios";
|
||||
|
||||
export default {
|
||||
name: "FileUploader",
|
||||
props: {
|
||||
allowUrl: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dragging: false,
|
||||
urlErrors: undefined,
|
||||
dragEnterCounter: 0,
|
||||
url: '',
|
||||
loading: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
imageDropped(e) {
|
||||
this.dragging = false;
|
||||
|
||||
if (e.dataTransfer.items.length > 0) {
|
||||
const item = e.dataTransfer.items[0];
|
||||
|
||||
switch (item.kind) {
|
||||
case 'string':
|
||||
item.getAsString(url => this.urlFilled(url));
|
||||
break;
|
||||
case 'file':
|
||||
this.handleFiles(item.getAsFile());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
dragEnter() {
|
||||
this.dragEnterCounter++;
|
||||
this.dragging = true;
|
||||
},
|
||||
dragLeave() {
|
||||
if (--this.dragEnterCounter <= 0) {
|
||||
this.dragging = false;
|
||||
}
|
||||
},
|
||||
async urlFilled(url) {
|
||||
if (url && url.length > 0) {
|
||||
this.loading = true;
|
||||
try {
|
||||
const {data, headers} = await axios.get(url);
|
||||
const name = url.split('/').pop();
|
||||
const file = new File([data], name, {type: headers['content-type']})
|
||||
|
||||
this.handleFiles(file);
|
||||
} catch (ignored) {
|
||||
this.urlErrors = 'Incorrect url'
|
||||
}
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
dragEnd() {
|
||||
this.dragging = false;
|
||||
},
|
||||
dragExit() {
|
||||
this.dragging = false;
|
||||
},
|
||||
handleFiles(file) {
|
||||
if (!file) return;
|
||||
|
||||
this.$emit('input', file)
|
||||
},
|
||||
manualUploadClicked() {
|
||||
this.$refs.uploadInput.click()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
.drop-area {
|
||||
border: 2px dashed #363636;
|
||||
border-radius: 10px;
|
||||
|
||||
& > *, .v-btn {
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
.or {
|
||||
opacity: 0.7;
|
||||
margin: 5px 0 !important;
|
||||
}
|
||||
|
||||
&.drag-over {
|
||||
border-color: #4CAF50;
|
||||
|
||||
}
|
||||
|
||||
.v-input__icon {
|
||||
button {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
</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>
|
@@ -1,60 +0,0 @@
|
||||
<template>
|
||||
<div class="hello">
|
||||
<h1>{{ msg }}</h1>
|
||||
<p>
|
||||
For a guide and recipes on how to configure / customize this project,<br>
|
||||
check out the
|
||||
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
|
||||
</p>
|
||||
<h3>Installed CLI Plugins</h3>
|
||||
<ul>
|
||||
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
|
||||
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-pwa" target="_blank" rel="noopener">pwa</a></li>
|
||||
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-router" target="_blank" rel="noopener">router</a></li>
|
||||
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
|
||||
</ul>
|
||||
<h3>Essential Links</h3>
|
||||
<ul>
|
||||
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
|
||||
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
|
||||
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
|
||||
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
|
||||
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
|
||||
</ul>
|
||||
<h3>Ecosystem</h3>
|
||||
<ul>
|
||||
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
|
||||
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
|
||||
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
|
||||
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
|
||||
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'HelloWorld',
|
||||
props: {
|
||||
msg: String
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped lang="less">
|
||||
h3 {
|
||||
margin: 40px 0 0;
|
||||
}
|
||||
ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
li {
|
||||
display: inline-block;
|
||||
margin: 0 10px;
|
||||
}
|
||||
a {
|
||||
color: #42b983;
|
||||
}
|
||||
</style>
|
59
src/components/SearchBar.vue
Normal file
@@ -0,0 +1,59 @@
|
||||
<template>
|
||||
<v-autocomplete
|
||||
label="Search..."
|
||||
single-line
|
||||
append-icon="fa-search"
|
||||
color="white"
|
||||
hide-details
|
||||
:items="items"
|
||||
item-text="text"
|
||||
item-value="path"
|
||||
solo-inverted
|
||||
@change="choose"
|
||||
:filter="filter"
|
||||
clearable
|
||||
cache-items
|
||||
>
|
||||
<template v-slot:no-data>
|
||||
<v-list-item>
|
||||
<v-list-item-title>
|
||||
Search for the <strong>tool</strong> you need!
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
</template>
|
||||
</v-autocomplete>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {toolsComponentsFlat} from '../router'
|
||||
|
||||
export default {
|
||||
name: "SearchBar",
|
||||
data() {
|
||||
const vm = this;
|
||||
return {
|
||||
items: toolsComponentsFlat,
|
||||
choose(path) {
|
||||
vm.$router.push(path).catch(() => {
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
filter(item, queryText, itemText) {
|
||||
const query = queryText.trim().toLowerCase();
|
||||
const nameContainsText = itemText.toLowerCase().includes(query);
|
||||
const keywordContainsText = item.keywords ? item.keywords.some(keyword => keyword.toLowerCase().includes(query)) : false;
|
||||
return nameContainsText || keywordContainsText;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
::v-deep .v-list-item__mask{
|
||||
color: inherit !important;
|
||||
background: inherit !important;
|
||||
}
|
||||
|
||||
</style>
|
@@ -2,10 +2,18 @@ import Vue from 'vue'
|
||||
import App from './App.vue'
|
||||
import './registerServiceWorker'
|
||||
import router from './router'
|
||||
import vuetify from './plugins/vuetify'
|
||||
import 'roboto-fontface/css/roboto/roboto-fontface.css'
|
||||
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
|
||||
|
||||
new Vue({
|
||||
router,
|
||||
vuetify,
|
||||
render: h => h(App)
|
||||
}).$mount('#app')
|
||||
|
4
src/plugins/crypto-js.js
Normal file
@@ -0,0 +1,4 @@
|
||||
import Vue from 'vue'
|
||||
import VueCryptojs from 'vue-cryptojs'
|
||||
|
||||
Vue.use(VueCryptojs)
|
4
src/plugins/toast-snackbar.js
Normal file
@@ -0,0 +1,4 @@
|
||||
import Vue from 'vue'
|
||||
import VuetifyToast from 'vuetify-toast-snackbar'
|
||||
|
||||
Vue.use(VuetifyToast)
|
10
src/plugins/vue-analytics.js
Normal file
@@ -0,0 +1,10 @@
|
||||
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
|
||||
})
|
||||
}
|
4
src/plugins/vue-headful.js
Normal file
@@ -0,0 +1,4 @@
|
||||
import Vue from 'vue';
|
||||
import vueHeadful from 'vue-headful';
|
||||
|
||||
Vue.component('vue-headful', vueHeadful);
|
29
src/plugins/vuetify.js
Normal file
@@ -0,0 +1,29 @@
|
||||
import Vue from 'vue';
|
||||
import Vuetify, { VSnackbar, VBtn, VIcon } from 'vuetify/lib'
|
||||
|
||||
Vue.use(Vuetify, {
|
||||
components: {
|
||||
VSnackbar,
|
||||
VBtn,
|
||||
VIcon
|
||||
}
|
||||
})
|
||||
export default new Vuetify({
|
||||
theme: {
|
||||
themes: {
|
||||
theme: 'dark',
|
||||
dark: {
|
||||
primary: '#4CAF50',
|
||||
secondary: '#424242',
|
||||
accent: '#4CAF50',
|
||||
error: '#FF5252',
|
||||
info: '#2196F3',
|
||||
success: '#4CAF50',
|
||||
warning: '#FFC107'
|
||||
},
|
||||
},
|
||||
},
|
||||
icons: {
|
||||
iconfont: 'fa',
|
||||
},
|
||||
});
|
145
src/router.js
Normal file
@@ -0,0 +1,145 @@
|
||||
import Vue from 'vue'
|
||||
import VueRouter from 'vue-router'
|
||||
import Home from './routes/Home.vue'
|
||||
|
||||
Vue.use(VueRouter)
|
||||
|
||||
const toolsComponents = [
|
||||
{
|
||||
title: 'Crypto',
|
||||
child: [
|
||||
{
|
||||
icon: 'fa-key',
|
||||
text: 'Token generator',
|
||||
path: '/token-generator',
|
||||
component: () => import('./routes/tools/TokenGenerator'),
|
||||
keywords: ['token', 'random', 'string', 'alphanumeric'],
|
||||
description: 'Generate random tokens.'
|
||||
},
|
||||
{
|
||||
icon: 'fa-fingerprint',
|
||||
text: 'Uuid generator',
|
||||
path: '/uuid-generator',
|
||||
component: () => import('./routes/tools/UuidGenerator'),
|
||||
keywords: ['token', 'v4', 'string', 'alphanumeric']
|
||||
},
|
||||
{
|
||||
icon: 'fa-font',
|
||||
text: 'Hash text',
|
||||
path: '/hash',
|
||||
component: () => import('./routes/tools/Hash'),
|
||||
keywords: ['md5', 'sha1', 'sha256', 'sha224', 'sha512', 'sha384', 'sha3', 'ripemd160', 'random']
|
||||
|
||||
},
|
||||
{
|
||||
icon: 'fa-lock',
|
||||
text: 'Cypher/uncypher text',
|
||||
path: '/cypher',
|
||||
component: () => import('./routes/tools/TextCypher'),
|
||||
keywords: ['aes', 'tripledes', 'rabbit', 'rabbitlegacy', 'rc4']
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Converter',
|
||||
child: [
|
||||
{
|
||||
icon: 'fa-calendar',
|
||||
text: 'Date/Time converter',
|
||||
path: '/date-converter',
|
||||
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: () => import('./routes/tools/BaseConverter'),
|
||||
keywords: ['binary', 'hexadecimal', 'decimal']
|
||||
},
|
||||
{
|
||||
icon: 'fa-palette',
|
||||
text: 'Color picker/converter',
|
||||
path: '/color-picker-converter',
|
||||
component: () => import('./routes/tools/ColorConverter'),
|
||||
keywords: ['rgb', 'rgba', 'hexadecimal', 'hsla', 'red', 'green', 'blue', 'alpha']
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Web',
|
||||
child: [
|
||||
{
|
||||
icon: 'fa-link',
|
||||
text: 'URL encode/decode',
|
||||
path: '/url-encoder',
|
||||
component: () => import('./routes/tools/UrlEncoder'),
|
||||
keywords: ['%20']
|
||||
},
|
||||
{
|
||||
icon: 'fa-file-export',
|
||||
text: 'File to Base64',
|
||||
path: '/file-to-base64',
|
||||
component: () => import('./routes/tools/FileToBase64')
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
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']
|
||||
}
|
||||
],
|
||||
}
|
||||
];
|
||||
|
||||
const toolsComponentsFlat = toolsComponents.reduce((acc, section) => [...acc, ...section.child], [])
|
||||
|
||||
const routes = [
|
||||
...toolsComponentsFlat,
|
||||
{
|
||||
path: '/',
|
||||
component: Home
|
||||
},
|
||||
{
|
||||
path: '/about',
|
||||
name: 'About',
|
||||
component: () => import('./routes/About.vue')
|
||||
},
|
||||
{
|
||||
path: '*',
|
||||
name: '404',
|
||||
component: () => import('./routes/NotFound.vue')
|
||||
}
|
||||
]
|
||||
|
||||
const router = new VueRouter({
|
||||
base: process.env.BASE_URL,
|
||||
routes
|
||||
});
|
||||
|
||||
export default router;
|
||||
export {
|
||||
routes,
|
||||
toolsComponents,
|
||||
toolsComponentsFlat
|
||||
};
|
@@ -1,29 +0,0 @@
|
||||
import Vue from 'vue'
|
||||
import VueRouter from 'vue-router'
|
||||
import Home from '../views/Home.vue'
|
||||
|
||||
Vue.use(VueRouter)
|
||||
|
||||
const routes = [
|
||||
{
|
||||
path: '/',
|
||||
name: 'Home',
|
||||
component: Home
|
||||
},
|
||||
{
|
||||
path: '/about',
|
||||
name: 'About',
|
||||
// route level code-splitting
|
||||
// this generates a separate chunk (about.[hash].js) for this route
|
||||
// which is lazy-loaded when the route is visited.
|
||||
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
|
||||
}
|
||||
]
|
||||
|
||||
const router = new VueRouter({
|
||||
mode: 'history',
|
||||
base: process.env.BASE_URL,
|
||||
routes
|
||||
})
|
||||
|
||||
export default router
|
63
src/routes/About.vue
Normal file
@@ -0,0 +1,63 @@
|
||||
<template>
|
||||
<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 GithubContributors from "../components/GithubContributors";
|
||||
import changelog from "../../CHANGELOG.md"
|
||||
import marked from 'marked'
|
||||
import DOMPurify from 'dompurify';
|
||||
|
||||
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>
|
118
src/routes/Home.vue
Normal file
@@ -0,0 +1,118 @@
|
||||
<template>
|
||||
<div>
|
||||
<v-row justify="center" align="center">
|
||||
<v-col cols="12" lg="5" md="12">
|
||||
<v-card>
|
||||
<v-card-title>IT-Tools</v-card-title>
|
||||
<v-card-text class="description">
|
||||
<Abstract />
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-row justify="center" align="center">
|
||||
<v-col cols="12" lg="8" md="12">
|
||||
<v-card class="card-auto">
|
||||
<v-card-text>
|
||||
<div class="card-wrapper ">
|
||||
<div v-for="item in items" :key="item.text" class="pa-2">
|
||||
<v-card class="card-element" color="primary" :to="item.path">
|
||||
<v-card-text>
|
||||
<v-icon>{{ item.icon }}</v-icon>
|
||||
<div class="item-title">{{item.text}}</div>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</div>
|
||||
</div>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {toolsComponentsFlat} from "../router";
|
||||
import Abstract from "../components/Abstract";
|
||||
|
||||
export default {
|
||||
name: 'Home',
|
||||
components : {
|
||||
Abstract
|
||||
},
|
||||
data: () => ({
|
||||
items: toolsComponentsFlat
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.card-auto {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.card-wrapper {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
div {
|
||||
flex: 0 1 20%;
|
||||
|
||||
@media only screen and (max-width: 800px) {
|
||||
flex: 0 1 33%;
|
||||
}
|
||||
@media only screen and (max-width: 620px) {
|
||||
flex: 0 1 50%;
|
||||
}
|
||||
@media only screen and (max-width: 420px) {
|
||||
flex: 0 1 220px;
|
||||
margin: auto;
|
||||
}
|
||||
@media only screen and (max-width: 300px) {
|
||||
flex: 0 1 100%;
|
||||
}
|
||||
|
||||
.card-element {
|
||||
width: 100%;
|
||||
border-radius: 24px 4px !important;
|
||||
color: #ffffff !important;
|
||||
font-weight: bold !important;
|
||||
text-align: center;
|
||||
transition: 0.2s ease;
|
||||
position: relative;
|
||||
top: 0;
|
||||
|
||||
&:hover {
|
||||
position: relative;
|
||||
top: -5px;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.v-card__text {
|
||||
padding: 16px 10px;
|
||||
}
|
||||
|
||||
.v-icon {
|
||||
font-size: 40px;
|
||||
color: #ffffff;
|
||||
margin: 10px 0;
|
||||
transition: 0.3s cubic-bezier(0.25, 0.8, 0.5, 1);
|
||||
|
||||
}
|
||||
|
||||
.item-title {
|
||||
overflow-wrap: anywhere;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
height: 44px;
|
||||
opacity: 1;
|
||||
color: #ffffff;
|
||||
transition: 0.3s cubic-bezier(0.25, 0.8, 0.5, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
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>
|
123
src/routes/tools/BaseConverter.vue
Normal file
@@ -0,0 +1,123 @@
|
||||
<template>
|
||||
<v-card class="single-card">
|
||||
<v-card-title>Base converter</v-card-title>
|
||||
<v-card-text>
|
||||
<v-row>
|
||||
<v-col cols="12" sm="4">
|
||||
<v-text-field
|
||||
label="Input base"
|
||||
outlined
|
||||
type="number"
|
||||
v-model.number="inputBase"
|
||||
ref="inputBase"
|
||||
hide-details="auto"
|
||||
:rules="baseRules"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="8">
|
||||
<v-text-field
|
||||
ref="inputField"
|
||||
label="Input number"
|
||||
outlined
|
||||
v-model="inputNumber"
|
||||
hide-details="auto"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<br>
|
||||
<v-divider/>
|
||||
<br>
|
||||
<v-row>
|
||||
<v-col cols="12" sm="4">
|
||||
<v-text-field
|
||||
label="Output base"
|
||||
outlined
|
||||
type="number"
|
||||
v-model.number="outputBase"
|
||||
ref="outputBase"
|
||||
:rules="baseRules"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="8">
|
||||
<v-text-field
|
||||
label="Output number"
|
||||
outlined
|
||||
v-model="outputNumber"
|
||||
readonly
|
||||
append-icon="fa-clipboard"
|
||||
@click:append="copy"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {copyToClipboard, isInt} from "../../utils/helpers";
|
||||
|
||||
const convertBase = (value, fromBase, toBase) => {
|
||||
const range = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/'.split('');
|
||||
const fromRange = range.slice(0, fromBase);
|
||||
const toRange = range.slice(0, toBase);
|
||||
|
||||
let decValue = value.split('').reverse().reduce((carry, digit, index) => {
|
||||
if (fromRange.indexOf(digit) === -1) throw new Error('Invalid digit `' + digit + '` for base ' + fromBase + '.');
|
||||
return carry += fromRange.indexOf(digit) * (Math.pow(fromBase, index));
|
||||
}, 0);
|
||||
|
||||
let newValue = '';
|
||||
while (decValue > 0) {
|
||||
newValue = toRange[decValue % toBase] + newValue;
|
||||
decValue = (decValue - (decValue % toBase)) / toBase;
|
||||
}
|
||||
return newValue || '0';
|
||||
}
|
||||
|
||||
export default {
|
||||
name: "BaseConverter",
|
||||
data() {
|
||||
return {
|
||||
inputError:'',
|
||||
inputNumber: '42',
|
||||
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'
|
||||
],
|
||||
isMounted: false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.isMounted = true;
|
||||
},
|
||||
methods: {
|
||||
copy() {
|
||||
copyToClipboard(this.outputNumber);
|
||||
this.$toast.success('Copied to clipboard.')
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
outputNumber() {
|
||||
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 ''
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
226
src/routes/tools/ColorConverter.vue
Normal file
@@ -0,0 +1,226 @@
|
||||
<template>
|
||||
<v-card class="single-card">
|
||||
<v-card-title>Color picker/converter</v-card-title>
|
||||
|
||||
<v-card-text>
|
||||
<v-row no-gutters align="center" align-content="center" justify="center">
|
||||
<v-col cols="12" sm="6" align="center">
|
||||
<v-color-picker
|
||||
flat
|
||||
canvas-height="300"
|
||||
hide-inputs
|
||||
mode="rgba"
|
||||
v-model="rgbPicker"
|
||||
@input="(v) => updateColors(v, 'picker')"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="6" align="center">
|
||||
<v-text-field
|
||||
outlined
|
||||
ref="hex"
|
||||
label="hex"
|
||||
:value="hex"
|
||||
@input="(v) => updateColors(v, 'hex')"
|
||||
:rules="rules.hex"
|
||||
dense
|
||||
/>
|
||||
<v-text-field
|
||||
outlined
|
||||
label="rgb"
|
||||
ref="rgb"
|
||||
:value="rgb"
|
||||
@input="(v) => updateColors(v, 'rgb')"
|
||||
:rules="rules.rgb"
|
||||
dense
|
||||
/>
|
||||
<v-text-field
|
||||
outlined
|
||||
label="hsl"
|
||||
ref="hsl"
|
||||
:value="hsl"
|
||||
:rules="rules.hsl"
|
||||
@input="(v) => updateColors(v, 'hsl')"
|
||||
dense
|
||||
/>
|
||||
<v-combobox
|
||||
:value="keyword"
|
||||
outlined
|
||||
label="css keyword"
|
||||
ref="keyword"
|
||||
:items="colorsName"
|
||||
:rules="rules.keyword"
|
||||
@change="(v) => updateColors(v, 'keyword')"
|
||||
no-data-text="This is not an authorized color name."
|
||||
dense
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import convert from "color-convert";
|
||||
import colors from "color-name";
|
||||
|
||||
const required = v => !!v || 'A value is required'
|
||||
|
||||
export default {
|
||||
name: "ColorConverter",
|
||||
data: () => ({
|
||||
rgbPicker: {
|
||||
"r": 76,
|
||||
"g": 175,
|
||||
"b": 80
|
||||
},
|
||||
colorsName: Object.keys(colors).sort(),
|
||||
valid: true,
|
||||
rules: {
|
||||
hex: [
|
||||
required,
|
||||
v => /^#(?:[0-9a-fA-F]{6})$/.test(v) || 'Format should be like #112233'
|
||||
],
|
||||
rgb: [
|
||||
required,
|
||||
v => /^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/.test(v) || 'Format should be like rgb(255, 0, 0)'
|
||||
],
|
||||
hsl: [
|
||||
required,
|
||||
v => /^hsl\((\d+),\s*(\d+)%,\s*(\d+)%\)$/.test(v) || 'Format should be like hsl(360, 100%, 50%)'
|
||||
],
|
||||
keywords: [
|
||||
required,
|
||||
v => !!colors[v] || 'Value should be from the list'
|
||||
]
|
||||
},
|
||||
hex: '#4CAF50',
|
||||
rgb: undefined,
|
||||
hsl: undefined,
|
||||
keyword: undefined,
|
||||
}),
|
||||
mounted() {
|
||||
this.updateColors(this.hex, 'hex');
|
||||
},
|
||||
methods: {
|
||||
setHSL(r, g, b) {
|
||||
const [h, s, l] = convert.rgb.hsl(r, g, b)
|
||||
this.hsl = `hsl(${Math.floor(h)}, ${Math.floor(s)}%, ${Math.floor(l)}%)`;
|
||||
},
|
||||
setRGB(r, g, b) {
|
||||
this.rgb = `rgb(${r}, ${g}, ${b})`;
|
||||
},
|
||||
setHEX(r, g, b) {
|
||||
const result = convert.rgb.hex(r, g, b);
|
||||
this.hex = `#${result}`
|
||||
},
|
||||
setKeyword(r, g, b) {
|
||||
this.keyword = convert.rgb.keyword(r, g, b);
|
||||
},
|
||||
updateColors(value, fromType) {
|
||||
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}
|
||||
|
||||
this.setHEX(r, g, b);
|
||||
this.setHSL(r, g, b);
|
||||
this.setKeyword(r, g, b);
|
||||
} else if (fromType === 'hex') {
|
||||
const [r, g, b] = convert.hex.rgb(value.replace(/#/g, ''));
|
||||
this.rgbPicker = {r, g, b}
|
||||
|
||||
this.setRGB(r, g, b);
|
||||
this.setHSL(r, g, b);
|
||||
this.setKeyword(r, g, b);
|
||||
} else if (fromType === 'hsl') {
|
||||
const [h, s, l] = value.match(/^hsl\((\d+),\s*(\d+)%,\s*(\d+)%\)$/).slice(1).map(v => parseInt(v));
|
||||
const [r, g, b] = convert.hsl.rgb(h, s, l)
|
||||
this.rgbPicker = {r, g, b}
|
||||
|
||||
this.setRGB(r, g, b);
|
||||
this.setHEX(r, g, b);
|
||||
this.setKeyword(r, g, b);
|
||||
} else if (fromType === 'keyword') {
|
||||
try {
|
||||
const [r, g, b] = convert.keyword.rgb(value);
|
||||
this.rgbPicker = {r, g, b}
|
||||
|
||||
this.setRGB(r, g, b);
|
||||
this.setHEX(r, g, b);
|
||||
this.setHSL(r, g, b);
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
// computed: {
|
||||
// _hex: {
|
||||
// get() {
|
||||
// const result = convert.rgb.hex(this.rgb.r, this.rgb.g, this.rgb.b)
|
||||
// return `#${result}`
|
||||
// },
|
||||
// set(value) {
|
||||
// if (this.$refs.hex.validate()) {
|
||||
// const [r, g, b] = convert.hex.rgb(value.replace(/#/g, ''))
|
||||
// this.rgb = {r, g, b}
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// _rgb: {
|
||||
// get() {
|
||||
// return `rgb(${this.rgb.r}, ${this.rgb.g}, ${this.rgb.b})`
|
||||
// },
|
||||
// set(value) {
|
||||
// if (this.$refs.rgb.validate()) {
|
||||
// const [r, g, b] = value.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/).slice(1).map(v => parseInt(v));
|
||||
// this.rgb = {r, g, b}
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// _hsl: {
|
||||
// get() {
|
||||
// const [h, s, l] = convert.rgb.hsl(this.rgb.r, this.rgb.g, this.rgb.b)
|
||||
// return `hsl(${Math.floor(h)}, ${Math.floor(s)}%, ${Math.floor(l)}%)`
|
||||
// },
|
||||
// set(value) {
|
||||
// if (this.$refs.hsl.validate()) {
|
||||
// const [h, s, l] = value.match(/^hsl\((\d+),\s*(\d+)%,\s*(\d+)%\)$/).slice(1).map(v => parseInt(v));
|
||||
// const [r, g, b] = convert.hsl.rgb(h, s, l)
|
||||
//
|
||||
// this.rgb = {r, g, b}
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// _keyword: {
|
||||
// get() {
|
||||
// return convert.rgb.keyword(this.rgb.r, this.rgb.g, this.rgb.b)
|
||||
// },
|
||||
// set(value) {
|
||||
// if (this.$refs.keyword.validate()) {
|
||||
// try {
|
||||
// const [r, g, b] = convert.keyword.rgb(value)
|
||||
// this.rgb = {r, g, b}
|
||||
// } catch (ignored) {
|
||||
// // ignored
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
::v-deep .v-input__icon {
|
||||
height: 18px !important;
|
||||
}
|
||||
</style>
|
157
src/routes/tools/DateConverter.vue
Normal file
@@ -0,0 +1,157 @@
|
||||
<template>
|
||||
<v-row justify="center" align="center">
|
||||
<v-col cols="12" xl="4" lg="6" md="12">
|
||||
<v-card class="mb-5">
|
||||
<v-card-title>Input</v-card-title>
|
||||
<v-card-text>
|
||||
<div class="text-center">
|
||||
<v-switch v-model="useCurrentDate" label="Use current date"/>
|
||||
</div>
|
||||
<v-divider></v-divider>
|
||||
<br>
|
||||
|
||||
<v-row>
|
||||
<v-col md="4" sm="12" class="pt-0 pb-0">
|
||||
<v-select
|
||||
:items="formats.filter(f => !f.title.toLowerCase().includes('locale')).map(v => v.title)"
|
||||
outlined
|
||||
label="Your date format"
|
||||
placeholder="Input format"
|
||||
v-model="inputFormatterTitle"
|
||||
@input="userInputChanged()"
|
||||
:disabled="useCurrentDate"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col md="8" sm="12" class="pt-0 pb-0">
|
||||
<v-text-field
|
||||
outlined
|
||||
v-model="inputString"
|
||||
label="Your date string"
|
||||
@input="userInputChanged()"
|
||||
:error="invalidInput"
|
||||
:disabled="useCurrentDate"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
<v-col cols="12" xl="4" lg="6" md="12">
|
||||
<v-card>
|
||||
<v-card-title>Dates formats</v-card-title>
|
||||
<v-card-text>
|
||||
|
||||
<v-text-field
|
||||
dense
|
||||
readonly
|
||||
outlined
|
||||
v-for="format of formats"
|
||||
v-bind:key="format.title"
|
||||
:label="format.title"
|
||||
:value="format.getDate()"
|
||||
append-icon="fa-clipboard"
|
||||
@click:append="copyDate(format.getDate())"
|
||||
/>
|
||||
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {copyToClipboard} from "../../utils/helpers";
|
||||
|
||||
export default {
|
||||
name: "DateConverter",
|
||||
created() {
|
||||
setInterval(this.refreshCurrentDate.bind(this), 1000);
|
||||
this.inputFormatterTitle = this.formats[1].title;
|
||||
},
|
||||
data() {
|
||||
const vm = this;
|
||||
|
||||
return {
|
||||
inputString: '',
|
||||
inputFormatterTitle: undefined,
|
||||
useCurrentDate: true,
|
||||
displayedDate: new Date(),
|
||||
invalidInput: false,
|
||||
formats: [
|
||||
{
|
||||
title: 'Locale datetime',
|
||||
getDate() {
|
||||
return vm.displayedDate.toLocaleString();
|
||||
},
|
||||
dateFromFormat(dateString) {
|
||||
return dateString
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'ISO 8601',
|
||||
getDate() {
|
||||
return vm.displayedDate.toISOString();
|
||||
},
|
||||
dateFromFormat(dateString) {
|
||||
return new Date(dateString)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'UTC format',
|
||||
getDate() {
|
||||
return vm.displayedDate.toUTCString();
|
||||
},
|
||||
dateFromFormat(dateString) {
|
||||
return new Date(dateString)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'UNIX Timestamp (ms)',
|
||||
getDate() {
|
||||
return vm.displayedDate.getTime();
|
||||
},
|
||||
dateFromFormat(dateString) {
|
||||
return new Date(parseInt(dateString))
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Complete',
|
||||
getDate() {
|
||||
return vm.displayedDate.toString();
|
||||
},
|
||||
dateFromFormat(dateString) {
|
||||
return new Date(dateString)
|
||||
}
|
||||
}
|
||||
],
|
||||
refreshCurrentDate() {
|
||||
if (this.useCurrentDate) {
|
||||
this.displayedDate = new Date();
|
||||
}
|
||||
},
|
||||
copyDate(date) {
|
||||
copyToClipboard(date);
|
||||
this.$toast.success('Copied to clipboard.')
|
||||
},
|
||||
userInputChanged() {
|
||||
try {
|
||||
this.invalidInput = false;
|
||||
const newDate = this.formats.find(f => f.title === this.inputFormatterTitle)?.dateFromFormat(this.inputString);
|
||||
|
||||
if (newDate && !isNaN(newDate.getTime())) {
|
||||
this.useCurrentDate = false;
|
||||
this.displayedDate = newDate;
|
||||
} else if (this.inputString.length > 0) {
|
||||
this.invalidInput = true;
|
||||
}
|
||||
} catch (ignored) {
|
||||
//
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
</style>
|
72
src/routes/tools/FileToBase64.vue
Normal file
@@ -0,0 +1,72 @@
|
||||
<template>
|
||||
<v-row justify="center" align="center">
|
||||
<v-col cols="12" lg="4" md="6" sm="12">
|
||||
<v-card>
|
||||
<v-card-title>File to Base64</v-card-title>
|
||||
<v-card-text>
|
||||
<FileUploader v-model="file"/>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
<v-col cols="12" lg="4" md="6" sm="12" v-if="base64 || loading">
|
||||
<v-card>
|
||||
<v-card-title>Result</v-card-title>
|
||||
<v-card-text>
|
||||
<v-textarea
|
||||
label="File in base 64"
|
||||
outlined
|
||||
readonly
|
||||
v-model="base64"
|
||||
hide-details
|
||||
:loading="loading"
|
||||
/>
|
||||
<div class="text-center mt-4">
|
||||
<v-btn @click="copyBase64()" depressed>Copy base64</v-btn>
|
||||
</div>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FileUploader from '../../components/FileUploader'
|
||||
import {copyToClipboard} from "../../utils/helpers";
|
||||
|
||||
export default {
|
||||
name: "FileToBase64",
|
||||
components: {FileUploader},
|
||||
data() {
|
||||
return {
|
||||
file: undefined,
|
||||
loading: false,
|
||||
base64: '',
|
||||
copyBase64() {
|
||||
copyToClipboard(this.base64)
|
||||
this.$toast.success('Copied to clipboard.')
|
||||
}
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
handleBase64(base64){
|
||||
this.base64 = base64;
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
file() {
|
||||
this.loading = true;
|
||||
this.base64 = '';
|
||||
const reader = new FileReader();
|
||||
reader.onload = () => this.handleBase64(reader.result);
|
||||
reader.onerror = () => this.handleBase64('[An error as occurred]');
|
||||
reader.readAsDataURL(this.file);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
73
src/routes/tools/Hash.vue
Normal file
@@ -0,0 +1,73 @@
|
||||
<template>
|
||||
<v-card class="single-card">
|
||||
<v-card-title>Hash text</v-card-title>
|
||||
<v-card-text>
|
||||
<v-textarea
|
||||
outlined
|
||||
v-model="inputText"
|
||||
label="Text to hash"
|
||||
></v-textarea>
|
||||
|
||||
<v-select
|
||||
:items="Object.keys(algorithms)"
|
||||
label="Algorithm"
|
||||
outlined
|
||||
v-model="algorithm"
|
||||
></v-select>
|
||||
|
||||
<v-textarea
|
||||
outlined
|
||||
readonly
|
||||
v-model="hashed"
|
||||
label="Hashed text"
|
||||
></v-textarea>
|
||||
<div class="text-center">
|
||||
<v-btn depressed @click="copyHash()">Copy hash</v-btn>
|
||||
</div>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Vue from 'vue'
|
||||
import {copyToClipboard} from "../../utils/helpers";
|
||||
|
||||
export default {
|
||||
name: "Hash",
|
||||
data() {
|
||||
return {
|
||||
inputText: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.',
|
||||
algorithm: 'SHA256',
|
||||
algorithms:{
|
||||
'MD5': Vue.CryptoJS.MD5,
|
||||
'SHA1': Vue.CryptoJS.SHA1,
|
||||
'SHA256': Vue.CryptoJS.SHA256,
|
||||
'SHA224': Vue.CryptoJS.SHA224,
|
||||
'SHA512': Vue.CryptoJS.SHA512,
|
||||
'SHA384': Vue.CryptoJS.SHA384,
|
||||
'SHA3': Vue.CryptoJS.SHA3,
|
||||
'RIPEMD160': Vue.CryptoJS.RIPEMD160
|
||||
},
|
||||
copyHash(){
|
||||
copyToClipboard(this.hashed)
|
||||
this.$toast.success('Copied to clipboard.')
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
hashed() {
|
||||
if(!this.algorithms[this.algorithm]){
|
||||
this.$toast.error('Invalid algorithm.')
|
||||
return '';
|
||||
}else{
|
||||
return this.algorithms[this.algorithm](this.inputText).toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</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>
|
77
src/routes/tools/MarkdownEditor.vue
Normal file
@@ -0,0 +1,77 @@
|
||||
<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;
|
||||
}
|
||||
code{
|
||||
background-color: rgba(0, 0, 0, 0.3) !important;
|
||||
box-shadow: none;
|
||||
color: #9a9a9a;
|
||||
font-weight: normal;
|
||||
}
|
||||
pre {
|
||||
width: 100%;
|
||||
|
||||
code {
|
||||
width: 100% !important;
|
||||
padding: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
95
src/routes/tools/TextCypher.vue
Normal file
@@ -0,0 +1,95 @@
|
||||
<template>
|
||||
<v-card class="single-card">
|
||||
<v-card-title>Cypher text</v-card-title>
|
||||
<v-card-text>
|
||||
<v-row justify="center" align="center">
|
||||
<v-col cols="12" lg="8" md="12">
|
||||
<v-textarea
|
||||
outlined
|
||||
v-model="key"
|
||||
label="Encryption key"
|
||||
rows="1"
|
||||
@input="encrypt"
|
||||
></v-textarea>
|
||||
</v-col>
|
||||
<v-col cols="12" lg="4" md="12">
|
||||
<v-select
|
||||
:items="Object.keys(algorithms)"
|
||||
label="Algorithm"
|
||||
outlined
|
||||
v-model="algorithm"
|
||||
@change="encrypt"
|
||||
></v-select>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-textarea
|
||||
outlined
|
||||
v-model="decrypted"
|
||||
label="Clear text"
|
||||
@input="encrypt"
|
||||
></v-textarea>
|
||||
|
||||
<v-textarea
|
||||
outlined
|
||||
v-model="encrypted"
|
||||
label="Cyphered text"
|
||||
@input="decrypt"
|
||||
></v-textarea>
|
||||
<div class="text-center">
|
||||
<v-btn depressed @click="copy()">Copy result</v-btn>
|
||||
</div>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Vue from 'vue'
|
||||
import {copyToClipboard} from "../../utils/helpers";
|
||||
|
||||
export default {
|
||||
name: "TextCypher",
|
||||
data() {
|
||||
return {
|
||||
decrypted: 'Lorem ipsum dolor sit amet.',
|
||||
key: 'sup3r s3cr3t k3y',
|
||||
encrypted: '',
|
||||
algorithm: 'AES',
|
||||
algorithms: {
|
||||
'AES': Vue.CryptoJS.AES,
|
||||
'TripleDES': Vue.CryptoJS.TripleDES,
|
||||
'Rabbit': Vue.CryptoJS.Rabbit,
|
||||
'RabbitLegacy': Vue.CryptoJS.RabbitLegacy,
|
||||
'RC4': Vue.CryptoJS.RC4
|
||||
}
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.encrypt();
|
||||
},
|
||||
methods: {
|
||||
copy(text) {
|
||||
copyToClipboard(text)
|
||||
this.$toast.success('Copied to clipboard.')
|
||||
},
|
||||
encrypt() {
|
||||
try {
|
||||
this.encrypted = this.algorithms[this.algorithm].encrypt(this.decrypted.trim(), this.key).toString()
|
||||
} catch (ignored) {
|
||||
// ignored
|
||||
}
|
||||
},
|
||||
decrypt() {
|
||||
try {
|
||||
this.decrypted = this.algorithms[this.algorithm].decrypt(this.encrypted.trim(), this.key).toString(Vue.CryptoJS.enc.Utf8)
|
||||
} catch (ignored) {
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
|
||||
</style>
|
72
src/routes/tools/TextStats.vue
Normal file
@@ -0,0 +1,72 @@
|
||||
<template>
|
||||
<v-card class="single-card">
|
||||
<v-card-title>Text stats</v-card-title>
|
||||
<v-card-text>
|
||||
<v-textarea
|
||||
outlined
|
||||
v-model="inputText"
|
||||
label="Input text"
|
||||
/>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td><strong>Character count:</strong></td>
|
||||
<td>{{ inputText.length }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Character count (without spaces):</strong></td>
|
||||
<td>{{ inputText.split(' ').join('').length }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Word count:</strong></td>
|
||||
<td>{{ inputText.length > 0 ? inputText.trim().split(/\s+/).length : 0 }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Line count:</strong></td>
|
||||
<td>{{ inputText.length > 0 ? inputText.split(/\r\n|\r|\n/).length : 0 }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Byte size:</strong></td>
|
||||
<td>{{ formatBytes(bytesSize) }} <span v-if="bytesSize >= 1024">({{bytesSize}} Bytes)</span></td>
|
||||
</tr>
|
||||
</table>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {formatBytes} from "../../utils/helpers";
|
||||
|
||||
export default {
|
||||
name: "TextStats",
|
||||
data() {
|
||||
return {
|
||||
Blob: Blob,
|
||||
formatBytes,
|
||||
inputText: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.',
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
bytesSize() {
|
||||
return new Blob([this.inputText]).size
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
table {
|
||||
width: 100%;
|
||||
|
||||
tr {
|
||||
td {
|
||||
width: 50%;
|
||||
padding: 5px;
|
||||
|
||||
&:first-child {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
82
src/routes/tools/TokenGenerator.vue
Normal file
@@ -0,0 +1,82 @@
|
||||
<template>
|
||||
<v-card class="single-card">
|
||||
<v-card-title>Token generator</v-card-title>
|
||||
|
||||
<v-card-text>
|
||||
<v-row no-gutters>
|
||||
<v-col lg="6" md="12">
|
||||
<v-switch v-model="withLowercase" label="Lowercase (abc...)"/>
|
||||
<v-switch v-model="withUppercase" label="Uppercase (ABC...)"/>
|
||||
|
||||
</v-col>
|
||||
<v-col lg="6" md="12">
|
||||
<v-switch v-model="withNumbers" label="Numbers (123...)"/>
|
||||
<v-switch v-model="withSpecials" label="Specials (#]-...)"/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
|
||||
<v-slider :label="`Length (${length})`" v-model="length" min="1" max="256"></v-slider>
|
||||
|
||||
<v-textarea outlined v-model="token"></v-textarea>
|
||||
|
||||
<div class="text-center">
|
||||
<v-btn @click="refreshToken()" depressed class="mr-4">Refresh</v-btn>
|
||||
<v-btn @click="copyToken()" depressed>Copy token</v-btn>
|
||||
</div>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {copyToClipboard} from "../../utils/helpers";
|
||||
|
||||
const shuffle = (str) => str.split('').sort(() => 0.5 - Math.random()).join('');
|
||||
const noop = () => {
|
||||
};
|
||||
|
||||
const lowercase = 'abcdefghijklmopqrstuvwxyz';
|
||||
const uppercase = 'ABCDEFGHIJKLMOPQRSTUVWXYZ';
|
||||
const numbers = '0123456789';
|
||||
const specials = '.,;:!?./-"\'#{([-|\\@)]=}*+';
|
||||
|
||||
|
||||
export default {
|
||||
name: 'TokenGenerator',
|
||||
data() {
|
||||
return {
|
||||
withNumbers: true,
|
||||
withLowercase: true,
|
||||
withUppercase: true,
|
||||
withSpecials: false,
|
||||
length: 32,
|
||||
refreshBool: true,
|
||||
refreshToken() {
|
||||
this.refreshBool = !this.refreshBool;
|
||||
},
|
||||
copyToken() {
|
||||
copyToClipboard(this.token);
|
||||
this.$toast.success('Copied to clipboard.')
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
token() {
|
||||
if (this.refreshBool) noop(); // To force recomputation
|
||||
|
||||
let result = '';
|
||||
|
||||
if (this.withLowercase) result += lowercase;
|
||||
if (this.withUppercase) result += uppercase;
|
||||
if (this.withNumbers) result += numbers;
|
||||
if (this.withSpecials) result += specials;
|
||||
|
||||
return shuffle(result.repeat(this.length)).substring(0, this.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style >
|
||||
|
||||
</style>
|
81
src/routes/tools/UrlEncoder.vue
Normal file
@@ -0,0 +1,81 @@
|
||||
<template>
|
||||
<v-row justify="center" align="center">
|
||||
<v-col cols="12" lg="4" md="6" sm="12">
|
||||
<v-card>
|
||||
<v-card-title>URL Encode</v-card-title>
|
||||
<v-card-text>
|
||||
<v-textarea
|
||||
outlined
|
||||
label="String to encode"
|
||||
v-model="encodeInput"
|
||||
/>
|
||||
<v-textarea
|
||||
readonly
|
||||
outlined
|
||||
label="URL encoded string"
|
||||
v-model="encodeOutput"
|
||||
/>
|
||||
|
||||
<div class="text-center">
|
||||
<v-btn @click="copyText(encodeOutput)" depressed>Copy result</v-btn>
|
||||
</div>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
|
||||
<v-col cols="12" lg="4" md="6" sm="12">
|
||||
<v-card>
|
||||
<v-card-title>URL Decode</v-card-title>
|
||||
<v-card-text>
|
||||
<v-textarea
|
||||
outlined
|
||||
label="String to decode"
|
||||
v-model="decodeInput"
|
||||
/>
|
||||
<v-textarea
|
||||
readonly
|
||||
outlined
|
||||
label="URL decoded string"
|
||||
v-model="decodeOutput"
|
||||
/>
|
||||
|
||||
<div class="text-center">
|
||||
<v-btn @click="copyText(decodeOutput)" depressed>Copy result</v-btn>
|
||||
</div>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
|
||||
|
||||
</v-row>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {copyToClipboard} from "../../utils/helpers";
|
||||
|
||||
export default {
|
||||
name: "UrlEncoder",
|
||||
data(){
|
||||
return {
|
||||
encodeInput: 'Hello world :)',
|
||||
decodeInput: 'Hello%20world%20%3A)',
|
||||
copyText(text){
|
||||
copyToClipboard(text)
|
||||
this.$toast.success('Copied to clipboard.')
|
||||
}
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
encodeOutput(){
|
||||
return encodeURIComponent(this.encodeInput)
|
||||
},
|
||||
decodeOutput(){
|
||||
return decodeURIComponent(this.encodeInput)
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
88
src/routes/tools/UuidGenerator.vue
Normal file
@@ -0,0 +1,88 @@
|
||||
<template>
|
||||
<v-card class="single-card">
|
||||
<v-card-title>Uuid v4 generator</v-card-title>
|
||||
|
||||
<v-card-text>
|
||||
<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 uuid{{ quantity > 1 ? 's' : ''}}</v-btn>
|
||||
</div>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
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,
|
||||
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);
|
||||
this.$toast.success('Copied to clipboard.')
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
token() {
|
||||
if (this.isMounted && this.$refs.quantity.validate()) {
|
||||
if (this.refreshBool) noop(); // To force recomputation
|
||||
|
||||
return Array.from({length: this.quantity}, generateUuid).join('\n');
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<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>
|
52
src/utils/helpers.js
Normal file
@@ -0,0 +1,52 @@
|
||||
const copyToClipboard = (text) => {
|
||||
const input = document.createElement('textarea');
|
||||
input.innerHTML = text;
|
||||
document.body.appendChild(input);
|
||||
input.select();
|
||||
const result = document.execCommand('copy');
|
||||
document.body.removeChild(input);
|
||||
return result;
|
||||
}
|
||||
|
||||
const fileIsImage = (file) => {
|
||||
return file.type.split('/')[0] === 'image';
|
||||
}
|
||||
|
||||
const formatBytes = (bytes, decimals = 2) => {
|
||||
if (bytes === 0) return '0 Bytes';
|
||||
|
||||
const k = 1024;
|
||||
const dm = decimals < 0 ? 0 : decimals;
|
||||
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
||||
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
|
||||
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)
|
||||
|
||||
export {
|
||||
copyToClipboard,
|
||||
fileIsImage,
|
||||
formatBytes,
|
||||
isInt,
|
||||
debounce,
|
||||
randFromArray,
|
||||
randIntFromInterval
|
||||
}
|
@@ -1,5 +0,0 @@
|
||||
<template>
|
||||
<div class="about">
|
||||
<h1>This is an about page</h1>
|
||||
</div>
|
||||
</template>
|
@@ -1,18 +0,0 @@
|
||||
<template>
|
||||
<div class="home">
|
||||
<img alt="Vue logo" src="../assets/logo.png">
|
||||
<HelloWorld msg="Welcome to Your Vue.js App"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// @ is an alias to /src
|
||||
import HelloWorld from '@/components/HelloWorld.vue'
|
||||
|
||||
export default {
|
||||
name: 'Home',
|
||||
components: {
|
||||
HelloWorld
|
||||
}
|
||||
}
|
||||
</script>
|
23
vue.config.js
Normal file
@@ -0,0 +1,23 @@
|
||||
const webpack = require('webpack');
|
||||
|
||||
module.exports = {
|
||||
"transpileDependencies": [
|
||||
"vuetify"
|
||||
],
|
||||
configureWebpack: () => {
|
||||
return {
|
||||
module:{
|
||||
rules: [
|
||||
{ test: /\.md$/, use: 'raw-loader' }
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': {
|
||||
'APPLICATION_VERSION': JSON.stringify(require('./package.json').version),
|
||||
}
|
||||
})
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|