You're Invited:Meet the Socket Team at BlackHat and DEF CON in Las Vegas, Aug 4-6.RSVP
Socket
Book a DemoInstallSign in
Socket

@tbela99/css-parser

Package Overview
Dependencies
Maintainers
1
Versions
31
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@tbela99/css-parser - npm Package Compare versions

Comparing version

to
0.9.1

37

dist/index.d.ts

@@ -94,2 +94,3 @@ declare enum EnumToken {

PseudoPageTokenType = 91,
PseudoElementTokenType = 92,
Time = 25,

@@ -133,3 +134,3 @@ Iden = 7,

*/
declare function minify(ast: AstNode, options?: ParserOptions | MinifyOptions, recursive?: boolean, errors?: ErrorDescription[], nestingContent?: boolean, context?: {
declare function minify(ast: AstNode, options?: ParserOptions | MinifyFeatureOptions, recursive?: boolean, errors?: ErrorDescription[], nestingContent?: boolean, context?: {
[key: string]: any;

@@ -522,2 +523,8 @@ }): AstNode;

export declare interface PseudoElementToken extends BaseToken {
typ: EnumToken.PseudoElementTokenType;
val: string;
}
export declare interface PseudoPageToken extends BaseToken {

@@ -818,2 +825,3 @@

| PseudoPageToken
| PseudoElementToken
| PseudoClassFunctionToken

@@ -1042,11 +1050,20 @@ | DelimToken

export declare interface ParserOptions extends ValidationOptions, PropertyListOptions {
interface MinifyOptions {
minify?: boolean;
nestingRules?: boolean;
expandNestingRules?: boolean;
removeDuplicateDeclarations?: boolean;
computeShorthand?: boolean;
computeCalcExpression?: boolean;
inlineCssVariables?: boolean;
removeEmpty?: boolean;
pass?: number;
}
export declare interface ParserOptions extends MinifyOptions, ValidationOptions, PropertyListOptions {
src?: string;
sourcemap?: boolean;
nestingRules?: boolean;
expandNestingRules?: boolean;
removeCharset?: boolean;
removeEmpty?: boolean;
resolveUrls?: boolean;

@@ -1056,7 +1073,3 @@ resolveImport?: boolean;

parseColor?: boolean;
removeDuplicateDeclarations?: boolean;
computeShorthand?: boolean;
removePrefix?: boolean;
inlineCssVariables?: boolean;
computeCalcExpression?: boolean;
load?: (url: string, currentUrl: string) => Promise<string>;

@@ -1073,3 +1086,3 @@ dirname?: (path: string) => string;

export declare interface MinifyOptions extends ParserOptions {
export declare interface MinifyFeatureOptions extends ParserOptions {

@@ -1083,3 +1096,3 @@ features: MinifyFeature[];

register(options: MinifyOptions | ParserOptions): void;
register(options: MinifyFeatureOptions | ParserOptions): void;

@@ -1094,3 +1107,3 @@ // run(ast: AstRule | AstAtRule, options: ParserOptions = {}, parent: AstRule | AstAtRule | AstRuleStyleSheet, context: { [key: string]: any }): void;

ordering: number;
register: (options: MinifyOptions | ParserOptions) => void;
register: (options: MinifyFeatureOptions | ParserOptions) => void;
run: (ast: AstRule | AstAtRule, options: ParserOptions, parent: AstRule | AstAtRule | AstRuleStyleSheet, context: {

@@ -1097,0 +1110,0 @@ [key: string]: any

@@ -72,3 +72,10 @@ import { splitRule, combinators } from './minify.js';

else {
selRule.forEach(arr => combinators.includes(arr[0].charAt(0)) ? arr.unshift(ast.sel) : arr.unshift(ast.sel, ' '));
// selRule = splitRule(selRule.reduce((acc, curr) => acc + (acc.length > 0 ? ',' : '') + curr.join(''), ''));
const arSelf = splitRule(ast.sel).filter((r) => r.every((t) => t != ':before' && t != ':after' && !t.startsWith('::'))).reduce((acc, curr) => acc.concat([curr.join('')]), []).join(',');
if (arSelf.length == 0) {
ast.chi.splice(i--, 1);
continue;
}
//
selRule.forEach(arr => combinators.includes(arr[0].charAt(0)) ? arr.unshift(arSelf) : arr.unshift(arSelf, ' '));
rule.sel = selRule.reduce((acc, curr) => {

@@ -84,4 +91,10 @@ acc.push(curr.join(''));

let withoutCompound = [];
const rules = splitRule(ast.sel);
// pseudo elements cannot be used with '&'
// https://www.w3.org/TR/css-nesting-1/#example-7145ff1e
const rules = splitRule(ast.sel).filter((r) => r.every((t) => t != ':before' && t != ':after' && !t.startsWith('::')));
const parentSelector = !node.sel.includes('&');
if (rules.length == 0) {
ast.chi.splice(i--, 1);
continue;
}
for (const sel of (rule.raw ?? splitRule(rule.sel))) {

@@ -88,0 +101,0 @@ const s = sel.join('');

@@ -230,3 +230,3 @@ import { parseString } from '../parser/parse.js';

// @ts-ignore
let sel = wrap ? node.optimized.optimized[0] + `:is(${rule})` : rule;
let sel = wrap ? node.optimized.optimized.join('') + `:is(${rule})` : rule;
if (rule.includes('&')) {

@@ -233,0 +233,0 @@ // @ts-ignore

@@ -104,2 +104,3 @@ var ValidationLevel;

EnumToken[EnumToken["PseudoPageTokenType"] = 91] = "PseudoPageTokenType";
EnumToken[EnumToken["PseudoElementTokenType"] = 92] = "PseudoElementTokenType";
/* aliases */

@@ -106,0 +107,0 @@ EnumToken[EnumToken["Time"] = 25] = "Time";

@@ -1,2 +0,2 @@

import { webkitPseudoAliasMap, isIdentStart, isIdent, mathFuncs, isColor, isHexColor, isPseudo, isAtKeyword, isFunction, isNumber, isPercentage, isFlex, isDimension, parseDimension, isHash, mediaTypes } from '../syntax/syntax.js';
import { webkitPseudoAliasMap, isIdentStart, isIdent, mathFuncs, isColor, isHexColor, isPseudo, pseudoElements, isAtKeyword, isFunction, isNumber, isPercentage, isFlex, isDimension, parseDimension, isHash, mediaTypes } from '../syntax/syntax.js';
import './utils/config.js';

@@ -49,2 +49,3 @@ import { EnumToken, funcLike, ValidationLevel } from '../ast/types.js';

minify: true,
pass: 1,
parseColor: true,

@@ -169,3 +170,3 @@ nestingRules: false,

if (context != null && context.typ == EnumToken.InvalidRuleTokenType) {
const index = context.chi.findIndex(node => node == context);
const index = context.chi.findIndex((node) => node == context);
if (index > -1) {

@@ -230,3 +231,6 @@ context.chi.splice(index, 1);

if (ast.chi.length > 0) {
minify(ast, options, true, errors, false);
let passes = options.pass ?? 1;
while (passes--) {
minify(ast, options, true, errors, false);
}
}

@@ -332,4 +336,9 @@ }

if (type != EnumToken.AtRuleNodeType) {
errors.push({ action: 'drop', message: 'invalid @import', location: { src, ...position } });
return null;
// @ts-ignore
if (!(type == EnumToken.InvalidAtRuleTokenType &&
// @ts-ignore
['charset', 'layer', 'import'].includes(context.chi[i].nam))) {
errors.push({ action: 'drop', message: 'invalid @import', location: { src, ...position } });
return null;
}
}

@@ -369,3 +378,3 @@ // @ts-ignore

tokens.shift();
if (tokens[1].typ == EnumToken.UrlTokenTokenType) {
if (tokens[0]?.typ == EnumToken.UrlTokenTokenType) {
// @ts-ignore

@@ -376,2 +385,10 @@ tokens[0].typ = EnumToken.StringTokenType;

}
// @ts-ignore
while (tokens[1]?.typ == EnumToken.WhitespaceTokenType || tokens[1]?.typ == EnumToken.CommentTokenType) {
tokens.splice(1, 1);
}
// @ts-ignore
if (tokens[1]?.typ == EnumToken.EndParensTokenType) {
tokens.splice(1, 1);
}
}

@@ -460,7 +477,7 @@ }

nam: renderToken(atRule, { removeComments: true }),
tokens: t,
// tokens: t,
val: raw.join('')
};
Object.defineProperties(node, {
tokens: { ...definedPropertySettings, enumerable: true, value: tokens.slice() },
tokens: { ...definedPropertySettings, enumerable: false, value: tokens.slice() },
raw: { ...definedPropertySettings, value: raw }

@@ -590,3 +607,3 @@ });

...definedPropertySettings,
enumerable: true,
enumerable: false,
value: tokens.slice()

@@ -692,3 +709,3 @@ });

//
// console.error({valid});
// // console.error({valid});
//

@@ -1065,6 +1082,12 @@ // if (valid.valid == ValidationLevel.Drop) {

}
: {
typ: EnumToken.PseudoClassTokenType,
: (
// https://www.w3.org/TR/selectors-4/#single-colon-pseudos
val.startsWith('::') || pseudoElements.includes(val) ? {
typ: EnumToken.PseudoElementTokenType,
val
};
} :
{
typ: EnumToken.PseudoClassTokenType,
val
});
}

@@ -1246,3 +1269,3 @@ if (isAtKeyword(val)) {

}
Object.assign(t, {
const attr = Object.assign(t, {
typ: inAttr == 0 ? EnumToken.AttrTokenType : EnumToken.InvalidAttrTokenType,

@@ -1252,16 +1275,16 @@ chi: tokens.splice(i + 1, k - i)

// @ts-ignore
if (t.chi.at(-1).typ == EnumToken.AttrEndTokenType) {
if (attr.chi.at(-1).typ == EnumToken.AttrEndTokenType) {
// @ts-ignore
t.chi.pop();
attr.chi.pop();
}
// @ts-ignore
if (t.chi.length > 1) {
if (attr.chi.length > 1) {
/*(<AttrToken>t).chi =*/
// @ts-ignore
parseTokens(t.chi, t.typ);
parseTokens(attr.chi, t.typ);
}
let m = t.chi.length;
let m = attr.chi.length;
let val;
for (m = 0; m < t.chi.length; m++) {
val = t.chi[m];
for (m = 0; m < attr.chi.length; m++) {
val = attr.chi[m];
if (val.typ == EnumToken.StringTokenType) {

@@ -1276,4 +1299,4 @@ const slice = val.val.slice(1, -1);

let lower = m;
while (++upper < t.chi.length) {
if (t.chi[upper].typ == EnumToken.CommentTokenType) {
while (++upper < attr.chi.length) {
if (attr.chi[upper].typ == EnumToken.CommentTokenType) {
continue;

@@ -1284,3 +1307,3 @@ }

while (lower-- > 0) {
if (t.chi[lower].typ == EnumToken.CommentTokenType) {
if (attr.chi[lower].typ == EnumToken.CommentTokenType) {
continue;

@@ -1291,10 +1314,10 @@ }

// @ts-ignore
t.chi[m] = {
attr.chi[m] = {
typ: EnumToken.NameSpaceAttributeTokenType,
l: t.chi[lower],
r: t.chi[upper]
l: attr.chi[lower],
r: attr.chi[upper]
};
t.chi.splice(upper, 1);
attr.chi.splice(upper, 1);
if (lower >= 0) {
t.chi.splice(lower, 1);
attr.chi.splice(lower, 1);
m--;

@@ -1305,7 +1328,7 @@ }

EnumToken.DashMatchTokenType, EnumToken.StartMatchTokenType, EnumToken.ContainMatchTokenType, EnumToken.EndMatchTokenType, EnumToken.IncludeMatchTokenType, EnumToken.DelimTokenType
].includes(t.chi[m].typ)) {
].includes(attr.chi[m].typ)) {
let upper = m;
let lower = m;
while (++upper < t.chi.length) {
if (t.chi[upper].typ == EnumToken.CommentTokenType) {
while (++upper < attr.chi.length) {
if (attr.chi[upper].typ == EnumToken.CommentTokenType) {
continue;

@@ -1316,3 +1339,3 @@ }

while (lower-- > 0) {
if (t.chi[lower].typ == EnumToken.CommentTokenType) {
if (attr.chi[lower].typ == EnumToken.CommentTokenType) {
continue;

@@ -1322,3 +1345,3 @@ }

}
val = t.chi[lower];
val = attr.chi[lower];
if (val.typ == EnumToken.StringTokenType) {

@@ -1330,3 +1353,3 @@ const slice = val.val.slice(1, -1);

}
val = t.chi[upper];
val = attr.chi[upper];
if (val.typ == EnumToken.StringTokenType) {

@@ -1451,3 +1474,5 @@ const slice = val.val.slice(1, -1);

t.kin = t.val;
// @ts-ignore
if (t.chi[0].typ == EnumToken.IdenTokenType) {
// @ts-ignore
if (t.chi[0].val == 'from') {

@@ -1462,6 +1487,7 @@ // @ts-ignore

}
else if (t.val == 'color') {
// @ts-ignore
t.cal = 'col';
// t.chi = t.chi.filter((t: Token) => [EnumToken.IdenTokenType, EnumToken.NumberTokenType, EnumToken.PercentageTokenType].includes(t.typ));
else { // @ts-ignore
if (t.val == 'color') {
// @ts-ignore
t.cal = 'col';
}
}

@@ -1500,3 +1526,3 @@ }

//
const count = t.chi.filter(t => t.typ != EnumToken.CommentTokenType).length;
const count = t.chi.filter((t) => t.typ != EnumToken.CommentTokenType).length;
if (count == 1 ||

@@ -1503,0 +1529,0 @@ (i == 0 &&

@@ -18,5 +18,5 @@ import { EnumToken } from '../../ast/types.js';

import { rec20202srgb, srgb2rec2020values } from './rec2020.js';
import { xyzd502srgb, srgb2xyz } from './xyz.js';
import { srgb2xyz } from './xyz.js';
import { p32srgbvalues, srgb2p3values } from './p3.js';
import { XYZ_D65_to_D50 } from './xyzd50.js';
import { xyzd502srgb, XYZ_D65_to_D50 } from './xyzd50.js';
import '../sourcemap/lib/encode.js';

@@ -23,0 +23,0 @@ import '../../parser/utils/config.js';

import { e, k, D50 } from './utils/constants.js';
import { getComponents } from './utils/components.js';
import { srgb2xyz, xyzd502srgb } from './xyz.js';
import { srgb2xyz } from './xyz.js';
import { oklch2srgb, hwb2srgb, hsl2srgb, rgb2srgb, hex2srgb } from './srgb.js';

@@ -12,2 +12,3 @@ import { getLCHComponents } from './lch.js';

import '../../parser/parse.js';
import { xyzd502srgb } from './xyzd50.js';
import '../sourcemap/lib/encode.js';

@@ -14,0 +15,0 @@ import '../../parser/utils/config.js';

@@ -1,3 +0,3 @@

import { srgb2xyz, xyzd502srgb } from './xyz.js';
import { XYZ_D65_to_D50 } from './xyzd50.js';
import { srgb2xyz } from './xyz.js';
import { XYZ_D65_to_D50, xyzd502srgb } from './xyzd50.js';

@@ -4,0 +4,0 @@ function prophotorgb2srgbvalues(r, g, b, a = null) {

@@ -1,3 +0,3 @@

import { srgb2xyz, xyzd502srgb } from './xyz.js';
import { XYZ_D65_to_D50 } from './xyzd50.js';
import { srgb2xyz } from './xyz.js';
import { XYZ_D65_to_D50, xyzd502srgb } from './xyzd50.js';

@@ -4,0 +4,0 @@ function prophotorgb2srgbvalues(r, g, b, a = null) {

@@ -7,22 +7,6 @@ import { multiplyMatrices } from './utils/matrix.js';

import '../../parser/parse.js';
import { srgb2lsrgbvalues, lsrgb2srgbvalues } from './srgb.js';
import { srgb2lsrgbvalues } from './srgb.js';
import '../sourcemap/lib/encode.js';
import '../../parser/utils/config.js';
function xyzd502srgb(x, y, z) {
// @ts-ignore
return lsrgb2srgbvalues(
/* r: */
x * 3.1341359569958707 -
y * 1.6173863321612538 -
0.4906619460083532 * z,
/* g: */
x * -0.978795502912089 +
y * 1.916254567259524 +
0.03344273116131949 * z,
/* b: */
x * 0.07195537988411677 -
y * 0.2289768264158322 +
1.405386058324125 * z);
}
function XYZ_to_lin_sRGB(x, y, z) {

@@ -67,2 +51,2 @@ // convert XYZ to linear-light sRGB

export { XYZ_D50_to_D65, XYZ_to_lin_sRGB, srgb2xyz, xyzd502srgb };
export { XYZ_D50_to_D65, XYZ_to_lin_sRGB, srgb2xyz };

@@ -0,1 +1,2 @@

import { lsrgb2srgbvalues } from './srgb.js';
import { multiplyMatrices } from './utils/matrix.js';

@@ -13,2 +14,4 @@ import './utils/constants.js';

/*
*/
function xyzd502lch(x, y, z, alpha) {

@@ -18,3 +21,2 @@ // @ts-ignore

// L in range [0,100]. For use in CSS, add a percent
// @ts-ignore
return lab2lchvalues(l, a, b, alpha);

@@ -36,3 +38,19 @@ }

}
function xyzd502srgb(x, y, z) {
// @ts-ignore
return lsrgb2srgbvalues(
/* r: */
x * 3.1341359569958707 -
y * 1.6173863321612538 -
0.4906619460083532 * z,
/* g: */
x * -0.978795502912089 +
y * 1.916254567259524 +
0.03344273116131949 * z,
/* b: */
x * 0.07195537988411677 -
y * 0.2289768264158322 +
1.405386058324125 * z);
}
export { XYZ_D65_to_D50, xyzd502lch };
export { XYZ_D65_to_D50, xyzd502lch, xyzd502srgb };

@@ -12,3 +12,3 @@ import { getAngle, color2srgbvalues, clamp } from './color/color.js';

import { SourceMap } from './sourcemap/sourcemap.js';
import { isColor, mathFuncs, isNewLine } from '../syntax/syntax.js';
import { isColor, pseudoElements, mathFuncs, isNewLine } from '../syntax/syntax.js';

@@ -593,4 +593,5 @@ const colorsFunc = ['rgb', 'rgba', 'hsl', 'hsla', 'hwb', 'device-cmyk', 'color-mix', 'color', 'oklab', 'lab', 'oklch', 'lch', 'light-dark'];

case EnumToken.PseudoClassTokenType:
case EnumToken.PseudoElementTokenType:
// https://www.w3.org/TR/selectors-4/#single-colon-pseudos
if (token.typ == EnumToken.PseudoClassTokenType && ['::before', '::after', '::first-line', '::first-letter'].includes(token.val)) {
if (token.typ == EnumToken.PseudoElementTokenType && pseudoElements.includes(token.val.slice(1))) {
return token.val.slice(1);

@@ -597,0 +598,0 @@ }

import { encode } from './lib/encode.js';
class SourceMap {
lastLocation = null;
#version = 3;

@@ -8,3 +9,2 @@ #sources = [];

#line = -1;
lastLocation = null;
add(source, original) {

@@ -11,0 +11,0 @@ if (original.src !== '') {

@@ -28,2 +28,3 @@ import { colorsFunc } from '../renderer/render.js';

const mathFuncs = ['calc', 'clamp', 'min', 'max', 'round', 'mod', 'rem', 'sin', 'cos', 'tan', 'asin', 'acos', 'atan', 'atan2', 'pow', 'sqrt', 'hypot', 'log', 'exp', 'abs', 'sign'];
const pseudoElements = [':before', ':after', ':first-line', ':first-letter'];
const webkitPseudoAliasMap = {

@@ -815,2 +816,2 @@ '-webkit-autofill': 'autofill',

export { colorFontTech, fontFeaturesTech, fontFormat, isAngle, isAtKeyword, isColor, isColorspace, isDigit, isDimension, isFlex, isFrequency, isFunction, isHash, isHexColor, isHueInterpolationMethod, isIdent, isIdentCodepoint, isIdentStart, isLength, isNewLine, isNonPrintable, isNumber, isPercentage, isPolarColorspace, isPseudo, isRectangularOrthogonalColorspace, isResolution, isTime, isWhiteSpace, mathFuncs, mediaTypes, mozExtensions, parseDimension, webkitExtensions, webkitPseudoAliasMap };
export { colorFontTech, fontFeaturesTech, fontFormat, isAngle, isAtKeyword, isColor, isColorspace, isDigit, isDimension, isFlex, isFrequency, isFunction, isHash, isHexColor, isHueInterpolationMethod, isIdent, isIdentCodepoint, isIdentStart, isLength, isNewLine, isNonPrintable, isNumber, isPercentage, isPolarColorspace, isPseudo, isRectangularOrthogonalColorspace, isResolution, isTime, isWhiteSpace, mathFuncs, mediaTypes, mozExtensions, parseDimension, pseudoElements, webkitExtensions, webkitPseudoAliasMap };

@@ -9,2 +9,3 @@ import { ValidationLevel, EnumToken } from '../../ast/types.js';

import { consumeWhitespace } from '../utils/whitespace.js';
import { splitTokenList } from '../utils/list.js';
import { validateURL } from '../syntaxes/url.js';

@@ -38,67 +39,46 @@

}
if (tokens[0].typ == EnumToken.CommaTokenType) {
for (const t of splitTokenList(tokens)) {
if (t.length != 1) {
return {
valid: ValidationLevel.Drop,
matches: [],
node: t[0] ?? atRule,
syntax: '@document',
error: 'unexpected token',
tokens
};
}
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0],
syntax: '@document',
error: 'unexpected token',
tokens
};
}
while (tokens.length > 0) {
if (tokens[0].typ == EnumToken.CommentTokenType) {
tokens.shift();
consumeWhitespace(tokens);
if ((t[0].typ != EnumToken.FunctionTokenType && t[0].typ != EnumToken.UrlFunctionTokenType) || !['url', 'url-prefix', 'domain', 'media-document', 'regexp'].some((f) => f.localeCompare(t[0].val, undefined, { sensitivity: 'base' }) == 0)) {
return {
valid: ValidationLevel.Drop,
matches: [],
node: t[0] ?? atRule,
syntax: '@document',
error: 'expecting any of url-prefix(), domain(), media-document(), regexp() but found ' + t[0].val,
tokens
};
}
result = validateURL(tokens[0]);
if (result.valid == ValidationLevel.Valid) {
tokens.shift();
consumeWhitespace(tokens);
if (t[0].typ == EnumToken.UrlFunctionTokenType) {
result = validateURL(t[0]);
if (result.valid == ValidationLevel.Drop) {
return result;
}
continue;
}
if (tokens[0].typ == EnumToken.FunctionTokenType) {
if (!['url-prefix', 'domain', 'media-document', 'regexp'].some((t) => t.localeCompare(tokens[0].val, undefined, { sensitivity: 'base' }) == 0)) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0],
syntax: '@document',
error: 'unexpected token',
tokens
};
}
const children = tokens[0].chi.slice();
consumeWhitespace(children);
if (children.length == 0) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0],
syntax: '@document',
error: 'expecting string argument',
tokens
};
}
if (children[0].typ == EnumToken.StringTokenType) {
children.shift();
consumeWhitespace(children);
}
if (children.length > 0) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: children[0],
syntax: '@document',
error: 'unexpected token',
tokens
};
}
tokens.shift();
consumeWhitespace(tokens);
const children = t[0].chi.slice();
consumeWhitespace(children);
if (children.length != 1 || (children[0].typ != EnumToken.StringTokenType && children[0].typ != EnumToken.UrlTokenTokenType)) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0],
syntax: '@document',
error: 'expecting string argument',
tokens
};
}
tokens.shift();
consumeWhitespace(tokens);
}

@@ -105,0 +85,0 @@ // @ts-ignore

@@ -8,3 +8,2 @@ import { ValidationLevel, EnumToken } from '../../ast/types.js';

import '../../parser/utils/config.js';
import { validateAtRuleSupports } from './supports.js';
import { validateAtRuleMediaQueryList } from './media.js';

@@ -17,2 +16,3 @@ import { consumeWhitespace } from '../utils/whitespace.js';

import '../config.js';
import { validateAtRuleSupportsConditions } from './supports.js';

@@ -87,2 +87,5 @@ function validateAtRuleImport(atRule, options, root) {

}
tokens.shift();
// @ts-ignore
consumeWhitespace(tokens);
}

@@ -123,68 +126,67 @@ else {

// @ts-ignore
if ('layer'.localeCompare(tokens[0].val, undefined, { sensitivity: 'base' }) != 0) {
if ('layer'.localeCompare(tokens[0].val, undefined, { sensitivity: 'base' }) == 0) {
const result = validateLayerName(tokens[0].chi);
if (result.valid == ValidationLevel.Drop) {
return result;
}
tokens.shift();
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0],
syntax: '@' + atRule.nam,
error: 'expecting layer()',
tokens
};
consumeWhitespace(tokens);
}
// @ts-ignore
const result = validateLayerName(tokens[0].chi);
if (result.valid == ValidationLevel.Drop) {
return result;
}
tokens.shift();
// @ts-ignore
if (!consumeWhitespace(tokens)) {
if ('supports'.localeCompare(tokens[0]?.val, undefined, { sensitivity: 'base' }) == 0) {
const result = validateAtRuleSupportsConditions(atRule, tokens[0].chi);
if (result.valid == ValidationLevel.Drop) {
return result;
}
tokens.shift();
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0],
syntax: '@' + atRule.nam,
error: 'expecting whitespace',
tokens
};
consumeWhitespace(tokens);
}
}
}
// if (tokens.length > 0) {
//
// // @ts-ignore
// if (tokens[0].typ == EnumToken.AtRuleTokenType) {
//
// if ((tokens[0] as AstAtRule).nam != 'supports') {
//
// // @ts-ignore
// return {
// valid: ValidationLevel.Drop,
// matches: [],
// node: tokens[0],
// syntax: '@' + atRule.nam,
// error: 'expecting @supports or media query list',
// tokens
// }
// }
//
// // @ts-ignore
// const result: ValidationSyntaxResult = validateAtRuleSupports(tokens[0] as AstAtRule, options, atRule);
//
// if (result.valid == ValidationLevel.Drop) {
//
// return result;
// }
//
// tokens.shift();
//
// // @ts-ignore
// if (!consumeWhitespace(tokens)) {
//
// // @ts-ignore
// return {
// valid: ValidationLevel.Drop,
// matches: [],
// node: tokens[0],
// syntax: '@' + atRule.nam,
// error: 'expecting whitespace',
// tokens
// }
// }
// }
// }
if (tokens.length > 0) {
// @ts-ignore
if (tokens[0].typ == EnumToken.AtRuleTokenType) {
if (tokens[0].nam != 'supports') {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0],
syntax: '@' + atRule.nam,
error: 'expecting @supports or media query list',
tokens
};
}
// @ts-ignore
const result = validateAtRuleSupports(tokens[0]);
if (result.valid == ValidationLevel.Drop) {
return result;
}
tokens.shift();
// @ts-ignore
if (!consumeWhitespace(tokens)) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: [],
node: tokens[0],
syntax: '@' + atRule.nam,
error: 'expecting whitespace',
tokens
};
}
}
}
if (tokens.length > 0) {
return validateAtRuleMediaQueryList(tokens, atRule);

@@ -191,0 +193,0 @@ }

@@ -228,3 +228,3 @@ import { ValidationLevel, EnumToken } from '../../ast/types.js';

}
if (token.typ != EnumToken.ParensTokenType && !(['when', 'else'].includes(atRule.nam) && token.typ == EnumToken.FunctionTokenType && ['media', 'supports'].includes(token.val))) {
if (token.typ != EnumToken.ParensTokenType && !(['when', 'else', 'import'].includes(atRule.nam) && token.typ == EnumToken.FunctionTokenType && ['media', 'supports', 'selector'].includes(token.val))) {
return false;

@@ -245,2 +245,3 @@ }

}
console.error(chi[0].parent);
return false;

@@ -247,0 +248,0 @@ }

import { ValidationLevel, EnumToken } from '../../ast/types.js';
import '../../ast/minify.js';
import '../../ast/walk.js';
import '../../parser/parse.js';
import { parseSelector } from '../../parser/parse.js';
import { colorFontTech, fontFeaturesTech, fontFormat } from '../../syntax/syntax.js';

@@ -11,4 +11,3 @@ import '../../parser/utils/config.js';

import { splitTokenList } from '../utils/list.js';
import { validateSyntax } from '../syntax.js';
import { getParsedSyntax } from '../config.js';
import { validateComplexSelector } from '../syntaxes/complex-selector.js';

@@ -57,2 +56,3 @@ function validateAtRuleSupports(atRule, options, root) {

function validateAtRuleSupportsConditions(atRule, tokenList) {
let result = null;
for (const tokens of splitTokenList(tokenList)) {

@@ -71,7 +71,6 @@ if (tokens.length == 0) {

let previousToken = null;
let result = null;
while (tokens.length > 0) {
result = validateSupportCondition(atRule, tokens[0]);
// supports-condition
if (result == null || result.valid == ValidationLevel.Valid) {
if (result.valid == ValidationLevel.Valid) {
previousToken = tokens[0];

@@ -82,3 +81,3 @@ tokens.shift();

result = validateSupportFeature(tokens[0]);
if (result == null || result.valid == ValidationLevel.Valid) {
if ( /*result == null || */result.valid == ValidationLevel.Valid) {
previousToken = tokens[0];

@@ -88,3 +87,28 @@ tokens.shift();

else {
return result;
if (tokens[0].typ == EnumToken.ParensTokenType) {
result = validateAtRuleSupportsConditions(atRule, tokens[0].chi);
if ( /* result == null || */result.valid == ValidationLevel.Valid) {
previousToken = tokens[0];
tokens.shift();
// continue;
}
else {
return result;
}
}
else {
return result;
}
// if (result!= null && result.valid == ValidationLevel.Drop) {
//
// return {
// valid: ValidationLevel.Drop,
// matches: [],
// node: tokens[0] ?? atRule,
// syntax: '@' + atRule.nam,
// // @ts-ignore
// error: result.error as string ?? 'unexpected token',
// tokens: []
// };
// }
}

@@ -144,3 +168,10 @@ }

}
return null;
return {
valid: ValidationLevel.Valid,
matches: [],
node: atRule,
syntax: '@' + atRule.nam,
error: '',
tokens: []
};
}

@@ -212,3 +243,3 @@ function validateSupportCondition(atRule, token) {

if (token.val.localeCompare('selector', undefined, { sensitivity: 'base' }) == 0) {
return validateSyntax(getParsedSyntax("syntaxes" /* ValidationSyntaxGroupEnum.Syntaxes */, 'complex-selector'), token.chi);
return validateComplexSelector(parseSelector(token.chi));
}

@@ -215,0 +246,0 @@ if (token.val.localeCompare('font-tech', undefined, { sensitivity: 'base' }) == 0) {

@@ -8,3 +8,3 @@ import { EnumToken, ValidationLevel } from '../ast/types.js';

import '../parser/utils/config.js';
import { getParsedSyntax, getSyntaxConfig } from './config.js';
import { getSyntaxConfig, getParsedSyntax } from './config.js';
import { validateSyntax } from './syntax.js';

@@ -27,3 +27,2 @@

const syntax = getParsedSyntax("atRules" /* ValidationSyntaxGroupEnum.AtRules */, '@' + root.nam)?.[0];
// console.error({syntax});
if (syntax != null) {

@@ -57,3 +56,3 @@ if (!('chi' in syntax)) {

syntax: `<${declaration.nam}>`,
error: ` declaration <${declaration.nam}> is not allowed in <@${root.nam}>`
error: `declaration <${declaration.nam}> is not allowed in <@${root.nam}>`
};

@@ -95,9 +94,2 @@ }

}
// return {
//
// valid: ValidationLevel.Valid,
// node: declaration,
// syntax: null,
// error: ''
// }
return validateSyntax(getParsedSyntax("declarations" /* ValidationSyntaxGroupEnum.Declarations */, name), declaration.val);

@@ -104,0 +96,0 @@ }

@@ -952,96 +952,2 @@ import { ValidationTokenEnum } from './types.js';

}
function renderSyntax(token, parent) {
let glue;
switch (token.typ) {
case ValidationTokenEnum.Root:
return token.chi.reduce((acc, curr) => acc + renderSyntax(curr), '');
case ValidationTokenEnum.Whitespace:
return ' ';
case ValidationTokenEnum.ValidationFunctionDefinition:
return '<' + token.val + '()>';
case ValidationTokenEnum.HashMark:
return '#';
case ValidationTokenEnum.Pipe:
return '|';
case ValidationTokenEnum.Column:
return '||';
case ValidationTokenEnum.PipeToken:
return token.chi.reduce((acc, curr) => acc + (acc.trim().length > 0 ? '|' : '') + curr.reduce((acc, curr) => acc + renderSyntax(curr), ''), '');
case ValidationTokenEnum.ColumnToken:
case ValidationTokenEnum.AmpersandToken:
glue = token.typ == ValidationTokenEnum.ColumnToken ? '||' : '&&';
return token.l.reduce((acc, curr) => acc + renderSyntax(curr), '') +
glue +
token.r.reduce((acc, curr) => acc + renderSyntax(curr), '');
case ValidationTokenEnum.Function:
case ValidationTokenEnum.PseudoClassFunctionToken:
case ValidationTokenEnum.Parens:
return token.val + '(' + token.chi.reduce((acc, curr) => acc + renderSyntax(curr), '') + ')' + renderAttributes(token);
case ValidationTokenEnum.Comma:
return ',';
case ValidationTokenEnum.Keyword:
return token.val + renderAttributes(token);
case ValidationTokenEnum.OpenBracket:
return '[';
case ValidationTokenEnum.Ampersand:
return '&&';
case ValidationTokenEnum.QuestionMark:
return '?';
case ValidationTokenEnum.Separator:
return '/';
case ValidationTokenEnum.Bracket:
return '[' + token.chi.reduce((acc, curr) => acc + renderSyntax(curr), '') + ']' + renderAttributes(token);
case ValidationTokenEnum.PropertyType:
return '<' + token.val + '>' + renderAttributes(token);
case ValidationTokenEnum.DeclarationType:
return "<'" + token.val + "'>" + renderAttributes(token);
case ValidationTokenEnum.Number:
case ValidationTokenEnum.PseudoClassToken:
case ValidationTokenEnum.StringToken:
return token.val + '';
case ValidationTokenEnum.SemiColon:
return ';';
case ValidationTokenEnum.AtRule:
return '@' + token.val;
case ValidationTokenEnum.AtRuleDefinition:
return '@' + token.val +
(token.prelude == null ? '' : ' ' + token.prelude.reduce((acc, curr) => acc + renderSyntax(curr), '')) +
(token.chi == null ? '' : ' {\n' + token.chi.reduce((acc, curr) => acc + renderSyntax(curr), '')).slice(1, -1) + '\n}';
case ValidationTokenEnum.Block:
return '{' + token.chi.reduce((acc, t) => acc + renderSyntax(t), '') + '}';
case ValidationTokenEnum.DeclarationDefinitionToken:
return token.nam + ': ' + renderSyntax(token.val);
case ValidationTokenEnum.ColumnArrayToken:
return token.chi.reduce((acc, curr) => acc + (acc.trim().length > 0 ? '||' : '') + renderSyntax(curr), '');
default:
throw new Error('Unhandled token: ' + JSON.stringify({ token }));
}
}
function renderAttributes(token) {
let result = '';
if (token.isList) {
result += '#';
}
if (token.isOptional) {
result += '?';
}
if (token.isRepeatableGroup) {
result += '!';
}
if (token.isRepeatable) {
result += '*';
}
if (token.atLeastOnce) {
result += '+';
}
if (token.occurence != null) {
if (token.occurence.max == 0 || token.occurence.max == token.occurence.min || Number.isNaN(token.occurence.max)) {
result += '{' + token.occurence.min + '}';
}
else {
result += '{' + token.occurence.min + ',' + token.occurence.max + '}';
}
}
return result;
}
function minify(ast) {

@@ -1147,2 +1053,2 @@ if (Array.isArray(ast)) {

export { WalkValidationTokenEnum, WalkValidationTokenKeyTypeEnum, parseSyntax, renderSyntax, walkValidationToken };
export { WalkValidationTokenEnum, WalkValidationTokenKeyTypeEnum, parseSyntax, walkValidationToken };

@@ -1,2 +0,1 @@

const specialValues = ['inherit', 'initial', 'unset', 'revert', 'revert-layer'];
var ValidationTokenEnum;

@@ -55,2 +54,2 @@ (function (ValidationTokenEnum) {

export { ValidationSyntaxGroupEnum, ValidationTokenEnum, specialValues };
export { ValidationSyntaxGroupEnum, ValidationTokenEnum };

@@ -9,4 +9,3 @@ import { ValidationTokenEnum, specialValues } from './parser/types.js';

import '../parser/utils/config.js';
import '../renderer/color/utils/constants.js';
import '../renderer/sourcemap/lib/encode.js';
import { renderToken } from '../renderer/render.js';
import { getSyntaxConfig, getParsedSyntax } from './config.js';

@@ -37,5 +36,5 @@ import { validateSelector } from './selector.js';

console.error(JSON.stringify({
syntax: syntaxes.reduce((acc, curr) => acc + renderSyntax(curr), ''),
syntaxes,
tokens,
syntax: syntaxes?.reduce?.((acc, curr) => acc + renderSyntax(curr), ''),
// syntaxes,
tokens: tokens.reduce((acc, curr) => acc + renderToken(curr), ''),
s: new Error('bar').stack

@@ -1396,2 +1395,37 @@ }, null, 1));

break;
case ValidationTokenEnum.ColumnArrayToken:
{
matches = [];
queue = [];
const children = syntax.chi;
let child;
while (child = children.shift()) {
result = validateSyntax([child], tokens, root, options, context);
if (result.valid == ValidationLevel.Valid) {
matches.push(child);
consumeToken(tokens);
token = tokens[0];
if (queue.length > 0) {
children.unshift(...queue);
queue = [];
}
if (token == null) {
break;
}
}
else {
queue.push(child);
}
}
valid = matches.length > 0;
result = {
valid: valid ? ValidationLevel.Valid : ValidationLevel.Drop,
matches: valid ? [token] : [],
node: valid ? null : token,
syntax,
error: valid ? '' : 'expecting token',
tokens
};
}
break;
case ValidationTokenEnum.ColumnToken:

@@ -1398,0 +1432,0 @@ children = [...syntax.l.slice(), ...syntax.r.slice()];

@@ -83,4 +83,4 @@ import { ValidationLevel, EnumToken } from '../../ast/types.js';

}
while (tokens.length > 0 && tokens[0].typ == EnumToken.PseudoClassTokenType) {
const isPseudoElement = tokens[0].val.startsWith('::');
while (tokens.length > 0 && (tokens[0].typ == EnumToken.PseudoElementTokenType || tokens[0].typ == EnumToken.PseudoClassTokenType)) {
const isPseudoElement = tokens[0].typ == EnumToken.PseudoElementTokenType;
if (

@@ -87,0 +87,0 @@ // https://developer.mozilla.org/en-US/docs/Web/CSS/WebKit_Extensions#pseudo-elements

@@ -18,3 +18,3 @@ import { EnumToken, ValidationLevel } from '../../ast/types.js';

return acc;
}, [[]]).slice(1);
}, [[]]);
for (let i = 0; i < slice.length; i++) {

@@ -32,15 +32,4 @@ if (slice[i].length == 0) {

}
if (slice[i][0].typ != EnumToken.IdenTokenType) {
// @ts-ignore
return {
valid: ValidationLevel.Drop,
matches: tokens,
node: slice[i][0],
syntax: 'ident',
error: 'expecting ident',
tokens
};
}
for (let j = 1; j < slice[i].length; j++) {
if (slice[i][j].typ != EnumToken.ClassSelectorTokenType) {
for (let j = 0; j < slice[i].length; j++) {
if (slice[i][j].typ != EnumToken.IdenTokenType && slice[i][j].typ != EnumToken.ClassSelectorTokenType) {
// @ts-ignore

@@ -51,4 +40,4 @@ return {

node: slice[i][j],
syntax: 'layer-name',
error: 'expecting class selector',
syntax: '<layer-name>',
error: 'expecting ident or class selector',
tokens

@@ -55,0 +44,0 @@ };

{
"name": "@tbela99/css-parser",
"description": "CSS parser for node and the browser",
"version": "v0.9.0",
"version": "v0.9.1",
"exports": {
".": "./dist/node/index.js",
"./node": "./dist/node/index.js",
"./umd": "./dist/index-umd-web.js",

@@ -20,4 +21,4 @@ "./web": "./dist/web/index.js",

"test:node": "mocha --reporter-options='maxDiffSize=1801920' \"test/**/node.spec.js\"",
"test:cov": "c8 --reporter=html --reporter=text --reporter=json-summary mocha --reporter-options='maxDiffSize=1801920' \"test/**/node.spec.js\"",
"test:web-cov": "web-test-runner \"test/**/web.spec.js\" --node-resolve --playwright --browsers chromium firefox webkit --root-dir=. --coverage",
"test:cov": "c8 -x dist/lib/validation/syntax.js -x 'dist/lib/validation/parser/*.js' --reporter=html --reporter=text --reporter=json-summary mocha --reporter-options='maxDiffSize=1801920' \"test/**/node.spec.js\"",
"test:web-cov": "web-test-runner -x dist/lib/validation/syntax.js,dist/lib/validation/parser \"test/**/web.spec.js\" --node-resolve --playwright --browsers chromium firefox webkit --root-dir=. --coverage",
"profile": "node --enable-source-maps --inspect-brk test/inspect.js",

@@ -24,0 +25,0 @@ "syntax-update": "esno tools/validation.ts",

[![playground](https://img.shields.io/badge/playground-try%20it%20now-%230a7398
)](https://tbela99.github.io/css-parser/playground/) [![npm](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fraw.githubusercontent.com%2Ftbela99%2Fcss-parser%2Fmaster%2Fpackage.json&query=version&logo=npm&label=npm&link=https%3A%2F%2Fwww.npmjs.com%2Fpackage%2F%40tbela99%2Fcss-parser)](https://www.npmjs.com/package/@tbela99/css-parser) [![npm](https://img.shields.io/jsr/v/%40tbela99/css-parser?link=https%3A%2F%2Fjsr.io%2F%40tbela99%2Fcss-parser
)](https://jsr.io/@tbela99/css-parser) [![cov](https://tbela99.github.io/css-parser/badges/coverage.svg)](https://github.com/tbela99/css-parser/actions) [![NPM Downloads](https://img.shields.io/npm/dm/%40tbela99%2Fcss-parser)](https://www.npmjs.com/package/@tbela99/css-parser)
)](https://jsr.io/@tbela99/css-parser) [![cov](https://tbela99.github.io/css-parser/badges/coverage.svg)](https://github.com/tbela99/css-parser/actions) [![NPM Downloads](https://img.shields.io/npm/dm/%40tbela99%2Fcss-parser)](https://www.npmjs.com/package/@tbela99/css-parser) [![bundle size](https://img.shields.io/bundlejs/size/%40tbela99/css-parser%400.9.0?exports=cjs)](https://www.npmjs.com/package/@tbela99/css-parser)

@@ -68,3 +68,3 @@ # css-parser

import {transform} from 'npm:@tbela99/css-parser';
import {transform} from '@tbela99/css-parser';

@@ -100,3 +100,3 @@ // ...

import {transform} from 'https://esm.sh/@tbela99/css-parser@0.4.0/web';
import {transform} from 'https://esm.sh/@tbela99/css-parser@0.9.0/web';

@@ -159,2 +159,3 @@

- minify: boolean, optional. default to _true_. optimize ast.
- pass: number, optional. minification pass. default to 1
- nestingRules: boolean, optional. automatically generated nested rules.

@@ -706,3 +707,5 @@ - expandNestingRules: boolean, optional. convert nesting rules into separate rules. will automatically set nestingRules

- [x] reduce calc()
- [x] evaluate math functions calc(), clamp(), min(), max(), round(), mod(), rem(), sin(), cos(), tan(), asin(),
acos(), atan(), atan2(), pow(), sqrt(), hypot(), log(), exp(), abs(), sign()
- [x] multi-pass minification
- [x] inline css variables

@@ -823,3 +826,3 @@ - [x] merge identical rules

import {AstDeclaration, LengthToken, ParserOptions} from "../src/@types";
import {EnumToken, EnumToken} from "../src/lib";
import {EnumToken} from "../src/lib";
import {transform} from "../src/node";

@@ -826,0 +829,0 @@

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display