diff --git a/.eslintrc-auto-import.json b/.eslintrc-auto-import.json
index 4084d922..086a67de 100644
--- a/.eslintrc-auto-import.json
+++ b/.eslintrc-auto-import.json
@@ -286,6 +286,7 @@
"watchTriggerable": true,
"watchWithFilter": true,
"whenever": true,
- "toValue": true
+ "toValue": true,
+ "WritableComputedRef": true
}
}
diff --git a/components.d.ts b/components.d.ts
index d034fc78..56198201 100644
--- a/components.d.ts
+++ b/components.d.ts
@@ -84,11 +84,11 @@ declare module '@vue/runtime-core' {
HmacGenerator: typeof import('./src/tools/hmac-generator/hmac-generator.vue')['default']
'Home.page': typeof import('./src/pages/Home.page.vue')['default']
HtmlEntities: typeof import('./src/tools/html-entities/html-entities.vue')['default']
+ HtmlMdConverter: typeof import('./src/tools/html-md-converter/html-md-converter.vue')['default']
HtmlWysiwygEditor: typeof import('./src/tools/html-wysiwyg-editor/html-wysiwyg-editor.vue')['default']
HttpStatusCodes: typeof import('./src/tools/http-status-codes/http-status-codes.vue')['default']
IbanValidatorAndParser: typeof import('./src/tools/iban-validator-and-parser/iban-validator-and-parser.vue')['default']
'IconMdi:brushVariant': typeof import('~icons/mdi/brush-variant')['default']
- 'IconMdi:contentCopy': typeof import('~icons/mdi/content-copy')['default']
'IconMdi:kettleSteamOutline': typeof import('~icons/mdi/kettle-steam-outline')['default']
IconMdiArrowDown: typeof import('~icons/mdi/arrow-down')['default']
IconMdiArrowRight: typeof import('~icons/mdi/arrow-right')['default']
@@ -170,6 +170,7 @@ declare module '@vue/runtime-core' {
NSwitch: typeof import('naive-ui')['NSwitch']
NTable: typeof import('naive-ui')['NTable']
NTag: typeof import('naive-ui')['NTag']
+ NTooltip: typeof import('naive-ui')['NTooltip']
NumeronymGenerator: typeof import('./src/tools/numeronym-generator/numeronym-generator.vue')['default']
NUpload: typeof import('naive-ui')['NUpload']
NUploadDragger: typeof import('naive-ui')['NUploadDragger']
diff --git a/package.json b/package.json
index e0148f87..c7818407 100644
--- a/package.json
+++ b/package.json
@@ -79,6 +79,7 @@
"plausible-tracker": "^0.3.8",
"qrcode": "^1.5.1",
"sql-formatter": "^13.0.0",
+ "turndown": "^7.1.2",
"ua-parser-js": "^1.0.35",
"ulid": "^2.3.0",
"unicode-emoji-json": "^0.4.0",
@@ -103,11 +104,13 @@
"@types/dompurify": "^3.0.5",
"@types/jsdom": "^21.0.0",
"@types/lodash": "^4.14.192",
+ "@types/marked": "^5.0.1",
"@types/mime-types": "^2.1.1",
"@types/netmask": "^2.0.0",
"@types/node": "^18.15.11",
"@types/node-forge": "^1.3.2",
"@types/qrcode": "^1.5.0",
+ "@types/turndown": "^5.0.4",
"@types/ua-parser-js": "^0.7.36",
"@types/uuid": "^9.0.0",
"@unocss/eslint-config": "^0.57.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index dfacabd4..cfe4a175 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -137,6 +137,9 @@ dependencies:
sql-formatter:
specifier: ^13.0.0
version: 13.0.0
+ turndown:
+ specifier: ^7.1.2
+ version: 7.1.2
ua-parser-js:
specifier: ^1.0.35
version: 1.0.35
@@ -205,6 +208,9 @@ devDependencies:
'@types/lodash':
specifier: ^4.14.192
version: 4.14.192
+ '@types/marked':
+ specifier: ^5.0.1
+ version: 5.0.2
'@types/mime-types':
specifier: ^2.1.1
version: 2.1.1
@@ -220,6 +226,9 @@ devDependencies:
'@types/qrcode':
specifier: ^1.5.0
version: 1.5.0
+ '@types/turndown':
+ specifier: ^5.0.4
+ version: 5.0.4
'@types/ua-parser-js':
specifier: ^0.7.36
version: 0.7.36
@@ -2988,6 +2997,10 @@ packages:
'@types/mdurl': 1.0.2
dev: true
+ /@types/marked@5.0.2:
+ resolution: {integrity: sha512-OucS4KMHhFzhz27KxmWg7J+kIYqyqoW5kdIEI319hqARQQUTqhao3M/F+uFnDXD0Rg72iDDZxZNxq5gvctmLlg==}
+ dev: true
+
/@types/mdast@3.0.11:
resolution: {integrity: sha512-Y/uImid8aAwrEA24/1tcRZwpxX3pIFTSilcNDKSPn+Y2iDywSEachzRuvgAYYLR3wpGXAsMbv5lvKLDZLeYPAw==}
dependencies:
@@ -3074,6 +3087,10 @@ packages:
resolution: {integrity: sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==}
dev: true
+ /@types/turndown@5.0.4:
+ resolution: {integrity: sha512-28GI33lCCkU4SGH1GvjDhFgOVr+Tym4PXGBIU1buJUa6xQolniPArtUT+kv42RR2N9MsMLInkr904Aq+ESHBJg==}
+ dev: true
+
/@types/ua-parser-js@0.7.36:
resolution: {integrity: sha512-N1rW+njavs70y2cApeIw1vLMYXRwfBy+7trgavGuuTfOd7j1Yh7QTRc/yqsPl6ncokt72ZXuxEU0PiCp9bSwNQ==}
dev: true
@@ -3374,7 +3391,7 @@ packages:
dependencies:
'@unhead/dom': 0.5.1
'@unhead/schema': 0.5.1
- '@vueuse/shared': 10.6.1(vue@3.3.4)
+ '@vueuse/shared': 10.7.2(vue@3.3.4)
unhead: 0.5.1
vue: 3.3.4
transitivePeerDependencies:
@@ -4010,14 +4027,14 @@ packages:
/@vueuse/shared@10.3.0(vue@3.3.4):
resolution: {integrity: sha512-kGqCTEuFPMK4+fNWy6dUOiYmxGcUbtznMwBZLC1PubidF4VZY05B+Oht7Jh7/6x4VOWGpvu3R37WHi81cKpiqg==}
dependencies:
- vue-demi: 0.14.5(vue@3.3.4)
+ vue-demi: 0.14.6(vue@3.3.4)
transitivePeerDependencies:
- '@vue/composition-api'
- vue
dev: false
- /@vueuse/shared@10.6.1(vue@3.3.4):
- resolution: {integrity: sha512-TECVDTIedFlL0NUfHWncf3zF9Gc4VfdxfQc8JFwoVZQmxpONhLxFrlm0eHQeidHj4rdTPL3KXJa0TZCk1wnc5Q==}
+ /@vueuse/shared@10.7.2(vue@3.3.4):
+ resolution: {integrity: sha512-qFbXoxS44pi2FkgFjPvF4h7c9oMDutpyBdcJdMYIMg9XyXli2meFMuaKn+UMgsClo//Th6+beeCgqweT/79BVA==}
dependencies:
vue-demi: 0.14.6(vue@3.3.4)
transitivePeerDependencies:
@@ -4940,6 +4957,10 @@ packages:
domelementtype: 2.3.0
dev: true
+ /domino@2.1.6:
+ resolution: {integrity: sha512-3VdM/SXBZX2omc9JF9nOPCtDaYQ67BGp5CoLpIQlO2KCAPETs8TcDHacF26jXadGbvUteZzRTeos2fhID5+ucQ==}
+ dev: false
+
/dompurify@3.0.6:
resolution: {integrity: sha512-ilkD8YEnnGh1zJ240uJsW7AzE+2qpbOUYjacomn3AvJ6J4JhKGSZ2nh4wUIXPZrEPppaCLx5jFe8T89Rk8tQ7w==}
dev: false
@@ -8553,6 +8574,12 @@ packages:
typescript: 5.2.2
dev: true
+ /turndown@7.1.2:
+ resolution: {integrity: sha512-ntI9R7fcUKjqBP6QU8rBK2Ehyt8LAzt3UBT9JR9tgo6GtuKvyUzpayWmeMKJw1DPdXzktvtIT8m2mVXz+bL/Qg==}
+ dependencies:
+ domino: 2.1.6
+ dev: false
+
/type-check@0.3.2:
resolution: {integrity: sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==}
engines: {node: '>= 0.8.0'}
diff --git a/src/tools/html-md-converter/html-md-converter-service.ts b/src/tools/html-md-converter/html-md-converter-service.ts
new file mode 100644
index 00000000..910c33bc
--- /dev/null
+++ b/src/tools/html-md-converter/html-md-converter-service.ts
@@ -0,0 +1,13 @@
+import TurnDownService from 'turndown';
+
+const turnDownService = new TurnDownService();
+
+/**
+ * Converts the given HTML string to Markdown format.
+ *
+ * @param html - The HTML string to convert.
+ * @returns The converted Markdown string.
+ */
+export function convertHtmlToMarkdown(html: string): string {
+ return turnDownService.turndown(html);
+}
diff --git a/src/tools/html-md-converter/html-md-converter.vue b/src/tools/html-md-converter/html-md-converter.vue
new file mode 100644
index 00000000..bd9fa29c
--- /dev/null
+++ b/src/tools/html-md-converter/html-md-converter.vue
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/tools/html-md-converter/index.ts b/src/tools/html-md-converter/index.ts
new file mode 100644
index 00000000..a06afd64
--- /dev/null
+++ b/src/tools/html-md-converter/index.ts
@@ -0,0 +1,11 @@
+import { BrandHtml5 } from '@vicons/tabler';
+import { defineTool } from '../tool';
+
+export const tool = defineTool({
+ name: 'HTML-MD converter',
+ path: '/html-md-converter',
+ description: 'Convert an html div with all contained data to Markdown using turndown',
+ keywords: ['html', 'md', 'converter'],
+ component: () => import('./html-md-converter.vue'),
+ icon: BrandHtml5,
+});
diff --git a/src/tools/index.ts b/src/tools/index.ts
index 52bdf8e3..0b833ade 100644
--- a/src/tools/index.ts
+++ b/src/tools/index.ts
@@ -75,6 +75,7 @@ import { tool as urlParser } from './url-parser';
import { tool as uuidGenerator } from './uuid-generator';
import { tool as macAddressLookup } from './mac-address-lookup';
import { tool as xmlFormatter } from './xml-formatter';
+import { tool as htmlMdConverter } from './html-md-converter';
export const toolsByCategory: ToolCategory[] = [
{
@@ -100,6 +101,7 @@ export const toolsByCategory: ToolCategory[] = [
listConverter,
tomlToJson,
tomlToYaml,
+ htmlMdConverter,
],
},
{