full site update

This commit is contained in:
2025-07-24 18:46:24 +02:00
parent bfe2b90d8d
commit 37a6e0ab31
6912 changed files with 540482 additions and 361712 deletions

View File

@@ -0,0 +1,16 @@
'use strict';
const createCustomError = require('../utils/create-custom-error.cjs');
function SyntaxError(message, input, offset) {
return Object.assign(createCustomError.createCustomError('SyntaxError', message), {
input,
offset,
rawMessage: message,
message: message + '\n' +
' ' + input + '\n' +
'--' + new Array((offset || input.length) + 1).join('-') + '^'
});
}
exports.SyntaxError = SyntaxError;

View File

@@ -0,0 +1,139 @@
'use strict';
function noop(value) {
return value;
}
function generateMultiplier(multiplier) {
const { min, max, comma } = multiplier;
if (min === 0 && max === 0) {
return comma ? '#?' : '*';
}
if (min === 0 && max === 1) {
return '?';
}
if (min === 1 && max === 0) {
return comma ? '#' : '+';
}
if (min === 1 && max === 1) {
return '';
}
return (
(comma ? '#' : '') +
(min === max
? '{' + min + '}'
: '{' + min + ',' + (max !== 0 ? max : '') + '}'
)
);
}
function generateTypeOpts(node) {
switch (node.type) {
case 'Range':
return (
' [' +
(node.min === null ? '-∞' : node.min) +
',' +
(node.max === null ? '∞' : node.max) +
']'
);
default:
throw new Error('Unknown node type `' + node.type + '`');
}
}
function generateSequence(node, decorate, forceBraces, compact) {
const combinator = node.combinator === ' ' || compact ? node.combinator : ' ' + node.combinator + ' ';
const result = node.terms
.map(term => internalGenerate(term, decorate, forceBraces, compact))
.join(combinator);
if (node.explicit || forceBraces) {
return (compact || result[0] === ',' ? '[' : '[ ') + result + (compact ? ']' : ' ]');
}
return result;
}
function internalGenerate(node, decorate, forceBraces, compact) {
let result;
switch (node.type) {
case 'Group':
result =
generateSequence(node, decorate, forceBraces, compact) +
(node.disallowEmpty ? '!' : '');
break;
case 'Multiplier':
// return since node is a composition
return (
internalGenerate(node.term, decorate, forceBraces, compact) +
decorate(generateMultiplier(node), node)
);
case 'Boolean':
result = '<boolean-expr[' + internalGenerate(node.term, decorate, forceBraces, compact) + ']>';
break;
case 'Type':
result = '<' + node.name + (node.opts ? decorate(generateTypeOpts(node.opts), node.opts) : '') + '>';
break;
case 'Property':
result = '<\'' + node.name + '\'>';
break;
case 'Keyword':
result = node.name;
break;
case 'AtKeyword':
result = '@' + node.name;
break;
case 'Function':
result = node.name + '(';
break;
case 'String':
case 'Token':
result = node.value;
break;
case 'Comma':
result = ',';
break;
default:
throw new Error('Unknown node type `' + node.type + '`');
}
return decorate(result, node);
}
function generate(node, options) {
let decorate = noop;
let forceBraces = false;
let compact = false;
if (typeof options === 'function') {
decorate = options;
} else if (options) {
forceBraces = Boolean(options.forceBraces);
compact = Boolean(options.compact);
if (typeof options.decorate === 'function') {
decorate = options.decorate;
}
}
return internalGenerate(node, decorate, forceBraces, compact);
}
exports.generate = generate;

13
node_modules/css-tree/cjs/definition-syntax/index.cjs generated vendored Normal file
View File

@@ -0,0 +1,13 @@
'use strict';
const SyntaxError = require('./SyntaxError.cjs');
const generate = require('./generate.cjs');
const parse = require('./parse.cjs');
const walk = require('./walk.cjs');
exports.SyntaxError = SyntaxError.SyntaxError;
exports.generate = generate.generate;
exports.parse = parse.parse;
exports.walk = walk.walk;

556
node_modules/css-tree/cjs/definition-syntax/parse.cjs generated vendored Normal file
View File

