repl-sdk 0.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/apl-fqmucPXA.js +141 -0
- package/dist/apl-fqmucPXA.js.map +1 -0
- package/dist/asciiarmor-DucZyvP0.js +57 -0
- package/dist/asciiarmor-DucZyvP0.js.map +1 -0
- package/dist/asn1-BnOEsgAm.js +145 -0
- package/dist/asn1-BnOEsgAm.js.map +1 -0
- package/dist/assets/tar-worker-CxTcoQcr.js +593 -0
- package/dist/assets/tar-worker-CxTcoQcr.js.map +1 -0
- package/dist/asterisk-QAlztEwS.js +346 -0
- package/dist/asterisk-QAlztEwS.js.map +1 -0
- package/dist/brainfuck-DZVCuF_t.js +54 -0
- package/dist/brainfuck-DZVCuF_t.js.map +1 -0
- package/dist/clike-CTYGlS6x.js +800 -0
- package/dist/clike-CTYGlS6x.js.map +1 -0
- package/dist/clojure-BhXMqnxz.js +850 -0
- package/dist/clojure-BhXMqnxz.js.map +1 -0
- package/dist/cmake-BGaNd9E7.js +72 -0
- package/dist/cmake-BGaNd9E7.js.map +1 -0
- package/dist/cobol-4yqQntpt.js +121 -0
- package/dist/cobol-4yqQntpt.js.map +1 -0
- package/dist/codemirror-De3S70Np.js +2912 -0
- package/dist/codemirror-De3S70Np.js.map +1 -0
- package/dist/coffeescript-D2dXvhEc.js +309 -0
- package/dist/coffeescript-D2dXvhEc.js.map +1 -0
- package/dist/commonlisp-CF_VNHQR.js +131 -0
- package/dist/commonlisp-CF_VNHQR.js.map +1 -0
- package/dist/crystal-DyuLTqLs.js +399 -0
- package/dist/crystal-DyuLTqLs.js.map +1 -0
- package/dist/css-DkSyTW67.js +1773 -0
- package/dist/css-DkSyTW67.js.map +1 -0
- package/dist/cypher-Dlu_3r4V.js +122 -0
- package/dist/cypher-Dlu_3r4V.js.map +1 -0
- package/dist/d-UURgV0Ux.js +180 -0
- package/dist/d-UURgV0Ux.js.map +1 -0
- package/dist/diff-B_Bi2Crb.js +26 -0
- package/dist/diff-B_Bi2Crb.js.map +1 -0
- package/dist/dockerfile-Bvk733Ga.js +202 -0
- package/dist/dockerfile-Bvk733Ga.js.map +1 -0
- package/dist/dtd-Dy74G54E.js +115 -0
- package/dist/dtd-Dy74G54E.js.map +1 -0
- package/dist/dylan-TSb-Nfix.js +315 -0
- package/dist/dylan-TSb-Nfix.js.map +1 -0
- package/dist/ebnf-4fKAGW3a.js +141 -0
- package/dist/ebnf-4fKAGW3a.js.map +1 -0
- package/dist/ecl-B59qGGVg.js +179 -0
- package/dist/ecl-B59qGGVg.js.map +1 -0
- package/dist/eiffel-Dze7nlu3.js +135 -0
- package/dist/eiffel-Dze7nlu3.js.map +1 -0
- package/dist/elm-DG7jkhNZ.js +177 -0
- package/dist/elm-DG7jkhNZ.js.map +1 -0
- package/dist/erlang-BO6gOnGA.js +675 -0
- package/dist/erlang-BO6gOnGA.js.map +1 -0
- package/dist/factor-CMxFHDqz.js +66 -0
- package/dist/factor-CMxFHDqz.js.map +1 -0
- package/dist/fcl-CDDUNjTj.js +142 -0
- package/dist/fcl-CDDUNjTj.js.map +1 -0
- package/dist/forth-B9D2JCeE.js +117 -0
- package/dist/forth-B9D2JCeE.js.map +1 -0
- package/dist/fortran-CAG2BFbe.js +468 -0
- package/dist/fortran-CAG2BFbe.js.map +1 -0
- package/dist/gas-0Aw8zDr5.js +294 -0
- package/dist/gas-0Aw8zDr5.js.map +1 -0
- package/dist/gherkin-DhZlEZiy.js +116 -0
- package/dist/gherkin-DhZlEZiy.js.map +1 -0
- package/dist/gjs-DfguZDLq.js +173 -0
- package/dist/gjs-DfguZDLq.js.map +1 -0
- package/dist/gmd-Yas-Oo8k.js +163 -0
- package/dist/gmd-Yas-Oo8k.js.map +1 -0
- package/dist/groovy-CpwJiBl7.js +224 -0
- package/dist/groovy-CpwJiBl7.js.map +1 -0
- package/dist/haskell-ySd-OUo8.js +460 -0
- package/dist/haskell-ySd-OUo8.js.map +1 -0
- package/dist/haxe-7MlzfeYV.js +515 -0
- package/dist/haxe-7MlzfeYV.js.map +1 -0
- package/dist/hbs-CxcmWxSJ.js +62 -0
- package/dist/hbs-CxcmWxSJ.js.map +1 -0
- package/dist/http-BqypyemW.js +80 -0
- package/dist/http-BqypyemW.js.map +1 -0
- package/dist/idl-4HIGJlDI.js +986 -0
- package/dist/idl-4HIGJlDI.js.map +1 -0
- package/dist/index-B3Meoznj.js +118 -0
- package/dist/index-B3Meoznj.js.map +1 -0
- package/dist/index-BQyfDUUx.js +692 -0
- package/dist/index-BQyfDUUx.js.map +1 -0
- package/dist/index-BRDroAD8.js +305 -0
- package/dist/index-BRDroAD8.js.map +1 -0
- package/dist/index-BRMAzRyM.js +179 -0
- package/dist/index-BRMAzRyM.js.map +1 -0
- package/dist/index-Bb8uYQgv.js +927 -0
- package/dist/index-Bb8uYQgv.js.map +1 -0
- package/dist/index-BlOjO66K.js +17618 -0
- package/dist/index-BlOjO66K.js.map +1 -0
- package/dist/index-BoGWnSNL.js +706 -0
- package/dist/index-BoGWnSNL.js.map +1 -0
- package/dist/index-BsRrEiOu.js +98 -0
- package/dist/index-BsRrEiOu.js.map +1 -0
- package/dist/index-C2sFZMth.js +391 -0
- package/dist/index-C2sFZMth.js.map +1 -0
- package/dist/index-C7xwOjmS.js +291 -0
- package/dist/index-C7xwOjmS.js.map +1 -0
- package/dist/index-CA3lFUx6.js +315 -0
- package/dist/index-CA3lFUx6.js.map +1 -0
- package/dist/index-CB-pPTIf.js +98 -0
- package/dist/index-CB-pPTIf.js.map +1 -0
- package/dist/index-CCa6x1FE.js +386 -0
- package/dist/index-CCa6x1FE.js.map +1 -0
- package/dist/index-CD4DINI1.js +158 -0
- package/dist/index-CD4DINI1.js.map +1 -0
- package/dist/index-CE0B_fcG.js +328 -0
- package/dist/index-CE0B_fcG.js.map +1 -0
- package/dist/index-CVGAEPMV.js +2139 -0
- package/dist/index-CVGAEPMV.js.map +1 -0
- package/dist/index-CmaT2afn.js +332 -0
- package/dist/index-CmaT2afn.js.map +1 -0
- package/dist/index-D8sUxXp5.js +83 -0
- package/dist/index-D8sUxXp5.js.map +1 -0
- package/dist/index-DIz8Vpn-.js +737 -0
- package/dist/index-DIz8Vpn-.js.map +1 -0
- package/dist/index-DNP1xT-S.js +408 -0
- package/dist/index-DNP1xT-S.js.map +1 -0
- package/dist/index-DOAqdvnQ.js +862 -0
- package/dist/index-DOAqdvnQ.js.map +1 -0
- package/dist/index-DVUMFbgi.js +152 -0
- package/dist/index-DVUMFbgi.js.map +1 -0
- package/dist/index-VeTBKRVd.js +83 -0
- package/dist/index-VeTBKRVd.js.map +1 -0
- package/dist/index-dXZeR7Bx.js +1767 -0
- package/dist/index-dXZeR7Bx.js.map +1 -0
- package/dist/index-gtqbIb6T.js +62 -0
- package/dist/index-gtqbIb6T.js.map +1 -0
- package/dist/index-pN_pUAQ7.js +2426 -0
- package/dist/index-pN_pUAQ7.js.map +1 -0
- package/dist/index-wasu5VX0.js +1150 -0
- package/dist/index-wasu5VX0.js.map +1 -0
- package/dist/javascript-Bt8B7yTi.js +993 -0
- package/dist/javascript-Bt8B7yTi.js.map +1 -0
- package/dist/julia-Bs6JJhYG.js +408 -0
- package/dist/julia-Bs6JJhYG.js.map +1 -0
- package/dist/livescript-DmzgM3Yt.js +297 -0
- package/dist/livescript-DmzgM3Yt.js.map +1 -0
- package/dist/lua-8cJgIlqe.js +257 -0
- package/dist/lua-8cJgIlqe.js.map +1 -0
- package/dist/mathematica-DNLOL9PQ.js +111 -0
- package/dist/mathematica-DNLOL9PQ.js.map +1 -0
- package/dist/mbox-Ga7d4MMN.js +118 -0
- package/dist/mbox-Ga7d4MMN.js.map +1 -0
- package/dist/mirc-Dma3B8rS.js +108 -0
- package/dist/mirc-Dma3B8rS.js.map +1 -0
- package/dist/mllike-DHn7xckP.js +335 -0
- package/dist/mllike-DHn7xckP.js.map +1 -0
- package/dist/modelica-0d55jYY0.js +148 -0
- package/dist/modelica-0d55jYY0.js.map +1 -0
- package/dist/mscgen-DdqZYINH.js +136 -0
- package/dist/mscgen-DdqZYINH.js.map +1 -0
- package/dist/mumps-Btr8VblO.js +94 -0
- package/dist/mumps-Btr8VblO.js.map +1 -0
- package/dist/nginx-DTDtBDVN.js +142 -0
- package/dist/nginx-DTDtBDVN.js.map +1 -0
- package/dist/nsis-3zG7tgur.js +63 -0
- package/dist/nsis-3zG7tgur.js.map +1 -0
- package/dist/ntriples-CvgOYMpL.js +154 -0
- package/dist/ntriples-CvgOYMpL.js.map +1 -0
- package/dist/octave-DYBj3-tl.js +201 -0
- package/dist/octave-DYBj3-tl.js.map +1 -0
- package/dist/oz-R_e8WMIi.js +232 -0
- package/dist/oz-R_e8WMIi.js.map +1 -0
- package/dist/parse-CAqQaKsh.js +21685 -0
- package/dist/parse-CAqQaKsh.js.map +1 -0
- package/dist/pascal-GD8iposT.js +106 -0
- package/dist/pascal-GD8iposT.js.map +1 -0
- package/dist/perl-DL9mHpoi.js +1106 -0
- package/dist/perl-DL9mHpoi.js.map +1 -0
- package/dist/pig-C_4T4YIV.js +102 -0
- package/dist/pig-C_4T4YIV.js.map +1 -0
- package/dist/powershell-B0suO7Vd.js +329 -0
- package/dist/powershell-B0suO7Vd.js.map +1 -0
- package/dist/properties-BR-vP1aU.js +59 -0
- package/dist/properties-BR-vP1aU.js.map +1 -0
- package/dist/protobuf-BxgpyhoW.js +78 -0
- package/dist/protobuf-BxgpyhoW.js.map +1 -0
- package/dist/pug-vHnWR0UE.js +406 -0
- package/dist/pug-vHnWR0UE.js.map +1 -0
- package/dist/puppet-Bdao66PW.js +138 -0
- package/dist/puppet-Bdao66PW.js.map +1 -0
- package/dist/python-BFGRmuZ9.js +427 -0
- package/dist/python-BFGRmuZ9.js.map +1 -0
- package/dist/q-CrbCVq4a.js +132 -0
- package/dist/q-CrbCVq4a.js.map +1 -0
- package/dist/r-V7nswm59.js +171 -0
- package/dist/r-V7nswm59.js.map +1 -0
- package/dist/render-app-island-B-i8rvGi.js +61 -0
- package/dist/render-app-island-B-i8rvGi.js.map +1 -0
- package/dist/repl-sdk.js +7 -0
- package/dist/repl-sdk.js.map +1 -0
- package/dist/rpm-C-DLY-If.js +110 -0
- package/dist/rpm-C-DLY-If.js.map +1 -0
- package/dist/ruby-JDKLJNK0.js +331 -0
- package/dist/ruby-JDKLJNK0.js.map +1 -0
- package/dist/sas-D2UG-yhZ.js +208 -0
- package/dist/sas-D2UG-yhZ.js.map +1 -0
- package/dist/scheme-BKzrkGJD.js +223 -0
- package/dist/scheme-BKzrkGJD.js.map +1 -0
- package/dist/shell-BlsXDxCn.js +223 -0
- package/dist/shell-BlsXDxCn.js.map +1 -0
- package/dist/sieve-CjwBwOY5.js +136 -0
- package/dist/sieve-CjwBwOY5.js.map +1 -0
- package/dist/simple-mode-DMneyfDu.js +131 -0
- package/dist/simple-mode-DMneyfDu.js.map +1 -0
- package/dist/smalltalk-BOIGQuhN.js +122 -0
- package/dist/smalltalk-BOIGQuhN.js.map +1 -0
- package/dist/solr-CwD7U71z.js +70 -0
- package/dist/solr-CwD7U71z.js.map +1 -0
- package/dist/sparql-DYskk2vE.js +250 -0
- package/dist/sparql-DYskk2vE.js.map +1 -0
- package/dist/spreadsheet-Bgtt3oLP.js +88 -0
- package/dist/spreadsheet-Bgtt3oLP.js.map +1 -0
- package/dist/sql-Cei9CMfk.js +343 -0
- package/dist/sql-Cei9CMfk.js.map +1 -0
- package/dist/stex-C1nZSzAw.js +231 -0
- package/dist/stex-C1nZSzAw.js.map +1 -0
- package/dist/stylus-BkS-boTH.js +566 -0
- package/dist/stylus-BkS-boTH.js.map +1 -0
- package/dist/swift-FRZi1uvB.js +292 -0
- package/dist/swift-FRZi1uvB.js.map +1 -0
- package/dist/tcl-CUcaCdmq.js +115 -0
- package/dist/tcl-CUcaCdmq.js.map +1 -0
- package/dist/textile-BnFpjsrl.js +415 -0
- package/dist/textile-BnFpjsrl.js.map +1 -0
- package/dist/tiddlywiki-CjprD-Qp.js +219 -0
- package/dist/tiddlywiki-CjprD-Qp.js.map +1 -0
- package/dist/tiki-DK9DOeWn.js +269 -0
- package/dist/tiki-DK9DOeWn.js.map +1 -0
- package/dist/toml-BOuWGMcf.js +77 -0
- package/dist/toml-BOuWGMcf.js.map +1 -0
- package/dist/troff-E1bJ0PPL.js +62 -0
- package/dist/troff-E1bJ0PPL.js.map +1 -0
- package/dist/ttcn-cfg-Dc39-fIP.js +134 -0
- package/dist/ttcn-cfg-Dc39-fIP.js.map +1 -0
- package/dist/ttcn-tKd4HLu4.js +193 -0
- package/dist/ttcn-tKd4HLu4.js.map +1 -0
- package/dist/turtle-Dq7-1WAf.js +125 -0
- package/dist/turtle-Dq7-1WAf.js.map +1 -0
- package/dist/vb-Dp90gtsv.js +197 -0
- package/dist/vb-Dp90gtsv.js.map +1 -0
- package/dist/vbscript-Bfn8O8I7.js +479 -0
- package/dist/vbscript-Bfn8O8I7.js.map +1 -0
- package/dist/velocity-BwIZK1TH.js +150 -0
- package/dist/velocity-BwIZK1TH.js.map +1 -0
- package/dist/verilog-CnT9bMk0.js +430 -0
- package/dist/verilog-CnT9bMk0.js.map +1 -0
- package/dist/vhdl-DCkMIyT9.js +159 -0
- package/dist/vhdl-DCkMIyT9.js.map +1 -0
- package/dist/webidl-BTLTThCm.js +205 -0
- package/dist/webidl-BTLTThCm.js.map +1 -0
- package/dist/xquery-BrBUuxMR.js +526 -0
- package/dist/xquery-BrBUuxMR.js.map +1 -0
- package/dist/yacas-b5lAVEIl.js +131 -0
- package/dist/yacas-b5lAVEIl.js.map +1 -0
- package/dist/z80-ClgwfNdB.js +93 -0
- package/dist/z80-ClgwfNdB.js.map +1 -0
- package/package.json +81 -9
- package/src/cache.js +138 -0
- package/src/cdn.js +93 -0
- package/src/codemirror.js +161 -0
- package/src/compilers/ember/gjs.js +212 -0
- package/src/compilers/ember/gmd.js +190 -0
- package/src/compilers/ember/hbs.js +98 -0
- package/src/compilers/ember/render-app-island.js +83 -0
- package/src/compilers/ember.js +166 -0
- package/src/compilers/js.js +32 -0
- package/src/compilers/markdown/build-compiler.js +151 -0
- package/src/compilers/markdown/const.js +2 -0
- package/src/compilers/markdown/heading-id.js +75 -0
- package/src/compilers/markdown/live-code-extraction.js +198 -0
- package/src/compilers/markdown/parse.js +22 -0
- package/src/compilers/markdown/parse.test.ts +363 -0
- package/src/compilers/markdown/sanitize-for-glimmer.js +26 -0
- package/src/compilers/markdown/types.ts +21 -0
- package/src/compilers/markdown/utils.js +78 -0
- package/src/compilers/markdown.js +125 -0
- package/src/compilers/mermaid.js +35 -0
- package/src/compilers/react.js +59 -0
- package/src/compilers/svelte.js +116 -0
- package/src/compilers/vue.js +58 -0
- package/src/compilers.js +108 -0
- package/src/es-module-shim.js +53 -0
- package/src/index.d.ts +53 -4
- package/src/index.js +744 -89
- package/src/npm.js +58 -0
- package/src/request.Request.test.ts +59 -0
- package/src/request.js +140 -0
- package/src/resolve.fromImports.test.ts +35 -0
- package/src/resolve.fromInternalImport.test.ts +69 -0
- package/src/resolve.js +352 -0
- package/src/resolve.resolvePath.test.ts +24 -0
- package/src/resolve.test.ts +23 -0
- package/src/specifier.js +71 -0
- package/src/specifier.test.ts +90 -0
- package/src/tar-worker.js +61 -0
- package/src/tar.js +76 -0
- package/src/types.ts +335 -58
- package/src/utils.js +28 -1
- package/declarations/index.d.ts +0 -73
- package/dist/index.js +0 -107
- package/dist/index.js.map +0 -1
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {import('unified').Plugin} UPlugin
|
|
3
|
+
*/
|
|
4
|
+
import { buildCompiler } from './build-compiler.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @param {string} input
|
|
8
|
+
* @param {import('./types').InternalOptions} options
|
|
9
|
+
*
|
|
10
|
+
* @returns {Promise<{ text: string; codeBlocks: { lang: string; format: string; code: string; name: string }[] }>}
|
|
11
|
+
*/
|
|
12
|
+
export async function parseMarkdown(input, options) {
|
|
13
|
+
const markdownCompiler = buildCompiler(options);
|
|
14
|
+
const processed = await markdownCompiler.process(input);
|
|
15
|
+
const liveCode = /** @type {{ lang: string; format: string; code: string; name: string }[]} */ (
|
|
16
|
+
processed.data.liveCode || []
|
|
17
|
+
);
|
|
18
|
+
// @ts-ignore - processed is typed as unknown due to unified processor complexity
|
|
19
|
+
const templateOnly = processed.toString();
|
|
20
|
+
|
|
21
|
+
return { text: templateOnly, codeBlocks: liveCode };
|
|
22
|
+
}
|
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
import rehypeShiki from '@shikijs/rehype';
|
|
2
|
+
import { stripIndent } from 'common-tags';
|
|
3
|
+
import { visit } from 'unist-util-visit';
|
|
4
|
+
import { describe, expect as errorExpect, it } from 'vitest';
|
|
5
|
+
|
|
6
|
+
import { parseMarkdown } from './parse.js';
|
|
7
|
+
import { buildCodeFenceMetaUtils } from './utils.js';
|
|
8
|
+
|
|
9
|
+
import type { Element, Root as HastRoot } from 'hast';
|
|
10
|
+
import type { Heading, Root as MdastRoot } from 'mdast';
|
|
11
|
+
|
|
12
|
+
const expect = errorExpect.soft;
|
|
13
|
+
|
|
14
|
+
function assertOutput(actual: string, expected: string) {
|
|
15
|
+
const _actual = actual?.split('\n')?.filter(Boolean)?.join('\n')?.trim();
|
|
16
|
+
const _expected = expected.split('\n').filter(Boolean).join('\n').trim();
|
|
17
|
+
|
|
18
|
+
expect(_actual).toBe(_expected);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function assertCodeBlocks(
|
|
22
|
+
actual: unknown,
|
|
23
|
+
expected: { code: string; format: string; meta: string }[]
|
|
24
|
+
) {
|
|
25
|
+
expect(actual).toMatchObject(expected);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const ALLOWED_FORMATS = ['gjs', 'jsx', 'vue', 'svelte', 'hbs'];
|
|
29
|
+
const defaults = {
|
|
30
|
+
...buildCodeFenceMetaUtils({
|
|
31
|
+
getAllowedFormats: () => ALLOWED_FORMATS,
|
|
32
|
+
getFlavorsFor: (lang) => {
|
|
33
|
+
if (lang === 'jsx') {
|
|
34
|
+
return ['react'];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return [];
|
|
38
|
+
},
|
|
39
|
+
optionsFor: () => ({}),
|
|
40
|
+
}),
|
|
41
|
+
ALLOWED_FORMATS,
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
describe('options', () => {
|
|
45
|
+
describe('remarkPlugins', () => {
|
|
46
|
+
it('works', async () => {
|
|
47
|
+
const result = await parseMarkdown(`# Title`, {
|
|
48
|
+
...defaults,
|
|
49
|
+
remarkPlugins: [
|
|
50
|
+
function noH1() {
|
|
51
|
+
return (tree: MdastRoot) => {
|
|
52
|
+
visit(tree, 'heading', function (node: Heading) {
|
|
53
|
+
if (node.depth === 1) {
|
|
54
|
+
node.depth = 2;
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
};
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
expect(result.text).toBe('<h2 id="title">Title</h2>');
|
|
63
|
+
expect(result.codeBlocks).to.deep.equal([]);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('w/ options', async () => {
|
|
67
|
+
const result = await parseMarkdown(`# Title`, {
|
|
68
|
+
...defaults,
|
|
69
|
+
remarkPlugins: [
|
|
70
|
+
[
|
|
71
|
+
function noH1(options: { depth: 1 | 2 | 3 | 4 | 5 | 6 }) {
|
|
72
|
+
return (tree: MdastRoot) => {
|
|
73
|
+
visit(tree, 'heading', function (node: Heading) {
|
|
74
|
+
if (node.depth === 1) {
|
|
75
|
+
node.depth = options.depth;
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
};
|
|
79
|
+
},
|
|
80
|
+
{ depth: 3 },
|
|
81
|
+
],
|
|
82
|
+
],
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
expect(result.text).toBe('<h3 id="title">Title</h3>');
|
|
86
|
+
expect(result.codeBlocks).to.deep.equal([]);
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
describe('rehypePlugins', () => {
|
|
91
|
+
it('works', async () => {
|
|
92
|
+
const result = await parseMarkdown(`# Title`, {
|
|
93
|
+
...defaults,
|
|
94
|
+
rehypePlugins: [
|
|
95
|
+
function noH1() {
|
|
96
|
+
return (tree: HastRoot) => {
|
|
97
|
+
visit(tree, 'element', function (node: Element) {
|
|
98
|
+
if (node.tagName === 'h1') {
|
|
99
|
+
node.tagName = 'h2';
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
};
|
|
103
|
+
},
|
|
104
|
+
],
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
expect(result.text).toBe('<h2 id="title">Title</h2>');
|
|
108
|
+
expect(result.codeBlocks).to.deep.equal([]);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it('w/ options', async () => {
|
|
112
|
+
const result = await parseMarkdown(`# Title`, {
|
|
113
|
+
...defaults,
|
|
114
|
+
rehypePlugins: [
|
|
115
|
+
[
|
|
116
|
+
function noH1(options: { depth: 1 | 2 | 3 | 4 | 5 | 6 }) {
|
|
117
|
+
return (tree: HastRoot) => {
|
|
118
|
+
visit(tree, 'element', function (node: Element) {
|
|
119
|
+
if (node.tagName === 'h1') {
|
|
120
|
+
node.tagName = `h${options.depth ?? 2}`;
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
};
|
|
124
|
+
},
|
|
125
|
+
{ depth: 3 },
|
|
126
|
+
],
|
|
127
|
+
],
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
expect(result.text).toBe('<h3 id="title">Title</h3>');
|
|
131
|
+
expect(result.codeBlocks).to.deep.equal([]);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('retains {{ }} escaping', async () => {
|
|
135
|
+
const result = await parseMarkdown(
|
|
136
|
+
stripIndent`
|
|
137
|
+
# Title
|
|
138
|
+
|
|
139
|
+
\`\`\`gjs
|
|
140
|
+
const two = 2
|
|
141
|
+
|
|
142
|
+
<template>
|
|
143
|
+
{{two}}
|
|
144
|
+
</template>
|
|
145
|
+
\`\`\`
|
|
146
|
+
`,
|
|
147
|
+
{
|
|
148
|
+
...defaults,
|
|
149
|
+
rehypePlugins: [[rehypeShiki, { theme: 'github-dark' }]],
|
|
150
|
+
}
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
assertOutput(
|
|
154
|
+
result.text,
|
|
155
|
+
`<h1 id="title">Title</h1>
|
|
156
|
+
<div class="repl-sdk__snippet" data-repl-output><pre class="shiki github-dark" style="background-color:#24292e;color:#e1e4e8" tabindex="0"><code><span class="line"><span style="color:#F97583">const</span><span style="color:#79B8FF"> two</span><span style="color:#F97583"> =</span><span style="color:#79B8FF"> 2</span></span>
|
|
157
|
+
<span class="line"></span>
|
|
158
|
+
<span class="line"><span style="color:#E1E4E8"><</span><span style="color:#85E89D">template</span><span style="color:#E1E4E8">></span></span>
|
|
159
|
+
<span class="line"><span style="color:#F97583"> \\{{</span><span style="color:#79B8FF">two</span><span style="color:#F97583">}}</span></span>
|
|
160
|
+
<span class="line"><span style="color:#E1E4E8"></</span><span style="color:#85E89D">template</span><span style="color:#E1E4E8">></span></span></code></pre></div>`
|
|
161
|
+
);
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
describe('codefences', () => {
|
|
166
|
+
describe('hbs', () => {
|
|
167
|
+
it('Code fence is live', async () => {
|
|
168
|
+
const snippet = `{{concat "hello" " " "there"}}`;
|
|
169
|
+
const result = await parseMarkdown(
|
|
170
|
+
stripIndent`
|
|
171
|
+
# Title
|
|
172
|
+
|
|
173
|
+
\`\`\`hbs live
|
|
174
|
+
${snippet}
|
|
175
|
+
\`\`\`
|
|
176
|
+
`.trim(),
|
|
177
|
+
{ ...defaults }
|
|
178
|
+
);
|
|
179
|
+
|
|
180
|
+
expect(result.text).toMatchInlineSnapshot(`
|
|
181
|
+
"<h1 id="title">Title</h1>
|
|
182
|
+
<div id="repl_1" class="repl-sdk__demo"></div>"
|
|
183
|
+
`);
|
|
184
|
+
|
|
185
|
+
assertCodeBlocks(result.codeBlocks, [
|
|
186
|
+
{
|
|
187
|
+
code: snippet,
|
|
188
|
+
format: 'hbs',
|
|
189
|
+
meta: 'live',
|
|
190
|
+
},
|
|
191
|
+
]);
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
describe('gjs', () => {
|
|
196
|
+
it('Code fence does not have the "live" keyword', async function () {
|
|
197
|
+
const result = await parseMarkdown(
|
|
198
|
+
stripIndent`
|
|
199
|
+
# Title
|
|
200
|
+
|
|
201
|
+
\`\`\`gjs
|
|
202
|
+
const two = 2;
|
|
203
|
+
\`\`\`
|
|
204
|
+
`,
|
|
205
|
+
{ ...defaults }
|
|
206
|
+
);
|
|
207
|
+
|
|
208
|
+
assertOutput(
|
|
209
|
+
result.text,
|
|
210
|
+
stripIndent`
|
|
211
|
+
<h1 id="title">Title</h1>
|
|
212
|
+
|
|
213
|
+
<div class=\"repl-sdk__snippet\" data-repl-output><pre><code class=\"language-gjs\"> const two = 2;
|
|
214
|
+
</code></pre></div>
|
|
215
|
+
`
|
|
216
|
+
);
|
|
217
|
+
|
|
218
|
+
expect(result.codeBlocks).to.deep.equal([]);
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
it('Code fence is live', async function () {
|
|
222
|
+
const snippet = `const two = 2`;
|
|
223
|
+
const result = await parseMarkdown(
|
|
224
|
+
stripIndent`
|
|
225
|
+
# Title
|
|
226
|
+
|
|
227
|
+
\`\`\`gjs live
|
|
228
|
+
${snippet}
|
|
229
|
+
\`\`\`
|
|
230
|
+
`,
|
|
231
|
+
{ ...defaults }
|
|
232
|
+
);
|
|
233
|
+
|
|
234
|
+
expect(result.text).toMatchInlineSnapshot(`
|
|
235
|
+
"<h1 id="title">Title</h1>
|
|
236
|
+
<div id="repl_2" class="repl-sdk__demo"></div>"
|
|
237
|
+
`);
|
|
238
|
+
|
|
239
|
+
assertCodeBlocks(result.codeBlocks, [
|
|
240
|
+
{
|
|
241
|
+
code: snippet,
|
|
242
|
+
format: 'gjs',
|
|
243
|
+
meta: 'live',
|
|
244
|
+
},
|
|
245
|
+
]);
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
it('Code with preview fence has {{ }} tokens escaped', async function () {
|
|
249
|
+
const result = await parseMarkdown(
|
|
250
|
+
stripIndent`
|
|
251
|
+
# Title
|
|
252
|
+
|
|
253
|
+
\`\`\`gjs
|
|
254
|
+
const two = 2
|
|
255
|
+
|
|
256
|
+
<template>
|
|
257
|
+
{{two}}
|
|
258
|
+
</template>
|
|
259
|
+
\`\`\`
|
|
260
|
+
`,
|
|
261
|
+
{ ...defaults }
|
|
262
|
+
);
|
|
263
|
+
|
|
264
|
+
assertOutput(
|
|
265
|
+
result.text,
|
|
266
|
+
stripIndent`
|
|
267
|
+
<h1 id="title">Title</h1>
|
|
268
|
+
|
|
269
|
+
<div class=\"repl-sdk__snippet\" data-repl-output><pre><code class=\"language-gjs\">const two = 2
|
|
270
|
+
|
|
271
|
+
<template>
|
|
272
|
+
\\{{two}}
|
|
273
|
+
</template>
|
|
274
|
+
</code></pre></div>
|
|
275
|
+
`
|
|
276
|
+
);
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
it('Inline Code with {{ }} tokens is escaped', async function () {
|
|
280
|
+
const result = await parseMarkdown(
|
|
281
|
+
stripIndent`
|
|
282
|
+
# Title
|
|
283
|
+
|
|
284
|
+
\`{{ foo }}\`
|
|
285
|
+
`,
|
|
286
|
+
{ ...defaults }
|
|
287
|
+
);
|
|
288
|
+
|
|
289
|
+
assertOutput(
|
|
290
|
+
result.text,
|
|
291
|
+
stripIndent`
|
|
292
|
+
<h1 id="title">Title</h1>
|
|
293
|
+
<p><code>\\{{ foo }}</code></p>
|
|
294
|
+
`
|
|
295
|
+
);
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
it('Can invoke a component again when defined in a live fence', async function () {
|
|
299
|
+
const snippet = `const two = 2`;
|
|
300
|
+
const result = await parseMarkdown(
|
|
301
|
+
stripIndent`
|
|
302
|
+
# Title
|
|
303
|
+
|
|
304
|
+
\`\`\`gjs live
|
|
305
|
+
${snippet}
|
|
306
|
+
\`\`\`
|
|
307
|
+
<Demo />
|
|
308
|
+
`,
|
|
309
|
+
{ ...defaults }
|
|
310
|
+
);
|
|
311
|
+
|
|
312
|
+
expect(result.text).toMatchInlineSnapshot(`
|
|
313
|
+
"<h1 id="title">Title</h1>
|
|
314
|
+
<div id="repl_3" class="repl-sdk__demo"></div>
|
|
315
|
+
<Demo />"
|
|
316
|
+
`);
|
|
317
|
+
|
|
318
|
+
assertCodeBlocks(result.codeBlocks, [
|
|
319
|
+
{
|
|
320
|
+
code: snippet,
|
|
321
|
+
format: 'gjs',
|
|
322
|
+
meta: 'live',
|
|
323
|
+
},
|
|
324
|
+
]);
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
it('Code fence imports things', async function () {
|
|
328
|
+
const snippet = stripIndent`
|
|
329
|
+
import Component from '@glimmer/component';
|
|
330
|
+
import { on } from '@ember/modifier';
|
|
331
|
+
|
|
332
|
+
<template>
|
|
333
|
+
<button {{on "click" console.log}}>Click</button>
|
|
334
|
+
</template>
|
|
335
|
+
`;
|
|
336
|
+
const result = await parseMarkdown(
|
|
337
|
+
`hi\n` + `\n` + '```gjs live preview\n' + snippet + '\n```',
|
|
338
|
+
{ ...defaults }
|
|
339
|
+
);
|
|
340
|
+
|
|
341
|
+
expect(result.text).toMatchInlineSnapshot(`
|
|
342
|
+
"<p>hi</p>
|
|
343
|
+
<div id="repl_4" class="repl-sdk__demo"></div>
|
|
344
|
+
<div class="repl-sdk__snippet" data-repl-output><pre><code class="language-gjs">import Component from '@glimmer/component';
|
|
345
|
+
import { on } from '@ember/modifier';
|
|
346
|
+
|
|
347
|
+
<template>
|
|
348
|
+
<button \\{{on "click" console.log}}>Click</button>
|
|
349
|
+
</template>
|
|
350
|
+
</code></pre></div>"
|
|
351
|
+
`);
|
|
352
|
+
|
|
353
|
+
assertCodeBlocks(result.codeBlocks, [
|
|
354
|
+
{
|
|
355
|
+
code: snippet,
|
|
356
|
+
format: 'gjs',
|
|
357
|
+
meta: 'live preview',
|
|
358
|
+
},
|
|
359
|
+
]);
|
|
360
|
+
});
|
|
361
|
+
});
|
|
362
|
+
});
|
|
363
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { visit } from 'unist-util-visit';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @type {import('unified').Plugin<[], import('hast').Root>}
|
|
5
|
+
*/
|
|
6
|
+
export function sanitizeForGlimmer(/* options */) {
|
|
7
|
+
return function transformer(tree) {
|
|
8
|
+
visit(tree, 'element', function visitor(node) {
|
|
9
|
+
if (node.type === 'element' && 'tagName' in node) {
|
|
10
|
+
const element = /** @type {import('hast').Element} */ (node);
|
|
11
|
+
|
|
12
|
+
if (!['pre', 'code'].includes(element.tagName)) return;
|
|
13
|
+
|
|
14
|
+
visit(node, 'text', function textVisitor(textNode) {
|
|
15
|
+
if (textNode.type === 'text') {
|
|
16
|
+
const text = /** @type {import('hast').Text} */ (textNode);
|
|
17
|
+
|
|
18
|
+
text.value = text.value.replace(/{{/g, '\\{{');
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
return 'skip';
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export interface LiveCodeExtractionOptions {
|
|
2
|
+
isLive?: (meta: string, lang: string) => boolean;
|
|
3
|
+
ALLOWED_FORMATS?: string[];
|
|
4
|
+
isPreview?: (meta: string) => boolean;
|
|
5
|
+
isBelow?: (meta: string) => boolean;
|
|
6
|
+
needsLive?: (lang: string) => boolean;
|
|
7
|
+
getFlavorFromMeta?: (meta: string, lang: string) => string | undefined;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface PublicOptions {
|
|
11
|
+
code?: {
|
|
12
|
+
classList?: string[];
|
|
13
|
+
};
|
|
14
|
+
demo?: {
|
|
15
|
+
classList?: string[];
|
|
16
|
+
};
|
|
17
|
+
remarkPlugins?: unknown[];
|
|
18
|
+
rehypePlugins?: unknown[];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export type InternalOptions = PublicOptions & LiveCodeExtractionOptions;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {string} lang
|
|
3
|
+
*/
|
|
4
|
+
export function isNotMarkdownLike(lang) {
|
|
5
|
+
return lang !== 'md' && lang !== 'gmd' && lang !== 'mdx';
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @param {string} meta
|
|
10
|
+
*/
|
|
11
|
+
export function isPreview(meta) {
|
|
12
|
+
if (!meta) return false;
|
|
13
|
+
|
|
14
|
+
return meta.includes('preview');
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @param {string} meta
|
|
19
|
+
*/
|
|
20
|
+
export function isBelow(meta) {
|
|
21
|
+
if (!meta) return false;
|
|
22
|
+
|
|
23
|
+
return meta.includes('below');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @param {Pick<import('../../types').PublicMethods, 'getAllowedFormats' | 'getFlavorsFor' | 'optionsFor'>} api
|
|
28
|
+
*/
|
|
29
|
+
export function buildCodeFenceMetaUtils(api) {
|
|
30
|
+
const allowedFormats = api.getAllowedFormats().filter(isNotMarkdownLike);
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @param {string} lang
|
|
34
|
+
* @param {string | undefined} [ flavor ]
|
|
35
|
+
*/
|
|
36
|
+
function needsLive(lang, flavor) {
|
|
37
|
+
if (!allowedFormats.includes(lang)) return false;
|
|
38
|
+
|
|
39
|
+
return api.optionsFor(lang, flavor).needsLiveMeta ?? true;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @param {string} meta
|
|
44
|
+
* @param {string} lang
|
|
45
|
+
*/
|
|
46
|
+
function getFlavorFromMeta(meta, lang) {
|
|
47
|
+
const flavors = api.getFlavorsFor(lang);
|
|
48
|
+
|
|
49
|
+
const flavor = meta
|
|
50
|
+
?.trim()
|
|
51
|
+
.split(' ')
|
|
52
|
+
.find((metum) => flavors.includes(metum));
|
|
53
|
+
|
|
54
|
+
return flavor;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* @param {string} meta
|
|
59
|
+
* @param {string} lang
|
|
60
|
+
*/
|
|
61
|
+
function isLive(meta, lang) {
|
|
62
|
+
const flavor = getFlavorFromMeta(meta, lang);
|
|
63
|
+
|
|
64
|
+
if (!needsLive(lang, flavor)) return true;
|
|
65
|
+
if (!meta) return false;
|
|
66
|
+
|
|
67
|
+
return meta.includes('live');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return {
|
|
71
|
+
isPreview,
|
|
72
|
+
isBelow,
|
|
73
|
+
isLive,
|
|
74
|
+
needsLive,
|
|
75
|
+
allowedFormats,
|
|
76
|
+
getFlavorFromMeta,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {import('unified').Plugin} Plugin
|
|
3
|
+
*/
|
|
4
|
+
import { assert, isRecord } from '../utils.js';
|
|
5
|
+
import { buildCodeFenceMetaUtils } from './markdown/utils.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @param {unknown} [ options ]
|
|
9
|
+
* @returns {{ remarkPlugins: Plugin[], rehypePlugins: Plugin[] }}
|
|
10
|
+
*/
|
|
11
|
+
export function filterOptions(options) {
|
|
12
|
+
if (!isRecord(options)) {
|
|
13
|
+
return { remarkPlugins: [], rehypePlugins: [] };
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return {
|
|
17
|
+
remarkPlugins: /** @type {Plugin[]}*/ (options?.remarkPlugins || []),
|
|
18
|
+
rehypePlugins: /** @type {Plugin[]}*/ (options?.rehypePlugins || []),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @type {import('../types.ts').CompilerConfig}
|
|
24
|
+
*/
|
|
25
|
+
export const md = {
|
|
26
|
+
codemirror: {
|
|
27
|
+
lang: async () => {
|
|
28
|
+
const { glimdown } = await import('codemirror-lang-glimdown');
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* pre-configured markdown with GFM, and a few other extensions
|
|
32
|
+
*/
|
|
33
|
+
return glimdown();
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
compiler: async (config, api) => {
|
|
37
|
+
const { isLive, isPreview, needsLive, allowedFormats, isBelow, getFlavorFromMeta } =
|
|
38
|
+
buildCodeFenceMetaUtils(api);
|
|
39
|
+
|
|
40
|
+
// Try both possible structures
|
|
41
|
+
const userOptions = filterOptions(
|
|
42
|
+
/** @type {Record<string, unknown>} */ (config.userOptions)?.md || config
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
// No recursing for now.
|
|
46
|
+
|
|
47
|
+
const { parseMarkdown } = await import('./markdown/parse.js');
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* @type {import('../types.ts').Compiler}
|
|
51
|
+
*/
|
|
52
|
+
return {
|
|
53
|
+
compile: async (text, options) => {
|
|
54
|
+
const compileOptions = filterOptions(options);
|
|
55
|
+
const result = await parseMarkdown(text, {
|
|
56
|
+
remarkPlugins: [...userOptions.remarkPlugins, ...compileOptions.remarkPlugins],
|
|
57
|
+
rehypePlugins: [...userOptions.rehypePlugins, ...compileOptions.rehypePlugins],
|
|
58
|
+
isLive,
|
|
59
|
+
isPreview,
|
|
60
|
+
isBelow,
|
|
61
|
+
needsLive,
|
|
62
|
+
ALLOWED_FORMATS: allowedFormats,
|
|
63
|
+
getFlavorFromMeta,
|
|
64
|
+
});
|
|
65
|
+
const escaped = result.text.replace(/`/g, '\\`');
|
|
66
|
+
|
|
67
|
+
return { compiled: `export default \`${escaped}\``, ...result };
|
|
68
|
+
},
|
|
69
|
+
render: async (element, compiled, extra, compiler) => {
|
|
70
|
+
element.innerHTML = /** @type {string} */ (compiled);
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* @type {(() => void)[]}
|
|
74
|
+
*/
|
|
75
|
+
const destroyables = [];
|
|
76
|
+
|
|
77
|
+
await Promise.all(
|
|
78
|
+
/** @type {unknown[]} */ (extra.codeBlocks).map(async (/** @type {unknown} */ info) => {
|
|
79
|
+
/** @type {Record<string, unknown>} */
|
|
80
|
+
const infoObj = /** @type {Record<string, unknown>} */ (info);
|
|
81
|
+
|
|
82
|
+
if (
|
|
83
|
+
!api.canCompile(
|
|
84
|
+
/** @type {string} */ (infoObj.format),
|
|
85
|
+
/** @type {string} */ (infoObj.flavor)
|
|
86
|
+
)
|
|
87
|
+
) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const flavor = /** @type {string} */ (infoObj.flavor);
|
|
92
|
+
const subRender = await compiler.compile(
|
|
93
|
+
/** @type {string} */ (infoObj.format),
|
|
94
|
+
/** @type {string} */ (infoObj.code),
|
|
95
|
+
{
|
|
96
|
+
...compiler.optionsFor(/** @type {string} */ (infoObj.format), flavor),
|
|
97
|
+
flavor: flavor,
|
|
98
|
+
}
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
const selector = `#${/** @type {string} */ (infoObj.placeholderId)}`;
|
|
102
|
+
const target = element.querySelector(selector);
|
|
103
|
+
|
|
104
|
+
assert(
|
|
105
|
+
`Could not find placeholder / target element (using selector: \`${selector}\`). ` +
|
|
106
|
+
`Could not render ${/** @type {string} */ (infoObj.format)} block.`,
|
|
107
|
+
target
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
destroyables.push(subRender.destroy);
|
|
111
|
+
target.appendChild(subRender.element);
|
|
112
|
+
})
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
compiler.announce('info', 'Done');
|
|
116
|
+
|
|
117
|
+
return () => {
|
|
118
|
+
for (const subDestroy of destroyables) {
|
|
119
|
+
subDestroy();
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
},
|
|
125
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { esmsh } from '../cdn.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @type {import('../types.ts').CompilerConfig}
|
|
5
|
+
*/
|
|
6
|
+
export const mermaid = {
|
|
7
|
+
needsLiveMeta: false,
|
|
8
|
+
codemirror: {
|
|
9
|
+
lang: async () => {
|
|
10
|
+
const { mermaid } = await import('codemirror-lang-mermaid');
|
|
11
|
+
|
|
12
|
+
return mermaid();
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
compiler: async (config, api) => {
|
|
16
|
+
const versions = config.versions;
|
|
17
|
+
const { default: mermaid } = await api.tryResolve('mermaid', () => {
|
|
18
|
+
return esmsh.import(versions, 'mermaid');
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
let id = 0;
|
|
22
|
+
|
|
23
|
+
return {
|
|
24
|
+
compile: async (text) => {
|
|
25
|
+
return `export default \`${text}\`;`;
|
|
26
|
+
},
|
|
27
|
+
render: async (element, text, _, compiler) => {
|
|
28
|
+
const { svg } = await mermaid.render('graphDiv' + id++, text);
|
|
29
|
+
|
|
30
|
+
element.innerHTML = svg;
|
|
31
|
+
compiler.announce('info', 'Done');
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
},
|
|
35
|
+
};
|