mirror of
				https://github.com/CorentinTh/it-tools.git
				synced 2025-10-31 12:03:48 +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). | ||||
							
								
								
									
										522
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										522
									
								
								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,8 +3297,8 @@ | ||||
|       "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", | ||||
| @@ -3239,13 +3306,37 @@ | ||||
|           "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": "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.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.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> | ||||
|   | ||||
							
								
								
									
										203
									
								
								src/App.vue
									
									
									
									
									
								
							
							
						
						
									
										203
									
								
								src/App.vue
									
									
									
									
									
								
							| @@ -1,32 +1,195 @@ | ||||
| <template> | ||||
|   <div id="app"> | ||||
|     <div id="nav"> | ||||
|       <router-link to="/">Home</router-link> | | ||||
|     <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> | ||||
|     <router-view/> | ||||
|   </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; | ||||
|     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() | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| </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 { | ||||
|     font-weight: bold; | ||||
|     color: #2c3e50; | ||||
|             border-bottom: 1px dashed; | ||||
|             text-decoration: none; | ||||
|             color: rgba(255, 255, 255, 0.52) !important; | ||||
|  | ||||
|     &.router-link-exact-active { | ||||
|       color: #42b983; | ||||
|             &: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