Revisão | 103 (tree) |
---|---|
Hora | 2022-07-27 17:37:07 |
Autor | ![]() |
* catalpa 0.9
flexmark-ext-highlight-0.3.2.jar, flexmark-ext-inline-tags-0.3.2.jar をソースコードに取り込み、外部ライブラリとして参照しなくなりました。
flexmark 0.62.2 -> 0.64.0
fx-util 0.4.4 -> 0.4.5
jna 5.6.0 -> 5.11.0
ikonli 12.2.0 -> 12.3.1
@@ -1,5 +1,7 @@ | ||
1 | 1 | package net.osdn.catalpa.addon.blog; |
2 | 2 | |
3 | +import javafx.scene.paint.Color; | |
4 | + | |
3 | 5 | import java.time.LocalDate; |
4 | 6 | import java.util.ArrayList; |
5 | 7 | import java.util.List; |
@@ -30,6 +32,14 @@ | ||
30 | 32 | public String getName() { |
31 | 33 | return name; |
32 | 34 | } |
35 | + | |
36 | + /** カテゴリー名から決定した色相を返します。 | |
37 | + * | |
38 | + * @return 色相(0~359) | |
39 | + */ | |
40 | + public int getHue() { | |
41 | + return (name.hashCode() & 0x7FFF) % 360; | |
42 | + } | |
33 | 43 | |
34 | 44 | public void add(Post post) { |
35 | 45 | date = null; |
@@ -48,6 +48,20 @@ | ||
48 | 48 | public Set<Category> getCategories() { |
49 | 49 | return categories; |
50 | 50 | } |
51 | + | |
52 | + /** 記事のカテゴリーから決定した色相を返します。 | |
53 | + * | |
54 | + * @return 色相(0~359) | |
55 | + */ | |
56 | + public int getHue() { | |
57 | + int hue = 0; | |
58 | + int influence = 1; | |
59 | + for(Category category : categories) { | |
60 | + hue += (category.getHue() / influence); | |
61 | + influence++; | |
62 | + } | |
63 | + return hue % 360; | |
64 | + } | |
51 | 65 | |
52 | 66 | public String getLeading() { |
53 | 67 | return leading; |
@@ -0,0 +1,35 @@ | ||
1 | +package net.osdn.catalpa.flexmark.ext.highlight; | |
2 | + | |
3 | +import com.vladsch.flexmark.html.HtmlRenderer; | |
4 | +import com.vladsch.flexmark.html.HtmlRenderer.Builder; | |
5 | +import com.vladsch.flexmark.html.renderer.NodeRenderer; | |
6 | +import com.vladsch.flexmark.html.renderer.NodeRendererFactory; | |
7 | +import com.vladsch.flexmark.util.data.DataHolder; | |
8 | +import com.vladsch.flexmark.util.data.DataKey; | |
9 | +import com.vladsch.flexmark.util.data.MutableDataHolder; | |
10 | +import com.vladsch.flexmark.util.misc.Extension; | |
11 | + | |
12 | +public class HighlightExtension implements HtmlRenderer.HtmlRendererExtension { | |
13 | + public static final DataKey<Boolean> REPLACE_YEN_SIGN = new DataKey<>("REPLACE_YEN_SIGN", true); | |
14 | + | |
15 | + private HighlightExtension() { | |
16 | + } | |
17 | + | |
18 | + public static Extension create() { | |
19 | + return new HighlightExtension(); | |
20 | + } | |
21 | + | |
22 | + @Override | |
23 | + public void rendererOptions(MutableDataHolder options) { | |
24 | + } | |
25 | + | |
26 | + @Override | |
27 | + public void extend(Builder rendererBuilder, String rendererType) { | |
28 | + rendererBuilder.nodeRendererFactory(new NodeRendererFactory() { | |
29 | + @Override | |
30 | + public NodeRenderer apply(DataHolder options) { | |
31 | + return new HighlightRenderer(options); | |
32 | + } | |
33 | + }); | |
34 | + } | |
35 | +} |
@@ -0,0 +1,185 @@ | ||
1 | +package net.osdn.catalpa.flexmark.ext.highlight; | |
2 | + | |
3 | +import java.util.HashSet; | |
4 | +import java.util.Set; | |
5 | +import java.util.regex.Matcher; | |
6 | +import java.util.regex.Pattern; | |
7 | + | |
8 | +import com.codewaves.codehighlight.core.Highlighter; | |
9 | +import com.codewaves.codehighlight.core.Highlighter.HighlightResult; | |
10 | +import com.codewaves.codehighlight.core.StyleRenderer; | |
11 | +import com.codewaves.codehighlight.core.StyleRendererFactory; | |
12 | +import com.codewaves.codehighlight.renderer.HtmlRenderer; | |
13 | +import com.vladsch.flexmark.ast.FencedCodeBlock; | |
14 | +import com.vladsch.flexmark.html.HtmlWriter; | |
15 | +import com.vladsch.flexmark.html.renderer.AttributablePart; | |
16 | +import com.vladsch.flexmark.html.renderer.NodeRenderer; | |
17 | +import com.vladsch.flexmark.html.renderer.NodeRendererContext; | |
18 | +import com.vladsch.flexmark.html.renderer.NodeRenderingHandler; | |
19 | +import com.vladsch.flexmark.parser.Parser; | |
20 | +import com.vladsch.flexmark.util.data.DataHolder; | |
21 | +import com.vladsch.flexmark.util.misc.CharPredicate; | |
22 | +import com.vladsch.flexmark.util.sequence.BasedSequence; | |
23 | + | |
24 | +public class HighlightRenderer implements NodeRenderer { | |
25 | + private static final AttributablePart CODE_CONTENT = new AttributablePart("FENCED_CODE_CONTENT"); | |
26 | + private static final String ADDITIONAL_CHARS = ""; | |
27 | + private static final String ATTRIBUTENAME = "[a-zA-Z" + ADDITIONAL_CHARS + "_:][a-zA-Z0-9" + ADDITIONAL_CHARS + ":._-]*"; | |
28 | + private static final String UNQUOTEDVALUE = "[^\"'=<>{}`\u0000-\u0020]+"; | |
29 | + private static final String SINGLEQUOTEDVALUE = "'[^']*'"; | |
30 | + private static final String DOUBLEQUOTEDVALUE = "\"[^\"]*\""; | |
31 | + private static final String ATTRIBUTEVALUE = "(?:" + UNQUOTEDVALUE + "|" + SINGLEQUOTEDVALUE + "|" + DOUBLEQUOTEDVALUE + ")"; | |
32 | + private static final Pattern ATTRIBUTES_TAG = Pattern.compile( | |
33 | + "\\{((?:[#.])|(?:" + "\\s*([#.]" + UNQUOTEDVALUE + "|" + ATTRIBUTENAME + ")\\s*(?:=\\s*(" + ATTRIBUTEVALUE + ")?" + ")?" + ")" + | |
34 | + "(?:" + "\\s+([#.]" + UNQUOTEDVALUE + "|" + ATTRIBUTENAME + ")\\s*(?:=\\s*(" + ATTRIBUTEVALUE + ")?" + ")?" + ")*" + "\\s*)\\}$"); | |
35 | + private static final Pattern ATTRIBUTE = Pattern.compile("\\s*([#.]" + UNQUOTEDVALUE + "|" + ATTRIBUTENAME + ")\\s*(?:=\\s*(" + ATTRIBUTEVALUE + ")?" + ")?"); | |
36 | + | |
37 | + private static final String COPY_SCRIPT = | |
38 | + "document.getSelection().selectAllChildren(event.target.parentNode.nextSibling);" + | |
39 | + "document.execCommand('copy');" + | |
40 | + "document.getSelection().removeAllRanges();" + | |
41 | + "return false;"; | |
42 | + | |
43 | + private final boolean codeContentBlock; | |
44 | + private final boolean isReplaceYenSign; | |
45 | + | |
46 | + private final Highlighter highlighter = new Highlighter(new StyleRendererFactory() { | |
47 | + @Override | |
48 | + public StyleRenderer create(String languageName) { | |
49 | + return new HtmlRenderer("hljs-"); | |
50 | + } | |
51 | + }); | |
52 | + | |
53 | + public HighlightRenderer(DataHolder options) { | |
54 | + codeContentBlock = Parser.FENCED_CODE_CONTENT_BLOCK.get(options); | |
55 | + isReplaceYenSign = HighlightExtension.REPLACE_YEN_SIGN.get(options); | |
56 | + } | |
57 | + | |
58 | + @Override | |
59 | + public Set<NodeRenderingHandler<?>> getNodeRenderingHandlers() { | |
60 | + Set<NodeRenderingHandler<?>> set = new HashSet<NodeRenderingHandler<?>>(); | |
61 | + set.add(new NodeRenderingHandler<FencedCodeBlock>(FencedCodeBlock.class, new NodeRenderingHandler.CustomNodeRenderer<FencedCodeBlock>() { | |
62 | + @Override | |
63 | + public void render(FencedCodeBlock node, NodeRendererContext context, HtmlWriter html) { | |
64 | + HighlightRenderer.this.render(node, context, html); | |
65 | + } | |
66 | + })); | |
67 | + return set; | |
68 | + } | |
69 | + | |
70 | + protected void render(FencedCodeBlock node, NodeRendererContext context, HtmlWriter html) { | |
71 | + String languageName = null; | |
72 | + BasedSequence language = BasedSequence.NULL; | |
73 | + BasedSequence title = BasedSequence.EMPTY; | |
74 | + boolean isCopyable = false; | |
75 | + | |
76 | + html.line(); | |
77 | + | |
78 | + BasedSequence attributes = node.getAttributes(); | |
79 | + BasedSequence info = node.getInfo(); | |
80 | + if(info.isNotNull() && !info.isBlank()) { | |
81 | + Matcher matcher = ATTRIBUTES_TAG.matcher(info); | |
82 | + if(matcher.find()) { | |
83 | + attributes = info.subSequence(matcher.start()).trim(); | |
84 | + info = info.subSequence(0, matcher.start()).trim(); | |
85 | + } | |
86 | + } | |
87 | + if(attributes.isNotNull() && !attributes.isBlank()) { | |
88 | + Matcher matcher = ATTRIBUTES_TAG.matcher(attributes); | |
89 | + if (matcher.find()) { | |
90 | + BasedSequence attributesText = attributes.subSequence(matcher.start(1), matcher.end(1)).trim(); | |
91 | + if (!attributesText.isEmpty()) { | |
92 | + Matcher attributeMatcher = ATTRIBUTE.matcher(attributesText); | |
93 | + while (attributeMatcher.find()) { | |
94 | + BasedSequence attributeName = attributesText.subSequence(attributeMatcher.start(1), attributeMatcher.end(1)); | |
95 | + if (attributeName.isNotNull() && attributeName.length() > 0) { | |
96 | + if (attributeName.charAt(0) == '.') { | |
97 | + BasedSequence cls = attributeName.subSequence(1); | |
98 | + html.attr("class", cls); | |
99 | + if (cls.startsWith("cop")) { | |
100 | + isCopyable = true; | |
101 | + } | |
102 | + } else if (attributeName.charAt(0) == '#') { | |
103 | + html.attr("id", attributeName.subSequence(1)); | |
104 | + } else { | |
105 | + BasedSequence attributeValue = attributeMatcher.groupCount() == 1 || attributeMatcher.start(2) == -1 ? BasedSequence.NULL : attributesText.subSequence(attributeMatcher.start(2), attributeMatcher.end(2)); | |
106 | + boolean isQuoted = attributeValue.length() >= 2 && (attributeValue.charAt(0) == '"' && attributeValue.endCharAt(1) == '"' || attributeValue.charAt(0) == '\'' && attributeValue.endCharAt(1) == '\''); | |
107 | + if (isQuoted) { | |
108 | + attributeValue = attributeValue.midSequence(1, -1); | |
109 | + } | |
110 | + if (attributeValue.isNotNull()) { | |
111 | + html.attr(attributeName, attributeValue); | |
112 | + } | |
113 | + } | |
114 | + } | |
115 | + } | |
116 | + } | |
117 | + } | |
118 | + } | |
119 | + | |
120 | + if (info.isNotNull() && !info.isBlank()) { | |
121 | + int space = info.indexOfAny(CharPredicate.SPACE); | |
122 | + if (space == -1) { | |
123 | + language = info; | |
124 | + } else { | |
125 | + language = info.subSequence(0, space); | |
126 | + title = info.subSequence(space).trim(); | |
127 | + } | |
128 | + languageName = language.unescape(); | |
129 | + } | |
130 | + html.srcPosWithTrailingEOL(node.getChars()).withAttr().tag("pre").openPre(); | |
131 | + | |
132 | + if(!title.isEmpty() || isCopyable) { | |
133 | + html.attr("class", "title").withAttr().tag("div"); | |
134 | + html.append(title.isEmpty() ? " " : title); | |
135 | + if(isCopyable) { | |
136 | + html.attr("class", "copy-button").attr("onclick", COPY_SCRIPT).withAttr().tag("span").tag("/span"); | |
137 | + } | |
138 | + html.tag("/div"); | |
139 | + } | |
140 | + | |
141 | + if(language.isNotNull()) { | |
142 | + html.attr("class", context.getHtmlOptions().languageClassPrefix + language.unescape()); | |
143 | + } else { | |
144 | + String noLanguageClass = context.getHtmlOptions().noLanguageClass.trim(); | |
145 | + if (!noLanguageClass.isEmpty()) { | |
146 | + html.attr("class", noLanguageClass); | |
147 | + } | |
148 | + } | |
149 | + html.srcPosWithEOL(node.getContentChars()).withAttr(CODE_CONTENT).tag("code"); | |
150 | + if (codeContentBlock) { | |
151 | + context.renderChildren(node); | |
152 | + } else { | |
153 | + if(languageName == null) { | |
154 | + // nohighlight (html escape) | |
155 | + html.text(node.getContentChars().normalizeEOL()); | |
156 | + } else if(languageName.equals("raw")) { | |
157 | + // raw (without html escape) | |
158 | + html.append(node.getContentChars().normalizeEOL()); | |
159 | + } else { | |
160 | + String code = node.getContentChars().normalizeEOL(); | |
161 | + CharSequence content; | |
162 | + if(Highlighter.findLanguage(languageName) != null) { | |
163 | + content = highlight(languageName, code); | |
164 | + } else { | |
165 | + content = code | |
166 | + .replace("&", "&") | |
167 | + .replace("<", "<") | |
168 | + .replace(">", ">"); | |
169 | + } | |
170 | + if(isReplaceYenSign) { | |
171 | + content = content.toString().replace("\\", "¥"); | |
172 | + } | |
173 | + html.append(content); | |
174 | + } | |
175 | + } | |
176 | + html.tag("/code"); | |
177 | + html.tag("/pre").closePre(); | |
178 | + html.lineIf(context.getHtmlOptions().htmlBlockCloseTagEol); | |
179 | + } | |
180 | + | |
181 | + protected CharSequence highlight(String languageName, String code) { | |
182 | + HighlightResult result = highlighter.highlight(languageName, code); | |
183 | + return result.getResult(); | |
184 | + } | |
185 | +} |
@@ -0,0 +1,80 @@ | ||
1 | +package net.osdn.catalpa.flexmark.ext.kbd.internal; | |
2 | + | |
3 | +import java.util.Set; | |
4 | +import java.util.regex.Matcher; | |
5 | +import java.util.regex.Pattern; | |
6 | + | |
7 | +import com.vladsch.flexmark.parser.InlineParser; | |
8 | +import com.vladsch.flexmark.parser.InlineParserExtension; | |
9 | +import com.vladsch.flexmark.parser.InlineParserExtensionFactory; | |
10 | +import com.vladsch.flexmark.parser.LightInlineParser; | |
11 | +import com.vladsch.flexmark.util.sequence.BasedSequence; | |
12 | + | |
13 | +import net.osdn.catalpa.flexmark.ext.kbd.Kbd; | |
14 | + | |
15 | +public class KbdInlineParserExtension implements InlineParserExtension { | |
16 | + private final Pattern PATTERN = Pattern.compile("\\['([^']*)'\\]"); | |
17 | + | |
18 | + public KbdInlineParserExtension(LightInlineParser inlineParser) { | |
19 | + } | |
20 | + | |
21 | + @Override | |
22 | + public void finalizeDocument(InlineParser inlineParser) { | |
23 | + } | |
24 | + | |
25 | + @Override | |
26 | + public void finalizeBlock(InlineParser inlineParser) { | |
27 | + } | |
28 | + | |
29 | + @Override | |
30 | + public boolean parse(LightInlineParser inlineParser) { | |
31 | + if (inlineParser.peek(1) == '\'') { | |
32 | + BasedSequence input = inlineParser.getInput(); | |
33 | + Matcher matcher = inlineParser.matcher(PATTERN); | |
34 | + if (matcher != null) { | |
35 | + BasedSequence tag = input.subSequence(matcher.start(), matcher.end()); | |
36 | + BasedSequence text = input.subSequence(matcher.start(1), matcher.end(1)); | |
37 | + Kbd node = new Kbd(tag.subSequence(0, 2), text, tag.endSequence(2)); | |
38 | + node.setCharsFromContent(); | |
39 | + inlineParser.flushTextNode(); | |
40 | + inlineParser.getBlock().appendChild(node); | |
41 | + return true; | |
42 | + } | |
43 | + } | |
44 | + return false; | |
45 | + } | |
46 | + | |
47 | + public static class Factory implements InlineParserExtensionFactory { | |
48 | + @Override | |
49 | + public Set<Class<?>> getAfterDependents() { | |
50 | + return null; | |
51 | + } | |
52 | + | |
53 | + @Override | |
54 | + public CharSequence getCharacters() { | |
55 | + return "['"; | |
56 | + } | |
57 | + | |
58 | + @Override | |
59 | + public Set<Class<?>> getBeforeDependents() { | |
60 | + return null; | |
61 | + } | |
62 | + | |
63 | + /* | |
64 | + @Override | |
65 | + public InlineParserExtension create(final InlineParser inlineParser) { | |
66 | + return new KbdInlineParserExtension(inlineParser); | |
67 | + } | |
68 | + */ | |
69 | + | |
70 | + @Override | |
71 | + public InlineParserExtension apply(LightInlineParser inlineParser) { | |
72 | + return new KbdInlineParserExtension(inlineParser); | |
73 | + } | |
74 | + | |
75 | + @Override | |
76 | + public boolean affectsGlobalScope() { | |
77 | + return false; | |
78 | + } | |
79 | + } | |
80 | +} |
@@ -0,0 +1,44 @@ | ||
1 | +package net.osdn.catalpa.flexmark.ext.kbd.internal; | |
2 | + | |
3 | +import java.util.HashSet; | |
4 | +import java.util.Set; | |
5 | + | |
6 | +import com.vladsch.flexmark.html.HtmlWriter; | |
7 | +import com.vladsch.flexmark.html.renderer.NodeRenderer; | |
8 | +import com.vladsch.flexmark.html.renderer.NodeRendererContext; | |
9 | +import com.vladsch.flexmark.html.renderer.NodeRendererFactory; | |
10 | +import com.vladsch.flexmark.html.renderer.NodeRenderingHandler; | |
11 | + | |
12 | +import com.vladsch.flexmark.util.data.DataHolder; | |
13 | +import net.osdn.catalpa.flexmark.ext.kbd.Kbd; | |
14 | + | |
15 | +public class KbdNodeRenderer implements NodeRenderer { | |
16 | + | |
17 | + public KbdNodeRenderer(DataHolder options) { | |
18 | + } | |
19 | + | |
20 | + @Override | |
21 | + public Set<NodeRenderingHandler<?>> getNodeRenderingHandlers() { | |
22 | + Set<NodeRenderingHandler<?>> set = new HashSet<NodeRenderingHandler<?>>(); | |
23 | + set.add(new NodeRenderingHandler<Kbd>(Kbd.class, new NodeRenderingHandler.CustomNodeRenderer<Kbd>() { | |
24 | + @Override | |
25 | + public void render(Kbd node, NodeRendererContext context, HtmlWriter html) { | |
26 | + KbdNodeRenderer.this.render(node, context, html); | |
27 | + } | |
28 | + })); | |
29 | + return set; | |
30 | + } | |
31 | + | |
32 | + private void render(Kbd node, NodeRendererContext context, HtmlWriter html) { | |
33 | + html.withAttr() | |
34 | + .attr("data-length", Integer.toString(node.getText().length())) | |
35 | + .tag("kbd").text(node.getText()).tag("/kbd"); | |
36 | + } | |
37 | + | |
38 | + public static class Factory implements NodeRendererFactory { | |
39 | + @Override | |
40 | + public NodeRenderer apply(DataHolder options) { | |
41 | + return new KbdNodeRenderer(options); | |
42 | + } | |
43 | + } | |
44 | +} |
@@ -0,0 +1,60 @@ | ||
1 | +package net.osdn.catalpa.flexmark.ext.kbd; | |
2 | + | |
3 | +import com.vladsch.flexmark.util.ast.Node; | |
4 | +import com.vladsch.flexmark.util.sequence.BasedSequence; | |
5 | + | |
6 | +public class Kbd extends Node { | |
7 | + protected BasedSequence openingMarker = BasedSequence.NULL; | |
8 | + protected BasedSequence text = BasedSequence.NULL; | |
9 | + protected BasedSequence closingMarker = BasedSequence.NULL; | |
10 | + | |
11 | + @Override | |
12 | + public BasedSequence[] getSegments() { | |
13 | + return new BasedSequence[] { openingMarker, text, closingMarker }; | |
14 | + } | |
15 | + | |
16 | + @Override | |
17 | + public void getAstExtra(StringBuilder out) { | |
18 | + segmentSpanChars(out, openingMarker, "open"); | |
19 | + segmentSpanChars(out, text, "text"); | |
20 | + segmentSpanChars(out, closingMarker, "close"); | |
21 | + } | |
22 | + | |
23 | + public Kbd() { | |
24 | + } | |
25 | + | |
26 | + public Kbd(BasedSequence chars) { | |
27 | + super(chars); | |
28 | + } | |
29 | + | |
30 | + public Kbd(BasedSequence openingMarker, BasedSequence text, BasedSequence closingMarker) { | |
31 | + super(openingMarker.baseSubSequence(openingMarker.getStartOffset(), closingMarker.getEndOffset())); | |
32 | + this.openingMarker = openingMarker; | |
33 | + this.text = text; | |
34 | + this.closingMarker = closingMarker; | |
35 | + } | |
36 | + | |
37 | + public BasedSequence getOpeningMarker() { | |
38 | + return openingMarker; | |
39 | + } | |
40 | + | |
41 | + public void setOpeningMarker(BasedSequence openingMarker) { | |
42 | + this.openingMarker = openingMarker; | |
43 | + } | |
44 | + | |
45 | + public BasedSequence getText() { | |
46 | + return text; | |
47 | + } | |
48 | + | |
49 | + public void setText(BasedSequence text) { | |
50 | + this.text = text; | |
51 | + } | |
52 | + | |
53 | + public BasedSequence getClosingMarker() { | |
54 | + return closingMarker; | |
55 | + } | |
56 | + | |
57 | + public void setClosingMarker(BasedSequence closingMarker) { | |
58 | + this.closingMarker = closingMarker; | |
59 | + } | |
60 | +} |
@@ -0,0 +1,44 @@ | ||
1 | +package net.osdn.catalpa.flexmark.ext.kbd; | |
2 | + | |
3 | +import com.vladsch.flexmark.html.HtmlRenderer; | |
4 | +import com.vladsch.flexmark.html.HtmlRenderer.HtmlRendererExtension; | |
5 | +import com.vladsch.flexmark.parser.Parser; | |
6 | +import com.vladsch.flexmark.parser.Parser.ParserExtension; | |
7 | + | |
8 | +import com.vladsch.flexmark.util.data.MutableDataHolder; | |
9 | +import com.vladsch.flexmark.util.misc.Extension; | |
10 | +import net.osdn.catalpa.flexmark.ext.kbd.internal.KbdInlineParserExtension; | |
11 | +import net.osdn.catalpa.flexmark.ext.kbd.internal.KbdNodeRenderer; | |
12 | + | |
13 | +public class KbdExtension implements ParserExtension, HtmlRendererExtension { | |
14 | + | |
15 | + private KbdExtension() { | |
16 | + } | |
17 | + | |
18 | + public static Extension create() { | |
19 | + return new KbdExtension(); | |
20 | + } | |
21 | + | |
22 | + @Override | |
23 | + public void rendererOptions(final MutableDataHolder options) { | |
24 | + | |
25 | + } | |
26 | + | |
27 | + @Override | |
28 | + public void parserOptions(final MutableDataHolder options) { | |
29 | + | |
30 | + } | |
31 | + | |
32 | + @Override | |
33 | + public void extend(Parser.Builder parserBuilder) { | |
34 | + parserBuilder.customInlineParserExtensionFactory(new KbdInlineParserExtension.Factory()); | |
35 | + } | |
36 | + | |
37 | + @Override | |
38 | + public void extend(HtmlRenderer.Builder rendererBuilder, String rendererType) { | |
39 | + if ("HTML".equals(rendererType)) { | |
40 | + rendererBuilder.nodeRendererFactory(new KbdNodeRenderer.Factory()); | |
41 | + } | |
42 | + } | |
43 | + | |
44 | +} |
@@ -0,0 +1,74 @@ | ||
1 | +package net.osdn.catalpa.flexmark.ext.samp_button.internal; | |
2 | + | |
3 | +import java.util.Set; | |
4 | +import java.util.regex.Matcher; | |
5 | +import java.util.regex.Pattern; | |
6 | + | |
7 | +import com.vladsch.flexmark.parser.InlineParser; | |
8 | +import com.vladsch.flexmark.parser.InlineParserExtension; | |
9 | +import com.vladsch.flexmark.parser.InlineParserExtensionFactory; | |
10 | +import com.vladsch.flexmark.parser.LightInlineParser; | |
11 | +import com.vladsch.flexmark.util.sequence.BasedSequence; | |
12 | + | |
13 | +import net.osdn.catalpa.flexmark.ext.samp_button.SampButton; | |
14 | + | |
15 | +public class SampButtonInlineParserExtension implements InlineParserExtension { | |
16 | + private final Pattern PATTERN = Pattern.compile("\\[\"([^\"]*)\"\\]"); | |
17 | + | |
18 | + public SampButtonInlineParserExtension(LightInlineParser inlineParser) { | |
19 | + } | |
20 | + | |
21 | + | |
22 | + @Override | |
23 | + public void finalizeDocument(InlineParser inlineParser) { | |
24 | + } | |
25 | + | |
26 | + @Override | |
27 | + public void finalizeBlock(InlineParser inlineParser) { | |
28 | + } | |
29 | + | |
30 | + @Override | |
31 | + public boolean parse(LightInlineParser inlineParser) { | |
32 | + if (inlineParser.peek(1) == '"') { | |
33 | + BasedSequence input = inlineParser.getInput(); | |
34 | + Matcher matcher = inlineParser.matcher(PATTERN); | |
35 | + if (matcher != null) { | |
36 | + BasedSequence tag = input.subSequence(matcher.start(), matcher.end()); | |
37 | + BasedSequence text = input.subSequence(matcher.start(1), matcher.end(1)); | |
38 | + SampButton node = new SampButton(tag.subSequence(0, 2), text, tag.endSequence(2)); | |
39 | + node.setCharsFromContent(); | |
40 | + inlineParser.flushTextNode(); | |
41 | + inlineParser.getBlock().appendChild(node); | |
42 | + return true; | |
43 | + } | |
44 | + } | |
45 | + return false; | |
46 | + } | |
47 | + | |
48 | + public static class Factory implements InlineParserExtensionFactory { | |
49 | + @Override | |
50 | + public Set<Class<?>> getAfterDependents() { | |
51 | + return null; | |
52 | + } | |
53 | + | |
54 | + @Override | |
55 | + public CharSequence getCharacters() { | |
56 | + return "[\""; | |
57 | + } | |
58 | + | |
59 | + @Override | |
60 | + public Set<Class<?>> getBeforeDependents() { | |
61 | + return null; | |
62 | + } | |
63 | + | |
64 | + @Override | |
65 | + public InlineParserExtension apply(LightInlineParser inlineParser) { | |
66 | + return new SampButtonInlineParserExtension(inlineParser); | |
67 | + } | |
68 | + | |
69 | + @Override | |
70 | + public boolean affectsGlobalScope() { | |
71 | + return false; | |
72 | + } | |
73 | + } | |
74 | +} |
@@ -0,0 +1,45 @@ | ||
1 | +package net.osdn.catalpa.flexmark.ext.samp_button.internal; | |
2 | + | |
3 | +import java.util.HashSet; | |
4 | +import java.util.Set; | |
5 | + | |
6 | +import com.vladsch.flexmark.html.HtmlWriter; | |
7 | +import com.vladsch.flexmark.html.renderer.NodeRenderer; | |
8 | +import com.vladsch.flexmark.html.renderer.NodeRendererContext; | |
9 | +import com.vladsch.flexmark.html.renderer.NodeRendererFactory; | |
10 | +import com.vladsch.flexmark.html.renderer.NodeRenderingHandler; | |
11 | + | |
12 | +import com.vladsch.flexmark.util.data.DataHolder; | |
13 | +import net.osdn.catalpa.flexmark.ext.samp_button.SampButton; | |
14 | + | |
15 | +public class SampButtonNodeRenderer implements NodeRenderer { | |
16 | + | |
17 | + public SampButtonNodeRenderer(DataHolder options) { | |
18 | + } | |
19 | + | |
20 | + @Override | |
21 | + public Set<NodeRenderingHandler<?>> getNodeRenderingHandlers() { | |
22 | + Set<NodeRenderingHandler<?>> set = new HashSet<NodeRenderingHandler<?>>(); | |
23 | + set.add(new NodeRenderingHandler<SampButton>(SampButton.class, new NodeRenderingHandler.CustomNodeRenderer<SampButton>() { | |
24 | + @Override | |
25 | + public void render(SampButton node, NodeRendererContext context, HtmlWriter html) { | |
26 | + SampButtonNodeRenderer.this.render(node, context, html); | |
27 | + } | |
28 | + })); | |
29 | + return set; | |
30 | + } | |
31 | + | |
32 | + private void render(SampButton node, NodeRendererContext context, HtmlWriter html) { | |
33 | + html.withAttr() | |
34 | + .attr("class", "button") | |
35 | + .attr("data-length", Integer.toString(node.getText().length())) | |
36 | + .tag("samp").text(node.getText()).tag("/samp"); | |
37 | + } | |
38 | + | |
39 | + public static class Factory implements NodeRendererFactory { | |
40 | + @Override | |
41 | + public NodeRenderer apply(DataHolder options) { | |
42 | + return new SampButtonNodeRenderer(options); | |
43 | + } | |
44 | + } | |
45 | +} |
@@ -0,0 +1,60 @@ | ||
1 | +package net.osdn.catalpa.flexmark.ext.samp_button; | |
2 | + | |
3 | +import com.vladsch.flexmark.util.ast.Node; | |
4 | +import com.vladsch.flexmark.util.sequence.BasedSequence; | |
5 | + | |
6 | +public class SampButton extends Node { | |
7 | + protected BasedSequence openingMarker = BasedSequence.NULL; | |
8 | + protected BasedSequence text = BasedSequence.NULL; | |
9 | + protected BasedSequence closingMarker = BasedSequence.NULL; | |
10 | + | |
11 | + @Override | |
12 | + public BasedSequence[] getSegments() { | |
13 | + return new BasedSequence[] { openingMarker, text, closingMarker }; | |
14 | + } | |
15 | + | |
16 | + @Override | |
17 | + public void getAstExtra(StringBuilder out) { | |
18 | + segmentSpanChars(out, openingMarker, "open"); | |
19 | + segmentSpanChars(out, text, "text"); | |
20 | + segmentSpanChars(out, closingMarker, "close"); | |
21 | + } | |
22 | + | |
23 | + public SampButton() { | |
24 | + } | |
25 | + | |
26 | + public SampButton(BasedSequence chars) { | |
27 | + super(chars); | |
28 | + } | |
29 | + | |
30 | + public SampButton(BasedSequence openingMarker, BasedSequence text, BasedSequence closingMarker) { | |
31 | + super(openingMarker.baseSubSequence(openingMarker.getStartOffset(), closingMarker.getEndOffset())); | |
32 | + this.openingMarker = openingMarker; | |
33 | + this.text = text; | |
34 | + this.closingMarker = closingMarker; | |
35 | + } | |
36 | + | |
37 | + public BasedSequence getOpeningMarker() { | |
38 | + return openingMarker; | |
39 | + } | |
40 | + | |
41 | + public void setOpeningMarker(BasedSequence openingMarker) { | |
42 | + this.openingMarker = openingMarker; | |
43 | + } | |
44 | + | |
45 | + public BasedSequence getText() { | |
46 | + return text; | |
47 | + } | |
48 | + | |
49 | + public void setText(BasedSequence text) { | |
50 | + this.text = text; | |
51 | + } | |
52 | + | |
53 | + public BasedSequence getClosingMarker() { | |
54 | + return closingMarker; | |
55 | + } | |
56 | + | |
57 | + public void setClosingMarker(BasedSequence closingMarker) { | |
58 | + this.closingMarker = closingMarker; | |
59 | + } | |
60 | +} |
@@ -0,0 +1,44 @@ | ||
1 | +package net.osdn.catalpa.flexmark.ext.samp_button; | |
2 | + | |
3 | +import com.vladsch.flexmark.html.HtmlRenderer; | |
4 | +import com.vladsch.flexmark.html.HtmlRenderer.HtmlRendererExtension; | |
5 | +import com.vladsch.flexmark.parser.Parser; | |
6 | +import com.vladsch.flexmark.parser.Parser.ParserExtension; | |
7 | + | |
8 | +import com.vladsch.flexmark.util.data.MutableDataHolder; | |
9 | +import com.vladsch.flexmark.util.misc.Extension; | |
10 | +import net.osdn.catalpa.flexmark.ext.samp_button.internal.SampButtonInlineParserExtension; | |
11 | +import net.osdn.catalpa.flexmark.ext.samp_button.internal.SampButtonNodeRenderer; | |
12 | + | |
13 | +public class SampButtonExtension implements ParserExtension, HtmlRendererExtension { | |
14 | + | |
15 | + private SampButtonExtension() { | |
16 | + } | |
17 | + | |
18 | + public static Extension create() { | |
19 | + return new SampButtonExtension(); | |
20 | + } | |
21 | + | |
22 | + @Override | |
23 | + public void rendererOptions(final MutableDataHolder options) { | |
24 | + | |
25 | + } | |
26 | + | |
27 | + @Override | |
28 | + public void parserOptions(final MutableDataHolder options) { | |
29 | + | |
30 | + } | |
31 | + | |
32 | + @Override | |
33 | + public void extend(Parser.Builder parserBuilder) { | |
34 | + parserBuilder.customInlineParserExtensionFactory(new SampButtonInlineParserExtension.Factory()); | |
35 | + } | |
36 | + | |
37 | + @Override | |
38 | + public void extend(HtmlRenderer.Builder rendererBuilder, String rendererType) { | |
39 | + if ("HTML".equals(rendererType)) { | |
40 | + rendererBuilder.nodeRendererFactory(new SampButtonNodeRenderer.Factory()); | |
41 | + } | |
42 | + } | |
43 | + | |
44 | +} |
@@ -58,9 +58,9 @@ | ||
58 | 58 | import freemarker.template.Template; |
59 | 59 | import freemarker.template.TemplateException; |
60 | 60 | import freemarker.template.TemplateNotFoundException; |
61 | -import net.osdn.blogs.flexmark.ext.highlight.HighlightExtension; | |
62 | -import net.osdn.blogs.flexmark.ext.kbd.KbdExtension; | |
63 | -import net.osdn.blogs.flexmark.ext.samp_button.SampButtonExtension; | |
61 | +import net.osdn.catalpa.flexmark.ext.highlight.HighlightExtension; | |
62 | +import net.osdn.catalpa.flexmark.ext.kbd.KbdExtension; | |
63 | +import net.osdn.catalpa.flexmark.ext.samp_button.SampButtonExtension; | |
64 | 64 | import net.osdn.catalpa.SitemapItem.ChangeFreq; |
65 | 65 | import net.osdn.catalpa.addon.blog.BlogAddOn; |
66 | 66 | import net.osdn.catalpa.flexmark.ext.BasicNodeExtension; |