pi-studio 0.6.1 → 0.6.3
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 +12 -0
- package/client/studio.css +25 -17
- package/index.ts +55 -5
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,18 @@ All notable changes to `pi-studio` are documented here.
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.6.3] — 2026-04-29
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
- Polished rendered code blocks so ordinary code text uses normal foreground, Python function definitions keep function-name highlighting, and fenced-block borders are softened to better match theme intent.
|
|
11
|
+
- Slightly sharpened footer metadata and shortcut text for better readability across darker custom themes.
|
|
12
|
+
|
|
13
|
+
## [0.6.2] — 2026-04-29
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
- Polished refreshed Studio theme surfaces so light-mode header actions, scratchpad panels, response-history badges, and editor surfaces are more consistent.
|
|
17
|
+
- Softened overly sharp derived borders in high-contrast themes while preserving theme hue and tightened secondary info text contrast in comment, outline, and scratchpad panels.
|
|
18
|
+
|
|
7
19
|
## [0.6.1] — 2026-04-29
|
|
8
20
|
|
|
9
21
|
### Added
|
package/client/studio.css
CHANGED
|
@@ -1143,7 +1143,7 @@
|
|
|
1143
1143
|
}
|
|
1144
1144
|
|
|
1145
1145
|
.rendered-markdown pre code {
|
|
1146
|
-
color: var(--
|
|
1146
|
+
color: var(--text);
|
|
1147
1147
|
white-space: inherit;
|
|
1148
1148
|
}
|
|
1149
1149
|
|
|
@@ -1846,7 +1846,7 @@
|
|
|
1846
1846
|
footer {
|
|
1847
1847
|
border-top: 1px solid var(--panel-border);
|
|
1848
1848
|
padding: 8px 12px;
|
|
1849
|
-
color: var(--muted);
|
|
1849
|
+
color: var(--studio-footer-text, var(--muted));
|
|
1850
1850
|
font-size: 12px;
|
|
1851
1851
|
min-height: 32px;
|
|
1852
1852
|
background: var(--panel);
|
|
@@ -1903,7 +1903,7 @@
|
|
|
1903
1903
|
.footer-meta {
|
|
1904
1904
|
grid-area: meta;
|
|
1905
1905
|
justify-self: start;
|
|
1906
|
-
color: var(--muted);
|
|
1906
|
+
color: var(--studio-footer-text, var(--muted));
|
|
1907
1907
|
font-size: 11px;
|
|
1908
1908
|
text-align: left;
|
|
1909
1909
|
max-width: 100%;
|
|
@@ -1954,12 +1954,12 @@
|
|
|
1954
1954
|
grid-area: hint;
|
|
1955
1955
|
justify-self: end;
|
|
1956
1956
|
align-self: center;
|
|
1957
|
-
color: var(--muted);
|
|
1957
|
+
color: var(--studio-footer-text, var(--muted));
|
|
1958
1958
|
font-size: 11px;
|
|
1959
1959
|
white-space: nowrap;
|
|
1960
1960
|
text-align: right;
|
|
1961
1961
|
font-style: normal;
|
|
1962
|
-
opacity: 0.
|
|
1962
|
+
opacity: 0.86;
|
|
1963
1963
|
display: inline-flex;
|
|
1964
1964
|
align-items: center;
|
|
1965
1965
|
gap: 8px;
|
|
@@ -2020,7 +2020,7 @@
|
|
|
2020
2020
|
gap: 12px;
|
|
2021
2021
|
padding: 16px 18px 12px;
|
|
2022
2022
|
border-bottom: 1px solid var(--panel-border);
|
|
2023
|
-
background: var(--panel-2);
|
|
2023
|
+
background: var(--scratchpad-header-bg, var(--panel-2));
|
|
2024
2024
|
}
|
|
2025
2025
|
|
|
2026
2026
|
.scratchpad-header > div {
|
|
@@ -2038,7 +2038,7 @@
|
|
|
2038
2038
|
margin: 6px 0 0;
|
|
2039
2039
|
font-size: 12px;
|
|
2040
2040
|
line-height: 1.45;
|
|
2041
|
-
color: var(--muted);
|
|
2041
|
+
color: var(--studio-info-text, var(--muted));
|
|
2042
2042
|
max-width: none;
|
|
2043
2043
|
}
|
|
2044
2044
|
|
|
@@ -2057,7 +2057,7 @@
|
|
|
2057
2057
|
border-radius: 0;
|
|
2058
2058
|
margin: 0;
|
|
2059
2059
|
padding: 16px 18px;
|
|
2060
|
-
background: var(--panel);
|
|
2060
|
+
background: var(--scratchpad-body-bg, var(--panel));
|
|
2061
2061
|
color: var(--text);
|
|
2062
2062
|
font-family: var(--font-mono);
|
|
2063
2063
|
font-size: 13px;
|
|
@@ -2073,12 +2073,12 @@
|
|
|
2073
2073
|
gap: 12px;
|
|
2074
2074
|
flex-wrap: wrap;
|
|
2075
2075
|
padding: 12px 18px 16px;
|
|
2076
|
-
background: var(--panel);
|
|
2076
|
+
background: var(--scratchpad-body-bg, var(--panel));
|
|
2077
2077
|
}
|
|
2078
2078
|
|
|
2079
2079
|
.scratchpad-meta {
|
|
2080
2080
|
font-size: 12px;
|
|
2081
|
-
color: var(--muted);
|
|
2081
|
+
color: var(--studio-info-text, var(--muted));
|
|
2082
2082
|
}
|
|
2083
2083
|
|
|
2084
2084
|
.scratchpad-actions {
|
|
@@ -2140,7 +2140,7 @@
|
|
|
2140
2140
|
padding: 14px;
|
|
2141
2141
|
font-size: 13px;
|
|
2142
2142
|
line-height: 1.5;
|
|
2143
|
-
color: var(--muted);
|
|
2143
|
+
color: var(--studio-info-text, var(--muted));
|
|
2144
2144
|
border-bottom: 1px solid var(--panel-border);
|
|
2145
2145
|
background: var(--panel);
|
|
2146
2146
|
}
|
|
@@ -2229,7 +2229,7 @@
|
|
|
2229
2229
|
|
|
2230
2230
|
.outline-entry-meta {
|
|
2231
2231
|
font-size: 11px;
|
|
2232
|
-
color: var(--muted);
|
|
2232
|
+
color: var(--studio-info-text, var(--muted));
|
|
2233
2233
|
white-space: nowrap;
|
|
2234
2234
|
font-variant-numeric: tabular-nums;
|
|
2235
2235
|
}
|
|
@@ -2553,7 +2553,7 @@
|
|
|
2553
2553
|
body.studio-ui-refresh #rightSectionHeader button:not(:disabled):hover,
|
|
2554
2554
|
body.studio-ui-refresh .studio-refresh-toolbar button:not(:disabled):hover,
|
|
2555
2555
|
body.studio-ui-refresh .studio-refresh-toolbar select:not(:disabled):hover {
|
|
2556
|
-
background: var(--panel-2);
|
|
2556
|
+
background: var(--studio-header-action-hover-bg, var(--panel-2));
|
|
2557
2557
|
}
|
|
2558
2558
|
|
|
2559
2559
|
body.studio-ui-refresh #leftSectionHeader #editorViewSelect,
|
|
@@ -2653,10 +2653,18 @@
|
|
|
2653
2653
|
border-radius: 8px;
|
|
2654
2654
|
}
|
|
2655
2655
|
|
|
2656
|
+
body.studio-ui-refresh #reviewNotesBtn,
|
|
2657
|
+
body.studio-ui-refresh #outlineBtn,
|
|
2658
|
+
body.studio-ui-refresh #scratchpadBtn,
|
|
2659
|
+
body.studio-ui-refresh .studio-refresh-tool-tab {
|
|
2660
|
+
background: var(--studio-header-action-bg, transparent);
|
|
2661
|
+
border-color: var(--studio-header-action-border, transparent);
|
|
2662
|
+
}
|
|
2663
|
+
|
|
2656
2664
|
body.studio-ui-refresh #exportPdfBtn {
|
|
2657
|
-
background: var(--panel-2);
|
|
2665
|
+
background: var(--studio-header-filled-bg, var(--panel-2));
|
|
2658
2666
|
color: var(--text);
|
|
2659
|
-
border-color: transparent;
|
|
2667
|
+
border-color: var(--studio-header-action-border, transparent);
|
|
2660
2668
|
}
|
|
2661
2669
|
|
|
2662
2670
|
body.studio-ui-refresh #reviewNotesBtn.is-active,
|
|
@@ -2834,7 +2842,7 @@
|
|
|
2834
2842
|
|
|
2835
2843
|
body.studio-ui-refresh .studio-refresh-chip.is-open,
|
|
2836
2844
|
body.studio-ui-refresh .studio-refresh-chip:hover {
|
|
2837
|
-
background: var(--panel-2);
|
|
2845
|
+
background: var(--studio-header-action-hover-bg, var(--panel-2));
|
|
2838
2846
|
color: var(--text);
|
|
2839
2847
|
}
|
|
2840
2848
|
|
|
@@ -2917,7 +2925,7 @@
|
|
|
2917
2925
|
|
|
2918
2926
|
body.studio-ui-refresh .studio-refresh-menu-item > button:not(:disabled):hover,
|
|
2919
2927
|
body.studio-ui-refresh .studio-refresh-menu-item > select:not(:disabled):hover {
|
|
2920
|
-
background: var(--panel-2);
|
|
2928
|
+
background: var(--studio-header-action-hover-bg, var(--panel-2));
|
|
2921
2929
|
}
|
|
2922
2930
|
|
|
2923
2931
|
body.studio-ui-refresh #copyDraftBtn:only-child {
|
package/index.ts
CHANGED
|
@@ -864,6 +864,26 @@ function readableTextOn(background: string, darkText = "#0e1616", lightText = "#
|
|
|
864
864
|
return contrastRatio(background, darkText) >= contrastRatio(background, lightText) ? darkText : lightText;
|
|
865
865
|
}
|
|
866
866
|
|
|
867
|
+
function capBorderContrast(color: string, surface: string, maxContrast: number): string {
|
|
868
|
+
if (!hexToRgb(color) || !hexToRgb(surface)) return color;
|
|
869
|
+
if (contrastRatio(color, surface) <= maxContrast) return color;
|
|
870
|
+
|
|
871
|
+
let low = 0;
|
|
872
|
+
let high = 1;
|
|
873
|
+
let result = color;
|
|
874
|
+
for (let i = 0; i < 12; i += 1) {
|
|
875
|
+
const mid = (low + high) / 2;
|
|
876
|
+
const candidate = blendColors(color, surface, mid);
|
|
877
|
+
if (contrastRatio(candidate, surface) > maxContrast) {
|
|
878
|
+
low = mid;
|
|
879
|
+
} else {
|
|
880
|
+
result = candidate;
|
|
881
|
+
high = mid;
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
return result;
|
|
885
|
+
}
|
|
886
|
+
|
|
867
887
|
function deriveCanvasColors(
|
|
868
888
|
baseColor: string,
|
|
869
889
|
mode: StudioThemeMode,
|
|
@@ -4321,6 +4341,13 @@ async function writeStudioSystemClipboard(text: string): Promise<{ ok: true; met
|
|
|
4321
4341
|
return { ok: false, error: errors.join("; ") || "No system clipboard command is available." };
|
|
4322
4342
|
}
|
|
4323
4343
|
|
|
4344
|
+
function decorateStudioPandocSyntaxHtml(html: string): string {
|
|
4345
|
+
return html.replace(
|
|
4346
|
+
/(<span class="kw">def<\/span>)(\s*)([A-Za-z_][A-Za-z0-9_]*)(?=\s*\()/g,
|
|
4347
|
+
(_match, keyword: string, spacing: string, name: string) => `${keyword}${spacing}<span class="fu">${name}</span>`,
|
|
4348
|
+
);
|
|
4349
|
+
}
|
|
4350
|
+
|
|
4324
4351
|
async function renderStudioMarkdownWithPandoc(markdown: string, isLatex?: boolean, resourcePath?: string, sourcePath?: string): Promise<string> {
|
|
4325
4352
|
const pandocCommand = process.env.PANDOC_PATH?.trim() || "pandoc";
|
|
4326
4353
|
const markdownWithoutHtmlComments = isLatex ? markdown : stripStudioMarkdownHtmlComments(markdown);
|
|
@@ -4401,6 +4428,7 @@ async function renderStudioMarkdownWithPandoc(markdown: string, isLatex?: boolea
|
|
|
4401
4428
|
} else {
|
|
4402
4429
|
html = decorateStudioPreviewPageBreakHtml(html);
|
|
4403
4430
|
}
|
|
4431
|
+
html = decorateStudioPandocSyntaxHtml(html);
|
|
4404
4432
|
succeed(stripMathMlAnnotationTags(html));
|
|
4405
4433
|
return;
|
|
4406
4434
|
}
|
|
@@ -6165,10 +6193,14 @@ function buildThemeCssVars(style: StudioThemeStyle): Record<string, string> {
|
|
|
6165
6193
|
style.mode === "light"
|
|
6166
6194
|
? `0 1px 2px ${withAlpha(style.palette.text, 0.035, "rgba(15, 23, 42, 0.03)")}, 0 4px 14px ${withAlpha(style.palette.text, 0.055, "rgba(15, 23, 42, 0.04)")}`
|
|
6167
6195
|
: "0 1px 2px rgba(0, 0, 0, 0.30), 0 6px 18px rgba(0, 0, 0, 0.18)";
|
|
6168
|
-
const
|
|
6169
|
-
const
|
|
6170
|
-
const
|
|
6171
|
-
const
|
|
6196
|
+
const rawBorderSubtle = blendColors(style.palette.borderMuted, style.palette.panel, style.mode === "light" ? 0.58 : 0.48);
|
|
6197
|
+
const rawPanelBorder = blendColors(style.palette.borderMuted, style.palette.panel, style.mode === "light" ? 0.42 : 0.36);
|
|
6198
|
+
const rawControlBorder = blendColors(style.palette.borderMuted, style.palette.panel, style.mode === "light" ? 0.30 : 0.22);
|
|
6199
|
+
const rawPaneActiveBorder = blendColors(style.palette.border, style.palette.panel, style.mode === "light" ? 0.34 : 0.48);
|
|
6200
|
+
const borderSubtle = capBorderContrast(rawBorderSubtle, style.palette.panel, style.mode === "light" ? 1.10 : 1.12);
|
|
6201
|
+
const panelBorder = capBorderContrast(rawPanelBorder, style.palette.panel, style.mode === "light" ? 1.15 : 1.18);
|
|
6202
|
+
const controlBorder = capBorderContrast(rawControlBorder, style.palette.panel, style.mode === "light" ? 1.22 : 1.25);
|
|
6203
|
+
const paneActiveBorder = capBorderContrast(rawPaneActiveBorder, style.palette.panel, style.mode === "light" ? 1.38 : 1.45);
|
|
6172
6204
|
const accentContrast = style.accentContrast ?? (style.mode === "light" ? "#ffffff" : "#0e1616");
|
|
6173
6205
|
const errorContrast = style.errorContrast ?? readableTextOn(style.palette.error);
|
|
6174
6206
|
const blockquoteBg = withAlpha(
|
|
@@ -6186,6 +6218,8 @@ function buildThemeCssVars(style: StudioThemeStyle): Record<string, string> {
|
|
|
6186
6218
|
style.mode === "light" ? 0.13 : 0.18,
|
|
6187
6219
|
style.mode === "light" ? "rgba(15, 23, 42, 0.06)" : "rgba(255, 255, 255, 0.07)",
|
|
6188
6220
|
);
|
|
6221
|
+
const rawCodeBlockBorder = blendColors(style.palette.mdCodeBlockBorder, style.palette.panel2, style.mode === "light" ? 0.62 : 0.72);
|
|
6222
|
+
const codeBlockBorder = capBorderContrast(rawCodeBlockBorder, style.palette.panel2, style.mode === "light" ? 1.16 : 1.18);
|
|
6189
6223
|
const diffAddedBg = withAlpha(style.palette.ok, style.mode === "light" ? 0.10 : 0.14, "rgba(46, 160, 67, 0.12)");
|
|
6190
6224
|
const diffRemovedBg = withAlpha(style.palette.error, style.mode === "light" ? 0.10 : 0.14, "rgba(248, 81, 73, 0.12)");
|
|
6191
6225
|
const okSoft = withAlpha(style.palette.ok, style.mode === "light" ? 0.10 : 0.12, "rgba(115, 209, 61, 0.08)");
|
|
@@ -6201,6 +6235,14 @@ function buildThemeCssVars(style: StudioThemeStyle): Record<string, string> {
|
|
|
6201
6235
|
const editorGutterBg = style.mode === "light" ? lightSecondarySurface : style.palette.panel2;
|
|
6202
6236
|
const referenceMetaBg = style.mode === "light" ? lightSecondarySurface : style.palette.panel2;
|
|
6203
6237
|
const referenceBadgeBg = style.mode === "light" ? lightPrimarySurface : style.palette.panel;
|
|
6238
|
+
const scratchpadHeaderBg = style.mode === "light" ? lightSecondarySurface : style.palette.panel2;
|
|
6239
|
+
const scratchpadBodyBg = style.mode === "light" ? lightPrimarySurface : style.palette.panel;
|
|
6240
|
+
const infoText = blendColors(style.palette.text, style.palette.muted, style.mode === "light" ? 0.36 : 0.30);
|
|
6241
|
+
const footerText = blendColors(style.palette.text, style.palette.muted, style.mode === "light" ? 0.50 : 0.42);
|
|
6242
|
+
const headerActionBg = style.mode === "light" ? lightPrimarySurface : "transparent";
|
|
6243
|
+
const headerActionHoverBg = style.mode === "light" ? lightPrimarySurface : style.palette.panel2;
|
|
6244
|
+
const headerActionBorder = style.mode === "light" ? controlBorder : "transparent";
|
|
6245
|
+
const headerFilledBg = style.mode === "light" ? lightPrimarySurface : style.palette.panel2;
|
|
6204
6246
|
const monoFontStack = getStudioMonoFontStack();
|
|
6205
6247
|
const uiFontStack = getStudioUiFontStack();
|
|
6206
6248
|
const proseFontStack = getStudioProseFontStack();
|
|
@@ -6233,7 +6275,7 @@ function buildThemeCssVars(style: StudioThemeStyle): Record<string, string> {
|
|
|
6233
6275
|
"--md-link-url": style.palette.mdLinkUrl,
|
|
6234
6276
|
"--md-code": style.palette.mdCode,
|
|
6235
6277
|
"--md-codeblock": style.palette.mdCodeBlock,
|
|
6236
|
-
"--md-codeblock-border":
|
|
6278
|
+
"--md-codeblock-border": codeBlockBorder,
|
|
6237
6279
|
"--md-quote": style.palette.mdQuote,
|
|
6238
6280
|
"--md-quote-border": style.palette.mdQuoteBorder,
|
|
6239
6281
|
"--md-hr": style.palette.mdHr,
|
|
@@ -6264,6 +6306,14 @@ function buildThemeCssVars(style: StudioThemeStyle): Record<string, string> {
|
|
|
6264
6306
|
"--editor-gutter-bg": editorGutterBg,
|
|
6265
6307
|
"--reference-meta-bg": referenceMetaBg,
|
|
6266
6308
|
"--reference-badge-bg": referenceBadgeBg,
|
|
6309
|
+
"--scratchpad-header-bg": scratchpadHeaderBg,
|
|
6310
|
+
"--scratchpad-body-bg": scratchpadBodyBg,
|
|
6311
|
+
"--studio-info-text": infoText,
|
|
6312
|
+
"--studio-footer-text": footerText,
|
|
6313
|
+
"--studio-header-action-bg": headerActionBg,
|
|
6314
|
+
"--studio-header-action-hover-bg": headerActionHoverBg,
|
|
6315
|
+
"--studio-header-action-border": headerActionBorder,
|
|
6316
|
+
"--studio-header-filled-bg": headerFilledBg,
|
|
6267
6317
|
"--font-ui": uiFontStack,
|
|
6268
6318
|
"--font-prose": proseFontStack,
|
|
6269
6319
|
"--font-mono": monoFontStack,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-studio",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.3",
|
|
4
4
|
"description": "Two-pane browser workspace for pi with prompt/response editing, annotations, critiques, prompt/response history, and live Markdown/LaTeX/code preview",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|