Skip to content

Commit a828c54

Browse files
committed
update
1 parent 02aee22 commit a828c54

File tree

10 files changed

+1221
-4
lines changed

10 files changed

+1221
-4
lines changed

.github/workflows/generate-download-files.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ jobs:
2727
git config --global user.email ${{ env.COMMIT_EMAIL }}
2828
yarn install
2929
yarn scripts:create:shareable_guides
30+
yarn scripts:create:shareable_guides_pdf
31+
32+
3033
echo "[END]"
3134
git add .
3235
git commit -m "docs: update downloadable files" || echo "Up to date with main"

_data/downloadFiles/PT_BR/agile.html

Lines changed: 415 additions & 0 deletions
Large diffs are not rendered by default.
281 KB
Binary file not shown.
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// Function to group list items with checkboxes
2+
export function groupCheckboxListItems(html: string): string {
3+
// Use regex to find <ul> blocks and process them
4+
return html.replace(/<ul>([\s\S]*?)<\/ul>/g, (match, ulContent) => {
5+
// Split the content by <li> tags
6+
const listItems = ulContent.split(/(?=<li>)/);
7+
let result = "<ul>";
8+
9+
for (let i = 0; i < listItems.length; i++) {
10+
const item = listItems[i];
11+
if (item.trim() === "") continue;
12+
13+
// Check if this <li> contains a checkbox
14+
if (item.includes("<input") && item.includes('type="checkbox"')) {
15+
// Find all subsequent non-checkbox items until the next checkbox
16+
const nestedItems: string[] = [];
17+
let j = i + 1;
18+
while (j < listItems.length) {
19+
const nextItem = listItems[j];
20+
if (nextItem.trim() === "") {
21+
j++;
22+
continue;
23+
}
24+
// If we hit another checkbox, stop
25+
if (
26+
nextItem.includes("<input") &&
27+
nextItem.includes('type="checkbox"')
28+
) {
29+
break;
30+
}
31+
nestedItems.push(nextItem);
32+
j++;
33+
}
34+
35+
// Create the checkbox item with nested list
36+
if (nestedItems.length > 0) {
37+
// Remove the closing </li> from the checkbox item
38+
const checkboxItem = item.replace(/<\/li>$/, "");
39+
result += checkboxItem;
40+
result += "<ul>";
41+
result += nestedItems.join("");
42+
result += "</ul></li>";
43+
// Skip the items we've already processed
44+
i = j - 1;
45+
} else {
46+
result += item;
47+
}
48+
} else {
49+
// This is a regular list item, add it directly
50+
result += item;
51+
}
52+
}
53+
54+
result += "</ul>";
55+
return result;
56+
});
57+
}
58+
59+
// Function to wrap input tags with span for custom styling
60+
export function wrapInputTagsWithSpan(html: string): string {
61+
return html.replace(
62+
/(<input[^>]*type="checkbox"[^>]*>)/g,
63+
'<span class="checkbox-wrapper">$1</span>'
64+
);
65+
}
66+
67+
// Main function to process HTML with all transformations
68+
export function processHtml(html: string): string {
69+
let processedHtml = html;
70+
71+
// First wrap input tags with spans
72+
processedHtml = wrapInputTagsWithSpan(processedHtml);
73+
74+
// Then group checkbox list items
75+
processedHtml = groupCheckboxListItems(processedHtml);
76+
77+
return processedHtml;
78+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import { log } from "@scripts/modules/infra/log";
2+
import * as fs from "fs";
3+
import * as path from "path";
4+
import puppeteer from "puppeteer";
5+
import { parseMarkdownToHTML } from "./parseMarkdownToHTML";
6+
import { processHtml } from "./htmlProcessor";
7+
8+
// Function to load HTML template
9+
function loadTemplate(): string {
10+
const templatePath = path.join(__dirname, "template.html");
11+
return fs.readFileSync(templatePath, "utf-8");
12+
}
13+
14+
const main = async () => {
15+
try {
16+
log("Starting PDF generation for Agile guide...");
17+
18+
// Read the markdown file
19+
const markdownPath = path.join(
20+
process.cwd(),
21+
"_data",
22+
"downloadFiles",
23+
"PT_BR",
24+
"agile.md"
25+
);
26+
log(`Reading markdown file from: ${markdownPath}`);
27+
28+
if (!fs.existsSync(markdownPath)) {
29+
throw new Error(`Markdown file not found: ${markdownPath}`);
30+
}
31+
32+
const markdownContent = fs.readFileSync(markdownPath, "utf-8");
33+
log("Markdown file read successfully");
34+
35+
// Convert markdown to HTML using the parseMarkdownToHTML function
36+
const htmlContent = parseMarkdownToHTML({ markdown: markdownContent });
37+
38+
// Process HTML with custom transformations
39+
const styledHtmlContent = processHtml(htmlContent);
40+
log("Markdown converted to HTML");
41+
42+
// Load template and create the complete HTML document
43+
const template = loadTemplate();
44+
const completeHtml = template
45+
.replace("{{content}}", styledHtmlContent)
46+
.replace("{{date}}", new Date().toLocaleDateString("pt-BR"));
47+
48+
// Get the directory where the markdown file is located
49+
const markdownDir = path.dirname(markdownPath);
50+
51+
// Save HTML file for debugging
52+
const htmlPath = path.join(markdownDir, "agile.html");
53+
fs.writeFileSync(htmlPath, completeHtml);
54+
log(`HTML file saved to: ${htmlPath}`);
55+
56+
// Generate PDF using Puppeteer
57+
log("Launching Puppeteer...");
58+
const browser = await puppeteer.launch({
59+
headless: true,
60+
args: ["--no-sandbox", "--disable-setuid-sandbox"],
61+
});
62+
63+
const page = await browser.newPage();
64+
65+
// Set content and wait for rendering
66+
await page.setContent(completeHtml, { waitUntil: "networkidle0" });
67+
68+
// Generate PDF in the same directory as the markdown file
69+
const pdfPath = path.join(markdownDir, "agile.pdf");
70+
await page.pdf({
71+
path: pdfPath,
72+
format: "A4",
73+
margin: {
74+
top: "20mm",
75+
right: "20mm",
76+
bottom: "20mm",
77+
left: "20mm",
78+
},
79+
printBackground: true,
80+
});
81+
82+
await browser.close();
83+
log(`PDF generated successfully: ${pdfPath}`);
84+
} catch (error) {
85+
log(`Error generating PDF: ${error}`);
86+
process.exit(1);
87+
}
88+
};
89+
90+
main();
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { marked } from "marked";
2+
3+
interface parseMarkdownToHTMLParams {
4+
markdown: string;
5+
singleLine?: boolean;
6+
}
7+
export function parseMarkdownToHTML({
8+
markdown,
9+
singleLine = false,
10+
}: parseMarkdownToHTMLParams) {
11+
const html = marked(trimLines(markdown), {
12+
async: false,
13+
});
14+
const hasOnlyOneParagraph = html.match(/<p>/g)?.length === 1;
15+
16+
if (singleLine && hasOnlyOneParagraph) {
17+
return html?.replace(/<p>|<\/p>/g, "").trim();
18+
}
19+
20+
return html.trim();
21+
}
22+
23+
function trimLines(str: string) {
24+
return str?.replace(/^ +/gm, "");
25+
}

0 commit comments

Comments
 (0)