From 9ea175b6f8edec83771a05cb128778a8ab7c2953 Mon Sep 17 00:00:00 2001 From: Jake Jackson Date: Wed, 30 Sep 2026 18:13:49 +1000 Subject: [PATCH 1/2] Match the universal selector * in the standard CSS mode (mpdf/mpdf#312) * matches every element: alone, with a class, an id, an attribute or a pseudo-class, on either side of a combinator, and inside :is(), :where() and :not(). It weighs nothing, and reaches body as the document's root, below body's own rules. mPDF's barcode, dottab and textcircle are only reached by a rule naming their tag, or an id or class they carry. The legacy mode keeps dropping these rules. A row border that draws nothing, as a * { border-color } reset gives every row, no longer takes a collapsed table's cell borders away, and a row's top or bottom border is drawn without a left one. Co-Authored-By: Claude Opus 5.5 --- CHANGELOG-GRAVITYPDF.md | 10 +- src/Css/CssMerger.php | 2 +- src/Css/CssParser.php | 4 +- src/Css/RuleSet.php | 13 +- src/Css/SelectorCompiler.php | 20 +- src/Tag/Td.php | 6 +- src/Tag/Tr.php | 17 +- tests/Mpdf/Css/CssParserTest.php | 9 +- tests/Mpdf/Css/RuleSetTest.php | 24 + tests/Mpdf/Css/SelectorCompilerTest.php | 38 +- tests/Mpdf/Css/SelectorMatcherTest.php | 19 + tests/Mpdf/LogicalSelectorTest.php | 4 +- tests/Mpdf/StructuralSelectorTest.php | 8 +- tests/Mpdf/Tag/TrBordersTest.php | 112 +++++ tests/Mpdf/UniversalSelectorTest.php | 457 ++++++++++++++++++ .../UniversalSelectorSnapshotTest.php | 160 ++++++ .../UniversalStylesheetSnapshotTest.php | 110 +++++ tests/data/snapshots/universal-selector.pdf | Bin 0 -> 79868 bytes tests/data/snapshots/universal-stylesheet.pdf | Bin 0 -> 74506 bytes 19 files changed, 954 insertions(+), 59 deletions(-) create mode 100644 tests/Mpdf/UniversalSelectorTest.php create mode 100644 tests/Snapshots/UniversalSelectorSnapshotTest.php create mode 100644 tests/Snapshots/UniversalStylesheetSnapshotTest.php create mode 100644 tests/data/snapshots/universal-selector.pdf create mode 100644 tests/data/snapshots/universal-stylesheet.pdf diff --git a/CHANGELOG-GRAVITYPDF.md b/CHANGELOG-GRAVITYPDF.md index ee436a7a5..8ddf87fbd 100644 --- a/CHANGELOG-GRAVITYPDF.md +++ b/CHANGELOG-GRAVITYPDF.md @@ -127,6 +127,9 @@ New features * `WriteHTML()` reads ahead through the HTML it is given to count each element's children. An element still open at the end of a call that leaves it open is not known in full, so these do not match its children in that call, and nor does `:not()` of them. * `:empty` matches as in browsers: an element holding white space is not empty, and one holding only a comment is. A table cell holding only white space is empty, as mPDF strips it. * **`:root`, `html`, `:link` and `:any-link`, in standard mode.** `a:link` and `:any-link` match a link with an `href`. mPDF has no `html` element, so `html` and `:root` match it as the parent of `body`: their rules reach the text as a parent's would, and rules for `body` win over them. `:visited`, `:hover`, `:focus`, `:active`, `:focus-within`, `:focus-visible` and `:target` never match, as a PDF is never visited or hovered, so `:not(:hover)` always does. Rules using them were dropped before, so a document that has them changes. Set `'cssMode' => \Mpdf\CssMode::LEGACY` to keep dropping them. [#529] [#642] +* **The universal selector.** `*` matches every element: alone, with a class, an id, an attribute or a pseudo-class, on either side of a combinator, and inside `:is()`, `:where()` and `:not()`. It weighs nothing, so any rule naming a tag, class, id, attribute or pseudo-class beats it. It reaches `html` and `body` too, so `* { color: … }` colours text written straight into the body, and `* { font-size: … }` sets the size `rem` is read against. Rules using it were dropped before, so a document that has them changes. Set `'cssMode' => \Mpdf\CssMode::LEGACY` to keep dropping them. [mpdf/mpdf#312] [mpdf/mpdf#1168] [mpdf/mpdf#1838] [#530] [#644] + * A reset such as `* { margin: 0; padding: 0 }` now takes away the default margins of paragraphs, headings and lists, a list's indent and a cell's padding, as in a browser. It reaches the lines of the table of contents and the index as well, which are the document's elements, so their levels are no longer indented. Style `div.mpdf_toc_level_1` and the like to indent them again. + * mPDF's own ``, `` and `` are not HTML elements. A rule reaches them only by naming their tag, or an id or class they carry, so `*`, and `:empty`, `[attr]` or `:not()` alone, leave them as they are: `:empty { display: none }` does not hide a barcode. Performance ----------- @@ -218,6 +221,7 @@ Bugfixes * `background-size` lengths such as `60mm` or `100px` drew the image 2.83 times too small, because they were used as points. [#574] * A stylesheet `url()` did not load its image when the path had spaces or parentheses, when there was whitespace inside the parentheses, or when it was an SVG data URI that is not base64, such as Bootstrap's `form-select` arrow. [#573] * `linear-gradient(to bottom, …)` and `to top` were drawn upside down, and so was the vertical half of `to bottom right` and the other corners. Angles ran counter-clockwise from pointing right, so `90deg` drew bottom to top. A gradient now runs as CSS Images gives: `0deg` points up and angles turn clockwise, `turn` is read, and a corner keyword leaves the other two corners halfway along. `-moz-`, `-webkit-` and `-o-` gradients keep their legacy angles, and their side keyword, such as `left`, names the side the gradient starts from. Set `'cssMode' => \Mpdf\CssMode::LEGACY` to keep the directions mPDF v7 drew, prefixed or not. [#577] [#639] +* In a table with collapsed borders, a row with a `border-color` and no border style, or a border of no width, took the borders of its cells away. A reset such as `* { border-color: #dee2e6 }` or `* { border: 0 solid }` gives every row a border like that. A row border that draws nothing now leaves the cells' borders; `hidden` still takes them away. A row's `border-top` or `border-bottom` was drawn only when the row also set `border-left`; each side is now drawn on its own. [#644] * Characters mPDF moved into a substitute font (`useSubstitutions`, and the fonts for supplementary planes) were wrapped in a `` that stylesheet rules reached, so `span { border: 1px solid }` drew a box around them, and the span counted among its siblings for `:nth-child()`. In the standard CSS mode no rule reaches that span and it is not counted, as a browser has no such element. The legacy mode styles it as before. [#634] ### Images and SVG @@ -414,12 +418,14 @@ These changes do not change output. [mpdf/mpdf#7]: https://github.com/mpdf/mpdf/issues/7 [mpdf/mpdf#83]: https://github.com/mpdf/mpdf/issues/83 [mpdf/mpdf#134]: https://github.com/mpdf/mpdf/issues/134 +[mpdf/mpdf#312]: https://github.com/mpdf/mpdf/issues/312 [mpdf/mpdf#318]: https://github.com/mpdf/mpdf/issues/318 [mpdf/mpdf#747]: https://github.com/mpdf/mpdf/issues/747 [mpdf/mpdf#830]: https://github.com/mpdf/mpdf/issues/830 [mpdf/mpdf#833]: https://github.com/mpdf/mpdf/issues/833 [mpdf/mpdf#1010]: https://github.com/mpdf/mpdf/issues/1010 [mpdf/mpdf#1089]: https://github.com/mpdf/mpdf/issues/1089 +[mpdf/mpdf#1168]: https://github.com/mpdf/mpdf/issues/1168 [mpdf/mpdf#1220]: https://github.com/mpdf/mpdf/issues/1220 [mpdf/mpdf#1334]: https://github.com/mpdf/mpdf/issues/1334 [mpdf/mpdf#1368]: https://github.com/mpdf/mpdf/issues/1368 @@ -810,6 +816,7 @@ These changes do not change output. [#527]: https://github.com/GravityPDF/mpdf/issues/527 [#528]: https://github.com/GravityPDF/mpdf/issues/528 [#529]: https://github.com/GravityPDF/mpdf/issues/529 +[#530]: https://github.com/GravityPDF/mpdf/issues/530 [#531]: https://github.com/GravityPDF/mpdf/issues/531 [#532]: https://github.com/GravityPDF/mpdf/issues/532 [#533]: https://github.com/GravityPDF/mpdf/issues/533 @@ -871,5 +878,6 @@ These changes do not change output. [#639]: https://github.com/GravityPDF/mpdf/pull/639 [#641]: https://github.com/GravityPDF/mpdf/pull/641 [#646]: https://github.com/GravityPDF/mpdf/pull/646 -[#643]: https://github.com/GravityPDF/mpdf/pull/643 [#642]: https://github.com/GravityPDF/mpdf/pull/642 +[#643]: https://github.com/GravityPDF/mpdf/pull/643 +[#644]: https://github.com/GravityPDF/mpdf/pull/644 diff --git a/src/Css/CssMerger.php b/src/Css/CssMerger.php index 7c1b40f1f..4c363220e 100644 --- a/src/Css/CssMerger.php +++ b/src/Css/CssMerger.php @@ -241,7 +241,7 @@ private function mergeInCascadeOrder($inherit, $tag, array $attr) * Merges html's rules into body's CSS, and body's own rules again over them. mPDF has no html element: the * document's frame stands for body, and html is matched as its parent, so html's declarations, its !important * ones included, reach the text as a parent's would, and lose to body's. Both win over what SetDefaultBodyCSS() and - * the like set. + * the like set. The rules for any element, such as *, are among the rules of each. * * html's font size, read against the default font size, is the root's, which rem and body's own size are read * against diff --git a/src/Css/CssParser.php b/src/Css/CssParser.php index 0b4da5eba..fff58e413 100644 --- a/src/Css/CssParser.php +++ b/src/Css/CssParser.php @@ -468,9 +468,7 @@ private function compileRule($selector, array $classProperties, array $important } $compiled = $this->selectorCompiler->compile($selector); - - // The universal selector changes which elements existing documents style, so it waits for #530 - if ($compiled !== null && !$compiled['universal'] && !$compiled['never']) { + if ($compiled !== null && !$compiled['never']) { $this->compiledRules[] = [$compiled, $classProperties, $important]; } } diff --git a/src/Css/RuleSet.php b/src/Css/RuleSet.php index 1c7b69441..126617429 100644 --- a/src/Css/RuleSet.php +++ b/src/Css/RuleSet.php @@ -10,6 +10,13 @@ class RuleSet { + /** + * @var array The tags mPDF adds to HTML that take CSS. They are not HTML elements, and draw what + * their attributes describe, so a rule reaches one only by naming its tag, or an id or a + * class it has: *, :empty or [title] alone does not + */ + private static $ownTags = ['BARCODE' => true, 'DOTTAB' => true, 'TEXTCIRCLE' => true]; + /** * @var array[] Each rule, by its position in the stylesheets read: [compiled selector, declarations, the ancestors * it requires as requiredAncestors() gives them, !important declarations] @@ -54,7 +61,7 @@ public function add(array $selector, array $declarations, array $important = []) * The rules an element could match, going by the rightmost compound of each. The rest of each selector is still * to be matched * - * @param string $tag Uppercased + * @param string $tag Uppercased, or empty for the document itself, which is matched as body * @param string $id Uppercased, or empty for none * @param string[] $classes Uppercased * @@ -69,7 +76,7 @@ public function candidates($tag, $id, array $classes) * The declarations of the rules an element matches, in the order they apply: by specificity, then by position. * The normal declarations and the !important ones are given apart, as they apply in different layers * - * @param string $tag Uppercased + * @param string $tag Uppercased, or empty for the document itself, which is matched as body * @param string $id Uppercased, or empty for none * @param string[] $classes Uppercased * @param callable $path Gives the open elements from the document down to the element, or null for none. Only @@ -204,7 +211,7 @@ private static function file(array &$index, array $subject, $position) */ private static function collect(array $index, $tag, $id, array $classes) { - $positions = $index['any']; + $positions = isset(self::$ownTags[$tag]) ? [] : $index['any']; if (isset($index['tag'][$tag])) { $positions = array_merge($positions, $index['tag'][$tag]); } diff --git a/src/Css/SelectorCompiler.php b/src/Css/SelectorCompiler.php index f1e7676f1..283577845 100644 --- a/src/Css/SelectorCompiler.php +++ b/src/Css/SelectorCompiler.php @@ -15,7 +15,6 @@ * Mpdf::WriteHTML() leaves an element's tag, id and classes. * - combinators: the combinator after each compound but the last, one of ' ', '>', '+' and '~' * - specificity: [ids, classes and attributes and pseudo-classes, tags] - * - universal: whether it names the universal selector * * - never: whether one of its compounds holds a pseudo-class that no element in a PDF matches, so that it matches * nothing * @@ -150,11 +149,10 @@ private function parseComplex($text, &$pos) $compounds = []; $combinators = []; $specificity = [0, 0, 0]; - $universal = false; $never = false; while (true) { - $compound = $this->parseCompound($text, $pos, $specificity, $universal); + $compound = $this->parseCompound($text, $pos, $specificity); if ($compound === null) { return null; } @@ -181,7 +179,6 @@ private function parseComplex($text, &$pos) 'compounds' => $compounds, 'combinators' => $combinators, 'specificity' => $specificity, - 'universal' => $universal, 'never' => $never, ]; } @@ -193,18 +190,16 @@ private function parseComplex($text, &$pos) * @param string $text * @param int $pos * @param int[] $specificity Added to for what is read - * @param bool $universal Set when the compound names * * * @return array|null */ - private function parseCompound($text, &$pos, array &$specificity, &$universal) + private function parseCompound($text, &$pos, array &$specificity) { $length = strlen($text); $compound = ['tag' => null, 'ids' => [], 'classes' => [], 'attributes' => [], 'pseudos' => []]; $start = $pos; if ($pos < $length && $text[$pos] === '*') { - $universal = true; $pos++; } elseif ($this->startsIdentifier($text, $pos)) { $compound['tag'] = strtoupper($this->readName($text, $pos)); @@ -241,7 +236,7 @@ private function parseCompound($text, &$pos, array &$specificity, &$universal) $specificity[1]++; } elseif ($c === ':') { $pos++; - $pseudo = $this->parsePseudoClass($text, $pos, $specificity, $universal); + $pseudo = $this->parsePseudoClass($text, $pos, $specificity); if ($pseudo === null) { return null; } @@ -261,11 +256,10 @@ private function parseCompound($text, &$pos, array &$specificity, &$universal) * @param string $text * @param int $pos * @param int[] $specificity Added to for the pseudo-class - * @param bool $universal Set when an argument names * * * @return array|null As the class describes, or null for a pseudo-element or a pseudo-class mPDF cannot match */ - private function parsePseudoClass($text, &$pos, array &$specificity, &$universal) + private function parsePseudoClass($text, &$pos, array &$specificity) { if (!$this->startsIdentifier($text, $pos)) { return null; @@ -291,7 +285,7 @@ private function parsePseudoClass($text, &$pos, array &$specificity, &$universal } if ($name === 'not' || $name === 'is' || $name === 'where') { - return $this->parseSelectorArgument($name, $argument, $specificity, $universal); + return $this->parseSelectorArgument($name, $argument, $specificity); } if ($name === 'lang') { @@ -316,11 +310,10 @@ private function parsePseudoClass($text, &$pos, array &$specificity, &$universal * @param string $name not, is or where * @param string $argument * @param int[] $specificity Added to for the most specific selector, except for :where() - * @param bool $universal Set when a selector names * * * @return array|null */ - private function parseSelectorArgument($name, $argument, array &$specificity, &$universal) + private function parseSelectorArgument($name, $argument, array &$specificity) { $selectors = []; $heaviest = [0, 0, 0]; @@ -334,7 +327,6 @@ private function parseSelectorArgument($name, $argument, array &$specificity, &$ } $selectors[] = $compiled; - $universal = $universal || $compiled['universal']; if ($compiled['specificity'] > $heaviest) { $heaviest = $compiled['specificity']; } diff --git a/src/Tag/Td.php b/src/Tag/Td.php index 2a137794e..7d19c5bc6 100644 --- a/src/Tag/Td.php +++ b/src/Tag/Td.php @@ -337,9 +337,9 @@ public function open($attr, &$ahtml, &$ihtml) $table['border'] = $table['simple']['border']; } - // Border set on TR (if collapsed only) - if (!$table['borders_separate'] && !$this->mpdf->simpleTables && isset($table['trborder-left'][$this->mpdf->row])) { - if ($this->mpdf->col == 0) { + // Border set on TR (if collapsed only), on each side it sets + if (!$table['borders_separate'] && !$this->mpdf->simpleTables) { + if ($this->mpdf->col == 0 && isset($table['trborder-left'][$this->mpdf->row])) { $left = $this->mpdf->border_details($table['trborder-left'][$this->mpdf->row]); $c['border_details']['L'] = $left; $this->mpdf->setBorder($c['border'], Border::LEFT, $c['border_details']['L']['s']); diff --git a/src/Tag/Tr.php b/src/Tag/Tr.php index 175489e72..4d8d8f8fa 100644 --- a/src/Tag/Tr.php +++ b/src/Tag/Tr.php @@ -30,17 +30,12 @@ public function open($attr, &$ahtml, &$ihtml) if (!$this->mpdf->simpleTables && (!isset($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['borders_separate']) || !$this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['borders_separate'])) { - if (!empty($properties['BORDER-LEFT'])) { - $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['trborder-left'][$this->mpdf->row] = $properties['BORDER-LEFT']; - } - if (!empty($properties['BORDER-RIGHT'])) { - $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['trborder-right'][$this->mpdf->row] = $properties['BORDER-RIGHT']; - } - if (!empty($properties['BORDER-TOP'])) { - $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['trborder-top'][$this->mpdf->row] = $properties['BORDER-TOP']; - } - if (!empty($properties['BORDER-BOTTOM'])) { - $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['trborder-bottom'][$this->mpdf->row] = $properties['BORDER-BOTTOM']; + // Kept only for a side the row draws, or hides with hidden: a border that draws nothing, such as a + // border-color alone, leaves the cells' borders + foreach (['LEFT', 'RIGHT', 'TOP', 'BOTTOM'] as $side) { + if (!empty($properties['BORDER-' . $side]) && $this->mpdf->border_details($properties['BORDER-' . $side])['s']) { + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['trborder-' . strtolower($side)][$this->mpdf->row] = $properties['BORDER-' . $side]; + } } } diff --git a/tests/Mpdf/Css/CssParserTest.php b/tests/Mpdf/Css/CssParserTest.php index bff52d2bb..7fe14bbca 100644 --- a/tests/Mpdf/Css/CssParserTest.php +++ b/tests/Mpdf/Css/CssParserTest.php @@ -277,6 +277,13 @@ public function routedSelectors() 'link' => ['a:link', true], 'any-link' => [':any-link', true], 'not hover' => ['p:not(:hover)', true], + 'universal' => ['*', true], + 'universal with a class' => ['*.a', true], + 'universal with an id' => ['*#i', true], + 'universal as a descendant' => ['div *', true], + 'universal as an ancestor' => ['* p', true], + 'universal as a sibling' => ['* + p', true], + 'universal in not' => ['p:not(*)', true], ]; } @@ -315,8 +322,6 @@ public function droppedSelectors() 'first-line and first-letter' => ['p::first-line, p:first-letter'], 'has' => ['li:has(> a)'], 'a tag outside allowedCSStags' => ['div > sup'], - 'the universal selector, which waits for #530' => ['div > *'], - 'the universal selector as an ancestor' => ['* + p'], ]; } diff --git a/tests/Mpdf/Css/RuleSetTest.php b/tests/Mpdf/Css/RuleSetTest.php index 713f4642d..84f56662f 100644 --- a/tests/Mpdf/Css/RuleSetTest.php +++ b/tests/Mpdf/Css/RuleSetTest.php @@ -88,6 +88,12 @@ public function elements() 'a class written twice' => ['DIV', '', ['B', 'B'], [2, 3]], 'a span' => ['SPAN', '', [], [3, 4]], 'a tag no rule names' => ['LI', '', [], [3]], + 'the document, matched as body' => ['', '', [], [3]], + "mPDF's barcode" => ['BARCODE', '', [], []], + "mPDF's dot tab" => ['DOTTAB', '', [], []], + "mPDF's text circle" => ['TEXTCIRCLE', '', [], []], + "mPDF's barcode with a class a rule is filed under" => ['BARCODE', '', ['B'], [2]], + "mPDF's barcode with an id a rule is filed under" => ['BARCODE', 'MAIN', [], [1]], ]; } @@ -159,6 +165,24 @@ public function testGivesTheImportantDeclarationsApartInTheSameOrder() ); } + /** + * The document's own frame is matched as body, by the rules filed for any element alone: the universal selector + * and the other rules whose subject names no tag, id or class, when they match the root + */ + public function testMatchesTheDocumentAsBodyWithTheRulesForAnyElement() + { + $rules = new RuleSet(); + foreach (['*', 'body', '* > *', ':not(p)', ':not(body)', '*:first-child', '*.a', '*:lang(fr)'] as $position => $selector) { + $rules->add($this->compiler->compile($selector), ['COLOR' => 'rule ' . $position]); + } + + $path = function () { + return array_slice($this->path(), 0, 1); + }; + + $this->assertSame([['COLOR' => 'rule 0'], ['COLOR' => 'rule 3']], $rules->matchingDeclarations('', '', [], $path)); + } + /** * The open elements are only asked for when a rule is filed under the element */ diff --git a/tests/Mpdf/Css/SelectorCompilerTest.php b/tests/Mpdf/Css/SelectorCompilerTest.php index 4ca571858..fc4ba3ced 100644 --- a/tests/Mpdf/Css/SelectorCompilerTest.php +++ b/tests/Mpdf/Css/SelectorCompilerTest.php @@ -112,6 +112,7 @@ public function selectors() $tag = function ($tag) { return ['tag' => $tag, 'ids' => [], 'classes' => [], 'pseudos' => []]; }; + $any = ['compounds' => [['tag' => null, 'ids' => [], 'classes' => [], 'attributes' => [], 'pseudos' => []]], 'combinators' => [], 'specificity' => [0, 0, 0]]; return [ 'type' => ['p', [$tag('P')], []], @@ -151,7 +152,7 @@ public function selectors() 'only-of-type' => ['p:only-of-type', [['tag' => 'P', 'pseudos' => [['only-of-type']]]], []], 'empty' => ['p:empty', [['tag' => 'P', 'pseudos' => [['empty']]]], []], 'first and last together' => ['td:first-child:last-child', [['tag' => 'TD', 'pseudos' => [['nth-child', 0, 1], ['nth-last-child', 0, 1]]]], []], - 'last-child in not' => [':not(:last-child)', [['pseudos' => [['not', [['compounds' => [['tag' => null, 'ids' => [], 'classes' => [], 'attributes' => [], 'pseudos' => [['nth-last-child', 0, 1]]]], 'combinators' => [], 'specificity' => [0, 1, 0], 'universal' => false, 'never' => false]]]]]], []], + 'last-child in not' => [':not(:last-child)', [['pseudos' => [['not', [['compounds' => [['tag' => null, 'ids' => [], 'classes' => [], 'attributes' => [], 'pseudos' => [['nth-last-child', 0, 1]]]], 'combinators' => [], 'specificity' => [0, 1, 0], 'never' => false]]]]]], []], 'root' => [':root', [['tag' => null, 'pseudos' => [['root']]]], []], 'html' => ['HTML > body', [$tag('HTML'), $tag('BODY')], ['>']], 'link' => ['a:link', [['tag' => 'A', 'pseudos' => [['link']]]], []], @@ -165,6 +166,23 @@ public function selectors() [['tag' => 'P', 'pseudos' => [['lang', ['fr', 'de-at', 'en']]]]], [], ], + 'universal' => ['*', [$tag(null)], []], + 'universal with a class' => ['*.note', [['tag' => null, 'classes' => ['NOTE']]], []], + 'universal with an id' => ['*#main', [['tag' => null, 'ids' => ['MAIN']]], []], + 'universal with an attribute' => ['*[title]', [['tag' => null, 'attributes' => [['TITLE', '', '', false]]]], []], + 'universal as the subject of a descendant' => ['div *', [$tag('DIV'), $tag(null)], [' ']], + 'universal as an ancestor' => ['* p', [$tag(null), $tag('P')], [' ']], + 'universal as the subject of a child' => ['div>*', [$tag('DIV'), $tag(null)], ['>']], + 'universal as a sibling' => ['* + p', [$tag(null), $tag('P')], ['+']], + 'universal on both sides' => ['* ~ *', [$tag(null), $tag(null)], ['~']], + 'universal in is and not' => [ + ':is(*) + p:not(*)', + [ + ['tag' => null, 'pseudos' => [['is', [$any]]]], + ['tag' => 'P', 'pseudos' => [['not', [$any]]]], + ], + ['+'], + ], 'attribute in a chain' => [ 'div[data-role="card"] > a[href]', [['tag' => 'DIV', 'attributes' => [['DATA-ROLE', '=', 'card', false]]], ['tag' => 'A', 'attributes' => [['HREF', '', '', false]]]], @@ -362,6 +380,10 @@ public function specificities() 'id' => ['#i', [1, 0, 0]], 'every kind' => ['div#i.a.b p:first-child', [1, 3, 2]], 'pseudo-class on the universal selector' => ['*:nth-of-type(2)', [0, 1, 0]], + 'class on the universal selector' => ['*.a', [0, 1, 0]], + 'universal selectors around a type' => ['* > p + *', [0, 0, 1]], + 'not of the universal selector' => ['p:not(*)', [0, 0, 1]], + 'is of the universal selector and a class' => [':is(*, .a)', [0, 1, 0]], 'two ids' => ['#a #b', [2, 0, 0]], 'attribute' => ['[data-x]', [0, 1, 0]], 'attribute on a type' => ['a[href^="http"]', [0, 1, 1]], @@ -420,20 +442,6 @@ public function selectorsThatNeverMatch() ]; } - /** - * Whether a selector names the universal selector, which waits for #530 - */ - public function testMarksASelectorThatNamesTheUniversalSelector() - { - $this->assertTrue($this->compiler->compile('*')['universal']); - $this->assertTrue($this->compiler->compile('div > *')['universal']); - $this->assertTrue($this->compiler->compile('* + p')['universal']); - $this->assertFalse($this->compiler->compile('div > :first-child')['universal']); - $this->assertTrue($this->compiler->compile('p:not(*)')['universal']); - $this->assertTrue($this->compiler->compile(':is(h1, *) + p')['universal']); - $this->assertFalse($this->compiler->compile(':is(h1, h2) + p')['universal']); - } - /** * An an+b argument is read into a and b * diff --git a/tests/Mpdf/Css/SelectorMatcherTest.php b/tests/Mpdf/Css/SelectorMatcherTest.php index e93a57e51..5980ef426 100644 --- a/tests/Mpdf/Css/SelectorMatcherTest.php +++ b/tests/Mpdf/Css/SelectorMatcherTest.php @@ -134,6 +134,25 @@ public function selectors() 'is hover' => ['li:is(:hover)', false], 'link on an element with no href' => ['li:link', false], 'not link on an element with no href' => ['li:not(:link)', true], + 'the universal selector' => ['*', true], + 'the universal selector with its class' => ['*.x', true], + 'the universal selector with a class it does not have' => ['*.y', false], + 'the universal selector as its parent' => ['* > li', true], + 'the universal selector as a child of its parent' => ['ul > *', true], + 'the universal selector as a child of an ancestor that is not its parent' => ['div > *.x', false], + 'the universal selector as an ancestor' => ['#main * li', true], + 'the universal selector as html, an ancestor of body' => ['* body li', true], + 'the universal selector as a descendant of body' => ['body * li', true], + 'the universal selector as the root' => ['* > div > ul > li', true], + 'the universal selector as html, the parent of body' => ['* > * > div > ul > li', true], + 'the universal selector as a parent of html' => ['* > * > * > div > ul > li', false], + 'the universal selector as the sibling before it' => ['* + li', true], + 'the universal selector as a sibling before its first sibling' => ['li:first-child + *', true], + 'the universal selector before the first child' => ['* + h1', false], + 'the universal selector as a sibling of an ancestor' => ['* ~ div li', true], + 'the universal selector in is' => [':is(*) > li', true], + 'the universal selector in not' => ['li:not(*)', false], + 'the universal selector in not on an ancestor' => ['div:not(*) li', false], ]; } diff --git a/tests/Mpdf/LogicalSelectorTest.php b/tests/Mpdf/LogicalSelectorTest.php index 736c91da5..cc4c56760 100644 --- a/tests/Mpdf/LogicalSelectorTest.php +++ b/tests/Mpdf/LogicalSelectorTest.php @@ -131,10 +131,10 @@ public function selectors() '

plain

', ['plain' => self::BLACK], ], - 'the universal selector as an argument waits for #530' => [ + 'the universal selector as an argument' => [ 'p:not(*) { color: #f00; } :is(*) + p { color: #f00; }', '

one

two

', - ['one' => self::BLACK, 'two' => self::BLACK], + ['one' => self::BLACK, 'two' => self::RED], ], ]; } diff --git a/tests/Mpdf/StructuralSelectorTest.php b/tests/Mpdf/StructuralSelectorTest.php index 0c32fa4c6..9d50eadec 100644 --- a/tests/Mpdf/StructuralSelectorTest.php +++ b/tests/Mpdf/StructuralSelectorTest.php @@ -243,10 +243,10 @@ public function selectors() '

child

top

', ['child' => self::RED, 'top' => self::BLUE], ], - 'a rule naming the universal selector waits for #530' => [ - 'div > * { color: #f00; } * + p { color: #f00; }', - '

child

next

', - ['child' => self::BLACK, 'next' => self::BLACK], + 'the universal selector on either side of a combinator' => [ + 'div > * { color: #f00; } * + p { color: #00f; }', + '

child

next

first in a section

', + ['child' => self::RED, 'next' => self::BLUE, 'first in a section' => self::BLACK], ], 'a pseudo-class that looks inside the element is still dropped' => [ 'li:has(> b) { color: #f00; }', diff --git a/tests/Mpdf/Tag/TrBordersTest.php b/tests/Mpdf/Tag/TrBordersTest.php index 50e31a21e..cb629d2c4 100644 --- a/tests/Mpdf/Tag/TrBordersTest.php +++ b/tests/Mpdf/Tag/TrBordersTest.php @@ -84,9 +84,121 @@ public function testARowBorderOnTheRightIsDrawn() $this->assertSame(1, $this->redSegments($this->render('border-right: 2px solid #ff0000'))); } + /** + * Td::open() read the row's top and bottom borders only when the row also set its left one, so a row that named + * only its top or bottom drew neither + * + * @dataProvider topAndBottom + * + * @param string $side + */ + public function testARowBorderOnTheTopOrBottomAloneIsDrawn($side) + { + $this->assertGreaterThan(0, $this->redSegments($this->render('border-' . $side . ': 2px solid #ff0000'))); + } + + /** + * The sides Td::open() draws for a row + * + * @return array[] + */ + public function topAndBottom() + { + return ['top' => ['top'], 'bottom' => ['bottom']]; + } + public function testARowWithNoBorderOfItsOwnDrawsNone() { $this->assertSame(0, $this->redSegments($this->render(''))); } + /** + * The cells' blue borders on the side a row covers are drawn, or not, and the row's red border is drawn, or not + * + * @dataProvider rowBorders + * + * @param string $side bottom, top, left or right + * @param string $css Rules for the row + * @param bool $cellBorder Whether the cells' borders are drawn + * @param bool $rowBorder Whether the row's border is drawn + */ + public function testARowBorderReplacesTheCellsOnlyWhenItIsDrawnOrHidden($side, $css, $cellBorder, $rowBorder) + { + foreach ([\Mpdf\CssMode::STANDARD, \Mpdf\CssMode::LEGACY] as $mode) { + $pdf = $this->renderStylesheet('td { border-' . $side . ': 0.5mm solid #00f; } ' . $css, $mode); + + $this->assertSame($cellBorder, strpos($pdf, '0.000 0.000 1.000 RG') !== false, $mode . ': the cells\' border'); + $this->assertSame($rowBorder, strpos($pdf, '1.000 0.000 0.000 RG') !== false, $mode . ': the row\'s border'); + } + } + + /** + * Each side a row covers, with rules for the rows, whether the cells' borders are drawn, and whether the row's is + * + * @return array[] + */ + public function rowBorders() + { + $rules = [ + 'no border' => ['', true, false], + 'a colour alone' => ['tr { border-color: #f00; }', true, false], + 'no width' => ['tr { border: 0 solid #f00; }', true, false], + 'no style' => ['tr { border: none; }', true, false], + 'a style and a colour but no width' => ['tr { border-style: solid; border-width: 0; border-color: #f00; }', true, false], + 'hidden' => ['tr { border: hidden; }', false, false], + 'drawn' => ['tr { border: 0.5mm solid #f00; }', false, true], + ]; + + $data = []; + foreach (['bottom', 'top', 'left', 'right'] as $side) { + foreach ($rules as $name => $rule) { + $data[$side . ': ' . $name] = array_merge([$side], $rule); + } + } + + return $data; + } + + /** + * A reset reaching every element leaves the borders a later rule gives the cells + * + * @dataProvider resets + * + * @param string $reset + */ + public function testAResetLeavesTheCellsBorders($reset) + { + $this->assertStringContainsString('0.000 0.000 1.000 RG', $this->renderStylesheet($reset . ' td { border-bottom: 0.5mm solid #00f; }', \Mpdf\CssMode::STANDARD)); + } + + /** + * Resets as frameworks write them + * + * @return array[] + */ + public function resets() + { + return [ + 'a border colour' => ['* { border-color: #dee2e6; }'], + 'no width, a style and a colour' => ['*, ::before, ::after { border-width: 0; border-style: solid; border-color: #e5e7eb; }'], + 'the border shorthand' => ['* { border: 0 solid; }'], + ]; + } + + /** + * @param string $css + * @param string $mode A CssMode value + * + * @return string An uncompressed document holding a table of one-cell rows with collapsed borders, under a + * stylesheet + */ + private function renderStylesheet($css, $mode) + { + $mpdf = new Mpdf(['mode' => 'c', 'cssMode' => $mode]); + $mpdf->SetCompression(false); + $mpdf->WriteHTML('
a
b
'); + + return $mpdf->Output('', 'S'); + } + } diff --git a/tests/Mpdf/UniversalSelectorTest.php b/tests/Mpdf/UniversalSelectorTest.php new file mode 100644 index 000000000..ed1934d94 --- /dev/null +++ b/tests/Mpdf/UniversalSelectorTest.php @@ -0,0 +1,457 @@ +, and , are only reached by a rule that + * names their tag, or an id or class they have. In the legacy mode rules using it are dropped, as they were before. + */ +class UniversalSelectorTest extends TestCase +{ + + use DrawnStyles; + + const RED = '1.000 0.000 0.000 rg'; + const GREEN = '0.000 0.502 0.000 rg'; + const BLUE = '0.000 0.000 1.000 rg'; + const BLACK = '0.000 g'; + + /** @var string[] The contexts document() writes the cases in */ + private static $contexts = ['block', 'inline', 'table cell', 'list item', 'header', 'footer', 'positioned block', 'kept block', 'forced page break']; + + /** + * Each piece of text is drawn in the colour the rules leave it in, in every context, and where the context puts + * it. The document is closed, so its header and footer are drawn on the page + * + * @dataProvider casesInContexts + * + * @param string $context + * @param string $css With {T} for the subjects' tag and {O} for another tag + * @param array[] $groups As cases() gives them + */ + public function testMatchesInEveryContext($context, $css, array $groups) + { + $mpdf = $this->drawDocument($this->document($context, $css, $groups), ['cssMode' => CssMode::STANDARD]); + $mpdf->OutputBinaryData(); + + $expected = $this->expectedColours($groups); + $this->assertDrawnInColours($expected, $this->keyedByText($mpdf, $mpdf->drawnColours)); + $this->assertDrawnInContext($context, $mpdf, array_keys($expected)); + } + + /** + * Every case in every context + * + * @return array[] + */ + public function casesInContexts() + { + $data = []; + foreach (self::$contexts as $context) { + foreach ($this->cases() as $name => $case) { + $data[$context . ': ' . $name] = [$context, $case[0], $case[1]]; + } + } + + return $data; + } + + /** + * Rules, with the elements they are matched against: those that match, and near misses that must not. A rule + * that could match the element each group is written in is kept to its children with .g >, so the children do + * not inherit the colour from it + * + * @return array[] Each [css, groups]. A group is [the class of the element it is written in, its children], and a + * child is [T or O for its tag, its text, the colour it should be drawn in, its attributes] + */ + private function cases() + { + $r = self::RED; + $g = self::GREEN; + $b = self::BLUE; + $k = self::BLACK; + + return [ + 'alone' => [ + '* { color: #f00; }', + [['g', [['T', 'subject', $r], ['O', 'another tag', $r]]]], + ], + 'loses to a type selector written before it' => [ + '{T} { color: #00f; } * { color: #f00; }', + [['g', [['T', 'named by the type', $b], ['O', 'not named', $r]]]], + ], + 'loses to a class written before it' => [ + '.c { color: #008000; } * { color: #f00; }', + [['g', [['T', 'with the class', $g, 'class="c"'], ['T', 'without the class', $r]]]], + ], + 'with a class' => [ + '*.c { color: #f00; }', + [['g', [['T', 'with the class', $r, 'class="c"'], ['T', 'without the class', $k], ['O', 'another tag with it', $r, 'class="c"']]]], + ], + 'with an id' => [ + '*#i { color: #f00; }', + [['g', [['T', 'with the id', $r, 'id="i"'], ['T', 'without the id', $k]]]], + ], + 'with an attribute' => [ + '*[title] { color: #f00; }', + [['g', [['T', 'with a title', $r, 'title="t"'], ['O', 'without a title', $k]]]], + ], + 'with a pseudo-class' => [ + '.g > *:first-child { color: #f00; }', + [['g', [['T', 'first child', $r], ['T', 'second child', $k]]]], + ], + 'as the subject of a descendant combinator' => [ + '.in * { color: #f00; }', + [['in', [['T', 'inside', $r], ['O', 'another tag inside', $r]]], ['out', [['T', 'outside', $k]]]], + ], + 'as an ancestor' => [ + '* {T} { color: #f00; }', + [['g', [['T', 'a descendant of any', $r], ['O', 'another tag', $k]]]], + ], + 'as the subject of a child combinator' => [ + '.in > * { color: #f00; }', + [['in', [['T', 'a child of in', $r]]], ['out', [['T', 'a child of out', $k]]]], + ], + 'as the parent' => [ + '* > {T} { color: #f00; }', + [['g', [['T', 'a child of any', $r], ['O', 'another tag', $k]]]], + ], + 'as the sibling before' => [ + '.g > * + {T} { color: #f00; }', + [['g', [['T', 'first', $k], ['T', 'after a sibling', $r], ['O', 'another tag after a sibling', $k]]]], + ], + 'as the sibling after' => [ + '.g > {O} + * { color: #f00; }', + [['g', [['O', 'another tag', $k], ['T', 'after the other tag', $r], ['T', 'after the subject tag', $k]]]], + ], + 'on both sides of a general sibling combinator' => [ + '.g > * ~ * { color: #f00; }', + [['g', [['T', 'the first', $k], ['O', 'the second', $r], ['T', 'the third', $r]]]], + ], + 'in is' => [ + '.g > :is(*) + * { color: #f00; }', + [['g', [['T', 'the first', $k], ['O', 'the second', $r]]]], + ], + 'in where, which weighs nothing' => [ + '{T} { color: #f00; } :where(*) { color: #00f; }', + [['g', [['T', 'named by the type', $r], ['O', 'not named', $b]]]], + ], + 'in not, which then matches nothing' => [ + '{T}:not(*) { color: #f00; } :not(*) { color: #f00; }', + [['g', [['T', 'subject', $k], ['O', 'another tag', $k]]]], + ], + 'with a class in not' => [ + '{T}:not(*.c) { color: #f00; }', + [['g', [['T', 'without the class', $r], ['T', 'with the class', $k, 'class="c"']]]], + ], + ]; + } + + /** + * @param string $context + * + * @return string[] The tag of the subjects in a context, another tag for their siblings, and the start, with %s + * for its class, and the end of the element each group is written in + */ + private function tags($context) + { + switch ($context) { + case 'inline': + return ['em', 'b', '

', '

']; + case 'table cell': + return ['td', 'th', '', '
']; + case 'list item': + return ['li', 'div', '
    ', '
']; + default: + return ['p', 'h5', '
', '
']; + } + } + + /** + * A document with each group in its own parent, in a context, under a stylesheet naming the tags the context + * gives them + * + * @param string $context + * @param string $css With {T} for the subjects' tag and {O} for the other tag + * @param array[] $groups As cases() gives them + * + * @return string + */ + private function document($context, $css, array $groups) + { + list($subject, $other, $open, $close) = $this->tags($context); + + $html = ''; + foreach ($groups as $group) { + $html .= sprintf($open, $group[0]); + foreach ($group[1] as $child) { + $tag = $child[0] === 'T' ? $subject : $other; + $html .= '<' . $tag . (isset($child[3]) ? ' ' . $child[3] : '') . '>' . $child[1] . ' '; + } + $html .= $close; + } + + return '' . $this->inContext($context, $html); + } + + /** + * @param array[] $groups As cases() gives them + * + * @return array The text of each child and the colour it should be drawn in + */ + private function expectedColours(array $groups) + { + $expected = []; + foreach ($groups as $group) { + foreach ($group[1] as $child) { + $expected[$child[1]] = $child[2]; + } + } + + return $expected; + } + + /** + * In the legacy CSS mode rules using the universal selector are dropped: every case in every context is drawn as + * it is with those rules taken out + * + * @dataProvider casesInContexts + * + * @param string $context + * @param string $css + * @param array[] $groups + */ + public function testTheLegacyModeDropsThem($context, $css, array $groups) + { + $without = preg_replace('/[^{}]*\*[^{}]*\{[^}]*\}/', '', $css); + $this->assertNotSame($css, $without); + + $dropped = $this->drawDocument($this->document($context, $without, $groups), ['cssMode' => CssMode::LEGACY]); + $dropped->OutputBinaryData(); + $written = $this->drawDocument($this->document($context, $css, $groups), ['cssMode' => CssMode::LEGACY]); + $written->OutputBinaryData(); + + $this->assertSame($dropped->drawnText, $written->drawnText); + $this->assertSame($dropped->drawnColours, $written->drawnColours); + $this->assertSame($dropped->drawnBoxes, $written->drawnBoxes); + } + + /** + * The universal selector reaches body, as the document's root: text written straight into the body takes its + * colour, and body's own rules outweigh it wherever they are written. Rules that need body to have a parent or a + * sibling do not reach it + * + * @dataProvider bodyRules + * + * @param string $css + * @param string $expected The colour of the text written straight into the body + */ + public function testReachesBody($css, $expected) + { + $colours = $this->drawnColours('before

paragraph

after', ['cssMode' => CssMode::STANDARD]); + + $this->assertSame($expected, $colours['before']); + $this->assertSame($expected, $colours['after']); + } + + /** + * Rules, and the colour of the text written straight into the body + * + * @return array[] + */ + public function bodyRules() + { + return [ + 'the universal selector' => ['* { color: #f00; }', self::RED], + 'a body rule written after it' => ['* { color: #f00; } body { color: #00f; }', self::BLUE], + 'a body rule written before it' => ['body { color: #00f; } * { color: #f00; }', self::BLUE], + 'the later of two' => ['* { color: #00f; } * { color: #f00; }', self::RED], + 'not another tag' => [':not(p) { color: #f00; }', self::RED], + 'not body' => ['*:not(body) { color: #f00; }', self::BLACK], + 'a child of anything' => ['* > * { color: #f00; }', self::BLACK], + 'a descendant of anything' => ['* * { color: #f00; }', self::BLACK], + 'a sibling of anything' => ['* + *, * ~ * { color: #f00; }', self::BLACK], + 'with a class it does not have' => ['*.c { color: #f00; }', self::BLACK], + ]; + } + + /** + * A universal rule's background reaches body, which paints the page + */ + public function testPaintsThePageFromAUniversalBackground() + { + $html = '

text

'; + $this->assertNotEmpty($this->drawDocument($html, ['cssMode' => CssMode::STANDARD])->bodyBackgroundColor); + + $mpdf = $this->drawDocument($html, ['cssMode' => CssMode::LEGACY]); + $this->assertEmpty($mpdf->bodyBackgroundColor); + } + + /** + * A reset that zeroes every margin and padding reaches the default margins of paragraphs, headings, lists and + * blockquotes, a list's indent and a cell's padding, as in a browser: the text is drawn where it is drawn with the + * same declarations written on each element. In the legacy mode it is dropped, and the text is drawn where it is + * with no stylesheet + */ + public function testAResetReachesTheDefaultMarginsAndPadding() + { + $html = 'HeadingFirst paragraph

Second paragraph

' + . 'BulletNumber' + . 'TermDescriptionQuote' + . 'CellLast paragraph

'; + $reset = 'margin: 0; padding: 0'; + + $plain = $this->drawDocument(sprintf($html, ''), ['cssMode' => CssMode::STANDARD]); + $inline = $this->drawDocument(sprintf($html, ' style="' . $reset . '"'), ['cssMode' => CssMode::STANDARD]); + $document = '' . sprintf($html, ''); + $universal = $this->drawDocument($document, ['cssMode' => CssMode::STANDARD]); + $legacy = $this->drawDocument($document, ['cssMode' => CssMode::LEGACY]); + + $this->assertNotEquals($plain->drawnBoxes, $inline->drawnBoxes, 'The declarations should move the text'); + $this->assertSame($inline->drawnText, $universal->drawnText); + $this->assertEquals($inline->drawnBoxes, $universal->drawnBoxes); + $this->assertEquals($inline->drawnY, $universal->drawnY); + $this->assertEquals($plain->drawnBoxes, $legacy->drawnBoxes); + $this->assertEquals($plain->drawnY, $legacy->drawnY); + } + + /** + * Rules that do not name mPDF's own tags leave a barcode, a dot tab and a text circle as they are drawn without + * them. The page is otherwise the same, so its content is compared whole + * + * @dataProvider rulesNotNamingMpdfTags + * + * @param string $css + */ + public function testLeavesMpdfOwnTagsAlone($css) + { + $this->assertSame($this->ownTagsPage(''), $this->ownTagsPage($css)); + } + + /** + * Rules that reach every child of the paragraph the tags are written in, which holds nothing else + * + * @return array[] + */ + public function rulesNotNamingMpdfTags() + { + $everything = '{ display: none; margin: 5mm; padding: 5mm; border: 1mm solid #f00; color: #f00; background-color: #ff0;' + . ' vertical-align: top; font-size: 20pt; font-weight: bold; outdent: 20mm; visibility: hidden; }'; + + return [ + 'the universal selector' => ['p > * ' . $everything], + 'the universal selector with a pseudo-class' => ['*:empty ' . $everything], + 'a pseudo-class alone' => [':empty ' . $everything], + 'an attribute alone' => ['[code], [r], [outdent] ' . $everything], + 'not another tag' => ['p > :not(b) ' . $everything], + 'a sibling' => ['p > * + *, p > * ~ * ' . $everything], + ]; + } + + /** + * A rule that names one of mPDF's own tags by its tag, or by an id or class it has, still reaches it + * + * @dataProvider rulesNamingMpdfTags + * + * @param string $css + */ + public function testStillAppliesRulesThatNameMpdfOwnTags($css) + { + $this->assertNotSame($this->ownTagsPage(''), $this->ownTagsPage($css)); + } + + /** + * Rules that name one of mPDF's own tags + * + * @return array[] + */ + public function rulesNamingMpdfTags() + { + return [ + 'the text circle by its tag' => ['textcircle { display: none; }'], + 'the dot tab by its tag' => ['p > dottab { outdent: 20mm; }'], + 'the barcode by its class' => ['*.code { display: none; }'], + 'the barcode by its id' => ['#code { display: none; }'], + ]; + } + + /** + * @param string $css + * + * @return string[] The content of each page of a paragraph holding a barcode, a dot tab and a text circle, written + * in the standard mode under a stylesheet + */ + private function ownTagsPage($css) + { + $mpdf = new Mpdf(['mode' => 'c', 'cssMode' => CssMode::STANDARD]); + $mpdf->WriteHTML( + '

' + . '

' + ); + + return $mpdf->pages; + } + + /** + * The spans mPDF wraps a run of another script in are not the document's elements, and the universal selector + * does not reach them any more than a type selector does + */ + public function testLeavesTheSpansAroundARunOfAnotherScriptAlone() + { + $html = '

שלום bold שלום

'; + $config = ['mode' => '', 'autoScriptToLang' => true, 'autoLangToFont' => true, 'cssMode' => CssMode::STANDARD]; + + $colours = $this->drawnColours('' . $html, $config); + + $this->assertSame(self::RED, $colours['bold']); + foreach ($colours as $text => $colour) { + if ($text !== 'bold') { + $this->assertSame(self::BLUE, $colour, sprintf('"%s" is drawn as a child of the paragraph', $text)); + } + } + } + + /** + * The universal selector weighs nothing: every rule naming a tag, class, id, attribute or pseudo-class outweighs + * it, and between universal rules the later one wins + * + * @dataProvider precedence + * + * @param string $css + * @param string $expected The colour of the text "subject" + */ + public function testPrecedence($css, $expected) + { + $html = '

subject

'; + + $this->assertSame($expected, $this->drawnColours('' . $html, ['cssMode' => CssMode::STANDARD])['subject']); + } + + /** + * Competing rules, and the colour they leave the subject in + * + * @return array[] + */ + public function precedence() + { + return [ + 'a type written before' => ['p { color: #008000; } * { color: #f00; }', self::GREEN], + 'a class written before' => ['.c { color: #008000; } * { color: #f00; }', self::GREEN], + 'an id written before' => ['#i { color: #008000; } * { color: #f00; }', self::GREEN], + 'an attribute written before' => ['[title] { color: #008000; } * { color: #f00; }', self::GREEN], + 'a pseudo-class written before' => [':first-child { color: #008000; } * { color: #f00; }', self::GREEN], + 'a class with the universal selector against a type' => ['*.c { color: #008000; } p { color: #f00; }', self::GREEN], + 'a universal chain against a type' => ['* > * { color: #f00; } p { color: #008000; }', self::GREEN], + 'a universal chain against a class' => ['* div > * { color: #f00; } .c { color: #008000; }', self::GREEN], + 'a universal chain weighs as its type: the later wins' => ['p { color: #f00; } div > * { color: #008000; }', self::GREEN], + 'a universal chain with two types against one' => ['body div > * { color: #008000; } p { color: #f00; }', self::GREEN], + 'where against the universal selector: the later wins' => ['* { color: #f00; } :where(p) { color: #008000; }', self::GREEN], + 'the universal selector against where: the later wins' => [':where(p) { color: #f00; } * { color: #008000; }', self::GREEN], + 'two universal rules: the later wins' => ['* { color: #f00; } * { color: #008000; }', self::GREEN], + ]; + } +} diff --git a/tests/Snapshots/UniversalSelectorSnapshotTest.php b/tests/Snapshots/UniversalSelectorSnapshotTest.php new file mode 100644 index 000000000..a0edfece5 --- /dev/null +++ b/tests/Snapshots/UniversalSelectorSnapshotTest.php @@ -0,0 +1,160 @@ + + + +

The universal selector

+ +

*

+

Text no other rule colours is navy: * reaches every element, and every other rule on this page outweighs it. The captions stay grey and the headings black, from their own rules.

+
+

A paragraph

+
  • A list item
+
+ +

*.hl

+

The paragraph and the span with class hl are red and bold. The paragraph without it stays navy.

+
+

With the class

+

Without the class, a span with it

+
+ +

*#pick

+

Only the paragraph with id pick has a yellow background.

+
+

With the id

+

Without the id

+
+ +

*[title]

+

The paragraph and the item with a title are green and bold; the others stay navy.

+
+

With a title

+

Without a title

+
  • An item with a title
  • An item without
+
+ +

div.inside *

+

Everything inside the box is red: the paragraph, the span in it and the list item. The paragraph after the box stays navy.

+
+

A paragraph with a span

+
  • A list item
+
+

After the box

+ +

div.deep * em

+

The emphasis inside the paragraph is red and bold. The one written straight into the box has no element between it and the box, and stays navy.

+
+ Straight in the box +

In a paragraph, emphasised

+
+ +

div.children > *

+

The box's two children have a red bar on their left. The span inside the paragraph does not.

+
+

A child with a span in it

+

Another child

+
+ +

div.after * + p

+

The paragraphs after another element are red and bold. The first paragraph stays navy.

+
+

The first paragraph

+

After a paragraph

+

A heading

+

After the heading

+
+ +

div.later h4 ~ *

+

Everything after the heading is red. The paragraph before it and the heading stay navy.

+
+

Before the heading

+

The heading

+

After the heading

+

After that

+
+ +

div.is > :is(*):first-child

+

The box's first child is red. The second stays navy.

+
+

The first child

+

The second child

+
+ +

div.never p:not(*)

+

Every element is an element, so :not(*) matches nothing: the paragraph stays navy.

+
+

A paragraph

+
+ +

table.first tr > *:first-child

+

The first cell of each row is yellow, whether it is a header or a data cell.

+ + + +
HeadHead 2
R1 C1R1 C2
+ +

ul.rest > * + *

+

Every item but the first is red and bold.

+
+
  • First
  • Second
  • Third
+
+ mpdf = $this->createMpdf(['cssMode' => \Mpdf\CssMode::STANDARD]); + + $this->mpdf->WriteHTML($html); + } + +} diff --git a/tests/Snapshots/UniversalStylesheetSnapshotTest.php b/tests/Snapshots/UniversalStylesheetSnapshotTest.php new file mode 100644 index 000000000..5a7cab694 --- /dev/null +++ b/tests/Snapshots/UniversalStylesheetSnapshotTest.php @@ -0,0 +1,110 @@ + + + +

A framework's reset, with *

+ +

Cards

+

The reset leaves no space between the paragraphs of a card; .stack > * + * puts 2 mm back between the cards and between the parts of each, and none above the first. The first card's text is blue, from .card > *, and its heading black, the heavier .card > h3 winning. The muted card's text is grey, .muted * being as heavy as .card > * and written after it, and the paragraph marked hidden is not drawn. The featured card's text is bold, from #featured *. The cards' borders are light grey, from * { border-color }.

+
+
+

First card

+

A paragraph with no margin of its own.

+

A second paragraph, 2 mm below it.

+
+
+

Muted card

+

Grey text, from .muted *.

+ +
  • A list item, grey
  • Another
+
+ +
+ +

Table

+

The cells keep the padding of .table td, .table th over the reset, and the light grey rule under each row takes its colour from * { border-color }, which reaches the rows too without taking the cells' rules away. The first cell of each row, a th or a td, is grey, from .table tr > *:first-child.

+ + + + +
ItemAmount
First10.00
Second20.00
+ +

mPDF's own tags

+

No rule names the barcode, the dot tab or the text circle, so the reset and .label * + * leave them as they are drawn without a stylesheet. The label's lines are 1 mm apart, the barcode's line included.

+
+

Ship to: A. Person

+

+

Reference4711

+

+
+ + +

Index

+

The reset reaches the index's lines too: its letters have no space above them.

+ + mpdf = $this->createMpdf(['cssMode' => \Mpdf\CssMode::STANDARD]); + + $this->mpdf->WriteHTML($html); + } + +} diff --git a/tests/data/snapshots/universal-selector.pdf b/tests/data/snapshots/universal-selector.pdf new file mode 100644 index 0000000000000000000000000000000000000000..f6702fdf51340050596af9a51bf927fa669d078c GIT binary patch literal 79868 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 literal 0 HcmV?d00001 From b9581ea9fafe2e94f6deae62785d6742cb34b3cf Mon Sep 17 00:00:00 2001 From: Jake Jackson Date: Wed, 30 Sep 2026 20:58:43 +1000 Subject: [PATCH 2/2] Match html and body by the universal selector through #642's document rules #642 matches html as body's parent and merges both through documentDeclarations(), which takes the rules filed for any element, so the separate merge of those rules for body goes. A universal rule now reaches html too: it sets the size rem is read against, and * > *, * * and *:not(body) reach body through html, as in a browser. Its !important declarations apply in their layer. Co-Authored-By: Claude Opus 5.5 --- tests/Mpdf/Css/RuleSetTest.php | 22 ++++++++++++------- tests/Mpdf/Css/SelectorCompilerTest.php | 2 +- tests/Mpdf/UniversalSelectorTest.php | 28 +++++++++++++++++++------ 3 files changed, 37 insertions(+), 15 deletions(-) diff --git a/tests/Mpdf/Css/RuleSetTest.php b/tests/Mpdf/Css/RuleSetTest.php index 84f56662f..d647e1582 100644 --- a/tests/Mpdf/Css/RuleSetTest.php +++ b/tests/Mpdf/Css/RuleSetTest.php @@ -166,21 +166,27 @@ public function testGivesTheImportantDeclarationsApartInTheSameOrder() } /** - * The document's own frame is matched as body, by the rules filed for any element alone: the universal selector - * and the other rules whose subject names no tag, id or class, when they match the root + * html and body are matched by the rules filed for any element too: the universal selector and the other rules + * whose subject names no tag, id or class, when they match there. html is body's parent and has no parent, and + * neither has siblings */ - public function testMatchesTheDocumentAsBodyWithTheRulesForAnyElement() + public function testMatchesHtmlAndBodyWithTheRulesForAnyElement() { $rules = new RuleSet(); - foreach (['*', 'body', '* > *', ':not(p)', ':not(body)', '*:first-child', '*.a', '*:lang(fr)'] as $position => $selector) { + foreach (['*', 'body', '* > *', ':not(p)', ':not(body)', '*:first-child', '*.a', '*:lang(fr)', '* + *'] as $position => $selector) { $rules->add($this->compiler->compile($selector), ['COLOR' => 'rule ' . $position]); } - $path = function () { - return array_slice($this->path(), 0, 1); - }; + $document = [$this->path()[0]]; - $this->assertSame([['COLOR' => 'rule 0'], ['COLOR' => 'rule 3']], $rules->matchingDeclarations('', '', [], $path)); + $this->assertSame( + [[['COLOR' => 'rule 0'], ['COLOR' => 'rule 3'], ['COLOR' => 'rule 4']], []], + $rules->documentDeclarations(true, $document) + ); + $this->assertSame( + [[['COLOR' => 'rule 0'], ['COLOR' => 'rule 2'], ['COLOR' => 'rule 1'], ['COLOR' => 'rule 3']], []], + $rules->documentDeclarations(false, $document) + ); } /** diff --git a/tests/Mpdf/Css/SelectorCompilerTest.php b/tests/Mpdf/Css/SelectorCompilerTest.php index fc4ba3ced..2867bacef 100644 --- a/tests/Mpdf/Css/SelectorCompilerTest.php +++ b/tests/Mpdf/Css/SelectorCompilerTest.php @@ -112,7 +112,7 @@ public function selectors() $tag = function ($tag) { return ['tag' => $tag, 'ids' => [], 'classes' => [], 'pseudos' => []]; }; - $any = ['compounds' => [['tag' => null, 'ids' => [], 'classes' => [], 'attributes' => [], 'pseudos' => []]], 'combinators' => [], 'specificity' => [0, 0, 0]]; + $any = ['compounds' => [['tag' => null, 'ids' => [], 'classes' => [], 'attributes' => [], 'pseudos' => []]], 'combinators' => [], 'specificity' => [0, 0, 0], 'never' => false]; return [ 'type' => ['p', [$tag('P')], []], diff --git a/tests/Mpdf/UniversalSelectorTest.php b/tests/Mpdf/UniversalSelectorTest.php index ed1934d94..df431a7d1 100644 --- a/tests/Mpdf/UniversalSelectorTest.php +++ b/tests/Mpdf/UniversalSelectorTest.php @@ -241,9 +241,10 @@ public function testTheLegacyModeDropsThem($context, $css, array $groups) } /** - * The universal selector reaches body, as the document's root: text written straight into the body takes its - * colour, and body's own rules outweigh it wherever they are written. Rules that need body to have a parent or a - * sibling do not reach it + * The universal selector reaches html and body: text written straight into the body takes its colour, and body's + * own rules outweigh it wherever they are written. html is body's parent, so rules that need body to have a + * parent, or html to be there, reach it, and text takes their colour from one or the other. Rules that need body to + * have a sibling do not reach it * * @dataProvider bodyRules * @@ -270,15 +271,30 @@ public function bodyRules() 'a body rule written after it' => ['* { color: #f00; } body { color: #00f; }', self::BLUE], 'a body rule written before it' => ['body { color: #00f; } * { color: #f00; }', self::BLUE], 'the later of two' => ['* { color: #00f; } * { color: #f00; }', self::RED], + 'an important universal rule over a body rule' => ['* { color: #f00 !important; } body { color: #00f; }', self::RED], + 'an important body rule over an important universal rule' => ['body { color: #00f !important; } * { color: #f00 !important; }', self::BLUE], 'not another tag' => [':not(p) { color: #f00; }', self::RED], - 'not body' => ['*:not(body) { color: #f00; }', self::BLACK], - 'a child of anything' => ['* > * { color: #f00; }', self::BLACK], - 'a descendant of anything' => ['* * { color: #f00; }', self::BLACK], + 'not body, which html is' => ['*:not(body) { color: #f00; }', self::RED], + 'a child of anything, as body is of html' => ['* > * { color: #f00; }', self::RED], + 'a descendant of anything, as body is of html' => ['* * { color: #f00; }', self::RED], + 'a child of anything but html' => [':not(html) > * { color: #f00; }', self::BLACK], 'a sibling of anything' => ['* + *, * ~ * { color: #f00; }', self::BLACK], 'with a class it does not have' => ['*.c { color: #f00; }', self::BLACK], ]; } + /** + * The universal selector reaches html, so its font size is the one rem is read against + */ + public function testSetsTheSizeRemIsReadAgainst() + { + $mpdf = $this->drawDocument('

rem

half

', ['cssMode' => CssMode::STANDARD]); + $sizes = $this->keyedByText($mpdf, $mpdf->drawnFontSize); + + $this->assertEqualsWithDelta(20, $sizes['rem'], 0.001); + $this->assertEqualsWithDelta(10, $sizes['half'], 0.001); + } + /** * A universal rule's background reaches body, which paints the page */