d68463548f
Run Tests on Branches / Detect Changes (push) Successful in 19s
Run Tests on Branches / Backend Tests (push) Successful in 2m46s
Run Tests on Branches / PIP Platform Tests (push) Has been skipped
Run Tests on Branches / Frontend Tests (push) Successful in 2m24s
Run Tests on Branches / Frontend Mobile Tests (push) Has been skipped
Run Tests on Branches / Parapharmacy API Tests (push) Has been skipped
151 lines
5.7 KiB
JavaScript
151 lines
5.7 KiB
JavaScript
import fs from 'fs';
|
|
import os from 'os';
|
|
import path from 'path';
|
|
import { execFileSync } from 'child_process';
|
|
|
|
const root = process.cwd();
|
|
const sourcePdf = path.join(root, 'Patentes', 'SOLICITUD_PATENTE_OEPM_FARMAFINDER.pdf');
|
|
const outDir = path.join(root, 'Patentes');
|
|
|
|
function ensureExists(file) {
|
|
if (!fs.existsSync(file)) {
|
|
throw new Error(`Missing file: ${file}`);
|
|
}
|
|
}
|
|
|
|
function run(cmd, args) {
|
|
execFileSync(cmd, args, { stdio: 'inherit' });
|
|
}
|
|
|
|
function mergePages(output, pages) {
|
|
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'farmafinder-clean-'));
|
|
run('pdfseparate', [sourcePdf, path.join(tmp, 'page-%d.pdf')]);
|
|
const inputs = pages.map((n) => path.join(tmp, `page-${n}.pdf`));
|
|
run('pdfunite', [...inputs, output]);
|
|
}
|
|
|
|
function esc(s) {
|
|
return String(s).replace(/\\/g, '\\\\').replace(/\(/g, '\\(').replace(/\)/g, '\\)');
|
|
}
|
|
|
|
function latin1(s) {
|
|
return Buffer.from(s, 'latin1').toString('latin1');
|
|
}
|
|
|
|
function wrapText(text, widthChars) {
|
|
const words = String(text).split(/\s+/);
|
|
const lines = [];
|
|
let line = '';
|
|
for (const word of words) {
|
|
const candidate = line ? `${line} ${word}` : word;
|
|
if (candidate.length > widthChars && line) {
|
|
lines.push(line);
|
|
line = word;
|
|
} else {
|
|
line = candidate;
|
|
}
|
|
}
|
|
if (line) lines.push(line);
|
|
return lines;
|
|
}
|
|
|
|
function writeDrawingsPdf(output) {
|
|
const PAGE_W = 595.28;
|
|
const PAGE_H = 841.89;
|
|
const MARGIN_L = 56;
|
|
const MARGIN_R = 56;
|
|
const MARGIN_T = 56;
|
|
const MARGIN_B = 54;
|
|
const CONTENT_W = PAGE_W - MARGIN_L - MARGIN_R;
|
|
|
|
const lines = [
|
|
{ type: 'title', text: 'Dibujos' },
|
|
{ type: 'subtitle', text: 'Bloque limpio para la presentación de la solicitud' },
|
|
{ type: 'spacer', lines: 1 },
|
|
{ type: 'heading', text: 'Breve descripción de los dibujos' },
|
|
{ type: 'paragraph', text: 'Figura 1. Diagrama de bloques general del sistema.' },
|
|
{ type: 'paragraph', text: 'Figura 2. Flujo de captura y validación del escaneo de la TSI.' },
|
|
{ type: 'paragraph', text: 'Figura 3. Flujo de contraste entre necesidad terapéutica y stock de farmacias.' },
|
|
{ type: 'paragraph', text: 'Figura 4. Flujo de acción cuando no existe stock disponible.' },
|
|
{ type: 'spacer', lines: 1 },
|
|
{ type: 'heading', text: 'Nota' },
|
|
{ type: 'paragraph', text: 'El documento fuente contiene referencias esquemáticas a las figuras, pero no incluye láminas técnicas dibujadas de forma separada. Si la Oficina requiere placas gráficas, habrá que añadirlas antes de la presentación definitiva.' },
|
|
];
|
|
|
|
const objects = [''];
|
|
const add = (body) => {
|
|
objects.push(body);
|
|
return objects.length - 1;
|
|
};
|
|
const fontReg = add('<< /Type /Font /Subtype /Type1 /BaseFont /Times-Roman /Encoding /WinAnsiEncoding >>');
|
|
const fontBold = add('<< /Type /Font /Subtype /Type1 /BaseFont /Times-Bold /Encoding /WinAnsiEncoding >>');
|
|
const fontIt = add('<< /Type /Font /Subtype /Type1 /BaseFont /Times-Italic /Encoding /WinAnsiEncoding >>');
|
|
const pagesTree = add('');
|
|
|
|
const ops = [];
|
|
let y = PAGE_H - MARGIN_T;
|
|
const write = (txt, x, size, font = 'F1') => {
|
|
ops.push(`BT /${font} ${size} Tf ${x} ${y} Td (${esc(latin1(txt))}) Tj ET`);
|
|
y -= size * 1.25;
|
|
};
|
|
const ensure = (needed) => y - needed > MARGIN_B;
|
|
for (const item of lines) {
|
|
if (item.type === 'title') {
|
|
for (const line of wrapText(item.text, 26)) write(line, MARGIN_L + 175, 18, 'F2');
|
|
continue;
|
|
}
|
|
if (item.type === 'subtitle') {
|
|
for (const line of wrapText(item.text, 40)) write(line, MARGIN_L + 45, 11.5, 'F3');
|
|
y -= 6;
|
|
continue;
|
|
}
|
|
if (item.type === 'spacer') {
|
|
y -= (item.lines || 1) * 12;
|
|
continue;
|
|
}
|
|
if (item.type === 'heading') {
|
|
if (!ensure(20)) break;
|
|
write(item.text, MARGIN_L, 13, 'F2');
|
|
y -= 2;
|
|
ops.push(`0.3 w ${MARGIN_L} ${y} m ${PAGE_W - MARGIN_R} ${y} l S`);
|
|
y -= 8;
|
|
continue;
|
|
}
|
|
if (item.type === 'paragraph') {
|
|
const wrapped = wrapText(item.text, 80);
|
|
if (!ensure(wrapped.length * 14 + 6)) break;
|
|
for (const line of wrapped) write(line, MARGIN_L, 11.5, 'F1');
|
|
y -= 2;
|
|
}
|
|
}
|
|
ops.push(`BT /F1 9 Tf ${PAGE_W - 100} ${24} Td (Page 1) Tj ET`);
|
|
const content = ops.join('\n');
|
|
const contentObj = add(`<< /Length ${Buffer.byteLength(content, 'latin1')} >>\nstream\n${content}\nendstream`);
|
|
const pageObj = add(`<< /Type /Page /Parent ${pagesTree} 0 R /MediaBox [0 0 ${PAGE_W} ${PAGE_H}] /Resources << /Font << /F1 ${fontReg} 0 R /F2 ${fontBold} 0 R /F3 ${fontIt} 0 R >> >> /Contents ${contentObj} 0 R >>`);
|
|
objects[pagesTree] = `<< /Type /Pages /Kids [${pageObj} 0 R] /Count 1 >>`;
|
|
const catalog = add(`<< /Type /Catalog /Pages ${pagesTree} 0 R >>`);
|
|
|
|
let pdf = '%PDF-1.4\n';
|
|
const offsets = [0];
|
|
for (let i = 1; i < objects.length; i += 1) {
|
|
offsets[i] = Buffer.byteLength(pdf, 'latin1');
|
|
pdf += `${i} 0 obj\n${objects[i]}\nendobj\n`;
|
|
}
|
|
const xref = Buffer.byteLength(pdf, 'latin1');
|
|
pdf += `xref\n0 ${objects.length}\n`;
|
|
pdf += '0000000000 65535 f \n';
|
|
for (let i = 1; i < objects.length; i += 1) {
|
|
pdf += `${String(offsets[i]).padStart(10, '0')} 00000 n \n`;
|
|
}
|
|
pdf += `trailer << /Size ${objects.length} /Root ${catalog} 0 R >>\nstartxref\n${xref}\n%%EOF\n`;
|
|
fs.writeFileSync(output, Buffer.from(pdf, 'latin1'));
|
|
}
|
|
|
|
ensureExists(sourcePdf);
|
|
mergePages(path.join(outDir, 'SOLICITUD_PATENTE_OEPM_FARMAFINDER_descripcion_limpia.pdf'), [2, 3, 4]);
|
|
mergePages(path.join(outDir, 'SOLICITUD_PATENTE_OEPM_FARMAFINDER_reivindicaciones_limpia.pdf'), [5]);
|
|
mergePages(path.join(outDir, 'SOLICITUD_PATENTE_OEPM_FARMAFINDER_resumen_limpia.pdf'), [6]);
|
|
writeDrawingsPdf(path.join(outDir, 'SOLICITUD_PATENTE_OEPM_FARMAFINDER_dibujos_limpia.pdf'));
|
|
|
|
console.log('Clean section PDFs generated.');
|