@@ -0,0 +1,556 @@
'use strict';
const scanner = require('./scanner.cjs');
const TAB = 9;
const N = 10;
const F = 12;
const R = 13;
const SPACE = 32;
const EXCLAMATIONMARK = 33; // !
const NUMBERSIGN = 35; // #
const AMPERSAND = 38; // &
const APOSTROPHE = 39; // '
const LEFTPARENTHESIS = 40; // (
const RIGHTPARENTHESIS = 41; // )
const ASTERISK = 42; // *
const PLUSSIGN = 43; // +
const COMMA = 44; // ,
const HYPERMINUS = 45; // -
const LESSTHANSIGN = 60; // <
const GREATERTHANSIGN = 62; // >
const QUESTIONMARK = 63; // ?
const COMMERCIALAT = 64; // @
const LEFTSQUAREBRACKET = 91; // [
const RIGHTSQUAREBRACKET = 93; // ]
const LEFTCURLYBRACKET = 123; // {
const VERTICALLINE = 124; // |
const RIGHTCURLYBRACKET = 125; // }
const INFINITY = 8734; // ∞
const COMBINATOR_PRECEDENCE = {
' ': 1,
'&&': 2,
'||': 3,
'|': 4
};
function readMultiplierRange(scanner) {
let min = null;
let max = null;
scanner.eat(LEFTCURLYBRACKET);
scanner.skipWs();
min = scanner.scanNumber(scanner);
scanner.skipWs();
if (scanner.charCode() === COMMA) {
scanner.pos++;
scanner.skipWs();
if (scanner.charCode() !== RIGHTCURLYBRACKET) {
max = scanner.scanNumber(scanner);
scanner.skipWs();
}
} else {
max = min;
}
scanner.eat(RIGHTCURLYBRACKET);
return {
min: Number(min),
max: max ? Number(max) : 0
};
}
function readMultiplier(scanner) {
let range = null;
let comma = false;
switch (scanner.charCode()) {
case ASTERISK:
scanner.pos++;
range = {
min: 0,
max: 0
};
break;
case PLUSSIGN:
scanner.pos++;
range = {
min: 1,
max: 0
};
break;
case QUESTIONMARK:
scanner.pos++;
range = {
min: 0,
max: 1
};
break;
case NUMBERSIGN:
scanner.pos++;
comma = true;
if (scanner.charCode() === LEFTCURLYBRACKET) {
range = readMultiplierRange(scanner);
} else if (scanner.charCode() === QUESTIONMARK) {
// https://www.w3.org/TR/css-values-4/#component-multipliers
// > the # and ? multipliers may be stacked as #?
// In this case just treat "#?" as a single multiplier
// { min: 0, max: 0, comma: true }
scanner.pos++;
range = {
min: 0,
max: 0
};
} else {
range = {
min: 1,
max: 0
};
}
break;
case LEFTCURLYBRACKET:
range = readMultiplierRange(scanner);
break;
default:
return null;
}
return {
type: 'Multiplier',
comma,
min: range.min,
max: range.max,
term: null
};
}
function maybeMultiplied(scanner, node) {
const multiplier = readMultiplier(scanner);
if (multiplier !== null) {
multiplier.term = node;
// https://www.w3.org/TR/css-values-4/#component-multipliers
// > The + and # multipliers may be stacked as +#;
// Represent "+#" as nested multipliers:
// { ...<multiplier #>,
// term: {
// ...<multipler +>,
// term: node
// }
// }
if (scanner.charCode() === NUMBERSIGN &&
scanner.charCodeAt(scanner.pos - 1) === PLUSSIGN) {
return maybeMultiplied(scanner, multiplier);
}
return multiplier;
}
return node;
}
function maybeToken(scanner) {
const ch = scanner.peek();
if (ch === '') {
return null;
}
return maybeMultiplied(scanner, {
type: 'Token',
value: ch
});
}
function readProperty(scanner) {
let name;
scanner.eat(LESSTHANSIGN);
scanner.eat(APOSTROPHE);
name = scanner.scanWord();
scanner.eat(APOSTROPHE);
scanner.eat(GREATERTHANSIGN);
return maybeMultiplied(scanner, {
type: 'Property',
name
});
}
// https://drafts.csswg.org/css-values-3/#numeric-ranges
// 4.1. Range Restrictions and Range Definition Notation
//
// Range restrictions can be annotated in the numeric type notation using CSS bracketed
// range notation—[min,max]—within the angle brackets, after the identifying keyword,
// indicating a closed range between (and including) min and max.
// For example, <integer [0, 10]> indicates an integer between 0 and 10, inclusive.
function readTypeRange(scanner) {
// use null for Infinity to make AST format JSON serializable/deserializable
let min = null; // -Infinity
let max = null; // Infinity
let sign = 1;
scanner.eat(LEFTSQUAREBRACKET);
if (scanner.charCode() === HYPERMINUS) {
scanner.peek();
sign = -1;
}
if (sign == -1 && scanner.charCode() === INFINITY) {
scanner.peek();
} else {
min = sign * Number(scanner.scanNumber(scanner));
if (scanner.isNameCharCode()) {
min += scanner.scanWord();
}
}
scanner.skipWs();
scanner.eat(COMMA);
scanner.skipWs();
if (scanner.charCode() === INFINITY) {
scanner.peek();
} else {
sign = 1;
if (scanner.charCode() === HYPERMINUS) {
scanner.peek();
sign = -1;
}
max = sign * Number(scanner.scanNumber(scanner));
if (scanner.isNameCharCode()) {
max += scanner.scanWord();
}
}
scanner.eat(RIGHTSQUAREBRACKET);
return {
type: 'Range',
min,
max
};
}
function readType(scanner) {
let name;
let opts = null;
scanner.eat(LESSTHANSIGN);
name = scanner.scanWord();
// https://drafts.csswg.org/css-values-5/#boolean
if (name === 'boolean-expr') {
scanner.eat(LEFTSQUAREBRACKET);
const implicitGroup = readImplicitGroup(scanner, RIGHTSQUAREBRACKET);
scanner.eat(RIGHTSQUAREBRACKET);
scanner.eat(GREATERTHANSIGN);
return maybeMultiplied(scanner, {
type: 'Boolean',
term: implicitGroup.terms.length === 1
? implicitGroup.terms[0]
: implicitGroup
});
}
if (scanner.charCode() === LEFTPARENTHESIS &&
scanner.nextCharCode() === RIGHTPARENTHESIS) {
scanner.pos += 2;
name += '()';
}
if (scanner.charCodeAt(scanner.findWsEnd(scanner.pos)) === LEFTSQUAREBRACKET) {
scanner.skipWs();
opts = readTypeRange(scanner);
}
scanner.eat(GREATERTHANSIGN);
return maybeMultiplied(scanner, {
type: 'Type',
name,
opts
});
}
function readKeywordOrFunction(scanner) {
const name = scanner.scanWord();
if (scanner.charCode() === LEFTPARENTHESIS) {
scanner.pos++;
return {
type: 'Function',
name
};
}
return maybeMultiplied(scanner, {
type: 'Keyword',
name
});
}
function regroupTerms(terms, combinators) {
function createGroup(terms, combinator) {
return {
type: 'Group',
terms,
combinator,
disallowEmpty: false,
explicit: false
};
}
let combinator;
combinators = Object.keys(combinators)
.sort((a, b) => COMBINATOR_PRECEDENCE[a] - COMBINATOR_PRECEDENCE[b]);
while (combinators.length > 0) {
combinator = combinators.shift();
let i = 0;
let subgroupStart = 0;
for (; i < terms.length; i++) {
const term = terms[i];
if (term.type === 'Combinator') {
if (term.value === combinator) {
if (subgroupStart === -1) {
subgroupStart = i - 1;
}
terms.splice(i, 1);
i--;
} else {
if (subgroupStart !== -1 && i - subgroupStart > 1) {
terms.splice(
subgroupStart,
i - subgroupStart,
createGroup(terms.slice(subgroupStart, i), combinator)
);
i = subgroupStart + 1;
}
subgroupStart = -1;
}
}
}
if (subgroupStart !== -1 && combinators.length) {
terms.splice(
subgroupStart,
i - subgroupStart,
createGroup(terms.slice(subgroupStart, i), combinator)
);
}
}
return combinator;
}
function readImplicitGroup(scanner, stopCharCode) {
const combinators = Object.create(null);
const terms = [];
let token;
let prevToken = null;
let prevTokenPos = scanner.pos;
while (scanner.charCode() !== stopCharCode && (token = peek(scanner, stopCharCode))) {
if (token.type !== 'Spaces') {
if (token.type === 'Combinator') {
// check for combinator in group beginning and double combinator sequence
if (prevToken === null || prevToken.type === 'Combinator') {
scanner.pos = prevTokenPos;
scanner.error('Unexpected combinator');
}
combinators[token.value] = true;
} else if (prevToken !== null && prevToken.type !== 'Combinator') {
combinators[' '] = true; // a b
terms.push({
type: 'Combinator',
value: ' '
});
}
terms.push(token);
prevToken = token;
prevTokenPos = scanner.pos;
}
}
// check for combinator in group ending
if (prevToken !== null && prevToken.type === 'Combinator') {
scanner.pos -= prevTokenPos;
scanner.error('Unexpected combinator');
}
return {
type: 'Group',
terms,
combinator: regroupTerms(terms, combinators) || ' ',
disallowEmpty: false,
explicit: false
};
}
function readGroup(scanner, stopCharCode) {
let result;
scanner.eat(LEFTSQUAREBRACKET);
result = readImplicitGroup(scanner, stopCharCode);
scanner.eat(RIGHTSQUAREBRACKET);
result.explicit = true;
if (scanner.charCode() === EXCLAMATIONMARK) {
scanner.pos++;
result.disallowEmpty = true;
}
return result;
}
function peek(scanner, stopCharCode) {
let code = scanner.charCode();
switch (code) {
case RIGHTSQUAREBRACKET:
// don't eat, stop scan a group
break;
case LEFTSQUAREBRACKET:
return maybeMultiplied(scanner, readGroup(scanner, stopCharCode));
case LESSTHANSIGN:
return scanner.nextCharCode() === APOSTROPHE
? readProperty(scanner)
: readType(scanner);
case VERTICALLINE:
return {
type: 'Combinator',
value: scanner.substringToPos(
scanner.pos + (scanner.nextCharCode() === VERTICALLINE ? 2 : 1)
)
};
case AMPERSAND:
scanner.pos++;
scanner.eat(AMPERSAND);
return {
type: 'Combinator',
value: '&&'
};
case COMMA:
scanner.pos++;
return {
type: 'Comma'
};
case APOSTROPHE:
return maybeMultiplied(scanner, {
type: 'String',
value: scanner.scanString()
});
case SPACE:
case TAB:
case N:
case R:
case F:
return {
type: 'Spaces',
value: scanner.scanSpaces()
};
case COMMERCIALAT:
code = scanner.nextCharCode();
if (scanner.isNameCharCode(code)) {
scanner.pos++;
return {
type: 'AtKeyword',
name: scanner.scanWord()
};
}
return maybeToken(scanner);
case ASTERISK:
case PLUSSIGN:
case QUESTIONMARK:
case NUMBERSIGN:
case EXCLAMATIONMARK:
// prohibited tokens (used as a multiplier start)
break;
case LEFTCURLYBRACKET:
// LEFTCURLYBRACKET is allowed since mdn/data uses it w/o quoting
// check next char isn't a number, because it's likely a disjoined multiplier
code = scanner.nextCharCode();
if (code < 48 || code > 57) {
return maybeToken(scanner);
}
break;
default:
if (scanner.isNameCharCode(code)) {
return readKeywordOrFunction(scanner);
}
return maybeToken(scanner);
}
}
function parse(source) {
const scanner$1 = new scanner.Scanner(source);
const result = readImplicitGroup(scanner$1);
if (scanner$1.pos !== source.length) {
scanner$1.error('Unexpected input');
}
// reduce redundant groups with single group term
if (result.terms.length === 1 && result.terms[0].type === 'Group') {
return result.terms[0];
}
return result;
}
exports.parse = parse;

