diff --git a/docs/reference/enhancements.md b/docs/reference/enhancements.md
index 6156312e..24c301f2 100644
--- a/docs/reference/enhancements.md
+++ b/docs/reference/enhancements.md
@@ -441,6 +441,12 @@ Works with all list types:
block attribute for that following block; the list and item are
not terminated.
+**Stripped attribute names:** `start`, `type`, and `reversed` are HTML
+attributes valid only on `
`. When authored on a list item they are
+silently dropped from the rendered `- ` to keep output HTML valid.
+To set `
`, use a standard block-attribute line **before**
+the list: `{start=5}` followed by `1. ...`.
+
---
### Table Row and Cell Attributes
@@ -749,6 +755,9 @@ Attributes can be attached to individual ``, `- `, and `
- ` elements:
- `{...}` on line after term → applies to that `
- `
- `{...}` as last line in definition block → applies to that `
- ` (consistent with list items)
+**Stripped attribute names:** the same `start`, `type`, `reversed`
+strip applies to `
- ` output.
+
---
### Table Multi-line Cells, Rowspan, and Colspan
diff --git a/src/Renderer/HtmlRenderer.php b/src/Renderer/HtmlRenderer.php
index 2667a713..b068e3b9 100644
--- a/src/Renderer/HtmlRenderer.php
+++ b/src/Renderer/HtmlRenderer.php
@@ -88,6 +88,15 @@ class HtmlRenderer implements RendererInterface
*/
protected array $nodeRenderers = [];
+ /**
+ * Attribute names valid on
but not on - /
- . Stripped from
+ *
- /
- output to avoid emitting invalid HTML when authors put
+ * these names on a list item (e.g. as a postfix {start=5} line).
+ *
+ * @var array
+ */
+ protected const OL_ONLY_ATTRIBUTES = ['start', 'type', 'reversed'];
+
public function __construct(protected bool $xhtml = false)
{
$this->sharedRenderContext = new RenderContext();
@@ -741,7 +750,7 @@ protected function renderList(ListBlock $node): string
protected function renderListItem(ListItem $node, bool $tight = true): string
{
- $attrs = $this->renderAttributes($node);
+ $attrs = $this->renderAttributesExcluding($node, self::OL_ONLY_ATTRIBUTES);
$content = $this->renderChildren($node);
if ($tight) {
@@ -1239,7 +1248,7 @@ protected function renderDefinitionTerm(DefinitionTerm $node): string
protected function renderDefinitionDescription(DefinitionDescription $node): string
{
- $attrs = $this->renderAttributes($node);
+ $attrs = $this->renderAttributesExcluding($node, self::OL_ONLY_ATTRIBUTES);
$content = $this->renderChildren($node);
// Content goes on separate lines
diff --git a/tests/TestCase/DjotConverterTest.php b/tests/TestCase/DjotConverterTest.php
index 144cde52..25d74eb1 100644
--- a/tests/TestCase/DjotConverterTest.php
+++ b/tests/TestCase/DjotConverterTest.php
@@ -1104,6 +1104,80 @@ public function testListItemAttributesLooseListUnchanged(): void
$this->assertStringContainsString('
', $result);
}
+ public function testListItemAttributeStartIsStrippedFromLi(): void
+ {
+ // G3: `start` is an HTML attribute valid only on . It must
+ // be stripped from - output, never feed
, and never
+ // appear in HTML.
+ $djot = "1. item\n {start=5}\n";
+
+ $result = $this->converter->convert($djot);
+
+ $this->assertStringContainsString('- ', $result);
+ $this->assertStringNotContainsString('
- . Stripped
+ // from
- ; never overrides marker-derived
.
+ $djot = "(a) x\n {type=i}\n";
+
+ $result = $this->converter->convert($djot);
+
+ $this->assertStringContainsString('', $result);
+ $this->assertStringNotContainsString('- -only. Stripped from
- .
+ $djot = "1. item\n {reversed}\n";
+
+ $result = $this->converter->convert($djot);
+
+ $this->assertStringContainsString('
- ', $result);
+ $this->assertStringNotContainsString('
- assertStringNotContainsString('reversed=""', $result);
+ }
+
+ public function testListItemOtherAttributesUnchanged(): void
+ {
+ // G3 regression guard: only start/type/reversed are stripped.
+ // class, id, data-* pass through unchanged on
- .
+ $djot = "1. item\n {#anchor .step data-step=\"1\"}\n";
+
+ $result = $this->converter->convert($djot);
+
+ $this->assertStringContainsString('id="anchor"', $result);
+ $this->assertStringContainsString('class="step"', $result);
+ $this->assertStringContainsString('data-step="1"', $result);
+ }
+
+ public function testOlStartFromBlockAttrUnchanged(): void
+ {
+ // G3 regression guard: a block-attribute line BEFORE a list
+ // applies to the
and must still emit start/type as before.
+ $djot = "{start=5}\n1. item\n2. next\n";
+
+ $result = $this->converter->convert($djot);
+
+ $this->assertStringContainsString('.
+ $djot = ": term\n\n definition\n {start=5}\n";
+
+ $result = $this->converter->convert($djot);
+
+ $this->assertStringContainsString('- ', $result);
+ $this->assertStringNotContainsString('