Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 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 78 79 80 81 82 | 2x 5x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 132x 52x 1x 52x 52x 2704x 52x 52x 52x 52x 52x 6x 6x 6x 57x 57x 5x 52x 52x | import { readdir, readFile, stat } from "node:fs/promises";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { resolvePathWithinRoot } from "../../security/safe-paths";
import type { ExampleRecord } from "./examples-schema";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
export class BuiltInProvider {
private snapshotPromise: Promise<ExampleRecord[]> | null = null;
getExamples(): Promise<ExampleRecord[]> {
this.snapshotPromise ??= this.loadExamples();
return this.snapshotPromise;
}
private async loadExamples(): Promise<ExampleRecord[]> {
const publicCandidates = [
path.resolve(__dirname, "../../../public"),
path.resolve(__dirname, "public"),
path.resolve(__dirname, "../../public"),
];
let publicDir = publicCandidates[0];
for (const candidate of publicCandidates) {
try {
await stat(candidate);
publicDir = candidate;
break;
} catch {
// Try the next runtime layout.
}
}
const examplesRoot = path.resolve(publicDir, "examples");
const files: string[] = [];
await this.collectFiles(examplesRoot, examplesRoot, files);
files.sort((a, b) => a.localeCompare(b));
const sketches = files.filter((file) => file.toLowerCase().endsWith(".ino"));
return Promise.all(sketches.map(async (relativePath) => {
const relativeDirectory = path.dirname(relativePath);
const relatedHeaders = files.filter(
(file) => path.dirname(file) === relativeDirectory && file.toLowerCase().endsWith(".h"),
);
const exampleFiles = [relativePath, ...relatedHeaders];
const loadedFiles = await Promise.all(exampleFiles.map(async (file) => ({
name: path.basename(file),
path: file.replaceAll(path.sep, "/"),
content: await readFile(resolvePathWithinRoot(examplesRoot, file), "utf8"),
})));
const name = path.basename(relativePath);
const category = relativePath.split(path.sep)[0] ?? "Built-in";
return {
id: `builtin-${relativePath.replaceAll(path.sep, "-").replaceAll(/[^A-Za-z0-9_-]/g, "-").replaceAll(/-+/g, "-").replaceAll(/(?:^-|-$)/g, "")}`,
title: name.replaceAll(/\.(?:ino|h)$/gi, "").replaceAll(/[-_]+/g, " "),
category,
files: loadedFiles,
main: name,
source: "builtin" as const,
};
}));
}
private async collectFiles(root: string, current: string, output: string[]): Promise<void> {
let entries;
try {
entries = await readdir(current, { withFileTypes: true });
} catch {
return;
}
for (const entry of entries) {
const relative = path.relative(root, path.join(current, entry.name));
if (entry.isDirectory()) {
await this.collectFiles(root, path.join(current, entry.name), output);
E} else if (/\.(?:ino|h)$/i.test(entry.name)) {
output.push(relative);
}
}
}
}
|