pi-studio 0.9.32 → 0.9.33
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/CHANGELOG.md +14 -0
- package/README.md +1 -1
- package/client/studio-client.js +20 -3
- package/client/studio.css +44 -28
- package/index.ts +63 -12
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,20 @@ All notable changes to `pi-studio` are documented here.
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.9.33] — 2026-06-16
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
- Added `Cmd/Ctrl+Alt+E` to switch the right pane directly to Editor Preview.
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
- Calmed annotation and comment affordance styling so annotations read more like highlighted feedback and less like heavy badges.
|
|
14
|
+
- Slightly muted active Stop button styling while keeping it in the theme error colour family.
|
|
15
|
+
- Derived PDF annotation colours from the active theme accent hue while keeping a light, print-friendly background.
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
- Preserved the Working view scroll position when switching between `All`, `Thinking`, and `Tools` filters unless the view was already pinned to the bottom.
|
|
19
|
+
- Rendered standalone long `[an: ...]` annotations correctly in LaTeX-mode PDF exports even when Pandoc wraps the escaped marker across generated LaTeX lines.
|
|
20
|
+
|
|
7
21
|
## [0.9.32] — 2026-06-10
|
|
8
22
|
|
|
9
23
|
### Added
|
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@ Extension for [pi](https://pi.dev) that opens a local two-pane browser workspace
|
|
|
22
22
|
- Supports one canonical full Studio view per Pi session, plus additional editor-only companion views when you want extra editing/preview surfaces; editor-only views can also browse files and use the Studio REPL send controls without taking over the full Studio session view
|
|
23
23
|
- Includes a global **Zen** mode for hiding secondary Studio chrome without changing the current left/right pane layout
|
|
24
24
|
- Runs editor text directly, asks for structured critique (auto/writing/code focus), offers a manual **Suggest completion** action for short cursor-aware continuations (`Option/Alt+Tab` where available or `Cmd/Ctrl+Shift+Space` from the editor, `Tab` to insert a visible suggestion) with an optional editor-plus-latest-response context mode, or opens **Quiz me** for a Studio-native active-recall loop over the current editor text, selection, current file, folder, or repo, with optional focus guidance for shaping question selection
|
|
25
|
-
- Includes a live **Working** view for following current model/tool activity, with `All` / `Thinking` / `Tools` filters, image previews for image-producing tool outputs, plus **Load visible into editor** and **Copy visible** actions; when cycling response history, Working follows saved working details for the selected response when available, and `Cmd/Ctrl+Alt+
|
|
25
|
+
- Includes a live **Working** view for following current model/tool activity, with `All` / `Thinking` / `Tools` filters, image previews for image-producing tool outputs, plus **Load visible into editor** and **Copy visible** actions; when cycling response history, Working follows saved working details for the selected response when available, and `Cmd/Ctrl+Alt+P` / `Cmd/Ctrl+Alt+E` / `Cmd/Ctrl+Alt+W` switch directly between Response Preview, Editor Preview, and Working
|
|
26
26
|
- Includes a right-pane **Changes** view for browsing the current git diff by file, previewing per-file diffs, opening changed files, loading the full diff into the editor, and copying the diff
|
|
27
27
|
- Includes a right-pane **Files** view for browsing the current Pi session/resource directory, opening folders, opening the Files root in Finder/the system file manager, loading text/code/CSV/TSV documents into the editor, previewing PDFs/images, opening PDF/image previews in a new Studio tab, converting DOCX/ODT documents to editable Markdown when Pandoc is available after confirmation, copying paths, setting the current folder as the Studio working directory, and revealing files in the file manager
|
|
28
28
|
- Includes an optional tmux-backed **REPL** view for Shell, Python, IPython, Julia, R, GHCi, and Clojure sessions, with Raw/Literate send modes, `Cmd/Ctrl+Shift+Enter` **Send to REPL**, session start/stop/interrupt controls, a compact refresh-persistent **Studio REPL Record** of user and Pi-sent code, a secondary raw tmux mirror, agent-facing `studio_repl_status` / `studio_repl_send` tools, and Markdown/PDF/HTML export
|
package/client/studio-client.js
CHANGED
|
@@ -269,8 +269,8 @@
|
|
|
269
269
|
option.disabled = isEditorOnlyMode && !editorOnlyAllowed.has(option.value);
|
|
270
270
|
});
|
|
271
271
|
rightViewSelect.title = isEditorOnlyMode
|
|
272
|
-
? "Editor-only views: editor preview, Changes, Files, or REPL. F7 cycles when the right pane is active; Cmd/Ctrl+Alt+P switches directly to Preview."
|
|
273
|
-
: "Right pane view mode. F7 cycles when the right pane is active; Cmd/Ctrl+Alt+P switches directly to Preview; Cmd/Ctrl+Alt+W switches directly to Working.";
|
|
272
|
+
? "Editor-only views: editor preview, Changes, Files, or REPL. F7 cycles when the right pane is active; Cmd/Ctrl+Alt+P or Cmd/Ctrl+Alt+E switches directly to Preview."
|
|
273
|
+
: "Right pane view mode. F7 cycles when the right pane is active; Cmd/Ctrl+Alt+P switches directly to Response Preview; Cmd/Ctrl+Alt+E switches directly to Editor Preview; Cmd/Ctrl+Alt+W switches directly to Working.";
|
|
274
274
|
}
|
|
275
275
|
|
|
276
276
|
function getInitialRightView(source) {
|
|
@@ -859,7 +859,7 @@
|
|
|
859
859
|
const normalized = normalizeTraceFilter(nextFilter);
|
|
860
860
|
if (traceFilter === normalized) return;
|
|
861
861
|
traceFilter = normalized;
|
|
862
|
-
traceAutoScroll =
|
|
862
|
+
traceAutoScroll = rightView === "trace" ? shouldStickTraceToBottom() : traceAutoScroll;
|
|
863
863
|
renderTraceViewIfActive();
|
|
864
864
|
}
|
|
865
865
|
|
|
@@ -3817,6 +3817,13 @@
|
|
|
3817
3817
|
setStatus("Right pane view: Working.");
|
|
3818
3818
|
}
|
|
3819
3819
|
|
|
3820
|
+
function switchRightPaneToEditorPreview() {
|
|
3821
|
+
const snapshot = snapshotStudioScrollablePositions();
|
|
3822
|
+
setRightView("editor-preview");
|
|
3823
|
+
scheduleStudioScrollablePositionRestore(snapshot);
|
|
3824
|
+
setStatus("Right pane view: Editor (Preview).");
|
|
3825
|
+
}
|
|
3826
|
+
|
|
3820
3827
|
function cycleActivePaneView(direction) {
|
|
3821
3828
|
if (activePane === "right") {
|
|
3822
3829
|
if (!rightViewSelect || rightViewSelect.disabled) {
|
|
@@ -4135,6 +4142,16 @@
|
|
|
4135
4142
|
return;
|
|
4136
4143
|
}
|
|
4137
4144
|
|
|
4145
|
+
const isEditorPreviewShortcut = (key.toLowerCase() === "e" || code === "KeyE")
|
|
4146
|
+
&& (event.metaKey || event.ctrlKey)
|
|
4147
|
+
&& event.altKey
|
|
4148
|
+
&& !event.shiftKey;
|
|
4149
|
+
if (isEditorPreviewShortcut) {
|
|
4150
|
+
event.preventDefault();
|
|
4151
|
+
switchRightPaneToEditorPreview();
|
|
4152
|
+
return;
|
|
4153
|
+
}
|
|
4154
|
+
|
|
4138
4155
|
const isContentFocusShortcut = key === "F8" && !event.metaKey && !event.ctrlKey && !event.altKey;
|
|
4139
4156
|
if (isContentFocusShortcut) {
|
|
4140
4157
|
event.preventDefault();
|
package/client/studio.css
CHANGED
|
@@ -210,15 +210,17 @@
|
|
|
210
210
|
|
|
211
211
|
#sendRunBtn.request-stop-active,
|
|
212
212
|
#critiqueBtn.request-stop-active {
|
|
213
|
-
background: var(--error);
|
|
214
|
-
border-color: var(--error);
|
|
213
|
+
background: color-mix(in srgb, var(--error) 82%, var(--panel));
|
|
214
|
+
border-color: color-mix(in srgb, var(--error) 88%, var(--panel));
|
|
215
215
|
color: var(--error-contrast);
|
|
216
|
-
font-weight:
|
|
216
|
+
font-weight: 700;
|
|
217
217
|
}
|
|
218
218
|
|
|
219
219
|
#sendRunBtn.request-stop-active:not(:disabled):hover,
|
|
220
220
|
#critiqueBtn.request-stop-active:not(:disabled):hover {
|
|
221
|
-
|
|
221
|
+
background: var(--error);
|
|
222
|
+
border-color: var(--error);
|
|
223
|
+
filter: none;
|
|
222
224
|
}
|
|
223
225
|
|
|
224
226
|
.file-label {
|
|
@@ -930,17 +932,17 @@
|
|
|
930
932
|
padding: 0 10px;
|
|
931
933
|
font-size: 12px;
|
|
932
934
|
line-height: 1;
|
|
933
|
-
background: var(--accent-soft);
|
|
934
|
-
border-color: var(--
|
|
935
|
-
color: var(--
|
|
935
|
+
background: color-mix(in srgb, var(--panel) 88%, var(--accent-soft));
|
|
936
|
+
border-color: var(--control-border);
|
|
937
|
+
color: var(--text);
|
|
936
938
|
box-shadow: 0 1px 2px var(--shadow-color);
|
|
937
939
|
}
|
|
938
940
|
|
|
939
941
|
.editor-selection-action-btn:hover,
|
|
940
942
|
.editor-selection-action-btn:focus-visible {
|
|
941
|
-
background: var(--accent-soft
|
|
943
|
+
background: var(--accent-soft);
|
|
942
944
|
color: var(--accent);
|
|
943
|
-
border-color: var(--accent);
|
|
945
|
+
border-color: color-mix(in srgb, var(--accent) 45%, var(--control-border));
|
|
944
946
|
}
|
|
945
947
|
|
|
946
948
|
.editor-selection-actions[hidden],
|
|
@@ -1043,12 +1045,12 @@
|
|
|
1043
1045
|
}
|
|
1044
1046
|
|
|
1045
1047
|
.hl-annotation {
|
|
1046
|
-
color: var(--accent);
|
|
1047
|
-
background: var(--accent-soft);
|
|
1048
|
+
color: color-mix(in srgb, var(--accent) 72%, var(--text));
|
|
1049
|
+
background: color-mix(in srgb, var(--accent-soft) 58%, transparent);
|
|
1048
1050
|
border: 0;
|
|
1049
|
-
border-radius:
|
|
1051
|
+
border-radius: 3px;
|
|
1050
1052
|
padding: 0;
|
|
1051
|
-
box-shadow: inset 0 0 0
|
|
1053
|
+
box-shadow: inset 0 -0.08em 0 color-mix(in srgb, var(--accent) 26%, transparent);
|
|
1052
1054
|
}
|
|
1053
1055
|
|
|
1054
1056
|
.hl-annotation-muted {
|
|
@@ -1057,10 +1059,10 @@
|
|
|
1057
1059
|
}
|
|
1058
1060
|
|
|
1059
1061
|
.annotation-preview-marker {
|
|
1060
|
-
color: var(--accent);
|
|
1061
|
-
background: var(--accent-soft);
|
|
1062
|
-
border: 1px solid var(--marker-border);
|
|
1063
|
-
border-radius:
|
|
1062
|
+
color: color-mix(in srgb, var(--accent) 72%, var(--text));
|
|
1063
|
+
background: color-mix(in srgb, var(--accent-soft) 58%, transparent);
|
|
1064
|
+
border: 1px solid color-mix(in srgb, var(--marker-border) 26%, transparent);
|
|
1065
|
+
border-radius: 3px;
|
|
1064
1066
|
display: inline-block;
|
|
1065
1067
|
max-width: 100%;
|
|
1066
1068
|
padding: 0 4px;
|
|
@@ -1068,6 +1070,20 @@
|
|
|
1068
1070
|
vertical-align: baseline;
|
|
1069
1071
|
}
|
|
1070
1072
|
|
|
1073
|
+
.annotation-preview-marker strong {
|
|
1074
|
+
color: color-mix(in srgb, var(--accent) 82%, var(--text));
|
|
1075
|
+
font-weight: 750;
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
.annotation-preview-marker em {
|
|
1079
|
+
color: color-mix(in srgb, currentColor 82%, var(--muted));
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1082
|
+
.annotation-preview-marker s {
|
|
1083
|
+
color: color-mix(in srgb, currentColor 70%, var(--muted));
|
|
1084
|
+
text-decoration-thickness: 0.08em;
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1071
1087
|
.annotation-preview-marker code {
|
|
1072
1088
|
font-family: var(--mono-font, ui-monospace, SFMono-Regular, Menlo, monospace);
|
|
1073
1089
|
font-size: 0.95em;
|
|
@@ -1216,9 +1232,9 @@
|
|
|
1216
1232
|
padding: 0 10px;
|
|
1217
1233
|
font-size: 12px;
|
|
1218
1234
|
line-height: 1;
|
|
1219
|
-
background: var(--accent-soft);
|
|
1220
|
-
border-color: var(--
|
|
1221
|
-
color: var(--
|
|
1235
|
+
background: color-mix(in srgb, var(--panel) 88%, var(--accent-soft));
|
|
1236
|
+
border-color: var(--control-border);
|
|
1237
|
+
color: var(--text);
|
|
1222
1238
|
box-shadow: 0 1px 2px var(--shadow-color);
|
|
1223
1239
|
pointer-events: auto;
|
|
1224
1240
|
}
|
|
@@ -1227,9 +1243,9 @@
|
|
|
1227
1243
|
.preview-comment-add:focus-visible,
|
|
1228
1244
|
.preview-comment-jump:hover,
|
|
1229
1245
|
.preview-comment-jump:focus-visible {
|
|
1230
|
-
background: var(--accent-soft
|
|
1246
|
+
background: var(--accent-soft);
|
|
1231
1247
|
color: var(--accent);
|
|
1232
|
-
border-color: var(--accent);
|
|
1248
|
+
border-color: color-mix(in srgb, var(--accent) 45%, var(--control-border));
|
|
1233
1249
|
}
|
|
1234
1250
|
|
|
1235
1251
|
.preview-jump-highlight {
|
|
@@ -5779,10 +5795,10 @@
|
|
|
5779
5795
|
}
|
|
5780
5796
|
|
|
5781
5797
|
body.studio-ui-refresh .studio-refresh-review-btn.request-stop-active {
|
|
5782
|
-
background: var(--error);
|
|
5783
|
-
border-color: var(--error);
|
|
5798
|
+
background: color-mix(in srgb, var(--error) 82%, var(--panel));
|
|
5799
|
+
border-color: color-mix(in srgb, var(--error) 88%, var(--panel));
|
|
5784
5800
|
color: var(--error-contrast);
|
|
5785
|
-
font-weight:
|
|
5801
|
+
font-weight: 700;
|
|
5786
5802
|
}
|
|
5787
5803
|
|
|
5788
5804
|
body.studio-ui-refresh .studio-refresh-review-btn.request-stop-active::after {
|
|
@@ -5790,10 +5806,10 @@
|
|
|
5790
5806
|
}
|
|
5791
5807
|
|
|
5792
5808
|
body.studio-ui-refresh .studio-refresh-menu #critiqueBtn.request-stop-active {
|
|
5793
|
-
background: var(--error);
|
|
5794
|
-
border-color: var(--error);
|
|
5809
|
+
background: color-mix(in srgb, var(--error) 82%, var(--panel));
|
|
5810
|
+
border-color: color-mix(in srgb, var(--error) 88%, var(--panel));
|
|
5795
5811
|
color: var(--error-contrast);
|
|
5796
|
-
font-weight:
|
|
5812
|
+
font-weight: 700;
|
|
5797
5813
|
}
|
|
5798
5814
|
|
|
5799
5815
|
.studio-preview-link-menu {
|
package/index.ts
CHANGED
|
@@ -1066,7 +1066,23 @@ function buildStudioPdfCalloutTitleSizeCommand(options?: StudioPdfRenderOptions)
|
|
|
1066
1066
|
return "\\footnotesize";
|
|
1067
1067
|
}
|
|
1068
1068
|
|
|
1069
|
-
function
|
|
1069
|
+
function formatStudioPdfHtmlColor(color: string, fallback: string): string {
|
|
1070
|
+
return hexToRgb(color) ? color.replace(/^#/, "").toUpperCase() : fallback;
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
function buildStudioPdfAnnotationColors(style: StudioThemeStyle): { bg: string; border: string; text: string } {
|
|
1074
|
+
const accent = hexToRgb(style.palette.accent) ? style.palette.accent : "#2F6FEB";
|
|
1075
|
+
const page = "#FFFFFF";
|
|
1076
|
+
const darkText = "#0E1616";
|
|
1077
|
+
return {
|
|
1078
|
+
bg: formatStudioPdfHtmlColor(blendColors(accent, page, 0.91), "F1F7FF"),
|
|
1079
|
+
border: formatStudioPdfHtmlColor(blendColors(accent, page, 0.68), "C7DDFF"),
|
|
1080
|
+
text: formatStudioPdfHtmlColor(blendColors(accent, darkText, style.mode === "light" ? 0.40 : 0.34), "1F5FBF"),
|
|
1081
|
+
};
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
function buildStudioPdfPreamble(options?: StudioPdfRenderOptions, extraPreamble = "", themeStyle?: StudioThemeStyle): string {
|
|
1085
|
+
const annotationColors = buildStudioPdfAnnotationColors(themeStyle ?? getStudioThemeStyle());
|
|
1070
1086
|
const sectionHeadingSize = buildStudioPdfHeadingSizeCommand(options?.sectionSize, "\\Large");
|
|
1071
1087
|
const subsectionHeadingSize = buildStudioPdfHeadingSizeCommand(options?.subsectionSize, "\\large");
|
|
1072
1088
|
const subsubsectionHeadingSize = buildStudioPdfHeadingSizeCommand(options?.subsubsectionSize, "\\normalsize");
|
|
@@ -1088,9 +1104,9 @@ function buildStudioPdfPreamble(options?: StudioPdfRenderOptions, extraPreamble
|
|
|
1088
1104
|
\\usepackage{xcolor}
|
|
1089
1105
|
\\usepackage{varwidth}
|
|
1090
1106
|
\\usepackage[normalem]{ulem}
|
|
1091
|
-
\\definecolor{StudioAnnotationBg}{HTML}{
|
|
1092
|
-
\\definecolor{StudioAnnotationBorder}{HTML}{
|
|
1093
|
-
\\definecolor{StudioAnnotationText}{HTML}{
|
|
1107
|
+
\\definecolor{StudioAnnotationBg}{HTML}{${annotationColors.bg}}
|
|
1108
|
+
\\definecolor{StudioAnnotationBorder}{HTML}{${annotationColors.border}}
|
|
1109
|
+
\\definecolor{StudioAnnotationText}{HTML}{${annotationColors.text}}
|
|
1094
1110
|
\\definecolor{StudioCodeBlockBg}{HTML}{F6F8FA}
|
|
1095
1111
|
\\definecolor{StudioDiffAddText}{HTML}{1A7F37}
|
|
1096
1112
|
\\definecolor{StudioDiffDelText}{HTML}{CF222E}
|
|
@@ -6501,9 +6517,20 @@ ${literalPdfConfig.fontSizeCommand}\\section*{${title.replace(/[{}\\]/g, "").tri
|
|
|
6501
6517
|
function replaceStudioAnnotationMarkersInGeneratedLatex(latex: string): string {
|
|
6502
6518
|
const lines = String(latex ?? "").split("\n");
|
|
6503
6519
|
const out: string[] = [];
|
|
6520
|
+
const pendingTextLines: string[] = [];
|
|
6504
6521
|
const rawEnvStack: string[] = [];
|
|
6505
6522
|
const rawEnvNames = new Set(["verbatim", "Verbatim", "Highlighting", "lstlisting"]);
|
|
6506
6523
|
|
|
6524
|
+
const hasRawEnvBoundary = (line: string): boolean => {
|
|
6525
|
+
const envPattern = /\\(begin|end)\{([^}]+)\}/g;
|
|
6526
|
+
let match: RegExpExecArray | null;
|
|
6527
|
+
while ((match = envPattern.exec(line)) !== null) {
|
|
6528
|
+
const envName = match[2];
|
|
6529
|
+
if (envName && rawEnvNames.has(envName)) return true;
|
|
6530
|
+
}
|
|
6531
|
+
return false;
|
|
6532
|
+
};
|
|
6533
|
+
|
|
6507
6534
|
const updateRawEnvStack = (line: string) => {
|
|
6508
6535
|
const envPattern = /\\(begin|end)\{([^}]+)\}/g;
|
|
6509
6536
|
let match: RegExpExecArray | null;
|
|
@@ -6524,6 +6551,12 @@ function replaceStudioAnnotationMarkersInGeneratedLatex(latex: string): string {
|
|
|
6524
6551
|
}
|
|
6525
6552
|
};
|
|
6526
6553
|
|
|
6554
|
+
const flushPendingText = () => {
|
|
6555
|
+
if (pendingTextLines.length === 0) return;
|
|
6556
|
+
out.push(replaceStudioAnnotationMarkersForPdfInSegment(pendingTextLines.join("\n")));
|
|
6557
|
+
pendingTextLines.length = 0;
|
|
6558
|
+
};
|
|
6559
|
+
|
|
6527
6560
|
for (const line of lines) {
|
|
6528
6561
|
if (rawEnvStack.length > 0) {
|
|
6529
6562
|
out.push(line);
|
|
@@ -6531,10 +6564,17 @@ function replaceStudioAnnotationMarkersInGeneratedLatex(latex: string): string {
|
|
|
6531
6564
|
continue;
|
|
6532
6565
|
}
|
|
6533
6566
|
|
|
6534
|
-
|
|
6535
|
-
|
|
6567
|
+
if (hasRawEnvBoundary(line)) {
|
|
6568
|
+
flushPendingText();
|
|
6569
|
+
out.push(line);
|
|
6570
|
+
updateRawEnvStack(line);
|
|
6571
|
+
continue;
|
|
6572
|
+
}
|
|
6573
|
+
|
|
6574
|
+
pendingTextLines.push(line);
|
|
6536
6575
|
}
|
|
6537
6576
|
|
|
6577
|
+
flushPendingText();
|
|
6538
6578
|
return out.join("\n");
|
|
6539
6579
|
}
|
|
6540
6580
|
|
|
@@ -6727,6 +6767,7 @@ async function renderStudioPdfFromGeneratedLatex(
|
|
|
6727
6767
|
alignedImageBlocks: StudioPdfAlignedImageBlock[] = [],
|
|
6728
6768
|
pdfOptions?: StudioPdfRenderOptions,
|
|
6729
6769
|
extraPreamble = "",
|
|
6770
|
+
themeStyle?: StudioThemeStyle,
|
|
6730
6771
|
): Promise<{ pdf: Buffer; warning?: string }> {
|
|
6731
6772
|
const tempDir = join(tmpdir(), `pi-studio-pdf-${Date.now()}-${randomUUID()}`);
|
|
6732
6773
|
const preamblePath = join(tempDir, "_pdf_preamble.tex");
|
|
@@ -6734,7 +6775,7 @@ async function renderStudioPdfFromGeneratedLatex(
|
|
|
6734
6775
|
const outputPath = join(tempDir, "studio-export.pdf");
|
|
6735
6776
|
|
|
6736
6777
|
await mkdir(tempDir, { recursive: true });
|
|
6737
|
-
await writeFile(preamblePath, buildStudioPdfPreamble(pdfOptions, extraPreamble), "utf-8");
|
|
6778
|
+
await writeFile(preamblePath, buildStudioPdfPreamble(pdfOptions, extraPreamble, themeStyle), "utf-8");
|
|
6738
6779
|
|
|
6739
6780
|
const pandocArgs = [
|
|
6740
6781
|
"-f", inputFormat,
|
|
@@ -6805,6 +6846,7 @@ async function renderStudioPdfWithPandoc(
|
|
|
6805
6846
|
editorPdfLanguage?: string,
|
|
6806
6847
|
sourcePath?: string,
|
|
6807
6848
|
pdfOptions?: StudioPdfRenderOptions,
|
|
6849
|
+
themeStyle?: StudioThemeStyle,
|
|
6808
6850
|
): Promise<{ pdf: Buffer; warning?: string }> {
|
|
6809
6851
|
const pandocCommand = process.env.PANDOC_PATH?.trim() || "pandoc";
|
|
6810
6852
|
const pdfEngine = process.env.PANDOC_PDF_ENGINE?.trim() || "xelatex";
|
|
@@ -6842,7 +6884,7 @@ async function renderStudioPdfWithPandoc(
|
|
|
6842
6884
|
const outputPath = join(tempDir, "studio-export.pdf");
|
|
6843
6885
|
|
|
6844
6886
|
await mkdir(tempDir, { recursive: true });
|
|
6845
|
-
await writeFile(preamblePath, buildStudioPdfPreamble(pdfOptions), "utf-8");
|
|
6887
|
+
await writeFile(preamblePath, buildStudioPdfPreamble(pdfOptions, "", themeStyle), "utf-8");
|
|
6846
6888
|
|
|
6847
6889
|
const hasYamlHeaderIncludesForPdf = inputFormat !== "latex" && hasStudioYamlHeaderIncludes(markdownForPdf);
|
|
6848
6890
|
const headerIncludeArgs = hasYamlHeaderIncludesForPdf ? [] : ["--include-in-header", preamblePath];
|
|
@@ -6895,6 +6937,8 @@ async function renderStudioPdfWithPandoc(
|
|
|
6895
6937
|
[],
|
|
6896
6938
|
[],
|
|
6897
6939
|
pdfOptions,
|
|
6940
|
+
"",
|
|
6941
|
+
themeStyle,
|
|
6898
6942
|
);
|
|
6899
6943
|
}
|
|
6900
6944
|
|
|
@@ -6915,6 +6959,8 @@ async function renderStudioPdfWithPandoc(
|
|
|
6915
6959
|
[],
|
|
6916
6960
|
[],
|
|
6917
6961
|
pdfOptions,
|
|
6962
|
+
"",
|
|
6963
|
+
themeStyle,
|
|
6918
6964
|
);
|
|
6919
6965
|
} catch {
|
|
6920
6966
|
const fenced = parseStudioSingleFencedCodeBlock(diffMarkdown);
|
|
@@ -6941,7 +6987,7 @@ async function renderStudioPdfWithPandoc(
|
|
|
6941
6987
|
const outputPath = join(tempDir, "studio-export.pdf");
|
|
6942
6988
|
|
|
6943
6989
|
await mkdir(tempDir, { recursive: true });
|
|
6944
|
-
await writeFile(preamblePath, buildStudioPdfPreamble(pdfOptions, extraPdfPreamble), "utf-8");
|
|
6990
|
+
await writeFile(preamblePath, buildStudioPdfPreamble(pdfOptions, extraPdfPreamble, themeStyle), "utf-8");
|
|
6945
6991
|
|
|
6946
6992
|
const mermaidPrepared: StudioMermaidPdfPreprocessResult = isLatex
|
|
6947
6993
|
? { markdown: normalizedMarkdownBody, found: 0, replaced: 0, failed: 0, missingCli: false }
|
|
@@ -6964,6 +7010,7 @@ async function renderStudioPdfWithPandoc(
|
|
|
6964
7010
|
pdfAlignedImageTransform.blocks,
|
|
6965
7011
|
pdfOptions,
|
|
6966
7012
|
extraPdfPreamble,
|
|
7013
|
+
themeStyle,
|
|
6967
7014
|
);
|
|
6968
7015
|
await rm(tempDir, { recursive: true, force: true }).catch(() => undefined);
|
|
6969
7016
|
return { pdf: rendered.pdf, warning: mermaidPrepared.warning ?? rendered.warning };
|
|
@@ -10514,7 +10561,7 @@ ${cssVarsBlock}
|
|
|
10514
10561
|
<section id="rightPane">
|
|
10515
10562
|
<div id="rightSectionHeader" class="section-header">
|
|
10516
10563
|
<div class="section-header-main">
|
|
10517
|
-
<select id="rightViewSelect" aria-label="Response view mode" title="Right pane view mode. F7 cycles when the right pane is active; Cmd/Ctrl+Alt+P switches directly to Preview; Cmd/Ctrl+Alt+W switches directly to Working.">
|
|
10564
|
+
<select id="rightViewSelect" aria-label="Response view mode" title="Right pane view mode. F7 cycles when the right pane is active; Cmd/Ctrl+Alt+P switches directly to Response Preview; Cmd/Ctrl+Alt+E switches directly to Editor Preview; Cmd/Ctrl+Alt+W switches directly to Working.">
|
|
10518
10565
|
<option value="markdown">Response (Raw)</option>
|
|
10519
10566
|
<option value="preview" selected>Response (Preview)</option>
|
|
10520
10567
|
<option value="editor-preview">Editor (Preview)</option>
|
|
@@ -10608,7 +10655,8 @@ ${cssVarsBlock}
|
|
|
10608
10655
|
<dl>
|
|
10609
10656
|
<div><dt>F6</dt><dd>Switch between editor and right pane</dd></div>
|
|
10610
10657
|
<div><dt>F7 / Shift+F7</dt><dd>Cycle the active pane's view</dd></div>
|
|
10611
|
-
<div><dt>Cmd/Ctrl+Alt+P</dt><dd>Switch the right pane directly to Preview</dd></div>
|
|
10658
|
+
<div><dt>Cmd/Ctrl+Alt+P</dt><dd>Switch the right pane directly to Response Preview</dd></div>
|
|
10659
|
+
<div><dt>Cmd/Ctrl+Alt+E</dt><dd>Switch the right pane directly to Editor Preview</dd></div>
|
|
10612
10660
|
<div><dt>Cmd/Ctrl+Alt+W</dt><dd>Switch the right pane directly to Working</dd></div>
|
|
10613
10661
|
<div><dt>F8</dt><dd>Focus editor text</dd></div>
|
|
10614
10662
|
<div><dt>Shift+F8</dt><dd>Focus right-pane content</dd></div>
|
|
@@ -13553,7 +13601,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
13553
13601
|
const filename = sanitizePdfFilename(requestedFilename || (isLatex ? "studio-latex-preview.pdf" : "studio-preview.pdf"));
|
|
13554
13602
|
|
|
13555
13603
|
try {
|
|
13556
|
-
const { pdf, warning } = await renderStudioPdfWithPandoc(markdown, isLatex, resourcePath, editorPdfLanguage, sourcePath || undefined);
|
|
13604
|
+
const { pdf, warning } = await renderStudioPdfWithPandoc(markdown, isLatex, resourcePath, editorPdfLanguage, sourcePath || undefined, undefined, getStudioThemeStyle(lastCommandCtx?.ui?.theme));
|
|
13557
13605
|
const writeResult = writeStudioPreviewExportFile(buildStudioPreviewExportPath(sourcePath || undefined, userResourceDir || undefined, studioCwd, filename), pdf);
|
|
13558
13606
|
const exportId = storePreparedPdfExport(pdf, filename, warning, writeResult.filePath ?? undefined);
|
|
13559
13607
|
const token = serverState?.token ?? "";
|
|
@@ -14984,6 +15032,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
14984
15032
|
editorPdfLanguage,
|
|
14985
15033
|
source.sourcePath,
|
|
14986
15034
|
pdfOptions,
|
|
15035
|
+
getStudioThemeStyle(ctx.ui.theme),
|
|
14987
15036
|
);
|
|
14988
15037
|
await writeFile(source.outputPath, pdf);
|
|
14989
15038
|
const openError = await maybeOpenStudioExportPath(source.outputPath, params.open);
|
|
@@ -15296,6 +15345,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
15296
15345
|
editorPdfLanguage,
|
|
15297
15346
|
undefined,
|
|
15298
15347
|
pdfOptions,
|
|
15348
|
+
getStudioThemeStyle(ctx.ui.theme),
|
|
15299
15349
|
);
|
|
15300
15350
|
await writeFile(outputPath, pdf);
|
|
15301
15351
|
|
|
@@ -15354,6 +15404,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
15354
15404
|
editorPdfLanguage,
|
|
15355
15405
|
file.resolvedPath,
|
|
15356
15406
|
pdfOptions,
|
|
15407
|
+
getStudioThemeStyle(ctx.ui.theme),
|
|
15357
15408
|
);
|
|
15358
15409
|
await writeFile(outputPath, pdf);
|
|
15359
15410
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-studio",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.33",
|
|
4
4
|
"description": "Two-pane browser workspace for pi with prompt/response editing, annotations, critiques, active quiz, prompt/response history, live previews, and tmux-backed REPL/literate REPL workflows",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|