From 3f86aeaf0cb95b6ea5118f0cbfe51705654d89bc Mon Sep 17 00:00:00 2001 From: hesukastro Date: Wed, 27 May 2026 22:42:19 +0800 Subject: [PATCH] filenames --- src/tools/playworksConverter.ts | 25 +++++++++++++++++--- standalone/playworks.go | 41 +++++++++++++++++++++++++++++---- 2 files changed, 59 insertions(+), 7 deletions(-) diff --git a/src/tools/playworksConverter.ts b/src/tools/playworksConverter.ts index 7a5af6e..3951673 100644 --- a/src/tools/playworksConverter.ts +++ b/src/tools/playworksConverter.ts @@ -9,6 +9,7 @@ const store: { panel: vscode.WebviewPanel | null } = { panel: null }; interface ConvertOptions { sourcePath: string; outputDir: string; + baseName?: string; networks: string[]; } @@ -38,7 +39,7 @@ export function openPlayworksConverter(_context: vscode.ExtensionContext) { if (!picked?.[0]) return; const srcPath = picked[0].fsPath; const dir = path.dirname(srcPath); - panel.webview.postMessage({ type: 'sourcePicked', path: srcPath, dir }); + panel.webview.postMessage({ type: 'sourcePicked', path: srcPath, dir, baseName: sourceBaseName(srcPath) }); break; } case 'pickOutput': { @@ -111,10 +112,17 @@ function sourceBaseName(sourcePath: string): string { .replace(/_(?:un|al|is|fb|gg|mo|vu|mtg|tt)$/, ''); } +function outputBaseName(opts: ConvertOptions): string { + const rawBaseName = opts.baseName?.trim() || sourceBaseName(opts.sourcePath); + const withoutExtension = rawBaseName.replace(/\.html?$/i, ''); + const safeBaseName = path.basename(withoutExtension).replace(/[<>:"/\\|?*]/g, '_').trim(); + return safeBaseName || sourceBaseName(opts.sourcePath); +} + async function convertNetwork(html: string, opts: ConvertOptions, network: string): Promise { const transformed = transformHtml(html, network); const needsZip = ZIPPED_NETWORKS.has(network); - const baseName = sourceBaseName(opts.sourcePath); + const baseName = outputBaseName(opts); const htmlFileName = `${baseName}_${network}.html`; const outputDir = path.join(opts.outputDir, NETWORK_OUTPUT_FOLDERS[network] ?? network); fs.mkdirSync(outputDir, { recursive: true }); @@ -384,6 +392,13 @@ function getHtml(): string { +
+ +
+ +
+
+
@@ -417,6 +432,7 @@ function getHtml(): string { const srcEl = document.getElementById('src'); const outEl = document.getElementById('outDir'); + const baseNameEl = document.getElementById('baseName'); const convertBtn = document.getElementById('convert'); const openOutBtn = document.getElementById('openOut'); const statusEl = document.getElementById('status'); @@ -424,7 +440,7 @@ function getHtml(): string { function updateConvertBtn() { const hasNet = [...document.querySelectorAll('.net-cb')].some(c => c.checked); - convertBtn.disabled = !srcEl.value || !outEl.value || !hasNet; + convertBtn.disabled = !srcEl.value || !outEl.value || !baseNameEl.value.trim() || !hasNet; } document.getElementById('pickSrc').addEventListener('click', () => vscode.postMessage({ type: 'pickSource' })); @@ -439,6 +455,7 @@ function getHtml(): string { }); document.querySelectorAll('.net-cb').forEach(c => c.addEventListener('change', updateConvertBtn)); outEl.addEventListener('input', updateConvertBtn); + baseNameEl.addEventListener('input', updateConvertBtn); openOutBtn.addEventListener('click', () => { if (outputDir) vscode.postMessage({ type: 'openOutput', dir: outputDir }); @@ -461,6 +478,7 @@ function getHtml(): string { opts: { sourcePath: srcEl.value, outputDir: outEl.value, + baseName: baseNameEl.value, networks, }, }); @@ -470,6 +488,7 @@ function getHtml(): string { const msg = event.data; if (msg.type === 'sourcePicked') { srcEl.value = msg.path; + baseNameEl.value = msg.baseName || ''; if (!outEl.value && msg.dir) { outEl.value = msg.dir; outputDir = msg.dir; diff --git a/standalone/playworks.go b/standalone/playworks.go index 8efc607..d926f90 100644 --- a/standalone/playworks.go +++ b/standalone/playworks.go @@ -14,6 +14,7 @@ import ( type playworksConvertOptions struct { SourcePath string `json:"sourcePath"` OutputDir string `json:"outputDir"` + BaseName string `json:"baseName"` Networks []string `json:"networks"` } @@ -60,6 +61,13 @@ func PlayworksPage(w http.ResponseWriter, r *http.Request) {
+
+ +
+ +
+
+
@@ -101,6 +109,7 @@ func PlayworksPage(w http.ResponseWriter, r *http.Request) { let outputDir = ''; const srcEl = document.getElementById('src'); const outEl = document.getElementById('outDir'); +const baseNameEl = document.getElementById('baseName'); const convertBtn = document.getElementById('convert'); const openOutBtn = document.getElementById('openOut'); const statusEl = document.getElementById('status'); @@ -108,7 +117,7 @@ const resultsEl = document.getElementById('results'); function updateConvertBtn() { const hasNet = [...document.querySelectorAll('.net-cb')].some(c => c.checked); - convertBtn.disabled = !srcEl.value || !outEl.value || !hasNet; + convertBtn.disabled = !srcEl.value || !outEl.value || !baseNameEl.value.trim() || !hasNet; } document.getElementById('pickSrc').addEventListener('click', async () => { @@ -116,6 +125,7 @@ document.getElementById('pickSrc').addEventListener('click', async () => { const j = await r.json(); if (j.path) { srcEl.value = j.path; + baseNameEl.value = j.baseName || ''; if (!outEl.value && j.dir) { outEl.value = j.dir; outputDir = j.dir; } updateConvertBtn(); } @@ -135,6 +145,7 @@ document.getElementById('selectNone').addEventListener('click', () => { }); document.querySelectorAll('.net-cb').forEach(c => c.addEventListener('change', updateConvertBtn)); outEl.addEventListener('input', updateConvertBtn); +baseNameEl.addEventListener('input', updateConvertBtn); openOutBtn.addEventListener('click', () => { if (outputDir) fetch('/api/open', { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({ url: outputDir }) }); }); @@ -153,7 +164,7 @@ document.getElementById('convert').addEventListener('click', async () => { const res = await fetch('/api/playworks/convert', { method:'POST', headers:{'Content-Type':'application/json'}, - body: JSON.stringify({ sourcePath: srcEl.value, outputDir: outEl.value, networks }) + body: JSON.stringify({ sourcePath: srcEl.value, outputDir: outEl.value, baseName: baseNameEl.value, networks }) }); const msg = await res.json(); convertBtn.disabled = false; @@ -197,7 +208,7 @@ func PlayworksPickSource(w http.ResponseWriter, r *http.Request) { writeJSON(w, map[string]any{}) return } - writeJSON(w, map[string]any{"path": picked[0], "dir": filepath.Dir(picked[0])}) + writeJSON(w, map[string]any{"path": picked[0], "dir": filepath.Dir(picked[0]), "baseName": playworksSourceBaseName(picked[0])}) } func PlayworksPickOutput(w http.ResponseWriter, r *http.Request) { @@ -243,9 +254,31 @@ func playworksSourceBaseName(sourcePath string) string { return playworksSuffixRx.ReplaceAllString(base, "") } +func playworksOutputBaseName(opts playworksConvertOptions) string { + baseName := strings.TrimSpace(opts.BaseName) + if baseName == "" { + baseName = playworksSourceBaseName(opts.SourcePath) + } + baseName = strings.TrimSuffix(baseName, filepath.Ext(baseName)) + baseName = filepath.Base(baseName) + baseName = strings.Map(func(r rune) rune { + switch r { + case '<', '>', ':', '"', '/', '\\', '|', '?', '*': + return '_' + default: + return r + } + }, baseName) + baseName = strings.TrimSpace(baseName) + if baseName == "" { + return playworksSourceBaseName(opts.SourcePath) + } + return baseName +} + func convertPlayworksNetwork(htmlSrc string, opts playworksConvertOptions, network string) (string, error) { transformed := transformPlayworksHTML(htmlSrc, network) - baseName := playworksSourceBaseName(opts.SourcePath) + baseName := playworksOutputBaseName(opts) htmlFileName := fmt.Sprintf("%s_%s.html", baseName, network) outputDir := filepath.Join(opts.OutputDir, playworksNetworkOutputFolder(network)) if err := os.MkdirAll(outputDir, 0755); err != nil {