1. Project Clover database Tue Dec 20 2016 21:24:09 CET
  2. Package org.xwiki.wysiwyg.server.internal.converter

File DefaultHTMLConverter.java

 

Coverage histogram

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

Code metrics

0
33
4
1
214
110
7
0.21
8.25
4
1.75

Classes

Class Line # Actions
DefaultHTMLConverter 57 33 0% 7 4
0.891891989.2%
 

Contributing tests

This file is covered by 3 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.wysiwyg.server.internal.converter;
21   
22    import java.io.StringReader;
23   
24    import javax.inject.Inject;
25    import javax.inject.Named;
26    import javax.inject.Singleton;
27   
28    import org.slf4j.Logger;
29    import org.xwiki.component.annotation.Component;
30    import org.xwiki.component.manager.ComponentManager;
31    import org.xwiki.gwt.wysiwyg.client.cleaner.HTMLCleaner;
32    import org.xwiki.gwt.wysiwyg.client.converter.HTMLConverter;
33    import org.xwiki.rendering.block.XDOM;
34    import org.xwiki.rendering.internal.transformation.MutableRenderingContext;
35    import org.xwiki.rendering.listener.MetaData;
36    import org.xwiki.rendering.parser.ParseException;
37    import org.xwiki.rendering.parser.Parser;
38    import org.xwiki.rendering.parser.StreamParser;
39    import org.xwiki.rendering.renderer.BlockRenderer;
40    import org.xwiki.rendering.renderer.PrintRendererFactory;
41    import org.xwiki.rendering.renderer.printer.DefaultWikiPrinter;
42    import org.xwiki.rendering.renderer.printer.WikiPrinter;
43    import org.xwiki.rendering.syntax.Syntax;
44    import org.xwiki.rendering.syntax.SyntaxFactory;
45    import org.xwiki.rendering.transformation.RenderingContext;
46    import org.xwiki.rendering.transformation.Transformation;
47    import org.xwiki.rendering.transformation.TransformationContext;
48    import org.xwiki.rendering.transformation.TransformationException;
49   
50    /**
51    * Converts HTML into/from markup syntax.
52    *
53    * @version $Id: 3f7e20647f8c486fdebff4b873f1c60f68eaddbb $
54    */
55    @Component
56    @Singleton
 
