|
93 | 93 | if (name.charAt(0) != '#') {
|
94 | 94 | return false;
|
95 | 95 | }
|
96 |
| - if (isIdent(name.charAt(1))) { |
97 |
| - return true; |
98 |
| - } |
99 |
| - return true; |
| 96 | + return isIdent(name.charAt(1)); |
100 | 97 | }
|
101 | 98 | function isNumber(name) {
|
102 | 99 | if (name.length == 0) {
|
|
1566 | 1563 | }
|
1567 | 1564 |
|
1568 | 1565 | function render(data, opt = {}) {
|
| 1566 | + const startTime = performance.now(); |
1569 | 1567 | const options = Object.assign(opt.minify ?? true ? {
|
1570 | 1568 | indent: '',
|
1571 | 1569 | newLine: '',
|
|
1584 | 1582 | }
|
1585 | 1583 | return acc + renderToken(curr, options);
|
1586 | 1584 | }
|
1587 |
| - return { code: doRender(data, options, reducer, 0) }; |
| 1585 | + return { code: doRender(data, options, reducer, 0), stats: { |
| 1586 | + total: `${(performance.now() - startTime).toFixed(2)}ms` |
| 1587 | + } }; |
1588 | 1588 | }
|
1589 | 1589 | // @ts-ignore
|
1590 | 1590 | function doRender(data, options, reducer, level = 0, indents = []) {
|
|
1613 | 1613 | case 'AtRule':
|
1614 | 1614 | case 'Rule':
|
1615 | 1615 | if (data.typ == 'AtRule' && !('chi' in data)) {
|
1616 |
| - return `${indent}@${data.nam} ${data.val};`; |
| 1616 | + return `${indent}@${data.nam}${data.val === '' ? '' : options.indent || ' '}${data.val};`; |
1617 | 1617 | }
|
1618 | 1618 | // @ts-ignore
|
1619 | 1619 | let children = data.chi.reduce((css, node) => {
|
|
1625 | 1625 | str = `${node.nam}:${options.indent}${node.val.reduce(reducer, '').trimEnd()};`;
|
1626 | 1626 | }
|
1627 | 1627 | else if (node.typ == 'AtRule' && !('chi' in node)) {
|
1628 |
| - str = `@${node.nam} ${node.val};`; |
| 1628 | + str = `${data.val === '' ? '' : options.indent || ' '}${data.val};`; |
1629 | 1629 | }
|
1630 | 1630 | else {
|
1631 | 1631 | str = doRender(node, options, reducer, level + 1, indents);
|
|
1642 | 1642 | children = children.slice(0, -1);
|
1643 | 1643 | }
|
1644 | 1644 | if (data.typ == 'AtRule') {
|
1645 |
| - return `@${data.nam}${data.val ? ' ' + data.val + options.indent : ''}{${options.newLine}` + (children === '' ? '' : indentSub + children + options.newLine) + indent + `}`; |
| 1645 | + return `@${data.nam}${data.val === '' ? '' : options.indent || ' '}${data.val}${options.indent}{${options.newLine}` + (children === '' ? '' : indentSub + children + options.newLine) + indent + `}`; |
1646 | 1646 | }
|
1647 | 1647 | return data.sel + `${options.indent}{${options.newLine}` + (children === '' ? '' : indentSub + children + options.newLine) + indent + `}`;
|
1648 | 1648 | }
|
|
1792 | 1792 | case 'Delim':
|
1793 | 1793 | return /* options.minify && 'Pseudo-class' == token.typ && '::' == token.val.slice(0, 2) ? token.val.slice(1) : */ token.val;
|
1794 | 1794 | }
|
1795 |
| - throw new Error(`unexpected token ${JSON.stringify(token, null, 1)}`); |
| 1795 | + console.error(`unexpected token ${JSON.stringify(token, null, 1)}`); |
| 1796 | + // throw new Error(`unexpected token ${JSON.stringify(token, null, 1)}`); |
| 1797 | + return ''; |
1796 | 1798 | }
|
1797 | 1799 |
|
1798 | 1800 | function eq(a, b) {
|
|
2581 | 2583 | // @ts-ignore
|
2582 | 2584 | return null;
|
2583 | 2585 | }
|
2584 |
| - return { result, node1: exchanged ? node2 : node1, node2: exchanged ? node2 : node2 }; |
| 2586 | + return { result, node1: exchanged ? node2 : node1, node2: exchanged ? node1 : node2 }; |
2585 | 2587 | }
|
2586 | 2588 | function matchSelectors(selector1, selector2, parentType) {
|
2587 | 2589 | let match = [[]];
|
|
2769 | 2771 | if (node.typ == 'AtRule' && node.nam == 'font-face') {
|
2770 | 2772 | continue;
|
2771 | 2773 | }
|
2772 |
| - if (node.typ == 'AtRule' && node.val == 'all') { |
| 2774 | + if (node.typ == 'AtRule') { |
| 2775 | + if (node.nam == 'media' && node.val == 'all') { |
| 2776 | + // @ts-ignore |
| 2777 | + ast.chi?.splice(i, 1, ...node.chi); |
| 2778 | + i--; |
| 2779 | + continue; |
| 2780 | + } |
| 2781 | + // console.debug({previous, node}); |
2773 | 2782 | // @ts-ignore
|
2774 |
| - ast.chi?.splice(i, 1, ...node.chi); |
2775 |
| - i--; |
2776 |
| - continue; |
| 2783 | + if (previous?.typ == 'AtRule' && |
| 2784 | + previous.nam == node.nam && |
| 2785 | + previous.val == node.val) { |
| 2786 | + if ('chi' in node) { |
| 2787 | + // @ts-ignore |
| 2788 | + previous.chi.push(...node.chi); |
| 2789 | + } |
| 2790 | + // else { |
| 2791 | + ast?.chi?.splice(i--, 1); |
| 2792 | + continue; |
| 2793 | + // } |
| 2794 | + } |
2777 | 2795 | }
|
2778 | 2796 | // @ts-ignore
|
2779 | 2797 | if (node.typ == 'Rule') {
|
|
3288 | 3306 | }
|
3289 | 3307 | buffer += quoteStr;
|
3290 | 3308 | while (value = peek()) {
|
3291 |
| - if (ind >= iterator.length) { |
3292 |
| - yield pushToken(buffer, hasNewLine ? 'Bad-string' : 'Unclosed-string'); |
3293 |
| - break; |
3294 |
| - } |
| 3309 | + // if (ind >= iterator.length) { |
| 3310 | + // |
| 3311 | + // yield pushToken(buffer, hasNewLine ? 'Bad-string' : 'Unclosed-string'); |
| 3312 | + // break; |
| 3313 | + // } |
3295 | 3314 | if (value == '\\') {
|
3296 | 3315 | const sequence = peek(6);
|
3297 | 3316 | let escapeSequence = '';
|
|
3314 | 3333 | // not hex or new line
|
3315 | 3334 | // @ts-ignore
|
3316 | 3335 | if (i == 1 && !isNewLine(codepoint)) {
|
3317 |
| - buffer += sequence[i]; |
| 3336 | + buffer += value + sequence[i]; |
3318 | 3337 | next(2);
|
3319 | 3338 | continue;
|
3320 | 3339 | }
|
|
3334 | 3353 | continue;
|
3335 | 3354 | }
|
3336 | 3355 | // buffer += value;
|
3337 |
| - if (ind >= iterator.length) { |
3338 |
| - // drop '\\' at the end |
3339 |
| - yield pushToken(buffer); |
3340 |
| - break; |
3341 |
| - } |
| 3356 | + // if (ind >= iterator.length) { |
| 3357 | + // |
| 3358 | + // // drop '\\' at the end |
| 3359 | + // yield pushToken(buffer); |
| 3360 | + // break; |
| 3361 | + // } |
3342 | 3362 | buffer += next(2);
|
3343 | 3363 | continue;
|
3344 | 3364 | }
|
|
3507 | 3527 | buffer = '';
|
3508 | 3528 | break;
|
3509 | 3529 | }
|
3510 |
| - buffer += value; |
| 3530 | + buffer += prev() + value; |
3511 | 3531 | break;
|
3512 | 3532 | case '"':
|
3513 | 3533 | case "'":
|
|
3709 | 3729 | * @param opt
|
3710 | 3730 | */
|
3711 | 3731 | async function parse$1(iterator, opt = {}) {
|
| 3732 | + const startTime = performance.now(); |
3712 | 3733 | const errors = [];
|
3713 | 3734 | const options = {
|
3714 | 3735 | src: '',
|
|
3847 | 3868 | src: options.resolve(url, options.src).absolute
|
3848 | 3869 | }));
|
3849 | 3870 | });
|
3850 |
| - bytesIn += root.bytesIn; |
| 3871 | + bytesIn += root.stats.bytesIn; |
3851 | 3872 | if (root.ast.chi.length > 0) {
|
3852 | 3873 | context.chi.push(...root.ast.chi);
|
3853 | 3874 | }
|
|
3893 | 3914 | // rule
|
3894 | 3915 | if (delim.typ == 'Block-start') {
|
3895 | 3916 | const position = map.get(tokens[0]);
|
3896 |
| - // if (context.typ == 'Rule') { |
3897 |
| - // |
3898 |
| - // if (tokens[0]?.typ == 'Iden') { |
3899 |
| - // errors.push({action: 'drop', message: 'invalid nesting rule', location: {src, ...position}}); |
3900 |
| - // return null; |
3901 |
| - // } |
3902 |
| - // } |
3903 | 3917 | const uniq = new Map;
|
3904 | 3918 | parseTokens(tokens, { minify: options.minify }).reduce((acc, curr, index, array) => {
|
3905 | 3919 | if (curr.typ == 'Whitespace') {
|
|
4075 | 4089 | if (tokens.length > 0) {
|
4076 | 4090 | await parseNode(tokens);
|
4077 | 4091 | }
|
| 4092 | + const endParseTime = performance.now(); |
4078 | 4093 | if (options.minify) {
|
4079 | 4094 | if (ast.chi.length > 0) {
|
4080 | 4095 | minify(ast, options, true);
|
4081 | 4096 | }
|
4082 | 4097 | }
|
4083 |
| - return { ast, errors, bytesIn }; |
| 4098 | + const endTime = performance.now(); |
| 4099 | + return { |
| 4100 | + ast, errors, stats: { |
| 4101 | + bytesIn, |
| 4102 | + parse: `${(endParseTime - startTime).toFixed(2)}ms`, |
| 4103 | + minify: `${(endTime - endParseTime).toFixed(2)}ms`, |
| 4104 | + total: `${(endTime - startTime).toFixed(2)}ms` |
| 4105 | + } |
| 4106 | + }; |
4084 | 4107 | }
|
4085 | 4108 | function parseString(src, options = { location: false }) {
|
4086 | 4109 | return [...tokenize(src)].map(t => {
|
|
4431 | 4454 | async function transform$1(css, options = {}) {
|
4432 | 4455 | options = { minify: true, removeEmpty: true, ...options };
|
4433 | 4456 | const startTime = performance.now();
|
4434 |
| - const parseResult = await parse$1(css, options); |
4435 |
| - const renderTime = performance.now(); |
4436 |
| - const rendered = render(parseResult.ast, options); |
4437 |
| - const endTime = performance.now(); |
4438 |
| - return { |
4439 |
| - ...parseResult, ...rendered, stats: { |
4440 |
| - bytesIn: parseResult.bytesIn, |
4441 |
| - bytesOut: rendered.code.length, |
4442 |
| - parse: `${(renderTime - startTime).toFixed(2)}ms`, |
4443 |
| - render: `${(endTime - renderTime).toFixed(2)}ms`, |
4444 |
| - total: `${(endTime - startTime).toFixed(2)}ms` |
4445 |
| - } |
4446 |
| - }; |
| 4457 | + return parse$1(css, options).then((parseResult) => { |
| 4458 | + const rendered = render(parseResult.ast, options); |
| 4459 | + return { |
| 4460 | + ...parseResult, ...rendered, stats: { |
| 4461 | + bytesOut: rendered.code.length, |
| 4462 | + ...parseResult.stats, |
| 4463 | + render: rendered.stats.total, |
| 4464 | + total: `${(performance.now() - startTime).toFixed(2)}ms` |
| 4465 | + } |
| 4466 | + }; |
| 4467 | + }); |
4447 | 4468 | }
|
4448 | 4469 |
|
4449 | 4470 | const matchUrl = /^(https?:)?\/\//;
|
|
0 commit comments