113
node_modules/css-tree/cjs/definition-syntax/scanner.cjs generated vendored Normal file
View File

@@ -0,0 +1,113 @@
'use strict';
const SyntaxError = require('./SyntaxError.cjs');
const TAB = 9;
const N = 10;
const F = 12;
const R = 13;
const SPACE = 32;
const NAME_CHAR = new Uint8Array(128).map((_, idx) =>
/[a-zA-Z0-9\-]/.test(String.fromCharCode(idx)) ? 1 : 0
);
class Scanner {
constructor(str) {
this.str = str;
this.pos = 0;
}
charCodeAt(pos) {
return pos < this.str.length ? this.str.charCodeAt(pos) : 0;
}
charCode() {
return this.charCodeAt(this.pos);
}
isNameCharCode(code = this.charCode()) {
return code < 128 && NAME_CHAR[code] === 1;
}
nextCharCode() {
return this.charCodeAt(this.pos + 1);
}
nextNonWsCode(pos) {
return this.charCodeAt(this.findWsEnd(pos));
}
skipWs() {
this.pos = this.findWsEnd(this.pos);
}
findWsEnd(pos) {
for (; pos < this.str.length; pos++) {
const code = this.str.charCodeAt(pos);
if (code !== R && code !== N && code !== F && code !== SPACE && code !== TAB) {
break;
}
}
return pos;
}
substringToPos(end) {
return this.str.substring(this.pos, this.pos = end);
}
eat(code) {
if (this.charCode() !== code) {
this.error('Expect `' + String.fromCharCode(code) + '`');
}
this.pos++;
}
peek() {
return this.pos < this.str.length ? this.str.charAt(this.pos++) : '';
}
error(message) {
throw new SyntaxError.SyntaxError(message, this.str, this.pos);
}
scanSpaces() {
return this.substringToPos(this.findWsEnd(this.pos));
}
scanWord() {
let end = this.pos;
for (; end < this.str.length; end++) {
const code = this.str.charCodeAt(end);
if (code >= 128 || NAME_CHAR[code] === 0) {
break;
}
}
if (this.pos === end) {
this.error('Expect a keyword');
}
return this.substringToPos(end);
}
scanNumber() {
let end = this.pos;
for (; end < this.str.length; end++) {
const code = this.str.charCodeAt(end);
if (code < 48 || code > 57) {
break;
}
}
if (this.pos === end) {
this.error('Expect a number');
}
return this.substringToPos(end);
}
scanString() {
const end = this.str.indexOf('\'', this.pos + 1);
if (end === -1) {
this.pos = this.str.length;
this.error('Expect an apostrophe');
}
return this.substringToPos(end + 1);
}
}
exports.Scanner = Scanner;

