Perf: don't run the regex replace unless the selectorText contains a colon (#1280)
* Perf: don't run the regex replace unless the selectorText contains a colon (rules generally contain colons) * Need to check type before querying selectorText property - also good as it means we only try to fix colons at the leaf level --------- Authored-by: eoghan murray <eoghan@getthere.ie>
This commit is contained in:
@@ -22,7 +22,6 @@ import {
|
|||||||
stringifyStylesheet,
|
stringifyStylesheet,
|
||||||
getInputType,
|
getInputType,
|
||||||
toLowerCase,
|
toLowerCase,
|
||||||
validateStringifiedCssRule,
|
|
||||||
} from './utils';
|
} from './utils';
|
||||||
|
|
||||||
let _id = 1;
|
let _id = 1;
|
||||||
|
|||||||
@@ -119,26 +119,29 @@ export function stringifyRule(rule: CSSRule): string {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
|
} else if (isCSSStyleRule(rule) && rule.selectorText.includes(':')) {
|
||||||
|
// Safari does not escape selectors with : properly
|
||||||
|
// see https://bugs.webkit.org/show_bug.cgi?id=184604
|
||||||
|
return fixSafariColons(rule.cssText);
|
||||||
}
|
}
|
||||||
|
|
||||||
return validateStringifiedCssRule(importStringified || rule.cssText);
|
return importStringified || rule.cssText;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function validateStringifiedCssRule(cssStringified: string): string {
|
export function fixSafariColons(cssStringified: string): string {
|
||||||
// Safari does not escape selectors with : properly
|
// Replace e.g. [aa:bb] with [aa\\:bb]
|
||||||
if (cssStringified.includes(':')) {
|
const regex = /(\[(?:[\w-]+)[^\\])(:(?:[\w-]+)\])/gm;
|
||||||
// Replace e.g. [aa:bb] with [aa\\:bb]
|
return cssStringified.replace(regex, '$1\\$2');
|
||||||
const regex = /(\[(?:[\w-]+)[^\\])(:(?:[\w-]+)\])/gm;
|
|
||||||
return cssStringified.replace(regex, '$1\\$2');
|
|
||||||
}
|
|
||||||
|
|
||||||
return cssStringified;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isCSSImportRule(rule: CSSRule): rule is CSSImportRule {
|
export function isCSSImportRule(rule: CSSRule): rule is CSSImportRule {
|
||||||
return 'styleSheet' in rule;
|
return 'styleSheet' in rule;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isCSSStyleRule(rule: CSSRule): rule is CSSStyleRule {
|
||||||
|
return 'selectorText' in rule;
|
||||||
|
}
|
||||||
|
|
||||||
export class Mirror implements IMirror<Node> {
|
export class Mirror implements IMirror<Node> {
|
||||||
private idNodeMap: idNodeMap = new Map();
|
private idNodeMap: idNodeMap = new Map();
|
||||||
private nodeMetaMap: nodeMetaMap = new WeakMap();
|
private nodeMetaMap: nodeMetaMap = new WeakMap();
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
import { parse, Rule, Media } from '../src/css';
|
import { parse, Rule, Media } from '../src/css';
|
||||||
import {
|
import { fixSafariColons, escapeImportStatement } from './../src/utils';
|
||||||
validateStringifiedCssRule,
|
|
||||||
escapeImportStatement,
|
|
||||||
} from './../src/utils';
|
|
||||||
|
|
||||||
describe('css parser', () => {
|
describe('css parser', () => {
|
||||||
it('should save the filename and source', () => {
|
it('should save the filename and source', () => {
|
||||||
@@ -112,15 +109,13 @@ describe('css parser', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('parses : in attribute selectors correctly', () => {
|
it('parses : in attribute selectors correctly', () => {
|
||||||
const out1 = validateStringifiedCssRule('[data-foo] { color: red; }');
|
const out1 = fixSafariColons('[data-foo] { color: red; }');
|
||||||
expect(out1).toEqual('[data-foo] { color: red; }');
|
expect(out1).toEqual('[data-foo] { color: red; }');
|
||||||
|
|
||||||
const out2 = validateStringifiedCssRule('[data-foo:other] { color: red; }');
|
const out2 = fixSafariColons('[data-foo:other] { color: red; }');
|
||||||
expect(out2).toEqual('[data-foo\\:other] { color: red; }');
|
expect(out2).toEqual('[data-foo\\:other] { color: red; }');
|
||||||
|
|
||||||
const out3 = validateStringifiedCssRule(
|
const out3 = fixSafariColons('[data-aa\\:other] { color: red; }');
|
||||||
'[data-aa\\:other] { color: red; }',
|
|
||||||
);
|
|
||||||
expect(out3).toEqual('[data-aa\\:other] { color: red; }');
|
expect(out3).toEqual('[data-aa\\:other] { color: red; }');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -5522,15 +5522,10 @@ csso@^4.0.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
css-tree "^1.1.2"
|
css-tree "^1.1.2"
|
||||||
|
|
||||||
cssom@^0.4.4, "cssom@https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz":
|
cssom@^0.4.4, cssom@^0.5.0, "cssom@https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz":
|
||||||
version "0.6.0"
|
version "0.6.0"
|
||||||
resolved "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz#ed298055b97cbddcdeb278f904857629dec5e0e1"
|
resolved "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz#ed298055b97cbddcdeb278f904857629dec5e0e1"
|
||||||
|
|
||||||
cssom@^0.5.0:
|
|
||||||
version "0.5.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.5.0.tgz#d254fa92cd8b6fbd83811b9fbaed34663cc17c36"
|
|
||||||
integrity sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==
|
|
||||||
|
|
||||||
cssom@~0.3.6:
|
cssom@~0.3.6:
|
||||||
version "0.3.8"
|
version "0.3.8"
|
||||||
resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a"
|
resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a"
|
||||||
|
|||||||
Reference in New Issue
Block a user