updated packages

This commit is contained in:
2019-05-18 09:06:43 +00:00
parent 901d16349e
commit e9487fa58a
2025 changed files with 30366 additions and 49653 deletions

View File

@@ -55,22 +55,22 @@ class CssSelectorConverterTest extends TestCase
public function getCssToXPathWithoutPrefixTestData()
{
return array(
array('h1', 'h1'),
array('foo|h1', 'foo:h1'),
array('h1, h2, h3', 'h1 | h2 | h3'),
array('h1:nth-child(3n+1)', "*/*[(name() = 'h1') and (position() - 1 >= 0 and (position() - 1) mod 3 = 0)]"),
array('h1 > p', 'h1/p'),
array('h1#foo', "h1[@id = 'foo']"),
array('h1.foo', "h1[@class and contains(concat(' ', normalize-space(@class), ' '), ' foo ')]"),
array('h1[class*="foo bar"]', "h1[@class and contains(@class, 'foo bar')]"),
array('h1[foo|class*="foo bar"]', "h1[@foo:class and contains(@foo:class, 'foo bar')]"),
array('h1[class]', 'h1[@class]'),
array('h1 .foo', "h1/descendant-or-self::*/*[@class and contains(concat(' ', normalize-space(@class), ' '), ' foo ')]"),
array('h1 #foo', "h1/descendant-or-self::*/*[@id = 'foo']"),
array('h1 [class*=foo]', "h1/descendant-or-self::*/*[@class and contains(@class, 'foo')]"),
array('div>.foo', "div/*[@class and contains(concat(' ', normalize-space(@class), ' '), ' foo ')]"),
array('div > .foo', "div/*[@class and contains(concat(' ', normalize-space(@class), ' '), ' foo ')]"),
);
return [
['h1', 'h1'],
['foo|h1', 'foo:h1'],
['h1, h2, h3', 'h1 | h2 | h3'],
['h1:nth-child(3n+1)', "*/*[(name() = 'h1') and (position() - 1 >= 0 and (position() - 1) mod 3 = 0)]"],
['h1 > p', 'h1/p'],
['h1#foo', "h1[@id = 'foo']"],
['h1.foo', "h1[@class and contains(concat(' ', normalize-space(@class), ' '), ' foo ')]"],
['h1[class*="foo bar"]', "h1[@class and contains(@class, 'foo bar')]"],
['h1[foo|class*="foo bar"]', "h1[@foo:class and contains(@foo:class, 'foo bar')]"],
['h1[class]', 'h1[@class]'],
['h1 .foo', "h1/descendant-or-self::*/*[@class and contains(concat(' ', normalize-space(@class), ' '), ' foo ')]"],
['h1 #foo', "h1/descendant-or-self::*/*[@id = 'foo']"],
['h1 [class*=foo]', "h1/descendant-or-self::*/*[@class and contains(@class, 'foo')]"],
['div>.foo', "div/*[@class and contains(concat(' ', normalize-space(@class), ' '), ' foo ')]"],
['div > .foo', "div/*[@class and contains(concat(' ', normalize-space(@class), ' '), ' foo ')]"],
];
}
}

View File

@@ -18,20 +18,20 @@ class AttributeNodeTest extends AbstractNodeTest
{
public function getToStringConversionTestData()
{
return array(
array(new AttributeNode(new ElementNode(), null, 'attribute', 'exists', null), 'Attribute[Element[*][attribute]]'),
array(new AttributeNode(new ElementNode(), null, 'attribute', '$=', 'value'), "Attribute[Element[*][attribute $= 'value']]"),
array(new AttributeNode(new ElementNode(), 'namespace', 'attribute', '$=', 'value'), "Attribute[Element[*][namespace|attribute $= 'value']]"),
);
return [
[new AttributeNode(new ElementNode(), null, 'attribute', 'exists', null), 'Attribute[Element[*][attribute]]'],
[new AttributeNode(new ElementNode(), null, 'attribute', '$=', 'value'), "Attribute[Element[*][attribute $= 'value']]"],
[new AttributeNode(new ElementNode(), 'namespace', 'attribute', '$=', 'value'), "Attribute[Element[*][namespace|attribute $= 'value']]"],
];
}
public function getSpecificityValueTestData()
{
return array(
array(new AttributeNode(new ElementNode(), null, 'attribute', 'exists', null), 10),
array(new AttributeNode(new ElementNode(null, 'element'), null, 'attribute', 'exists', null), 11),
array(new AttributeNode(new ElementNode(), null, 'attribute', '$=', 'value'), 10),
array(new AttributeNode(new ElementNode(), 'namespace', 'attribute', '$=', 'value'), 10),
);
return [
[new AttributeNode(new ElementNode(), null, 'attribute', 'exists', null), 10],
[new AttributeNode(new ElementNode(null, 'element'), null, 'attribute', 'exists', null), 11],
[new AttributeNode(new ElementNode(), null, 'attribute', '$=', 'value'), 10],
[new AttributeNode(new ElementNode(), 'namespace', 'attribute', '$=', 'value'), 10],
];
}
}

View File

@@ -18,16 +18,16 @@ class ClassNodeTest extends AbstractNodeTest
{
public function getToStringConversionTestData()
{
return array(
array(new ClassNode(new ElementNode(), 'class'), 'Class[Element[*].class]'),
);
return [
[new ClassNode(new ElementNode(), 'class'), 'Class[Element[*].class]'],
];
}
public function getSpecificityValueTestData()
{
return array(
array(new ClassNode(new ElementNode(), 'class'), 10),
array(new ClassNode(new ElementNode(null, 'element'), 'class'), 11),
);
return [
[new ClassNode(new ElementNode(), 'class'), 10],
[new ClassNode(new ElementNode(null, 'element'), 'class'), 11],
];
}
}

View File

@@ -18,18 +18,18 @@ class CombinedSelectorNodeTest extends AbstractNodeTest
{
public function getToStringConversionTestData()
{
return array(
array(new CombinedSelectorNode(new ElementNode(), '>', new ElementNode()), 'CombinedSelector[Element[*] > Element[*]]'),
array(new CombinedSelectorNode(new ElementNode(), ' ', new ElementNode()), 'CombinedSelector[Element[*] <followed> Element[*]]'),
);
return [
[new CombinedSelectorNode(new ElementNode(), '>', new ElementNode()), 'CombinedSelector[Element[*] > Element[*]]'],
[new CombinedSelectorNode(new ElementNode(), ' ', new ElementNode()), 'CombinedSelector[Element[*] <followed> Element[*]]'],
];
}
public function getSpecificityValueTestData()
{
return array(
array(new CombinedSelectorNode(new ElementNode(), '>', new ElementNode()), 0),
array(new CombinedSelectorNode(new ElementNode(null, 'element'), '>', new ElementNode()), 1),
array(new CombinedSelectorNode(new ElementNode(null, 'element'), '>', new ElementNode(null, 'element')), 2),
);
return [
[new CombinedSelectorNode(new ElementNode(), '>', new ElementNode()), 0],
[new CombinedSelectorNode(new ElementNode(null, 'element'), '>', new ElementNode()), 1],
[new CombinedSelectorNode(new ElementNode(null, 'element'), '>', new ElementNode(null, 'element')), 2],
];
}
}

View File

@@ -17,19 +17,19 @@ class ElementNodeTest extends AbstractNodeTest
{
public function getToStringConversionTestData()
{
return array(
array(new ElementNode(), 'Element[*]'),
array(new ElementNode(null, 'element'), 'Element[element]'),
array(new ElementNode('namespace', 'element'), 'Element[namespace|element]'),
);
return [
[new ElementNode(), 'Element[*]'],
[new ElementNode(null, 'element'), 'Element[element]'],
[new ElementNode('namespace', 'element'), 'Element[namespace|element]'],
];
}
public function getSpecificityValueTestData()
{
return array(
array(new ElementNode(), 0),
array(new ElementNode(null, 'element'), 1),
array(new ElementNode('namespace', 'element'), 1),
);
return [
[new ElementNode(), 0],
[new ElementNode(null, 'element'), 1],
[new ElementNode('namespace', 'element'), 1],
];
}
}

View File

@@ -19,29 +19,29 @@ class FunctionNodeTest extends AbstractNodeTest
{
public function getToStringConversionTestData()
{
return array(
array(new FunctionNode(new ElementNode(), 'function'), 'Function[Element[*]:function()]'),
array(new FunctionNode(new ElementNode(), 'function', array(
return [
[new FunctionNode(new ElementNode(), 'function'), 'Function[Element[*]:function()]'],
[new FunctionNode(new ElementNode(), 'function', [
new Token(Token::TYPE_IDENTIFIER, 'value', 0),
)), "Function[Element[*]:function(['value'])]"),
array(new FunctionNode(new ElementNode(), 'function', array(
]), "Function[Element[*]:function(['value'])]"],
[new FunctionNode(new ElementNode(), 'function', [
new Token(Token::TYPE_STRING, 'value1', 0),
new Token(Token::TYPE_NUMBER, 'value2', 0),
)), "Function[Element[*]:function(['value1', 'value2'])]"),
);
]), "Function[Element[*]:function(['value1', 'value2'])]"],
];
}
public function getSpecificityValueTestData()
{
return array(
array(new FunctionNode(new ElementNode(), 'function'), 10),
array(new FunctionNode(new ElementNode(), 'function', array(
return [
[new FunctionNode(new ElementNode(), 'function'), 10],
[new FunctionNode(new ElementNode(), 'function', [
new Token(Token::TYPE_IDENTIFIER, 'value', 0),
)), 10),
array(new FunctionNode(new ElementNode(), 'function', array(
]), 10],
[new FunctionNode(new ElementNode(), 'function', [
new Token(Token::TYPE_STRING, 'value1', 0),
new Token(Token::TYPE_NUMBER, 'value2', 0),
)), 10),
);
]), 10],
];
}
}

