Fix async lifecycle ordering, add _spa_init boot phase, update to jqhtml _load_only/_load_render_only flags

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2026-03-06 22:33:38 +00:00
parent 11c95a2886
commit d1ac456279
2718 changed files with 70593 additions and 6320 deletions

View File

@@ -7,7 +7,91 @@ const charCodeDefinitions = require('../tokenizer/char-code-definitions.cjs');
const types = require('../tokenizer/types.cjs');
const utils = require('../tokenizer/utils.cjs');
const calcFunctionNames = ['calc(', '-moz-calc(', '-webkit-calc('];
// CSS mathematical functions categorized by return type behavior
// See: https://www.w3.org/TR/css-values-4/#math
// Calculation functions that return different types depending on input
const calcFunctionNames = [
'calc(',
'-moz-calc(',
'-webkit-calc('
];
// Comparison functions that return different types depending on input
const comparisonFunctionNames = [
'min(',
'max(',
'clamp('
];
// Functions that return a stepped value, i.e. a value that is rounded to the nearest step
const steppedValueFunctionNames = [
'round(',
'mod(',
'rem('
];
// Trigonometrical functions that return a <number>
const trigNumberFunctionNames = [
'sin(',
'cos(',
'tan('
];
// Trigonometrical functions that return a <angle>
const trigAngleFunctionNames = [
'asin(',
'acos(',
'atan(',
'atan2('
];
// Other functions that return a <number>
const otherNumberFunctionNames = [
'pow(',
'sqrt(',
'log(',
'exp(',
'sign('
];
// Exponential functions that return a <number> or <dimension> or <percentage>
const expNumberDimensionPercentageFunctionNames = [
'hypot('
];
// Return the same type as the input
const signFunctionNames = [
'abs('
];
const numberFunctionNames = [
...calcFunctionNames,
...comparisonFunctionNames,
...steppedValueFunctionNames,
...trigNumberFunctionNames,
...otherNumberFunctionNames,
...expNumberDimensionPercentageFunctionNames,
...signFunctionNames
];
const percentageFunctionNames = [
...calcFunctionNames,
...comparisonFunctionNames,
...steppedValueFunctionNames,
...expNumberDimensionPercentageFunctionNames,
...signFunctionNames
];
const dimensionFunctionNames = [
...calcFunctionNames,
...comparisonFunctionNames,
...steppedValueFunctionNames,
...trigAngleFunctionNames,
...expNumberDimensionPercentageFunctionNames,
...signFunctionNames
];
const balancePair = new Map([
[types.Function, types.RightParenthesis],
[types.LeftParenthesis, types.RightParenthesis],
@@ -114,16 +198,17 @@ function consumeFunction(token, getNextToken) {
return length;
}
// TODO: implement
// can be used wherever <length>, <frequency>, <angle>, <time>, <percentage>, <number>, or <integer> values are allowed
// https://drafts.csswg.org/css-values/#calc-notation
function calc(next) {
function math(next, functionNames) {
return function(token, getNextToken, opts) {
if (token === null) {
return 0;
}
if (token.type === types.Function && eqStrAny(token.value, calcFunctionNames)) {
if (token.type === types.Function && eqStrAny(token.value, functionNames)) {
return consumeFunction(token, getNextToken);
}
@@ -530,12 +615,12 @@ const productionTypes = {
'ident': tokenType(types.Ident),
// percentage
'percentage': calc(percentage),
'percentage': math(percentage, percentageFunctionNames),
// numeric
'zero': zero(),
'number': calc(number),
'integer': calc(integer),
'number': math(number, numberFunctionNames),
'integer': math(integer, numberFunctionNames),
// complex types
'custom-ident': customIdent,
@@ -549,6 +634,17 @@ const productionTypes = {
'any-value': anyValue
};
const unitGroups = [
'length',
'angle',
'time',
'frequency',
'resolution',
'flex',
'decibel',
'semitones'
];
// dimensions types depend on units set
function createDemensionTypes(units) {
const {
@@ -563,15 +659,45 @@ function createDemensionTypes(units) {
} = units || {};
return {
'dimension': calc(dimension(null)),
'angle': calc(dimension(angle)),
'decibel': calc(dimension(decibel)),
'frequency': calc(dimension(frequency)),
'flex': calc(dimension(flex)),
'length': calc(zero(dimension(length))),
'resolution': calc(dimension(resolution)),
'semitones': calc(dimension(semitones)),
'time': calc(dimension(time))
'dimension': math(dimension(null), dimensionFunctionNames),
'angle': math(dimension(angle), dimensionFunctionNames),
'decibel': math(dimension(decibel), dimensionFunctionNames),
'frequency': math(dimension(frequency), dimensionFunctionNames),
'flex': math(dimension(flex), dimensionFunctionNames),
'length': math(zero(dimension(length)), dimensionFunctionNames),
'resolution': math(dimension(resolution), dimensionFunctionNames),
'semitones': math(dimension(semitones), dimensionFunctionNames),
'time': math(dimension(time), dimensionFunctionNames)
};
}
// The <attr-unit> production matches any identifier that is an ASCII case-insensitive
// match for the name of a CSS dimension unit, such as px, or the <delim-token> %.
function createAttrUnit(units) {
const unitSet = new Set();
for (const group of unitGroups) {
if (Array.isArray(units[group])) {
for (const unit of units[group]) {
unitSet.add(unit.toLowerCase());
}
}
}
return function attrUnit(token) {
if (token === null) {
return 0;
}
if (token.type === types.Delim && token.value === '%') {
return 1;
}
if (token.type === types.Ident && unitSet.has(token.value.toLowerCase())) {
return 1;
}
return 0;
};
}
@@ -579,7 +705,8 @@ function createGenericTypes(units) {
return {
...tokenTypes,
...productionTypes,
...createDemensionTypes(units)
...createDemensionTypes(units),
'attr-unit': createAttrUnit(units)
};
}
@@ -587,3 +714,4 @@ exports.createDemensionTypes = createDemensionTypes;
exports.createGenericTypes = createGenericTypes;
exports.productionTypes = productionTypes;
exports.tokenTypes = tokenTypes;
exports.unitGroups = unitGroups;