pi-studio 0.5.39 → 0.5.40
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 +6 -0
- package/client/studio-client.js +47 -24
- package/client/studio.css +16 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,12 @@ All notable changes to `pi-studio` are documented here.
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.5.40] — 2026-03-30
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
- Studio editor highlighting now keeps plain text in code files closer to the normal editor foreground while preserving a distinct markdown-code tint for inline backticks and unlabeled fenced blocks.
|
|
11
|
+
- Language-aware Studio syntax highlighting for code files and labeled fenced code blocks is now a bit richer, with additional highlighting for function-like identifiers, type/class-like names, and a few language-specific constructs such as decorators or macros.
|
|
12
|
+
|
|
7
13
|
## [0.5.39] — 2026-03-30
|
|
8
14
|
|
|
9
15
|
### Added
|
package/client/studio-client.js
CHANGED
|
@@ -2768,7 +2768,7 @@
|
|
|
2768
2768
|
}
|
|
2769
2769
|
|
|
2770
2770
|
if (match[1]) {
|
|
2771
|
-
out += wrapHighlight("hl-code", token);
|
|
2771
|
+
out += wrapHighlight("hl-md-code", token);
|
|
2772
2772
|
} else if (match[2]) {
|
|
2773
2773
|
const linkMatch = token.match(/^\[([^\]]+)\]\(([^)]+)\)$/);
|
|
2774
2774
|
if (linkMatch) {
|
|
@@ -2870,37 +2870,43 @@
|
|
|
2870
2870
|
}
|
|
2871
2871
|
|
|
2872
2872
|
if (lang === "javascript" || lang === "typescript") {
|
|
2873
|
-
const jsPattern = /(
|
|
2873
|
+
const jsPattern = /(\/\/.*$|\/\*.*?\*\/)|(`(?:[^`\\]|\\.)*`|"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')|(\b(?:const|let|var|function|return|if|else|for|while|switch|case|break|continue|try|catch|finally|throw|new|class|extends|import|from|export|default|async|await|true|false|null|undefined|typeof|instanceof|interface|implements|enum|type|public|private|protected|readonly|abstract|declare|this|super)\b)|(\b[A-Za-z_$][A-Za-z0-9_$]*(?=\s*\())|(\b[A-Z][A-Za-z0-9_$]*\b)|(\b\d+(?:\.\d+)?\b)/g;
|
|
2874
2874
|
const highlighted = highlightCodeTokens(source, jsPattern, (match) => {
|
|
2875
2875
|
if (match[1]) return "hl-code-com";
|
|
2876
2876
|
if (match[2]) return "hl-code-str";
|
|
2877
2877
|
if (match[3]) return "hl-code-kw";
|
|
2878
|
-
if (match[4]) return "hl-code-
|
|
2878
|
+
if (match[4]) return "hl-code-fn";
|
|
2879
|
+
if (match[5]) return "hl-code-type";
|
|
2880
|
+
if (match[6]) return "hl-code-num";
|
|
2879
2881
|
return "hl-code";
|
|
2880
2882
|
});
|
|
2881
2883
|
return "<span class='hl-code'>" + highlighted + "</span>";
|
|
2882
2884
|
}
|
|
2883
2885
|
|
|
2884
2886
|
if (lang === "python") {
|
|
2885
|
-
const pyPattern = /(#.*$)|("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')|(\b(?:def|class|return|if|elif|else|for|while|try|except|finally|import|from|as|with|lambda|yield|True|False|None|and|or|not|in|is|pass|break|continue|raise|global|nonlocal|assert)\b)|(\b\d+(?:\.\d+)?\b)/g;
|
|
2887
|
+
const pyPattern = /(#.*$)|("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')|(@[A-Za-z_][A-Za-z0-9_]*)|(\b(?:def|class|return|if|elif|else|for|while|try|except|finally|import|from|as|with|lambda|yield|True|False|None|and|or|not|in|is|pass|break|continue|raise|global|nonlocal|assert)\b)|(\b[A-Za-z_][A-Za-z0-9_]*(?=\s*\())|(\b[A-Z][A-Za-z0-9_]*\b)|(\b\d+(?:\.\d+)?\b)/g;
|
|
2886
2888
|
const highlighted = highlightCodeTokens(source, pyPattern, (match) => {
|
|
2887
2889
|
if (match[1]) return "hl-code-com";
|
|
2888
2890
|
if (match[2]) return "hl-code-str";
|
|
2889
|
-
if (match[3]) return "hl-code-
|
|
2890
|
-
if (match[4]) return "hl-code-
|
|
2891
|
+
if (match[3]) return "hl-code-fn";
|
|
2892
|
+
if (match[4]) return "hl-code-kw";
|
|
2893
|
+
if (match[5]) return "hl-code-fn";
|
|
2894
|
+
if (match[6]) return "hl-code-type";
|
|
2895
|
+
if (match[7]) return "hl-code-num";
|
|
2891
2896
|
return "hl-code";
|
|
2892
2897
|
});
|
|
2893
2898
|
return "<span class='hl-code'>" + highlighted + "</span>";
|
|
2894
2899
|
}
|
|
2895
2900
|
|
|
2896
2901
|
if (lang === "bash") {
|
|
2897
|
-
const shPattern = /(#.*$)|("(?:[^"\\]|\\.)*"|'[^']*')|(\$\{[^}]+\}|\$[A-Za-z_][A-Za-z0-9_]*)|(\b(?:if|then|else|fi|for|in|do|done|case|esac|function|local|export|readonly|return|break|continue|while|until)\b)|(\b\d+\b)/g;
|
|
2902
|
+
const shPattern = /(#.*$)|("(?:[^"\\]|\\.)*"|'[^']*')|(\$\{[^}]+\}|\$[A-Za-z_][A-Za-z0-9_]*)|(\b(?:if|then|else|fi|for|in|do|done|case|esac|function|local|export|readonly|return|break|continue|while|until)\b)|(\b[A-Za-z_][A-Za-z0-9_]*(?=\s*\(\s*\)))|(\b\d+\b)/g;
|
|
2898
2903
|
const highlighted = highlightCodeTokens(source, shPattern, (match) => {
|
|
2899
2904
|
if (match[1]) return "hl-code-com";
|
|
2900
2905
|
if (match[2]) return "hl-code-str";
|
|
2901
2906
|
if (match[3]) return "hl-code-var";
|
|
2902
2907
|
if (match[4]) return "hl-code-kw";
|
|
2903
|
-
if (match[5]) return "hl-code-
|
|
2908
|
+
if (match[5]) return "hl-code-fn";
|
|
2909
|
+
if (match[6]) return "hl-code-num";
|
|
2904
2910
|
return "hl-code";
|
|
2905
2911
|
});
|
|
2906
2912
|
return "<span class='hl-code'>" + highlighted + "</span>";
|
|
@@ -2919,74 +2925,85 @@
|
|
|
2919
2925
|
}
|
|
2920
2926
|
|
|
2921
2927
|
if (lang === "rust") {
|
|
2922
|
-
const rustPattern = /(\/\/.*$)|("(?:[^"\\]|\\.)*")|(\b(?:fn|let|mut|const|struct|enum|impl|trait|pub|mod|use|crate|self|super|match|if|else|for|while|loop|return|break|continue|where|as|in|ref|move|async|await|unsafe|extern|type|static|true|false|Some|None|Ok|Err|Self)\b)|(\b\d[\d_]*(?:\.\d[\d_]*)?(?:f32|f64|u8|u16|u32|u64|u128|usize|i8|i16|i32|i64|i128|isize)?\b)/g;
|
|
2928
|
+
const rustPattern = /(\/\/.*$)|("(?:[^"\\]|\\.)*")|(\b[A-Za-z_][A-Za-z0-9_]*!(?=\s*(?:\(|\{|\[)))|(\b(?:fn|let|mut|const|struct|enum|impl|trait|pub|mod|use|crate|self|super|match|if|else|for|while|loop|return|break|continue|where|as|in|ref|move|async|await|unsafe|extern|type|static|true|false|Some|None|Ok|Err|Self)\b)|(\b[A-Za-z_][A-Za-z0-9_]*(?=\s*\())|(\b[A-Z][A-Za-z0-9_]*\b)|(\b\d[\d_]*(?:\.\d[\d_]*)?(?:f32|f64|u8|u16|u32|u64|u128|usize|i8|i16|i32|i64|i128|isize)?\b)/g;
|
|
2923
2929
|
const highlighted = highlightCodeTokens(source, rustPattern, (match) => {
|
|
2924
2930
|
if (match[1]) return "hl-code-com";
|
|
2925
2931
|
if (match[2]) return "hl-code-str";
|
|
2926
|
-
if (match[3]) return "hl-code-
|
|
2927
|
-
if (match[4]) return "hl-code-
|
|
2932
|
+
if (match[3]) return "hl-code-fn";
|
|
2933
|
+
if (match[4]) return "hl-code-kw";
|
|
2934
|
+
if (match[5]) return "hl-code-fn";
|
|
2935
|
+
if (match[6]) return "hl-code-type";
|
|
2936
|
+
if (match[7]) return "hl-code-num";
|
|
2928
2937
|
return "hl-code";
|
|
2929
2938
|
});
|
|
2930
2939
|
return "<span class='hl-code'>" + highlighted + "</span>";
|
|
2931
2940
|
}
|
|
2932
2941
|
|
|
2933
2942
|
if (lang === "c" || lang === "cpp") {
|
|
2934
|
-
const cPattern = /(
|
|
2943
|
+
const cPattern = /(\/\/.*$|\/\*.*?\*\/)|("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)')|(#\s*\w+)|(\b(?:if|else|for|while|do|switch|case|break|continue|return|goto|struct|union|enum|typedef|sizeof|void|int|char|short|long|float|double|unsigned|signed|const|static|extern|volatile|register|inline|auto|restrict|true|false|NULL|nullptr|class|public|private|protected|virtual|override|template|typename|namespace|using|new|delete|try|catch|throw|noexcept|constexpr|auto|decltype|static_cast|dynamic_cast|reinterpret_cast|const_cast|std|include|define|ifdef|ifndef|endif|pragma)\b)|(\b[A-Za-z_][A-Za-z0-9_]*(?=\s*\())|(\b[A-Z][A-Za-z0-9_]*\b)|(\b\d+(?:\.\d+)?(?:[eE][+-]?\d+)?[fFlLuU]*\b)/g;
|
|
2935
2944
|
const highlighted = highlightCodeTokens(source, cPattern, (match) => {
|
|
2936
2945
|
if (match[1]) return "hl-code-com";
|
|
2937
2946
|
if (match[2]) return "hl-code-str";
|
|
2938
2947
|
if (match[3]) return "hl-code-kw";
|
|
2939
2948
|
if (match[4]) return "hl-code-kw";
|
|
2940
|
-
if (match[5]) return "hl-code-
|
|
2949
|
+
if (match[5]) return "hl-code-fn";
|
|
2950
|
+
if (match[6]) return "hl-code-type";
|
|
2951
|
+
if (match[7]) return "hl-code-num";
|
|
2941
2952
|
return "hl-code";
|
|
2942
2953
|
});
|
|
2943
2954
|
return "<span class='hl-code'>" + highlighted + "</span>";
|
|
2944
2955
|
}
|
|
2945
2956
|
|
|
2946
2957
|
if (lang === "julia") {
|
|
2947
|
-
const jlPattern = /(#.*$)|("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')|(\b(?:function|end|if|elseif|else|for|while|begin|let|local|global|const|return|break|continue|do|try|catch|finally|throw|module|import|using|export|struct|mutable|abstract|primitive|where|macro|quote|true|false|nothing|missing|in|isa|typeof)\b)|(\b\d+(?:\.\d+)?(?:[eE][+-]?\d+)?\b)/g;
|
|
2958
|
+
const jlPattern = /(#.*$)|("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')|(@[A-Za-z_][A-Za-z0-9_]*)|(\b(?:function|end|if|elseif|else|for|while|begin|let|local|global|const|return|break|continue|do|try|catch|finally|throw|module|import|using|export|struct|mutable|abstract|primitive|where|macro|quote|true|false|nothing|missing|in|isa|typeof)\b)|(\b[A-Za-z_][A-Za-z0-9_]*!?(?=\s*\())|(\b[A-Z][A-Za-z0-9_]*\b)|(\b\d+(?:\.\d+)?(?:[eE][+-]?\d+)?\b)/g;
|
|
2948
2959
|
const highlighted = highlightCodeTokens(source, jlPattern, (match) => {
|
|
2949
2960
|
if (match[1]) return "hl-code-com";
|
|
2950
2961
|
if (match[2]) return "hl-code-str";
|
|
2951
|
-
if (match[3]) return "hl-code-
|
|
2952
|
-
if (match[4]) return "hl-code-
|
|
2962
|
+
if (match[3]) return "hl-code-fn";
|
|
2963
|
+
if (match[4]) return "hl-code-kw";
|
|
2964
|
+
if (match[5]) return "hl-code-fn";
|
|
2965
|
+
if (match[6]) return "hl-code-type";
|
|
2966
|
+
if (match[7]) return "hl-code-num";
|
|
2953
2967
|
return "hl-code";
|
|
2954
2968
|
});
|
|
2955
2969
|
return "<span class='hl-code'>" + highlighted + "</span>";
|
|
2956
2970
|
}
|
|
2957
2971
|
|
|
2958
2972
|
if (lang === "fortran") {
|
|
2959
|
-
const fPattern = /(!.*$)|("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')|(\b(?:program|end|subroutine|function|module|use|implicit|none|integer|real|double|precision|complex|character|logical|dimension|allocatable|intent|in|out|inout|parameter|data|do|if|then|else|elseif|endif|enddo|call|return|write|read|print|format|stop|contains|type|class|select|case|where|forall|associate|block|procedure|interface|abstract|extends|allocate|deallocate|cycle|exit|go|to|common|equivalence|save|external|intrinsic)\b)|(\b\d+(?:\.\d+)?(?:[dDeE][+-]?\d+)?\b)/gi;
|
|
2973
|
+
const fPattern = /(!.*$)|("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')|(\b(?:program|end|subroutine|function|module|use|implicit|none|integer|real|double|precision|complex|character|logical|dimension|allocatable|intent|in|out|inout|parameter|data|do|if|then|else|elseif|endif|enddo|call|return|write|read|print|format|stop|contains|type|class|select|case|where|forall|associate|block|procedure|interface|abstract|extends|allocate|deallocate|cycle|exit|go|to|common|equivalence|save|external|intrinsic)\b)|(\b[A-Za-z_][A-Za-z0-9_]*(?=\s*\())|(\b\d+(?:\.\d+)?(?:[dDeE][+-]?\d+)?\b)/gi;
|
|
2960
2974
|
const highlighted = highlightCodeTokens(source, fPattern, (match) => {
|
|
2961
2975
|
if (match[1]) return "hl-code-com";
|
|
2962
2976
|
if (match[2]) return "hl-code-str";
|
|
2963
2977
|
if (match[3]) return "hl-code-kw";
|
|
2964
|
-
if (match[4]) return "hl-code-
|
|
2978
|
+
if (match[4]) return "hl-code-fn";
|
|
2979
|
+
if (match[5]) return "hl-code-num";
|
|
2965
2980
|
return "hl-code";
|
|
2966
2981
|
});
|
|
2967
2982
|
return "<span class='hl-code'>" + highlighted + "</span>";
|
|
2968
2983
|
}
|
|
2969
2984
|
|
|
2970
2985
|
if (lang === "r") {
|
|
2971
|
-
const rPattern = /(#.*$)|("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')|(\b(?:function|if|else|for|while|repeat|in|next|break|return|TRUE|FALSE|NULL|NA|NA_integer_|NA_real_|NA_complex_|NA_character_|Inf|NaN|library|require|source|local|switch)\b)|(<-|->|<<-|->>)|(\b\d+(?:\.\d+)?(?:[eE][+-]?\d+)?[Li]?\b)/g;
|
|
2986
|
+
const rPattern = /(#.*$)|("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')|(\b(?:function|if|else|for|while|repeat|in|next|break|return|TRUE|FALSE|NULL|NA|NA_integer_|NA_real_|NA_complex_|NA_character_|Inf|NaN|library|require|source|local|switch)\b)|(<-|->|<<-|->>)|(\b[A-Za-z.][A-Za-z0-9._]*(?=\s*\())|(\b\d+(?:\.\d+)?(?:[eE][+-]?\d+)?[Li]?\b)/g;
|
|
2972
2987
|
const highlighted = highlightCodeTokens(source, rPattern, (match) => {
|
|
2973
2988
|
if (match[1]) return "hl-code-com";
|
|
2974
2989
|
if (match[2]) return "hl-code-str";
|
|
2975
2990
|
if (match[3]) return "hl-code-kw";
|
|
2976
|
-
if (match[4]) return "hl-code-
|
|
2977
|
-
if (match[5]) return "hl-code-
|
|
2991
|
+
if (match[4]) return "hl-code-op";
|
|
2992
|
+
if (match[5]) return "hl-code-fn";
|
|
2993
|
+
if (match[6]) return "hl-code-num";
|
|
2978
2994
|
return "hl-code";
|
|
2979
2995
|
});
|
|
2980
2996
|
return "<span class='hl-code'>" + highlighted + "</span>";
|
|
2981
2997
|
}
|
|
2982
2998
|
|
|
2983
2999
|
if (lang === "matlab") {
|
|
2984
|
-
const matPattern = /(%.*$)|('(?:[^']|'')*'|"(?:[^"\\]|\\.)*")|(\b(?:function|end|if|elseif|else|for|while|switch|case|otherwise|try|catch|return|break|continue|global|persistent|classdef|properties|methods|events|enumeration|true|false)\b)|(\b\d+(?:\.\d+)?(?:[eE][+-]?\d+)?[i]?\b)/g;
|
|
3000
|
+
const matPattern = /(%.*$)|('(?:[^']|'')*'|"(?:[^"\\]|\\.)*")|(\b(?:function|end|if|elseif|else|for|while|switch|case|otherwise|try|catch|return|break|continue|global|persistent|classdef|properties|methods|events|enumeration|true|false)\b)|(\b[A-Za-z_][A-Za-z0-9_]*(?=\s*\())|(\b\d+(?:\.\d+)?(?:[eE][+-]?\d+)?[i]?\b)/g;
|
|
2985
3001
|
const highlighted = highlightCodeTokens(source, matPattern, (match) => {
|
|
2986
3002
|
if (match[1]) return "hl-code-com";
|
|
2987
3003
|
if (match[2]) return "hl-code-str";
|
|
2988
3004
|
if (match[3]) return "hl-code-kw";
|
|
2989
|
-
if (match[4]) return "hl-code-
|
|
3005
|
+
if (match[4]) return "hl-code-fn";
|
|
3006
|
+
if (match[5]) return "hl-code-num";
|
|
2990
3007
|
return "hl-code";
|
|
2991
3008
|
});
|
|
2992
3009
|
return "<span class='hl-code'>" + highlighted + "</span>";
|
|
@@ -3084,7 +3101,13 @@
|
|
|
3084
3101
|
}
|
|
3085
3102
|
|
|
3086
3103
|
if (inFence) {
|
|
3087
|
-
|
|
3104
|
+
if (line.length === 0) {
|
|
3105
|
+
out.push(EMPTY_OVERLAY_LINE);
|
|
3106
|
+
} else if (fenceLanguage) {
|
|
3107
|
+
out.push(highlightCodeLine(line, fenceLanguage));
|
|
3108
|
+
} else {
|
|
3109
|
+
out.push(wrapHighlight("hl-md-code", line));
|
|
3110
|
+
}
|
|
3088
3111
|
continue;
|
|
3089
3112
|
}
|
|
3090
3113
|
|
package/client/studio.css
CHANGED
|
@@ -482,6 +482,10 @@
|
|
|
482
482
|
}
|
|
483
483
|
|
|
484
484
|
.hl-code {
|
|
485
|
+
color: var(--text);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
.hl-md-code {
|
|
485
489
|
color: var(--md-code);
|
|
486
490
|
}
|
|
487
491
|
|
|
@@ -508,6 +512,18 @@
|
|
|
508
512
|
color: var(--syntax-variable);
|
|
509
513
|
}
|
|
510
514
|
|
|
515
|
+
.hl-code-fn {
|
|
516
|
+
color: var(--syntax-function);
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
.hl-code-type {
|
|
520
|
+
color: var(--syntax-type);
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
.hl-code-op {
|
|
524
|
+
color: var(--syntax-operator);
|
|
525
|
+
}
|
|
526
|
+
|
|
511
527
|
.hl-diff-add {
|
|
512
528
|
color: var(--ok);
|
|
513
529
|
background: rgba(46, 160, 67, 0.12);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-studio",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.40",
|
|
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",
|