-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathbuild.ts
More file actions
77 lines (61 loc) · 2.67 KB
/
build.ts
File metadata and controls
77 lines (61 loc) · 2.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#!/usr/bin/env -S deno run --allow-read --allow-write
import { remark } from "npm:remark@15";
import { visit } from "npm:unist-util-visit@5";
import { readFileSync, writeFileSync } from "node:fs";
import { resolve, dirname, join } from "node:path";
// Custom plugin to handle !include() syntax
function remarkInclude() {
const processingFiles = new Set<string>();
return (tree: any, file: any) => {
const basePath = dirname(file.path || file.history?.[0] || ".");
const currentFile = file.path || file.history?.[0] || "";
visit(tree, "paragraph", (node, index, parent) => {
// Check if paragraph contains only an include directive
if (node.children?.length === 1 && node.children[0].type === "text") {
const text = node.children[0].value.trim();
const includeMatch = text.match(/^!include\(([^)]+)\)$/);
if (includeMatch) {
const includePath = includeMatch[1].trim().replace(/['"]/g, "");
const fullPath = resolve(basePath, includePath);
// Check for circular includes
if (processingFiles.has(fullPath)) {
console.warn(`Warning: Circular include detected for ${includePath}`);
return;
}
try {
const content = readFileSync(fullPath, "utf-8");
// Process included content with same processor (recursive)
processingFiles.add(fullPath);
const processor = remark().use(remarkInclude);
const result = processor.processSync({ value: content, path: fullPath });
processingFiles.delete(fullPath);
const parsed = processor.parse(String(result));
// Replace the paragraph with the parsed content
if (parent && typeof index === "number") {
parent.children.splice(index, 1, ...parsed.children);
}
} catch (err) {
processingFiles.delete(fullPath);
console.warn(`Warning: Could not include ${includePath}: ${err.message}`);
}
}
}
});
};
}
async function processMarkdown(inputPath: string, outputPath: string) {
const processor = remark().use(remarkInclude);
const input = readFileSync(inputPath, "utf-8");
const result = await processor.process({ value: input, path: inputPath });
writeFileSync(outputPath, String(result));
console.log(`Processed: ${inputPath} → ${outputPath}`);
}
// Process a single file or directory
if (import.meta.main) {
const [inputPath, outputPath] = Deno.args;
if (!inputPath || !outputPath) {
console.log("Usage: deno run --allow-read --allow-write templater.ts input.md output.md");
Deno.exit(1);
}
await processMarkdown(inputPath, outputPath);
}