1. Project Clover database Sat Feb 2 2019 06:45:20 CET
  2. Package org.xwiki.rendering.internal.renderer.xwiki20

File XWikiSyntaxEscapeWikiPrinter.java

 

Coverage histogram

../../../../../../img/srcFileCovDistChart9.png
41% of files have more coverage

Code metrics

42
86
16
1
270
184
43
0.5
5.38
16
2.69

Classes

Class Line # Actions
XWikiSyntaxEscapeWikiPrinter 38 86 0% 43 16
0.888888988.9%
 

Contributing tests

This file is covered by 295 tests. .

Source view

1    /*
2    * See the NOTICE file distributed with this work for additional
3    * information regarding copyright ownership.
4    *
5    * This is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU Lesser General Public License as
7    * published by the Free Software Foundation; either version 2.1 of
8    * the License, or (at your option) any later version.
9    *
10    * This software is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13    * Lesser General Public License for more details.
14    *
15    * You should have received a copy of the GNU Lesser General Public
16    * License along with this software; if not, write to the Free
17    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19    */
20    package org.xwiki.rendering.internal.renderer.xwiki20;
21   
22    import java.util.ArrayDeque;
23    import java.util.Deque;
24    import java.util.regex.Matcher;
25    import java.util.regex.Pattern;
26   
27    import org.xwiki.rendering.renderer.printer.LookaheadWikiPrinter;
28    import org.xwiki.rendering.renderer.printer.WikiPrinter;
29   
30    /**
31    * A Wiki printer that knows how to escape characters that would otherwise mean something different in XWiki wiki
32    * syntax. For example if we have "**" as special symbols (and not as a Bold Format block) we need to escape them to
33    * "~*~*" as otherwise they'd be considered bold after being rendered.
34    *
35    * @version $Id: 3a5fe3e2486a01166bfe4e4ea44f35107ff7375a $
36    * @since 1.7
37    */
 
