mirror of
https://github.com/StepanovPlaton/SSAUGenerator.git
synced 2026-10-31 10:18:29 +04:00
- Move projects into content/<project>/{docx,pptx} with shared assets/
- Flatten config paths; output = project name in project folder
- Add pptx --init scaffold; remove docx exe build
- Add feature-complete content/example; ignore content/* except example
- Rewrite README and AGENTS.md
116 lines
3.6 KiB
JavaScript
116 lines
3.6 KiB
JavaScript
"use strict";
|
||
|
||
const fs = require("fs");
|
||
const path = require("path");
|
||
const yaml = require("js-yaml");
|
||
|
||
const { DEFAULTS, deepMerge } = require("./config");
|
||
const { solidPng } = require("./png");
|
||
|
||
const CONFIG_HEADER = `# Конфигурация генератора SSAU Generator PPTX.
|
||
# Все относительные пути считаются от каталога этого файла.
|
||
# Любой ключ можно опустить — будет использовано значение по умолчанию.
|
||
|
||
`;
|
||
|
||
const SAMPLE = {
|
||
"slides/00-title.md": `# Название презентации
|
||
|
||
## Подзаголовок
|
||
`,
|
||
"slides/01-content.md": `# Первый слайд
|
||
|
||
- первый пункт списка;
|
||
- второй пункт списка:
|
||
|
||
- вложенный пункт;
|
||
|
||
Обычный абзац с **полужирным**, *курсивом* и ==выделением==.
|
||
`,
|
||
"slides/02-final.md": `# Спасибо за внимание
|
||
`,
|
||
};
|
||
|
||
// Цвета задников: [R, G, B].
|
||
const BRAND = [27, 135, 201];
|
||
const BACKGROUNDS = {
|
||
"title-bg.png": BRAND,
|
||
"content-bg.png": [255, 255, 255],
|
||
"final-bg.png": BRAND,
|
||
};
|
||
|
||
function isGeneratorDir(baseDir) {
|
||
const base = path.basename(baseDir).toLowerCase();
|
||
return base === "docx" || base === "pptx";
|
||
}
|
||
|
||
/**
|
||
* Раскладка проекта: имя проекта = имя папки проекта, общие ресурсы в
|
||
* content/<проект>/assets/, результат — content/<проект>/<проект>.pptx.
|
||
*/
|
||
function projectLayout(baseDir) {
|
||
const isSub = isGeneratorDir(baseDir);
|
||
const projectDir = isSub ? path.dirname(baseDir) : baseDir;
|
||
const projectName = path.basename(projectDir) || "project";
|
||
return {
|
||
projectDir,
|
||
projectName,
|
||
assetsRel: isSub ? "../assets" : "assets",
|
||
assetsDir: path.join(projectDir, "assets"),
|
||
outputRel: isSub ? `../${projectName}.pptx` : `${projectName}.pptx`,
|
||
};
|
||
}
|
||
|
||
function defaultConfigYaml(layout) {
|
||
const config = deepMerge(DEFAULTS, {
|
||
presentation: { output: layout.outputRel },
|
||
theme: {
|
||
backgrounds: {
|
||
title: `${layout.assetsRel}/title-bg.png`,
|
||
content: `${layout.assetsRel}/content-bg.png`,
|
||
final: `${layout.assetsRel}/final-bg.png`,
|
||
},
|
||
},
|
||
content: { dir: "." },
|
||
slides: [
|
||
{ type: "title", file: "slides/00-title.md" },
|
||
{ type: "content", file: "slides/01-content.md" },
|
||
{ type: "final", file: "slides/02-final.md" },
|
||
],
|
||
});
|
||
return (
|
||
CONFIG_HEADER +
|
||
yaml.dump(config, { noRefs: true, lineWidth: -1, sortKeys: false })
|
||
);
|
||
}
|
||
|
||
/**
|
||
* Создаёт config.yaml, примеры слайдов и общие ресурсы проекта
|
||
* (content/<проект>/assets/), если их ещё нет.
|
||
*/
|
||
async function ensureScaffold(baseDir) {
|
||
const layout = projectLayout(baseDir);
|
||
const created = [];
|
||
const write = (target, content) => {
|
||
if (fs.existsSync(target)) return;
|
||
fs.mkdirSync(path.dirname(target), { recursive: true });
|
||
if (content && typeof content === "object" && content.binary) {
|
||
fs.writeFileSync(target, content.binary);
|
||
} else {
|
||
fs.writeFileSync(target, content, "utf8");
|
||
}
|
||
created.push(target);
|
||
};
|
||
|
||
write(path.join(baseDir, "config.yaml"), defaultConfigYaml(layout));
|
||
for (const [name, content] of Object.entries(SAMPLE)) {
|
||
write(path.join(baseDir, name), content);
|
||
}
|
||
for (const [name, color] of Object.entries(BACKGROUNDS)) {
|
||
write(path.join(layout.assetsDir, name), { binary: solidPng(1920, 1080, color) });
|
||
}
|
||
return created;
|
||
}
|
||
|
||
module.exports = { projectLayout, defaultConfigYaml, ensureScaffold, SAMPLE };
|