diff --git a/README.md b/README.md index bfb30f8..6293361 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,68 @@ -# cut-extension +# Diplodoc cut extension -[![NPM version](https://img.shields.io/npm/v/@diplodoc/viewer.svg?style=flat)](https://www.npmjs.org/package/@diplodoc/viewer) +[![NPM version](https://img.shields.io/npm/v/@diplodoc/cut-extension.svg?style=flat)](https://www.npmjs.org/package/@diplodoc/cut-extension) +This is an extension of the Diplodoc platform, which allows adding collapsible sections in the documentation. + +The extension contains some parts: +- [Prepared runtime](#prepared-runtime) +- [MarkdownIt transform plugin](#markdownit-transform-plugin) + +## Quickstart + +Attach the plugin to the transformer: + +```js +import cutExtension from '@diplodoc/cut-extension'; +import transform from '@diplodoc/transform'; + +const {result} = await transform(` +{% cut "Cut title" %} + +Cut content + +{% endcut %} +`, { + plugins: [ + tabsExtension.transform({ bundle: false }) + ] +}); +``` + +## Prepared runtime + +It is necessary to add `runtime` scripts to make cuts interactive on your page.
+You can add assets files which were generated by the [MarkdownIt transform plugin](#markdownit-transform-plugin). +```html + + + + + + + + ${result.html} + + +``` + +Or you can just include runtime's source code in your bundle. +```js +import '@diplodoc/cut-extension/runtime' +import '@diplodoc/cut-extension/runtime/styles.css' +``` + +## MarkdownIt transform plugin + +Plugin for [@diplodoc/transform](https://github.com/diplodoc-platform/transform) package. + +Options: +- `runtime.script` - name on runtime script which will be exposed in results `script` section.
+ Default: `_assets/tabs-extension.js`
+ +- `runtime.style` - name on runtime css file which will be exposed in results `style` section.
+ (Default: `_assets/tabs-extension.css`)
+ +- `bundle` - boolean flag to enable/disable copying of bundled runtime to target directory.
+ Where target directore is `/`
+ Default: `true`
diff --git a/esbuild/build.mjs b/esbuild/build.mjs index 6340d70..6cfda0b 100755 --- a/esbuild/build.mjs +++ b/esbuild/build.mjs @@ -1,6 +1,7 @@ #!/usr/bin/env node import {build} from 'esbuild'; +import {sassPlugin} from 'esbuild-sass-plugin'; import tsConfig from '../tsconfig.json' assert { type: "json" }; @@ -14,9 +15,24 @@ const common = { tsconfig: './tsconfig.json', }; -build({ +/** @type {import('esbuild').BuildOptions}*/ +const plugin = { + ...common, + entryPoints: ['src/plugin/index.ts'], + outfile: outDir + 'plugin/index.js', + platform: 'node', + packages: 'external', +} + +/** @type {import('esbuild').BuildOptions}*/ +const runtime = { ...common, - entryPoints: ['src/index.ts'], - outfile: outDir + 'index.js', + entryPoints: ['src/runtime/index.ts'], + outfile: outDir + 'runtime/index.js', minify: true, -}); + platform: 'browser', + plugins: [sassPlugin()], +}; + +build(plugin); +build(runtime); diff --git a/package-lock.json b/package-lock.json index 2a27aa3..96faadc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,12 +11,16 @@ "devDependencies": { "@diplodoc/eslint-config": "^2.0.0", "@diplodoc/prettier-config": "^2.0.0", + "@diplodoc/transform": "^4.20.0", "@diplodoc/tsconfig": "^1.0.2", "@types/jest": "^29.5.12", + "@types/markdown-it": "^13.0.8", "esbuild": "^0.22.0", + "esbuild-sass-plugin": "^3.3.1", "husky": "^9.0.11", "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", + "markdown-it": "^13.0.2", "npm-run-all": "^4.1.5", "ts-jest": "^29.2.2", "typescript": "^5.5.3" @@ -635,6 +639,13 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, + "node_modules/@bufbuild/protobuf": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-1.10.0.tgz", + "integrity": "sha512-QDdVFLoN93Zjg36NoQPZfsVH9tZew7wKDKyV5qRdj8ntT4wQCOradQjRaTdwMhWUYsgKsvCINKKm87FdEk96Ag==", + "dev": true, + "peer": true + }, "node_modules/@diplodoc/eslint-config": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@diplodoc/eslint-config/-/eslint-config-2.0.0.tgz", @@ -662,6 +673,125 @@ "prettier": "^3.0.3" } }, + "node_modules/@diplodoc/tabs-extension": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@diplodoc/tabs-extension/-/tabs-extension-3.1.1.tgz", + "integrity": "sha512-FWywClCNtMUQGZAsd6Hr/Cs1TX9aOJ4t9SOR9pIuOVsJwVWXNihdUW7x2yaAT0WwP4bBqXg7GSUQ/DIVIde9Ww==", + "dev": true, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + } + } + }, + "node_modules/@diplodoc/transform": { + "version": "4.20.0", + "resolved": "https://registry.npmjs.org/@diplodoc/transform/-/transform-4.20.0.tgz", + "integrity": "sha512-9VVTLE17DgoTyWHzPXlMD1kKHBpxXXMfO/Ey1qSTqEg48SWPF38/lOozyV5w79H2KkzEy788WZuUSFxdk4bCnw==", + "dev": true, + "dependencies": { + "@diplodoc/tabs-extension": "^3.0.0", + "chalk": "^4.1.2", + "cheerio": "^1.0.0-rc.12", + "css": "^3.0.0", + "cssfilter": "0.0.10", + "get-root-node-polyfill": "1.0.0", + "github-slugger": "^1.5.0", + "js-yaml": "^4.1.0", + "lodash": "4.17.21", + "markdown-it": "^13.0.2", + "markdown-it-attrs": "4.1.4", + "markdown-it-deflist": "2.1.0", + "markdown-it-meta": "0.0.1", + "markdown-it-sup": "1.0.0", + "markdownlint": "^0.32.1", + "markdownlint-rule-helpers": "0.17.2", + "sanitize-html": "^2.11.0", + "slugify": "1.6.5", + "svgo": "^3.2.0" + }, + "peerDependencies": { + "highlight.js": "^10.0.3 || ^11" + }, + "peerDependenciesMeta": { + "highlight.js": { + "optional": true + } + } + }, + "node_modules/@diplodoc/transform/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@diplodoc/transform/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@diplodoc/transform/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@diplodoc/transform/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@diplodoc/transform/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@diplodoc/transform/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/@diplodoc/tsconfig": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@diplodoc/tsconfig/-/tsconfig-1.0.2.tgz", @@ -2126,6 +2256,15 @@ "node": ">= 10" } }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -2233,6 +2372,28 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, + "node_modules/@types/linkify-it": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.5.tgz", + "integrity": "sha512-yg6E+u0/+Zjva+buc3EIb+29XEg4wltq7cSmd4Uc2EE/1nUVmxyzpX6gUXD0V8jIrG0r7YeOGVIbYRkxeooCtw==", + "dev": true + }, + "node_modules/@types/markdown-it": { + "version": "13.0.8", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-13.0.8.tgz", + "integrity": "sha512-V+KmpgiipS+zoypeUSS9ojesWtY/0k4XfqcK2fnVrX/qInJhX7rsCxZ/rygiPH2zxlPPrhfuW0I6ddMcWTKLsg==", + "dev": true, + "dependencies": { + "@types/linkify-it": "^3", + "@types/mdurl": "^1" + } + }, + "node_modules/@types/mdurl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.5.tgz", + "integrity": "sha512-6L6VymKTzYSrEf4Nev4Xa1LCHKrlTlYCBMTlQKFuddo1CvQcE52I0mwfOJayueUC7MJuXOeHTcIU683lzd0cUA==", + "dev": true + }, "node_modules/@types/node": { "version": "20.14.10", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", @@ -2862,6 +3023,18 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "dev": true }, + "node_modules/atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true, + "bin": { + "atob": "bin/atob.js" + }, + "engines": { + "node": ">= 4.5.0" + } + }, "node_modules/available-typed-arrays": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", @@ -3078,6 +3251,24 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true + }, "node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -3152,6 +3343,13 @@ "node-int64": "^0.4.0" } }, + "node_modules/buffer-builder": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/buffer-builder/-/buffer-builder-0.2.0.tgz", + "integrity": "sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg==", + "dev": true, + "peer": true + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -3238,6 +3436,80 @@ "node": ">=10" } }, + "node_modules/cheerio": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", + "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", + "dev": true, + "dependencies": { + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "htmlparser2": "^8.0.1", + "parse5": "^7.0.0", + "parse5-htmlparser2-tree-adapter": "^7.0.0" + }, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" + } + }, + "node_modules/cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/ci-info": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", @@ -3316,6 +3588,15 @@ "node": ">= 0.8" } }, + "node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -3433,6 +3714,97 @@ "node": ">= 8" } }, + "node_modules/css": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/css/-/css-3.0.0.tgz", + "integrity": "sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.4", + "source-map": "^0.6.1", + "source-map-resolve": "^0.6.0" + } + }, + "node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "dev": true, + "dependencies": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "dev": true, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/cssfilter": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/cssfilter/-/cssfilter-0.0.10.tgz", + "integrity": "sha512-FAaLDaplstoRsDR8XGYH51znUN0UY7nMc6Z9/fvE8EXGwvJE9hu7W2vHwx1+bd6gCYnln9nLbzxFTrcO9YQDZw==", + "dev": true + }, + "node_modules/csso": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", + "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", + "dev": true, + "dependencies": { + "css-tree": "~2.2.0" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", + "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", + "dev": true, + "dependencies": { + "mdn-data": "2.0.28", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.28", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", + "dev": true + }, "node_modules/cssom": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", @@ -3551,6 +3923,15 @@ "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", "dev": true }, + "node_modules/decode-uri-component": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, "node_modules/dedent": { "version": "1.5.3", "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", @@ -3697,6 +4078,32 @@ "node": ">=6.0.0" } }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dev": true, + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, "node_modules/domexception": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", @@ -3710,6 +4117,35 @@ "node": ">=12" } }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dev": true, + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "dev": true, + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, "node_modules/ejs": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", @@ -4000,6 +4436,21 @@ "@esbuild/win32-x64": "0.22.0" } }, + "node_modules/esbuild-sass-plugin": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/esbuild-sass-plugin/-/esbuild-sass-plugin-3.3.1.tgz", + "integrity": "sha512-SnO1ls+d52n6j8gRRpjexXI8MsHEaumS0IdDHaYM29Y6gakzZYMls6i9ql9+AWMSQk/eryndmUpXEgT34QrX1A==", + "dev": true, + "dependencies": { + "resolve": "^1.22.8", + "safe-identifier": "^0.4.2", + "sass": "^1.71.1" + }, + "peerDependencies": { + "esbuild": ">=0.20.1", + "sass-embedded": "^1.71.1" + } + }, "node_modules/escalade": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", @@ -5023,6 +5474,12 @@ "node": ">=8.0.0" } }, + "node_modules/get-root-node-polyfill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-root-node-polyfill/-/get-root-node-polyfill-1.0.0.tgz", + "integrity": "sha512-AzucsG1DdepagLF8tkxfjUqn3cCQ63MgH/tBWwPSy0BIDt8iLFZYDwnTxA08d+zdgL8l2dkPdZDe+Qkd+RMl9Q==", + "dev": true + }, "node_modules/get-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", @@ -5064,7 +5521,13 @@ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, - "node_modules/glob": { + "node_modules/github-slugger": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.5.0.tgz", + "integrity": "sha512-wIh+gKBI9Nshz2o46B0B3f5k/W+WI9ZAv6y5Dn5WJ5SK1t0TnDimB4WE5rmTD05ZAIn8HALCZVmCsvj0w0v0lw==", + "dev": true + }, + "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", @@ -5293,6 +5756,25 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, + "node_modules/htmlparser2": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", + "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "entities": "^4.4.0" + } + }, "node_modules/http-proxy-agent": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", @@ -5365,6 +5847,12 @@ "node": ">= 4" } }, + "node_modules/immutable": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.6.tgz", + "integrity": "sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ==", + "dev": true + }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -5505,6 +5993,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-boolean-object": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", @@ -5701,6 +6201,15 @@ "node": ">=8" } }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-potential-custom-element-name": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", @@ -7887,6 +8396,15 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true }, + "node_modules/linkify-it": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-4.0.1.tgz", + "integrity": "sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==", + "dev": true, + "dependencies": { + "uc.micro": "^1.0.1" + } + }, "node_modules/load-json-file": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", @@ -7917,6 +8435,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -7992,6 +8516,135 @@ "tmpl": "1.0.5" } }, + "node_modules/markdown-it": { + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-13.0.2.tgz", + "integrity": "sha512-FtwnEuuK+2yVU7goGn/MJ0WBZMM9ZPgU9spqlFs7/A/pDIUNSOQZhUgOqYCficIuR2QaFnrt8LHqBWsbTAoI5w==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1", + "entities": "~3.0.1", + "linkify-it": "^4.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "bin": { + "markdown-it": "bin/markdown-it.js" + } + }, + "node_modules/markdown-it-attrs": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/markdown-it-attrs/-/markdown-it-attrs-4.1.4.tgz", + "integrity": "sha512-53Zfv8PTb6rlVFDlD106xcZHKBSsRZKJ2IW/rTxEJBEVbVaoxaNsmRkG0HXfbHl2SK8kaxZ2QKqdthWy/QBwmA==", + "dev": true, + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "markdown-it": ">= 9.0.0" + } + }, + "node_modules/markdown-it-deflist": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/markdown-it-deflist/-/markdown-it-deflist-2.1.0.tgz", + "integrity": "sha512-3OuqoRUlSxJiuQYu0cWTLHNhhq2xtoSFqsZK8plANg91+RJQU1ziQ6lA2LzmFAEes18uPBsHZpcX6We5l76Nzg==", + "dev": true + }, + "node_modules/markdown-it-meta": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/markdown-it-meta/-/markdown-it-meta-0.0.1.tgz", + "integrity": "sha512-sCQG7mHJM3i4l6MztgzxE8t3aTQB5CSCO0wq8k6CEaqud40eryWXqPesq5AyztbYgwnxJcNIsmFsKDRkrl6Zuw==", + "dev": true, + "dependencies": { + "js-yaml": "^3.8.1" + } + }, + "node_modules/markdown-it-meta/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/markdown-it-meta/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/markdown-it-sup": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/markdown-it-sup/-/markdown-it-sup-1.0.0.tgz", + "integrity": "sha512-E32m0nV9iyhRR7CrhnzL5msqic7rL1juWre6TQNxsnApg7Uf+F97JOKxUijg5YwXz86lZ0mqfOnutoryyNdntQ==", + "dev": true + }, + "node_modules/markdown-it/node_modules/entities": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", + "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/markdownlint": { + "version": "0.32.1", + "resolved": "https://registry.npmjs.org/markdownlint/-/markdownlint-0.32.1.tgz", + "integrity": "sha512-3sx9xpi4xlHlokGyHO9k0g3gJbNY4DI6oNEeEYq5gQ4W7UkiJ90VDAnuDl2U+yyXOUa6BX+0gf69ZlTUGIBp6A==", + "dev": true, + "dependencies": { + "markdown-it": "13.0.2", + "markdownlint-micromark": "0.1.7" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/DavidAnson" + } + }, + "node_modules/markdownlint-micromark": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/markdownlint-micromark/-/markdownlint-micromark-0.1.7.tgz", + "integrity": "sha512-BbRPTC72fl5vlSKv37v/xIENSRDYL/7X/XoFzZ740FGEbs9vZerLrIkFRY0rv7slQKxDczToYuMmqQFN61fi4Q==", + "dev": true, + "engines": { + "node": ">=16" + } + }, + "node_modules/markdownlint-rule-helpers": { + "version": "0.17.2", + "resolved": "https://registry.npmjs.org/markdownlint-rule-helpers/-/markdownlint-rule-helpers-0.17.2.tgz", + "integrity": "sha512-XaeoW2NYSlWxMCZM2B3H7YTG6nlaLfkEZWMBhr4hSPlq9MuY2sy83+Xr89jXOqZMZYjvi5nBCGoFh7hHoPKZmA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "dev": true + }, + "node_modules/mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", + "dev": true + }, "node_modules/memorystream": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", @@ -8089,6 +8742,24 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -8269,6 +8940,18 @@ "node": ">=8" } }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, "node_modules/nwsapi": { "version": "2.2.12", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.12.tgz", @@ -8524,6 +9207,12 @@ "node": ">=4" } }, + "node_modules/parse-srcset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz", + "integrity": "sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==", + "dev": true + }, "node_modules/parse5": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", @@ -8536,6 +9225,19 @@ "url": "https://github.com/inikulin/parse5?sponsor=1" } }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", + "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", + "dev": true, + "dependencies": { + "domhandler": "^5.0.2", + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -8699,6 +9401,34 @@ "node": ">= 0.4" } }, + "node_modules/postcss": { + "version": "8.4.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.39.tgz", + "integrity": "sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.1", + "source-map-js": "^1.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -8880,6 +9610,18 @@ "node": ">=4" } }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/reflect.getprototypeof": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", @@ -9057,6 +9799,16 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dev": true, + "peer": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, "node_modules/safe-array-concat": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", @@ -9075,6 +9827,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/safe-identifier": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/safe-identifier/-/safe-identifier-0.4.2.tgz", + "integrity": "sha512-6pNbSMW6OhAi9j+N8V+U715yBQsaWJ7eyEUaOrawX+isg5ZxhUlV1NipNtgaKHmFGiABwt+ZF04Ii+3Xjkg+8w==", + "dev": true + }, "node_modules/safe-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-2.1.1.tgz", @@ -9107,6 +9865,440 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, + "node_modules/sanitize-html": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.13.0.tgz", + "integrity": "sha512-Xff91Z+4Mz5QiNSLdLWwjgBDm5b1RU6xBT0+12rapjiaR7SwfRdjw8f+6Rir2MXKLrDicRFHdb51hGOAxmsUIA==", + "dev": true, + "dependencies": { + "deepmerge": "^4.2.2", + "escape-string-regexp": "^4.0.0", + "htmlparser2": "^8.0.0", + "is-plain-object": "^5.0.0", + "parse-srcset": "^1.0.2", + "postcss": "^8.3.11" + } + }, + "node_modules/sanitize-html/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/sass": { + "version": "1.77.8", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.77.8.tgz", + "integrity": "sha512-4UHg6prsrycW20fqLGPShtEvo/WyHRVRHwOP4DzkUrObWoWI05QBSfzU71TVB7PFaL104TwNaHpjlWXAZbQiNQ==", + "dev": true, + "dependencies": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded": { + "version": "1.77.8", + "resolved": "https://registry.npmjs.org/sass-embedded/-/sass-embedded-1.77.8.tgz", + "integrity": "sha512-WGXA6jcaoBo5Uhw0HX/s6z/sl3zyYQ7ZOnLOJzqwpctFcFmU4L07zn51e2VSkXXFpQZFAdMZNqOGz/7h/fvcRA==", + "dev": true, + "peer": true, + "dependencies": { + "@bufbuild/protobuf": "^1.0.0", + "buffer-builder": "^0.2.0", + "immutable": "^4.0.0", + "rxjs": "^7.4.0", + "supports-color": "^8.1.1", + "varint": "^6.0.0" + }, + "engines": { + "node": ">=16.0.0" + }, + "optionalDependencies": { + "sass-embedded-android-arm": "1.77.8", + "sass-embedded-android-arm64": "1.77.8", + "sass-embedded-android-ia32": "1.77.8", + "sass-embedded-android-x64": "1.77.8", + "sass-embedded-darwin-arm64": "1.77.8", + "sass-embedded-darwin-x64": "1.77.8", + "sass-embedded-linux-arm": "1.77.8", + "sass-embedded-linux-arm64": "1.77.8", + "sass-embedded-linux-ia32": "1.77.8", + "sass-embedded-linux-musl-arm": "1.77.8", + "sass-embedded-linux-musl-arm64": "1.77.8", + "sass-embedded-linux-musl-ia32": "1.77.8", + "sass-embedded-linux-musl-x64": "1.77.8", + "sass-embedded-linux-x64": "1.77.8", + "sass-embedded-win32-arm64": "1.77.8", + "sass-embedded-win32-ia32": "1.77.8", + "sass-embedded-win32-x64": "1.77.8" + } + }, + "node_modules/sass-embedded-android-arm": { + "version": "1.77.8", + "resolved": "https://registry.npmjs.org/sass-embedded-android-arm/-/sass-embedded-android-arm-1.77.8.tgz", + "integrity": "sha512-GpGL7xZ7V1XpFbnflib/NWbM0euRzineK0iwoo31/ntWKAXGj03iHhGzkSiOwWSFcXgsJJi3eRA5BTmBvK5Q+w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "peer": true, + "bin": { + "sass": "dart-sass/sass" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-android-arm64": { + "version": "1.77.8", + "resolved": "https://registry.npmjs.org/sass-embedded-android-arm64/-/sass-embedded-android-arm64-1.77.8.tgz", + "integrity": "sha512-EmWHLbEx0Zo/f/lTFzMeH2Du+/I4RmSRlEnERSUKQWVp3aBSO04QDvdxfFezgQ+2Yt/ub9WMqBpma9P/8MPsLg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "peer": true, + "bin": { + "sass": "dart-sass/sass" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-android-ia32": { + "version": "1.77.8", + "resolved": "https://registry.npmjs.org/sass-embedded-android-ia32/-/sass-embedded-android-ia32-1.77.8.tgz", + "integrity": "sha512-+GjfJ3lDezPi4dUUyjQBxlNKXNa+XVWsExtGvVNkv1uKyaOxULJhubVo2G6QTJJU0esJdfeXf5Ca5/J0ph7+7w==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "peer": true, + "bin": { + "sass": "dart-sass/sass" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-android-x64": { + "version": "1.77.8", + "resolved": "https://registry.npmjs.org/sass-embedded-android-x64/-/sass-embedded-android-x64-1.77.8.tgz", + "integrity": "sha512-YZbFDzGe5NhaMCygShqkeCWtzjhkWxGVunc7ULR97wmxYPQLPeVyx7XFQZc84Aj0lKAJBJS4qRZeqphMqZEJsQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "peer": true, + "bin": { + "sass": "dart-sass/sass" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-darwin-arm64": { + "version": "1.77.8", + "resolved": "https://registry.npmjs.org/sass-embedded-darwin-arm64/-/sass-embedded-darwin-arm64-1.77.8.tgz", + "integrity": "sha512-aifgeVRNE+i43toIkDFFJc/aPLMo0PJ5s5hKb52U+oNdiJE36n65n2L8F/8z3zZRvCa6eYtFY2b7f1QXR3B0LA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "bin": { + "sass": "dart-sass/sass" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-darwin-x64": { + "version": "1.77.8", + "resolved": "https://registry.npmjs.org/sass-embedded-darwin-x64/-/sass-embedded-darwin-x64-1.77.8.tgz", + "integrity": "sha512-/VWZQtcWIOek60Zj6Sxk6HebXA1Qyyt3sD8o5qwbTgZnKitB1iEBuNunyGoAgMNeUz2PRd6rVki6hvbas9hQ6w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "bin": { + "sass": "dart-sass/sass" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-arm": { + "version": "1.77.8", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-arm/-/sass-embedded-linux-arm-1.77.8.tgz", + "integrity": "sha512-2edZMB6jf0whx3T0zlgH+p131kOEmWp+I4wnKj7ZMUeokiY4Up05d10hSvb0Q63lOrSjFAWu6P5/pcYUUx8arQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "bin": { + "sass": "dart-sass/sass" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-arm64": { + "version": "1.77.8", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-arm64/-/sass-embedded-linux-arm64-1.77.8.tgz", + "integrity": "sha512-6iIOIZtBFa2YfMsHqOb3qake3C9d/zlKxjooKKnTSo+6g6z+CLTzMXe1bOfayb7yxeenElmFoK1k54kWD/40+g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "bin": { + "sass": "dart-sass/sass" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-ia32": { + "version": "1.77.8", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-ia32/-/sass-embedded-linux-ia32-1.77.8.tgz", + "integrity": "sha512-63GsFFHWN5yRLTWiSef32TM/XmjhCBx1DFhoqxmj+Yc6L9Z1h0lDHjjwdG6Sp5XTz5EmsaFKjpDgnQTP9hJX3Q==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "bin": { + "sass": "dart-sass/sass" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-musl-arm": { + "version": "1.77.8", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm/-/sass-embedded-linux-musl-arm-1.77.8.tgz", + "integrity": "sha512-nFkhSl3uu9btubm+JBW7uRglNVJ8W8dGfzVqh3fyQJKS1oyBC3vT3VOtfbT9YivXk28wXscSHpqXZwY7bUuopA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-musl-arm64": { + "version": "1.77.8", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-arm64/-/sass-embedded-linux-musl-arm64-1.77.8.tgz", + "integrity": "sha512-j8cgQxNWecYK+aH8ESFsyam/Q6G+9gg8eJegiRVpA9x8yk3ykfHC7UdQWwUcF22ZcuY4zegrjJx8k+thsgsOVA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-musl-ia32": { + "version": "1.77.8", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-ia32/-/sass-embedded-linux-musl-ia32-1.77.8.tgz", + "integrity": "sha512-oWveMe+8TFlP8WBWPna/+Ec5TV0CE+PxEutyi0ltSruBds2zxRq9dPVOqrpPcDN9QUx50vNZC0Afgch0aQEd0g==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-musl-x64": { + "version": "1.77.8", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-musl-x64/-/sass-embedded-linux-musl-x64-1.77.8.tgz", + "integrity": "sha512-2NtRpMXHeFo9kaYxuZ+Ewwo39CE7BTS2JDfXkTjZTZqd8H+8KC53eBh516YQnn2oiqxSiKxm7a6pxbxGZGwXOQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-linux-x64": { + "version": "1.77.8", + "resolved": "https://registry.npmjs.org/sass-embedded-linux-x64/-/sass-embedded-linux-x64-1.77.8.tgz", + "integrity": "sha512-ND5qZLWUCpOn7LJfOf0gLSZUWhNIysY+7NZK1Ctq+pM6tpJky3JM5I1jSMplNxv5H3o8p80n0gSm+fcjsEFfjQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "bin": { + "sass": "dart-sass/sass" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-win32-arm64": { + "version": "1.77.8", + "resolved": "https://registry.npmjs.org/sass-embedded-win32-arm64/-/sass-embedded-win32-arm64-1.77.8.tgz", + "integrity": "sha512-7L8zT6xzEvTYj86MvUWnbkWYCNQP+74HvruLILmiPPE+TCgOjgdi750709BtppVJGGZSs40ZuN6mi/YQyGtwXg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "bin": { + "sass": "dart-sass/sass.bat" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-win32-ia32": { + "version": "1.77.8", + "resolved": "https://registry.npmjs.org/sass-embedded-win32-ia32/-/sass-embedded-win32-ia32-1.77.8.tgz", + "integrity": "sha512-7Buh+4bP0WyYn6XPbthkIa3M2vtcR8QIsFVg3JElVlr+8Ng19jqe0t0SwggDgbMX6AdQZC+Wj4F1BprZSok42A==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "bin": { + "sass": "dart-sass/sass.bat" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded-win32-x64": { + "version": "1.77.8", + "resolved": "https://registry.npmjs.org/sass-embedded-win32-x64/-/sass-embedded-win32-x64-1.77.8.tgz", + "integrity": "sha512-rZmLIx4/LLQm+4GW39sRJW0MIlDqmyV0fkRzTmhFP5i/wVC7cuj8TUubPHw18rv2rkHFfBZKZJTCkPjCS5Z+SA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "bin": { + "sass": "dart-sass/sass.bat" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-embedded/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/sass-embedded/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, "node_modules/saxes": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", @@ -9229,6 +10421,15 @@ "node": ">=8" } }, + "node_modules/slugify": { + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.5.tgz", + "integrity": "sha512-8mo9bslnBO3tr5PEVFzMPIWwWnipGS0xVbYf65zxDqfNwmzYn1LpiKNrR6DlClusuvo+hDHd1zKpmfAe83NQSQ==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -9238,6 +10439,26 @@ "node": ">=0.10.0" } }, + "node_modules/source-map-js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-resolve": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.6.0.tgz", + "integrity": "sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==", + "deprecated": "See https://github.com/lydell/source-map-resolve#deprecated", + "dev": true, + "dependencies": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0" + } + }, "node_modules/source-map-support": { "version": "0.5.13", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", @@ -9521,6 +10742,31 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/svgo": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.2.tgz", + "integrity": "sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==", + "dev": true, + "dependencies": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^5.1.0", + "css-tree": "^2.3.1", + "css-what": "^6.1.0", + "csso": "^5.0.5", + "picocolors": "^1.0.0" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/svgo" + } + }, "node_modules/symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", @@ -9869,6 +11115,12 @@ "node": ">=14.17" } }, + "node_modules/uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "dev": true + }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -9972,6 +11224,13 @@ "spdx-expression-parse": "^3.0.0" } }, + "node_modules/varint": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", + "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==", + "dev": true, + "peer": true + }, "node_modules/w3c-xmlserializer": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", diff --git a/package.json b/package.json index 261eb0f..a8bb256 100644 --- a/package.json +++ b/package.json @@ -2,8 +2,20 @@ "name": "@diplodoc/cut-extension", "version": "0.0.0", "description": "Cut extension for Diplodoc platform", - "main": "build/index.js", - "types": "build/index.d.ts", + "main": "build/plugin/index.js", + "types": "build/plugin/index.d.ts", + "exports": { + ".": { + "types": "./build/plugin/index.d.ts", + "default": "./build/plugin/index.js" + }, + "./runtime": { + "types": "./build/runtime/index.d.ts", + "style": "./build/runtime/index.css", + "default": "./build/runtime/index.js" + }, + "./runtime/styles.css": "./build/runtime/index.css" + }, "homepage": "https://diplodoc.com/", "repository": { "type": "git", @@ -23,7 +35,7 @@ "precommit": "npm run lint && npm run test", "build": "run-p build:*", "build:js": "./esbuild/build.mjs", - "build:declarations": "tsc --emitDeclarationOnly --outDir ./build/", + "build:declarations": "tsc --emitDeclarationOnly --outDir ./build", "lint": "eslint .", "lint:fix": "eslint --fix .", "test": "jest" @@ -31,12 +43,16 @@ "devDependencies": { "@diplodoc/eslint-config": "^2.0.0", "@diplodoc/prettier-config": "^2.0.0", + "@diplodoc/transform": "^4.20.0", "@diplodoc/tsconfig": "^1.0.2", "@types/jest": "^29.5.12", + "@types/markdown-it": "^13.0.8", "esbuild": "^0.22.0", + "esbuild-sass-plugin": "^3.3.1", "husky": "^9.0.11", "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", + "markdown-it": "^13.0.2", "npm-run-all": "^4.1.5", "ts-jest": "^29.2.2", "typescript": "^5.5.3" diff --git a/src/index.ts b/src/index.ts deleted file mode 100644 index 1432367..0000000 --- a/src/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -declare const someProp: unknown; - -console.log(someProp); diff --git a/src/plugin/const.ts b/src/plugin/const.ts new file mode 100644 index 0000000..67a8da6 --- /dev/null +++ b/src/plugin/const.ts @@ -0,0 +1,19 @@ +export const ENV_FLAG_NAME = 'has-yfm-cut'; + +export const TokenType = { + Cut: 'yfm_cut', + CutOpen: 'yfm_cut_open', + CutClose: 'yfm_cut_close', + Title: 'yfm_cut_title', + TitleOpen: 'yfm_cut_title_open', + TitleClose: 'yfm_cut_title_close', + Content: 'yfm_cut_content', + ContentOpen: 'yfm_cut_content_open', + ContentClose: 'yfm_cut_content_close', +} as const; + +export const ClassNames = { + Cut: 'yfm-cut', + Title: 'yfm-cut-title', + Content: 'yfm-cut-content', +} as const; diff --git a/src/plugin/helpers.ts b/src/plugin/helpers.ts new file mode 100644 index 0000000..bdfe90e --- /dev/null +++ b/src/plugin/helpers.ts @@ -0,0 +1,38 @@ +import type MdIt from 'markdown-it'; + +const CUT_REGEXP = /^{%\s*cut\s*["|'](.*)["|']\s*%}/; + +export function matchOpenToken(tokens: MdIt.Token[], i: number) { + return ( + tokens[i].type === 'paragraph_open' && + tokens[i + 1].type === 'inline' && + tokens[i + 1].content.match(CUT_REGEXP) + ); +} + +export function matchCloseToken(tokens: MdIt.Token[], i: number) { + return ( + tokens[i].type === 'paragraph_open' && + tokens[i + 1].type === 'inline' && + tokens[i + 1].content.trim() === '{% endcut %}' + ); +} + +export function findCloseTokenIdx(tokens: MdIt.Token[], idx: number) { + let level = 0; + let i = idx; + while (i < tokens.length) { + if (matchOpenToken(tokens, i)) { + level++; + } else if (matchCloseToken(tokens, i)) { + if (level === 0) { + return i; + } + level--; + } + + i++; + } + + return null; +} diff --git a/src/plugin/index.ts b/src/plugin/index.ts new file mode 100644 index 0000000..c871968 --- /dev/null +++ b/src/plugin/index.ts @@ -0,0 +1,3 @@ +export type {TransformOptions} from './transform'; +export {transform} from './transform'; +export {TokenType} from './const'; diff --git a/src/plugin/plugin.ts b/src/plugin/plugin.ts new file mode 100644 index 0000000..2d04d13 --- /dev/null +++ b/src/plugin/plugin.ts @@ -0,0 +1,80 @@ +import type MarkdownIt from 'markdown-it'; +import type Core from 'markdown-it/lib/parser_core'; + +import {ClassNames, ENV_FLAG_NAME, TokenType} from './const'; +import {findCloseTokenIdx, matchOpenToken} from './helpers'; + +export const cutPlugin: MarkdownIt.PluginSimple = (md) => { + const rule: Core.RuleCore = (state) => { + const tokens = state.tokens; + let i = 0; + + while (i < tokens.length) { + const match = matchOpenToken(tokens, i); + + if (match) { + const closeTokenIdx = findCloseTokenIdx(tokens, i + 4); + + if (!closeTokenIdx) { + i += 3; + continue; + } + + const newOpenToken = new state.Token(TokenType.CutOpen, 'div', 1); + newOpenToken.attrSet('class', ClassNames.Cut); + newOpenToken.map = tokens[i].map; + + const titleOpen = new state.Token(TokenType.TitleOpen, 'div', 1); + titleOpen.attrSet('class', ClassNames.Title); + + const titleInline = state.md.parseInline( + match[1] === undefined ? 'ad' : match[1], + state.env, + )[0]; + + const titleClose = new state.Token(TokenType.TitleClose, 'div', -1); + + const contentOpen = new state.Token(TokenType.ContentOpen, 'div', 1); + contentOpen.attrSet('class', ClassNames.Content); + + if (newOpenToken.map) { + const contentOpenStart = newOpenToken.map[0] + 1; + const contentOpenEnd = newOpenToken.map[0] + 2; + + contentOpen.map = [contentOpenStart, contentOpenEnd]; + } + + const contentClose = new state.Token(TokenType.ContentClose, 'div', -1); + + const newCloseToken = new state.Token(TokenType.CutClose, 'div', -1); + newCloseToken.map = tokens[closeTokenIdx].map; + + const insideTokens = [ + newOpenToken, + titleOpen, + titleInline, + titleClose, + contentOpen, + ...tokens.slice(i + 3, closeTokenIdx), + contentClose, + newCloseToken, + ]; + + tokens.splice(i, closeTokenIdx - i + 3, ...insideTokens); + + state.env ??= {}; + state.env[ENV_FLAG_NAME] = true; + + i++; + } else { + i++; + } + } + }; + + try { + md.core.ruler.before('curly_attributes', 'cut', rule); + } catch (e) { + md.core.ruler.push('cut', rule); + } +}; diff --git a/src/plugin/transform.ts b/src/plugin/transform.ts new file mode 100644 index 0000000..9f502a2 --- /dev/null +++ b/src/plugin/transform.ts @@ -0,0 +1,94 @@ +import type MarkdownIt from 'markdown-it'; +import {cutPlugin} from './plugin'; +import {type Runtime, copyRuntime, dynrequire, hidden} from './utils'; +import {ENV_FLAG_NAME} from './const'; + +export type TransformOptions = { + runtime?: + | string + | { + script: string; + style: string; + }; + bundle?: boolean; +}; + +type NormalizedPluginOptions = Omit & { + runtime: Runtime; +}; + +const registerTransform = ( + md: MarkdownIt, + { + runtime, + bundle, + output, + }: Pick & { + output: string; + }, +) => { + md.use(cutPlugin); + md.core.ruler.push('yfm_cut_after', ({env}) => { + hidden(env, 'bundled', new Set()); + + if (env?.[ENV_FLAG_NAME]) { + env.meta = env.meta || {}; + env.meta.script = env.meta.script || []; + env.meta.script.push(runtime.script); + env.meta.style = env.meta.style || []; + env.meta.style.push(runtime.style); + + if (bundle) { + copyRuntime({runtime, output}, env.bundled); + } + } + }); +}; + +type InputOptions = { + destRoot: string; +}; + +export function transform(options: Partial = {}) { + const {bundle = true} = options; + + if (bundle && typeof options.runtime === 'string') { + throw new TypeError('Option `runtime` should be record when `bundle` is enabled.'); + } + + const runtime: Runtime = + typeof options.runtime === 'string' + ? {script: options.runtime, style: options.runtime} + : options.runtime || { + script: '_assets/cut-extension.js', + style: '_assets/cut-extension.css', + }; + + const plugin: MarkdownIt.PluginWithOptions<{output?: string}> = function ( + md: MarkdownIt, + {output = '.'} = {}, + ) { + registerTransform(md, { + runtime, + bundle, + output, + }); + }; + + Object.assign(plugin, { + collect(input: string, {destRoot = '.'}: InputOptions) { + const MdIt = dynrequire('markdown-it'); + const md = new MdIt().use((md: MarkdownIt) => { + registerTransform(md, { + runtime, + bundle, + output: destRoot, + }); + }); + + md.parse(input, {}); + }, + }); + + return plugin; +} diff --git a/src/plugin/utils.ts b/src/plugin/utils.ts new file mode 100644 index 0000000..05a7df3 --- /dev/null +++ b/src/plugin/utils.ts @@ -0,0 +1,55 @@ +export function hidden, F extends string | symbol, V>( + box: B, + field: F, + value: V, +) { + if (!(field in box)) { + Object.defineProperty(box, field, { + enumerable: false, + value: value, + }); + } + + return box as B & {[P in F]: V}; +} + +export type Runtime = { + script: string; + style: string; +}; + +declare const __dirname: string; +export function copyRuntime( + {runtime, output}: {runtime: Runtime; output: string}, + cache: Set, +) { + const PATH_TO_RUNTIME = '../runtime'; + const {join, resolve} = dynrequire('node:path'); + const runtimeFiles = { + 'index.js': runtime.script, + 'index.css': runtime.style, + }; + for (const [originFile, outputFile] of Object.entries(runtimeFiles)) { + const file = join(PATH_TO_RUNTIME, originFile); + if (!cache.has(file)) { + cache.add(file); + copy(resolve(__dirname, file), join(output, outputFile)); + } + } +} + +export function copy(from: string, to: string) { + const {mkdirSync, copyFileSync} = dynrequire('node:fs'); + const {dirname} = dynrequire('node:path'); + + mkdirSync(dirname(to), {recursive: true}); + copyFileSync(from, to); +} + +/* + * Runtime require hidden for builders. + * Used for nodejs api + */ +export function dynrequire(module: string) { + return eval(`require('${module}')`); +} diff --git a/src/runtime/const.ts b/src/runtime/const.ts new file mode 100644 index 0000000..97352c9 --- /dev/null +++ b/src/runtime/const.ts @@ -0,0 +1,11 @@ +export const GLOBAL_KEY = 'yfm_cut'; + +export const Selector = { + CUT: '.yfm .yfm-cut', + TITLE: '.yfm .yfm-cut-title', + CONTENT: '.yfm .yfm-cut-content', +}; + +export const ClassName = { + OPEN: 'open', +}; diff --git a/src/runtime/contoller.ts b/src/runtime/contoller.ts new file mode 100644 index 0000000..53e5957 --- /dev/null +++ b/src/runtime/contoller.ts @@ -0,0 +1,48 @@ +import {ClassName, Selector} from './const'; +import {getEventTarget, isCustom} from './utils'; + +export class YfmCutContoller { + private readonly __doc: Document; + + constructor(doc: Document) { + this.__doc = doc; + this.__doc.addEventListener('click', this._onDocClick); + } + + destroy() { + this.__doc.removeEventListener('click', this._onDocClick); + } + + private _onDocClick = (event: MouseEvent) => { + if (isCustom(event)) { + return; + } + + const title = this._findTitleInPath(event); + if (title) { + this._toggleCut(title); + } + }; + + private _findTitleInPath(event: MouseEvent): HTMLElement | undefined { + const target = getEventTarget(event); + if (this._matchTitle(target)) { + return target as HTMLElement; + } + + const path = event.composedPath?.(); + return path?.find(this._matchTitle) as HTMLElement | undefined; + } + + private _matchTitle = (target: EventTarget | null) => { + if (target instanceof HTMLElement) { + return target?.matches?.(Selector.TITLE); + } + return false; + }; + + private _toggleCut(element: HTMLElement) { + const cutNode = element.parentElement; + cutNode?.classList.toggle(ClassName.OPEN); + } +} diff --git a/src/runtime/index.ts b/src/runtime/index.ts new file mode 100644 index 0000000..e1854c1 --- /dev/null +++ b/src/runtime/index.ts @@ -0,0 +1,14 @@ +import {GLOBAL_KEY} from './const'; +import {YfmCutContoller} from './contoller'; + +import './styles/cut.scss'; + +if (typeof window !== 'undefined' && typeof document !== 'undefined' && !window[GLOBAL_KEY]) { + window[GLOBAL_KEY] = new YfmCutContoller(document); +} + +declare global { + interface Window { + [GLOBAL_KEY]: YfmCutContoller; + } +} diff --git a/src/runtime/styles/cut.scss b/src/runtime/styles/cut.scss new file mode 100644 index 0000000..a503b05 --- /dev/null +++ b/src/runtime/styles/cut.scss @@ -0,0 +1,54 @@ +.yfm-cut { + $class: &; + + margin-bottom: 15px; + + &-title { + cursor: pointer; + position: relative; + user-select: none; + padding: 5px 0 5px 30px; + + &:before { + content: ''; + z-index: 1; + left: 0; + top: 50%; + background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNiAxNiI+CiAgICA8cGF0aCBzdHJva2U9ImN1cnJlbnRDb2xvciIgZmlsbD0ibm9uZSIgZD0iTTMgNmw1IDUgNS01Ii8+Cjwvc3ZnPgo="); + transform: translateY(-50%) rotate(-90deg); + transition: transform 0.3s ease; + height: 20px; + width: 20px; + position: absolute; + } + } + + &-content { + display: none; + overflow: hidden; + transition: height 0.3s ease-in-out; + } + + &.open { + > #{$class}-content { + display: revert; + padding: 5px 0 15px 30px; + } + + > #{$class}-title:before { + transform: translateY(-50%); + } + } + + .yfm:not(.yfm_no-list-reset) & ol { + counter-reset: cut-list; + + & > li { + counter-increment: cut-list; + + &::before { + content: counters(cut-list, '.') '. '; + } + } + } +} diff --git a/src/runtime/utils.ts b/src/runtime/utils.ts new file mode 100644 index 0000000..1dbe970 --- /dev/null +++ b/src/runtime/utils.ts @@ -0,0 +1,9 @@ +export const getEventTarget = (event: Event) => { + const path = event.composedPath(); + return Array.isArray(path) && path.length > 0 ? path[0] : event.target; +}; + +export const isCustom = (event: Event) => { + const target = getEventTarget(event); + return !target || !(target as HTMLElement).matches; +}; diff --git a/tests/index.test.ts b/tests/index.test.ts deleted file mode 100644 index ffa1724..0000000 --- a/tests/index.test.ts +++ /dev/null @@ -1,5 +0,0 @@ -describe('index', () => { - it('should be null', () => { - expect(null).toBeNull(); - }); -}); diff --git a/tests/plugin.test.ts b/tests/plugin.test.ts new file mode 100644 index 0000000..7ac01b0 --- /dev/null +++ b/tests/plugin.test.ts @@ -0,0 +1,184 @@ +import transform from '@diplodoc/transform'; + +import * as cutExtension from '../src/plugin'; + +const transformYfm = (text: string, opts?: cutExtension.TransformOptions) => { + const { + result, + } = transform(text, { + plugins: [cutExtension.transform({bundle: false, ...opts})], + }); + return result; +}; + +describe('Cut extension - plugin', () => { + it('should render simple cut', () => { + expect( + transformYfm( + '{% cut "Cut title" %}\n' + '\n' + 'Cut content\n' + '\n' + '{% endcut %}', + ).html.replace(/(\r\n|\n|\r)/gm, ''), + ).toBe( + '
Cut title
' + + '

Cut content

' + + '
', + ); + }); + + it('should render simple cut with code in it', () => { + expect( + transformYfm( + '{% cut "Cut title" %}\n' + + '\n' + + '```\n' + + 'Code\n' + + '```\n' + + '\n' + + '{% endcut %}', + ).html.replace(/(\r\n|\n|\r)/gm, ''), + ).toBe( + '
Cut title
' + + '
Code
' + + '
', + ); + }); + + it('should render siblings cuts', () => { + expect( + transformYfm( + '{% cut "Cut title 1" %}\n' + + '\n' + + 'Cut content 1\n' + + '\n' + + '{% endcut %}\n' + + '\n' + + '{% cut "Cut title 2" %}\n' + + '\n' + + 'Cut content 2\n' + + '\n' + + '{% endcut %}', + ).html.replace(/(\r\n|\n|\r)/gm, ''), + ).toBe( + '
Cut title 1
' + + '

Cut content 1

' + + '
' + + '
Cut title 2
' + + '

Cut content 2

' + + '
', + ); + }); + + it('should render nested cuts', () => { + expect( + transformYfm( + '{% cut "Outer title" %}\n' + + '\n' + + 'Outer content\n' + + '\n' + + '{% cut "Inner title" %}\n' + + '\n' + + 'Inner content\n' + + '\n' + + '{% endcut %}\n' + + '\n' + + '{% endcut %}', + ).html.replace(/(\r\n|\n|\r)/gm, ''), + ).toBe( + '
Outer title
' + + '

Outer content

' + + '
Inner title
' + + '

Inner content

' + + '
', + ); + }); + + it('should render title with format', () => { + expect( + transformYfm( + '{% cut "**Strong cut title**" %}\n' + + '\n' + + 'Content we want to hide\n' + + '\n' + + '{% endcut %}', + ).html.replace(/(\r\n|\n|\r)/gm, ''), + ).toBe( + '
' + + '
Strong cut title
' + + '

Content we want to hide

' + + '
', + ); + }); + + it('should close all tags correctly and insert two p tags', () => { + expect( + transformYfm( + '* {% cut "Cut 1" %}\n' + + '\n' + + ' Some text\n' + + '\n' + + ' Some text\n' + + '\n' + + '{% endcut %}', + ).html.replace(/(\r\n|\n|\r)/gm, ''), + ).toBe( + '
  • Cut 1
    ' + + '

    Some text

    Some text

', + ); + }); + + it('should close all tags correctly when given a bullet-list with several items', () => { + expect( + transformYfm( + '* {% cut "Cut 1" %}\n' + + '\n' + + ' Some text\n' + + '\n' + + ' {% endcut %}' + + '\n' + + '* {% cut "Cut 2" %}\n' + + '\n' + + ' Some text\n' + + '\n' + + ' {% endcut %}' + + '\n' + + '* {% cut "Cut 3" %}\n' + + '\n' + + ' Some text\n' + + '\n' + + '{% endcut %}', + ).html.replace(/(\r\n|\n|\r)/gm, ''), + ).toBe( + '
  • Cut 1
    ' + + '

    Some text

  • ' + + '
  • Cut 2
    ' + + '

    Some text

  • ' + + '
  • Cut 3
    ' + + '

    Some text

', + ); + }); + + it('should dont add assets to meta if no yfm-cut is found', () => { + const markup = 'paragraph'; + expect(transformYfm(markup).meta).toBeUndefined(); + }); + + it('should add default assets to meta', () => { + const markup = '{% cut "Cut title" %}\n' + '\n' + 'Cut content\n' + '\n' + '{% endcut %}'; + expect( + transformYfm(markup).meta + ).toStrictEqual({ script: ['_assets/cut-extension.js'], style: ['_assets/cut-extension.css'] }); + }); + + it('should add custom assets to meta', () => { + const markup = '{% cut "Cut title" %}\n' + '\n' + 'Cut content\n' + '\n' + '{% endcut %}'; + expect( + transformYfm(markup, {runtime: 'yfm-cut'}).meta + ).toStrictEqual({ script: ['yfm-cut'], style: ['yfm-cut'] }); + }); + + it('should add custom assets to meta 2', () => { + const markup = '{% cut "Cut title" %}\n' + '\n' + 'Cut content\n' + '\n' + '{% endcut %}'; + expect( + transformYfm(markup, {runtime: {script: 'yfm-cut.script', style: 'yfm-cut.style'}}).meta + ).toStrictEqual({ script: ['yfm-cut.script'], style: ['yfm-cut.style'] }); + }); +});