@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hyperpuncher/pi-ui",
3
- "version": "0.38.2",
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.3",
52
- "@earendil-works/pi-coding-agent": "^0.84.3",
53
- "@earendil-works/pi-tui": "^0.84.3",
54
- "@iconify-json/lucide": "^1.2.126",
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.19"
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.0",
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({ path: uploaded[index], file: files[index] });
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.paths) ? result.paths : [];
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-wcnadmhs.js";import"./main-7fchxg57.js";import"./main-61mzprk0.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 = {
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-61mzprk0.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))}};
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))}};