Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
}
},
"devDependencies": {
"@types/ini": "^4.1.1",
"@types/jszip": "^3.4.0",
"@types/opentype.js": "^1.3.9",
"electron": "^40.6.0",
Expand Down Expand Up @@ -73,6 +74,7 @@
"celaria-formats": "^1.0.2",
"chess.js": "^1.4.0",
"imagetracer": "^0.2.2",
"ini": "^6.0.0",
"js-synthesizer": "^1.11.0",
"json5": "^2.2.3",
"jszip": "^3.10.1",
Expand Down
172 changes: 172 additions & 0 deletions src/handlers/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
import type { FileData, FileFormat, FormatHandler } from "../FormatHandler.ts";
import CommonFormats from "src/CommonFormats.ts";
import * as ini from 'ini';

class configHandler implements FormatHandler {
public name: string = "config";
public supportedFormats?: FileFormat[];
public ready: boolean = false;

private readonly cfgExt = ['ini', 'cfg', 'cnf', 'conf', 'cf'];

async init() {
this.supportedFormats = [
CommonFormats.JSON.builder("json").allowFrom(true).allowTo(true),
{
name: "INI Configuration File",
format: "ini",
extension: "ini",
mime: "text/plain",
from: true,
to: true,
internal: "ini",
lossless: true,
},
{
name: "Configuration File",
format: "cfg",
extension: "cfg",
mime: "text/plain",
from: true,
to: true,
internal: "ini",
lossless: true,
},
{
name: "Configuration File",
format: "cnf",
extension: "cnf",
mime: "text/plain",
from: true,
to: true,
internal: "ini",
lossless: true,
},
{
name: "Configuration File",
format: "conf",
extension: "conf",
mime: "text/plain",
from: true,
to: true,
internal: "ini",
lossless: true,
},
{
name: "Configuration File",
format: "cf",
extension: "cf",
mime: "text/plain",
from: true,
to: true,
internal: "ini",
lossless: true,
},
{
name: "RIVALS Configuration File", // https://www.roblox.com/games/17625359962
format: "txt",
extension: "txt",
mime: "text/plain",
from: true,
to: true,
internal: "txt",
lossless: true,
},
Comment on lines +65 to +74
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where did this come from??

A text configuration for a random Roblox game is incredibly out of scope for a general-purpose "config" handler, and for this pull request. There's also no distinction between this and a regular text file, given that all of format, extension, and mime are identical to a plaintext file.

];
this.ready = true;
}

async doConvert(
inputFiles: FileData[],
inputFormat: FileFormat,
outputFormat: FileFormat,
): Promise<FileData[]> {
const outputFiles: FileData[] = [];
const decoder = new TextDecoder();
const encoder = new TextEncoder();

const cfgRegex = new RegExp(`\\.(${this.cfgExt.join('|')})$`, 'i');

// rivals -> json
if (inputFormat.name === "RIVALS Configuration File" && outputFormat.internal === "json") {
for (const file of inputFiles) {
const content = decoder.decode(file.bytes);
const decoded = content
.split("")
.reverse()
.map((char) => String.fromCharCode(char.charCodeAt(0) - 1))
.join("");

outputFiles.push({
name: file.name.replace(/\.txt$/i, ".json"),
bytes: encoder.encode(decoded),
});
}
}

// json -> rivals
if (inputFormat.internal === "json" && outputFormat.name === "RIVALS Configuration File") {
for (const file of inputFiles) {
const content = decoder.decode(file.bytes);
const encoded = content
.split("")
.map((char) => String.fromCharCode(char.charCodeAt(0) + 1))
.reverse()
.join("");

outputFiles.push({
name: file.name.replace(/\.json$/i, ".txt"),
bytes: encoder.encode(encoded),
});
}
}

// config -> json
if (inputFormat.internal === "ini" && outputFormat.internal === "json") {
for (const file of inputFiles) {
const decode = decoder.decode(file.bytes);
const parsed = ini.parse(decode);
const stringified = JSON.stringify(parsed, null, 2);

outputFiles.push({
name: file.name.replace(cfgRegex, ".json"),
bytes: encoder.encode(stringified),
});
}
}

// json -> config
if (inputFormat.internal === "json" && outputFormat.internal === "ini") {
for (const file of inputFiles) {
const decode = decoder.decode(file.bytes);
const parsed = JSON.parse(decode);
const stringified = ini.stringify(parsed);

outputFiles.push({
name: file.name.replace(/\.json$/i, `.${outputFormat.extension}`),
bytes: encoder.encode(stringified),
});
}
}

// config -> config
if (inputFormat.internal === outputFormat.internal) {
for (const file of inputFiles) {
outputFiles.push({
name: file.name.replace(cfgRegex, `.${outputFormat.extension}`),
bytes: file.bytes,
});
}
}

if (outputFiles.length === 0) {
throw new Error(
`configHandler does not support route: ${inputFormat.internal} -> ${outputFormat.internal}`,
);
}
Comment thread
Pendonym marked this conversation as resolved.

return outputFiles;
}
}

export default configHandler;
2 changes: 2 additions & 0 deletions src/handlers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ import mclangHandler from "./minecraftLangfileHandler.ts";
import celariaMapHandler from "./celariaMap.ts";
import cybergrindHandler from "./cybergrindHandler.ts";
import textToSourceHandler from "./textToSource.ts";
import configHandler from "./config.ts";
import chessjsHandler from "./chessjs.ts";
import fenToJsonHandler from "./fenToJson.ts";
import piskelHandler from "./piskel.ts";
Expand Down Expand Up @@ -138,6 +139,7 @@ try { handlers.push(new mclangHandler()) } catch (_) { };
try { handlers.push(new celariaMapHandler()) } catch (_) { };
try { handlers.push(new cybergrindHandler()) } catch (_) { };
try { handlers.push(new textToSourceHandler()) } catch (_) { };
try { handlers.push(new configHandler()) } catch (_) { };
try { handlers.push(new chessjsHandler()) } catch (_) { };
try { handlers.push(new fenToJsonHandler()) } catch (_) { };
try { handlers.push(new piskelHandler()) } catch (_) { };
Expand Down