add mod enabling/disabling

This commit is contained in:
dragonwocky 2021-04-27 22:06:45 +10:00
parent 16ab3a4969
commit 62ba127793
4 changed files with 57 additions and 30 deletions

View File

@ -196,45 +196,50 @@ fmt.slugger = (heading, slugs = new Set()) => {
return slug;
};
regexers.uuid = (str) => {
regexers.uuid = (str, err = () => {}) => {
const match = str.match(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i);
if (match && match.length) return true;
error(`invalid uuid ${str}`);
return false;
err(`invalid uuid ${str}`);
return ERROR;
};
regexers.semver = (str) => {
regexers.semver = (str, err = () => {}) => {
const match = str.match(
/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/i
);
if (match && match.length) return true;
error(`invalid semver ${str}`);
return false;
err(`invalid semver ${str}`);
return ERROR;
};
regexers.email = (str) => {
regexers.email = (str, err = () => {}) => {
const match = str.match(
/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/i
);
if (match && match.length) return true;
error(`invalid email ${str}`);
return false;
err(`invalid email ${str}`);
return ERROR;
};
regexers.url = (str) => {
regexers.url = (str, err = () => {}) => {
const match = str.match(
/^[(http(s)?):\/\/(www\.)?a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)$/i
);
if (match && match.length) return true;
error(`invalid url ${str}`);
return false;
err(`invalid url ${str}`);
return ERROR;
};
registry.CORE = [
'a6621988-551d-495a-97d8-3c568bca2e9e',
'0f0bf8b6-eae6-4273-b307-8fc43f2ee082',
];
registry.validate = async (mod, err, check) => {
let conditions = [
check('name', mod.name, typeof mod.name === 'string'),
check('id', mod.id, typeof mod.id === 'string').then((id) =>
id === ERROR ? ERROR : regexers.uuid(id)
id === ERROR ? ERROR : regexers.uuid(id, err)
),
check('version', mod.version, typeof mod.version === 'string').then((version) =>
version === ERROR ? ERROR : regexers.semver(version)
version === ERROR ? ERROR : regexers.semver(version, err)
),
check('description', mod.description, typeof mod.description === 'string'),
check(
@ -242,7 +247,7 @@ registry.validate = async (mod, err, check) => {
mod.preview,
mod.preview === undefined || typeof mod.preview === 'string'
).then((preview) =>
preview ? (preview === ERROR ? ERROR : regexers.url(preview)) : undefined
preview ? (preview === ERROR ? ERROR : regexers.url(preview, err)) : undefined
),
check('tags', mod.tags, Array.isArray(mod.tags)).then((tags) =>
tags === ERROR ? ERROR : tags.map((tag) => check('tag', tag, typeof tag === 'string'))
@ -256,12 +261,12 @@ registry.validate = async (mod, err, check) => {
'author.email',
author.email,
typeof author.email === 'string'
).then((email) => (email === ERROR ? ERROR : regexers.email(email))),
).then((email) => (email === ERROR ? ERROR : regexers.email(email, err))),
check('author.url', author.url, typeof author.url === 'string').then((url) =>
url === ERROR ? ERROR : regexers.url(url)
url === ERROR ? ERROR : regexers.url(url, err)
),
check('author.icon', author.icon, typeof author.icon === 'string').then((icon) =>
icon === ERROR ? ERROR : regexers.url(icon)
icon === ERROR ? ERROR : regexers.url(icon, err)
),
])
),
@ -420,7 +425,10 @@ registry.validate = async (mod, err, check) => {
return conditions;
};
registry.defaults = async (id) => {
const mod = (await registry.get()).find((mod) => mod.id === id);
const mod =
regexers.uuid(id) !== ERROR
? (await registry.get()).find((mod) => mod.id === id)
: undefined;
if (!mod || !mod.options) return {};
const defaults = {};
for (const opt of mod.options) {
@ -445,7 +453,8 @@ registry.defaults = async (id) => {
return defaults;
};
registry.get = async () => {
registry.get = async (enabled) => {
if (registry._list && registry._list.length) return registry._list;
registry._list = [];
if (!registry._errors) registry._errors = [];
for (const dir of await fs.getJSON('repo/registry.json')) {
@ -472,3 +481,7 @@ registry.errors = async () => {
if (!registry._errors) await registry.get();
return registry._errors;
};
registry.enabled = async (id) => {
if (registry.CORE.includes(id)) return true;
return await storage.get('_enabled', id, false);
};

View File

@ -9,6 +9,7 @@
import(chrome.runtime.getURL('helpers.js')).then(({ web, registry }) => {
web.whenReady().then(async () => {
for (let mod of await registry.get()) {
if (!(await registry.enabled(mod.id))) continue;
for (let sheet of mod.css?.client || []) {
web.loadStyleset(`repo/${mod._dir}/${sheet}`);
}

View File

@ -361,11 +361,10 @@ label [data-icon='fa/question-circle'] {
border: none;
background: none;
}
.library--title {
margin: 0;
}
.library--title,
.library--title h2 {
margin: 0;
font-size: var(--theme--font_ui-size);
}
.library--title h2 > span {
font-size: var(--theme--font_heading2-size);

View File

@ -10,6 +10,7 @@ const _id = 'a6621988-551d-495a-97d8-3c568bca2e9e';
import { env, storage, web, fmt, fs, registry } from '../../helpers.js';
for (let mod of await registry.get()) {
if (!(await registry.enabled(mod.id))) continue;
for (let sheet of mod.css?.menu || []) {
web.loadStyleset(`repo/${mod._dir}/${sheet}`);
}
@ -50,13 +51,21 @@ components.card = {
alt=""
class="library--preview"
src="${web.escapeHtml(preview)}"
/>`),
name: ({ name, id, version }) =>
web.createElement(web.html`<label
/>`),
async name({ name, id, version }) {
if (registry.CORE.includes(id))
return web.createElement(web.html`<div class="library--title"><h2>
<span>
${web.escapeHtml(name)}
<span class="library--version">v${web.escapeHtml(version)}</span>
</span>
</h2></div>`);
const $name = web.createElement(web.html`<label
for="enable--${web.escapeHtml(id)}"
class="library--title library--toggle_label"
>
<input type="checkbox" id="enable--${web.escapeHtml(id)}" />
>
<input type="checkbox" id="enable--${web.escapeHtml(id)}"
${(await storage.get('_enabled', id, false)) ? 'checked' : ''}/>
<h2>
<span>
${web.escapeHtml(name)}
@ -64,7 +73,12 @@ components.card = {
</span>
<span class="library--toggle"></span>
</h2>
</label>`),
</label>`);
$name.addEventListener('change', async (event) =>
storage.set('_enabled', id, !(await storage.get('_enabled', id, false)))
);
return $name;
},
tags: ({ tags = [] }) =>
web.createElement(web.html`<ul class="library--tags">
${tags.map((tag) => web.html`<li>#${web.escapeHtml(tag)}</li>`).join('')}
@ -102,7 +116,7 @@ components.card = {
const card = web.createElement(web.html`<article class="library--card"></article>`),
body = web.createElement(web.html`<div></div>`);
card.append(this.preview(mod));
body.append(this.name(mod));
body.append(await this.name(mod));
body.append(this.tags(mod));
body.append(this.description(mod));
body.append(this.authors(mod));