Files
pole-book/server/node_modules/media-chrome/dist/utils/template-processor.js

238 lines
6.7 KiB
JavaScript

import {
AttrPart,
InnerTemplatePart,
TemplateInstance
} from "./template-parts.js";
import { isNumericString } from "./utils.js";
const pipeModifiers = {
string: (value) => String(value)
};
class PartialTemplate {
constructor(template) {
this.template = template;
this.state = void 0;
}
}
const templates = /* @__PURE__ */ new WeakMap();
const templateInstances = /* @__PURE__ */ new WeakMap();
const Directives = {
partial: (part, state) => {
state[part.expression] = new PartialTemplate(part.template);
},
if: (part, state) => {
var _a;
if (evaluateExpression(part.expression, state)) {
if (templates.get(part) !== part.template) {
templates.set(part, part.template);
const tpl = new TemplateInstance(part.template, state, processor);
part.replace(tpl);
templateInstances.set(part, tpl);
} else {
(_a = templateInstances.get(part)) == null ? void 0 : _a.update(state);
}
} else {
part.replace("");
templates.delete(part);
templateInstances.delete(part);
}
}
};
const DirectiveNames = Object.keys(Directives);
const processor = {
processCallback(instance, parts, state) {
var _a, _b;
if (!state)
return;
for (const [expression, part] of parts) {
if (part instanceof InnerTemplatePart) {
if (!part.directive) {
const directive = DirectiveNames.find(
(n) => part.template.hasAttribute(n)
);
if (directive) {
part.directive = directive;
part.expression = part.template.getAttribute(directive);
}
}
(_a = Directives[part.directive]) == null ? void 0 : _a.call(Directives, part, state);
continue;
}
let value = evaluateExpression(expression, state);
if (value instanceof PartialTemplate) {
if (templates.get(part) !== value.template) {
templates.set(part, value.template);
value = new TemplateInstance(value.template, value.state, processor);
part.value = value;
templateInstances.set(part, value);
} else {
(_b = templateInstances.get(part)) == null ? void 0 : _b.update(value.state);
}
continue;
}
if (value) {
if (part instanceof AttrPart) {
if (part.attributeName.startsWith("aria-")) {
value = String(value);
}
}
if (part instanceof AttrPart) {
if (typeof value === "boolean") {
part.booleanValue = value;
} else if (typeof value === "function") {
part.element[part.attributeName] = value;
} else {
part.value = value;
}
} else {
part.value = value;
templates.delete(part);
templateInstances.delete(part);
}
} else {
if (part instanceof AttrPart) {
part.value = void 0;
} else {
part.value = void 0;
templates.delete(part);
templateInstances.delete(part);
}
}
}
}
};
const operators = {
"!": (a) => !a,
"!!": (a) => !!a,
"==": (a, b) => a == b,
"!=": (a, b) => a != b,
">": (a, b) => a > b,
">=": (a, b) => a >= b,
"<": (a, b) => a < b,
"<=": (a, b) => a <= b,
"??": (a, b) => a != null ? a : b,
"|": (a, b) => {
var _a;
return (_a = pipeModifiers[b]) == null ? void 0 : _a.call(pipeModifiers, a);
}
};
function tokenizeExpression(expr) {
return tokenize(expr, {
boolean: /true|false/,
number: /-?\d+\.?\d*/,
string: /(["'])((?:\\.|[^\\])*?)\1/,
operator: /[!=><][=!]?|\?\?|\|/,
ws: /\s+/,
param: /[$a-z_][$\w]*/i
}).filter(({ type }) => type !== "ws");
}
function evaluateExpression(expr, state = {}) {
var _a, _b, _c, _d, _e, _f, _g;
const tokens = tokenizeExpression(expr);
if (tokens.length === 0 || tokens.some(({ type }) => !type)) {
return invalidExpression(expr);
}
if (((_a = tokens[0]) == null ? void 0 : _a.token) === ">") {
const partial = state[(_b = tokens[1]) == null ? void 0 : _b.token];
if (!partial) {
return invalidExpression(expr);
}
const partialState = { ...state };
partial.state = partialState;
const args = tokens.slice(2);
for (let i = 0; i < args.length; i += 3) {
const name = (_c = args[i]) == null ? void 0 : _c.token;
const operator = (_d = args[i + 1]) == null ? void 0 : _d.token;
const value = (_e = args[i + 2]) == null ? void 0 : _e.token;
if (name && operator === "=") {
partialState[name] = getParamValue(value, state);
}
}
return partial;
}
if (tokens.length === 1) {
if (!isValidParam(tokens[0])) {
return invalidExpression(expr);
}
return getParamValue(tokens[0].token, state);
}
if (tokens.length === 2) {
const operator = (_f = tokens[0]) == null ? void 0 : _f.token;
const run = operators[operator];
if (!run || !isValidParam(tokens[1])) {
return invalidExpression(expr);
}
const a = getParamValue(tokens[1].token, state);
return run(a);
}
if (tokens.length === 3) {
const operator = (_g = tokens[1]) == null ? void 0 : _g.token;
const run = operators[operator];
if (!run || !isValidParam(tokens[0]) || !isValidParam(tokens[2])) {
return invalidExpression(expr);
}
const a = getParamValue(tokens[0].token, state);
if (operator === "|") {
return run(a, tokens[2].token);
}
const b = getParamValue(tokens[2].token, state);
return run(a, b);
}
}
function invalidExpression(expr) {
console.warn(`Warning: invalid expression \`${expr}\``);
return false;
}
function isValidParam({ type }) {
return ["number", "boolean", "string", "param"].includes(type);
}
function getParamValue(raw, state) {
const firstChar = raw[0];
const lastChar = raw.slice(-1);
if (raw === "true" || raw === "false") {
return raw === "true";
}
if (firstChar === lastChar && [`'`, `"`].includes(firstChar)) {
return raw.slice(1, -1);
}
if (isNumericString(raw)) {
return parseFloat(raw);
}
return state[raw];
}
function tokenize(str, parsers) {
let len, match, token;
const tokens = [];
while (str) {
token = null;
len = str.length;
for (const key in parsers) {
match = parsers[key].exec(str);
if (match && match.index < len) {
token = {
token: match[0],
type: key,
matches: match.slice(1)
};
len = match.index;
}
}
if (len) {
tokens.push({
token: str.substr(0, len),
type: void 0
});
}
if (token) {
tokens.push(token);
}
str = str.substr(len + (token ? token.token.length : 0));
}
return tokens;
}
export {
evaluateExpression,
getParamValue,
processor,
tokenizeExpression
};