tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

rendering.mjs (7694B)


      1 function generateTemplate(className, variable, selector) {
      2    if (className[variable] === undefined) {
      3        className[variable] = document.querySelector(selector).content;
      4    }
      5 }
      6 
      7 class ParameterTemplate extends HTMLElement {
      8    default = null;
      9 
     10    inputElement = null;
     11 
     12    static baseTemplate;
     13    constructor(options = {}, className, selector, defaultValue=null, ...args) {
     14        super();
     15        generateTemplate(ParameterTemplate, "baseTemplate", "#parameter");
     16        generateTemplate(className, "template", selector);
     17        let baseClone = ParameterTemplate.baseTemplate.cloneNode(true);
     18 
     19        let clone = className["template"].cloneNode(true);
     20 
     21        this.initialize(clone, ...args);
     22 
     23        this.inputElement = clone.querySelector("*[data-oninput]");
     24        if (this.inputElement !== null) {
     25            this.inputElement.addEventListener("input", this.input.bind(this));
     26        }
     27 
     28        clone.slot = "parameter";
     29        baseClone.appendChild(clone);
     30 
     31        const shadowRoot = this.attachShadow({ mode: "open" });
     32        shadowRoot.appendChild(baseClone);
     33 
     34        if ("defaultValue" in options) {
     35            this.default = options.defaultValue;
     36            this.setValue(options.defaultValue);
     37        } else if (this.default === null) {
     38            this.default = defaultValue;
     39        }
     40    }
     41 
     42    setValue(v) {
     43        if (this.inputElement !== null) {
     44            this.inputElement.value = v;
     45        }
     46    }
     47 
     48    getEventValue(event) {
     49        return event.target.value;
     50    }
     51 
     52    input(event) {
     53        this.dispatchEvent(new CustomEvent("parameter-input", {
     54            detail: this.getEventValue(event)
     55        }));
     56    }
     57 
     58    initialize(clone) {
     59 
     60    }
     61 }
     62 
     63 customElements.define("terminus-param", ParameterTemplate);
     64 
     65 class BooleanTemplate extends ParameterTemplate {
     66    static template;
     67    constructor(options) {
     68        super(options, BooleanTemplate, "template#boolean", false);
     69    }
     70 
     71    getEventValue(event) {
     72        return event.target.checked;
     73    }
     74 
     75    setValue(v) {
     76        this.inputElement.checked = v;
     77    }
     78 }
     79 
     80 customElements.define("terminus-param-boolean", BooleanTemplate);
     81 
     82 class NumberTemplate extends ParameterTemplate {
     83    static template;
     84    constructor(options) {
     85        super(options, NumberTemplate, "template#number", 0);
     86    }
     87 
     88    getEventValue(event) {
     89        return parseFloat(event.target.value);
     90    }
     91 }
     92 
     93 customElements.define("terminus-param-number", NumberTemplate);
     94 
     95 class StringTemplate extends ParameterTemplate {
     96    static template;
     97    constructor(options) {
     98        super(options, StringTemplate, "template#string", "");
     99    }
    100 }
    101 
    102 customElements.define("terminus-param-string", StringTemplate);
    103 
    104 class StringArrayTemplate extends ParameterTemplate {
    105    static template;
    106    constructor(options) {
    107        super(options, StringArrayTemplate, "template#string-array", []);
    108    }
    109 
    110    getEventValue(event) {
    111        return event.target.value.split(",");
    112    }
    113 }
    114 
    115 customElements.define("terminus-param-string-array", StringArrayTemplate);
    116 
    117 class EnumOption extends HTMLElement {
    118    static template;
    119    constructor(optionText) {
    120        super();
    121        generateTemplate(EnumOption, "template", "template#enum-option");
    122        let clone = EnumOption.template.cloneNode(true);
    123 
    124        clone.querySelector("slot[name='option-text']").parentElement.innerText = optionText;
    125 
    126        this.append(...clone.children);
    127    }
    128 }
    129 
    130 customElements.define("terminus-enum-option", EnumOption);
    131 
    132 class EnumTemplate extends ParameterTemplate {
    133    static template;
    134 
    135    #enumType;
    136    constructor(options, enumType) {
    137        super(options, EnumTemplate, "template#enum", null, enumType);
    138        this.#enumType = enumType;
    139    }
    140 
    141    initialize(clone, enumType) {
    142        let options = clone.querySelector("*[data-options]");
    143 
    144        for (let entry of enumType.getAllEntries()) {
    145 
    146            if (this.default === null) {
    147                this.default = entry[0];
    148            }
    149            options.append(...(new EnumOption(entry[0])).children);
    150        }
    151    }
    152 
    153    getEventValue(event) {
    154        return this.#enumType[event.target.value];
    155    }
    156 }
    157 
    158 customElements.define("terminus-param-enum", EnumTemplate);
    159 
    160 class TerminusParams extends HTMLElement {
    161    #params = [];
    162 
    163    constructor(library, evaluateExternal, params){
    164        super();
    165 
    166        for (var i = 0; i < params.length; i++) {
    167            let param = params[i];
    168            let paramName = document.createElement("span");
    169            paramName.slot = "param-name";
    170            paramName.innerText = param.name;
    171 
    172            var newChild;
    173 
    174            switch (param.typeUse) {
    175                case "string":
    176                    newChild = new StringTemplate(param);
    177                    this.#params[i] = "";
    178                    break;
    179                case "boolean":
    180                    newChild = new BooleanTemplate(param);
    181                    this.#params[i] = false;
    182                    break;
    183                case "number":
    184                    newChild = new NumberTemplate(param);
    185                    this.#params[i] = 0;
    186                    break;
    187                case "Array<string>":
    188                    newChild = new StringArrayTemplate(param);
    189                    this.#params[i] = [];
    190                    break;
    191                case "enumerator":
    192                    newChild = new EnumTemplate(param, library[param.type]);
    193                    this.#params[i] = newChild.default
    194                    break;
    195                case "external":
    196                    let updateParamEvent = (value) => {
    197                        this.#params[i] = value;
    198                    };
    199                    evaluateExternal(param, updateParamEvent);
    200                    break;
    201                default:
    202                    console.error("Unrecognized parameter: ", param);
    203                    break;
    204            }
    205 
    206            newChild.addEventListener("parameter-input", this.input.bind(this, i));
    207            this.#params[i] = newChild.default;
    208 
    209            newChild.appendChild(paramName);
    210            this.appendChild(newChild);
    211        }
    212    }
    213 
    214    input(paramIdx, event) {
    215        this.#params[paramIdx] = event.detail;
    216    }
    217 
    218    get paramArray() {
    219        return this.#params;
    220    }
    221 }
    222 
    223 customElements.define("terminus-params", TerminusParams);
    224 
    225 export class TerminusRender extends HTMLElement {
    226    static template;
    227 
    228    #func = null;
    229    #parameters;
    230    #output;
    231    constructor(library, evaluateExternal, terminus) {
    232        super();
    233        generateTemplate(TerminusRender, "template", "template#terminus");
    234        let clone = TerminusRender.template.cloneNode(true);
    235 
    236        this.id = terminus.funcName;
    237 
    238        this.#func = terminus.func;
    239 
    240        let button = clone.querySelector("*[data-submit]");
    241        button.addEventListener("click", this.submit.bind(this));
    242 
    243        let funcText = document.createElement("span");
    244        funcText.slot = "func-name";
    245        funcText.innerText = terminus.funcName;
    246        this.appendChild(funcText);
    247 
    248        this.#parameters = new TerminusParams(library, evaluateExternal, terminus.parameters);
    249        this.#parameters.slot = "parameters";
    250        this.appendChild(this.#parameters);
    251 
    252        this.#output = document.createElement("span");
    253        this.#output.slot = "output";
    254 
    255        this.appendChild(this.#output);
    256 
    257        const shadowRoot = this.attachShadow({ mode: "open" });
    258        shadowRoot.appendChild(clone);
    259    }
    260 
    261    submit() {
    262        try {
    263            this.#output.innerText = this.#func(...this.#parameters.paramArray);
    264        } catch(e) {
    265            this.#output.innerText = e;
    266            throw e;
    267        }
    268    }
    269 }
    270 
    271 customElements.define("terminus-render", TerminusRender);