From a4ee38540d547fdc14039077ec3289f62c3a519d Mon Sep 17 00:00:00 2001 From: "Jonathan Pallant (Ferrous Systems)" Date: Wed, 22 Mar 2023 10:28:51 +0000 Subject: [PATCH] Ensure marp can render slides. We bundle markdown-it-kroki, which can add mermaid diagrams to marp slides using https://kroki.io. --- down-the-stack-book/README.md | 11 ++ down-the-stack-book/marp.config.js | 6 + .../node_modules/.package-lock.json | 13 ++ .../markdown-it-kroki/CHANGELOG.md | 17 ++ .../@kazumatu981/markdown-it-kroki/LICENSE | 21 +++ .../@kazumatu981/markdown-it-kroki/README.md | 157 +++++++++++++++ .../markdown-it-kroki/demo/marp.config.js | 8 + .../markdown-it-kroki/demo/test.md | 59 ++++++ .../markdown-it-kroki/img/plantuml-sample.png | Bin 0 -> 30545 bytes .../@kazumatu981/markdown-it-kroki/index.js | 6 + .../markdown-it-kroki/lib/contract.js | 37 ++++ .../markdown-it-kroki/lib/diagram-encoder.js | 27 +++ .../lib/obs/marp-it-kroki.js | 52 +++++ .../markdown-it-kroki/lib/plugin-core.js | 74 ++++++++ .../markdown-it-kroki/lib/safe-property.js | 18 ++ .../markdown-it-kroki/lib/support.js | 54 ++++++ .../markdown-it-kroki/package.json | 35 ++++ .../tests/securitytest/security.test.js | 94 +++++++++ .../tests/totaltest/canrender.test.js | 96 ++++++++++ .../tests/unittest/conract.test.js | 35 ++++ .../tests/unittest/diagram-encoder.test.js | 75 ++++++++ .../plugin-core.buuildEmbedHTML.test.js | 146 ++++++++++++++ .../unittest/plugin-core.setOptions.test.js | 178 ++++++++++++++++++ .../plugin-core.static-methods.test.js | 49 +++++ .../tests/unittest/safe-property.test.js | 120 ++++++++++++ down-the-stack-book/package-lock.json | 18 ++ down-the-stack-book/package.json | 5 + 27 files changed, 1411 insertions(+) create mode 100644 down-the-stack-book/README.md create mode 100644 down-the-stack-book/marp.config.js create mode 100644 down-the-stack-book/node_modules/.package-lock.json create mode 100644 down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/CHANGELOG.md create mode 100644 down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/LICENSE create mode 100644 down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/README.md create mode 100644 down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/demo/marp.config.js create mode 100644 down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/demo/test.md create mode 100644 down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/img/plantuml-sample.png create mode 100644 down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/index.js create mode 100644 down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/lib/contract.js create mode 100644 down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/lib/diagram-encoder.js create mode 100644 down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/lib/obs/marp-it-kroki.js create mode 100644 down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/lib/plugin-core.js create mode 100644 down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/lib/safe-property.js create mode 100644 down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/lib/support.js create mode 100644 down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/package.json create mode 100644 down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/tests/securitytest/security.test.js create mode 100644 down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/tests/totaltest/canrender.test.js create mode 100644 down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/tests/unittest/conract.test.js create mode 100644 down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/tests/unittest/diagram-encoder.test.js create mode 100644 down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/tests/unittest/plugin-core.buuildEmbedHTML.test.js create mode 100644 down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/tests/unittest/plugin-core.setOptions.test.js create mode 100644 down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/tests/unittest/plugin-core.static-methods.test.js create mode 100644 down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/tests/unittest/safe-property.test.js create mode 100644 down-the-stack-book/package-lock.json create mode 100644 down-the-stack-book/package.json diff --git a/down-the-stack-book/README.md b/down-the-stack-book/README.md new file mode 100644 index 0000000..d156996 --- /dev/null +++ b/down-the-stack-book/README.md @@ -0,0 +1,11 @@ +# Down the Stack Slides + +To read as an mdbook: + +1. `cargo install mdbook` +2. `mdbook serve` + +To read as a slide-show: + +1. Download [marp-cli](https://github.com/marp-team/marp-cli/releases) and unpack into your `$PATH` +2. `marp -c marp.config.js -I . -s` diff --git a/down-the-stack-book/marp.config.js b/down-the-stack-book/marp.config.js new file mode 100644 index 0000000..6fd55d6 --- /dev/null +++ b/down-the-stack-book/marp.config.js @@ -0,0 +1,6 @@ +module.exports = { + inputDir: './slides', + engine: ({ marp }) => marp.use(require('@kazumatu981/markdown-it-kroki'), { + entrypoint: "https://kroki.io", + }) +} diff --git a/down-the-stack-book/node_modules/.package-lock.json b/down-the-stack-book/node_modules/.package-lock.json new file mode 100644 index 0000000..6503422 --- /dev/null +++ b/down-the-stack-book/node_modules/.package-lock.json @@ -0,0 +1,13 @@ +{ + "name": "down-the-stack-book", + "lockfileVersion": 3, + "requires": true, + "packages": { + "node_modules/@kazumatu981/markdown-it-kroki": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@kazumatu981/markdown-it-kroki/-/markdown-it-kroki-1.1.1.tgz", + "integrity": "sha512-LDYl+mV2WogLQ5r4olxovm+gphL/MNGfWZ1M1woBO/YhFnfwdn5EAUu9zF/KoVZzytJPq0RNfyeDtMkv+GJihg==", + "dev": true + } + } +} diff --git a/down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/CHANGELOG.md b/down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/CHANGELOG.md new file mode 100644 index 0000000..ca902a6 --- /dev/null +++ b/down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/CHANGELOG.md @@ -0,0 +1,17 @@ +# CHANGELOG + +## v1.1.1 + +* fix readme, see [this issue](https://github.com/kazumatu981/markdown-it-kroki/issues/1) + +## v1.1.0 + +* Obsolated Option `marpAutoScaling` and detect automatically wether it is nessesury or not. + +## v1.0.1 + +release on npm + +## v1.0.0 + +create new diff --git a/down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/LICENSE b/down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/LICENSE new file mode 100644 index 0000000..9cf3147 --- /dev/null +++ b/down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Kazuyoshi Matsumoto + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/README.md b/down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/README.md new file mode 100644 index 0000000..ec7ffe7 --- /dev/null +++ b/down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/README.md @@ -0,0 +1,157 @@ +# markdown-it-kroki + +> This library was designed to embed [Kori.io](https://kroki.io/) diagram into [Marp](https://marp.app/) Slide-deks!! + + +This library is a pugin for markdown-it to embed figure is created by textual syntax. +To use this package, You can embed **Software Diagram** (like uml) is written by **code** in Marp Slides-deck. + +See marp sample code. + +## Sample + + --- + marp: true + --- + + + ## plantuml + + ```plantuml[platuml image] + @startuml + left to right direction + actor Guest as g + package Professional { + actor Chef as c + actor "Food Critic" as fc + } + package Restaurant { + usecase "Eat Food" as UC1 + usecase "Pay for Food" as UC2 + usecase "Drink" as UC3 + usecase "Review" as UC4 + } + fc --> UC4 + g --> UC1 + g --> UC2 + g --> UC3 + @enduml + ``` + +![plantuml-sample](img/plantuml-sample.png) + +If you want to write daigram, you write Diagram Language (like [plantuml](https://plantuml.com/), [mermaid.js](https://mermaid-js.github.io/mermaid/#/)) with in fenced code block. + +## How to install + +You can install `npm install` command like bellow. + +```bash +npm install -D @kazumatu981/markdown-it-kroki +``` + +## How to use + +Here is the how to use `markdow-it-kroki`. +This section introduce how to create Marp slides-deck project, +and introduce how to create Marp slides-deck server. + +You can find deltail info in [here](https://marp.app/), +and you can learn about marp plugin eco-system, [here](https://marpit.marp.app/usage?id=extend-marpit-by-plugins). + +### **[1st step]** Create Slides-deck project + +First, for create slides-deck, you have to prepair to **Marp Project** directory. +So First, Create slides-deck project, and init npm package. + +```bash +mkdir myslides +cd myslides + +npm init -y +``` + +Secondary, Build Marp Environment. +Install [@marp-team/marp-cli](https://github.com/marp-team/marp-cli). + +```bash +npm install -D @marp-team/marp-cli +``` + +> Off-course you can install as **global package** (like `npm install -g @marp-team/marp-cli`), or **run at-once** (like `npx`). + +### **[2nd step]** Download this project and install + +```bash +git clone https://github.com/kazumatu981/markdown-it-kroki.git + +cd myslides +npm install -D path/to/markdown-it-kroki +``` + + +### **[3rd step]** Create `marp.config.js`. + +Here is the configuration file for **Marp**. + +```javascript +module.exports = { + inputDir: './slides', + engine: ({ marp }) => marp.use(require('@kazumatu981/markdown-it-kroki'), { + entrypoint: "https://kroki.io", + }) +} +``` + +### **[4th step]** Create your slides + +On `slies` directory. you create slides-deck. like this. + + --- + marp: true + --- + + + ## mermaid + + ```mermaid[mermaid image] + flowchart TD + Start --> Stop + ``` + +### **[5th step]** run server + +Run marp server. + +```bash +marp -s -c marp.config.js +``` + +## Detail + +### Syntax of Markdown + +#### Diagram Language + +You have to write diagram language by [fenced code block](https://spec.commonmark.org/0.30/#fenced-code-blocks) syntax, start with **triple back quot** and after that the language. + + ```plantuml + +This package depends on kroki.io. +If you want to know which is **supported diagram language**, +you will see in [Kroki.io official web site (https://kroki.io/)](https://kroki.io/). + +#### Alt Text + +You can write Alt-text attribute to IMG tag in HTML. +Write in `square blacket` after **Diagram Language**. + + ```mermaid [check your network config..] + +### Options of `constructor` + +| property-name | type | mean | defaul value | +| ---------------- | -------- | ------------------------------------------------------ | ------------------------- | +| `entrypoint` | `string` | The entry point for Kroki server. | `'https://kroki.io'` | +| `containerClass` | `string` | class name of container (`DIV`-tag `class` attribute). | `'kroki-image-container'` | +| `imageFormat` | `string` | image format of diagram. see [here](https://kroki.io/) | `'svg'` | diff --git a/down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/demo/marp.config.js b/down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/demo/marp.config.js new file mode 100644 index 0000000..12e5fa9 --- /dev/null +++ b/down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/demo/marp.config.js @@ -0,0 +1,8 @@ + +module.exports = { + inputDir: './', + engine: ({ marp }) => marp.use(require('../index'), { + entrypoint: "https://kroki.io", + marpAutoScaling: true + }) +} \ No newline at end of file diff --git a/down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/demo/test.md b/down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/demo/test.md new file mode 100644 index 0000000..9dca75a --- /dev/null +++ b/down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/demo/test.md @@ -0,0 +1,59 @@ +--- +marp: true +--- + +# @kazumatu981/markdown-it-kroki + +## Marp Sample + +--- + +## plantuml + +```plantuml[platuml image] +@startuml +left to right direction +actor Guest as g +package Professional { + actor Chef as c + actor "Food Critic" as fc +} +package Restaurant { + usecase "Eat Food" as UC1 + usecase "Pay for Food" as UC2 + usecase "Drink" as UC3 + usecase "Review" as UC4 +} +fc --> UC4 +g --> UC1 +g --> UC2 +g --> UC3 +@enduml +``` + +--- + +## mermaid + +```mermaid[mermaid image] +graph TD + A[ Anyone ] -->|Can help | B( Go to github.com/yuzutech/kroki ) + B --> C{ How to contribute? } + C --> D[ Reporting bugs ] + C --> E[ Sharing ideas ] + C --> F[ Advocating ] +``` + +--- + +## normal code + +```JavaScript +function testFunc(test) { + let sum = 0; + for(let x = 1; x<=test; x++) { + sum += x; + } + return sum; +} +``` \ No newline at end of file diff --git a/down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/img/plantuml-sample.png b/down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/img/plantuml-sample.png new file mode 100644 index 0000000000000000000000000000000000000000..6db813186d31abf49b436e027f4591eace3802b0 GIT binary patch literal 30545 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 { + const plugin = new MarkdownItKrokiCore(md); + plugin.setOptions(opt).use(); +}; diff --git a/down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/lib/contract.js b/down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/lib/contract.js new file mode 100644 index 0000000..690c13a --- /dev/null +++ b/down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/lib/contract.js @@ -0,0 +1,37 @@ +'use strict'; + +module.exports = { + /** + * contract `test` to be non-empty string. + * @param {string} test test string + * @param {string} msg message on exception + */ + toNonEmptyString: function (test, msg) { + if (typeof test !== 'string') throw new Error(msg); + if (test === '' + || test === null + || test === undefined) throw new Error(msg); + }, + /** + * contract `test` to be true. + * @param {boolean} test test boolean. + * @param {sting} msg massage on excetion. + */ + toTrue: function (test, msg) { + if (typeof test !== 'boolean') throw new Error(msg); + if (!test) throw new Error(msg); + }, + toBeUrlString: function (test, msg) { + this.toNonEmptyString(test, msg); + try { + require('url').parse(test); + } catch { + throw new Error(msg); + } + }, + toBeClassName: function (test, msg) { + if (!/^[A-Za-z0-9]+(-?[A-Za-z0-9]+)*$/.exec(test)) { + throw new Error(msg); + } + } +}; diff --git a/down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/lib/diagram-encoder.js b/down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/lib/diagram-encoder.js new file mode 100644 index 0000000..e18b918 --- /dev/null +++ b/down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/lib/diagram-encoder.js @@ -0,0 +1,27 @@ +'use strict'; + +const { deflateSync } = require('zlib'); +const contract = require('./contract'); +const support = require('./support'); + +function encode(diagram) { + return deflateSync(diagram, { level: 9 }).toString('base64url'); +} +function generateUrl(entrypoint, lang, imgType, diagram) { + + contract.toNonEmptyString(entrypoint, '\'entrypoint\' must be non-empty string.'); + contract.toNonEmptyString(lang, '\'lang\' must be non-empty string.'); + contract.toNonEmptyString(imgType, '\'imgType\' must be non-empty string.'); + contract.toNonEmptyString(diagram, '\'diagram\' must be non-empty string.'); + contract.toTrue(support.languageSupports(lang), 'Not Supported Diagram Language.'); + contract.toTrue(support.imageFormatSupports(imgType), 'Not Supported Image Type.'); + + const api = `${lang}/${imgType}/${encode(diagram)}`; + + return entrypoint.endsWith('/') ? + `${entrypoint}${api}` : `${entrypoint}/${api}`; +} + +module.exports = { + encode, generateUrl +}; diff --git a/down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/lib/obs/marp-it-kroki.js b/down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/lib/obs/marp-it-kroki.js new file mode 100644 index 0000000..5c34e28 --- /dev/null +++ b/down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/lib/obs/marp-it-kroki.js @@ -0,0 +1,52 @@ +const { deflateSync } = require('zlib') + +const krokiLangs = [ + 'actdiag', + 'blockdiag', + 'bpmn', + 'bytefield', + 'c4plantuml', + 'ditaa', + 'dot', + 'erd', + 'excalidraw', + 'graphviz', + 'mermaid', + 'nomnoml', + 'nwdiag', + 'packetdiag', + 'pikchr', + 'plantuml', + 'rackdiag', + 'seqdiag', + 'svgbob', + 'umlet', + 'vega', + 'vegalite', + 'wavedrom', +] + +const entrypoint = 'https://kroki.io/' + +const marpKrokiPlugin = (md) => { + const { fence } = md.renderer.rules + + md.renderer.rules.fence = (tokens, idx, options, env, self) => { + const info = md.utils.unescapeAll(tokens[idx].info).trim() + + if (info) { + const [lang] = info.split(/(\s+)/g) + + if (krokiLangs.includes(lang)) { + const data = deflateSync(tokens[idx].content).toString('base64url') + + // is working only with Marp Core v3 + return `

