crossing the streams
1// index.ts
2// based on: https://github.com/FujoWebDev/fujocoded-plugins/blob/main/expressive-code-output/index.ts
3
4import { definePlugin, AttachedPluginData } from "@expressive-code/core";
5import { h } from "@expressive-code/core/hast";
6var outputData = new AttachedPluginData(() => ({ output: [] }));
7function pluginCodeOutput() {
8 return definePlugin({
9 name: "Code output",
10 baseStyles: `
11 .expressive-code .frame pre.output {
12 display: block;
13 border: var(--ec-brdWd) solid var(--ec-brdCol);
14 border-top: var(--ec-brdWd) dashed var(--ec-brdCol);
15 padding: var(--ec-codePadBlk) 0;
16 padding-inline-start: var(--ec-codePadInl);
17 }
18 `,
19 hooks: {
20 preprocessCode: (context) => {
21 if (!context.codeBlock.meta.includes("withOutput")) return;
22 const blockData = outputData.getOrCreateFor(context.codeBlock);
23 const outputStart = context.codeBlock.getLines().findIndex((line) => !line.text.startsWith("> "));
24 context.codeBlock.getLines(0, outputStart == -1 ? void 0 : outputStart).forEach((line) => {
25 line.editText(0, 2, "");
26 });
27 if (outputStart === -1) return;
28 context.codeBlock.getLines(outputStart).forEach((line) => {
29 blockData.output.push(line.text);
30 });
31 for (let i = context.codeBlock.getLines().length; i > outputStart; i--) {
32 context.codeBlock.deleteLine(i - 1);
33 }
34 },
35 postprocessRenderedBlock: async (context) => {
36 if (!context.codeBlock.meta.includes("withOutput")) return;
37 const blockData = outputData.getOrCreateFor(context.codeBlock);
38 if (!blockData.output.length) return;
39 const lastPre = context.renderData.blockAst.children.findLastIndex(
40 (child) => child.type === "element" && child.tagName === "pre"
41 );
42 if (lastPre === -1) return;
43 const currentChildren = context.renderData.blockAst.children;
44 const newChildren = [
45 ...currentChildren.slice(0, lastPre + 1),
46 h(
47 "pre.output",
48 blockData.output.map((line) => h("div", line))
49 ),
50 ...currentChildren.slice(lastPre + 1)
51 ];
52 context.renderData.blockAst.children = newChildren;
53 }
54 }
55 });
56}
57export {
58 pluginCodeOutput
59};