Skip to content

Commit a129a85

Browse files
committed
fix attributes to be immutable to prevent accidental changes to shared.
1 parent c96ee58 commit a129a85

File tree

30 files changed

+263
-217
lines changed

30 files changed

+263
-217
lines changed

VERSION-TODO.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
- [Release 0.60.0](#release-0600)
88
- [API Refactoring](#api-refactoring)
99
- [Next 0.61.xx](#next-061xx)
10-
- [0.61.36](#06136)
10+
- [0.62.0](#0620)
1111
- [0.61.34](#06134)
1212
- [0.61.32](#06132)
1313
- [0.61.30](#06130)
@@ -230,10 +230,13 @@ Please give feedback on the upcoming changes if you have concerns about breaking
230230
* [ ] Fix: Html converter to not add spaces between end of inline marker and next punctuation:
231231
`.,:;`
232232

233-
## 0.61.36
233+
## 0.62.0
234234

235235
* Fix: HTML to Md converter to convert empty a tags to empty link text links. ie. `<a
236236
href="#abc"></a>` to `[](#abc)`, except when contained in heading elements.
237+
* Break: rename `Attributes` to `MutableAttributes` and create new immutable `Attributes` class.
238+
* Fix: do not remove `title` attribute provided by `LinkResolver` when link has no title. Allow
239+
link resolver titles to be used.
237240

238241
## 0.61.34
239242

flexmark-core-test/src/test/java/com/vladsch/flexmark/core/test/util/html/HtmlEmbeddedAttributeTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import com.vladsch.flexmark.util.data.MutableDataHolder;
1414
import com.vladsch.flexmark.util.data.MutableDataSet;
1515
import com.vladsch.flexmark.util.html.Attributes;
16+
import com.vladsch.flexmark.util.html.MutableAttributes;
1617
import com.vladsch.flexmark.util.sequence.BasedSequence;
1718
import org.jetbrains.annotations.NotNull;
1819
import org.junit.Before;
@@ -77,7 +78,7 @@ public static NodePostProcessorFactory Factory(DataHolder options) {
7778
public void process(@NotNull NodeTracker state, @NotNull Node node) {
7879
BasedSequence paragraphText = BasedSequence.NULL;
7980
if (node instanceof Paragraph) { // [foo](http://example.com)
80-
Attributes attributes = new Attributes();
81+
MutableAttributes attributes = new MutableAttributes();
8182
attributes.addValue("class", "caption");
8283

8384
node.appendChild(new EmbeddedAttributeProvider.EmbeddedNodeAttributes(node, attributes));

flexmark-docx-converter/src/main/java/com/vladsch/flexmark/docx/converter/DocxRenderer.java

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
import com.vladsch.flexmark.util.data.ScopedDataSet;
2121
import com.vladsch.flexmark.util.dependency.DependencyResolver;
2222
import com.vladsch.flexmark.util.html.Attributes;
23+
import com.vladsch.flexmark.util.html.MutableAttribute;
24+
import com.vladsch.flexmark.util.html.MutableAttributes;
2325
import com.vladsch.flexmark.util.misc.Extension;
2426
import com.vladsch.flexmark.util.sequence.Escaping;
2527
import org.docx4j.Docx4J;
@@ -704,7 +706,7 @@ private class MainDocxRenderer extends DocxContextImpl<Node> implements DocxRend
704706
String calculateNodeId(Node node) {
705707
String id = htmlIdGenerator.getId(node);
706708
if (attributeProviderFactories.size() != 0) {
707-
Attributes attributes = new Attributes();
709+
MutableAttributes attributes = new MutableAttributes();
708710
if (id != null) attributes.replaceValue("id", id);
709711

710712
for (AttributeProvider attributeProvider : myAttributeProviders) {
@@ -768,17 +770,17 @@ public String encodeUrl(@NotNull CharSequence url) {
768770
}
769771

770772
@Override
771-
public Attributes extendRenderingNodeAttributes(@NotNull AttributablePart part, @Nullable Attributes attributes) {
772-
Attributes attr = attributes != null ? attributes : new Attributes();
773+
public MutableAttributes extendRenderingNodeAttributes(@NotNull AttributablePart part, @Nullable Attributes attributes) {
774+
MutableAttributes attr = attributes != null ? attributes.toMutable() : new MutableAttributes();
773775
for (AttributeProvider attributeProvider : myAttributeProviders) {
774776
attributeProvider.setAttributes(this.renderingNode, part, attr);
775777
}
776778
return attr;
777779
}
778780

779781
@Override
780-
public Attributes extendRenderingNodeAttributes(@NotNull Node node, @NotNull AttributablePart part, @Nullable Attributes attributes) {
781-
Attributes attr = attributes != null ? attributes : new Attributes();
782+
public MutableAttributes extendRenderingNodeAttributes(@NotNull Node node, @NotNull AttributablePart part, @Nullable Attributes attributes) {
783+
MutableAttributes attr = attributes != null ? attributes.toMutable() : new MutableAttributes();
782784
for (AttributeProvider attributeProvider : myAttributeProviders) {
783785
attributeProvider.setAttributes(node, part, attr);
784786
}
@@ -836,12 +838,6 @@ final public Iterable<? extends Node> reversedNodesOfType(Collection<Class<?>> c
836838
return collectedNodes == null ? NULL_ITERABLE : collectedNodes.reversedItemsOfType(Node.class, classes);
837839
}
838840

839-
@NotNull
840-
@Override
841-
public ResolvedLink resolveLink(@NotNull LinkType linkType, @NotNull CharSequence url, Boolean urlEncode) {
842-
return resolveLink(linkType, url, null, urlEncode);
843-
}
844-
845841
@NotNull
846842
@Override
847843
public ResolvedLink resolveLink(@NotNull LinkType linkType, @NotNull CharSequence url, Attributes attributes, Boolean urlEncode) {
@@ -865,7 +861,6 @@ public ResolvedLink resolveLink(@NotNull LinkType linkType, @NotNull CharSequenc
865861
}
866862
}
867863

868-
// put it in the map
869864
resolvedLinks.put(urlSeq, resolvedLink);
870865
}
871866

flexmark-docx-converter/src/main/java/com/vladsch/flexmark/docx/converter/internal/CoreNodeDocxRenderer.java

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import com.vladsch.flexmark.util.format.options.ListSpacing;
4646
import com.vladsch.flexmark.util.html.Attribute;
4747
import com.vladsch.flexmark.util.html.Attributes;
48+
import com.vladsch.flexmark.util.html.MutableAttributes;
4849
import com.vladsch.flexmark.util.misc.ImageUtils;
4950
import com.vladsch.flexmark.util.misc.Pair;
5051
import com.vladsch.flexmark.util.sequence.BasedSequence;
@@ -933,7 +934,7 @@ private void render(Link node, DocxRendererContext docx) {
933934
ResolvedLink resolvedLink = docx.resolveLink(LinkType.LINK, node.getUrl().unescape(), null, null);
934935

935936
// we have a title part, use that
936-
Attributes attributes = resolvedLink.getNonNullAttributes();
937+
MutableAttributes attributes = resolvedLink.getNonNullAttributes().toMutable();
937938

938939
if (node.getTitle().isNotNull()) {
939940
attributes.replaceValue(Attribute.TITLE_ATTR, node.getTitle().unescape());
@@ -1440,9 +1441,7 @@ private void render(LinkRef node, DocxRendererContext docx) {
14401441

14411442
resolvedLink = docx.resolveLink(LinkType.LINK, url, null, null);
14421443
if (reference.getTitle().isNotNull()) {
1443-
resolvedLink.getNonNullAttributes().replaceValue(Attribute.TITLE_ATTR, reference.getTitle().unescape());
1444-
} else {
1445-
resolvedLink.getNonNullAttributes().remove(Attribute.TITLE_ATTR);
1444+
resolvedLink = resolvedLink.withTitle(reference.getTitle().unescape());
14461445
}
14471446
} else {
14481447
// see if have reference resolver and this is resolved
@@ -1635,7 +1634,7 @@ public R newImage(DocxRendererContext docx, BufferedImage image, String filename
16351634
private void render(Image node, DocxRendererContext docx) {
16361635
String altText = new TextCollectingVisitor().collectAndGetText(node);
16371636
ResolvedLink resolvedLink = docx.resolveLink(LinkType.IMAGE, node.getUrl().unescape(), null, null);
1638-
Attributes attributes = resolvedLink.getNonNullAttributes();
1637+
MutableAttributes attributes = resolvedLink.getNonNullAttributes().toMutable();
16391638

16401639
if (!node.getUrlContent().isEmpty()) {
16411640
// reverse URL encoding of =, &
@@ -1667,7 +1666,7 @@ private void render(Emoji node, DocxRendererContext docx) {
16671666
} else {
16681667
ResolvedLink resolvedLink = docx.resolveLink(LinkType.IMAGE, shortcut.emojiText, null, null);
16691668
//String altText = shortcut.alt;
1670-
Attributes attributes = resolvedLink.getNonNullAttributes();
1669+
MutableAttributes attributes = resolvedLink.getNonNullAttributes().toMutable();
16711670

16721671
if (shortcut.alt != null) {
16731672
attributes.replaceValue("alt", shortcut.alt);
@@ -1748,9 +1747,7 @@ private void render(ImageRef node, DocxRendererContext docx) {
17481747

17491748
resolvedLink = docx.resolveLink(LinkType.IMAGE, url, null, null);
17501749
if (reference.getTitle().isNotNull()) {
1751-
resolvedLink.getNonNullAttributes().replaceValue(Attribute.TITLE_ATTR, reference.getTitle().unescape());
1752-
} else {
1753-
resolvedLink.getNonNullAttributes().remove(Attribute.TITLE_ATTR);
1750+
resolvedLink = resolvedLink.withTitle(reference.getTitle().unescape());
17541751
}
17551752
} else {
17561753
// see if have reference resolver and this is resolved
@@ -1770,7 +1767,7 @@ private void render(ImageRef node, DocxRendererContext docx) {
17701767
}
17711768
} else {
17721769
String altText = new TextCollectingVisitor().collectAndGetText(node);
1773-
Attributes attributes = resolvedLink.getNonNullAttributes();
1770+
MutableAttributes attributes = resolvedLink.getNonNullAttributes().toMutable();
17741771

17751772
if (!altText.isEmpty()) {
17761773
attributes.replaceValue("alt", altText);
@@ -1788,7 +1785,7 @@ private void render(ImageRef node, DocxRendererContext docx) {
17881785
}
17891786
}
17901787

1791-
private R renderImage(DocxRendererContext docx, ResolvedLink resolvedLink, Attributes attributes, double scale) {
1788+
private R renderImage(DocxRendererContext docx, ResolvedLink resolvedLink, MutableAttributes attributes, double scale) {
17921789
BufferedImage image = null;
17931790
int id1 = imageId++;
17941791
int id2 = imageId++;
@@ -2152,7 +2149,7 @@ private void render(EnumeratedReferenceLink node, DocxRendererContext docx) {
21522149
EnumeratedReferenceRendering[] renderings = enumeratedOrdinals.getEnumeratedReferenceOrdinals(text);
21532150

21542151
String title = new EnumRefTextCollectingVisitor().collectAndGetText(node.getChars().getBaseSequence(), renderings, null);
2155-
Attributes attributes = new Attributes();
2152+
MutableAttributes attributes = new MutableAttributes();
21562153

21572154
if (title != null) {
21582155
attributes.replaceValue(Attribute.TITLE_ATTR, title);

flexmark-docx-converter/src/main/java/com/vladsch/flexmark/docx/converter/util/DocxContext.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.vladsch.flexmark.html.renderer.AttributablePart;
55
import com.vladsch.flexmark.util.ast.Node;
66
import com.vladsch.flexmark.util.html.Attributes;
7+
import com.vladsch.flexmark.util.html.MutableAttributes;
78
import org.docx4j.openpackaging.exceptions.Docx4JException;
89
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
910
import org.docx4j.openpackaging.parts.Part;
@@ -53,7 +54,7 @@ public interface DocxContext<T> extends DocxContextFrameProvider<T> {
5354
* @param attributes the attributes that were calculated by the renderer or null, these may be modified. To preserve originals pass a copy.
5455
* @return the extended attributes with added/updated/removed entries
5556
*/
56-
Attributes extendRenderingNodeAttributes(AttributablePart part, Attributes attributes);
57+
MutableAttributes extendRenderingNodeAttributes(AttributablePart part, Attributes attributes);
5758

5859
/**
5960
* Extend the attributes by extensions for the node being currently rendered.
@@ -63,7 +64,7 @@ public interface DocxContext<T> extends DocxContextFrameProvider<T> {
6364
* @param attributes the attributes that were calculated by the renderer or null, these may be modified. To preserve originals pass a copy.
6465
* @return the extended attributes with added/updated/removed entries
6566
*/
66-
Attributes extendRenderingNodeAttributes(Node node, AttributablePart part, Attributes attributes);
67+
MutableAttributes extendRenderingNodeAttributes(Node node, AttributablePart part, Attributes attributes);
6768

6869
/**
6970
* @return the main document

flexmark-docx-converter/src/test/java/com/vladsch/flexmark/docx/converter/ComboDocxConverterSpecTestBase.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import com.vladsch.flexmark.util.data.MutableDataSet;
3636
import com.vladsch.flexmark.util.data.SharedDataKeys;
3737
import com.vladsch.flexmark.util.html.Attributes;
38+
import com.vladsch.flexmark.util.html.MutableAttributes;
3839
import org.apache.log4j.Logger;
3940
import org.apache.log4j.varia.NullAppender;
4041
import org.docx4j.Docx4J;
@@ -282,12 +283,12 @@ final public void fullTestSpecStarting() {
282283

283284
myDocxContext = new DocxContextImpl<Node>(myPackage, null) {
284285
@Override
285-
public Attributes extendRenderingNodeAttributes(AttributablePart part, Attributes attributes) {
286+
public MutableAttributes extendRenderingNodeAttributes(AttributablePart part, Attributes attributes) {
286287
return null;
287288
}
288289

289290
@Override
290-
public Attributes extendRenderingNodeAttributes(Node node, AttributablePart part, Attributes attributes) {
291+
public MutableAttributes extendRenderingNodeAttributes(Node node, AttributablePart part, Attributes attributes) {
291292
return null;
292293
}
293294

flexmark-ext-attributes/src/main/java/com/vladsch/flexmark/ext/attributes/internal/AttributesAttributeProvider.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
import com.vladsch.flexmark.util.ast.Node;
1313
import com.vladsch.flexmark.util.data.DataHolder;
1414
import com.vladsch.flexmark.util.html.Attribute;
15-
import com.vladsch.flexmark.util.html.Attributes;
15+
import com.vladsch.flexmark.util.html.MutableAttributes;
1616
import com.vladsch.flexmark.util.sequence.BasedSequence;
1717
import org.jetbrains.annotations.NotNull;
1818

@@ -31,7 +31,7 @@ public AttributesAttributeProvider(LinkResolverContext context) {
3131
}
3232

3333
@Override
34-
public void setAttributes(@NotNull Node node, @NotNull AttributablePart part, @NotNull Attributes attributes) {
34+
public void setAttributes(@NotNull Node node, @NotNull AttributablePart part, @NotNull MutableAttributes attributes) {
3535
// regression bug, issue #372, add option, default to both as before
3636
if (part == CoreNodeRenderer.CODE_CONTENT ? attributeOptions.fencedCodeAddAttributes.addToCode : attributeOptions.fencedCodeAddAttributes.addToPre) {
3737
ArrayList<AttributesNode> nodeAttributesList = nodeAttributeRepository.get(node);

flexmark-ext-attributes/src/main/java/com/vladsch/flexmark/ext/attributes/internal/AttributesNodeFormatter.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@
44
import com.vladsch.flexmark.ast.Heading;
55
import com.vladsch.flexmark.ast.util.AnchorRefTargetBlockVisitor;
66
import com.vladsch.flexmark.ext.attributes.*;
7-
import com.vladsch.flexmark.formatter.*;
87
import com.vladsch.flexmark.formatter.Formatter;
8+
import com.vladsch.flexmark.formatter.*;
99
import com.vladsch.flexmark.html.renderer.HtmlIdGenerator;
1010
import com.vladsch.flexmark.util.ast.Document;
1111
import com.vladsch.flexmark.util.ast.Node;
1212
import com.vladsch.flexmark.util.data.DataHolder;
1313
import com.vladsch.flexmark.util.data.DataKey;
1414
import com.vladsch.flexmark.util.html.Attribute;
15-
import com.vladsch.flexmark.util.html.Attributes;
15+
import com.vladsch.flexmark.util.html.MutableAttributes;
1616
import com.vladsch.flexmark.util.sequence.BasedSequence;
1717
import com.vladsch.flexmark.util.sequence.PrefixedSubSequence;
1818
import org.jetbrains.annotations.NotNull;
@@ -637,7 +637,7 @@ static AttributeNode combineAttributes(LinkedHashMap<String, AttributeNode> attr
637637
AttributeNode removed1 = attributeNodes.remove(Attribute.CLASS_ATTR);
638638
AttributeNode removed2 = attributeNodes.remove(".");
639639
if (removed1 != null || removed2 != null) {
640-
Attributes attributes = new Attributes();
640+
MutableAttributes attributes = new MutableAttributes();
641641
if (removed1 != null) attributes.addValue(Attribute.CLASS_ATTR, removed1.getValue());
642642
if (removed2 != null) attributes.addValue(Attribute.CLASS_ATTR, removed2.getValue());
643643
String value = attributes.getValue(Attribute.CLASS_ATTR);
@@ -651,7 +651,7 @@ static AttributeNode combineAttributes(LinkedHashMap<String, AttributeNode> attr
651651
AttributeNode newNode = attributeNode;
652652
AttributeNode removed1 = attributeNodes.remove(Attribute.STYLE_ATTR);
653653
if (removed1 != null) {
654-
Attributes attributes = new Attributes();
654+
MutableAttributes attributes = new MutableAttributes();
655655
attributes.addValue(Attribute.STYLE_ATTR, removed1.getValue());
656656
String value = attributes.getValue(Attribute.STYLE_ATTR);
657657
if (!attributeNode.getValue().equals(value)) {

flexmark-ext-gitlab/src/main/java/com/vladsch/flexmark/ext/gitlab/internal/GitLabNodeRenderer.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -198,9 +198,7 @@ private void render(ImageRef node, NodeRendererContext context, HtmlWriter html)
198198

199199
resolvedLink = context.resolveLink(LinkType.IMAGE, url, null, null);
200200
if (reference.getTitle().isNotNull()) {
201-
resolvedLink.getNonNullAttributes().replaceValue(Attribute.TITLE_ATTR, reference.getTitle().unescape());
202-
} else {
203-
resolvedLink.getNonNullAttributes().remove(Attribute.TITLE_ATTR);
201+
resolvedLink = resolvedLink.withTitle(reference.getTitle().unescape());
204202
}
205203
} else {
206204
// see if have reference resolver and this is resolved

flexmark-ext-zzzzzz/src/main/java/com/vladsch/flexmark/ext/zzzzzz/internal/ZzzzzzAttributeProvider.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import com.vladsch.flexmark.util.ast.Node;
1313
import com.vladsch.flexmark.util.data.DataHolder;
1414
import com.vladsch.flexmark.util.html.Attributes;
15+
import com.vladsch.flexmark.util.html.MutableAttributes;
1516
import org.jetbrains.annotations.NotNull;
1617

1718
import static com.vladsch.flexmark.html.renderer.AttributablePart.LINK;
@@ -36,19 +37,19 @@ public ZzzzzzAttributeProvider(LinkResolverContext context) {
3637
}
3738

3839
@Override
39-
public void setAttributes(@NotNull Node node, @NotNull AttributablePart part, @NotNull Attributes attributes) {
40+
public void setAttributes(@NotNull Node node, @NotNull AttributablePart part, @NotNull MutableAttributes attributes) {
4041
nodeAdapter.setAttributes(node, part, attributes);
4142
}
4243

43-
private void setLinkAttributes(LinkNode node, AttributablePart part, Attributes attributes) {
44+
private void setLinkAttributes(LinkNode node, AttributablePart part, MutableAttributes attributes) {
4445
setLinkAttributes(part, attributes);
4546
}
4647

47-
private void setLinkAttributes(RefNode node, AttributablePart part, Attributes attributes) {
48+
private void setLinkAttributes(RefNode node, AttributablePart part, MutableAttributes attributes) {
4849
setLinkAttributes(part, attributes);
4950
}
5051

51-
private void setLinkAttributes(AttributablePart part, Attributes attributes) {
52+
private void setLinkAttributes(AttributablePart part, MutableAttributes attributes) {
5253
if (part == LINK) {
5354
String linkStatus = attributes.getValue(LINK_STATUS_ATTR);
5455
if (LinkStatus.NOT_FOUND.isStatus(linkStatus)) {

0 commit comments

Comments
 (0)