` + } + } + + return fence.call(self, tokens, idx, options, env, self) + } +} + +module.exports = marpKrokiPlugin diff --git a/down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/lib/plugin-core.js b/down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/lib/plugin-core.js new file mode 100644 index 0000000..60fcc65 --- /dev/null +++ b/down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/lib/plugin-core.js @@ -0,0 +1,74 @@ +'use strict'; + +const support = require('./support'); +const contract = require('./contract'); +const { safeProperty, safeChoice } = require('./safe-property'); +const diagramEncoder = require('./diagram-encoder'); + +class MarkdownItKrokiCore { + constructor(md) { + this._md = md; + } + setOptions(opt) { + this._entrypoint = safeProperty(opt, "entrypoint", "string", 'https://kroki.io'); + this._containerClass = safeProperty(opt, "containerClass", "string", "kroki-image-container"); + this._imageFormat = safeProperty(opt, "imageFormat", "string", "svg"); + + this._imageFormat = safeChoice(this._imageFormat, support.imageFormats, "svg"); + this._entrypoint = require('url').parse(this._entrypoint).href; + + contract.toBeClassName(this._containerClass, "containerClass must be className."); + + return this; + } + use() { + // if _md has `marpit` property then use tag + this._marpAutoScaling = this._md['marpit'] !== undefined; + + this._defaultFence = this._md.renderer.rules.fence; + this._md.renderer.rules.fence + = (tokens, idx, options, env, self) => this.krokiFencePlugin(tokens, idx, options, env, self); + } + static readLanguageAndAltText(info) { + if (!info) return { language: '', alt: '' }; + + const trimed = info.trim(); + const langFound = /[\s|\[]/.exec(trimed); + const altFound = /\[.*?\]/.exec(trimed); + + return { + language: langFound ? + trimed.substring(0, langFound.index) : trimed, + alt: altFound ? + altFound[0].replace('[', '').replace(']', '') : '' + }; + } + buildEmbedHTML(langAndAlt, diagramCode) { + // alt build url + const url = diagramEncoder.generateUrl( + this._entrypoint, langAndAlt.language, this._imageFormat, diagramCode); + + // sanitize alt + const alt = langAndAlt.alt ? + this._md.utils.escapeHtml(langAndAlt.alt) : undefined; + // build img tag + const imgTag = langAndAlt.alt ? + `${alt}` : ``; + // build container contents + const containerContents = this._marpAutoScaling ? + `${imgTag}` : imgTag; + // build embed HTML + return `

