thibaud frere commited on
Commit
98af9a5
·
1 Parent(s): 89de168
app/scripts/export-pdf.mjs CHANGED
@@ -64,6 +64,29 @@ function parseMargin(margin) {
64
  return { top: parts[0] || '12mm', right: parts[1] || '12mm', bottom: parts[2] || '16mm', left: parts[3] || '12mm' };
65
  }
66
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  async function waitForImages(page, timeoutMs = 15000) {
68
  await page.evaluate(async (timeout) => {
69
  const deadline = Date.now() + timeout;
@@ -149,9 +172,15 @@ async function main() {
149
  } catch {}
150
  }, theme);
151
  const page = await context.newPage();
 
 
 
 
 
152
  await page.goto(baseUrl, { waitUntil: 'load', timeout: 60000 });
153
  // Give time for CDN scripts (Plotly/D3) to attach and for our fragment hooks to run
154
  try { await page.waitForFunction(() => !!window.Plotly, { timeout: 8000 }); } catch {}
 
155
  // Compute slug from title if needed
156
  if (!args.filename) {
157
  const title = await page.evaluate(() => {
 
64
  return { top: parts[0] || '12mm', right: parts[1] || '12mm', bottom: parts[2] || '16mm', left: parts[3] || '12mm' };
65
  }
66
 
67
+ function cssLengthToMm(val) {
68
+ if (!val) return 0;
69
+ const s = String(val).trim();
70
+ if (/mm$/i.test(s)) return parseFloat(s);
71
+ if (/cm$/i.test(s)) return parseFloat(s) * 10;
72
+ if (/in$/i.test(s)) return parseFloat(s) * 25.4;
73
+ if (/px$/i.test(s)) return (parseFloat(s) / 96) * 25.4; // 96 CSS px per inch
74
+ const num = parseFloat(s);
75
+ return Number.isFinite(num) ? num : 0; // assume mm if unitless
76
+ }
77
+
78
+ function getFormatSizeMm(format) {
79
+ const f = String(format || 'A4').toLowerCase();
80
+ switch (f) {
81
+ case 'letter': return { w: 215.9, h: 279.4 };
82
+ case 'legal': return { w: 215.9, h: 355.6 };
83
+ case 'a3': return { w: 297, h: 420 };
84
+ case 'tabloid': return { w: 279.4, h: 431.8 };
85
+ case 'a4':
86
+ default: return { w: 210, h: 297 };
87
+ }
88
+ }
89
+
90
  async function waitForImages(page, timeoutMs = 15000) {
91
  await page.evaluate(async (timeout) => {
92
  const deadline = Date.now() + timeout;
 
172
  } catch {}
173
  }, theme);
174
  const page = await context.newPage();
175
+ // Pre-fit viewport width to printable width so charts size correctly
176
+ const fmt = getFormatSizeMm(format);
177
+ const mw = fmt.w - cssLengthToMm(margin.left) - cssLengthToMm(margin.right);
178
+ const printableWidthPx = Math.max(320, Math.round((mw / 25.4) * 96));
179
+ await page.setViewportSize({ width: printableWidthPx, height: 1200 });
180
  await page.goto(baseUrl, { waitUntil: 'load', timeout: 60000 });
181
  // Give time for CDN scripts (Plotly/D3) to attach and for our fragment hooks to run
182
  try { await page.waitForFunction(() => !!window.Plotly, { timeout: 8000 }); } catch {}
183
+ try { await page.waitForFunction(() => !!window.d3, { timeout: 8000 }); } catch {}
184
  // Compute slug from title if needed
185
  if (!args.filename) {
186
  const title = await page.evaluate(() => {
app/src/components/HtmlFragment.astro CHANGED
@@ -51,8 +51,8 @@ const mountId = `frag-${Math.random().toString(36).slice(2)}`;
51
  }
52
  });
53
  };
54
- // Ensure execution when ready: run now if Plotly is present or document already loaded; otherwise wait for 'load'
55
- if (window.Plotly || document.readyState === 'complete') execute();
56
  else window.addEventListener('load', execute, { once: true });
57
  </script>
58
 
 
51
  }
52
  });
53
  };
54
+ // Ensure execution when ready: run now if Plotly or D3 is present, or when document is ready; otherwise wait for 'load'
55
+ if (window.Plotly || window.d3 || document.readyState === 'complete') execute();
56
  else window.addEventListener('load', execute, { once: true });
57
  </script>
58
 
app/src/content/article.mdx CHANGED
@@ -402,7 +402,9 @@ Favor **concise captions** and callouts that clarify what to look at and why it
402
 
403
  ### Use the right color scale
404
 
405
- Choosing colors well is critical: a **palette** encodes **meaning** (categories, magnitudes, oppositions), preserves **readability** and **accessibility** (**sufficient contrast**, **color‑vision safety**), and ensures **perceptually smooth transitions**. The three families below illustrate when to use **categorical**, **sequential**, or **diverging** colors and how they evolve from the same **reference hue**.
 
 
406
 
407
  <div className="">
408
  <HtmlFragment src="palettes.html" />
 
402
 
403
  ### Use the right color scale
404
 
405
+ A **palette** encodes **meaning** (categories, magnitudes, oppositions), preserves **readability** and **accessibility** (**sufficient contrast**, **color‑vision safety**), and ensures **perceptually smooth transitions**.
406
+
407
+ The three families below illustrate when to use **categorical**, **sequential**, or **diverging** colors and how they evolve from the same **reference hue**.
408
 
409
  <div className="">
410
  <HtmlFragment src="palettes.html" />
app/src/pages/index.astro CHANGED
@@ -1,7 +1,6 @@
1
  ---
2
  import Article, { frontmatter as articleFM } from '../content/article.mdx';
3
  import Meta from '../components/Meta.astro';
4
- import HtmlFragment from '../components/HtmlFragment.astro';
5
  import Footer from '../components/Footer.astro';
6
  import Header from '../components/Header.astro';
7
  import ThemeToggle from '../components/ThemeToggle.astro';
 
1
  ---
2
  import Article, { frontmatter as articleFM } from '../content/article.mdx';
3
  import Meta from '../components/Meta.astro';
 
4
  import Footer from '../components/Footer.astro';
5
  import Header from '../components/Header.astro';
6
  import ThemeToggle from '../components/ThemeToggle.astro';