View File

@@ -18,16 +18,16 @@ class HashNodeTest extends AbstractNodeTest
{
public function getToStringConversionTestData()
{
return array(
array(new HashNode(new ElementNode(), 'id'), 'Hash[Element[*]#id]'),
);
return [
[new HashNode(new ElementNode(), 'id'), 'Hash[Element[*]#id]'],
];
}
public function getSpecificityValueTestData()
{
return array(
array(new HashNode(new ElementNode(), 'id'), 100),
array(new HashNode(new ElementNode(null, 'id'), 'class'), 101),
);
return [
[new HashNode(new ElementNode(), 'id'), 100],
[new HashNode(new ElementNode(null, 'id'), 'class'), 101],
];
}
}

View File

@@ -19,15 +19,15 @@ class NegationNodeTest extends AbstractNodeTest
{
public function getToStringConversionTestData()
{
return array(
array(new NegationNode(new ElementNode(), new ClassNode(new ElementNode(), 'class')), 'Negation[Element[*]:not(Class[Element[*].class])]'),
);
return [
[new NegationNode(new ElementNode(), new ClassNode(new ElementNode(), 'class')), 'Negation[Element[*]:not(Class[Element[*].class])]'],
];
}
public function getSpecificityValueTestData()
{
return array(
array(new NegationNode(new ElementNode(), new ClassNode(new ElementNode(), 'class')), 10),
);
return [
[new NegationNode(new ElementNode(), new ClassNode(new ElementNode(), 'class')), 10],
];
}
}

View File

@@ -18,15 +18,15 @@ class PseudoNodeTest extends AbstractNodeTest
{
public function getToStringConversionTestData()
{
return array(
array(new PseudoNode(new ElementNode(), 'pseudo'), 'Pseudo[Element[*]:pseudo]'),
);
return [
[new PseudoNode(new ElementNode(), 'pseudo'), 'Pseudo[Element[*]:pseudo]'],
];
}
public function getSpecificityValueTestData()
{
return array(
array(new PseudoNode(new ElementNode(), 'pseudo'), 10),
);
return [
[new PseudoNode(new ElementNode(), 'pseudo'), 10],
];
}
}

View File

@@ -18,17 +18,17 @@ class SelectorNodeTest extends AbstractNodeTest
{
public function getToStringConversionTestData()
{
return array(
array(new SelectorNode(new ElementNode()), 'Selector[Element[*]]'),
array(new SelectorNode(new ElementNode(), 'pseudo'), 'Selector[Element[*]::pseudo]'),
);
return [
[new SelectorNode(new ElementNode()), 'Selector[Element[*]]'],
[new SelectorNode(new ElementNode(), 'pseudo'), 'Selector[Element[*]::pseudo]'],
];
}
public function getSpecificityValueTestData()
{
return array(
array(new SelectorNode(new ElementNode()), 0),
array(new SelectorNode(new ElementNode(), 'pseudo'), 1),
);
return [
[new SelectorNode(new ElementNode()), 0],
[new SelectorNode(new ElementNode(), 'pseudo'), 1],
];
}
}

View File

@@ -30,13 +30,13 @@ class SpecificityTest extends TestCase
public function getValueTestData()
{
return array(
array(new Specificity(0, 0, 0), 0),
array(new Specificity(0, 0, 2), 2),
array(new Specificity(0, 3, 0), 30),
array(new Specificity(4, 0, 0), 400),
array(new Specificity(4, 3, 2), 432),
);
return [
[new Specificity(0, 0, 0), 0],
[new Specificity(0, 0, 2), 2],
[new Specificity(0, 3, 0), 30],
[new Specificity(4, 0, 0), 400],
[new Specificity(4, 3, 2), 432],
];
}
/** @dataProvider getCompareTestData */
@@ -47,17 +47,17 @@ class SpecificityTest extends TestCase
public function getCompareTestData()
{
return array(
array(new Specificity(0, 0, 0), new Specificity(0, 0, 0), 0),
array(new Specificity(0, 0, 1), new Specificity(0, 0, 1), 0),
array(new Specificity(0, 0, 2), new Specificity(0, 0, 1), 1),
array(new Specificity(0, 0, 2), new Specificity(0, 0, 3), -1),
array(new Specificity(0, 4, 0), new Specificity(0, 4, 0), 0),
array(new Specificity(0, 6, 0), new Specificity(0, 5, 11), 1),
array(new Specificity(0, 7, 0), new Specificity(0, 8, 0), -1),
array(new Specificity(9, 0, 0), new Specificity(9, 0, 0), 0),
array(new Specificity(11, 0, 0), new Specificity(10, 11, 0), 1),
array(new Specificity(12, 11, 0), new Specificity(13, 0, 0), -1),
);
return [
[new Specificity(0, 0, 0), new Specificity(0, 0, 0), 0],
[new Specificity(0, 0, 1), new Specificity(0, 0, 1), 0],
[new Specificity(0, 0, 2), new Specificity(0, 0, 1), 1],
[new Specificity(0, 0, 2), new Specificity(0, 0, 3), -1],
[new Specificity(0, 4, 0), new Specificity(0, 4, 0), 0],
[new Specificity(0, 6, 0), new Specificity(0, 5, 11), 1],
[new Specificity(0, 7, 0), new Specificity(0, 8, 0), -1],
[new Specificity(9, 0, 0), new Specificity(9, 0, 0), 0],
[new Specificity(11, 0, 0), new Specificity(10, 11, 0), 1],
[new Specificity(12, 11, 0), new Specificity(13, 0, 0), -1],
];
}
}

View File

@@ -54,7 +54,7 @@ abstract class AbstractHandlerTest extends TestCase
$property = new \ReflectionProperty($stream, 'tokens');
$property->setAccessible(true);
$this->assertEquals(array(), $property->getValue($stream));
$this->assertEquals([], $property->getValue($stream));
}
protected function assertRemainingContent(Reader $reader, $remainingContent)

View File

@@ -32,20 +32,20 @@ class CommentHandlerTest extends AbstractHandlerTest
public function getHandleValueTestData()
{
return array(
return [
// 2nd argument only exists for inherited method compatibility
array('/* comment */', new Token(null, null, null), ''),
array('/* comment */foo', new Token(null, null, null), 'foo'),
);
['/* comment */', new Token(null, null, null), ''],
['/* comment */foo', new Token(null, null, null), 'foo'],
];
}
public function getDontHandleValueTestData()
{
return array(
array('>'),
array('+'),
array(' '),
);
return [
['>'],
['+'],
[' '],
];
}
protected function generateHandler()

View File