${containerContents}

`; + } + krokiFencePlugin(tokens, idx, options, env, self) { + const info = this._md.utils.unescapeAll(tokens[idx].info) + const langAndAlt = MarkdownItKrokiCore.readLanguageAndAltText(info); + + return support.languageSupports(langAndAlt.language) ? + this.buildEmbedHTML(langAndAlt, tokens[idx].content) : + this._defaultFence.call(self, tokens, idx, options, env, self); + } +} +module.exports = { + MarkdownItKrokiCore +} \ No newline at end of file diff --git a/down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/lib/safe-property.js b/down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/lib/safe-property.js new file mode 100644 index 0000000..953e305 --- /dev/null +++ b/down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/lib/safe-property.js @@ -0,0 +1,18 @@ +'use strict'; + +function safeProperty(test, name, type, defaultValue) { + if (test == null || test == undefined) return defaultValue; + if (typeof test[name] !== type) return defaultValue; + if (typeof test[name] === "string" && test[name] === '') return defaultValue; + return test[name]; +} + +function safeChoice(test, candidates, defaultValue) { + return candidates.includes(test) ? + test : defaultValue; +} +function safeUrl(test) { + +} + +module.exports = { safeProperty, safeChoice }; diff --git a/down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/lib/support.js b/down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/lib/support.js new file mode 100644 index 0000000..e8144ae --- /dev/null +++ b/down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/lib/support.js @@ -0,0 +1,54 @@ +'use strict'; + +/** + * Diagram Languages are supported by kroki.io + */ +const LANGUAGES = [ + 'actdiag', + 'blockdiag', + 'bpmn', + 'bytefield', + 'c4plantuml', + 'ditaa', + 'dot', + 'erd', + 'excalidraw', + 'graphviz', + 'mermaid', + 'nomnoml', + 'nwdiag', + 'packetdiag', + 'pikchr', + 'plantuml', + 'rackdiag', + 'seqdiag', + 'svgbob', + 'umlet', + 'vega', + 'vegalite', + 'wavedrom', +]; + +/** + * Image formats are supported by kroki.io + */ +const IMG_FORMATS = [ + 'png', 'svg', 'jpeg', 'pdf', 'base64' +]; + +module.exports = { + lnaguages: LANGUAGES, + imageFormats: IMG_FORMATS, + /** + * test whether `lang` is supported diagram language by kroki.io + * @param {string} lang target language + * @returns is supported + */ + languageSupports: (lang) => LANGUAGES.includes(lang), + /** + * test whether `format` is supported image format by kroki.io + * @param {string} format name of image format like 'png', 'svg', ... etc + * @returns is supported + */ + imageFormatSupports: (format) => IMG_FORMATS.includes(format) +}; \ No newline at end of file diff --git a/down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/package.json b/down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/package.json new file mode 100644 index 0000000..2ae5ecd --- /dev/null +++ b/down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/package.json @@ -0,0 +1,35 @@ +{ + "name": "@kazumatu981/markdown-it-kroki", + "version": "1.1.1", + "description": "markdown-it kroki plugin.", + "main": "index.js", + "scripts": { + "test": "mocha tests/**/*.test.js", + "demo": "marp -s -c demo/marp.config.js" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/kazumatu981/markdown-it-kroki.git" + }, + "keywords": [ + "markdown-it", + "markdown-it-plugin", + "kroki", + "marp", + "markdown" + ], + "author": "kazumatu981", + "license": "MIT", + "bugs": { + "url": "https://github.com/kazumatu981/markdown-it-kroki/issues" + }, + "homepage": "https://github.com/kazumatu981/markdown-it-kroki#readme", + "devDependencies": { + "@marp-team/marp-cli": "^2.2.0", + "chai": "^4.3.6", + "jsdom": "^20.0.1", + "markdown-it": "^13.0.1", + "mocha": "^10.1.0", + "nyc": "^15.1.0" + } +} \ No newline at end of file diff --git a/down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/tests/securitytest/security.test.js b/down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/tests/securitytest/security.test.js new file mode 100644 index 0000000..eb8f20a --- /dev/null +++ b/down-the-stack-book/node_modules/@kazumatu981/markdown-it-kroki/tests/securitytest/security.test.js @@ -0,0 +1,94 @@ +const MarkdownIt = require('markdown-it'); +const { expect } = require('chai'); +const { JSDOM } = require('jsdom'); +const MarkdownItKroki = require('../../index'); + +describe('# [Security-test] anti-injecttion for syntax.', () => { + describe("## for alt", () => { + it('* escape double quote', () => { + const expected = 'this is a "test comment" test'; + + const md = new MarkdownIt(); + md.use(MarkdownItKroki, { + entrypoint: "https://kroki.io", + marpAutoScaling: true, + containerClass: "the-container" + }); + + const result = md.render( + '```graphviz [this is a "test comment" test]\r\n' + + 'digraph G {Hello->World}\r\n' + + '```\r\n' + ); + const dom = new JSDOM(result); + const imgTag = dom.window.document.getElementsByTagName("img")[0]; + const actual = imgTag.getAttribute('alt'); + + expect(actual).to.be.equal(expected); + }) + }) +}); +describe('# [Security-test] anti-injecttion for option.', () => { + describe("## for entrypoint", () => { + it('* deny invalid URL', () => { + const md = new MarkdownIt(); + md.use(MarkdownItKroki, { + entrypoint: "https://kroki.io\">