-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathconvert-theme.js
99 lines (86 loc) · 2.83 KB
/
convert-theme.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import AsarCreator from "./asar.js";
/**
* Builds a Replugged-compatible theme manifest from a BD theme.
* @param {string} css CSS string to parse into a manifest.
* @param {string} filename Name of the .theme.css file
* @returns {object} Replugged theme manifest
*/
function buildManifest(css, filename) {
// Parse meta comment
const fields = new Map();
const meta = css.match(/^\s*\/\*\*\s*[\s\S]+?(?=\*\/)/)?.[0]; // entire meta
if (meta) {
// New meta
const lines = meta.matchAll(/\s*\*\s*@([a-zA-Z]+)\s*(.*)/g); // individual meta lines
for (const match of lines) {
fields.set(match[1], match[2].trim());
}
} else {
// Old meta
const oldMeta = css.match(/(?<=\/\/META).+?(?=\*\/\/)/)[0];
return JSON.parse(oldMeta)
}
// Build Replugged theme manifest
const manifest = {
id: "bd.theme." + filename.split(".").slice(0, -2).join(".")
};
for (const key of ["name", "description", "version"]) {
if (fields.has(key)) {
manifest[key] = fields.get(key);
}
}
if (fields.has("author")) {
manifest.author = {
name: fields.get("author")
}
if (fields.has("authorId")) {
manifest.author.discordID = fields.get("authorId");
}
}
manifest.type = "replugged-theme";
manifest.main = filename;
manifest.license = "Unknown";
manifest.bdMeta = Object.fromEntries(fields);
return manifest;
}
/**
* Creates an asar for a CSS file and the manifest.
* @param {string} css CSS of the BD theme
* @param {object} manifest Manifest for the Replugged theme
* @returns {Blob} Blob representing the theme asar.
*/
function createAsar(css, manifest) {
const asar = new AsarCreator();
// Add the manifest to the asar
asar.addFile("manifest.json",
new TextEncoder().encode(JSON.stringify(manifest)).buffer);
// Add the CSS to the asar
asar.addFile(manifest.main, new TextEncoder().encode(css).buffer);
// Return the asar as a blob
return asar.exportBlob();
}
/**
* Downloads a file to the user's file system.
* @param {Blob} file file to download as a Blob
* @param {string} name Filename
*/
function downloadFile(file, name) {
// Thank you random blog guy
// https://www.delftstack.com/howto/javascript/javascript-download/
const linkElem = document.createElement("a");
linkElem.href = URL.createObjectURL(file);
linkElem.setAttribute("download", name);
document.body.appendChild(linkElem);
linkElem.click();
document.body.removeChild(linkElem);
}
/**
* Converts a BD .theme.css file to a Replugged theme asar and downloads it.
* @param {File} input Blob containing the input .theme.css File object.
*/
export async function convertTheme(input) {
const css = await input.text();
const manifest = buildManifest(css, input.name);
const asar = createAsar(css, manifest);
downloadFile(asar, `${manifest.id}.asar`);
}