mirror of
https://github.com/CorentinTh/it-tools.git
synced 2025-10-23 04:52:14 +00:00
Compare commits
32 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
44a18a1484 | ||
|
c6dd9b4ff9 | ||
|
ef2f5bae33 | ||
|
4fdd6439ca | ||
|
e25928e434 | ||
|
67808db93a | ||
|
201cf24325 | ||
|
caa559e905 | ||
|
dfc8876e71 | ||
|
d512db0951 | ||
|
8a054561bc | ||
|
d22988ba4e | ||
|
95df202ea1 | ||
|
cab52baa66 | ||
|
f2af2ed35d | ||
|
7dc70c5741 | ||
|
db189b4bcb | ||
|
d4f57fde34 | ||
|
da2891751d | ||
|
793d840c49 | ||
|
4801e2f6c5 | ||
|
e47ff2456b | ||
|
0c120a3c5a | ||
|
e5969a534f | ||
|
abc7fc6259 | ||
|
1876db0ddc | ||
|
da092a9bd3 | ||
|
49f0721107 | ||
|
34889eb1ce | ||
|
3ef90b84ca | ||
|
662b84cda0 | ||
|
e1ebeefdc4 |
BIN
.github/logo.png
vendored
Normal file
BIN
.github/logo.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.8 KiB |
76
CODE_OF_CONDUCT.md
Normal file
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
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
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.
|
55
README.md
55
README.md
@@ -1,24 +1,53 @@
|
||||
# it-tools
|
||||

