Skip to content

Commit 0bc5fdb

Browse files
gravitypdf-botclaudejakejackson1
authored
Merge css() declarations into each element's own style (#107)
css() read the style attribute of every match into one map and wrote the union back to all of them, so elements picked up each other's declarations. Parse, merge and write per element instead. Fixes #77. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Jake Jackson <jakejackson1@users.noreply.github.com>
1 parent 95dbf53 commit 0bc5fdb

3 files changed

Lines changed: 31 additions & 15 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ QueryPath Changelog
3333
- Fix `tag()` emitting an "Undefined property" warning and returning `NULL` when the first match is not an element, such as a text, comment or processing instruction node returned by `contents()`. It now returns an empty string, as it does for an empty match set (issue #93)
3434
- Fix QueryPath's error handler staying installed for the rest of the request when an exception other than a `QueryPath\Exception` (a `TypeError`, or one thrown by a stream wrapper, for example) escaped from parsing a document, inserting markup, or `writeXML()`/`writeHTML()` (issue #95)
3535
- Fix `writeHTML()` throwing `QueryPath\ParseException` instead of `QueryPath\IOException` when the file cannot be written, as `writeXML()` and `writeHTML5()` do (issue #92). `IOException` extends `ParseException`, so existing `catch (ParseException $e)` blocks still catch it
36+
- Fix `css()` merging the inline styles of every matched element and writing the combined result back to all of them. The new declarations are now merged into each element's own `style` attribute (issue #77)
3637
- Fix `not()` keeping only the given nodes, instead of removing them, when passed an `SplObjectStorage` such as `get(null, true)` returns (issue #75)
3738

3839
# 4.1.0

‎src/Helpers/QueryMutators.php‎

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,9 +1040,11 @@ public function css($name = null, $value = '')
10401040
return $this->attr('style');
10411041
}
10421042

1043-
// Get any existing CSS.
1044-
$css = [];
1043+
$rules = is_array($name) ? $name : [$name => $value];
1044+
10451045
foreach ($this->elements() as $match) {
1046+
// Get this element's existing CSS.
1047+
$css = [];
10461048
$style = $match->getAttribute('style');
10471049
if (! empty($style)) {
10481050
// XXX: Is this sufficient?
@@ -1059,23 +1061,18 @@ public function css($name = null, $value = '')
10591061
$css[$css_att] = trim($css_val);
10601062
}
10611063
}
1062-
}
10631064

1064-
if (is_array($name)) {
10651065
// Use array_merge instead of + to preserve order.
1066-
$css = array_merge($css, $name);
1067-
} else {
1068-
$css[$name] = $value;
1069-
}
1066+
$css = array_merge($css, $rules);
10701067

1071-
// Collapse CSS into a string.
1072-
$format = '%s: %s;';
1073-
$css_string = '';
1074-
foreach ($css as $n => $v) {
1075-
$css_string .= sprintf($format, $n, trim($v));
1076-
}
1068+
// Collapse CSS into a string.
1069+
$css_string = '';
1070+
foreach ($css as $n => $v) {
1071+
$css_string .= sprintf('%s: %s;', $n, trim($v));
1072+
}
10771073

1078-
$this->attr('style', $css_string);
1074+
$match->setAttribute('style', $css_string);
1075+
}
10791076

10801077
return $this;
10811078
}

‎tests/QueryPath/DOMQueryTest.php‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,24 @@ public function testCss()
517517
$this->assertEquals('a: c;b: b;', $qp->css());
518518
}
519519

520+
public function testCssMergesIntoEachElementsOwnStyle()
521+
{
522+
$html = '<div><p style="color: red"></p><p style="font-size: 2px; margin: 5px"></p><p></p></div>';
523+
524+
$qp = html5qp($html, 'p')->css('margin', '0');
525+
$this->assertSame('color: red;margin: 0;', $qp->get(0)->getAttribute('style'));
526+
$this->assertSame('font-size: 2px;margin: 0;', $qp->get(1)->getAttribute('style'));
527+
$this->assertSame('margin: 0;', $qp->get(2)->getAttribute('style'));
528+
529+
$qp = html5qp($html, 'p')->css(['margin' => '0', 'color' => 'blue']);
530+
$this->assertSame('color: blue;margin: 0;', $qp->get(0)->getAttribute('style'));
531+
$this->assertSame('font-size: 2px;margin: 0;color: blue;', $qp->get(1)->getAttribute('style'));
532+
$this->assertSame('margin: 0;color: blue;', $qp->get(2)->getAttribute('style'));
533+
534+
// The getter still returns the first element's style, unparsed.
535+
$this->assertSame('color: red', html5qp($html, 'p')->css());
536+
}
537+
520538
public function testRemoveAttr()
521539
{
522540
$file = DATA_FILE;

0 commit comments

Comments
 (0)