@hpcc-js/markdown-it-plugins 1.5.4 → 1.5.6

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.
@@ -1,12 +1,12 @@
1
- import type { LanguageInput } from "shiki";
2
-
3
- import ecl_lang from "./ecl.tmLanguage.json" with { type: "json" };
4
-
5
- export function eclLang(): LanguageInput {
6
- const retVal = {
7
- ...ecl_lang,
8
- name: "ecl"
9
- } as unknown as LanguageInput;
10
- return retVal;
11
- }
12
-
1
+ import type { LanguageInput } from "shiki";
2
+
3
+ import ecl_lang from "./ecl.tmLanguage.json" with { type: "json" };
4
+
5
+ export function eclLang(): LanguageInput {
6
+ const retVal = {
7
+ ...ecl_lang,
8
+ name: "ecl"
9
+ } as unknown as LanguageInput;
10
+ return retVal;
11
+ }
12
+
package/src/fence.ts CHANGED
@@ -1,59 +1,59 @@
1
- import type MarkdownIt from "markdown-it";
2
- import type { Options } from "markdown-it";
3
- import type Token from "markdown-it/lib/token.mjs";
4
- import type Renderer from "markdown-it/lib/renderer.mjs";
5
- import { RenderNode } from "./render.ts";
6
- import { ENV_KEY, executeSrc, FenceInfo, fenceInfoDefaults, generatePlaceholders, showSrc } from "./util.ts";
7
-
8
- const deserializeFenceInfo = (attrs: string): FenceInfo =>
9
- attrs
10
- .split(/\s+/)
11
- .reduce((acc: FenceInfo, pair, idx: number) => {
12
- if (idx === 0) {
13
- acc.type = pair as "js" | "javascript" | string;
14
- return acc;
15
- }
16
-
17
- const [key, value] = pair.split("=") as [keyof FenceInfo, string];
18
- switch (key) {
19
- case "exec":
20
- case "echo":
21
- case "hide":
22
- acc[key] = value !== "false";
23
- break;
24
- }
25
- return acc;
26
- }, { ...fenceInfoDefaults })
27
- ;
28
-
29
- const proxy = (tokens: Token[], idx: number, options: Options, _env: any, self: Renderer) => self.renderToken(tokens, idx, options);
30
-
31
- export function hookFence(md: MarkdownIt) {
32
- const defaultFenceRenderer = md.renderer.rules.fence || proxy;
33
- const fenceRenderer = (tokens: Token[], idx: number, options: Options, env: { [ENV_KEY]?: RenderNode[] }, self: Renderer) => {
34
- const token = tokens[idx];
35
- const fenceInfo = deserializeFenceInfo(token.info);
36
- if (fenceInfo.type === "javascript") {
37
- fenceInfo.type = "js";
38
- }
39
- token.content += "\n";
40
- let preHtml = "";
41
- switch (fenceInfo.type) {
42
- case "js":
43
- if (executeSrc(fenceInfo)) {
44
- if (!env[ENV_KEY]) {
45
- env[ENV_KEY] = [];
46
- }
47
- preHtml += generatePlaceholders(token.content, fenceInfo, env);
48
- }
49
- if (showSrc(fenceInfo)) {
50
- return preHtml + defaultFenceRenderer(tokens, idx, options, env, self);
51
- }
52
- break;
53
- default:
54
- return preHtml + defaultFenceRenderer(tokens, idx, options, env, self);
55
- }
56
- return preHtml;
57
- };
58
- md.renderer.rules.fence = fenceRenderer;
59
- }
1
+ import type MarkdownIt from "markdown-it";
2
+ import type { Options } from "markdown-it";
3
+ import type Token from "markdown-it/lib/token.mjs";
4
+ import type Renderer from "markdown-it/lib/renderer.mjs";
5
+ import { RenderNode } from "./render.ts";
6
+ import { ENV_KEY, executeSrc, FenceInfo, fenceInfoDefaults, generatePlaceholders, showSrc } from "./util.ts";
7
+
8
+ const deserializeFenceInfo = (attrs: string): FenceInfo =>
9
+ attrs
10
+ .split(/\s+/)
11
+ .reduce((acc: FenceInfo, pair, idx: number) => {
12
+ if (idx === 0) {
13
+ acc.type = pair as "js" | "javascript" | string;
14
+ return acc;
15
+ }
16
+
17
+ const [key, value] = pair.split("=") as [keyof FenceInfo, string];
18
+ switch (key) {
19
+ case "exec":
20
+ case "echo":
21
+ case "hide":
22
+ acc[key] = value !== "false";
23
+ break;
24
+ }
25
+ return acc;
26
+ }, { ...fenceInfoDefaults })
27
+ ;
28
+
29
+ const proxy = (tokens: Token[], idx: number, options: Options, _env: any, self: Renderer) => self.renderToken(tokens, idx, options);
30
+
31
+ export function hookFence(md: MarkdownIt) {
32
+ const defaultFenceRenderer = md.renderer.rules.fence || proxy;
33
+ const fenceRenderer = (tokens: Token[], idx: number, options: Options, env: { [ENV_KEY]?: RenderNode[] }, self: Renderer) => {
34
+ const token = tokens[idx];
35
+ const fenceInfo = deserializeFenceInfo(token.info);
36
+ if (fenceInfo.type === "javascript") {
37
+ fenceInfo.type = "js";
38
+ }
39
+ token.content += "\n";
40
+ let preHtml = "";
41
+ switch (fenceInfo.type) {
42
+ case "js":
43
+ if (executeSrc(fenceInfo)) {
44
+ if (!env[ENV_KEY]) {
45
+ env[ENV_KEY] = [];
46
+ }
47
+ preHtml += generatePlaceholders(token.content, fenceInfo, env);
48
+ }
49
+ if (showSrc(fenceInfo)) {
50
+ return preHtml + defaultFenceRenderer(tokens, idx, options, env, self);
51
+ }
52
+ break;
53
+ default:
54
+ return preHtml + defaultFenceRenderer(tokens, idx, options, env, self);
55
+ }
56
+ return preHtml;
57
+ };
58
+ md.renderer.rules.fence = fenceRenderer;
59
+ }
package/src/index.ts CHANGED
@@ -1,47 +1,47 @@
1
- import type MarkdownIt from "markdown-it";
2
- import { render } from "./render.ts";
3
- import { ENV_KEY } from "./util.ts";
4
- import { hookTemplateLiterals } from "./template-literal.ts";
5
- import { hookFence } from "./fence.ts";
6
-
7
- function hookRender(md: MarkdownIt) {
8
- const originalRender = md.render;
9
- md.render = (src: string, _env?: any): string => {
10
- const env = { ..._env };
11
- const retVal = originalRender.call(md, src, env);
12
- render(env[ENV_KEY] ?? []);
13
- return retVal;
14
- };
15
- }
16
-
17
- function hookVitepressRender(md: MarkdownIt) {
18
-
19
- const originalRender = md.render;
20
- md.render = (src: string, env?: any): string => {
21
- const myEnv = env ?? {};
22
- let retVal = originalRender.call(md, src, myEnv);
23
- if (env[ENV_KEY]?.length) {
24
- const content = encodeURI(JSON.stringify(env[ENV_KEY]));
25
- retVal += `<RenderComponent content="${content}" />`;
26
- }
27
- return retVal;
28
- };
29
- }
30
-
31
- export interface ObservableOptions {
32
- vitePress?: boolean;
33
- }
34
-
35
- export function observable(md: MarkdownIt, opts: ObservableOptions = {}) {
36
- hookTemplateLiterals(md);
37
- hookFence(md);
38
- if (opts.vitePress) {
39
- hookVitepressRender(md);
40
- } else {
41
- hookRender(md);
42
- }
43
- }
44
-
45
- export {
46
- render
47
- };
1
+ import type MarkdownIt from "markdown-it";
2
+ import { render } from "./render.ts";
3
+ import { ENV_KEY } from "./util.ts";
4
+ import { hookTemplateLiterals } from "./template-literal.ts";
5
+ import { hookFence } from "./fence.ts";
6
+
7
+ function hookRender(md: MarkdownIt) {
8
+ const originalRender = md.render;
9
+ md.render = (src: string, _env?: any): string => {
10
+ const env = { ..._env };
11
+ const retVal = originalRender.call(md, src, env);
12
+ render(env[ENV_KEY] ?? []);
13
+ return retVal;
14
+ };
15
+ }
16
+
17
+ function hookVitepressRender(md: MarkdownIt) {
18
+
19
+ const originalRender = md.render;
20
+ md.render = (src: string, env?: any): string => {
21
+ const myEnv = env ?? {};
22
+ let retVal = originalRender.call(md, src, myEnv);
23
+ if (env[ENV_KEY]?.length) {
24
+ const content = encodeURI(JSON.stringify(env[ENV_KEY]));
25
+ retVal += `<RenderComponent content="${content}" />`;
26
+ }
27
+ return retVal;
28
+ };
29
+ }
30
+
31
+ export interface ObservableOptions {
32
+ vitePress?: boolean;
33
+ }
34
+
35
+ export function observable(md: MarkdownIt, opts: ObservableOptions = {}) {
36
+ hookTemplateLiterals(md);
37
+ hookFence(md);
38
+ if (opts.vitePress) {
39
+ hookVitepressRender(md);
40
+ } else {
41
+ hookRender(md);
42
+ }
43
+ }
44
+
45
+ export {
46
+ render
47
+ };
package/src/loader.ts CHANGED
@@ -1,154 +1,154 @@
1
- import { existsSync } from "node:fs";
2
- import { readdir, readFile } from "node:fs/promises";
3
- import path from "node:path";
4
- import { pathToFileURL } from "node:url";
5
- import { dsvFormat, autoType } from "d3-dsv";
6
- import { LoaderResolver, } from "@observablehq/framework/dist/loader.js";
7
- import { getResolvers } from "@observablehq/framework/dist/resolvers.js";
8
- import { normalizeConfig } from "@observablehq/framework/dist/config.js";
9
- import { parseMarkdown } from "@observablehq/framework/dist/markdown.js";
10
-
11
- function getOptions({ path, ...config }) {
12
- return { ...normalizeConfig(config), path };
13
- }
14
-
15
- export class DataFile {
16
-
17
- private filePath: string;
18
- private options: any;
19
- private resolvers: any;
20
- readonly ext: string;
21
-
22
- protected constructor(filePath, options, resolvers) {
23
- this.filePath = filePath;
24
- this.options = options;
25
- this.resolvers = resolvers;
26
- this.ext = path.extname(filePath).substring(1);
27
- }
28
-
29
- static async attach(partialPath: string, root: string = path.resolve(".")) {
30
- const exists = existsSync(path.resolve(root, partialPath));
31
- const loaders = new LoaderResolver({ root, interpreters: {} });
32
- const loader = loaders.find(partialPath);
33
- if (loader) {
34
- await loader.load();
35
- const ext = path.extname(partialPath);
36
- const options = getOptions({ root, path: "dummy.md" });
37
- const page = parseMarkdown(`\${FileAttachment('${partialPath}')${ext}()}`, options);
38
- const resolvers = await getResolvers(page, options);
39
- resolvers.resolveFile(partialPath);
40
- return new DataFile(exists ? path.resolve(root, partialPath) : path.resolve(path.join(root, ".observablehq", "cache", partialPath)), options, resolvers);
41
- }
42
- }
43
-
44
- async myResolve(module: string) {
45
- const partialPath = await this.resolvers.resolveImport(module);
46
- return path.resolve(path.join(this.options.root, ".observablehq", "cache", partialPath));
47
- }
48
-
49
- async myImport(module: string) {
50
- if (module === "npm:apache-arrow") {
51
- return import("apache-arrow");
52
- }
53
- const fullPath = await this.myResolve(module);
54
- const href = pathToFileURL(fullPath).href;
55
- return import(href).catch((error) => {
56
- console.error(error);
57
- });
58
- }
59
-
60
- buffer(): Promise<Buffer> {
61
- return readFile(this.filePath);
62
- }
63
-
64
- arrayBuffer() {
65
- return this.buffer().then(buffer => buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength));
66
- }
67
-
68
- text(encoding: BufferEncoding = "utf8") {
69
- return readFile(this.filePath, encoding);
70
- }
71
-
72
- json() {
73
- return this.text().then(txt => {
74
- return JSON.parse(txt);
75
- });
76
- }
77
-
78
- dsv({ delimiter = ",", array = false, typed = false } = {}) {
79
- return this.text().then(text => {
80
- const format = dsvFormat(delimiter);
81
- const parse: any = array ? format.parseRows : format.parse;
82
- return parse(text, typed && autoType);
83
- });
84
- }
85
-
86
- csv(options?) {
87
- return this.dsv({ ...options, delimiter: "," });
88
- }
89
-
90
- tsv(options?) {
91
- return this.dsv({ ...options, delimiter: "\t" });
92
- }
93
-
94
- arrow() {
95
- return Promise.all([this.myImport("npm:apache-arrow"), this.arrayBuffer()]).then(([Arrow, response]) => {
96
- return Arrow.tableFromIPC(response);
97
- });
98
- }
99
-
100
- parquet() {
101
- return this.myResolve("npm:parquet-wasm/esm/parquet_wasm_bg.wasm").then(wasmBytes => {
102
- const wasmFile = new DataFile(wasmBytes, this.options, this.resolvers);
103
- return Promise.all([
104
- this.myImport("npm:apache-arrow"),
105
- this.myImport("npm:parquet-wasm"),
106
- wasmFile.arrayBuffer(),
107
- this.arrayBuffer()
108
- ]).then(([Arrow, Parquet, wasm, buffer]) => {
109
- Parquet.initSync(wasm);
110
- return Arrow.tableFromIPC(Parquet.readParquet(new Uint8Array(buffer)).intoIPCStream());
111
- });
112
- });
113
- }
114
-
115
- fetch() {
116
- if (this[this.ext]) {
117
- return this[this.ext]();
118
- }
119
- }
120
- }
121
-
122
- const regex = /^(.+\.(csv|tsv|txt|json|arrow|parquet))(?:\..*)?$/;
123
- interface FileInfo {
124
- path: string;
125
- data: any;
126
- }
127
- export async function findDataFiles(directory: string, recursive: boolean = false): Promise<FileInfo[]> {
128
- const files = await readdir(directory, { withFileTypes: true });
129
- let dataFiles: FileInfo[] = [];
130
-
131
- for (const file of files) {
132
- const fullPath = path.join(directory, file.name);
133
- if (file.isDirectory() && recursive) {
134
- const nestedFiles = await findDataFiles(fullPath, recursive);
135
- dataFiles = dataFiles.concat(nestedFiles);
136
- } else if (file.isFile()) {
137
- const match = file.name.match(regex);
138
- if (match) {
139
- const _path = path.join(directory, match[1]);
140
- dataFiles.push({
141
- path: _path,
142
- data: await DataFile.attach(_path)
143
- });
144
- }
145
- }
146
- }
147
- return dataFiles;
148
- }
149
-
150
- export async function fetchData(partialPath: string) {
151
- const dataFile = await DataFile.attach(partialPath);
152
- return dataFile?.fetch();
153
- }
154
-
1
+ import { existsSync } from "node:fs";
2
+ import { readdir, readFile } from "node:fs/promises";
3
+ import path from "node:path";
4
+ import { pathToFileURL } from "node:url";
5
+ import { dsvFormat, autoType } from "d3-dsv";
6
+ import { LoaderResolver, } from "@observablehq/framework/dist/loader.js";
7
+ import { getResolvers } from "@observablehq/framework/dist/resolvers.js";
8
+ import { normalizeConfig } from "@observablehq/framework/dist/config.js";
9
+ import { parseMarkdown } from "@observablehq/framework/dist/markdown.js";
10
+
11
+ function getOptions({ path, ...config }) {
12
+ return { ...normalizeConfig(config), path };
13
+ }
14
+
15
+ export class DataFile {
16
+
17
+ private filePath: string;
18
+ private options: any;
19
+ private resolvers: any;
20
+ readonly ext: string;
21
+
22
+ protected constructor(filePath, options, resolvers) {
23
+ this.filePath = filePath;
24
+ this.options = options;
25
+ this.resolvers = resolvers;
26
+ this.ext = path.extname(filePath).substring(1);
27
+ }
28
+
29
+ static async attach(partialPath: string, root: string = path.resolve(".")) {
30
+ const exists = existsSync(path.resolve(root, partialPath));
31
+ const loaders = new LoaderResolver({ root, interpreters: {} });
32
+ const loader = loaders.find(partialPath);
33
+ if (loader) {
34
+ await loader.load();
35
+ const ext = path.extname(partialPath);
36
+ const options = getOptions({ root, path: "dummy.md" });
37
+ const page = parseMarkdown(`\${FileAttachment('${partialPath}')${ext}()}`, options);
38
+ const resolvers = await getResolvers(page, options);
39
+ resolvers.resolveFile(partialPath);
40
+ return new DataFile(exists ? path.resolve(root, partialPath) : path.resolve(path.join(root, ".observablehq", "cache", partialPath)), options, resolvers);
41
+ }
42
+ }
43
+
44
+ async myResolve(module: string) {
45
+ const partialPath = await this.resolvers.resolveImport(module);
46
+ return path.resolve(path.join(this.options.root, ".observablehq", "cache", partialPath));
47
+ }
48
+
49
+ async myImport(module: string) {
50
+ if (module === "npm:apache-arrow") {
51
+ return import("apache-arrow");
52
+ }
53
+ const fullPath = await this.myResolve(module);
54
+ const href = pathToFileURL(fullPath).href;
55
+ return import(href).catch((error) => {
56
+ console.error(error);
57
+ });
58
+ }
59
+
60
+ buffer(): Promise<Buffer> {
61
+ return readFile(this.filePath);
62
+ }
63
+
64
+ arrayBuffer() {
65
+ return this.buffer().then(buffer => buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength));
66
+ }
67
+
68
+ text(encoding: BufferEncoding = "utf8") {
69
+ return readFile(this.filePath, encoding);
70
+ }
71
+
72
+ json() {
73
+ return this.text().then(txt => {
74
+ return JSON.parse(txt);
75
+ });
76
+ }
77
+
78
+ dsv({ delimiter = ",", array = false, typed = false } = {}) {
79
+ return this.text().then(text => {
80
+ const format = dsvFormat(delimiter);
81
+ const parse: any = array ? format.parseRows : format.parse;
82
+ return parse(text, typed && autoType);
83
+ });
84
+ }
85
+
86
+ csv(options?) {
87
+ return this.dsv({ ...options, delimiter: "," });
88
+ }
89
+
90
+ tsv(options?) {
91
+ return this.dsv({ ...options, delimiter: "\t" });
92
+ }
93
+
94
+ arrow() {
95
+ return Promise.all([this.myImport("npm:apache-arrow"), this.arrayBuffer()]).then(([Arrow, response]) => {
96
+ return Arrow.tableFromIPC(response);
97
+ });
98
+ }
99
+
100
+ parquet() {
101
+ return this.myResolve("npm:parquet-wasm/esm/parquet_wasm_bg.wasm").then(wasmBytes => {
102
+ const wasmFile = new DataFile(wasmBytes, this.options, this.resolvers);
103
+ return Promise.all([
104
+ this.myImport("npm:apache-arrow"),
105
+ this.myImport("npm:parquet-wasm"),
106
+ wasmFile.arrayBuffer(),
107
+ this.arrayBuffer()
108
+ ]).then(([Arrow, Parquet, wasm, buffer]) => {
109
+ Parquet.initSync(wasm);
110
+ return Arrow.tableFromIPC(Parquet.readParquet(new Uint8Array(buffer)).intoIPCStream());
111
+ });
112
+ });
113
+ }
114
+
115
+ fetch() {
116
+ if (this[this.ext]) {
117
+ return this[this.ext]();
118
+ }
119
+ }
120
+ }
121
+
122
+ const regex = /^(.+\.(csv|tsv|txt|json|arrow|parquet))(?:\..*)?$/;
123
+ interface FileInfo {
124
+ path: string;
125
+ data: any;
126
+ }
127
+ export async function findDataFiles(directory: string, recursive: boolean = false): Promise<FileInfo[]> {
128
+ const files = await readdir(directory, { withFileTypes: true });
129
+ let dataFiles: FileInfo[] = [];
130
+
131
+ for (const file of files) {
132
+ const fullPath = path.join(directory, file.name);
133
+ if (file.isDirectory() && recursive) {
134
+ const nestedFiles = await findDataFiles(fullPath, recursive);
135
+ dataFiles = dataFiles.concat(nestedFiles);
136
+ } else if (file.isFile()) {
137
+ const match = file.name.match(regex);
138
+ if (match) {
139
+ const _path = path.join(directory, match[1]);
140
+ dataFiles.push({
141
+ path: _path,
142
+ data: await DataFile.attach(_path)
143
+ });
144
+ }
145
+ }
146
+ }
147
+ return dataFiles;
148
+ }
149
+
150
+ export async function fetchData(partialPath: string) {
151
+ const dataFile = await DataFile.attach(partialPath);
152
+ return dataFile?.fetch();
153
+ }
154
+