feat: added components
							
								
								
									
										68
									
								
								CHANGELOG.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,68 @@ | |||||||
|  | # Changelog | ||||||
|  | All notable changes to this project will be documented in this file. | ||||||
|  | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), | ||||||
|  | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). | ||||||
|  | 
 | ||||||
|  | ## Next | ||||||
|  | ### Changed | ||||||
|  | - Switched to [Nuxt.js](//nuxtjs.org) | ||||||
|  |     - Server-Side rendered static app  | ||||||
|  |     - Better SEO | ||||||
|  | - Switched to Typescript using class components decorators from [nuxt-property-decorator](https://github.com/nuxt-community/nuxt-property-decorator) | ||||||
|  | - UI and theme reworked | ||||||
|  | - URL path changed | ||||||
|  |     - `/hash` -> [`/hash-text`](https://it-tools.tech/hash-text) | ||||||
|  |     - `/cypher` -> [`/cypher-uncyfer-text`](https://it-tools.tech/cypher-uncyfer-text) | ||||||
|  | 
 | ||||||
|  | ### Added | ||||||
|  | - Added [/how-to-report-bug-or-request](/how-to-report-bug-or-request) route to explain how to report bug and request features | ||||||
|  | 
 | ||||||
|  | ## 1.7.0 | ||||||
|  | - [feat] [Crontab friendly generator](https://it-tools.tech/crontab-generator) | ||||||
|  | 
 | ||||||
|  | ## 1.6.0 | ||||||
|  | - [feat] [BIP39 generator](https://it-tools.tech/bip39-generator) | ||||||
|  | - [feat] [Base 64 converter](https://it-tools.tech/base64-string-converter) | ||||||
|  | 
 | ||||||
|  | ## 1.5.2 | ||||||
|  | - [feat] [humans.txt](https://it-tools.tech/humans.txt) | ||||||
|  | - [feat] pwa auto update on new changes | ||||||
|  | 
 | ||||||
|  | ## 1.5.1 | ||||||
|  | - [feat] switched back to history mode (no more '#' in url) | ||||||
|  | 
 | ||||||
|  | ## 1.5.0 | ||||||
|  | - [feat] added [qr-code generator](https://it-tools.tech/qrcode-generator) | ||||||
|  | 
 | ||||||
|  | ## 1.4.0 | ||||||
|  | - [ui] condensed + colored sidenav | ||||||
|  | - [feat] added [git memo](https://it-tools.tech/git-memo) | ||||||
|  | - [refactor] changed app title | ||||||
|  | 
 | ||||||
|  | ## 1.3.0 | ||||||
|  | - [fix] [GithubContributors] ordered contributors by contribution count | ||||||
|  | - [refactor] used vue-typecasting for number inputs | ||||||
|  | - [feat] lazy loading tools routes | ||||||
|  | - [feat] added [markdown editor](https://it-tools.tech/markdown-editor) | ||||||
|  | - [feat] added [lorem ipsum generator](https://it-tools.tech/lorem-ipsum-generator) | ||||||
|  | 
 | ||||||
|  | ## 1.2.1 | ||||||
|  | - [fix] [UuidGenerator] added quantity validation rules | ||||||
|  | - [refactor] better isInt checker | ||||||
|  | 
 | ||||||
|  | ## 1.2.0 | ||||||
|  | - [feat] [UuidGenerator] can generate multiple uuids  | ||||||
|  | 
 | ||||||
|  | ## 1.1.0 | ||||||
|  | - [feat] 404 route + page | ||||||
|  | - [feat] changelog in the About page  | ||||||
|  | - [feat] contributors list in the About page  | ||||||
|  | - [fix] [ColorConverter] color picker now updates fields  | ||||||
|  | 
 | ||||||
|  | ## 1.0.1 | ||||||
|  | - [chore] added changelog | ||||||
|  | - [fix] [BaseConverter] prevented non-integer bases | ||||||
|  | - [fix] remove history move (incompatible with vercel.com) | ||||||
|  | 
 | ||||||
|  | ## 1.0.0 | ||||||
|  | - First release | ||||||
| @ -3,3 +3,4 @@ | |||||||
| // The variables you want to modify | // The variables you want to modify | ||||||
| // $font-size-root: 20px; | // $font-size-root: 20px; | ||||||
| 
 | 
 | ||||||
|  | $test: linear-gradient(90deg, rgba(37, 99, 108, 1) 0%, rgba(59, 149, 111, 1) 60%, rgba(71, 177, 113, 1) 100%) | ||||||
|  | |||||||
| @ -2,14 +2,15 @@ | |||||||
|   <v-autocomplete |   <v-autocomplete | ||||||
|     label="Search..." |     label="Search..." | ||||||
|     single-line |     single-line | ||||||
|     append-icon="fa-search" |     append-icon="mdi-magnify" | ||||||
|     color="white" |     color="white" | ||||||
|     hide-details |     hide-details | ||||||
|     :items="items" |     :items="toolRoutesFlat" | ||||||
|     item-text="text" |     :item-text="item => item.config.title" | ||||||
|     item-value="path" |     item-value="path" | ||||||
|     solo-inverted |     solo-inverted | ||||||
|     :filter="filter" |     dense | ||||||
|  |     :filter="filterItems" | ||||||
|     clearable |     clearable | ||||||
|     cache-items |     cache-items | ||||||
|     @change="choose" |     @change="choose" | ||||||
| @ -24,23 +25,39 @@ | |||||||
|   </v-autocomplete> |   </v-autocomplete> | ||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
| <script> | <script lang="ts"> | ||||||
| import {Component, Vue} from 'nuxt-property-decorator' | import {Component, mixins} from 'nuxt-property-decorator' | ||||||
| import {ToolRoutes} from '~/mixins/tool-routes' | import {ToolRoutesMixin} from '@/mixins/tool-routes.mixin' | ||||||
|  | import {ToolRouteConfig} from '~/types/ToolConfig' | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component | ||||||
|   mixins: [ToolRoutes] | export default class SearchBar extends mixins(ToolRoutesMixin) { | ||||||
| }) |   choose(path:string) { | ||||||
| export default class SearchBar extends Vue { |     this.$router.push({path}) | ||||||
|   title = 'IT - Tools' |   } | ||||||
|   drawer = false | 
 | ||||||
|   items = [] |   filterItems(item:ToolRouteConfig, queryText:string, itemText:string) { | ||||||
|  |     const query = queryText.trim().toLowerCase() | ||||||
|  |     const nameContainsText = itemText.toLowerCase().includes(query) | ||||||
|  |     const keywordContainsText = item?.config?.keywords.some((keyword:string) => keyword.toLowerCase().includes(query)) ?? false | ||||||
|  |     return nameContainsText || keywordContainsText | ||||||
|  |   } | ||||||
| } | } | ||||||
| </script> | </script> | ||||||
| 
 | 
 | ||||||
| <style scoped lang="less"> | <style scoped lang="less"> | ||||||
| ::v-deep .v-list-item__mask{ | ::v-deep { | ||||||
|   color: inherit !important; |   .v-input__slot{ | ||||||
|   background: inherit !important; |     background: var(--v-primary-base) !important; | ||||||
|  |     background: linear-gradient(90deg, rgba(37,99,108,1) 0%, rgba(59,149,111,1) 60%, rgba(71,177,113,1) 100%) !important; | ||||||
|  |     input { | ||||||
|  |       color: #ffffff !important; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .v-list{ | ||||||
|  |   background: var(--v-foreground-base) !important; | ||||||
| } | } | ||||||
| </style> | </style> | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| <template> | <template> | ||||||
|   <div class="tool-wrapper"> |   <div class="tool-wrapper"> | ||||||
|     <v-row no-gutters justify="center" align="center"> |     <v-row no-gutters justify="center" align="center"> | ||||||
|       <v-col cols="12" lg="6"> |       <v-col cols="12" xl="6" lg="8" md="10"> | ||||||
|         <div class="tool-wrapper-info"> |         <div class="tool-wrapper-info"> | ||||||
|           <h1>{{ config.title }}</h1> |           <h1>{{ config.title }}</h1> | ||||||
|           <div class="spacer" /> |           <div class="spacer" /> | ||||||
| @ -50,9 +50,10 @@ export default class ToolWrapper extends Vue { | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   .spacer{ |   .spacer{ | ||||||
|     width: 130px; |     width: 200px; | ||||||
|     height: 1px; |     height: 2px; | ||||||
|     background-color: var(--v-primary-base); |     background: var(--v-primary-base); | ||||||
|  |     background: linear-gradient(90deg, rgba(71, 177, 113, 1) 0%, rgba(59, 149, 111, 1) 60%, rgba(37, 99, 108, 1) 200%); | ||||||
|     margin-bottom: 10px; |     margin-bottom: 10px; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -17,6 +17,8 @@ | |||||||
|         </div> |         </div> | ||||||
|       </div> |       </div> | ||||||
| 
 | 
 | ||||||
|  |       <SearchBar class="hidden-sm-and-up" /> | ||||||
|  | 
 | ||||||
|       <v-list> |       <v-list> | ||||||
|         <div v-for="(items, section) in toolRoutesSections" :key="section"> |         <div v-for="(items, section) in toolRoutesSections" :key="section"> | ||||||
|           <v-subheader class="mt-4 pl-4"> |           <v-subheader class="mt-4 pl-4"> | ||||||
| @ -26,13 +28,15 @@ | |||||||
|           <v-list-item |           <v-list-item | ||||||
|             v-for="(item, i) in items" |             v-for="(item, i) in items" | ||||||
|             :key="i" |             :key="i" | ||||||
|             :to="items.path" |             :to="item.path" | ||||||
|             router |             router | ||||||
|             exact |             exact | ||||||
|             dense |             dense | ||||||
|           > |           > | ||||||
|             <v-list-item-action> |             <v-list-item-action> | ||||||
|               <v-icon>{{ item.config.icon }}</v-icon> |               <v-icon color="primary"> | ||||||
|  |                 {{ item.config.icon }} | ||||||
|  |               </v-icon> | ||||||
|             </v-list-item-action> |             </v-list-item-action> | ||||||
|             <v-list-item-content> |             <v-list-item-content> | ||||||
|               <v-list-item-title v-text="item.config.title" /> |               <v-list-item-title v-text="item.config.title" /> | ||||||
| @ -48,8 +52,24 @@ | |||||||
|       height="60px" |       height="60px" | ||||||
|     > |     > | ||||||
|       <v-app-bar-nav-icon @click.stop="drawer = !drawer" /> |       <v-app-bar-nav-icon @click.stop="drawer = !drawer" /> | ||||||
|       <v-toolbar-title v-if="!drawer" v-text="title" /> |       <v-toolbar-title> | ||||||
|  |         <NuxtLink to="/" class="title"> | ||||||
|  |           {{ title }} | ||||||
|  |         </NuxtLink> | ||||||
|  |       </v-toolbar-title> | ||||||
|       <v-spacer /> |       <v-spacer /> | ||||||
|  |       <SearchBar class="hidden-sm-and-down" /> | ||||||
|  |       <v-spacer /> | ||||||
|  | 
 | ||||||
|  |       <NuxtLink to="/how-to-report-bug-or-request"> | ||||||
|  |         Bug / Request | ||||||
|  |       </NuxtLink> | ||||||
|  |       <NuxtLink to="/about"> | ||||||
|  |         About | ||||||
|  |       </NuxtLink> | ||||||
|  |       <a href="https://github.com/CorentinTh/it-tools" target="_blank" class="github-link"> | ||||||
|  |         <v-icon>mdi-github</v-icon> | ||||||
|  |       </a> | ||||||
|     </v-app-bar> |     </v-app-bar> | ||||||
| 
 | 
 | ||||||
|     <v-main> |     <v-main> | ||||||
| @ -65,17 +85,19 @@ | |||||||
| 
 | 
 | ||||||
| <script lang="ts"> | <script lang="ts"> | ||||||
| import {Component, mixins} from 'nuxt-property-decorator' | import {Component, mixins} from 'nuxt-property-decorator' | ||||||
| import {ToolRoutes} from '~/mixins/tool-routes' | import {ToolRoutesMixin} from '~/mixins/tool-routes.mixin' | ||||||
| import LogoOutlined from '~/assets/logo-outlined.svg?inline' | import LogoOutlined from '~/assets/logo-outlined.svg?inline' | ||||||
| import HeroGradient from '~/assets/small-hero-gradient.svg?inline' | import HeroGradient from '~/assets/small-hero-gradient.svg?inline' | ||||||
|  | import SearchBar from '~/components/SearchBar.vue' | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   components: { |   components: { | ||||||
|     LogoOutlined, |     LogoOutlined, | ||||||
|     HeroGradient |     HeroGradient, | ||||||
|  |     SearchBar | ||||||
|   } |   } | ||||||
| }) | }) | ||||||
| export default class DefaultLayout extends mixins(ToolRoutes) { | export default class DefaultLayout extends mixins(ToolRoutesMixin) { | ||||||
|   title = 'IT - Tools' |   title = 'IT - Tools' | ||||||
|   drawer = false |   drawer = false | ||||||
|   items = [] |   items = [] | ||||||
| @ -84,6 +106,40 @@ export default class DefaultLayout extends mixins(ToolRoutes) { | |||||||
| 
 | 
 | ||||||
| <style lang="less"> | <style lang="less"> | ||||||
| 
 | 
 | ||||||
|  | .v-toolbar__content { | ||||||
|  |   a { | ||||||
|  |     color: #ffffff; | ||||||
|  |     text-decoration: none; | ||||||
|  |     transition: all ease 0.2s; | ||||||
|  |     margin: 0 10px; | ||||||
|  |     opacity: 0.5; | ||||||
|  |     font-size: 15px; | ||||||
|  | 
 | ||||||
|  |     &.title{ | ||||||
|  |       opacity: 1; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     &:hover { | ||||||
|  |       opacity: 1; | ||||||
|  |       color: var(--v-primary-base); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   .github-link { | ||||||
|  |     border-bottom: none; | ||||||
|  |     margin-left: 10px; | ||||||
|  |     transition: all ease 0.2s; | ||||||
|  | 
 | ||||||
|  |     .v-icon { | ||||||
|  |       font-size: 37px !important; | ||||||
|  |       color: var(--v-primary-base); | ||||||
|  |       transition: all ease 0.2s; | ||||||
|  |       transition: all ease 0.2s; | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| .small-hero { | .small-hero { | ||||||
|   position: relative; |   position: relative; | ||||||
| 
 | 
 | ||||||
| @ -96,18 +152,26 @@ export default class DefaultLayout extends mixins(ToolRoutes) { | |||||||
|     width: 100%; |     width: 100%; | ||||||
| 
 | 
 | ||||||
|     .small-hero-content-logo { |     .small-hero-content-logo { | ||||||
|       width: 30%; |       width: 25%; | ||||||
|       margin: 0 auto; |       margin: 0 auto; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     .small-hero-content-title { |     .small-hero-content-title { | ||||||
|       font-size: 30px; |       margin-top: 10px; | ||||||
|  |       font-size: 25px; | ||||||
|       font-weight: 600; |       font-weight: 600; | ||||||
|       font-family: Ubuntu, Roboto, sans-serif; |       font-family: Ubuntu, Roboto, sans-serif; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | .v-navigation-drawer__content{ | ||||||
|  |   .v-list-item--active{ | ||||||
|  |     color: var(--v-anchor-base); | ||||||
|  |     border-left: 3px solid var(--v-primary-base); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| .v-application { | .v-application { | ||||||
|   background-color: var(--v-background-base, #121212) !important; |   background-color: var(--v-background-base, #121212) !important; | ||||||
| } | } | ||||||
|  | |||||||
| @ -11,7 +11,7 @@ const copyToClipboard = (text: string) => { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @Component | @Component | ||||||
| export class Copyable extends Vue { | export class CopyableMixin extends Vue { | ||||||
|   copy(text: string, toastText = 'Copied to clipboard !') { |   copy(text: string, toastText = 'Copied to clipboard !') { | ||||||
|     copyToClipboard(text) |     copyToClipboard(text) | ||||||
|     console.log(toastText) |     console.log(toastText) | ||||||
| @ -1,33 +1,36 @@ | |||||||
| import {Component, Vue} from 'nuxt-property-decorator' | import {Component, Vue} from 'nuxt-property-decorator' | ||||||
| import {RouteConfig} from '@nuxt/types/config/router' | import {ToolRouteConfig} from '~/types/ToolConfig' | ||||||
| import {ToolConfig} from '~/types/ToolConfig' |  | ||||||
| import {capitalise} from '~/utils/string' | import {capitalise} from '~/utils/string' | ||||||
| 
 | 
 | ||||||
| export type ToolRouteConfig = RouteConfig & {config: ToolConfig} |  | ||||||
| 
 | 
 | ||||||
| @Component | @Component | ||||||
| export class ToolRoutes extends Vue { | export class ToolRoutesMixin extends Vue { | ||||||
|   toolRoutesFlat : ToolRouteConfig[] = [] |   toolRoutesFlat : ToolRouteConfig[] = [] | ||||||
|   toolRoutesSections : {[key: string]: ToolRouteConfig[]} = {} |   toolRoutesSections : {[key: string]: ToolRouteConfig[]} = {} | ||||||
| 
 | 
 | ||||||
|   async mounted() { |   async created() { | ||||||
|     const routes = this.$router.options.routes?.filter(r => r.meta?.isTool) || [] |     const routes = this.$router.options.routes?.filter(r => r.meta?.isTool) || [] | ||||||
|  |     const flat: ToolRouteConfig[] = [] | ||||||
|  |     const sections: { [key: string]: ToolRouteConfig[] } = {} | ||||||
| 
 | 
 | ||||||
|     for (const route of routes) { |     for (const route of routes) { | ||||||
|       if ('component' in route) { |       if ('component' in route) { | ||||||
|         // @ts-ignore
 |         // @ts-ignore
 | ||||||
|         const component = await route.component() |         const component = await route.component() | ||||||
|         const routeConfig = {...route, config: component.options.methods.config()} as ToolRouteConfig |         const routeConfig = {...route, config: component.options.methods.config()} as ToolRouteConfig | ||||||
|         this.toolRoutesFlat.push(routeConfig) |         flat.push(routeConfig) | ||||||
| 
 | 
 | ||||||
|         const sectionKey = capitalise(route.meta.section).replace(/_/g, ' ') |         const sectionKey = capitalise(route.meta.section).replace(/_/g, ' ') | ||||||
| 
 | 
 | ||||||
|         if (!(sectionKey in this.toolRoutesSections)) { |         if (!(sectionKey in sections)) { | ||||||
|           this.toolRoutesSections[sectionKey] = [] |           sections[sectionKey] = [] | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         this.toolRoutesSections[sectionKey].push(routeConfig) |         sections[sectionKey].push(routeConfig) | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     this.toolRoutesSections = sections | ||||||
|  |     this.toolRoutesFlat = flat | ||||||
|   } |   } | ||||||
| } | } | ||||||
							
								
								
									
										3534
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						| @ -13,11 +13,13 @@ | |||||||
|   }, |   }, | ||||||
|   "dependencies": { |   "dependencies": { | ||||||
|     "@nuxt/typescript-runtime": "^2.0.1", |     "@nuxt/typescript-runtime": "^2.0.1", | ||||||
|     "@nuxtjs/axios": "^5.12.2", |     "@nuxtjs/axios": "^5.13.1", | ||||||
|     "@nuxtjs/pwa": "^3.0.2", |     "@nuxtjs/pwa": "^3.0.2", | ||||||
|     "@nuxtjs/toast": "^3.3.1", |     "@nuxtjs/toast": "^3.3.1", | ||||||
|     "core-js": "^3.6.5", |     "core-js": "^3.6.5", | ||||||
|  |     "crypto-js": "^4.0.0", | ||||||
|     "nuxt": "^2.14.12", |     "nuxt": "^2.14.12", | ||||||
|  |     "vuetify": "^2.4.5", | ||||||
|     "vuetify-toast-snackbar": "^0.6.1" |     "vuetify-toast-snackbar": "^0.6.1" | ||||||
|   }, |   }, | ||||||
|   "devDependencies": { |   "devDependencies": { | ||||||
| @ -28,11 +30,12 @@ | |||||||
|     "@nuxtjs/eslint-module": "^2.0.0", |     "@nuxtjs/eslint-module": "^2.0.0", | ||||||
|     "@nuxtjs/svg": "^0.1.12", |     "@nuxtjs/svg": "^0.1.12", | ||||||
|     "@nuxtjs/vuetify": "^1.11.2", |     "@nuxtjs/vuetify": "^1.11.2", | ||||||
|  |     "@types/crypto-js": "^4.0.1", | ||||||
|     "@vue/test-utils": "^1.1.0", |     "@vue/test-utils": "^1.1.0", | ||||||
|     "babel-core": "7.0.0-bridge.0", |     "babel-core": "7.0.0-bridge.0", | ||||||
|     "babel-eslint": "^10.1.0", |     "babel-eslint": "^10.1.0", | ||||||
|     "babel-jest": "^26.5.0", |     "babel-jest": "^26.5.0", | ||||||
|     "eslint": "^7.10.0", |     "eslint": "^7.20.0", | ||||||
|     "eslint-config-prettier": "^6.12.0", |     "eslint-config-prettier": "^6.12.0", | ||||||
|     "eslint-plugin-nuxt": "^1.0.0", |     "eslint-plugin-nuxt": "^1.0.0", | ||||||
|     "eslint-plugin-prettier": "^3.1.4", |     "eslint-plugin-prettier": "^3.1.4", | ||||||
| @ -40,7 +43,7 @@ | |||||||
|     "less": "^4.0.0", |     "less": "^4.0.0", | ||||||
|     "less-loader": "^7.1.0", |     "less-loader": "^7.1.0", | ||||||
|     "nuxt-property-decorator": "^2.9.1", |     "nuxt-property-decorator": "^2.9.1", | ||||||
|     "ts-jest": "^26.4.1", |     "ts-jest": "^26.5.1", | ||||||
|     "vue-jest": "^3.0.4" |     "vue-jest": "^3.0.4" | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										20
									
								
								pages/about.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,20 @@ | |||||||
|  | <template> | ||||||
|  |   <v-row justify="center" align="center"> | ||||||
|  |     <v-col cols="12" sm="12" md="8"> | ||||||
|  |       <h1>Yolo</h1> | ||||||
|  |     </v-col> | ||||||
|  |   </v-row> | ||||||
|  | </template> | ||||||
|  | 
 | ||||||
|  | <script> | ||||||
|  | import {Component, Vue} from 'nuxt-property-decorator' | ||||||
|  | 
 | ||||||
|  | @Component | ||||||
|  | export default class About extends Vue { | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | <style lang="less"> | ||||||
|  | 
 | ||||||
|  | </style> | ||||||
							
								
								
									
										20
									
								
								pages/how-to-report-bug-or-request.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,20 @@ | |||||||
|  | <template> | ||||||
|  |   <v-row justify="center" align="center"> | ||||||
|  |     <v-col cols="12" sm="12" md="8"> | ||||||
|  |       <h1>How-to-report-bug-or-request</h1> | ||||||
|  |     </v-col> | ||||||
|  |   </v-row> | ||||||
|  | </template> | ||||||
|  | 
 | ||||||
|  | <script> | ||||||
|  | import {Component, Vue} from 'nuxt-property-decorator' | ||||||
|  | 
 | ||||||
|  | @Component | ||||||
|  | export default class HowToReportBugOrRequest extends Vue { | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | <style lang="less"> | ||||||
|  | 
 | ||||||
|  | </style> | ||||||
| @ -2,17 +2,57 @@ | |||||||
|   <v-row justify="center" align="center"> |   <v-row justify="center" align="center"> | ||||||
|     <v-col cols="12" sm="12" md="8"> |     <v-col cols="12" sm="12" md="8"> | ||||||
|       <h1>Yolo</h1> |       <h1>Yolo</h1> | ||||||
|  | 
 | ||||||
|  |       <v-card v-for="(items, section) in toolRoutesSections" :key="section"> | ||||||
|  |         <v-card-title>{{ section }}</v-card-title> | ||||||
|  |         <v-card-text> | ||||||
|  |           <v-list> | ||||||
|  |             <v-list-item | ||||||
|  |               v-for="(item, i) in items" | ||||||
|  |               :key="i" | ||||||
|  |               :to="item.path" | ||||||
|  |               router | ||||||
|  |               exact | ||||||
|  |             > | ||||||
|  |               <v-list-item-action> | ||||||
|  |                 <v-icon>{{ item.config.icon }}</v-icon> | ||||||
|  |               </v-list-item-action> | ||||||
|  |               <v-list-item-content> | ||||||
|  |                 <v-list-item-title v-text="item.config.title" /> | ||||||
|  |               </v-list-item-content> | ||||||
|  |             </v-list-item> | ||||||
|  |           </v-list> | ||||||
|  |         </v-card-text> | ||||||
|  |       </v-card> | ||||||
|     </v-col> |     </v-col> | ||||||
|   </v-row> |   </v-row> | ||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
| <script> | <script> | ||||||
|  | import {Component, mixins} from 'nuxt-property-decorator' | ||||||
|  | import {ToolRoutesMixin} from '@/mixins/tool-routes.mixin' | ||||||
| 
 | 
 | ||||||
| export default { | @Component | ||||||
|   components: {} | export default class Index extends mixins(ToolRoutesMixin) { | ||||||
| } | } | ||||||
| </script> | </script> | ||||||
| 
 | 
 | ||||||
| <style lang="less"> | <style scopedlang="less"> | ||||||
|  |   .v-list{ | ||||||
|  |     background: transparent !important; | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
|  |   .v-card__title{ | ||||||
|  |     background: var(--v-primary-base) !important; | ||||||
|  |     background: linear-gradient(90deg, rgba(37,99,108,1) 0%, rgba(59,149,111,1) 60%, rgba(71,177,113,1) 100%) !important; | ||||||
|  |     padding-left: 33px; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   .v-list-item{ | ||||||
|  |     padding-left: 31px; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   .v-card__text{ | ||||||
|  |     padding: 0; | ||||||
|  |   } | ||||||
| </style> | </style> | ||||||
|  | |||||||
							
								
								
									
										106
									
								
								pages/tools/crypto/cypher-uncyfer-text.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,106 @@ | |||||||
|  | <template> | ||||||
|  |   <ToolWrapper :config="config()"> | ||||||
|  |     <v-row justify="center" align="center"> | ||||||
|  |       <v-col cols="12" lg="8" md="12"> | ||||||
|  |         <v-textarea | ||||||
|  |           v-model="key" | ||||||
|  |           outlined | ||||||
|  |           label="Encryption key" | ||||||
|  |           rows="1" | ||||||
|  |           @input="encrypt" | ||||||
|  |         /> | ||||||
|  |       </v-col> | ||||||
|  |       <v-col cols="12" lg="4" md="12"> | ||||||
|  |         <v-select | ||||||
|  |           v-model="algorithm" | ||||||
|  |           :items="Object.keys(algorithms)" | ||||||
|  |           label="Algorithm" | ||||||
|  |           outlined | ||||||
|  |           @change="encrypt" | ||||||
|  |         /> | ||||||
|  |       </v-col> | ||||||
|  |     </v-row> | ||||||
|  | 
 | ||||||
|  |     <v-textarea | ||||||
|  |       v-model="decrypted" | ||||||
|  |       outlined | ||||||
|  |       label="Clear text" | ||||||
|  |       @input="encrypt" | ||||||
|  |     /> | ||||||
|  | 
 | ||||||
|  |     <v-textarea | ||||||
|  |       v-model="encrypted" | ||||||
|  |       outlined | ||||||
|  |       label="Cyphered text" | ||||||
|  |       @input="decrypt" | ||||||
|  |     /> | ||||||
|  |     <div class="text-center"> | ||||||
|  |       <v-btn depressed @click="copy(encrypted)"> | ||||||
|  |         Copy result | ||||||
|  |       </v-btn> | ||||||
|  |     </div> | ||||||
|  |   </ToolWrapper> | ||||||
|  | </template> | ||||||
|  | 
 | ||||||
|  | <script lang="ts"> | ||||||
|  | import {Component} from 'nuxt-property-decorator' | ||||||
|  | import {CopyableMixin} from '@/mixins/copyable.mixin' | ||||||
|  | import Tool from '@/components/Tool' | ||||||
|  | import {ToolConfig} from '@/types/ToolConfig' | ||||||
|  | import CryptoJS from 'crypto-js' | ||||||
|  | 
 | ||||||
|  | const algos = { | ||||||
|  |   AES: CryptoJS.AES, | ||||||
|  |   TripleDES: CryptoJS.TripleDES, | ||||||
|  |   Rabbit: CryptoJS.Rabbit, | ||||||
|  |   RabbitLegacy: CryptoJS.RabbitLegacy, | ||||||
|  |   RC4: CryptoJS.RC4 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | @Component({ | ||||||
|  |   mixins: [CopyableMixin] | ||||||
|  | }) | ||||||
|  | export default class CypherUncyferText extends Tool { | ||||||
|  |   algorithm: keyof typeof algos = 'AES' | ||||||
|  |   algorithms: typeof algos = algos | ||||||
|  |   key = 'sup3r s3cr3t k3y' | ||||||
|  |   decrypted = 'Lorem ipsum dolor sit amet.' | ||||||
|  |   encrypted = '' | ||||||
|  | 
 | ||||||
|  |   config(): ToolConfig { | ||||||
|  |     return { | ||||||
|  |       title: 'Cypher / uncypher text', | ||||||
|  |       description: 'Cypher and uncyfer text.', | ||||||
|  |       icon: 'mdi-lock-open', | ||||||
|  |       keywords: ['cypher', 'uncypher', 'text', ...Object.keys(algos).map(s => s.toLowerCase())] | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   mounted() { | ||||||
|  |     this.encrypt() | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   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(CryptoJS.enc.Utf8) | ||||||
|  |     } catch (ignored) { | ||||||
|  |       // ignored | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | <style lang="less"> | ||||||
|  | </style> | ||||||
							
								
								
									
										78
									
								
								pages/tools/crypto/hash-text.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,78 @@ | |||||||
|  | <template> | ||||||
|  |   <ToolWrapper :config="config()"> | ||||||
|  |     <v-textarea | ||||||
|  |       v-model="inputText" | ||||||
|  |       outlined | ||||||
|  |       label="Text to hash" | ||||||
|  |     /> | ||||||
|  | 
 | ||||||
|  |     <v-select | ||||||
|  |       v-model="algorithm" | ||||||
|  |       :items="Object.keys(algorithms)" | ||||||
|  |       label="Algorithm" | ||||||
|  |       outlined | ||||||
|  |     /> | ||||||
|  | 
 | ||||||
|  |     <v-textarea | ||||||
|  |       v-model="hashed" | ||||||
|  |       outlined | ||||||
|  |       readonly | ||||||
|  |       label="Hashed text" | ||||||
|  |     /> | ||||||
|  |     <div class="text-center"> | ||||||
|  |       <v-btn depressed @click="copy(hashed)"> | ||||||
|  |         Copy hash | ||||||
|  |       </v-btn> | ||||||
|  |     </div> | ||||||
|  |   </ToolWrapper> | ||||||
|  | </template> | ||||||
|  | 
 | ||||||
|  | <script lang="ts"> | ||||||
|  | import {Component} from 'nuxt-property-decorator' | ||||||
|  | import CryptoJS from 'crypto-js' | ||||||
|  | import {CopyableMixin} from '~/mixins/copyable.mixin' | ||||||
|  | import Tool from '~/components/Tool.vue' | ||||||
|  | import {ToolConfig} from '~/types/ToolConfig' | ||||||
|  | 
 | ||||||
|  | const algos = { | ||||||
|  |   MD5: CryptoJS.MD5, | ||||||
|  |   SHA1: CryptoJS.SHA1, | ||||||
|  |   SHA256: CryptoJS.SHA256, | ||||||
|  |   SHA224: CryptoJS.SHA224, | ||||||
|  |   SHA512: CryptoJS.SHA512, | ||||||
|  |   SHA384: CryptoJS.SHA384, | ||||||
|  |   SHA3: CryptoJS.SHA3, | ||||||
|  |   RIPEMD160: CryptoJS.RIPEMD160 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | @Component({ | ||||||
|  |   mixins: [CopyableMixin] | ||||||
|  | }) | ||||||
|  | export default class HashText extends Tool { | ||||||
|  |   config(): ToolConfig { | ||||||
|  |     return { | ||||||
|  |       title: 'Hash text', | ||||||
|  |       description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Delectus distinctio dolor dolorum eaque eligendi, facilis impedit laboriosam odit placeat.', | ||||||
|  |       icon: 'mdi-script-text-play', | ||||||
|  |       keywords: ['hash', 'text', ...Object.keys(algos).map(s => s.toLowerCase())] | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   inputText = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.' | ||||||
|  |   algorithm: keyof typeof algos = 'SHA256' | ||||||
|  |   algorithms: typeof algos = algos | ||||||
|  | 
 | ||||||
|  |   get hashed() { | ||||||
|  |     if (this.algorithms[this.algorithm]) { | ||||||
|  |       return this.algorithms[this.algorithm](this.inputText).toString() | ||||||
|  |     } else { | ||||||
|  |       this.$toast.error('Invalid algorithm.') | ||||||
|  |       return '' | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | <style> | ||||||
|  | </style> | ||||||
| @ -11,7 +11,7 @@ | |||||||
|       </v-col> |       </v-col> | ||||||
|     </v-row> |     </v-row> | ||||||
| 
 | 
 | ||||||
|     <v-slider v-model="length" :label="`Length (${length})`" min="1" max="256" /> |     <v-slider v-model="length" :label="`Length (${length})`" min="1" max="512" /> | ||||||
| 
 | 
 | ||||||
|     <v-textarea v-model="token" outlined /> |     <v-textarea v-model="token" outlined /> | ||||||
| 
 | 
 | ||||||
| @ -30,16 +30,16 @@ | |||||||
| import {Component} from 'nuxt-property-decorator' | import {Component} from 'nuxt-property-decorator' | ||||||
| import Tool from '~/components/Tool.vue' | import Tool from '~/components/Tool.vue' | ||||||
| import {ToolConfig} from '~/types/ToolConfig' | import {ToolConfig} from '~/types/ToolConfig' | ||||||
| import {Copyable} from '~/mixins/copyable' | import {CopyableMixin} from '~/mixins/copyable.mixin' | ||||||
|  | import {shuffle} from '~/utils/string' | ||||||
| 
 | 
 | ||||||
| const shuffle = (s: string) => s.split('').sort(() => 0.5 - Math.random()).join('') |  | ||||||
| const lowercase = 'abcdefghijklmopqrstuvwxyz' | const lowercase = 'abcdefghijklmopqrstuvwxyz' | ||||||
| const uppercase = 'ABCDEFGHIJKLMOPQRSTUVWXYZ' | const uppercase = 'ABCDEFGHIJKLMOPQRSTUVWXYZ' | ||||||
| const numbers = '0123456789' | const numbers = '0123456789' | ||||||
| const specials = '.,;:!?./-"\'#{([-|\\@)]=}*+' | const specials = '.,;:!?./-"\'#{([-|\\@)]=}*+' | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   mixins: [Copyable] |   mixins: [CopyableMixin] | ||||||
| }) | }) | ||||||
| export default class TokenGenerator extends Tool { | export default class TokenGenerator extends Tool { | ||||||
|   config(): ToolConfig { |   config(): ToolConfig { | ||||||
|  | |||||||
							
								
								
									
										92
									
								
								pages/tools/crypto/uuid-generator.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,92 @@ | |||||||
|  | <template> | ||||||
|  |   <ToolWrapper :config="config()"> | ||||||
|  |     <v-text-field | ||||||
|  |       v-model.number="quantity" | ||||||
|  |       outlined | ||||||
|  |       type="number" | ||||||
|  |       label="Quantity" | ||||||
|  |       dense | ||||||
|  |       class="quantity" | ||||||
|  |       :rules="rules.quantity" | ||||||
|  |     /> | ||||||
|  |     <v-textarea | ||||||
|  |       v-model="token" | ||||||
|  |       outlined | ||||||
|  |       class="centered-input" | ||||||
|  |       :rows="quantity <= 10 ? quantity : 10" | ||||||
|  |       readonly | ||||||
|  |     /> | ||||||
|  | 
 | ||||||
|  |     <div class="text-center"> | ||||||
|  |       <v-btn depressed class="mr-4" @click="computeToken"> | ||||||
|  |         Refresh | ||||||
|  |       </v-btn> | ||||||
|  |       <v-btn depressed @click="copy(token, `UUID${quantity > 1 ? 's' : ''} copied !`)"> | ||||||
|  |         Copy UUID{{ quantity > 1 ? 's' : '' }} | ||||||
|  |       </v-btn> | ||||||
|  |     </div> | ||||||
|  |   </ToolWrapper> | ||||||
|  | </template> | ||||||
|  | 
 | ||||||
|  | <script lang="ts"> | ||||||
|  | 
 | ||||||
|  | import {Component, Ref, Watch} from 'nuxt-property-decorator' | ||||||
|  | import {CopyableMixin} from '@/mixins/copyable.mixin' | ||||||
|  | import {ToolConfig} from '@/types/ToolConfig' | ||||||
|  | import { VTextField } from 'vuetify/lib' | ||||||
|  | import Tool from '~/components/Tool.vue' | ||||||
|  | 
 | ||||||
|  | const generateUuid = () => '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, c => ((c as unknown as number) ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> (c as unknown as number) / 4).toString(16)) | ||||||
|  | 
 | ||||||
|  | @Component({ | ||||||
|  |   mixins: [CopyableMixin] | ||||||
|  | }) | ||||||
|  | export default class UuidGenerator extends Tool { | ||||||
|  |   config(): ToolConfig { | ||||||
|  |     return { | ||||||
|  |       title: 'UUIDs generator', | ||||||
|  |       description: 'A universally unique identifier (UUID) is a 128-bit number used to identify information in computer systems. ', | ||||||
|  |       icon: 'mdi-fingerprint', | ||||||
|  |       keywords: ['uuid', 'v4', 'random', 'id', 'alphanumeric', 'identity'] | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @Ref() readonly quantityEl! : typeof VTextField | ||||||
|  |   token = '' | ||||||
|  |   quantity = 1 | ||||||
|  |   rules = { | ||||||
|  |     quantity: [ | ||||||
|  |       (v: any) => !!v || 'Quantity is required', | ||||||
|  |       (v: any) => (v > 0 && v <= 50) || 'Quantity should be > 0 and <= 50', | ||||||
|  |       (v: any) => Number.isInteger(v) || 'Quantity should be an integer' | ||||||
|  |     ] | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   mounted() { | ||||||
|  |     this.computeToken() | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   @Watch('quantity') | ||||||
|  |   computeToken() { | ||||||
|  |     this.token = Array.from({length: this.quantity}, generateUuid).join('\n') | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | <style scoped lang="less"> | ||||||
|  | .quantity { | ||||||
|  |   width: 100px; | ||||||
|  |   margin: auto; | ||||||
|  |   text-align: center; | ||||||
|  | 
 | ||||||
|  |   ::v-deep input { | ||||||
|  |     text-align: center; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ::v-deep .centered-input textarea { | ||||||
|  |   text-align: center; | ||||||
|  |   margin-top: 13px !important; | ||||||
|  |   font-family: Consolas, monospace; | ||||||
|  | } | ||||||
|  | </style> | ||||||
							
								
								
									
										
											BIN
										
									
								
								static/android-chrome-192x192.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 7.7 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/android-chrome-512x512.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 24 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/apple-touch-icon.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 7.2 KiB | 
							
								
								
									
										9
									
								
								static/browserconfig.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,9 @@ | |||||||
|  | <?xml version="1.0" encoding="utf-8"?> | ||||||
|  | <browserconfig> | ||||||
|  |     <msapplication> | ||||||
|  |         <tile> | ||||||
|  |             <square150x150logo src="/mstile-150x150.png"/> | ||||||
|  |             <TileColor>#2b5797</TileColor> | ||||||
|  |         </tile> | ||||||
|  |     </msapplication> | ||||||
|  | </browserconfig> | ||||||
							
								
								
									
										
											BIN
										
									
								
								static/favicon-16x16.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.1 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/favicon-32x32.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.9 KiB | 
| Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 15 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/icon.png
									
									
									
									
									
								
							
							
						
						| Before Width: | Height: | Size: 12 KiB | 
							
								
								
									
										
											BIN
										
									
								
								static/mstile-150x150.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 4.0 KiB | 
							
								
								
									
										83
									
								
								static/safari-pinned-tab.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,83 @@ | |||||||
|  | <?xml version="1.0" standalone="no"?> | ||||||
|  | <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" | ||||||
|  |  "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> | ||||||
|  | <svg version="1.0" xmlns="http://www.w3.org/2000/svg" | ||||||
|  |  width="726.000000pt" height="726.000000pt" viewBox="0 0 726.000000 726.000000" | ||||||
|  |  preserveAspectRatio="xMidYMid meet"> | ||||||
|  | <metadata> | ||||||
|  | Created by potrace 1.11, written by Peter Selinger 2001-2013 | ||||||
|  | </metadata> | ||||||
|  | <g transform="translate(0.000000,726.000000) scale(0.100000,-0.100000)" | ||||||
|  | fill="#000000" stroke="none"> | ||||||
|  | <path d="M3255 7239 c-112 -39 -191 -120 -230 -238 -14 -43 -17 -88 -17 -237 | ||||||
|  | 0 -144 -3 -186 -14 -195 -8 -6 -14 -9 -14 -6 0 3 -23 -1 -52 -9 -28 -9 -60 | ||||||
|  | -17 -71 -19 -10 -3 -28 -7 -40 -11 -12 -5 -26 -8 -32 -9 -5 -1 -17 -4 -25 -7 | ||||||
|  | -8 -3 -53 -19 -100 -34 -47 -15 -89 -31 -94 -36 -6 -4 -16 -8 -24 -8 -15 0 | ||||||
|  | -68 -22 -114 -46 -16 -9 -28 -12 -28 -7 0 4 -4 4 -8 -2 -6 -9 -103 -58 -109 | ||||||
|  | -56 -2 0 -46 -24 -99 -54 -53 -30 -100 -55 -105 -55 -5 0 -9 -3 -9 -7 0 -9 | ||||||
|  | -57 -43 -71 -43 -5 0 -69 60 -142 133 -132 130 -163 152 -264 185 -76 24 -223 | ||||||
|  | -4 -292 -57 -56 -42 -441 -432 -466 -471 -60 -96 -75 -246 -32 -325 6 -11 12 | ||||||
|  | -25 13 -32 4 -23 60 -88 177 -205 64 -64 117 -120 117 -123 0 -4 -13 -25 -29 | ||||||
|  | -48 -15 -23 -31 -52 -35 -64 -4 -13 -11 -23 -15 -23 -5 0 -14 -15 -22 -32 -7 | ||||||
|  | -18 -16 -35 -19 -38 -5 -4 -82 -157 -85 -170 -1 -3 -9 -23 -19 -45 -41 -92 | ||||||
|  | -103 -255 -111 -290 -1 -5 -5 -17 -8 -25 -9 -20 -47 -164 -59 -222 -6 -27 -13 | ||||||
|  | -48 -17 -49 -3 0 -91 -2 -196 -3 -105 -1 -208 -8 -231 -14 -120 -35 -230 -160 | ||||||
|  | -251 -287 -5 -27 -8 -185 -7 -350 1 -282 3 -303 23 -357 41 -106 113 -177 222 | ||||||
|  | -220 48 -18 77 -21 249 -22 l195 -1 13 -50 c7 -27 15 -58 17 -68 2 -10 7 -27 | ||||||
|  | 10 -37 3 -10 7 -27 9 -37 15 -75 116 -345 128 -341 5 2 186 180 402 396 l393 | ||||||
|  | 393 -8 44 c-24 126 -32 424 -15 550 5 33 9 71 10 85 10 99 86 364 138 480 70 | ||||||
|  | 156 158 310 222 392 12 14 32 41 46 59 85 113 253 277 380 372 116 87 304 191 | ||||||
|  | 440 244 120 47 141 55 155 58 6 2 35 10 65 19 30 8 73 18 95 22 22 3 44 8 48 | ||||||
|  | 11 4 2 22 7 40 9 18 3 43 7 57 9 112 18 365 24 485 11 299 -32 547 -112 810 | ||||||
|  | -260 39 -22 72 -43 75 -46 3 -3 26 -19 52 -35 27 -17 48 -33 48 -37 0 -5 5 -8 | ||||||
|  | 11 -8 11 0 84 -59 168 -135 41 -37 58 -54 141 -145 50 -54 142 -178 194 -258 | ||||||
|  | 90 -142 216 -429 241 -552 2 -8 8 -33 13 -55 6 -22 13 -53 16 -70 3 -16 7 -41 | ||||||
|  | 10 -55 7 -36 17 -109 21 -155 6 -61 6 -315 0 -360 -25 -201 -29 -221 -80 -405 | ||||||
|  | -31 -114 -117 -310 -183 -420 -12 -19 -29 -48 -38 -65 -9 -16 -20 -32 -23 -35 | ||||||
|  | -3 -3 -19 -24 -34 -48 -32 -50 -172 -217 -215 -259 -95 -90 -183 -165 -242 | ||||||
|  | -206 -154 -107 -272 -173 -410 -230 -79 -33 -223 -82 -266 -92 -228 -50 -308 | ||||||
|  | -60 -499 -59 -170 0 -297 10 -355 29 -14 4 -111 -87 -414 -390 -218 -218 -396 | ||||||
|  | -400 -396 -405 0 -4 24 -16 53 -26 28 -9 57 -20 62 -24 6 -4 57 -22 115 -39 | ||||||
|  | 58 -18 116 -37 130 -41 14 -5 50 -14 80 -20 106 -23 97 -1 98 -223 0 -122 5 | ||||||
|  | -203 12 -216 6 -12 8 -21 5 -21 -3 0 6 -22 20 -49 27 -53 103 -141 123 -141 7 | ||||||
|  | 0 12 -4 12 -9 0 -5 17 -15 38 -22 20 -6 43 -17 51 -23 10 -8 117 -11 350 -11 | ||||||
|  | 307 0 341 2 394 20 31 10 57 23 57 27 0 4 6 8 14 8 20 0 112 96 131 137 36 75 | ||||||
|  | 42 119 42 307 1 103 2 189 5 191 2 2 15 6 28 9 140 29 398 113 533 174 37 17 | ||||||
|  | 67 28 67 24 0 -4 4 -2 8 3 4 6 43 28 87 49 44 22 82 42 85 45 3 4 17 12 32 18 | ||||||
|  | 15 7 46 25 70 40 98 64 83 69 228 -76 138 -139 184 -172 270 -193 92 -23 172 | ||||||
|  | -12 265 36 40 21 440 412 487 476 77 107 85 261 19 386 -12 23 -83 103 -157 | ||||||
|  | 178 l-136 137 19 26 c22 32 48 75 76 128 12 22 24 42 28 45 6 6 102 202 103 | ||||||
|  | 211 1 3 12 30 25 60 13 30 27 63 32 74 17 42 71 203 85 255 19 69 45 170 48 | ||||||
|  | 190 2 13 32 15 187 16 201 2 230 5 296 35 46 21 70 38 110 79 24 24 75 104 80 | ||||||
|  | 125 1 5 7 31 13 56 12 49 9 646 -3 688 -33 117 -150 231 -262 257 -16 3 -115 | ||||||
|  | 7 -219 8 -211 3 -199 -2 -216 83 -5 26 -19 80 -30 118 -12 39 -22 77 -25 85 | ||||||
|  | -2 8 -4 16 -5 18 -2 1 -3 5 -5 10 -1 4 -5 14 -8 22 -4 8 -14 38 -23 65 -9 28 | ||||||
|  | -21 61 -27 75 -5 14 -11 30 -12 36 -7 29 -149 311 -202 400 l-60 102 136 138 | ||||||
|  | c91 92 144 155 159 187 68 144 44 300 -63 415 -114 123 -402 403 -435 424 -95 | ||||||
|  | 58 -234 73 -325 34 -22 -9 -42 -17 -45 -18 -13 -1 -86 -67 -191 -172 -64 -64 | ||||||
|  | -124 -116 -132 -116 -9 0 -25 10 -37 22 -11 12 -20 18 -20 12 0 -5 -4 -4 -8 2 | ||||||
|  | -9 13 -185 111 -277 154 -73 34 -263 111 -280 114 -5 1 -14 4 -20 7 -5 4 -37 | ||||||
|  | 14 -70 24 -33 10 -87 26 -120 36 -33 10 -85 23 -115 29 l-55 12 0 207 -1 206 | ||||||
|  | -29 60 c-29 60 -125 165 -151 165 -8 0 -14 4 -14 8 0 5 -26 16 -57 25 -48 13 | ||||||
|  | -115 16 -373 16 -293 1 -319 -1 -375 -20z"/> | ||||||
|  | <path d="M3577 5134 c-1 -1 -44 -4 -94 -8 -51 -4 -98 -8 -105 -11 -7 -2 -24 | ||||||
|  | -6 -38 -9 -106 -19 -283 -79 -375 -126 -65 -34 -177 -100 -185 -109 -3 -4 -23 | ||||||
|  | -18 -45 -33 -22 -15 -56 -42 -76 -60 -20 -18 -47 -43 -60 -55 -74 -66 -182 | ||||||
|  | -197 -237 -288 -56 -90 -130 -249 -152 -325 -13 -41 -27 -80 -31 -86 -5 -6 -7 | ||||||
|  | -13 -4 -16 3 -2 0 -20 -5 -39 -6 -19 -13 -52 -16 -74 -3 -22 -8 -51 -10 -65 | ||||||
|  | -3 -14 -6 -88 -8 -165 -3 -123 7 -245 28 -345 3 -14 8 -35 10 -48 3 -12 15 | ||||||
|  | -54 28 -92 l22 -71 -1037 -1037 c-570 -570 -1053 -1059 -1072 -1086 -19 -27 | ||||||
|  | -35 -55 -35 -63 0 -7 -3 -13 -8 -13 -8 0 -31 -48 -37 -79 -2 -12 -6 -25 -9 | ||||||
|  | -29 -21 -34 -29 -211 -14 -291 9 -51 55 -180 67 -191 3 -3 12 -17 19 -31 17 | ||||||
|  | -33 116 -137 162 -171 110 -80 245 -120 388 -114 110 5 176 22 277 74 65 33 | ||||||
|  | 151 116 1128 1092 l1058 1058 49 -19 c27 -10 59 -20 72 -23 13 -3 32 -7 43 | ||||||
|  | -10 148 -34 189 -39 350 -39 150 -1 226 7 345 34 82 19 233 70 275 92 11 6 22 | ||||||
|  | 12 25 12 23 4 240 133 260 155 3 3 25 21 50 41 134 108 265 260 348 404 49 86 | ||||||
|  | 121 250 137 315 1 3 4 12 7 20 10 24 37 146 44 195 11 70 14 116 15 215 0 101 | ||||||
|  | -8 237 -16 250 -2 3 -6 26 -10 50 -22 151 -160 233 -287 171 -28 -14 -133 | ||||||
|  | -111 -303 -282 -143 -144 -282 -279 -309 -301 -131 -104 -308 -135 -469 -81 | ||||||
|  | -39 14 -74 28 -77 31 -3 4 -17 13 -32 21 -39 20 -109 89 -144 142 -106 157 | ||||||
|  | -115 340 -26 513 31 59 78 111 328 362 160 161 298 306 307 322 8 16 14 57 15 | ||||||
|  | 90 0 63 -24 113 -73 154 -34 29 -172 62 -280 68 -69 4 -175 6 -178 4z"/> | ||||||
|  | </g> | ||||||
|  | </svg> | ||||||
| After Width: | Height: | Size: 5.6 KiB | 
							
								
								
									
										19
									
								
								static/site.webmanifest
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,19 @@ | |||||||
|  | { | ||||||
|  |     "name": "IT - Tools", | ||||||
|  |     "short_name": "IT Tools", | ||||||
|  |     "icons": [ | ||||||
|  |         { | ||||||
|  |             "src": "/android-chrome-192x192.png", | ||||||
|  |             "sizes": "192x192", | ||||||
|  |             "type": "image/png" | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "src": "/android-chrome-512x512.png", | ||||||
|  |             "sizes": "512x512", | ||||||
|  |             "type": "image/png" | ||||||
|  |         } | ||||||
|  |     ], | ||||||
|  |     "theme_color": "#ffffff", | ||||||
|  |     "background_color": "#ffffff", | ||||||
|  |     "display": "standalone" | ||||||
|  | } | ||||||
| @ -28,7 +28,8 @@ | |||||||
|       "@types/node", |       "@types/node", | ||||||
|       "@nuxtjs/toast", |       "@nuxtjs/toast", | ||||||
|       "@nuxt/types", |       "@nuxt/types", | ||||||
|       "~/types/custom.d.ts" |       "~/types/custom.d.ts", | ||||||
|  |       "vuetify" | ||||||
|     ] |     ] | ||||||
|   }, |   }, | ||||||
|   "exclude": [ |   "exclude": [ | ||||||
|  | |||||||
| @ -1,3 +1,5 @@ | |||||||
|  | import {RouteConfig} from '@nuxt/types/config/router'; | ||||||
|  | 
 | ||||||
| interface ToolConfig { | interface ToolConfig { | ||||||
|   title: string; |   title: string; | ||||||
|   description: string; |   description: string; | ||||||
| @ -6,5 +8,6 @@ interface ToolConfig { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type ToolConfigMethod = () => ToolConfig; | type ToolConfigMethod = () => ToolConfig; | ||||||
|  | type ToolRouteConfig = RouteConfig & {config: ToolConfig} | ||||||
| 
 | 
 | ||||||
| export {ToolConfig, ToolConfigMethod} | export {ToolConfig, ToolConfigMethod, ToolRouteConfig} | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| function capitalise(s: string) { | const capitalise = (s: string) => s.charAt(0).toUpperCase() + s.slice(1) | ||||||
|   return s.charAt(0).toUpperCase() + s.slice(1) |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| export {capitalise} | const shuffle = (s: string) => s.split('').sort(() => 0.5 - Math.random()).join('') | ||||||
|  | 
 | ||||||
|  | export {capitalise, shuffle} | ||||||
|  | |||||||