From cb08e0bf9f1a36d77fac9688959a7e6edeaa53e4 Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Tue, 15 Aug 2023 19:26:49 +0200 Subject: [PATCH] feat: Implement initial version of formatter app --- packages/backend/package.json | 3 + .../src/apps/formatter/actions/index.ts | 3 + .../src/apps/formatter/actions/text/index.ts | 64 +++++++++++++++ .../actions/text/transformers/capitalize.ts | 10 +++ .../transformers/extract-email-address.ts | 12 +++ .../text/transformers/html-to-markdown.ts | 11 +++ .../text/transformers/markdown-to-html.ts | 13 +++ .../text/transformers/use-default-value.ts | 13 +++ .../src/apps/formatter/assets/favicon.svg | 3 + .../apps/formatter/dynamic-fields/index.ts | 3 + .../list-transform-options/index.ts | 23 ++++++ .../options/capitalize.ts | 12 +++ .../options/extract-email-address.ts | 12 +++ .../options/html-to-markdown.ts | 12 +++ .../options/markdown-to-html.ts | 12 +++ .../options/use-default-value.ts | 21 +++++ .../backend/src/apps/formatter/index.d.ts | 0 packages/backend/src/apps/formatter/index.ts | 16 ++++ .../src/graphql/queries/get-dynamic-fields.ts | 2 +- packages/docs/pages/.vitepress/config.js | 9 ++ packages/docs/pages/apps/formatter/actions.md | 12 +++ .../docs/pages/apps/formatter/connection.md | 11 +++ packages/docs/pages/guide/available-apps.md | 3 +- .../docs/pages/public/favicons/formatter.svg | 3 + yarn.lock | 82 ++++++++++++++++++- 25 files changed, 361 insertions(+), 4 deletions(-) create mode 100644 packages/backend/src/apps/formatter/actions/index.ts create mode 100644 packages/backend/src/apps/formatter/actions/text/index.ts create mode 100644 packages/backend/src/apps/formatter/actions/text/transformers/capitalize.ts create mode 100644 packages/backend/src/apps/formatter/actions/text/transformers/extract-email-address.ts create mode 100644 packages/backend/src/apps/formatter/actions/text/transformers/html-to-markdown.ts create mode 100644 packages/backend/src/apps/formatter/actions/text/transformers/markdown-to-html.ts create mode 100644 packages/backend/src/apps/formatter/actions/text/transformers/use-default-value.ts create mode 100644 packages/backend/src/apps/formatter/assets/favicon.svg create mode 100644 packages/backend/src/apps/formatter/dynamic-fields/index.ts create mode 100644 packages/backend/src/apps/formatter/dynamic-fields/list-transform-options/index.ts create mode 100644 packages/backend/src/apps/formatter/dynamic-fields/list-transform-options/options/capitalize.ts create mode 100644 packages/backend/src/apps/formatter/dynamic-fields/list-transform-options/options/extract-email-address.ts create mode 100644 packages/backend/src/apps/formatter/dynamic-fields/list-transform-options/options/html-to-markdown.ts create mode 100644 packages/backend/src/apps/formatter/dynamic-fields/list-transform-options/options/markdown-to-html.ts create mode 100644 packages/backend/src/apps/formatter/dynamic-fields/list-transform-options/options/use-default-value.ts create mode 100644 packages/backend/src/apps/formatter/index.d.ts create mode 100644 packages/backend/src/apps/formatter/index.ts create mode 100644 packages/docs/pages/apps/formatter/actions.md create mode 100644 packages/docs/pages/apps/formatter/connection.md create mode 100644 packages/docs/pages/public/favicons/formatter.svg diff --git a/packages/backend/package.json b/packages/backend/package.json index c72f6dcf..b8507f68 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -62,12 +62,14 @@ "memory-cache": "^0.2.0", "morgan": "^1.10.0", "multer": "1.4.5-lts.1", + "node-html-markdown": "^1.3.0", "nodemailer": "6.7.0", "oauth-1.0a": "^2.2.6", "objection": "^3.0.0", "passport": "^0.6.0", "pg": "^8.7.1", "php-serialize": "^4.0.2", + "showdown": "^2.1.0", "stripe": "^11.13.0", "winston": "^3.7.1", "xmlrpc": "^1.3.2" @@ -124,6 +126,7 @@ "@types/nodemailer": "^6.4.4", "@types/pg": "^8.6.1", "@types/pino": "^7.0.5", + "@types/showdown": "^2.0.1", "ava": "^3.15.0", "nodemon": "^2.0.13", "sinon": "^11.1.2", diff --git a/packages/backend/src/apps/formatter/actions/index.ts b/packages/backend/src/apps/formatter/actions/index.ts new file mode 100644 index 00000000..3f0691a8 --- /dev/null +++ b/packages/backend/src/apps/formatter/actions/index.ts @@ -0,0 +1,3 @@ +import text from './text'; + +export default [text]; diff --git a/packages/backend/src/apps/formatter/actions/text/index.ts b/packages/backend/src/apps/formatter/actions/text/index.ts new file mode 100644 index 00000000..6c5e65ed --- /dev/null +++ b/packages/backend/src/apps/formatter/actions/text/index.ts @@ -0,0 +1,64 @@ +import defineAction from '../../../../helpers/define-action'; +import capitalize from './transformers/capitalize'; +import htmlToMarkdown from './transformers/html-to-markdown'; +import markdownToHtml from './transformers/markdown-to-html'; +import useDefaultValue from './transformers/use-default-value'; +import extractEmailAddress from './transformers/extract-email-address'; + +const transformers = { + capitalize, + htmlToMarkdown, + markdownToHtml, + useDefaultValue, + extractEmailAddress, +}; + +export default defineAction({ + name: 'Text', + key: 'text', + description: + 'Transform text data to capitalize, extract emails, apply default value, and much more.', + arguments: [ + { + label: 'Transform', + key: 'transform', + type: 'dropdown' as const, + required: true, + description: 'Pick a channel to send the message to.', + variables: true, + options: [ + { label: 'Capitalize', value: 'capitalize' }, + { label: 'Convert HTML to Markdown', value: 'htmlToMarkdown' }, + { label: 'Convert Markdown to HTML', value: 'markdownToHtml' }, + { label: 'Use Default Value', value: 'useDefaultValue' }, + { label: 'Extract Email Address', value: 'extractEmailAddress' }, + ], + additionalFields: { + type: 'query', + name: 'getDynamicFields', + arguments: [ + { + name: 'key', + value: 'listTransformOptions', + }, + { + name: 'parameters.transform', + value: '{parameters.transform}', + }, + ], + }, + }, + ], + + async run($) { + const transformerName = $.step.parameters + .transform as keyof typeof transformers; + const output = transformers[transformerName]($); + + $.setActionItem({ + raw: { + output, + }, + }); + }, +}); diff --git a/packages/backend/src/apps/formatter/actions/text/transformers/capitalize.ts b/packages/backend/src/apps/formatter/actions/text/transformers/capitalize.ts new file mode 100644 index 00000000..1e385a0a --- /dev/null +++ b/packages/backend/src/apps/formatter/actions/text/transformers/capitalize.ts @@ -0,0 +1,10 @@ +import { IGlobalVariable } from '@automatisch/types'; +import { startCase } from 'lodash'; + +const capitalize = ($: IGlobalVariable) => { + const input = $.step.parameters.input as string; + + return startCase(input); +}; + +export default capitalize; diff --git a/packages/backend/src/apps/formatter/actions/text/transformers/extract-email-address.ts b/packages/backend/src/apps/formatter/actions/text/transformers/extract-email-address.ts new file mode 100644 index 00000000..14f7fb4f --- /dev/null +++ b/packages/backend/src/apps/formatter/actions/text/transformers/extract-email-address.ts @@ -0,0 +1,12 @@ +import { IGlobalVariable } from '@automatisch/types'; + +const extractEmailAddress = ($: IGlobalVariable) => { + const input = $.step.parameters.input as string; + const emailRegexp = + /[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/; + + const email = input.match(emailRegexp); + return email ? email[0] : ''; +}; + +export default extractEmailAddress; diff --git a/packages/backend/src/apps/formatter/actions/text/transformers/html-to-markdown.ts b/packages/backend/src/apps/formatter/actions/text/transformers/html-to-markdown.ts new file mode 100644 index 00000000..89d3a817 --- /dev/null +++ b/packages/backend/src/apps/formatter/actions/text/transformers/html-to-markdown.ts @@ -0,0 +1,11 @@ +import { IGlobalVariable } from '@automatisch/types'; +import { NodeHtmlMarkdown } from 'node-html-markdown'; + +const htmlToMarkdown = ($: IGlobalVariable) => { + const input = $.step.parameters.input as string; + + const markdown = NodeHtmlMarkdown.translate(input); + return markdown; +}; + +export default htmlToMarkdown; diff --git a/packages/backend/src/apps/formatter/actions/text/transformers/markdown-to-html.ts b/packages/backend/src/apps/formatter/actions/text/transformers/markdown-to-html.ts new file mode 100644 index 00000000..42e254aa --- /dev/null +++ b/packages/backend/src/apps/formatter/actions/text/transformers/markdown-to-html.ts @@ -0,0 +1,13 @@ +import { IGlobalVariable } from '@automatisch/types'; +import showdown from 'showdown'; + +const converter = new showdown.Converter(); + +const markdownToHtml = ($: IGlobalVariable) => { + const input = $.step.parameters.input as string; + + const html = converter.makeHtml(input); + return html; +}; + +export default markdownToHtml; diff --git a/packages/backend/src/apps/formatter/actions/text/transformers/use-default-value.ts b/packages/backend/src/apps/formatter/actions/text/transformers/use-default-value.ts new file mode 100644 index 00000000..37276152 --- /dev/null +++ b/packages/backend/src/apps/formatter/actions/text/transformers/use-default-value.ts @@ -0,0 +1,13 @@ +import { IGlobalVariable } from '@automatisch/types'; + +const useDefaultValue = ($: IGlobalVariable) => { + const input = $.step.parameters.input as string; + + if (input && input.trim().length > 0) { + return input; + } + + return $.step.parameters.defaultValue as string; +}; + +export default useDefaultValue; diff --git a/packages/backend/src/apps/formatter/assets/favicon.svg b/packages/backend/src/apps/formatter/assets/favicon.svg new file mode 100644 index 00000000..858aed39 --- /dev/null +++ b/packages/backend/src/apps/formatter/assets/favicon.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/backend/src/apps/formatter/dynamic-fields/index.ts b/packages/backend/src/apps/formatter/dynamic-fields/index.ts new file mode 100644 index 00000000..83a189e9 --- /dev/null +++ b/packages/backend/src/apps/formatter/dynamic-fields/index.ts @@ -0,0 +1,3 @@ +import listTransformOptions from './list-transform-options'; + +export default [listTransformOptions]; diff --git a/packages/backend/src/apps/formatter/dynamic-fields/list-transform-options/index.ts b/packages/backend/src/apps/formatter/dynamic-fields/list-transform-options/index.ts new file mode 100644 index 00000000..cc4ae277 --- /dev/null +++ b/packages/backend/src/apps/formatter/dynamic-fields/list-transform-options/index.ts @@ -0,0 +1,23 @@ +import { IGlobalVariable, IJSONObject } from '@automatisch/types'; +import capitalize from './options/capitalize'; +import htmlToMarkdown from './options/html-to-markdown'; +import markdownToHtml from './options/markdown-to-html'; +import useDefaultValue from './options/use-default-value'; +import extractEmailAddress from './options/extract-email-address'; + +const options: IJSONObject = { + capitalize, + htmlToMarkdown, + markdownToHtml, + useDefaultValue, + extractEmailAddress, +}; + +export default { + name: 'List fields after transform', + key: 'listTransformOptions', + + async run($: IGlobalVariable) { + return options[$.step.parameters.transform as string]; + }, +}; diff --git a/packages/backend/src/apps/formatter/dynamic-fields/list-transform-options/options/capitalize.ts b/packages/backend/src/apps/formatter/dynamic-fields/list-transform-options/options/capitalize.ts new file mode 100644 index 00000000..c8b72c08 --- /dev/null +++ b/packages/backend/src/apps/formatter/dynamic-fields/list-transform-options/options/capitalize.ts @@ -0,0 +1,12 @@ +const capitalize = [ + { + label: 'Input', + key: 'input', + type: 'string' as const, + required: true, + description: 'Text that will be capitalized.', + variables: true, + }, +]; + +export default capitalize; diff --git a/packages/backend/src/apps/formatter/dynamic-fields/list-transform-options/options/extract-email-address.ts b/packages/backend/src/apps/formatter/dynamic-fields/list-transform-options/options/extract-email-address.ts new file mode 100644 index 00000000..439caa85 --- /dev/null +++ b/packages/backend/src/apps/formatter/dynamic-fields/list-transform-options/options/extract-email-address.ts @@ -0,0 +1,12 @@ +const extractEmailAddress = [ + { + label: 'Input', + key: 'input', + type: 'string' as const, + required: true, + description: 'Text that will be searched for an email address.', + variables: true, + }, +]; + +export default extractEmailAddress; diff --git a/packages/backend/src/apps/formatter/dynamic-fields/list-transform-options/options/html-to-markdown.ts b/packages/backend/src/apps/formatter/dynamic-fields/list-transform-options/options/html-to-markdown.ts new file mode 100644 index 00000000..a9ab3325 --- /dev/null +++ b/packages/backend/src/apps/formatter/dynamic-fields/list-transform-options/options/html-to-markdown.ts @@ -0,0 +1,12 @@ +const htmlToMarkdown = [ + { + label: 'Input', + key: 'input', + type: 'string' as const, + required: true, + description: 'HTML that will be converted to Markdown.', + variables: true, + }, +]; + +export default htmlToMarkdown; diff --git a/packages/backend/src/apps/formatter/dynamic-fields/list-transform-options/options/markdown-to-html.ts b/packages/backend/src/apps/formatter/dynamic-fields/list-transform-options/options/markdown-to-html.ts new file mode 100644 index 00000000..39c013bf --- /dev/null +++ b/packages/backend/src/apps/formatter/dynamic-fields/list-transform-options/options/markdown-to-html.ts @@ -0,0 +1,12 @@ +const markdownToHtml = [ + { + label: 'Input', + key: 'input', + type: 'string' as const, + required: true, + description: 'Markdown text that will be converted to HTML.', + variables: true, + }, +]; + +export default markdownToHtml; diff --git a/packages/backend/src/apps/formatter/dynamic-fields/list-transform-options/options/use-default-value.ts b/packages/backend/src/apps/formatter/dynamic-fields/list-transform-options/options/use-default-value.ts new file mode 100644 index 00000000..2c1f850b --- /dev/null +++ b/packages/backend/src/apps/formatter/dynamic-fields/list-transform-options/options/use-default-value.ts @@ -0,0 +1,21 @@ +const useDefaultValue = [ + { + label: 'Input', + key: 'input', + type: 'string' as const, + required: true, + description: 'Text you want to check whether it is empty or not.', + variables: true, + }, + { + label: 'Default Value', + key: 'defaultValue', + type: 'string' as const, + required: true, + description: + 'Text that will be used as a default value if the input is empty.', + variables: true, + }, +]; + +export default useDefaultValue; diff --git a/packages/backend/src/apps/formatter/index.d.ts b/packages/backend/src/apps/formatter/index.d.ts new file mode 100644 index 00000000..e69de29b diff --git a/packages/backend/src/apps/formatter/index.ts b/packages/backend/src/apps/formatter/index.ts new file mode 100644 index 00000000..300b471d --- /dev/null +++ b/packages/backend/src/apps/formatter/index.ts @@ -0,0 +1,16 @@ +import defineApp from '../../helpers/define-app'; +import actions from './actions'; +import dynamicFields from './dynamic-fields'; + +export default defineApp({ + name: 'Formatter', + key: 'formatter', + iconUrl: '{BASE_URL}/apps/formatter/assets/favicon.svg', + authDocUrl: 'https://automatisch.io/docs/apps/formatter/connection', + supportsConnections: false, + baseUrl: '', + apiBaseUrl: '', + primaryColor: '001F52', + actions, + dynamicFields, +}); diff --git a/packages/backend/src/graphql/queries/get-dynamic-fields.ts b/packages/backend/src/graphql/queries/get-dynamic-fields.ts index a066ab48..698de79f 100644 --- a/packages/backend/src/graphql/queries/get-dynamic-fields.ts +++ b/packages/backend/src/graphql/queries/get-dynamic-fields.ts @@ -32,7 +32,7 @@ const getDynamicFields = async ( const connection = step.connection; - if (!connection || !step.appKey) return null; + if (!step.appKey) return null; const app = await App.findOneByKey(step.appKey); const $ = await globalVariable({ connection, app, flow: step.flow, step }); diff --git a/packages/docs/pages/.vitepress/config.js b/packages/docs/pages/.vitepress/config.js index 20d0b618..d87539a5 100644 --- a/packages/docs/pages/.vitepress/config.js +++ b/packages/docs/pages/.vitepress/config.js @@ -86,6 +86,15 @@ export default defineConfig({ { text: 'Connection', link: '/apps/flickr/connection' }, ], }, + { + text: 'Formatter', + collapsible: true, + collapsed: true, + items: [ + { text: 'Actions', link: '/apps/formatter/actions' }, + { text: 'Connection', link: '/apps/formatter/connection' }, + ], + }, { text: 'GitHub', collapsible: true, diff --git a/packages/docs/pages/apps/formatter/actions.md b/packages/docs/pages/apps/formatter/actions.md new file mode 100644 index 00000000..93cb161c --- /dev/null +++ b/packages/docs/pages/apps/formatter/actions.md @@ -0,0 +1,12 @@ +--- +favicon: /favicons/formatter.svg +items: + - name: Text + desc: Transform text data to capitalize, extract emails, apply default value, and much more. +--- + + + + diff --git a/packages/docs/pages/apps/formatter/connection.md b/packages/docs/pages/apps/formatter/connection.md new file mode 100644 index 00000000..d75a5d9d --- /dev/null +++ b/packages/docs/pages/apps/formatter/connection.md @@ -0,0 +1,11 @@ +# Formatter + +Formatter is a built-in app shipped with Automatisch, and it doesn't need to talk with any other external service to run. So there are no additional steps to use the Formatter app. It can be used as an action, and you can use it to format the data from the previous steps. It can be used to format the data in the following ways. + +## Text + +- Capitalize +- Convert HTML to Markdown +- Convert Markdown to HTML +- Use Default Value +- Extract Email Address diff --git a/packages/docs/pages/guide/available-apps.md b/packages/docs/pages/guide/available-apps.md index 35f6e678..63578431 100644 --- a/packages/docs/pages/guide/available-apps.md +++ b/packages/docs/pages/guide/available-apps.md @@ -1,6 +1,6 @@ # Available Apps -Following integrations are currently supported by Automatisch. +The following integrations are currently supported by Automatisch. - [DeepL](/apps/deepl/actions) - [Delay](/apps/delay/actions) @@ -8,6 +8,7 @@ Following integrations are currently supported by Automatisch. - [Dropbox](/apps/dropbox/actions) - [Filter](/apps/filter/actions) - [Flickr](/apps/flickr/triggers) +- [Formatter](/apps/formatter/actions) - [GitHub](/apps/github/triggers) - [GitLab](/apps/gitlab/triggers) - [Google Drive](/apps/google-drive/triggers) diff --git a/packages/docs/pages/public/favicons/formatter.svg b/packages/docs/pages/public/favicons/formatter.svg new file mode 100644 index 00000000..858aed39 --- /dev/null +++ b/packages/docs/pages/public/favicons/formatter.svg @@ -0,0 +1,3 @@ + + + diff --git a/yarn.lock b/yarn.lock index defc1a7b..035f2d89 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4348,6 +4348,11 @@ "@types/mime" "^1" "@types/node" "*" +"@types/showdown@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@types/showdown/-/showdown-2.0.1.tgz#24134738ba3107237d6a783e054a54773e739f81" + integrity sha512-xdnAw2nFqomkaL0QdtEk0t7yz26UkaVPl4v1pYJvtE1T0fmfQEH3JaxErEhGByEAl3zUZrkNBlneuJp0WJGqEA== + "@types/sinon@*": version "10.0.11" resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-10.0.11.tgz#8245827b05d3fc57a6601bd35aee1f7ad330fc42" @@ -6750,7 +6755,7 @@ commander@^8.3.0: resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== -commander@^9.1.0: +commander@^9.0.0, commander@^9.1.0: version "9.5.0" resolved "https://registry.yarnpkg.com/commander/-/commander-9.5.0.tgz#bc08d1eb5cedf7ccb797a96199d41c7bc3e60d30" integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ== @@ -7235,6 +7240,17 @@ css-select@^4.1.3: domutils "^2.8.0" nth-check "^2.0.1" +css-select@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-5.1.0.tgz#b8ebd6554c3637ccc76688804ad3f6a6fdaea8a6" + integrity sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg== + dependencies: + boolbase "^1.0.0" + css-what "^6.1.0" + domhandler "^5.0.2" + domutils "^3.0.1" + nth-check "^2.0.1" + css-tree@1.0.0-alpha.37: version "1.0.0-alpha.37" resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.37.tgz#98bebd62c4c1d9f960ec340cf9f7522e30709a22" @@ -7261,6 +7277,11 @@ css-what@^5.1.0: resolved "https://registry.yarnpkg.com/css-what/-/css-what-5.1.0.tgz#3f7b707aadf633baf62c2ceb8579b545bb40f7fe" integrity sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw== +css-what@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" + integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== + css.escape@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb" @@ -7837,6 +7858,15 @@ dom-serializer@^1.0.1: domhandler "^4.2.0" entities "^2.0.0" +dom-serializer@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53" + integrity sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg== + dependencies: + domelementtype "^2.3.0" + domhandler "^5.0.2" + entities "^4.2.0" + domelementtype@1: version "1.3.1" resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" @@ -7847,6 +7877,11 @@ domelementtype@^2.0.1, domelementtype@^2.2.0: resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.2.0.tgz#9a0b6c2782ed6a1c7323d42267183df9bd8b1d57" integrity sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A== +domelementtype@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" + integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== + domexception@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/domexception/-/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304" @@ -7861,6 +7896,13 @@ domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.0: dependencies: domelementtype "^2.2.0" +domhandler@^5.0.2, domhandler@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31" + integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w== + dependencies: + domelementtype "^2.3.0" + domutils@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" @@ -7878,6 +7920,15 @@ domutils@^2.5.2, domutils@^2.8.0: domelementtype "^2.2.0" domhandler "^4.2.0" +domutils@^3.0.1: + version "3.1.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.1.0.tgz#c47f551278d3dc4b0b1ab8cbb42d751a6f0d824e" + integrity sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA== + dependencies: + dom-serializer "^2.0.0" + domelementtype "^2.3.0" + domhandler "^5.0.3" + dot-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" @@ -8033,6 +8084,11 @@ entities@^2.0.0: resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== +entities@^4.2.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" + integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== + env-paths@^2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" @@ -9855,7 +9911,7 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" -he@^1.2.0: +he@1.2.0, he@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== @@ -12761,6 +12817,21 @@ node-gyp@^8.2.0: tar "^6.1.2" which "^2.0.2" +node-html-markdown@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/node-html-markdown/-/node-html-markdown-1.3.0.tgz#ef0b19a3bbfc0f1a880abb9ff2a0c9aa6bbff2a9" + integrity sha512-OeFi3QwC/cPjvVKZ114tzzu+YoR+v9UXW5RwSXGUqGb0qCl0DvP406tzdL7SFn8pZrMyzXoisfG2zcuF9+zw4g== + dependencies: + node-html-parser "^6.1.1" + +node-html-parser@^6.1.1: + version "6.1.5" + resolved "https://registry.yarnpkg.com/node-html-parser/-/node-html-parser-6.1.5.tgz#c819dceb13a10a7642ff92f94f870b4f77968097" + integrity sha512-fAaM511feX++/Chnhe475a0NHD8M7AxDInsqQpz6x63GRF7xYNdS8Vo5dKsIVPgsOvG7eioRRTZQnWBrhDHBSg== + dependencies: + css-select "^5.1.0" + he "1.2.0" + node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" @@ -15888,6 +15959,13 @@ shiki@^0.11.1: vscode-oniguruma "^1.6.1" vscode-textmate "^6.0.0" +showdown@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/showdown/-/showdown-2.1.0.tgz#1251f5ed8f773f0c0c7bfc8e6fd23581f9e545c5" + integrity sha512-/6NVYu4U819R2pUIk79n67SYgJHWCce0a5xTP979WbNp0FL9MN1I1QK662IDU1b6JzKTvmhgI7T7JYIxBi3kMQ== + dependencies: + commander "^9.0.0" + shx@^0.3.3: version "0.3.4" resolved "https://registry.yarnpkg.com/shx/-/shx-0.3.4.tgz#74289230b4b663979167f94e1935901406e40f02"