mirror of
https://github.com/CorentinTh/it-tools.git
synced 2025-04-21 23:36:15 -04:00
Merge branch 'main' into fix/phone-parser-storage
This commit is contained in:
commit
2bba23635d
27 changed files with 942 additions and 22 deletions
BIN
.github/logo-dark.png
vendored
Normal file
BIN
.github/logo-dark.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 40 KiB |
BIN
.github/logo-white.png
vendored
Normal file
BIN
.github/logo-white.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 39 KiB |
BIN
.github/logo.png
vendored
BIN
.github/logo.png
vendored
Binary file not shown.
Before Width: | Height: | Size: 7.8 KiB |
|
@ -1,4 +1,8 @@
|
||||||

|
<picture>
|
||||||
|
<source srcset="./.github/logo-dark.png" media="(prefers-color-scheme: light)">
|
||||||
|
<source srcset="./.github/logo-white.png" media="(prefers-color-scheme: dark)">
|
||||||
|
<img src="./.github/logo-dark.png" alt="logo">
|
||||||
|
</picture>
|
||||||
|
|
||||||
Useful tools for developer and people working in IT. [Have a look !](https://it-tools.tech).
|
Useful tools for developer and people working in IT. [Have a look !](https://it-tools.tech).
|
||||||
|
|
||||||
|
|
12
components.d.ts
vendored
12
components.d.ts
vendored
|
@ -72,6 +72,7 @@ declare module '@vue/runtime-core' {
|
||||||
DockerRunToDockerComposeConverter: typeof import('./src/tools/docker-run-to-docker-compose-converter/docker-run-to-docker-compose-converter.vue')['default']
|
DockerRunToDockerComposeConverter: typeof import('./src/tools/docker-run-to-docker-compose-converter/docker-run-to-docker-compose-converter.vue')['default']
|
||||||
DynamicValues: typeof import('./src/tools/benchmark-builder/dynamic-values.vue')['default']
|
DynamicValues: typeof import('./src/tools/benchmark-builder/dynamic-values.vue')['default']
|
||||||
Editor: typeof import('./src/tools/html-wysiwyg-editor/editor/editor.vue')['default']
|
Editor: typeof import('./src/tools/html-wysiwyg-editor/editor/editor.vue')['default']
|
||||||
|
EmailNormalizer: typeof import('./src/tools/email-normalizer/email-normalizer.vue')['default']
|
||||||
EmojiCard: typeof import('./src/tools/emoji-picker/emoji-card.vue')['default']
|
EmojiCard: typeof import('./src/tools/emoji-picker/emoji-card.vue')['default']
|
||||||
EmojiGrid: typeof import('./src/tools/emoji-picker/emoji-grid.vue')['default']
|
EmojiGrid: typeof import('./src/tools/emoji-picker/emoji-grid.vue')['default']
|
||||||
EmojiPicker: typeof import('./src/tools/emoji-picker/emoji-picker.vue')['default']
|
EmojiPicker: typeof import('./src/tools/emoji-picker/emoji-picker.vue')['default']
|
||||||
|
@ -110,6 +111,7 @@ declare module '@vue/runtime-core' {
|
||||||
JsonMinify: typeof import('./src/tools/json-minify/json-minify.vue')['default']
|
JsonMinify: typeof import('./src/tools/json-minify/json-minify.vue')['default']
|
||||||
JsonToCsv: typeof import('./src/tools/json-to-csv/json-to-csv.vue')['default']
|
JsonToCsv: typeof import('./src/tools/json-to-csv/json-to-csv.vue')['default']
|
||||||
JsonToToml: typeof import('./src/tools/json-to-toml/json-to-toml.vue')['default']
|
JsonToToml: typeof import('./src/tools/json-to-toml/json-to-toml.vue')['default']
|
||||||
|
JsonToXml: typeof import('./src/tools/json-to-xml/json-to-xml.vue')['default']
|
||||||
JsonToYaml: typeof import('./src/tools/json-to-yaml-converter/json-to-yaml.vue')['default']
|
JsonToYaml: typeof import('./src/tools/json-to-yaml-converter/json-to-yaml.vue')['default']
|
||||||
JsonViewer: typeof import('./src/tools/json-viewer/json-viewer.vue')['default']
|
JsonViewer: typeof import('./src/tools/json-viewer/json-viewer.vue')['default']
|
||||||
JwtParser: typeof import('./src/tools/jwt-parser/jwt-parser.vue')['default']
|
JwtParser: typeof import('./src/tools/jwt-parser/jwt-parser.vue')['default']
|
||||||
|
@ -119,6 +121,7 @@ declare module '@vue/runtime-core' {
|
||||||
LoremIpsumGenerator: typeof import('./src/tools/lorem-ipsum-generator/lorem-ipsum-generator.vue')['default']
|
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']
|
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']
|
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']
|
MathEvaluator: typeof import('./src/tools/math-evaluator/math-evaluator.vue')['default']
|
||||||
MenuBar: typeof import('./src/tools/html-wysiwyg-editor/editor/menu-bar.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']
|
MenuBarItem: typeof import('./src/tools/html-wysiwyg-editor/editor/menu-bar-item.vue')['default']
|
||||||
|
@ -134,14 +137,9 @@ declare module '@vue/runtime-core' {
|
||||||
NConfigProvider: typeof import('naive-ui')['NConfigProvider']
|
NConfigProvider: typeof import('naive-ui')['NConfigProvider']
|
||||||
NDivider: typeof import('naive-ui')['NDivider']
|
NDivider: typeof import('naive-ui')['NDivider']
|
||||||
NEllipsis: typeof import('naive-ui')['NEllipsis']
|
NEllipsis: typeof import('naive-ui')['NEllipsis']
|
||||||
NFormItem: typeof import('naive-ui')['NFormItem']
|
|
||||||
NGi: typeof import('naive-ui')['NGi']
|
|
||||||
NGrid: typeof import('naive-ui')['NGrid']
|
|
||||||
NH1: typeof import('naive-ui')['NH1']
|
NH1: typeof import('naive-ui')['NH1']
|
||||||
NH3: typeof import('naive-ui')['NH3']
|
NH3: typeof import('naive-ui')['NH3']
|
||||||
NIcon: typeof import('naive-ui')['NIcon']
|
NIcon: typeof import('naive-ui')['NIcon']
|
||||||
NInputNumber: typeof import('naive-ui')['NInputNumber']
|
|
||||||
NLabel: typeof import('naive-ui')['NLabel']
|
|
||||||
NLayout: typeof import('naive-ui')['NLayout']
|
NLayout: typeof import('naive-ui')['NLayout']
|
||||||
NLayoutSider: typeof import('naive-ui')['NLayoutSider']
|
NLayoutSider: typeof import('naive-ui')['NLayoutSider']
|
||||||
NMenu: typeof import('naive-ui')['NMenu']
|
NMenu: typeof import('naive-ui')['NMenu']
|
||||||
|
@ -157,6 +155,9 @@ declare module '@vue/runtime-core' {
|
||||||
PhoneParserAndFormatter: typeof import('./src/tools/phone-parser-and-formatter/phone-parser-and-formatter.vue')['default']
|
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']
|
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']
|
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']
|
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']
|
RomanNumeralConverter: typeof import('./src/tools/roman-numeral-converter/roman-numeral-converter.vue')['default']
|
||||||
RouterLink: typeof import('vue-router')['RouterLink']
|
RouterLink: typeof import('vue-router')['RouterLink']
|
||||||
|
@ -189,6 +190,7 @@ declare module '@vue/runtime-core' {
|
||||||
UuidGenerator: typeof import('./src/tools/uuid-generator/uuid-generator.vue')['default']
|
UuidGenerator: typeof import('./src/tools/uuid-generator/uuid-generator.vue')['default']
|
||||||
WifiQrCodeGenerator: typeof import('./src/tools/wifi-qr-code-generator/wifi-qr-code-generator.vue')['default']
|
WifiQrCodeGenerator: typeof import('./src/tools/wifi-qr-code-generator/wifi-qr-code-generator.vue')['default']
|
||||||
XmlFormatter: typeof import('./src/tools/xml-formatter/xml-formatter.vue')['default']
|
XmlFormatter: typeof import('./src/tools/xml-formatter/xml-formatter.vue')['default']
|
||||||
|
XmlToJson: typeof import('./src/tools/xml-to-json/xml-to-json.vue')['default']
|
||||||
YamlToJson: typeof import('./src/tools/yaml-to-json-converter/yaml-to-json.vue')['default']
|
YamlToJson: typeof import('./src/tools/yaml-to-json-converter/yaml-to-json.vue')['default']
|
||||||
YamlToToml: typeof import('./src/tools/yaml-to-toml/yaml-to-toml.vue')['default']
|
YamlToToml: typeof import('./src/tools/yaml-to-toml/yaml-to-toml.vue')['default']
|
||||||
YamlViewer: typeof import('./src/tools/yaml-viewer/yaml-viewer.vue')['default']
|
YamlViewer: typeof import('./src/tools/yaml-viewer/yaml-viewer.vue')['default']
|
||||||
|
|
|
@ -37,11 +37,13 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@it-tools/bip39": "^0.0.4",
|
"@it-tools/bip39": "^0.0.4",
|
||||||
"@it-tools/oggen": "^1.3.0",
|
"@it-tools/oggen": "^1.3.0",
|
||||||
|
"@regexper/render": "^1.0.0",
|
||||||
"@sindresorhus/slugify": "^2.2.1",
|
"@sindresorhus/slugify": "^2.2.1",
|
||||||
"@tiptap/pm": "2.1.6",
|
"@tiptap/pm": "2.1.6",
|
||||||
"@tiptap/starter-kit": "2.1.6",
|
"@tiptap/starter-kit": "2.1.6",
|
||||||
"@tiptap/vue-3": "2.0.3",
|
"@tiptap/vue-3": "2.0.3",
|
||||||
"@types/figlet": "^1.5.8",
|
"@types/figlet": "^1.5.8",
|
||||||
|
"@types/markdown-it": "^13.0.7",
|
||||||
"@vicons/material": "^0.12.0",
|
"@vicons/material": "^0.12.0",
|
||||||
"@vicons/tabler": "^0.12.0",
|
"@vicons/tabler": "^0.12.0",
|
||||||
"@vueuse/core": "^10.3.0",
|
"@vueuse/core": "^10.3.0",
|
||||||
|
@ -57,6 +59,7 @@
|
||||||
"crypto-js": "^4.1.1",
|
"crypto-js": "^4.1.1",
|
||||||
"date-fns": "^2.29.3",
|
"date-fns": "^2.29.3",
|
||||||
"dompurify": "^3.0.6",
|
"dompurify": "^3.0.6",
|
||||||
|
"email-normalizer": "^1.0.0",
|
||||||
"emojilib": "^3.0.10",
|
"emojilib": "^3.0.10",
|
||||||
"figlet": "^1.7.0",
|
"figlet": "^1.7.0",
|
||||||
"figue": "^1.2.0",
|
"figue": "^1.2.0",
|
||||||
|
@ -69,6 +72,7 @@
|
||||||
"jwt-decode": "^3.1.2",
|
"jwt-decode": "^3.1.2",
|
||||||
"libphonenumber-js": "^1.10.28",
|
"libphonenumber-js": "^1.10.28",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
|
"markdown-it": "^14.0.0",
|
||||||
"marked": "^10.0.0",
|
"marked": "^10.0.0",
|
||||||
"mathjs": "^11.9.1",
|
"mathjs": "^11.9.1",
|
||||||
"mime-types": "^2.1.35",
|
"mime-types": "^2.1.35",
|
||||||
|
@ -81,6 +85,7 @@
|
||||||
"pinia": "^2.0.34",
|
"pinia": "^2.0.34",
|
||||||
"plausible-tracker": "^0.3.8",
|
"plausible-tracker": "^0.3.8",
|
||||||
"qrcode": "^1.5.1",
|
"qrcode": "^1.5.1",
|
||||||
|
"randexp": "^0.5.3",
|
||||||
"sql-formatter": "^13.0.0",
|
"sql-formatter": "^13.0.0",
|
||||||
"ua-parser-js": "^1.0.35",
|
"ua-parser-js": "^1.0.35",
|
||||||
"ulid": "^2.3.0",
|
"ulid": "^2.3.0",
|
||||||
|
@ -90,8 +95,10 @@
|
||||||
"vue": "^3.3.4",
|
"vue": "^3.3.4",
|
||||||
"vue-i18n": "^9.9.1",
|
"vue-i18n": "^9.9.1",
|
||||||
"vue-router": "^4.1.6",
|
"vue-router": "^4.1.6",
|
||||||
|
"vue-shadow-dom": "^4.2.0",
|
||||||
"vue-tsc": "^1.8.1",
|
"vue-tsc": "^1.8.1",
|
||||||
"xml-formatter": "^3.3.2",
|
"xml-formatter": "^3.3.2",
|
||||||
|
"xml-js": "^1.6.11",
|
||||||
"yaml": "^2.2.1"
|
"yaml": "^2.2.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
137
pnpm-lock.yaml
generated
137
pnpm-lock.yaml
generated
|
@ -11,6 +11,9 @@ dependencies:
|
||||||
'@it-tools/oggen':
|
'@it-tools/oggen':
|
||||||
specifier: ^1.3.0
|
specifier: ^1.3.0
|
||||||
version: 1.3.0
|
version: 1.3.0
|
||||||
|
'@regexper/render':
|
||||||
|
specifier: ^1.0.0
|
||||||
|
version: 1.0.0
|
||||||
'@sindresorhus/slugify':
|
'@sindresorhus/slugify':
|
||||||
specifier: ^2.2.1
|
specifier: ^2.2.1
|
||||||
version: 2.2.1
|
version: 2.2.1
|
||||||
|
@ -26,6 +29,9 @@ dependencies:
|
||||||
'@types/figlet':
|
'@types/figlet':
|
||||||
specifier: ^1.5.8
|
specifier: ^1.5.8
|
||||||
version: 1.5.8
|
version: 1.5.8
|
||||||
|
'@types/markdown-it':
|
||||||
|
specifier: ^13.0.7
|
||||||
|
version: 13.0.9
|
||||||
'@vicons/material':
|
'@vicons/material':
|
||||||
specifier: ^0.12.0
|
specifier: ^0.12.0
|
||||||
version: 0.12.0
|
version: 0.12.0
|
||||||
|
@ -71,6 +77,9 @@ dependencies:
|
||||||
dompurify:
|
dompurify:
|
||||||
specifier: ^3.0.6
|
specifier: ^3.0.6
|
||||||
version: 3.0.6
|
version: 3.0.6
|
||||||
|
email-normalizer:
|
||||||
|
specifier: ^1.0.0
|
||||||
|
version: 1.0.0
|
||||||
emojilib:
|
emojilib:
|
||||||
specifier: ^3.0.10
|
specifier: ^3.0.10
|
||||||
version: 3.0.10
|
version: 3.0.10
|
||||||
|
@ -107,6 +116,9 @@ dependencies:
|
||||||
lodash:
|
lodash:
|
||||||
specifier: ^4.17.21
|
specifier: ^4.17.21
|
||||||
version: 4.17.21
|
version: 4.17.21
|
||||||
|
markdown-it:
|
||||||
|
specifier: ^14.0.0
|
||||||
|
version: 14.1.0
|
||||||
marked:
|
marked:
|
||||||
specifier: ^10.0.0
|
specifier: ^10.0.0
|
||||||
version: 10.0.0
|
version: 10.0.0
|
||||||
|
@ -143,6 +155,9 @@ dependencies:
|
||||||
qrcode:
|
qrcode:
|
||||||
specifier: ^1.5.1
|
specifier: ^1.5.1
|
||||||
version: 1.5.1
|
version: 1.5.1
|
||||||
|
randexp:
|
||||||
|
specifier: ^0.5.3
|
||||||
|
version: 0.5.3
|
||||||
sql-formatter:
|
sql-formatter:
|
||||||
specifier: ^13.0.0
|
specifier: ^13.0.0
|
||||||
version: 13.0.0
|
version: 13.0.0
|
||||||
|
@ -170,12 +185,18 @@ dependencies:
|
||||||
vue-router:
|
vue-router:
|
||||||
specifier: ^4.1.6
|
specifier: ^4.1.6
|
||||||
version: 4.1.6(vue@3.3.4)
|
version: 4.1.6(vue@3.3.4)
|
||||||
|
vue-shadow-dom:
|
||||||
|
specifier: ^4.2.0
|
||||||
|
version: 4.2.0
|
||||||
vue-tsc:
|
vue-tsc:
|
||||||
specifier: ^1.8.1
|
specifier: ^1.8.1
|
||||||
version: 1.8.1(typescript@5.2.2)
|
version: 1.8.1(typescript@5.2.2)
|
||||||
xml-formatter:
|
xml-formatter:
|
||||||
specifier: ^3.3.2
|
specifier: ^3.3.2
|
||||||
version: 3.3.2
|
version: 3.3.2
|
||||||
|
xml-js:
|
||||||
|
specifier: ^1.6.11
|
||||||
|
version: 1.6.11
|
||||||
yaml:
|
yaml:
|
||||||
specifier: ^2.2.1
|
specifier: ^2.2.1
|
||||||
version: 2.2.1
|
version: 2.2.1
|
||||||
|
@ -2468,6 +2489,17 @@ packages:
|
||||||
resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==}
|
resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==}
|
||||||
dev: false
|
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:
|
/@remirror/core-constants@2.0.1:
|
||||||
resolution: {integrity: sha512-ZR4aihtnnT9lMbhh5DEbsriJRlukRXmLZe7HmM+6ufJNNUDoazc75UX26xbgQlNUqgAqMcUdGFAnPc1JwgAdLQ==}
|
resolution: {integrity: sha512-ZR4aihtnnT9lMbhh5DEbsriJRlukRXmLZe7HmM+6ufJNNUDoazc75UX26xbgQlNUqgAqMcUdGFAnPc1JwgAdLQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -2617,6 +2649,10 @@ packages:
|
||||||
string.prototype.matchall: 4.0.10
|
string.prototype.matchall: 4.0.10
|
||||||
dev: true
|
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):
|
/@tiptap/core@2.1.12(@tiptap/pm@2.1.6):
|
||||||
resolution: {integrity: sha512-ZGc3xrBJA9KY8kln5AYTj8y+GDrKxi7u95xIl2eccrqTY5CQeRu6HRNM1yT4mAjuSaG9jmazyjGRlQuhyxCKxQ==}
|
resolution: {integrity: sha512-ZGc3xrBJA9KY8kln5AYTj8y+GDrKxi7u95xIl2eccrqTY5CQeRu6HRNM1yT4mAjuSaG9jmazyjGRlQuhyxCKxQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
@ -2946,7 +2982,6 @@ packages:
|
||||||
|
|
||||||
/@types/linkify-it@3.0.2:
|
/@types/linkify-it@3.0.2:
|
||||||
resolution: {integrity: sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==}
|
resolution: {integrity: sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@types/lodash-es@4.17.10:
|
/@types/lodash-es@4.17.10:
|
||||||
resolution: {integrity: sha512-YJP+w/2khSBwbUSFdGsSqmDvmnN3cCKoPOL7Zjle6s30ZtemkkqhjVfFqGwPN7ASil5VyjE2GtyU/yqYY6mC0A==}
|
resolution: {integrity: sha512-YJP+w/2khSBwbUSFdGsSqmDvmnN3cCKoPOL7Zjle6s30ZtemkkqhjVfFqGwPN7ASil5VyjE2GtyU/yqYY6mC0A==}
|
||||||
|
@ -2968,6 +3003,13 @@ packages:
|
||||||
'@types/mdurl': 1.0.2
|
'@types/mdurl': 1.0.2
|
||||||
dev: true
|
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:
|
/@types/mdast@3.0.11:
|
||||||
resolution: {integrity: sha512-Y/uImid8aAwrEA24/1tcRZwpxX3pIFTSilcNDKSPn+Y2iDywSEachzRuvgAYYLR3wpGXAsMbv5lvKLDZLeYPAw==}
|
resolution: {integrity: sha512-Y/uImid8aAwrEA24/1tcRZwpxX3pIFTSilcNDKSPn+Y2iDywSEachzRuvgAYYLR3wpGXAsMbv5lvKLDZLeYPAw==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -2976,7 +3018,6 @@ packages:
|
||||||
|
|
||||||
/@types/mdurl@1.0.2:
|
/@types/mdurl@1.0.2:
|
||||||
resolution: {integrity: sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==}
|
resolution: {integrity: sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/@types/mime-types@2.1.1:
|
/@types/mime-types@2.1.1:
|
||||||
resolution: {integrity: sha512-vXOTGVSLR2jMw440moWTC7H19iUyLtP3Z1YTj7cSsubOICinjMxFeb/V57v9QdyyPGbbWolUFSSmSiRSn94tFw==}
|
resolution: {integrity: sha512-vXOTGVSLR2jMw440moWTC7H19iUyLtP3Z1YTj7cSsubOICinjMxFeb/V57v9QdyyPGbbWolUFSSmSiRSn94tFw==}
|
||||||
|
@ -3354,7 +3395,7 @@ packages:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@unhead/dom': 0.5.1
|
'@unhead/dom': 0.5.1
|
||||||
'@unhead/schema': 0.5.1
|
'@unhead/schema': 0.5.1
|
||||||
'@vueuse/shared': 10.8.0(vue@3.3.4)
|
'@vueuse/shared': 11.0.3(vue@3.3.4)
|
||||||
unhead: 0.5.1
|
unhead: 0.5.1
|
||||||
vue: 3.3.4
|
vue: 3.3.4
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
|
@ -3996,10 +4037,10 @@ packages:
|
||||||
- vue
|
- vue
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@vueuse/shared@10.8.0(vue@3.3.4):
|
/@vueuse/shared@11.0.3(vue@3.3.4):
|
||||||
resolution: {integrity: sha512-dUdy6zwHhULGxmr9YUg8e+EnB39gcM4Fe2oKBSrh3cOsV30JcMPtsyuspgFCUo5xxFNaeMf/W2yyKfST7Bg8oQ==}
|
resolution: {integrity: sha512-0rY2m6HS5t27n/Vp5cTDsKTlNnimCqsbh/fmT2LgE+aaU42EMfXo8+bNX91W9I7DDmxfuACXMmrd7d79JxkqWA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
vue-demi: 0.14.7(vue@3.3.4)
|
vue-demi: 0.14.10(vue@3.3.4)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@vue/composition-api'
|
- '@vue/composition-api'
|
||||||
- vue
|
- vue
|
||||||
|
@ -4945,6 +4986,11 @@ packages:
|
||||||
tslib: 2.5.0
|
tslib: 2.5.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/drange@1.1.1:
|
||||||
|
resolution: {integrity: sha512-pYxfDYpued//QpnLIm4Avk7rsNtAtQkUES2cwAYSvD/wd2pKD71gN2Ebj3e7klzXwjocvE8c5vx/1fxwpqmSxA==}
|
||||||
|
engines: {node: '>=4'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/duplexer@0.1.2:
|
/duplexer@0.1.2:
|
||||||
resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==}
|
resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==}
|
||||||
dev: true
|
dev: true
|
||||||
|
@ -4973,6 +5019,12 @@ packages:
|
||||||
/electron-to-chromium@1.4.572:
|
/electron-to-chromium@1.4.572:
|
||||||
resolution: {integrity: sha512-RlFobl4D3ieetbnR+2EpxdzFl9h0RAJkPK3pfiwMug2nhBin2ZCsGIAJWdpNniLz43sgXam/CgipOmvTA+rUiA==}
|
resolution: {integrity: sha512-RlFobl4D3ieetbnR+2EpxdzFl9h0RAJkPK3pfiwMug2nhBin2ZCsGIAJWdpNniLz43sgXam/CgipOmvTA+rUiA==}
|
||||||
|
|
||||||
|
/email-normalizer@1.0.0:
|
||||||
|
resolution: {integrity: sha512-wZYuuMtL4kUOmg/TPtCrf9hAZjbFq+FcjWA85Z5nr2lGllRnWJPxCJw3gy4Cx+adMoyVw4VJfGGvt/OHgIW+qg==}
|
||||||
|
dependencies:
|
||||||
|
typescript: 5.5.4
|
||||||
|
dev: false
|
||||||
|
|
||||||
/emitter-component@1.1.1:
|
/emitter-component@1.1.1:
|
||||||
resolution: {integrity: sha512-G+mpdiAySMuB7kesVRLuyvYRqDmshB7ReKEVuyBPkzQlmiDiLrt7hHHIy4Aff552bgknVN7B2/d3lzhGO5dvpQ==}
|
resolution: {integrity: sha512-G+mpdiAySMuB7kesVRLuyvYRqDmshB7ReKEVuyBPkzQlmiDiLrt7hHHIy4Aff552bgknVN7B2/d3lzhGO5dvpQ==}
|
||||||
dev: false
|
dev: false
|
||||||
|
@ -5004,7 +5056,6 @@ packages:
|
||||||
/entities@4.5.0:
|
/entities@4.5.0:
|
||||||
resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
|
resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
|
||||||
engines: {node: '>=0.12'}
|
engines: {node: '>=0.12'}
|
||||||
dev: true
|
|
||||||
|
|
||||||
/errno@0.1.8:
|
/errno@0.1.8:
|
||||||
resolution: {integrity: sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==}
|
resolution: {integrity: sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==}
|
||||||
|
@ -6676,6 +6727,12 @@ packages:
|
||||||
dependencies:
|
dependencies:
|
||||||
uc.micro: 1.0.6
|
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:
|
/local-pkg@0.4.3:
|
||||||
resolution: {integrity: sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==}
|
resolution: {integrity: sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==}
|
||||||
engines: {node: '>=14'}
|
engines: {node: '>=14'}
|
||||||
|
@ -6813,6 +6870,18 @@ packages:
|
||||||
mdurl: 1.0.1
|
mdurl: 1.0.1
|
||||||
uc.micro: 1.0.6
|
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:
|
/marked@10.0.0:
|
||||||
resolution: {integrity: sha512-YiGcYcWj50YrwBgNzFoYhQ1hT6GmQbFG8SksnYJX1z4BXTHSOrz1GB5/Jm2yQvMg4nN1FHP4M6r03R10KrVUiA==}
|
resolution: {integrity: sha512-YiGcYcWj50YrwBgNzFoYhQ1hT6GmQbFG8SksnYJX1z4BXTHSOrz1GB5/Jm2yQvMg4nN1FHP4M6r03R10KrVUiA==}
|
||||||
engines: {node: '>= 18'}
|
engines: {node: '>= 18'}
|
||||||
|
@ -6861,6 +6930,10 @@ packages:
|
||||||
/mdurl@1.0.1:
|
/mdurl@1.0.1:
|
||||||
resolution: {integrity: sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==}
|
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:
|
/merge-stream@2.0.0:
|
||||||
resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
|
resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
|
||||||
dev: true
|
dev: true
|
||||||
|
@ -7670,6 +7743,11 @@ packages:
|
||||||
resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==}
|
resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/punycode.js@2.3.1:
|
||||||
|
resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==}
|
||||||
|
engines: {node: '>=6'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/punycode@2.3.0:
|
/punycode@2.3.0:
|
||||||
resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==}
|
resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
@ -7709,6 +7787,14 @@ packages:
|
||||||
ret: 0.1.15
|
ret: 0.1.15
|
||||||
dev: false
|
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:
|
/randombytes@2.1.0:
|
||||||
resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==}
|
resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -7879,6 +7965,11 @@ packages:
|
||||||
engines: {node: '>=0.12'}
|
engines: {node: '>=0.12'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/ret@0.2.2:
|
||||||
|
resolution: {integrity: sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==}
|
||||||
|
engines: {node: '>=4'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/reusify@1.0.4:
|
/reusify@1.0.4:
|
||||||
resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
|
resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
|
||||||
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
|
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
|
||||||
|
@ -7959,8 +8050,6 @@ packages:
|
||||||
/sax@1.2.4:
|
/sax@1.2.4:
|
||||||
resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==}
|
resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==}
|
||||||
requiresBuild: true
|
requiresBuild: true
|
||||||
dev: true
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
/saxes@6.0.0:
|
/saxes@6.0.0:
|
||||||
resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==}
|
resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==}
|
||||||
|
@ -8603,6 +8692,12 @@ packages:
|
||||||
engines: {node: '>=14.17'}
|
engines: {node: '>=14.17'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
/typescript@5.5.4:
|
||||||
|
resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==}
|
||||||
|
engines: {node: '>=14.17'}
|
||||||
|
hasBin: true
|
||||||
|
dev: false
|
||||||
|
|
||||||
/ua-parser-js@1.0.35:
|
/ua-parser-js@1.0.35:
|
||||||
resolution: {integrity: sha512-fKnGuqmTBnIE+/KXSzCn4db8RTigUzw1AN0DmdU6hJovUTbYJKyqj+8Mt1c4VfRDnOVJnENmfYkIPZ946UrSAA==}
|
resolution: {integrity: sha512-fKnGuqmTBnIE+/KXSzCn4db8RTigUzw1AN0DmdU6hJovUTbYJKyqj+8Mt1c4VfRDnOVJnENmfYkIPZ946UrSAA==}
|
||||||
dev: false
|
dev: false
|
||||||
|
@ -8610,6 +8705,10 @@ packages:
|
||||||
/uc.micro@1.0.6:
|
/uc.micro@1.0.6:
|
||||||
resolution: {integrity: sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==}
|
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:
|
/ufo@1.1.2:
|
||||||
resolution: {integrity: sha512-TrY6DsjTQQgyS3E3dBaOXf0TpPD8u9FVrVYmKVegJuFw51n/YB9XPt+U6ydzFG5ZIN7+DIjPbNmXoBj9esYhgQ==}
|
resolution: {integrity: sha512-TrY6DsjTQQgyS3E3dBaOXf0TpPD8u9FVrVYmKVegJuFw51n/YB9XPt+U6ydzFG5ZIN7+DIjPbNmXoBj9esYhgQ==}
|
||||||
|
|
||||||
|
@ -9143,8 +9242,8 @@ packages:
|
||||||
vue: 3.3.4
|
vue: 3.3.4
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/vue-demi@0.14.5(vue@3.3.4):
|
/vue-demi@0.14.10(vue@3.3.4):
|
||||||
resolution: {integrity: sha512-o9NUVpl/YlsGJ7t+xuqJKx8EBGf1quRhCiT6D/J0pfwmk9zUwYkC7yrF4SZCe6fETvSM3UNL2edcbYrSyc4QHA==}
|
resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
requiresBuild: true
|
requiresBuild: true
|
||||||
|
@ -9158,8 +9257,8 @@ packages:
|
||||||
vue: 3.3.4
|
vue: 3.3.4
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/vue-demi@0.14.7(vue@3.3.4):
|
/vue-demi@0.14.5(vue@3.3.4):
|
||||||
resolution: {integrity: sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==}
|
resolution: {integrity: sha512-o9NUVpl/YlsGJ7t+xuqJKx8EBGf1quRhCiT6D/J0pfwmk9zUwYkC7yrF4SZCe6fETvSM3UNL2edcbYrSyc4QHA==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
requiresBuild: true
|
requiresBuild: true
|
||||||
|
@ -9211,6 +9310,10 @@ packages:
|
||||||
vue: 3.3.4
|
vue: 3.3.4
|
||||||
dev: false
|
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:
|
/vue-template-compiler@2.7.14:
|
||||||
resolution: {integrity: sha512-zyA5Y3ArvVG0NacJDkkzJuPQDF8RFeRlzV2vLeSnhSpieO6LK2OVbdLPi5MPPs09Ii+gMO8nY4S3iKQxBxDmWQ==}
|
resolution: {integrity: sha512-zyA5Y3ArvVG0NacJDkkzJuPQDF8RFeRlzV2vLeSnhSpieO6LK2OVbdLPi5MPPs09Ii+gMO8nY4S3iKQxBxDmWQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -9449,6 +9552,7 @@ packages:
|
||||||
|
|
||||||
/workbox-google-analytics@7.0.0:
|
/workbox-google-analytics@7.0.0:
|
||||||
resolution: {integrity: sha512-MEYM1JTn/qiC3DbpvP2BVhyIH+dV/5BjHk756u9VbwuAhu0QHyKscTnisQuz21lfRpOwiS9z4XdqeVAKol0bzg==}
|
resolution: {integrity: sha512-MEYM1JTn/qiC3DbpvP2BVhyIH+dV/5BjHk756u9VbwuAhu0QHyKscTnisQuz21lfRpOwiS9z4XdqeVAKol0bzg==}
|
||||||
|
deprecated: It is not compatible with newer versions of GA starting with v4, as long as you are using GAv3 it should be ok, but the package is not longer being maintained
|
||||||
dependencies:
|
dependencies:
|
||||||
workbox-background-sync: 7.0.0
|
workbox-background-sync: 7.0.0
|
||||||
workbox-core: 7.0.0
|
workbox-core: 7.0.0
|
||||||
|
@ -9549,6 +9653,13 @@ packages:
|
||||||
xml-parser-xo: 4.0.5
|
xml-parser-xo: 4.0.5
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/xml-js@1.6.11:
|
||||||
|
resolution: {integrity: sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==}
|
||||||
|
hasBin: true
|
||||||
|
dependencies:
|
||||||
|
sax: 1.2.4
|
||||||
|
dev: false
|
||||||
|
|
||||||
/xml-name-validator@4.0.0:
|
/xml-name-validator@4.0.0:
|
||||||
resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==}
|
resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import sqlHljs from 'highlight.js/lib/languages/sql';
|
||||||
import xmlHljs from 'highlight.js/lib/languages/xml';
|
import xmlHljs from 'highlight.js/lib/languages/xml';
|
||||||
import yamlHljs from 'highlight.js/lib/languages/yaml';
|
import yamlHljs from 'highlight.js/lib/languages/yaml';
|
||||||
import iniHljs from 'highlight.js/lib/languages/ini';
|
import iniHljs from 'highlight.js/lib/languages/ini';
|
||||||
|
import markdownHljs from 'highlight.js/lib/languages/markdown';
|
||||||
import { useCopy } from '@/composable/copy';
|
import { useCopy } from '@/composable/copy';
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
|
@ -30,6 +31,7 @@ hljs.registerLanguage('html', xmlHljs);
|
||||||
hljs.registerLanguage('xml', xmlHljs);
|
hljs.registerLanguage('xml', xmlHljs);
|
||||||
hljs.registerLanguage('yaml', yamlHljs);
|
hljs.registerLanguage('yaml', yamlHljs);
|
||||||
hljs.registerLanguage('toml', iniHljs);
|
hljs.registerLanguage('toml', iniHljs);
|
||||||
|
hljs.registerLanguage('markdown', markdownHljs);
|
||||||
|
|
||||||
const { value, language, followHeightOf, copyPlacement, copyMessage } = toRefs(props);
|
const { value, language, followHeightOf, copyPlacement, copyMessage } = toRefs(props);
|
||||||
const { height } = followHeightOf.value ? useElementSize(followHeightOf) : { height: ref(null) };
|
const { height } = followHeightOf.value ? useElementSize(followHeightOf) : { height: ref(null) };
|
||||||
|
|
|
@ -3,9 +3,11 @@ import _ from 'lodash';
|
||||||
import { type Ref, reactive, watch } from 'vue';
|
import { type Ref, reactive, watch } from 'vue';
|
||||||
|
|
||||||
type ValidatorReturnType = unknown;
|
type ValidatorReturnType = unknown;
|
||||||
|
type GetErrorMessageReturnType = string;
|
||||||
|
|
||||||
export interface UseValidationRule<T> {
|
export interface UseValidationRule<T> {
|
||||||
validator: (value: T) => ValidatorReturnType
|
validator: (value: T) => ValidatorReturnType
|
||||||
|
getErrorMessage?: (value: T) => GetErrorMessageReturnType
|
||||||
message: string
|
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 {
|
export interface ValidationAttrs {
|
||||||
feedback: string
|
feedback: string
|
||||||
validationStatus: string | undefined
|
validationStatus: string | undefined
|
||||||
|
@ -61,7 +72,13 @@ export function useValidation<T>({
|
||||||
|
|
||||||
for (const rule of get(rules)) {
|
for (const rule of get(rules)) {
|
||||||
if (isFalsyOrHasThrown(() => rule.validator(source.value))) {
|
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';
|
state.status = 'error';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { createPinia } from 'pinia';
|
||||||
import { createHead } from '@vueuse/head';
|
import { createHead } from '@vueuse/head';
|
||||||
|
|
||||||
import { registerSW } from 'virtual:pwa-register';
|
import { registerSW } from 'virtual:pwa-register';
|
||||||
|
import shadow from 'vue-shadow-dom';
|
||||||
import { plausible } from './plugins/plausible.plugin';
|
import { plausible } from './plugins/plausible.plugin';
|
||||||
|
|
||||||
import 'virtual:uno.css';
|
import 'virtual:uno.css';
|
||||||
|
@ -23,5 +24,6 @@ app.use(i18nPlugin);
|
||||||
app.use(router);
|
app.use(router);
|
||||||
app.use(naive);
|
app.use(naive);
|
||||||
app.use(plausible);
|
app.use(plausible);
|
||||||
|
app.use(shadow);
|
||||||
|
|
||||||
app.mount('#app');
|
app.mount('#app');
|
||||||
|
|
65
src/tools/email-normalizer/email-normalizer.vue
Normal file
65
src/tools/email-normalizer/email-normalizer.vue
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { normalizeEmail } from 'email-normalizer';
|
||||||
|
import { withDefaultOnError } from '@/utils/defaults';
|
||||||
|
import { useCopy } from '@/composable/copy';
|
||||||
|
|
||||||
|
const emails = ref('');
|
||||||
|
const normalizedEmails = computed(() => {
|
||||||
|
if (!emails.value) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return emails.value
|
||||||
|
.split('\n')
|
||||||
|
.map((email) => {
|
||||||
|
return withDefaultOnError(() => normalizeEmail({ email }), `Unable to parse email: ${email}`);
|
||||||
|
})
|
||||||
|
.join('\n');
|
||||||
|
});
|
||||||
|
|
||||||
|
const { copy } = useCopy({ source: normalizedEmails, text: 'Normalized emails copied to the clipboard', createToast: true });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div class="mb-2">
|
||||||
|
Raw emails to normalize:
|
||||||
|
</div>
|
||||||
|
<c-input-text
|
||||||
|
v-model:value="emails"
|
||||||
|
placeholder="Put your emails here (one per line)..."
|
||||||
|
rows="3"
|
||||||
|
multiline
|
||||||
|
autocomplete="off"
|
||||||
|
autocorrect="off"
|
||||||
|
autocapitalize="off"
|
||||||
|
spellcheck="false"
|
||||||
|
autofocus
|
||||||
|
monospace
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div class="mb-2 mt-4">
|
||||||
|
Normalized emails:
|
||||||
|
</div>
|
||||||
|
<c-input-text
|
||||||
|
:value="normalizedEmails"
|
||||||
|
placeholder="Normalized emails will appear here..."
|
||||||
|
rows="3"
|
||||||
|
autocomplete="off"
|
||||||
|
autocorrect="off"
|
||||||
|
autocapitalize="off"
|
||||||
|
spellcheck="false"
|
||||||
|
multiline
|
||||||
|
readonly
|
||||||
|
monospace
|
||||||
|
/>
|
||||||
|
<div class="mt-4 flex justify-center gap-2">
|
||||||
|
<c-button @click="emails = ''">
|
||||||
|
Clear emails
|
||||||
|
</c-button>
|
||||||
|
<c-button :disabled="!normalizedEmails" @click="copy()">
|
||||||
|
Copy normalized emails
|
||||||
|
</c-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
12
src/tools/email-normalizer/index.ts
Normal file
12
src/tools/email-normalizer/index.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import { Mail } from '@vicons/tabler';
|
||||||
|
import { defineTool } from '../tool';
|
||||||
|
|
||||||
|
export const tool = defineTool({
|
||||||
|
name: 'Email normalizer',
|
||||||
|
path: '/email-normalizer',
|
||||||
|
description: 'Normalize email addresses to a standard format for easier comparison. Useful for deduplication and data cleaning.',
|
||||||
|
keywords: ['email', 'normalizer'],
|
||||||
|
component: () => import('./email-normalizer.vue'),
|
||||||
|
icon: Mail,
|
||||||
|
createdAt: new Date('2024-08-15'),
|
||||||
|
});
|
|
@ -1,11 +1,17 @@
|
||||||
import { tool as base64FileConverter } from './base64-file-converter';
|
import { tool as base64FileConverter } from './base64-file-converter';
|
||||||
import { tool as base64StringConverter } from './base64-string-converter';
|
import { tool as base64StringConverter } from './base64-string-converter';
|
||||||
import { tool as basicAuthGenerator } from './basic-auth-generator';
|
import { tool as basicAuthGenerator } from './basic-auth-generator';
|
||||||
|
import { tool as emailNormalizer } from './email-normalizer';
|
||||||
|
|
||||||
import { tool as asciiTextDrawer } from './ascii-text-drawer';
|
import { tool as asciiTextDrawer } from './ascii-text-drawer';
|
||||||
|
|
||||||
import { tool as textToUnicode } from './text-to-unicode';
|
import { tool as textToUnicode } from './text-to-unicode';
|
||||||
import { tool as safelinkDecoder } from './safelink-decoder';
|
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 pdfSignatureChecker } from './pdf-signature-checker';
|
||||||
import { tool as numeronymGenerator } from './numeronym-generator';
|
import { tool as numeronymGenerator } from './numeronym-generator';
|
||||||
import { tool as macAddressGenerator } from './mac-address-generator';
|
import { tool as macAddressGenerator } from './mac-address-generator';
|
||||||
|
@ -107,6 +113,9 @@ export const toolsByCategory: ToolCategory[] = [
|
||||||
listConverter,
|
listConverter,
|
||||||
tomlToJson,
|
tomlToJson,
|
||||||
tomlToYaml,
|
tomlToYaml,
|
||||||
|
xmlToJson,
|
||||||
|
jsonToXml,
|
||||||
|
markdownToHtml,
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -148,6 +157,9 @@ export const toolsByCategory: ToolCategory[] = [
|
||||||
dockerRunToDockerComposeConverter,
|
dockerRunToDockerComposeConverter,
|
||||||
xmlFormatter,
|
xmlFormatter,
|
||||||
yamlViewer,
|
yamlViewer,
|
||||||
|
emailNormalizer,
|
||||||
|
regexTester,
|
||||||
|
regexMemo,
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
12
src/tools/json-to-xml/index.ts
Normal file
12
src/tools/json-to-xml/index.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import { Braces } from '@vicons/tabler';
|
||||||
|
import { defineTool } from '../tool';
|
||||||
|
|
||||||
|
export const tool = defineTool({
|
||||||
|
name: 'JSON to XML',
|
||||||
|
path: '/json-to-xml',
|
||||||
|
description: 'Convert JSON to XML',
|
||||||
|
keywords: ['json', 'xml'],
|
||||||
|
component: () => import('./json-to-xml.vue'),
|
||||||
|
icon: Braces,
|
||||||
|
createdAt: new Date('2024-08-09'),
|
||||||
|
});
|
32
src/tools/json-to-xml/json-to-xml.vue
Normal file
32
src/tools/json-to-xml/json-to-xml.vue
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import convert from 'xml-js';
|
||||||
|
import JSON5 from 'json5';
|
||||||
|
import { withDefaultOnError } from '@/utils/defaults';
|
||||||
|
import type { UseValidationRule } from '@/composable/validation';
|
||||||
|
|
||||||
|
const defaultValue = '{"a":{"_attributes":{"x":"1.234","y":"It\'s"}}}';
|
||||||
|
function transformer(value: string) {
|
||||||
|
return withDefaultOnError(() => {
|
||||||
|
return convert.js2xml(JSON5.parse(value), { compact: true });
|
||||||
|
}, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
const rules: UseValidationRule<string>[] = [
|
||||||
|
{
|
||||||
|
validator: (v: string) => v === '' || JSON5.parse(v),
|
||||||
|
message: 'Provided JSON is not valid.',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<format-transformer
|
||||||
|
input-label="Your JSON content"
|
||||||
|
:input-default="defaultValue"
|
||||||
|
input-placeholder="Paste your JSON content here..."
|
||||||
|
output-label="Converted XML"
|
||||||
|
output-language="xml"
|
||||||
|
:transformer="transformer"
|
||||||
|
:input-validation-rules="rules"
|
||||||
|
/>
|
||||||
|
</template>
|
|
@ -2,6 +2,7 @@
|
||||||
import { generateLoremIpsum } from './lorem-ipsum-generator.service';
|
import { generateLoremIpsum } from './lorem-ipsum-generator.service';
|
||||||
import { useCopy } from '@/composable/copy';
|
import { useCopy } from '@/composable/copy';
|
||||||
import { randIntFromInterval } from '@/utils/random';
|
import { randIntFromInterval } from '@/utils/random';
|
||||||
|
import { computedRefreshable } from '@/composable/computedRefreshable';
|
||||||
|
|
||||||
const paragraphs = ref(1);
|
const paragraphs = ref(1);
|
||||||
const sentences = ref([3, 8]);
|
const sentences = ref([3, 8]);
|
||||||
|
@ -9,7 +10,7 @@ const words = ref([8, 15]);
|
||||||
const startWithLoremIpsum = ref(true);
|
const startWithLoremIpsum = ref(true);
|
||||||
const asHTML = ref(false);
|
const asHTML = ref(false);
|
||||||
|
|
||||||
const loremIpsumText = computed(() =>
|
const [loremIpsumText, refreshLoremIpsum] = computedRefreshable(() =>
|
||||||
generateLoremIpsum({
|
generateLoremIpsum({
|
||||||
paragraphCount: paragraphs.value,
|
paragraphCount: paragraphs.value,
|
||||||
asHTML: asHTML.value,
|
asHTML: asHTML.value,
|
||||||
|
@ -18,6 +19,7 @@ const loremIpsumText = computed(() =>
|
||||||
startWithLoremIpsum: startWithLoremIpsum.value,
|
startWithLoremIpsum: startWithLoremIpsum.value,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
const { copy } = useCopy({ source: loremIpsumText, text: 'Lorem ipsum copied to the clipboard' });
|
const { copy } = useCopy({ source: loremIpsumText, text: 'Lorem ipsum copied to the clipboard' });
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -41,10 +43,13 @@ const { copy } = useCopy({ source: loremIpsumText, text: 'Lorem ipsum copied to
|
||||||
|
|
||||||
<c-input-text :value="loremIpsumText" multiline placeholder="Your lorem ipsum..." readonly mt-5 rows="5" />
|
<c-input-text :value="loremIpsumText" multiline placeholder="Your lorem ipsum..." readonly mt-5 rows="5" />
|
||||||
|
|
||||||
<div mt-5 flex justify-center>
|
<div mt-5 flex justify-center gap-3>
|
||||||
<c-button autofocus @click="copy()">
|
<c-button autofocus @click="copy()">
|
||||||
Copy
|
Copy
|
||||||
</c-button>
|
</c-button>
|
||||||
|
<c-button @click="refreshLoremIpsum">
|
||||||
|
Refresh
|
||||||
|
</c-button>
|
||||||
</div>
|
</div>
|
||||||
</c-card>
|
</c-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
12
src/tools/markdown-to-html/index.ts
Normal file
12
src/tools/markdown-to-html/index.ts
Normal file
|
@ -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'),
|
||||||
|
});
|
44
src/tools/markdown-to-html/markdown-to-html.vue
Normal file
44
src/tools/markdown-to-html/markdown-to-html.vue
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import markdownit from 'markdown-it';
|
||||||
|
import TextareaCopyable from '@/components/TextareaCopyable.vue';
|
||||||
|
|
||||||
|
const inputMarkdown = ref('');
|
||||||
|
const outputHtml = computed(() => {
|
||||||
|
const md = markdownit();
|
||||||
|
return md.render(inputMarkdown.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
function printHtml() {
|
||||||
|
const w = window.open();
|
||||||
|
if (w === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
w.document.body.innerHTML = outputHtml.value;
|
||||||
|
w.print();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<c-input-text
|
||||||
|
v-model:value="inputMarkdown"
|
||||||
|
multiline raw-text
|
||||||
|
placeholder="Your Markdown content..."
|
||||||
|
rows="8"
|
||||||
|
autofocus
|
||||||
|
label="Your Markdown to convert:"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<n-divider />
|
||||||
|
|
||||||
|
<n-form-item label="Output HTML:">
|
||||||
|
<TextareaCopyable :value="outputHtml" :word-wrap="true" language="html" />
|
||||||
|
</n-form-item>
|
||||||
|
|
||||||
|
<div flex justify-center>
|
||||||
|
<n-button @click="printHtml">
|
||||||
|
Print as PDF
|
||||||
|
</n-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
12
src/tools/regex-memo/index.ts
Normal file
12
src/tools/regex-memo/index.ts
Normal file
|
@ -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'),
|
||||||
|
});
|
121
src/tools/regex-memo/regex-memo.content.md
Normal file
121
src/tools/regex-memo/regex-memo.content.md
Normal file
|
@ -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`
|
||||||
|
`(?<!bar)foo` | match `foo` if it’s *not* after `bar`
|
||||||
|
|
||||||
|
### Grouping and capturing
|
||||||
|
|
||||||
|
Expression | Description
|
||||||
|
:--|:--
|
||||||
|
`(foo)` | capturing group; match and capture `foo`
|
||||||
|
`(?:foo)` | non-capturing group; match `foo` but *without* capturing `foo`
|
||||||
|
`(foo)bar\1` | `\1` is a backreference to the 1st capturing group; match `foobarfoo`
|
||||||
|
|
||||||
|
- Capturing groups are only relevant in the following methods:
|
||||||
|
- `string.match(regexp)`
|
||||||
|
- `string.matchAll(regexp)`
|
||||||
|
- `string.replace(regexp, callback)`
|
||||||
|
- `\N` is a backreference to the `Nth` capturing group. Capturing groups are numbered starting from 1.
|
||||||
|
|
||||||
|
## References and tools
|
||||||
|
|
||||||
|
- [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions)
|
||||||
|
- [RegExplained](https://leaverou.github.io/regexplained/)
|
32
src/tools/regex-memo/regex-memo.vue
Normal file
32
src/tools/regex-memo/regex-memo.vue
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { useThemeVars } from 'naive-ui';
|
||||||
|
import Memo from './regex-memo.content.md';
|
||||||
|
|
||||||
|
const themeVars = useThemeVars();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<Memo />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
::v-deep(pre) {
|
||||||
|
margin: 0;
|
||||||
|
padding: 15px 22px;
|
||||||
|
background-color: v-bind('themeVars.cardColor');
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
::v-deep(table) {
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
::v-deep(table), ::v-deep(td), ::v-deep(th) {
|
||||||
|
border: 1px solid v-bind('themeVars.textColor1');
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
::v-deep(a) {
|
||||||
|
color: v-bind('themeVars.textColor1');
|
||||||
|
}
|
||||||
|
</style>
|
12
src/tools/regex-tester/index.ts
Normal file
12
src/tools/regex-tester/index.ts
Normal file
|
@ -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'),
|
||||||
|
});
|
106
src/tools/regex-tester/regex-tester.service.test.ts
Normal file
106
src/tools/regex-tester/regex-tester.service.test.ts
Normal file
|
@ -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: '(.)(?<g>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);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
61
src/tools/regex-tester/regex-tester.service.ts
Normal file
61
src/tools/regex-tester/regex-tester.service.ts
Normal file
|
@ -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<GroupCapture> = [];
|
||||||
|
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<GroupCapture> = [];
|
||||||
|
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;
|
||||||
|
}
|
193
src/tools/regex-tester/regex-tester.vue
Normal file
193
src/tools/regex-tester/regex-tester.vue
Normal file
|
@ -0,0 +1,193 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import RandExp from 'randexp';
|
||||||
|
import { render } from '@regexper/render';
|
||||||
|
import type { ShadowRootExpose } from 'vue-shadow-dom';
|
||||||
|
import { matchRegex } from './regex-tester.service';
|
||||||
|
import { useValidation } from '@/composable/validation';
|
||||||
|
import { useQueryParamOrStorage } from '@/composable/queryParams';
|
||||||
|
|
||||||
|
const regex = useQueryParamOrStorage({ name: 'regex', storageName: 'regex-tester:regex', defaultValue: '' });
|
||||||
|
const text = ref('');
|
||||||
|
const global = ref(true);
|
||||||
|
const ignoreCase = ref(false);
|
||||||
|
const multiline = ref(false);
|
||||||
|
const dotAll = ref(true);
|
||||||
|
const unicode = ref(true);
|
||||||
|
const unicodeSets = ref(false);
|
||||||
|
const visualizerSVG = ref<ShadowRootExpose>();
|
||||||
|
|
||||||
|
const regexValidation = useValidation({
|
||||||
|
source: regex,
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
message: 'Invalid regex: {0}',
|
||||||
|
validator: value => new RegExp(value),
|
||||||
|
getErrorMessage: (value) => {
|
||||||
|
const _ = new RegExp(value);
|
||||||
|
return '';
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
const results = computed(() => {
|
||||||
|
let flags = 'd';
|
||||||
|
if (global.value) {
|
||||||
|
flags += 'g';
|
||||||
|
}
|
||||||
|
if (ignoreCase.value) {
|
||||||
|
flags += 'i';
|
||||||
|
}
|
||||||
|
if (multiline.value) {
|
||||||
|
flags += 'm';
|
||||||
|
}
|
||||||
|
if (dotAll.value) {
|
||||||
|
flags += 's';
|
||||||
|
}
|
||||||
|
if (unicode.value) {
|
||||||
|
flags += 'u';
|
||||||
|
}
|
||||||
|
else if (unicodeSets.value) {
|
||||||
|
flags += 'v';
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return matchRegex(regex.value, text.value, flags);
|
||||||
|
}
|
||||||
|
catch (_) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const sample = computed(() => {
|
||||||
|
try {
|
||||||
|
const randexp = new RandExp(new RegExp(regex.value.replace(/\(\?\<[^\>]*\>/g, '(?:')));
|
||||||
|
return randexp.gen();
|
||||||
|
}
|
||||||
|
catch (_) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
watchEffect(
|
||||||
|
async () => {
|
||||||
|
const regexValue = regex.value;
|
||||||
|
// shadow root is required:
|
||||||
|
// @regexper/render append a <defs><style> that broke svg transparency of icons in the whole site
|
||||||
|
const visualizer = visualizerSVG.value?.shadow_root;
|
||||||
|
if (visualizer) {
|
||||||
|
while (visualizer.lastChild) {
|
||||||
|
visualizer.removeChild(visualizer.lastChild);
|
||||||
|
}
|
||||||
|
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
||||||
|
try {
|
||||||
|
await render(regexValue, svg);
|
||||||
|
}
|
||||||
|
catch (_) {
|
||||||
|
}
|
||||||
|
visualizer.appendChild(svg);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div max-w-600px>
|
||||||
|
<c-card title="Regex" mb-1>
|
||||||
|
<c-input-text
|
||||||
|
v-model:value="regex"
|
||||||
|
label="Regex to test:"
|
||||||
|
placeholder="Put the regex to test"
|
||||||
|
multiline
|
||||||
|
rows="3"
|
||||||
|
:validation="regexValidation"
|
||||||
|
/>
|
||||||
|
<router-link target="_blank" to="/regex-memo" mb-1 mt-1>
|
||||||
|
See Regular Expression Cheatsheet
|
||||||
|
</router-link>
|
||||||
|
<n-space>
|
||||||
|
<n-checkbox v-model:checked="global">
|
||||||
|
<span title="Global search">Global search. (<code>g</code>)</span>
|
||||||
|
</n-checkbox>
|
||||||
|
<n-checkbox v-model:checked="ignoreCase">
|
||||||
|
<span title="Case-insensitive search">Case-insensitive search. (<code>i</code>)</span>
|
||||||
|
</n-checkbox>
|
||||||
|
<n-checkbox v-model:checked="multiline">
|
||||||
|
<span title="Allows ^ and $ to match next to newline characters.">Multiline(<code>m</code>)</span>
|
||||||
|
</n-checkbox>
|
||||||
|
<n-checkbox v-model:checked="dotAll">
|
||||||
|
<span title="Allows . to match newline characters.">Singleline(<code>s</code>)</span>
|
||||||
|
</n-checkbox>
|
||||||
|
<n-checkbox v-model:checked="unicode">
|
||||||
|
<span title="Unicode; treat a pattern as a sequence of Unicode code points.">Unicode(<code>u</code>)</span>
|
||||||
|
</n-checkbox>
|
||||||
|
<n-checkbox v-model:checked="unicodeSets">
|
||||||
|
<span title="An upgrade to the u mode with more Unicode features.">Unicode Sets (<code>v</code>)</span>
|
||||||
|
</n-checkbox>
|
||||||
|
</n-space>
|
||||||
|
|
||||||
|
<n-divider />
|
||||||
|
|
||||||
|
<c-input-text
|
||||||
|
v-model:value="text"
|
||||||
|
label="Text to match:"
|
||||||
|
placeholder="Put the text to match"
|
||||||
|
multiline
|
||||||
|
rows="5"
|
||||||
|
/>
|
||||||
|
</c-card>
|
||||||
|
|
||||||
|
<c-card title="Matches" mb-1 mt-3>
|
||||||
|
<n-table v-if="results?.length > 0">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">
|
||||||
|
Index in text
|
||||||
|
</th>
|
||||||
|
<th scope="col">
|
||||||
|
Value
|
||||||
|
</th>
|
||||||
|
<th scope="col">
|
||||||
|
Captures
|
||||||
|
</th>
|
||||||
|
<th scope="col">
|
||||||
|
Groups
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr v-for="match of results" :key="match.index">
|
||||||
|
<td>{{ match.index }}</td>
|
||||||
|
<td>{{ match.value }}</td>
|
||||||
|
<td>
|
||||||
|
<ul>
|
||||||
|
<li v-for="capture in match.captures" :key="capture.name">
|
||||||
|
"{{ capture.name }}" = {{ capture.value }} [{{ capture.start }} - {{ capture.end }}]
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul>
|
||||||
|
<li v-for="group in match.groups" :key="group.name">
|
||||||
|
"{{ group.name }}" = {{ group.value }} [{{ group.start }} - {{ group.end }}]
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</n-table>
|
||||||
|
<c-alert v-else>
|
||||||
|
No match
|
||||||
|
</c-alert>
|
||||||
|
</c-card>
|
||||||
|
|
||||||
|
<c-card title="Sample matching text" mt-3>
|
||||||
|
<pre style="white-space: pre-wrap; word-break: break-all;">{{ sample }}</pre>
|
||||||
|
</c-card>
|
||||||
|
|
||||||
|
<c-card title="Regex Diagram" style="overflow-x: scroll;" mt-3>
|
||||||
|
<shadow-root ref="visualizerSVG">
|
||||||
|
 
|
||||||
|
</shadow-root>
|
||||||
|
</c-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
12
src/tools/xml-to-json/index.ts
Normal file
12
src/tools/xml-to-json/index.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import { Braces } from '@vicons/tabler';
|
||||||
|
import { defineTool } from '../tool';
|
||||||
|
|
||||||
|
export const tool = defineTool({
|
||||||
|
name: 'XML to JSON',
|
||||||
|
path: '/xml-to-json',
|
||||||
|
description: 'Convert XML to JSON',
|
||||||
|
keywords: ['xml', 'json'],
|
||||||
|
component: () => import('./xml-to-json.vue'),
|
||||||
|
icon: Braces,
|
||||||
|
createdAt: new Date('2024-08-09'),
|
||||||
|
});
|
32
src/tools/xml-to-json/xml-to-json.vue
Normal file
32
src/tools/xml-to-json/xml-to-json.vue
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import convert from 'xml-js';
|
||||||
|
import { isValidXML } from '../xml-formatter/xml-formatter.service';
|
||||||
|
import { withDefaultOnError } from '@/utils/defaults';
|
||||||
|
import type { UseValidationRule } from '@/composable/validation';
|
||||||
|
|
||||||
|
const defaultValue = '<a x="1.234" y="It\'s"/>';
|
||||||
|
function transformer(value: string) {
|
||||||
|
return withDefaultOnError(() => {
|
||||||
|
return JSON.stringify(convert.xml2js(value, { compact: true }), null, 2);
|
||||||
|
}, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
const rules: UseValidationRule<string>[] = [
|
||||||
|
{
|
||||||
|
validator: isValidXML,
|
||||||
|
message: 'Provided XML is not valid.',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<format-transformer
|
||||||
|
input-label="Your XML content"
|
||||||
|
:input-default="defaultValue"
|
||||||
|
input-placeholder="Paste your XML content here..."
|
||||||
|
output-label="Converted JSON"
|
||||||
|
output-language="json"
|
||||||
|
:transformer="transformer"
|
||||||
|
:input-validation-rules="rules"
|
||||||
|
/>
|
||||||
|
</template>
|
Loading…
Add table
Add a link
Reference in a new issue