57    public class DefaultHTMLConverter implements HTMLConverter
58    {
59    private static final String TRANSFORMATION_ID = "wysiwygtxid";
60   
61    /**
62    * Logger.
63    */
64    @Inject
65    private Logger logger;
66   
67    /**
68    * The component used to clean the HTML before the conversion.
69    */
70    @Inject
71    private HTMLCleaner htmlCleaner;
72   
73    /**
74    * The component used to parse the XHTML obtained after cleaning.
75    */
76    @Inject
77    @Named("xhtml/1.0")
78    private Parser xhtmlParser;
79   
80    /**
81    * The component used to parse the XHTML obtained after cleaning, when transformations are not executed.
82    */
83    @Inject
84    @Named("xhtml/1.0")
85    private StreamParser xhtmlStreamParser;
86   
87    /**
88    * The component used to create syntax instances from syntax identifiers.
89    */
90    @Inject
91    private SyntaxFactory syntaxFactory;
92   
93    /**
94    * Used to update the rendering context.
95    */
96    @Inject
97    private RenderingContext renderingContext;
98   
99    /**
100    * The component used to execute the XDOM macro transformations before rendering to XHTML.
101    * <p>
102    * NOTE: We execute only macro transformations because they are the only transformations protected by the WYSIWYG
103    * editor. We should use the transformation manager once generic transformation markers are implemented in the
104    * rendering module and the WYSIWYG editor supports them.
105    *
106    * @see <a href="http://jira.xwiki.org/browse/XRENDERING-78">XWIKI-3260: Add markers to modified XDOM by
107    * Transformations/Macros</a>
108    */
109    @Inject
110    @Named("macro")
111    private Transformation macroTransformation;
112   
113    /**
114    * The component used to render a XDOM to XHTML.
115    */
116    @Inject
117    @Named("annotatedxhtml/1.0")
118    private BlockRenderer xhtmlRenderer;
119   
120    /**
121    * The component manager. We need it because we have to access some components dynamically based on the input
122    * syntax.
123    */
124    @Inject
125    @Named("context")
126    private ComponentManager contextComponentManager;
127   
 
128  11 toggle @Override
129    public String fromHTML(String dirtyHTML, String syntaxId)
130    {
131  11 try {
132    // Clean
133  11 String html = this.htmlCleaner.clean(dirtyHTML);
134   
135    // Parse & Render
136    // Note that transformations are not executed when converting XHTML to source syntax.
137  11 WikiPrinter printer = new DefaultWikiPrinter();
138  11 PrintRendererFactory printRendererFactory =
139    this.contextComponentManager.getInstance(PrintRendererFactory.class, syntaxId);
140  11 this.xhtmlStreamParser.parse(new StringReader(html), printRendererFactory.createRenderer(printer));
141   
142  9 return printer.toString();
143    } catch (Exception e) {
144  2 this.logger.error(e.getLocalizedMessage(), e);
145  2 throw new RuntimeException("Exception while parsing HTML", e);
146    }
147    }
148   
 
149  23 toggle @Override
150    public String toHTML(String source, String syntaxId)
151    {
152  23 try {
153    // Parse
154  23 Parser parser = this.contextComponentManager.getInstance(Parser.class, syntaxId);
155  23 XDOM xdom = parser.parse(new StringReader(source));
156   
157    // Execute the macro transformation
158  23 executeMacroTransformation(xdom, this.syntaxFactory.createSyntaxFromIdString(syntaxId));
159   
160    // Render
161  23 WikiPrinter printer = new DefaultWikiPrinter();
162  23 this.xhtmlRenderer.render(xdom, printer);
163   
164  23 return printer.toString();
165    } catch (Exception e) {
166  0 this.logger.error(e.getLocalizedMessage(), e);
167  0 throw new RuntimeException("Exception while rendering HTML", e);
168    }
169    }
170   
 
171  1 toggle @Override
172    public String parseAndRender(String dirtyHTML, String syntaxId)
173    {
174  1 try {
175    // Clean
176  1 String html = this.htmlCleaner.clean(dirtyHTML);
177   
178    // Parse
179  1 XDOM xdom = this.xhtmlParser.parse(new StringReader(html));
180   
181    // The XHTML parser sets the "syntax" meta data property of the created XDOM to "xhtml/1.0". The syntax meta
182    // data is used as the default syntax for macro content. We have to change this to the specified syntax
183    // because HTML is used only to be able to edit the source syntax in the WYSIWYG editor.
184  1 Syntax syntax = this.syntaxFactory.createSyntaxFromIdString(syntaxId);
185  1 xdom.getMetaData().addMetaData(MetaData.SYNTAX, syntax);
186   
187    // Execute the macro transformation
188  1 executeMacroTransformation(xdom, this.syntaxFactory.createSyntaxFromIdString(syntaxId));
189   
190    // Render
191  1 WikiPrinter printer = new DefaultWikiPrinter();
192  1 this.xhtmlRenderer.render(xdom, printer);
193   
194  1 return printer.toString();
195    } catch (Exception e) {
196  0 this.logger.error(e.getLocalizedMessage(), e);
197  0 throw new RuntimeException("Exception while refreshing HTML", e);
198    }
199    }
200   
 
201  24 toggle private void executeMacroTransformation(XDOM xdom, Syntax syntax) throws TransformationException, ParseException
202    {
203  24 TransformationContext txContext = new TransformationContext();
204  23 txContext.setXDOM(xdom);
205  24 txContext.setSyntax(syntax);
206   
207    // It's very important to set a Transformation id as otherwise if any Velocity Macro is executed it'll be
208    // executed in isolation (and if you have, say, 2 velocity macros, the second one will not 'see' what's defined
209    // in the first one...
210  24 txContext.setId(TRANSFORMATION_ID);
211   
212  24 ((MutableRenderingContext) this.renderingContext).transformInContext(this.macroTransformation, txContext, xdom);
213    }
214    }