feat: add new css parser - postcss (#1458)
* feat: add new css parser * make selectors change * selectors and tests * media changes * remove old css references * better variable name * use postcss and port tests * fix media test * inline plugins * fix failing multiline selector * correct test result * move tests to correct file * cleanup all tests * remove unused css-tree * update bundle * cleanup dependencies * revert config files to master * remove d.ts files * update snapshot * reset rebuilt test * apply fuzzy css matching * remove extra test * Fix imports * Newer versions of nswapi break rrdom-nodejs tests. Example: FAIL test/document-nodejs.test.ts > RRDocument for nodejs environment > RRDocument API > querySelectorAll TypeError: e[api] is not a function ❯ byTag ../../node_modules/nwsapi/src/nwsapi.js:390:37 ❯ Array.<anonymous> ../../node_modules/nwsapi/src/nwsapi.js:327:113 ❯ collect ../../node_modules/nwsapi/src/nwsapi.js:1578:32 ❯ Object._querySelectorAll [as select] ../../node_modules/nwsapi/src/nwsapi.js:1533:36 ❯ RRDocument.querySelectorAll src/document-nodejs.ts:96:24 * Migrate from jest to vitest * Order of selectors has changed with postcss * Remove unused eslint --------- Co-authored-by: Justin Halsall <Juice10@users.noreply.github.com>
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
*/
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { describe, it, beforeEach, expect } from 'vitest';
|
||||
import { describe, it, beforeEach, expect as _expect } from 'vitest';
|
||||
import {
|
||||
adaptCssForReplay,
|
||||
buildNodeWithSN,
|
||||
@@ -12,6 +12,30 @@ import {
|
||||
import { NodeType } from '../src/types';
|
||||
import { createMirror, Mirror } from '../src/utils';
|
||||
|
||||
const expect = _expect as unknown as {
|
||||
<T = unknown>(actual: T): {
|
||||
toMatchCss(expected: string): void;
|
||||
} & ReturnType<typeof _expect>;
|
||||
} & typeof _expect;
|
||||
|
||||
expect.extend({
|
||||
toMatchCss: function (received: string, expected: string) {
|
||||
const pass = normCss(received) === normCss(expected);
|
||||
const message: () => string = () =>
|
||||
pass
|
||||
? ''
|
||||
: `Received (${received}) is not the same as expected (${expected})`;
|
||||
return {
|
||||
message,
|
||||
pass,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
function normCss(cssText: string): string {
|
||||
return cssText.replace(/[\s;]/g, '');
|
||||
}
|
||||
|
||||
function getDuration(hrtime: [number, number]) {
|
||||
const [seconds, nanoseconds] = hrtime;
|
||||
return seconds * 1000 + nanoseconds / 1000000;
|
||||
@@ -86,19 +110,19 @@ describe('rebuild', function () {
|
||||
describe('add hover class to hover selector related rules', function () {
|
||||
it('will do nothing to css text without :hover', () => {
|
||||
const cssText = 'body { color: white }';
|
||||
expect(adaptCssForReplay(cssText, cache)).toEqual(cssText);
|
||||
expect(adaptCssForReplay(cssText, cache)).toMatchCss(cssText);
|
||||
});
|
||||
|
||||
it('can add hover class to css text', () => {
|
||||
const cssText = '.a:hover { color: white }';
|
||||
expect(adaptCssForReplay(cssText, cache)).toEqual(
|
||||
expect(adaptCssForReplay(cssText, cache)).toMatchCss(
|
||||
'.a:hover, .a.\\:hover { color: white }',
|
||||
);
|
||||
});
|
||||
|
||||
it('can correctly add hover when in middle of selector', () => {
|
||||
const cssText = 'ul li a:hover img { color: white }';
|
||||
expect(adaptCssForReplay(cssText, cache)).toEqual(
|
||||
expect(adaptCssForReplay(cssText, cache)).toMatchCss(
|
||||
'ul li a:hover img, ul li a.\\:hover img { color: white }',
|
||||
);
|
||||
});
|
||||
@@ -111,14 +135,15 @@ img,
|
||||
ul li.specified c:hover img {
|
||||
color: white
|
||||
}`;
|
||||
expect(adaptCssForReplay(cssText, cache)).toEqual(
|
||||
`ul li.specified a:hover img, ul li.specified a.\\:hover img,
|
||||
expect(adaptCssForReplay(cssText, cache)).toMatchCss(
|
||||
`ul li.specified a:hover img,
|
||||
ul li.multiline
|
||||
b:hover
|
||||
img, ul li.multiline
|
||||
b.\\:hover
|
||||
img,
|
||||
ul li.specified c:hover img, ul li.specified c.\\:hover img {
|
||||
ul li.specified c:hover img,
|
||||
ul li.specified a.\\:hover img,
|
||||
ul li.multiline b.\\:hover img,
|
||||
ul li.specified c.\\:hover img {
|
||||
color: white
|
||||
}`,
|
||||
);
|
||||
@@ -126,48 +151,48 @@ ul li.specified c:hover img, ul li.specified c.\\:hover img {
|
||||
|
||||
it('can add hover class within media query', () => {
|
||||
const cssText = '@media screen { .m:hover { color: white } }';
|
||||
expect(adaptCssForReplay(cssText, cache)).toEqual(
|
||||
expect(adaptCssForReplay(cssText, cache)).toMatchCss(
|
||||
'@media screen { .m:hover, .m.\\:hover { color: white } }',
|
||||
);
|
||||
});
|
||||
|
||||
it('can add hover class when there is multi selector', () => {
|
||||
const cssText = '.a, .b:hover, .c { color: white }';
|
||||
expect(adaptCssForReplay(cssText, cache)).toEqual(
|
||||
'.a, .b:hover, .b.\\:hover, .c { color: white }',
|
||||
expect(adaptCssForReplay(cssText, cache)).toMatchCss(
|
||||
'.a, .b:hover, .c, .b.\\:hover { color: white }',
|
||||
);
|
||||
});
|
||||
|
||||
it('can add hover class when there is a multi selector with the same prefix', () => {
|
||||
const cssText = '.a:hover, .a:hover::after { color: white }';
|
||||
expect(adaptCssForReplay(cssText, cache)).toEqual(
|
||||
'.a:hover, .a.\\:hover, .a:hover::after, .a.\\:hover::after { color: white }',
|
||||
expect(adaptCssForReplay(cssText, cache)).toMatchCss(
|
||||
'.a:hover, .a:hover::after, .a.\\:hover, .a.\\:hover::after { color: white }',
|
||||
);
|
||||
});
|
||||
|
||||
it('can add hover class when :hover is not the end of selector', () => {
|
||||
const cssText = 'div:hover::after { color: white }';
|
||||
expect(adaptCssForReplay(cssText, cache)).toEqual(
|
||||
expect(adaptCssForReplay(cssText, cache)).toMatchCss(
|
||||
'div:hover::after, div.\\:hover::after { color: white }',
|
||||
);
|
||||
});
|
||||
|
||||
it('can add hover class when the selector has multi :hover', () => {
|
||||
const cssText = 'a:hover b:hover { color: white }';
|
||||
expect(adaptCssForReplay(cssText, cache)).toEqual(
|
||||
expect(adaptCssForReplay(cssText, cache)).toMatchCss(
|
||||
'a:hover b:hover, a.\\:hover b.\\:hover { color: white }',
|
||||
);
|
||||
});
|
||||
|
||||
it('will ignore :hover in css value', () => {
|
||||
const cssText = '.a::after { content: ":hover" }';
|
||||
expect(adaptCssForReplay(cssText, cache)).toEqual(cssText);
|
||||
expect(adaptCssForReplay(cssText, cache)).toMatchCss(cssText);
|
||||
});
|
||||
|
||||
it('can adapt media rules to replay context', () => {
|
||||
const cssText =
|
||||
'@media only screen and (min-device-width : 1200px) { .a { width: 10px; }}';
|
||||
expect(adaptCssForReplay(cssText, cache)).toEqual(
|
||||
expect(adaptCssForReplay(cssText, cache)).toMatchCss(
|
||||
'@media only screen and (min-width : 1200px) { .a { width: 10px; }}',
|
||||
);
|
||||
});
|
||||
@@ -210,7 +235,7 @@ ul li.specified c:hover img, ul li.specified c.\\:hover img {
|
||||
// previously that part was being incorrectly consumed by the selector regex
|
||||
const should_not_modify =
|
||||
".tailwind :is(.before\\:content-\\[\\'\\'\\])::before { --tw-content: \":hover\"; content: var(--tw-content); }.tailwind :is(.\\[\\&\\>li\\]\\:before\\:content-\\[\\'-\\'\\] > li)::before { color: pink; }";
|
||||
expect(adaptCssForReplay(should_not_modify, cache)).toEqual(
|
||||
expect(adaptCssForReplay(should_not_modify, cache)).toMatchCss(
|
||||
should_not_modify,
|
||||
);
|
||||
});
|
||||
@@ -219,7 +244,7 @@ ul li.specified c:hover img, ul li.specified c.\\:hover img {
|
||||
// the ':hover' in the below is a decoy which is not part of the selector,
|
||||
const should_not_modify =
|
||||
'@import url("https://fonts.googleapis.com/css2?family=Rubik:ital,wght@0,400;0,500;0,700;1,400&display=:hover");';
|
||||
expect(adaptCssForReplay(should_not_modify, cache)).toEqual(
|
||||
expect(adaptCssForReplay(should_not_modify, cache)).toMatchCss(
|
||||
should_not_modify,
|
||||
);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user