|
||||
|
||||
Aggregated set of useful tools that every developer may need once in a while. Available [here](https://it-tools.tech).
|
||||
|
||||
## Functionality/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
|
||||
- [ ] Lorem ipsum text generator
|
||||
- [ ] Image exif editor/remover
|
||||
- [ ] QR code generator
|
||||
- [ ] Bip39 pass-phrase generator
|
||||
- [ ] Crontab friendly generator
|
||||
- [ ] Image format converter?
|
||||
- [ ] Image cropper
|
||||
|
||||
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).
|
536
package-lock.json
generated
536
package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "it-tools",
|
||||
"version": "0.1.0",
|
||||
"version": "1.0.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",
|
||||
@@ -3195,6 +3251,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 +3297,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 +3731,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",
|
||||
@@ -4751,9 +4847,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,6 +6242,11 @@
|
||||
"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",
|
||||
@@ -6212,9 +6313,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 +6464,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 +6760,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 +6775,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 +7308,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 +8049,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 +8088,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",
|
||||
@@ -8049,25 +8126,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 +8681,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 +8865,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",
|
||||
@@ -10050,6 +10089,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 +10434,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 +10493,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 +10743,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 +10773,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 +10955,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 +12117,32 @@
|
||||
"resolved": "https://registry.npmjs.org/vue/-/vue-2.6.11.tgz",
|
||||
"integrity": "sha512-VfPwgcGABbGAue9+sfrD4PuwFar7gPb1yl1UK1MwXoQPAw0BKSqWfoYCT/ThFrdEVWoI51dBuyCoiNU9bZDZxQ=="
|
||||
},
|
||||
"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 +12169,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 +12243,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 +12388,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 +12401,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 +12435,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 +12477,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 +12523,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 +12563,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 +12609,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,13 +12704,11 @@
|
||||
}
|
||||
},
|
||||
"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"
|
||||
}
|
||||
},
|
||||
|
20
package.json
20
package.json
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"name": "it-tools",
|
||||
"version": "0.1.0",
|
||||
"description": "",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
@@ -8,12 +9,21 @@
|
||||
"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",
|
||||
"register-service-worker": "^1.7.1",
|
||||
"roboto-fontface": "*",
|
||||
"vue": "^2.6.11",
|
||||
"vue-router": "^3.1.6"
|
||||
"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 +35,11 @@
|
||||
"less": "^3.0.4",
|
||||
"less-loader": "^5.0.0",
|
||||
"lint-staged": "^9.5.0",
|
||||
"vue-template-compiler": "^2.6.11"
|
||||
"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"
|
||||
|
BIN
public/img/banner.png
Normal file
BIN
public/img/banner.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 64 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">
|
||||
<meta property="og:title">
|
||||
<meta name="twitter:title">
|
||||
<meta name="description"/>
|
||||
<meta itemprop="description">
|
||||
<meta property="og:description">
|
||||
<meta name="twitter:description">
|
||||
<meta itemprop="image">
|
||||
<meta property="og:image">
|
||||
<meta name="twitter:image">
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
|
217
src/App.vue
217
src/App.vue
@@ -1,32 +1,195 @@
|
||||
<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>
|
||||
|
||||
<SearchBar class="hidden-sm-and-up" />
|
||||
|
||||
<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>{{ 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;
|
||||
}
|
||||
|
||||
.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>
|
Binary file not shown.
Before Width: | Height: | Size: 6.7 KiB |
48
src/components/Abstract.vue
Normal file
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
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>
|
@@ -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
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,17 @@ 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'
|
||||
|
||||
Vue.config.productionTip = false
|
||||
|
||||
new Vue({
|
||||
router,
|
||||
vuetify,
|
||||
render: h => h(App)
|
||||
}).$mount('#app')
|
||||
|
4
src/plugins/crypto-js.js
Normal file
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
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)
|
4
src/plugins/vue-headful.js
Normal file
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
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',
|
||||
},
|
||||
});
|
138
src/router.js
Normal file
138
src/router.js
Normal file
@@ -0,0 +1,138 @@
|
||||
import Vue from 'vue'
|
||||
import VueRouter from 'vue-router'
|
||||
import Home from './routes/Home.vue'
|
||||
import TokenGenerator from "./routes/tools/TokenGenerator";
|
||||
import Hash from "./routes/tools/Hash";
|
||||
import DateConverter from "./routes/tools/DateConverter";
|
||||
import UrlEncoder from "./routes/tools/UrlEncoder";
|
||||
import FileToBase64 from "./routes/tools/FileToBase64";
|
||||
import TextCypher from "./routes/tools/TextCypher";
|
||||
import TextStats from "./routes/tools/TextStats";
|
||||
import BaseConverter from "./routes/tools/BaseConverter";
|
||||
import UuidGenerator from "./routes/tools/UuidGenerator";
|
||||
import ColorConverter from "./routes/tools/ColorConverter";
|
||||
|
||||
Vue.use(VueRouter)
|
||||
|
||||
|
||||
const toolsComponents = [
|
||||
{
|
||||
title: 'Crypto',
|
||||
child: [
|
||||
{
|
||||
icon: 'fa-key',
|
||||
text: 'Token generator',
|
||||
path: '/token-generator',
|
||||
component: TokenGenerator,
|
||||
keywords: ['token', 'random', 'string', 'alphanumeric'],
|
||||
description: 'Generate random tokens.'
|
||||
},
|
||||
{
|
||||
icon: 'fa-fingerprint',
|
||||
text: 'Uuid generator',
|
||||
path: '/uuid-generator',
|
||||
component: UuidGenerator,
|
||||
keywords: ['token', 'v4', 'string', 'alphanumeric']
|
||||
},
|
||||
{
|
||||
icon: 'fa-font',
|
||||
text: 'Hash text',
|
||||
path: '/hash',
|
||||
component: Hash,
|
||||
keywords: ['md5', 'sha1', 'sha256', 'sha224', 'sha512', 'sha384', 'sha3', 'ripemd160', 'random']
|
||||
|
||||
},
|
||||
{
|
||||
icon: 'fa-lock',
|
||||
text: 'Cypher/uncypher text',
|
||||
path: '/cypher',
|
||||
component: TextCypher,
|
||||
keywords: ['aes', 'tripledes', 'rabbit', 'rabbitlegacy', 'rc4']
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Converter',
|
||||
child: [
|
||||
{
|
||||
icon: 'fa-calendar',
|
||||
text: 'Date/Time converter',
|
||||
path: '/date-converter',
|
||||
component: DateConverter,
|
||||
keywords: ['locale', 'format', 'iso 8601', 'utc', 'timestamp', 'unix', 'year', 'month', 'day', 'hours', 'minutes', 'seconds']
|
||||
},
|
||||
{
|
||||
icon: 'fa-exchange-alt',
|
||||
text: 'Base converter',
|
||||
path: '/base-converter',
|
||||
component: BaseConverter,
|
||||
keywords: ['binary', 'hexadecimal', 'decimal']
|
||||
},
|
||||
{
|
||||
icon: 'fa-palette',
|
||||
text: 'Color picker/converter',
|
||||
path: '/color-picker-converter',
|
||||
component: ColorConverter,
|
||||
keywords: ['rgb', 'rgba', 'hexadecimal', 'hsla', 'red', 'green', 'blue', 'alpha']
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Web',
|
||||
child: [
|
||||
{
|
||||
icon: 'fa-link',
|
||||
text: 'URL encode/decode',
|
||||
path: '/url-encoder',
|
||||
component: UrlEncoder,
|
||||
keywords: ['%20']
|
||||
},
|
||||
{
|
||||
icon: 'fa-file-export',
|
||||
text: 'File to Base64',
|
||||
path: '/file-to-base64',
|
||||
component: FileToBase64
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Miscellaneous',
|
||||
child: [
|
||||
{
|
||||
icon: 'fa-align-left\n',
|
||||
text: 'Text stats',
|
||||
path: '/text-stats',
|
||||
component: TextStats,
|
||||
keywords: ['word', 'count', 'size', 'bytes', 'length']
|
||||
},
|
||||
],
|
||||
}
|
||||
];
|
||||
|
||||
const toolsComponentsFlat = toolsComponents.reduce((acc, section) => [...acc, ...section.child], [])
|
||||
|
||||
const routes = [
|
||||
...toolsComponentsFlat,
|
||||
{
|
||||
path: '/',
|
||||
component: Home
|
||||
},
|
||||
{
|
||||
path: '/about',
|
||||
name: 'About',
|
||||
component: () => import('./routes/About.vue')
|
||||
}
|
||||
]
|
||||
|
||||
const router = new VueRouter({
|
||||
mode: 'history',
|
||||
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
|
19
src/routes/About.vue
Normal file
19
src/routes/About.vue
Normal file
@@ -0,0 +1,19 @@
|
||||
<template>
|
||||
<v-card class="single-card">
|
||||
<v-card-title>About</v-card-title>
|
||||
<v-card-text>
|
||||
<Abstract />
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Abstract from "../components/Abstract";
|
||||
|
||||
export default {
|
||||
name: "About",
|
||||
components : {
|
||||
Abstract
|
||||
},
|
||||
}
|
||||
</script>
|
118
src/routes/Home.vue
Normal file
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>
|
112
src/routes/tools/BaseConverter.vue
Normal file
112
src/routes/tools/BaseConverter.vue
Normal file
@@ -0,0 +1,112 @@
|
||||
<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="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="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} 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 => !!v || 'Required',
|
||||
v => v > 1 || 'Base should be > 1',
|
||||
v => v <= 64 || 'Base should be <= 64',
|
||||
],
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
copy() {
|
||||
copyToClipboard(this.outputNumber);
|
||||
this.$toast.success('Copied to clipboard.')
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
outputNumber() {
|
||||
try{
|
||||
return convertBase(this.inputNumber, this.inputBase, this.outputBase)
|
||||
}catch (e) {
|
||||
return e.message;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
218
src/routes/tools/ColorConverter.vue
Normal file
218
src/routes/tools/ColorConverter.vue
Normal file
@@ -0,0 +1,218 @@
|
||||
<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"
|
||||
/>
|
||||
</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 (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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
// 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
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
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
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>
|
||||
|
95
src/routes/tools/TextCypher.vue
Normal file
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
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
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
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>
|
47
src/routes/tools/UuidGenerator.vue
Normal file
47
src/routes/tools/UuidGenerator.vue
Normal file
@@ -0,0 +1,47 @@
|
||||
<template>
|
||||
<v-card class="single-card">
|
||||
<v-card-title>Uuid v4 generator</v-card-title>
|
||||
|
||||
<v-card-text>
|
||||
<v-text-field outlined v-model="token" class="centered-input"/>
|
||||
|
||||
<div class="text-center">
|
||||
<v-btn @click="refreshBool = !refreshBool" depressed class="mr-4">Refresh</v-btn>
|
||||
<v-btn @click="copyToken()" depressed>Copy token</v-btn>
|
||||
</div>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {copyToClipboard} from "../../utils/helpers";
|
||||
|
||||
const noop = () => {
|
||||
};
|
||||
|
||||
export default {
|
||||
name: "UuidGenerator",
|
||||
data: () => ({
|
||||
refreshBool: true
|
||||
}),
|
||||
methods: {
|
||||
copyToken() {
|
||||
copyToClipboard(this.token);
|
||||
this.$toast.success('Copied to clipboard.')
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
token() {
|
||||
if (this.refreshBool) noop(); // To force recomputation
|
||||
|
||||
return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c => (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16));
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
::v-deep .centered-input input {
|
||||
text-align: center
|
||||
}
|
||||
</style>
|
31
src/utils/helpers.js
Normal file
31
src/utils/helpers.js
Normal file
@@ -0,0 +1,31 @@
|
||||
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];
|
||||
}
|
||||
|
||||
export {
|
||||
copyToClipboard,
|
||||
fileIsImage,
|
||||
formatBytes
|
||||
}
|
@@ -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>
|
18
vue.config.js
Normal file
18
vue.config.js
Normal file
@@ -0,0 +1,18 @@
|
||||
const webpack = require('webpack');
|
||||
|
||||
module.exports = {
|
||||
"transpileDependencies": [
|
||||
"vuetify"
|
||||
],
|
||||
configureWebpack: () => {
|
||||
return {
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': {
|
||||
'APPLICATION_VERSION': JSON.stringify(require('./package.json').version),
|
||||
}
|
||||
})
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user