Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

# v0.9.0

validation
- [x] validate invalid pseudo classes
- [x] rewrite selector validation
- [ ] lenient mode that preserves
- [ ] unknown at-rules
- [ ] unknown declarations
- [ ] unknown pseudo classes

media query level 5
- [x] at-rule custom-media
- [x] at-rule when-else custom media
Expand Down
4,120 changes: 2,409 additions & 1,711 deletions dist/index-umd-web.js

Large diffs are not rendered by default.

4,120 changes: 2,409 additions & 1,711 deletions dist/index.cjs

Large diffs are not rendered by default.

43 changes: 43 additions & 0 deletions dist/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,15 @@ declare enum EnumToken {
TimelineFunction = 16
}

/**
* minify ast
* @param ast
* @param options
* @param recursive
* @param errors
* @param nestingContent
* @param context
*/
declare function minify(ast: AstNode, options?: ParserOptions | MinifyOptions, recursive?: boolean, errors?: ErrorDescription[], nestingContent?: boolean, context?: {
[key: string]: any;
}): AstNode;
Expand All @@ -128,22 +137,56 @@ declare enum WalkerValueEvent {
Enter = 0,
Leave = 1
}
/**
* walk ast nodes
* @param node
* @param filter
*/
declare function walk(node: AstNode, filter?: WalkerFilter): Generator<WalkResult>;
/**
* walk ast values
* @param values
* @param root
* @param filter
* @param reverse
*/
declare function walkValues(values: Token[], root?: AstNode | Token | null, filter?: WalkerValueFilter | {
event: WalkerValueEvent;
fn?: WalkerValueFilter;
type?: EnumToken | EnumToken[] | ((token: Token) => boolean);
}, reverse?: boolean): Generator<WalkAttributesResult>;

/**
* expand nested css ast
* @param ast
*/
declare function expand(ast: AstNode): AstNode;

/**
* render ast token
* @param token
* @param options
* @param cache
* @param reducer
* @param errors
*/
declare function renderToken(token: Token, options?: RenderOptions, cache?: {
[key: string]: any;
}, reducer?: (acc: string, curr: Token) => string, errors?: ErrorDescription[]): string;

/**
* parse string
* @param src
* @param options
*/
declare function parseString(src: string, options?: {
location: boolean;
}): Token[];
/**
* parse token list
* @param tokens
* @param options
*/
declare function parseTokens(tokens: Token[], options?: ParseTokenOptions): Token[];

