View Javadoc
1   package org.apache.maven.doxia.module.xhtml;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.StringWriter;
23  import java.io.Writer;
24  
25  import org.apache.maven.doxia.markup.HtmlMarkup;
26  import org.apache.maven.doxia.sink.Sink;
27  import org.apache.maven.doxia.sink.impl.AbstractSinkTest;
28  import org.apache.maven.doxia.sink.impl.SinkEventAttributeSet;
29  import org.junit.jupiter.api.Test;
30  
31  import static org.apache.maven.doxia.util.HtmlTools.escapeHTML;
32  import static org.junit.jupiter.api.Assertions.assertEquals;
33  import static org.junit.jupiter.api.Assertions.assertTrue;
34  
35  /**
36   * @author Jason van Zyl
37   * @since 1.0
38   */
39  public class XhtmlSinkTest
40      extends AbstractSinkTest
41  {
42      /** {@inheritDoc} */
43      protected String outputExtension()
44      {
45          return "xhtml";
46      }
47  
48      /** {@inheritDoc} */
49      protected Sink createSink( Writer writer )
50      {
51          return new XhtmlSink( writer, "UTF-8" );
52      }
53  
54      /** {@inheritDoc} */
55      protected boolean isXmlSink()
56      {
57          return true;
58      }
59  
60      /**
61       * Test link generation.
62       *
63       */
64      @Test
65      public void testLinks()
66      {
67          XhtmlSink sink = null;
68          Writer writer =  new StringWriter();
69          try
70          {
71              sink = (XhtmlSink) createSink( writer );
72              sink.link( "http:/www.xdoc.com" );
73              sink.link_();
74              sink.link( "./index.html#anchor" );
75              sink.link_();
76              sink.link( "../index.html#anchor" );
77              sink.link_();
78              sink.link( "index.html" );
79              sink.link_();
80          }
81          finally
82          {
83              if ( sink != null )
84              {
85                  sink.close();
86              }
87          }
88  
89          String actual = writer.toString();
90          assertTrue( actual.contains( "<a class=\"externalLink\" href=\"http:/www.xdoc.com\"></a>" ) );
91          assertTrue( actual.contains( "<a href=\"./index.html#anchor\"></a>" ) );
92          assertTrue( actual.contains( "<a href=\"../index.html#anchor\"></a>" ) );
93          assertTrue( actual.contains( "<a href=\"index.html\"></a>" ) );
94      }
95  
96      /** {@inheritDoc} */
97      protected String getTitleBlock( String title )
98      {
99          return "<title>" + title + "</title>";
100     }
101 
102     /** {@inheritDoc} */
103     protected String getAuthorBlock( String author )
104     {
105         return author;
106     }
107 
108     /** {@inheritDoc} */
109     protected String getDateBlock( String date )
110     {
111         return date;
112     }
113 
114     /** {@inheritDoc} */
115     protected String getHeadBlock()
116     {
117         return "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">" +
118                 "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<title></title>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"/></head>";
119     }
120 
121     /** {@inheritDoc} */
122     protected String getBodyBlock()
123     {
124         return "<body></body></html>";
125     }
126 
127     /** {@inheritDoc} */
128     protected String getArticleBlock()
129     {
130         return "";
131     }
132 
133     /** {@inheritDoc} */
134     protected String getNavigationBlock()
135     {
136         return "";
137     }
138 
139     /** {@inheritDoc} */
140     protected String getSidebarBlock()
141     {
142         return "";
143     }
144 
145     /** {@inheritDoc} */
146     protected String getSectionTitleBlock( String title )
147     {
148         return title;
149     }
150 
151     /** {@inheritDoc} */
152     protected String getSection1Block( String title )
153     {
154         return "<div class=\"section\">\n<h2>" + title + "</h2></div>";
155     }
156 
157     /** {@inheritDoc} */
158     protected String getSection2Block( String title )
159     {
160         return "<div class=\"section\">\n<h3>" + title + "</h3></div>";
161     }
162 
163     /** {@inheritDoc} */
164     protected String getSection3Block( String title )
165     {
166         return "<div class=\"section\">\n<h4>" + title + "</h4></div>";
167     }
168 
169     /** {@inheritDoc} */
170     protected String getSection4Block( String title )
171     {
172         return "<div class=\"section\">\n<h5>" + title + "</h5></div>";
173     }
174 
175     /** {@inheritDoc} */
176     protected String getSection5Block( String title )
177     {
178         return "<div class=\"section\">\n<h6>" + title + "</h6></div>";
179     }
180 
181     /** {@inheritDoc} */
182     protected String getHeaderBlock()
183     {
184         return "";
185     }
186 
187     /** {@inheritDoc} */
188     protected String getContentBlock()
189     {
190         return "";
191     }
192 
193     /** {@inheritDoc} */
194     protected String getFooterBlock()
195     {
196         return "";
197     }
198 
199     /** {@inheritDoc} */
200     protected String getListBlock( String item )
201     {
202         return "<ul>\n<li>" + item + "</li></ul>";
203     }
204 
205     /** {@inheritDoc} */
206     protected String getNumberedListBlock( String item )
207     {
208         return "<ol style=\"list-style-type: lower-roman\">\n<li>" + item + "</li></ol>";
209     }
210 
211     /** {@inheritDoc} */
212     protected String getDefinitionListBlock( String definum, String definition )
213     {
214         return "<dl>\n<dt>" + definum + "</dt>\n<dd>" + definition + "</dd></dl>";
215     }
216 
217     /** {@inheritDoc} */
218     protected String getFigureBlock( String source, String caption )
219     {
220         String figureBlock = "<img src=\"" + escapeHTML( source, true ) + "\"";
221         if( caption != null )
222         {
223             figureBlock += " alt=\"" + caption + "\"";
224         }
225         else //@todo fix DOXIA-361
226         {
227             figureBlock += " alt=\"\"";
228         }
229         figureBlock += " />";
230         return figureBlock;
231     }
232 
233     /** {@inheritDoc} */
234     protected String getTableBlock( String cell, String caption )
235     {
236         return "<table border=\"0\" class=\"bodyTable\">"
237             + "<caption>Table caption</caption><tr class=\"a\">\n<td>cell</td></tr>"
238             + "</table>";
239     }
240 
241     // Disable testTable until the order of attributes issue is clarified
242     // TODO: remove
243     /** {@inheritDoc} */
244     @Test
245     public void testTable()
246     {
247         assertEquals( "", "", "Dummy!" );
248     }
249 
250     /** {@inheritDoc} */
251     protected String getParagraphBlock( String text )
252     {
253         return "<p>" + text + "</p>";
254     }
255 
256     /** {@inheritDoc} */
257     protected String getDataBlock( String value, String text )
258     {
259         return text;
260     }
261 
262     /** {@inheritDoc} */
263     protected String getTimeBlock( String datetime, String text )
264     {
265         return text;
266     }
267 
268     /** {@inheritDoc} */
269     protected String getAddressBlock( String text )
270     {
271         return "<address>" + text + "</address>";
272     }
273 
274     /** {@inheritDoc} */
275     protected String getBlockquoteBlock( String text )
276     {
277         return "<blockquote>" + text + "</blockquote>";
278     }
279 
280     /** {@inheritDoc} */
281     protected String getDivisionBlock( String text )
282     {
283         return "<div>" + text + "</div>";
284     }
285 
286     /** {@inheritDoc} */
287     protected String getVerbatimBlock( String text )
288     {
289         return "<div class=\"source\">\n<pre>" + text + "</pre></div>";
290     }
291 
292     /** {@inheritDoc} */
293     protected String getHorizontalRuleBlock()
294     {
295         return "<hr />";
296     }
297 
298     /** {@inheritDoc} */
299     protected String getPageBreakBlock()
300     {
301         return "<!-- PB -->";
302     }
303 
304     /** {@inheritDoc} */
305     protected String getAnchorBlock( String anchor )
306     {
307         return "<a name=\"" + anchor + "\">" + anchor + "</a>";
308     }
309 
310     /** {@inheritDoc} */
311     protected String getLinkBlock( String link, String text )
312     {
313         return "<a href=\"" + link + "\">" + text + "</a>";
314     }
315 
316     /** {@inheritDoc} */
317     protected String getInlineBlock( String text )
318     {
319         return text;
320     }
321 
322     /** {@inheritDoc} */
323     protected String getInlineItalicBlock( String text )
324     {
325         return "<i>" + text + "</i>";
326     }
327 
328     /** {@inheritDoc} */
329     protected String getInlineBoldBlock( String text )
330     {
331         return "<b>" + text + "</b>";
332     }
333 
334     /** {@inheritDoc} */
335     protected String getInlineCodeBlock( String text )
336     {
337         return "<code>" + text + "</code>";
338     }
339 
340     /** {@inheritDoc} */
341     protected String getItalicBlock( String text )
342     {
343         return "<i>" + text + "</i>";
344     }
345 
346     /** {@inheritDoc} */
347     protected String getBoldBlock( String text )
348     {
349         return "<b>" + text + "</b>";
350     }
351 
352     /** {@inheritDoc} */
353     protected String getMonospacedBlock( String text )
354     {
355         return "<tt>" + text + "</tt>";
356     }
357 
358     /** {@inheritDoc} */
359     protected String getLineBreakBlock()
360     {
361         return "<br />";
362     }
363 
364     /** {@inheritDoc} */
365     protected String getLineBreakOpportunityBlock()
366     {
367         return "";
368     }
369 
370     /** {@inheritDoc} */
371     protected String getNonBreakingSpaceBlock()
372     {
373         return "&#160;";
374     }
375 
376     /** {@inheritDoc} */
377     protected String getTextBlock( String text )
378     {
379         // TODO: need to be able to retreive those from outside the sink
380         return "~,_=,_-,_+,_*,_[,_],_&lt;,_&gt;,_{,_},_\\";
381     }
382 
383     /** {@inheritDoc} */
384     protected String getRawTextBlock( String text )
385     {
386         return text;
387     }
388 
389     /**
390      * Test entities is section titles and paragraphs.
391      */
392     @Test
393     public void testEntities()
394     {
395         XhtmlSink sink = null;
396         Writer writer =  new StringWriter();
397 
398         try
399         {
400             sink = new XhtmlSink( writer );
401             sink.section( Sink.SECTION_LEVEL_1, null );
402             sink.sectionTitle( Sink.SECTION_LEVEL_1, null );
403             sink.text( "&", null );
404             sink.sectionTitle_( Sink.SECTION_LEVEL_1 );
405             sink.paragraph( null );
406             sink.text( "&", null );
407             sink.paragraph_();
408             sink.section_( Sink.SECTION_LEVEL_1 );
409         }
410         finally
411         {
412             sink.close();
413         }
414 
415         assertEquals( "<div class=\"section\">\n<h2>&amp;</h2>\n<p>&amp;</p></div>", writer.toString() );
416     }
417 
418     /**
419      * Test head events.
420      */
421     @Test
422     public void testHead()
423     {
424         XhtmlSink sink = null;
425         Writer writer =  new StringWriter();
426 
427         try
428         {
429             sink = new XhtmlSink( writer );
430             sink.head();
431             sink.title();
432             sink.text( "Title" );
433             sink.title_();
434             sink.comment( "A comment" );
435             sink.author();
436             // note: this is really illegal, there should be no un-resolved entities emitted into text()
437             sink.text( "&#x123;&" );
438             sink.author_();
439             SinkEventAttributeSet atts = new SinkEventAttributeSet( 1 );
440             atts.addAttribute( "href", "http://maven.apache.org/" );
441             sink.unknown( "base", new Object[] { HtmlMarkup.TAG_TYPE_SIMPLE }, atts );
442             sink.head_();
443         }
444         finally
445         {
446             sink.close();
447         }
448 
449         String expected =
450             "<head>\n<title>Title</title><!--A comment--><meta name=\"author\" content=\"&#x123;&amp;\" />"
451                 + "<base href=\"http://maven.apache.org/\" /></head>";
452         String actual = writer.toString();
453         assertTrue( actual.contains( expected ), actual );
454     }
455 
456     /** {@inheritDoc} */
457     protected String getCommentBlock( String text )
458     {
459         return "<!--" + toXmlComment( text ) + "-->";
460     }
461 }