@hyperpuncher/pi-ui 0.38.2 → 0.39.0
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/README.md +53 -18
- package/dist/npm/server-main.js +123 -120
- package/package.json +7 -7
- package/static/app/file-transfer.js +13 -2
- package/static/app/file-transfer_test.ts +16 -0
- package/static/build/chunks/{code-theme-y49p9zss.js → code-theme-4n26zw8w.js} +1 -1
- package/static/build/chunks/{fonts-pcnzbv4q.js → fonts-fmjkwnbd.js} +1 -1
- package/static/build/chunks/{main-61mzprk0.js → main-3kywnyz0.js} +5 -5
- package/static/build/chunks/{main-wcnadmhs.js → main-r8cn68g6.js} +1 -1
- package/static/build/chunks/{workspace-review-3scrbyaw.js → workspace-review-p84b3znd.js} +1 -1
- package/static/build/main.js +4 -4
- package/static/vendor/datastar-inspector.min.js +0 -1021
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyperpuncher/pi-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.39.0",
|
|
4
4
|
"description": "keyboard-first minimal gui for pi",
|
|
5
5
|
"homepage": "https://pi-ui.app",
|
|
6
6
|
"bugs": "https://github.com/hyperpuncher/pi-ui/issues",
|
|
@@ -48,15 +48,15 @@
|
|
|
48
48
|
"audit": "bunx fallow audit"
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
|
-
"@earendil-works/pi-ai": "^0.84.
|
|
52
|
-
"@earendil-works/pi-coding-agent": "^0.84.
|
|
53
|
-
"@earendil-works/pi-tui": "^0.84.
|
|
54
|
-
"@iconify-json/lucide": "^1.2.
|
|
51
|
+
"@earendil-works/pi-ai": "^0.84.4",
|
|
52
|
+
"@earendil-works/pi-coding-agent": "^0.84.4",
|
|
53
|
+
"@earendil-works/pi-tui": "^0.84.4",
|
|
54
|
+
"@iconify-json/lucide": "^1.2.127",
|
|
55
55
|
"@kitajs/html": "5.0.0-next.1",
|
|
56
56
|
"@pierre/diffs": "^1.3.6",
|
|
57
57
|
"@pierre/trees": "^1.0.0-beta.6",
|
|
58
58
|
"@starfederation/datastar-sdk": "^1.0.0",
|
|
59
|
-
"typebox": "^1.3.
|
|
59
|
+
"typebox": "^1.3.20"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
62
|
"@oxlint/plugins": "^1.80.0",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"concurrently": "^10.0.5",
|
|
67
67
|
"oxfmt": "^0.65.0",
|
|
68
68
|
"oxlint": "^1.80.0",
|
|
69
|
-
"oxlint-tailwindcss": "^1.10.
|
|
69
|
+
"oxlint-tailwindcss": "^1.10.2",
|
|
70
70
|
"tailwindcss": "^4.3.3",
|
|
71
71
|
"typescript": "^7.0.2"
|
|
72
72
|
},
|
|
@@ -89,7 +89,10 @@ export async function insert(data) {
|
|
|
89
89
|
}
|
|
90
90
|
const uploaded = await uploadTransferredFiles(files);
|
|
91
91
|
for (let index = 0; index < uploaded.length; index += 1) {
|
|
92
|
-
addAttachment({
|
|
92
|
+
addAttachment({
|
|
93
|
+
path: uploaded[index].path,
|
|
94
|
+
file: fileWithDetectedMimeType(files[index], uploaded[index].mimeType),
|
|
95
|
+
});
|
|
93
96
|
}
|
|
94
97
|
}
|
|
95
98
|
|
|
@@ -172,6 +175,14 @@ export function jpegFileName(name) {
|
|
|
172
175
|
: `${name || "image"}.jpg`;
|
|
173
176
|
}
|
|
174
177
|
|
|
178
|
+
export function fileWithDetectedMimeType(file, mimeType) {
|
|
179
|
+
if (mimeType === undefined || file.type === mimeType) return file;
|
|
180
|
+
return new File([file], file.name, {
|
|
181
|
+
type: mimeType ?? "",
|
|
182
|
+
lastModified: file.lastModified,
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
|
|
175
186
|
async function prepareTransferredImages(files) {
|
|
176
187
|
const prepared = [];
|
|
177
188
|
for (const file of files) {
|
|
@@ -272,7 +283,7 @@ async function uploadTransferredFiles(files) {
|
|
|
272
283
|
return [];
|
|
273
284
|
}
|
|
274
285
|
showTransferError("");
|
|
275
|
-
return Array.isArray(result.
|
|
286
|
+
return Array.isArray(result.imports) ? result.imports : [];
|
|
276
287
|
} catch {
|
|
277
288
|
showTransferError("Could not transfer the selected files.");
|
|
278
289
|
return [];
|
|
@@ -20,6 +20,7 @@ const {
|
|
|
20
20
|
composePrompt,
|
|
21
21
|
convertAvifToJpeg,
|
|
22
22
|
extractTransferredFilePaths,
|
|
23
|
+
fileWithDetectedMimeType,
|
|
23
24
|
formatFileReferences,
|
|
24
25
|
isAvifImageFile,
|
|
25
26
|
isHeicImageFile,
|
|
@@ -67,6 +68,21 @@ test("attachment file kinds use MIME types and extensions", () => {
|
|
|
67
68
|
assertEquals(attachmentFileKind("unknown.bin", ""), "file");
|
|
68
69
|
});
|
|
69
70
|
|
|
71
|
+
test("server-detected MIME types replace untrusted browser metadata", async () => {
|
|
72
|
+
const original = new File(["image"], "screenshot.bin", {
|
|
73
|
+
type: "application/octet-stream",
|
|
74
|
+
lastModified: 42,
|
|
75
|
+
});
|
|
76
|
+
const detected = fileWithDetectedMimeType(original, "image/png");
|
|
77
|
+
assertEquals(detected.name, original.name);
|
|
78
|
+
assertEquals(detected.type, "image/png");
|
|
79
|
+
assertEquals(detected.lastModified, 42);
|
|
80
|
+
assertEquals(await detected.text(), "image");
|
|
81
|
+
assertEquals(fileWithDetectedMimeType(detected, "image/png"), detected);
|
|
82
|
+
assertEquals(fileWithDetectedMimeType(detected, null).type, "");
|
|
83
|
+
assertEquals(fileWithDetectedMimeType(detected, undefined), detected);
|
|
84
|
+
});
|
|
85
|
+
|
|
70
86
|
test("AVIF images are detected and renamed for JPEG conversion", () => {
|
|
71
87
|
assertEquals(isAvifImageFile({ name: "photo.bin", type: "image/avif" }), true);
|
|
72
88
|
assertEquals(isAvifImageFile({ name: "photo.AVIF", type: "" }), true);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{j as c,k as l}from"./main-
|
|
1
|
+
import{j as c,k as l}from"./main-r8cn68g6.js";import"./main-7fchxg57.js";import"./main-3kywnyz0.js";import"./main-x61973bh.js";var k=["pierre-light","pierre-light-soft","pierre-light-vibrant","pierre-light-protanopia-deuteranopia","pierre-light-tritanopia","ayu-light","catppuccin-latte","everforest-light","github-light","github-light-default","github-light-high-contrast","gruvbox-light-hard","gruvbox-light-medium","gruvbox-light-soft","horizon-bright","kanagawa-lotus","light-plus","material-theme-lighter","min-light","night-owl-light","one-light","rose-pine-dawn","slack-ochin","snazzy-light","solarized-light","vitesse-light"],T=["pierre-dark","pierre-dark-soft","pierre-dark-vibrant","pierre-dark-protanopia-deuteranopia","pierre-dark-tritanopia","ayu-dark","ayu-mirage","catppuccin-frappe","catppuccin-macchiato","catppuccin-mocha","everforest-dark","github-dark","github-dark-default","github-dark-dimmed","github-dark-high-contrast","gruvbox-dark-hard","gruvbox-dark-medium","gruvbox-dark-soft","horizon","kanagawa-wave","kanagawa-dragon","dark-plus","material-theme","material-theme-darker","material-theme-ocean","material-theme-palenight","min-dark","night-owl","one-dark-pro","rose-pine","rose-pine-moon","slack-dark","andromeeda","solarized-dark","vitesse-dark","vitesse-black","aurora-x","dracula","dracula-soft","houston","laserwave","monokai","nord","plastic","poimandres","red","synthwave-84","tokyo-night","vesper"],y=new Map(Object.entries({ayu:"Ayu",cvd:"CVD",github:"GitHub",min:"Min",pierre:"Pierre",vscode:"VS Code"}));function v(e){return e.split("-").map((t)=>y.get(t)??`${t[0]?.toUpperCase()??""}${t.slice(1)}`).join(" ")}function p(e,t){return{appearance:t,group:e.startsWith("pierre-")?"pierre":"shiki",label:v(e),name:e}}var C=k.map((e)=>p(e,"light")).toSorted((e,t)=>e.label.localeCompare(t.label)),b=T.map((e)=>p(e,"dark")).toSorted((e,t)=>e.label.localeCompare(t.label)),h=[...C,...b];var w=h.map((e)=>e.name),m;window.piUi.codeTheme={loadFontPreviews(e,t){E(document.documentElement.classList.contains("dark")?t:e)},loadPreviews(){m??=x()}};async function E(e){let t=[...document.querySelectorAll("[data-font-code-preview]")],n=t[0]?.textContent;if(!n)return;try{await l({langs:["typescript"],themes:[e]});let r=c();if(!r)return;let o=r.codeToTokens(n,{lang:"typescript",theme:e});for(let d of t)u(d,o.tokens,o.fg??"inherit")}catch{}}async function x(){s("Loading theme previews…");try{await l({langs:["typescript"],themes:w});let e=c();if(!e)throw Error("Highlighter unavailable");let t=document.querySelectorAll("[data-theme-name]");for(let[n,r]of[...t].entries()){let o=r.dataset.themeName,d=P(r.dataset.themeAppearance),i=r.querySelector(".code-theme-preview");if(!o||!d||!i)continue;let a=e.codeToTokens(A(o,d),{lang:"typescript",theme:o});if(u(i,a.tokens,a.fg??"inherit"),n>0&&n%8===0)await H()}s("Theme previews ready.")}catch{m=void 0,s("Could not load theme previews.")}}function P(e){return e==="light"||e==="dark"?e:void 0}function A(e,t){return`const theme = {
|
|
2
2
|
name: '${e}',
|
|
3
3
|
mode: '${t}',
|
|
4
4
|
}`}function u(e,t,n){e.replaceChildren(),e.style.color=n,e.style.removeProperty("background-color");let r=document.createElement("code");for(let[o,d]of t.entries()){for(let i of d){let a=document.createElement("span");if(a.textContent=i.content,i.color)a.style.color=i.color;for(let[g,f]of Object.entries(i.htmlStyle??{}))a.style.setProperty(g,f);r.append(a)}if(o<t.length-1)r.append(`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./main-
|
|
1
|
+
import"./main-3kywnyz0.js";import"./main-x61973bh.js";var s="system";function e(n,o){let t=n==="mono"?'ui-monospace, "SF Mono", "Cascadia Mono", monospace':"ui-sans-serif, system-ui, sans-serif";return o===s?t:`${r(o)}, ${t}`}function r(n){return`"${n.replaceAll("\\","\\\\").replaceAll('"',"\\\"")}"`}window.piUi.fonts={apply(n,o){document.documentElement.style.setProperty("--font-mono",e("mono",n)),document.documentElement.style.setProperty("--font-sans",e("sans",o))}};
|