From f1a26ef91d3fd90999fe44d39b8ee2d1a04e816a Mon Sep 17 00:00:00 2001 From: Matthieu Jouis Date: Wed, 17 Jul 2024 13:27:31 +0200 Subject: [PATCH] markdown widget --- frontend/package-lock.json | 128 +++++++++++++++- frontend/package.json | 7 + frontend/src/assets/fixtures/markdown.md | 159 ++++++++++++++++++++ frontend/src/components/MarkdownWidget.vue | 28 ++++ frontend/src/env.d.ts | 3 + frontend/src/{router/index.ts => router.ts} | 9 +- frontend/src/views/ComponentsView.vue | 11 ++ 7 files changed, 342 insertions(+), 3 deletions(-) create mode 100644 frontend/src/assets/fixtures/markdown.md create mode 100644 frontend/src/components/MarkdownWidget.vue rename frontend/src/{router/index.ts => router.ts} (63%) create mode 100644 frontend/src/views/ComponentsView.vue diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 06f0761f..dfb93430 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -8,6 +8,11 @@ "name": "mandr-frontend", "version": "0.0.0", "dependencies": { + "markdown-it": "^14.1.0", + "markdown-it-emoji": "^3.0.0", + "markdown-it-highlightjs": "^4.1.0", + "markdown-it-sub": "^2.0.0", + "markdown-it-sup": "^2.0.0", "pinia": "^2.1.7", "vue": "^3.4.29", "vue-router": "^4.3.3" @@ -16,6 +21,8 @@ "@rushstack/eslint-patch": "^1.8.0", "@tsconfig/node20": "^20.1.4", "@types/jsdom": "^21.1.7", + "@types/markdown-it": "^14.1.1", + "@types/markdown-it-emoji": "^3.0.1", "@types/node": "^20.14.5", "@vitejs/plugin-vue": "^5.0.5", "@vue/eslint-config-prettier": "^9.0.0", @@ -1743,6 +1750,41 @@ "parse5": "^7.0.0" } }, + "node_modules/@types/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/markdown-it": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.1.tgz", + "integrity": "sha512-4NpsnpYl2Gt1ljyBGrKMxFYAYvpqbnnkgP/i/g+NLpjEUa3obn1XJCur9YbEXKDAkaXqsR1LbDnGEJ0MmKFxfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/linkify-it": "^5", + "@types/mdurl": "^2" + } + }, + "node_modules/@types/markdown-it-emoji": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/markdown-it-emoji/-/markdown-it-emoji-3.0.1.tgz", + "integrity": "sha512-cz1j8R35XivBqq9mwnsrP2fsz2yicLhB8+PDtuVkKOExwEdsVBNI+ROL3sbhtR5occRZ66vT0QnwFZCqdjf3pA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/markdown-it": "^14" + } + }, + "node_modules/@types/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/node": { "version": "20.14.10", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", @@ -2478,8 +2520,7 @@ "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/array-union": { "version": "2.1.0", @@ -3921,6 +3962,15 @@ "he": "bin/he" } }, + "node_modules/highlight.js": { + "version": "11.10.0", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.10.0.tgz", + "integrity": "sha512-SYVnVFswQER+zu1laSya563s+F8VDGt7o35d4utbamowvUNLLMovFqwCLSocpZTz3MgaSRA1IbqRWZv97dtErQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/hookable": { "version": "5.5.3", "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", @@ -4454,6 +4504,15 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true }, + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "license": "MIT", + "dependencies": { + "uc.micro": "^2.0.0" + } + }, "node_modules/local-pkg": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.0.tgz", @@ -4526,6 +4585,50 @@ "@jridgewell/sourcemap-codec": "^1.4.15" } }, + "node_modules/markdown-it": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/markdown-it-emoji": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/markdown-it-emoji/-/markdown-it-emoji-3.0.0.tgz", + "integrity": "sha512-+rUD93bXHubA4arpEZO3q80so0qgoFJEKRkRbjKX8RTdca89v2kfyF+xR3i2sQTwql9tpPZPOQN5B+PunspXRg==", + "license": "MIT" + }, + "node_modules/markdown-it-highlightjs": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/markdown-it-highlightjs/-/markdown-it-highlightjs-4.1.0.tgz", + "integrity": "sha512-aYcgme5aYn10BHEvLZaCNgwxU2oaAX9inK9dwCv38wJdq7tal5FzZrLdQQY8MR3I1H07S3BKgYGRX2kKuPT+sA==", + "license": "Unlicense", + "dependencies": { + "highlight.js": "^11.9.0" + } + }, + "node_modules/markdown-it-sub": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/markdown-it-sub/-/markdown-it-sub-2.0.0.tgz", + "integrity": "sha512-iCBKgwCkfQBRg2vApy9vx1C1Tu6D8XYo8NvevI3OlwzBRmiMtsJ2sXupBgEA7PPxiDwNni3qIUkhZ6j5wofDUA==", + "license": "MIT" + }, + "node_modules/markdown-it-sup": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/markdown-it-sup/-/markdown-it-sup-2.0.0.tgz", + "integrity": "sha512-5VgmdKlkBd8sgXuoDoxMpiU+BiEt3I49GItBzzw7Mxq9CxvnhE/k09HFli09zgfFDRixDQDfDxi0mgBCXtaTvA==", + "license": "MIT" + }, "node_modules/mathml-tag-names": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", @@ -4542,6 +4645,12 @@ "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", "dev": true }, + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "license": "MIT" + }, "node_modules/memorystream": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", @@ -5354,6 +5463,15 @@ "node": ">=6" } }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/querystringify": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", @@ -6421,6 +6539,12 @@ "node": ">=14.17" } }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "license": "MIT" + }, "node_modules/ufo": { "version": "1.5.3", "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.3.tgz", diff --git a/frontend/package.json b/frontend/package.json index 7a4398b1..d1dca7ea 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -16,6 +16,11 @@ "format": "prettier --write src/" }, "dependencies": { + "markdown-it": "^14.1.0", + "markdown-it-emoji": "^3.0.0", + "markdown-it-highlightjs": "^4.1.0", + "markdown-it-sub": "^2.0.0", + "markdown-it-sup": "^2.0.0", "pinia": "^2.1.7", "vue": "^3.4.29", "vue-router": "^4.3.3" @@ -24,6 +29,8 @@ "@rushstack/eslint-patch": "^1.8.0", "@tsconfig/node20": "^20.1.4", "@types/jsdom": "^21.1.7", + "@types/markdown-it": "^14.1.1", + "@types/markdown-it-emoji": "^3.0.1", "@types/node": "^20.14.5", "@vitejs/plugin-vue": "^5.0.5", "@vue/eslint-config-prettier": "^9.0.0", diff --git a/frontend/src/assets/fixtures/markdown.md b/frontend/src/assets/fixtures/markdown.md new file mode 100644 index 00000000..39542a18 --- /dev/null +++ b/frontend/src/assets/fixtures/markdown.md @@ -0,0 +1,159 @@ +# h1 Heading 8-) + +## h2 Heading + +### h3 Heading + +#### h4 Heading + +##### h5 Heading + +###### h6 Heading + +## Horizontal Rules + +--- + +--- + +--- + +## Typographic replacements + +Enable typographer option to see result. + +(c) (C) (r) (R) (tm) (TM) (p) (P) +- + +test.. test... test..... test?..... test!.... + +!!!!!! ???? ,, -- --- + +"Smartypants, double quotes" and 'single quotes' + +## Emphasis + +**This is bold text** + +**This is bold text** + +_This is italic text_ + +_This is italic text_ + +~~Strikethrough~~ + +## Blockquotes + +> Blockquotes can also be nested... +> +> > ...by using additional greater-than signs right next to each other... +> > +> > > ...or with spaces between arrows. + +## Lists + +Unordered + +- Create a list by starting a line with `+`, `-`, or `*` +- Sub-lists are made by indenting 2 spaces: + - Marker character change forces new list start: + - Ac tristique libero volutpat at + * Facilisis in pretium nisl aliquet + - Nulla volutpat aliquam velit +- Very easy! + +Ordered + +1. Lorem ipsum dolor sit amet +2. Consectetur adipiscing elit +3. Integer molestie lorem at massa + +4. You can use sequential numbers... +5. ...or keep all the numbers as `1.` + +Start numbering with offset: + +57. foo +1. bar + +## Code + +Inline `code` + +Indented code + + // Some comments + line 1 of code + line 2 of code + line 3 of code + +Block code "fences" + +``` +Sample text here... +``` + +Syntax highlighting + +```js +var foo = function (bar) { + return bar++; +}; + +console.log(foo(5)); +``` + +## Tables + +| Option | Description | +| ------ | ------------------------------------------------------------------------- | +| data | path to data files to supply the data that will be passed into templates. | +| engine | engine to be used for processing templates. Handlebars is the default. | +| ext | extension to be used for dest files. | + +Right aligned columns + +| Option | Description | +| -----: | ------------------------------------------------------------------------: | +| data | path to data files to supply the data that will be passed into templates. | +| engine | engine to be used for processing templates. Handlebars is the default. | +| ext | extension to be used for dest files. | + +## Links + +[link text](http://dev.nodeca.com) + +[link with title](http://nodeca.github.io/pica/demo/ "title text!") + +Autoconverted link https://github.com/nodeca/pica (enable linkify to see) + +## Images + +![Minion](https://octodex.github.com/images/minion.png) +![Stormtroopocat](https://octodex.github.com/images/stormtroopocat.jpg "The Stormtroopocat") + +Like links, Images also have a footnote style syntax + +![Alt text][id] + +With a reference later in the document defining the URL location: + +[id]: https://octodex.github.com/images/dojocat.jpg "The Dojocat" + +## Plugins + +The killer feature of `markdown-it` is very effective support of +[syntax plugins](https://www.npmjs.org/browse/keyword/markdown-it-plugin). + +### [Emojies](https://github.com/markdown-it/markdown-it-emoji) + +> Classic markup: :wink: :cry: :laughing: :yum: +> +> Shortcuts (emoticons): :-) :-( 8-) ;) + +see [how to change output](https://github.com/markdown-it/markdown-it-emoji#change-output) with twemoji. + +### [Subscript](https://github.com/markdown-it/markdown-it-sub) / [Superscript](https://github.com/markdown-it/markdown-it-sup) + +- 19^th^ +- H~2~O diff --git a/frontend/src/components/MarkdownWidget.vue b/frontend/src/components/MarkdownWidget.vue new file mode 100644 index 00000000..85269b12 --- /dev/null +++ b/frontend/src/components/MarkdownWidget.vue @@ -0,0 +1,28 @@ + + + diff --git a/frontend/src/env.d.ts b/frontend/src/env.d.ts index 11f02fe2..38781a11 100644 --- a/frontend/src/env.d.ts +++ b/frontend/src/env.d.ts @@ -1 +1,4 @@ /// + +declare module "markdown-it-sub"; +declare module "markdown-it-sup"; diff --git a/frontend/src/router/index.ts b/frontend/src/router.ts similarity index 63% rename from frontend/src/router/index.ts rename to frontend/src/router.ts index d9aa1183..b2573e0e 100644 --- a/frontend/src/router/index.ts +++ b/frontend/src/router.ts @@ -1,5 +1,7 @@ import { createRouter, createWebHashHistory } from "vue-router"; -import DashboardView from "../views/DashboardView.vue"; + +import ComponentsView from "./views/ComponentsView.vue"; +import DashboardView from "./views/DashboardView.vue"; const router = createRouter({ history: createWebHashHistory(import.meta.env.BASE_URL), @@ -14,6 +16,11 @@ const router = createRouter({ name: "mander", component: DashboardView, }, + { + path: "/components", + name: "components", + component: ComponentsView, + }, ], }); diff --git a/frontend/src/views/ComponentsView.vue b/frontend/src/views/ComponentsView.vue new file mode 100644 index 00000000..7664d886 --- /dev/null +++ b/frontend/src/views/ComponentsView.vue @@ -0,0 +1,11 @@ + + +