|
|
|
@ -25,6 +25,8 @@ const whitelist_attribute_selector = new Map([
|
|
|
|
['dialog', new Set(['open'])]
|
|
|
|
['dialog', new Set(['open'])]
|
|
|
|
]);
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const regex_is_single_css_selector = /[^\\],(?!([^([]+[^\\]|[^([\\])[)\]])/;
|
|
|
|
|
|
|
|
|
|
|
|
export default class Selector {
|
|
|
|
export default class Selector {
|
|
|
|
node: CssNode;
|
|
|
|
node: CssNode;
|
|
|
|
stylesheet: Stylesheet;
|
|
|
|
stylesheet: Stylesheet;
|
|
|
|
@ -157,7 +159,7 @@ export default class Selector {
|
|
|
|
for (const block of this.blocks) {
|
|
|
|
for (const block of this.blocks) {
|
|
|
|
for (const selector of block.selectors) {
|
|
|
|
for (const selector of block.selectors) {
|
|
|
|
if (selector.type === 'PseudoClassSelector' && selector.name === 'global') {
|
|
|
|
if (selector.type === 'PseudoClassSelector' && selector.name === 'global') {
|
|
|
|
if (/[^\\],(?!([^([]+[^\\]|[^([\\])[)\]])/.test(selector.children[0].value)) {
|
|
|
|
if (regex_is_single_css_selector.test(selector.children[0].value)) {
|
|
|
|
component.error(selector, compiler_errors.css_invalid_global_selector);
|
|
|
|
component.error(selector, compiler_errors.css_invalid_global_selector);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -338,6 +340,9 @@ function test_attribute(operator, expected_value, case_insensitive, value) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const regex_starts_with_whitespace = /^\s/;
|
|
|
|
|
|
|
|
const regex_ends_with_whitespace = /\s$/;
|
|
|
|
|
|
|
|
|
|
|
|
function attribute_matches(node: CssNode, name: string, expected_value: string, operator: string, case_insensitive: boolean) {
|
|
|
|
function attribute_matches(node: CssNode, name: string, expected_value: string, operator: string, case_insensitive: boolean) {
|
|
|
|
const spread = node.attributes.find(attr => attr.type === 'Spread');
|
|
|
|
const spread = node.attributes.find(attr => attr.type === 'Spread');
|
|
|
|
if (spread) return true;
|
|
|
|
if (spread) return true;
|
|
|
|
@ -373,7 +378,7 @@ function attribute_matches(node: CssNode, name: string, expected_value: string,
|
|
|
|
const start_with_space = [];
|
|
|
|
const start_with_space = [];
|
|
|
|
const remaining = [];
|
|
|
|
const remaining = [];
|
|
|
|
current_possible_values.forEach((current_possible_value: string) => {
|
|
|
|
current_possible_values.forEach((current_possible_value: string) => {
|
|
|
|
if (/^\s/.test(current_possible_value)) {
|
|
|
|
if (regex_starts_with_whitespace.test(current_possible_value)) {
|
|
|
|
start_with_space.push(current_possible_value);
|
|
|
|
start_with_space.push(current_possible_value);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
remaining.push(current_possible_value);
|
|
|
|
remaining.push(current_possible_value);
|
|
|
|
@ -394,7 +399,7 @@ function attribute_matches(node: CssNode, name: string, expected_value: string,
|
|
|
|
prev_values = combined;
|
|
|
|
prev_values = combined;
|
|
|
|
|
|
|
|
|
|
|
|
start_with_space.forEach((value: string) => {
|
|
|
|
start_with_space.forEach((value: string) => {
|
|
|
|
if (/\s$/.test(value)) {
|
|
|
|
if (regex_ends_with_whitespace.test(value)) {
|
|
|
|
possible_values.add(value);
|
|
|
|
possible_values.add(value);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
prev_values.push(value);
|
|
|
|
prev_values.push(value);
|
|
|
|
@ -408,7 +413,7 @@ function attribute_matches(node: CssNode, name: string, expected_value: string,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
current_possible_values.forEach((current_possible_value: string) => {
|
|
|
|
current_possible_values.forEach((current_possible_value: string) => {
|
|
|
|
if (/\s$/.test(current_possible_value)) {
|
|
|
|
if (regex_ends_with_whitespace.test(current_possible_value)) {
|
|
|
|
possible_values.add(current_possible_value);
|
|
|
|
possible_values.add(current_possible_value);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
prev_values.push(current_possible_value);
|
|
|
|
prev_values.push(current_possible_value);
|
|
|
|
|