- Adicionado estrutura completa do projeto - Configurado MCP server para Premiere Pro - Adicionado documentação e skills - Configurado Gitignore para o projeto
103 lines
4.8 KiB
JavaScript
Executable File
103 lines
4.8 KiB
JavaScript
Executable File
import { readFile, writeFile } from "node:fs/promises";
|
|
import { resolve } from "node:path";
|
|
|
|
const repository = "docsforadobe/premiere-scripting-guide";
|
|
const commit = "4253cea094e84d43590b77012b33bd1c140f72ea";
|
|
const referencePath = resolve(process.env.EXTENDSCRIPT_REFERENCE_PATH ?? "src/resources/cep-reference-inventory.json");
|
|
const outputPath = resolve(process.env.EXTENDSCRIPT_INVENTORY_OUTPUT_PATH ?? "src/resources/extendscript-api-inventory.json");
|
|
const fixtureDirectory = process.env.EXTENDSCRIPT_INVENTORY_FIXTURE_DIRECTORY;
|
|
const check = process.argv.includes("--check");
|
|
|
|
async function markdown(path) {
|
|
if (fixtureDirectory) return readFile(resolve(fixtureDirectory, path), "utf8");
|
|
const response = await fetch(`https://raw.githubusercontent.com/${repository}/${commit}/${path}`, {
|
|
signal: AbortSignal.timeout(30_000),
|
|
});
|
|
if (!response.ok) throw new Error(`Guide request failed for ${path}: HTTP ${response.status}`);
|
|
return response.text();
|
|
}
|
|
|
|
function parsePage(path, source) {
|
|
const lines = source.replaceAll("\r\n", "\n").split("\n");
|
|
const title = lines.find((line) => line.startsWith("# "))?.slice(2).trim();
|
|
if (!title || !/ object$/i.test(title)) return [];
|
|
const objectName = title.replace(/ object$/i, "");
|
|
let section = null;
|
|
let sectionHasHeadings = false;
|
|
const symbols = [];
|
|
for (let index = 0; index < lines.length; index += 1) {
|
|
const line = lines[index];
|
|
if (line === "## Attributes") { section = "attribute"; sectionHasHeadings = false; }
|
|
else if (line === "## Methods") { section = "method"; sectionHasHeadings = false; }
|
|
else if (line.startsWith("## ")) section = null;
|
|
if (section && !sectionHasHeadings) {
|
|
const tableMember = line.match(/^\|\s*`([^`]+)`\s*\|/);
|
|
if (tableMember) {
|
|
const member = tableMember[1];
|
|
symbols.push({
|
|
object: objectName,
|
|
name: `${objectName}.${member}`,
|
|
kind: section,
|
|
signature: member,
|
|
sourcePath: path,
|
|
});
|
|
continue;
|
|
}
|
|
}
|
|
if (!section || !line.startsWith("### ")) continue;
|
|
sectionHasHeadings = true;
|
|
const name = line.slice(4).trim();
|
|
const signatureLine = lines.slice(index + 1).find((candidate) => candidate.trim() !== "");
|
|
const match = signatureLine?.match(/^`([^`]+)`$/);
|
|
if (!match) throw new Error(`Missing inline signature for ${path}:${name}`);
|
|
symbols.push({ object: objectName, name, kind: section, signature: match[1], sourcePath: path });
|
|
}
|
|
return symbols;
|
|
}
|
|
|
|
const reference = JSON.parse(await readFile(referencePath, "utf8"));
|
|
const guideEntries = reference.entries.filter((entry) => entry.repository === repository);
|
|
if (guideEntries.some((entry) => entry.commit !== commit || entry.scope !== "premiere-extendscript-guide")) {
|
|
throw new Error("Scripting guide reference entries do not match the pinned commit and scope");
|
|
}
|
|
const paths = reference.entries
|
|
.filter((entry) => entry.repository === repository
|
|
&& entry.commit === commit
|
|
&& entry.scope === "premiere-extendscript-guide"
|
|
&& entry.path.startsWith("docs/")
|
|
&& entry.path.endsWith(".md"))
|
|
.map((entry) => entry.path)
|
|
.sort();
|
|
if (paths.length === 0) throw new Error("Pinned CEP reference inventory contains no scripting guide Markdown files");
|
|
const symbols = [];
|
|
for (const path of paths) symbols.push(...parsePage(path, await markdown(path)));
|
|
symbols.sort((left, right) => `${left.object}:${left.kind}:${left.name}`.localeCompare(`${right.object}:${right.kind}:${right.name}`));
|
|
if (symbols.length === 0) throw new Error("No ExtendScript symbols were parsed from the guide");
|
|
const keys = symbols.map((symbol) => `${symbol.object}:${symbol.kind}:${symbol.name}`);
|
|
if (new Set(keys).size !== keys.length) throw new Error("ExtendScript inventory contains duplicate object members");
|
|
const objects = [...new Set(symbols.map((symbol) => symbol.object))].sort();
|
|
const inventory = {
|
|
schemaVersion: 1,
|
|
source: { repository, commit, authority: "community", authorityNote: "Community-maintained guide; not Adobe API authority." },
|
|
stats: {
|
|
total: symbols.length,
|
|
objects: objects.length,
|
|
attributes: symbols.filter((symbol) => symbol.kind === "attribute").length,
|
|
methods: symbols.filter((symbol) => symbol.kind === "method").length,
|
|
},
|
|
objects,
|
|
symbols,
|
|
};
|
|
const rendered = `${JSON.stringify(inventory, null, 2)}\n`;
|
|
if (check) {
|
|
let current = "";
|
|
try { current = await readFile(outputPath, "utf8"); } catch {}
|
|
if (current.replaceAll("\r\n", "\n") !== rendered) {
|
|
console.error("ExtendScript API inventory is stale. Run npm run extendscript:api-inventory.");
|
|
process.exitCode = 1;
|
|
} else console.log(`ExtendScript API inventory is current: ${symbols.length} symbols.`);
|
|
} else {
|
|
await writeFile(outputPath, rendered);
|
|
console.log(`Wrote ${symbols.length} ExtendScript symbols across ${objects.length} objects.`);
|
|
}
|