@borrowdev/docval 0.1.2 → 0.1.4

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.
@@ -0,0 +1,6 @@
1
+ [package]
2
+ name = "docval-env"
3
+ version = "0.0.0"
4
+ edition = "2024"
5
+
6
+ [dependencies]
@@ -0,0 +1,6 @@
1
+ {
2
+ "name": "docval-env",
3
+ "version": "0.0.0",
4
+ "private": true,
5
+ "type": "module"
6
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["adapterJavaScript","adapterTypeScript","adapterJSX","adapterTSX","adapterRust"],"sources":["../../src/adapters/index.ts"],"sourcesContent":["import adapterJavaScript from \"./javascript\";\nimport adapterJSX from \"./jsx\";\nimport adapterRust from \"./rust\";\nimport adapterTSX from \"./tsx\";\nimport adapterTypeScript from \"./typescript\";\n\nconst map: { [key: string]: (code: string, metadata: string[]) => Promise<void> } = {\n javascript: adapterJavaScript,\n js: adapterJavaScript,\n typescript: adapterTypeScript,\n ts: adapterTypeScript,\n jsx: adapterJSX,\n tsx: adapterTSX,\n rust: adapterRust,\n rs: adapterRust,\n};\n\nexport default map;\n"],"mappings":";;;;;;;AAMA,MAAM,MAA8E;CAClF,YAAYA;CACZ,IAAIA;CACJ,YAAYC;CACZ,IAAIA;CACJ,KAAKC;CACL,KAAKC;CACL,MAAMC;CACN,IAAIA;CACL"}
1
+ {"version":3,"file":"index.mjs","names":["adapterJavaScript","adapterTypeScript","adapterJSX","adapterTSX","adapterRust"],"sources":["../../src/adapters/index.ts"],"sourcesContent":["import adapterJavaScript from \"./javascript\";\nimport adapterJSX from \"./jsx\";\nimport adapterRust from \"./rust\";\nimport adapterTSX from \"./tsx\";\nimport adapterTypeScript from \"./typescript\";\n\nconst map = {\n javascript: adapterJavaScript,\n js: adapterJavaScript,\n typescript: adapterTypeScript,\n ts: adapterTypeScript,\n jsx: adapterJSX,\n tsx: adapterTSX,\n rust: adapterRust,\n rs: adapterRust,\n} as const;\n\ntype Language = keyof typeof map;\n\nexport { Language };\nexport default map;\n"],"mappings":";;;;;;;AAMA,MAAM,MAAM;CACV,YAAYA;CACZ,IAAIA;CACJ,YAAYC;CACZ,IAAIA;CACJ,KAAKC;CACL,KAAKC;CACL,MAAMC;CACN,IAAIA;CACL"}
@@ -8,6 +8,16 @@ import { join } from "path";
8
8
  import { isBuiltin } from "module";
9
9
 
10
10
  //#region src/adapters/javascript/utils.ts
