ModuleBuilder/src/preprocessors/genericTheme.js

232 lines
6.5 KiB
JavaScript

import axios from 'axios';
const discordVars = [
'--header-primary',
'--header-secondary',
'--text-normal',
'--text-muted',
'--text-link',
'--channels-default',
'--interactive-normal',
'--interactive-hover',
'--interactive-active',
'--interactive-muted',
'--background-primary',
'--background-secondary',
'--background-secondary-alt',
'--background-tertiary',
'--background-accent',
'--background-floating',
'--background-mobile-primary',
'--background-mobile-secondary',
'--background-modifier-hover',
'--background-modifier-active',
'--background-modifier-selected',
'--background-modifier-accent',
'--background-mentioned',
'--background-mentioned-hover',
'--background-message-hover',
'--background-help-warning',
'--background-help-info',
'--scrollbar-thin-thumb',
'--scrollbar-thin-track',
'--scrollbar-auto-thumb',
'--scrollbar-auto-track',
'--scrollbar-auto-scrollbar-color-thumb',
'--scrollbar-auto-scrollbar-color-track',
'--elevation-stroke',
'--elevation-low',
'--elevation-medium',
'--elevation-high',
'--logo-primary',
'--focus-primary',
'--radio-group-dot-foreground',
'--guild-header-text-shadow',
'--channeltextarea-background',
'--activity-card-background',
'--textbox-markdown-syntax',
'--deprecated-card-bg',
'--deprecated-card-editable-bg',
'--deprecated-store-bg',
'--deprecated-quickswitcher-input-background',
'--deprecated-quickswitcher-input-placeholder',
'--deprecated-text-input-bg',
'--deprecated-text-input-border',
'--deprecated-text-input-border-hover',
'--deprecated-text-input-border-disabled',
'--deprecated-text-input-prefix',
];
const imagePaletteVars = [
'--background-primary',
'--background-secondary',
'--background-secondary-alt',
'--background-tertiary',
'--background-accent',
'--background-floating',
];
export default async (manifest, _content, repo) => {
const content = _content.replace(/\\/g, '\\\\').replace(/`/g, '\\`').replace(/\$/g, '\\$');
let variables = content.match(/--([^*!\n}]*): ([^*\n}]*);/g) || [];
let imports = content.match(/@import url\(['"`]?(.*)['"`]?\);/g) || [];
for (const x of imports) {
let url = x.replace(/@import url\(['"`]?/, '').replace(/['"`]?\);/, '');
if (url.startsWith('//')) url = 'https:' + url;
console.log(x, url);
let imported;
try {
imported = (await axios.get(url)).data;
} catch (e) {
console.log('failed to get css for', url);
continue;
}
variables = variables.concat(imported.match(/--([^*!\n}]*): ([^*\n}]*);/g) || []);
}
if (variables.length > 0)
variables = variables.map((x) => {
const spl = x.split(':');
let name = spl[0].trim();
let val = spl.slice(1).join(':').trim().slice(0, -1).replace(' !important', '');
let type = 'text';
if (val.match(/(#[0-9a-fA-F]{6}|([0-9]{1,3}, ?[0-9]{1,3}, ?[0-9]{1,3}))/)) {
type = 'color';
}
return [name, val, type];
});
const imagePalette = [];
for (const wanted of imagePaletteVars) {
const v = variables.find((x) => x[0] === wanted);
if (!v) {
console.log('aborting color palette image, could not find var', wanted);
break;
}
let abortNoVal = false;
while (v[1].startsWith('var(')) {
v[1] = variables.find((y) => y[0] === v[1].slice(4, -1))?.[1];
if (!v[1]) {
abortNoVal = true;
break;
}
}
if (abortNoVal) {
console.log('aborting color palette image, could not find var substitute', wanted);
break;
}
imagePalette.push([v[0], v[1]]);
}
if (imagePalette.length === imagePaletteVars.length) {
if (!repo[4].images) repo[4].images = [];
repo[4].images.push(imagePalette);
}
// Filter out Discord standard vars, and duplicate names
if (variables.length > 0)
variables = variables.filter(
(x, i, s) =>
!discordVars.includes(x[0]) &&
!x[1].includes('var(') &&
!x[0].includes('glasscord') &&
s.indexOf(s.find((y) => y[0] === x[0])) === i,
);
const toShowSettings = repo[5] === true && variables.length > 0;
console.log(variables, toShowSettings);
return `// Generated by MS2Builder - genericTheme preprocessor / porter
let style;
export default {
goosemodHandlers: {
onImport: async () => {
style = document.createElement("style");
document.head.appendChild(style);
style.appendChild(
document.createTextNode(
\`${content}\`
)
);
if (${toShowSettings} || (goosemodScope.settings.gmSettings.get().allThemeSettings)) goosemodScope.settings.createItem('${
manifest.name
}', [
'',
${variables
.map(
(x) => `{
type: '${x[2] === 'color' ? 'text-and-color' : 'text-input'}',
text: '${x[0]
.replace('--rs-', '--radial-status:-')
.substring(2)
.replace(/-/g, ' ')
.replace(/\w\S*/g, (_) => _[0].toUpperCase() + _.substring(1).toLowerCase())
.replace('Rgb', 'RGB')
.replace('Afk', 'AFK')
.replace('Dnd', 'DND')}',
oninput: (val) => {
${
'' /* x[2] === 'color' && x[1][0] !== '#' ? `val = 'rgb(' + parseInt(val.substring(1, 3), 16).toString() + ', ' + parseInt(val.substring(3, 5), 16).toString() + ', ' + parseInt(val.substring(5, 7), 16).toString() + ')'` : '' */
}
document.body.style.setProperty('${x[0]}', val);
},
initialValue: () => {
let val = document.body.style.getPropertyValue(\`${x[0]}\`) || \`${x[1]}\`;
${
x[2] === 'color'
? `if (val[0] !== '#') { val = '#' + val.split(', ').map((x) => parseInt(x).toString(16).padStart(2, '0')).join(''); }`
: ''
}
console.log(val);
return val;
}
}`,
)
.join(', ')}
])
},
onRemove: async () => {
style.remove();
try {
goosemodScope.settings.removeItem('${manifest.name}');
} catch (e) { }
},
getSettings: async () => [${variables
.map((x) => `['${x[0]}', document.body.style.getPropertyValue(\`${x[0]}\`)]`)
.join(', ')}],
loadSettings: async (settings) => {
settings.forEach((x) => {
document.body.style.setProperty(x[0], x[1]);
});
}
}
};`;
};