View File

@@ -0,0 +1,59 @@
'use strict';
const SyntaxError = require('./SyntaxError.cjs');
const TAB = 9;
const N = 10;
const F = 12;
const R = 13;
const SPACE = 32;
class Tokenizer {
constructor(str) {
this.str = str;
this.pos = 0;
}
charCodeAt(pos) {
return pos < this.str.length ? this.str.charCodeAt(pos) : 0;
}
charCode() {
return this.charCodeAt(this.pos);
}
nextCharCode() {
return this.charCodeAt(this.pos + 1);
}
nextNonWsCode(pos) {
return this.charCodeAt(this.findWsEnd(pos));
}
skipWs() {
this.pos = this.findWsEnd(this.pos);
}
findWsEnd(pos) {
for (; pos < this.str.length; pos++) {
const code = this.str.charCodeAt(pos);
if (code !== R && code !== N && code !== F && code !== SPACE && code !== TAB) {
break;
}
}
return pos;
}
substringToPos(end) {
return this.str.substring(this.pos, this.pos = end);
}
eat(code) {
if (this.charCode() !== code) {
this.error('Expect `' + String.fromCharCode(code) + '`');
}
this.pos++;
}
peek() {
return this.pos < this.str.length ? this.str.charAt(this.pos++) : '';
}
error(message) {
throw new SyntaxError.SyntaxError(message, this.str, this.pos);
}
}
exports.Tokenizer = Tokenizer;

57
node_modules/css-tree/cjs/definition-syntax/walk.cjs generated vendored Normal file
View File

@@ -0,0 +1,57 @@
'use strict';
const noop = function() {};
function ensureFunction(value) {
return typeof value === 'function' ? value : noop;
}
function walk(node, options, context) {
function walk(node) {
enter.call(context, node);
switch (node.type) {
case 'Group':
node.terms.forEach(walk);
break;
case 'Multiplier':
case 'Boolean':
walk(node.term);
break;
case 'Type':
case 'Property':
case 'Keyword':
case 'AtKeyword':
case 'Function':
case 'String':
case 'Token':
case 'Comma':
break;
default:
throw new Error('Unknown type: ' + node.type);
}
leave.call(context, node);
}
let enter = noop;
let leave = noop;
if (typeof options === 'function') {
enter = options;
} else if (options) {
enter = ensureFunction(options.enter);
leave = ensureFunction(options.leave);
}
if (enter === noop && leave === noop) {
throw new Error('Neither `enter` nor `leave` walker handler is set or both aren\'t a function');
}
walk(node);
}
exports.walk = walk;