export declare interface LiteralToken extends BaseToken {
Expand Down
17 changes: 15 additions & 2 deletions dist/lib/ast/expand.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import { renderToken } from '../renderer/render.js';
import '../renderer/color/utils/constants.js';
import '../parser/utils/config.js';

/**
* expand nested css ast
* @param ast
*/
function expand(ast) {
//
if (![EnumToken.RuleNodeType, EnumToken.StyleSheetNodeType, EnumToken.AtRuleNodeType].includes(ast.typ)) {
Expand Down Expand Up @@ -50,7 +54,7 @@ function expand(ast) {
}
return result;
}
function expandRule(node, parent) {
function expandRule(node) {
const ast = { ...node, chi: node.chi.slice() };
const result = [];
if (ast.typ == EnumToken.RuleNodeType) {
Expand Down Expand Up @@ -155,7 +159,11 @@ function expandRule(node, parent) {
if (astAtRule.val.includes('&')) {
astAtRule.val = replaceCompound(astAtRule.val, ast.sel);
}
astAtRule = expand(astAtRule);
/* astAtRule = <AstAtRule> */
const slice = astAtRule.chi.slice().filter(t => t.typ == EnumToken.RuleNodeType && t.sel.includes('&'));
if (slice.length > 0) {
expandRule({ ...node, chi: astAtRule.chi.slice() });
}
}
else {
// @ts-ignore
Expand Down Expand Up @@ -194,6 +202,11 @@ function expandRule(node, parent) {
// @ts-ignore
return ast.chi.length > 0 ? [ast].concat(result) : result;
}
/**
* replace compound selector
* @param input
* @param replace
*/
function replaceCompound(input, replace) {
const tokens = parseString(input);
let replacement = null;
Expand Down
2 changes: 1 addition & 1 deletion dist/lib/ast/math/expression.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { EnumToken } from '../types.js';
import { compute, rem } from './math.js';
import { rem, compute } from './math.js';
import { reduceNumber } from '../../renderer/render.js';
import { mathFuncs } from '../../syntax/syntax.js';

Expand Down
19 changes: 16 additions & 3 deletions dist/lib/ast/minify.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,26 @@ import { parseString } from '../parser/parse.js';
import { EnumToken } from './types.js';
import { walkValues } from './walk.js';
import { replaceCompound } from './expand.js';
import { isWhiteSpace, isIdent, isFunction, isIdentStart } from '../syntax/syntax.js';
import { isIdent, isFunction, isWhiteSpace, isIdentStart } from '../syntax/syntax.js';
import '../parser/utils/config.js';
import { eq } from '../parser/utils/eq.js';
import { renderToken, doRender } from '../renderer/render.js';
import { doRender, renderToken } from '../renderer/render.js';
import * as index from './features/index.js';

const combinators = ['+', '>', '~', '||', '|'];
const definedPropertySettings = { configurable: true, enumerable: false, writable: true };
const notEndingWith = ['(', '['].concat(combinators);
// @ts-ignore
const features = Object.values(index).sort((a, b) => a.ordering - b.ordering);
/**
* minify ast
* @param ast
* @param options
* @param recursive
* @param errors
* @param nestingContent
* @param context
*/
function minify(ast, options = {}, recursive = false, errors, nestingContent, context = {}) {
if (!('nodes' in context)) {
context.nodes = new Set;
Expand Down Expand Up @@ -510,6 +519,10 @@ function reduceSelector(selector) {
reducible: selector.every((selector) => !['>', '+', '~', '&'].includes(selector[0]))
};
}
/**
* split selector string
* @param buffer
*/
function splitRule(buffer) {
const result = [[]];
let str = '';
Expand Down Expand Up @@ -996,4 +1009,4 @@ function reduceRuleSelector(node) {
}
}

export { combinators, definedPropertySettings, hasDeclaration, matchSelectors, minify, reduceSelector, splitRule };
export { combinators, definedPropertySettings, minify, splitRule };
1 change: 1 addition & 0 deletions dist/lib/ast/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ var ValidationLevel;
(function (ValidationLevel) {
ValidationLevel[ValidationLevel["Valid"] = 0] = "Valid";
ValidationLevel[ValidationLevel["Drop"] = 1] = "Drop";
ValidationLevel[ValidationLevel["Lenient"] = 2] = "Lenient"; /* preserve unknown at-rules, declarations and pseudo-classes */
})(ValidationLevel || (ValidationLevel = {}));
var EnumToken;
(function (EnumToken) {
Expand Down
12 changes: 12 additions & 0 deletions dist/lib/ast/walk.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ var WalkerValueEvent;
WalkerValueEvent[WalkerValueEvent["Enter"] = 0] = "Enter";
WalkerValueEvent[WalkerValueEvent["Leave"] = 1] = "Leave";
})(WalkerValueEvent || (WalkerValueEvent = {}));
/**
* walk ast nodes
* @param node
* @param filter
*/
function* walk(node, filter) {
const parents = [node];
const root = node;
Expand Down Expand Up @@ -33,6 +38,13 @@ function* walk(node, filter) {
}
}
}
/**
* walk ast values
* @param values
* @param root
* @param filter
* @param reverse
*/
function* walkValues(values, root = null, filter, reverse) {
// const set = new Set<Token>();
const stack = values.slice();
Expand Down
111 changes: 59 additions & 52 deletions dist/lib/parser/declaration/map.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,55 +162,6 @@ class PropertyMap {
}
return this;
}
matchTypes(declaration) {
const patterns = this.pattern.slice();
const values = [...declaration.val];
let i;
let j;
const map = new Map;
for (i = 0; i < patterns.length; i++) {
for (j = 0; j < values.length; j++) {
if (!map.has(patterns[i])) {
// @ts-ignore
map.set(patterns[i], this.config.properties?.[patterns[i]]?.constraints?.mapping?.max ?? 1);
}
let count = map.get(patterns[i]);
if (count > 0 && matchType(values[j], this.config.properties[patterns[i]])) {
Object.defineProperty(values[j], 'propertyName', {
enumerable: false,
writable: true,
value: patterns[i]
});
map.set(patterns[i], --count);
values.splice(j--, 1);
}
}
}
if (this.config.set != null) {
for (const [key, val] of Object.entries(this.config.set)) {
if (map.has(key)) {
for (const v of val) {
// missing
if (map.get(v) == 1) {
let i = declaration.val.length;
while (i--) {
// @ts-ignore
if (declaration.val[i].propertyName == key) {
const val = { ...declaration.val[i] };
Object.defineProperty(val, 'propertyName', {
enumerable: false,
writable: true,
value: v
});
declaration.val.splice(i, 0, val, { typ: EnumToken.WhitespaceTokenType });
}
}
}
}
}
}
}
}
[Symbol.iterator]() {
let iterable;
let requiredCount = 0;
Expand Down Expand Up @@ -249,9 +200,15 @@ class PropertyMap {
// @ts-ignore
let typ = (EnumToken[this.config.separator?.typ] ?? EnumToken.CommaTokenType);
// @ts-ignore
const sep = this.config.separator == null ? null : { ...this.config.separator, typ: EnumToken[this.config.separator.typ] };
const sep = this.config.separator == null ? null : {
...this.config.separator,
typ: EnumToken[this.config.separator.typ]
};
// @ts-ignore
const separator = this.config.separator ? renderToken({ ...this.config.separator, typ: EnumToken[this.config.separator.typ] }) : ',';
const separator = this.config.separator ? renderToken({
...this.config.separator,
typ: EnumToken[this.config.separator.typ]
}) : ',';
this.matchTypes(declaration);
values.push(value);
for (i = 0; i < declaration.val.length; i++) {
Expand Down Expand Up @@ -446,7 +403,6 @@ class PropertyMap {
acc.push(curr);
return acc;
}, []);
// @todo remove renderToken call
if (props.default.includes(curr[1][i].reduce((acc, curr) => acc + renderToken(curr) + ' ', '').trimEnd())) {
if (!this.config.properties[curr[0]].required) {
continue;
Expand Down Expand Up @@ -544,6 +500,7 @@ class PropertyMap {
}
// @ts-ignore
if (values.length == 1 &&
// @ts-ignore
typeof values[0].val == 'string' &&
this.config.default.includes(values[0].val.toLowerCase()) &&
this.config.default[0] != values[0].val.toLowerCase()) {
Expand All @@ -562,6 +519,7 @@ class PropertyMap {
// @ts-ignore
next() {
let v = iterable.next();
// @ts-ignore
while (v.done || v.value instanceof PropertySet) {
if (v.value instanceof PropertySet) {
// @ts-ignore
Expand All @@ -584,6 +542,55 @@ class PropertyMap {
}
};
}
matchTypes(declaration) {
const patterns = this.pattern.slice();
const values = [...declaration.val];
let i;
let j;
const map = new Map;
for (i = 0; i < patterns.length; i++) {
for (j = 0; j < values.length; j++) {
if (!map.has(patterns[i])) {
// @ts-ignore
map.set(patterns[i], this.config.properties?.[patterns[i]]?.constraints?.mapping?.max ?? 1);
}
let count = map.get(patterns[i]);
if (count > 0 && matchType(values[j], this.config.properties[patterns[i]])) {
Object.defineProperty(values[j], 'propertyName', {
enumerable: false,
writable: true,
value: patterns[i]
});
map.set(patterns[i], --count);
values.splice(j--, 1);
}
}
}
if (this.config.set != null) {
for (const [key, val] of Object.entries(this.config.set)) {
if (map.has(key)) {
for (const v of val) {
// missing
if (map.get(v) == 1) {
let i = declaration.val.length;
while (i--) {
// @ts-ignore
if (declaration.val[i].propertyName == key) {
const val = { ...declaration.val[i] };
Object.defineProperty(val, 'propertyName', {
enumerable: false,
writable: true,
value: v
});
declaration.val.splice(i, 0, val, { typ: EnumToken.WhitespaceTokenType });
}
}
}
}
}
}
}
}
removeDefaults(map, value) {
for (const [key, val] of map) {
const config = this.config.properties[key];
Expand Down
12 changes: 0 additions & 12 deletions dist/lib/parser/declaration/set.js
Original file line number Diff line number Diff line change
Expand Up @@ -181,20 +181,8 @@ class PropertySet {
return acc;
}, [])
}][Symbol.iterator]();
// return {
// next() {
//
// return iterator.next();
// }
// }
}
return iterator;
// return {
// next() {
//
// return iterator.next();
// }
// }
}
}

Expand Down
Loading