spec-up-t 1.1.54 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/compiled/body.js +59 -8
- package/assets/compiled/head.css +13 -12
- package/assets/css/adjust-font-size.css +11 -0
- package/assets/css/collapse-meta-info.css +27 -8
- package/assets/css/create-term-filter.css +11 -0
- package/assets/css/index.css +15 -0
- package/assets/css/prism.css +176 -153
- package/assets/css/prism.dark.css +157 -0
- package/assets/css/prism.default.css +180 -0
- package/assets/css/terms-and-definitions.1.css +223 -0
- package/assets/css/terms-and-definitions.css +214 -100
- package/assets/js/addAnchorsToTerms.js +1 -1
- package/assets/js/collapse-definitions.js +2 -1
- package/assets/js/collapse-meta-info.js +25 -11
- package/assets/js/create-term-filter.js +61 -0
- package/assets/js/horizontal-scroll-hint.js +159 -0
- package/assets/js/index.1.js +137 -0
- package/assets/js/index.js +2 -1
- package/assets/js/insert-trefs.js +122 -116
- package/assets/js/insert-xrefs.1.js +372 -0
- package/assets/js/{show-commit-hashes.js → insert-xrefs.js} +67 -7
- package/assets/js/prism.dark.js +24 -0
- package/assets/js/prism.default.js +23 -0
- package/assets/js/prism.js +4 -5
- package/assets/js/search.js +1 -1
- package/assets/js/toggle-dense-info.js +40 -0
- package/branches.md +4 -29
- package/index.js +397 -189
- package/index.new.js +662 -0
- package/package.json +1 -1
- package/src/asset-map.json +9 -5
- package/src/collect-external-references.js +16 -9
- package/src/collectExternalReferences/fetchTermsFromIndex.js +328 -0
- package/src/collectExternalReferences/processXTrefsData.js +73 -18
- package/src/create-pdf.js +385 -89
- package/src/health-check/external-specs-checker.js +207 -0
- package/src/health-check/output-gitignore-checker.js +261 -0
- package/src/health-check/specs-configuration-checker.js +274 -0
- package/src/health-check/term-references-checker.js +191 -0
- package/src/health-check/terms-intro-checker.js +81 -0
- package/src/health-check/tref-term-checker.js +463 -0
- package/src/health-check.js +445 -0
- package/src/install-from-boilerplate/config-scripts-keys.js +2 -0
- package/src/install-from-boilerplate/menu.sh +6 -3
- package/src/markdown-it-extensions.js +134 -103
- package/src/prepare-tref.js +61 -24
- package/src/utils/fetch.js +100 -0
- package/templates/template.html +12 -7
- package/assets/js/css-helper.js +0 -30
- package/src/collectExternalReferences/fetchTermsFromGitHubRepository.js +0 -232
- package/src/collectExternalReferences/fetchTermsFromGitHubRepository.test.js +0 -385
- package/src/collectExternalReferences/octokitClient.js +0 -96
package/src/create-pdf.js
CHANGED
|
@@ -19,39 +19,61 @@ const pdfLib = require('pdf-lib');
|
|
|
19
19
|
|
|
20
20
|
// Extract the output_path from the specs.json file
|
|
21
21
|
const outputPath = config.specs[0].output_path;
|
|
22
|
+
|
|
23
|
+
// Extract title and description from the config
|
|
24
|
+
const title = config.specs[0].title || '';
|
|
25
|
+
const description = config.specs[0].description || '';
|
|
26
|
+
const logo = config.specs[0].logo || '';
|
|
27
|
+
const logoLink = config.specs[0].logo_link || '#';
|
|
22
28
|
|
|
23
29
|
// Define the path to the HTML file based on the directory where the script is called from
|
|
24
30
|
const filePath = path.resolve(process.cwd(), outputPath, 'index.html');
|
|
25
31
|
const fileUrl = `file://${filePath}`;
|
|
26
32
|
|
|
33
|
+
// Path to Bootstrap CSS file
|
|
34
|
+
const bootstrapCssPath = path.resolve(process.cwd(), 'assets/css/bootstrap.min.css');
|
|
35
|
+
|
|
36
|
+
// Check if Bootstrap CSS file exists
|
|
37
|
+
const bootstrapExists = fs.existsSync(bootstrapCssPath);
|
|
38
|
+
|
|
39
|
+
// Read Bootstrap CSS if it exists
|
|
40
|
+
let bootstrapCss = '';
|
|
41
|
+
if (bootstrapExists) {
|
|
42
|
+
bootstrapCss = fs.readFileSync(bootstrapCssPath, 'utf8');
|
|
43
|
+
}
|
|
44
|
+
|
|
27
45
|
// Navigate to the HTML file
|
|
28
46
|
await page.goto(fileUrl, { waitUntil: 'networkidle2' });
|
|
29
47
|
|
|
30
|
-
//
|
|
48
|
+
// Handle cross-reference terms that may be fetched from another domain
|
|
31
49
|
const targetClass = '.fetched-xref-term';
|
|
32
|
-
|
|
33
|
-
//
|
|
34
|
-
const hasTargetElements = await page.evaluate((targetClass) => {
|
|
35
|
-
return document.querySelectorAll(targetClass).length > 0;
|
|
36
|
-
}, targetClass);
|
|
37
|
-
|
|
38
|
-
// Fetch the initial innerText of the element
|
|
50
|
+
|
|
51
|
+
// Try to get the first element with the target class
|
|
39
52
|
const targetElement = await page.$(targetClass);
|
|
40
|
-
|
|
41
|
-
|
|
53
|
+
|
|
54
|
+
// If such an element exists, wait for its content to be fully loaded
|
|
55
|
+
if (targetElement) {
|
|
56
|
+
const targetText = await page.evaluate(el => el.innerText, targetElement);
|
|
42
57
|
await page.waitForFunction(
|
|
43
58
|
(targetClass, targetText) => {
|
|
44
59
|
const element = document.querySelector(targetClass);
|
|
45
60
|
return element && element.innerText !== targetText;
|
|
46
61
|
},
|
|
47
|
-
{}, //
|
|
62
|
+
{}, // Additional options if needed
|
|
48
63
|
targetClass,
|
|
49
64
|
targetText
|
|
50
65
|
);
|
|
51
66
|
}
|
|
52
67
|
|
|
53
|
-
// Inject CSS to set padding
|
|
54
|
-
await page.evaluate(() => {
|
|
68
|
+
// Inject CSS to set padding, enforce system fonts, and apply Bootstrap print styles
|
|
69
|
+
await page.evaluate((bootstrapCss) => {
|
|
70
|
+
// Add Bootstrap CSS including its print media queries
|
|
71
|
+
if (bootstrapCss) {
|
|
72
|
+
const bootstrapStyle = document.createElement('style');
|
|
73
|
+
bootstrapStyle.innerHTML = bootstrapCss;
|
|
74
|
+
document.head.appendChild(bootstrapStyle);
|
|
75
|
+
}
|
|
76
|
+
|
|
55
77
|
const style = document.createElement('style');
|
|
56
78
|
style.innerHTML = `
|
|
57
79
|
@page {
|
|
@@ -62,15 +84,162 @@ const pdfLib = require('pdf-lib');
|
|
|
62
84
|
border: none;
|
|
63
85
|
}
|
|
64
86
|
|
|
65
|
-
/* Override all fonts with system fonts */
|
|
87
|
+
/* Override all fonts with system fonts and increase base font size */
|
|
66
88
|
* {
|
|
67
89
|
font-family: Arial, Helvetica, sans-serif !important;
|
|
68
90
|
}
|
|
91
|
+
|
|
92
|
+
/* Set base font size to improve readability */
|
|
93
|
+
body {
|
|
94
|
+
font-size: 14pt !important; /* Medium font size */
|
|
95
|
+
line-height: 1.5 !important;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/* Adjust heading sizes proportionally */
|
|
99
|
+
h1 { font-size: 22pt !important; font-weight: bold !important; }
|
|
100
|
+
h2 { font-size: 20pt !important; font-weight: bold !important; }
|
|
101
|
+
h3 { font-size: 18pt !important; font-weight: bold !important; }
|
|
102
|
+
h4 { font-size: 16pt !important; font-weight: bold !important; }
|
|
103
|
+
h5 { font-size: 15pt !important; font-weight: bold !important; }
|
|
104
|
+
h6 { font-size: 14pt !important; font-weight: bold !important; }
|
|
105
|
+
|
|
106
|
+
/* Make pre and code blocks more readable */
|
|
107
|
+
pre, code {
|
|
108
|
+
font-size: 13pt !important;
|
|
109
|
+
line-height: 1.4 !important;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/* Make table text more readable */
|
|
113
|
+
table, th, td {
|
|
114
|
+
font-size: 13pt !important;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/* Additional print-specific styles */
|
|
118
|
+
@media print {
|
|
119
|
+
a[href]:after {
|
|
120
|
+
content: none !important;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.container {
|
|
124
|
+
width: auto;
|
|
125
|
+
max-width: 100%;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/* Improve page breaks */
|
|
129
|
+
h1, h2, h3, h4, h5, h6 {
|
|
130
|
+
page-break-after: avoid;
|
|
131
|
+
margin-top: 1.2em !important;
|
|
132
|
+
margin-bottom: 0.6em !important;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
img {
|
|
136
|
+
page-break-inside: avoid;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
table {
|
|
140
|
+
page-break-inside: avoid;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
pre, blockquote {
|
|
144
|
+
page-break-inside: avoid;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/* Add Bootstrap print classes explicitly */
|
|
148
|
+
.d-print-none {
|
|
149
|
+
display: none !important;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.d-print-block {
|
|
153
|
+
display: block !important;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.d-print-inline {
|
|
157
|
+
display: inline !important;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.d-print-inline-block {
|
|
161
|
+
display: inline-block !important;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.d-print-flex {
|
|
165
|
+
display: flex !important;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.d-print-inline-flex {
|
|
169
|
+
display: inline-flex !important;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
69
172
|
`;
|
|
70
173
|
document.head.appendChild(style);
|
|
174
|
+
}, bootstrapCss);
|
|
175
|
+
|
|
176
|
+
// Apply Bootstrap classes to elements in the page
|
|
177
|
+
await page.evaluate(() => {
|
|
178
|
+
// Add container class to body for better formatting
|
|
179
|
+
document.body.classList.add('container-fluid', 'print');
|
|
180
|
+
|
|
181
|
+
// Add Bootstrap classes to headings
|
|
182
|
+
document.querySelectorAll('h1, h2, h3, h4, h5, h6').forEach(heading => {
|
|
183
|
+
heading.classList.add('mt-4', 'mb-3');
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
// Add Bootstrap classes to tables
|
|
187
|
+
document.querySelectorAll('table').forEach(table => {
|
|
188
|
+
table.classList.add('table', 'table-bordered', 'mb-4');
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
// Add Bootstrap classes to code blocks
|
|
192
|
+
document.querySelectorAll('pre').forEach(pre => {
|
|
193
|
+
pre.classList.add('p-3', 'bg-light', 'border', 'rounded');
|
|
194
|
+
});
|
|
71
195
|
});
|
|
72
196
|
|
|
73
|
-
//
|
|
197
|
+
// Inject logo, title and description at the top of the document
|
|
198
|
+
await page.evaluate((logo, logoLink, title, description) => {
|
|
199
|
+
// Create wrapper for the logo, title and description using Bootstrap classes
|
|
200
|
+
const titleWrapper = document.createElement('div');
|
|
201
|
+
titleWrapper.className = 'text-center mb-5 pb-4 border-bottom';
|
|
202
|
+
|
|
203
|
+
// Add the logo if it exists
|
|
204
|
+
if (logo) {
|
|
205
|
+
const logoContainer = document.createElement('a');
|
|
206
|
+
logoContainer.href = logoLink || '#';
|
|
207
|
+
logoContainer.className = 'd-block mb-3';
|
|
208
|
+
|
|
209
|
+
const logoImg = document.createElement('img');
|
|
210
|
+
logoImg.src = logo;
|
|
211
|
+
logoImg.className = 'img-fluid';
|
|
212
|
+
logoImg.style.maxHeight = '90px'; // Moderate logo size
|
|
213
|
+
logoImg.alt = title || 'Logo';
|
|
214
|
+
|
|
215
|
+
logoContainer.appendChild(logoImg);
|
|
216
|
+
titleWrapper.appendChild(logoContainer);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Create and style the title element
|
|
220
|
+
if (title) {
|
|
221
|
+
const titleElement = document.createElement('h1');
|
|
222
|
+
titleElement.textContent = title;
|
|
223
|
+
titleElement.className = 'display-4 mb-2'; // Moderate title size
|
|
224
|
+
titleElement.style.fontSize = '26pt'; // Explicitly set title font size
|
|
225
|
+
titleWrapper.appendChild(titleElement);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Create and style the description element
|
|
229
|
+
if (description) {
|
|
230
|
+
const descriptionElement = document.createElement('p');
|
|
231
|
+
descriptionElement.textContent = description;
|
|
232
|
+
descriptionElement.className = 'lead';
|
|
233
|
+
descriptionElement.style.fontSize = '16pt'; // Explicitly set description font size
|
|
234
|
+
titleWrapper.appendChild(descriptionElement);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Insert at the top of the body
|
|
238
|
+
const body = document.body;
|
|
239
|
+
body.insertBefore(titleWrapper, body.firstChild);
|
|
240
|
+
}, logo, logoLink, title, description);
|
|
241
|
+
|
|
242
|
+
// Remove or hide elements not needed for print
|
|
74
243
|
await page.evaluate(() => {
|
|
75
244
|
// Remove elements with display: none
|
|
76
245
|
const hiddenElements = document.querySelectorAll('[style*="display: none"]');
|
|
@@ -78,115 +247,242 @@ const pdfLib = require('pdf-lib');
|
|
|
78
247
|
element.remove();
|
|
79
248
|
});
|
|
80
249
|
|
|
250
|
+
// Remove elements that should be hidden in print
|
|
251
|
+
document.querySelectorAll('.d-print-none').forEach(element => {
|
|
252
|
+
element.remove();
|
|
253
|
+
});
|
|
254
|
+
|
|
81
255
|
// Remove all script elements
|
|
82
256
|
const scriptElements = document.querySelectorAll('script');
|
|
83
257
|
scriptElements.forEach((element) => {
|
|
84
258
|
element.remove();
|
|
85
259
|
});
|
|
86
260
|
|
|
87
|
-
// Remove
|
|
88
|
-
const styleElements = document.querySelectorAll('style');
|
|
261
|
+
// Remove most style elements (keeping Bootstrap)
|
|
262
|
+
const styleElements = document.querySelectorAll('style:not([data-bootstrap])');
|
|
89
263
|
styleElements.forEach((element) => {
|
|
90
264
|
element.remove();
|
|
91
265
|
});
|
|
92
266
|
|
|
93
|
-
//
|
|
94
|
-
// const images = document.querySelectorAll('img');
|
|
95
|
-
// images.forEach((img) => {
|
|
96
|
-
// img.remove();
|
|
97
|
-
// });
|
|
98
|
-
|
|
99
|
-
const displayNoneInPdf = document.querySelectorAll('#header span, #container-search-h7vc6omi2hr2880, .btn'); // Adjust the selector as needed
|
|
100
|
-
if (displayNoneInPdf) {
|
|
101
|
-
displayNoneInPdf.forEach((element) => {
|
|
102
|
-
element.remove();
|
|
103
|
-
// or
|
|
104
|
-
// element.style.display = 'none';
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// Set terms and defs backgrounds to white to save ink when printing
|
|
267
|
+
// Improve styling for definition terms and descriptions
|
|
109
268
|
const termsAndDefs = document.querySelectorAll('dt,dd');
|
|
110
269
|
termsAndDefs.forEach((element) => {
|
|
270
|
+
// Base styling for all terms and definitions
|
|
111
271
|
element.style.backgroundColor = 'white';
|
|
112
272
|
element.style.border = 'none';
|
|
273
|
+
element.style.pageBreakInside = 'avoid'; // Avoid page breaks within terms/definitions
|
|
274
|
+
|
|
275
|
+
if (element.tagName === 'DT') {
|
|
276
|
+
// Styling specifically for definition terms
|
|
277
|
+
element.style.fontWeight = 'bold';
|
|
278
|
+
element.style.marginTop = '1.3em';
|
|
279
|
+
element.style.paddingBottom = '0.4em';
|
|
280
|
+
element.style.borderBottom = '1px solid #e0e0e0';
|
|
281
|
+
element.style.fontSize = '16pt'; // Moderate font size for definition terms
|
|
282
|
+
} else if (element.tagName === 'DD') {
|
|
283
|
+
// Styling specifically for definition descriptions
|
|
284
|
+
element.style.paddingLeft = '1.5em';
|
|
285
|
+
element.style.paddingTop = '0.6em';
|
|
286
|
+
element.style.paddingBottom = '0.8em';
|
|
287
|
+
element.style.marginBottom = '0.8em';
|
|
288
|
+
element.style.textAlign = 'justify';
|
|
289
|
+
element.style.fontSize = '14pt'; // Moderate font size for definition descriptions
|
|
290
|
+
|
|
291
|
+
// Style tables inside definition descriptions
|
|
292
|
+
const tables = element.querySelectorAll('table');
|
|
293
|
+
tables.forEach(table => {
|
|
294
|
+
table.style.width = '100%';
|
|
295
|
+
table.style.marginTop = '0.6em';
|
|
296
|
+
table.style.marginBottom = '0.6em';
|
|
297
|
+
table.style.borderCollapse = 'collapse';
|
|
298
|
+
|
|
299
|
+
// Style table cells
|
|
300
|
+
const cells = table.querySelectorAll('th, td');
|
|
301
|
+
cells.forEach(cell => {
|
|
302
|
+
cell.style.border = '1px solid #ddd';
|
|
303
|
+
cell.style.padding = '0.4em';
|
|
304
|
+
cell.style.fontSize = '13pt'; // Moderate font size for table cells
|
|
305
|
+
});
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
// Ensure proper spacing between definition groups
|
|
311
|
+
const dts = document.querySelectorAll('dt');
|
|
312
|
+
dts.forEach((dt, index) => {
|
|
313
|
+
if (index > 0) {
|
|
314
|
+
dt.style.marginTop = '2em'; // Add moderate space between definition groups
|
|
315
|
+
}
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
// Set moderate font size for paragraphs and list items
|
|
319
|
+
document.querySelectorAll('p, li').forEach(element => {
|
|
320
|
+
element.style.fontSize = '14pt'; // Moderate size for paragraphs and lists
|
|
321
|
+
element.style.margin = '0.4em 0';
|
|
322
|
+
element.style.lineHeight = '1.5';
|
|
113
323
|
});
|
|
324
|
+
|
|
325
|
+
// Set moderate font size for code blocks and inline code
|
|
326
|
+
document.querySelectorAll('pre code, code').forEach(element => {
|
|
327
|
+
element.style.fontSize = '13pt'; // Moderate size for code blocks
|
|
328
|
+
});
|
|
329
|
+
});
|
|
114
330
|
|
|
115
|
-
|
|
331
|
+
// Add hierarchical section numbering for PDF output only
|
|
332
|
+
await page.evaluate(() => {
|
|
116
333
|
const style = document.createElement('style');
|
|
117
334
|
style.innerHTML = `
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
335
|
+
@media print {
|
|
336
|
+
/* Base styles for all numbered elements */
|
|
337
|
+
article#content h1,
|
|
338
|
+
article#content h2,
|
|
339
|
+
article#content h3,
|
|
340
|
+
article#content h4,
|
|
341
|
+
article#content h5,
|
|
342
|
+
article#content h6,
|
|
343
|
+
article#content dt {
|
|
344
|
+
position: relative;
|
|
345
|
+
padding-left: 2.8em; /* Moderate padding for better readability */
|
|
346
|
+
text-indent: 0;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/* Number styling for all heading levels */
|
|
350
|
+
article#content h1::before,
|
|
351
|
+
article#content h2::before,
|
|
352
|
+
article#content h3::before,
|
|
353
|
+
article#content h4::before,
|
|
354
|
+
article#content h5::before,
|
|
355
|
+
article#content h6::before,
|
|
356
|
+
article#content dt::before {
|
|
357
|
+
position: absolute;
|
|
358
|
+
left: 0;
|
|
359
|
+
font-weight: bold;
|
|
360
|
+
color: #333;
|
|
361
|
+
font-size: 100%; /* Match the font size of the respective heading */
|
|
362
|
+
}
|
|
132
363
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
364
|
+
/* Counter setup for the root element */
|
|
365
|
+
article#content {
|
|
366
|
+
counter-reset: h1;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/* Level 1 headings */
|
|
370
|
+
article#content h1 {
|
|
371
|
+
counter-increment: h1;
|
|
372
|
+
counter-reset: h2;
|
|
373
|
+
padding-left: 1.9em; /* Specific padding for h1 */
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
article#content h1::before {
|
|
377
|
+
content: counter(h1) ".";
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/* Level 2 headings */
|
|
381
|
+
article#content h2 {
|
|
382
|
+
counter-increment: h2;
|
|
383
|
+
counter-reset: h3;
|
|
384
|
+
padding-left: 2.6em; /* Specific padding for h2 */
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
article#content h2::before {
|
|
388
|
+
content: counter(h1) "." counter(h2) ".";
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
/* Level 3 headings */
|
|
392
|
+
article#content h3 {
|
|
393
|
+
counter-increment: h3;
|
|
394
|
+
counter-reset: h4;
|
|
395
|
+
padding-left: 3.3em; /* Specific padding for h3 */
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
article#content h3::before {
|
|
399
|
+
content: counter(h1) "." counter(h2) "." counter(h3) ".";
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/* Level 4 headings */
|
|
403
|
+
article#content h4 {
|
|
404
|
+
counter-increment: h4;
|
|
405
|
+
counter-reset: h5;
|
|
406
|
+
padding-left: 4em; /* Specific padding for h4 */
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
article#content h4::before {
|
|
410
|
+
content: counter(h1) "." counter(h2) "." counter(h3) "." counter(h4) ".";
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/* Level 5 headings */
|
|
414
|
+
article#content h5 {
|
|
415
|
+
counter-increment: h5;
|
|
416
|
+
counter-reset: h6;
|
|
417
|
+
padding-left: 4.7em; /* Specific padding for h5 */
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
article#content h5::before {
|
|
421
|
+
content: counter(h1) "." counter(h2) "." counter(h3) "." counter(h4) "." counter(h5) ".";
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/* Level 6 headings */
|
|
425
|
+
article#content h6 {
|
|
426
|
+
counter-increment: h6;
|
|
427
|
+
padding-left: 5.4em; /* Specific padding for h6 */
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
article#content h6::before {
|
|
431
|
+
content: counter(h1) "." counter(h2) "." counter(h3) "." counter(h4) "." counter(h5) "." counter(h6) ".";
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/* Definition terms - treat as level 3 since they appear under level 2 headings */
|
|
435
|
+
article#content dt {
|
|
436
|
+
counter-increment: h3;
|
|
437
|
+
padding-left: 3.3em; /* Match h3 padding */
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
article#content dt::before {
|
|
441
|
+
content: counter(h1) "." counter(h2) "." counter(h3) ".";
|
|
442
|
+
position: absolute;
|
|
443
|
+
left: 0;
|
|
444
|
+
/* Improve vertical alignment with the text */
|
|
445
|
+
top: 50%;
|
|
446
|
+
transform: translateY(-50%);
|
|
447
|
+
line-height: normal;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/* Add spacing after the numbers */
|
|
451
|
+
article#content h1::before,
|
|
452
|
+
article#content h2::before,
|
|
453
|
+
article#content h3::before,
|
|
454
|
+
article#content h4::before,
|
|
455
|
+
article#content h5::before,
|
|
456
|
+
article#content h6::before,
|
|
457
|
+
article#content dt::before {
|
|
458
|
+
margin-right: 0.4em;
|
|
459
|
+
}
|
|
168
460
|
}
|
|
169
461
|
`;
|
|
170
462
|
document.head.appendChild(style);
|
|
171
463
|
});
|
|
172
464
|
|
|
173
|
-
|
|
174
465
|
// Generate the PDF with optimized settings
|
|
175
466
|
const pdfBuffer = await page.pdf({
|
|
176
467
|
path: path.resolve(process.cwd(), 'docs/index.pdf'), // Output file path
|
|
177
468
|
format: 'A4', // Paper format
|
|
178
469
|
displayHeaderFooter: false, // Do not display header and footer
|
|
179
470
|
preferCSSPageSize: true, // Use CSS-defined page size
|
|
180
|
-
printBackground:
|
|
181
|
-
quality:
|
|
182
|
-
|
|
471
|
+
printBackground: true, // Enable background graphics for Bootstrap styling
|
|
472
|
+
quality: 100, // Maximum quality for images
|
|
473
|
+
margin: {
|
|
474
|
+
top: '18mm', // Moderate margins for better readability
|
|
475
|
+
bottom: '18mm',
|
|
476
|
+
left: '18mm',
|
|
477
|
+
right: '18mm',
|
|
478
|
+
}
|
|
183
479
|
});
|
|
184
480
|
|
|
185
481
|
await browser.close();
|
|
186
482
|
|
|
187
483
|
// Load the PDF with pdf-lib to remove metadata and optimize fonts
|
|
188
484
|
const pdfDoc = await pdfLib.PDFDocument.load(pdfBuffer);
|
|
189
|
-
pdfDoc.setTitle(
|
|
485
|
+
pdfDoc.setTitle(title);
|
|
190
486
|
pdfDoc.setAuthor('');
|
|
191
487
|
pdfDoc.setSubject('');
|
|
192
488
|
pdfDoc.setKeywords([]);
|
|
@@ -197,7 +493,7 @@ const pdfLib = require('pdf-lib');
|
|
|
197
493
|
const optimizedPdfBytes = await pdfDoc.save();
|
|
198
494
|
fs.writeFileSync('docs/index.pdf', optimizedPdfBytes);
|
|
199
495
|
|
|
200
|
-
console.log('✅ PDF generated successfully! Find the PDF in the
|
|
496
|
+
console.log('✅ PDF generated successfully! Find the PDF in the docs directory.');
|
|
201
497
|
} catch (error) {
|
|
202
498
|
console.error('❌ Error generating PDF:', error);
|
|
203
499
|
}
|