This is an automated email from the ASF dual-hosted git repository.
kwin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven-doxia.git
The following commit(s) were added to refs/heads/master by this push:
new bb0037ed Optionally leave fragments of internal links untouched
bb0037ed is described below
commit bb0037eda90a3ec59c054b94b51e18e75572d604
Author: Konrad Windszus <[email protected]>
AuthorDate: Wed Feb 11 11:08:52 2026 +0100
Optionally leave fragments of internal links untouched
Evaluate "rel" attribute. If set to "external" the fragment is not
normalized to a Doxia ID.
This is particularly helpful to link out to (internal) javadoc, where
fragments contain "(" and ")" characters which are invalid in Doxia IDs.
This closes #1029
---
.../maven/doxia/parser/Xhtml5BaseParser.java | 4 ++-
.../maven/doxia/parser/Xhtml5BaseParserTest.java | 41 +++++++++++++++-------
.../doxia-module-markdown/src/site/apt/index.apt | 3 +-
.../doxia/module/markdown/MarkdownParserTest.java | 27 ++++++++++++++
.../doxia-module-xhtml5/src/site/markdown/index.md | 33 +++++++++++++++++
5 files changed, 94 insertions(+), 14 deletions(-)
diff --git
a/doxia-core/src/main/java/org/apache/maven/doxia/parser/Xhtml5BaseParser.java
b/doxia-core/src/main/java/org/apache/maven/doxia/parser/Xhtml5BaseParser.java
index dbfed392..a2b03c81 100644
---
a/doxia-core/src/main/java/org/apache/maven/doxia/parser/Xhtml5BaseParser.java
+++
b/doxia-core/src/main/java/org/apache/maven/doxia/parser/Xhtml5BaseParser.java
@@ -813,7 +813,9 @@ public class Xhtml5BaseParser extends AbstractXmlParser
implements HtmlMarkup {
if (href != null) {
int hashIndex = href.indexOf('#');
- if (hashIndex != -1 && !DoxiaUtils.isExternalLink(href)) {
+ if (hashIndex != -1
+ && !DoxiaUtils.isExternalLink(href)
+ &&
!"external".equals(attribs.getAttribute(Attribute.REL.toString()))) {
String hash = href.substring(hashIndex + 1);
if (!DoxiaUtils.isValidId(hash)) {
diff --git
a/doxia-core/src/test/java/org/apache/maven/doxia/parser/Xhtml5BaseParserTest.java
b/doxia-core/src/test/java/org/apache/maven/doxia/parser/Xhtml5BaseParserTest.java
index 1777e648..b29b8e3d 100644
---
a/doxia-core/src/test/java/org/apache/maven/doxia/parser/Xhtml5BaseParserTest.java
+++
b/doxia-core/src/test/java/org/apache/maven/doxia/parser/Xhtml5BaseParserTest.java
@@ -841,6 +841,35 @@ class Xhtml5BaseParserTest extends AbstractParserTest {
assertEquals("division_", element.getName());
}
+ @Test
+ void anchorLinkWithExternalRel() throws Exception {
+ // although the fragment is not a valid doxia id it should be used as
is, because the rel="external" indicates
+ // that this is an external link
+ String text = "<a href=\"index.html#1invalid\" rel=\"external\"></a>";
+
+ parser.parse(text, sink);
+ Iterator<SinkEventElement> it = sink.getEventList().iterator();
+
+ SinkEventElement element = it.next();
+
+ assertEquals("link", element.getName());
+ assertEquals("index.html#1invalid", element.getArgs()[0]);
+ assertEquals("external", ((SinkEventAttributeSet)
element.getArgs()[1]).getAttribute("rel"));
+ assertEquals("link_", it.next().getName());
+ }
+
+ @Test
+ void anchorWithName() throws ParseException {
+ String text = "<a name=\"test\"></a>";
+
+ parser.parse(text, sink);
+
+ Iterator<SinkEventElement> it = sink.getEventList().iterator();
+ // first attribute is the id, second is all given attributes
+ assertSinkEquals(it.next(), "anchor", "test", new
SinkEventAttributeSet("name", "test"));
+ assertSinkEquals(it, "anchor_");
+ }
+
/**
* Test entities in attributes.
*
@@ -942,16 +971,4 @@ class Xhtml5BaseParserTest extends AbstractParserTest {
protected String getVerbatimCodeSource() {
return "<pre><code><>{}=#*</code></pre>";
}
-
- @Test
- void anchorWithName() throws ParseException {
- String text = "<a name=\"test\"></a>";
-
- parser.parse(text, sink);
-
- Iterator<SinkEventElement> it = sink.getEventList().iterator();
- // first attribute is the id, second is all given attributes
- assertSinkEquals(it.next(), "anchor", "test", new
SinkEventAttributeSet("name", "test"));
- assertSinkEquals(it, "anchor_");
- }
}
diff --git a/doxia-modules/doxia-module-markdown/src/site/apt/index.apt
b/doxia-modules/doxia-module-markdown/src/site/apt/index.apt
index bbfbb15c..55aad201 100644
--- a/doxia-modules/doxia-module-markdown/src/site/apt/index.apt
+++ b/doxia-modules/doxia-module-markdown/src/site/apt/index.apt
@@ -82,7 +82,8 @@ doxia-module-markdown
* Parser
- The parser will first convert Markdown into HTML and then parse the HTML
into Doxia Sink API methods calls.
+ The parser will first convert Markdown into HTML and then parse the HTML
into Doxia Sink API methods calls leveraging the
+ {{{../doxia-module-xhtml5/index.html}XHTML5 parser}}.
* References
diff --git
a/doxia-modules/doxia-module-markdown/src/test/java/org/apache/maven/doxia/module/markdown/MarkdownParserTest.java
b/doxia-modules/doxia-module-markdown/src/test/java/org/apache/maven/doxia/module/markdown/MarkdownParserTest.java
index 1fad1a69..27a29f72 100644
---
a/doxia-modules/doxia-module-markdown/src/test/java/org/apache/maven/doxia/module/markdown/MarkdownParserTest.java
+++
b/doxia-modules/doxia-module-markdown/src/test/java/org/apache/maven/doxia/module/markdown/MarkdownParserTest.java
@@ -888,4 +888,31 @@ class MarkdownParserTest extends AbstractParserTest {
assertSinkStartsWith(eventIterator, "paragraph", "anchor", "text",
"anchor_", "paragraph_");
assertEventSuffix(eventIterator);
}
+
+ @Test
+ void relativeLinkWithAnchorInvalidDoxiaId() throws ParseException {
+ Iterator<SinkEventElement> eventIterator =
parseSourceToEventTestingSink("[Test URL](test.html#anchor\\(\\))")
+ .getEventList()
+ .iterator();
+ assertEventPrefix(eventIterator);
+ assertSinkStartsWith(eventIterator, "paragraph");
+ SinkEventElement linkEvent = eventIterator.next();
+ assertEquals("link", linkEvent.getName());
+ // converted to valid doxia id (through DoxiaUtils.encodeId)
+ assertEquals("test.html#anchor.28.29", linkEvent.getArgs()[0]);
+ }
+
+ @Test
+ void relativeLinkWithAnchorInvalidDoxiaIdAndRelExternal() throws
ParseException {
+ Iterator<SinkEventElement> eventIterator =
parseSourceToEventTestingSink(
+ "<a href=\"test.html#anchor()\" rel=\"external\">Test
URL</a>")
+ .getEventList()
+ .iterator();
+ assertEventPrefix(eventIterator);
+ assertSinkStartsWith(eventIterator, "paragraph");
+ SinkEventElement linkEvent = eventIterator.next();
+ assertEquals("link", linkEvent.getName());
+ // converted to valid doxia id (through DoxiaUtils.encodeId)
+ assertEquals("test.html#anchor()", linkEvent.getArgs()[0]);
+ }
}
diff --git a/doxia-modules/doxia-module-xhtml5/src/site/markdown/index.md
b/doxia-modules/doxia-module-xhtml5/src/site/markdown/index.md
new file mode 100644
index 00000000..f2ef3f70
--- /dev/null
+++ b/doxia-modules/doxia-module-xhtml5/src/site/markdown/index.md
@@ -0,0 +1,33 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+# Doxia XHTML5 Module
+
+This parser and sink digests and emits sources compliant with the [XML syntax
of HTML5](https://html.spec.whatwg.org/#the-xhtml-syntax).
+
+## Special handling of anchors
+
+Anchor ids/names need to follow a strict syntax in Doxia, therefore both
anchor links as well as targets are automatically adjusted to comply with that
syntax. Further details in
[DoxiaUtils.encodeId(...)](../../doxia-core/apidocs/org/apache/maven/doxia/util/DoxiaUtils.html#encodeId-java.lang.String-).
+
+In order to leave the links unprocessed use attribute `rel` with value
`external` like this
+
+```
+<a href="testpage#specialanchor()" rel="external">...</a>
+```
+
+Otherwise the fragment `specialanchor()` would be converted as `(` and `)` are
not valid in Doxia IDs.
\ No newline at end of file