-
Notifications
You must be signed in to change notification settings - Fork 274
/
Copy pathYouTubeLinkSample.java
161 lines (135 loc) · 5.91 KB
/
YouTubeLinkSample.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
package com.vladsch.flexmark.java.samples;
import com.vladsch.flexmark.ast.InlineLinkNode;
import com.vladsch.flexmark.ast.Link;
import com.vladsch.flexmark.ast.Text;
import com.vladsch.flexmark.html.HtmlRenderer;
import com.vladsch.flexmark.html.HtmlWriter;
import com.vladsch.flexmark.html.renderer.*;
import com.vladsch.flexmark.parser.Parser;
import com.vladsch.flexmark.parser.block.NodePostProcessor;
import com.vladsch.flexmark.parser.block.NodePostProcessorFactory;
import com.vladsch.flexmark.util.ast.Document;
import com.vladsch.flexmark.util.ast.Node;
import com.vladsch.flexmark.util.ast.NodeTracker;
import com.vladsch.flexmark.util.data.DataHolder;
import com.vladsch.flexmark.util.data.MutableDataHolder;
import com.vladsch.flexmark.util.sequence.BasedSequence;
import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.Set;
public class YouTubeLinkSample {
public static class YouTubeLink extends InlineLinkNode {
public YouTubeLink() {
}
public YouTubeLink(Link other) {
super(other.baseSubSequence(other.getStartOffset() - 1, other.getEndOffset()),
other.baseSubSequence(other.getStartOffset() - 1, other.getTextOpeningMarker().getEndOffset()),
other.getText(),
other.getTextClosingMarker(),
other.getLinkOpeningMarker(),
other.getUrl(),
other.getTitleOpeningMarker(),
other.getTitle(),
other.getTitleClosingMarker(),
other.getLinkClosingMarker()
);
}
@Override
public void setTextChars(BasedSequence textChars) {
int textCharsLength = textChars.length();
this.textOpeningMarker = textChars.subSequence(0, 1);
this.text = textChars.subSequence(1, textCharsLength - 1).trim();
this.textClosingMarker = textChars.subSequence(textCharsLength - 1, textCharsLength);
}
}
public static class YouTubeLinkNodePostProcessor extends NodePostProcessor {
public YouTubeLinkNodePostProcessor(DataHolder options) {
}
@Override
public void process(@NotNull NodeTracker state, @NotNull Node node) {
if (node instanceof Link) {
Node previous = node.getPrevious();
if (previous instanceof Text) {
BasedSequence chars = previous.getChars();
if (chars.endsWith("@") && chars.isContinuedBy(node.getChars())) {
// trim previous chars to remove '@'
previous.setChars(chars.subSequence(0, chars.length() - 1));
YouTubeLink youTubeLink = new YouTubeLink((Link) node);
youTubeLink.takeChildren(node);
node.unlink();
previous.insertAfter(youTubeLink);
state.nodeRemoved(node);
state.nodeAddedWithChildren(youTubeLink);
}
}
}
}
public static class Factory extends NodePostProcessorFactory {
public Factory(DataHolder options) {
super(false);
addNodes(Link.class);
}
@NotNull
@Override
public NodePostProcessor apply(@NotNull Document document) {
return new YouTubeLinkNodePostProcessor(document);
}
}
}
public static class YouTubeLinkNodeRenderer implements NodeRenderer {
public YouTubeLinkNodeRenderer(DataHolder options) {
}
@Override
public Set<NodeRenderingHandler<?>> getNodeRenderingHandlers() {
HashSet<NodeRenderingHandler<?>> set = new HashSet<>();
set.add(new NodeRenderingHandler<>(YouTubeLink.class, this::render));
return set;
}
private void render(YouTubeLink node, NodeRendererContext context, HtmlWriter html) {
if (context.isDoNotRenderLinks()) {
context.renderChildren(node);
} else {
// standard Link Rendering
ResolvedLink resolvedLink = context.resolveLink(LinkType.LINK, node.getUrl().unescape(), null);
html.attr("href", resolvedLink.getUrl());
if (node.getTitle().isNotNull()) {
html.attr("title", node.getTitle().unescape());
}
html.srcPos(node.getChars()).withAttr(resolvedLink).tag("a");
context.renderChildren(node);
html.tag("/a");
}
}
public static class Factory implements NodeRendererFactory {
@NotNull
@Override
public NodeRenderer apply(@NotNull DataHolder options) {
return new YouTubeLinkNodeRenderer(options);
}
}
}
public static class YouTubeLinkExtension implements Parser.ParserExtension, HtmlRenderer.HtmlRendererExtension {
private YouTubeLinkExtension() {
}
public static YouTubeLinkExtension create() {
return new YouTubeLinkExtension();
}
@Override
public void extend(Parser.Builder parserBuilder) {
parserBuilder.postProcessorFactory(new YouTubeLinkNodePostProcessor.Factory(parserBuilder));
}
@Override
public void rendererOptions(@NotNull MutableDataHolder options) {
}
@Override
public void parserOptions(MutableDataHolder options) {
}
@Override
public void extend(@NotNull HtmlRenderer.Builder htmlRendererBuilder, @NotNull String rendererType) {
if (htmlRendererBuilder.isRendererType("HTML")) {
htmlRendererBuilder.nodeRendererFactory(new YouTubeLinkNodeRenderer.Factory());
} else if (htmlRendererBuilder.isRendererType("JIRA")) {
}
}
}
}