Document application modes (development/debug/production) Add global file drop handler, order column normalization, SPA hash fix Serve CDN assets via /_vendor/ URLs instead of merging into bundles Add production minification with license preservation Improve JSON formatting for debugging and production optimization Add CDN asset caching with CSS URL inlining for production builds Add three-mode system (development, debug, production) Update Manifest CLAUDE.md to reflect helper class architecture Refactor Manifest.php into helper classes for better organization Pre-manifest-refactor checkpoint: Add app_mode documentation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
222 lines
6.9 KiB
JavaScript
Executable File
222 lines
6.9 KiB
JavaScript
Executable File
import boolbase from "boolbase";
|
|
/**
|
|
* All reserved characters in a regex, used for escaping.
|
|
*
|
|
* Taken from XRegExp, (c) 2007-2020 Steven Levithan under the MIT license
|
|
* https://github.com/slevithan/xregexp/blob/95eeebeb8fac8754d54eafe2b4743661ac1cf028/src/xregexp.js#L794
|
|
*/
|
|
const reChars = /[-[\]{}()*+?.,\\^$|#\s]/g;
|
|
function escapeRegex(value) {
|
|
return value.replace(reChars, "\\$&");
|
|
}
|
|
/**
|
|
* Attributes that are case-insensitive in HTML.
|
|
*
|
|
* @private
|
|
* @see https://html.spec.whatwg.org/multipage/semantics-other.html#case-sensitivity-of-selectors
|
|
*/
|
|
const caseInsensitiveAttributes = new Set([
|
|
"accept",
|
|
"accept-charset",
|
|
"align",
|
|
"alink",
|
|
"axis",
|
|
"bgcolor",
|
|
"charset",
|
|
"checked",
|
|
"clear",
|
|
"codetype",
|
|
"color",
|
|
"compact",
|
|
"declare",
|
|
"defer",
|
|
"dir",
|
|
"direction",
|
|
"disabled",
|
|
"enctype",
|
|
"face",
|
|
"frame",
|
|
"hreflang",
|
|
"http-equiv",
|
|
"lang",
|
|
"language",
|
|
"link",
|
|
"media",
|
|
"method",
|
|
"multiple",
|
|
"nohref",
|
|
"noresize",
|
|
"noshade",
|
|
"nowrap",
|
|
"readonly",
|
|
"rel",
|
|
"rev",
|
|
"rules",
|
|
"scope",
|
|
"scrolling",
|
|
"selected",
|
|
"shape",
|
|
"target",
|
|
"text",
|
|
"type",
|
|
"valign",
|
|
"valuetype",
|
|
"vlink",
|
|
]);
|
|
function shouldIgnoreCase(selector, options) {
|
|
return typeof selector.ignoreCase === "boolean"
|
|
? selector.ignoreCase
|
|
: selector.ignoreCase === "quirks"
|
|
? !!options.quirksMode
|
|
: !options.xmlMode && caseInsensitiveAttributes.has(selector.name);
|
|
}
|
|
/**
|
|
* Attribute selectors
|
|
*/
|
|
export const attributeRules = {
|
|
equals(next, data, options) {
|
|
const { adapter } = options;
|
|
const { name } = data;
|
|
let { value } = data;
|
|
if (shouldIgnoreCase(data, options)) {
|
|
value = value.toLowerCase();
|
|
return (elem) => {
|
|
const attr = adapter.getAttributeValue(elem, name);
|
|
return (attr != null &&
|
|
attr.length === value.length &&
|
|
attr.toLowerCase() === value &&
|
|
next(elem));
|
|
};
|
|
}
|
|
return (elem) => adapter.getAttributeValue(elem, name) === value && next(elem);
|
|
},
|
|
hyphen(next, data, options) {
|
|
const { adapter } = options;
|
|
const { name } = data;
|
|
let { value } = data;
|
|
const len = value.length;
|
|
if (shouldIgnoreCase(data, options)) {
|
|
value = value.toLowerCase();
|
|
return function hyphenIC(elem) {
|
|
const attr = adapter.getAttributeValue(elem, name);
|
|
return (attr != null &&
|
|
(attr.length === len || attr.charAt(len) === "-") &&
|
|
attr.substr(0, len).toLowerCase() === value &&
|
|
next(elem));
|
|
};
|
|
}
|
|
return function hyphen(elem) {
|
|
const attr = adapter.getAttributeValue(elem, name);
|
|
return (attr != null &&
|
|
(attr.length === len || attr.charAt(len) === "-") &&
|
|
attr.substr(0, len) === value &&
|
|
next(elem));
|
|
};
|
|
},
|
|
element(next, data, options) {
|
|
const { adapter } = options;
|
|
const { name, value } = data;
|
|
if (/\s/.test(value)) {
|
|
return boolbase.falseFunc;
|
|
}
|
|
const regex = new RegExp(`(?:^|\\s)${escapeRegex(value)}(?:$|\\s)`, shouldIgnoreCase(data, options) ? "i" : "");
|
|
return function element(elem) {
|
|
const attr = adapter.getAttributeValue(elem, name);
|
|
return (attr != null &&
|
|
attr.length >= value.length &&
|
|
regex.test(attr) &&
|
|
next(elem));
|
|
};
|
|
},
|
|
exists(next, { name }, { adapter }) {
|
|
return (elem) => adapter.hasAttrib(elem, name) && next(elem);
|
|
},
|
|
start(next, data, options) {
|
|
const { adapter } = options;
|
|
const { name } = data;
|
|
let { value } = data;
|
|
const len = value.length;
|
|
if (len === 0) {
|
|
return boolbase.falseFunc;
|
|
}
|
|
if (shouldIgnoreCase(data, options)) {
|
|
value = value.toLowerCase();
|
|
return (elem) => {
|
|
const attr = adapter.getAttributeValue(elem, name);
|
|
return (attr != null &&
|
|
attr.length >= len &&
|
|
attr.substr(0, len).toLowerCase() === value &&
|
|
next(elem));
|
|
};
|
|
}
|
|
return (elem) => {
|
|
var _a;
|
|
return !!((_a = adapter.getAttributeValue(elem, name)) === null || _a === void 0 ? void 0 : _a.startsWith(value)) &&
|
|
next(elem);
|
|
};
|
|
},
|
|
end(next, data, options) {
|
|
const { adapter } = options;
|
|
const { name } = data;
|
|
let { value } = data;
|
|
const len = -value.length;
|
|
if (len === 0) {
|
|
return boolbase.falseFunc;
|
|
}
|
|
if (shouldIgnoreCase(data, options)) {
|
|
value = value.toLowerCase();
|
|
return (elem) => {
|
|
var _a;
|
|
return ((_a = adapter
|
|
.getAttributeValue(elem, name)) === null || _a === void 0 ? void 0 : _a.substr(len).toLowerCase()) === value && next(elem);
|
|
};
|
|
}
|
|
return (elem) => {
|
|
var _a;
|
|
return !!((_a = adapter.getAttributeValue(elem, name)) === null || _a === void 0 ? void 0 : _a.endsWith(value)) &&
|
|
next(elem);
|
|
};
|
|
},
|
|
any(next, data, options) {
|
|
const { adapter } = options;
|
|
const { name, value } = data;
|
|
if (value === "") {
|
|
return boolbase.falseFunc;
|
|
}
|
|
if (shouldIgnoreCase(data, options)) {
|
|
const regex = new RegExp(escapeRegex(value), "i");
|
|
return function anyIC(elem) {
|
|
const attr = adapter.getAttributeValue(elem, name);
|
|
return (attr != null &&
|
|
attr.length >= value.length &&
|
|
regex.test(attr) &&
|
|
next(elem));
|
|
};
|
|
}
|
|
return (elem) => {
|
|
var _a;
|
|
return !!((_a = adapter.getAttributeValue(elem, name)) === null || _a === void 0 ? void 0 : _a.includes(value)) &&
|
|
next(elem);
|
|
};
|
|
},
|
|
not(next, data, options) {
|
|
const { adapter } = options;
|
|
const { name } = data;
|
|
let { value } = data;
|
|
if (value === "") {
|
|
return (elem) => !!adapter.getAttributeValue(elem, name) && next(elem);
|
|
}
|
|
else if (shouldIgnoreCase(data, options)) {
|
|
value = value.toLowerCase();
|
|
return (elem) => {
|
|
const attr = adapter.getAttributeValue(elem, name);
|
|
return ((attr == null ||
|
|
attr.length !== value.length ||
|
|
attr.toLowerCase() !== value) &&
|
|
next(elem));
|
|
};
|
|
}
|
|
return (elem) => adapter.getAttributeValue(elem, name) !== value && next(elem);
|
|
},
|
|
};
|
|
//# sourceMappingURL=attributes.js.map
|