@@ -20,24 +20,24 @@ class HashHandlerTest extends AbstractHandlerTest
{
public function getHandleValueTestData()
{
return array(
array('#id', new Token(Token::TYPE_HASH, 'id', 0), ''),
array('#123', new Token(Token::TYPE_HASH, '123', 0), ''),
return [
['#id', new Token(Token::TYPE_HASH, 'id', 0), ''],
['#123', new Token(Token::TYPE_HASH, '123', 0), ''],
array('#id.class', new Token(Token::TYPE_HASH, 'id', 0), '.class'),
array('#id element', new Token(Token::TYPE_HASH, 'id', 0), ' element'),
);
['#id.class', new Token(Token::TYPE_HASH, 'id', 0), '.class'],
['#id element', new Token(Token::TYPE_HASH, 'id', 0), ' element'],
];
}
public function getDontHandleValueTestData()
{
return array(
array('id'),
array('123'),
array('<'),
array('<'),
array('#'),
);
return [
['id'],
['123'],
['<'],
['<'],
['#'],
];
}
protected function generateHandler()

View File

@@ -20,24 +20,24 @@ class IdentifierHandlerTest extends AbstractHandlerTest
{
public function getHandleValueTestData()
{
return array(
array('foo', new Token(Token::TYPE_IDENTIFIER, 'foo', 0), ''),
array('foo|bar', new Token(Token::TYPE_IDENTIFIER, 'foo', 0), '|bar'),
array('foo.class', new Token(Token::TYPE_IDENTIFIER, 'foo', 0), '.class'),
array('foo[attr]', new Token(Token::TYPE_IDENTIFIER, 'foo', 0), '[attr]'),
array('foo bar', new Token(Token::TYPE_IDENTIFIER, 'foo', 0), ' bar'),
);
return [
['foo', new Token(Token::TYPE_IDENTIFIER, 'foo', 0), ''],
['foo|bar', new Token(Token::TYPE_IDENTIFIER, 'foo', 0), '|bar'],
['foo.class', new Token(Token::TYPE_IDENTIFIER, 'foo', 0), '.class'],
['foo[attr]', new Token(Token::TYPE_IDENTIFIER, 'foo', 0), '[attr]'],
['foo bar', new Token(Token::TYPE_IDENTIFIER, 'foo', 0), ' bar'],
];
}
public function getDontHandleValueTestData()
{
return array(
array('>'),
array('+'),
array(' '),
array('*|foo'),
array('/* comment */'),
);
return [
['>'],
['+'],
[' '],
['*|foo'],
['/* comment */'],
];
}
protected function generateHandler()

View File

@@ -19,26 +19,26 @@ class NumberHandlerTest extends AbstractHandlerTest
{
public function getHandleValueTestData()
{
return array(
array('12', new Token(Token::TYPE_NUMBER, '12', 0), ''),
array('12.34', new Token(Token::TYPE_NUMBER, '12.34', 0), ''),
array('+12.34', new Token(Token::TYPE_NUMBER, '+12.34', 0), ''),
array('-12.34', new Token(Token::TYPE_NUMBER, '-12.34', 0), ''),
return [
['12', new Token(Token::TYPE_NUMBER, '12', 0), ''],
['12.34', new Token(Token::TYPE_NUMBER, '12.34', 0), ''],
['+12.34', new Token(Token::TYPE_NUMBER, '+12.34', 0), ''],
['-12.34', new Token(Token::TYPE_NUMBER, '-12.34', 0), ''],
array('12 arg', new Token(Token::TYPE_NUMBER, '12', 0), ' arg'),
array('12]', new Token(Token::TYPE_NUMBER, '12', 0), ']'),
);
['12 arg', new Token(Token::TYPE_NUMBER, '12', 0), ' arg'],
['12]', new Token(Token::TYPE_NUMBER, '12', 0), ']'],
];
}
public function getDontHandleValueTestData()
{
return array(
array('hello'),
array('>'),
array('+'),
array(' '),
array('/* comment */'),
);
return [
['hello'],
['>'],
['+'],
[' '],
['/* comment */'],
];
}
protected function generateHandler()

View File

@@ -20,25 +20,25 @@ class StringHandlerTest extends AbstractHandlerTest
{
public function getHandleValueTestData()
{
return array(
array('"hello"', new Token(Token::TYPE_STRING, 'hello', 1), ''),
array('"1"', new Token(Token::TYPE_STRING, '1', 1), ''),
array('" "', new Token(Token::TYPE_STRING, ' ', 1), ''),
array('""', new Token(Token::TYPE_STRING, '', 1), ''),
array("'hello'", new Token(Token::TYPE_STRING, 'hello', 1), ''),
return [
['"hello"', new Token(Token::TYPE_STRING, 'hello', 1), ''],
['"1"', new Token(Token::TYPE_STRING, '1', 1), ''],
['" "', new Token(Token::TYPE_STRING, ' ', 1), ''],
['""', new Token(Token::TYPE_STRING, '', 1), ''],
["'hello'", new Token(Token::TYPE_STRING, 'hello', 1), ''],
array("'foo'bar", new Token(Token::TYPE_STRING, 'foo', 1), 'bar'),
);
["'foo'bar", new Token(Token::TYPE_STRING, 'foo', 1), 'bar'],
];
}
public function getDontHandleValueTestData()
{
return array(
array('hello'),
array('>'),
array('1'),
array(' '),
);
return [
['hello'],
['>'],
['1'],
[' '],
];
}
protected function generateHandler()

View File

@@ -18,23 +18,23 @@ class WhitespaceHandlerTest extends AbstractHandlerTest
{
public function getHandleValueTestData()
{
return array(
array(' ', new Token(Token::TYPE_WHITESPACE, ' ', 0), ''),
array("\n", new Token(Token::TYPE_WHITESPACE, "\n", 0), ''),
array("\t", new Token(Token::TYPE_WHITESPACE, "\t", 0), ''),
return [
[' ', new Token(Token::TYPE_WHITESPACE, ' ', 0), ''],
["\n", new Token(Token::TYPE_WHITESPACE, "\n", 0), ''],
["\t", new Token(Token::TYPE_WHITESPACE, "\t", 0), ''],
array(' foo', new Token(Token::TYPE_WHITESPACE, ' ', 0), 'foo'),
array(' .foo', new Token(Token::TYPE_WHITESPACE, ' ', 0), '.foo'),
);
[' foo', new Token(Token::TYPE_WHITESPACE, ' ', 0), 'foo'],
[' .foo', new Token(Token::TYPE_WHITESPACE, ' ', 0), '.foo'],
];
}
public function getDontHandleValueTestData()
{
return array(
array('>'),
array('1'),
array('a'),
);
return [
['>'],
['1'],
['a'],
];
}
protected function generateHandler()

View File

@@ -77,7 +77,7 @@ class ParserTest extends TestCase
/** @var FunctionNode $function */
$function = $selectors[0]->getTree();
$this->assertEquals(array($a, $b), Parser::parseSeries($function->getArguments()));
$this->assertEquals([$a, $b], Parser::parseSeries($function->getArguments()));
}
/** @dataProvider getParseSeriesExceptionTestData */
@@ -95,159 +95,159 @@ class ParserTest extends TestCase
public function getParserTestData()
{
return array(
array('*', array('Element[*]')),
array('*|*', array('Element[*]')),
array('*|foo', array('Element[foo]')),
array('foo|*', array('Element[foo|*]')),
array('foo|bar', array('Element[foo|bar]')),
array('#foo#bar', array('Hash[Hash[Element[*]#foo]#bar]')),
array('div>.foo', array('CombinedSelector[Element[div] > Class[Element[*].foo]]')),
array('div> .foo', array('CombinedSelector[Element[div] > Class[Element[*].foo]]')),
array('div >.foo', array('CombinedSelector[Element[div] > Class[Element[*].foo]]')),
array('div > .foo', array('CombinedSelector[Element[div] > Class[Element[*].foo]]')),
array("div \n> \t \t .foo", array('CombinedSelector[Element[div] > Class[Element[*].foo]]')),
array('td.foo,.bar', array('Class[Element[td].foo]', 'Class[Element[*].bar]')),
array('td.foo, .bar', array('Class[Element[td].foo]', 'Class[Element[*].bar]')),
array("td.foo\t\r\n\f ,\t\r\n\f .bar", array('Class[Element[td].foo]', 'Class[Element[*].bar]')),
array('td.foo,.bar', array('Class[Element[td].foo]', 'Class[Element[*].bar]')),
array('td.foo, .bar', array('Class[Element[td].foo]', 'Class[Element[*].bar]')),
array("td.foo\t\r\n\f ,\t\r\n\f .bar", array('Class[Element[td].foo]', 'Class[Element[*].bar]')),
array('div, td.foo, div.bar span', array('Element[div]', 'Class[Element[td].foo]', 'CombinedSelector[Class[Element[div].bar] <followed> Element[span]]')),
array('div > p', array('CombinedSelector[Element[div] > Element[p]]')),
array('td:first', array('Pseudo[Element[td]:first]')),
array('td :first', array('CombinedSelector[Element[td] <followed> Pseudo[Element[*]:first]]')),
array('a[name]', array('Attribute[Element[a][name]]')),
array("a[ name\t]", array('Attribute[Element[a][name]]')),
array('a [name]', array('CombinedSelector[Element[a] <followed> Attribute[Element[*][name]]]')),
array('[name="foo"]', array("Attribute[Element[*][name = 'foo']]")),
array("[name='foo[1]']", array("Attribute[Element[*][name = 'foo[1]']]")),
array("[name='foo[0][bar]']", array("Attribute[Element[*][name = 'foo[0][bar]']]")),
array('a[rel="include"]', array("Attribute[Element[a][rel = 'include']]")),
array('a[rel = include]', array("Attribute[Element[a][rel = 'include']]")),
array("a[hreflang |= 'en']", array("Attribute[Element[a][hreflang |= 'en']]")),
array('a[hreflang|=en]', array("Attribute[Element[a][hreflang |= 'en']]")),
array('div:nth-child(10)', array("Function[Element[div]:nth-child(['10'])]")),
array(':nth-child(2n+2)', array("Function[Element[*]:nth-child(['2', 'n', '+2'])]")),
array('div:nth-of-type(10)', array("Function[Element[div]:nth-of-type(['10'])]")),
array('div div:nth-of-type(10) .aclass', array("CombinedSelector[CombinedSelector[Element[div] <followed> Function[Element[div]:nth-of-type(['10'])]] <followed> Class[Element[*].aclass]]")),
array('label:only', array('Pseudo[Element[label]:only]')),
array('a:lang(fr)', array("Function[Element[a]:lang(['fr'])]")),
array('div:contains("foo")', array("Function[Element[div]:contains(['foo'])]")),
array('div#foobar', array('Hash[Element[div]#foobar]')),
array('div:not(div.foo)', array('Negation[Element[div]:not(Class[Element[div].foo])]')),
array('td ~ th', array('CombinedSelector[Element[td] ~ Element[th]]')),
array('.foo[data-bar][data-baz=0]', array("Attribute[Attribute[Class[Element[*].foo][data-bar]][data-baz = '0']]")),
);
return [
['*', ['Element[*]']],
['*|*', ['Element[*]']],
['*|foo', ['Element[foo]']],
['foo|*', ['Element[foo|*]']],
['foo|bar', ['Element[foo|bar]']],
['#foo#bar', ['Hash[Hash[Element[*]#foo]#bar]']],
['div>.foo', ['CombinedSelector[Element[div] > Class[Element[*].foo]]']],
['div> .foo', ['CombinedSelector[Element[div] > Class[Element[*].foo]]']],
['div >.foo', ['CombinedSelector[Element[div] > Class[Element[*].foo]]']],
['div > .foo', ['CombinedSelector[Element[div] > Class[Element[*].foo]]']],
["div \n> \t \t .foo", ['CombinedSelector[Element[div] > Class[Element[*].foo]]']],
['td.foo,.bar', ['Class[Element[td].foo]', 'Class[Element[*].bar]']],
['td.foo, .bar', ['Class[Element[td].foo]', 'Class[Element[*].bar]']],
["td.foo\t\r\n\f ,\t\r\n\f .bar", ['Class[Element[td].foo]', 'Class[Element[*].bar]']],
['td.foo,.bar', ['Class[Element[td].foo]', 'Class[Element[*].bar]']],
['td.foo, .bar', ['Class[Element[td].foo]', 'Class[Element[*].bar]']],
["td.foo\t\r\n\f ,\t\r\n\f .bar", ['Class[Element[td].foo]', 'Class[Element[*].bar]']],
['div, td.foo, div.bar span', ['Element[div]', 'Class[Element[td].foo]', 'CombinedSelector[Class[Element[div].bar] <followed> Element[span]]']],
['div > p', ['CombinedSelector[Element[div] > Element[p]]']],
['td:first', ['Pseudo[Element[td]:first]']],
['td :first', ['CombinedSelector[Element[td] <followed> Pseudo[Element[*]:first]]']],
['a[name]', ['Attribute[Element[a][name]]']],
["a[ name\t]", ['Attribute[Element[a][name]]']],
['a [name]', ['CombinedSelector[Element[a] <followed> Attribute[Element[*][name]]]']],
['[name="foo"]', ["Attribute[Element[*][name = 'foo']]"]],
["[name='foo[1]']", ["Attribute[Element[*][name = 'foo[1]']]"]],
["[name='foo[0][bar]']", ["Attribute[Element[*][name = 'foo[0][bar]']]"]],
['a[rel="include"]', ["Attribute[Element[a][rel = 'include']]"]],
['a[rel = include]', ["Attribute[Element[a][rel = 'include']]"]],
["a[hreflang |= 'en']", ["Attribute[Element[a][hreflang |= 'en']]"]],
['a[hreflang|=en]', ["Attribute[Element[a][hreflang |= 'en']]"]],
['div:nth-child(10)', ["Function[Element[div]:nth-child(['10'])]"]],
[':nth-child(2n+2)', ["Function[Element[*]:nth-child(['2', 'n', '+2'])]"]],
['div:nth-of-type(10)', ["Function[Element[div]:nth-of-type(['10'])]"]],
['div div:nth-of-type(10) .aclass', ["CombinedSelector[CombinedSelector[Element[div] <followed> Function[Element[div]:nth-of-type(['10'])]] <followed> Class[Element[*].aclass]]"]],
['label:only', ['Pseudo[Element[label]:only]']],
['a:lang(fr)', ["Function[Element[a]:lang(['fr'])]"]],
['div:contains("foo")', ["Function[Element[div]:contains(['foo'])]"]],
['div#foobar', ['Hash[Element[div]#foobar]']],
['div:not(div.foo)', ['Negation[Element[div]:not(Class[Element[div].foo])]']],
['td ~ th', ['CombinedSelector[Element[td] ~ Element[th]]']],
['.foo[data-bar][data-baz=0]', ["Attribute[Attribute[Class[Element[*].foo][data-bar]][data-baz = '0']]"]],
];
}
public function getParserExceptionTestData()
{
return array(
array('attributes(href)/html/body/a', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_DELIMITER, '(', 10))->getMessage()),
array('attributes(href)', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_DELIMITER, '(', 10))->getMessage()),
array('html/body/a', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_DELIMITER, '/', 4))->getMessage()),
array(' ', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_FILE_END, '', 1))->getMessage()),
array('div, ', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_FILE_END, '', 5))->getMessage()),
array(' , div', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_DELIMITER, ',', 1))->getMessage()),
array('p, , div', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_DELIMITER, ',', 3))->getMessage()),
array('div > ', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_FILE_END, '', 6))->getMessage()),
array(' > div', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_DELIMITER, '>', 2))->getMessage()),
array('foo|#bar', SyntaxErrorException::unexpectedToken('identifier or "*"', new Token(Token::TYPE_HASH, 'bar', 4))->getMessage()),
array('#.foo', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_DELIMITER, '#', 0))->getMessage()),
array('.#foo', SyntaxErrorException::unexpectedToken('identifier', new Token(Token::TYPE_HASH, 'foo', 1))->getMessage()),
array(':#foo', SyntaxErrorException::unexpectedToken('identifier', new Token(Token::TYPE_HASH, 'foo', 1))->getMessage()),
array('[*]', SyntaxErrorException::unexpectedToken('"|"', new Token(Token::TYPE_DELIMITER, ']', 2))->getMessage()),
array('[foo|]', SyntaxErrorException::unexpectedToken('identifier', new Token(Token::TYPE_DELIMITER, ']', 5))->getMessage()),
array('[#]', SyntaxErrorException::unexpectedToken('identifier or "*"', new Token(Token::TYPE_DELIMITER, '#', 1))->getMessage()),
array('[foo=#]', SyntaxErrorException::unexpectedToken('string or identifier', new Token(Token::TYPE_DELIMITER, '#', 5))->getMessage()),
array(':nth-child()', SyntaxErrorException::unexpectedToken('at least one argument', new Token(Token::TYPE_DELIMITER, ')', 11))->getMessage()),
array('[href]a', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_IDENTIFIER, 'a', 6))->getMessage()),
array('[rel:stylesheet]', SyntaxErrorException::unexpectedToken('operator', new Token(Token::TYPE_DELIMITER, ':', 4))->getMessage()),
array('[rel=stylesheet', SyntaxErrorException::unexpectedToken('"]"', new Token(Token::TYPE_FILE_END, '', 15))->getMessage()),
array(':lang(fr', SyntaxErrorException::unexpectedToken('an argument', new Token(Token::TYPE_FILE_END, '', 8))->getMessage()),
array(':contains("foo', SyntaxErrorException::unclosedString(10)->getMessage()),
array('foo!', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_DELIMITER, '!', 3))->getMessage()),
);
return [
['attributes(href)/html/body/a', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_DELIMITER, '(', 10))->getMessage()],
['attributes(href)', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_DELIMITER, '(', 10))->getMessage()],
['html/body/a', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_DELIMITER, '/', 4))->getMessage()],
[' ', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_FILE_END, '', 1))->getMessage()],
['div, ', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_FILE_END, '', 5))->getMessage()],
[' , div', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_DELIMITER, ',', 1))->getMessage()],
['p, , div', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_DELIMITER, ',', 3))->getMessage()],
['div > ', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_FILE_END, '', 6))->getMessage()],
[' > div', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_DELIMITER, '>', 2))->getMessage()],
['foo|#bar', SyntaxErrorException::unexpectedToken('identifier or "*"', new Token(Token::TYPE_HASH, 'bar', 4))->getMessage()],
['#.foo', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_DELIMITER, '#', 0))->getMessage()],
['.#foo', SyntaxErrorException::unexpectedToken('identifier', new Token(Token::TYPE_HASH, 'foo', 1))->getMessage()],
[':#foo', SyntaxErrorException::unexpectedToken('identifier', new Token(Token::TYPE_HASH, 'foo', 1))->getMessage()],
['[*]', SyntaxErrorException::unexpectedToken('"|"', new Token(Token::TYPE_DELIMITER, ']', 2))->getMessage()],
['[foo|]', SyntaxErrorException::unexpectedToken('identifier', new Token(Token::TYPE_DELIMITER, ']', 5))->getMessage()],
['[#]', SyntaxErrorException::unexpectedToken('identifier or "*"', new Token(Token::TYPE_DELIMITER, '#', 1))->getMessage()],
['[foo=#]', SyntaxErrorException::unexpectedToken('string or identifier', new Token(Token::TYPE_DELIMITER, '#', 5))->getMessage()],
[':nth-child()', SyntaxErrorException::unexpectedToken('at least one argument', new Token(Token::TYPE_DELIMITER, ')', 11))->getMessage()],
['[href]a', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_IDENTIFIER, 'a', 6))->getMessage()],
['[rel:stylesheet]', SyntaxErrorException::unexpectedToken('operator', new Token(Token::TYPE_DELIMITER, ':', 4))->getMessage()],
['[rel=stylesheet', SyntaxErrorException::unexpectedToken('"]"', new Token(Token::TYPE_FILE_END, '', 15))->getMessage()],
[':lang(fr', SyntaxErrorException::unexpectedToken('an argument', new Token(Token::TYPE_FILE_END, '', 8))->getMessage()],
[':contains("foo', SyntaxErrorException::unclosedString(10)->getMessage()],
['foo!', SyntaxErrorException::unexpectedToken('selector', new Token(Token::TYPE_DELIMITER, '!', 3))->getMessage()],
];
}
public function getPseudoElementsTestData()
{
return array(
array('foo', 'Element[foo]', ''),
array('*', 'Element[*]', ''),
array(':empty', 'Pseudo[Element[*]:empty]', ''),
array(':BEfore', 'Element[*]', 'before'),
array(':aftER', 'Element[*]', 'after'),
array(':First-Line', 'Element[*]', 'first-line'),
array(':First-Letter', 'Element[*]', 'first-letter'),
array('::befoRE', 'Element[*]', 'before'),
array('::AFter', 'Element[*]', 'after'),
array('::firsT-linE', 'Element[*]', 'first-line'),
array('::firsT-letteR', 'Element[*]', 'first-letter'),
array('::Selection', 'Element[*]', 'selection'),
array('foo:after', 'Element[foo]', 'after'),
array('foo::selection', 'Element[foo]', 'selection'),
array('lorem#ipsum ~ a#b.c[href]:empty::selection', 'CombinedSelector[Hash[Element[lorem]#ipsum] ~ Pseudo[Attribute[Class[Hash[Element[a]#b].c][href]]:empty]]', 'selection'),
array('video::-webkit-media-controls', 'Element[video]', '-webkit-media-controls'),
);
return [
['foo', 'Element[foo]', ''],
['*', 'Element[*]', ''],
[':empty', 'Pseudo[Element[*]:empty]', ''],
[':BEfore', 'Element[*]', 'before'],
[':aftER', 'Element[*]', 'after'],
[':First-Line', 'Element[*]', 'first-line'],
[':First-Letter', 'Element[*]', 'first-letter'],
['::befoRE', 'Element[*]', 'before'],
['::AFter', 'Element[*]', 'after'],
['::firsT-linE', 'Element[*]', 'first-line'],
['::firsT-letteR', 'Element[*]', 'first-letter'],
['::Selection', 'Element[*]', 'selection'],
['foo:after', 'Element[foo]', 'after'],
['foo::selection', 'Element[foo]', 'selection'],
['lorem#ipsum ~ a#b.c[href]:empty::selection', 'CombinedSelector[Hash[Element[lorem]#ipsum] ~ Pseudo[Attribute[Class[Hash[Element[a]#b].c][href]]:empty]]', 'selection'],
['video::-webkit-media-controls', 'Element[video]', '-webkit-media-controls'],
];
}
public function getSpecificityTestData()
{
return array(
array('*', 0),
array(' foo', 1),
array(':empty ', 10),
array(':before', 1),
array('*:before', 1),
array(':nth-child(2)', 10),
array('.bar', 10),
array('[baz]', 10),
array('[baz="4"]', 10),
array('[baz^="4"]', 10),
array('#lipsum', 100),
array(':not(*)', 0),
array(':not(foo)', 1),
array(':not(.foo)', 10),
array(':not([foo])', 10),
array(':not(:empty)', 10),
array(':not(#foo)', 100),
array('foo:empty', 11),
array('foo:before', 2),
array('foo::before', 2),
array('foo:empty::before', 12),
array('#lorem + foo#ipsum:first-child > bar:first-line', 213),
);
return [
['*', 0],
[' foo', 1],
[':empty ', 10],
[':before', 1],
['*:before', 1],
[':nth-child(2)', 10],
['.bar', 10],
['[baz]', 10],
['[baz="4"]', 10],
['[baz^="4"]', 10],
['#lipsum', 100],
[':not(*)', 0],
[':not(foo)', 1],
[':not(.foo)', 10],
[':not([foo])', 10],
[':not(:empty)', 10],
[':not(#foo)', 100],
['foo:empty', 11],
['foo:before', 2],
['foo::before', 2],
['foo:empty::before', 12],
['#lorem + foo#ipsum:first-child > bar:first-line', 213],
];
}
public function getParseSeriesTestData()
{
return array(
array('1n+3', 1, 3),
array('1n +3', 1, 3),
array('1n + 3', 1, 3),
array('1n+ 3', 1, 3),
array('1n-3', 1, -3),
array('1n -3', 1, -3),
array('1n - 3', 1, -3),
array('1n- 3', 1, -3),
array('n-5', 1, -5),
array('odd', 2, 1),
array('even', 2, 0),
array('3n', 3, 0),
array('n', 1, 0),
array('+n', 1, 0),
array('-n', -1, 0),
array('5', 0, 5),
);
return [
['1n+3', 1, 3],
['1n +3', 1, 3],
['1n + 3', 1, 3],
['1n+ 3', 1, 3],
['1n-3', 1, -3],
['1n -3', 1, -3],
['1n - 3', 1, -3],
['1n- 3', 1, -3],
['n-5', 1, -5],
['odd', 2, 1],
['even', 2, 0],
['3n', 3, 0],
['n', 1, 0],
['+n', 1, 0],
['-n', -1, 0],
['5', 0, 5],
];
}
public function getParseSeriesExceptionTestData()
{
return array(
array('foo'),
array('n+'),
);
return [
['foo'],
['n+'],
];
}
}

