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>
|
||||||
|
@ -57,25 +77,27 @@
|
||||||
<nuxt />
|
<nuxt />
|
||||||
</v-container>
|
</v-container>
|
||||||
</v-main>
|
</v-main>
|
||||||
<!-- <v-footer app>-->
|
<!--<v-footer app>-->
|
||||||
<!-- <span>© {{ new Date().getFullYear() }}</span>-->
|
<!-- <span>© {{ new Date().getFullYear() }}</span>-->
|
||||||
<!-- </v-footer>-->
|
<!--</v-footer>-->
|
||||||
</v-app>
|
</v-app>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<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
|
||||||
}
|
}
|
||||||
}
|
}
|
3514
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 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}
|
||||||
|
|