From e96719ef710b77b91fdfc4637c92e47e54e99c36 Mon Sep 17 00:00:00 2001 From: mycroftjr Date: Tue, 29 Aug 2023 20:18:16 -0700 Subject: [PATCH 1/6] sanitize filenames --- package-lock.json | 43 +++++++++++++++++++++++++ package.json | 1 + src/core/workspace/folder-to-project.ts | 3 +- 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 2d20ead..5beb622 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "glob": "^10.2.2", "jsonschema": "^1.4.1", "jszip": "^3.10.1", + "sanitize-filename": "^1.6.3", "uuid": "^9.0.0" }, "devDependencies": { @@ -1132,6 +1133,14 @@ } ] }, + "node_modules/sanitize-filename": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz", + "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==", + "dependencies": { + "truncate-utf8-bytes": "^1.0.0" + } + }, "node_modules/setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", @@ -1339,6 +1348,14 @@ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, + "node_modules/truncate-utf8-bytes": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", + "integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==", + "dependencies": { + "utf8-byte-length": "^1.0.1" + } + }, "node_modules/tsc-alias": { "version": "1.8.4", "resolved": "https://registry.npmjs.org/tsc-alias/-/tsc-alias-1.8.4.tgz", @@ -1369,6 +1386,11 @@ "node": ">=12.20" } }, + "node_modules/utf8-byte-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz", + "integrity": "sha512-4+wkEYLBbWxqTahEsWrhxepcoVOJ+1z5PGIjPZxRkytcdSUaNjIjBM7Xn8E+pdSuV7SzvWovBFA54FO0JSoqhA==" + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -2255,6 +2277,14 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, + "sanitize-filename": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz", + "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==", + "requires": { + "truncate-utf8-bytes": "^1.0.0" + } + }, "setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", @@ -2402,6 +2432,14 @@ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, + "truncate-utf8-bytes": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", + "integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==", + "requires": { + "utf8-byte-length": "^1.0.1" + } + }, "tsc-alias": { "version": "1.8.4", "resolved": "https://registry.npmjs.org/tsc-alias/-/tsc-alias-1.8.4.tgz", @@ -2422,6 +2460,11 @@ "integrity": "sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==", "dev": true }, + "utf8-byte-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz", + "integrity": "sha512-4+wkEYLBbWxqTahEsWrhxepcoVOJ+1z5PGIjPZxRkytcdSUaNjIjBM7Xn8E+pdSuV7SzvWovBFA54FO0JSoqhA==" + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", diff --git a/package.json b/package.json index 5fa22ff..cfba216 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "glob": "^10.2.2", "jsonschema": "^1.4.1", "jszip": "^3.10.1", + "sanitize-filename": "^1.6.3", "uuid": "^9.0.0" }, "devDependencies": { diff --git a/src/core/workspace/folder-to-project.ts b/src/core/workspace/folder-to-project.ts index 2839222..2b62143 100644 --- a/src/core/workspace/folder-to-project.ts +++ b/src/core/workspace/folder-to-project.ts @@ -8,6 +8,7 @@ import { formatResourceType, formatResourceKey, formatAsHexString } from "@s4tk/ import { findGlobMatches, parseKeyFromTgi } from "#building/resources"; import StringTableJson from "#stbls/stbl-json"; import * as inference from "#indexing/inference"; +var sanitize = require("sanitize-filename"); /** * Prompts the user for a folder containing packages and/or loose TGI files and @@ -78,7 +79,7 @@ function _getDestFilename(destFolder: string, filename: string, ext: string): st ); let index = 0; - let destPath = baseDestPath; + let destPath = sanitize(baseDestPath, "_"); while (fs.existsSync(`${destPath}.${ext}`)) { destPath = `${baseDestPath}_${index++}`; } From 76df8dd930f4e733f703bd9aac00aaf2e6ea8ef9 Mon Sep 17 00:00:00 2001 From: mycroftjr Date: Tue, 29 Aug 2023 20:31:59 -0700 Subject: [PATCH 2/6] correct usage --- src/core/workspace/folder-to-project.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/core/workspace/folder-to-project.ts b/src/core/workspace/folder-to-project.ts index 2b62143..784f7ad 100644 --- a/src/core/workspace/folder-to-project.ts +++ b/src/core/workspace/folder-to-project.ts @@ -71,15 +71,17 @@ function _appendFolder(basepath: string, ...toAppend: string[]): string { } function _getDestFilename(destFolder: string, filename: string, ext: string): string { + const pfilename = filename.includes(":") + ? filename.split(":").slice(1).join(":") + : filename + const sanitized = sanitize(pfilename, { replacement: '_', }) const baseDestPath = path.join( destFolder, - filename.includes(":") - ? filename.split(":").slice(1).join(":") - : filename + sanitized ); let index = 0; - let destPath = sanitize(baseDestPath, "_"); + let destPath = baseDestPath; while (fs.existsSync(`${destPath}.${ext}`)) { destPath = `${baseDestPath}_${index++}`; } From c1bcebb196d6e1f2f204809c995edbd76baa8db9 Mon Sep 17 00:00:00 2001 From: mycroftjr Date: Tue, 29 Aug 2023 21:54:54 -0700 Subject: [PATCH 3/6] improve folder to S4TK SimData naming --- src/core/workspace/folder-to-project.ts | 42 +++++++++++++++++++------ 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/src/core/workspace/folder-to-project.ts b/src/core/workspace/folder-to-project.ts index 784f7ad..ae102fe 100644 --- a/src/core/workspace/folder-to-project.ts +++ b/src/core/workspace/folder-to-project.ts @@ -10,6 +10,8 @@ import StringTableJson from "#stbls/stbl-json"; import * as inference from "#indexing/inference"; var sanitize = require("sanitize-filename"); +var instanceMap: Map; + /** * Prompts the user for a folder containing packages and/or loose TGI files and * turns them into a structure that is easier to use with the S4TK extension. @@ -41,6 +43,8 @@ export async function convertFolderToProject() { const sourcePattern = path.join(sourceFolderUri.fsPath, "**/*").replace(/\\/g, "/"); const matches = findGlobMatches([sourcePattern], undefined, "supported"); + instanceMap = new Map(); + matches.forEach((sourcePath: string) => { _processSourceFile(sourcePath, destFolderUri.fsPath); }); @@ -99,6 +103,19 @@ function _processSourceFile(sourcePath: string, destFolder: string) { Package.extractResources(buffer, { loadRaw: true, decompressBuffers: true, + resourceFilter(type, group, inst) { + return type in TuningResourceType; + } + }).forEach(entry => { + _processResource(entry.key, entry.value.buffer, packageDest); + }); + + Package.extractResources(buffer, { + loadRaw: true, + decompressBuffers: true, + resourceFilter(type, group, inst) { + return !(type in TuningResourceType); + } }).forEach(entry => { _processResource(entry.key, entry.value.buffer, packageDest); }); @@ -136,10 +153,10 @@ function _processResource(key: ResourceKey, buffer: Buffer, destFolder: string) xmlContent = inference.insertXmlKeyOverrides(xmlContent, overrides) ?? xmlContent; // FIXME: remove creator name prefix - fs.writeFileSync( - _getDestFilename(subfolder, metadata.attrs?.n ?? "UnnamedTuning", "xml"), - xmlContent - ); + const dest = _getDestFilename(subfolder, metadata.attrs?.n ?? "UnnamedTuning", "xml"); + fs.writeFileSync(dest, xmlContent); + + instanceMap.set(key.instance, dest); } else if (key.type in BinaryResourceType) { if (key.type === BinaryResourceType.SimData) { const subfolder = key.group in SimDataGroup @@ -152,12 +169,17 @@ function _processResource(key: ResourceKey, buffer: Buffer, destFolder: string) const xmlContent = simdata.toXmlDocument().toXml(); - // TODO: insert group and instance override if tuning not found - - fs.writeFileSync( - _getDestFilename(subfolder, simdata.instance.name, "SimData.xml"), - xmlContent - ); + + var dest: string; + const val = instanceMap.get(key.instance); + if (val) { + dest = val.replace(".xml", ".SimData.xml"); + } else { + // TODO: insert group and instance override instead of using formatResourceKey + dest = _getDestFilename(subfolder, formatResourceKey(key, "_"), "SimData.xml"); + } + + fs.writeFileSync(dest, xmlContent); } else if (key.type === BinaryResourceType.StringTable) { const subfolder = getSubfolder("StringTable"); const stbl = StringTableResource.from(buffer); From 5b596eb5c480366afc41779ec696a438f428d928 Mon Sep 17 00:00:00 2001 From: mycroftjr Date: Thu, 31 Aug 2023 22:31:40 -0700 Subject: [PATCH 4/6] also set the SimData instance names --- src/core/workspace/folder-to-project.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/core/workspace/folder-to-project.ts b/src/core/workspace/folder-to-project.ts index ae102fe..bd63ec5 100644 --- a/src/core/workspace/folder-to-project.ts +++ b/src/core/workspace/folder-to-project.ts @@ -10,7 +10,7 @@ import StringTableJson from "#stbls/stbl-json"; import * as inference from "#indexing/inference"; var sanitize = require("sanitize-filename"); -var instanceMap: Map; +var instanceMap: Map; /** * Prompts the user for a folder containing packages and/or loose TGI files and @@ -153,10 +153,11 @@ function _processResource(key: ResourceKey, buffer: Buffer, destFolder: string) xmlContent = inference.insertXmlKeyOverrides(xmlContent, overrides) ?? xmlContent; // FIXME: remove creator name prefix - const dest = _getDestFilename(subfolder, metadata.attrs?.n ?? "UnnamedTuning", "xml"); + const name = metadata.attrs?.n ?? "UnnamedTuning" + const dest = _getDestFilename(subfolder, name, "xml"); fs.writeFileSync(dest, xmlContent); - instanceMap.set(key.instance, dest); + instanceMap.set(key.instance, [name, dest]); } else if (key.type in BinaryResourceType) { if (key.type === BinaryResourceType.SimData) { const subfolder = key.group in SimDataGroup @@ -167,18 +168,17 @@ function _processResource(key: ResourceKey, buffer: Buffer, destFolder: string) ? SimDataResource.from(buffer) : SimDataResource.fromXml(buffer); - const xmlContent = simdata.toXmlDocument().toXml(); - - var dest: string; const val = instanceMap.get(key.instance); if (val) { - dest = val.replace(".xml", ".SimData.xml"); + simdata.instance.name = val[0] + "_SimData"; + dest = val[1].replace(".xml", ".SimData.xml"); } else { // TODO: insert group and instance override instead of using formatResourceKey dest = _getDestFilename(subfolder, formatResourceKey(key, "_"), "SimData.xml"); } + const xmlContent = simdata.toXmlDocument().toXml(); fs.writeFileSync(dest, xmlContent); } else if (key.type === BinaryResourceType.StringTable) { const subfolder = getSubfolder("StringTable"); From 606bd53ae54bda3371439605749cbed6829a80bb Mon Sep 17 00:00:00 2001 From: mycroftjr Date: Fri, 1 Sep 2023 00:30:39 -0700 Subject: [PATCH 5/6] use the same sanitization for Clone Tuning --- src/core/tuning/commands.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/core/tuning/commands.ts b/src/core/tuning/commands.ts index 5d51a8d..db80343 100644 --- a/src/core/tuning/commands.ts +++ b/src/core/tuning/commands.ts @@ -9,6 +9,8 @@ import { insertXmlKeyOverrides } from "#indexing/inference"; import { reduceBits } from "#helpers/hashing"; import { maxBitsForClass } from "#diagnostics/helpers"; +var sanitize = require("sanitize-filename"); + /** * Clones the tuning file (and its SimData, if it has one) at the given URI, * prompting the user for a new name to use. A new hash with the correct number @@ -44,7 +46,7 @@ export async function cloneWithNewName(srcUri: vscode.Uri) { const tuningFsPath = path.join( path.dirname(srcUri.fsPath), - `${newFilename.replace(/^[^:]*:/, "")}.xml` + sanitize(newFilename + ".xml", { replacement: '_', }) ); if (fs.existsSync(tuningFsPath)) { From 48103e78f904ba9b9a2014374bf9d0a656f3aeda Mon Sep 17 00:00:00 2001 From: mycroftjr Date: Thu, 14 Sep 2023 21:38:31 -0700 Subject: [PATCH 6/6] requested changes --- schemas/s4tk-config.schema.json | 4 ++ src/contributions/commands/workspace.ts | 5 +- src/core/building/builder.ts | 2 +- src/core/helpers/fs.ts | 11 ++++ src/core/tuning/commands.ts | 6 +- src/core/workspace/folder-to-project.ts | 80 ++++++++++++++----------- src/core/workspace/s4tk-config.ts | 8 ++- tsconfig.json | 3 +- 8 files changed, 75 insertions(+), 44 deletions(-) diff --git a/schemas/s4tk-config.schema.json b/schemas/s4tk-config.schema.json index 59d885e..6c46b26 100644 --- a/schemas/s4tk-config.schema.json +++ b/schemas/s4tk-config.schema.json @@ -237,6 +237,10 @@ "overrideIndexRoot": { "type": "string", "description": "The root to use for the resource index instead of `buildInstructions.source`. You likely do not have a use for this unless your project includes multiple packages that have files that override each other." + }, + "setSimDataNames": { + "type": "boolean", + "description": "Whether or not commands like 'Convert Folder to S4TK Project' are allowed to set SimData names to match their tuning." } } } diff --git a/src/contributions/commands/workspace.ts b/src/contributions/commands/workspace.ts index 1ed2b9d..dd73b9c 100644 --- a/src/contributions/commands/workspace.ts +++ b/src/contributions/commands/workspace.ts @@ -64,5 +64,8 @@ export default function registerWorkspaceCommands() { if (workspace) workspace.index.refresh(); }); - vscode.commands.registerCommand(S4TKCommand.workspace.folderToProject, convertFolderToProject); + vscode.commands.registerCommand(S4TKCommand.workspace.folderToProject, async () => { + const workspace = await S4TKWorkspaceManager.chooseWorkspace(); + if (workspace) convertFolderToProject(workspace); + }); } diff --git a/src/core/building/builder.ts b/src/core/building/builder.ts index 91ccf22..9540bfc 100644 --- a/src/core/building/builder.ts +++ b/src/core/building/builder.ts @@ -1,6 +1,6 @@ import * as fs from "fs"; import * as path from "path"; -import * as JSZip from "jszip"; +import JSZip from "jszip"; import * as models from "@s4tk/models"; import * as enums from "@s4tk/models/enums"; import * as types from "@s4tk/models/types"; diff --git a/src/core/helpers/fs.ts b/src/core/helpers/fs.ts index 1e3a0ec..816b133 100644 --- a/src/core/helpers/fs.ts +++ b/src/core/helpers/fs.ts @@ -1,4 +1,5 @@ import { existsSync } from "fs"; +import sanitize from "sanitize-filename"; import * as vscode from "vscode"; /** @@ -14,6 +15,16 @@ export function findOpenDocument(uri: vscode.Uri): vscode.TextDocument | undefin }); } +/** + * Sanitizes and removes the author prefix from the given filename. + * + * @param filename a raw filename + * @returns the simplified filename + */ +export function simplifyTuningFilename(filename: string) { + return sanitize(`${filename.replace(/^[^:]*:/, "")}.xml`, { replacement: '_', }) +} + /** * Replaces an entire document's contents using its editor, and returns whether * the edits could be made or not. diff --git a/src/core/tuning/commands.ts b/src/core/tuning/commands.ts index db80343..23f0053 100644 --- a/src/core/tuning/commands.ts +++ b/src/core/tuning/commands.ts @@ -4,13 +4,11 @@ import * as vscode from "vscode"; import { fnv64 } from "@s4tk/hashing"; import { formatAsHexString } from "@s4tk/hashing/formatting"; import { SimDataResource, XmlResource } from "@s4tk/models"; -import { replaceEntireDocument } from "#helpers/fs"; +import { replaceEntireDocument, simplifyTuningFilename } from "#helpers/fs"; import { insertXmlKeyOverrides } from "#indexing/inference"; import { reduceBits } from "#helpers/hashing"; import { maxBitsForClass } from "#diagnostics/helpers"; -var sanitize = require("sanitize-filename"); - /** * Clones the tuning file (and its SimData, if it has one) at the given URI, * prompting the user for a new name to use. A new hash with the correct number @@ -46,7 +44,7 @@ export async function cloneWithNewName(srcUri: vscode.Uri) { const tuningFsPath = path.join( path.dirname(srcUri.fsPath), - sanitize(newFilename + ".xml", { replacement: '_', }) + simplifyTuningFilename(newFilename) ); if (fs.existsSync(tuningFsPath)) { diff --git a/src/core/workspace/folder-to-project.ts b/src/core/workspace/folder-to-project.ts index bd63ec5..a34cfb1 100644 --- a/src/core/workspace/folder-to-project.ts +++ b/src/core/workspace/folder-to-project.ts @@ -1,22 +1,21 @@ import * as fs from "fs"; import * as path from "path"; import * as vscode from "vscode"; -import { ResourceKey } from "@s4tk/models/types"; +import { ResourceFilter, ResourceKey } from "@s4tk/models/types"; import { Package, RawResource, SimDataResource, StringTableResource } from "@s4tk/models"; import { BinaryResourceType, SimDataGroup, TuningResourceType } from "@s4tk/models/enums"; import { formatResourceType, formatResourceKey, formatAsHexString } from "@s4tk/hashing/formatting"; import { findGlobMatches, parseKeyFromTgi } from "#building/resources"; -import StringTableJson from "#stbls/stbl-json"; +import { simplifyTuningFilename } from "#helpers/fs"; import * as inference from "#indexing/inference"; -var sanitize = require("sanitize-filename"); - -var instanceMap: Map; +import StringTableJson from "#stbls/stbl-json"; +import S4TKWorkspace from "#workspace/s4tk-workspace"; /** * Prompts the user for a folder containing packages and/or loose TGI files and * turns them into a structure that is easier to use with the S4TK extension. */ -export async function convertFolderToProject() { +export async function convertFolderToProject(workspace: S4TKWorkspace) { const sourceFolderUri = await _promptForFolder({ title: "Folder Containing TS4 Resources", openLabel: "Use as Source" @@ -43,10 +42,10 @@ export async function convertFolderToProject() { const sourcePattern = path.join(sourceFolderUri.fsPath, "**/*").replace(/\\/g, "/"); const matches = findGlobMatches([sourcePattern], undefined, "supported"); - instanceMap = new Map(); + var instanceMap = new Map(); matches.forEach((sourcePath: string) => { - _processSourceFile(sourcePath, destFolderUri.fsPath); + _processSourceFile(workspace, sourcePath, destFolderUri.fsPath, instanceMap); }); } @@ -78,10 +77,9 @@ function _getDestFilename(destFolder: string, filename: string, ext: string): st const pfilename = filename.includes(":") ? filename.split(":").slice(1).join(":") : filename - const sanitized = sanitize(pfilename, { replacement: '_', }) const baseDestPath = path.join( destFolder, - sanitized + simplifyTuningFilename(pfilename) ); let index = 0; @@ -93,42 +91,56 @@ function _getDestFilename(destFolder: string, filename: string, ext: string): st return `${destPath}.${ext}`; } -function _processSourceFile(sourcePath: string, destFolder: string) { +function _processSourceFile( + workspace: S4TKWorkspace, + sourcePath: string, + destFolder: string, + instanceMap: Map +) { const sourceName = path.basename(sourcePath); if (sourceName.endsWith(".package")) { const packageName = sourceName.replace(/\.package/g, ""); const packageDest = _appendFolder(destFolder, "Packages", packageName); const buffer = fs.readFileSync(sourcePath); - Package.extractResources(buffer, { - loadRaw: true, - decompressBuffers: true, - resourceFilter(type, group, inst) { - return type in TuningResourceType; - } - }).forEach(entry => { - _processResource(entry.key, entry.value.buffer, packageDest); - }); - - Package.extractResources(buffer, { - loadRaw: true, - decompressBuffers: true, - resourceFilter(type, group, inst) { - return !(type in TuningResourceType); - } - }).forEach(entry => { - _processResource(entry.key, entry.value.buffer, packageDest); - }); + // Process the tuning types first to populate the instanceMap... + _processPackage(workspace, buffer, packageDest, instanceMap, true); + // ... so they'll be available when the SimData is seen + _processPackage(workspace, buffer, packageDest, instanceMap, false); } else { const key = parseKeyFromTgi(sourceName); if (!key) return; const buffer = fs.readFileSync(sourcePath); const resourceDest = _appendFolder(destFolder, "Loose Files"); - _processResource(key, buffer, resourceDest); + _processResource(workspace, key, buffer, resourceDest, instanceMap); } } -function _processResource(key: ResourceKey, buffer: Buffer, destFolder: string) { +function _processPackage( + workspace: S4TKWorkspace, + buffer: Buffer, + packageDest: string, + instanceMap: Map, + tuning: boolean +) { + Package.extractResources(buffer, { + loadRaw: true, + decompressBuffers: true, + resourceFilter(type, group, inst) { + return (type in TuningResourceType) == tuning; + } + }).forEach(entry => { + _processResource(workspace, entry.key, entry.value.buffer, packageDest, instanceMap); + }); +} + +function _processResource( + workspace: S4TKWorkspace, + key: ResourceKey, + buffer: Buffer, + destFolder: string, + instanceMap: Map +) { const getSubfolder = (...args: string[]) => _appendFolder(destFolder, ...args); if (key.type in TuningResourceType) { @@ -152,7 +164,6 @@ function _processResource(key: ResourceKey, buffer: Buffer, destFolder: string) xmlContent = inference.insertXmlKeyOverrides(xmlContent, overrides) ?? xmlContent; - // FIXME: remove creator name prefix const name = metadata.attrs?.n ?? "UnnamedTuning" const dest = _getDestFilename(subfolder, name, "xml"); fs.writeFileSync(dest, xmlContent); @@ -171,7 +182,8 @@ function _processResource(key: ResourceKey, buffer: Buffer, destFolder: string) var dest: string; const val = instanceMap.get(key.instance); if (val) { - simdata.instance.name = val[0] + "_SimData"; + if (workspace.config.workspaceSettings.setSimDataNames) + simdata.instance.name = val[0] + "_SimData"; dest = val[1].replace(".xml", ".SimData.xml"); } else { // TODO: insert group and instance override instead of using formatResourceKey diff --git a/src/core/workspace/s4tk-config.ts b/src/core/workspace/s4tk-config.ts index e2b0faa..404f521 100644 --- a/src/core/workspace/s4tk-config.ts +++ b/src/core/workspace/s4tk-config.ts @@ -53,6 +53,7 @@ export interface S4TKConfig { workspaceSettings: { overrideIndexRoot?: string; + setSimDataNames: boolean; }; } @@ -89,7 +90,9 @@ const _CONFIG_TRANSFORMER: ConfigTransformer = { }, }, workspaceSettings: { - defaults: {}, + defaults: { + setSimDataNames: false, + }, }, }; @@ -186,8 +189,7 @@ function _getObjectProxy(target: T | undefined, { getConverter = (_, value) => value }: ConfigPropertyTransformer): T { return new Proxy(target ?? {} as T, { - //@ts-ignore I genuinely do not understand why TS doesn't like this - get(target, prop: keyof T) { + get(target, prop: Exclude) { return getConverter(prop, target[prop] ?? defaults[prop]); }, }) as T; diff --git a/tsconfig.json b/tsconfig.json index 28570d7..9a1669c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -19,7 +19,8 @@ "#stbls/*": ["core/stbls/*"], "#tuning/*": ["core/tuning/*"], "#workspace/*": ["core/workspace/*"], - } + }, + "esModuleInterop": true }, "include": ["src/**/*.ts"], "exclude": ["node_modules", ".vscode-test"],