View File

@@ -70,11 +70,11 @@ class ReaderTest extends TestCase
$reader = new Reader('hello');
$this->assertFalse($reader->findPattern('/world/'));
$this->assertEquals(array('hello', 'h'), $reader->findPattern('/^([a-z]).*/'));
$this->assertEquals(['hello', 'h'], $reader->findPattern('/^([a-z]).*/'));
$this->assignPosition($reader, 2);
$this->assertFalse($reader->findPattern('/^h.*/'));
$this->assertEquals(array('llo'), $reader->findPattern('/^llo$/'));
$this->assertEquals(['llo'], $reader->findPattern('/^llo$/'));
}
public function testMoveForward()

View File

@@ -34,12 +34,12 @@ class ClassParserTest extends TestCase
public function getParseTestData()
{
return array(
array('.testclass', 'Class[Element[*].testclass]'),
array('testel.testclass', 'Class[Element[testel].testclass]'),
array('testns|.testclass', 'Class[Element[testns|*].testclass]'),
array('testns|*.testclass', 'Class[Element[testns|*].testclass]'),
array('testns|testel.testclass', 'Class[Element[testns|testel].testclass]'),
);
return [
['.testclass', 'Class[Element[*].testclass]'],
['testel.testclass', 'Class[Element[testel].testclass]'],
['testns|.testclass', 'Class[Element[testns|*].testclass]'],
['testns|*.testclass', 'Class[Element[testns|*].testclass]'],
['testns|testel.testclass', 'Class[Element[testns|testel].testclass]'],
];
}
}

