Skip to content

Commit f6d69eb

Browse files
CopilotnadarCopilot
authored
Fix heading rendering when combined with alignment attributes (#98)
* Initial plan * Implement heading with alignment support Co-authored-by: nadar <3417221+nadar@users.noreply.github.com> * Validate fix with comprehensive manual tests Co-authored-by: nadar <3417221+nadar@users.noreply.github.com> * Remove placeholder issue reference from test comment Co-authored-by: nadar <3417221+nadar@users.noreply.github.com> * Apply rector changes --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: nadar <3417221+nadar@users.noreply.github.com> Co-authored-by: Copilot <Copilot@users.noreply.github.com>
1 parent 6033cd6 commit f6d69eb

File tree

5 files changed

+124
-15
lines changed

5 files changed

+124
-15
lines changed

composer.lock

Lines changed: 13 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/listener/Align.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ class Align extends BlockListener
2626
public function process(Line $line)
2727
{
2828
$alignment = $line->getAttribute('align');
29-
if ($alignment) {
29+
// Skip if line has a header attribute - let Heading listener handle it
30+
if ($alignment && !$line->getAttribute('header')) {
3031
$this->pick($line, ['alignment' => $alignment]);
3132
$line->setDone();
3233
}

src/listener/Heading.php

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,21 @@ class Heading extends BlockListener
2121
*/
2222
public $levels = [1, 2, 3, 4, 5, 6];
2323

24+
/**
25+
* @var array<string> Supported alignments.
26+
* @since 3.3.0
27+
*/
28+
public $alignments = ['center', 'right', 'justify', 'left'];
29+
2430
/**
2531
* {@inheritDoc}
2632
*/
2733
public function process(Line $line)
2834
{
2935
$heading = $line->getAttribute('header');
3036
if ($heading) {
31-
$this->pick($line, ['heading' => $heading]);
37+
$alignment = $line->getAttribute('align');
38+
$this->pick($line, ['heading' => $heading, 'alignment' => $alignment]);
3239
$line->setDone();
3340
}
3441
}
@@ -45,8 +52,20 @@ public function render(Lexer $lexer)
4552
// prevent html injection in case the attribute is user input
4653
throw new Exception('An unknown heading level "' . $pick->optionValue('heading') . '" has been detected.');
4754
}
55+
56+
$alignment = $pick->optionValue('alignment');
57+
if ($alignment && !in_array($alignment, $this->alignments)) {
58+
// prevent html injection in case the attribute is user input
59+
throw new Exception('An unknown alignment "' . $alignment . '" has been detected.');
60+
}
4861
}
4962

50-
$this->wrapElement('<h{heading}>{__buffer__}</h{heading}>', ['heading']);
63+
$this->wrapElement('<h{heading}{style}>{__buffer__}</h{heading}>', [
64+
'heading',
65+
'style' => static function ($value, $pick) {
66+
$alignment = $pick->optionValue('alignment');
67+
return $alignment ? ' style="text-align: ' . $alignment . ';"' : '';
68+
}
69+
]);
5170
}
5271
}

tests/HeadingAlignmentTest.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
namespace nadar\quill\tests;
3+
4+
/**
5+
* Test heading with alignment attributes.
6+
*
7+
* This test addresses the issue where headers with alignment attributes
8+
* were being rendered as <p> tags instead of <h1>-<h6> tags.
9+
*/
10+
class HeadingAlignmentTest extends DeltaTestCase
11+
{
12+
public $json = <<<'JSON'
13+
{
14+
"ops": [
15+
{
16+
"attributes": {
17+
"background": "transparent",
18+
"color": "#000000"
19+
},
20+
"insert": "Header"
21+
},
22+
{
23+
"attributes": {
24+
"align": "center",
25+
"header": 1
26+
},
27+
"insert": "\n"
28+
}
29+
]
30+
}
31+
JSON;
32+
33+
public $html = <<<'EOT'
34+
<h1 style="text-align: center;"><span style="background-color:transparent"><span style="color:#000000">Header</span></span></h1>
35+
EOT;
36+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php
2+
namespace nadar\quill\tests;
3+
4+
/**
5+
* Test various heading levels with different alignment options.
6+
*/
7+
class HeadingAlignmentVariationsTest extends DeltaTestCase
8+
{
9+
public $json = <<<'JSON'
10+
{
11+
"ops": [
12+
{
13+
"insert": "Right H2"
14+
},
15+
{
16+
"attributes": {
17+
"align": "right",
18+
"header": 2
19+
},
20+
"insert": "\n"
21+
},
22+
{
23+
"attributes": {
24+
"bold": true
25+
},
26+
"insert": "Justified H4"
27+
},
28+
{
29+
"attributes": {
30+
"align": "justify",
31+
"header": 4
32+
},
33+
"insert": "\n"
34+
},
35+
{
36+
"insert": "Left H3"
37+
},
38+
{
39+
"attributes": {
40+
"align": "left",
41+
"header": 3
42+
},
43+
"insert": "\n"
44+
}
45+
]
46+
}
47+
JSON;
48+
49+
public $html = <<<'EOT'
50+
<h2 style="text-align: right;">Right H2</h2><h4 style="text-align: justify;"><strong>Justified H4</strong></h4><h3 style="text-align: left;">Left H3</h3>
51+
EOT;
52+
}

0 commit comments

Comments
 (0)