52 lines
2.2 KiB
JavaScript
52 lines
2.2 KiB
JavaScript
#!/usr/bin/env node
|
|
// Execute the real ACL editor initializer, not just parse it: an uninitialized
|
|
// i18n helper used to stop the entire fingerprinted dashboard bundle at load.
|
|
import assert from 'node:assert/strict';
|
|
import { readFileSync } from 'node:fs';
|
|
import { runInNewContext } from 'node:vm';
|
|
|
|
const source = readFileSync('src/admin/web/management.js', 'utf8');
|
|
const start = source.lastIndexOf('(() => {');
|
|
assert(start > 0 && source.slice(start).includes('window.rustProxyAclProfiles ='), 'ACL editor IIFE not found');
|
|
|
|
function element(tag = 'div') {
|
|
return {
|
|
tag, children: [], dataset: {}, value: '', checked: false, hidden: false,
|
|
classList: { add() {}, remove() {}, toggle() {} },
|
|
append(...nodes) { this.children.push(...nodes); },
|
|
after(...nodes) { this.insertedAfter = nodes; },
|
|
replaceChildren(...nodes) { this.children = nodes; },
|
|
addEventListener() {},
|
|
reset() {},
|
|
querySelector() { return element(); },
|
|
querySelectorAll() { return []; },
|
|
};
|
|
}
|
|
const nodes = new Map();
|
|
const get = id => {
|
|
if (!nodes.has(id)) nodes.set(id, element());
|
|
return nodes.get(id);
|
|
};
|
|
const modes = ['allow_exceptions', 'block_exceptions', 'custom'].map((value, i) => ({ value, checked: i === 0 }));
|
|
get('acl-profile-form').querySelectorAll = selector => selector === 'input[name="acl-profile-mode"]' ? modes : [];
|
|
const window = {};
|
|
const context = {
|
|
$: get, window, envelope: null,
|
|
t: key => `localized:${key}`,
|
|
el: (tag, text, cls) => {
|
|
const node = element(tag);
|
|
if (text !== undefined) node.textContent = text;
|
|
if (cls) node.className = cls;
|
|
return node;
|
|
},
|
|
};
|
|
runInNewContext(source.slice(start), context, { filename: 'src/admin/web/management.js' });
|
|
assert.equal(typeof window.rustProxyAclProfiles?.render, 'function', 'ACL panel initializer must finish');
|
|
assert.equal(typeof window.rustProxyAclProfiles?.refreshTranslations, 'function');
|
|
const hint = get('acl-profile-ip-help').insertedAfter?.[0];
|
|
assert.equal(hint?.tag, 'p', 'DDNS hint must be rendered');
|
|
assert.equal(hint?.dataset.i18n, 'aclDnsHelp', 'DDNS hint must remain translatable');
|
|
assert.equal(hint?.textContent, 'localized:aclDnsHelp');
|
|
window.rustProxyAclProfiles.reset();
|
|
console.log('PASS: ACL/DDNS real initializer runs without i18n temporal dead zone');
|