View File

@@ -34,11 +34,11 @@ class ElementParserTest extends TestCase
public function getParseTestData()
{
return array(
array('*', 'Element[*]'),
array('testel', 'Element[testel]'),
array('testns|*', 'Element[testns|*]'),
array('testns|testel', 'Element[testns|testel]'),
);
return [
['*', 'Element[*]'],
['testel', 'Element[testel]'],
['testns|*', 'Element[testns|*]'],
['testns|testel', 'Element[testns|testel]'],
];
}
}

View File

@@ -34,12 +34,12 @@ class HashParserTest extends TestCase
public function getParseTestData()
{
return array(
array('#testid', 'Hash[Element[*]#testid]'),
array('testel#testid', 'Hash[Element[testel]#testid]'),
array('testns|#testid', 'Hash[Element[testns|*]#testid]'),
array('testns|*#testid', 'Hash[Element[testns|*]#testid]'),
array('testns|testel#testid', 'Hash[Element[testns|testel]#testid]'),
);
return [
['#testid', 'Hash[Element[*]#testid]'],
['testel#testid', 'Hash[Element[testel]#testid]'],
['testns|#testid', 'Hash[Element[testns|*]#testid]'],
['testns|*#testid', 'Hash[Element[testns|*]#testid]'],
['testns|testel#testid', 'Hash[Element[testns|testel]#testid]'],
];
}
}

View File

