From 87984e2081de4e436adac552f520c02e07e371ab Mon Sep 17 00:00:00 2001 From: sharevb Date: Sun, 25 Aug 2024 22:57:07 +0200 Subject: [PATCH 01/16] feat(new tool): Markdown to HTML (#916) * feat(new tool): Markdown to HTML Fix partially #538 * feat: add print button * Update src/tools/markdown-to-html/index.ts * Update src/tools/markdown-to-html/markdown-to-html.vue --------- Co-authored-by: Corentin THOMASSET --- components.d.ts | 2 + package.json | 2 + pnpm-lock.yaml | 61 ++++++++++++++++--- src/components/TextareaCopyable.vue | 2 + src/tools/index.ts | 2 + src/tools/markdown-to-html/index.ts | 12 ++++ .../markdown-to-html/markdown-to-html.vue | 44 +++++++++++++ 7 files changed, 115 insertions(+), 10 deletions(-) create mode 100644 src/tools/markdown-to-html/index.ts create mode 100644 src/tools/markdown-to-html/markdown-to-html.vue diff --git a/components.d.ts b/components.d.ts index 89f41f808..8e59366ab 100644 --- a/components.d.ts +++ b/components.d.ts @@ -121,6 +121,7 @@ declare module '@vue/runtime-core' { LoremIpsumGenerator: typeof import('./src/tools/lorem-ipsum-generator/lorem-ipsum-generator.vue')['default'] MacAddressGenerator: typeof import('./src/tools/mac-address-generator/mac-address-generator.vue')['default'] MacAddressLookup: typeof import('./src/tools/mac-address-lookup/mac-address-lookup.vue')['default'] + MarkdownToHtml: typeof import('./src/tools/markdown-to-html/markdown-to-html.vue')['default'] MathEvaluator: typeof import('./src/tools/math-evaluator/math-evaluator.vue')['default'] MenuBar: typeof import('./src/tools/html-wysiwyg-editor/editor/menu-bar.vue')['default'] MenuBarItem: typeof import('./src/tools/html-wysiwyg-editor/editor/menu-bar-item.vue')['default'] @@ -129,6 +130,7 @@ declare module '@vue/runtime-core' { MetaTagGenerator: typeof import('./src/tools/meta-tag-generator/meta-tag-generator.vue')['default'] MimeTypes: typeof import('./src/tools/mime-types/mime-types.vue')['default'] NavbarButtons: typeof import('./src/components/NavbarButtons.vue')['default'] + NButton: typeof import('naive-ui')['NButton'] NCode: typeof import('naive-ui')['NCode'] NCollapseTransition: typeof import('naive-ui')['NCollapseTransition'] NConfigProvider: typeof import('naive-ui')['NConfigProvider'] diff --git a/package.json b/package.json index 6191f702c..63e5856a5 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "@tiptap/pm": "2.1.6", "@tiptap/starter-kit": "2.1.6", "@tiptap/vue-3": "2.0.3", + "@types/markdown-it": "^13.0.7", "@types/figlet": "^1.5.8", "@vicons/material": "^0.12.0", "@vicons/tabler": "^0.12.0", @@ -70,6 +71,7 @@ "jwt-decode": "^3.1.2", "libphonenumber-js": "^1.10.28", "lodash": "^4.17.21", + "markdown-it": "^14.0.0", "marked": "^10.0.0", "mathjs": "^11.9.1", "mime-types": "^2.1.35", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3044541a2..2311f3aff 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -26,6 +26,9 @@ dependencies: '@types/figlet': specifier: ^1.5.8 version: 1.5.8 + '@types/markdown-it': + specifier: ^13.0.7 + version: 13.0.9 '@vicons/material': specifier: ^0.12.0 version: 0.12.0 @@ -110,6 +113,9 @@ dependencies: lodash: specifier: ^4.17.21 version: 4.17.21 + markdown-it: + specifier: ^14.0.0 + version: 14.1.0 marked: specifier: ^10.0.0 version: 10.0.0 @@ -2952,7 +2958,6 @@ packages: /@types/linkify-it@3.0.2: resolution: {integrity: sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==} - dev: true /@types/lodash-es@4.17.10: resolution: {integrity: sha512-YJP+w/2khSBwbUSFdGsSqmDvmnN3cCKoPOL7Zjle6s30ZtemkkqhjVfFqGwPN7ASil5VyjE2GtyU/yqYY6mC0A==} @@ -2974,6 +2979,13 @@ packages: '@types/mdurl': 1.0.2 dev: true + /@types/markdown-it@13.0.9: + resolution: {integrity: sha512-1XPwR0+MgXLWfTn9gCsZ55AHOKW1WN+P9vr0PaQh5aerR9LLQXUbjfEAFhjmEmyoYFWAyuN2Mqkn40MZ4ukjBw==} + dependencies: + '@types/linkify-it': 3.0.2 + '@types/mdurl': 1.0.2 + dev: false + /@types/mdast@3.0.11: resolution: {integrity: sha512-Y/uImid8aAwrEA24/1tcRZwpxX3pIFTSilcNDKSPn+Y2iDywSEachzRuvgAYYLR3wpGXAsMbv5lvKLDZLeYPAw==} dependencies: @@ -2982,7 +2994,6 @@ packages: /@types/mdurl@1.0.2: resolution: {integrity: sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==} - dev: true /@types/mime-types@2.1.1: resolution: {integrity: sha512-vXOTGVSLR2jMw440moWTC7H19iUyLtP3Z1YTj7cSsubOICinjMxFeb/V57v9QdyyPGbbWolUFSSmSiRSn94tFw==} @@ -3360,7 +3371,7 @@ packages: dependencies: '@unhead/dom': 0.5.1 '@unhead/schema': 0.5.1 - '@vueuse/shared': 10.11.1(vue@3.3.4) + '@vueuse/shared': 11.0.3(vue@3.3.4) unhead: 0.5.1 vue: 3.3.4 transitivePeerDependencies: @@ -3993,19 +4004,19 @@ packages: - vue dev: false - /@vueuse/shared@10.11.1(vue@3.3.4): - resolution: {integrity: sha512-LHpC8711VFZlDaYUXEBbFBCQ7GS3dVU9mjOhhMhXP6txTV4EhYQg/KGnQuvt/sPAtoUKq7VVUnL6mVtFoL42sA==} + /@vueuse/shared@10.3.0(vue@3.3.4): + resolution: {integrity: sha512-kGqCTEuFPMK4+fNWy6dUOiYmxGcUbtznMwBZLC1PubidF4VZY05B+Oht7Jh7/6x4VOWGpvu3R37WHi81cKpiqg==} dependencies: - vue-demi: 0.14.10(vue@3.3.4) + vue-demi: 0.14.5(vue@3.3.4) transitivePeerDependencies: - '@vue/composition-api' - vue dev: false - /@vueuse/shared@10.3.0(vue@3.3.4): - resolution: {integrity: sha512-kGqCTEuFPMK4+fNWy6dUOiYmxGcUbtznMwBZLC1PubidF4VZY05B+Oht7Jh7/6x4VOWGpvu3R37WHi81cKpiqg==} + /@vueuse/shared@11.0.3(vue@3.3.4): + resolution: {integrity: sha512-0rY2m6HS5t27n/Vp5cTDsKTlNnimCqsbh/fmT2LgE+aaU42EMfXo8+bNX91W9I7DDmxfuACXMmrd7d79JxkqWA==} dependencies: - vue-demi: 0.14.5(vue@3.3.4) + vue-demi: 0.14.10(vue@3.3.4) transitivePeerDependencies: - '@vue/composition-api' - vue @@ -5016,7 +5027,6 @@ packages: /entities@4.5.0: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} - dev: true /errno@0.1.8: resolution: {integrity: sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==} @@ -6688,6 +6698,12 @@ packages: dependencies: uc.micro: 1.0.6 + /linkify-it@5.0.0: + resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==} + dependencies: + uc.micro: 2.1.0 + dev: false + /local-pkg@0.4.3: resolution: {integrity: sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==} engines: {node: '>=14'} @@ -6825,6 +6841,18 @@ packages: mdurl: 1.0.1 uc.micro: 1.0.6 + /markdown-it@14.1.0: + resolution: {integrity: sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==} + hasBin: true + dependencies: + argparse: 2.0.1 + entities: 4.5.0 + linkify-it: 5.0.0 + mdurl: 2.0.0 + punycode.js: 2.3.1 + uc.micro: 2.1.0 + dev: false + /marked@10.0.0: resolution: {integrity: sha512-YiGcYcWj50YrwBgNzFoYhQ1hT6GmQbFG8SksnYJX1z4BXTHSOrz1GB5/Jm2yQvMg4nN1FHP4M6r03R10KrVUiA==} engines: {node: '>= 18'} @@ -6873,6 +6901,10 @@ packages: /mdurl@1.0.1: resolution: {integrity: sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==} + /mdurl@2.0.0: + resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} + dev: false + /merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} dev: true @@ -7682,6 +7714,11 @@ packages: resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} dev: true + /punycode.js@2.3.1: + resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} + engines: {node: '>=6'} + dev: false + /punycode@2.3.0: resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} engines: {node: '>=6'} @@ -8626,6 +8663,10 @@ packages: /uc.micro@1.0.6: resolution: {integrity: sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==} + /uc.micro@2.1.0: + resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==} + dev: false + /ufo@1.1.2: resolution: {integrity: sha512-TrY6DsjTQQgyS3E3dBaOXf0TpPD8u9FVrVYmKVegJuFw51n/YB9XPt+U6ydzFG5ZIN7+DIjPbNmXoBj9esYhgQ==} diff --git a/src/components/TextareaCopyable.vue b/src/components/TextareaCopyable.vue index 8b0aae617..9585177d1 100644 --- a/src/components/TextareaCopyable.vue +++ b/src/components/TextareaCopyable.vue @@ -7,6 +7,7 @@ import sqlHljs from 'highlight.js/lib/languages/sql'; import xmlHljs from 'highlight.js/lib/languages/xml'; import yamlHljs from 'highlight.js/lib/languages/yaml'; import iniHljs from 'highlight.js/lib/languages/ini'; +import markdownHljs from 'highlight.js/lib/languages/markdown'; import { useCopy } from '@/composable/copy'; const props = withDefaults( @@ -30,6 +31,7 @@ hljs.registerLanguage('html', xmlHljs); hljs.registerLanguage('xml', xmlHljs); hljs.registerLanguage('yaml', yamlHljs); hljs.registerLanguage('toml', iniHljs); +hljs.registerLanguage('markdown', markdownHljs); const { value, language, followHeightOf, copyPlacement, copyMessage } = toRefs(props); const { height } = followHeightOf.value ? useElementSize(followHeightOf) : { height: ref(null) }; diff --git a/src/tools/index.ts b/src/tools/index.ts index b4c161ef8..c9003fe81 100644 --- a/src/tools/index.ts +++ b/src/tools/index.ts @@ -9,6 +9,7 @@ import { tool as textToUnicode } from './text-to-unicode'; import { tool as safelinkDecoder } from './safelink-decoder'; import { tool as xmlToJson } from './xml-to-json'; import { tool as jsonToXml } from './json-to-xml'; +import { tool as markdownToHtml } from './markdown-to-html'; import { tool as pdfSignatureChecker } from './pdf-signature-checker'; import { tool as numeronymGenerator } from './numeronym-generator'; import { tool as macAddressGenerator } from './mac-address-generator'; @@ -112,6 +113,7 @@ export const toolsByCategory: ToolCategory[] = [ tomlToYaml, xmlToJson, jsonToXml, + markdownToHtml, ], }, { diff --git a/src/tools/markdown-to-html/index.ts b/src/tools/markdown-to-html/index.ts new file mode 100644 index 000000000..73a6cfb33 --- /dev/null +++ b/src/tools/markdown-to-html/index.ts @@ -0,0 +1,12 @@ +import { Markdown } from '@vicons/tabler'; +import { defineTool } from '../tool'; + +export const tool = defineTool({ + name: 'Markdown to HTML', + path: '/markdown-to-html', + description: 'Convert Markdown to Html and allow to print (as PDF)', + keywords: ['markdown', 'html', 'converter', 'pdf'], + component: () => import('./markdown-to-html.vue'), + icon: Markdown, + createdAt: new Date('2024-08-25'), +}); diff --git a/src/tools/markdown-to-html/markdown-to-html.vue b/src/tools/markdown-to-html/markdown-to-html.vue new file mode 100644 index 000000000..c84d44ecf --- /dev/null +++ b/src/tools/markdown-to-html/markdown-to-html.vue @@ -0,0 +1,44 @@ + + + From 67094980c9687652c10847bf4112ae0f36a31ce9 Mon Sep 17 00:00:00 2001 From: Corentin THOMASSET Date: Fri, 13 Sep 2024 20:56:32 +0200 Subject: [PATCH 02/16] chore(readme): updated logos (#1294) --- .github/logo-dark.png | Bin 0 -> 40398 bytes .github/logo-white.png | Bin 0 -> 39632 bytes .github/logo.png | Bin 8000 -> 0 bytes README.md | 6 +++++- 4 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 .github/logo-dark.png create mode 100644 .github/logo-white.png delete mode 100644 .github/logo.png diff --git a/.github/logo-dark.png b/.github/logo-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..9bee8a9cc024cb685e4159137bfa738b9f68a3a2 GIT binary patch literal 40398 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 UF8lQHKU$~!&Yff&zi{h+0p?k<*8l(j literal 0 HcmV?d00001 diff --git a/.github/logo-white.png b/.github/logo-white.png new file mode 100644 index 0000000000000000000000000000000000000000..560a135b652634440c8d1d76e5467546cee50b01 GIT binary patch literal 39632 zcmeGCi#yZ*{|AoGp;VHNB!@{kl*2-ieP}DCQ733>(plN)Cn1A#_4=m_s(_ zksRkxPQ#pvP0Vp~+Q#->d4IqE!tc6%*T;3a*z?-s`M5uB_xt01xZUqB?wDN{*>_?e z000oVdE<%&0I;hA0N^9<+0A>x?#XxN{n_h#!_FT75I*wvmk*Hs_Bih$pTEWR%Yfo; zsaf6!L3bllBLJW@L3r!_E&w1McJqqSyJg zDjdu{QmOAkwfykkiKo+3hgP5I=Aa)Qw;HI;7?Jt;z=C2vxd4hFIz?pQ2clx1Jt0Qe zchv^5K~G>hIX&Nfh`FjLjCPNcJlfBx;-%&@C3Bf@;25w=a>rm&k@?lZSQKe ziG9Vr_ZF!d8%JhgOV?z4YR?OGEX~tIee|H!ZiCigD&%DmQJryYulDGT!GYE}$*q&5 z%+>l|W&nWuAtj*_yFLJ;U^d&GzUiIEM^U7Usr=zW8s!mMjvG$GGDia_at2k^4@94! z6b$~Xr8Xwm=-d#E4?AUW(eI$cY2oVa%QD>iodv;{7Oj>11w6Gmw{Z8tju`~8TFaa) z?>e7lA%|5FKnY#oALbV82i-a8QL>>``$O6GZlz{3zKVk9KrLtg1fIg&H)F&hyJjYh z7!!A>zHxl% z6PKx|3V z%jXa8ye9@OGkgGjNjp zJQKOlto8kL8-xNgk$Of*VWkZ&ri1+c5M&MJtvkB2PJ*Jk+9QZ{0WtYrg*I+z5&Vrp zBDV4ijW}wZh_z6e-pTjF#;R_w38VToTN|r;0mX;@Ep#w|&?6^XGswc4dkNygl}J^j z^&E5=xsU_?bYDkIe~+>|!?;MYu^{a9w)A!2UVy_PehN>}N)N5rx09_kjk*=s_nmTF z+httVUK7AC1Lc4~P_Sd@uS_7Ic>m58^1N-eL+=MN?X+UIgzt+nYj7CDnl1l9wbmM~ zlzjJInhK28HQEaVREi09@XXOS03Ij{{JxIrDkl=$0uk=abC@cped8F)*vVv_T4k}* z+*`{yLwVZ+lPCU}UV~L>j&hOt>SyWrGS@7H9Y&aRXX;9)rfqw87zo#Gu%sIjZu>^Kp?Sw-V%@Z-8D-+yk*({l zgZY`=j6l|mWur@|wLmDtJG2sywj%@Vkc;k4wQ}z`tLU-}#y;?`u|u)$b}k+6i-YJAoWxOsL^qvA1Ky zb)+_O>}ECssfk>GsBdpI&C*)?NLxQPg~{u^%kk#`85{q+AucY05|BoU=X4!qS0%-j zRV;5rdOp?!zf0>F#R{5t^|+F$0Osg;m`+O1(jvKyvtESUcH?9kT*->+@m~%Dk+n%p zqR_xB!153e;0A#b=SxX(X}b%~lF#*|Gd&xV@Xgf^v_FK)lb5IGUKW|ui#uc>bY20y z)SWeQXldsdD<`}-d?MqqlEcM5xmfe@uhMU!L8%<(z`bHZ^0=E9QhJ#=Ce4V7brJ@^ zcU%Cx_X&gh+F@y=OlVef@AgE6Xa{MWQ>Rcb)zSkqo^KqgKv&t1AJ~AGjO{X!aH9L<~7bSu9umDa{V^bY6aw-4SUXKlLzYHq&VK?D!KpfN|soOGa3`HzKTpV zlgS37CN7O_1+L9z6Ov_Ct4hN+{Duv)z@Gv-VtriosIp9`+Jq4cK2X)UeV@Y=A&x>r z?AR~1YX;s;(MC)NEh>%l^A5qO`f#!w*4EMr!G5qGYMgmyqEU}$C`Y3wyU6@N~|Oduz- z>qlK$J?bPG+WQ+umA9qpv#fm=P;z8O7kkf}8blzoC5i&LKGEfDQVK^5u8RSk0S%G=d=HL__p@8f z#b(6pxi{V#N%eRB9)-b7|F`Q4urH^p1ANa(M_vs{=$h|Gp%=mpqU6JdXR%k z!A`%nP2~J^uOKL78ySYnQWOji`W)ybTO4MnFd$V@Ah>j(1GZ?Fs}JRV*BbpNrb0LB zl1@a|jz3eaN~VCQX(8b8A)&jwg;Ti>EbC1X5dc#83`2mtw|9QI%-;?F-GYw6(ogG-*@j{0TQWCoU ze2WoosZn51>~^REd1G|E$~Q5t{5-THo!OISg{oLDQ%_jsLla&vFe5^QoC|i2tc)`( z-;hOKTT(#VAspp>t6t>jLVv5frTEl!GNaN!l*l1J6~;VWyv)nLB;Jk^yhjKjK;6Bha1l6o4Wfll9Ejr*(kGH>I6m0=|fYr8rXz-_w>Q}f{qbfk~JKvhumI0jJ8J{6LzRiTnK5iqd?UBg=S%kvf|#lF$e>$ zxob_T6)JO2a$c(~onlpK2+*1p;{O}+Kg9JYa0k(el_&gpZu*BI#w%T5D2OiO6{f{B zDn5N$>o8E>H26RhJntug#tk zfgM^5RF)N|F*K`@FfcsL&~dU#9JMP6gL?n^58ku&D-xX1TiGmX_&p$%I22U8@2Bv|jwX$TGyiK~Dqy6nUFLxX!C0WZQ44)8Qn~Yd&7XDN*{R zLFWqLE2DP2J*8YTvP?x?_n-wDcJmT@0H7hN+%5wW%4TXJM(UFncA>}ZoXKu^6Ky#C z_Tg!7-3`6r@j^dC-<1&fim}TWBj1!&rz*4yFtih3gZD!+DwqpLzp^v+?@MM{anz#F z+GVQ#C~*7VO}(s{sC`hBQsr);VH{Ih)4$|x#R{MEsU57;N8504)k|Bp)P@E0;Mr`_ zE0hfp3t#xvscnwXs&cW`8UHxZw%)b$gc;^B!|`B^jP%|CEKl#`Sy5&9bONm+Z=xm1 zF(b_DV|hoo+!D_qh?Y>^M^8j)&iY;-Z=wmda3K#1;im$YD|fbi@1?pYK=E^ZvRBn> zysN1DdYN=kr-HdwL72&stMfJHu@a&1AV0fx3w~Z492)|R6yGbR5gS_$r->D%Kv61kJK@3Q9|Z1I1pO!JcKOArAOf5Bm{}g>mq>^TM<_fd;)x|Lk4#5s3Wl@bQhBq=g}(WIF#1 zMwEn1w?j0zE%4mOty@Di#}=n`yS&IeK|LdRTdwb5d2%}k-ip`qKQZHV<{{#gkGCgZ zk1B;W2=};FW#HNvP}yQf@tldIYV!kvz5e;A^q!I_^OI@+XA=ljCVqD zQ5qW_Lc<5p&?>q0<)t&cJV1jzOABPB3s9ZPvvdHj{&&I!m>x%ox67`;i6?HGP~6nN zEr0Ryq?9wZoMxWmi5!+X&8=4HDia3;|Nh@9uSd~Tqvf+g!|~dxddXG9vYZ_C)Vrum zsvV`a=F~zCsEckB22hH~+o=L%zPGp)AX{V3)}sk%o(3|8ElQGt)N4o3{HcN+*u;u$ zu(*svCgV0;;8OTW!1DM1;WBLTl~X@dCQl;eJ^8((M9kZ`eBBb`)+*`G>qmi7mbc7%yw9~|1{Td@aC!126H z{wmCl8lkg<1Nf%=I~<_0=c-T#9;a4686YhfEGtMPVCq&Qm`i!L6oreb_gqlCKCu0yyn@8Z zV`gjhJbH^FJqb>sYWGcaZ;glBLm?;^_E*)sC8{*d_tk7@8Ud7{Z8lJFyQR9>CLXXLV`V15+5TE1|7>=Hh;AhpHDi&T@(bUNon#bzF=dvId_HAB+jMySaGrmnUUYK&3^vQnAM^g4?GV99a@x+ zC^FI4`7nUYcuIusgjizp|lNvcS$o6f|k0#N-jAfK9(2N!Rabfu3T$-y^0-!)~j z3Jpmd?fZiMefYE!YB*_dE444dUv`xmoDAZi6uGV8TVMmW2e&6{Vb_q1TLT}!?6z@c zPi{Esv`RC*`fsJtm%3a9X!!3GFGe*;4u!K4vI@4gm+~5xySB>z%UQtM*E8M)i(Utj zuQoU^u68{bwhugY=+ef->bU^XEOL)brM2)!a`(LaNEBIXqK3QltcCA)K$qFKyq6@q zg}KMUUPTJHrJCUtbSr?tG-O*Qaks%+!0gA2XTwG~UIr#}0=BsJ+9voO!$PHxB&8C5 zGFaL_b32Ul&YV{}UgLoqvGi!)8$zmFbGAADE^sx%PxR2ni*bWODZUkryEPS?jxTIy z&YmrOUF;sFo&VG)+^XE?d|m?NA%v)Q!Tp7&NN&PljKg}NMsf28qJ9=hZXof_LFw^*kpyf)?Kg$wVG5q7&e`(^wj2PHm;d_1 z$<9E z#-4PJq~dyJw7+84@=c|o zZRp(dezEb04zp(;Ho+GBaE+clPu~REmT%qEYYRN66m9_N$cw5?>k9Lw^;@Hqg7eQL ztn3xBkVA&TZU4GyB9ZkGuY0YRRR_kS&Lb+n0JKZ2e4r+keuLo0OB$U7Eq!w_hD_ zOWKg2q+j>a;X}RrKs%h=lhei4RVRK??Mnb}^_kTlo?JP^laO?9Xzcd8FuHML!8}Y4 zcQ3Hykjy#!h0d7+Vw0EZN|hl#!2Wxb%lV zP5UO1=~Xc;SEDg&6#56mcyi8y`9|-lBBYCSj zqfV(1{kpgKvj1{T|MH#M__6G8H~+Fwz(s{yGxXoMhL?X1dZ8VJaW-H0qq6x zrczDe_us(WGwKww&Hf&k<%3@snKti3NML+EQ{t`X38U>no714#%DYa|B~$qb`S*jv$#S$q!#Epell9cb z^ARS0S>_1R9U(c#hTb9z0= z-IN;5+g^Reo=5fa+%d?Tg?us~TKGdl8dqY}(f}AC zV5Me;KIxVs_upX0c2yL8+*?P1-sX9j=B zBj=D18~*}`NPsA7SX5R-w<}-ZMYn1+vpvy96#Vp{F{|5>)PwB`g91nwDfq@74=NT z53Mf;u_Mf1^x(hBA{cAt_GaQB_B<#~aQ~5J{M0!A&!HmLj3riOZqTK&AN6Zd$cXE_Hk9IJmha49v4o?Zs#Rk z!Iug|`M2M%zGG_pIi~Ui>e~_M-r}d0IIA3$%X0F6M&bXxIh?ev>PN>F8kUtapDb6G z#w5#6jT^oQ!!tzpRCJk48j1^&ZeUe}bH4wcE0S{CtQS%IYCrDaXN{P+sdl5U>Bq>e0teLABTL80Vn9QZxN?x*N5(^JO0N8=#6x2dh{u zA7Fz)1ty=8uXdhFT%7RSesy=2_;pjCj=S}<9k0=?f?4Uig#q?k<6d0L;0J??w%RTp=7;pBY)QI*93i>bPwdJYVgwQmaDpJEplj#$Bh4 z@T%m**L~7J1CK1v zcff$H{dXz?nhgGoh38M{PMs|{=G0B@)DqczQ8-jA9r{#2{%{Wv3jDZhMVijb9f@rxSq>)XPbUiVMr57V^&AYXef zlJ;+Hd{XP#`*q$k>oqD_yi*|t4tj`aqAN!gbDnWc zmxojs=AVQ*Mg1hGTFb_K5pjP>mWGXGEN7NWze;Y8)rc9j-i{x*s&UDX#`ouWHgWlK z_|3E%Y5~`R9sko`*FqgZpP4r`IP*n^=8%rw-~l_TI+<&?s8 z!^bGZi67R#7!LKd+`01b?THE0nP9rgLxdt(UFc7$m70n41aaMsRaYQ?ZqXHDc&xIB z(wqqpZ{erLzpTKhDQ{0+ZQN9i)*BtvPWtzxdqzNCruEBieQfF`@80+^S~ zypXEm5G@6Td{WGAToyB^kI=(i3lCza0cLr`j!t=pI7HaC`)PL2g(G2}KskLv(yw-G z0+`aMIXq|qE}z)z`#x98U&hDr+q|D4P_TjeFT9Fu6@;^T2oLFb+_0BQ6Ww4>(IX&} z>`gfeb2tl@6|mQ917@o7uE>z$5PH5gWz9OBo6EFNT4x(7*A^%JCVt!$hB?&1HlLZF zp{0agA!F=HtvX>_n|Ht-PPeY1gPBK@Co0g{@+XcATxFl21cmE%B&6Mp*TjiE522TL zXzONdnT==aOmc9*eXQaYv*-nbw@ma}`{UWd{oH#vX%)gDz|ir3Iq~}@cYI7!Z1~E} zBrx|OK53>#ONg_Y;1O~Ik=n3ur2Q1U2zTXW(S2{_>>IToI_C$cLRQfAe_nJ+VLfxE zQH+_*fQ08W@D9R@7QtLS+~lKu{@}@`+PwG<2-OUk2^tf&X!jZ{+wk2DwWp#l)D{5+h494HK zix2ETDz9{SjxVc=u?XcE)ctFJd%u7AxmQ^Rc)++N12UYYhuElpy-=5QpGWD5 z(^or<=yh;njl&V(kYI)#=LP&n|2mRK>Ym&oOq8^$w>tC-wv-WdN+G^+PAqyyK@ce)36!y)s*0-22%P|at{jlpGOVMn zb>#VHFt$$(=Rz6>QaeU`0wDEhFJ}=HAozdm3>*@sw+Y{?Kug(03}744$wH~a>>N0$ z7Rt1aYWKO#hBKWyw7N{TYnNg)gKZ%hI&~?!$b*1}x*fXZ?l8Ggw9GWL>VtFDu6DeB zK~SLbQX2B}Oc6W@{H`kf-_uI5`p}b=S`gvnrJ`*l974o^_x-=8hBsPczNIcu_C-=) z3QRO+y)rZb_`3>6k@zm7!nIW!-6hyA+D9@@(b0daTHK5bSUQRj;#dQmjsFSYEKGez zL4#f4AOl~-De<<*Edpji$OGCYP#UDcW4gK;>DaZ);7NbfIZfnP2QF&59AfyLaaP(j z6eXA71CrDjs3V90h7Rrk`UH2h#hP?BD0H@wF79WfQVAAn-zf7E)yWw3s_X1B%q;$8 zgISG_raQaQfVV>uy$Iz1AMaScAxT6SgvUvFF@If*P<;81htayf?@c!mE9J_jHc*_r z416DHhRo<^Vj#m7zSD-F>8Fkjg?<~iS;px_LRm9@8xCqyjh(NCr%5!Pp=OBGD)WeN zmsrxCh9f(~IE1cTwVyrfc>qlqdeAUBh|7vf;SFH;viFp?k16^|@TiIfYj;c!U&E{? zN{LbB&=Qr_bdRd`OL|wZz&gM+Ruc{MI`csUMdjnsE${>Xj1Jy%baeBYnoBe`BT9xa zcB`RQP?>-xrv9YKs5(F5s}T3o$+{VSqx?k#;*39o6z32x9_bmBxPa*7H8(i;fF$pwr?!6>hn-Wl%GNEF&`xDDZDoZ=@6-_{K^(8ZlPU@B}&gQWeb6Kw)DlK|#C zIlr@1i@8>l0iy`iZpf&hjyIB6wZL zea`m2TWPz_a&Lv8#@Z;naTg2lS@yYMlh8|3JV|Yg1-mA$AMEZJjZ2{sQi%H#YqEv2 zB3tddXRX%h5hf)=dgg|hIK+1f4loG?ALO|R=TK_SMXH2vXw_{Vx|};rGnR=D4tzs- zI{7<0GlwI~v93n(2sA5ZeJRetyS}h4cq}Ye$q_TsRD@!YpREx-VlLZHViEm2Tn4d*@FEP$;g?eJWCem0c)dtW2NDTOmLSG zUDa^9`WRqH_MgoUeLCaot3CFo$K<6xhE{>eo0U!2S=8Ts4HxY|=V1!nDN2Nd@LW&?m9_WV0W;9Q>D&{*qz9=I8R%<>9g z#v=BLRdrsVulVr>1kO8ti@`1CVG*-=6ZR48xMa~lP95C8>R8ZqN5K-S&VPN8!7gB} z_Qa+WL*ul0d#v#0K|BJ-j&ta#9yK4+R;kiRbw9_wtJWH{4xokBL{MzLWH5<_q~G23 z-KhGAB7?>3Q|H1_&8>bqz~WG4K*`-5^L*qVF}YVIX64?f3lNKgHDRR>~bX*Q8_ zz2oYS6YHOKWYC42Fb}-_4bk+*Z|h8c(qu_vPc9&$p;wt_B}4idrkj_2+Yj`DRTy$Z z`@6G+)yB;2sJ|X%fR`?_=HdGF5MC$lZygDUh;`O{o%SLyjhZ8stZ6ScRte%0Lh3--7sukm4`1kMv{BN|74FI=8 z4Xd@(2ClC5nCJA|Zh{4Ka)ICR$7(Zv{jQyC(tErc_IpJt7bN4rH>Cehsg+8CL{P^- z=Uis@RN6rmf*@Y7{c(KPS;ALQjXE(<;nMC1)BlO;;xnOOTkmC~T|kQDbv}yHqo&0f zPfLT3`e!^jsQ<|)H>BP88bJK%KkHOG+(xo+#c0lG z1E24oe6YihH_O@9-?SkZo+p;T4;cB?YC$6Zn_OrL?iLE>uRQ%vCB8rB6}EVz7kJ); z%zS>Ks29)W^8SsK)v3qkcXoQFFiL3KtVnqqfWr=vUKz|F&*ouuY`cXj4C0v!YhaXz z(V)sH318$et7W=$iRkGD% zoDS?9y^Y}J0DRnwYicED$8>M>*Z?Xo?nq{(;@e(L5uLIQN!*e(A9})>*aKU9-)Ypv zn`JPIz`Ft$bx4kpl%}Gn?|UUt(lX^)F>0)@K3hwyV>>(0pmVW z!ZS+vc%F{W-fzD$C%^3&fmK-pMQSVfWH2V|8i)ved!NYd1gaqp)+*Qc zcVL6hMQuFosS5TKI(g&3jpPt@p`<<0wWG;ke6RcG@qOciwS`>? zwjR4g|1LTe^zE<%pjdEc2CJ@2rA10mXHPv=Z}w>-Z&IweV^qKV?J&iMDvK23wb-x5 z$9$i02m?8FE{%SO=l|a%*0SquZ3gi~>$lqzB#P(jo~H)~myiOCdB4ybjLXZqyy3>n zn+<0AALu&b_(*?h2+Kd?sVKmP$6WL7O;)l-U(f;Q_}=anXG(%??ADl)31DpBqQCNb z_b#{3ze`t&6GO*tV)G_=vqKU)QTRk(4olotbbEFpmT zPMCaWyX!JF9J^qwGUMEuxtdlBJ`JF6)^-l-Nm6-p52P7yR*0I!6TLmY?{9(C!47q} z3!Qrt1%k`|86m*kR(6`#-y-E^3Zy!A%w)fWRE?s3o3Y#j56TKHyKZ0NfeENh?m}%3Y~_3bnsPZ;LN5KfhVwk& z*GX$1H+3SM{PWnZuyd^2$uf;>0`dfxhl3Nn(uqS`2VPZ;A~iFcoP?LJ+@>Ja*o-FC zv^n^~DZ@7l)k#pNa8n>3;2$6nOU;od86*s&N9;2F5tq(F}4gRR-Ed-&>9G;#y zpB=6y>gk<}t<#6fc4Jo32vqvIP^8x-ZfERlHpNlTk|((!77J{jGIY+Q&1NFE<5~Lv z9~J%zKQ586&3?Zc(FWBB=BP!cP2B7rF&Gl(>rm|Ge;j@$59SS8qBeFJh3FK(mLP7g z1bkX#0ukW5G#Ye#ygJ*K^_&^X+6xHQ`KRp$fzk*nkL?s@4{(lwba+wsZ9ONDgOL@g z2PymeBgkZ|VIoGTN0j2!A+_8vUXr~Wo?re~j{p1l|0e_@mh$&5f1l3=b0>kE46uPs zO7^@x8MwB2KjY7pLbI=&35pGI;)=gepQu;JudM<^6myA|es4X8V^cx8#np+Yglhzt zBQvTifaTTSXmn5uH5%oe0WrGV6H@@kG5ED_$#{ zZRJgh5f`bJdLBKDO-qC$SaiV38&)53O_bRWPkN&+ALrGk*nXt^$?!GP4jQD#az($# z@!=U`j&T=8-p)kLeNcsqcNvtDcJd^P=Cm+Q5u27-3WyU1MmY|+th}a_H!12f)`Zxy zANnz7#aoH$9%L163*~j+zIPYQw?b~!Uu*dQC*7}X$y@W(35=ZxNn4_fVFzuwx4b%> zZoz?T-R8s|XSJq41M4-#-V?1aHAv-Hn8HI<(Dsr+6P!@zSf;-sJi5_;WzY+qyt{$u zJxrZXiDd!Bn@0|*diCY^AuseSIns6+na>6HTS}9^_;u3jLSSb}^m*nh3N`G+cG+;V zEzF8@K|4+#JbaySuauxt03FZO|ASo!z#bjcsyB;%9gWC;0Z^!|94tB5lTH;*Pj??rohK2hF3hgu){-h-f&0_YJ40wf^L5Vx-<89 z4DSOP-wpFo4|8IuvLxcVAF62E_hz;p@~p}AuC@CKno7Anu~qQVO?tzhY&QlaES|@< zFuK-hpRlFicGhY?ii9mQ8cBaA!M;OAk zXpG+S`@KdRRRTj!+~T~|Vy(@bOM4RscVyJgy~W!t}7i4B_|{e4)Eu z&F%uy&9B{dhdVg6h6j*wpWAL~_sV5|FRpTGrIKJu1{<%qD*- z^Y?X`g*%>26-BV10eXTsnRrzdQ&iM)<$|(@z&Xyi<;A5bI9uL@G5R0~s(0_fq%X?9 zXvT8}5h86O^Lb63#^}74f;;VJ8`FJ(27lYd)WTz0>l3oLrq)y8pr)+rsCX0m*88t; z8XS^EYzya`q==_K8}(odq?I-;1=P8n z`?OT_)&*F<-{^(kKJ~!E5}Nq8uO`mLwt1)w$r)UiXfc#m{8Y5)7VUX%KdD7z?!QEh zk!6)N+5a+qT7vx^7Mx(GBt=+^3c@_Dwl+X}@@_6%Hs(0GNioa^2gzPbi)@kGP3&7{DwhB(=XZ1Cxt~b%ikDcm%NZgk$E8JcC zLGD%B8@?}o{50pc9o6yFOWJdOQp$Y;BePw#u8s64mPkx;u!YFhRkl^PvQTr@8Dq5p z%dZwGFQC1po;4?(OQfbg)2dI*7=)J>c#ZlxYRU#2eydAb9I1~1G~d)y*${$yq+2a* zBT|G8-7cGmU%02^@%7T{rEM8q^7WNKqmfw}Y~bd@(`r2hqjI7tg_)=2Jg=(GGzF}5 zmCwbmS#+=7lsMjY7_q1ly=2mNXXCX^MT+y=E9n8pRHTUynL1=FrJ^X4CS7z6Q(`Ge z|1ghG5{15=J84dD*LHLye@-d$$dUU)RtdFo-H%F``Ftq8v;2%pY?)8^L92KQ=%EW4 zRC;&av?)7g{d*u(#t&17g@McO|8X*qr&QY`;*U6Hx&*pXEJEL@cEcYAh3M#h$tvQ^ zyu2dq{UW*SpfT{SC}(~5*^re#x(1HhR@Ug5h4?q>dx6G90$Ky9f6`w}o%#B!(>zMD z;>)~sIJmnMK4B?hZ8!2&a73lSGV*@T+qt1VXx;i^#$9~f`$vN)JI1uQ!HAbhtJK4h ztG-XHxF3nV0a4}E^Ha2b0S}p|t_Ko2Ag>q7dqrpUyq0Q z&lYIbX`tCFRXeZk^Tf79N%)-KlP3admFXuRPE7vHU0cgJQAp12{brl-pbj!yW4#u>rs8@Lci?INLzg-(T;fNH%9(5CvNzI{13Hl+`oh_8?9eO8B1zO>3+e-lLlUn{dkbf zA!LO@h1g?rf`y{bJ++eewlAKQu}v}jjK<@tr+%oP+D;A38jkK?|H6@)kuO-`c9(l8 zA>=l8cUIt9@p?L_b?xkf=UV%I2nO?W`odQy^s`yd%=3J}%M$~9;nL?I35vAIN`gYx z*n zNGPSyok>cIa?y1ujnKDFqH;2){7#5_AE%}?dfy~Ck#u8GwK6)Ru?&eN2pg3lLVI9b z^B?2r0K~cU9TZyXuT4XA1o(y-f`%?m)>gZ*1cT*Udic{}BPo1B}WeHZd0-W@8W^Q};C+Xe_ zuUest{G17aZq)wnH;^;lQmcbVnmH9Aa6==$hrZ1Optw~w32op;kI6pF2#KKfp_PJ)8G$;XJy zngJ zvb_-ZxNyj6R{X$_YBsL$@P~D-HUF`uQV3)hHQM?6@#OIoSxQNE(xrj+9@L59iSxoQ zq)bGd>b#GO;*Vec`u;Y%#C))8=xofC0}OsVI!2^S5Ds_yctJ~S`H@8OS~k(vtrKj* zc%0UpCi-%&LWd+0d{C2^?^NjZKBuoTH_yL*Uw94buFKM1SbhDz zjo8Y4Gc&tT*is>BfuFVm&jbe*x+ZGU2u=(O{g%3v?3ft&ZO$oL(v_yu8iMgA(o#TZ z^YP8jHRUzyg&8S`o58@!1vIX$WC*(^|KWlyR8K+2VEvI}q0M*JwVK@*E*h?PcCF{> z^i?Nc)w>0$^UtGBsYMYt;<#+$z33IffM@%l#iG~1VB?gM<_Q?}YvgqOR;|m8f*gY{ zbu15H&RQbJ_h$6)Y?ihQvTUCjRD!$WJI9s+<+8W4v$wELdweN@{0>#z zX#&f~=}$4zu!0k=&Mn*yAGw7eZ%qk2@^#hyC-B9@S90#p*Z52j;@6bL+Gd*c$*B7k z9}KNM4NXoT$%ScA+IlpW0=AFRN8z2?*Y_1V zU;kiI>oshNx38+4Qhh(Hc1N{g*7&u8qvQ(W5!&q#wUrT}D+Y;6tS=x;PoOC@FXg`n$fQpTaR_ z^iuHuWu?AJiPD%%_-*eUp&_7()xV*HG9k5OQY#)BACZ-Fw?Djcnp9hDZY>!%wP|E9 zbE`f6{Dw|gX&pKu;LN9=(e5=5)(k|GwWEe7zWRw(@L6WK3~YQ+1tn5$4;Q(HAGK_Kr6|~OA$#9o`0I`ysL{lcuBT5eg3U}YbA;M^CcDm5E^=K6(~<;h_Qk+U;r4;lRkHdNO-ZgAs> zX`OvR%8bOv{c%rP;Xe7Qcc%yLc*`rhF5bG;Z8DAW%mLW1oTz>|vZvtf6WyHQEa{oa zq+9vi!>1Bi7E5rN&-Q6E7PnWix$x)6^wNhtD#O!Ed)z^yE7ovuwV$;lp&dB)lZ%(q zTyvdHwX|U;O4$eN*?$RVxaC}(?1scn4INdpDzp=`zf{^^WF0k)Lr%opINDgM=61ea zM&sdhEZ275m2m%t68JN>=eDi-^ifX=yomA^4~?82X;DwYydET0w6IT}3Z8MN4xFKv zXis^>nG@3%&K`1hYUwOBT}{f-hz%0*Nc&AW|3++Y39aCZix<5i)l0qK#gj#XeeuZ_ z`HGjaK34`#Xt_R>$zN2|%AFHeQ|5FRT%LIJNSVIX&*u8+gq&@e%UrvdUOB?QpLDg5 zgCX5ip5oGFQpVqpX>y#@Qo)xz2OqILNmE?)OfN;3?IQP&#OCKmJaV$dfG=>ce~e6#8m$Z>qM=;X2=)u9y>Yd1E#P=xl%Z zgEMaoAH;SK^=Pl##CSB_4kHKnB!swA^@?0(-|Qp9%7ymXajnX|Qk0reKI&PoUQLBd zs7?Mbge}6@`D+G0>!8SUNH#Nk8N`Vd=lK?ehGXSv)7jYYC4*O79;0}3$@i*eq7A+x z>+*y0q3fPaASM76#$(BX<@`crk*RmBy==~{h z3A){!p}__F1G0Xs^k08yOPYu7qNBeLD!XcW+E=Z8wv&8)%e>)Y#wh)B7!WII!6OZ( ziy~Vh?5~WZS^OCo?szpK5QU1%QCJAOR#cpyC8je0l`jaZt>~Y_eI4v3D2#6-t6k&9 zA@0Q6?P5eJTR#jQ4Ph2x`xsvB)q7T-4O}K9|3b9qeQfP3_ugM#_2dR5`|*=kzca{K zay4VYrW-fUe1om%tL>@2gym%RSx&TZmKyfNeP9TiRVKdjyVochlgW z@)+h7Y2g#sXFMpm-^~x*b0=-$XaC3-!!EK+(Hq>!07bSv<>$~f(&YPB<@1o$;)3cw zn7kqu_sy%e3@f%D%fAcb$XGX_RU{9jEYm%}7eck8&_Wl`#RE0jWef9?t~J&LWe4(3 z9yQ_4PCIM!f$IrPPE z)%1^!p>B- zK?O8Sbb8dbsD3hR#eo##XV6`!?mg@9=@ArGP;-1-YhP0b3D75$FpIVQF!g~7;CJ9Qg@;CPlVsk~ps9|-X z2bC-2Q>*RYeCk&;S*}{)et{nFdL%h6ad5cbwa{G7cuZf_vaZ?k^`H6Q*z&->;gkn%9{-gV2Tzjw3ZrB=0?ysd~IFknrQVP^#-Xo__w6G!uAIgCO)3@i`K*1zq=++ z)Tp`l9P$PG$S18<+dd0$1IGb&$T9t{oVeE(wH=NoIzFI?3TWv5yrM6JY2(kVJ8CYs zt6yFkU@aLv+pLQAat+wGZlXLhHT$y1!7&Hh|Is??v&;AU4->k-_TUO0n#)BTetISj z=QV`dV~-u0sMtD=Q56_3Xn}_zGUuYHvXhKyk809V4Z`Hv=aqmm$ z0a^`nvxBt;J(gc!fz0son6rUdkI{4Cu~Tsd&q>5mw^dqjGX0XQebOjAKf!n~#s5uu z7suD=R>^7Znih2G*PXZ2Auhz{i4zz2IDNlin{WAe%b+rL>844YnG3GUbPy&d1T4t? zNiM8bENWb=@2Nab3;euW^aBBcx3X(g0mZv?huXcFpRx&HeC2|)mo;!{x?-CjsKhUS zvJ32HILR}P-Nf!-gL_Id2K#e0mMw^5Rg4wl@7Gtrt6#P+iogAAr_ukmR15}@AOC-7 zIt#ZZ-0$zJ82FJ8lr9xP5eAYeC$z$$W}W!-j48CRu24%h!i7jq>{_3eI>y7JF7UN7 zWN7WnDHC4{^;&eCg9_9#9mL->+^QqERHjr(>z)6o;PS1fU2FrUehx}%QG1w8Fkd`! zJBM@XOq`k`vyVQpiR^n=>iX)UCIATR}Pjb_G4%CN)nf_5W)FWiy+Nf zw$D%bdv)vZjDW%S^b-LzO{kH0#4{_!z-9GAq@B!CXNiR8PedZ>=YYk*tsm?Tjj6hUfqApu z^4R#g;sSJb>TcSGszAm*oSm@Swu=}%Nb=*7*nrkuZVlO`0tK-33%S7lC0WstIEK@F zC$H79EsB8KYIjk$%Xu#7&@$x#YbbP66xxVqJlg3kw~2#xk4ZLwP6zw61(9>=daZWf z?^R)=`IyF^pN{om1Y_q@IvnN<@!5JC%N_^FMldZ-s(DMLnwsseK3x{*YA6C}p5Q-@ zx?vB0874L$q1Sjs%YwFj@?klD_|K2`;RDs6DMJSIJjZeOJ(6zG<_p}*df7({!2|6F zZHEb>%6k|4!9zoX%tF1#{%5}JezS34E6DWw)?4GLm`PYLL9?zn1^TvihK4tI%6}_o z2?eX_2P$W!Yc}zJz|nU^%C8Dz#QiS+dHRz+^bN*)-(cVB%=rA8k7BW=&qYJKhJYoq~WWP9WVw^NT4r!WA)Q zpa&9XX>M-^3MHTW^Bp|}PJ0;+AB2XHm9tN(bMbC|lK%awXDMfHT~t6VnO!FjJ&zXX z*sm$PKXPXirl1lr9Ya%qw_A-#34a~FZ#uDn!H-mJ5>%7-wXme7at(BpDPGR-4R_wY zF}QH}o|iy#%JjM9Wy3|?I!ps2`n|(XpSEX-sDWHg*qb%R5+b=k+sPuhV!9gmin7kKG z(`Nst@wB`+#oxHur7q}&y2E0y0EN-iM9?sF4oWMB2ZK*6rd?=T_R;d+RjxM2>XP0d zrIc+;H(ACIX0rcDy}PeIKES3~H|AG=bE>-ZHt5nB`<;o5tHkJ$9T-gU%`enczG=AU ze0s_&n}ORz_D#-IP2n0w{NY&jhZ=rIT4|BZ;&HhyyX7}$vDpTP?DGUi9b>nU0+nO;_T5(UNVhj0KUc2bTF_~Y z*)qu^I8-ueoG)g5vi?2pzyER|cIltr6rv#V+SE+3Fw3Elf|P(_g)<~8xJJmd{@?Ep z*szM$slIka8kAu7mq1tmz!M$AXe9_WGs~!o!Qfr8t^?0aGOe-p1G?el%HeH=I0n>q ze!x0}@IH0Hm%Hr!X1k{%L2SUjl`NJ;d;DS|@U%~(g^?9G-my4l3Wd_^v7>mn7}@4V zlNUC%iP3+ebl0ha*uUq@y-OIxgCbu_?kZjALvZ?sI#2R@KuB-LUm&ML5-w(xPJN-Fr z+LzpYaWspR*d_Z`;_h30;pW&&BVP~hix;nbXM%&kaVit>=3dhNG{32#S9?+#|G6z@ z6`&s6FkoZz`~j7ZF?w$)_Q+Fo1nBi++kxGFUwPoL?zthS)7z|-QIA7{Cku%HFdl!J zSQm(s@x+ZF-RVI-;@9mHZixBfz#{Ee1aiF7^k0!ufA!yR%#Dm)!~!jU zu50q098btwvMY}O-cP3Ai!N-m&MC#giZmHV62rn>RsJCUknRy%q;Q_)v^!xta?jkW zs8FpxH!J^s-ie`;;N4$miTGJ-!EG0HufF3OjhA98-E#6V*Ao^>p%S++ubgeX3Pa)( zb3?y^&W0sHg~@JZIff)})0@5Ttrz#Ut#DO1@UWJgJ%`9*traMETw zCFxFpi7Vr;wz~arOSVP;dxKQfV98-t)IiW*#KSj+^mz$y8V`S;_?eaom6(L85GO9dk1leqbb`g-7GB zaoMznTO-)KHw;)R!#};5_=e9Zz2ocp43{$&PXJkfD88zC!!D+}<3DW23r&4mA}&Fut50xb%} zD|ASETkWxD6yo^g({bt4X>Isn>TBzhpfmy^#nV0Gp$ph*X3U>bs)0a~{KdRplc#h) zgTh|xmle)C*z_>W7+boNhfbOeux4y%w=icp|J(gsWcM>Fw?y3Anw5=2f#+EC+uGc@ ziL{+tPH7zMZ-b*%@W@ySzw5F@lJC1NA{)*}n^ZJ*oQSb(7Pn`#GNY`@)X$8bTB2n8 z_R8ABg(Di(T2o?uVXP^x;-#;oECR?bx z6rh(tQ8^`We&)?TT(1c8t53|yOZV1t7&|rlxwBL|q5fi4d7#t4aSa~1q|~o^Z|HHN z4EwL6GW1;D;=yV16X-p(Q=LHB%?%9H>?QdcVNt>MJL~ zRHpB86$4AwEgmh3gHp9;LC{5t)_zVci@%4rtu*f8x3NC{esJ0e15soVUM~F6i{l$# zP5rvGnQc!4`aD}#{$muI-4Jz0m=~) ztlBzW>>iN;Fn(fe*(mGAG3-qnmM|0k^o^C~Cy0sDc`nCkEy9h|x9@?S5QfNOR0A>o*76E3%~ub>Z568~ zO>f`NYW85|XCc+;wxzcB#$n|P)2HVCYCCriXi2~*F7Cyz(2#ev?@-wqcgpCa`ph_) z7`vM?+6V7*B?bh?Z{E!_`;cOvl_#_1*{7DcZj65(fq0T{DZ^7_Q-N?{iH*WFGn=_x zQwI!!GLHGl*fdJ^@6cqk46(|bWCENXf6~5e#Zm%#?U%p?t-*m=Y5$5g@gT|ehiN`@ z$L9>J>O{O1C8m{-7Y^38l zW2;*oXkxCo`L*8%ydwvWL|$chzOCQ)lr1F1;f_{(Qo`p;=g@$-!U!PK@^m2hz>Ryx zlCNxcEOc6t->{&ssWmzAi@41=6tEpGUw17y=%wh2Qrx|X`p6~NOc19p z@B2fQPDbQ_sso-ffEz^f?2>_bhy-Bj%M!BxMK#WIsL-ori6>YG3molSS2PUw8-5AW z0F-aMPmxl61zk!?Iu@@Occ<@k)>(G`^7zluRwUMXXs>Rd^5wDj#_O4c)E^jwfb!=9 z`wkg<*H2zOB)7A(i$&|eWaOO_0++OYs}EOXqajdzWF}E_hOXLv{r7(ycY7_Y zzh+JZf3=A=(&$m_oIhfg+cbkcbT>AIu|sysI&at?^|`1OgG5&9&uJM1B_y3|Iv=lPSlP?t8nKUH*Itt6mV z@1cN?`YRdPP;B&TwYasKvz=+9#dbBg2oGMDp0%Cvz8|`OOeNo?BN*vShd?SaC^@=6kK{cab#n0NFTc}z>kE{vI~sTwQ!~_2`zTH;ceyF}{zhSAgn|v#o*H`h z<*wI_{ys}As;2I~Ve@nzt}J-;Sq`39ulIO%&bVac{vJQ4jtSMp>_`dt2=m7r#fUj` zi2Ie8in?ZVr+nl4^7w~h;L6f%vVwRz~Xk;5mxh#s13ss(q!cMLhjgER%;lm%4Ilod-{?;4J?vNk|GYcrt&K-q6DF zr2MH{+DGPRL4z{HNuT4QG#;%e&)^}yI8BtJNPFb(brT#I)*42wHMc{YWW{`FTaeSG zl2&Agd-lFt)l`&L1`Db`!F~rReB}OU*8C)$iODp_a&FHXqWJ;P`tR_Z9*p;I9ZOy6 zpFNb}5>3fW!m>o6XzGg;7N>xQXCVo^!ES>2IpxcKCDY8PvyRc>KS-N%)d&0S!Xv}D zb9pC)iVXU*R#a~X@EB8=CgAe-$U1~pEf~_<{4`j(@2%f?Fx6zP8&{_BZSXHVEb42O zjA7J;!$Y0uf!Ps_3QARGd@b{`2RK|xY)(XVB8jF;j(v&E$e(GWWyGL_ASE#YrUqq7 z&aTldHnEIWH+|)nX=OcNJ!456Xt zHv^t((G&5GeYK?wpW>6|g=eV*A(HM}$y4NsmAgl;Cg=o41CIV(aeU|*$e%@1>TDQ5 zR5t7l(w^w_+V|P7zWXNMX>I%#N%0P>cGC40cArj}gq&xd4haTs0-#SAqBg zh76W?n#oPo*cfO`22`aOTm)HYW9h{~KL48UiyZFnp^D7d&B8az7QT=yS+F5eQ)CG} zK!)s-DEAkM9i}2L5ZdD2>Qdb&K*W3q_T9m~XfbSFZLZ$YeT@&V6kQElw~5xc+=_1h zQNe7~R^3y>IKJQG#c&%_a<*@(eOE}xVubHOPRQp>TK~vb))j}7t77_we~FSP22RPT zMMhQLt4?yN<%wc~XY{SxzZu!sn#1UaCg2PIoFldoroxE@*=#uf*;*CH)X}hExw*0O zGGFD-vl1>}<>%5pEGN9fx8;&|^OVsWphliOLh{E$hiNjfTQa%G`(eik)(Hk`^)0JU z3m|}}qx1J}z$sr3%p$=jxZHBbILy3c&ip~QqPOWb0@f#B&G^Q!@A5VjGiWTI2C>_e z&29%_wqKcg0}QsxX%e7w{nKvY?yc$x2-7ZNnD3Y?1*vHafKh)fTO)C|a(ce`VaoJK z(&Tpf`0Z%zokIIF)MJD|&Wcb*?`YwJhEcAkb$!-j>SSlQW%0y`{Jj=CL2p{kMvSWM zR`xe|zJuJT`Q-FN6*nzDhbVL^cx{cAT`uw?+T*e!IJ^Lc#=K`xFg)_ufWvh?jC0R>AVC184Gd87RX4HMxG zx(=gRx{bvvB`Ph$@@oYt4sxo*ynWbUo(y{y@gYJez@qe&qN4#UjSq3-W7IF?f$bG! z972qzHnnMW;R^Q@qj!R17$KEI!mFsMgAp|@+Y zVR6ic4(bwsy~u;_q5jlgt+N$Z-}%}Wmf#pyL>>z{C74kj-B#UbAaT&@?@hTJa5FTn z*J#urA39#hoM-y0NW#tp7oOt5c--CFb!-0;?nZg{*74g;4p_}4zU%IBRgYuX+g%^a?M|MnHf znnz_GjbD715Bt+ht+GptEP@|7*9+ubH}igY>j=cR`-in9TNpJNfY$~ zq&j}dZNLs>P2FAsJd*6*{3zsgd9~|Td(2F@!ja)&R=DnNDn0m2*?DpB1Qj@Tm$XOj zjf@4co;Pgd*=dgTY#Ugx;wy ze1iH!iZYHLYe)ZQO&oK90I>k`+LuLpfpd#G6QbvwhQL3@ri$?h%JVSYBjF?7N^j+F zc1$V$?Dv5y2*4sJHLMlaXYbu>W;aK>Xl4urU`Cyovp~bc}pt1%L zflD9fZshQ9)NxuKxvd?Ro=Lhtts4BByEje=6jq!8aOK2}Tr08hT=7QRPO#i%46P^o zmQL+I6^7II+P=2guGcAsmgf|ivQ4kQA(|k;;KGr>34@~FpYrwNnDgEdTK;6GB?6uf z$;j-HTQ^(U?baSZdz1P65YV8(nPBEEqCK3s&#a2q;nETc1Jgasm3P>@$>x|=$_P5ql zvi)HnnBkHnR`#eCQAW%Qi4qG|qfcEkJg8KR2OJj7q|#=mnF0$}wHdRRVy=z@y&8BVD*_Po3!GUOpG2mZqt<})5E~)A~dwqL;Sos zTHYRBb~ZZdyud-@@DVs-ucS;xKTuWOOd!5eqxo4$YRJ{5YNc(3zbe(_{NHx7{k3mq zaWkMfFSl(nHsbIy;!HvJul#u7kn>Khtx?(HXoru_ zV%Zr3>m7)2>BPr6LXJjh?CDxOSa``LQxVcK$=l}%9nm}VZh4zcjGy=b-!P^k*f!M} z>q0mzR+%e8?CA6)dGK-3j(nB#Ssz?Fa2d)q8C2C=rawB*<#cyFP|trYYNqpbAWWj9 zeeX?_K#9t6X>ddtr_&T_j~x)2C8D%OglH>CKa;H2ANp4IK;|c`PgR7%S|X9r_57oE zxg7UbREI^0q4Qs-Gv^hxu-OjeXUUn0a(jEsppPqyw+d==6hFC=+i8q++6Zw2zsT045wq2j$g91RG%huscG(_( zd`r+T`K!~_p8s-+BrBhR>$&in@RQ_28B^io>n(b&|K-V|VZZt@u+9fG742IstceYh z!XvPtJ5jMY<=q2%ujo%5Kj)HGh51YTgYZ1elOvww29+u{+6g#?kLM3YNC4Q`QhNcWH&kGBuzE%jta z@^!eVhc{)DLNBjkEcNuN>v~SMIi8LD6KKwaHFMt2hkgoe*cPPt&{zh7;TsO8z4#k z|1?pzZAhI>p4PujhSQAiEaOnZN}!}cHSZ(CYqw}OO<7Xa%Zcmf)$U6K3_&k?;Hk3p z20GI07eVe)`M7A`e2ho@9Ww_o#gp%RHx$M@TAs>tiX7c3*vgF%enDG)79QRYFzWHO zS_DC5mK@nTq<#y-swZh&G8>Bbk%-IrC%sHfIH2i;8uP0nO+k{^0WaD0h~pXDs^1SQ z(pCR$f{x3|_+2&Knq7~*3DSEBB1%(oS?b1=PF?J%m@7j3DB*ba(kSEUG@ACAbAKqH zrrwSdkTAOHvSfD#6y;6bEx!1XW@|ZKthSqkM;eCe@R2b^_Jp9=_>Z9VC2L}bCDV)i z@Dr8T`QRLY(|vIIOui>i>@(Ilu-#x2*U*y~`*+Y&)WzwF)4|R`66 zEYF#6Lw$KF%(YzXFOW$VZ&SM;%FOb|l#VtpJlbkcNyyaWvmxz^F?_wctnDH55O$^W zbH3MNGv2xgL1)y1p3bwE!8a}Z#=|OodQBa9G?XS1D_jCaHKZn3#JipyGW%-(Fg4T` zHJ>xU8_tv*u0_qGOKO`Sk~ZESdgRWzSF6O``3AA?3CZrtioRsyv|%yg8vAGJjFsZ1 z$UtnQ-D@uOz-yAeh@n#qI?IZ<4?i_tDO!GerV=xMsq3G#?pL$0RwoWH`zJEmN)`UD zqRzdlgiXNZY|2Yl$T~y^>-5^j-%!7{Q|F%=G=gW#@*H@^WD?^pw(O*361;wc-QRg$W3l5VcDjDqLXjL&3ADg zsAP-mxSrO`OaTsPqv7D$P&|?dX=$sAQ$&gKvsU8PDkwPiEKR&?9I?~N*oxa z2f%<^?6uBhkLG7_c2U-$gCp|OR?*Pll-hs^xq>WsFkZjT2s&f1G(#lA}K+wf^v^)bnXtJk&nK(0!yNW&qkJ8Q1(D+s;dO8URF_K zM{$IE{Bc101Y=dec(V(~|5THaq!twtx5>P{?rpl9rwWrDenqXRR91xW#furkb~ul= zZbZ8_)N;n`zSW6?$lbj)NA5CtYLtC6@M~m>;s|>cDU^~VgRBwONFCm$x{XdI>uQ4- zuNpWV*5N|vCbqSIKP+qGZEhYbayZwq;^azQj7KQtj77pXd}#lSI|SjDd^P3fW_gI+ zgYKnQ1y<0U$K|1UV&5OO^If_}$eZ~-Lu*`4?SDS}7-PduZM75rBAjX88s#Z398Aybq#}gbQI43gXQ@ zi@C5DY2h&YLf<0U{N_IslkAfv@Np0JFX<`KbK-kV?JZiJ7nu?}R(X3OHRHE-$3!_p zX`XHi?(z6Wd-=!&Gk2t1R&`UhmZ)sNIZXV4(f_0p1NPmaU+>^6g&K!$A=b0Wj(aXLmmp+;O@;o zWQ9F9YV8;~>%`&&ViA0!CVKMqD~r3~s}h#(9svuHy@Ma3((f)M7#6h-%lFHs^c(D>(i&o71VB&{-9QEzX;NubfJL$_?0q5|< zoT;6yNUPRb2D#m{~G0QEo-7 zZkTxHiY|&?YbQ~2s;=8R^nb+#LspatwJ{FIJk?*xcEftS^9^`s+ zeArLoWhnWz|LOULnd491*JItDFMN*&s>FFJw!A(PT1k9+_k-~LtaeQg^%1jv=QlxL z=XwsHHCDWvFTjIFaq4wIVK%qhsz${t_R*IlvTrJOh=~=xNDYaL&0t|oruR(mkDrMM z)G2h9ULos9Y~Pi$#t*$sy&G&dRj(LtidaAP>~VWtiViER?ip-%0KS$;EzUHNbWLMF z24$Us*)*t4tY@E>-3Oxb8Jmy?DsUMWLxuyjUK~3O)HH~ptvjo=H)Z*A!PdFxOoa7) zjcg8?KiJK@z+%ggzMy#>wjTnB?rC38uJ7(s zk*L+BFX;?K`nIG|V)sTp3e9oRXQ;UM-p49BFontWH(At`!4>K2EyZ ztSAQ9&b!oVP&0kI!l8_)i2QnM4pw)#$!Sad>VVZ}_QxL@_A(Br_wiRHPK^(>oy7Lr zqo{`o>ju?yi9lu_H4zCJchuoStv7nN530q}7(*vH6cO+b9M;?$6IkX*D5$*V5ak5F zdv)(cUCGFDitK%>z%MX!M#)OZjy>urzH*~rH@6U4U6q;4F}$|lz8uRq)h`o$CP`-y zF2|LlPTG_*vwKFT`SIK@ibKnn%aSCoDB?A(aj>OeO5ssPFWYn5NVYv-6s0lwSt(dFX&wL(T7A9&f_D zmS@-Y=dsPx`|bS*_td_Om%j+p_o8NGPcDnwEPXBOWnJg>CjQUL!~Kzf%E{;0Nl)nh^~)v3T`>nsd%gb&+KKy6`?f3y_V zteepB&kuQP?Q?>BgciH>G?s59V}CzB*X|u@+Dz`J^<%TW-BQ?Bty)-dZ_hI-PJPoThh=V62CxtQ4UI9Z>&?p>-j^eGlcJ4&60d5$M{ove z{pznQc74~|)EcGp%nTcOSmk`T1h3+%l=>_+eZeLS4EyZi1KqN@gprN3b2-G9Bzm6I z#8)eUt(r%RTg?8WkOeKN=MK2y0yXr{*O9TWng0;}4)h9@&TZ*%NK~cdif)JXQ}Xwo z(jO(9+j6O3g!1xeSJ|?uGhVOLKVlv}_xSfyz~xB4#(~DN75E9TR=>SbXmS*z2{!6d z9YkyZ>dUFrfs{t*N@C}`a(&=W1#*$|eL05`+4TWL+kajY^?Ne&A~lp67Y!HLI^V)W z(psU!K=dUq?ZvG}@#YAqWKrRhLN#Vu=7`eN3f|zj$>Bdny=#C-1K?d}@k*m-v|b|_ z&>Mj6?&4;o4D6XeR>mmbo$0MQX?)3+TH5pSkw?6-#@WDK^)zMV-X2ff$L5iGnkZxXYM^{!O3gIDkqgIQMMp>ZO0+7d3% zX;!FxLbtSG54l)fFMtsYB4iw7t$f9VNU^IU+Gt8Tax%Re2vZp=&FXw0uPQM5($j2+ z`V}$F2A@e4r1^)3_L#;S-7y9#uZwH%QtY)IXrC=$2xhG}Lku^789b_<0c3urtL08COe4s($+%;~+@rTb?Bs?<(_&ASZTRu0rXS*fgz975DzsY8*sAC~Q zFRmP}d^js|kh;+H^f9O`HDq-IrdN|`eO~D}aqmOQD1=RApw8(8OMb2WX196Jw940B zou8kS1 zI$7yQBX3d!Fepap=EM`$M)*W$F5CVE4>Wgii(&ug*!DK(&jyhKQ{B}da;Hc8m55+* z+Kq%-ezAL)rdZsQqj2G1)iHe9LL(4q$*4OC722ky^KTUHZ{%OvqauBMZ#w>)zXb?& z&8-eKdGTOommiDrx7j_+5&K>jo_Mn)@nZk6N@`!R(jw$Zcyn?eP*QofG*oe7;C1wo z8@hf;`9q0|33j`%Q2FzgEhd=-8iDsGm<#xQZ)sJ9m2d2*@2QaklI3b-@A=Q1C8+An z>eoU!>nQ;eaqv_go>?rEnq=x-TOFJx$uO-sdFobhN=2|lYp(F2$#%f$XT_E(0ODq~ zaRke*69VcG&Xwn6fxWgwz>Ql~THo%GDad+p@gkXNxJ^L7!>x>F;UWKf;c@#uezSL6 zNr-slrd{~gsGM@|`44xk>EJFP^#yIk3~l59mB~>!v)Nz7G0@ObQ4q?vQSecV^F2S~E9omkyEI^vg5GSGkI=%FrTSVOs z{tc}*8(MBP78ea_#6)WPS=i3CmJB1{@6|^ni|~EN`;t}3spR?zp$BS zF{ygxv^r*;G&vl@p!lPv?SuXXnV+V?c5B>9>S&29OHpzs^)HHO62On?6E~lnH-NQs zN7P;tLrY)1jsIO5Bc>E?kw|mEGGNV826F2+sY*THwiCD7bvdFn@<#rhhH!aAS)mpA zF%`ROXXkkz_y5v4$oLj^Gk)HpcDB@xS2gh@@?wC7?8zRz-vQqm zQg#`n^`MW`*NZ1_(id!z)~id%%F{MUym-MWCF8~FJ;HQjP6lS<)*`Jm$4(Z2z}rO$S43$rp=$er&O@M3fG>3rEs3_Bq&M0%c(ByMq%Y9z(p>nF1o z)AjUbrUP}acUR#5eP22^c;=s@_h*mk_dR~`>go6BBa${hoEG9%{et5&;(vkHgpBh! zrkTcJiob@CikA%h&)=Zc6{wBH0>b2ZcRfz89mU{xCfhJE&Dz6r5!0~8-+EQd_>6BM zN5iOI39={6oF?@GfBl})?9dkhsL{?uIVGTXK&49{v|C#DVxp)Q?J>9wHomDX_b)*1 z5&u}J?71>6uC2H4yCOQ?pY^G^K9z(m>MK>4#KJNyQ_uW+J>4T*2sIlQ^scXEzq;YD zNSf@C&DIqGZ#Yhf(<(Z`>u5XB;bLbykB}El1{SK9-zF1hX2MxErAz?kZ&NccK>RLk zviqugHL^VD2sXUEW!LP&w6xWATMo2jm5771$fa3v_JgW2%7Ml*WTXJW%+?Z#x##9{ zHUl7kz)k0R#vDW* zbQD%V71~e6G}7ypES7YCoE{p|%EsShJ!!uAZH4QG@r=^ev?#~5hk*TirfFf<67?Lo z`^FSNq+dzf`A$A}318tifYm3iD%Hk!ACGd+5=M_CA~7btEs;tka7|g;zG4pA?BxU| zh-N4X&HB7<;8$q(l&*jUvd-6|aA6f)mO?6K;C)jwht9e9j}UXR_w965!XKJ>iyF|p zocb$yhS@Ftd!#)ny2crsh<{Pd^EdOtgTM78i6G&*7;@qZt6d!mLDI&@*u|!N6CqRA%Wx| zZj)XHs4gk#KJp^sRA0yG4ejwUjt(Zh!wm_yd#=OWHV!uf0(cgCuW#1jq*IIPNHnf1 zCc&lh^hC=#ncAE6a9ii=9PY@6za5#Sw-85f)l$*7>k_V4#db5wF12km5 zlBQ{{y^K&mf!cCk#)W>rzV@fOM|#6oigk0NME{r*8XPEFZ zc)#UTYJRW2B=~%Ir^^1u(%D?vNAl4`UsA+NYpj6CMMSb?v%|$R+2(VD`l!alB&}xE zKjD3q?MHtcgwHoTIX~coIq8^Z{7x$2VEkP*F3!*sN?@;NQfl~@aku@c)ZRqLl9Niz z#Q|^+xUt=Q{{GVr3Y`m!2YKcBM@$Co&EZwurd)&PzjeMPZWbJc=mL*es`W3%6A{ii z9ED18r-nuECAV7|jwON2Vn0Z5+;BEB_I@o+?#yltDu)gkbBt}?Q%+Iac?F3Ij%KFIGhJiA?D7uP2j~4B94c z+MR!CaIV{I`5-NLLiSb@e;whhzr6|$J_{3KS8sboze3B%Mo2em@-byYkfg-PBW+xz ziA7(w#fXf|=Kz{#4(wU>A&UP)P~`QA#H2ujY#y!0-ifiPR_D;jA-^3;&BSh#R~0Nx zr#i(ZQ!zhp1FM3t06gB=uHZ|V4oluV$~tM>I`){qWg17=2zFncZY<^Q-C3?lr7r1n zNOWx8b%kUAv92&OVAUrvJmHDAL+j0crM*90!8Y4dCGanqDOONqZK2rjxoGDajcwlg zc6v*khx+4MxQ)A%=T~m#t1>avD*-^Byc}|gcbbrm67-8C~rhOAF?GVXdloJbUshte{uuHS8lsutc*u;*@3(g&f&s%#G+xjJ_#~@L#&4 zd6bZkrV>!p3ack!hu)<9;-c734_>Qo)qPF5(Xjc-?b_jQh!np~9rn9e^!WGl7Vc4i zRA)<6SOI1~bSh*bzt}K)f;qqZ{jljfoq?z_nL48(53W@ld6}P!BAcY=6C(mE9XRI3vZj5<$(i+_WM#rry^&PGpHu%m|%2JRG8sR8V{21Z@joQNHZC zh}y}e-zc<$`@!jlLd>8N6~(`{JGF5ut@&PO^KH4nY4s&!S(#FlDZ`RlCWcp%&fQ)w zTFerYTQ;m+$#$Sc0SI7A?CL9C#?dOMI#ai;cC6$nRW+885z8{M_cf<|~+=my!BUlK^73S_r$8RW5 zI#;ioN!w8~QZncAtHRT`ya%1JF{@euz}lSoT^jqj?r;#fH>6Wv>8%Rb*`(Xz` zhwk8PQde98V;|w#gKhjW({T`bK>I4b*J?dmDa4aTto08Y@SC5O z^`&!0FO8yBC@coM0+e5>%>Aw&em6Fgr@&EFF9i>T;l@2|$1Yv5y?@Mn1(488+F`s^LHB95xCz`5usMb5T80{-QD4HeG@b>qmQ5S(M=VE z09l|nF=wM_CM|kiC8B2rp?~}nzRQrx2E%nGayFLT*hb^x$_M$iDjp1hd}(88Rm6ko z%=E4M*q|8O0v+~fFWI;-jX+l~C-7~JrckK969lA7ERH#xa~ctTus9)`-DYrOoIm3T z_WeuM71IlTog|gkIHv=EH|p;*uxz)Un=1C5u=me&Po$ndR(NxZUhV`&1$+5t`#4 zddaPjbZ9X#)vIVf^aY~f(tgA!t<9%zT1<50_kryLIfVQ=M$5}E^=(O&v31_R9)is+c^Pxl7>*OM!F+2eCpdAEnFWSfu^xN=`!Dlai# zs60QS7nHK%Y22%jFk8dr+9rC$(6A2WnjD~_^W!rUEZH`KKSmgs=e<3!(mbTm%t3&Tz9Is+zs!ISzLwPO z9qkRH^#vkZmSJ6Otw_s=>O<>^y|roxzGnb%F7g3JZRlQQnd?{`={PgMVmG8VEMn&ra|-RCEoTj|#P-6`p35$iGa;o)WY_1HM-s8kntuE42}4zU zbsi`40{F7|jAq?##^}oKGQ=eyPW~k4=m8f{=RX^xv=(kgCHOe!Y18!7D$gY{^sTQ; z5X%|dheeI~!{ZG>tIKv-A?!)=X2}p-b%6QyMIgg%m;+`s!=vW=I>Yt7?|4w%KC&&6vCe%HWdjPMZ%q=?JLeMhO zs=N%>Y>Z*}sB3>jnzBNcR8dicuNYrJaMiU?l!cBq`fUxmcAp{W1ie=gZ6-Nh?X`t; z4#6EDL>l>V@$HO!O`iwKn$4jve~f$=IU%+mk5?Y!H{ZnVweyT@&?hs4JOb30si8xm zU1Pr9kA?!u`GSe6Z-?i%GHU3Le>zn}S(4ZkdmfIwDQCGiC!#3S>#P|Mr*hM^Jqf8~ z`Rdbft7mWg3s3Jiv7uJ5nFQ_j?D7%s{gbt$O6|%Eu%4MdyOWf7|?BDL&ZWOW2*`i5vPiXGD}m zG)Iio&tgk|&ou=H5-k;6>gw~=mt}7O4!pA~674==Gy{YJV_Sj(W5Pv52utx&zwMQl z*6&#HWhw^1-r_|{Z8x5*uPf)EMMV67u@alZp(ryU7;v_HbCq7>S{nPPesDwfkA1sn z@A!e&eyOy{fg7zR&L%I6H1k{~&My`siP{%kPFUT?mCn%^KFgjxH!!Dw8v_?;75zA$ zlQ$m}tFPRr4XWI;oZ7i5zUQ+01J^EBxZDWL9I3O)+0+rlTtDJgjvFGb5I?{tDAL_? zRx6oQjj!5bo2T zQBfpwK}DpgNpnQVOv_ZL$SeWP5SJ8~%ES~UHCGf$0xSeZ5f@Oneg1~$-0z;(zjMAX zelM=;dtKK#-_JHetgy#i!d`zgT3c1Qn1XdJ zfXqD|u*gV!i}g(q72Bd#EktFEN(b%aZM`cQ3qeqB0B{q|vYl<6DpQReP`P40PU=Gm zym(-2W*f1b?2@N<_tF*5nAfxuHM0hHC9z>gqKV*G5M^|2yyF|yqYk;?H#242Z@ysn z%5p!9`Otpo)Q^2R2cM267l^9X_`a4g@Nxu3bjeF+Zp(c-lEQ#8^RM8sA~XIGy$G8N zJcvlLGQ}S$N!{eGGZ2csa^w7f#qf-qXbE<)QMc@PG6>`ggIoj}*m%vFVO1#7ORkZl zoqAR(mfqslWVqE~(W=6rbz>WpqXnEj(eUlrX&d3gn}^s%h=to%N4CKwff!f>^7Sd$ z&ggh@89dh|N>#*I^|iLMsgf7QM6C62>#8Z%!Iq$JJ;pa%OCN99;`nxPUn5qkqZ})r zz&M^T;~wZ(vOf~;GCw)Us8zFnfG&1IM3a%XABFm^QoX#fagLcTnyo%LzD?WfgY^zf z@1f+wmypK~{W^#3wnrrR{5=2>ZTz||fIX+KD}HO`SI_sO$|DpGgfun0+3)^3Q9b1* zY47=#A2Uc9%iFk_VV6uoJbxjUe-PXl@3G&Gf)WB{U~s^OG+B}qSlCm|N=kg`jHiI& zcb$CJU`(?fQ|5N$ttJ?!E*QAqA+3{i1J`?;i{u!43)FW)P|}U3Wtb=e1iITaJQUNX z`nmqcbkn{n))~H_hvDEGYv|qZu-s)mj3|cEdVPV!;W`f?ag@z|b=$SjCmEa-57R4E8|E*jAje6)j{m>~u zy|Z#H^QR?!y03S`VI(>(hkP$vjbeC2PPXc=XedsEEE`UKF1_P^RBb4Ql(^C=NraKa zZE|7_bDqZrcQtNk1AM01yev>&OQl1siHzsWCf?i$Tf1Ji6>fIXBA|j*Y6#4J2>lyn- zSbiR^v!EACue;CVJ9S332<5lhQ8R!h^m)iJGUFhIw~ybMT#_9|)B>=xW~bn>qSNbT z50Q%Z+WD%26<(L#uup5E!B#VZ2E{Ion^6jlxgj`&clMtFhcHav!^8!VQ;&gEF=L`U ztqwJ;b}r-kf%G{EKlzSYeR;>S>zo|7P|I1AnBrDtQMG?SElnQJ&M>AKA-|ma6RWtn zSb@FOkw0Z>&s1HVt!(O~3GzkAp@fB){#58&xANaw@^U97A%)8KeKGaTXTp9m53$h2 zDwGc*j$nfB7Z6UgSw*uAD`Vb}$g1}6oPel8-X(kC-p`-aRpuwE(4q883eDef!D^S6 z_q^7pUKzF;ePzj3p(cj%@B`314)o#6)7r12$FL=Lu^q2Ut}r_k?X1TTbZ5rV?$97h zj@b!9*>tzo+E(X{^tY-^Dtlws?GQF&*_~#1BNu0e&|v;nPT-z8O6~wj88Iy=dVd2#7yNS+}KW6gh{IKOync~eA{d&_ZU56i^Of`-FFpXElfey z&eq`Lki3l zC81o^6VOhQo^E-RX$*@4JI$d!F9&7F-rZx0oaAO}`r0A- zB+Q9IYrdEql0vPHXOHvD=LWmCA1GN9^7{{_9l9)S{n;zlQHMUzW|~kgp=9?9__|BX zAJ9mnesD@|;p@w^j7Yl~u3YkQ9*u9Hw1@+OJCrf=EZR$OH8VYBD{NySy=HkO!NMy> z)G!R2W_D@I>lEQ_i+j^+C^bl{2GK+;flt-)RsarV6QgrV@nWm9sChilY8kYsOwH@Z zkn4>u0E(&!d6O=|d*ACH^#!+K$`moDH;!eKu+Almrx5b);62kk;}OThB`pK8t}qTh zCU))gtKW34MbY?Fz}f!f&Q+1DI=-;EqscXXov8zT*$njH6t~4r9;&pMVC-BdI?8%a z#(r_~Uz&PthMTs32IJg1b#h}`?MziIN%6RgvOH!#Km@G}m=a8-S@>wAqk7hdT(cNQ zKBWxB7q=$;N!|KM9T=6uz^3HEwh=6pWRCE5r47mp-_pmD&7DotNcio8oDTi@uLNoi zS~o@xqd2|#ed9toPmskZcqKDkoo_aNJ-^wf95*}zKSO71Fp(&x$2 z8e-Sp-N9s3%-F4*2^3VVZ7g*~pi_g~5I3IJELrY?m46&qi}&A$N^;lX!k;YHhoCP+ ztoKB)O($$}c$pg$c>MTLj}Y1BNl3{0HFK)OdVOp5hppPndL=%IWcs~V(HRJFF;1gRE>M`l;ecrdL|R`(w$YR6XO=cx7M}k& zp9L0i@1#9@pPEc}q?3K#AGenkIPEJQpypkmcg+ln+GUR-^6AD?fs9%z1vNWQy+d0Z z2PB}bwp;}u&9l3^pugu@y8h5F(7gdQTUW~E-RlLKAF^(G*nw*t=a+Lg8qVoI$pa1l zK*bz`)=Q*o2O9s^7$|1{HRb;o{=fc!0cF^NfBosxiwWS#|J6F<>F-hh>*eeJ0Z~IJ AyZ`_I literal 0 HcmV?d00001 diff --git a/.github/logo.png b/.github/logo.png deleted file mode 100644 index 18bac95080859922223d82aac99703971011c5ca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8000 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 Gzx^kVX6^<6 diff --git a/README.md b/README.md index a51f9c538..b9726864a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,8 @@ -![logo](.github/logo.png) + + + + logo + Useful tools for developer and people working in IT. [Have a look !](https://it-tools.tech). From f5c4ab19bc10ea468a453a1460b1de2d7ccab87b Mon Sep 17 00:00:00 2001 From: sharevb Date: Fri, 20 Sep 2024 20:39:40 +0200 Subject: [PATCH 03/16] feat(new tool): Regex Tester (and Cheatsheet) (#1030) * feat(new tool): Regex Tester Fix https://github.com/CorentinTh/it-tools/issues/1007, https://github.com/CorentinTh/it-tools/issues/991, https://github.com/CorentinTh/it-tools/issues/936, https://github.com/CorentinTh/it-tools/issues/761, https://github.com/CorentinTh/it-tools/issues/649 https://github.com/CorentinTh/it-tools/issues/644, https://github.com/CorentinTh/it-tools/issues/554 https://github.com/CorentinTh/it-tools/issues/308 * fix: refactor to service + add regex diagram + ui enhancements * fix: update queryParams * fix: deps * fix: svg style bug in @regexper/render @regexper/render use a stylesheet in svg that cause bugs in whole site. So add regexper in a shadow root * feat(new tool): added Regex Cheatsheet * Update src/tools/regex-memo/index.ts * Update src/tools/regex-tester/index.ts --------- Co-authored-by: Corentin THOMASSET --- components.d.ts | 15 +- package.json | 5 +- pnpm-lock.yaml | 46 +++++ src/composable/queryParams.ts | 33 ++- src/composable/validation.ts | 19 +- src/main.ts | 2 + src/tools/index.ts | 4 + src/tools/regex-memo/index.ts | 12 ++ src/tools/regex-memo/regex-memo.content.md | 121 +++++++++++ src/tools/regex-memo/regex-memo.vue | 32 +++ src/tools/regex-tester/index.ts | 12 ++ .../regex-tester/regex-tester.service.test.ts | 106 ++++++++++ .../regex-tester/regex-tester.service.ts | 61 ++++++ src/tools/regex-tester/regex-tester.vue | 193 ++++++++++++++++++ 14 files changed, 650 insertions(+), 11 deletions(-) create mode 100644 src/tools/regex-memo/index.ts create mode 100644 src/tools/regex-memo/regex-memo.content.md create mode 100644 src/tools/regex-memo/regex-memo.vue create mode 100644 src/tools/regex-tester/index.ts create mode 100644 src/tools/regex-tester/regex-tester.service.test.ts create mode 100644 src/tools/regex-tester/regex-tester.service.ts create mode 100644 src/tools/regex-tester/regex-tester.vue diff --git a/components.d.ts b/components.d.ts index 8e59366ab..3e65c3cc5 100644 --- a/components.d.ts +++ b/components.d.ts @@ -130,23 +130,19 @@ declare module '@vue/runtime-core' { MetaTagGenerator: typeof import('./src/tools/meta-tag-generator/meta-tag-generator.vue')['default'] MimeTypes: typeof import('./src/tools/mime-types/mime-types.vue')['default'] NavbarButtons: typeof import('./src/components/NavbarButtons.vue')['default'] - NButton: typeof import('naive-ui')['NButton'] - NCode: typeof import('naive-ui')['NCode'] + NCheckbox: typeof import('naive-ui')['NCheckbox'] NCollapseTransition: typeof import('naive-ui')['NCollapseTransition'] NConfigProvider: typeof import('naive-ui')['NConfigProvider'] + NDivider: typeof import('naive-ui')['NDivider'] NEllipsis: typeof import('naive-ui')['NEllipsis'] - NForm: typeof import('naive-ui')['NForm'] - NFormItem: typeof import('naive-ui')['NFormItem'] NH1: typeof import('naive-ui')['NH1'] NH3: typeof import('naive-ui')['NH3'] NIcon: typeof import('naive-ui')['NIcon'] - NInputNumber: typeof import('naive-ui')['NInputNumber'] NLayout: typeof import('naive-ui')['NLayout'] NLayoutSider: typeof import('naive-ui')['NLayoutSider'] NMenu: typeof import('naive-ui')['NMenu'] - NScrollbar: typeof import('naive-ui')['NScrollbar'] - NSlider: typeof import('naive-ui')['NSlider'] - NSwitch: typeof import('naive-ui')['NSwitch'] + NSpace: typeof import('naive-ui')['NSpace'] + NTable: typeof import('naive-ui')['NTable'] NumeronymGenerator: typeof import('./src/tools/numeronym-generator/numeronym-generator.vue')['default'] OtpCodeGeneratorAndValidator: typeof import('./src/tools/otp-code-generator-and-validator/otp-code-generator-and-validator.vue')['default'] PasswordStrengthAnalyser: typeof import('./src/tools/password-strength-analyser/password-strength-analyser.vue')['default'] @@ -156,6 +152,9 @@ declare module '@vue/runtime-core' { PhoneParserAndFormatter: typeof import('./src/tools/phone-parser-and-formatter/phone-parser-and-formatter.vue')['default'] QrCodeGenerator: typeof import('./src/tools/qr-code-generator/qr-code-generator.vue')['default'] RandomPortGenerator: typeof import('./src/tools/random-port-generator/random-port-generator.vue')['default'] + RegexMemo: typeof import('./src/tools/regex-memo/regex-memo.vue')['default'] + 'RegexMemo.content': typeof import('./src/tools/regex-memo/regex-memo.content.md')['default'] + RegexTester: typeof import('./src/tools/regex-tester/regex-tester.vue')['default'] ResultRow: typeof import('./src/tools/ipv4-range-expander/result-row.vue')['default'] RomanNumeralConverter: typeof import('./src/tools/roman-numeral-converter/roman-numeral-converter.vue')['default'] RouterLink: typeof import('vue-router')['RouterLink'] diff --git a/package.json b/package.json index 63e5856a5..f5dedc0c6 100644 --- a/package.json +++ b/package.json @@ -37,12 +37,13 @@ "dependencies": { "@it-tools/bip39": "^0.0.4", "@it-tools/oggen": "^1.3.0", + "@regexper/render": "^1.0.0", "@sindresorhus/slugify": "^2.2.1", "@tiptap/pm": "2.1.6", "@tiptap/starter-kit": "2.1.6", "@tiptap/vue-3": "2.0.3", - "@types/markdown-it": "^13.0.7", "@types/figlet": "^1.5.8", + "@types/markdown-it": "^13.0.7", "@vicons/material": "^0.12.0", "@vicons/tabler": "^0.12.0", "@vueuse/core": "^10.3.0", @@ -84,6 +85,7 @@ "pinia": "^2.0.34", "plausible-tracker": "^0.3.8", "qrcode": "^1.5.1", + "randexp": "^0.5.3", "sql-formatter": "^13.0.0", "ua-parser-js": "^1.0.35", "ulid": "^2.3.0", @@ -93,6 +95,7 @@ "vue": "^3.3.4", "vue-i18n": "^9.9.1", "vue-router": "^4.1.6", + "vue-shadow-dom": "^4.2.0", "vue-tsc": "^1.8.1", "xml-formatter": "^3.3.2", "xml-js": "^1.6.11", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2311f3aff..e43a3217e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,6 +11,9 @@ dependencies: '@it-tools/oggen': specifier: ^1.3.0 version: 1.3.0 + '@regexper/render': + specifier: ^1.0.0 + version: 1.0.0 '@sindresorhus/slugify': specifier: ^2.2.1 version: 2.2.1 @@ -152,6 +155,9 @@ dependencies: qrcode: specifier: ^1.5.1 version: 1.5.1 + randexp: + specifier: ^0.5.3 + version: 0.5.3 sql-formatter: specifier: ^13.0.0 version: 13.0.0 @@ -179,6 +185,9 @@ dependencies: vue-router: specifier: ^4.1.6 version: 4.1.6(vue@3.3.4) + vue-shadow-dom: + specifier: ^4.2.0 + version: 4.2.0 vue-tsc: specifier: ^1.8.1 version: 1.8.1(typescript@5.2.2) @@ -2480,6 +2489,17 @@ packages: resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} dev: false + /@regexper/parser@1.0.0: + resolution: {integrity: sha512-S8AWIGpCNdl9PNHdbhI6TpXZsPk6FDU/RTZI+6UFF4rVFqDQKjCIbZSgFu7NihoEZKq57wKFPbbT1EzrjVvPHA==} + dev: false + + /@regexper/render@1.0.0: + resolution: {integrity: sha512-xYm9RUgnhhZotTtf8UZpK1PG2CcTRXQ3JPwfTlYUZsy2J+UcTVc7BaO/MJadpMoVuT8jrIyptH4Y0HLzqhI3hQ==} + dependencies: + '@regexper/parser': 1.0.0 + '@svgdotjs/svg.js': 3.2.4 + dev: false + /@remirror/core-constants@2.0.1: resolution: {integrity: sha512-ZR4aihtnnT9lMbhh5DEbsriJRlukRXmLZe7HmM+6ufJNNUDoazc75UX26xbgQlNUqgAqMcUdGFAnPc1JwgAdLQ==} dependencies: @@ -2629,6 +2649,10 @@ packages: string.prototype.matchall: 4.0.10 dev: true + /@svgdotjs/svg.js@3.2.4: + resolution: {integrity: sha512-BjJ/7vWNowlX3Z8O4ywT58DqbNRyYlkk6Yz/D13aB7hGmfQTvGX4Tkgtm/ApYlu9M7lCQi15xUEidqMUmdMYwg==} + dev: false + /@tiptap/core@2.1.12(@tiptap/pm@2.1.6): resolution: {integrity: sha512-ZGc3xrBJA9KY8kln5AYTj8y+GDrKxi7u95xIl2eccrqTY5CQeRu6HRNM1yT4mAjuSaG9jmazyjGRlQuhyxCKxQ==} peerDependencies: @@ -4962,6 +4986,11 @@ packages: tslib: 2.5.0 dev: false + /drange@1.1.1: + resolution: {integrity: sha512-pYxfDYpued//QpnLIm4Avk7rsNtAtQkUES2cwAYSvD/wd2pKD71gN2Ebj3e7klzXwjocvE8c5vx/1fxwpqmSxA==} + engines: {node: '>=4'} + dev: false + /duplexer@0.1.2: resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} dev: true @@ -7758,6 +7787,14 @@ packages: ret: 0.1.15 dev: false + /randexp@0.5.3: + resolution: {integrity: sha512-U+5l2KrcMNOUPYvazA3h5ekF80FHTUG+87SEAmHZmolh1M+i/WyTCxVzmi+tidIa1tM4BSe8g2Y/D3loWDjj+w==} + engines: {node: '>=4'} + dependencies: + drange: 1.1.1 + ret: 0.2.2 + dev: false + /randombytes@2.1.0: resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} dependencies: @@ -7928,6 +7965,11 @@ packages: engines: {node: '>=0.12'} dev: false + /ret@0.2.2: + resolution: {integrity: sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==} + engines: {node: '>=4'} + dev: false + /reusify@1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} @@ -9268,6 +9310,10 @@ packages: vue: 3.3.4 dev: false + /vue-shadow-dom@4.2.0: + resolution: {integrity: sha512-lguI064rT2HT/dxqSmXtz860KOvCq+W3nU1jMqroTmX3K1H46q22BMR4emh/Ld3ozy35XJKOaNGcr6mkJ/t/yg==} + dev: false + /vue-template-compiler@2.7.14: resolution: {integrity: sha512-zyA5Y3ArvVG0NacJDkkzJuPQDF8RFeRlzV2vLeSnhSpieO6LK2OVbdLPi5MPPs09Ii+gMO8nY4S3iKQxBxDmWQ==} dependencies: diff --git a/src/composable/queryParams.ts b/src/composable/queryParams.ts index 9699abbc1..7cc8cc0dd 100644 --- a/src/composable/queryParams.ts +++ b/src/composable/queryParams.ts @@ -1,7 +1,8 @@ import { useRouteQuery } from '@vueuse/router'; import { computed } from 'vue'; +import { useStorage } from '@vueuse/core'; -export { useQueryParam }; +export { useQueryParam, useQueryParamOrStorage }; const transformers = { number: { @@ -16,6 +17,12 @@ const transformers = { fromQuery: (value: string) => value.toLowerCase() === 'true', toQuery: (value: boolean) => (value ? 'true' : 'false'), }, + object: { + fromQuery: (value: string) => { + return JSON.parse(value); + }, + toQuery: (value: object) => JSON.stringify(value), + }, }; function useQueryParam({ name, defaultValue }: { name: string; defaultValue: T }) { @@ -33,3 +40,27 @@ function useQueryParam({ name, defaultValue }: { name: string; defaultValue: }, }); } + +function useQueryParamOrStorage({ name, storageName, defaultValue }: { name: string; storageName: string; defaultValue: T }) { + const type = typeof defaultValue; + const transformer = transformers[type as keyof typeof transformers] ?? transformers.string; + + const storageRef = useStorage(storageName, defaultValue); + const proxyDefaultValue = transformer.toQuery(defaultValue as never); + const proxy = useRouteQuery(name, proxyDefaultValue); + + const r = ref(defaultValue); + + watch(r, + (value) => { + proxy.value = transformer.toQuery(value as never); + storageRef.value = value as never; + }, + { deep: true }); + + r.value = (proxy.value && proxy.value !== proxyDefaultValue + ? transformer.fromQuery(proxy.value) as unknown as T + : storageRef.value as T) as never; + + return r; +} diff --git a/src/composable/validation.ts b/src/composable/validation.ts index 472ca4b21..33a6a7b2e 100644 --- a/src/composable/validation.ts +++ b/src/composable/validation.ts @@ -3,9 +3,11 @@ import _ from 'lodash'; import { type Ref, reactive, watch } from 'vue'; type ValidatorReturnType = unknown; +type GetErrorMessageReturnType = string; export interface UseValidationRule { validator: (value: T) => ValidatorReturnType + getErrorMessage?: (value: T) => GetErrorMessageReturnType message: string } @@ -24,6 +26,15 @@ export function isFalsyOrHasThrown(cb: () => ValidatorReturnType): boolean { } } +export function getErrorMessageOrThrown(cb: () => GetErrorMessageReturnType): string { + try { + return cb() || ''; + } + catch (e: any) { + return e.toString(); + } +} + export interface ValidationAttrs { feedback: string validationStatus: string | undefined @@ -61,7 +72,13 @@ export function useValidation({ for (const rule of get(rules)) { if (isFalsyOrHasThrown(() => rule.validator(source.value))) { - state.message = rule.message; + if (rule.getErrorMessage) { + const getErrorMessage = rule.getErrorMessage; + state.message = rule.message.replace('{0}', getErrorMessageOrThrown(() => getErrorMessage(source.value))); + } + else { + state.message = rule.message; + } state.status = 'error'; } } diff --git a/src/main.ts b/src/main.ts index 36ba3b7f8..19d28bf2e 100644 --- a/src/main.ts +++ b/src/main.ts @@ -3,6 +3,7 @@ import { createPinia } from 'pinia'; import { createHead } from '@vueuse/head'; import { registerSW } from 'virtual:pwa-register'; +import shadow from 'vue-shadow-dom'; import { plausible } from './plugins/plausible.plugin'; import 'virtual:uno.css'; @@ -23,5 +24,6 @@ app.use(i18nPlugin); app.use(router); app.use(naive); app.use(plausible); +app.use(shadow); app.mount('#app'); diff --git a/src/tools/index.ts b/src/tools/index.ts index c9003fe81..388cfaf49 100644 --- a/src/tools/index.ts +++ b/src/tools/index.ts @@ -9,6 +9,8 @@ import { tool as textToUnicode } from './text-to-unicode'; import { tool as safelinkDecoder } from './safelink-decoder'; import { tool as xmlToJson } from './xml-to-json'; import { tool as jsonToXml } from './json-to-xml'; +import { tool as regexTester } from './regex-tester'; +import { tool as regexMemo } from './regex-memo'; import { tool as markdownToHtml } from './markdown-to-html'; import { tool as pdfSignatureChecker } from './pdf-signature-checker'; import { tool as numeronymGenerator } from './numeronym-generator'; @@ -156,6 +158,8 @@ export const toolsByCategory: ToolCategory[] = [ xmlFormatter, yamlViewer, emailNormalizer, + regexTester, + regexMemo, ], }, { diff --git a/src/tools/regex-memo/index.ts b/src/tools/regex-memo/index.ts new file mode 100644 index 000000000..f1f56489d --- /dev/null +++ b/src/tools/regex-memo/index.ts @@ -0,0 +1,12 @@ +import { BrandJavascript } from '@vicons/tabler'; +import { defineTool } from '../tool'; + +export const tool = defineTool({ + name: 'Regex cheatsheet', + path: '/regex-memo', + description: 'Javascript Regex/Regular Expression cheatsheet', + keywords: ['regex', 'regular', 'expression', 'javascript', 'memo', 'cheatsheet'], + component: () => import('./regex-memo.vue'), + icon: BrandJavascript, + createdAt: new Date('2024-09-20'), +}); diff --git a/src/tools/regex-memo/regex-memo.content.md b/src/tools/regex-memo/regex-memo.content.md new file mode 100644 index 000000000..0f779401b --- /dev/null +++ b/src/tools/regex-memo/regex-memo.content.md @@ -0,0 +1,121 @@ +### Normal characters + +Expression | Description +:--|:-- +`.` or `[^\n\r]` | any character *excluding* a newline or carriage return +`[A-Za-z]` | alphabet +`[a-z]` | lowercase alphabet +`[A-Z]` | uppercase alphabet +`\d` or `[0-9]` | digit +`\D` or `[^0-9]` | non-digit +`_` | underscore +`\w` or `[A-Za-z0-9_]` | alphabet, digit or underscore +`\W` or `[^A-Za-z0-9_]` | inverse of `\w` +`\S` | inverse of `\s` + +### Whitespace characters + +Expression | Description +:--|:-- +` ` | space +`\t` | tab +`\n` | newline +`\r` | carriage return +`\s` | space, tab, newline or carriage return + +### Character set + +Expression | Description +:--|:-- +`[xyz]` | either `x`, `y` or `z` +`[^xyz]` | neither `x`, `y` nor `z` +`[1-3]` | either `1`, `2` or `3` +`[^1-3]` | neither `1`, `2` nor `3` + +- Think of a character set as an `OR` operation on the single characters that are enclosed between the square brackets. +- Use `^` after the opening `[` to “negate” the character set. +- Within a character set, `.` means a literal period. + +### Characters that require escaping + +#### Outside a character set + +Expression | Description +:--|:-- +`\.` | period +`\^` | caret +`\$` | dollar sign +`\|` | pipe +`\\` | back slash +`\/` | forward slash +`\(` | opening bracket +`\)` | closing bracket +`\[` | opening square bracket +`\]` | closing square bracket +`\{` | opening curly bracket +`\}` | closing curly bracket + +#### Inside a character set + +Expression | Description +:--|:-- +`\\` | back slash +`\]` | closing square bracket + +- A `^` must be escaped only if it occurs immediately after the opening `[` of the character set. +- A `-` must be escaped only if it occurs between two alphabets or two digits. + +### Quantifiers + +Expression | Description +:--|:-- +`{2}` | exactly 2 +`{2,}` | at least 2 +`{2,7}` | at least 2 but no more than 7 +`*` | 0 or more +`+` | 1 or more +`?` | exactly 0 or 1 + +- The quantifier goes *after* the expression to be quantified. + +### Boundaries + +Expression | Description +:--|:-- +`^` | start of string +`$` | end of string +`\b` | word boundary + +- How word boundary matching works: + - At the beginning of the string if the first character is `\w`. + - Between two adjacent characters within the string, if the first character is `\w` and the second character is `\W`. + - At the end of the string if the last character is `\w`. + +### Matching + +Expression | Description +:--|:-- +`foo\|bar` | match either `foo` or `bar` +`foo(?=bar)` | match `foo` if it’s before `bar` +`foo(?!bar)` | match `foo` if it’s *not* before `bar` +`(?<=bar)foo` | match `foo` if it’s after `bar` +`(? +import { useThemeVars } from 'naive-ui'; +import Memo from './regex-memo.content.md'; + +const themeVars = useThemeVars(); + + + + + diff --git a/src/tools/regex-tester/index.ts b/src/tools/regex-tester/index.ts new file mode 100644 index 000000000..9cc542f0e --- /dev/null +++ b/src/tools/regex-tester/index.ts @@ -0,0 +1,12 @@ +import { Language } from '@vicons/tabler'; +import { defineTool } from '../tool'; + +export const tool = defineTool({ + name: 'Regex Tester', + path: '/regex-tester', + description: 'Regex Tester', + keywords: ['regex', 'tester', 'sample', 'expression'], + component: () => import('./regex-tester.vue'), + icon: Language, + createdAt: new Date('2024-09-20'), +}); diff --git a/src/tools/regex-tester/regex-tester.service.test.ts b/src/tools/regex-tester/regex-tester.service.test.ts new file mode 100644 index 000000000..bd4efbbc8 --- /dev/null +++ b/src/tools/regex-tester/regex-tester.service.test.ts @@ -0,0 +1,106 @@ +import { describe, expect, it } from 'vitest'; +import { matchRegex } from './regex-tester.service'; + +const regexesData = [ + { + regex: '', + text: '', + flags: '', + result: [], + }, + { + regex: '.*', + text: '', + flags: '', + result: [], + }, + { + regex: '', + text: 'aaa', + flags: '', + result: [], + }, + { + regex: 'a', + text: 'baaa', + flags: '', + result: [ + { + captures: [], + groups: [], + index: 1, + value: 'a', + }, + ], + }, + { + regex: '(.)(?r)', + text: 'azertyr', + flags: 'g', + result: [ + { + captures: [ + { + end: 3, + name: '1', + start: 2, + value: 'e', + }, + { + end: 4, + name: '2', + start: 3, + value: 'r', + }, + ], + groups: [ + { + end: 4, + name: 'g', + start: 3, + value: 'r', + }, + ], + index: 2, + value: 'er', + }, + { + captures: [ + { + end: 6, + name: '1', + start: 5, + value: 'y', + }, + { + end: 7, + name: '2', + start: 6, + value: 'r', + }, + ], + groups: [ + { + end: 7, + name: 'g', + start: 6, + value: 'r', + }, + ], + index: 5, + value: 'yr', + }, + ], + }, +]; + +describe('regex-tester', () => { + for (const reg of regexesData) { + const { regex, text, flags, result: expected_result } = reg; + it(`Should matchRegex("${regex}","${text}","${flags}") return correct result`, async () => { + const result = matchRegex(regex, text, `${flags}d`); + + expect(result).to.deep.equal(expected_result); + }); + } +}); diff --git a/src/tools/regex-tester/regex-tester.service.ts b/src/tools/regex-tester/regex-tester.service.ts new file mode 100644 index 000000000..ec8682c5c --- /dev/null +++ b/src/tools/regex-tester/regex-tester.service.ts @@ -0,0 +1,61 @@ +interface RegExpGroupIndices { + [name: string]: [number, number] +} +interface RegExpIndices extends Array<[number, number]> { + groups: RegExpGroupIndices +} +interface RegExpExecArrayWithIndices extends RegExpExecArray { + indices: RegExpIndices +} +interface GroupCapture { + name: string + value: string + start: number + end: number +}; + +export function matchRegex(regex: string, text: string, flags: string) { + // if (regex === '' || text === '') { + // return []; + // } + + let lastIndex = -1; + const re = new RegExp(regex, flags); + const results = []; + let match = re.exec(text) as RegExpExecArrayWithIndices; + while (match !== null) { + if (re.lastIndex === lastIndex || match[0] === '') { + break; + } + const indices = match.indices; + const captures: Array = []; + Object.entries(match).forEach(([captureName, captureValue]) => { + if (captureName !== '0' && captureName.match(/\d+/)) { + captures.push({ + name: captureName, + value: captureValue, + start: indices[Number(captureName)][0], + end: indices[Number(captureName)][1], + }); + } + }); + const groups: Array = []; + Object.entries(match.groups || {}).forEach(([groupName, groupValue]) => { + groups.push({ + name: groupName, + value: groupValue, + start: indices.groups[groupName][0], + end: indices.groups[groupName][1], + }); + }); + results.push({ + index: match.index, + value: match[0], + captures, + groups, + }); + lastIndex = re.lastIndex; + match = re.exec(text) as RegExpExecArrayWithIndices; + } + return results; +} diff --git a/src/tools/regex-tester/regex-tester.vue b/src/tools/regex-tester/regex-tester.vue new file mode 100644 index 000000000..a1fa79584 --- /dev/null +++ b/src/tools/regex-tester/regex-tester.vue @@ -0,0 +1,193 @@ + + + From 72517002f39d5c5ab21d8473c2fcc04f12818069 Mon Sep 17 00:00:00 2001 From: Corentin Thomasset Date: Fri, 27 Sep 2024 10:40:56 +0200 Subject: [PATCH 04/16] refactor(regex-tester): better description --- src/tools/regex-tester/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/regex-tester/index.ts b/src/tools/regex-tester/index.ts index 9cc542f0e..62a5e2346 100644 --- a/src/tools/regex-tester/index.ts +++ b/src/tools/regex-tester/index.ts @@ -4,7 +4,7 @@ import { defineTool } from '../tool'; export const tool = defineTool({ name: 'Regex Tester', path: '/regex-tester', - description: 'Regex Tester', + description: 'Test your regular expressions with sample text.', keywords: ['regex', 'tester', 'sample', 'expression'], component: () => import('./regex-tester.vue'), icon: Language, From 1c35ac37043f05bd9d0c7a026dd67d82aa026796 Mon Sep 17 00:00:00 2001 From: Corentin THOMASSET Date: Fri, 27 Sep 2024 14:49:11 +0200 Subject: [PATCH 05/16] docs(author): updated author links (#1316) --- README.md | 2 +- locales/de.yml | 2 +- locales/en.yml | 2 +- locales/es.yml | 6 +++--- locales/fr.yml | 2 +- locales/pt.yml | 2 +- locales/uk.yml | 2 +- locales/vi.yml | 2 +- locales/zh.yml | 2 +- package.json | 16 ++++++++-------- src/layouts/base.layout.vue | 2 +- 11 files changed, 20 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index b9726864a..93c7aa735 100644 --- a/README.md +++ b/README.md @@ -117,7 +117,7 @@ Big thanks to all the people who have already contributed! ## Credits -Coded with ❤️ by [Corentin Thomasset](//corentin-thomasset.fr). +Coded with ❤️ by [Corentin Thomasset](https://corentin.tech?utm_source=it-tools&utm_medium=readme). This project is continuously deployed using [vercel.com](https://vercel.com). diff --git a/locales/de.yml b/locales/de.yml index 5a47c85d4..e59ca1144 100644 --- a/locales/de.yml +++ b/locales/de.yml @@ -38,7 +38,7 @@ about: # Über IT-Tools Diese wunderbare Website, erstellt mit ❤ von [Corentin - Thomasset](https://github.com/CorentinTh), sammelt nützliche Tools für + Thomasset](https://corentin.tech?utm_source=it-tools&utm_medium=about), sammelt nützliche Tools für Entwickler und Menschen, die in der IT arbeiten. Wenn du sie nützlich findest, teile sie gerne mit Personen, von denen du denkst, dass sie sie ebenfalls nützlich finden könnten, und vergiss nicht, sie in deiner diff --git a/locales/en.yml b/locales/en.yml index d09d435aa..d1cd21c47 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -30,7 +30,7 @@ about: content: > # About IT-Tools - This wonderful website, made with ❤ by [Corentin Thomasset](https://github.com/CorentinTh) , aggregates useful tools for developer and people working in IT. If you find it useful, please feel free to share it to people you think may find it useful too and don't forget to bookmark it in your shortcut bar! + This wonderful website, made with ❤ by [Corentin Thomasset](https://corentin.tech?utm_source=it-tools&utm_medium=about) , aggregates useful tools for developer and people working in IT. If you find it useful, please feel free to share it to people you think may find it useful too and don't forget to bookmark it in your shortcut bar! IT Tools is open-source (under the MIT license) and free, and will always be, but it costs me money to host and renew the domain name. If you want to support my work, and encourage me to add more tools, please consider supporting by [sponsoring me](https://www.buymeacoffee.com/cthmsst). diff --git a/locales/es.yml b/locales/es.yml index b87502fc0..2d8b2515a 100644 --- a/locales/es.yml +++ b/locales/es.yml @@ -30,7 +30,7 @@ about: content: > # Sobre IT-Tools - Este maravilloso sitio web, hecho con ❤ por [Corentin Thomasset](https://github.com/CorentinTh) , agrega herramientas útiles para desarrolladores y personas que trabajan en IT. Si lo encuentra útil, no dude en compartirlo con las personas que crea que también pueden encontrarlo útil y ¡no olvide marcarlo como favorito en su barra de accesos directos! + Este maravilloso sitio web, hecho con ❤ por [Corentin Thomasset](https://corentin.tech?utm_source=it-tools&utm_medium=about) , agrega herramientas útiles para desarrolladores y personas que trabajan en IT. Si lo encuentra útil, no dude en compartirlo con las personas que crea que también pueden encontrarlo útil y ¡no olvide marcarlo como favorito en su barra de accesos directos! IT Tools es de código abierto (under the MIT license) y gratis, y siempre lo será, pero me cuesta dinero alojar y renovar el nombre de dominio. Si desea apoyar mi trabajo y animarme a agregar más herramientas, considere apoyarme a través de[sponsoring me](https://www.buymeacoffee.com/cthmsst). @@ -39,7 +39,7 @@ about: IT Tools está creado en Vue.js (Vue 3) con la biblioteca de componentes Naive UI y Vercel lo aloja y lo implementa continuamente. En algunas herramientas se utilizan bibliotecas de código abierto de terceros; puede encontrar la lista completa en [package.json](https://github.com/CorentinTh/it-tools/blob/main/package.json) archivo del repositorio. ## ¿Encontraste un error? ¿Falta una herramienta? - + Si necesita una herramienta que actualmente no está presente aquí y cree que puede ser útil, puede enviar una solicitud de función en el [issues section](https://github.com/CorentinTh/it-tools/issues/new/choose) en el repositorio de GitHub. Y si encontró un error o algo no funciona como se esperaba, presente un reporte de error en el [issues section](https://github.com/CorentinTh/it-tools/issues/new/choose) en el repositorio de GitHub. @@ -68,4 +68,4 @@ tools: math: Math measurement: Measurement text: Text - data: Data \ No newline at end of file + data: Data diff --git a/locales/fr.yml b/locales/fr.yml index 35c7df2ef..cd5cc0e8a 100644 --- a/locales/fr.yml +++ b/locales/fr.yml @@ -29,7 +29,7 @@ about: content: > # À propos de IT-Tools - Ce merveilleux site, fait avec ❤ par [Corentin Thomasset](https://github.com/CorentinTh), regroupe des outils utiles pour les développeurs et les personnes travaillant dans l'informatique. Si vous le trouvez utile, n'hésitez pas à le partager et n'oubliez pas de le mettre dans vos favoris ! + Ce merveilleux site, fait avec ❤ par [Corentin Thomasset](https://corentin.tech?utm_source=it-tools&utm_medium=about), regroupe des outils utiles pour les développeurs et les personnes travaillant dans l'informatique. Si vous le trouvez utile, n'hésitez pas à le partager et n'oubliez pas de le mettre dans vos favoris ! IT Tools est open-source (sous licence MIT) et gratuit, et le restera toujours, mais cela me coûte de l'argent pour l'héberger et renouveler le nom de domaine. Si vous voulez soutenir mon travail, et m'encourager à ajouter plus d'outils, n'hésitez pas à me [soutenir](https://www.buymeacoffee.com/cthmsst). diff --git a/locales/pt.yml b/locales/pt.yml index 96fdaed4c..822bea8ae 100644 --- a/locales/pt.yml +++ b/locales/pt.yml @@ -30,7 +30,7 @@ about: content: > # Sobre o IT-Tools - Este site maravilhoso, feito com ❤ por [Corentin Thomasset](https://github.com/CorentinTh), junta ferramentas úteis para desenvolvedores e outras pessoas que trabalham com TI. Se você achar o site útil, fique à vontade para compartilhar com quem também possa gostar e não esqueça de salvar o bookmark na sua barra de atalhos! + Este site maravilhoso, feito com ❤ por [Corentin Thomasset](https://corentin.tech?utm_source=it-tools&utm_medium=about), junta ferramentas úteis para desenvolvedores e outras pessoas que trabalham com TI. Se você achar o site útil, fique à vontade para compartilhar com quem também possa gostar e não esqueça de salvar o bookmark na sua barra de atalhos! O IT Tools é código aberto (sob a licença MIT), é gratuito, e sempre será, mas custa dinheiro para hospedar e renovar o domínio. Se quiser apoiar meu trabalho e me encorajar a adicionar mais ferramentas, por favor considere [ser patrocinador](https://www.buymeacoffee.com/cthmsst). diff --git a/locales/uk.yml b/locales/uk.yml index 2d28f157d..ad455a7d5 100644 --- a/locales/uk.yml +++ b/locales/uk.yml @@ -30,7 +30,7 @@ about: content: > # Про IT-Tools - Цей чудовий вебсайт, створений з ❤ [Corentin Thomasset](https://github.com/CorentinTh), агрегує корисні інструменти для розробників і людей, які працюють в сфері IT. Якщо вам це корисно, будь ласка, поділіться цим з людьми, які, на вашу думку, також можуть знайти його корисним, і не забудьте додати його до закладок у вашій панелі швидкого доступу! + Цей чудовий вебсайт, створений з ❤ [Corentin Thomasset](https://corentin.tech?utm_source=it-tools&utm_medium=about), агрегує корисні інструменти для розробників і людей, які працюють в сфері IT. Якщо вам це корисно, будь ласка, поділіться цим з людьми, які, на вашу думку, також можуть знайти його корисним, і не забудьте додати його до закладок у вашій панелі швидкого доступу! IT Tools є відкритим програмним забезпеченням (під ліцензією MIT) і безкоштовним, і завжди буде таким, але мені коштує гроші для хостингу і продовження доменного імені. Якщо ви хочете підтримати мою роботу і підтримати мене у додаванні нових інструментів, розгляньте можливість підтримки, [спонсоруючи мене](https://www.buymeacoffee.com/cthmsst). diff --git a/locales/vi.yml b/locales/vi.yml index 9eb16bf0f..de574a6cf 100644 --- a/locales/vi.yml +++ b/locales/vi.yml @@ -30,7 +30,7 @@ about: content: > # Về IT-Tools - Website tuyệt vời này, được tạo ra bằng ❤ bởi [Corentin Thomasset](https://github.com/CorentinTh), tổng hợp các công cụ hữu ích cho nhà phát triển và những người làm việc trong lĩnh vực IT. Nếu bạn thấy nó hữu ích, xin đừng ngần ngại chia sẻ cho những người mà bạn nghĩ sẽ thấy nó hữu ích và đừng quên đánh dấu nó trong thanh lối tắt của bạn! + Website tuyệt vời này, được tạo ra bằng ❤ bởi [Corentin Thomasset](https://corentin.tech?utm_source=it-tools&utm_medium=about), tổng hợp các công cụ hữu ích cho nhà phát triển và những người làm việc trong lĩnh vực IT. Nếu bạn thấy nó hữu ích, xin đừng ngần ngại chia sẻ cho những người mà bạn nghĩ sẽ thấy nó hữu ích và đừng quên đánh dấu nó trong thanh lối tắt của bạn! IT Tools là mã nguồn mở (dưới giấy phép MIT) và miễn phí, và sẽ luôn như vậy, nhưng tôi phải trả tiền để lưu trữ và gia hạn tên miền. Nếu bạn muốn hỗ trợ công việc của tôi, và khích lệ tôi thêm nhiều công cụ hơn, hãy xem xét hỗ trợ bằng cách [tài trợ cho tôi](https://www.buymeacoffee.com/cthmsst). diff --git a/locales/zh.yml b/locales/zh.yml index 160fe1fad..9b065682c 100644 --- a/locales/zh.yml +++ b/locales/zh.yml @@ -30,7 +30,7 @@ about: content: > # 关于 IT-Tools - IT-Tools 由 [Corentin Thomasset](https://github.com/CorentinTh) 用 ❤ 开发,汇集了对开发人员和 IT 从业者有用的工具。如果对您有帮助,请将其分享给您的朋友,并且添加到收藏夹中! + IT-Tools 由 [Corentin Thomasset](https://corentin.tech?utm_source=it-tools&utm_medium=about) 用 ❤ 开发,汇集了对开发人员和 IT 从业者有用的工具。如果对您有帮助,请将其分享给您的朋友,并且添加到收藏夹中! IT-Tools 永久免费且开源(MIT 许可证),但需要资金用于托管和续订域名。如果您想支持我的工作,并鼓励我添加更多工具,请考虑通过 [赞助我](https://www.buymeacoffee.com/cthmsst) 进行支持。 diff --git a/package.json b/package.json index f5dedc0c6..8a1c069f1 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,14 @@ { "name": "it-tools", "version": "2024.5.13-a0bc346", + "packageManager": "pnpm@8.15.3", "description": "Collection of handy online tools for developers, with great UX. ", + "author": "Corentin Th (https://corentin.tech)", + "license": "GNU GPLv3", + "repository": { + "type": "git", + "url": "https://github.com/CorentinTh/it-tools" + }, "keywords": [ "productivity", "converter", @@ -13,12 +20,6 @@ "developer-tools", "developer-productivity" ], - "author": "Corentin Th (https://github.com/CorentinTh)", - "license": "GNU GPLv3", - "repository": { - "type": "git", - "url": "https://github.com/CorentinTh/it-tools" - }, "scripts": { "dev": "vite", "build": "vue-tsc --noEmit && NODE_OPTIONS=--max_old_space_size=4096 vite build", @@ -145,6 +146,5 @@ "vitest": "^0.34.0", "workbox-window": "^7.0.0", "zx": "^7.2.1" - }, - "packageManager": "pnpm@8.15.3" + } } diff --git a/src/layouts/base.layout.vue b/src/layouts/base.layout.vue index 62ac5113c..ef5342094 100644 --- a/src/layouts/base.layout.vue +++ b/src/layouts/base.layout.vue @@ -81,7 +81,7 @@ const tools = computed(() => [
© {{ new Date().getFullYear() }} - + Corentin Thomasset
From f962c416a33e1481fd7d1f4eca927bbf5810cde7 Mon Sep 17 00:00:00 2001 From: Corentin THOMASSET Date: Thu, 3 Oct 2024 00:01:09 +0200 Subject: [PATCH 06/16] chore(sponsors): fern sponsor banners (#1314) * chore(sponsors): readme banner * chore(sponsors): app sponsor --- .github/fern-banner.svg | 11 +++++++++++ README.md | 4 ++++ src/config.ts | 6 ++++++ src/pages/Home.page.vue | 30 ++++++++++++++++++++++++++++-- 4 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 .github/fern-banner.svg diff --git a/.github/fern-banner.svg b/.github/fern-banner.svg new file mode 100644 index 000000000..20b918f70 --- /dev/null +++ b/.github/fern-banner.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/README.md b/README.md index 93c7aa735..dfe7f3d46 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,10 @@ Useful tools for developer and people working in IT. [Have a look !](https://it-tools.tech). +## Sponsors + +[![Fern banner](./.github/fern-banner.svg)](https://bit.ly/3zBl7DG) + ## Functionalities and roadmap Please check the [issues](https://github.com/CorentinTh/it-tools/issues) to see if some feature listed to be implemented. diff --git a/src/config.ts b/src/config.ts index 2558d0385..fa2421eff 100644 --- a/src/config.ts +++ b/src/config.ts @@ -59,6 +59,12 @@ export const config = figue({ default: false, env: 'VITE_SHOW_BANNER', }, + showSponsorBanner: { + doc: 'Show the sponsor banner', + format: 'boolean', + default: false, + env: 'VITE_SHOW_SPONSOR_BANNER', + }, }) .loadEnv({ ...import.meta.env, diff --git a/src/pages/Home.page.vue b/src/pages/Home.page.vue index dfd12b604..190601c1a 100644 --- a/src/pages/Home.page.vue +++ b/src/pages/Home.page.vue @@ -15,8 +15,8 @@ const { t } = useI18n();