diff options
| author | Craig Jennings <c@cjennings.net> | 2026-06-20 03:34:57 -0400 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-06-20 03:34:57 -0400 |
| commit | 0679c47c54dd935a0cc7d87c64081262b4367697 (patch) | |
| tree | de84ffb19404a9a3767a77f2e56b1f3e6986ae12 /scripts/theme-studio/app.js | |
| parent | f0158f6b8460da2cfbfec596ae39b4b42953299f (diff) | |
| download | dotemacs-0679c47c54dd935a0cc7d87c64081262b4367697.tar.gz dotemacs-0679c47c54dd935a0cc7d87c64081262b4367697.zip | |
feat(theme-studio): export through the save-file picker to overwrite in place
Re-exporting a theme used to land a "name (1).json" duplicate. The export built a blob and clicked a download link, which routes through the browser's downloads folder, and the browser uniquifies a re-save rather than replacing the file.
I switched export to the File System Access API (showSaveFilePicker): it writes straight to the file you pick, so re-exporting the same WIP.json overwrites it. Where the API is absent the old blob download still runs, mirroring importTheme's picker-with-fallback shape. A new #savetest browser gate stubs the picker and checks the written content and the close.
Diffstat (limited to 'scripts/theme-studio/app.js')
| -rw-r--r-- | scripts/theme-studio/app.js | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/scripts/theme-studio/app.js b/scripts/theme-studio/app.js index f6e4cd2cd..d6b42a324 100644 --- a/scripts/theme-studio/app.js +++ b/scripts/theme-studio/app.js @@ -436,7 +436,18 @@ function exportObj(){normalizePalette();const o={name:themeName(),palette:PALETT function exportState(){const t=document.getElementById('export');t.value=JSON.stringify(exportObj(),null,1);t.style.display='block';t.focus();t.select();} function toggleJSON(){const t=document.getElementById('export'),b=document.getElementById('jsonbtn');if(t.style.display==='block'){t.style.display='none';b.textContent='show';}else{exportState();b.textContent='hide';}} function updateTitle(){const n=document.getElementById('themename').value.trim();document.getElementById('pagetitle').textContent=(n||'Untitled')+': theme';} -function exportTheme(){const blob=new Blob([JSON.stringify(exportObj(),null,1)],{type:'application/json'});const a=document.createElement('a');a.href=URL.createObjectURL(blob);a.download=fileSlug()+'.json';a.click();} +// Export the theme JSON. Prefer the File System Access API (showSaveFilePicker) +// so re-exporting overwrites the chosen file in place -- a blob download routes +// through the browser's downloads folder, which uniquifies a re-save as +// "name (1).json" rather than replacing it. Fall back to the blob download where +// the API is absent (mirrors importTheme's showOpenFilePicker/fileinput fallback). +async function exportTheme(){ + const data=JSON.stringify(exportObj(),null,1); + if(!window.showSaveFilePicker){const blob=new Blob([data],{type:'application/json'});const a=document.createElement('a');a.href=URL.createObjectURL(blob);a.download=fileSlug()+'.json';a.click();return;} + try{const h=await window.showSaveFilePicker({suggestedName:fileSlug()+'.json',types:[{description:'theme JSON',accept:{'application/json':['.json']}}]}); + const w=await h.createWritable();await w.write(data);await w.close(); + notify('saved "'+fileSlug()+'.json"',false); + }catch(e){if(e&&e.name!=='AbortError')notify('export failed: '+e.message,true);}} function applyImported(text){const d=JSON.parse(text);lastGone={};if(d.name)document.getElementById('themename').value=d.name;if(d.palette)PALETTE=d.palette.map(normalizePaletteEntry); if(!d.syntax)throw new Error('theme JSON is missing syntax; convert older files first'); SYNTAX={};CATS.forEach(c=>{const k=c[0];SYNTAX[k]=Object.assign(syntaxBlank(k),migrateLegacyFace(d.syntax[k]||{}));});syncAllSyntaxCache(); |