@@ -12,8 +12,12 @@
namespace Symfony\Component\CssSelector\Tests\XPath;
use PHPUnit\Framework\TestCase;
use Symfony\Component\CssSelector\Node\ElementNode;
use Symfony\Component\CssSelector\Node\FunctionNode;
use Symfony\Component\CssSelector\Parser\Parser;
use Symfony\Component\CssSelector\XPath\Extension\HtmlExtension;
use Symfony\Component\CssSelector\XPath\Translator;
use Symfony\Component\CssSelector\XPath\XPathExpr;
class TranslatorTest extends TestCase
{
@@ -31,6 +35,73 @@ class TranslatorTest extends TestCase
$this->assertEquals($xpath, $translator->cssToXPath($css, ''));
}
/**
* @expectedException \Symfony\Component\CssSelector\Exception\ExpressionErrorException
*/
public function testCssToXPathPseudoElement()
{
$translator = new Translator();
$translator->registerExtension(new HtmlExtension($translator));
$translator->cssToXPath('e::first-line');
}
/**
* @expectedException \Symfony\Component\CssSelector\Exception\ExpressionErrorException
*/
public function testGetExtensionNotExistsExtension()
{
$translator = new Translator();
$translator->registerExtension(new HtmlExtension($translator));
$translator->getExtension('fake');
}
/**
* @expectedException \Symfony\Component\CssSelector\Exception\ExpressionErrorException
*/
public function testAddCombinationNotExistsExtension()
{
$translator = new Translator();
$translator->registerExtension(new HtmlExtension($translator));
$parser = new Parser();
$xpath = $parser->parse('*')[0];
$combinedXpath = $parser->parse('*')[0];
$translator->addCombination('fake', $xpath, $combinedXpath);
}
/**
* @expectedException \Symfony\Component\CssSelector\Exception\ExpressionErrorException
*/
public function testAddFunctionNotExistsFunction()
{
$translator = new Translator();
$translator->registerExtension(new HtmlExtension($translator));
$xpath = new XPathExpr();
$function = new FunctionNode(new ElementNode(), 'fake');
$translator->addFunction($xpath, $function);
}
/**
* @expectedException \Symfony\Component\CssSelector\Exception\ExpressionErrorException
*/
public function testAddPseudoClassNotExistsClass()
{
$translator = new Translator();
$translator->registerExtension(new HtmlExtension($translator));
$xpath = new XPathExpr();
$translator->addPseudoClass($xpath, 'fake');
}
/**
* @expectedException \Symfony\Component\CssSelector\Exception\ExpressionErrorException
*/
public function testAddAttributeMatchingClassNotExistsClass()
{
$translator = new Translator();
$translator->registerExtension(new HtmlExtension($translator));
$xpath = new XPathExpr();
$translator->addAttributeMatching($xpath, '', '', '');
}
/** @dataProvider getXmlLangTestData */
public function testXmlLang($css, array $elementsId)
{
@@ -80,248 +151,248 @@ class TranslatorTest extends TestCase
public function getXpathLiteralTestData()
{
return array(
array('foo', "'foo'"),
array("foo's bar", '"foo\'s bar"'),
array("foo's \"middle\" bar", 'concat(\'foo\', "\'", \'s "middle" bar\')'),
array("foo's 'middle' \"bar\"", 'concat(\'foo\', "\'", \'s \', "\'", \'middle\', "\'", \' "bar"\')'),
);
return [
['foo', "'foo'"],
["foo's bar", '"foo\'s bar"'],
["foo's \"middle\" bar", 'concat(\'foo\', "\'", \'s "middle" bar\')'],
["foo's 'middle' \"bar\"", 'concat(\'foo\', "\'", \'s \', "\'", \'middle\', "\'", \' "bar"\')'],
];
}
public function getCssToXPathTestData()
{
return array(
array('*', '*'),
array('e', 'e'),
array('*|e', 'e'),
array('e|f', 'e:f'),
array('e[foo]', 'e[@foo]'),
array('e[foo|bar]', 'e[@foo:bar]'),
array('e[foo="bar"]', "e[@foo = 'bar']"),
array('e[foo~="bar"]', "e[@foo and contains(concat(' ', normalize-space(@foo), ' '), ' bar ')]"),
array('e[foo^="bar"]', "e[@foo and starts-with(@foo, 'bar')]"),
array('e[foo$="bar"]', "e[@foo and substring(@foo, string-length(@foo)-2) = 'bar']"),
array('e[foo*="bar"]', "e[@foo and contains(@foo, 'bar')]"),
array('e[foo!="bar"]', "e[not(@foo) or @foo != 'bar']"),
array('e[foo!="bar"][foo!="baz"]', "e[(not(@foo) or @foo != 'bar') and (not(@foo) or @foo != 'baz')]"),
array('e[hreflang|="en"]', "e[@hreflang and (@hreflang = 'en' or starts-with(@hreflang, 'en-'))]"),
array('e:nth-child(1)', "*/*[(name() = 'e') and (position() = 1)]"),
array('e:nth-last-child(1)', "*/*[(name() = 'e') and (position() = last() - 0)]"),
array('e:nth-last-child(2n+2)', "*/*[(name() = 'e') and (last() - position() - 1 >= 0 and (last() - position() - 1) mod 2 = 0)]"),
array('e:nth-of-type(1)', '*/e[position() = 1]'),
array('e:nth-last-of-type(1)', '*/e[position() = last() - 0]'),
array('div e:nth-last-of-type(1) .aclass', "div/descendant-or-self::*/e[position() = last() - 0]/descendant-or-self::*/*[@class and contains(concat(' ', normalize-space(@class), ' '), ' aclass ')]"),
array('e:first-child', "*/*[(name() = 'e') and (position() = 1)]"),
array('e:last-child', "*/*[(name() = 'e') and (position() = last())]"),
array('e:first-of-type', '*/e[position() = 1]'),
array('e:last-of-type', '*/e[position() = last()]'),
array('e:only-child', "*/*[(name() = 'e') and (last() = 1)]"),
array('e:only-of-type', 'e[last() = 1]'),
array('e:empty', 'e[not(*) and not(string-length())]'),
array('e:EmPTY', 'e[not(*) and not(string-length())]'),
array('e:root', 'e[not(parent::*)]'),
array('e:hover', 'e[0]'),
array('e:contains("foo")', "e[contains(string(.), 'foo')]"),
array('e:ConTains(foo)', "e[contains(string(.), 'foo')]"),
array('e.warning', "e[@class and contains(concat(' ', normalize-space(@class), ' '), ' warning ')]"),
array('e#myid', "e[@id = 'myid']"),
array('e:not(:nth-child(odd))', 'e[not(position() - 1 >= 0 and (position() - 1) mod 2 = 0)]'),
array('e:nOT(*)', 'e[0]'),
array('e f', 'e/descendant-or-self::*/f'),
array('e > f', 'e/f'),
array('e + f', "e/following-sibling::*[(name() = 'f') and (position() = 1)]"),
array('e ~ f', 'e/following-sibling::f'),
array('div#container p', "div[@id = 'container']/descendant-or-self::*/p"),
);
return [
['*', '*'],
['e', 'e'],
['*|e', 'e'],
['e|f', 'e:f'],
['e[foo]', 'e[@foo]'],
['e[foo|bar]', 'e[@foo:bar]'],
['e[foo="bar"]', "e[@foo = 'bar']"],
['e[foo~="bar"]', "e[@foo and contains(concat(' ', normalize-space(@foo), ' '), ' bar ')]"],
['e[foo^="bar"]', "e[@foo and starts-with(@foo, 'bar')]"],
['e[foo$="bar"]', "e[@foo and substring(@foo, string-length(@foo)-2) = 'bar']"],
['e[foo*="bar"]', "e[@foo and contains(@foo, 'bar')]"],
['e[foo!="bar"]', "e[not(@foo) or @foo != 'bar']"],
['e[foo!="bar"][foo!="baz"]', "e[(not(@foo) or @foo != 'bar') and (not(@foo) or @foo != 'baz')]"],
['e[hreflang|="en"]', "e[@hreflang and (@hreflang = 'en' or starts-with(@hreflang, 'en-'))]"],
['e:nth-child(1)', "*/*[(name() = 'e') and (position() = 1)]"],
['e:nth-last-child(1)', "*/*[(name() = 'e') and (position() = last() - 0)]"],
['e:nth-last-child(2n+2)', "*/*[(name() = 'e') and (last() - position() - 1 >= 0 and (last() - position() - 1) mod 2 = 0)]"],
['e:nth-of-type(1)', '*/e[position() = 1]'],
['e:nth-last-of-type(1)', '*/e[position() = last() - 0]'],
['div e:nth-last-of-type(1) .aclass', "div/descendant-or-self::*/e[position() = last() - 0]/descendant-or-self::*/*[@class and contains(concat(' ', normalize-space(@class), ' '), ' aclass ')]"],
['e:first-child', "*/*[(name() = 'e') and (position() = 1)]"],
['e:last-child', "*/*[(name() = 'e') and (position() = last())]"],
['e:first-of-type', '*/e[position() = 1]'],
['e:last-of-type', '*/e[position() = last()]'],
['e:only-child', "*/*[(name() = 'e') and (last() = 1)]"],
['e:only-of-type', 'e[last() = 1]'],
['e:empty', 'e[not(*) and not(string-length())]'],
['e:EmPTY', 'e[not(*) and not(string-length())]'],
['e:root', 'e[not(parent::*)]'],
['e:hover', 'e[0]'],
['e:contains("foo")', "e[contains(string(.), 'foo')]"],
['e:ConTains(foo)', "e[contains(string(.), 'foo')]"],
['e.warning', "e[@class and contains(concat(' ', normalize-space(@class), ' '), ' warning ')]"],
['e#myid', "e[@id = 'myid']"],
['e:not(:nth-child(odd))', 'e[not(position() - 1 >= 0 and (position() - 1) mod 2 = 0)]'],
['e:nOT(*)', 'e[0]'],
['e f', 'e/descendant-or-self::*/f'],
['e > f', 'e/f'],
['e + f', "e/following-sibling::*[(name() = 'f') and (position() = 1)]"],
['e ~ f', 'e/following-sibling::f'],
['div#container p', "div[@id = 'container']/descendant-or-self::*/p"],
];
}
public function getXmlLangTestData()
{
return array(
array(':lang("EN")', array('first', 'second', 'third', 'fourth')),
array(':lang("en-us")', array('second', 'fourth')),
array(':lang(en-nz)', array('third')),
array(':lang(fr)', array('fifth')),
array(':lang(ru)', array('sixth')),
array(":lang('ZH')", array('eighth')),
array(':lang(de) :lang(zh)', array('eighth')),
array(':lang(en), :lang(zh)', array('first', 'second', 'third', 'fourth', 'eighth')),
array(':lang(es)', array()),
);
return [
[':lang("EN")', ['first', 'second', 'third', 'fourth']],
[':lang("en-us")', ['second', 'fourth']],
[':lang(en-nz)', ['third']],
[':lang(fr)', ['fifth']],
[':lang(ru)', ['sixth']],
[":lang('ZH')", ['eighth']],
[':lang(de) :lang(zh)', ['eighth']],
[':lang(en), :lang(zh)', ['first', 'second', 'third', 'fourth', 'eighth']],
[':lang(es)', []],
];
}
public function getHtmlIdsTestData()
{
return array(
array('div', array('outer-div', 'li-div', 'foobar-div')),
array('DIV', array('outer-div', 'li-div', 'foobar-div')), // case-insensitive in HTML
array('div div', array('li-div')),
array('div, div div', array('outer-div', 'li-div', 'foobar-div')),
array('a[name]', array('name-anchor')),
array('a[NAme]', array('name-anchor')), // case-insensitive in HTML:
array('a[rel]', array('tag-anchor', 'nofollow-anchor')),
array('a[rel="tag"]', array('tag-anchor')),
array('a[href*="localhost"]', array('tag-anchor')),
array('a[href*=""]', array()),
array('a[href^="http"]', array('tag-anchor', 'nofollow-anchor')),
array('a[href^="http:"]', array('tag-anchor')),
array('a[href^=""]', array()),
array('a[href$="org"]', array('nofollow-anchor')),
array('a[href$=""]', array()),
array('div[foobar~="bc"]', array('foobar-div')),
array('div[foobar~="cde"]', array('foobar-div')),
array('[foobar~="ab bc"]', array('foobar-div')),
array('[foobar~=""]', array()),
array('[foobar~=" \t"]', array()),
array('div[foobar~="cd"]', array()),
array('*[lang|="En"]', array('second-li')),
array('[lang|="En-us"]', array('second-li')),
return [
['div', ['outer-div', 'li-div', 'foobar-div']],
['DIV', ['outer-div', 'li-div', 'foobar-div']], // case-insensitive in HTML
['div div', ['li-div']],
['div, div div', ['outer-div', 'li-div', 'foobar-div']],
['a[name]', ['name-anchor']],
['a[NAme]', ['name-anchor']], // case-insensitive in HTML:
['a[rel]', ['tag-anchor', 'nofollow-anchor']],
['a[rel="tag"]', ['tag-anchor']],
['a[href*="localhost"]', ['tag-anchor']],
['a[href*=""]', []],
['a[href^="http"]', ['tag-anchor', 'nofollow-anchor']],
['a[href^="http:"]', ['tag-anchor']],
['a[href^=""]', []],
['a[href$="org"]', ['nofollow-anchor']],
['a[href$=""]', []],
['div[foobar~="bc"]', ['foobar-div']],
['div[foobar~="cde"]', ['foobar-div']],
['[foobar~="ab bc"]', ['foobar-div']],
['[foobar~=""]', []],
['[foobar~=" \t"]', []],
['div[foobar~="cd"]', []],
['*[lang|="En"]', ['second-li']],
['[lang|="En-us"]', ['second-li']],
// Attribute values are case sensitive
array('*[lang|="en"]', array()),
array('[lang|="en-US"]', array()),
array('*[lang|="e"]', array()),
['*[lang|="en"]', []],
['[lang|="en-US"]', []],
['*[lang|="e"]', []],
// ... :lang() is not.
array(':lang("EN")', array('second-li', 'li-div')),
array('*:lang(en-US)', array('second-li', 'li-div')),
array(':lang("e")', array()),
array('li:nth-child(3)', array('third-li')),
array('li:nth-child(10)', array()),
array('li:nth-child(2n)', array('second-li', 'fourth-li', 'sixth-li')),
array('li:nth-child(even)', array('second-li', 'fourth-li', 'sixth-li')),
array('li:nth-child(2n+0)', array('second-li', 'fourth-li', 'sixth-li')),
array('li:nth-child(+2n+1)', array('first-li', 'third-li', 'fifth-li', 'seventh-li')),
array('li:nth-child(odd)', array('first-li', 'third-li', 'fifth-li', 'seventh-li')),
array('li:nth-child(2n+4)', array('fourth-li', 'sixth-li')),
array('li:nth-child(3n+1)', array('first-li', 'fourth-li', 'seventh-li')),
array('li:nth-child(n)', array('first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li')),
array('li:nth-child(n-1)', array('first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li')),
array('li:nth-child(n+1)', array('first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li')),
array('li:nth-child(n+3)', array('third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li')),
array('li:nth-child(-n)', array()),
array('li:nth-child(-n-1)', array()),
array('li:nth-child(-n+1)', array('first-li')),
array('li:nth-child(-n+3)', array('first-li', 'second-li', 'third-li')),
array('li:nth-last-child(0)', array()),
array('li:nth-last-child(2n)', array('second-li', 'fourth-li', 'sixth-li')),
array('li:nth-last-child(even)', array('second-li', 'fourth-li', 'sixth-li')),
array('li:nth-last-child(2n+2)', array('second-li', 'fourth-li', 'sixth-li')),
array('li:nth-last-child(n)', array('first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li')),
array('li:nth-last-child(n-1)', array('first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li')),
array('li:nth-last-child(n-3)', array('first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li')),
array('li:nth-last-child(n+1)', array('first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li')),
array('li:nth-last-child(n+3)', array('first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li')),
array('li:nth-last-child(-n)', array()),
array('li:nth-last-child(-n-1)', array()),
array('li:nth-last-child(-n+1)', array('seventh-li')),
array('li:nth-last-child(-n+3)', array('fifth-li', 'sixth-li', 'seventh-li')),
array('ol:first-of-type', array('first-ol')),
array('ol:nth-child(1)', array('first-ol')),
array('ol:nth-of-type(2)', array('second-ol')),
array('ol:nth-last-of-type(1)', array('second-ol')),
array('span:only-child', array('foobar-span')),
array('li div:only-child', array('li-div')),
array('div *:only-child', array('li-div', 'foobar-span')),
array('p:only-of-type', array('paragraph')),
array('a:empty', array('name-anchor')),
array('a:EMpty', array('name-anchor')),
array('li:empty', array('third-li', 'fourth-li', 'fifth-li', 'sixth-li')),
array(':root', array('html')),
array('html:root', array('html')),
array('li:root', array()),
array('* :root', array()),
array('*:contains("link")', array('html', 'outer-div', 'tag-anchor', 'nofollow-anchor')),
array(':CONtains("link")', array('html', 'outer-div', 'tag-anchor', 'nofollow-anchor')),
array('*:contains("LInk")', array()), // case sensitive
array('*:contains("e")', array('html', 'nil', 'outer-div', 'first-ol', 'first-li', 'paragraph', 'p-em')),
array('*:contains("E")', array()), // case-sensitive
array('.a', array('first-ol')),
array('.b', array('first-ol')),
array('*.a', array('first-ol')),
array('ol.a', array('first-ol')),
array('.c', array('first-ol', 'third-li', 'fourth-li')),
array('*.c', array('first-ol', 'third-li', 'fourth-li')),
array('ol *.c', array('third-li', 'fourth-li')),
array('ol li.c', array('third-li', 'fourth-li')),
array('li ~ li.c', array('third-li', 'fourth-li')),
array('ol > li.c', array('third-li', 'fourth-li')),
array('#first-li', array('first-li')),
array('li#first-li', array('first-li')),
array('*#first-li', array('first-li')),
array('li div', array('li-div')),
array('li > div', array('li-div')),
array('div div', array('li-div')),
array('div > div', array()),
array('div>.c', array('first-ol')),
array('div > .c', array('first-ol')),
array('div + div', array('foobar-div')),
array('a ~ a', array('tag-anchor', 'nofollow-anchor')),
array('a[rel="tag"] ~ a', array('nofollow-anchor')),
array('ol#first-ol li:last-child', array('seventh-li')),
array('ol#first-ol *:last-child', array('li-div', 'seventh-li')),
array('#outer-div:first-child', array('outer-div')),
array('#outer-div :first-child', array('name-anchor', 'first-li', 'li-div', 'p-b', 'checkbox-fieldset-disabled', 'area-href')),
array('a[href]', array('tag-anchor', 'nofollow-anchor')),
array(':not(*)', array()),
array('a:not([href])', array('name-anchor')),
array('ol :Not(li[class])', array('first-li', 'second-li', 'li-div', 'fifth-li', 'sixth-li', 'seventh-li')),
[':lang("EN")', ['second-li', 'li-div']],
['*:lang(en-US)', ['second-li', 'li-div']],
[':lang("e")', []],
['li:nth-child(3)', ['third-li']],
['li:nth-child(10)', []],
['li:nth-child(2n)', ['second-li', 'fourth-li', 'sixth-li']],
['li:nth-child(even)', ['second-li', 'fourth-li', 'sixth-li']],
['li:nth-child(2n+0)', ['second-li', 'fourth-li', 'sixth-li']],
['li:nth-child(+2n+1)', ['first-li', 'third-li', 'fifth-li', 'seventh-li']],
['li:nth-child(odd)', ['first-li', 'third-li', 'fifth-li', 'seventh-li']],
['li:nth-child(2n+4)', ['fourth-li', 'sixth-li']],
['li:nth-child(3n+1)', ['first-li', 'fourth-li', 'seventh-li']],
['li:nth-child(n)', ['first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li']],
['li:nth-child(n-1)', ['first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li']],
['li:nth-child(n+1)', ['first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li']],
['li:nth-child(n+3)', ['third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li']],
['li:nth-child(-n)', []],
['li:nth-child(-n-1)', []],
['li:nth-child(-n+1)', ['first-li']],
['li:nth-child(-n+3)', ['first-li', 'second-li', 'third-li']],
['li:nth-last-child(0)', []],
['li:nth-last-child(2n)', ['second-li', 'fourth-li', 'sixth-li']],
['li:nth-last-child(even)', ['second-li', 'fourth-li', 'sixth-li']],
['li:nth-last-child(2n+2)', ['second-li', 'fourth-li', 'sixth-li']],
['li:nth-last-child(n)', ['first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li']],
['li:nth-last-child(n-1)', ['first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li']],
['li:nth-last-child(n-3)', ['first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li']],
['li:nth-last-child(n+1)', ['first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li', 'sixth-li', 'seventh-li']],
['li:nth-last-child(n+3)', ['first-li', 'second-li', 'third-li', 'fourth-li', 'fifth-li']],
['li:nth-last-child(-n)', []],
['li:nth-last-child(-n-1)', []],
['li:nth-last-child(-n+1)', ['seventh-li']],
['li:nth-last-child(-n+3)', ['fifth-li', 'sixth-li', 'seventh-li']],
['ol:first-of-type', ['first-ol']],
['ol:nth-child(1)', ['first-ol']],
['ol:nth-of-type(2)', ['second-ol']],
['ol:nth-last-of-type(1)', ['second-ol']],
['span:only-child', ['foobar-span']],
['li div:only-child', ['li-div']],
['div *:only-child', ['li-div', 'foobar-span']],
['p:only-of-type', ['paragraph']],
['a:empty', ['name-anchor']],
['a:EMpty', ['name-anchor']],
['li:empty', ['third-li', 'fourth-li', 'fifth-li', 'sixth-li']],
[':root', ['html']],
['html:root', ['html']],
['li:root', []],
['* :root', []],
['*:contains("link")', ['html', 'outer-div', 'tag-anchor', 'nofollow-anchor']],
[':CONtains("link")', ['html', 'outer-div', 'tag-anchor', 'nofollow-anchor']],
['*:contains("LInk")', []], // case sensitive
['*:contains("e")', ['html', 'nil', 'outer-div', 'first-ol', 'first-li', 'paragraph', 'p-em']],
['*:contains("E")', []], // case-sensitive
['.a', ['first-ol']],
['.b', ['first-ol']],
['*.a', ['first-ol']],
['ol.a', ['first-ol']],
['.c', ['first-ol', 'third-li', 'fourth-li']],
['*.c', ['first-ol', 'third-li', 'fourth-li']],
['ol *.c', ['third-li', 'fourth-li']],
['ol li.c', ['third-li', 'fourth-li']],
['li ~ li.c', ['third-li', 'fourth-li']],
['ol > li.c', ['third-li', 'fourth-li']],
['#first-li', ['first-li']],
['li#first-li', ['first-li']],
['*#first-li', ['first-li']],
['li div', ['li-div']],
['li > div', ['li-div']],
['div div', ['li-div']],
['div > div', []],
['div>.c', ['first-ol']],
['div > .c', ['first-ol']],
['div + div', ['foobar-div']],
['a ~ a', ['tag-anchor', 'nofollow-anchor']],
['a[rel="tag"] ~ a', ['nofollow-anchor']],
['ol#first-ol li:last-child', ['seventh-li']],
['ol#first-ol *:last-child', ['li-div', 'seventh-li']],
['#outer-div:first-child', ['outer-div']],
['#outer-div :first-child', ['name-anchor', 'first-li', 'li-div', 'p-b', 'checkbox-fieldset-disabled', 'area-href']],
['a[href]', ['tag-anchor', 'nofollow-anchor']],
[':not(*)', []],
['a:not([href])', ['name-anchor']],
['ol :Not(li[class])', ['first-li', 'second-li', 'li-div', 'fifth-li', 'sixth-li', 'seventh-li']],
// HTML-specific
array(':link', array('link-href', 'tag-anchor', 'nofollow-anchor', 'area-href')),
array(':visited', array()),
array(':enabled', array('link-href', 'tag-anchor', 'nofollow-anchor', 'checkbox-unchecked', 'text-checked', 'checkbox-checked', 'area-href')),
array(':disabled', array('checkbox-disabled', 'checkbox-disabled-checked', 'fieldset', 'checkbox-fieldset-disabled')),
array(':checked', array('checkbox-checked', 'checkbox-disabled-checked')),
);
[':link', ['link-href', 'tag-anchor', 'nofollow-anchor', 'area-href']],
[':visited', []],
[':enabled', ['link-href', 'tag-anchor', 'nofollow-anchor', 'checkbox-unchecked', 'text-checked', 'checkbox-checked', 'area-href']],
[':disabled', ['checkbox-disabled', 'checkbox-disabled-checked', 'fieldset', 'checkbox-fieldset-disabled']],
[':checked', ['checkbox-checked', 'checkbox-disabled-checked']],
];
}
public function getHtmlShakespearTestData()
{
return array(
array('*', 246),
array('div:contains(CELIA)', 26),
array('div:only-child', 22), // ?
array('div:nth-child(even)', 106),
array('div:nth-child(2n)', 106),
array('div:nth-child(odd)', 137),
array('div:nth-child(2n+1)', 137),
array('div:nth-child(n)', 243),
array('div:last-child', 53),
array('div:first-child', 51),
array('div > div', 242),
array('div + div', 190),
array('div ~ div', 190),
array('body', 1),
array('body div', 243),
array('div', 243),
array('div div', 242),
array('div div div', 241),
array('div, div, div', 243),
array('div, a, span', 243),
array('.dialog', 51),
array('div.dialog', 51),
array('div .dialog', 51),
array('div.character, div.dialog', 99),
array('div.direction.dialog', 0),
array('div.dialog.direction', 0),
array('div.dialog.scene', 1),
array('div.scene.scene', 1),
array('div.scene .scene', 0),
array('div.direction .dialog ', 0),
array('div .dialog .direction', 4),
array('div.dialog .dialog .direction', 4),
array('#speech5', 1),
array('div#speech5', 1),
array('div #speech5', 1),
array('div.scene div.dialog', 49),
array('div#scene1 div.dialog div', 142),
array('#scene1 #speech1', 1),
array('div[class]', 103),
array('div[class=dialog]', 50),
array('div[class^=dia]', 51),
array('div[class$=log]', 50),
array('div[class*=sce]', 1),
array('div[class|=dialog]', 50), // ? Seems right
array('div[class!=madeup]', 243), // ? Seems right
array('div[class~=dialog]', 51), // ? Seems right
);
return [
['*', 246],
['div:contains(CELIA)', 26],
['div:only-child', 22], // ?
['div:nth-child(even)', 106],
['div:nth-child(2n)', 106],
['div:nth-child(odd)', 137],
['div:nth-child(2n+1)', 137],
['div:nth-child(n)', 243],
['div:last-child', 53],
['div:first-child', 51],
['div > div', 242],
['div + div', 190],
['div ~ div', 190],
['body', 1],
['body div', 243],
['div', 243],
['div div', 242],
['div div div', 241],
['div, div, div', 243],
['div, a, span', 243],
['.dialog', 51],
['div.dialog', 51],
['div .dialog', 51],
['div.character, div.dialog', 99],
['div.direction.dialog', 0],
['div.dialog.direction', 0],
['div.dialog.scene', 1],
['div.scene.scene', 1],
['div.scene .scene', 0],
['div.direction .dialog ', 0],
['div .dialog .direction', 4],
['div.dialog .dialog .direction', 4],
['#speech5', 1],
['div#speech5', 1],
['div #speech5', 1],
['div.scene div.dialog', 49],
['div#scene1 div.dialog div', 142],
['#scene1 #speech1', 1],
['div[class]', 103],
['div[class=dialog]', 50],
['div[class^=dia]', 51],
['div[class$=log]', 50],
['div[class*=sce]', 1],
['div[class|=dialog]', 50], // ? Seems right
['div[class!=madeup]', 243], // ? Seems right
['div[class~=dialog]', 51], // ? Seems right
];
}
}