From 690bd099ef0a7b5665f384c2d6f978dae0e0afd6 Mon Sep 17 00:00:00 2001 From: Corentin Thomasset Date: Fri, 28 May 2021 19:44:27 +0200 Subject: [PATCH] feat: externalized tool configuration --- buildModules/tool-config/index.ts | 85 ++++++++++++++++ buildModules/tool-config/loader.js | 13 +++ buildModules/tool-config/plugin.ts | 16 +++ components/Memo.vue | 2 +- components/SearchBar.vue | 11 +-- components/Tool.vue | 15 ++- layouts/default.vue | 11 +-- mixins/tool-config.mixin.ts | 12 +++ mixins/tool-routes.mixin.ts | 37 ------- nuxt.config.js | 6 +- package-lock.json | 92 ++++++++++-------- package.json | 10 +- pages/index.vue | 11 +-- static/icon.png | Bin 0 -> 24093 bytes .../converter/base-converter.vue | 20 ++-- .../converter/base64-string-converter.vue | 20 ++-- .../converter/color-picker-converter.vue | 20 ++-- .../converter/date-converter.vue | 20 ++-- .../crypto/bip39-generator.vue | 20 ++-- .../crypto/cypher-uncyfer-text.vue | 20 ++-- {pages/tools => tools}/crypto/hash-text.vue | 21 ++-- .../crypto/token-generator.vue | 20 ++-- .../tools => tools}/crypto/uuid-generator.vue | 20 ++-- {pages/tools => tools}/memos/git-memo.vue | 17 ++-- .../sys-admin/crontab-generator.vue | 20 ++-- .../sys-admin/random-port-generator.vue | 20 ++-- .../text/lorem-ipsum-generator.vue | 20 ++-- {pages/tools => tools}/text/text-stats.vue | 59 ++++++----- {pages/tools => tools}/web/file-to-base64.vue | 20 ++-- .../tools => tools}/web/qrcode-generator.vue | 20 ++-- types/ToolConfig.ts | 9 +- 31 files changed, 387 insertions(+), 300 deletions(-) create mode 100644 buildModules/tool-config/index.ts create mode 100644 buildModules/tool-config/loader.js create mode 100644 buildModules/tool-config/plugin.ts create mode 100644 mixins/tool-config.mixin.ts delete mode 100644 mixins/tool-routes.mixin.ts create mode 100644 static/icon.png rename {pages/tools => tools}/converter/base-converter.vue (92%) rename {pages/tools => tools}/converter/base64-string-converter.vue (70%) rename {pages/tools => tools}/converter/color-picker-converter.vue (92%) rename {pages/tools => tools}/converter/date-converter.vue (88%) rename {pages/tools => tools}/crypto/bip39-generator.vue (84%) rename {pages/tools => tools}/crypto/cypher-uncyfer-text.vue (85%) rename {pages/tools => tools}/crypto/hash-text.vue (75%) rename {pages/tools => tools}/crypto/token-generator.vue (81%) rename {pages/tools => tools}/crypto/uuid-generator.vue (82%) rename {pages/tools => tools}/memos/git-memo.vue (81%) rename {pages/tools => tools}/sys-admin/crontab-generator.vue (92%) rename {pages/tools => tools}/sys-admin/random-port-generator.vue (74%) rename {pages/tools => tools}/text/lorem-ipsum-generator.vue (90%) rename {pages/tools => tools}/text/text-stats.vue (61%) rename {pages/tools => tools}/web/file-to-base64.vue (84%) rename {pages/tools => tools}/web/qrcode-generator.vue (90%) diff --git a/buildModules/tool-config/index.ts b/buildModules/tool-config/index.ts new file mode 100644 index 00000000..2dd7e0d2 --- /dev/null +++ b/buildModules/tool-config/index.ts @@ -0,0 +1,85 @@ +import {readdirSync, readFileSync} from 'fs' +import path, {join} from 'path' +import {Module} from '@nuxt/types' +import {NuxtRouteConfig} from '@nuxt/types/config/router' +import YAML from 'yaml' +import {capitalise} from '../../utils/string' + +const toolDirName = 'tools' +const rootDir = join(__dirname, '..', '..') +const toolsDir = join(rootDir, toolDirName) + +interface toolConfigModuleOptions { +} + +function getTools() { + const categories = readdirSync(toolsDir) + const toolList: { [key: string]: any[] } = {} + + for (const category of categories) { + const categoryDir = join(toolsDir, category) + const categoryFormatted = capitalise(category) + + toolList[categoryFormatted] = readdirSync(categoryDir).map((toolFileName) => { + const toolPath = join(categoryDir, toolFileName) + const contentMatch = readFileSync(toolPath, 'utf8').match(/\s]*)*>([\S\s.]*?)<\/tool>/) + + return contentMatch + ? { + ...YAML.parse(contentMatch[2]), + componentPath: join(toolDirName, category, toolFileName) + } + : null + }).filter(v => v !== null) + } + + return toolList +} + +const toolConfigModule: Module = function () { + const {nuxt, extendBuild, addPlugin} = this + const toolList = getTools() + const toolListFlat = Object.values(toolList).flat() + + nuxt.hook('build:extendRoutes', (routes: NuxtRouteConfig[]) => { + toolListFlat.forEach((toolConfig) => { + const {path = '', title, componentPath} = toolConfig + const name = title.toLowerCase().split(/\s/).join('-').replace(/\.vue$/, '') + + const newRoute: NuxtRouteConfig = { + name, + path, + component: join(rootDir, componentPath), + chunkName: componentPath.replace(/\.vue$/, '') + } + + routes.push(newRoute) + }) + + nuxt.options.publicRuntimeConfig.toolList = toolList + }) + + extendBuild((config) => { + if (!config.module) { + // eslint-disable-next-line no-console + console.warn('Failed to register the tool-config module.') + return + } + + config.module.rules.push({ + resourceQuery: /blockType=tool/, + loader: require.resolve('./loader.js') + }) + }) + + addPlugin({ + src: path.resolve(__dirname, 'plugin.ts'), + fileName: 'tool-config/plugin.ts', + options: { + toolList, + toolListFlat + } + }) +} + +export default toolConfigModule diff --git a/buildModules/tool-config/loader.js b/buildModules/tool-config/loader.js new file mode 100644 index 00000000..159c440d --- /dev/null +++ b/buildModules/tool-config/loader.js @@ -0,0 +1,13 @@ +const YAML = require('yaml') + +const loader = function (source, map) { + this.callback( + null, + `export default function (Component) { + Component.options.__toolConfig = ${JSON.stringify(YAML.parse(source))} + }`, + map + ) +} + +module.exports = loader diff --git a/buildModules/tool-config/plugin.ts b/buildModules/tool-config/plugin.ts new file mode 100644 index 00000000..00f3661b --- /dev/null +++ b/buildModules/tool-config/plugin.ts @@ -0,0 +1,16 @@ +// @ts-nocheck +import {Plugin} from '@nuxt/types' +import type {ToolRouteConfig} from '~/types/ToolConfig'; + +declare module 'vue/types/vue' { + interface Vue { + $toolListFlat: ToolRouteConfig[] + $toolList: { [key: string]: ToolRouteConfig[] } + } +} + +const plugin: Plugin = (_, inject) => { + inject('toolListFlat', <%= serialize(options.toolListFlat) %>) + inject('toolList', <%= serialize(options.toolList) %>) +} +export default plugin diff --git a/components/Memo.vue b/components/Memo.vue index 4910710d..10ce3078 100644 --- a/components/Memo.vue +++ b/components/Memo.vue @@ -1,6 +1,6 @@ diff --git a/static/icon.png b/static/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..84f1f340c700d98d158a1b163e1137811cf4260b GIT binary patch literal 24093 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

hN=P93_2h{ifNYK&$2UtCIiUL{%t z{hWqd!6<}Dj|nW{!J2bCh=z_R zLsqXdG(t*D3oi>bgll&5KzW9UgWsbL<394*19ZQW#5)6;b9aun|X@dwQW3xAUyph?aiZGvf#J;n6U0j%Oq&Q*=vu+?)?_tqT}1 zIT*J)8(k3>yvBiuwm=8q4G_t|U0uvxj>_0)s&%38()j~$*6O{*CLY>W%t#f#5tv>a z6;ii0ySJ}uRY==)b_^xV z(BNYzot>SfOLpLc(Y9)}l3k$}mV%Ocp8g)?vDI@|Ps_YE^V@BLVP<1Xp!*(5S5{Vp zY=V8@tLJg9^OurS&H=CL@k@?R=yz4+(3jFS61ORW*zx@?5sb7;Q}&<^b>Air4IO$A zkBZ6R-mAh?tZoB25?6@NOe<;9P;ZfDYowC>epH~M_ixXZY;pMSD2$qTGxF2Z!vpl+ zjMP*LmfH@z9<#q&#J1rDXKZ2;K@Csf&d@B(Rf3RKIxE=GZouSUidz8HO-Hk*VizGj z`Xs_3%H0B!)G+_^+FGDo${EA(PREVWRnls>*k+w))w3bhzf6M8Luv~J z>q)evcYf)p`>R)a;uE}v$*l+BEWaTdMN2OF-J@Knh1=e4wf$(3@%Q{pL`u1InKe$M z1*o7`jRDgReUsczGki3G8tdASjg^;Aajvj<`mp)hYmoo(<)aXIXl5@_FAv3Y5f z5?v_oHf$$Y#X0!65Uxh^M^@(MSf6iA8w<5#BO__&a|5g2v|WcOfm`Z5cXNKwP9fD` ztgsp*dXiU^dVRC$5+47kEk|x@j2C;^Bkx@aZb5m~k!T!HiX=*RB4}F+^3-3eH{KL5 zIf4&$30E^TKbyt{{y+EnF&ddXGQIBe5PJyHYD)uu>p5nfbicXu zvSS&^)BqkB_hdPo{($e4;zP&u#UtfQ^WFSpP5|SDER`q!Az@432hVB3u zrhr6&hD3QepEfRn(D+72Wmrs2oDYCACq! zVg4zBvah7nPbLq$D?fSE#b9EX=ui%?r+?|Dlb2X>Qk^5)6hw_;G9&0QvMQEyJ;Q2L z4ltn@E|B~7m``(Ro!4eS5M;ctsb&`wf)Gr?;jjOX!v4Qp0qQoxv~9kJ!jYrLj1?4A6pyPY9Y2gYs)E5t=O~T;j{`isuDdt} z{qF~uZpU4P1I%#7=6;5DH^segcsaVbJBa%Qc{_-^c>CESNMQQJA1*c@Q#86=zvH9s zq#?q1fK$$%lm7t!g(Lw+esL{=V&iqj0~N;N9fO}+n?5#)HnDaPbh6INA+tg|{r+ew RCBsJ`x@YyYUTNBf{TEkyXu1FZ literal 0 HcmV?d00001 diff --git a/pages/tools/converter/base-converter.vue b/tools/converter/base-converter.vue similarity index 92% rename from pages/tools/converter/base-converter.vue rename to tools/converter/base-converter.vue index ad84a509..053b161f 100644 --- a/pages/tools/converter/base-converter.vue +++ b/tools/converter/base-converter.vue @@ -1,5 +1,5 @@ + +title: 'Base converter' +description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Delectus distinctio dolor dolorum eaque eligendi, facilis impedit laboriosam odit placeat.' +icon: 'mdi-swap-horizontal' +keywords: ['base', 'converter'] +path: '/color-picker-converter' + + diff --git a/pages/tools/sys-admin/crontab-generator.vue b/tools/sys-admin/crontab-generator.vue similarity index 92% rename from pages/tools/sys-admin/crontab-generator.vue rename to tools/sys-admin/crontab-generator.vue index 7df1407d..9ad0931e 100644 --- a/pages/tools/sys-admin/crontab-generator.vue +++ b/tools/sys-admin/crontab-generator.vue @@ -1,5 +1,5 @@ + +title: 'Crontab generator' +description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Delectus distinctio dolor dolorum eaque eligendi, facilis impedit laboriosam odit placeat.' +icon: 'mdi-calendar-clock' +keywords: ['year', 'month', 'week', 'day', 'minute', 'second'] +path: '/crontab-generator' + +