1 |
|
|
2 |
|
|
3 |
|
|
4 |
|
|
5 |
|
|
6 |
|
|
7 |
|
|
8 |
|
|
9 |
|
|
10 |
|
|
11 |
|
|
12 |
|
|
13 |
|
|
14 |
|
|
15 |
|
|
16 |
|
|
17 |
|
|
18 |
|
|
19 |
|
|
20 |
|
package org.xwiki.rendering.internal.macro.footnote; |
21 |
|
|
22 |
|
import java.util.Collections; |
23 |
|
import java.util.List; |
24 |
|
import java.util.ListIterator; |
25 |
|
|
26 |
|
import javax.inject.Inject; |
27 |
|
import javax.inject.Named; |
28 |
|
import javax.inject.Singleton; |
29 |
|
|
30 |
|
import org.apache.commons.lang3.StringUtils; |
31 |
|
import org.xwiki.component.annotation.Component; |
32 |
|
import org.xwiki.rendering.block.Block; |
33 |
|
import org.xwiki.rendering.block.FormatBlock; |
34 |
|
import org.xwiki.rendering.block.LinkBlock; |
35 |
|
import org.xwiki.rendering.block.ListItemBlock; |
36 |
|
import org.xwiki.rendering.block.MacroMarkerBlock; |
37 |
|
import org.xwiki.rendering.block.NumberedListBlock; |
38 |
|
import org.xwiki.rendering.block.SpaceBlock; |
39 |
|
import org.xwiki.rendering.block.WordBlock; |
40 |
|
import org.xwiki.rendering.block.match.ClassBlockMatcher; |
41 |
|
import org.xwiki.rendering.listener.Format; |
42 |
|
import org.xwiki.rendering.listener.reference.DocumentResourceReference; |
43 |
|
import org.xwiki.rendering.macro.AbstractMacro; |
44 |
|
import org.xwiki.rendering.macro.MacroContentParser; |
45 |
|
import org.xwiki.rendering.macro.MacroExecutionException; |
46 |
|
import org.xwiki.rendering.macro.footnote.FootnoteMacroParameters; |
47 |
|
import org.xwiki.rendering.transformation.MacroTransformationContext; |
48 |
|
|
49 |
|
|
50 |
|
|
51 |
|
|
52 |
|
@version |
53 |
|
@since |
54 |
|
|
55 |
|
@Component |
56 |
|
@Named(PutFootnotesMacro.MACRO_NAME) |
57 |
|
@Singleton |
|
|
| 84.5% |
Uncovered Elements: 13 (84) |
Complexity: 17 |
Complexity Density: 0.28 |
|
58 |
|
public class PutFootnotesMacro extends AbstractMacro<FootnoteMacroParameters> |
59 |
|
{ |
60 |
|
|
61 |
|
public static final String MACRO_NAME = "putFootnotes"; |
62 |
|
|
63 |
|
|
64 |
|
private static final String DESCRIPTION = |
65 |
|
"Displays the footnotes defined so far." |
66 |
|
+ " If missing, all footnotes are displayed by default at the end of the page."; |
67 |
|
|
68 |
|
|
69 |
|
private static final String ID_ATTRIBUTE_NAME = "id"; |
70 |
|
|
71 |
|
|
72 |
|
private static final String CLASS_ATTRIBUTE_NAME = "class"; |
73 |
|
|
74 |
|
|
75 |
|
private static final String FOOTNOTE_ID_PREFIX = "x_footnote_"; |
76 |
|
|
77 |
|
|
78 |
|
private static final String FOOTNOTE_REFERENCE_ID_PREFIX = "x_footnote_ref_"; |
79 |
|
|
80 |
|
|
81 |
|
|
82 |
|
|
83 |
|
@Inject |
84 |
|
private MacroContentParser contentParser; |
85 |
|
|
86 |
|
|
87 |
|
|
88 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (2) |
Complexity: 1 |
Complexity Density: 0.5 |
|
89 |
3 |
public PutFootnotesMacro()... |
90 |
|
{ |
91 |
3 |
super("Put Footnote", DESCRIPTION, FootnoteMacroParameters.class); |
92 |
3 |
setDefaultCategory(DEFAULT_CATEGORY_CONTENT); |
93 |
|
} |
94 |
|
|
|
|
| 0% |
Uncovered Elements: 1 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
95 |
0 |
@Override... |
96 |
|
public boolean supportsInlineMode() |
97 |
|
{ |
98 |
0 |
return false; |
99 |
|
} |
100 |
|
|
|
|
| 90.6% |
Uncovered Elements: 3 (32) |
Complexity: 6 |
Complexity Density: 0.27 |
|
101 |
3 |
@Override... |
102 |
|
public List<Block> execute(FootnoteMacroParameters parameters, String content, MacroTransformationContext context) |
103 |
|
throws MacroExecutionException |
104 |
|
{ |
105 |
3 |
List<Block> result = Collections.emptyList(); |
106 |
|
|
107 |
|
|
108 |
3 |
Block root = context.getXDOM(); |
109 |
3 |
List<MacroMarkerBlock> footnotes = |
110 |
|
root.getBlocks(new ClassBlockMatcher(MacroMarkerBlock.class), Block.Axes.DESCENDANT); |
111 |
29 |
for (ListIterator<MacroMarkerBlock> it = footnotes.listIterator(); it.hasNext();) { |
112 |
26 |
MacroMarkerBlock macro = it.next(); |
113 |
26 |
if (FootnoteMacro.MACRO_NAME.equals(macro.getId())) { |
114 |
2 |
continue; |
115 |
24 |
} else if (PutFootnotesMacro.MACRO_NAME.equals(macro.getId())) { |
116 |
0 |
macro.getParent().replaceChild(Collections.<Block>emptyList(), macro); |
117 |
|
} |
118 |
24 |
it.remove(); |
119 |
|
} |
120 |
3 |
if (footnotes.size() <= 0) { |
121 |
1 |
return result; |
122 |
|
} |
123 |
|
|
124 |
2 |
NumberedListBlock container = new NumberedListBlock(Collections.<Block>emptyList()); |
125 |
2 |
container.setParameter(CLASS_ATTRIBUTE_NAME, "footnotes"); |
126 |
2 |
Block footnoteResult; |
127 |
|
|
128 |
2 |
int counter = 1; |
129 |
2 |
for (MacroMarkerBlock footnote : footnotes) { |
130 |
2 |
footnoteResult = processFootnote(footnote, counter, context); |
131 |
2 |
if (footnoteResult != null) { |
132 |
2 |
container.addChild(footnoteResult); |
133 |
2 |
counter++; |
134 |
|
} |
135 |
|
} |
136 |
|
|
137 |
2 |
return Collections.<Block>singletonList(container); |
138 |
|
} |
139 |
|
|
140 |
|
|
141 |
|
|
142 |
|
|
143 |
|
|
144 |
|
@param |
145 |
|
@param |
146 |
|
@param |
147 |
|
@return |
148 |
|
@throws |
149 |
|
|
|
|
| 69.2% |
Uncovered Elements: 4 (13) |
Complexity: 4 |
Complexity Density: 0.44 |
|
150 |
2 |
private ListItemBlock processFootnote(MacroMarkerBlock footnoteMacro, int counter,... |
151 |
|
MacroTransformationContext context) throws MacroExecutionException |
152 |
|
{ |
153 |
2 |
String content = footnoteMacro.getContent(); |
154 |
2 |
if (StringUtils.isBlank(content)) { |
155 |
0 |
content = " "; |
156 |
|
} |
157 |
|
|
158 |
2 |
Block referenceBlock = createFootnoteReferenceBlock(counter); |
159 |
2 |
ListItemBlock footnoteBlock = createFootnoteBlock(content, counter, context); |
160 |
|
|
161 |
2 |
if (referenceBlock != null && footnoteBlock != null) { |
162 |
2 |
addFootnoteRef(footnoteMacro, referenceBlock); |
163 |
2 |
return footnoteBlock; |
164 |
|
} |
165 |
0 |
return null; |
166 |
|
} |
167 |
|
|
168 |
|
|
169 |
|
|
170 |
|
|
171 |
|
|
172 |
|
@param |
173 |
|
@param |
174 |
|
|
|
|
| 50% |
Uncovered Elements: 3 (6) |
Complexity: 2 |
Complexity Density: 0.5 |
|
175 |
2 |
private void addFootnoteRef(MacroMarkerBlock footnoteMacro, Block footnoteRef)... |
176 |
|
{ |
177 |
2 |
for (ListIterator<Block> it = footnoteMacro.getChildren().listIterator(); it.hasNext();) { |
178 |
0 |
Block b = it.next(); |
179 |
0 |
it.remove(); |
180 |
|
|
181 |
|
} |
182 |
2 |
footnoteMacro.addChild(footnoteRef); |
183 |
|
} |
184 |
|
|
185 |
|
|
186 |
|
|
187 |
|
|
188 |
|
|
189 |
|
@param |
190 |
|
@return |
191 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (8) |
Complexity: 1 |
Complexity Density: 0.12 |
|
192 |
2 |
private Block createFootnoteReferenceBlock(int counter)... |
193 |
|
{ |
194 |
2 |
Block result = new WordBlock(counter + ""); |
195 |
2 |
DocumentResourceReference reference = new DocumentResourceReference(null); |
196 |
2 |
reference.setAnchor(FOOTNOTE_ID_PREFIX + counter); |
197 |
2 |
result = new LinkBlock(Collections.singletonList(result), reference, false); |
198 |
2 |
result = new FormatBlock(Collections.singletonList(result), Format.SUPERSCRIPT); |
199 |
2 |
result.setParameter(ID_ATTRIBUTE_NAME, FOOTNOTE_REFERENCE_ID_PREFIX + counter); |
200 |
2 |
result.setParameter(CLASS_ATTRIBUTE_NAME, "footnoteRef"); |
201 |
2 |
return result; |
202 |
|
} |
203 |
|
|
204 |
|
|
205 |
|
|
206 |
|
|
207 |
|
|
208 |
|
@param |
209 |
|
@param |
210 |
|
@param |
211 |
|
@return |
212 |
|
@throws |
213 |
|
|
|
|
| 93.3% |
Uncovered Elements: 1 (15) |
Complexity: 2 |
Complexity Density: 0.13 |
|
214 |
2 |
private ListItemBlock createFootnoteBlock(String content, int counter, MacroTransformationContext context)... |
215 |
|
throws MacroExecutionException |
216 |
|
{ |
217 |
2 |
List<Block> parsedContent; |
218 |
2 |
try { |
219 |
2 |
parsedContent = this.contentParser.parse(content, context, false, true).getChildren(); |
220 |
|
} catch (MacroExecutionException e) { |
221 |
0 |
parsedContent = Collections.<Block>singletonList(new WordBlock(content)); |
222 |
|
} |
223 |
2 |
Block result = new WordBlock("^"); |
224 |
2 |
DocumentResourceReference reference = new DocumentResourceReference(null); |
225 |
2 |
reference.setAnchor(FOOTNOTE_REFERENCE_ID_PREFIX + counter); |
226 |
2 |
result = new LinkBlock(Collections.singletonList(result), reference, false); |
227 |
2 |
result.setParameter(ID_ATTRIBUTE_NAME, FOOTNOTE_ID_PREFIX + counter); |
228 |
2 |
result.setParameter(CLASS_ATTRIBUTE_NAME, "footnoteBackRef"); |
229 |
2 |
result = new ListItemBlock(Collections.singletonList(result)); |
230 |
2 |
result.addChild(new SpaceBlock()); |
231 |
2 |
result.addChildren(parsedContent); |
232 |
2 |
result.setParameter(CLASS_ATTRIBUTE_NAME, FootnoteMacro.MACRO_NAME); |
233 |
2 |
return (ListItemBlock) result; |
234 |
|
} |
235 |
|
} |