diff --git a/js/skinParser.js b/js/skinParser.js index b580c5f8..13653778 100644 --- a/js/skinParser.js +++ b/js/skinParser.js @@ -51,24 +51,16 @@ const CURSORS = [ */ ]; -async function genFileFromZip(zip, fileName, ext, mode) { - const regex = new RegExp(`^(.*/)?${fileName}(\.${ext})?$`, "i"); - const files = zip.file(regex); - if (!files.length) { - return null; - } - // Return a promise (awaitable). - return { - contents: await files[0].async(mode), - name: files[0].name, - }; -} - async function genImgFromFilename(zip, fileName) { // Winamp only supports .bmp images, but WACUP set a precidence of supporting // .png as well to reduce size. Since we care about size as well, we follow // suit. Our default skin uses .png to save 14kb. - const file = await genFileFromZip(zip, fileName, "(png|bmp)", "blob"); + const file = await SkinParserUtils.getFileFromZip( + zip, + fileName, + "(png|bmp)", + "blob" + ); if (!file) { return null; } @@ -90,12 +82,22 @@ async function genSpriteUrisFromFilename(zip, fileName) { } async function getCursorFromFilename(zip, fileName) { - const file = await genFileFromZip(zip, fileName, "CUR", "base64"); + const file = await SkinParserUtils.getFileFromZip( + zip, + fileName, + "CUR", + "base64" + ); return file && `data:image/x-win-bitmap;base64,${file.contents}`; } async function genPlaylistStyle(zip) { - const pledit = await genFileFromZip(zip, "PLEDIT", "txt", "text"); + const pledit = await SkinParserUtils.getFileFromZip( + zip, + "PLEDIT", + "txt", + "text" + ); const data = pledit && parseIni(pledit.contents).text; if (!data) { // Corrupt or missing PLEDIT.txt file. @@ -121,7 +123,12 @@ async function genPlaylistStyle(zip) { } async function genVizColors(zip) { - const viscolor = await genFileFromZip(zip, "VISCOLOR", "txt", "text"); + const viscolor = await SkinParserUtils.getFileFromZip( + zip, + "VISCOLOR", + "txt", + "text" + ); return viscolor ? parseViscolors(viscolor.contents) : DEFAULT_SKIN.colors; } @@ -144,7 +151,12 @@ async function genCursors(zip) { } async function genRegion(zip) { - const region = await genFileFromZip(zip, "REGION", "txt", "text"); + const region = await SkinParserUtils.getFileFromZip( + zip, + "REGION", + "txt", + "text" + ); return region ? regionParser(region.contents) : {}; } diff --git a/js/skinParserUtils.ts b/js/skinParserUtils.ts index e2c1bb8a..d3cb96d4 100644 --- a/js/skinParserUtils.ts +++ b/js/skinParserUtils.ts @@ -1,5 +1,24 @@ +import JSZip from "jszip"; import { Sprite } from "./skinSprites"; +export async function getFileFromZip( + zip: JSZip, + fileName: string, + ext: string, + mode: "blob" | "text" | "base64" +) { + const regex = new RegExp(`^(.*/)?${fileName}(\.${ext})?$`, "i"); + const files = zip.file(regex); + if (!files.length) { + return null; + } + // Return a promise (awaitable). + return { + contents: await files[0].async(mode), + name: files[0].name, + }; +} + function fallbackGetImgFromBlob(blob: Blob): Promise { return new Promise((resolve, reject) => { const img = new Image(); diff --git a/package.json b/package.json index 1e37cf05..8ba06a5c 100644 --- a/package.json +++ b/package.json @@ -66,6 +66,7 @@ "@types/fscreen": "^1.0.1", "@types/invariant": "^2.2.29", "@types/jest": "^23.3.2", + "@types/jszip": "^3.1.5", "@types/lodash": "^4.14.116", "@types/lodash-es": "^4.17.1", "@types/rc-slider": "^8.6.0", diff --git a/yarn.lock b/yarn.lock index e9a351d9..23c1b5c1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -925,6 +925,13 @@ version "23.3.2" resolved "https://registry.yarnpkg.com/@types/jest/-/jest-23.3.2.tgz#07b90f6adf75d42c34230c026a2529e56c249dbb" +"@types/jszip@^3.1.5": + version "3.1.5" + resolved "https://registry.yarnpkg.com/@types/jszip/-/jszip-3.1.5.tgz#664b424b15aadf0489e871d319f4b18ddc6e24ea" + integrity sha512-DXjYsQr0B9rbjI8n7ZoIFXFMNHDBb9XLYRgwVYxhtsnr/HfFglpxb/InshOBAzkmW4WjgtvnA212voeVV2vwiA== + dependencies: + "@types/node" "*" + "@types/lodash-es@^4.17.1": version "4.17.1" resolved "https://registry.yarnpkg.com/@types/lodash-es/-/lodash-es-4.17.1.tgz#56745e5411558362aeca31def918f88f725dd29d"