| package org.apache.maven.doxia.module.latex; |
| |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| import org.apache.maven.doxia.sink.Sink; |
| import org.apache.maven.doxia.sink.SinkEventAttributes; |
| import org.apache.maven.doxia.sink.impl.AbstractTextSink; |
| import org.apache.maven.doxia.sink.impl.SinkEventAttributeSet; |
| import org.apache.maven.doxia.util.DoxiaUtils; |
| import org.apache.maven.doxia.util.LineBreaker; |
| |
| import org.codehaus.plexus.util.IOUtil; |
| import org.codehaus.plexus.util.StringUtils; |
| |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.Writer; |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.Locale; |
| import java.util.Stack; |
| |
| /** |
| * Latex Sink implementation. |
| * <br> |
| * <b>Note</b>: The encoding used is UTF-8. |
| * |
| * @version $Id$ |
| * @since 1.0 |
| */ |
| public class LatexSink |
| extends AbstractTextSink |
| { |
| /** |
| * Flag that indicates if the document to be written is only a fragment. |
| * |
| * This implies that <code>\\begin{document}</code>, <code>\\title{..}</code> will not be output. |
| */ |
| private final boolean fragmentDocument; |
| |
| private boolean ignoreText; |
| |
| private final LineBreaker out; |
| |
| private final String sinkCommands; |
| |
| private final String preamble; |
| |
| private boolean titleFlag; |
| |
| private int numberedListNesting; |
| |
| private boolean verbatimFlag; |
| |
| private boolean figureFlag; |
| |
| private boolean tableFlag; |
| |
| private boolean gridFlag; |
| |
| private int[] cellJustif; |
| |
| private int cellCount; |
| |
| private boolean isTitle; |
| |
| private String title; |
| |
| /** Keep track of the closing tags for inline events. */ |
| protected Stack<List<String>> inlineStack = new Stack<List<String>>(); |
| |
| // ---------------------------------------------------------------------- |
| // |
| // ---------------------------------------------------------------------- |
| |
| /** |
| * Constructor, initialize the Writer and the variables. |
| * |
| * @param out not null writer to write the result. <b>Should</b> be an UTF-8 Writer. |
| * You could use <code>newWriter</code> methods from {@link org.codehaus.plexus.util.WriterFactory}. |
| */ |
| protected LatexSink( Writer out ) |
| { |
| this( out, null, null ); |
| } |
| |
| /** |
| * Constructor, initialize the Writer and the variables. |
| * |
| * @param out not null writer to write the result. <b>Should</b> be an UTF-8 Writer. |
| * You could use <code>newWriter</code> methods from {@link org.codehaus.plexus.util.WriterFactory}. |
| * @param sinkCommands A String representation of commands that go before \documentclass. |
| * @param preamble A String representation of commands that go between \documentclass and \begin{document}. |
| */ |
| protected LatexSink( Writer out, String sinkCommands, String preamble ) |
| { |
| this( out, sinkCommands, preamble, false ); |
| } |
| |
| /** |
| * Constructor, initialize the Writer and the variables. |
| * |
| * @param out not null writer to write the result. <b>Should</b> be an UTF-8 Writer. |
| * You could use <code>newWriter</code> methods from {@link org.codehaus.plexus.util.WriterFactory}. |
| * @param sinkCommands A String representation of commands that go before \documentclass. |
| * @param preamble A String representation of commands that go between \documentclass and \begin{document}. |
| * @param fragmentDocument If this receives events that that are only part of a document. |
| * Typically, headers are omitted if this is true. |
| */ |
| protected LatexSink( Writer out, String sinkCommands, String preamble, boolean fragmentDocument ) |
| { |
| this.out = new LineBreaker( out ); |
| |
| if ( sinkCommands == null ) |
| { |
| sinkCommands = defaultSinkCommands(); |
| } |
| if ( preamble == null ) |
| { |
| preamble = defaultPreamble(); |
| } |
| |
| this.sinkCommands = sinkCommands; |
| this.preamble = preamble; |
| this.fragmentDocument = fragmentDocument; |
| |
| init(); |
| } |
| |
| // ---------------------------------------------------------------------- |
| // Overridables |
| // ---------------------------------------------------------------------- |
| |
| /** |
| * Returns a default \documentclass declaration. |
| * |
| * @return String. |
| */ |
| protected String getDocumentStart() |
| { |
| return "\\documentclass[a4paper]{article}" + EOL + EOL; |
| } |
| |
| /** |
| * Returns a default \begin{document} declaration. |
| * |
| * @return String. |
| */ |
| protected String getDocumentBegin() |
| { |
| return "\\begin{document}" + EOL + EOL; |
| } |
| |
| /** |
| * Returns a default \end{document} declaration. |
| * |
| * @return String. |
| */ |
| protected String getDocumentEnd() |
| { |
| return "\\end{document}" + EOL; |
| } |
| |
| // ---------------------------------------------------------------------- |
| // Sink Implementation |
| // ---------------------------------------------------------------------- |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void head() |
| { |
| head( null ); |
| } |
| |
| /** {@inheritDoc} */ |
| public void head( SinkEventAttributes attributes ) |
| { |
| init(); |
| |
| if ( !fragmentDocument ) |
| { |
| markup( sinkCommands ); |
| |
| markup( getDocumentStart() ); |
| |
| markup( preamble ); |
| |
| markup( getDocumentBegin() ); |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void body() |
| { |
| body( null ); |
| } |
| |
| /** {@inheritDoc} */ |
| public void body( SinkEventAttributes attributes ) |
| { |
| if ( titleFlag ) |
| { |
| if ( fragmentDocument ) |
| { |
| markup( "\\section" ); |
| } |
| else |
| { |
| titleFlag = false; |
| markup( "\\maketitle" + EOL + EOL ); |
| } |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void body_() |
| { |
| if ( !fragmentDocument ) |
| { |
| markup( getDocumentEnd() ); |
| } |
| |
| flush(); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void title() |
| { |
| title( null ); |
| } |
| |
| /** {@inheritDoc} */ |
| public void title( SinkEventAttributes attributes ) |
| { |
| if ( !fragmentDocument ) |
| { |
| titleFlag = true; |
| markup( "\\title{" ); |
| } |
| else |
| { |
| ignoreText = true; |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void title_() |
| { |
| if ( !fragmentDocument ) |
| { |
| markup( "}" + EOL ); |
| } |
| else |
| { |
| ignoreText = false; |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void author() |
| { |
| author( null ); |
| } |
| |
| /** {@inheritDoc} */ |
| public void author( SinkEventAttributes attributes ) |
| { |
| if ( !fragmentDocument ) |
| { |
| markup( "\\author{" ); |
| } |
| else |
| { |
| ignoreText = true; |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void author_() |
| { |
| if ( !fragmentDocument ) |
| { |
| markup( "}" + EOL ); |
| } |
| else |
| { |
| ignoreText = false; |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void date() |
| { |
| date( null ); |
| } |
| |
| /** {@inheritDoc} */ |
| public void date( SinkEventAttributes attributes ) |
| { |
| if ( !fragmentDocument ) |
| { |
| markup( "\\date{" ); |
| } |
| else |
| { |
| ignoreText = true; |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void date_() |
| { |
| if ( !fragmentDocument ) |
| { |
| markup( "}" + EOL ); |
| } |
| else |
| { |
| ignoreText = false; |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| public void sectionTitle( int level, SinkEventAttributes attributes ) |
| { |
| isTitle = true; |
| } |
| |
| /** {@inheritDoc} */ |
| public void sectionTitle_( int level ) |
| { |
| String command = ""; |
| switch ( level ) |
| { |
| case SECTION_LEVEL_1: |
| command = "section"; |
| break; |
| case SECTION_LEVEL_2: |
| command = "subsection"; |
| break; |
| case SECTION_LEVEL_3: |
| command = "subsubsection"; |
| break; |
| case SECTION_LEVEL_4: |
| command = "paragraph"; |
| break; |
| case SECTION_LEVEL_5: |
| command = "subparagraph"; |
| break; |
| default: |
| throw new IllegalArgumentException( "Not a section level: " + level ); |
| } |
| |
| isTitle = false; |
| |
| if ( StringUtils.isNotEmpty( title ) ) |
| { |
| markup( EOL + "\\" + command + "{" + title + "}" + EOL ); |
| |
| title = null; |
| } |
| } |
| |
| // ---------------------------------------------------------------------- |
| // Section Title 1 |
| // ---------------------------------------------------------------------- |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void sectionTitle1() |
| { |
| sectionTitle( SECTION_LEVEL_1, null ); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void sectionTitle1_() |
| { |
| sectionTitle_( SECTION_LEVEL_1 ); |
| } |
| |
| // ---------------------------------------------------------------------- |
| // Section Title 2 |
| // ---------------------------------------------------------------------- |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void sectionTitle2() |
| { |
| sectionTitle( SECTION_LEVEL_2, null ); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void sectionTitle2_() |
| { |
| sectionTitle_( SECTION_LEVEL_2 ); |
| } |
| |
| // ---------------------------------------------------------------------- |
| // Section Title 3 |
| // ---------------------------------------------------------------------- |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void sectionTitle3() |
| { |
| sectionTitle( SECTION_LEVEL_3, null ); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void sectionTitle3_() |
| { |
| sectionTitle_( SECTION_LEVEL_3 ); |
| } |
| |
| // ---------------------------------------------------------------------- |
| // Section Title 4 |
| // ---------------------------------------------------------------------- |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void sectionTitle4() |
| { |
| sectionTitle( SECTION_LEVEL_4, null ); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void sectionTitle4_() |
| { |
| sectionTitle_( SECTION_LEVEL_4 ); |
| } |
| |
| // ---------------------------------------------------------------------- |
| // Section Title 5 |
| // ---------------------------------------------------------------------- |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void sectionTitle5() |
| { |
| sectionTitle( SECTION_LEVEL_5, null ); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void sectionTitle5_() |
| { |
| sectionTitle_( SECTION_LEVEL_5 ); |
| } |
| |
| // ---------------------------------------------------------------------- |
| // List |
| // ---------------------------------------------------------------------- |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void list() |
| { |
| list( null ); |
| } |
| |
| /** {@inheritDoc} */ |
| public void list( SinkEventAttributes attributes ) |
| { |
| markup( EOL + "\\begin{itemize}" ); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void list_() |
| { |
| markup( EOL + "\\end{itemize}" + EOL ); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void listItem() |
| { |
| listItem( null ); |
| } |
| |
| /** {@inheritDoc} */ |
| public void listItem( SinkEventAttributes attributes ) |
| { |
| markup( EOL + "\\item " ); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void numberedList( int numbering ) |
| { |
| numberedList( numbering, null ); |
| } |
| |
| /** {@inheritDoc} */ |
| public void numberedList( int numbering, SinkEventAttributes attributes ) |
| { |
| ++numberedListNesting; |
| |
| String counter; |
| switch ( numberedListNesting ) |
| { |
| case 1: |
| counter = "enumi"; |
| break; |
| case 2: |
| counter = "enumii"; |
| break; |
| case 3: |
| counter = "enumiii"; |
| break; |
| case 4: |
| default: |
| counter = "enumiv"; |
| } |
| |
| String style; |
| switch ( numbering ) |
| { |
| case NUMBERING_UPPER_ALPHA: |
| style = "Alph"; |
| break; |
| case NUMBERING_LOWER_ALPHA: |
| style = "alph"; |
| break; |
| case NUMBERING_UPPER_ROMAN: |
| style = "Roman"; |
| break; |
| case NUMBERING_LOWER_ROMAN: |
| style = "roman"; |
| break; |
| case NUMBERING_DECIMAL: |
| default: |
| style = "arabic"; |
| } |
| |
| markup( EOL + "\\begin{enumerate}" + EOL ); |
| markup( "\\renewcommand{\\the" + counter + "}{\\" + style + "{" + counter + "}}" + EOL ); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void numberedList_() |
| { |
| markup( EOL + "\\end{enumerate}" + EOL ); |
| --numberedListNesting; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void numberedListItem() |
| { |
| numberedListItem( null ); |
| } |
| |
| /** {@inheritDoc} */ |
| public void numberedListItem( SinkEventAttributes attributes ) |
| { |
| markup( "\\item " ); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void definitionList() |
| { |
| definitionList( null ); |
| } |
| |
| /** {@inheritDoc} */ |
| public void definitionList( SinkEventAttributes attributes ) |
| { |
| markup( EOL + "\\begin{description}" ); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void definitionList_() |
| { |
| markup( EOL + "\\end{description}" + EOL ); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void definedTerm() |
| { |
| definedTerm( null ); |
| } |
| |
| /** {@inheritDoc} */ |
| public void definedTerm( SinkEventAttributes attributes ) |
| { |
| markup( EOL + "\\item[\\mbox{" ); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void definedTerm_() |
| { |
| markup( "}] " ); |
| } |
| |
| /** {@inheritDoc} */ |
| public void definitionListItem() |
| { |
| definitionListItem( null ); |
| } |
| |
| /** {@inheritDoc} */ |
| public void definitionListItem( SinkEventAttributes attributes ) |
| { |
| // nop |
| } |
| |
| /** {@inheritDoc} */ |
| public void definitionListItem_() |
| { |
| // nop |
| } |
| |
| /** {@inheritDoc} */ |
| public void definition() |
| { |
| definition( null ); |
| } |
| |
| /** {@inheritDoc} */ |
| public void definition( SinkEventAttributes attributes ) |
| { |
| // nop |
| } |
| |
| /** {@inheritDoc} */ |
| public void definition_() |
| { |
| // nop |
| } |
| |
| // ---------------------------------------------------------------------- |
| // Figure |
| // ---------------------------------------------------------------------- |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void figure() |
| { |
| figure( null ); |
| } |
| |
| /** {@inheritDoc} */ |
| public void figure( SinkEventAttributes attributes ) |
| { |
| figureFlag = true; |
| markup( EOL + "\\begin{figure}[htb]" + EOL ); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void figure_() |
| { |
| markup( "\\end{figure}" + EOL ); |
| figureFlag = false; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void figureGraphics( String name ) |
| { |
| figureGraphics( name, null ); |
| } |
| |
| /** {@inheritDoc} */ |
| public void figureGraphics( String src, SinkEventAttributes attributes ) |
| { |
| if ( !src.toLowerCase( Locale.ENGLISH ).endsWith( ".eps" ) ) |
| { |
| getLog().warn( "[Latex Sink] Found non-eps figure graphics!" ); |
| } |
| |
| markup( "\\begin{center}" + EOL ); |
| markup( "\\includegraphics{" + src + "}" + EOL ); |
| markup( "\\end{center}" + EOL ); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void figureCaption() |
| { |
| figureCaption( null ); |
| } |
| |
| /** {@inheritDoc} */ |
| public void figureCaption( SinkEventAttributes attributes ) |
| { |
| markup( "\\caption{" ); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void figureCaption_() |
| { |
| markup( "}" + EOL ); |
| } |
| |
| // ---------------------------------------------------------------------- |
| // Table |
| // ---------------------------------------------------------------------- |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void table() |
| { |
| table( null ); |
| } |
| |
| /** {@inheritDoc} */ |
| public void table( SinkEventAttributes attributes ) |
| { |
| tableFlag = true; |
| markup( EOL + "\\begin{table}[htp]" + EOL ); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void table_() |
| { |
| markup( "\\end{table}" + EOL ); |
| tableFlag = false; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void tableRows( int[] justification, boolean grid ) |
| |
| { |
| StringBuilder justif = new StringBuilder(); |
| for ( int i = 0; i < justification.length; ++i ) |
| { |
| if ( grid ) |
| { |
| justif.append( '|' ); |
| } |
| switch ( justification[i] ) |
| { |
| case Sink.JUSTIFY_CENTER: |
| justif.append( 'c' ); |
| break; |
| case Sink.JUSTIFY_LEFT: |
| justif.append( 'l' ); |
| break; |
| case Sink.JUSTIFY_RIGHT: |
| justif.append( 'r' ); |
| break; |
| default: |
| break; |
| } |
| } |
| if ( grid ) |
| { |
| justif.append( '|' ); |
| } |
| |
| markup( "\\begin{center}" + EOL ); |
| markup( "\\begin{tabular}{" + justif.toString() + "}" + EOL ); |
| if ( grid ) |
| { |
| markup( "\\hline" + EOL ); |
| } |
| gridFlag = grid; |
| cellJustif = justification; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void tableRows_() |
| { |
| markup( "\\end{tabular}" + EOL ); |
| markup( "\\end{center}" + EOL ); |
| |
| gridFlag = false; |
| cellJustif = null; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void tableRow() |
| { |
| tableRow( null ); |
| } |
| |
| /** {@inheritDoc} */ |
| public void tableRow( SinkEventAttributes attributes ) |
| { |
| cellCount = 0; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void tableRow_() |
| { |
| markup( "\\\\" + EOL ); |
| if ( gridFlag || lastCellWasHeader ) |
| { |
| markup( "\\hline" + EOL ); |
| } |
| cellCount = 0; |
| lastCellWasHeader = false; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void tableCell() |
| { |
| tableCell( (SinkEventAttributes) null ); |
| } |
| |
| /** {@inheritDoc} */ |
| public void tableCell( String width ) |
| { |
| SinkEventAttributeSet att = new SinkEventAttributeSet(); |
| att.addAttribute( javax.swing.text.html.HTML.Attribute.WIDTH, width ); |
| |
| tableCell( att ); |
| } |
| |
| /** {@inheritDoc} */ |
| public void tableCell( SinkEventAttributes attributes ) |
| { |
| tableCell( false ); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void tableCell_() |
| { |
| markup( "\\end{tabular}" ); |
| ++cellCount; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void tableHeaderCell() |
| { |
| tableCell( (SinkEventAttributes) null ); |
| } |
| |
| /** {@inheritDoc} */ |
| public void tableHeaderCell( String width ) |
| { |
| SinkEventAttributeSet att = new SinkEventAttributeSet(); |
| att.addAttribute( javax.swing.text.html.HTML.Attribute.WIDTH, width ); |
| |
| tableHeaderCell( att ); |
| } |
| |
| /** {@inheritDoc} */ |
| public void tableHeaderCell( SinkEventAttributes attributes ) |
| { |
| tableCell( true ); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void tableHeaderCell_() |
| { |
| tableCell_(); |
| } |
| |
| private boolean lastCellWasHeader = false; |
| |
| /** |
| * Starts a table cell. |
| * |
| * @param header True if this is a header cell. |
| */ |
| private void tableCell( boolean header ) |
| { |
| lastCellWasHeader = header; |
| |
| if ( cellCount > 0 ) |
| { |
| markup( " &" + EOL ); |
| } |
| |
| char justif; |
| switch ( cellJustif[cellCount] ) |
| { |
| case Sink.JUSTIFY_LEFT: |
| justif = 'l'; |
| break; |
| case Sink.JUSTIFY_RIGHT: |
| justif = 'r'; |
| break; |
| case Sink.JUSTIFY_CENTER: |
| default: |
| justif = 'c'; |
| break; |
| } |
| markup( "\\begin{tabular}[t]{" + justif + "}" ); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void tableCaption() |
| { |
| tableCaption( null ); |
| } |
| |
| /** {@inheritDoc} */ |
| public void tableCaption( SinkEventAttributes attributes ) |
| { |
| markup( "\\caption{" ); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void tableCaption_() |
| { |
| markup( "}" + EOL ); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void paragraph() |
| { |
| paragraph( null ); |
| } |
| |
| /** {@inheritDoc} */ |
| public void paragraph( SinkEventAttributes attributes ) |
| { |
| markup( EOL + EOL ); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void paragraph_() |
| { |
| markup( EOL ); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void verbatim( boolean boxed ) |
| { |
| verbatim( boxed ? SinkEventAttributeSet.BOXED : null ); |
| } |
| |
| /** {@inheritDoc} */ |
| public void verbatim( SinkEventAttributes attributes ) |
| { |
| boolean boxed = false; |
| |
| if ( attributes != null && attributes.isDefined( SinkEventAttributes.DECORATION ) ) |
| { |
| boxed = "boxed".equals( |
| attributes.getAttribute( SinkEventAttributes.DECORATION ) ); |
| } |
| |
| markup( EOL + "\\begin{small}" + EOL ); |
| |
| if ( boxed ) |
| { |
| markup( "\\begin{Verbatim}[frame=single]" + EOL ); |
| } |
| else |
| { |
| markup( "\\begin{Verbatim}" + EOL ); |
| } |
| |
| verbatimFlag = true; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void verbatim_() |
| { |
| markup( EOL + "\\end{Verbatim}" + EOL ); |
| markup( "\\end{small}" + EOL ); |
| |
| verbatimFlag = false; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void horizontalRule() |
| { |
| horizontalRule( null ); |
| } |
| |
| /** {@inheritDoc} */ |
| public void horizontalRule( SinkEventAttributes attributes ) |
| { |
| markup( EOL + "\\begin{center}\\rule[0.5ex]{\\linewidth}{1pt}\\end{center}" + EOL ); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void pageBreak() |
| { |
| markup( EOL + "\\newpage" + EOL ); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void anchor( String name ) |
| { |
| anchor( name, null ); |
| } |
| |
| /** {@inheritDoc} */ |
| public void anchor( String name, SinkEventAttributes attributes ) |
| { |
| markup( "\\hypertarget{" + name + "}{" ); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void anchor_() |
| { |
| markup( "}" ); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void link( String name ) |
| { |
| link( name, null ); |
| } |
| |
| /** {@inheritDoc} */ |
| public void link( String name, SinkEventAttributes attributes ) |
| { |
| // TODO: use \\url for simple links |
| if ( DoxiaUtils.isExternalLink( name ) ) |
| { |
| markup( "\\href{" + name + "}{" ); |
| } |
| else |
| { |
| markup( "\\hyperlink{" + name + "}{" ); |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void link_() |
| { |
| markup( "}" ); |
| } |
| |
| /** {@inheritDoc} */ |
| public void inline() |
| { |
| inline( null ); |
| } |
| |
| /** {@inheritDoc} */ |
| public void inline( SinkEventAttributes attributes ) |
| { |
| List<String> tags = new ArrayList<String>(); |
| |
| if ( attributes != null ) |
| { |
| |
| if ( attributes.containsAttribute( SinkEventAttributes.SEMANTICS, "italic" ) ) |
| { |
| markup( "\\textit{" ); |
| tags.add( 0, "}" ); |
| } |
| |
| if ( attributes.containsAttribute( SinkEventAttributes.SEMANTICS, "bold" ) ) |
| { |
| markup( "\\textbf{" ); |
| tags.add( 0, "}" ); |
| } |
| |
| if ( attributes.containsAttribute( SinkEventAttributes.SEMANTICS, "code" ) ) |
| { |
| markup( "\\texttt{\\small " ); |
| tags.add( 0, "}" ); |
| } |
| |
| } |
| |
| inlineStack.push( tags ); |
| } |
| |
| /** {@inheritDoc} */ |
| public void inline_() |
| { |
| for ( String tag: inlineStack.pop() ) |
| { |
| markup( tag ); |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void italic() |
| { |
| inline( SinkEventAttributeSet.Semantics.ITALIC ); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void italic_() |
| { |
| inline_(); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void bold() |
| { |
| inline( SinkEventAttributeSet.Semantics.BOLD ); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void bold_() |
| { |
| inline_(); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void monospaced() |
| { |
| inline( SinkEventAttributeSet.Semantics.CODE ); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void monospaced_() |
| { |
| inline_(); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void lineBreak() |
| { |
| lineBreak( null ); |
| } |
| |
| /** {@inheritDoc} */ |
| public void lineBreak( SinkEventAttributes attributes ) |
| { |
| markup( ( figureFlag || tableFlag || titleFlag || verbatimFlag ) ? EOL : "\\newline" + EOL ); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void nonBreakingSpace() |
| { |
| markup( "~" ); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void text( String text ) |
| { |
| text( text, null ); |
| } |
| |
| /** {@inheritDoc} */ |
| public void text( String text, SinkEventAttributes attributes ) |
| { |
| if ( ignoreText ) |
| { |
| return; |
| } |
| if ( isTitle ) |
| { |
| title = text; |
| } |
| else if ( verbatimFlag ) |
| { |
| verbatimContent( text ); |
| } |
| else |
| { |
| content( text ); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| public void rawText( String text ) |
| { |
| verbatimContent( text ); |
| } |
| |
| /** {@inheritDoc} */ |
| public void comment( String comment ) |
| { |
| rawText( EOL + "%" + comment ); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * Unkown events just log a warning message but are ignored otherwise. |
| * @see org.apache.maven.doxia.sink.Sink#unknown(String,Object[],SinkEventAttributes) |
| */ |
| public void unknown( String name, Object[] requiredParams, SinkEventAttributes attributes ) |
| { |
| getLog().warn( "[Latex Sink] Unknown Sink event: '" + name + "', ignoring!" ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| /** |
| * Writes the text, preserving whitespace. |
| * |
| * @param text the text to write. |
| */ |
| protected void markup( String text ) |
| { |
| if ( text != null ) |
| { |
| out.write( text, /*preserveSpace*/ true ); |
| } |
| } |
| |
| /** |
| * Writes the text, without preserving whitespace. |
| * |
| * @param text the text to write. |
| */ |
| protected void content( String text ) |
| { |
| out.write( escaped( text ), /*preserveSpace*/ false ); |
| } |
| |
| /** |
| * Writes the text, preserving whitespace. |
| * |
| * @param text the text to write. |
| */ |
| protected void verbatimContent( String text ) |
| { |
| out.write( text, /*preserveSpace*/ true ); |
| } |
| |
| // ----------------------------------------------------------------------- |
| |
| /** |
| * Escapes special characters. |
| * |
| * @param text The text to escape. |
| * @return The text with special characters replaced. |
| */ |
| public static String escaped( String text ) |
| { |
| int length = text.length(); |
| StringBuilder buffer = new StringBuilder( length ); |
| |
| for ( int i = 0; i < length; ++i ) |
| { |
| char c = text.charAt( i ); |
| switch ( c ) |
| { |
| case '-': |
| case '<': |
| case '>': |
| buffer.append( "\\symbol{" ).append( (int) c ).append( "}" ); |
| break; |
| case '~': |
| buffer.append( "\\textasciitilde " ); |
| break; |
| case '^': |
| buffer.append( "\\textasciicircum " ); |
| break; |
| case '|': |
| buffer.append( "\\textbar " ); |
| break; |
| case '\\': |
| buffer.append( "\\textbackslash " ); |
| break; |
| case '$': |
| buffer.append( "\\$" ); |
| break; |
| case '&': |
| buffer.append( "\\&" ); |
| break; |
| case '%': |
| buffer.append( "\\%" ); |
| break; |
| case '#': |
| buffer.append( "\\#" ); |
| break; |
| case '{': |
| buffer.append( "\\{" ); |
| break; |
| case '}': |
| buffer.append( "\\}" ); |
| break; |
| case '_': |
| buffer.append( "\\_" ); |
| break; |
| default: |
| buffer.append( c ); |
| } |
| } |
| |
| return buffer.toString(); |
| } |
| |
| // ---------------------------------------------------------------------- |
| // |
| // ---------------------------------------------------------------------- |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void flush() |
| { |
| out.flush(); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void close() |
| { |
| out.close(); |
| |
| init(); |
| } |
| |
| // ---------------------------------------------------------------------- |
| // |
| // ---------------------------------------------------------------------- |
| |
| /** |
| * Returns the default sink commands from a resource. |
| * |
| * @throws java.io.IOException if the resource file cannot be read. |
| * @return InputStream |
| */ |
| private static InputStream getDefaultSinkCommands() |
| throws IOException |
| { |
| return LatexSink.class.getResource( "default_sink_commands.tex" ).openStream(); |
| } |
| |
| /** |
| * Returns the default preamble from a resource. |
| * |
| * @return InputStream |
| * @throws java.io.IOException if the resource file cannot be read. |
| */ |
| private static InputStream getDefaultPreamble() |
| throws IOException |
| { |
| return LatexSink.class.getResource( "default_preamble.tex" ).openStream(); |
| } |
| |
| /** |
| * Returns the default sink commands. |
| * |
| * @return String. |
| */ |
| protected String defaultSinkCommands() |
| { |
| try |
| { |
| return IOUtil.toString( getDefaultSinkCommands() ); |
| } |
| catch ( IOException ioe ) |
| { |
| // this should not happen |
| getLog().warn( "Could not read default LaTeX commands, the generated LaTeX file will not compile!" ); |
| getLog().debug( ioe ); |
| |
| return ""; |
| } |
| } |
| |
| /** |
| * Returns the default preamble. |
| * |
| * @return String. |
| */ |
| protected String defaultPreamble() |
| { |
| try |
| { |
| return IOUtil.toString( getDefaultPreamble() ); |
| } |
| catch ( IOException ioe ) |
| { |
| // this should not happen |
| getLog().warn( "Could not read default LaTeX preamble, the generated LaTeX file will not compile!" ); |
| getLog().debug( ioe ); |
| |
| return ""; |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| protected void init() |
| { |
| super.init(); |
| |
| this.ignoreText = false; |
| this.titleFlag = false; |
| this.numberedListNesting = 0; |
| this.verbatimFlag = false; |
| this.figureFlag = false; |
| this.tableFlag = false; |
| this.gridFlag = false; |
| this.cellJustif = null; |
| this.cellCount = 0; |
| this.isTitle = false; |
| this.title = null; |
| } |
| } |