feat(formacoes): módulo 2 (DHT22 + LCD 16x2 no Wokwi), PDFs e página de entrada
Release / Plano (reaproveitar a imagem?) (push) Successful in 7s
CI / Lint e auditorias (push) Successful in 1m48s
CI / Trivy (dependências e segredos) (push) Successful in 12s
CI / Imagem Docker (linux/arm64) (push) Failing after 2m27s
Release / ci (push) Failing after 4m31s
Release / Publica a imagem (linux/arm64) (push) Skipped
Release / Cria a release no Gitea (push) Skipped
Release / Plano (reaproveitar a imagem?) (push) Successful in 7s
CI / Lint e auditorias (push) Successful in 1m48s
CI / Trivy (dependências e segredos) (push) Successful in 12s
CI / Imagem Docker (linux/arm64) (push) Failing after 2m27s
Release / ci (push) Failing after 4m31s
Release / Publica a imagem (linux/arm64) (push) Skipped
Release / Cria a release no Gitea (push) Skipped
- Formação 2 da LASER: slides visuais, apostila, projeto do Wokwi e scanner I2C, validados no simulador (leitura normal, temperatura negativa e sensor desconectado). Circuito com pull-ups de 10 kΩ e 4,7 kΩ para 3V3 e aviso sobre os pull-ups de 5 V da plaquinha PCF8574. - PDFs prontos dos slides e das apostilas dos módulos 1 e 2; slides-pdf agora também exporta a apostila. - Página de entrada em /formacoes e /formacoes/N, gerada por scripts/formacoes-viewer.mjs a partir do formacao.json de cada pasta. - A apostila passou de index.html para apostila.html. - Corrige o link do Fritzing da apostila 1 (/apostilas/1 não existe). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
71c5708726
commit
1860e34cbb
32 files changed
+6469
-1943
No files matched your search
+34
-8
@@ -1,12 +1,13 @@
|
||||
/**
|
||||
* Exporta os slides de uma formação para PDF em 16:9 exato.
|
||||
* Exporta o material de uma formação para PDF: os slides em 16:9 exato e a
|
||||
* apostila em A4, já paginada pelo Paged.js.
|
||||
*
|
||||
* npm run slides-pdf → módulo 1
|
||||
* npm run slides-pdf -- 2 → módulo 2
|
||||
*
|
||||
* A página do PDF tem 1280 x 720 px (338,667 x 190,5 mm), a mesma caixa do
|
||||
* palco do slide.html, então nada é reescalado nem cortado. Sai um arquivo por
|
||||
* formação, ao lado do próprio slide.html.
|
||||
* A página do PDF dos slides tem 1280 x 720 px (338,667 x 190,5 mm), a mesma
|
||||
* caixa do palco do slide.html, então nada é reescalado nem cortado. Os dois
|
||||
* arquivos saem ao lado do slide.html e da apostila.html da formação.
|
||||
*
|
||||
* Existe porque a caixa de impressão do navegador depende de o usuário lembrar
|
||||
* de marcar "gráficos de segundo plano" e "margens: nenhuma". Aqui isso é fixo.
|
||||
@@ -22,6 +23,7 @@ const raiz = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
||||
const modulo = (process.argv[2] || "1").replace(/\D/g, "") || "1";
|
||||
const pastaModulo = path.join(raiz, "public", "formacoes", modulo);
|
||||
const saida = path.join(pastaModulo, `LASER-ESP32-Modulo-${modulo}-Slides.pdf`);
|
||||
const saidaApostila = path.join(pastaModulo, `LASER-ESP32-Modulo-${modulo}-Apostila.pdf`);
|
||||
|
||||
if (!fs.existsSync(path.join(pastaModulo, "slide.html"))) {
|
||||
console.error(`Não achei public/formacoes/${modulo}/slide.html`);
|
||||
@@ -38,6 +40,7 @@ const TIPOS = {
|
||||
".png": "image/png",
|
||||
".jpg": "image/jpeg",
|
||||
".json": "application/json",
|
||||
".woff2": "font/woff2",
|
||||
};
|
||||
|
||||
const servidor = http.createServer((req, res) => {
|
||||
@@ -55,7 +58,7 @@ await new Promise((r) => servidor.listen(0, "127.0.0.1", r));
|
||||
const porta = servidor.address().port;
|
||||
const url = `http://127.0.0.1:${porta}/formacoes/${modulo}/slide.html`;
|
||||
|
||||
console.log(`[1/3] Abrindo ${url}`);
|
||||
console.log(`[1/4] Abrindo ${url}`);
|
||||
const navegador = await puppeteer.launch({ headless: "new", args: ["--no-sandbox"] });
|
||||
|
||||
try {
|
||||
@@ -63,7 +66,7 @@ try {
|
||||
await pagina.goto(url, { waitUntil: "networkidle0", timeout: 60000 });
|
||||
await pagina.evaluate(() => document.fonts.ready);
|
||||
|
||||
console.log("[2/3] Conferindo o encaixe de cada slide no 16:9");
|
||||
console.log("[2/4] Conferindo o encaixe de cada slide no 16:9");
|
||||
await pagina.emulateMediaType("print");
|
||||
await new Promise((r) => setTimeout(r, 500));
|
||||
|
||||
@@ -80,7 +83,7 @@ try {
|
||||
console.log(` ${caixas.length} slides, todos em 1280x720`);
|
||||
}
|
||||
|
||||
console.log("[3/3] Gerando o PDF");
|
||||
console.log("[3/4] Gerando o PDF dos slides");
|
||||
await pagina.pdf({
|
||||
path: saida,
|
||||
printBackground: true,
|
||||
@@ -89,7 +92,30 @@ try {
|
||||
});
|
||||
|
||||
const kb = (fs.statSync(saida).size / 1024).toFixed(0);
|
||||
console.log(`\nPronto: ${path.relative(raiz, saida)} (${kb} KB, ${caixas.length} páginas em 16:9)`);
|
||||
console.log(` ${path.relative(raiz, saida)} (${kb} KB, ${caixas.length} páginas em 16:9)`);
|
||||
|
||||
/* A apostila é paginada no navegador pelo Paged.js, que não avisa quando
|
||||
termina. Espera-se o número de folhas parar de crescer. */
|
||||
console.log("[4/4] Paginando e gerando o PDF da apostila");
|
||||
const apostila = await navegador.newPage();
|
||||
await apostila.goto(`http://127.0.0.1:${porta}/formacoes/${modulo}/apostila.html`, { waitUntil: "networkidle0", timeout: 120000 });
|
||||
await apostila.waitForFunction(() => document.querySelectorAll(".pagedjs_page").length > 1, { timeout: 120000 });
|
||||
let folhas = 0;
|
||||
for (;;) {
|
||||
await new Promise((r) => setTimeout(r, 1500));
|
||||
const agora = await apostila.evaluate(() => document.querySelectorAll(".pagedjs_page").length);
|
||||
if (agora === folhas) break;
|
||||
folhas = agora;
|
||||
}
|
||||
await apostila.evaluate(() => document.fonts.ready);
|
||||
await apostila.pdf({
|
||||
path: saidaApostila,
|
||||
printBackground: true,
|
||||
preferCSSPageSize: true,
|
||||
margin: { top: 0, right: 0, bottom: 0, left: 0 },
|
||||
});
|
||||
const kbA = (fs.statSync(saidaApostila).size / 1024).toFixed(0);
|
||||
console.log(` ${path.relative(raiz, saidaApostila)} (${kbA} KB, ${folhas} páginas em A4)`);
|
||||
} finally {
|
||||
await navegador.close();
|
||||
servidor.close();
|
||||
|
||||
Reference in new issue
Block a user