38    public class XWikiSyntaxEscapeWikiPrinter extends LookaheadWikiPrinter
39    {
40    private static final Pattern VERBATIM_PATTERN = Pattern.compile("(\\{\\{\\{)|(\\}\\}\\})");
41   
42    private XWikiSyntaxListenerChain listenerChain;
43   
44    private XWikiSyntaxEscapeHandler escapeHandler;
45   
46    private boolean escapeLastChar;
47   
48    private Pattern escapeFirstIfMatching;
49   
50    private String lastPrinted;
51   
 
52  552 toggle public XWikiSyntaxEscapeWikiPrinter(WikiPrinter printer, XWikiSyntaxListenerChain listenerChain)
53    {
54  552 super(printer);
55   
56  552 this.escapeHandler = new XWikiSyntaxEscapeHandler();
57   
58  552 this.listenerChain = listenerChain;
59    }
60   
 
61  0 toggle public XWikiSyntaxEscapeHandler getEscapeHandler()
62    {
63  0 return this.escapeHandler;
64    }
65   
 
66  2844 toggle @Override
67    protected void printInternal(String text)
68    {
69  2844 super.printInternal(text);
70   
71  2844 int length = text.length();
72   
73  2844 if (length > 0) {
74  2811 this.escapeHandler.setOnNewLine(text.charAt(length - 1) == '\n');
75    }
76   
77  2844 this.lastPrinted = text;
78    }
79   
 
80  0 toggle @Override
81    protected void printlnInternal(String text)
82    {
83  0 super.printlnInternal(text);
84   
85  0 this.escapeHandler.setOnNewLine(true);
86   
87  0 this.lastPrinted = "\n";
88    }
89   
 
90  3656 toggle @Override
91    public void flush()
92    {
93  3656 if (getBuffer().length() > 0) {
94  791 this.escapeHandler.escape(getBuffer(), this.listenerChain, this.escapeLastChar, this.escapeFirstIfMatching);
95  791 super.flush();
96    }
97  3656 this.escapeLastChar = false;
98  3656 this.escapeFirstIfMatching = null;
99    }
100   
 
101  22 toggle public void printBeginBold()
102    {
103  22 flush();
104   
105  22 boolean isOnNewLine = this.escapeHandler.isOnNewLine();
106   
107  22 print("**");
108   
109  22 if (isOnNewLine) {
110  6 this.escapeFirstIfMatching = XWikiSyntaxEscapeHandler.STARLISTEND_PATTERN;
111    }
112    }
113   
 
114  1 toggle public void setEscapeLastChar(boolean escapeLastChar)
115    {
116  1 this.escapeLastChar = escapeLastChar;
117    }
118   
 
119  182 toggle public void setBeforeLink(boolean beforeLink)
120    {
121  182 this.escapeHandler.setBeforeLink(beforeLink);
122    }
123   
 
124  90 toggle public void setOnNewLine(boolean onNewLine)
125    {
126  90 this.escapeHandler.setOnNewLine(onNewLine);
127    }
128   
 
129  96 toggle public boolean isOnNewLine()
130    {
131  96 return this.escapeHandler.isOnNewLine();
132    }
133   
 
134  6 toggle public boolean isAfterWhiteSpace()
135    {
136  6 return isOnNewLine() || Character.isWhitespace(getLastPrinted().charAt(getLastPrinted().length() - 1));
137    }
138   
 
139  18 toggle public String getLastPrinted()
140    {
141  18 return this.lastPrinted;
142    }
143   
 
144  17 toggle public void printBeginItalic()
145    {
146    // If the lookahead buffer is not empty and the last character is ":" then we need to escape it
147    // since otherwise we would get "://" which could be confused for a URL.
148  17 if (getBuffer().length() > 0 && getBuffer().charAt(getBuffer().length() - 1) == ':') {
149  1 this.escapeLastChar = true;
150    }
151   
152  17 print("//");
153    }
154   
 
155  17 toggle public void printEndItalic()
156    {
157    // If the lookahead buffer is not empty and the last character is ":" then we need to escape it
158    // since otherwise we would get "://" which could be confused for a URL.
159  17 if (getBuffer().length() > 0 && getBuffer().charAt(getBuffer().length() - 1) == ':') {
160  1 this.escapeLastChar = true;
161    }
162   
163  17 print("//");
164    }
165   
 
166  9 toggle public void printInlineMacro(String xwikiSyntaxText)
167    {
168    // If the lookahead buffer is not empty and the last character is "{" then we need to escape it
169    // since otherwise we would get "{{{" which could be confused for a verbatim block.
170  9 if (getBuffer().length() > 0 && getBuffer().charAt(getBuffer().length() - 1) == '{') {
171  1 this.escapeLastChar = true;
172    }
173   
174  9 print(xwikiSyntaxText);
175    }
176   
 
177  22 toggle public void printVerbatimContent(String verbatimContent)
178    {
179  22 StringBuffer result = new StringBuffer();
180   
181  22 Deque<StringBuffer> subVerbatimStack = new ArrayDeque<StringBuffer>();
182  22 boolean printEndVerbatim = false;
183   
184  22 Matcher matcher = VERBATIM_PATTERN.matcher(verbatimContent);
185  22 int currentIndex = 0;
186  30 for (; matcher.find(); currentIndex = matcher.end()) {
187  8 String before = verbatimContent.substring(currentIndex, matcher.start());
188   
189  8 if (printEndVerbatim) {
190  1 if (before.startsWith("}")) {
191  0 result.append("~}~}~}");
192    } else {
193  1 result.append("~}}}");
194    }
195    }
196   
197  8 if (subVerbatimStack.isEmpty()) {
198  6 result.append(before);
199    } else {
200  2 subVerbatimStack.peek().append(before);
201    }
202   
203  8 if (matcher.group(1) != null) {
204  4 subVerbatimStack.push(new StringBuffer());
205    } else {
206  4 if (subVerbatimStack.isEmpty()) {
207  3 printEndVerbatim = true;
208    } else {
209  1 StringBuffer subVerbatim = subVerbatimStack.pop();
210   
211  1 if (subVerbatimStack.isEmpty()) {
212  1 result.append("{{{");
213  1 result.append(subVerbatim);
214  1 result.append("}}}");
215    } else {
216  0 subVerbatimStack.peek().append("{{{");
217  0 subVerbatimStack.peek().append(subVerbatim);
218  0 subVerbatimStack.peek().append("}}}");
219    }
220    }
221    }
222    }
223   
224  22 if (currentIndex == 0) {
225  17 print(verbatimContent);
226  17 return;
227    }
228   
229  5 String end = verbatimContent.substring(currentIndex);
230   
231  5 if (printEndVerbatim) {
232  2 if (end.length() == 0 || end.charAt(0) == '}') {
233  1 result.append("~}~}~}");
234    } else {
235  1 result.append("~}}}");
236    }
237    }
238   
239  5 if (!subVerbatimStack.isEmpty()) {
240    // Append remaining string
241  2 subVerbatimStack.peek().append(end);
242   
243    // Escape not closed verbatim blocks
244  5 while (!subVerbatimStack.isEmpty()) {
245  3 StringBuffer subVerbatim = subVerbatimStack.pop();
246   
247  3 if (subVerbatimStack.isEmpty()) {
248  2 if (subVerbatim.length() > 0 && subVerbatim.charAt(0) == '{') {
249  0 result.append("~{~{~{");
250    } else {
251  2 result.append("~{{{");
252    }
253  2 result.append(subVerbatim);
254    } else {
255  1 if (subVerbatim.length() > 0 && subVerbatim.charAt(0) == '{') {
256  1 subVerbatimStack.peek().append("~{~{~{");
257    } else {
258  0 subVerbatimStack.peek().append("~{{{");
259    }
260  1 subVerbatimStack.peek().append(subVerbatim);
261    }
262    }
263    } else {
264    // Append remaining string
265  3 result.append(end);
266    }
267   
268  5 print(result.toString());
269    }
270    }