├── .editorconfig ├── .gitattributes ├── .githooks ├── commit-msg └── pre-commit ├── .github └── workflows │ └── bring-it.yaml ├── .gitignore ├── LICENSE ├── README.md ├── lib ├── ast.mjs ├── fail.svg ├── fetch.mjs ├── index.mjs ├── transform.mjs ├── utils.mjs └── validate.mjs ├── package.json ├── pnpm-lock.yaml └── test ├── base.mjs ├── fail.mjs ├── helper └── lib.mjs ├── output.mjs ├── snapshots ├── base.mjs.md ├── base.mjs.snap ├── fail.mjs.md ├── fail.mjs.snap ├── output.mjs.md ├── output.mjs.snap ├── validate.mjs.md └── validate.mjs.snap └── validate.mjs /.editorconfig: -------------------------------------------------------------------------------- 1 | # Created by nice-move 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | end_of_line = lf 7 | indent_size = 2 8 | indent_style = space 9 | insert_final_newline = true 10 | max_line_length = 80 11 | quote_type = single 12 | tab_width = 2 13 | trim_trailing_whitespace = true 14 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Created by nice-move 2 | 3 | * text=auto eol=lf 4 | -------------------------------------------------------------------------------- /.githooks/commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | npx --no-install nice-move lint commit 4 | -------------------------------------------------------------------------------- /.githooks/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | pnpm run lint:staged 4 | pnpm test 5 | -------------------------------------------------------------------------------- /.github/workflows/bring-it.yaml: -------------------------------------------------------------------------------- 1 | name: bring-it 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | test: 10 | strategy: 11 | matrix: 12 | os: 13 | - macos-latest 14 | - windows-latest 15 | - ubuntu-latest 16 | node: 17 | - current 18 | - lts/* 19 | - lts/-1 20 | exclude: 21 | - os: ubuntu-latest 22 | node: lts/* 23 | 24 | runs-on: ${{ matrix.os }} 25 | steps: 26 | - name: Run 27 | uses: airkro/bring-it@actions 28 | with: 29 | node-version: ${{ matrix.node }} 30 | 31 | publish: 32 | needs: [test] 33 | runs-on: ubuntu-latest 34 | steps: 35 | - name: Run 36 | uses: airkro/bring-it@actions 37 | with: 38 | npm-token: ${{ secrets.NPM_TOKEN }} 39 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://gitignore.io/api/node,windows 2 | # Edit at https://gitignore.io?templates=node,windows 3 | 4 | ### Node ### 5 | # Logs 6 | logs 7 | *.log 8 | npm-debug.log* 9 | yarn-debug.log* 10 | yarn-error.log* 11 | lerna-debug.log* 12 | .pnpm-debug.log* 13 | 14 | # Diagnostic reports (https://nodejs.org/api/report.html) 15 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 16 | 17 | # Runtime data 18 | pids 19 | *.pid 20 | *.seed 21 | *.pid.lock 22 | 23 | # Directory for instrumented libs generated by jscoverage/JSCover 24 | lib-cov 25 | 26 | # Coverage directory used by tools like istanbul 27 | coverage 28 | *.lcov 29 | 30 | # nyc test coverage 31 | .nyc_output 32 | 33 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 34 | .grunt 35 | 36 | # Bower dependency directory (https://bower.io/) 37 | bower_components 38 | 39 | # node-waf configuration 40 | .lock-wscript 41 | 42 | # Compiled binary addons (https://nodejs.org/api/addons.html) 43 | build/Release 44 | 45 | # Dependency directories 46 | node_modules/ 47 | jspm_packages/ 48 | 49 | # Snowpack dependency directory (https://snowpack.dev/) 50 | web_modules/ 51 | 52 | # TypeScript cache 53 | *.tsbuildinfo 54 | 55 | # Optional npm cache directory 56 | .npm 57 | 58 | # Optional eslint cache 59 | .eslintcache 60 | 61 | # Optional stylelint cache 62 | .stylelintcache 63 | 64 | # Microbundle cache 65 | .rpt2_cache/ 66 | .rts2_cache_cjs/ 67 | .rts2_cache_es/ 68 | .rts2_cache_umd/ 69 | 70 | # Optional REPL history 71 | .node_repl_history 72 | 73 | # Output of 'npm pack' 74 | *.tgz 75 | 76 | # Yarn Integrity file 77 | .yarn-integrity 78 | 79 | # dotenv environment variable files 80 | .env 81 | .env.development.local 82 | .env.test.local 83 | .env.production.local 84 | .env.local 85 | 86 | # parcel-bundler cache (https://parceljs.org/) 87 | .cache 88 | .parcel-cache 89 | 90 | # Next.js build output 91 | .next 92 | out 93 | 94 | # Nuxt.js build / generate output 95 | .nuxt 96 | dist 97 | 98 | # Gatsby files 99 | .cache/ 100 | # Comment in the public line in if your project uses Gatsby and not Next.js 101 | # https://nextjs.org/blog/next-9-1#public-directory-support 102 | # public 103 | 104 | # vuepress build output 105 | .vuepress/dist 106 | 107 | # vuepress v2.x temp and cache directory 108 | .temp 109 | 110 | # Docusaurus cache and generated files 111 | .docusaurus 112 | 113 | # Serverless directories 114 | .serverless/ 115 | 116 | # FuseBox cache 117 | .fusebox/ 118 | 119 | # DynamoDB Local files 120 | .dynamodb/ 121 | 122 | # TernJS port file 123 | .tern-port 124 | 125 | # Stores VSCode versions used for testing VSCode extensions 126 | .vscode-test 127 | 128 | # yarn v2 129 | .yarn/cache 130 | .yarn/unplugged 131 | .yarn/build-state.yml 132 | .yarn/install-state.gz 133 | .pnp.* 134 | 135 | ### Node Patch ### 136 | # Serverless Webpack directories 137 | .webpack/ 138 | 139 | # Optional stylelint cache 140 | 141 | # SvelteKit build / generate output 142 | .svelte-kit 143 | 144 | ### Windows ### 145 | # Windows thumbnail cache files 146 | Thumbs.db 147 | Thumbs.db:encryptable 148 | ehthumbs.db 149 | ehthumbs_vista.db 150 | 151 | # Dump file 152 | *.stackdump 153 | 154 | # Folder config file 155 | [Dd]esktop.ini 156 | 157 | # Recycle Bin used on file shares 158 | $RECYCLE.BIN/ 159 | 160 | # Windows Installer files 161 | *.cab 162 | *.msi 163 | *.msix 164 | *.msm 165 | *.msp 166 | 167 | # Windows shortcuts 168 | *.lnk 169 | 170 | # End of https://gitignore.io/api/node,windows 171 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Eric Chen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # remark-kroki 2 | 3 | Remark plugin for showing [Kroki] diagram. 4 | 5 | [![npm][npm-badge]][npm-url] 6 | [![github][github-badge]][github-url] 7 | ![node][node-badge] 8 | 9 | [kroki]: https://kroki.io 10 | [npm-url]: https://www.npmjs.com/package/remark-kroki 11 | [npm-badge]: https://img.shields.io/npm/v/remark-kroki.svg?style=flat-square&logo=npm 12 | [github-url]: https://github.com/show-docs/remark-kroki 13 | [github-badge]: https://img.shields.io/npm/l/remark-kroki.svg?style=flat-square&colorB=blue&logo=github 14 | [node-badge]: https://img.shields.io/node/v/remark-kroki.svg?style=flat-square&colorB=green&logo=node.js 15 | 16 | ## Installation 17 | 18 | ```sh 19 | npm install remark-kroki --save-dev 20 | ``` 21 | 22 | ## Usage 23 | 24 | ```mjs 25 | import readFileSync from 'node:fs'; 26 | 27 | import { remark } from 'remark'; 28 | import { remarkKroki } from 'remark-kroki'; 29 | 30 | const markdownText = readFileSync('example.md', 'utf8'); 31 | 32 | remark() 33 | .use(remarkKroki, { 34 | server: 'http://localhost:8000', 35 | alias: ['plantuml'] 36 | }) 37 | .process(markdownText) 38 | .then((file) => console.info(file)) 39 | .catch((error) => console.warn(error)); 40 | ``` 41 | 42 | ### Docusaurus v3 project 43 | 44 | ```mjs 45 | // docusaurus.config.mjs 46 | import { remarkKroki } from 'remark-kroki'; 47 | 48 | export default { 49 | presets: [ 50 | [ 51 | 'classic', 52 | { 53 | docs: { 54 | remarkPlugins: [ 55 | [ 56 | remarkKroki, 57 | { 58 | // ...options here 59 | alias: ['plantuml'], 60 | target: 'mdx3' 61 | } 62 | ] 63 | ] 64 | } 65 | } 66 | ] 67 | ] 68 | }; 69 | ``` 70 | 71 | ### Docusaurus v2 project 72 | 73 | ```cjs 74 | // docusaurus.config.js 75 | module.exports = async function createConfig() { 76 | const { remarkKroki } = await import('remark-kroki'); 77 | 78 | return { 79 | presets: [ 80 | [ 81 | 'classic', 82 | { 83 | docs: { 84 | remarkPlugins: [ 85 | [ 86 | remarkKroki, 87 | { 88 | // ...options here 89 | alias: ['plantuml'] 90 | } 91 | ] 92 | ] 93 | } 94 | } 95 | ] 96 | ] 97 | }; 98 | }; 99 | ``` 100 | 101 | ## Options 102 | 103 | ### Options.server 104 | 105 | - type: string 106 | - default: http://localhost:8000 107 | - example: 108 | 109 | Using self host server by default. Set to use free service. 110 | 111 | ### Options.headers 112 | 113 | - type: object 114 | - default: `{}` 115 | 116 | HTTP headers to send to the server for custom authentication. 117 | 118 | ### Options.alias 119 | 120 | - type: array 121 | - default: `[]` 122 | - example: `['plantuml']` 123 | 124 | Alias code language name to treat as kroki code block, meta.type will be ignored. 125 | 126 | ```` 127 | ```kroki type=plantuml 128 | ``` 129 | ↓ 130 | 131 | ```plantuml 132 | ``` 133 | ```` 134 | 135 | ### Options.target 136 | 137 | - type: string 138 | - default: `'html'` 139 | - enum: `['html', 'mdx3']` 140 | 141 | Transform HTML tags as MDX 3.0 AST or not. When you using Docusaurus v3, you should use `mdx3`. 142 | 143 | ### Options.output 144 | 145 | - type: string 146 | - default: `'img-base64'` 147 | - enum: `['inline-svg', 'img-base64', 'img-html-base64', 'object-base64']` 148 | 149 | How to embed SVG as image. See the different and risk on [Best Way To Embed SVG](https://vecta.io/blog/best-way-to-embed-svg). 150 | 151 | ## Syntax 152 | 153 | ### Base 154 | 155 | ````markdown 156 | Turn 157 | 158 | ```kroki type=plantuml 159 | A --> B 160 | ``` 161 | 162 | Into 163 | 164 | ![plantuml](data:image/svg+xml;base64,xxxxxxxx) 165 | ```` 166 | 167 | ````markdown 168 | Turn 169 | 170 | ```kroki type=plantuml alt=abc 171 | A --> B 172 | ``` 173 | 174 | Into 175 | 176 | ![abc](data:image/svg+xml;base64,xxxxxxxx) 177 | ```` 178 | 179 | ### Set classnames 180 | 181 | ````markdown 182 | 183 | 184 | Turn 185 | 186 | ```d2 classnames="tw-w-1/2" 187 | A --> B 188 | ``` 189 | 190 | Into 191 | 192 | 193 | ```` 194 | 195 | ## Troubleshooting 196 | 197 | When you using `inline-svg` with `mdx3` mode, You may get following error: 198 | 199 | ```log 200 | Error: Cannot handle unknown node `raw` when using with `@mdx-js/mdx` 201 | ``` 202 | 203 | You need to add `rehype-raw` to the complier, for example: 204 | 205 | ```mjs 206 | // docusaurus.config.mjs 207 | import rehypeRaw from 'rehype-raw'; 208 | import { remarkKroki } from 'remark-kroki'; 209 | 210 | export default { 211 | presets: [ 212 | [ 213 | 'classic', 214 | { 215 | docs: { 216 | remarkPlugins: [ 217 | [ 218 | remarkKroki, 219 | { 220 | // ...options here 221 | target: 'mdx3', 222 | output: 'inline-svg' 223 | } 224 | ] 225 | ], 226 | rehypePlugins: [ 227 | [ 228 | rehypeRaw, 229 | { 230 | passThrough: [ 231 | 'mdxFlowExpression', 232 | 'mdxJsxFlowElement', 233 | 'mdxJsxTextElement', 234 | 'mdxTextExpression', 235 | 'mdxjsEsm' 236 | ] 237 | } 238 | ] 239 | ] 240 | } 241 | } 242 | ] 243 | ] 244 | }; 245 | ``` 246 | 247 | ## Related 248 | 249 | - [markdown-code-block-meta](https://github.com/show-docs/markdown-code-block-meta) 250 | - [rehype-extended-table](https://github.com/show-docs/rehype-extended-table) 251 | - [remark-code-example](https://github.com/show-docs/remark-code-example) 252 | - [remark-docusaurus](https://github.com/show-docs/remark-docusaurus) 253 | -------------------------------------------------------------------------------- /lib/ast.mjs: -------------------------------------------------------------------------------- 1 | import kebabCase from 'kebab-case'; 2 | 3 | function patch({ data }) { 4 | const io = data.estree.body[0].expression.properties[0]; 5 | 6 | return `${kebabCase(io.key.name)}:${io.value.value}`; 7 | } 8 | 9 | function attrString(attributes = []) { 10 | return attributes.length > 0 11 | ? attributes 12 | .map( 13 | ({ name, value }) => 14 | ` ${name === 'className' ? 'class' : name}="${ 15 | name === 'style' ? patch(value) : value 16 | }"`, 17 | ) 18 | .join('') 19 | : ''; 20 | } 21 | 22 | export function create(target, ast) { 23 | if (target === 'mdx3') { 24 | return ast; 25 | } 26 | 27 | const { name, attributes, children: [{ value: child } = {}] = [] } = ast; 28 | 29 | return { 30 | type: target, 31 | value: child 32 | ? [`<${name}${attrString(attributes)}>`, child, ``].join('') 33 | : `<${name}${attrString(attributes)} />`, 34 | }; 35 | } 36 | -------------------------------------------------------------------------------- /lib/fail.svg: -------------------------------------------------------------------------------- 1 | 2 | 6 | Fail, please check your input. 7 | 8 |
12 | ====== 13 |
14 |
15 |
16 | -------------------------------------------------------------------------------- /lib/fetch.mjs: -------------------------------------------------------------------------------- 1 | import nodeFetch from 'node-fetch'; 2 | 3 | export function httpPost({ url, body, headers }) { 4 | return nodeFetch(url, { 5 | method: 'POST', 6 | body, 7 | headers: { 8 | ...headers, 9 | 'Content-Type': 'text/plain', 10 | }, 11 | }).then(async (response) => { 12 | if (!response.ok) { 13 | throw new Error(await response.text()); 14 | } 15 | 16 | return response.arrayBuffer(); 17 | }); 18 | } 19 | -------------------------------------------------------------------------------- /lib/index.mjs: -------------------------------------------------------------------------------- 1 | import { visit } from 'unist-util-visit'; 2 | 3 | import { outputType, transform } from './transform.mjs'; 4 | import { isKroki } from './utils.mjs'; 5 | import { validate } from './validate.mjs'; 6 | 7 | export function remarkKroki({ 8 | server = 'http://localhost:8000', 9 | headers = {}, 10 | alias = [], 11 | output = outputType[0], 12 | target = 'html', 13 | } = {}) { 14 | validate({ server, headers, alias, output, target }); 15 | 16 | const condition = isKroki(alias); 17 | 18 | return async (tree) => { 19 | const temp = []; 20 | 21 | visit(tree, condition, (node) => { 22 | temp.push(transform({ node, server, headers, output, target })); 23 | }); 24 | 25 | // eslint-disable-next-line no-empty 26 | for await (const _ of temp) { 27 | } 28 | }; 29 | } 30 | -------------------------------------------------------------------------------- /lib/transform.mjs: -------------------------------------------------------------------------------- 1 | import { getValue, parse } from 'markdown-code-block-meta'; 2 | 3 | import { create } from './ast.mjs'; 4 | import { fetchData, mime, toDataURL } from './utils.mjs'; 5 | 6 | /* eslint-disable no-param-reassign */ 7 | 8 | function removeXML(string) { 9 | return string.replace(/<\?xml.+\?>/, ''); 10 | } 11 | 12 | const modes = { 13 | 'img-base64': ({ diagramType, data, alt }) => { 14 | return { 15 | type: 'paragraph', 16 | children: [ 17 | { 18 | type: 'image', 19 | _meta: { kroki: true, type: diagramType }, 20 | alt: alt || diagramType, 21 | url: toDataURL(data), 22 | }, 23 | ], 24 | }; 25 | }, 26 | 'object-base64': ({ target, diagramType, data, alt, classnames }) => { 27 | return create(target, { 28 | type: 'mdxJsxFlowElement', 29 | name: 'object', 30 | children: [ 31 | { 32 | type: 'text', 33 | value: 'Load SVG fail...', 34 | }, 35 | ], 36 | attributes: [ 37 | { 38 | type: 'mdxJsxAttribute', 39 | name: 'type', 40 | value: mime, 41 | }, 42 | { 43 | type: 'mdxJsxAttribute', 44 | name: 'className', 45 | value: classnames ? `kroki-object ${classnames}` : 'kroki-object', 46 | }, 47 | { 48 | type: 'mdxJsxAttribute', 49 | name: 'data-type', 50 | value: diagramType, 51 | }, 52 | { 53 | type: 'mdxJsxAttribute', 54 | name: 'title', 55 | value: alt || diagramType, 56 | }, 57 | { 58 | type: 'mdxJsxAttribute', 59 | name: 'data', 60 | value: toDataURL(data), 61 | }, 62 | ].filter(Boolean), 63 | }); 64 | }, 65 | 'img-html-base64': ({ target, diagramType, data, alt, classnames }) => { 66 | return { 67 | type: 'paragraph', 68 | children: [ 69 | create(target, { 70 | type: 'mdxJsxTextElement', 71 | name: 'img', 72 | attributes: [ 73 | { 74 | type: 'mdxJsxAttribute', 75 | name: 'className', 76 | value: classnames ? `kroki-image ${classnames}` : 'kroki-image', 77 | }, 78 | { 79 | type: 'mdxJsxAttribute', 80 | name: 'alt', 81 | value: alt || diagramType, 82 | }, 83 | { 84 | type: 'mdxJsxAttribute', 85 | name: 'data-type', 86 | value: diagramType, 87 | }, 88 | { 89 | type: 'mdxJsxAttribute', 90 | name: 'src', 91 | value: toDataURL(data), 92 | }, 93 | ], 94 | }), 95 | ], 96 | }; 97 | }, 98 | 'inline-svg': ({ target, diagramType, data, alt }) => { 99 | return create(target, { 100 | type: 'mdxJsxFlowElement', 101 | name: 'p', 102 | attributes: [ 103 | { 104 | type: 'mdxJsxAttribute', 105 | name: 'className', 106 | value: 'kroki-inline-svg', 107 | }, 108 | { 109 | type: 'mdxJsxAttribute', 110 | name: 'data-type', 111 | value: diagramType, 112 | }, 113 | { 114 | type: 'mdxJsxAttribute', 115 | name: 'data-alt', 116 | value: alt || diagramType, 117 | }, 118 | ], 119 | children: [ 120 | { 121 | type: 'html', 122 | value: removeXML(data.toString()), 123 | }, 124 | ], 125 | }); 126 | }, 127 | }; 128 | 129 | export const outputType = Object.keys(modes); 130 | 131 | export async function transform({ node, server, headers, output, target }) { 132 | const { meta, value, lang } = node; 133 | 134 | const object = parse(meta); 135 | 136 | const alt = getValue(object.get('alt')); 137 | const type = getValue(object.get('type')); 138 | const classnames = getValue(object.get('classnames')); 139 | 140 | const diagramType = lang === 'kroki' ? type : lang; 141 | 142 | const data = await fetchData({ 143 | server, 144 | headers, 145 | type: diagramType, 146 | value, 147 | }); 148 | 149 | for (const key of Object.keys(node)) { 150 | delete node[key]; 151 | } 152 | 153 | Object.assign( 154 | node, 155 | modes[output]({ 156 | diagramType, 157 | data, 158 | alt, 159 | target, 160 | classnames, 161 | }), 162 | ); 163 | } 164 | -------------------------------------------------------------------------------- /lib/utils.mjs: -------------------------------------------------------------------------------- 1 | import { readFileSync } from 'node:fs'; 2 | 3 | import { parse } from 'markdown-code-block-meta'; 4 | import pMemoize from 'p-memoize'; 5 | 6 | import { httpPost } from './fetch.mjs'; 7 | 8 | export function isKroki(alias = []) { 9 | return ({ type, lang, meta, value }) => { 10 | return ( 11 | type === 'code' && 12 | value && 13 | value.trim() && 14 | (alias.includes(lang) || 15 | (lang === 'kroki' && meta && parse(meta).has('type'))) 16 | ); 17 | }; 18 | } 19 | 20 | const failImage = new URL('fail.svg', import.meta.url); 21 | 22 | function createFailImage(server, message) { 23 | console.error(message); 24 | 25 | return readFileSync(failImage, 'utf8').replace( 26 | '======', 27 | message.replaceAll(server, '$server').slice(0, 500), 28 | ); 29 | } 30 | 31 | function Fetch({ server, headers, type, value }) { 32 | const serverURL = server.replace(/\/$/, ''); 33 | 34 | return httpPost({ 35 | url: `${serverURL}/${type}/svg`, 36 | body: value, 37 | headers, 38 | }) 39 | .catch((error) => createFailImage(serverURL, error.message)) 40 | .then((data) => Buffer.from(data)); 41 | } 42 | 43 | export const mime = 'image/svg+xml'; 44 | 45 | export function toDataURL(buffer) { 46 | const base64 = buffer.toString('base64'); 47 | 48 | return `data:${mime};base64,${base64}`; 49 | } 50 | 51 | export const fetchData = pMemoize(Fetch, { 52 | cacheKey: (arguments_) => JSON.stringify(arguments_), 53 | }); 54 | -------------------------------------------------------------------------------- /lib/validate.mjs: -------------------------------------------------------------------------------- 1 | import { strict as assert } from 'node:assert'; 2 | 3 | import isPlainObject from 'is-plain-obj'; 4 | 5 | import { outputType } from './transform.mjs'; 6 | 7 | const targets = ['html', 'mdx3']; 8 | 9 | export function validate({ server, headers, alias, output, target }) { 10 | try { 11 | assert( 12 | typeof server === 'string', 13 | new TypeError('`server` should be string'), 14 | ); 15 | 16 | assert.doesNotThrow(() => { 17 | try { 18 | // eslint-disable-next-line no-new 19 | new URL(server); 20 | } catch { 21 | throw new TypeError('`server` should be URL'); 22 | } 23 | }); 24 | 25 | assert( 26 | ['http:', 'https:'].includes(new URL(server).protocol), 27 | new TypeError('`server` protocol should be http or https'), 28 | ); 29 | 30 | assert( 31 | isPlainObject(headers), 32 | new TypeError('`headers` should be plain object'), 33 | ); 34 | 35 | assert( 36 | Object.values(headers).every((item) => typeof item === 'string'), 37 | new TypeError('`headers` should object of string'), 38 | ); 39 | 40 | assert(Array.isArray(alias), new TypeError('`alias` should be array')); 41 | 42 | assert( 43 | alias.every((item) => typeof item === 'string' && item.trim()), 44 | new TypeError('`alias` should array of non empty string'), 45 | ); 46 | 47 | assert( 48 | outputType.includes(output), 49 | new TypeError(`\`output\` should be one of \`${outputType.join('/')}\``), 50 | ); 51 | 52 | assert( 53 | targets.includes(target), 54 | new TypeError(`\`target\` should be one of \`${targets.join('/')}\``), 55 | ); 56 | } catch (error) { 57 | throw error.actual || error; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "remark-kroki", 3 | "version": "0.3.7", 4 | "description": "Remark plugin for showing Kroki diagram", 5 | "license": "MIT", 6 | "author": { 7 | "name": "Eric Chen", 8 | "email": "airkro@qq.com" 9 | }, 10 | "keywords": [ 11 | "blockdiag", 12 | "bytefield", 13 | "code-block", 14 | "diagram", 15 | "doc", 16 | "document", 17 | "documentation", 18 | "docusaurus", 19 | "graphViz", 20 | "kroki", 21 | "markdown", 22 | "mermaid", 23 | "nomnoml", 24 | "plantuml", 25 | "remark", 26 | "remark-plugin", 27 | "remarkjs", 28 | "site-generator", 29 | "vega" 30 | ], 31 | "homepage": "https://github.com/show-docs/remark-kroki", 32 | "repository": { 33 | "type": "git", 34 | "url": "https://github.com/show-docs/remark-kroki.git" 35 | }, 36 | "bugs": { 37 | "url": "https://github.com/show-docs/remark-kroki/issues" 38 | }, 39 | "main": "lib/index.mjs", 40 | "files": [ 41 | "lib" 42 | ], 43 | "type": "module", 44 | "scripts": { 45 | "lint:staged": "nice-move lint staged", 46 | "prepare": "nice-move git hooks", 47 | "prepublishOnly": "pnpm run lint:staged && pnpm test", 48 | "snapshot": "ava --fail-fast -u -w", 49 | "test": "ava --fail-fast" 50 | }, 51 | "dependencies": { 52 | "is-plain-obj": "^4.1.0", 53 | "kebab-case": "^2.0.1", 54 | "markdown-code-block-meta": "^0.0.2", 55 | "node-fetch": "^3.3.2", 56 | "p-memoize": "^7.1.1", 57 | "unist-util-visit": "^5.0.0" 58 | }, 59 | "devDependencies": { 60 | "@bring-it/npm": "^0.5.5", 61 | "@nice-move/cli": "^0.11.13", 62 | "@nice-move/eslint-config-base": "^0.11.10", 63 | "@nice-move/prettier-config": "^0.12.4", 64 | "ava": "^6.1.3", 65 | "eslint": "^8.57.0", 66 | "eslint-plugin-ava": "^14.0.0", 67 | "garou": "^0.7.6", 68 | "prettier": "^3.3.2", 69 | "remark": "^15.0.1", 70 | "remark-mdx": "^3.0.1", 71 | "unist-util-remove-position": "^5.0.0" 72 | }, 73 | "packageManager": "pnpm@9.4.0", 74 | "engines": { 75 | "node": ">=18.0.0 || ^16.13.0" 76 | }, 77 | "publishConfig": { 78 | "access": "public", 79 | "registry": "https://registry.npmjs.org/" 80 | }, 81 | "eslintConfig": { 82 | "extends": "@nice-move/eslint-config-base" 83 | }, 84 | "nice-move": { 85 | "import-groups": "nice-move-preset" 86 | }, 87 | "prettier": "@nice-move/prettier-config" 88 | } 89 | -------------------------------------------------------------------------------- /test/base.mjs: -------------------------------------------------------------------------------- 1 | import test from 'ava'; 2 | 3 | import { TransformSnapshot } from './helper/lib.mjs'; 4 | 5 | test( 6 | 'empty', 7 | TransformSnapshot, 8 | ` 9 | \`\`\`kroki 10 | \`\`\` 11 | 12 | \`\`\`kroki type=plantuml 13 | \`\`\` 14 | `, 15 | ); 16 | 17 | test( 18 | 'okay', 19 | TransformSnapshot, 20 | ` 21 | \`\`\`kroki type=plantuml alt=abc 22 | A --> B 23 | \`\`\` 24 | `, 25 | { server: 'https://kroki.io' }, 26 | ); 27 | 28 | test( 29 | 'alias', 30 | TransformSnapshot, 31 | ` 32 | \`\`\`plantuml type=mermaid alt=abc 33 | A --> B 34 | \`\`\` 35 | `, 36 | { 37 | server: 'https://kroki.io', 38 | alias: ['plantuml'], 39 | }, 40 | ); 41 | -------------------------------------------------------------------------------- /test/fail.mjs: -------------------------------------------------------------------------------- 1 | import test from 'ava'; 2 | 3 | import { TransformSnapshot } from './helper/lib.mjs'; 4 | 5 | test( 6 | 'input', 7 | TransformSnapshot, 8 | ` 9 | \`\`\`kroki type=plantuml alt=00 10 | ss 11 | \`\`\` 12 | `, 13 | { server: 'https://kroki.io' }, 14 | false, 15 | ); 16 | 17 | test( 18 | '404', 19 | TransformSnapshot, 20 | ` 21 | \`\`\`kroki type=fake 22 | ss 23 | \`\`\` 24 | `, 25 | { server: 'https://kroki.io' }, 26 | false, 27 | ); 28 | -------------------------------------------------------------------------------- /test/helper/lib.mjs: -------------------------------------------------------------------------------- 1 | import { remark } from 'remark'; 2 | import remarkMdx from 'remark-mdx'; 3 | import { removePosition } from 'unist-util-remove-position'; 4 | 5 | import { remarkKroki } from '../../lib/index.mjs'; 6 | 7 | function removePST(ast) { 8 | removePosition(ast, { force: true }); 9 | 10 | return ast.children; 11 | } 12 | 13 | export async function transform(input, option = {}) { 14 | const instance = remark().use(remarkKroki, option); 15 | 16 | const ast = instance.parse(input); 17 | 18 | return { 19 | output: await instance 20 | .process(input) 21 | .then((file) => file.toString().trim()), 22 | tree: removePST(await instance.run(ast)), 23 | ast: removePST(ast), 24 | }; 25 | } 26 | 27 | export async function TransformSnapshot(t, input, option = {}, slice = false) { 28 | const instance = remark().use(remarkMdx).use(remarkKroki, option); 29 | 30 | const ast = instance.parse(input); 31 | 32 | t.snapshot(input, 'input'); 33 | t.snapshot(removePST(ast), 'ast'); 34 | 35 | const tree = removePST(await instance.run(ast)); 36 | 37 | t.snapshot(tree, 'parsed'); 38 | 39 | const output = await instance 40 | .process(input) 41 | .then((file) => file.toString().trim()) 42 | .then((text) => (slice ? text.slice(0, 4000) : text)); 43 | 44 | t.snapshot(output, 'result'); 45 | } 46 | -------------------------------------------------------------------------------- /test/output.mjs: -------------------------------------------------------------------------------- 1 | import test from 'ava'; 2 | 3 | import { TransformSnapshot } from './helper/lib.mjs'; 4 | 5 | test.before((t) => { 6 | t.timeout(1000 ** 3); 7 | }); 8 | 9 | const source = ` 10 | \`\`\`kroki type=plantuml classnames=w-half 11 | A --> B 12 | \`\`\` 13 | `; 14 | 15 | function macro(t, options) { 16 | return TransformSnapshot(t, source, { 17 | ...options, 18 | server: 'https://kroki.io', 19 | }); 20 | } 21 | 22 | const mode = ['inline-svg', 'img-base64', 'img-html-base64', 'object-base64']; 23 | 24 | const targets = ['html', 'mdx3']; 25 | 26 | for (const output of mode) { 27 | if (output === mode[1]) { 28 | test(output, macro, { output }); 29 | } else { 30 | for (const target of targets) { 31 | test(`${output} | ${target}`, macro, { output, target }); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /test/snapshots/base.mjs.md: -------------------------------------------------------------------------------- 1 | # Snapshot report for `test/base.mjs` 2 | 3 | The actual snapshot is saved in `base.mjs.snap`. 4 | 5 | Generated by [AVA](https://avajs.dev). 6 | 7 | ## empty 8 | 9 | > input 10 | 11 | `␊ 12 | \`\`\`kroki␊ 13 | \`\`\`␊ 14 | ␊ 15 | \`\`\`kroki type=plantuml␊ 16 | \`\`\`␊ 17 | ` 18 | 19 | > ast 20 | 21 | [ 22 | { 23 | lang: 'kroki', 24 | meta: null, 25 | type: 'code', 26 | value: '', 27 | }, 28 | { 29 | lang: 'kroki', 30 | meta: 'type=plantuml', 31 | type: 'code', 32 | value: '', 33 | }, 34 | ] 35 | 36 | > parsed 37 | 38 | [ 39 | { 40 | lang: 'kroki', 41 | meta: null, 42 | type: 'code', 43 | value: '', 44 | }, 45 | { 46 | lang: 'kroki', 47 | meta: 'type=plantuml', 48 | type: 'code', 49 | value: '', 50 | }, 51 | ] 52 | 53 | > result 54 | 55 | `\`\`\`kroki␊ 56 | \`\`\`␊ 57 | ␊ 58 | \`\`\`kroki type=plantuml␊ 59 | \`\`\`` 60 | 61 | ## okay 62 | 63 | > input 64 | 65 | `␊ 66 | \`\`\`kroki type=plantuml alt=abc␊ 67 | A --> B␊ 68 | \`\`\`␊ 69 | ` 70 | 71 | > ast 72 | 73 | [ 74 | { 75 | lang: 'kroki', 76 | meta: 'type=plantuml alt=abc', 77 | type: 'code', 78 | value: ' A --> B', 79 | }, 80 | ] 81 | 82 | > parsed 83 | 84 | [ 85 | { 86 | children: [ 87 | { 88 | _meta: { 89 | kroki: true, 90 | type: 'plantuml', 91 | }, 92 | alt: 'abc', 93 | type: 'image', 94 | url: 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXMtYXNjaWkiIHN0YW5kYWxvbmU9Im5vIj8+PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBjb250ZW50U3R5bGVUeXBlPSJ0ZXh0L2NzcyIgaGVpZ2h0PSIxMDVweCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSIgc3R5bGU9IndpZHRoOjY4cHg7aGVpZ2h0OjEwNXB4O2JhY2tncm91bmQ6I0ZGRkZGRjsiIHZlcnNpb249IjEuMSIgdmlld0JveD0iMCAwIDY4IDEwNSIgd2lkdGg9IjY4cHgiIHpvb21BbmRQYW49Im1hZ25pZnkiPjxkZWZzLz48Zz48bGluZSBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjAuNTtzdHJva2UtZGFzaGFycmF5OjUuMCw1LjA7IiB4MT0iMTYiIHgyPSIxNiIgeTE9IjM2LjI5NjkiIHkyPSI3MC4yOTY5Ii8+PGxpbmUgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDowLjU7c3Ryb2tlLWRhc2hhcnJheTo1LjAsNS4wOyIgeDE9IjUwIiB4Mj0iNTAiIHkxPSIzNi4yOTY5IiB5Mj0iNzAuMjk2OSIvPjxyZWN0IGZpbGw9IiNFMkUyRjAiIGhlaWdodD0iMzAuMjk2OSIgcng9IjIuNSIgcnk9IjIuNSIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDowLjU7IiB3aWR0aD0iMjMiIHg9IjUiIHk9IjUiLz48dGV4dCBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0ic2Fucy1zZXJpZiIgZm9udC1zaXplPSIxNCIgbGVuZ3RoQWRqdXN0PSJzcGFjaW5nIiB0ZXh0TGVuZ3RoPSI5IiB4PSIxMiIgeT0iMjQuOTk1MSI+QTwvdGV4dD48cmVjdCBmaWxsPSIjRTJFMkYwIiBoZWlnaHQ9IjMwLjI5NjkiIHJ4PSIyLjUiIHJ5PSIyLjUiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MC41OyIgd2lkdGg9IjIzIiB4PSI1IiB5PSI2OS4yOTY5Ii8+PHRleHQgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9InNhbnMtc2VyaWYiIGZvbnQtc2l6ZT0iMTQiIGxlbmd0aEFkanVzdD0ic3BhY2luZyIgdGV4dExlbmd0aD0iOSIgeD0iMTIiIHk9Ijg5LjI5MiI+QTwvdGV4dD48cmVjdCBmaWxsPSIjRTJFMkYwIiBoZWlnaHQ9IjMwLjI5NjkiIHJ4PSIyLjUiIHJ5PSIyLjUiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MC41OyIgd2lkdGg9IjI0IiB4PSIzOCIgeT0iNSIvPjx0ZXh0IGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBsZW5ndGhBZGp1c3Q9InNwYWNpbmciIHRleHRMZW5ndGg9IjEwIiB4PSI0NSIgeT0iMjQuOTk1MSI+QjwvdGV4dD48cmVjdCBmaWxsPSIjRTJFMkYwIiBoZWlnaHQ9IjMwLjI5NjkiIHJ4PSIyLjUiIHJ5PSIyLjUiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MC41OyIgd2lkdGg9IjI0IiB4PSIzOCIgeT0iNjkuMjk2OSIvPjx0ZXh0IGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBsZW5ndGhBZGp1c3Q9InNwYWNpbmciIHRleHRMZW5ndGg9IjEwIiB4PSI0NSIgeT0iODkuMjkyIj5CPC90ZXh0Pjxwb2x5Z29uIGZpbGw9IiMxODE4MTgiIHBvaW50cz0iMzgsNDguMjk2OSw0OCw1Mi4yOTY5LDM4LDU2LjI5NjksNDIsNTIuMjk2OSIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxLjA7Ii8+PGxpbmUgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxLjA7c3Ryb2tlLWRhc2hhcnJheToyLjAsMi4wOyIgeDE9IjE2LjUiIHgyPSI0NCIgeTE9IjUyLjI5NjkiIHkyPSI1Mi4yOTY5Ii8+PCEtLVNSQz1bU3JKR3JSTEpTMDgwXS0tPjwvZz48L3N2Zz4=', 95 | }, 96 | ], 97 | type: 'paragraph', 98 | }, 99 | ] 100 | 101 | > result 102 | 103 | '![abc](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXMtYXNjaWkiIHN0YW5kYWxvbmU9Im5vIj8+PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBjb250ZW50U3R5bGVUeXBlPSJ0ZXh0L2NzcyIgaGVpZ2h0PSIxMDVweCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSIgc3R5bGU9IndpZHRoOjY4cHg7aGVpZ2h0OjEwNXB4O2JhY2tncm91bmQ6I0ZGRkZGRjsiIHZlcnNpb249IjEuMSIgdmlld0JveD0iMCAwIDY4IDEwNSIgd2lkdGg9IjY4cHgiIHpvb21BbmRQYW49Im1hZ25pZnkiPjxkZWZzLz48Zz48bGluZSBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjAuNTtzdHJva2UtZGFzaGFycmF5OjUuMCw1LjA7IiB4MT0iMTYiIHgyPSIxNiIgeTE9IjM2LjI5NjkiIHkyPSI3MC4yOTY5Ii8+PGxpbmUgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDowLjU7c3Ryb2tlLWRhc2hhcnJheTo1LjAsNS4wOyIgeDE9IjUwIiB4Mj0iNTAiIHkxPSIzNi4yOTY5IiB5Mj0iNzAuMjk2OSIvPjxyZWN0IGZpbGw9IiNFMkUyRjAiIGhlaWdodD0iMzAuMjk2OSIgcng9IjIuNSIgcnk9IjIuNSIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDowLjU7IiB3aWR0aD0iMjMiIHg9IjUiIHk9IjUiLz48dGV4dCBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0ic2Fucy1zZXJpZiIgZm9udC1zaXplPSIxNCIgbGVuZ3RoQWRqdXN0PSJzcGFjaW5nIiB0ZXh0TGVuZ3RoPSI5IiB4PSIxMiIgeT0iMjQuOTk1MSI+QTwvdGV4dD48cmVjdCBmaWxsPSIjRTJFMkYwIiBoZWlnaHQ9IjMwLjI5NjkiIHJ4PSIyLjUiIHJ5PSIyLjUiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MC41OyIgd2lkdGg9IjIzIiB4PSI1IiB5PSI2OS4yOTY5Ii8+PHRleHQgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9InNhbnMtc2VyaWYiIGZvbnQtc2l6ZT0iMTQiIGxlbmd0aEFkanVzdD0ic3BhY2luZyIgdGV4dExlbmd0aD0iOSIgeD0iMTIiIHk9Ijg5LjI5MiI+QTwvdGV4dD48cmVjdCBmaWxsPSIjRTJFMkYwIiBoZWlnaHQ9IjMwLjI5NjkiIHJ4PSIyLjUiIHJ5PSIyLjUiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MC41OyIgd2lkdGg9IjI0IiB4PSIzOCIgeT0iNSIvPjx0ZXh0IGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBsZW5ndGhBZGp1c3Q9InNwYWNpbmciIHRleHRMZW5ndGg9IjEwIiB4PSI0NSIgeT0iMjQuOTk1MSI+QjwvdGV4dD48cmVjdCBmaWxsPSIjRTJFMkYwIiBoZWlnaHQ9IjMwLjI5NjkiIHJ4PSIyLjUiIHJ5PSIyLjUiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MC41OyIgd2lkdGg9IjI0IiB4PSIzOCIgeT0iNjkuMjk2OSIvPjx0ZXh0IGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBsZW5ndGhBZGp1c3Q9InNwYWNpbmciIHRleHRMZW5ndGg9IjEwIiB4PSI0NSIgeT0iODkuMjkyIj5CPC90ZXh0Pjxwb2x5Z29uIGZpbGw9IiMxODE4MTgiIHBvaW50cz0iMzgsNDguMjk2OSw0OCw1Mi4yOTY5LDM4LDU2LjI5NjksNDIsNTIuMjk2OSIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxLjA7Ii8+PGxpbmUgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxLjA7c3Ryb2tlLWRhc2hhcnJheToyLjAsMi4wOyIgeDE9IjE2LjUiIHgyPSI0NCIgeTE9IjUyLjI5NjkiIHkyPSI1Mi4yOTY5Ii8+PCEtLVNSQz1bU3JKR3JSTEpTMDgwXS0tPjwvZz48L3N2Zz4=)' 104 | 105 | ## alias 106 | 107 | > input 108 | 109 | `␊ 110 | \`\`\`plantuml type=mermaid alt=abc␊ 111 | A --> B␊ 112 | \`\`\`␊ 113 | ` 114 | 115 | > ast 116 | 117 | [ 118 | { 119 | lang: 'plantuml', 120 | meta: 'type=mermaid alt=abc', 121 | type: 'code', 122 | value: ' A --> B', 123 | }, 124 | ] 125 | 126 | > parsed 127 | 128 | [ 129 | { 130 | children: [ 131 | { 132 | _meta: { 133 | kroki: true, 134 | type: 'plantuml', 135 | }, 136 | alt: 'abc', 137 | type: 'image', 138 | url: 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXMtYXNjaWkiIHN0YW5kYWxvbmU9Im5vIj8+PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBjb250ZW50U3R5bGVUeXBlPSJ0ZXh0L2NzcyIgaGVpZ2h0PSIxMDVweCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSIgc3R5bGU9IndpZHRoOjY4cHg7aGVpZ2h0OjEwNXB4O2JhY2tncm91bmQ6I0ZGRkZGRjsiIHZlcnNpb249IjEuMSIgdmlld0JveD0iMCAwIDY4IDEwNSIgd2lkdGg9IjY4cHgiIHpvb21BbmRQYW49Im1hZ25pZnkiPjxkZWZzLz48Zz48bGluZSBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjAuNTtzdHJva2UtZGFzaGFycmF5OjUuMCw1LjA7IiB4MT0iMTYiIHgyPSIxNiIgeTE9IjM2LjI5NjkiIHkyPSI3MC4yOTY5Ii8+PGxpbmUgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDowLjU7c3Ryb2tlLWRhc2hhcnJheTo1LjAsNS4wOyIgeDE9IjUwIiB4Mj0iNTAiIHkxPSIzNi4yOTY5IiB5Mj0iNzAuMjk2OSIvPjxyZWN0IGZpbGw9IiNFMkUyRjAiIGhlaWdodD0iMzAuMjk2OSIgcng9IjIuNSIgcnk9IjIuNSIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDowLjU7IiB3aWR0aD0iMjMiIHg9IjUiIHk9IjUiLz48dGV4dCBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0ic2Fucy1zZXJpZiIgZm9udC1zaXplPSIxNCIgbGVuZ3RoQWRqdXN0PSJzcGFjaW5nIiB0ZXh0TGVuZ3RoPSI5IiB4PSIxMiIgeT0iMjQuOTk1MSI+QTwvdGV4dD48cmVjdCBmaWxsPSIjRTJFMkYwIiBoZWlnaHQ9IjMwLjI5NjkiIHJ4PSIyLjUiIHJ5PSIyLjUiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MC41OyIgd2lkdGg9IjIzIiB4PSI1IiB5PSI2OS4yOTY5Ii8+PHRleHQgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9InNhbnMtc2VyaWYiIGZvbnQtc2l6ZT0iMTQiIGxlbmd0aEFkanVzdD0ic3BhY2luZyIgdGV4dExlbmd0aD0iOSIgeD0iMTIiIHk9Ijg5LjI5MiI+QTwvdGV4dD48cmVjdCBmaWxsPSIjRTJFMkYwIiBoZWlnaHQ9IjMwLjI5NjkiIHJ4PSIyLjUiIHJ5PSIyLjUiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MC41OyIgd2lkdGg9IjI0IiB4PSIzOCIgeT0iNSIvPjx0ZXh0IGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBsZW5ndGhBZGp1c3Q9InNwYWNpbmciIHRleHRMZW5ndGg9IjEwIiB4PSI0NSIgeT0iMjQuOTk1MSI+QjwvdGV4dD48cmVjdCBmaWxsPSIjRTJFMkYwIiBoZWlnaHQ9IjMwLjI5NjkiIHJ4PSIyLjUiIHJ5PSIyLjUiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MC41OyIgd2lkdGg9IjI0IiB4PSIzOCIgeT0iNjkuMjk2OSIvPjx0ZXh0IGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBsZW5ndGhBZGp1c3Q9InNwYWNpbmciIHRleHRMZW5ndGg9IjEwIiB4PSI0NSIgeT0iODkuMjkyIj5CPC90ZXh0Pjxwb2x5Z29uIGZpbGw9IiMxODE4MTgiIHBvaW50cz0iMzgsNDguMjk2OSw0OCw1Mi4yOTY5LDM4LDU2LjI5NjksNDIsNTIuMjk2OSIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxLjA7Ii8+PGxpbmUgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxLjA7c3Ryb2tlLWRhc2hhcnJheToyLjAsMi4wOyIgeDE9IjE2LjUiIHgyPSI0NCIgeTE9IjUyLjI5NjkiIHkyPSI1Mi4yOTY5Ii8+PCEtLVNSQz1bU3JKR3JSTEpTMDgwXS0tPjwvZz48L3N2Zz4=', 139 | }, 140 | ], 141 | type: 'paragraph', 142 | }, 143 | ] 144 | 145 | > result 146 | 147 | '![abc](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXMtYXNjaWkiIHN0YW5kYWxvbmU9Im5vIj8+PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBjb250ZW50U3R5bGVUeXBlPSJ0ZXh0L2NzcyIgaGVpZ2h0PSIxMDVweCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSIgc3R5bGU9IndpZHRoOjY4cHg7aGVpZ2h0OjEwNXB4O2JhY2tncm91bmQ6I0ZGRkZGRjsiIHZlcnNpb249IjEuMSIgdmlld0JveD0iMCAwIDY4IDEwNSIgd2lkdGg9IjY4cHgiIHpvb21BbmRQYW49Im1hZ25pZnkiPjxkZWZzLz48Zz48bGluZSBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjAuNTtzdHJva2UtZGFzaGFycmF5OjUuMCw1LjA7IiB4MT0iMTYiIHgyPSIxNiIgeTE9IjM2LjI5NjkiIHkyPSI3MC4yOTY5Ii8+PGxpbmUgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDowLjU7c3Ryb2tlLWRhc2hhcnJheTo1LjAsNS4wOyIgeDE9IjUwIiB4Mj0iNTAiIHkxPSIzNi4yOTY5IiB5Mj0iNzAuMjk2OSIvPjxyZWN0IGZpbGw9IiNFMkUyRjAiIGhlaWdodD0iMzAuMjk2OSIgcng9IjIuNSIgcnk9IjIuNSIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDowLjU7IiB3aWR0aD0iMjMiIHg9IjUiIHk9IjUiLz48dGV4dCBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0ic2Fucy1zZXJpZiIgZm9udC1zaXplPSIxNCIgbGVuZ3RoQWRqdXN0PSJzcGFjaW5nIiB0ZXh0TGVuZ3RoPSI5IiB4PSIxMiIgeT0iMjQuOTk1MSI+QTwvdGV4dD48cmVjdCBmaWxsPSIjRTJFMkYwIiBoZWlnaHQ9IjMwLjI5NjkiIHJ4PSIyLjUiIHJ5PSIyLjUiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MC41OyIgd2lkdGg9IjIzIiB4PSI1IiB5PSI2OS4yOTY5Ii8+PHRleHQgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9InNhbnMtc2VyaWYiIGZvbnQtc2l6ZT0iMTQiIGxlbmd0aEFkanVzdD0ic3BhY2luZyIgdGV4dExlbmd0aD0iOSIgeD0iMTIiIHk9Ijg5LjI5MiI+QTwvdGV4dD48cmVjdCBmaWxsPSIjRTJFMkYwIiBoZWlnaHQ9IjMwLjI5NjkiIHJ4PSIyLjUiIHJ5PSIyLjUiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MC41OyIgd2lkdGg9IjI0IiB4PSIzOCIgeT0iNSIvPjx0ZXh0IGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBsZW5ndGhBZGp1c3Q9InNwYWNpbmciIHRleHRMZW5ndGg9IjEwIiB4PSI0NSIgeT0iMjQuOTk1MSI+QjwvdGV4dD48cmVjdCBmaWxsPSIjRTJFMkYwIiBoZWlnaHQ9IjMwLjI5NjkiIHJ4PSIyLjUiIHJ5PSIyLjUiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MC41OyIgd2lkdGg9IjI0IiB4PSIzOCIgeT0iNjkuMjk2OSIvPjx0ZXh0IGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBsZW5ndGhBZGp1c3Q9InNwYWNpbmciIHRleHRMZW5ndGg9IjEwIiB4PSI0NSIgeT0iODkuMjkyIj5CPC90ZXh0Pjxwb2x5Z29uIGZpbGw9IiMxODE4MTgiIHBvaW50cz0iMzgsNDguMjk2OSw0OCw1Mi4yOTY5LDM4LDU2LjI5NjksNDIsNTIuMjk2OSIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxLjA7Ii8+PGxpbmUgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxLjA7c3Ryb2tlLWRhc2hhcnJheToyLjAsMi4wOyIgeDE9IjE2LjUiIHgyPSI0NCIgeTE9IjUyLjI5NjkiIHkyPSI1Mi4yOTY5Ii8+PCEtLVNSQz1bU3JKR3JSTEpTMDgwXS0tPjwvZz48L3N2Zz4=)' 148 | -------------------------------------------------------------------------------- /test/snapshots/base.mjs.snap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/show-docs/remark-kroki/5d2f4984c9bcbee796b319978e42c6e31dd95488/test/snapshots/base.mjs.snap -------------------------------------------------------------------------------- /test/snapshots/fail.mjs.md: -------------------------------------------------------------------------------- 1 | # Snapshot report for `test/fail.mjs` 2 | 3 | The actual snapshot is saved in `fail.mjs.snap`. 4 | 5 | Generated by [AVA](https://avajs.dev). 6 | 7 | ## input 8 | 9 | > input 10 | 11 | `␊ 12 | \`\`\`kroki type=plantuml alt=00␊ 13 | ss␊ 14 | \`\`\`␊ 15 | ` 16 | 17 | > ast 18 | 19 | [ 20 | { 21 | lang: 'kroki', 22 | meta: 'type=plantuml alt=00', 23 | type: 'code', 24 | value: 'ss', 25 | }, 26 | ] 27 | 28 | > parsed 29 | 30 | [ 31 | { 32 | children: [ 33 | { 34 | _meta: { 35 | kroki: true, 36 | type: 'plantuml', 37 | }, 38 | alt: '00', 39 | type: 'image', 40 | url: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2MDAgMTgwIj4KICA8cGF0aAogICAgZmlsbD0iI2FhYSIKICAgIGQ9Ik05Mi4xNyAzOS43NWMtLjE4LjIxIDAgLjk5Ljk3IDQuMTEuNzcgMi41Ljk1IDMuNy42OCA0LjY2LS4yMy44Mi0uNjEgMS4xOC0xLjYgMS40OS0uNDIuMTMtLjg2LjI4LS45OC4zMi0uMTIuMDQtLjM3LjAxLS41NS0uMDYtLjU5LS4yNC0xLjcxLTIuMTUtMi41Mi00LjMxLTEuNjMtNC4zNS0zLjc2LTE0LjQyLTUuNy0yNi45LS42MS0zLjk0LS43My01Ljc2LS40Ni02LjcxLjIyLS43OC45MS0xLjY2IDEuNTEtMS45Ny45OC0uNSAxLjM3LS41IDIuMzYtLjAzLjQ3LjIyNi43ODYuMzQzIDEuMDAyLjU2Mi40NDkuNDU1LjQ1NiAxLjM0Ni40OCA0LjU2NWwuMDA4Ljk2M2MuMDMgMy42My4xMiA1LjYuMyA3LjA1LjQxIDMuMTQuNTkgNC4wMi44NyA0LjA4LjE1LjAyLjc4LS42IDEuNjktMS42NyAxLjg3LTIuMjIgNS4wNC01LjI4IDYuNDMtNi4yIDEuODMtMS4yMyAyLjg2LTEuNjMgNC4xMi0xLjY0LjgzIDAgMS4yNS4wOCAxLjc5LjM1LjkzLjQ2IDEuMTYuOTUuOTkgMi4wN2wtLjEzLjg2LTIuMjcgMi4wNWMtMy43NSAzLjM5LTcuMTIgNy4wNy04LjMgOS4wOS0uNDkuODMtLjQ1IDEuMTIuMTYgMS4yNS41Ni4xMiA3Ljc1IDIuNjIgMTAuNDEgMy42MSAxLjE2LjQ0IDIuNjcuOTggMy4zNSAxLjIgMS42LjUzIDEuOTEuODYgMS45OSAyLjEuMTggMi43Mi0xLjExIDMuNTQtNC43OSAzLjA2LTMuMzYtLjQ0LTYuMDUtMS4yOS05LjQ5LTMuMDMtMS42NC0uODMtMi4yMS0xLjA2LTIuMzItLjkyWk0yMy4xOCAxNC45Yy0yLjk3IDAtNS42Ni44NC03LjkgMi40Ni0xLjc4IDEuMy02LjUxIDYuNDEtNy40NCA4LjA1LS40Ny44My0uODQgMS4wNC0xLjE1LjY0LS40NS0uNTctLjgtMi43NC0xLjAyLTYuMzEtLjMzLTUuNTMtLjUyLTYuNTUtMS41Mi04LjI1bC0uNDEtLjctLjc0LjA4Yy0xLjYuMTktMi41MSAxLjA5LTIuODcgMi44MS0uMjggMS4zMS0uMDkgNS4yNy4zNiA3LjcyIDEuNDQgNy44IDQuMiAxNy44NSA2LjU3IDIzLjg4IDEuMTYgMi45NSAyLjIyIDQuODQgMi45NyA1LjMuNjUuMzkgMS4yNS4zNyAyLjE4LS4xIDEuMDQtLjUxIDEuNDktMS4wOCAxLjcxLTIuMTMuNDMtMi4wOC0uMTEtNC4wMS0xLjk2LTcuMDgtMS40NS0yLjM5LTEuODUtMy4zMS0xLjg4LTQuMzQtLjA0LTEuMS4yMS0xLjI2IDEuNTgtMS4wNCAyLjIuMzcgNC4yOCAxLjM5IDguOSA0LjM3IDUuMTEgMy4zMSA3LjE1IDQuMjIgOS45MiA0LjQ4IDEuMzIuMTIgMS43LS4wNSAyLjE2LS45Ni40Mi0uODQuNDctMi40OS4xLTMuMjgtLjUxLTEuMDctMy40NC0zLjAzLTguMTQtNS40Mi00LjEyLTIuMTEtMTAuNjMtNC45Ni0xMi40Ni01LjQ1LS4xMS0uMDMtLjItLjE4LS4yLS4zMyAwLS40MSAzLjUzLTMuOTIgNi4yMi02LjE4IDIuNTgtMi4xOCA0LjQ2LTQuMDkgNS4xLTUuMTYuMjItLjM4LjQ5LTEuMTEuNTktMS42MWwuMDIzLS4xMWMuMTU4LS43NTQuMjI4LTEuMDg0LjA5NS0xLjIyOC0uMTAzLS4xMTItLjMyOS0uMTEyLS43My0uMTEyaC0uMDU4Wm05MC4yOC0uNWMxLjA1LjY1IDEuNzQgMS43MSAxLjgyIDIuNzcuMDMuNDgtLjAxIDEtLjEgMS4xNy0uNDUuODMtMi4xIDEtNC4yNi40NWwtMS4yOS0uMzMuMDUtLjgzYy4xLTIuMTEuNzktMy4xOCAyLjI0LTMuNDguODEtLjE3Ljg3LS4xNiAxLjU0LjI1Wm0xLjg4IDEwLjdjLjQ2LS4xMS40OC0uMDQuNjUgMS45Ny4xNiAxLjg2LjUyIDMuNjggMS41MSA3LjYzIDEuOTMgNy43IDIuNSAxMC43MSAyLjUgMTMuMiAwIDEuMzEtLjQyIDIuMjgtMS4xNiAyLjcxLS41OC4zMy0xLjc0LjQ1LTIuNTIuMjUtMS4zLS4zMi0yLjA5LTEuMDctMi45OC0yLjg1LTEuNDctMi45Mi0yLjI3LTkuNjYtMi4wNC0xNy4wNGwuMTEtMy4zNS41My0uNjJjLjUxLS42IDIuNDEtMS42NiAzLjQtMS45Wm0tNTguMTUgNy41OGMuNDctMi4yNC0xLTQuNzQtMy40NC01Ljg4LS44NS0uNC0xLjI0LS40OC0yLjQtLjUzLTIuNTMtLjEyLTQuMDEuNDUtNS44MSAyLjI0LTEuNTQgMS41Mi0zLjI2IDQuNC0zLjc4IDYuMzQtLjI1LjkyLS42NC44Mi0xLjA2LS4yNi0uNjQtMS42MS0yLjI0LTQuNzktMi45MS01Ljc4LS45LTEuMzMtMS40OC0xLjcxLTIuNDUtMS42Mi0xLjI3LjEyLTEuOSAxLjE0LTEuOSAzLjA1IDAgMy40NyAzLjk0IDEyLjg5IDcuMiAxNy4yMyAxLjYgMi4xMiAyLjYzIDMuMDIgMy44MiAzLjM0Ljg5LjI0LjkyLjI0IDEuODMuMDUuODItLjE4IDEuNTgtLjg2IDEuNzctMS41OS4xOS0uNzktLjA2LTMuMTgtLjU2LTUuMi0uNDYtMS44NS0uNTEtMi4yMy0uNDktNC4xNS4wMy00LjIxIDEuMDMtNi42NiAyLjk2LTcuMi4zNS0uMS43OS0uMzIuOTgtLjQ4LjQ0LS4zOS41OS0uMjcgMS41IDEuMjlsLjcxIDEuMjEgMS4wMS0uMDhjMS44Ny0uMTYgMi43Ni0uNzQgMy4wMi0xLjk4Wm0uNyA1LjE1Yy44Ni0zLjgzIDQtNy41NiA4LjA4LTkuNjIgMi40OC0xLjI1IDQuNTctMS44MSA3LjE5LTEuOTIgMi40OC0uMTEgMy4xOC4xNCA0Ljc4IDEuNzUgMi4zMiAyLjMyIDMuNiA1LjcyIDMuNDIgOS4wNy0uMSAxLjkxLS4zOSAzLjAxLTEuMTcgNC41OC0xLjcxIDMuNDItNC41NyA2LjIxLTguMDkgNy45LTIuMzEgMS4xMS01LjA1IDEuNTktNy4yNiAxLjI4LTMuNzItLjUxLTYuMTctMy4wNi02Ljk4LTcuMjMtLjI5LTEuNTEtLjI3LTQuNDUuMDMtNS44MVptNy4xMS0uMWMtMS41NSAxLjg0LTEuOSAyLjU3LTEuOSAzLjkgMCAyLjA3Ljc4IDMuMjIgMi40OSAzLjY3Ljc3LjIgMi42Ni4wNCAzLjU0LS4zMiAxLjI2LS40OSAyLjQtMS4zMSAzLjczLTIuNjQgMS4zMy0xLjM1IDIuMDQtMi40MyAyLjYtMy45Ny42Ny0xLjg0LjYxLTMuOTctLjE1LTUuNDctLjQ1LS45Mi0uOTgtMS4yNy0xLjg1LTEuMjYtMS44LjAzLTUuNzcgMi44OS04LjQ2IDYuMDlaIgogIC8+CiAgPHRleHQgeT0iODAiIGZpbGw9IiNhYWEiIGZvbnQtc2l6ZT0iMTQiPkZhaWwsIHBsZWFzZSBjaGVjayB5b3VyIGlucHV0LjwvdGV4dD4KICA8Zm9yZWlnbk9iamVjdCB3aWR0aD0iNjAwIiBoZWlnaHQ9IjgwIiB5PSI5MCIgZm9udC1zaXplPSIxNCI+CiAgICA8ZGl2CiAgICAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIgogICAgICBzdHlsZT0iY29sb3I6I2ZmMjIwMDt3b3JkLWJyZWFrOmJyZWFrLWFsbCIKICAgID4KICAgICAgRXJyb3IgNDAwOiBTeW50YXggRXJyb3I/IChsaW5lOiAxKQogICAgPC9kaXY+CiAgPC9mb3JlaWduT2JqZWN0Pgo8L3N2Zz4K', 41 | }, 42 | ], 43 | type: 'paragraph', 44 | }, 45 | ] 46 | 47 | > result 48 | 49 | '![00](data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2MDAgMTgwIj4KICA8cGF0aAogICAgZmlsbD0iI2FhYSIKICAgIGQ9Ik05Mi4xNyAzOS43NWMtLjE4LjIxIDAgLjk5Ljk3IDQuMTEuNzcgMi41Ljk1IDMuNy42OCA0LjY2LS4yMy44Mi0uNjEgMS4xOC0xLjYgMS40OS0uNDIuMTMtLjg2LjI4LS45OC4zMi0uMTIuMDQtLjM3LjAxLS41NS0uMDYtLjU5LS4yNC0xLjcxLTIuMTUtMi41Mi00LjMxLTEuNjMtNC4zNS0zLjc2LTE0LjQyLTUuNy0yNi45LS42MS0zLjk0LS43My01Ljc2LS40Ni02LjcxLjIyLS43OC45MS0xLjY2IDEuNTEtMS45Ny45OC0uNSAxLjM3LS41IDIuMzYtLjAzLjQ3LjIyNi43ODYuMzQzIDEuMDAyLjU2Mi40NDkuNDU1LjQ1NiAxLjM0Ni40OCA0LjU2NWwuMDA4Ljk2M2MuMDMgMy42My4xMiA1LjYuMyA3LjA1LjQxIDMuMTQuNTkgNC4wMi44NyA0LjA4LjE1LjAyLjc4LS42IDEuNjktMS42NyAxLjg3LTIuMjIgNS4wNC01LjI4IDYuNDMtNi4yIDEuODMtMS4yMyAyLjg2LTEuNjMgNC4xMi0xLjY0LjgzIDAgMS4yNS4wOCAxLjc5LjM1LjkzLjQ2IDEuMTYuOTUuOTkgMi4wN2wtLjEzLjg2LTIuMjcgMi4wNWMtMy43NSAzLjM5LTcuMTIgNy4wNy04LjMgOS4wOS0uNDkuODMtLjQ1IDEuMTIuMTYgMS4yNS41Ni4xMiA3Ljc1IDIuNjIgMTAuNDEgMy42MSAxLjE2LjQ0IDIuNjcuOTggMy4zNSAxLjIgMS42LjUzIDEuOTEuODYgMS45OSAyLjEuMTggMi43Mi0xLjExIDMuNTQtNC43OSAzLjA2LTMuMzYtLjQ0LTYuMDUtMS4yOS05LjQ5LTMuMDMtMS42NC0uODMtMi4yMS0xLjA2LTIuMzItLjkyWk0yMy4xOCAxNC45Yy0yLjk3IDAtNS42Ni44NC03LjkgMi40Ni0xLjc4IDEuMy02LjUxIDYuNDEtNy40NCA4LjA1LS40Ny44My0uODQgMS4wNC0xLjE1LjY0LS40NS0uNTctLjgtMi43NC0xLjAyLTYuMzEtLjMzLTUuNTMtLjUyLTYuNTUtMS41Mi04LjI1bC0uNDEtLjctLjc0LjA4Yy0xLjYuMTktMi41MSAxLjA5LTIuODcgMi44MS0uMjggMS4zMS0uMDkgNS4yNy4zNiA3LjcyIDEuNDQgNy44IDQuMiAxNy44NSA2LjU3IDIzLjg4IDEuMTYgMi45NSAyLjIyIDQuODQgMi45NyA1LjMuNjUuMzkgMS4yNS4zNyAyLjE4LS4xIDEuMDQtLjUxIDEuNDktMS4wOCAxLjcxLTIuMTMuNDMtMi4wOC0uMTEtNC4wMS0xLjk2LTcuMDgtMS40NS0yLjM5LTEuODUtMy4zMS0xLjg4LTQuMzQtLjA0LTEuMS4yMS0xLjI2IDEuNTgtMS4wNCAyLjIuMzcgNC4yOCAxLjM5IDguOSA0LjM3IDUuMTEgMy4zMSA3LjE1IDQuMjIgOS45MiA0LjQ4IDEuMzIuMTIgMS43LS4wNSAyLjE2LS45Ni40Mi0uODQuNDctMi40OS4xLTMuMjgtLjUxLTEuMDctMy40NC0zLjAzLTguMTQtNS40Mi00LjEyLTIuMTEtMTAuNjMtNC45Ni0xMi40Ni01LjQ1LS4xMS0uMDMtLjItLjE4LS4yLS4zMyAwLS40MSAzLjUzLTMuOTIgNi4yMi02LjE4IDIuNTgtMi4xOCA0LjQ2LTQuMDkgNS4xLTUuMTYuMjItLjM4LjQ5LTEuMTEuNTktMS42MWwuMDIzLS4xMWMuMTU4LS43NTQuMjI4LTEuMDg0LjA5NS0xLjIyOC0uMTAzLS4xMTItLjMyOS0uMTEyLS43My0uMTEyaC0uMDU4Wm05MC4yOC0uNWMxLjA1LjY1IDEuNzQgMS43MSAxLjgyIDIuNzcuMDMuNDgtLjAxIDEtLjEgMS4xNy0uNDUuODMtMi4xIDEtNC4yNi40NWwtMS4yOS0uMzMuMDUtLjgzYy4xLTIuMTEuNzktMy4xOCAyLjI0LTMuNDguODEtLjE3Ljg3LS4xNiAxLjU0LjI1Wm0xLjg4IDEwLjdjLjQ2LS4xMS40OC0uMDQuNjUgMS45Ny4xNiAxLjg2LjUyIDMuNjggMS41MSA3LjYzIDEuOTMgNy43IDIuNSAxMC43MSAyLjUgMTMuMiAwIDEuMzEtLjQyIDIuMjgtMS4xNiAyLjcxLS41OC4zMy0xLjc0LjQ1LTIuNTIuMjUtMS4zLS4zMi0yLjA5LTEuMDctMi45OC0yLjg1LTEuNDctMi45Mi0yLjI3LTkuNjYtMi4wNC0xNy4wNGwuMTEtMy4zNS41My0uNjJjLjUxLS42IDIuNDEtMS42NiAzLjQtMS45Wm0tNTguMTUgNy41OGMuNDctMi4yNC0xLTQuNzQtMy40NC01Ljg4LS44NS0uNC0xLjI0LS40OC0yLjQtLjUzLTIuNTMtLjEyLTQuMDEuNDUtNS44MSAyLjI0LTEuNTQgMS41Mi0zLjI2IDQuNC0zLjc4IDYuMzQtLjI1LjkyLS42NC44Mi0xLjA2LS4yNi0uNjQtMS42MS0yLjI0LTQuNzktMi45MS01Ljc4LS45LTEuMzMtMS40OC0xLjcxLTIuNDUtMS42Mi0xLjI3LjEyLTEuOSAxLjE0LTEuOSAzLjA1IDAgMy40NyAzLjk0IDEyLjg5IDcuMiAxNy4yMyAxLjYgMi4xMiAyLjYzIDMuMDIgMy44MiAzLjM0Ljg5LjI0LjkyLjI0IDEuODMuMDUuODItLjE4IDEuNTgtLjg2IDEuNzctMS41OS4xOS0uNzktLjA2LTMuMTgtLjU2LTUuMi0uNDYtMS44NS0uNTEtMi4yMy0uNDktNC4xNS4wMy00LjIxIDEuMDMtNi42NiAyLjk2LTcuMi4zNS0uMS43OS0uMzIuOTgtLjQ4LjQ0LS4zOS41OS0uMjcgMS41IDEuMjlsLjcxIDEuMjEgMS4wMS0uMDhjMS44Ny0uMTYgMi43Ni0uNzQgMy4wMi0xLjk4Wm0uNyA1LjE1Yy44Ni0zLjgzIDQtNy41NiA4LjA4LTkuNjIgMi40OC0xLjI1IDQuNTctMS44MSA3LjE5LTEuOTIgMi40OC0uMTEgMy4xOC4xNCA0Ljc4IDEuNzUgMi4zMiAyLjMyIDMuNiA1LjcyIDMuNDIgOS4wNy0uMSAxLjkxLS4zOSAzLjAxLTEuMTcgNC41OC0xLjcxIDMuNDItNC41NyA2LjIxLTguMDkgNy45LTIuMzEgMS4xMS01LjA1IDEuNTktNy4yNiAxLjI4LTMuNzItLjUxLTYuMTctMy4wNi02Ljk4LTcuMjMtLjI5LTEuNTEtLjI3LTQuNDUuMDMtNS44MVptNy4xMS0uMWMtMS41NSAxLjg0LTEuOSAyLjU3LTEuOSAzLjkgMCAyLjA3Ljc4IDMuMjIgMi40OSAzLjY3Ljc3LjIgMi42Ni4wNCAzLjU0LS4zMiAxLjI2LS40OSAyLjQtMS4zMSAzLjczLTIuNjQgMS4zMy0xLjM1IDIuMDQtMi40MyAyLjYtMy45Ny42Ny0xLjg0LjYxLTMuOTctLjE1LTUuNDctLjQ1LS45Mi0uOTgtMS4yNy0xLjg1LTEuMjYtMS44LjAzLTUuNzcgMi44OS04LjQ2IDYuMDlaIgogIC8+CiAgPHRleHQgeT0iODAiIGZpbGw9IiNhYWEiIGZvbnQtc2l6ZT0iMTQiPkZhaWwsIHBsZWFzZSBjaGVjayB5b3VyIGlucHV0LjwvdGV4dD4KICA8Zm9yZWlnbk9iamVjdCB3aWR0aD0iNjAwIiBoZWlnaHQ9IjgwIiB5PSI5MCIgZm9udC1zaXplPSIxNCI+CiAgICA8ZGl2CiAgICAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIgogICAgICBzdHlsZT0iY29sb3I6I2ZmMjIwMDt3b3JkLWJyZWFrOmJyZWFrLWFsbCIKICAgID4KICAgICAgRXJyb3IgNDAwOiBTeW50YXggRXJyb3I/IChsaW5lOiAxKQogICAgPC9kaXY+CiAgPC9mb3JlaWduT2JqZWN0Pgo8L3N2Zz4K)' 50 | 51 | ## 404 52 | 53 | > input 54 | 55 | `␊ 56 | \`\`\`kroki type=fake␊ 57 | ss␊ 58 | \`\`\`␊ 59 | ` 60 | 61 | > ast 62 | 63 | [ 64 | { 65 | lang: 'kroki', 66 | meta: 'type=fake', 67 | type: 'code', 68 | value: 'ss', 69 | }, 70 | ] 71 | 72 | > parsed 73 | 74 | [ 75 | { 76 | children: [ 77 | { 78 | _meta: { 79 | kroki: true, 80 | type: 'fake', 81 | }, 82 | alt: 'fake', 83 | type: 'image', 84 | url: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2MDAgMTgwIj4KICA8cGF0aAogICAgZmlsbD0iI2FhYSIKICAgIGQ9Ik05Mi4xNyAzOS43NWMtLjE4LjIxIDAgLjk5Ljk3IDQuMTEuNzcgMi41Ljk1IDMuNy42OCA0LjY2LS4yMy44Mi0uNjEgMS4xOC0xLjYgMS40OS0uNDIuMTMtLjg2LjI4LS45OC4zMi0uMTIuMDQtLjM3LjAxLS41NS0uMDYtLjU5LS4yNC0xLjcxLTIuMTUtMi41Mi00LjMxLTEuNjMtNC4zNS0zLjc2LTE0LjQyLTUuNy0yNi45LS42MS0zLjk0LS43My01Ljc2LS40Ni02LjcxLjIyLS43OC45MS0xLjY2IDEuNTEtMS45Ny45OC0uNSAxLjM3LS41IDIuMzYtLjAzLjQ3LjIyNi43ODYuMzQzIDEuMDAyLjU2Mi40NDkuNDU1LjQ1NiAxLjM0Ni40OCA0LjU2NWwuMDA4Ljk2M2MuMDMgMy42My4xMiA1LjYuMyA3LjA1LjQxIDMuMTQuNTkgNC4wMi44NyA0LjA4LjE1LjAyLjc4LS42IDEuNjktMS42NyAxLjg3LTIuMjIgNS4wNC01LjI4IDYuNDMtNi4yIDEuODMtMS4yMyAyLjg2LTEuNjMgNC4xMi0xLjY0LjgzIDAgMS4yNS4wOCAxLjc5LjM1LjkzLjQ2IDEuMTYuOTUuOTkgMi4wN2wtLjEzLjg2LTIuMjcgMi4wNWMtMy43NSAzLjM5LTcuMTIgNy4wNy04LjMgOS4wOS0uNDkuODMtLjQ1IDEuMTIuMTYgMS4yNS41Ni4xMiA3Ljc1IDIuNjIgMTAuNDEgMy42MSAxLjE2LjQ0IDIuNjcuOTggMy4zNSAxLjIgMS42LjUzIDEuOTEuODYgMS45OSAyLjEuMTggMi43Mi0xLjExIDMuNTQtNC43OSAzLjA2LTMuMzYtLjQ0LTYuMDUtMS4yOS05LjQ5LTMuMDMtMS42NC0uODMtMi4yMS0xLjA2LTIuMzItLjkyWk0yMy4xOCAxNC45Yy0yLjk3IDAtNS42Ni44NC03LjkgMi40Ni0xLjc4IDEuMy02LjUxIDYuNDEtNy40NCA4LjA1LS40Ny44My0uODQgMS4wNC0xLjE1LjY0LS40NS0uNTctLjgtMi43NC0xLjAyLTYuMzEtLjMzLTUuNTMtLjUyLTYuNTUtMS41Mi04LjI1bC0uNDEtLjctLjc0LjA4Yy0xLjYuMTktMi41MSAxLjA5LTIuODcgMi44MS0uMjggMS4zMS0uMDkgNS4yNy4zNiA3LjcyIDEuNDQgNy44IDQuMiAxNy44NSA2LjU3IDIzLjg4IDEuMTYgMi45NSAyLjIyIDQuODQgMi45NyA1LjMuNjUuMzkgMS4yNS4zNyAyLjE4LS4xIDEuMDQtLjUxIDEuNDktMS4wOCAxLjcxLTIuMTMuNDMtMi4wOC0uMTEtNC4wMS0xLjk2LTcuMDgtMS40NS0yLjM5LTEuODUtMy4zMS0xLjg4LTQuMzQtLjA0LTEuMS4yMS0xLjI2IDEuNTgtMS4wNCAyLjIuMzcgNC4yOCAxLjM5IDguOSA0LjM3IDUuMTEgMy4zMSA3LjE1IDQuMjIgOS45MiA0LjQ4IDEuMzIuMTIgMS43LS4wNSAyLjE2LS45Ni40Mi0uODQuNDctMi40OS4xLTMuMjgtLjUxLTEuMDctMy40NC0zLjAzLTguMTQtNS40Mi00LjEyLTIuMTEtMTAuNjMtNC45Ni0xMi40Ni01LjQ1LS4xMS0uMDMtLjItLjE4LS4yLS4zMyAwLS40MSAzLjUzLTMuOTIgNi4yMi02LjE4IDIuNTgtMi4xOCA0LjQ2LTQuMDkgNS4xLTUuMTYuMjItLjM4LjQ5LTEuMTEuNTktMS42MWwuMDIzLS4xMWMuMTU4LS43NTQuMjI4LTEuMDg0LjA5NS0xLjIyOC0uMTAzLS4xMTItLjMyOS0uMTEyLS43My0uMTEyaC0uMDU4Wm05MC4yOC0uNWMxLjA1LjY1IDEuNzQgMS43MSAxLjgyIDIuNzcuMDMuNDgtLjAxIDEtLjEgMS4xNy0uNDUuODMtMi4xIDEtNC4yNi40NWwtMS4yOS0uMzMuMDUtLjgzYy4xLTIuMTEuNzktMy4xOCAyLjI0LTMuNDguODEtLjE3Ljg3LS4xNiAxLjU0LjI1Wm0xLjg4IDEwLjdjLjQ2LS4xMS40OC0uMDQuNjUgMS45Ny4xNiAxLjg2LjUyIDMuNjggMS41MSA3LjYzIDEuOTMgNy43IDIuNSAxMC43MSAyLjUgMTMuMiAwIDEuMzEtLjQyIDIuMjgtMS4xNiAyLjcxLS41OC4zMy0xLjc0LjQ1LTIuNTIuMjUtMS4zLS4zMi0yLjA5LTEuMDctMi45OC0yLjg1LTEuNDctMi45Mi0yLjI3LTkuNjYtMi4wNC0xNy4wNGwuMTEtMy4zNS41My0uNjJjLjUxLS42IDIuNDEtMS42NiAzLjQtMS45Wm0tNTguMTUgNy41OGMuNDctMi4yNC0xLTQuNzQtMy40NC01Ljg4LS44NS0uNC0xLjI0LS40OC0yLjQtLjUzLTIuNTMtLjEyLTQuMDEuNDUtNS44MSAyLjI0LTEuNTQgMS41Mi0zLjI2IDQuNC0zLjc4IDYuMzQtLjI1LjkyLS42NC44Mi0xLjA2LS4yNi0uNjQtMS42MS0yLjI0LTQuNzktMi45MS01Ljc4LS45LTEuMzMtMS40OC0xLjcxLTIuNDUtMS42Mi0xLjI3LjEyLTEuOSAxLjE0LTEuOSAzLjA1IDAgMy40NyAzLjk0IDEyLjg5IDcuMiAxNy4yMyAxLjYgMi4xMiAyLjYzIDMuMDIgMy44MiAzLjM0Ljg5LjI0LjkyLjI0IDEuODMuMDUuODItLjE4IDEuNTgtLjg2IDEuNzctMS41OS4xOS0uNzktLjA2LTMuMTgtLjU2LTUuMi0uNDYtMS44NS0uNTEtMi4yMy0uNDktNC4xNS4wMy00LjIxIDEuMDMtNi42NiAyLjk2LTcuMi4zNS0uMS43OS0uMzIuOTgtLjQ4LjQ0LS4zOS41OS0uMjcgMS41IDEuMjlsLjcxIDEuMjEgMS4wMS0uMDhjMS44Ny0uMTYgMi43Ni0uNzQgMy4wMi0xLjk4Wm0uNyA1LjE1Yy44Ni0zLjgzIDQtNy41NiA4LjA4LTkuNjIgMi40OC0xLjI1IDQuNTctMS44MSA3LjE5LTEuOTIgMi40OC0uMTEgMy4xOC4xNCA0Ljc4IDEuNzUgMi4zMiAyLjMyIDMuNiA1LjcyIDMuNDIgOS4wNy0uMSAxLjkxLS4zOSAzLjAxLTEuMTcgNC41OC0xLjcxIDMuNDItNC41NyA2LjIxLTguMDkgNy45LTIuMzEgMS4xMS01LjA1IDEuNTktNy4yNiAxLjI4LTMuNzItLjUxLTYuMTctMy4wNi02Ljk4LTcuMjMtLjI5LTEuNTEtLjI3LTQuNDUuMDMtNS44MVptNy4xMS0uMWMtMS41NSAxLjg0LTEuOSAyLjU3LTEuOSAzLjkgMCAyLjA3Ljc4IDMuMjIgMi40OSAzLjY3Ljc3LjIgMi42Ni4wNCAzLjU0LS4zMiAxLjI2LS40OSAyLjQtMS4zMSAzLjczLTIuNjQgMS4zMy0xLjM1IDIuMDQtMi40MyAyLjYtMy45Ny42Ny0xLjg0LjYxLTMuOTctLjE1LTUuNDctLjQ1LS45Mi0uOTgtMS4yNy0xLjg1LTEuMjYtMS44LjAzLTUuNzcgMi44OS04LjQ2IDYuMDlaIgogIC8+CiAgPHRleHQgeT0iODAiIGZpbGw9IiNhYWEiIGZvbnQtc2l6ZT0iMTQiPkZhaWwsIHBsZWFzZSBjaGVjayB5b3VyIGlucHV0LjwvdGV4dD4KICA8Zm9yZWlnbk9iamVjdCB3aWR0aD0iNjAwIiBoZWlnaHQ9IjgwIiB5PSI5MCIgZm9udC1zaXplPSIxNCI+CiAgICA8ZGl2CiAgICAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIgogICAgICBzdHlsZT0iY29sb3I6I2ZmMjIwMDt3b3JkLWJyZWFrOmJyZWFrLWFsbCIKICAgID4KICAgICAgRXJyb3IgNDA0OiBOb3QgRm91bmQKICAgIDwvZGl2PgogIDwvZm9yZWlnbk9iamVjdD4KPC9zdmc+Cg==', 85 | }, 86 | ], 87 | type: 'paragraph', 88 | }, 89 | ] 90 | 91 | > result 92 | 93 | '![fake](data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2MDAgMTgwIj4KICA8cGF0aAogICAgZmlsbD0iI2FhYSIKICAgIGQ9Ik05Mi4xNyAzOS43NWMtLjE4LjIxIDAgLjk5Ljk3IDQuMTEuNzcgMi41Ljk1IDMuNy42OCA0LjY2LS4yMy44Mi0uNjEgMS4xOC0xLjYgMS40OS0uNDIuMTMtLjg2LjI4LS45OC4zMi0uMTIuMDQtLjM3LjAxLS41NS0uMDYtLjU5LS4yNC0xLjcxLTIuMTUtMi41Mi00LjMxLTEuNjMtNC4zNS0zLjc2LTE0LjQyLTUuNy0yNi45LS42MS0zLjk0LS43My01Ljc2LS40Ni02LjcxLjIyLS43OC45MS0xLjY2IDEuNTEtMS45Ny45OC0uNSAxLjM3LS41IDIuMzYtLjAzLjQ3LjIyNi43ODYuMzQzIDEuMDAyLjU2Mi40NDkuNDU1LjQ1NiAxLjM0Ni40OCA0LjU2NWwuMDA4Ljk2M2MuMDMgMy42My4xMiA1LjYuMyA3LjA1LjQxIDMuMTQuNTkgNC4wMi44NyA0LjA4LjE1LjAyLjc4LS42IDEuNjktMS42NyAxLjg3LTIuMjIgNS4wNC01LjI4IDYuNDMtNi4yIDEuODMtMS4yMyAyLjg2LTEuNjMgNC4xMi0xLjY0LjgzIDAgMS4yNS4wOCAxLjc5LjM1LjkzLjQ2IDEuMTYuOTUuOTkgMi4wN2wtLjEzLjg2LTIuMjcgMi4wNWMtMy43NSAzLjM5LTcuMTIgNy4wNy04LjMgOS4wOS0uNDkuODMtLjQ1IDEuMTIuMTYgMS4yNS41Ni4xMiA3Ljc1IDIuNjIgMTAuNDEgMy42MSAxLjE2LjQ0IDIuNjcuOTggMy4zNSAxLjIgMS42LjUzIDEuOTEuODYgMS45OSAyLjEuMTggMi43Mi0xLjExIDMuNTQtNC43OSAzLjA2LTMuMzYtLjQ0LTYuMDUtMS4yOS05LjQ5LTMuMDMtMS42NC0uODMtMi4yMS0xLjA2LTIuMzItLjkyWk0yMy4xOCAxNC45Yy0yLjk3IDAtNS42Ni44NC03LjkgMi40Ni0xLjc4IDEuMy02LjUxIDYuNDEtNy40NCA4LjA1LS40Ny44My0uODQgMS4wNC0xLjE1LjY0LS40NS0uNTctLjgtMi43NC0xLjAyLTYuMzEtLjMzLTUuNTMtLjUyLTYuNTUtMS41Mi04LjI1bC0uNDEtLjctLjc0LjA4Yy0xLjYuMTktMi41MSAxLjA5LTIuODcgMi44MS0uMjggMS4zMS0uMDkgNS4yNy4zNiA3LjcyIDEuNDQgNy44IDQuMiAxNy44NSA2LjU3IDIzLjg4IDEuMTYgMi45NSAyLjIyIDQuODQgMi45NyA1LjMuNjUuMzkgMS4yNS4zNyAyLjE4LS4xIDEuMDQtLjUxIDEuNDktMS4wOCAxLjcxLTIuMTMuNDMtMi4wOC0uMTEtNC4wMS0xLjk2LTcuMDgtMS40NS0yLjM5LTEuODUtMy4zMS0xLjg4LTQuMzQtLjA0LTEuMS4yMS0xLjI2IDEuNTgtMS4wNCAyLjIuMzcgNC4yOCAxLjM5IDguOSA0LjM3IDUuMTEgMy4zMSA3LjE1IDQuMjIgOS45MiA0LjQ4IDEuMzIuMTIgMS43LS4wNSAyLjE2LS45Ni40Mi0uODQuNDctMi40OS4xLTMuMjgtLjUxLTEuMDctMy40NC0zLjAzLTguMTQtNS40Mi00LjEyLTIuMTEtMTAuNjMtNC45Ni0xMi40Ni01LjQ1LS4xMS0uMDMtLjItLjE4LS4yLS4zMyAwLS40MSAzLjUzLTMuOTIgNi4yMi02LjE4IDIuNTgtMi4xOCA0LjQ2LTQuMDkgNS4xLTUuMTYuMjItLjM4LjQ5LTEuMTEuNTktMS42MWwuMDIzLS4xMWMuMTU4LS43NTQuMjI4LTEuMDg0LjA5NS0xLjIyOC0uMTAzLS4xMTItLjMyOS0uMTEyLS43My0uMTEyaC0uMDU4Wm05MC4yOC0uNWMxLjA1LjY1IDEuNzQgMS43MSAxLjgyIDIuNzcuMDMuNDgtLjAxIDEtLjEgMS4xNy0uNDUuODMtMi4xIDEtNC4yNi40NWwtMS4yOS0uMzMuMDUtLjgzYy4xLTIuMTEuNzktMy4xOCAyLjI0LTMuNDguODEtLjE3Ljg3LS4xNiAxLjU0LjI1Wm0xLjg4IDEwLjdjLjQ2LS4xMS40OC0uMDQuNjUgMS45Ny4xNiAxLjg2LjUyIDMuNjggMS41MSA3LjYzIDEuOTMgNy43IDIuNSAxMC43MSAyLjUgMTMuMiAwIDEuMzEtLjQyIDIuMjgtMS4xNiAyLjcxLS41OC4zMy0xLjc0LjQ1LTIuNTIuMjUtMS4zLS4zMi0yLjA5LTEuMDctMi45OC0yLjg1LTEuNDctMi45Mi0yLjI3LTkuNjYtMi4wNC0xNy4wNGwuMTEtMy4zNS41My0uNjJjLjUxLS42IDIuNDEtMS42NiAzLjQtMS45Wm0tNTguMTUgNy41OGMuNDctMi4yNC0xLTQuNzQtMy40NC01Ljg4LS44NS0uNC0xLjI0LS40OC0yLjQtLjUzLTIuNTMtLjEyLTQuMDEuNDUtNS44MSAyLjI0LTEuNTQgMS41Mi0zLjI2IDQuNC0zLjc4IDYuMzQtLjI1LjkyLS42NC44Mi0xLjA2LS4yNi0uNjQtMS42MS0yLjI0LTQuNzktMi45MS01Ljc4LS45LTEuMzMtMS40OC0xLjcxLTIuNDUtMS42Mi0xLjI3LjEyLTEuOSAxLjE0LTEuOSAzLjA1IDAgMy40NyAzLjk0IDEyLjg5IDcuMiAxNy4yMyAxLjYgMi4xMiAyLjYzIDMuMDIgMy44MiAzLjM0Ljg5LjI0LjkyLjI0IDEuODMuMDUuODItLjE4IDEuNTgtLjg2IDEuNzctMS41OS4xOS0uNzktLjA2LTMuMTgtLjU2LTUuMi0uNDYtMS44NS0uNTEtMi4yMy0uNDktNC4xNS4wMy00LjIxIDEuMDMtNi42NiAyLjk2LTcuMi4zNS0uMS43OS0uMzIuOTgtLjQ4LjQ0LS4zOS41OS0uMjcgMS41IDEuMjlsLjcxIDEuMjEgMS4wMS0uMDhjMS44Ny0uMTYgMi43Ni0uNzQgMy4wMi0xLjk4Wm0uNyA1LjE1Yy44Ni0zLjgzIDQtNy41NiA4LjA4LTkuNjIgMi40OC0xLjI1IDQuNTctMS44MSA3LjE5LTEuOTIgMi40OC0uMTEgMy4xOC4xNCA0Ljc4IDEuNzUgMi4zMiAyLjMyIDMuNiA1LjcyIDMuNDIgOS4wNy0uMSAxLjkxLS4zOSAzLjAxLTEuMTcgNC41OC0xLjcxIDMuNDItNC41NyA2LjIxLTguMDkgNy45LTIuMzEgMS4xMS01LjA1IDEuNTktNy4yNiAxLjI4LTMuNzItLjUxLTYuMTctMy4wNi02Ljk4LTcuMjMtLjI5LTEuNTEtLjI3LTQuNDUuMDMtNS44MVptNy4xMS0uMWMtMS41NSAxLjg0LTEuOSAyLjU3LTEuOSAzLjkgMCAyLjA3Ljc4IDMuMjIgMi40OSAzLjY3Ljc3LjIgMi42Ni4wNCAzLjU0LS4zMiAxLjI2LS40OSAyLjQtMS4zMSAzLjczLTIuNjQgMS4zMy0xLjM1IDIuMDQtMi40MyAyLjYtMy45Ny42Ny0xLjg0LjYxLTMuOTctLjE1LTUuNDctLjQ1LS45Mi0uOTgtMS4yNy0xLjg1LTEuMjYtMS44LjAzLTUuNzcgMi44OS04LjQ2IDYuMDlaIgogIC8+CiAgPHRleHQgeT0iODAiIGZpbGw9IiNhYWEiIGZvbnQtc2l6ZT0iMTQiPkZhaWwsIHBsZWFzZSBjaGVjayB5b3VyIGlucHV0LjwvdGV4dD4KICA8Zm9yZWlnbk9iamVjdCB3aWR0aD0iNjAwIiBoZWlnaHQ9IjgwIiB5PSI5MCIgZm9udC1zaXplPSIxNCI+CiAgICA8ZGl2CiAgICAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sIgogICAgICBzdHlsZT0iY29sb3I6I2ZmMjIwMDt3b3JkLWJyZWFrOmJyZWFrLWFsbCIKICAgID4KICAgICAgRXJyb3IgNDA0OiBOb3QgRm91bmQKICAgIDwvZGl2PgogIDwvZm9yZWlnbk9iamVjdD4KPC9zdmc+Cg==)' 94 | -------------------------------------------------------------------------------- /test/snapshots/fail.mjs.snap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/show-docs/remark-kroki/5d2f4984c9bcbee796b319978e42c6e31dd95488/test/snapshots/fail.mjs.snap -------------------------------------------------------------------------------- /test/snapshots/output.mjs.md: -------------------------------------------------------------------------------- 1 | # Snapshot report for `test/output.mjs` 2 | 3 | The actual snapshot is saved in `output.mjs.snap`. 4 | 5 | Generated by [AVA](https://avajs.dev). 6 | 7 | ## inline-svg | html 8 | 9 | > input 10 | 11 | `␊ 12 | \`\`\`kroki type=plantuml classnames=w-half␊ 13 | A --> B␊ 14 | \`\`\`␊ 15 | ` 16 | 17 | > ast 18 | 19 | [ 20 | { 21 | lang: 'kroki', 22 | meta: 'type=plantuml classnames=w-half', 23 | type: 'code', 24 | value: ' A --> B', 25 | }, 26 | ] 27 | 28 | > parsed 29 | 30 | [ 31 | { 32 | type: 'html', 33 | value: '

AABB

', 34 | }, 35 | ] 36 | 37 | > result 38 | 39 | '

AABB

' 40 | 41 | ## inline-svg | mdx3 42 | 43 | > input 44 | 45 | `␊ 46 | \`\`\`kroki type=plantuml classnames=w-half␊ 47 | A --> B␊ 48 | \`\`\`␊ 49 | ` 50 | 51 | > ast 52 | 53 | [ 54 | { 55 | lang: 'kroki', 56 | meta: 'type=plantuml classnames=w-half', 57 | type: 'code', 58 | value: ' A --> B', 59 | }, 60 | ] 61 | 62 | > parsed 63 | 64 | [ 65 | { 66 | attributes: [ 67 | { 68 | name: 'className', 69 | type: 'mdxJsxAttribute', 70 | value: 'kroki-inline-svg', 71 | }, 72 | { 73 | name: 'data-type', 74 | type: 'mdxJsxAttribute', 75 | value: 'plantuml', 76 | }, 77 | { 78 | name: 'data-alt', 79 | type: 'mdxJsxAttribute', 80 | value: 'plantuml', 81 | }, 82 | ], 83 | children: [ 84 | { 85 | type: 'html', 86 | value: 'AABB', 87 | }, 88 | ], 89 | name: 'p', 90 | type: 'mdxJsxFlowElement', 91 | }, 92 | ] 93 | 94 | > result 95 | 96 | `

␊ 97 | AABB␊ 98 |

` 99 | 100 | ## img-base64 101 | 102 | > input 103 | 104 | `␊ 105 | \`\`\`kroki type=plantuml classnames=w-half␊ 106 | A --> B␊ 107 | \`\`\`␊ 108 | ` 109 | 110 | > ast 111 | 112 | [ 113 | { 114 | lang: 'kroki', 115 | meta: 'type=plantuml classnames=w-half', 116 | type: 'code', 117 | value: ' A --> B', 118 | }, 119 | ] 120 | 121 | > parsed 122 | 123 | [ 124 | { 125 | children: [ 126 | { 127 | _meta: { 128 | kroki: true, 129 | type: 'plantuml', 130 | }, 131 | alt: 'plantuml', 132 | type: 'image', 133 | url: 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXMtYXNjaWkiIHN0YW5kYWxvbmU9Im5vIj8+PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBjb250ZW50U3R5bGVUeXBlPSJ0ZXh0L2NzcyIgaGVpZ2h0PSIxMDVweCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSIgc3R5bGU9IndpZHRoOjY4cHg7aGVpZ2h0OjEwNXB4O2JhY2tncm91bmQ6I0ZGRkZGRjsiIHZlcnNpb249IjEuMSIgdmlld0JveD0iMCAwIDY4IDEwNSIgd2lkdGg9IjY4cHgiIHpvb21BbmRQYW49Im1hZ25pZnkiPjxkZWZzLz48Zz48bGluZSBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjAuNTtzdHJva2UtZGFzaGFycmF5OjUuMCw1LjA7IiB4MT0iMTYiIHgyPSIxNiIgeTE9IjM2LjI5NjkiIHkyPSI3MC4yOTY5Ii8+PGxpbmUgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDowLjU7c3Ryb2tlLWRhc2hhcnJheTo1LjAsNS4wOyIgeDE9IjUwIiB4Mj0iNTAiIHkxPSIzNi4yOTY5IiB5Mj0iNzAuMjk2OSIvPjxyZWN0IGZpbGw9IiNFMkUyRjAiIGhlaWdodD0iMzAuMjk2OSIgcng9IjIuNSIgcnk9IjIuNSIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDowLjU7IiB3aWR0aD0iMjMiIHg9IjUiIHk9IjUiLz48dGV4dCBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0ic2Fucy1zZXJpZiIgZm9udC1zaXplPSIxNCIgbGVuZ3RoQWRqdXN0PSJzcGFjaW5nIiB0ZXh0TGVuZ3RoPSI5IiB4PSIxMiIgeT0iMjQuOTk1MSI+QTwvdGV4dD48cmVjdCBmaWxsPSIjRTJFMkYwIiBoZWlnaHQ9IjMwLjI5NjkiIHJ4PSIyLjUiIHJ5PSIyLjUiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MC41OyIgd2lkdGg9IjIzIiB4PSI1IiB5PSI2OS4yOTY5Ii8+PHRleHQgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9InNhbnMtc2VyaWYiIGZvbnQtc2l6ZT0iMTQiIGxlbmd0aEFkanVzdD0ic3BhY2luZyIgdGV4dExlbmd0aD0iOSIgeD0iMTIiIHk9Ijg5LjI5MiI+QTwvdGV4dD48cmVjdCBmaWxsPSIjRTJFMkYwIiBoZWlnaHQ9IjMwLjI5NjkiIHJ4PSIyLjUiIHJ5PSIyLjUiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MC41OyIgd2lkdGg9IjI0IiB4PSIzOCIgeT0iNSIvPjx0ZXh0IGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBsZW5ndGhBZGp1c3Q9InNwYWNpbmciIHRleHRMZW5ndGg9IjEwIiB4PSI0NSIgeT0iMjQuOTk1MSI+QjwvdGV4dD48cmVjdCBmaWxsPSIjRTJFMkYwIiBoZWlnaHQ9IjMwLjI5NjkiIHJ4PSIyLjUiIHJ5PSIyLjUiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MC41OyIgd2lkdGg9IjI0IiB4PSIzOCIgeT0iNjkuMjk2OSIvPjx0ZXh0IGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBsZW5ndGhBZGp1c3Q9InNwYWNpbmciIHRleHRMZW5ndGg9IjEwIiB4PSI0NSIgeT0iODkuMjkyIj5CPC90ZXh0Pjxwb2x5Z29uIGZpbGw9IiMxODE4MTgiIHBvaW50cz0iMzgsNDguMjk2OSw0OCw1Mi4yOTY5LDM4LDU2LjI5NjksNDIsNTIuMjk2OSIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxLjA7Ii8+PGxpbmUgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxLjA7c3Ryb2tlLWRhc2hhcnJheToyLjAsMi4wOyIgeDE9IjE2LjUiIHgyPSI0NCIgeTE9IjUyLjI5NjkiIHkyPSI1Mi4yOTY5Ii8+PCEtLVNSQz1bU3JKR3JSTEpTMDgwXS0tPjwvZz48L3N2Zz4=', 134 | }, 135 | ], 136 | type: 'paragraph', 137 | }, 138 | ] 139 | 140 | > result 141 | 142 | '![plantuml](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXMtYXNjaWkiIHN0YW5kYWxvbmU9Im5vIj8+PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBjb250ZW50U3R5bGVUeXBlPSJ0ZXh0L2NzcyIgaGVpZ2h0PSIxMDVweCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSIgc3R5bGU9IndpZHRoOjY4cHg7aGVpZ2h0OjEwNXB4O2JhY2tncm91bmQ6I0ZGRkZGRjsiIHZlcnNpb249IjEuMSIgdmlld0JveD0iMCAwIDY4IDEwNSIgd2lkdGg9IjY4cHgiIHpvb21BbmRQYW49Im1hZ25pZnkiPjxkZWZzLz48Zz48bGluZSBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjAuNTtzdHJva2UtZGFzaGFycmF5OjUuMCw1LjA7IiB4MT0iMTYiIHgyPSIxNiIgeTE9IjM2LjI5NjkiIHkyPSI3MC4yOTY5Ii8+PGxpbmUgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDowLjU7c3Ryb2tlLWRhc2hhcnJheTo1LjAsNS4wOyIgeDE9IjUwIiB4Mj0iNTAiIHkxPSIzNi4yOTY5IiB5Mj0iNzAuMjk2OSIvPjxyZWN0IGZpbGw9IiNFMkUyRjAiIGhlaWdodD0iMzAuMjk2OSIgcng9IjIuNSIgcnk9IjIuNSIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDowLjU7IiB3aWR0aD0iMjMiIHg9IjUiIHk9IjUiLz48dGV4dCBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0ic2Fucy1zZXJpZiIgZm9udC1zaXplPSIxNCIgbGVuZ3RoQWRqdXN0PSJzcGFjaW5nIiB0ZXh0TGVuZ3RoPSI5IiB4PSIxMiIgeT0iMjQuOTk1MSI+QTwvdGV4dD48cmVjdCBmaWxsPSIjRTJFMkYwIiBoZWlnaHQ9IjMwLjI5NjkiIHJ4PSIyLjUiIHJ5PSIyLjUiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MC41OyIgd2lkdGg9IjIzIiB4PSI1IiB5PSI2OS4yOTY5Ii8+PHRleHQgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9InNhbnMtc2VyaWYiIGZvbnQtc2l6ZT0iMTQiIGxlbmd0aEFkanVzdD0ic3BhY2luZyIgdGV4dExlbmd0aD0iOSIgeD0iMTIiIHk9Ijg5LjI5MiI+QTwvdGV4dD48cmVjdCBmaWxsPSIjRTJFMkYwIiBoZWlnaHQ9IjMwLjI5NjkiIHJ4PSIyLjUiIHJ5PSIyLjUiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MC41OyIgd2lkdGg9IjI0IiB4PSIzOCIgeT0iNSIvPjx0ZXh0IGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBsZW5ndGhBZGp1c3Q9InNwYWNpbmciIHRleHRMZW5ndGg9IjEwIiB4PSI0NSIgeT0iMjQuOTk1MSI+QjwvdGV4dD48cmVjdCBmaWxsPSIjRTJFMkYwIiBoZWlnaHQ9IjMwLjI5NjkiIHJ4PSIyLjUiIHJ5PSIyLjUiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MC41OyIgd2lkdGg9IjI0IiB4PSIzOCIgeT0iNjkuMjk2OSIvPjx0ZXh0IGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBsZW5ndGhBZGp1c3Q9InNwYWNpbmciIHRleHRMZW5ndGg9IjEwIiB4PSI0NSIgeT0iODkuMjkyIj5CPC90ZXh0Pjxwb2x5Z29uIGZpbGw9IiMxODE4MTgiIHBvaW50cz0iMzgsNDguMjk2OSw0OCw1Mi4yOTY5LDM4LDU2LjI5NjksNDIsNTIuMjk2OSIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxLjA7Ii8+PGxpbmUgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxLjA7c3Ryb2tlLWRhc2hhcnJheToyLjAsMi4wOyIgeDE9IjE2LjUiIHgyPSI0NCIgeTE9IjUyLjI5NjkiIHkyPSI1Mi4yOTY5Ii8+PCEtLVNSQz1bU3JKR3JSTEpTMDgwXS0tPjwvZz48L3N2Zz4=)' 143 | 144 | ## img-html-base64 | html 145 | 146 | > input 147 | 148 | `␊ 149 | \`\`\`kroki type=plantuml classnames=w-half␊ 150 | A --> B␊ 151 | \`\`\`␊ 152 | ` 153 | 154 | > ast 155 | 156 | [ 157 | { 158 | lang: 'kroki', 159 | meta: 'type=plantuml classnames=w-half', 160 | type: 'code', 161 | value: ' A --> B', 162 | }, 163 | ] 164 | 165 | > parsed 166 | 167 | [ 168 | { 169 | children: [ 170 | { 171 | type: 'html', 172 | value: 'plantuml', 173 | }, 174 | ], 175 | type: 'paragraph', 176 | }, 177 | ] 178 | 179 | > result 180 | 181 | 'plantuml' 182 | 183 | ## img-html-base64 | mdx3 184 | 185 | > input 186 | 187 | `␊ 188 | \`\`\`kroki type=plantuml classnames=w-half␊ 189 | A --> B␊ 190 | \`\`\`␊ 191 | ` 192 | 193 | > ast 194 | 195 | [ 196 | { 197 | lang: 'kroki', 198 | meta: 'type=plantuml classnames=w-half', 199 | type: 'code', 200 | value: ' A --> B', 201 | }, 202 | ] 203 | 204 | > parsed 205 | 206 | [ 207 | { 208 | children: [ 209 | { 210 | attributes: [ 211 | { 212 | name: 'className', 213 | type: 'mdxJsxAttribute', 214 | value: 'kroki-image w-half', 215 | }, 216 | { 217 | name: 'alt', 218 | type: 'mdxJsxAttribute', 219 | value: 'plantuml', 220 | }, 221 | { 222 | name: 'data-type', 223 | type: 'mdxJsxAttribute', 224 | value: 'plantuml', 225 | }, 226 | { 227 | name: 'src', 228 | type: 'mdxJsxAttribute', 229 | value: 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXMtYXNjaWkiIHN0YW5kYWxvbmU9Im5vIj8+PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBjb250ZW50U3R5bGVUeXBlPSJ0ZXh0L2NzcyIgaGVpZ2h0PSIxMDVweCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSIgc3R5bGU9IndpZHRoOjY4cHg7aGVpZ2h0OjEwNXB4O2JhY2tncm91bmQ6I0ZGRkZGRjsiIHZlcnNpb249IjEuMSIgdmlld0JveD0iMCAwIDY4IDEwNSIgd2lkdGg9IjY4cHgiIHpvb21BbmRQYW49Im1hZ25pZnkiPjxkZWZzLz48Zz48bGluZSBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjAuNTtzdHJva2UtZGFzaGFycmF5OjUuMCw1LjA7IiB4MT0iMTYiIHgyPSIxNiIgeTE9IjM2LjI5NjkiIHkyPSI3MC4yOTY5Ii8+PGxpbmUgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDowLjU7c3Ryb2tlLWRhc2hhcnJheTo1LjAsNS4wOyIgeDE9IjUwIiB4Mj0iNTAiIHkxPSIzNi4yOTY5IiB5Mj0iNzAuMjk2OSIvPjxyZWN0IGZpbGw9IiNFMkUyRjAiIGhlaWdodD0iMzAuMjk2OSIgcng9IjIuNSIgcnk9IjIuNSIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDowLjU7IiB3aWR0aD0iMjMiIHg9IjUiIHk9IjUiLz48dGV4dCBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0ic2Fucy1zZXJpZiIgZm9udC1zaXplPSIxNCIgbGVuZ3RoQWRqdXN0PSJzcGFjaW5nIiB0ZXh0TGVuZ3RoPSI5IiB4PSIxMiIgeT0iMjQuOTk1MSI+QTwvdGV4dD48cmVjdCBmaWxsPSIjRTJFMkYwIiBoZWlnaHQ9IjMwLjI5NjkiIHJ4PSIyLjUiIHJ5PSIyLjUiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MC41OyIgd2lkdGg9IjIzIiB4PSI1IiB5PSI2OS4yOTY5Ii8+PHRleHQgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9InNhbnMtc2VyaWYiIGZvbnQtc2l6ZT0iMTQiIGxlbmd0aEFkanVzdD0ic3BhY2luZyIgdGV4dExlbmd0aD0iOSIgeD0iMTIiIHk9Ijg5LjI5MiI+QTwvdGV4dD48cmVjdCBmaWxsPSIjRTJFMkYwIiBoZWlnaHQ9IjMwLjI5NjkiIHJ4PSIyLjUiIHJ5PSIyLjUiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MC41OyIgd2lkdGg9IjI0IiB4PSIzOCIgeT0iNSIvPjx0ZXh0IGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBsZW5ndGhBZGp1c3Q9InNwYWNpbmciIHRleHRMZW5ndGg9IjEwIiB4PSI0NSIgeT0iMjQuOTk1MSI+QjwvdGV4dD48cmVjdCBmaWxsPSIjRTJFMkYwIiBoZWlnaHQ9IjMwLjI5NjkiIHJ4PSIyLjUiIHJ5PSIyLjUiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MC41OyIgd2lkdGg9IjI0IiB4PSIzOCIgeT0iNjkuMjk2OSIvPjx0ZXh0IGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBsZW5ndGhBZGp1c3Q9InNwYWNpbmciIHRleHRMZW5ndGg9IjEwIiB4PSI0NSIgeT0iODkuMjkyIj5CPC90ZXh0Pjxwb2x5Z29uIGZpbGw9IiMxODE4MTgiIHBvaW50cz0iMzgsNDguMjk2OSw0OCw1Mi4yOTY5LDM4LDU2LjI5NjksNDIsNTIuMjk2OSIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxLjA7Ii8+PGxpbmUgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxLjA7c3Ryb2tlLWRhc2hhcnJheToyLjAsMi4wOyIgeDE9IjE2LjUiIHgyPSI0NCIgeTE9IjUyLjI5NjkiIHkyPSI1Mi4yOTY5Ii8+PCEtLVNSQz1bU3JKR3JSTEpTMDgwXS0tPjwvZz48L3N2Zz4=', 230 | }, 231 | ], 232 | name: 'img', 233 | type: 'mdxJsxTextElement', 234 | }, 235 | ], 236 | type: 'paragraph', 237 | }, 238 | ] 239 | 240 | > result 241 | 242 | 'plantuml' 243 | 244 | ## object-base64 | html 245 | 246 | > input 247 | 248 | `␊ 249 | \`\`\`kroki type=plantuml classnames=w-half␊ 250 | A --> B␊ 251 | \`\`\`␊ 252 | ` 253 | 254 | > ast 255 | 256 | [ 257 | { 258 | lang: 'kroki', 259 | meta: 'type=plantuml classnames=w-half', 260 | type: 'code', 261 | value: ' A --> B', 262 | }, 263 | ] 264 | 265 | > parsed 266 | 267 | [ 268 | { 269 | type: 'html', 270 | value: 'Load SVG fail...', 271 | }, 272 | ] 273 | 274 | > result 275 | 276 | 'Load SVG fail...' 277 | 278 | ## object-base64 | mdx3 279 | 280 | > input 281 | 282 | `␊ 283 | \`\`\`kroki type=plantuml classnames=w-half␊ 284 | A --> B␊ 285 | \`\`\`␊ 286 | ` 287 | 288 | > ast 289 | 290 | [ 291 | { 292 | lang: 'kroki', 293 | meta: 'type=plantuml classnames=w-half', 294 | type: 'code', 295 | value: ' A --> B', 296 | }, 297 | ] 298 | 299 | > parsed 300 | 301 | [ 302 | { 303 | attributes: [ 304 | { 305 | name: 'type', 306 | type: 'mdxJsxAttribute', 307 | value: 'image/svg+xml', 308 | }, 309 | { 310 | name: 'className', 311 | type: 'mdxJsxAttribute', 312 | value: 'kroki-object w-half', 313 | }, 314 | { 315 | name: 'data-type', 316 | type: 'mdxJsxAttribute', 317 | value: 'plantuml', 318 | }, 319 | { 320 | name: 'title', 321 | type: 'mdxJsxAttribute', 322 | value: 'plantuml', 323 | }, 324 | { 325 | name: 'data', 326 | type: 'mdxJsxAttribute', 327 | value: 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXMtYXNjaWkiIHN0YW5kYWxvbmU9Im5vIj8+PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBjb250ZW50U3R5bGVUeXBlPSJ0ZXh0L2NzcyIgaGVpZ2h0PSIxMDVweCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSIgc3R5bGU9IndpZHRoOjY4cHg7aGVpZ2h0OjEwNXB4O2JhY2tncm91bmQ6I0ZGRkZGRjsiIHZlcnNpb249IjEuMSIgdmlld0JveD0iMCAwIDY4IDEwNSIgd2lkdGg9IjY4cHgiIHpvb21BbmRQYW49Im1hZ25pZnkiPjxkZWZzLz48Zz48bGluZSBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjAuNTtzdHJva2UtZGFzaGFycmF5OjUuMCw1LjA7IiB4MT0iMTYiIHgyPSIxNiIgeTE9IjM2LjI5NjkiIHkyPSI3MC4yOTY5Ii8+PGxpbmUgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDowLjU7c3Ryb2tlLWRhc2hhcnJheTo1LjAsNS4wOyIgeDE9IjUwIiB4Mj0iNTAiIHkxPSIzNi4yOTY5IiB5Mj0iNzAuMjk2OSIvPjxyZWN0IGZpbGw9IiNFMkUyRjAiIGhlaWdodD0iMzAuMjk2OSIgcng9IjIuNSIgcnk9IjIuNSIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDowLjU7IiB3aWR0aD0iMjMiIHg9IjUiIHk9IjUiLz48dGV4dCBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0ic2Fucy1zZXJpZiIgZm9udC1zaXplPSIxNCIgbGVuZ3RoQWRqdXN0PSJzcGFjaW5nIiB0ZXh0TGVuZ3RoPSI5IiB4PSIxMiIgeT0iMjQuOTk1MSI+QTwvdGV4dD48cmVjdCBmaWxsPSIjRTJFMkYwIiBoZWlnaHQ9IjMwLjI5NjkiIHJ4PSIyLjUiIHJ5PSIyLjUiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MC41OyIgd2lkdGg9IjIzIiB4PSI1IiB5PSI2OS4yOTY5Ii8+PHRleHQgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9InNhbnMtc2VyaWYiIGZvbnQtc2l6ZT0iMTQiIGxlbmd0aEFkanVzdD0ic3BhY2luZyIgdGV4dExlbmd0aD0iOSIgeD0iMTIiIHk9Ijg5LjI5MiI+QTwvdGV4dD48cmVjdCBmaWxsPSIjRTJFMkYwIiBoZWlnaHQ9IjMwLjI5NjkiIHJ4PSIyLjUiIHJ5PSIyLjUiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MC41OyIgd2lkdGg9IjI0IiB4PSIzOCIgeT0iNSIvPjx0ZXh0IGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBsZW5ndGhBZGp1c3Q9InNwYWNpbmciIHRleHRMZW5ndGg9IjEwIiB4PSI0NSIgeT0iMjQuOTk1MSI+QjwvdGV4dD48cmVjdCBmaWxsPSIjRTJFMkYwIiBoZWlnaHQ9IjMwLjI5NjkiIHJ4PSIyLjUiIHJ5PSIyLjUiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MC41OyIgd2lkdGg9IjI0IiB4PSIzOCIgeT0iNjkuMjk2OSIvPjx0ZXh0IGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJzYW5zLXNlcmlmIiBmb250LXNpemU9IjE0IiBsZW5ndGhBZGp1c3Q9InNwYWNpbmciIHRleHRMZW5ndGg9IjEwIiB4PSI0NSIgeT0iODkuMjkyIj5CPC90ZXh0Pjxwb2x5Z29uIGZpbGw9IiMxODE4MTgiIHBvaW50cz0iMzgsNDguMjk2OSw0OCw1Mi4yOTY5LDM4LDU2LjI5NjksNDIsNTIuMjk2OSIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxLjA7Ii8+PGxpbmUgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxLjA7c3Ryb2tlLWRhc2hhcnJheToyLjAsMi4wOyIgeDE9IjE2LjUiIHgyPSI0NCIgeTE9IjUyLjI5NjkiIHkyPSI1Mi4yOTY5Ii8+PCEtLVNSQz1bU3JKR3JSTEpTMDgwXS0tPjwvZz48L3N2Zz4=', 328 | }, 329 | ], 330 | children: [ 331 | { 332 | type: 'text', 333 | value: 'Load SVG fail...', 334 | }, 335 | ], 336 | name: 'object', 337 | type: 'mdxJsxFlowElement', 338 | }, 339 | ] 340 | 341 | > result 342 | 343 | `␊ 344 | Load SVG fail...␊ 345 | ` 346 | -------------------------------------------------------------------------------- /test/snapshots/output.mjs.snap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/show-docs/remark-kroki/5d2f4984c9bcbee796b319978e42c6e31dd95488/test/snapshots/output.mjs.snap -------------------------------------------------------------------------------- /test/snapshots/validate.mjs.md: -------------------------------------------------------------------------------- 1 | # Snapshot report for `test/validate.mjs` 2 | 3 | The actual snapshot is saved in `validate.mjs.snap`. 4 | 5 | Generated by [AVA](https://avajs.dev). 6 | 7 | ## server 8 | 9 | > Snapshot 1 10 | 11 | TypeError { 12 | message: '`server` should be string', 13 | } 14 | 15 | > Snapshot 2 16 | 17 | TypeError { 18 | message: '`server` should be URL', 19 | } 20 | 21 | > Snapshot 3 22 | 23 | TypeError { 24 | message: '`server` protocol should be http or https', 25 | } 26 | 27 | ## headers 28 | 29 | > Snapshot 1 30 | 31 | TypeError { 32 | message: '`headers` should be plain object', 33 | } 34 | 35 | > Snapshot 2 36 | 37 | TypeError { 38 | message: '`headers` should be plain object', 39 | } 40 | 41 | > Snapshot 3 42 | 43 | TypeError { 44 | message: '`headers` should be plain object', 45 | } 46 | 47 | > Snapshot 4 48 | 49 | TypeError { 50 | message: '`headers` should object of string', 51 | } 52 | 53 | ## alias 54 | 55 | > Snapshot 1 56 | 57 | TypeError { 58 | message: '`alias` should be array', 59 | } 60 | 61 | > Snapshot 2 62 | 63 | TypeError { 64 | message: '`alias` should be array', 65 | } 66 | 67 | > Snapshot 3 68 | 69 | TypeError { 70 | message: '`alias` should array of non empty string', 71 | } 72 | 73 | > Snapshot 4 74 | 75 | TypeError { 76 | message: '`alias` should array of non empty string', 77 | } 78 | 79 | ## output 80 | 81 | > Snapshot 1 82 | 83 | TypeError { 84 | message: '`output` should be one of `img-base64/object-base64/img-html-base64/inline-svg`', 85 | } 86 | 87 | > Snapshot 2 88 | 89 | TypeError { 90 | message: '`output` should be one of `img-base64/object-base64/img-html-base64/inline-svg`', 91 | } 92 | 93 | > Snapshot 3 94 | 95 | TypeError { 96 | message: '`output` should be one of `img-base64/object-base64/img-html-base64/inline-svg`', 97 | } 98 | 99 | > Snapshot 4 100 | 101 | TypeError { 102 | message: '`output` should be one of `img-base64/object-base64/img-html-base64/inline-svg`', 103 | } 104 | 105 | ## target 106 | 107 | > Snapshot 1 108 | 109 | TypeError { 110 | message: '`target` should be one of `html/mdx3`', 111 | } 112 | 113 | > Snapshot 2 114 | 115 | TypeError { 116 | message: '`target` should be one of `html/mdx3`', 117 | } 118 | 119 | > Snapshot 3 120 | 121 | TypeError { 122 | message: '`target` should be one of `html/mdx3`', 123 | } 124 | 125 | > Snapshot 4 126 | 127 | TypeError { 128 | message: '`target` should be one of `html/mdx3`', 129 | } 130 | -------------------------------------------------------------------------------- /test/snapshots/validate.mjs.snap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/show-docs/remark-kroki/5d2f4984c9bcbee796b319978e42c6e31dd95488/test/snapshots/validate.mjs.snap -------------------------------------------------------------------------------- /test/validate.mjs: -------------------------------------------------------------------------------- 1 | import test from 'ava'; 2 | 3 | import { transform } from './helper/lib.mjs'; 4 | 5 | async function marco(t, ...configs) { 6 | for (const config of configs) { 7 | const error = await t.throwsAsync(transform('', config), { 8 | instanceOf: TypeError, 9 | }); 10 | 11 | t.snapshot(error); 12 | } 13 | } 14 | 15 | test( 16 | 'server', 17 | marco, 18 | { server: 1 }, 19 | { server: '55' }, 20 | { server: 'ftp://localhost' }, 21 | ); 22 | 23 | test( 24 | 'headers', 25 | marco, 26 | { headers: true }, 27 | { headers: [] }, 28 | { headers: null }, 29 | { headers: { a: 0 } }, 30 | ); 31 | 32 | test( 33 | 'alias', 34 | marco, 35 | { alias: true }, 36 | { alias: null }, 37 | { alias: [''] }, 38 | { alias: [' '] }, 39 | ); 40 | 41 | test( 42 | 'output', 43 | marco, 44 | { output: true }, 45 | { output: null }, 46 | { output: '' }, 47 | { output: 'any' }, 48 | ); 49 | 50 | test( 51 | 'target', 52 | marco, 53 | { target: true }, 54 | { target: null }, 55 | { target: '' }, 56 | { target: 'any' }, 57 | ); 58 | --------------------------------------------------------------------------------