pi-studio 0.5.24 → 0.5.25

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.
Files changed (3) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/index.ts +17 -5
  3. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -4,6 +4,11 @@ All notable changes to `pi-studio` are documented here.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.5.25] — 2026-03-21
8
+
9
+ ### Fixed
10
+ - Studio PDF exports now add more space below ruled section headings to keep bibliography entries clear of the `References` underline, and figure captions now use left-aligned ragged-right formatting for long multi-line captions, including reinjected PDF subfigure groups, without disturbing normal figure centering.
11
+
7
12
  ## [0.5.24] — 2026-03-20
8
13
 
9
14
  ### Fixed
package/index.ts CHANGED
@@ -175,11 +175,13 @@ const CMUX_STUDIO_STATUS_COLOR_DARK = "#5ea1ff";
175
175
  const CMUX_STUDIO_STATUS_COLOR_LIGHT = "#0047ab";
176
176
 
177
177
  const PDF_PREAMBLE = `\\usepackage{titlesec}
178
- \\titleformat{\\section}{\\Large\\bfseries\\sffamily}{}{0pt}{}[\\vspace{2pt}\\titlerule]
178
+ \\titleformat{\\section}{\\Large\\bfseries\\sffamily}{}{0pt}{}[\\vspace{3pt}\\titlerule\\vspace{12pt}]
179
179
  \\titleformat{\\subsection}{\\large\\bfseries\\sffamily}{}{0pt}{}
180
180
  \\titleformat{\\subsubsection}{\\normalsize\\bfseries\\sffamily}{}{0pt}{}
181
181
  \\titlespacing*{\\section}{0pt}{1.5ex plus 0.5ex minus 0.2ex}{1ex plus 0.2ex}
182
182
  \\titlespacing*{\\subsection}{0pt}{1.2ex plus 0.4ex minus 0.2ex}{0.6ex plus 0.1ex}
183
+ \\usepackage{caption}
184
+ \\captionsetup[figure]{justification=raggedright,singlelinecheck=false}
183
185
  \\usepackage{enumitem}
184
186
  \\setlist[itemize]{nosep, leftmargin=1.5em}
185
187
  \\setlist[enumerate]{nosep, leftmargin=1.5em}
@@ -1827,7 +1829,7 @@ function buildStudioLatexInjectedPdfSubfigureBlock(
1827
1829
  ? (group.caption ? `\\textbf{${figureLabel}} ${group.caption}` : `\\textbf{${figureLabel}}`)
1828
1830
  : (group.caption ? group.caption : "");
1829
1831
 
1830
- const minipageBlocks = group.items.map((item) => {
1832
+ const minipageBlocks = group.items.map((item) => {
1831
1833
  const widthSpec = item.widthSpec || "0.48\\textwidth";
1832
1834
  const imageCommand = `\\includegraphics${item.imageOptions ? `[${item.imageOptions}]` : "[width=\\linewidth]"}{${item.imagePath}}`;
1833
1835
  const subfigureLabel = formatStudioLatexSubfigureCaptionLabel(item.label, labels);
@@ -1838,7 +1840,7 @@ function buildStudioLatexInjectedPdfSubfigureBlock(
1838
1840
  `\\begin{minipage}[t]{${widthSpec}}`,
1839
1841
  "\\centering",
1840
1842
  imageCommand,
1841
- captionLine ? `\\par\\smallskip ${captionLine}` : "",
1843
+ captionLine ? `\\par\\smallskip{\\raggedright ${captionLine}\\par}` : "",
1842
1844
  "\\end{minipage}",
1843
1845
  ].filter(Boolean);
1844
1846
  return {
@@ -1866,7 +1868,7 @@ function buildStudioLatexInjectedPdfSubfigureBlock(
1866
1868
  "\\begin{figure}[p]",
1867
1869
  "\\centering",
1868
1870
  rows.join("\n\\par\\medskip\n"),
1869
- figureCaption ? `\\par\\bigskip ${figureCaption}` : "",
1871
+ figureCaption ? `\\par\\bigskip{\\raggedright ${figureCaption}\\par}` : "",
1870
1872
  "\\end{figure}",
1871
1873
  "\\clearpage",
1872
1874
  ].filter(Boolean);
@@ -1909,6 +1911,15 @@ function injectStudioLatexPdfSubfigureBlocks(
1909
1911
  return transformed;
1910
1912
  }
1911
1913
 
1914
+ function normalizeStudioGeneratedFigureCaptions(latex: string): string {
1915
+ return String(latex ?? "").replace(/\\begin\{figure\*?\}(?:\[[^\]]*\])?[\s\S]*?\\end\{figure\*?\}/g, (figureEnv) => {
1916
+ return String(figureEnv).replace(/\\caption(\[[^\]]*\])?\{/g, (_match, optionalArg) => {
1917
+ const suffix = typeof optionalArg === "string" ? optionalArg : "";
1918
+ return `\\captionsetup{justification=raggedright,singlelinecheck=false}\\caption${suffix}{\\raggedright `;
1919
+ });
1920
+ });
1921
+ }
1922
+
1912
1923
  function formatStudioLatexMainAlgorithmCaptionLabel(label: string | null, labels: Map<string, { number: string; kind: string }>): string | null {
1913
1924
  const normalizedLabel = String(label ?? "").trim();
1914
1925
  if (!normalizedLabel) return null;
@@ -3004,7 +3015,8 @@ async function renderStudioPdfFromGeneratedLatex(
3004
3015
 
3005
3016
  const generatedLatex = await readFile(latexPath, "utf-8");
3006
3017
  const injectedLatex = injectStudioLatexPdfSubfigureBlocks(generatedLatex, subfigureGroups, sourcePath, resourcePath);
3007
- await writeFile(latexPath, injectedLatex, "utf-8");
3018
+ const normalizedLatex = normalizeStudioGeneratedFigureCaptions(injectedLatex);
3019
+ await writeFile(latexPath, normalizedLatex, "utf-8");
3008
3020
 
3009
3021
  await new Promise<void>((resolve, reject) => {
3010
3022
  const child = spawn(pdfEngine, [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-studio",
3
- "version": "0.5.24",
3
+ "version": "0.5.25",
4
4
  "description": "Browser GUI for structured critique workflows in pi",
5
5
  "type": "module",
6
6
  "license": "MIT",