From 54eef678974b9a20b507a5efaab071237e4e9e17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20S=C3=B8rensen?= Date: Mon, 14 Apr 2025 22:03:57 +0200 Subject: [PATCH 1/3] Refactored tf-parser to use vdf-utils --- .github/ISSUE_TEMPLATE/bug_report.md | 6 +- .github/ISSUE_TEMPLATE/feature_request.md | 2 +- LICENSE | 2 +- README.md | 35 +++- examples/custom-parser.ts | 38 ---- .../{parse-language.ts => localization.ts} | 4 +- examples/{parse-items.ts => schema.ts} | 6 +- package-lock.json | 174 +++++------------- package.json | 3 + src/classes/index.ts | 7 + src/classes/items.parser.ts | 25 --- src/classes/language.parser.ts | 25 --- src/classes/parser.error.ts | 15 -- src/classes/parser.ts | 47 ----- src/classes/parsers/localization.ts | 17 ++ src/classes/parsers/schema.ts | 17 ++ src/classes/stack.error.ts | 15 -- src/classes/stack.ts | 98 ---------- src/index.ts | 17 +- src/lib/utils.ts | 95 ---------- src/resources/enums.ts | 8 - ...{language.interface.ts => localization.ts} | 4 +- src/types/{items.interface.ts => schema.ts} | 4 +- src/types/stack.interface.ts | 31 ---- test/localization.spec.ts | 43 +++++ test/parser.spec.ts | 101 ---------- test/schema.spec.ts | 57 ++++++ test/stack.spec.ts | 42 ----- test/utils.spec.ts | 33 ---- 29 files changed, 238 insertions(+), 733 deletions(-) delete mode 100644 examples/custom-parser.ts rename examples/{parse-language.ts => localization.ts} (82%) rename examples/{parse-items.ts => schema.ts} (79%) create mode 100644 src/classes/index.ts delete mode 100644 src/classes/items.parser.ts delete mode 100644 src/classes/language.parser.ts delete mode 100644 src/classes/parser.error.ts delete mode 100644 src/classes/parser.ts create mode 100644 src/classes/parsers/localization.ts create mode 100644 src/classes/parsers/schema.ts delete mode 100644 src/classes/stack.error.ts delete mode 100644 src/classes/stack.ts delete mode 100644 src/lib/utils.ts delete mode 100644 src/resources/enums.ts rename src/types/{language.interface.ts => localization.ts} (88%) rename src/types/{items.interface.ts => schema.ts} (99%) delete mode 100644 src/types/stack.interface.ts create mode 100644 test/localization.spec.ts delete mode 100644 test/parser.spec.ts create mode 100644 test/schema.spec.ts delete mode 100644 test/stack.spec.ts delete mode 100644 test/utils.spec.ts diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 00285de..d8fd794 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -26,17 +26,17 @@ A clear and concise description of what you expected to happen. A clear and concise description of what happens. ## Minimal reproducible example -Calling `LanguageParser.parse()` on the contents of `tf_english.txt` returns "Error parsing tf_english.txt...". +Calling `LocalizationParser.parse()` on the contents of `tf_english.txt` returns "Error parsing tf_english.txt...". ```js import { readFile } from "fs/promises"; -import { LanguageParser } from "@mann-conomy/tf-parser"; +import { LocalizationParser } from "@mann-conomy/tf-parser"; (async () => { try { const file = await readFile("tf_english.txt", { encoding: "utf16le" }); - const { lang } = LanguageParser.parse(file); + const { lang } = LocalizationParser.parse(file); console.log(lang.Language); console.log(lang.Tokens.rarity4); diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index d3de210..6295676 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -24,7 +24,7 @@ If applicable, provide an example of how the new feature or improvement would be ```js import { glob } from "glob"; -export default class LanguageParser { +export default class LocalizationParser { ... static async match(path: string) { return await glob("tf_*.txt", { cwd: path }); diff --git a/LICENSE b/LICENSE index f087935..01baf7e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2024 The Mann-Conomy Project +Copyright (c) 2025 The Mann-Conomy Project Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 41375cc..dddfef1 100644 --- a/README.md +++ b/README.md @@ -35,11 +35,12 @@ $ yarn test ``` ## Examples -Parsing UTF-16 encoded language files from the Team Fortress 2 game client into JSON objects. + +Parsing UTF-16 encoded localization files from the Team Fortress 2 game client into JSON objects. ```js import { readFile } from "fs/promises"; -import { LanguageParser } from "@mann-conomy/tf-parser"; +import { LocalizationParser } from "@mann-conomy/tf-parser"; (async () => { try { @@ -47,7 +48,7 @@ import { LanguageParser } from "@mann-conomy/tf-parser"; const file = await readFile("tf_english.txt", { encoding: "utf16le" }); // Parse english language translations - const { lang } = LanguageParser.parse(file); + const { lang } = LocalizationParser.parse(file); console.log(lang.Language); // English console.log(lang.Tokens.rarity4); // Unusual @@ -57,6 +58,32 @@ import { LanguageParser } from "@mann-conomy/tf-parser"; })(); ``` +Parsing the item schema from the Steam Web API. + +```js +import { SchemaParser } from "@mann-conomy/tf-parser"; + +(async() => { + try { + // Fetch the item schema from the Steam Web API + const response = await fetch("https://media.steampowered.com/apps/440/scripts/items/items_game.bdc614ad776fb2d43c1f247fce870485d2299152.txt"); + + // Resolve the response into a UTF-8 string + const items = await response.text(); + + // Parse the in-game items + const { items_game } = SchemaParser.parse(items); + + console.log(items_game.rarities.unusual?.value); // 99 + console.log(items_game.qualities.vintage?.value); // 3 + } catch (error: unknown) { + if (error instanceof Error) { + console.error("Error parsing items_game.txt", error.message); + } + } +})(); +``` + Some more examples are available in the [examples](https://github.com/Mann-Conomy/tf-parser/tree/main/examples) and [test](https://github.com/Mann-Conomy/tf-parser/tree/main/test) directories. ## Documentation @@ -67,4 +94,4 @@ See the [Wiki pages](https://github.com/Mann-Conomy/tf-parser/wiki) for further [MIT](LICENSE) -Copyright 2024, The Mann-Conomy Project +Copyright 2025, The Mann-Conomy Project diff --git a/examples/custom-parser.ts b/examples/custom-parser.ts deleted file mode 100644 index 9b0adf6..0000000 --- a/examples/custom-parser.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { readFile } from "fs/promises"; -import Parser from "../src/classes/parser"; - -/** - * Represents a Team Fortress 2 game file parsed into a JSON object. - */ -export interface CustomGameFile { - /** - * Regular property with a string value. - */ - property: string - /** - * A nested property that contains a string property value. - */ - custom_object: { - property: string // Nested property - } -} - -(async() => { - try { - // Read the contents of your chosen Team Fortress 2 game file - const file = await readFile("tf_custom_game.txt", { encoding: "utf8" }); - - // Stringify the file cotents to a JSON object - const result = Parser.stringify(file); - - // Parse the game file to a JSON object - const customFile: CustomGameFile = JSON.parse(result); - - console.log(customFile.property); // Access regular properties - console.log(customFile.custom_object.property); // Access nested properties - } catch (error: unknown) { - if (error instanceof Error) { - console.error("Error parsing tf_custom_game.txt", error.message); - } - } -})(); diff --git a/examples/parse-language.ts b/examples/localization.ts similarity index 82% rename from examples/parse-language.ts rename to examples/localization.ts index b769aa8..7960a2c 100644 --- a/examples/parse-language.ts +++ b/examples/localization.ts @@ -1,5 +1,5 @@ import { readFile } from "fs/promises"; -import LanguageParser from "../src/classes/language.parser"; +import { LocalizationParser } from "../src/index"; (async () => { try { @@ -7,7 +7,7 @@ import LanguageParser from "../src/classes/language.parser"; const file = await readFile("tf_english.txt", { encoding: "utf16le" }); // Parse the english language translations - const { lang } = LanguageParser.parse(file); + const { lang } = LocalizationParser.parse(file); console.log(lang.Language); // English console.log(lang.Tokens.rarity4); // Unusual diff --git a/examples/parse-items.ts b/examples/schema.ts similarity index 79% rename from examples/parse-items.ts rename to examples/schema.ts index d29ad78..4eca565 100644 --- a/examples/parse-items.ts +++ b/examples/schema.ts @@ -1,15 +1,15 @@ -import ItemsParser from "../src/classes/items.parser"; +import { SchemaParser } from "../src/index"; (async() => { try { - // Fetch the items_game file from Steam + // Fetch the item schema from the Steam Web API const response = await fetch("https://media.steampowered.com/apps/440/scripts/items/items_game.bdc614ad776fb2d43c1f247fce870485d2299152.txt"); // Resolve the response into a UTF-8 string const items = await response.text(); // Parse the in-game items - const { items_game } = ItemsParser.parse(items); + const { items_game } = SchemaParser.parse(items); console.log(items_game.rarities.unusual?.value); // 99 console.log(items_game.qualities.vintage?.value); // 3 diff --git a/package-lock.json b/package-lock.json index bf4911e..b4a08e7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,9 @@ "name": "@mann-conomy/tf-parser", "version": "1.1.4", "license": "MIT", + "dependencies": { + "@mann-conomy/vdf-utils": "^1.0.0" + }, "devDependencies": { "@eslint/js": "^8.57.0", "@jest/globals": "^29.7.0", @@ -41,12 +44,13 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.24.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", - "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", "dev": true, "dependencies": { - "@babel/highlight": "^7.24.2", + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", "picocolors": "^1.0.0" }, "engines": { @@ -222,18 +226,18 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", - "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.5.tgz", - "integrity": "sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", "dev": true, "engines": { "node": ">=6.9.0" @@ -249,110 +253,26 @@ } }, "node_modules/@babel/helpers": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.5.tgz", - "integrity": "sha512-CiQmBMMpMQHwM5m01YnrM6imUG1ebgYJ+fAIW4FZe6m4qHTPaRHti+R8cggAwkdz4oXhtO4/K9JWlh+8hIfR2Q==", - "dev": true, - "dependencies": { - "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.5", - "@babel/types": "^7.24.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.5.tgz", - "integrity": "sha512-8lLmua6AVh/8SLJRRVD6V8p73Hir9w5mJrhE+IPpILG31KKlI9iz5zmBYKcWPS59qSfgP9RaSBQSHHE81WKuEw==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.0.tgz", + "integrity": "sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.24.5", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "@babel/template": "^7.27.0", + "@babel/types": "^7.27.0" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/@babel/parser": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz", + "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==", "dev": true, "dependencies": { - "has-flag": "^3.0.0" + "@babel/types": "^7.27.0" }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/parser": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.5.tgz", - "integrity": "sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==", - "dev": true, "bin": { "parser": "bin/babel-parser.js" }, @@ -538,14 +458,14 @@ } }, "node_modules/@babel/template": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", - "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz", + "integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/parser": "^7.24.0", - "@babel/types": "^7.24.0" + "@babel/code-frame": "^7.26.2", + "@babel/parser": "^7.27.0", + "@babel/types": "^7.27.0" }, "engines": { "node": ">=6.9.0" @@ -582,14 +502,13 @@ } }, "node_modules/@babel/types": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.5.tgz", - "integrity": "sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", + "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.24.1", - "@babel/helper-validator-identifier": "^7.24.5", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1308,6 +1227,14 @@ "node": ">=18.0.0" } }, + "node_modules/@mann-conomy/vdf-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@mann-conomy/vdf-utils/-/vdf-utils-1.0.0.tgz", + "integrity": "sha512-wBTFhl5aaqPqpWijEJOVG1VwPAYl4E/bwQO5OjfyvVtkVNbNNqJnWFOEWAgwZBLT+zK6bBGIh204RGjruNR/WQ==", + "engines": { + "node": ">=6.17.1" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -2254,9 +2181,9 @@ "dev": true }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "dependencies": { "path-key": "^3.1.0", @@ -4938,15 +4865,6 @@ "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", "dev": true }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", diff --git a/package.json b/package.json index cc928af..13d41c9 100644 --- a/package.json +++ b/package.json @@ -57,5 +57,8 @@ "directories": { "example": "examples", "test": "test" + }, + "dependencies": { + "@mann-conomy/vdf-utils": "^1.0.0" } } diff --git a/src/classes/index.ts b/src/classes/index.ts new file mode 100644 index 0000000..da86efe --- /dev/null +++ b/src/classes/index.ts @@ -0,0 +1,7 @@ +import SchemaParser from "./parsers/schema"; +import LocalizationParser from "./parsers/localization"; + +export { + SchemaParser, + LocalizationParser +}; diff --git a/src/classes/items.parser.ts b/src/classes/items.parser.ts deleted file mode 100644 index fa11e15..0000000 --- a/src/classes/items.parser.ts +++ /dev/null @@ -1,25 +0,0 @@ -import Parser from "./parser"; -import ParserError from "./parser.error"; -import { isFileEmpty } from "../lib/utils"; -import type { ItemsFile } from "../types/items.interface"; - -/** - * A parser for converting Team Fortress 2 item files to JSON objects. - */ -export default class ItemsParser { - /** - * Parses a Team Fortress 2 items file to JSON. - * @param file The content of a Team Fortress 2 items file. - * @returns The items file as a JSON object. - * @throws A ParserError if the items file is an empty JSON object. - */ - static parse(file: string): ItemsFile { - const itemsFile = Parser.stringify(file); - - if (isFileEmpty(itemsFile)) { - throw new ParserError("The items file contains no JSON keys and or value pairs."); - } - - return JSON.parse(itemsFile); - } -} diff --git a/src/classes/language.parser.ts b/src/classes/language.parser.ts deleted file mode 100644 index 4b34ce9..0000000 --- a/src/classes/language.parser.ts +++ /dev/null @@ -1,25 +0,0 @@ -import Parser from "./parser"; -import ParserError from "./parser.error"; -import { isFileEmpty } from "../lib/utils"; -import type { LanguageFile } from "../types/language.interface"; - -/** - * A parser for converting Team Fortress 2 language files to JSON objects. - */ -export default class LanguageParser { - /** - * Parses a Team Fortress 2 language file to JSON. - * @param file The content of a Team Fortress 2 language file. - * @returns The language file as a JSON object. - * @throws A ParserError if the language file is an empty JSON object. - */ - static parse(file: string): LanguageFile { - const languageFile = Parser.stringify(file); - - if (isFileEmpty(languageFile)) { - throw new ParserError("The language file contains no JSON keys and or value pairs."); - } - - return JSON.parse(languageFile); - } -} diff --git a/src/classes/parser.error.ts b/src/classes/parser.error.ts deleted file mode 100644 index a62951e..0000000 --- a/src/classes/parser.error.ts +++ /dev/null @@ -1,15 +0,0 @@ -/** - * A wrapper for handling errors specific to the Parser class. - * @extends Error - */ -export default class ParserError extends Error { - /** - * Creates a new instance of ParserError. - * @param { string } message The error message. - */ - constructor(message: string) { - super(message); - - this.name = "ParserError"; - } -} diff --git a/src/classes/parser.ts b/src/classes/parser.ts deleted file mode 100644 index 91ebf86..0000000 --- a/src/classes/parser.ts +++ /dev/null @@ -1,47 +0,0 @@ -import Stack from "./stack"; -import { ObjectNotation } from "../resources/enums"; -import { getKeyAndValuePairOrThrow, getLastKeyOrThrow, getLinesOrThrow } from "../lib/utils"; - -/** - * A parser for converting Team Fortress 2 game files to JSON strings. - */ -export default class Parser { - /** - * Parses a Team Fortress 2 game file to a JSON string. - * @param file The content of a Team Fortress 2 game file. - * @returns The game file as a JSON string. - */ - static stringify(file: string): string { - const stack = new Stack({ populate: true }); - - const object = stack.peek(); - - for(const line of getLinesOrThrow(file)) { - if (line === ObjectNotation.OpeningBrace) { - const currentObject = stack.peek(); - - const lastKey = getLastKeyOrThrow(currentObject); - - const newObject = stack.create(); - - stack.update(lastKey, newObject); - - stack.push(newObject); - - continue; - } - - if (line === ObjectNotation.ClosingBrace) { - stack.pop(); - - continue; - } - - const { key, value } = getKeyAndValuePairOrThrow(line); - - stack.update(key, value); - } - - return JSON.stringify(object); - } -} diff --git a/src/classes/parsers/localization.ts b/src/classes/parsers/localization.ts new file mode 100644 index 0000000..786bb92 --- /dev/null +++ b/src/classes/parsers/localization.ts @@ -0,0 +1,17 @@ +import { VDF } from "@mann-conomy/vdf-utils"; +import type { LocalizationFile } from "../../types/localization"; + +/** + * A parser for converting Team Fortress 2 localization files to JSON objects. + */ +export default class LocalizationParser { + /** + * Parses a Team Fortress 2 localization file to JSON. + * @param file The content of a Team Fortress 2 localization file. + * @returns The localization file as a JSON object. + * @throws A RangeError if the localization file results in an empty JSON object. + */ + public static parse(file: string): LocalizationFile { + return VDF.parse(file); + } +} diff --git a/src/classes/parsers/schema.ts b/src/classes/parsers/schema.ts new file mode 100644 index 0000000..2d75180 --- /dev/null +++ b/src/classes/parsers/schema.ts @@ -0,0 +1,17 @@ +import { VDF } from "@mann-conomy/vdf-utils"; +import type { ItemSchema } from "../../types/schema"; + +/** + * A parser for converting Team Fortress 2 item schemas to JSON objects. + */ +export default class SchemaParser { + /** + * Parses a Team Fortress 2 item schema to JSON. + * @param schema The content of a Team Fortress 2 item schema. + * @returns The item schema as a JSON object. + * @throws A RangeError if the item schema results in an empty JSON object. + */ + public static parse(schema: string): ItemSchema { + return VDF.parse(schema); + } +} diff --git a/src/classes/stack.error.ts b/src/classes/stack.error.ts deleted file mode 100644 index 0c7ec46..0000000 --- a/src/classes/stack.error.ts +++ /dev/null @@ -1,15 +0,0 @@ -/** - * A wrapper for handling errors specific to the Stack class. - * @extends Error - */ -export default class StackError extends Error { - /** - * Creates a new instance of StackError. - * @param { string } message The error message. - */ - constructor(message: string) { - super(message); - - this.name = "StackError"; - } -} diff --git a/src/classes/stack.ts b/src/classes/stack.ts deleted file mode 100644 index a0de703..0000000 --- a/src/classes/stack.ts +++ /dev/null @@ -1,98 +0,0 @@ -import StackError from "./stack.error"; -import type { StackObject, StackOptions, StackValue } from "../types/stack.interface"; - -/** - * A class representing a custom Stack data structure. - */ -export default class Stack { - private readonly elements: StackObject[]; - - /** - * Creates a new instance with the specified options. - * @param { Partial} options Optional configuration object for the Stack. - */ - constructor(options: Partial = {}) { - this.elements = []; - - if (options.populate) { - const object = this.create(); - - this.elements.push(object); - } - } - - /** - * Pushes an element onto the top of the Stack. - * @param element The element to be pushed onto the Stack. - */ - push(element: StackObject) { - this.elements.push(element); - } - - /** - * Removes and returns the top element of the Stack. - * @returns The element at the top of the Stack. - * @throws A StackError if the Stack is empty. - */ - pop(): StackObject | undefined { - if (this.isEmpty()) { - throw new StackError("Cannot pop from an empty Stack."); - } - - return this.elements.pop(); - } - - /** - * Returns the top element of the stack without removing it. - * @returns The element at the top of the stack. - * @throws A StackError if the Stack is empty. - */ - peek(): StackObject { - if (this.isEmpty()) { - throw new StackError("Cannot peek into an empty Stack."); - } - - const element = this.elements[this.elements.length - 1]; - - if (element === undefined) { - throw new StackError("The last Stack element is undefined."); - } - - return element; - } - - /** - * Updates the specified key-value pair in the top element of the Stack. - * @param key The key to be updated. - * @param value The value to be assigned to the key. - */ - update(key: string, value: StackValue) { - const element = this.peek(); - - element[key] = value; - } - - /** - * Creates a new empty object to be used as an element in the Stack. - * @returns A new empty Stack object. - */ - create(): StackObject { - return Object.create(Object.prototype); - } - - /** - * Check if the Stack is empty. - * @returns True if the stack is empty, otherwise false. - */ - isEmpty(): boolean { - return this.size() === 0; - } - - /** - * Returns the number of elements in the Stack. - * @returns The size of the Stack. - */ - size(): number { - return this.elements.length; - } -} diff --git a/src/index.ts b/src/index.ts index 8a8610c..4a44be8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,14 +1,3 @@ -import Parser from "./classes/parser"; -import ItemsParser from "./classes/items.parser"; -import LanguageParser from "./classes/language.parser"; -import type { ItemsFile } from "./types/items.interface"; -import type { LanguageCode, LanguageFile } from "./types/language.interface"; - -export { - Parser, - ItemsFile, - ItemsParser, - LanguageCode, - LanguageFile, - LanguageParser -}; +export * from "./classes"; +export type * from "./types/schema"; +export type * from "./types/localization"; diff --git a/src/lib/utils.ts b/src/lib/utils.ts deleted file mode 100644 index 47285f3..0000000 --- a/src/lib/utils.ts +++ /dev/null @@ -1,95 +0,0 @@ -import ParserError from "../classes/parser.error"; -import { ObjectNotation } from "../resources/enums"; -import type { StackObject } from "../types/stack.interface"; - -/** - * Removes inline comments from the given array of lines. - * @param lines The array of lines to process. - * @returns The array of lines with inline comments removed. - */ -export function removeInlineComments(lines: string[]): string[] { - const quote = String.fromCharCode(34); - - // Filter out the lines that start with an inline comment or contain a single quote - return lines.filter(line => line.length > 0 && line !== quote && !line.startsWith("//")); -} - -/** - * Checks if the first element of the given array is an empty string. - * @param lines The array of strings to check. - * @returns Returns true if the first element is empty or undefined, otherwise false. - */ -function isFirstElementEmpty(lines: string[]): boolean { - const [ first ] = lines; - - return first === undefined || first.length === 0; -} - -/** - * Splits the input file content into lines, trims each line, and returns only valid lines. - * @param file The content of the file to process. - * @returns An array of filtered lines. - */ -function getFilteredLines(file: string) { - const lines = file.split("\n"); - const trimmed = lines.map(line => line.trim()); - - return removeInlineComments(trimmed); -} - -/** - * Splits the given file into lines, trims each line, and removes inline comments. - * @param file The content of the file to process. - * @returns The array of lines from the file, with inline comments removed. - * @throws A ParserError if the file contains no lines. - */ -export function getLinesOrThrow(file: string): string[] { - const lines = getFilteredLines(file); - - if (!(lines.length > 1) && isFirstElementEmpty(lines)) { - throw new ParserError("The file contains no JSON keys and or value pairs."); - } - - return lines; -} - -/** - * Retrieves the last key from the StackObject. - * @param object The StackObject to process. - * @returns The last key in the StackObject. - * @throws A ParserError if the StackObject contains no keys. - */ -export function getLastKeyOrThrow(object: StackObject): string { - const lastKey = Object.keys(object).pop(); - - if (lastKey === undefined) { - throw new ParserError("The StackObject contains no JSON keys."); - } - - return lastKey; -} - -/** - * Splits a line into a key and value pair. - * @param line The line to process. - * @returns The key and value pair parsed from the line. - * @throws A ParserError if the line cannot be split into a key and value pair. - */ -export function getKeyAndValuePairOrThrow(line: string) { - const [ key , value ] = line.split(/"\s*"/).map(element => element.replace(/"/g, "")); - - if (key === undefined || key.length === 0) { - throw new ParserError("The line contains no JSON key and or value."); - } - - return { key, value }; -} - -/** - * Checks if the parsed file is empty. - * @param file The content of the parsed file. - * @returns True if the file is empty, otherwise false. - */ -export function isFileEmpty(file: string) { - return file === ObjectNotation.EmptyObject; -} diff --git a/src/resources/enums.ts b/src/resources/enums.ts deleted file mode 100644 index 7cbaf71..0000000 --- a/src/resources/enums.ts +++ /dev/null @@ -1,8 +0,0 @@ -/** - * Enum for JSON object notation used in parsing strings into game objects. - */ -export enum ObjectNotation { - EmptyObject = "{}", - OpeningBrace = "{", - ClosingBrace = "}" -} diff --git a/src/types/language.interface.ts b/src/types/localization.ts similarity index 88% rename from src/types/language.interface.ts rename to src/types/localization.ts index 3fb3fa2..5ccc2b6 100644 --- a/src/types/language.interface.ts +++ b/src/types/localization.ts @@ -31,9 +31,9 @@ export type LanguageCode = | "brazilian"; /** - * Represents a Team Fortress 2 language file parsed into a JSON object. + * Represents a Team Fortress 2 localization file parsed into a JSON object. */ -export interface LanguageFile { +export interface LocalizationFile { lang: { /** * The language of the file. diff --git a/src/types/items.interface.ts b/src/types/schema.ts similarity index 99% rename from src/types/items.interface.ts rename to src/types/schema.ts index a362388..00fa921 100644 --- a/src/types/items.interface.ts +++ b/src/types/schema.ts @@ -3798,9 +3798,9 @@ export interface WarDefinition { } /** - * Represents a Team Fortress 2 items file parsed into a JSON object. + * Represents a Team Fortress 2 item schema parsed into a JSON object. */ -export interface ItemsFile { +export interface ItemSchema { items_game: { game_info: Record; qualities: Record; diff --git a/src/types/stack.interface.ts b/src/types/stack.interface.ts deleted file mode 100644 index 54ee249..0000000 --- a/src/types/stack.interface.ts +++ /dev/null @@ -1,31 +0,0 @@ -/** - * An array of Stack values. - */ -export type StackArray = StackValue[]; - -/** - * Represents a value that can be either null or undefined. - */ -export type UnknownValue = null | undefined; - -/** - * A value that can be a string, number, boolean, object, array, or unknown value. - */ -export type StackValue = string | number | boolean | StackObject | StackArray | UnknownValue; - -/** - * An object with string keys and values of type StackValue. - */ -export interface StackObject { - [key: string]: StackValue; -} - -/** - * Optional configuration object for the Stack. - */ -export interface StackOptions { - /** - * Whether to populate the Stack with an empty Stack object. - */ - populate: boolean -} diff --git a/test/localization.spec.ts b/test/localization.spec.ts new file mode 100644 index 0000000..c432a20 --- /dev/null +++ b/test/localization.spec.ts @@ -0,0 +1,43 @@ +import { describe, expect, test } from "@jest/globals"; +import { LocalizationParser } from "../src/index"; + +describe("LocalizationParser", () => { + test("new parser should be an instance of LocalizationParser", () => { + // Arrange + const parser = new LocalizationParser(); + + // Act and assert + expect(parser).toBeInstanceOf(LocalizationParser); + }); + + test("should return localization tokens given a valid file string", () => { + // Arrange + const file = createLocalizationFile(); + + // Act + const { lang } = LocalizationParser.parse(file); + + // Assert + expect(lang.Language).toBe("English"); + expect(lang.Tokens.rarity1).toBe("Genuine"); + expect(lang.Tokens["rarity4"]).toBe("Unusual"); + expect(lang.Tokens["TF_Tool_PaintCan_11"]).toBeUndefined(); + expect(lang.Tokens.TF_Weapon_GoldFryingPan).toBeUndefined(); + }); + + test("should throw a RangeError given a invalid file string", () => { + // Arrange + const file = "Teams have been switched."; + + // Act and assert + expect(() => LocalizationParser.parse(file)).toThrow(RangeError); + }); +}); + +/** + * Creates a mock string of a Team Fortress 2 localization file. + * @returns { string } A mock string of a Team Fortress 2 localization file. + */ +function createLocalizationFile(): string { + return "\"lang\"\n\{\n\"Language\"\t\"English\"\n\"Tokens\"\n{\n\"rarity1\"\t\"Genuine\"\n\"rarity4\"\t\"Unusual\"\n}\n}"; +} diff --git a/test/parser.spec.ts b/test/parser.spec.ts deleted file mode 100644 index b0656e2..0000000 --- a/test/parser.spec.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { describe, expect, test } from "@jest/globals"; -import ItemsParser from "../src/classes/items.parser"; -import ParserError from "../src/classes/parser.error"; -import LanguageParser from "../src/classes/language.parser"; - -describe("LanguageParser", () => { - test("new parser should be an instance of LanguageParser", () => { - // Arrange - const parser = new LanguageParser(); - - // Act and assert - expect(parser).toBeInstanceOf(LanguageParser); - }); - - test("should return language tokens given a valid file string", () => { - // Arrange - const file = createLanguageFile(); - - // Act - const { lang } = LanguageParser.parse(file); - - // Assert - expect(lang.Language).toBe("English"); - expect(lang.Tokens.rarity1).toBe("Genuine"); - expect(lang.Tokens["rarity4"]).toBe("Unusual"); - expect(lang.Tokens["TF_Tool_PaintCan_11"]).toBeUndefined(); - expect(lang.Tokens.TF_Weapon_GoldFryingPan).toBeUndefined(); - }); - - test("should throw a ParserError given a invalid file string", () => { - // Arrange - const file = "Teams have been switched."; - - // Act and assert - expect(() => LanguageParser.parse(file)).toThrow(ParserError); - }); -}); - -describe("ItemsParser", () => { - test("new parser should be an instance of ItemsParser", () => { - // Arrange - const parser = new ItemsParser(); - - // Act and assert - expect(parser).toBeInstanceOf(ItemsParser); - }); - - test("should return item tokens given a valid file string", () => { - // Arrange - const file = createItemsFile(); - - // Act - const { items_game } = ItemsParser.parse(file); - - // Assert - expect(items_game.qualities.vintage?.value).toBe("3"); - expect(items_game.qualities["strange"]?.value).toBe("11"); - expect(items_game.rarities?.common?.next_rarity).toBeUndefined(); - expect(items_game.rarities?.["rare"]?.next_rarity).toBeUndefined(); - }); - - test("should return item tokens given a valid url", async() => { - // Arrange - const response = await fetch("https://media.steampowered.com/apps/440/scripts/items/items_game.bdc614ad776fb2d43c1f247fce870485d2299152.txt"); - - const file = await response.text(); - - // Act - const { items_game } = ItemsParser.parse(file); - - // Assert - expect(items_game.qualities.vintage?.value).toBe("3"); - expect(items_game.qualities["strange"]?.value).toBe("11"); - expect(items_game.rarities?.common?.next_rarity).toBe("uncommon"); - expect(items_game.rarities?.["rare"]?.next_rarity).toBe("mythical"); - }, 10000); - - test("should throw a ParserError given a invalid file string", () => { - // Arrange - const file = "Circling Heart Team Captain"; - - // Act and assert - expect(() => ItemsParser.parse(file)).toThrow(ParserError); - }); -}); - -/** - * Creates a mock string of a Team Fortress 2 language file. - * @returns { string } A mock string of a Team Fortress 2 language file. - */ -function createLanguageFile(): string { - return "\"lang\"\n\{\n\"Language\"\t\"English\"\n\"Tokens\"\n{\n\"rarity1\"\t\"Genuine\"\n\"rarity4\"\t\"Unusual\"\n}\n}"; -} - -/** - * Creates a mock string of a Team Fortress 2 items file. - * @returns { string } A mock string of a Team Fortress 2 items file. - */ -function createItemsFile(): string { - return "\"items_game\"\n\{\n\"qualities\"\n{\n\"vintage\"\n{\n\"value\"\t\"3\"\n}\n\"strange\"\n{\n\"value\"\t\"11\"\n}\n}"; -} diff --git a/test/schema.spec.ts b/test/schema.spec.ts new file mode 100644 index 0000000..192e2c9 --- /dev/null +++ b/test/schema.spec.ts @@ -0,0 +1,57 @@ +import { describe, expect, test } from "@jest/globals"; +import { SchemaParser } from "../src/index"; + +describe("SchemaParser", () => { + test("new parser should be an instance of SchemaParser", () => { + // Arrange + const parser = new SchemaParser(); + + // Act and assert + expect(parser).toBeInstanceOf(SchemaParser); + }); + + test("should return item schema tokens given a valid file string", () => { + // Arrange + const file = createItemSchema(); + + // Act + const { items_game } = SchemaParser.parse(file); + + // Assert + expect(items_game.qualities.vintage?.value).toBe(3); + expect(items_game.qualities["strange"]?.value).toBe(11); + expect(items_game.rarities?.common?.next_rarity).toBeUndefined(); + expect(items_game.rarities?.["rare"]?.next_rarity).toBeUndefined(); + }); + + test("should return item tokens given a valid url", async() => { + // Arrange + const response = await fetch("https://media.steampowered.com/apps/440/scripts/items/items_game.bdc614ad776fb2d43c1f247fce870485d2299152.txt"); + const file = await response.text(); + + // Act + const { items_game } = SchemaParser.parse(file); + + // Assert + expect(items_game.qualities.vintage?.value).toBe(3); + expect(items_game.qualities["strange"]?.value).toBe(11); + expect(items_game.rarities?.common?.next_rarity).toBe("uncommon"); + expect(items_game.rarities?.["rare"]?.next_rarity).toBe("mythical"); + }, 10000); + + test("should throw a RangeError given a invalid schema string", () => { + // Arrange + const file = "Circling Heart Team Captain"; + + // Act and assert + expect(() => SchemaParser.parse(file)).toThrow(RangeError); + }); +}); + +/** + * Creates a mock string of a Team Fortress 2 item schema. + * @returns { string } A mock string of a Team Fortress 2 item schema. + */ +function createItemSchema(): string { + return "\"items_game\"\n\{\n\"qualities\"\n{\n\"vintage\"\n{\n\"value\"\t\"3\"\n}\n\"strange\"\n{\n\"value\"\t\"11\"\n}\n}"; +} diff --git a/test/stack.spec.ts b/test/stack.spec.ts deleted file mode 100644 index e29b51d..0000000 --- a/test/stack.spec.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { describe, expect, test } from "@jest/globals"; -import { StackObject } from "../src/types/stack.interface"; -import StackError from "../src/classes/stack.error"; -import Stack from "../src/classes/stack"; - -describe("Stack", () => { - test("should be an instance of the Stack class", () => { - // Arrange - const stack = new Stack(); - - // Act and assert - expect(stack).toBeInstanceOf(Stack); - }); - - test("should throw a StackError when calling pop on an empty Stack", () => { - // Arrange - const stack = new Stack(); - - // Act and assert - expect(() => stack.pop()).toThrow(StackError); - }); - - test("should throw a StackError when calling peek on an empty Stack", () => { - // Arrange - const stack = new Stack(); - - // Act and assert - expect(() => stack.peek()).toThrow(StackError); - }); - - test("should throw when the last Stack element is undefined", () => { - // Arrange - const stack = new Stack(); - const element = undefined as unknown as StackObject; - - // Act - stack.push(element); - - // Assert - expect(() => stack.peek()).toThrow(StackError); - }); -}); diff --git a/test/utils.spec.ts b/test/utils.spec.ts deleted file mode 100644 index 4aeafaf..0000000 --- a/test/utils.spec.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { describe, expect, test } from "@jest/globals"; -import ParserError from "../src/classes/parser.error"; -import { getLinesOrThrow, getLastKeyOrThrow, getKeyAndValuePairOrThrow } from "../src/lib/utils" - -describe("getLinesOrThrow", () => { - test("should throw when the file is empty", () => { - // Arrange - const empty = String(); - - // Act and assert - expect(() => getLinesOrThrow(empty)).toThrow(ParserError); - }); -}); - -describe("getLastKeyOrThrow", () => { - test("should throw when the Stack object is empty", () => { - // Arrange - const empty = {}; - - // Act and assert - expect(() => getLastKeyOrThrow(empty)).toThrow(ParserError); - }); -}); - -describe("getKeyAndValuePairOrThrow", () => { - test("should throw when the line is empty", () => { - // Arrange - const line = String(); - - // Act and assert - expect(() => getKeyAndValuePairOrThrow(line)).toThrow(ParserError); - }); -}); From 505de10af82ad3d1b1b29897ff75487d407da422 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20S=C3=B8rensen?= Date: Mon, 14 Apr 2025 22:07:19 +0200 Subject: [PATCH 2/3] Reorder keywords to match GitHub --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 13d41c9..66c7b2d 100644 --- a/package.json +++ b/package.json @@ -22,10 +22,10 @@ }, "keywords": [ "nodejs", - "language", "parser", "json", "typescript", + "localization", "file", "tf2", "mann-conomy" From 23972e10d32f6c1e5b5057cb299fe939d9c0e6d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20S=C3=B8rensen?= Date: Mon, 14 Apr 2025 22:07:31 +0200 Subject: [PATCH 3/3] 2.0.0 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index b4a08e7..f0393ab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@mann-conomy/tf-parser", - "version": "1.1.4", + "version": "2.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@mann-conomy/tf-parser", - "version": "1.1.4", + "version": "2.0.0", "license": "MIT", "dependencies": { "@mann-conomy/vdf-utils": "^1.0.0" diff --git a/package.json b/package.json index 66c7b2d..158dd41 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@mann-conomy/tf-parser", - "version": "1.1.4", + "version": "2.0.0", "description": "A Node.js parser for converting Team Fortress 2 game files to JSON objects.", "main": "dist/index.js", "types": "dist/index.d.ts",