11
+ function getTree(code, type, filename) {
12
+ return parse(filename ?? "unknown", code, { lang: type });
13
+ }
14
+ async function getComments(code, type) {
15
+ return (await getTree(code, type)).comments.map((comment) => ({
16
+ value: comment.value,
17
+ start: comment.start,
18
+ end: comment.end
19
+ }));
20
+ }
11
21
  function getPackage(importSpec) {
12
22
  let packageSpec = importSpec;
13
23
  if (packageSpec.startsWith("npm:")) packageSpec = packageSpec.slice(4);
@@ -15,7 +25,7 @@ function getPackage(importSpec) {
15
25
  return packageSpec.split("/")[0];
16
26
  }
17
27
  async function getImports(code, filename, type) {
18
- const ast = await parse(filename, code, { lang: type });
28
+ const ast = await getTree(code, type, filename);
19
29
  return [...ast.module.dynamicImports.map((d) => {
20
30
  const packageSpec = getPackage(code.slice(d.moduleRequest.start, d.moduleRequest.end).replaceAll(/['"]/g, ""));
21
31
  return {
@@ -55,5 +65,5 @@ async function createEnvironment(code, imports, env, options = { installCommand:
55
65
  }
56
66
 
57
67
  //#endregion
58
- export { createEnvironment, getEntryPath, getImports };
68
+ export { createEnvironment, getComments, getEntryPath, getImports };
59
69
  //# sourceMappingURL=utils.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.mjs","names":["manifest"],"sources":["../../../src/adapters/javascript/utils.ts"],"sourcesContent":["import { parse } from \"oxc-parser\";\nimport { tmpdir } from \"os\";\nimport { mkdir, writeFile } from \"fs/promises\";\nimport manifest from \"~/assets/package.json\";\nimport { join } from \"path\";\nimport { randomUUID } from \"crypto\";\nimport { isBuiltin } from \"module\";\nimport { cleanupEnvironment, execUntilExit, logger } from \"@/utils\";\n\ntype Import = {\n isExternal: boolean;\n package: string;\n};\n\nfunction getPackage(importSpec: string): string {\n let packageSpec = importSpec;\n // Deno environment\n if (packageSpec.startsWith(\"npm:\")) {\n packageSpec = packageSpec.slice(4);\n }\n if (packageSpec.startsWith(\"@\")) {\n return packageSpec.split(\"/\").slice(0, 2).join(\"/\");\n }\n return packageSpec.split(\"/\")[0];\n}\n\nasync function getImports(code: string, filename: string, type: JavaScriptType): Promise<Import[]> {\n const ast = await parse(filename, code, {\n lang: type,\n });\n return [\n ...ast.module.dynamicImports.map((d) => {\n const packageSpec = getPackage(\n code.slice(d.moduleRequest.start, d.moduleRequest.end).replaceAll(/['\"]/g, \"\"),\n );\n return { package: packageSpec, isExternal: !isBuiltin(packageSpec) };\n }),\n ...ast.module.staticImports.map((s) => ({\n package: getPackage(s.moduleRequest.value),\n isExternal: !isBuiltin(s.moduleRequest.value),\n })),\n ];\n}\n\ntype EnvironmentOptions = {\n environmentPath?: string;\n installCommand: string[];\n};\n\nfunction getEntryPath(environmentPath: string) {\n return `${environmentPath}/dist/index.js`;\n}\n\nasync function createEnvironment(\n code: string,\n imports: Import[],\n env: string | undefined,\n options: EnvironmentOptions = {\n installCommand: [\"npm\", \"install\"],\n },\n) {\n logger.info(\n \"Creating environment with imports\",\n imports.map((i) => i.package),\n );\n if (options.environmentPath) {\n logger.info(\"Using explicit environment at\", options.environmentPath);\n await mkdir(`${options.environmentPath}/dist`, { recursive: true });\n await writeFile(`${options.environmentPath}/dist/index.js`, code);\n return options.environmentPath;\n }\n\n const path = join(tmpdir(), \"docval\", randomUUID());\n await mkdir(`${path}/dist`, { recursive: true });\n await Promise.all([\n writeFile(`${path}/package.json`, JSON.stringify(manifest)),\n writeFile(`${path}/dist/index.js`, code),\n env ? writeFile(`${path}/.env`, env) : Promise.resolve(),\n ]);\n logger.info(\"Created environment at\", path);\n const cmd = options.installCommand\n .concat(imports.filter((i) => i.isExternal).map((i) => i.package))\n .join(\" \");\n if (imports.length > 0) {\n logger.info(\"Installing dependencies with command:\", cmd);\n await execUntilExit(cmd, path);\n }\n return path;\n}\n\ntype JavaScriptType = \"js\" | \"ts\" | \"tsx\" | \"jsx\";\n\nexport type { JavaScriptType };\nexport { getImports, createEnvironment, cleanupEnvironment, execUntilExit, getEntryPath };\n"],"mappings":";;;;;;;;;;AAcA,SAAS,WAAW,YAA4B;CAC9C,IAAI,cAAc;AAElB,KAAI,YAAY,WAAW,OAAO,CAChC,eAAc,YAAY,MAAM,EAAE;AAEpC,KAAI,YAAY,WAAW,IAAI,CAC7B,QAAO,YAAY,MAAM,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC,KAAK,IAAI;AAErD,QAAO,YAAY,MAAM,IAAI,CAAC;;AAGhC,eAAe,WAAW,MAAc,UAAkB,MAAyC;CACjG,MAAM,MAAM,MAAM,MAAM,UAAU,MAAM,EACtC,MAAM,MACP,CAAC;AACF,QAAO,CACL,GAAG,IAAI,OAAO,eAAe,KAAK,MAAM;EACtC,MAAM,cAAc,WAClB,KAAK,MAAM,EAAE,cAAc,OAAO,EAAE,cAAc,IAAI,CAAC,WAAW,SAAS,GAAG,CAC/E;AACD,SAAO;GAAE,SAAS;GAAa,YAAY,CAAC,UAAU,YAAY;GAAE;GACpE,EACF,GAAG,IAAI,OAAO,cAAc,KAAK,OAAO;EACtC,SAAS,WAAW,EAAE,cAAc,MAAM;EAC1C,YAAY,CAAC,UAAU,EAAE,cAAc,MAAM;EAC9C,EAAE,CACJ;;AAQH,SAAS,aAAa,iBAAyB;AAC7C,QAAO,GAAG,gBAAgB;;AAG5B,eAAe,kBACb,MACA,SACA,KACA,UAA8B,EAC5B,gBAAgB,CAAC,OAAO,UAAU,EACnC,EACD;AACA,QAAO,KACL,qCACA,QAAQ,KAAK,MAAM,EAAE,QAAQ,CAC9B;AACD,KAAI,QAAQ,iBAAiB;AAC3B,SAAO,KAAK,iCAAiC,QAAQ,gBAAgB;AACrE,QAAM,MAAM,GAAG,QAAQ,gBAAgB,QAAQ,EAAE,WAAW,MAAM,CAAC;AACnE,QAAM,UAAU,GAAG,QAAQ,gBAAgB,iBAAiB,KAAK;AACjE,SAAO,QAAQ;;CAGjB,MAAM,OAAO,KAAK,QAAQ,EAAE,UAAU,YAAY,CAAC;AACnD,OAAM,MAAM,GAAG,KAAK,QAAQ,EAAE,WAAW,MAAM,CAAC;AAChD,OAAM,QAAQ,IAAI;EAChB,UAAU,GAAG,KAAK,gBAAgB,KAAK,UAAUA,gBAAS,CAAC;EAC3D,UAAU,GAAG,KAAK,iBAAiB,KAAK;EACxC,MAAM,UAAU,GAAG,KAAK,QAAQ,IAAI,GAAG,QAAQ,SAAS;EACzD,CAAC;AACF,QAAO,KAAK,0BAA0B,KAAK;CAC3C,MAAM,MAAM,QAAQ,eACjB,OAAO,QAAQ,QAAQ,MAAM,EAAE,WAAW,CAAC,KAAK,MAAM,EAAE,QAAQ,CAAC,CACjE,KAAK,IAAI;AACZ,KAAI,QAAQ,SAAS,GAAG;AACtB,SAAO,KAAK,yCAAyC,IAAI;AACzD,QAAM,cAAc,KAAK,KAAK;;AAEhC,QAAO"}
1
+ {"version":3,"file":"utils.mjs","names":["manifest"],"sources":["../../../src/adapters/javascript/utils.ts"],"sourcesContent":["import { parse } from \"oxc-parser\";\nimport { tmpdir } from \"os\";\nimport { mkdir, writeFile } from \"fs/promises\";\nimport manifest from \"~/assets/package.json\";\nimport { join } from \"path\";\nimport { randomUUID } from \"crypto\";\nimport { isBuiltin } from \"module\";\nimport { cleanupEnvironment, execUntilExit, logger } from \"@/utils\";\nimport type { Comment } from \"@/utils\";\n\ntype Import = {\n isExternal: boolean;\n package: string;\n};\n\nfunction getTree(code: string, type: JavaScriptType, filename?: string) {\n return parse(filename ?? \"unknown\", code, {\n lang: type,\n });\n}\n\nasync function getComments(code: string, type: JavaScriptType): Promise<Comment[]> {\n const ast = await getTree(code, type);\n return ast.comments.map((comment) => ({\n value: comment.value,\n start: comment.start,\n end: comment.end,\n }));\n}\n\nfunction getPackage(importSpec: string): string {\n let packageSpec = importSpec;\n // Deno environment\n if (packageSpec.startsWith(\"npm:\")) {\n packageSpec = packageSpec.slice(4);\n }\n if (packageSpec.startsWith(\"@\")) {\n return packageSpec.split(\"/\").slice(0, 2).join(\"/\");\n }\n return packageSpec.split(\"/\")[0];\n}\n\nasync function getImports(code: string, filename: string, type: JavaScriptType): Promise<Import[]> {\n const ast = await getTree(code, type, filename);\n return [\n ...ast.module.dynamicImports.map((d) => {\n const packageSpec = getPackage(\n code.slice(d.moduleRequest.start, d.moduleRequest.end).replaceAll(/['\"]/g, \"\"),\n );\n return { package: packageSpec, isExternal: !isBuiltin(packageSpec) };\n }),\n ...ast.module.staticImports.map((s) => ({\n package: getPackage(s.moduleRequest.value),\n isExternal: !isBuiltin(s.moduleRequest.value),\n })),\n ];\n}\n\ntype EnvironmentOptions = {\n environmentPath?: string;\n installCommand: string[];\n};\n\nfunction getEntryPath(environmentPath: string) {\n return `${environmentPath}/dist/index.js`;\n}\n\nasync function createEnvironment(\n code: string,\n imports: Import[],\n env: string | undefined,\n options: EnvironmentOptions = {\n installCommand: [\"npm\", \"install\"],\n },\n) {\n logger.info(\n \"Creating environment with imports\",\n imports.map((i) => i.package),\n );\n if (options.environmentPath) {\n logger.info(\"Using explicit environment at\", options.environmentPath);\n await mkdir(`${options.environmentPath}/dist`, { recursive: true });\n await writeFile(`${options.environmentPath}/dist/index.js`, code);\n return options.environmentPath;\n }\n\n const path = join(tmpdir(), \"docval\", randomUUID());\n await mkdir(`${path}/dist`, { recursive: true });\n await Promise.all([\n writeFile(`${path}/package.json`, JSON.stringify(manifest)),\n writeFile(`${path}/dist/index.js`, code),\n env ? writeFile(`${path}/.env`, env) : Promise.resolve(),\n ]);\n logger.info(\"Created environment at\", path);\n const cmd = options.installCommand\n .concat(imports.filter((i) => i.isExternal).map((i) => i.package))\n .join(\" \");\n if (imports.length > 0) {\n logger.info(\"Installing dependencies with command:\", cmd);\n await execUntilExit(cmd, path);\n }\n return path;\n}\n\ntype JavaScriptType = \"js\" | \"ts\" | \"tsx\" | \"jsx\";\n\nexport type { JavaScriptType };\nexport {\n getImports,\n createEnvironment,\n cleanupEnvironment,\n execUntilExit,\n getEntryPath,\n getComments,\n};\n"],"mappings":";;;;;;;;;;AAeA,SAAS,QAAQ,MAAc,MAAsB,UAAmB;AACtE,QAAO,MAAM,YAAY,WAAW,MAAM,EACxC,MAAM,MACP,CAAC;;AAGJ,eAAe,YAAY,MAAc,MAA0C;AAEjF,SADY,MAAM,QAAQ,MAAM,KAAK,EAC1B,SAAS,KAAK,aAAa;EACpC,OAAO,QAAQ;EACf,OAAO,QAAQ;EACf,KAAK,QAAQ;EACd,EAAE;;AAGL,SAAS,WAAW,YAA4B;CAC9C,IAAI,cAAc;AAElB,KAAI,YAAY,WAAW,OAAO,CAChC,eAAc,YAAY,MAAM,EAAE;AAEpC,KAAI,YAAY,WAAW,IAAI,CAC7B,QAAO,YAAY,MAAM,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC,KAAK,IAAI;AAErD,QAAO,YAAY,MAAM,IAAI,CAAC;;AAGhC,eAAe,WAAW,MAAc,UAAkB,MAAyC;CACjG,MAAM,MAAM,MAAM,QAAQ,MAAM,MAAM,SAAS;AAC/C,QAAO,CACL,GAAG,IAAI,OAAO,eAAe,KAAK,MAAM;EACtC,MAAM,cAAc,WAClB,KAAK,MAAM,EAAE,cAAc,OAAO,EAAE,cAAc,IAAI,CAAC,WAAW,SAAS,GAAG,CAC/E;AACD,SAAO;GAAE,SAAS;GAAa,YAAY,CAAC,UAAU,YAAY;GAAE;GACpE,EACF,GAAG,IAAI,OAAO,cAAc,KAAK,OAAO;EACtC,SAAS,WAAW,EAAE,cAAc,MAAM;EAC1C,YAAY,CAAC,UAAU,EAAE,cAAc,MAAM;EAC9C,EAAE,CACJ;;AAQH,SAAS,aAAa,iBAAyB;AAC7C,QAAO,GAAG,gBAAgB;;AAG5B,eAAe,kBACb,MACA,SACA,KACA,UAA8B,EAC5B,gBAAgB,CAAC,OAAO,UAAU,EACnC,EACD;AACA,QAAO,KACL,qCACA,QAAQ,KAAK,MAAM,EAAE,QAAQ,CAC9B;AACD,KAAI,QAAQ,iBAAiB;AAC3B,SAAO,KAAK,iCAAiC,QAAQ,gBAAgB;AACrE,QAAM,MAAM,GAAG,QAAQ,gBAAgB,QAAQ,EAAE,WAAW,MAAM,CAAC;AACnE,QAAM,UAAU,GAAG,QAAQ,gBAAgB,iBAAiB,KAAK;AACjE,SAAO,QAAQ;;CAGjB,MAAM,OAAO,KAAK,QAAQ,EAAE,UAAU,YAAY,CAAC;AACnD,OAAM,MAAM,GAAG,KAAK,QAAQ,EAAE,WAAW,MAAM,CAAC;AAChD,OAAM,QAAQ,IAAI;EAChB,UAAU,GAAG,KAAK,gBAAgB,KAAK,UAAUA,gBAAS,CAAC;EAC3D,UAAU,GAAG,KAAK,iBAAiB,KAAK;EACxC,MAAM,UAAU,GAAG,KAAK,QAAQ,IAAI,GAAG,QAAQ,SAAS;EACzD,CAAC;AACF,QAAO,KAAK,0BAA0B,KAAK;CAC3C,MAAM,MAAM,QAAQ,eACjB,OAAO,QAAQ,QAAQ,MAAM,EAAE,WAAW,CAAC,KAAK,MAAM,EAAE,QAAQ,CAAC,CACjE,KAAK,IAAI;AACZ,KAAI,QAAQ,SAAS,GAAG;AACtB,SAAO,KAAK,yCAAyC,IAAI;AACzD,QAAM,cAAc,KAAK,KAAK;;AAEhC,QAAO"}
@@ -1,13 +1,13 @@
1
1
  import { getOptions } from "../../remark/utils.mjs";
2
- import { cleanupEnvironment, execUntilExit } from "../../utils.mjs";
3
2
  import { createEnvironment, getImports } from "./utils.mjs";
3
+ import { cleanupEnvironment, execUntilExit } from "../../utils.mjs";
4
4
  import { ADAPTER_OPTIONS } from "./constants.mjs";
5
5
 
6
6
  //#region src/adapters/rust/index.ts
7
7
  async function adapterRust(code, options) {
8
8
  const environmentPath = await createEnvironment(code, await getImports(code), { environmentPath: options.environment });
9
9
  try {
10
- await execUntilExit("cargo run", environmentPath);
10
+ await execUntilExit(`cargo run`, environmentPath);
11
11
  } finally {
12
12
  if (!options.environment) await cleanupEnvironment(environmentPath);
13
13
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/adapters/rust/index.ts"],"sourcesContent":["import { getOptions } from \"@/remark/utils\";\nimport { createEnvironment, getImports } from \"./utils\";\nimport { ADAPTER_OPTIONS } from \"./constants\";\nimport { cleanupEnvironment, execUntilExit } from \"@/utils\";\n\ntype AdapterOptions = {\n environment?: string;\n};\n\nasync function adapterRust(code: string, options: AdapterOptions): Promise<void> {\n const imports = await getImports(code);\n const environmentPath = await createEnvironment(code, imports, {\n environmentPath: options.environment,\n });\n\n try {\n await execUntilExit(\"cargo run\", environmentPath);\n } finally {\n if (!options.environment) {\n await cleanupEnvironment(environmentPath);\n }\n }\n}\n\nexport default (code: string, metadata: string[]) =>\n adapterRust(code, getOptions(metadata, ADAPTER_OPTIONS));\n"],"mappings":";;;;;;AASA,eAAe,YAAY,MAAc,SAAwC;CAE/E,MAAM,kBAAkB,MAAM,kBAAkB,MADhC,MAAM,WAAW,KAAK,EACyB,EAC7D,iBAAiB,QAAQ,aAC1B,CAAC;AAEF,KAAI;AACF,QAAM,cAAc,aAAa,gBAAgB;WACzC;AACR,MAAI,CAAC,QAAQ,YACX,OAAM,mBAAmB,gBAAgB;;;AAK/C,oBAAgB,MAAc,aAC5B,YAAY,MAAM,WAAW,UAAU,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../../src/adapters/rust/index.ts"],"sourcesContent":["import { getOptions } from \"@/remark/utils\";\nimport { createEnvironment, getImports } from \"./utils\";\nimport { ADAPTER_OPTIONS } from \"./constants\";\nimport { cleanupEnvironment, execUntilExit } from \"@/utils\";\n\ntype AdapterOptions = {\n environment?: string;\n};\n\nasync function adapterRust(code: string, options: AdapterOptions): Promise<void> {\n const imports = await getImports(code);\n const environmentPath = await createEnvironment(code, imports, {\n environmentPath: options.environment,\n });\n\n try {\n await execUntilExit(`cargo run`, environmentPath);\n } finally {\n if (!options.environment) {\n await cleanupEnvironment(environmentPath);\n }\n }\n}\n\nexport default (code: string, metadata: string[]) =>\n adapterRust(code, getOptions(metadata, ADAPTER_OPTIONS));\n"],"mappings":";;;;;;AASA,eAAe,YAAY,MAAc,SAAwC;CAE/E,MAAM,kBAAkB,MAAM,kBAAkB,MADhC,MAAM,WAAW,KAAK,EACyB,EAC7D,iBAAiB,QAAQ,aAC1B,CAAC;AAEF,KAAI;AACF,QAAM,cAAc,aAAa,gBAAgB;WACzC;AACR,MAAI,CAAC,QAAQ,YACX,OAAM,mBAAmB,gBAAgB;;;AAK/C,oBAAgB,MAAc,aAC5B,YAAY,MAAM,WAAW,UAAU,gBAAgB,CAAC"}
@@ -1,4 +1,4 @@
1
- import { execUntilExit, logger } from "../../utils.mjs";
1
+ import { execUntilExit, getDirectives, logger } from "../../utils.mjs";
2
2
  import { randomUUID } from "crypto";
3
3
  import { tmpdir } from "os";
4
4
  import { mkdir, readFile, writeFile } from "fs/promises";
@@ -27,12 +27,33 @@ const ERROR_CRATES = new Set([
27
27
  "super",
28
28
  "self"
29
29
  ]);
30
- async function getImports(code) {
30
+ async function getTree(code) {
31
31
  const language = await getRustLanguage();
32
32
  const parser = new Parser();
33
33
  parser.setLanguage(language);
34
- const tree = parser.parse(code);
34
+ return parser.parse(code);
35
+ }
36
+ async function getComments(input) {
37
+ const tree = typeof input === "string" ? await getTree(input) : input;
38
+ return tree ? tree.rootNode.descendantsOfType("line_comment").map((comment) => ({
39
+ value: comment.text,
40
+ start: comment.startIndex,
41
+ end: comment.endIndex
42
+ })) : [];
43
+ }
44
+ async function getImports(code) {
45
+ const tree = await getTree(code);
46
+ const directives = await getDirectives(code, "rust");
35
47
  const imports = [];
48
+ for (const directive of directives["cargo-add-options"] ?? []) {
49
+ const [packageSpec, ...options] = directive.args;
50
+ if (!packageSpec) continue;
51
+ imports.push({
52
+ package: packageSpec,
53
+ cargoAddOptions: options.join(" "),
54
+ isExternal: true
55
+ });
56
+ }
36
57
  for (const node of tree.rootNode.children) {
37
58
  let crateName;
38
59
  if (node.type === "use_declaration") {
@@ -42,6 +63,7 @@ async function getImports(code) {
42
63
  }
43
64
  if (crateName) {
44
65
  if (ERROR_CRATES.has(crateName)) throw new Error(`Unsupported import of "${crateName}". Imports of ${Array.from(ERROR_CRATES).map((c) => `"${c}"`).join(", ")} are not supported.`);
66
+ if (imports.some((i) => i.package === crateName)) continue;
45
67
  imports.push({
46
68
  package: crateName,
47
69
  isExternal: !BUILTIN_CRATES.has(crateName)
@@ -66,14 +88,14 @@ async function createEnvironment(code, imports, options = {}) {
66
88
  await mkdir(`${path}/src`, { recursive: true });
67
89
  await Promise.all([writeFile(`${path}/Cargo.toml`, manifest), writeFile(`${path}/src/main.rs`, code)]);
68
90
  if (imports.length > 0) {
69
- const crates = imports.filter((i) => i.isExternal).map((i) => i.package);
91
+ const crates = imports.filter((i) => i.isExternal);
70
92
  logger.info("Installing crates", crates);
71
- await execUntilExit(`cargo add ${crates.join(" ")}`, path);
93
+ for (const crate of crates) await execUntilExit(`cargo add ${crate.package}${crate.cargoAddOptions ? ` ${crate.cargoAddOptions}` : ""}`, path);
72
94
  }
73
95
  logger.info("Created Rust environment at", path);
74
96
  return path;
75
97
  }
76
98
 
77
99
  //#endregion
78
- export { createEnvironment, getImports };
100
+ export { createEnvironment, getComments, getImports };
79
101
  //# sourceMappingURL=utils.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.mjs","names":[],"sources":["../../../src/adapters/rust/utils.ts"],"sourcesContent":["import { Language, Parser } from \"web-tree-sitter\";\nimport { createRequire } from \"module\";\nimport { tmpdir } from \"os\";\nimport { mkdir, readFile, writeFile } from \"fs/promises\";\nimport { join } from \"path\";\nimport { randomUUID } from \"crypto\";\nimport { execUntilExit, logger } from \"@/utils\";\n\nconst require = createRequire(import.meta.url);\nconst RUST_WASM_PATH = require.resolve(\"tree-sitter-rust/tree-sitter-rust.wasm\");\n\nlet rustLanguage: Language | undefined;\n\nasync function getRustLanguage(): Promise<Language> {\n if (!rustLanguage) {\n await Parser.init();\n rustLanguage = await Language.load(RUST_WASM_PATH);\n }\n return rustLanguage!;\n}\n\nconst BUILTIN_CRATES = new Set([\"std\", \"core\", \"alloc\", \"crate\"]);\nconst ERROR_CRATES = new Set([\"crate\", \"super\", \"self\"]);\n\ntype Import = {\n isExternal: boolean;\n package: string;\n};\n\nasync function getImports(code: string): Promise<Import[]> {\n const language = await getRustLanguage();\n const parser = new Parser();\n parser.setLanguage(language);\n const tree = parser.parse(code);\n const imports: Import[] = [];\n\n for (const node of tree!.rootNode.children) {\n let crateName: string | undefined;\n\n if (node.type === \"use_declaration\") {\n const arg = node.child(1);\n if (!arg) continue;\n if (arg.type === \"identifier\" || arg.type === \"scoped_identifier\") {\n crateName = arg.text.split(\"::\")[0];\n }\n }\n\n if (crateName) {\n if (ERROR_CRATES.has(crateName)) {\n throw new Error(\n `Unsupported import of \"${crateName}\". ` +\n `Imports of ${Array.from(ERROR_CRATES)\n .map((c) => `\"${c}\"`)\n .join(\", \")} are not supported.`,\n );\n }\n\n imports.push({\n package: crateName,\n isExternal: !BUILTIN_CRATES.has(crateName),\n });\n }\n }\n\n return imports;\n}\n\ntype EnvironmentOptions = {\n environmentPath?: string;\n};\n\nfunction getEntryPath(environmentPath: string) {\n return `${environmentPath}/src/main.rs`;\n}\n\nasync function createEnvironment(\n code: string,\n imports: Import[],\n options: EnvironmentOptions = {},\n) {\n logger.info(\n \"Creating Rust environment with crates\",\n imports.map((i) => i.package),\n );\n\n if (options.environmentPath) {\n logger.info(\"Using explicit environment at\", options.environmentPath);\n await mkdir(`${options.environmentPath}/src`, { recursive: true });\n await writeFile(getEntryPath(options.environmentPath), code);\n return options.environmentPath;\n }\n\n const manifest = await readFile(new URL(\"../../../assets/Cargo.toml\", import.meta.url), \"utf-8\");\n const path = join(tmpdir(), \"docval\", randomUUID());\n await mkdir(`${path}/src`, { recursive: true });\n await Promise.all([\n writeFile(`${path}/Cargo.toml`, manifest),\n writeFile(`${path}/src/main.rs`, code),\n ]);\n if (imports.length > 0) {\n const crates = imports.filter((i) => i.isExternal).map((i) => i.package);\n logger.info(\"Installing crates\", crates);\n await execUntilExit(`cargo add ${crates.join(\" \")}`, path);\n }\n logger.info(\"Created Rust environment at\", path);\n return path;\n}\n\nexport { getImports, createEnvironment, getEntryPath };\nexport type { Import };\n"],"mappings":";;;;;;;;;AASA,MAAM,iBADU,cAAc,OAAO,KAAK,IAAI,CACf,QAAQ,yCAAyC;AAEhF,IAAI;AAEJ,eAAe,kBAAqC;AAClD,KAAI,CAAC,cAAc;AACjB,QAAM,OAAO,MAAM;AACnB,iBAAe,MAAM,SAAS,KAAK,eAAe;;AAEpD,QAAO;;AAGT,MAAM,iBAAiB,IAAI,IAAI;CAAC;CAAO;CAAQ;CAAS;CAAQ,CAAC;AACjE,MAAM,eAAe,IAAI,IAAI;CAAC;CAAS;CAAS;CAAO,CAAC;AAOxD,eAAe,WAAW,MAAiC;CACzD,MAAM,WAAW,MAAM,iBAAiB;CACxC,MAAM,SAAS,IAAI,QAAQ;AAC3B,QAAO,YAAY,SAAS;CAC5B,MAAM,OAAO,OAAO,MAAM,KAAK;CAC/B,MAAM,UAAoB,EAAE;AAE5B,MAAK,MAAM,QAAQ,KAAM,SAAS,UAAU;EAC1C,IAAI;AAEJ,MAAI,KAAK,SAAS,mBAAmB;GACnC,MAAM,MAAM,KAAK,MAAM,EAAE;AACzB,OAAI,CAAC,IAAK;AACV,OAAI,IAAI,SAAS,gBAAgB,IAAI,SAAS,oBAC5C,aAAY,IAAI,KAAK,MAAM,KAAK,CAAC;;AAIrC,MAAI,WAAW;AACb,OAAI,aAAa,IAAI,UAAU,CAC7B,OAAM,IAAI,MACR,0BAA0B,UAAU,gBACpB,MAAM,KAAK,aAAa,CACnC,KAAK,MAAM,IAAI,EAAE,GAAG,CACpB,KAAK,KAAK,CAAC,qBACjB;AAGH,WAAQ,KAAK;IACX,SAAS;IACT,YAAY,CAAC,eAAe,IAAI,UAAU;IAC3C,CAAC;;;AAIN,QAAO;;AAOT,SAAS,aAAa,iBAAyB;AAC7C,QAAO,GAAG,gBAAgB;;AAG5B,eAAe,kBACb,MACA,SACA,UAA8B,EAAE,EAChC;AACA,QAAO,KACL,yCACA,QAAQ,KAAK,MAAM,EAAE,QAAQ,CAC9B;AAED,KAAI,QAAQ,iBAAiB;AAC3B,SAAO,KAAK,iCAAiC,QAAQ,gBAAgB;AACrE,QAAM,MAAM,GAAG,QAAQ,gBAAgB,OAAO,EAAE,WAAW,MAAM,CAAC;AAClE,QAAM,UAAU,aAAa,QAAQ,gBAAgB,EAAE,KAAK;AAC5D,SAAO,QAAQ;;CAGjB,MAAM,WAAW,MAAM,SAAS,IAAI,IAAI,8BAA8B,OAAO,KAAK,IAAI,EAAE,QAAQ;CAChG,MAAM,OAAO,KAAK,QAAQ,EAAE,UAAU,YAAY,CAAC;AACnD,OAAM,MAAM,GAAG,KAAK,OAAO,EAAE,WAAW,MAAM,CAAC;AAC/C,OAAM,QAAQ,IAAI,CAChB,UAAU,GAAG,KAAK,cAAc,SAAS,EACzC,UAAU,GAAG,KAAK,eAAe,KAAK,CACvC,CAAC;AACF,KAAI,QAAQ,SAAS,GAAG;EACtB,MAAM,SAAS,QAAQ,QAAQ,MAAM,EAAE,WAAW,CAAC,KAAK,MAAM,EAAE,QAAQ;AACxE,SAAO,KAAK,qBAAqB,OAAO;AACxC,QAAM,cAAc,aAAa,OAAO,KAAK,IAAI,IAAI,KAAK;;AAE5D,QAAO,KAAK,+BAA+B,KAAK;AAChD,QAAO"}
1
+ {"version":3,"file":"utils.mjs","names":[],"sources":["../../../src/adapters/rust/utils.ts"],"sourcesContent":["import { Language, Parser, Tree } from \"web-tree-sitter\";\nimport { createRequire } from \"module\";\nimport { tmpdir } from \"os\";\nimport { mkdir, readFile, writeFile } from \"fs/promises\";\nimport { join } from \"path\";\nimport { randomUUID } from \"crypto\";\nimport { execUntilExit, logger, getDirectives } from \"@/utils\";\nimport type { Comment } from \"@/utils\";\n\nconst require = createRequire(import.meta.url);\nconst RUST_WASM_PATH = require.resolve(\"tree-sitter-rust/tree-sitter-rust.wasm\");\n\nlet rustLanguage: Language | undefined;\n\nasync function getRustLanguage(): Promise<Language> {\n if (!rustLanguage) {\n await Parser.init();\n rustLanguage = await Language.load(RUST_WASM_PATH);\n }\n return rustLanguage!;\n}\n\nconst BUILTIN_CRATES = new Set([\"std\", \"core\", \"alloc\", \"crate\"]);\nconst ERROR_CRATES = new Set([\"crate\", \"super\", \"self\"]);\n\ntype Import = {\n isExternal: boolean;\n package: string;\n cargoAddOptions?: string;\n};\n\nasync function getTree(code: string): Promise<Tree | null> {\n const language = await getRustLanguage();\n const parser = new Parser();\n parser.setLanguage(language);\n return parser.parse(code);\n}\n\nasync function getComments(input: string | Tree): Promise<Comment[]> {\n const tree = typeof input === \"string\" ? await getTree(input) : input;\n return tree\n ? tree.rootNode.descendantsOfType(\"line_comment\").map((comment) => ({\n value: comment.text,\n start: comment.startIndex,\n end: comment.endIndex,\n }))\n : [];\n}\n\nasync function getImports(code: string): Promise<Import[]> {\n const tree = await getTree(code);\n const directives = await getDirectives(code, \"rust\");\n const imports: Import[] = [];\n\n for (const directive of directives[\"cargo-add-options\"] ?? []) {\n const [packageSpec, ...options] = directive.args;\n if (!packageSpec) {\n continue;\n }\n\n imports.push({ package: packageSpec, cargoAddOptions: options.join(\" \"), isExternal: true });\n }\n\n for (const node of tree!.rootNode.children) {\n let crateName: string | undefined;\n\n if (node.type === \"use_declaration\") {\n const arg = node.child(1);\n if (!arg) continue;\n if (arg.type === \"identifier\" || arg.type === \"scoped_identifier\") {\n crateName = arg.text.split(\"::\")[0];\n }\n }\n\n if (crateName) {\n if (ERROR_CRATES.has(crateName)) {\n throw new Error(\n `Unsupported import of \"${crateName}\". ` +\n `Imports of ${Array.from(ERROR_CRATES)\n .map((c) => `\"${c}\"`)\n .join(\", \")} are not supported.`,\n );\n }\n if (imports.some((i) => i.package === crateName)) {\n continue;\n }\n\n imports.push({\n package: crateName,\n isExternal: !BUILTIN_CRATES.has(crateName),\n });\n }\n }\n return imports;\n}\n\ntype EnvironmentOptions = {\n environmentPath?: string;\n};\n\ntype Directive = \"cargo-add-options\";\n\nfunction getEntryPath(environmentPath: string) {\n return `${environmentPath}/src/main.rs`;\n}\n\nasync function createEnvironment(\n code: string,\n imports: Import[],\n options: EnvironmentOptions = {},\n) {\n logger.info(\n \"Creating Rust environment with crates\",\n imports.map((i) => i.package),\n );\n\n if (options.environmentPath) {\n logger.info(\"Using explicit environment at\", options.environmentPath);\n await mkdir(`${options.environmentPath}/src`, { recursive: true });\n await writeFile(getEntryPath(options.environmentPath), code);\n return options.environmentPath;\n }\n\n const manifest = await readFile(new URL(\"../../../assets/Cargo.toml\", import.meta.url), \"utf-8\");\n const path = join(tmpdir(), \"docval\", randomUUID());\n await mkdir(`${path}/src`, { recursive: true });\n await Promise.all([\n writeFile(`${path}/Cargo.toml`, manifest),\n writeFile(`${path}/src/main.rs`, code),\n ]);\n if (imports.length > 0) {\n const crates = imports.filter((i) => i.isExternal);\n logger.info(\"Installing crates\", crates);\n for (const crate of crates) {\n await execUntilExit(\n `cargo add ${crate.package}${crate.cargoAddOptions ? ` ${crate.cargoAddOptions}` : \"\"}`,\n path,\n );\n }\n }\n\n logger.info(\"Created Rust environment at\", path);\n return path;\n}\n\nexport { getImports, createEnvironment, getEntryPath, getComments };\nexport type { Import, Directive };\n"],"mappings":";;;;;;;;;AAUA,MAAM,iBADU,cAAc,OAAO,KAAK,IAAI,CACf,QAAQ,yCAAyC;AAEhF,IAAI;AAEJ,eAAe,kBAAqC;AAClD,KAAI,CAAC,cAAc;AACjB,QAAM,OAAO,MAAM;AACnB,iBAAe,MAAM,SAAS,KAAK,eAAe;;AAEpD,QAAO;;AAGT,MAAM,iBAAiB,IAAI,IAAI;CAAC;CAAO;CAAQ;CAAS;CAAQ,CAAC;AACjE,MAAM,eAAe,IAAI,IAAI;CAAC;CAAS;CAAS;CAAO,CAAC;AAQxD,eAAe,QAAQ,MAAoC;CACzD,MAAM,WAAW,MAAM,iBAAiB;CACxC,MAAM,SAAS,IAAI,QAAQ;AAC3B,QAAO,YAAY,SAAS;AAC5B,QAAO,OAAO,MAAM,KAAK;;AAG3B,eAAe,YAAY,OAA0C;CACnE,MAAM,OAAO,OAAO,UAAU,WAAW,MAAM,QAAQ,MAAM,GAAG;AAChE,QAAO,OACH,KAAK,SAAS,kBAAkB,eAAe,CAAC,KAAK,aAAa;EAChE,OAAO,QAAQ;EACf,OAAO,QAAQ;EACf,KAAK,QAAQ;EACd,EAAE,GACH,EAAE;;AAGR,eAAe,WAAW,MAAiC;CACzD,MAAM,OAAO,MAAM,QAAQ,KAAK;CAChC,MAAM,aAAa,MAAM,cAAc,MAAM,OAAO;CACpD,MAAM,UAAoB,EAAE;AAE5B,MAAK,MAAM,aAAa,WAAW,wBAAwB,EAAE,EAAE;EAC7D,MAAM,CAAC,aAAa,GAAG,WAAW,UAAU;AAC5C,MAAI,CAAC,YACH;AAGF,UAAQ,KAAK;GAAE,SAAS;GAAa,iBAAiB,QAAQ,KAAK,IAAI;GAAE,YAAY;GAAM,CAAC;;AAG9F,MAAK,MAAM,QAAQ,KAAM,SAAS,UAAU;EAC1C,IAAI;AAEJ,MAAI,KAAK,SAAS,mBAAmB;GACnC,MAAM,MAAM,KAAK,MAAM,EAAE;AACzB,OAAI,CAAC,IAAK;AACV,OAAI,IAAI,SAAS,gBAAgB,IAAI,SAAS,oBAC5C,aAAY,IAAI,KAAK,MAAM,KAAK,CAAC;;AAIrC,MAAI,WAAW;AACb,OAAI,aAAa,IAAI,UAAU,CAC7B,OAAM,IAAI,MACR,0BAA0B,UAAU,gBACpB,MAAM,KAAK,aAAa,CACnC,KAAK,MAAM,IAAI,EAAE,GAAG,CACpB,KAAK,KAAK,CAAC,qBACjB;AAEH,OAAI,QAAQ,MAAM,MAAM,EAAE,YAAY,UAAU,CAC9C;AAGF,WAAQ,KAAK;IACX,SAAS;IACT,YAAY,CAAC,eAAe,IAAI,UAAU;IAC3C,CAAC;;;AAGN,QAAO;;AAST,SAAS,aAAa,iBAAyB;AAC7C,QAAO,GAAG,gBAAgB;;AAG5B,eAAe,kBACb,MACA,SACA,UAA8B,EAAE,EAChC;AACA,QAAO,KACL,yCACA,QAAQ,KAAK,MAAM,EAAE,QAAQ,CAC9B;AAED,KAAI,QAAQ,iBAAiB;AAC3B,SAAO,KAAK,iCAAiC,QAAQ,gBAAgB;AACrE,QAAM,MAAM,GAAG,QAAQ,gBAAgB,OAAO,EAAE,WAAW,MAAM,CAAC;AAClE,QAAM,UAAU,aAAa,QAAQ,gBAAgB,EAAE,KAAK;AAC5D,SAAO,QAAQ;;CAGjB,MAAM,WAAW,MAAM,SAAS,IAAI,IAAI,8BAA8B,OAAO,KAAK,IAAI,EAAE,QAAQ;CAChG,MAAM,OAAO,KAAK,QAAQ,EAAE,UAAU,YAAY,CAAC;AACnD,OAAM,MAAM,GAAG,KAAK,OAAO,EAAE,WAAW,MAAM,CAAC;AAC/C,OAAM,QAAQ,IAAI,CAChB,UAAU,GAAG,KAAK,cAAc,SAAS,EACzC,UAAU,GAAG,KAAK,eAAe,KAAK,CACvC,CAAC;AACF,KAAI,QAAQ,SAAS,GAAG;EACtB,MAAM,SAAS,QAAQ,QAAQ,MAAM,EAAE,WAAW;AAClD,SAAO,KAAK,qBAAqB,OAAO;AACxC,OAAK,MAAM,SAAS,OAClB,OAAM,cACJ,aAAa,MAAM,UAAU,MAAM,kBAAkB,IAAI,MAAM,oBAAoB,MACnF,KACD;;AAIL,QAAO,KAAK,+BAA+B,KAAK;AAChD,QAAO"}
@@ -0,0 +1,9 @@
1
+ import { resolve } from "path";
2
+
3
+ //#region src/constants.ts
4
+ const CACHE_DIR = resolve(import.meta.dirname, ".docval", "cache");
5
+ const CONTENT_CACHE_DIR = resolve(CACHE_DIR, "content");
6
+
7
+ //#endregion
8
+ export { CONTENT_CACHE_DIR };
9
+ //# sourceMappingURL=constants.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.mjs","names":[],"sources":["../src/constants.ts"],"sourcesContent":["import { resolve } from \"path\";\n\nconst CACHE_DIR = resolve(import.meta.dirname, \".docval\", \"cache\");\nconst CONTENT_CACHE_DIR = resolve(CACHE_DIR, \"content\");\n\nexport { CACHE_DIR, CONTENT_CACHE_DIR };\n"],"mappings":";;;AAEA,MAAM,YAAY,QAAQ,OAAO,KAAK,SAAS,WAAW,QAAQ;AAClE,MAAM,oBAAoB,QAAQ,WAAW,UAAU"}
@@ -2,11 +2,10 @@ import { Root } from "mdast";
2
2
 
3
3
  //#region src/remark/plugin.d.ts
4
4
  type DocValOptions = {
5
- include?: boolean;
5
+ cache: boolean;
6
+ include: boolean;
6
7
  };
7
- declare function remarkDocval({
8
- include
9
- }?: DocValOptions): (tree: Root) => Promise<Root>;
8
+ declare function remarkDocval(options?: Partial<DocValOptions>): (tree: Root) => Promise<Root>;
10
9
  //#endregion
11
10
  export { remarkDocval };
12
11
  //# sourceMappingURL=plugin.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.mts","names":[],"sources":["../../src/remark/plugin.ts"],"mappings":";;;KAGY,aAAA;EACV,OAAA;AAAA;AAAA,iBAGsB,YAAA,CAAA;EAAe;AAAA,IAAW,aAAA,IAAkB,IAAA,EACrC,IAAA,KAAI,OAAA,CAAA,IAAA"}
1
+ {"version":3,"file":"plugin.d.mts","names":[],"sources":["../../src/remark/plugin.ts"],"mappings":";;;KAQY,aAAA;EACV,KAAA;EACA,OAAA;AAAA;AAAA,iBAUsB,YAAA,CAAa,OAAA,GAAS,OAAA,CAAQ,aAAA,KAA+B,IAAA,EAGtD,IAAA,KAAI,OAAA,CAAA,IAAA"}
@@ -1,22 +1,80 @@
1
+ import { filterHiddenCode, logger } from "../utils.mjs";
1
2
  import map from "../adapters/index.mjs";
3
+ import { CONTENT_CACHE_DIR } from "../constants.mjs";
4
+ import { hash } from "crypto";
5
+ import { readFile, writeFile } from "fs/promises";
6
+ import { existsSync, mkdirSync } from "fs";
2
7
 
3
8
  //#region src/remark/plugin.ts
4
- function remarkDocval({ include } = {}) {
9
+ mkdirSync(CONTENT_CACHE_DIR, { recursive: true });
10
+ const defaultOptions = {
11
+ cache: process.env.CI !== "true" && process.env.NODE_ENV !== "test",
12
+ include: false
13
+ };
14
+ function remarkDocval(options = defaultOptions) {
15
+ const { cache, include } = {
16
+ ...defaultOptions,
17
+ ...options
18
+ };
5
19
  return async function(tree) {
6
20
  const promises = [];
7
- tree.children.forEach((node) => {
21
+ const newTree = structuredClone(tree);
22
+ newTree.children = await Promise.all(tree.children.map(async (node) => {
8
23
  if (node.type === "code" && node.lang && node.lang in map) {
24
+ let newNode = node;
25
+ const lang = node.lang;
26
+ const contentHash = hash("sha1", JSON.stringify([
27
+ node.value,
28
+ lang,
29
+ node.meta
30
+ ]));
31
+ if (cache) {
32
+ const [success, originalResults] = await readFile(`${CONTENT_CACHE_DIR}/${contentHash}.txt`, { encoding: "utf-8" }).then((content) => {
33
+ const [success, results] = content.split("\n");
34
+ if (!["true", "false"].includes(success)) return [null, null];
35
+ return [success === "true", JSON.parse(results ?? "null")];
36
+ }).catch(() => [null, null]);
37
+ if (typeof success === "boolean") {
38
+ logger.debug("Result found in cache, skipping validation");
39
+ if (!success) throw JSON.stringify({
40
+ message: "One or more code blocks failed validation.",
41
+ originalResults
42
+ });
43
+ else return node;
44
+ }
45
+ }
9
46
  const metadata = node.meta?.split(" ") ?? [];
10
47
  const docValIndex = metadata.findIndex((item) => item === "docval");
11
- if (include || docValIndex !== -1) promises.push(map[node.lang](node.value, metadata));
48
+ const noDocValIndex = metadata.findIndex((item) => item === "no-docval");
49
+ if (include && noDocValIndex === -1 || docValIndex !== -1) promises.push((async () => {
50
+ try {
51
+ return {
52
+ result: await map[lang](node.value, metadata),
53
+ contentHash
54
+ };
55
+ } catch (err) {
56
+ throw {
57
+ result: err,
58
+ contentHash
59
+ };
60
+ }
61
+ })());
62
+ newNode.value = await filterHiddenCode(node.value, lang);
63
+ return newNode;
12
64
  } else if (node.type === "code" && process.env.DOCVAL_TEST_NO_SKIP === "true") throw new Error(`Skipped code block: ${JSON.stringify(node)}`);
13
- });
65
+ return node;
66
+ }));
14
67
  const res = await Promise.allSettled(promises);
68
+ if (cache) await Promise.all(res.map(async (r) => {
69
+ const path = (hash) => `${CONTENT_CACHE_DIR}/${hash}.txt`;
70
+ if (r.status === "rejected" && !existsSync(path(r.reason.contentHash))) await writeFile(`${CONTENT_CACHE_DIR}/${r.reason.contentHash}.txt`, `false\n${JSON.stringify(r.reason)}`);
71
+ else if (r.status === "fulfilled" && !existsSync(path(r.value.contentHash))) await writeFile(`${CONTENT_CACHE_DIR}/${r.value.contentHash}.txt`, "true");
72
+ }));
15
73
  if (res.some((r) => r.status === "rejected")) throw JSON.stringify({
16
74
  message: "One or more code blocks failed validation.",
17
75
  originalResults: res
18
76
  });
19
- return tree;
77
+ return newTree;
20
78
  };
21
79
  }
22
80
 
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.mjs","names":["adapters"],"sources":["../../src/remark/plugin.ts"],"sourcesContent":["import adapters from \"@/adapters\";\nimport type { Root } from \"mdast\";\n\nexport type DocValOptions = {\n include?: boolean;\n};\n\nexport default function remarkDocval({ include }: DocValOptions = {}) {\n return async function (tree: Root) {\n const promises: Promise<void>[] = [];\n tree.children.forEach((node) => {\n if (node.type === \"code\" && node.lang && node.lang in adapters) {\n const metadata = node.meta?.split(\" \") ?? [];\n const docValIndex = metadata.findIndex((item) => item === \"docval\");\n if (include || docValIndex !== -1) {\n promises.push(adapters[node.lang as keyof typeof adapters](node.value, metadata));\n }\n } else if (node.type === \"code\" && process.env.DOCVAL_TEST_NO_SKIP === \"true\") {\n throw new Error(`Skipped code block: ${JSON.stringify(node)}`);\n }\n });\n const res = await Promise.allSettled(promises);\n if (res.some((r) => r.status === \"rejected\")) {\n throw JSON.stringify({\n message: \"One or more code blocks failed validation.\",\n originalResults: res,\n });\n }\n\n return tree;\n };\n}\n"],"mappings":";;;AAOA,SAAwB,aAAa,EAAE,YAA2B,EAAE,EAAE;AACpE,QAAO,eAAgB,MAAY;EACjC,MAAM,WAA4B,EAAE;AACpC,OAAK,SAAS,SAAS,SAAS;AAC9B,OAAI,KAAK,SAAS,UAAU,KAAK,QAAQ,KAAK,QAAQA,KAAU;IAC9D,MAAM,WAAW,KAAK,MAAM,MAAM,IAAI,IAAI,EAAE;IAC5C,MAAM,cAAc,SAAS,WAAW,SAAS,SAAS,SAAS;AACnE,QAAI,WAAW,gBAAgB,GAC7B,UAAS,KAAKA,IAAS,KAAK,MAA+B,KAAK,OAAO,SAAS,CAAC;cAE1E,KAAK,SAAS,UAAU,QAAQ,IAAI,wBAAwB,OACrE,OAAM,IAAI,MAAM,uBAAuB,KAAK,UAAU,KAAK,GAAG;IAEhE;EACF,MAAM,MAAM,MAAM,QAAQ,WAAW,SAAS;AAC9C,MAAI,IAAI,MAAM,MAAM,EAAE,WAAW,WAAW,CAC1C,OAAM,KAAK,UAAU;GACnB,SAAS;GACT,iBAAiB;GAClB,CAAC;AAGJ,SAAO"}
1
+ {"version":3,"file":"plugin.mjs","names":["adapters"],"sources":["../../src/remark/plugin.ts"],"sourcesContent":["import adapters, { Language } from \"@/adapters\";\nimport { CONTENT_CACHE_DIR } from \"@/constants\";\nimport { filterHiddenCode, logger } from \"@/utils\";\nimport { hash } from \"crypto\";\nimport { existsSync, mkdirSync } from \"fs\";\nimport { readFile, writeFile } from \"fs/promises\";\nimport type { Root } from \"mdast\";\n\nexport type DocValOptions = {\n cache: boolean;\n include: boolean;\n};\n\nmkdirSync(CONTENT_CACHE_DIR, { recursive: true });\n\nconst defaultOptions: DocValOptions = {\n cache: process.env.CI !== \"true\" && process.env.NODE_ENV !== \"test\",\n include: false,\n};\n\nexport default function remarkDocval(options: Partial<DocValOptions> = defaultOptions) {\n const { cache, include } = { ...defaultOptions, ...options };\n\n return async function (tree: Root) {\n const promises: Promise<{\n result: any;\n contentHash: string;\n }>[] = [];\n const newTree = structuredClone(tree);\n\n newTree.children = await Promise.all(\n tree.children.map(async (node) => {\n if (node.type === \"code\" && node.lang && node.lang in adapters) {\n let newNode = node;\n const lang: Language = node.lang as Language;\n const contentHash = hash(\"sha1\", JSON.stringify([node.value, lang, node.meta]));\n if (cache) {\n const [success, originalResults]: [boolean | null, any] = await readFile(\n `${CONTENT_CACHE_DIR}/${contentHash}.txt`,\n { encoding: \"utf-8\" },\n )\n .then((content) => {\n const [success, results] = content.split(\"\\n\");\n\n if (![\"true\", \"false\"].includes(success)) {\n return [null, null] as [boolean | null, any];\n }\n return [success === \"true\", JSON.parse(results ?? \"null\")] as [boolean, any];\n })\n .catch(() => [null, null]);\n\n if (typeof success === \"boolean\") {\n logger.debug(\"Result found in cache, skipping validation\");\n\n if (!success) {\n throw JSON.stringify({\n message: \"One or more code blocks failed validation.\",\n originalResults: originalResults,\n });\n } else {\n return node;\n }\n }\n }\n\n const metadata = node.meta?.split(\" \") ?? [];\n const docValIndex = metadata.findIndex((item) => item === \"docval\");\n const noDocValIndex = metadata.findIndex((item) => item === \"no-docval\");\n if ((include && noDocValIndex === -1) || docValIndex !== -1) {\n promises.push(\n (async () => {\n try {\n const result = await adapters[lang as keyof typeof adapters](\n node.value,\n metadata,\n );\n return {\n result,\n contentHash,\n };\n } catch (err) {\n throw {\n result: err,\n contentHash,\n };\n }\n })(),\n );\n }\n\n newNode.value = await filterHiddenCode(node.value, lang);\n return newNode;\n } else if (node.type === \"code\" && process.env.DOCVAL_TEST_NO_SKIP === \"true\") {\n throw new Error(`Skipped code block: ${JSON.stringify(node)}`);\n }\n\n return node;\n }),\n );\n const res = await Promise.allSettled(promises);\n\n if (cache) {\n await Promise.all(\n res.map(async (r) => {\n const path = (hash: string) => `${CONTENT_CACHE_DIR}/${hash}.txt`;\n if (r.status === \"rejected\" && !existsSync(path(r.reason.contentHash))) {\n await writeFile(\n `${CONTENT_CACHE_DIR}/${r.reason.contentHash}.txt`,\n `false\\n${JSON.stringify(r.reason)}`,\n );\n } else if (r.status === \"fulfilled\" && !existsSync(path(r.value.contentHash))) {\n await writeFile(`${CONTENT_CACHE_DIR}/${r.value.contentHash}.txt`, \"true\");\n }\n }),\n );\n }\n\n if (res.some((r) => r.status === \"rejected\")) {\n throw JSON.stringify({\n message: \"One or more code blocks failed validation.\",\n originalResults: res,\n });\n }\n\n return newTree;\n };\n}\n"],"mappings":";;;;;;;;AAaA,UAAU,mBAAmB,EAAE,WAAW,MAAM,CAAC;AAEjD,MAAM,iBAAgC;CACpC,OAAO,QAAQ,IAAI,OAAO,UAAU,QAAQ,IAAI,aAAa;CAC7D,SAAS;CACV;AAED,SAAwB,aAAa,UAAkC,gBAAgB;CACrF,MAAM,EAAE,OAAO,YAAY;EAAE,GAAG;EAAgB,GAAG;EAAS;AAE5D,QAAO,eAAgB,MAAY;EACjC,MAAM,WAGC,EAAE;EACT,MAAM,UAAU,gBAAgB,KAAK;AAErC,UAAQ,WAAW,MAAM,QAAQ,IAC/B,KAAK,SAAS,IAAI,OAAO,SAAS;AAChC,OAAI,KAAK,SAAS,UAAU,KAAK,QAAQ,KAAK,QAAQA,KAAU;IAC9D,IAAI,UAAU;IACd,MAAM,OAAiB,KAAK;IAC5B,MAAM,cAAc,KAAK,QAAQ,KAAK,UAAU;KAAC,KAAK;KAAO;KAAM,KAAK;KAAK,CAAC,CAAC;AAC/E,QAAI,OAAO;KACT,MAAM,CAAC,SAAS,mBAA0C,MAAM,SAC9D,GAAG,kBAAkB,GAAG,YAAY,OACpC,EAAE,UAAU,SAAS,CACtB,CACE,MAAM,YAAY;MACjB,MAAM,CAAC,SAAS,WAAW,QAAQ,MAAM,KAAK;AAE9C,UAAI,CAAC,CAAC,QAAQ,QAAQ,CAAC,SAAS,QAAQ,CACtC,QAAO,CAAC,MAAM,KAAK;AAErB,aAAO,CAAC,YAAY,QAAQ,KAAK,MAAM,WAAW,OAAO,CAAC;OAC1D,CACD,YAAY,CAAC,MAAM,KAAK,CAAC;AAE5B,SAAI,OAAO,YAAY,WAAW;AAChC,aAAO,MAAM,6CAA6C;AAE1D,UAAI,CAAC,QACH,OAAM,KAAK,UAAU;OACnB,SAAS;OACQ;OAClB,CAAC;UAEF,QAAO;;;IAKb,MAAM,WAAW,KAAK,MAAM,MAAM,IAAI,IAAI,EAAE;IAC5C,MAAM,cAAc,SAAS,WAAW,SAAS,SAAS,SAAS;IACnE,MAAM,gBAAgB,SAAS,WAAW,SAAS,SAAS,YAAY;AACxE,QAAK,WAAW,kBAAkB,MAAO,gBAAgB,GACvD,UAAS,MACN,YAAY;AACX,SAAI;AAKF,aAAO;OACL,QALa,MAAMA,IAAS,MAC5B,KAAK,OACL,SACD;OAGC;OACD;cACM,KAAK;AACZ,YAAM;OACJ,QAAQ;OACR;OACD;;QAED,CACL;AAGH,YAAQ,QAAQ,MAAM,iBAAiB,KAAK,OAAO,KAAK;AACxD,WAAO;cACE,KAAK,SAAS,UAAU,QAAQ,IAAI,wBAAwB,OACrE,OAAM,IAAI,MAAM,uBAAuB,KAAK,UAAU,KAAK,GAAG;AAGhE,UAAO;IACP,CACH;EACD,MAAM,MAAM,MAAM,QAAQ,WAAW,SAAS;AAE9C,MAAI,MACF,OAAM,QAAQ,IACZ,IAAI,IAAI,OAAO,MAAM;GACnB,MAAM,QAAQ,SAAiB,GAAG,kBAAkB,GAAG,KAAK;AAC5D,OAAI,EAAE,WAAW,cAAc,CAAC,WAAW,KAAK,EAAE,OAAO,YAAY,CAAC,CACpE,OAAM,UACJ,GAAG,kBAAkB,GAAG,EAAE,OAAO,YAAY,OAC7C,UAAU,KAAK,UAAU,EAAE,OAAO,GACnC;YACQ,EAAE,WAAW,eAAe,CAAC,WAAW,KAAK,EAAE,MAAM,YAAY,CAAC,CAC3E,OAAM,UAAU,GAAG,kBAAkB,GAAG,EAAE,MAAM,YAAY,OAAO,OAAO;IAE5E,CACH;AAGH,MAAI,IAAI,MAAM,MAAM,EAAE,WAAW,WAAW,CAC1C,OAAM,KAAK,UAAU;GACnB,SAAS;GACT,iBAAiB;GAClB,CAAC;AAGJ,SAAO"}
package/dist/utils.mjs CHANGED
@@ -1,3 +1,5 @@
1
+ import { getComments } from "./adapters/rust/utils.mjs";
2
+ import { getComments as getComments$1 } from "./adapters/javascript/utils.mjs";
1
3
  import { spawn } from "child_process";
2
4
  import consola from "consola";
3
5
 
@@ -25,7 +27,66 @@ function execUntilExit(command, cwd) {
25
27
  async function cleanupEnvironment(path) {
26
28
  await execUntilExit(`rm -rf ${path}`, process.cwd());
27
29
  }
30
+ function isDirective(comment) {
31
+ return /@docval-.+/.test(comment.trim());
32
+ }
33
+ function isCodeDirective(directive) {
34
+ return directive === "hidden";
35
+ }
36
+ function getAssociatedCode(code, comment) {
37
+ const commentLineStart = code.lastIndexOf("\n", comment.start - 1);
38
+ const start = commentLineStart === -1 ? 0 : commentLineStart + 1;
39
+ const currentLineEnd = code.indexOf("\n", comment.end);
40
+ if (currentLineEnd === -1) return code.slice(start);
41
+ const nextLineStart = currentLineEnd + 1;
42
+ const nextLineEnd = code.indexOf("\n", nextLineStart);
43
+ return code.slice(start, nextLineEnd === -1 ? code.length : nextLineEnd + 1);
44
+ }
45
+ async function getDirectives(code, language) {
46
+ let comments = [];
47
+ switch (language) {
48
+ case "javascript":
49
+ case "js":
50
+ case "jsx":
51
+ case "typescript":
52
+ case "ts":
53
+ case "tsx":
54
+ comments = await getComments$1(code, ["javascript", "js"].includes(language) ? "js" : language === "jsx" ? "jsx" : ["typescript", "ts"].includes(language) ? "ts" : "tsx");
55
+ break;
56
+ case "rust":
57
+ case "rs":
58
+ comments = await getComments(code);
59
+ break;
60
+ }
61
+ const directives = {};
62
+ const prefix = "@docval-";
63
+ for (const comment of comments) {
64
+ if (!isDirective(comment.value)) continue;
65
+ const trimmed = comment.value.trim();
66
+ const prefixIndex = trimmed.indexOf(prefix);
67
+ if (prefixIndex === -1) continue;
68
+ const content = trimmed.slice(prefixIndex + 8);
69
+ const spaceIdx = content.indexOf(" ");
70
+ const directive = spaceIdx === -1 ? content : content.slice(0, spaceIdx);
71
+ const args = spaceIdx === -1 ? [] : content.slice(spaceIdx + 1).split(" ").filter(Boolean);
72
+ const key = directive;
73
+ directives[key] ??= [];
74
+ directives[key].push({
75
+ args,
76
+ code: isCodeDirective(directive) ? getAssociatedCode(code, comment) : void 0
77
+ });
78
+ }
79
+ return directives;
80
+ }
81
+ async function filterHiddenCode(code, language) {
82
+ const directives = await getDirectives(code, language);
83
+ let filteredCode = code;
84
+ if (directives.hidden) {
85
+ for (const directive of directives.hidden) if (directive.code) filteredCode = filteredCode.replace(directive.code, "");
86
+ }
87
+ return filteredCode;
88
+ }
28
89
 
29
90
  //#endregion
30
- export { cleanupEnvironment, execUntilExit, logger };
91
+ export { cleanupEnvironment, execUntilExit, filterHiddenCode, getDirectives, logger };
31
92
  //# sourceMappingURL=utils.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.mjs","names":[],"sources":["../src/utils.ts"],"sourcesContent":["import { spawn } from \"child_process\";\nimport consola from \"consola\";\n\nconst logger = consola.withTag(\"Borrow\").withTag(\"DocVal\");\n\nfunction execUntilExit(command: string, cwd: string): Promise<void> {\n let error = \"\";\n return new Promise((resolve, reject) => {\n const process = spawn(command, { cwd, shell: true });\n\n process.stdout.on(\"data\", (data) => {\n logger.debug(data.toString());\n });\n\n process.stderr.on(\"data\", (data) => {\n error += data;\n });\n\n process.on(\"close\", (code) => {\n if (code === 0) {\n resolve();\n } else {\n reject(`Command failed with exit code ${code}\\n${error})`);\n }\n });\n });\n}\n\nasync function cleanupEnvironment(path: string) {\n await execUntilExit(`rm -rf ${path}`, process.cwd());\n}\n\nexport { execUntilExit, cleanupEnvironment, logger };\n"],"mappings":";;;;AAGA,MAAM,SAAS,QAAQ,QAAQ,SAAS,CAAC,QAAQ,SAAS;AAE1D,SAAS,cAAc,SAAiB,KAA4B;CAClE,IAAI,QAAQ;AACZ,QAAO,IAAI,SAAS,SAAS,WAAW;EACtC,MAAM,UAAU,MAAM,SAAS;GAAE;GAAK,OAAO;GAAM,CAAC;AAEpD,UAAQ,OAAO,GAAG,SAAS,SAAS;AAClC,UAAO,MAAM,KAAK,UAAU,CAAC;IAC7B;AAEF,UAAQ,OAAO,GAAG,SAAS,SAAS;AAClC,YAAS;IACT;AAEF,UAAQ,GAAG,UAAU,SAAS;AAC5B,OAAI,SAAS,EACX,UAAS;OAET,QAAO,iCAAiC,KAAK,IAAI,MAAM,GAAG;IAE5D;GACF;;AAGJ,eAAe,mBAAmB,MAAc;AAC9C,OAAM,cAAc,UAAU,QAAQ,QAAQ,KAAK,CAAC"}
1
+ {"version":3,"file":"utils.mjs","names":["getCommentsJavaScript","getCommentsRust"],"sources":["../src/utils.ts"],"sourcesContent":["import { spawn } from \"child_process\";\nimport consola from \"consola\";\nimport { Language } from \"./adapters\";\nimport { Directive as DirectiveRust } from \"./adapters/rust/utils\";\nimport { getComments as getCommentsJavaScript } from \"./adapters/javascript/utils\";\nimport { getComments as getCommentsRust } from \"./adapters/rust/utils\";\n\nconst logger = consola.withTag(\"Borrow\").withTag(\"DocVal\");\n\nfunction execUntilExit(command: string, cwd: string): Promise<void> {\n let error = \"\";\n return new Promise((resolve, reject) => {\n const process = spawn(command, { cwd, shell: true });\n\n process.stdout.on(\"data\", (data) => {\n logger.debug(data.toString());\n });\n\n process.stderr.on(\"data\", (data) => {\n error += data;\n });\n\n process.on(\"close\", (code) => {\n if (code === 0) {\n resolve();\n } else {\n reject(`Command failed with exit code ${code}\\n${error})`);\n }\n });\n });\n}\n\nasync function cleanupEnvironment(path: string) {\n await execUntilExit(`rm -rf ${path}`, process.cwd());\n}\n\ntype Directive = \"hidden\";\n\ntype Comment = {\n value: string;\n start: number;\n end: number;\n};\n\ntype DirectiveValue = {\n args: string[];\n /**\n * Code associated with the directive\n */\n code?: string;\n};\n\ntype DirectiveKey = Directive | DirectiveRust;\ntype DirectiveMap = Partial<Record<DirectiveKey, DirectiveValue[]>>;\n\nfunction isDirective(comment: string): boolean {\n return /@docval-.+/.test(comment.trim());\n}\n\nfunction isCodeDirective(directive: string): boolean {\n return directive === \"hidden\";\n}\n\nfunction getAssociatedCode(code: string, comment: Comment): string | undefined {\n const commentLineStart = code.lastIndexOf(\"\\n\", comment.start - 1);\n const start = commentLineStart === -1 ? 0 : commentLineStart + 1;\n const currentLineEnd = code.indexOf(\"\\n\", comment.end);\n if (currentLineEnd === -1) {\n return code.slice(start);\n }\n\n const nextLineStart = currentLineEnd + 1;\n const nextLineEnd = code.indexOf(\"\\n\", nextLineStart);\n\n return code.slice(start, nextLineEnd === -1 ? code.length : nextLineEnd + 1);\n}\n\nasync function getDirectives(code: string, language: Language): Promise<DirectiveMap> {\n let comments: Comment[] = [];\n switch (language) {\n case \"javascript\":\n case \"js\":\n case \"jsx\":\n case \"typescript\":\n case \"ts\":\n case \"tsx\":\n const jsType = [\"javascript\", \"js\"].includes(language)\n ? \"js\"\n : language === \"jsx\"\n ? \"jsx\"\n : [\"typescript\", \"ts\"].includes(language)\n ? \"ts\"\n : \"tsx\";\n comments = await getCommentsJavaScript(code, jsType);\n break;\n case \"rust\":\n case \"rs\":\n comments = await getCommentsRust(code);\n break;\n }\n\n const directives: DirectiveMap = {};\n const prefix = \"@docval-\";\n for (const comment of comments) {\n if (!isDirective(comment.value)) continue;\n const trimmed = comment.value.trim();\n const prefixIndex = trimmed.indexOf(prefix);\n if (prefixIndex === -1) continue;\n const content = trimmed.slice(prefixIndex + prefix.length);\n const spaceIdx = content.indexOf(\" \");\n const directive = spaceIdx === -1 ? content : content.slice(0, spaceIdx);\n const args =\n spaceIdx === -1\n ? []\n : content\n .slice(spaceIdx + 1)\n .split(\" \")\n .filter(Boolean);\n const key = directive as DirectiveKey;\n directives[key] ??= [];\n directives[key].push({\n args,\n code: isCodeDirective(directive) ? getAssociatedCode(code, comment) : undefined,\n });\n }\n\n return directives;\n}\n\nasync function filterHiddenCode(code: string, language: Language): Promise<string> {\n const directives = await getDirectives(code, language);\n let filteredCode = code;\n if (directives.hidden) {\n for (const directive of directives.hidden) {\n if (directive.code) {\n filteredCode = filteredCode.replace(directive.code, \"\");\n }\n }\n }\n\n return filteredCode;\n}\n\nexport { execUntilExit, cleanupEnvironment, logger, getDirectives, filterHiddenCode };\nexport type { Comment };\n"],"mappings":";;;;;;AAOA,MAAM,SAAS,QAAQ,QAAQ,SAAS,CAAC,QAAQ,SAAS;AAE1D,SAAS,cAAc,SAAiB,KAA4B;CAClE,IAAI,QAAQ;AACZ,QAAO,IAAI,SAAS,SAAS,WAAW;EACtC,MAAM,UAAU,MAAM,SAAS;GAAE;GAAK,OAAO;GAAM,CAAC;AAEpD,UAAQ,OAAO,GAAG,SAAS,SAAS;AAClC,UAAO,MAAM,KAAK,UAAU,CAAC;IAC7B;AAEF,UAAQ,OAAO,GAAG,SAAS,SAAS;AAClC,YAAS;IACT;AAEF,UAAQ,GAAG,UAAU,SAAS;AAC5B,OAAI,SAAS,EACX,UAAS;OAET,QAAO,iCAAiC,KAAK,IAAI,MAAM,GAAG;IAE5D;GACF;;AAGJ,eAAe,mBAAmB,MAAc;AAC9C,OAAM,cAAc,UAAU,QAAQ,QAAQ,KAAK,CAAC;;AAsBtD,SAAS,YAAY,SAA0B;AAC7C,QAAO,aAAa,KAAK,QAAQ,MAAM,CAAC;;AAG1C,SAAS,gBAAgB,WAA4B;AACnD,QAAO,cAAc;;AAGvB,SAAS,kBAAkB,MAAc,SAAsC;CAC7E,MAAM,mBAAmB,KAAK,YAAY,MAAM,QAAQ,QAAQ,EAAE;CAClE,MAAM,QAAQ,qBAAqB,KAAK,IAAI,mBAAmB;CAC/D,MAAM,iBAAiB,KAAK,QAAQ,MAAM,QAAQ,IAAI;AACtD,KAAI,mBAAmB,GACrB,QAAO,KAAK,MAAM,MAAM;CAG1B,MAAM,gBAAgB,iBAAiB;CACvC,MAAM,cAAc,KAAK,QAAQ,MAAM,cAAc;AAErD,QAAO,KAAK,MAAM,OAAO,gBAAgB,KAAK,KAAK,SAAS,cAAc,EAAE;;AAG9E,eAAe,cAAc,MAAc,UAA2C;CACpF,IAAI,WAAsB,EAAE;AAC5B,SAAQ,UAAR;EACE,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;AAQH,cAAW,MAAMA,cAAsB,MAPxB,CAAC,cAAc,KAAK,CAAC,SAAS,SAAS,GAClD,OACA,aAAa,QACX,QACA,CAAC,cAAc,KAAK,CAAC,SAAS,SAAS,GACrC,OACA,MAC4C;AACpD;EACF,KAAK;EACL,KAAK;AACH,cAAW,MAAMC,YAAgB,KAAK;AACtC;;CAGJ,MAAM,aAA2B,EAAE;CACnC,MAAM,SAAS;AACf,MAAK,MAAM,WAAW,UAAU;AAC9B,MAAI,CAAC,YAAY,QAAQ,MAAM,CAAE;EACjC,MAAM,UAAU,QAAQ,MAAM,MAAM;EACpC,MAAM,cAAc,QAAQ,QAAQ,OAAO;AAC3C,MAAI,gBAAgB,GAAI;EACxB,MAAM,UAAU,QAAQ,MAAM,cAAc,EAAc;EAC1D,MAAM,WAAW,QAAQ,QAAQ,IAAI;EACrC,MAAM,YAAY,aAAa,KAAK,UAAU,QAAQ,MAAM,GAAG,SAAS;EACxE,MAAM,OACJ,aAAa,KACT,EAAE,GACF,QACG,MAAM,WAAW,EAAE,CACnB,MAAM,IAAI,CACV,OAAO,QAAQ;EACxB,MAAM,MAAM;AACZ,aAAW,SAAS,EAAE;AACtB,aAAW,KAAK,KAAK;GACnB;GACA,MAAM,gBAAgB,UAAU,GAAG,kBAAkB,MAAM,QAAQ,GAAG;GACvE,CAAC;;AAGJ,QAAO;;AAGT,eAAe,iBAAiB,MAAc,UAAqC;CACjF,MAAM,aAAa,MAAM,cAAc,MAAM,SAAS;CACtD,IAAI,eAAe;AACnB,KAAI,WAAW,QACb;OAAK,MAAM,aAAa,WAAW,OACjC,KAAI,UAAU,KACZ,gBAAe,aAAa,QAAQ,UAAU,MAAM,GAAG;;AAK7D,QAAO"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@borrowdev/docval",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Validate your documentation codeblocks at build-time, find bugs in record-time",
5
5
  "keywords": [
6
6
  "borrow.dev",
@@ -16,6 +16,7 @@
16
16
  },
17
17
  "files": [
18
18
  "dist",
19
+ "assets",
19
20
  "package.json",
20
21
  "README.md"
21
22
  ],