Skip to content

Commit

Permalink
[DOXIA-734] Restore handling of XHTML 1.0 obsolete attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
kwin committed Mar 14, 2024
1 parent 6091eef commit 6e9d899
Show file tree
Hide file tree
Showing 4 changed files with 196 additions and 93 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -379,11 +379,14 @@ protected void handleEntity(XmlPullParser parser, Sink sink) throws XmlPullParse
* method.
*/
protected void handleUnknown(XmlPullParser parser, Sink sink, int type) {
Object[] required = new Object[] {type};

SinkEventAttributeSet attribs = getAttributesFromParser(parser);

sink.unknown(parser.getName(), required, attribs);
handleUnknown(parser.getName(), attribs, sink, type);
}

protected void handleUnknown(String elementName, SinkEventAttributeSet attribs, Sink sink, int type) {
Object[] required = new Object[] {type};
sink.unknown(elementName, required, attribs);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* 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.
*/
package org.apache.maven.doxia.parser;

import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

import org.apache.maven.doxia.sink.Sink;
import org.apache.maven.doxia.sink.impl.SinkEventAttributeSet;
import org.codehaus.plexus.util.xml.pull.XmlPullParser;

/**
* Acts as bridge between legacy parsers relying on <a href="https://www.w3.org/TR/xhtml1/">XHTML 1.0 Transitional (based on HTML4.0.1)</a>
* and the {@link Xhtml5BaseParser} only supporting HTML5 elements/attributes.
*
* Adds support for elements/attributes which <a href="https://html.spec.whatwg.org/#non-conforming-features">became obsolete in HTML5</a> but are
* commonly used for XDoc/FML.
*
* @see <a href="https://www.w3.org/TR/html5-diff/">HTML5 Differences from HTML4</a>.
*/
public class Xhtml1BaseParser extends Xhtml5BaseParser {

private static final class AttributeMapping {
private final String sourceName;
private final String targetName;
private final Function<String, String> valueMapper;

AttributeMapping(String sourceAttribute, String targetAttribute) {
this(sourceAttribute, targetAttribute, Function.identity());
}

AttributeMapping(String sourceName, String targetName, Function<String, String> valueMapper) {
super();
this.sourceName = sourceName;
this.targetName = targetName;
this.valueMapper = valueMapper;
}

public String getSourceName() {
return sourceName;
}

public String getTargetName() {
return targetName;
}

public Function<String, String> getValueMapper() {
return valueMapper;
}
}

/**
* All obsolete attributes in a map with key = affected element name, value = {@link AttributeMapping}
*/
private static final Map<String, AttributeMapping> ATTRIBUTE_MAPPING_TABLE = new HashMap<>();

static {
ATTRIBUTE_MAPPING_TABLE.put("a", new AttributeMapping("name", "id"));
}

/**
* Translates obsolete XHTML 1.0 attributes to valid XHTML5 ones before calling the underlying {@link Xhtml5BaseParser}.
*/
@Override
protected boolean baseStartTag(XmlPullParser parser, Sink sink) {
SinkEventAttributeSet attribs = getAttributesFromParser(parser);
String elementName = parser.getName();
AttributeMapping attributeMapping = ATTRIBUTE_MAPPING_TABLE.get(elementName);
if (attributeMapping != null) {
String attributeValue = (String) attribs.getAttribute(attributeMapping.getSourceName());
if (attributeValue != null) {
attribs.addAttribute(
attributeMapping.getTargetName(),
attributeMapping.getValueMapper().apply(attributeValue));
attribs.removeAttribute(attributeMapping.getSourceName());
}
}
return super.baseStartTag(elementName, attribs, sink);
}
}

0 comments on commit 6e9d899

Please sign in to comment.