r696 - in branches/jrst-docutils-jython: . doxia-module-jrst-legacy doxia-module-jrst-legacy/src doxia-module-jrst-legacy/src/license doxia-module-jrst-legacy/src/main doxia-module-jrst-legacy/src/main/java doxia-module-jrst-legacy/src/main/java/org doxia-module-jrst-legacy/src/main/java/org/nuiton doxia-module-jrst-legacy/src/main/java/org/nuiton/jrst doxia-module-jrst-legacy/src/site doxia-module-jrst-legacy/src/site/apt doxia-module-jrst-legacy/src/site/en doxia-module-jrst-legacy/src/site
Author: jpages Date: 2012-06-05 16:44:35 +0200 (Tue, 05 Jun 2012) New Revision: 696 Url: http://nuiton.org/repositories/revision/jrst/696 Log: Creation du module doxia-module-jrst-legacy pour la g?\195?\169n?\195?\169ration de site en mode "simple" Correction de la documentation pour fonctionner avec l'ancien parseur (sommaires mal plac?\195?\169s, liens erron?\195?\169s,...) Added: branches/jrst-docutils-jython/doxia-module-jrst-legacy/ branches/jrst-docutils-jython/doxia-module-jrst-legacy/LICENSE.txt branches/jrst-docutils-jython/doxia-module-jrst-legacy/README.txt branches/jrst-docutils-jython/doxia-module-jrst-legacy/changelog.txt branches/jrst-docutils-jython/doxia-module-jrst-legacy/pom.xml branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/ branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/license/ branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/license/THIRD-PARTY.properties branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/main/ branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/main/java/ branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/main/java/org/ branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/main/java/org/nuiton/ branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/main/java/org/nuiton/jrst/ branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/main/java/org/nuiton/jrst/JrstParser.java branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/main/java/org/nuiton/jrst/JrstSiteModule.java branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/main/resources/ branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/site/ branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/site/apt/ branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/site/apt/devel.apt branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/site/apt/index.apt branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/site/en/ branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/site/en/apt/ branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/site/en/apt/devel.apt branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/site/en/apt/index.apt branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/site/site_en.xml branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/site/site_fr.xml branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/test/ branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/test/java/ branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/test/java/org/ branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/test/java/org/nuiton/ branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/test/java/org/nuiton/jrst/ branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/test/java/org/nuiton/jrst/JrstParserTest.java branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/test/resources/ branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/test/resources/test.rst branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/legacy/ branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/legacy/AdvancedReader.java branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/legacy/DocumentHandler.java branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/legacy/DocumentWalker.java branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/legacy/JRSTLexer.java branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/legacy/JRSTReader.java branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/legacy/ReStructuredText.java branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/legacy/directive/ Removed: branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/AdvancedReader.java branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/DocumentHandler.java branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/DocumentWalker.java branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/JRSTLexer.java branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/JRSTReader.java branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/ReStructuredText.java branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/directive/ Modified: branches/jrst-docutils-jython/jrst-doc/src/site/en/rst/devel/developerDoc.rst branches/jrst-docutils-jython/jrst-doc/src/site/en/rst/index.rst branches/jrst-docutils-jython/jrst-doc/src/site/rst/devel/docDevDocutils.rst branches/jrst-docutils-jython/jrst-doc/src/site/rst/devel/docDevJRSTParser.rst branches/jrst-docutils-jython/jrst-doc/src/site/rst/devel/docDeveloppeur.rst branches/jrst-docutils-jython/jrst-doc/src/site/rst/index.rst branches/jrst-docutils-jython/jrst-doc/src/site/site_en.xml branches/jrst-docutils-jython/jrst-doc/src/site/site_fr.xml branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/JRST.java branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/JRSTGenerator.java branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/convertisor/DocUtils2RST.java branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/convertisor/DocUtilsVisitor.java branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/legacy/directive/ContentDirective.java branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/legacy/directive/DateDirective.java branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/legacy/directive/ImageDirective.java branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/legacy/directive/SectnumDirective.java branches/jrst-docutils-jython/pom.xml Property changes on: branches/jrst-docutils-jython/doxia-module-jrst-legacy ___________________________________________________________________ Added: svn:ignore + target .settings .classpath .project *.iml Copied: branches/jrst-docutils-jython/doxia-module-jrst-legacy/LICENSE.txt (from rev 695, branches/jrst-docutils-jython/doxia-module-jrst/LICENSE.txt) =================================================================== --- branches/jrst-docutils-jython/doxia-module-jrst-legacy/LICENSE.txt (rev 0) +++ branches/jrst-docutils-jython/doxia-module-jrst-legacy/LICENSE.txt 2012-06-05 14:44:35 UTC (rev 696) @@ -0,0 +1,166 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. + Copied: branches/jrst-docutils-jython/doxia-module-jrst-legacy/README.txt (from rev 695, branches/jrst-docutils-jython/doxia-module-jrst/README.txt) =================================================================== --- branches/jrst-docutils-jython/doxia-module-jrst-legacy/README.txt (rev 0) +++ branches/jrst-docutils-jython/doxia-module-jrst-legacy/README.txt 2012-06-05 14:44:35 UTC (rev 696) @@ -0,0 +1,21 @@ +Doxia Module JRst +================= + +Configuration +------------- + +To use it, put it in your pom.xml : + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-site-plugin</artifactId> + <dependencies> + <dependency> + <groupId>org.codelutin</groupId> + <artifactId>doxia-module-jrst</artifactId> + <version>${doxia-module-jrst.version}</version> + </dependency> + </dependencies> + </plugin> + +That it ! Then run "mvn site". Copied: branches/jrst-docutils-jython/doxia-module-jrst-legacy/changelog.txt (from rev 695, branches/jrst-docutils-jython/doxia-module-jrst/changelog.txt) =================================================================== --- branches/jrst-docutils-jython/doxia-module-jrst-legacy/changelog.txt (rev 0) +++ branches/jrst-docutils-jython/doxia-module-jrst-legacy/changelog.txt 2012-06-05 14:44:35 UTC (rev 696) @@ -0,0 +1,15 @@ +doxia-module-jrst (1.6.0) + + * JrstParser use now JRST.java methods to generate the site + +doxia-module-jrst (1.1.0) ? + + * migrate to nuiton + +doxia-module-jrst (1.0.1) chemit 20090511 + + * Bump versions (lutinproject 3.5.4, jrst 0.8.6) + +doxia-module-jrst (1.0.0) chemit + + * Initial release \ No newline at end of file Copied: branches/jrst-docutils-jython/doxia-module-jrst-legacy/pom.xml (from rev 695, branches/jrst-docutils-jython/doxia-module-jrst/pom.xml) =================================================================== --- branches/jrst-docutils-jython/doxia-module-jrst-legacy/pom.xml (rev 0) +++ branches/jrst-docutils-jython/doxia-module-jrst-legacy/pom.xml 2012-06-05 14:44:35 UTC (rev 696) @@ -0,0 +1,161 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JRst :: Doxia module + + $Id$ + $HeadURL$ + %% + Copyright (C) 2009 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + + <modelVersion>4.0.0</modelVersion> + + <!-- ************************************************************* --> + <!-- *** POM Relationships *************************************** --> + <!-- ************************************************************* --> + + <parent> + <groupId>org.nuiton</groupId> + <artifactId>jrst</artifactId> + <version>1.6-SNAPSHOT</version> + </parent> + + <groupId>org.nuiton.jrst</groupId> + <artifactId>doxia-module-jrst-legacy</artifactId> + + <dependencies> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>jrst</artifactId> + <version>${project.version}</version> + <scope>compile</scope> + <!-- There is a pb with xalan --> + <exclusions> + <exclusion> + <groupId>xalan</groupId> + <artifactId>xalan</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.apache.maven.doxia</groupId> + <artifactId>doxia-module-xdoc</artifactId> + </dependency> + + <dependency> + <groupId>org.apache.maven.doxia</groupId> + <artifactId>doxia-sink-api</artifactId> + </dependency> + + <dependency> + <groupId>org.apache.maven.doxia</groupId> + <artifactId>doxia-core</artifactId> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>org.apache.maven.doxia</groupId> + <artifactId>doxia-core</artifactId> + <type>test-jar</type> + </dependency> + + <dependency> + <groupId>jaxen</groupId> + <artifactId>jaxen</artifactId> + <scope>runtime</scope> + </dependency> + + <dependency> + <groupId>dom4j</groupId> + <artifactId>dom4j</artifactId> + <!--<scope>runtime</scope>--> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + </dependency> + + <dependency> + <groupId>org.codehaus.plexus</groupId> + <artifactId>plexus-utils</artifactId> + </dependency> + + </dependencies> + + <!-- ************************************************************* --> + <!-- *** Project Information ************************************* --> + <!-- ************************************************************* --> + + <name>JRst :: Doxia module legacy</name> + <description>JRst legacy module for doxia</description> + <inceptionYear>2009</inceptionYear> + + <developers> + <developer> + <name>Eric Chatellier</name> + <id>echatellier</id> + <email>chatellier@codelutin.com + </email> + <organization>CodeLutin</organization> + <timezone>+2</timezone> + <roles> + <role>Développeur</role> + </roles> + </developer> + <developer> + <name>Tony Chemit</name> + <id>tchemit</id> + <email>chemit@codelutin.com + </email> + <organization>CodeLutin</organization> + <timezone>+2</timezone> + <roles> + <role>Développeur</role> + </roles> + </developer> + </developers> + + <!-- ************************************************************* --> + <!-- *** Build Settings ****************************************** --> + <!-- ************************************************************* --> + <packaging>jar</packaging> + + <build> + + <plugins> + <plugin> + <groupId>org.codehaus.plexus</groupId> + <artifactId>plexus-maven-plugin</artifactId> + <version>1.3.8</version> + <executions> + <execution> + <goals> + <goal>descriptor</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + +</project> Added: branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/license/THIRD-PARTY.properties =================================================================== --- branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/license/THIRD-PARTY.properties (rev 0) +++ branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/license/THIRD-PARTY.properties 2012-06-05 14:44:35 UTC (rev 696) @@ -0,0 +1,33 @@ +# Generated by org.codehaus.mojo.license.AddThirdPartyMojo +#------------------------------------------------------------------------------- +# Already used licenses in project : +# - Apache License +# - BSD License +# - BSD style +# - Bouncy Castle Licence +# - Bouncy Castle License +# - COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 +# - Common Public License Version 1.0 +# - GNU Lesser General Public License (LGPL), version 2.1 +# - Indiana University Extreme! Lab Software License, vesion 1.1.1 +# - Lesser General Public License (LGPL) v 3.0 +# - Lesser General Public License (LPGL) +# - Lesser General Public License (LPGL) v 2.1 +# - MIT License +# - Mozilla Public License +# - Mozilla Public License Version 1.0 +# - The Apache Software License, Version 2.0 +# - The Jython License +# - The Werken Company License +# - X License (http://icu-project.org/repos/icu/icu4j/trunk/main/shared/licenses/license.ht...) +# - http://classworlds.codehaus.org/license.html +#------------------------------------------------------------------------------- +# Please fill the missing licenses for dependencies : +# +# +#Fri May 25 10:28:45 CEST 2012 +com.ibm.icu--icu4j--2.6.1=X License (http\://icu-project.org/repos/icu/icu4j/trunk/main/shared/licenses/license.html) +commons-primitives--commons-primitives--1.0=The Apache Software License, Version 2.0 +dom4j--dom4j--1.6.1=BSD +jdom--jdom--1.0=The Apache Software License, Version 2.0 +org.codehaus.plexus--plexus-classworlds--1.2-alpha-9=http\://classworlds.codehaus.org/license.html Added: branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/main/java/org/nuiton/jrst/JrstParser.java =================================================================== --- branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/main/java/org/nuiton/jrst/JrstParser.java (rev 0) +++ branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/main/java/org/nuiton/jrst/JrstParser.java 2012-06-05 14:44:35 UTC (rev 696) @@ -0,0 +1,75 @@ +/* + * #%L + * JRst :: Doxia module + * + * $Id: JrstParser.java 685 2012-05-29 15:37:18Z jpages $ + * $HeadURL: http://svn.nuiton.org/svn/jrst/branches/jrst-docutils-jython/doxia-module-jr... $ + * %% + * Copyright (C) 2009 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jrst; + +import java.io.File; +import java.io.FileWriter; +import java.io.Reader; +import java.io.StringReader; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.maven.doxia.module.xdoc.XdocParser; +import org.apache.maven.doxia.parser.ParseException; +import org.apache.maven.doxia.sink.Sink; +import org.codehaus.plexus.util.IOUtil; +import org.dom4j.Document; + +/** + * Parse an RST model, transform it into xdoc model and emit events into the + * specified doxia Sink. + * + * @author <a href="mailto:chatellier@codelutin.com">Eric Chatellier</a> + * @version $Id: JrstParser.java 685 2012-05-29 15:37:18Z jpages $ + * @since 0.9.0 + * @plexus.component role="org.apache.maven.doxia.parser.Parser" role-hint="jrst" + */ +public class JrstParser extends XdocParser { + + @Override + public void parse(Reader source, Sink sink) throws ParseException { + + try { + // Write the source in a file to use it with JRST + File sourceFile = File.createTempFile("source",".rst"); + FileWriter fileWriter = new FileWriter(sourceFile); + IOUtil.copy(source, fileWriter); + + // Simple generation of the xml file + Document doc = JRST.generateSimpleDoc(sourceFile, JRST.UTF_8); + + // Application of xsl stylesheets + doc = JRST.generateXml(doc, JRST.TYPE_XDOC); + + // Give xsl result to XDoc parser + Reader reader = new StringReader(doc.asXML()); + super.parse(reader, sink); + } catch (Exception e) { + throw new ParseException("Can't parse rst file", e); + } + + } +} Added: branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/main/java/org/nuiton/jrst/JrstSiteModule.java =================================================================== --- branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/main/java/org/nuiton/jrst/JrstSiteModule.java (rev 0) +++ branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/main/java/org/nuiton/jrst/JrstSiteModule.java 2012-06-05 14:44:35 UTC (rev 696) @@ -0,0 +1,54 @@ +/* + * #%L + * JRst :: Doxia module + * + * $Id: JrstSiteModule.java 608 2011-08-18 09:25:35Z tchemit $ + * $HeadURL: http://svn.nuiton.org/svn/jrst/branches/jrst-docutils-jython/doxia-module-jr... $ + * %% + * Copyright (C) 2009 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jrst; + +import org.apache.maven.doxia.module.site.AbstractSiteModule; + +/** + * JrstSiteModule. + * + * @author <a href="mailto:chatellier@codelutin.com">Eric Chatellier</a> + * @version $Id: JrstSiteModule.java 608 2011-08-18 09:25:35Z tchemit $ + * @since 0.9.0 + * @plexus.component role="org.apache.maven.doxia.module.site.SiteModule" role-hint="jrst" + */ +public class JrstSiteModule extends AbstractSiteModule { + + @Override + public String getSourceDirectory() { + return "rst"; + } + + @Override + public String getExtension() { + return "rst"; + } + + @Override + public String getParserId() { + return "jrst"; + } +} Added: branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/site/apt/devel.apt =================================================================== --- branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/site/apt/devel.apt (rev 0) +++ branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/site/apt/devel.apt 2012-06-05 14:44:35 UTC (rev 696) @@ -0,0 +1,35 @@ +~~~ +~~ #%L +~~ JRst :: Doxia module +~~ +~~ $Id: devel.apt 608 2011-08-18 09:25:35Z tchemit $ +~~ $HeadURL: http://svn.nuiton.org/svn/jrst/branches/jrst-docutils-jython/doxia-module-jr... $ +~~ %% +~~ Copyright (C) 2009 - 2010 CodeLutin +~~ %% +~~ This program is free software: you can redistribute it and/or modify +~~ it under the terms of the GNU Lesser General Public License as +~~ published by the Free Software Foundation, either version 3 of the +~~ License, or (at your option) any later version. +~~ +~~ This program is distributed in the hope that it will be useful, +~~ but WITHOUT ANY WARRANTY; without even the implied warranty of +~~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +~~ GNU General Lesser Public License for more details. +~~ +~~ You should have received a copy of the GNU General Lesser Public +~~ License along with this program. If not, see +~~ <http://www.gnu.org/licenses/lgpl-3.0.html>. +~~ #L% +~~~ + + ------------- + Documentation + ------------- + +Documentation + + JRst doxia module, is inherited from {{{http://maven.apache.org/doxia/doxia-1.0.x/doxia-modules/doxia-module-xdoc/index.html}doxia-module-xdoc}}. + + It just intercept xdoc parser call, transform RST into xdoc, and + then send generated xdoc to XDoc parser. \ No newline at end of file Added: branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/site/apt/index.apt =================================================================== --- branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/site/apt/index.apt (rev 0) +++ branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/site/apt/index.apt 2012-06-05 14:44:35 UTC (rev 696) @@ -0,0 +1,47 @@ +~~~ +~~ #%L +~~ JRst :: Doxia module +~~ +~~ $Id: index.apt 608 2011-08-18 09:25:35Z tchemit $ +~~ $HeadURL: http://svn.nuiton.org/svn/jrst/branches/jrst-docutils-jython/doxia-module-jr... $ +~~ %% +~~ Copyright (C) 2009 - 2010 CodeLutin +~~ %% +~~ This program is free software: you can redistribute it and/or modify +~~ it under the terms of the GNU Lesser General Public License as +~~ published by the Free Software Foundation, either version 3 of the +~~ License, or (at your option) any later version. +~~ +~~ This program is distributed in the hope that it will be useful, +~~ but WITHOUT ANY WARRANTY; without even the implied warranty of +~~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +~~ GNU General Lesser Public License for more details. +~~ +~~ You should have received a copy of the GNU General Lesser Public +~~ License along with this program. If not, see +~~ <http://www.gnu.org/licenses/lgpl-3.0.html>. +~~ #L% +~~~ + + ----------------- + Doxia Module JRst + ----------------- + +Configuration + +-------------------------------------------------- + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-site-plugin</artifactId> + <version>2.0</version> + <dependencies> + <dependency> + <groupId>org.nuiton.jrst</groupId> + <artifactId>doxia-module-jrst</artifactId> + <version>1.0.0</version> + </dependency> + </dependencies> + </plugin> +-------------------------------------------------- + + Ensuite vous avez plus qu'à lancer la commande mvn site \ No newline at end of file Added: branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/site/en/apt/devel.apt =================================================================== --- branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/site/en/apt/devel.apt (rev 0) +++ branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/site/en/apt/devel.apt 2012-06-05 14:44:35 UTC (rev 696) @@ -0,0 +1,35 @@ +~~~ +~~ #%L +~~ JRst :: Doxia module +~~ +~~ $Id: devel.apt 608 2011-08-18 09:25:35Z tchemit $ +~~ $HeadURL: http://svn.nuiton.org/svn/jrst/branches/jrst-docutils-jython/doxia-module-jr... $ +~~ %% +~~ Copyright (C) 2009 - 2010 CodeLutin +~~ %% +~~ This program is free software: you can redistribute it and/or modify +~~ it under the terms of the GNU Lesser General Public License as +~~ published by the Free Software Foundation, either version 3 of the +~~ License, or (at your option) any later version. +~~ +~~ This program is distributed in the hope that it will be useful, +~~ but WITHOUT ANY WARRANTY; without even the implied warranty of +~~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +~~ GNU General Lesser Public License for more details. +~~ +~~ You should have received a copy of the GNU General Lesser Public +~~ License along with this program. If not, see +~~ <http://www.gnu.org/licenses/lgpl-3.0.html>. +~~ #L% +~~~ + + ------------- + Documentation + ------------- + +Documentation + + JRst doxia module, is inherited from {{{http://maven.apache.org/doxia/doxia-1.0.x/doxia-modules/doxia-module-xdoc/index.html}doxia-module-xdoc}}. + + It just intercept xdoc parser call, transform RST into xdoc, and + then send generated xdoc to XDoc parser. \ No newline at end of file Added: branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/site/en/apt/index.apt =================================================================== --- branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/site/en/apt/index.apt (rev 0) +++ branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/site/en/apt/index.apt 2012-06-05 14:44:35 UTC (rev 696) @@ -0,0 +1,52 @@ +~~~ +~~ #%L +~~ JRst :: Doxia module +~~ +~~ $Id: index.apt 608 2011-08-18 09:25:35Z tchemit $ +~~ $HeadURL: http://svn.nuiton.org/svn/jrst/branches/jrst-docutils-jython/doxia-module-jr... $ +~~ %% +~~ Copyright (C) 2009 - 2010 CodeLutin +~~ %% +~~ This program is free software: you can redistribute it and/or modify +~~ it under the terms of the GNU Lesser General Public License as +~~ published by the Free Software Foundation, either version 3 of the +~~ License, or (at your option) any later version. +~~ +~~ This program is distributed in the hope that it will be useful, +~~ but WITHOUT ANY WARRANTY; without even the implied warranty of +~~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +~~ GNU General Lesser Public License for more details. +~~ +~~ You should have received a copy of the GNU General Lesser Public +~~ License along with this program. If not, see +~~ <http://www.gnu.org/licenses/lgpl-3.0.html>. +~~ #L% +~~~ + + ----------------- + Doxia Module JRst + ----------------- + +Configuration + +-------------------------------------------------- + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-site-plugin</artifactId> + <version>2.0</version> + <dependencies> + <dependency> + <groupId>org.nuiton</groupId> + <artifactId>doxia-module-jrst</artifactId> + <version>1.1.0</version> + </dependency> + </dependencies> + </plugin> +-------------------------------------------------- + + That it ! Then run "mvn site". + + +Warning + + This version only works with doxia-1.0.x (provided by maven-site-plugin-2.0). \ No newline at end of file Added: branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/site/site_en.xml =================================================================== --- branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/site/site_en.xml (rev 0) +++ branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/site/site_en.xml 2012-06-05 14:44:35 UTC (rev 696) @@ -0,0 +1,89 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JRst :: Doxia module + + $Id: site_en.xml 679 2012-05-29 08:02:04Z jpages $ + $HeadURL: http://svn.nuiton.org/svn/jrst/branches/jrst-docutils-jython/doxia-module-jr... $ + %% + Copyright (C) 2009 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<project name="${project.name}"> + + <bannerLeft> + <name>${project.name}</name> + <href>/</href> + </bannerLeft> + + <body> + + <breadcrumbs> + <item name="${project.name}" href="index.html"/> + </breadcrumbs> + + <links> + <item name="[fr" href="../index.html"/> + <item name="en]" href="index.html"/> + </links> + + <menu name="Project Parent"> + <item name="JRst" href="../../en/index.html"/> + </menu> + + <menu name="User"> + <item href="/index.html" name="About"/> + </menu> + + <menu name="Developer"> + <item href="/devel.html" name="Documentation"/> + </menu> + + <menu name="Community"> + <item name="Bugtracker" href="http://nuiton.org/projects/jrst/issues"/> + <item name="Roadmap" href="http://nuiton.org/projects/roadmap/jrst"/> + <item name="Downloads" href="http://nuiton.org/projects/jrst/files"/> + <item name="Continuous integration" + href="http://hudson.nuiton.org/hudson/job/jrst"/> + <item name="Code analysis" + href="http://sonar.nuiton.org/sonar/project/index/org.nuiton:jrst"/> + </menu> + + <menu ref="reports"/> + + <footer> + + <script type="text/javascript" + src="http://maven-site.nuiton.org/public/js/maven-site-nuiton.org.js"> + </script> + + <div id='projectMetas' + projectversion='${project.version}' + platform='${project.platform}' + projectid='${project.projectId}' + scm='${project.scm.connection}' + scmwebeditorenabled='${project.scmwebeditorEnabled}' + scmwebeditorurl='${project.scmwebeditorUrl}' + siteSourcesType='${project.siteSourcesType}' + piwikEnabled='${project.piwikEnabled}' + piwikId='${project.piwikId}'> + </div> + </footer> + + </body> +</project> Added: branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/site/site_fr.xml =================================================================== --- branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/site/site_fr.xml (rev 0) +++ branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/site/site_fr.xml 2012-06-05 14:44:35 UTC (rev 696) @@ -0,0 +1,89 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + #%L + JRst :: Doxia module + + $Id: site_fr.xml 679 2012-05-29 08:02:04Z jpages $ + $HeadURL: http://svn.nuiton.org/svn/jrst/branches/jrst-docutils-jython/doxia-module-jr... $ + %% + Copyright (C) 2009 - 2010 CodeLutin + %% + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Lesser Public License for more details. + + You should have received a copy of the GNU General Lesser Public + License along with this program. If not, see + <http://www.gnu.org/licenses/lgpl-3.0.html>. + #L% + --> + +<project name="${project.name}"> + + <bannerLeft> + <name>${project.name}</name> + <href>/</href> + </bannerLeft> + + <body> + + <breadcrumbs> + <item name="${project.name}" href="${project.url}"/> + </breadcrumbs> + + <links> + <item name="[fr" href="index.html"/> + <item name="en]" href="en/index.html"/> + </links> + + <menu ref="parent"/> + + <menu name="Utilisateur"> + <item href="/index.html" name="A propos"/> + </menu> + + <menu name="Developpeur"> + <item href="/devel.html" name="Documentation"/> + </menu> + + <menu name="Communauté"> + <item name="Suivi des bugs" + href="http://nuiton.org/projects/jrst/issues"/> + <item name="Roadmap" href="http://nuiton.org/projects/roadmap/jrst"/> + <item name="Téléchargements" + href="http://nuiton.org/projects/jrst/files"/> + <item name="Intégration continue" + href="http://hudson.nuiton.org/hudson/job/jrst"/> + <item name="Analyse du code" + href="http://sonar.nuiton.org/sonar/project/index/org.nuiton:jrst"/> + </menu> + + <menu ref="reports"/> + + <footer> + + <script type="text/javascript" + src="http://maven-site.nuiton.org/public/js/maven-site-nuiton.org.js"> + </script> + + <div id='projectMetas' + projectversion='${project.version}' + platform='${project.platform}' + projectid='${project.projectId}' + scm='${project.scm.connection}' + scmwebeditorenabled='${project.scmwebeditorEnabled}' + scmwebeditorurl='${project.scmwebeditorUrl}' + siteSourcesType='${project.siteSourcesType}' + piwikEnabled='${project.piwikEnabled}' + piwikId='${project.piwikId}'> + </div> + </footer> + + </body> +</project> Added: branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/test/java/org/nuiton/jrst/JrstParserTest.java =================================================================== --- branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/test/java/org/nuiton/jrst/JrstParserTest.java (rev 0) +++ branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/test/java/org/nuiton/jrst/JrstParserTest.java 2012-06-05 14:44:35 UTC (rev 696) @@ -0,0 +1,85 @@ +/* + * #%L + * JRst :: Doxia module + * + * $Id: JrstParserTest.java 675 2012-05-25 09:30:55Z sletellier $ + * $HeadURL: http://svn.nuiton.org/svn/jrst/branches/jrst-docutils-jython/doxia-module-jr... $ + * %% + * Copyright (C) 2009 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jrst; + +import java.io.Reader; +import java.io.StringWriter; +import org.apache.maven.doxia.AbstractModuleTest; +import org.apache.maven.doxia.module.xdoc.XdocSink; +import org.apache.maven.doxia.parser.Parser; +import org.apache.maven.doxia.sink.Sink; + +/** + * @author chatellier + * @version $Revision : 1$ + */ +public class JrstParserTest extends AbstractModuleTest { + + protected JrstParser parser; + + @Override + protected void setUp() throws Exception { + super.setUp(); + + parser = (JrstParser) lookup(Parser.ROLE, "jrst"); + } + + public void testParse() throws Exception { + StringWriter output = null; + Reader reader = null; + + try { + output = new StringWriter(); + reader = getTestReader("test", "rst"); + + Sink sink = new XdocSink(output){}; + parser.parse(reader, sink); + + assertTrue(output.toString().contains("emphasis")); + assertTrue(output.toString().contains("This is the first item")); + assertTrue(output.toString().contains("Title")); + assertTrue(output.toString().contains("blocks.")); + } finally { + if (output != null) { + output.close(); + } + if (reader != null) { + reader.close(); + } + } + } + + @Override + protected String outputExtension() { + return "rst"; + } + + @Override + protected String getOutputDir(){ + return "parser/"; + } + +} Added: branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/test/resources/test.rst =================================================================== --- branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/test/resources/test.rst (rev 0) +++ branches/jrst-docutils-jython/doxia-module-jrst-legacy/src/test/resources/test.rst 2012-06-05 14:44:35 UTC (rev 696) @@ -0,0 +1,79 @@ +.. - +.. * #%L +.. * JRst :: Doxia module +.. * +.. * $Id: test.rst 608 2011-08-18 09:25:35Z tchemit $ +.. * $HeadURL: http://svn.nuiton.org/svn/jrst/branches/jrst-docutils-jython/doxia-module-jr... $ +.. * %% +.. * Copyright (C) 2009 - 2010 CodeLutin +.. * %% +.. * This program is free software: you can redistribute it and/or modify +.. * it under the terms of the GNU Lesser General Public License as +.. * published by the Free Software Foundation, either version 3 of the +.. * License, or (at your option) any later version. +.. * +.. * This program is distributed in the hope that it will be useful, +.. * but WITHOUT ANY WARRANTY; without even the implied warranty of +.. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +.. * GNU General Lesser Public License for more details. +.. * +.. * You should have received a copy of the GNU General Lesser Public +.. * License along with this program. If not, see +.. * <http://www.gnu.org/licenses/lgpl-3.0.html>. +.. * #L% +.. - +.. comment + +Title +===== + +.. comment2 + +Subtitle +-------- + +*emphasis* + +**strong emphasis** + +`interpreted text` + +``inline literal`` + +http://docutils.sf.net/ + ++------------+------------+-----------+ +| Header 1 | Header 2 | Header 3 | ++============+============+===========+ +| body row 1 | column 2 | column 3 | ++------------+------------+-----------+ +| body row 2 | Cells may span columns.| ++------------+------------+-----------+ +| body row 3 | Cells may | - Cells | ++------------+ span rows. | - contain | +| body row 4 | | - blocks. | ++------------+------------+-----------+ + +:: + + Test + Sub test + + +Bullet lists: + +- This is item 1 +- This is item 2 + + +Enumerated lists: + +3. This is the first item +4. This is the second item +5. Enumerators are arabic numbers, + single letters, or roman numerals +6. List items should be sequentially + numbered, but need not start at 1 + (although not all formatters will + honour the first index). +#. This item is auto-enumerated \ No newline at end of file Deleted: branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/AdvancedReader.java =================================================================== --- branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/AdvancedReader.java 2012-06-04 16:16:06 UTC (rev 695) +++ branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/AdvancedReader.java 2012-06-05 14:44:35 UTC (rev 696) @@ -1,406 +0,0 @@ -/* - * #%L - * JRst :: Api - * - * $Id: AdvancedReader.java 601 2011-06-09 16:31:45Z kcardineaud $ - * $HeadURL: http://svn.nuiton.org/svn/jrst/branches/jrst-docutils-jython/jrst/src/main/j... $ - * %% - * Copyright (C) 2004 - 2010 CodeLutin - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package org.nuiton.jrst; - -import org.apache.commons.collections.primitives.ArrayCharList; -import org.apache.commons.collections.primitives.CharList; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.LineNumberReader; -import java.io.PushbackReader; -import java.io.Reader; -import java.util.ArrayList; - -/** - * Le principe est d'avoir dans cette classe le moyen de lire, et de retourner - * la ou on etait avant la lecture (mark et reset de {@link BufferedReader}). - * <p> - * Mais il faut aussi pouvoir dire qu'en fin de compte on ne souhaite pas lire - * les caracteres que l'on vient de lire ({@link #unread(int)} a peu pres egal a - * {@link PushbackReader}) - * <p> - * Le pointer nextChar pointe toujours sur le prochain caractere qui sera lu - * <p> - * Lorsque l'on appelle la method {@link #mark()} on vide aussi le buffer pour - * liberer de la place, car on a plus le moyen de retourner avant le mark que - * l'on vient de positionner. - * <p> - * On contraire du mark de {@link BufferedReader} ou {@link LineNumberReader} il - * n'y a pas a specifier le nombre de caractere a garder au maximum, seul la - * memoire nous limite. Du coup si l'on utilise cette classe sans mark, au final - * on aura dans le buffer tout le contenu du reader, il faut donc utiliser mark - * avec cette classe - * - * buffer - * - * <pre> - * ######################### - * 0 ˆ ˆ - * | | - * | + nextChar - * + markChar - * </pre> - * - * Created: 27 oct. 06 00:24:57 - * - * @author poussin - * @version $Revision: 601 $ - * - * Last update: $Date: 2011-06-09 18:31:45 +0200 (jeu. 09 juin 2011) $ - * by : $Author: kcardineaud $ - */ -public class AdvancedReader { - - /** le nombre d'espace pour remplacer les tabulations */ - protected static final String TAB = " "; - /** nombre de caractere lu au minimum sur le vrai reader */ - protected static final int READ_AHEAD = 80; - - protected Reader in; - protected CharList buffer; - - protected int charNumber; - protected int charNumberMark; - protected int lineNumber; - protected int lineNumberMark; - - protected int nextChar; - protected int markChar; - - protected int readInMark; - - protected boolean nlTwoCtrlChars = false; - protected boolean noNlAtEOF = false; - - /** - * - * @param in the io reader - */ - public AdvancedReader(Reader in) { - this.in = new LineNumberReader(in); - buffer = new ArrayCharList(); - } - - public void mark() throws IOException { - markChar = nextChar; - charNumberMark = charNumber; - lineNumberMark = lineNumber; - - free(markChar); - } - - public void reset() throws IOException { - nextChar = markChar; - charNumber = charNumberMark; - lineNumber = lineNumberMark; - - } - - public int readSinceMark() { - return nextChar - markChar; - } - - /** - * @return the charNumber - */ - public int getCharNumber() { - return charNumber; - } - - /** - * @return the lineNumber - */ - public int getLineNumber() { - return lineNumber; - } - - /** - * remove number of char in buffer - * - * @param number - * @return the real number of char removed from the head of buffer - * @throws IOException - */ - private int free(int number) throws IOException { - // fill(number); - int result = Math.min(buffer.size(), number); - buffer.subList(0, result).clear(); - - nextChar -= result; - markChar -= result; - - return result; - } - - /** - * ensure that have number char available and not already read - * - * @param number ? - * @throws IOException - */ - private void fill(int number) throws IOException { - int needed = nextChar + number - buffer.size(); - if (needed > 0) { - char[] cbuf = new char[needed + READ_AHEAD]; - int read = in.read(cbuf); - if (read != -1) { - for (int i = 0; i < read; i++) { - buffer.add(cbuf[i]); - } - } - } - } - - public boolean eof() throws IOException { - boolean result = -1 == read(); - if (!result) { - unread(1); - } - return result; - } - - public int skip(int number) throws IOException { - int result = 0; - while (result < number && read() != -1) { - result++; - } - return result; - } - - /** - * Add a character at the current position - * @param character that you want to add - */ - public void add(char character) { - buffer.add(nextChar,character); - } - - - /** - * go left in reading char buffer - * - * @param number - * @return realy unread char number - */ - public int unread(int number) { - int result = Math.min(number, nextChar); - - nextChar -= result; - charNumber -= result; - for (int i = nextChar; i < nextChar + result; i++) { - if (buffer.get(i) == '\n' || (buffer.get(i) == '\r' && i + 1 < nextChar + result && buffer.get(i + 1) != '\n')) { - lineNumber--; - } - } - - return result; - } - - /** - * Unread the line length - * - * @param line - * line used to know the length to unread - * @param addNewLine - * if true then add +1 to unread lenght for not present '\n' - * @return number of unread char - */ - public int unread(String line, boolean addNewLine) { - int result = unread(line.length() + (addNewLine ? (nlTwoCtrlChars ? 2 : 1) : 0)); - return result; - } - - /** - * Unread the line length - * - * @param lines - * lines used to know the length to unread - * @param addNewLine - * if true then add +1 for each line to unread lenght for not - * present '\n' - * @return number of unread char - */ - public int unread(String[] lines, boolean addNewLine) { - int result = 0; - for (String line : lines) { - result += unread(line, addNewLine); - } - return result; - } - - /** - * read one char in buffer - * - * @return the next char - * @throws IOException pour tout pb de lecture - */ - public int read() throws IOException { - fill(1); - int result = -1; - if (nextChar < buffer.size()) { - result = buffer.get(nextChar++); - charNumber++; - if ((char)result == '\n' || ((char)result == '\r' && nextChar < buffer.size() && buffer.get(nextChar) != '\n')) { - lineNumber++; - } - } - return result; - } - - /** - * read one line - * - * @return one line without '\n' or null if end of file - * @throws IOException pour tout pb de lecture - */ - public String readLine() throws IOException { - StringBuffer result = new StringBuffer(READ_AHEAD); - int c = read(); - while (c != -1 && c != '\n' && c != '\r') { - result.append((char) c); - c = read(); - } - nlTwoCtrlChars = false; - if (c == '\r') { - c = read(); - if (c != '\n' && c != -1) { - unread(1); - } else { - nlTwoCtrlChars = true; - } - } - noNlAtEOF = false; - if (c == -1 && result.length() >= 0) { - if (c == -1 && result.length() == 0) { - return null; - } else { - noNlAtEOF = true; - return result.toString(); - } - } else { - return result.toString(); - } - } - - - - - /** - * passe les lignes blanches - * - * @throws IOException - */ - public void skipBlankLines() throws IOException { - readUntil("^\\s*\\S+.*"); - } - - /** - * lit toutes les lignes du fichier - * - * @return toutes les lignes du fichier - * @throws IOException pour tout pb de lecture - */ - String[] readAll() throws IOException { - String[] result = readLines(-1); - return result; - } - - /** - * lit un certain nombre de lignes - * - * @param count - * si negatif lit toutes les lignes - * @return un certain nombre de lignes - * @throws IOException pour tout pb de lecture - */ - public String[] readLines(int count) throws IOException { - ArrayList<String> result = new ArrayList<String>(); - - String tmp = ""; - for (int i = count; tmp != null && i != 0; i--) { - tmp = readLine(); - if (tmp != null) { - result.add(tmp); - } - } - return result.toArray(new String[result.size()]); - } - - /** - * lit les lignes jusqu'a la premiere ligne blanche (non retournée) - * - * @return toutes les ligne jusqu'à la première ligne blanche (non incluse) - * @throws IOException pour tout pb de lecture - */ - public String[] readUntilBlank() throws IOException { - String[] result = readUntil("\\s*"); - return result; - } - - /** - * lit les lignes jusqu'a la ligne qui correspond pas au pattern, cette - * ligne n'est pas mise dans le resultat retourne - * - * @param pattern ? - * @return les lignes jusqu'a la ligne qui correspond pas au pattern, cette - * ligne n'est pas mise dans le resultat retourne - * @throws IOException pour tout pb de lecture - */ - public String[] readUntil(String pattern) throws IOException { - ArrayList<String> result = new ArrayList<String>(); - String tmp = readLine(); - while (tmp != null && !tmp.matches(pattern)) { - result.add(tmp); - tmp = readLine(); - } - if (tmp != null) { - unread(tmp.length() + (!noNlAtEOF ? (nlTwoCtrlChars ? 2 : 1) : 0)); // +1 for '\n' not in line - } - return result.toArray(new String[result.size()]); - } - - /** - * lit les lignes tant que les lignes correspondent au pattern - * - * @param pattern ? - * @return les lignes tant que les lignes correspondent au pattern - * @throws IOException pour tout pb de lecture - */ - public String[] readWhile(String pattern) throws IOException { - ArrayList<String> result = new ArrayList<String>(); - String tmp = readLine(); - while (tmp != null && tmp.matches(pattern)) { - result.add(tmp); - tmp = readLine(); - } - if (tmp != null) { - unread(tmp.length() + (!noNlAtEOF ? (nlTwoCtrlChars ? 2 : 1) : 0)); // +1 for '\n' not in line - } - return result.toArray(new String[result.size()]); - } - -} Deleted: branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/DocumentHandler.java =================================================================== --- branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/DocumentHandler.java 2012-06-04 16:16:06 UTC (rev 695) +++ branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/DocumentHandler.java 2012-06-05 14:44:35 UTC (rev 696) @@ -1,55 +0,0 @@ -/* - * #%L - * JRst :: Api - * - * $Id$ - * $HeadURL$ - * %% - * Copyright (C) 2004 - 2010 CodeLutin - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package org.nuiton.jrst; - -import org.dom4j.Document; -import org.dom4j.Element; -import org.dom4j.Text; - -/** - * DocumentHandler.java - * - * Created: 30 oct. 06 10:22:52 - * - * @author poussin - * @version $Revision$ - * - * Last update: $Date$ - * by : $Author$ - */ -public interface DocumentHandler { - - void startDocument(Document doc); - - void endDocument(Document doc); - - void startElement(Element e); - - void endElement(Element e); - - void text(Text t); - -} Deleted: branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/DocumentWalker.java =================================================================== --- branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/DocumentWalker.java 2012-06-04 16:16:06 UTC (rev 695) +++ branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/DocumentWalker.java 2012-06-05 14:44:35 UTC (rev 696) @@ -1,85 +0,0 @@ -/* - * #%L - * JRst :: Api - * - * $Id$ - * $HeadURL$ - * %% - * Copyright (C) 2004 - 2010 CodeLutin - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package org.nuiton.jrst; - -import java.util.List; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.dom4j.Document; -import org.dom4j.Element; -import org.dom4j.Node; -import org.dom4j.Text; - -/** - * DocumentWalker. - * - * Created: 30 oct. 06 10:28:10 - * - * @author poussin - * @version $Revision$ - * - * Last update: $Date$ - * by : $Author$ - */ -public class DocumentWalker { - - static private Log log = LogFactory.getLog(DocumentWalker.class); - - protected DocumentHandler handler; - - /** - * - */ - public DocumentWalker(DocumentHandler handler) { - this.handler = handler; - } - - public void walk(Document doc) { - handler.startDocument(doc); - Element elem = doc.getRootElement(); - walk(elem); - handler.endDocument(doc); - } - - public void walk(Element elem) { - handler.startElement(elem); - for (Node node : (List<Node>) elem.content()) { - switch (node.getNodeType()) { - case Node.ELEMENT_NODE: - walk((Element) node); - break; - case Node.TEXT_NODE: - handler.text((Text) node); - break; - default: - log.warn("Not supported element type: " - + node.getNodeTypeName()); - break; - } - } - handler.endElement(elem); - } -} Modified: branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/JRST.java =================================================================== --- branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/JRST.java 2012-06-04 16:16:06 UTC (rev 695) +++ branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/JRST.java 2012-06-05 14:44:35 UTC (rev 696) @@ -55,6 +55,7 @@ import org.nuiton.i18n.init.ClassPathI18nInitializer; import org.nuiton.jrst.convertisor.DocUtils2RST; import org.nuiton.jrst.convertisor.DocUtilsVisitor; +import org.nuiton.jrst.legacy.JRSTReader; import org.nuiton.util.ApplicationConfig; import org.nuiton.util.Resource; import org.nuiton.util.StringUtil; @@ -266,7 +267,6 @@ return graph.getCmd(); } - /** * Transforms a Restructured Text (ReST) file to another type ( html, xdoc, pdf, etc... ) * @@ -307,6 +307,14 @@ } } + /** + * Transforms a restructured text file to a XML file using JRST parser (used with option --simple) + * + * @param fileIn Input restructured text file (.rst) + * @param encoding Output file encoding + * @return A document which contains XML code + * @throws Exception + */ public static Document generateSimpleDoc(File fileIn, String encoding) throws Exception { URL url = fileIn.toURI().toURL(); Reader in = new InputStreamReader(url.openStream(), encoding); Modified: branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/JRSTGenerator.java =================================================================== --- branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/JRSTGenerator.java 2012-06-04 16:16:06 UTC (rev 695) +++ branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/JRSTGenerator.java 2012-06-05 14:44:35 UTC (rev 696) @@ -45,45 +45,47 @@ import org.dom4j.Text; import org.dom4j.io.DocumentResult; import org.dom4j.io.DocumentSource; +import org.nuiton.jrst.legacy.DocumentHandler; +import org.nuiton.jrst.legacy.DocumentWalker; import org.nuiton.util.FasterCachedResourceResolver; import org.xml.sax.ContentHandler; -import static org.nuiton.jrst.ReStructuredText.ADDRESS; -import static org.nuiton.jrst.ReStructuredText.AUTHOR; -import static org.nuiton.jrst.ReStructuredText.AUTHORS; -import static org.nuiton.jrst.ReStructuredText.BULLET_LIST; -import static org.nuiton.jrst.ReStructuredText.CLASSIFIER; -import static org.nuiton.jrst.ReStructuredText.CONTACT; -import static org.nuiton.jrst.ReStructuredText.COPYRIGHT; -import static org.nuiton.jrst.ReStructuredText.DATE; -import static org.nuiton.jrst.ReStructuredText.DEFINITION; -import static org.nuiton.jrst.ReStructuredText.DEFINITION_LIST; -import static org.nuiton.jrst.ReStructuredText.DOCINFO; -import static org.nuiton.jrst.ReStructuredText.EMPHASIS; -import static org.nuiton.jrst.ReStructuredText.ENUMERATED_LIST; -import static org.nuiton.jrst.ReStructuredText.FIELD_BODY; -import static org.nuiton.jrst.ReStructuredText.FIELD_LIST; -import static org.nuiton.jrst.ReStructuredText.FIELD_NAME; -import static org.nuiton.jrst.ReStructuredText.LIST_ITEM; -import static org.nuiton.jrst.ReStructuredText.LITERAL; -import static org.nuiton.jrst.ReStructuredText.LITERAL_BLOCK; -import static org.nuiton.jrst.ReStructuredText.ORGANIZATION; -import static org.nuiton.jrst.ReStructuredText.PARAGRAPH; -import static org.nuiton.jrst.ReStructuredText.REVISION; -import static org.nuiton.jrst.ReStructuredText.SECTION; -import static org.nuiton.jrst.ReStructuredText.STATUS; -import static org.nuiton.jrst.ReStructuredText.STRONG; -import static org.nuiton.jrst.ReStructuredText.TABLE; -import static org.nuiton.jrst.ReStructuredText.TITLE; -import static org.nuiton.jrst.ReStructuredText.TITLE_CHAR; -import static org.nuiton.jrst.ReStructuredText.TRANSITION; -import static org.nuiton.jrst.ReStructuredText.VERSION; +import static org.nuiton.jrst.legacy.ReStructuredText.ADDRESS; +import static org.nuiton.jrst.legacy.ReStructuredText.AUTHOR; +import static org.nuiton.jrst.legacy.ReStructuredText.AUTHORS; +import static org.nuiton.jrst.legacy.ReStructuredText.BULLET_LIST; +import static org.nuiton.jrst.legacy.ReStructuredText.CLASSIFIER; +import static org.nuiton.jrst.legacy.ReStructuredText.CONTACT; +import static org.nuiton.jrst.legacy.ReStructuredText.COPYRIGHT; +import static org.nuiton.jrst.legacy.ReStructuredText.DATE; +import static org.nuiton.jrst.legacy.ReStructuredText.DEFINITION; +import static org.nuiton.jrst.legacy.ReStructuredText.DEFINITION_LIST; +import static org.nuiton.jrst.legacy.ReStructuredText.DOCINFO; +import static org.nuiton.jrst.legacy.ReStructuredText.EMPHASIS; +import static org.nuiton.jrst.legacy.ReStructuredText.ENUMERATED_LIST; +import static org.nuiton.jrst.legacy.ReStructuredText.FIELD_BODY; +import static org.nuiton.jrst.legacy.ReStructuredText.FIELD_LIST; +import static org.nuiton.jrst.legacy.ReStructuredText.FIELD_NAME; +import static org.nuiton.jrst.legacy.ReStructuredText.LIST_ITEM; +import static org.nuiton.jrst.legacy.ReStructuredText.LITERAL; +import static org.nuiton.jrst.legacy.ReStructuredText.LITERAL_BLOCK; +import static org.nuiton.jrst.legacy.ReStructuredText.ORGANIZATION; +import static org.nuiton.jrst.legacy.ReStructuredText.PARAGRAPH; +import static org.nuiton.jrst.legacy.ReStructuredText.REVISION; +import static org.nuiton.jrst.legacy.ReStructuredText.SECTION; +import static org.nuiton.jrst.legacy.ReStructuredText.STATUS; +import static org.nuiton.jrst.legacy.ReStructuredText.STRONG; +import static org.nuiton.jrst.legacy.ReStructuredText.TABLE; +import static org.nuiton.jrst.legacy.ReStructuredText.TITLE; +import static org.nuiton.jrst.legacy.ReStructuredText.TITLE_CHAR; +import static org.nuiton.jrst.legacy.ReStructuredText.TRANSITION; +import static org.nuiton.jrst.legacy.ReStructuredText.VERSION; /** * Cette classe contient plusieurs methodes pour générer, soit en utilisant une * feuille de style {@link #generate(Document, URL, Writer)}, soit un * {@link ContentHandler} avec {@link #generate(Document, ContentHandler)}, soit - * {@link DocumentHandler} avec {@link #generate(Document, ContentHandler)} ou + * {@link org.nuiton.jrst.legacy.DocumentHandler} avec {@link #generate(Document, ContentHandler)} ou * bien regénérer du RST avec {@link #generate(Document)} dans les deux derniers * cas il faut passer un {@link Writer} en parametre du constructeur. * <p> @@ -321,7 +323,7 @@ /* * (non-Javadoc) * - * @see org.nuiton.jrst.DocumentHandler#startDocument(org.dom4j.Document) + * @see org.nuiton.jrst.legacy.DocumentHandler#startDocument(org.dom4j.Document) */ @Override public void startDocument(Document doc) { @@ -330,7 +332,7 @@ /* * (non-Javadoc) * - * @see org.nuiton.jrst.DocumentHandler#endDocument(org.dom4j.Document) + * @see org.nuiton.jrst.legacy.DocumentHandler#endDocument(org.dom4j.Document) */ @Override public void endDocument(Document doc) { @@ -339,7 +341,7 @@ /* * (non-Javadoc) * - * @see org.nuiton.jrst.DocumentHandler#endElement(org.dom4j.Element) + * @see org.nuiton.jrst.legacy.DocumentHandler#endElement(org.dom4j.Element) */ @Override public void endElement(Element e) { @@ -443,7 +445,7 @@ /* * (non-Javadoc) * - * @see org.nuiton.jrst.DocumentHandler#startElement(org.dom4j.Element) + * @see org.nuiton.jrst.legacy.DocumentHandler#startElement(org.dom4j.Element) */ @Override public void startElement(Element e) { @@ -542,7 +544,7 @@ /* * (non-Javadoc) * - * @see org.nuiton.jrst.DocumentHandler#text(org.dom4j.Text) + * @see org.nuiton.jrst.legacy.DocumentHandler#text(org.dom4j.Text) */ @Override public void text(Text t) { Deleted: branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/JRSTLexer.java =================================================================== --- branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/JRSTLexer.java 2012-06-04 16:16:06 UTC (rev 695) +++ branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/JRSTLexer.java 2012-06-05 14:44:35 UTC (rev 696) @@ -1,2514 +0,0 @@ -/* - * #%L - * JRst :: Api - * - * $Id: JRSTLexer.java 623 2011-10-28 14:10:56Z sletellier $ - * $HeadURL: http://svn.nuiton.org/svn/jrst/branches/jrst-docutils-jython/jrst/src/main/j... $ - * %% - * Copyright (C) 2004 - 2010 CodeLutin - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package org.nuiton.jrst; - -import static org.nuiton.jrst.ReStructuredText.BLOCK_QUOTE; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.dom4j.DocumentHelper; -import org.dom4j.Element; - -import java.io.IOException; -import java.io.Reader; -import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Le principe est de positionner la mark du {@link AdvancedReader} lors du - * debut d'une methode peek*, puis a la fin de la methode de regarder le nombre - * de caractere utilisé pour la methode et de faire un reset. - * <p> - * Le nombre de caractere utilisé servira pour le remove lorsque l'utilisateur - * indiquera qu'il utilise l'element retourné, si l'utilisateur n'appelle pas - * remove alors il peut relire autant de fois qu'il veut le meme element, ou - * essayer d'en lire un autre. - * <p> - * Pour mettre en place ce mecanisme le plus simple est d'utiliser les methodes - * {@link JRSTLexer#beginPeek()} et {@link JRSTLexer#endPeek()} - * - * Created: 28 oct. 06 00:44:20 - * - * @author poussin, letellier - * @version $Revision: 623 $ - * - * Last update: $Date: 2011-10-28 16:10:56 +0200 (ven. 28 oct. 2011) $ - * by : $Author: sletellier $ - */ -public class JRSTLexer { - - /** to use log facility, just put in your code: log.info(\"...\"); */ - private static Log log = LogFactory.getLog(JRSTLexer.class); - - public static final String BULLET_CHAR = "*" + "+" + "-"/* - * + "\u2022" + - * "\u2023" + - * "\u2043" - */; - - public static final String TITLE_CHAR = "-=-~'`^+:!\"#$%&*,./;|?@\\_[\\]{}<>()"; - - public static final String DOCINFO_ITEM = "author|authors|organization|address|contact|version|revision|status|date|copyright"; - - public static final String ADMONITION_PATTERN = "admonition|attention|caution|danger|error|hint|important|note|tip|warning"; - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // Title Elements - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - public static final String TITLE = "title"; - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // Bibliographic Elements - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - public static final String DOCINFO = "docinfo"; - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // Decoration Elements - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - public static final String DECORATION = "decoration"; - - public static final String HEADER = "header"; - - public static final String FOOTER = "footer"; - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // Structural Elements - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - public static final String TRANSITION = "transition"; - - public static final String SIDEBAR = "sidebar"; - - public static final String TOPIC = "topic"; - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // Body Elements - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - static final public String LITERAL_BLOCK = "literal_block"; - - static final public String PARAGRAPH = "paragraph"; - - static final public String BLANK_LINE = "blankLine"; - - static final public String COMMENT = "comment"; - - static final public String SUBSTITUTION_DEFINITION = "substitution_definition"; - - static final public String BULLET_LIST = "bullet_list"; - - static final public String FIELD_LIST = "field_list"; - - static final public String DEFINITION_LIST = "definition_list"; - - static final public String ENUMERATED_LIST = "enumerated_list"; - - static final public String OPTION_LIST = "option_list"; - - public static final String LINE_BLOCK = "line_block"; - - public static final String LINE = "line"; - - public static final String ATTRIBUTION = "attribution"; - - public static final String DOCTEST_BLOCK = "doctest_block"; - - public static final String ADMONITION = "admonition"; - - public static final String TARGET = "target"; - - public static final String FOOTNOTE = "footnote"; - - public static final String FOOTNOTES = "footnotes"; - - public static final String LEVEL = "level"; - - public static final String TARGETANONYMOUS = "targetAnonymous"; - - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // Table Elements - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - static final public String TABLE = "table"; - - static final public String ROW = "row"; - - static final public String CELL = "cell"; - - static final public String TABLE_HEADER = "header"; - - static final public String TABLE_WIDTH = "width"; - - static final public String ROW_END_HEADER = "endHeader"; - - static final public String CELL_INDEX_START = "indexStart"; - - static final public String CELL_INDEX_END = "indexEnd"; - - static final public String CELL_BEGIN = "begin"; - - static final public String CELL_END = "end"; - - static final public String REMOVE = "remove"; - - static final public String INCLUDE = "include"; - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // Directive Elements - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - static final public String DIRECTIVE = "directive"; - - static final public String DIRECTIVE_TYPE = "type"; - - static final public String DIRECTIVE_VALUE = "value"; - - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // Attributs - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - static final public String AUTONUM = "autoNum"; - - static final public String AUTONUMLABEL = "autoNumLabel"; - - static final public String AUTOSYMBOL = "autoSymbol"; - - static final public String BULLET = "bullet"; - - static final public String CHAR = "char"; - - static final public String ID = "id"; - - static final public String CLASSIFIERS = "classifiers"; - - static final public String DELIMITER = "delimiter"; - - static final public String DELIMITEREXISTE ="delimiterExiste"; - - static final public String ENUMTYPE = "enumtype"; - - static final public String REFURI = "refuri"; - - static final public String OPTION = "option"; - - static final public String LITERAL = "literal"; - - static final public String NAME = "name"; - - static final public String NUM ="num"; - - static final public String OPTIONARGUMENT = "option_argument"; - - static final public String OPTIONSTRING = "option_string"; - - static final public String PREFIX = "prefix"; - - static final public String START = "start"; - - static final public String SUBEXISTE = "subExiste"; - - static final public String SUFFIX = "suffix"; - - static final public String SUBTITLE = "subtitle"; - - static final public String TERM = "term"; - - static final public String TITLEATTR = "title"; - - static final public String XMLSPACE = "xml:space"; - - static final public String TYPE = "type"; - - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - protected static final String TRUE = "true"; - - protected static final String FALSE = "false"; - - - /** - * retient le niveau du titre, pour un titre de type double, on met deux - * fois le caratere dans la chaine, sinon on le met une seul fois. - * - * <pre> - * ===== - * Super - * ===== - * titre - * ----- - * </pre> - * - * donnera dans la liste ["==", "-"] - */ - private List<String> titleLevels; - - private AdvancedReader in; - - /** - * length of the last element returned (number of char need to this element) - */ - private int elementLength; - - - - - public JRSTLexer(Reader reader) { - titleLevels = new ArrayList<String>(); - in = new AdvancedReader(reader); - } - - /** - * true if no more element to read - * - * @return boolean - * @throws IOException - */ - public boolean eof() throws IOException { - in.mark(); - in.skipBlankLines(); - boolean result = in.eof(); - in.reset(); - return result; - } - - /** - * remove one element from list of element already read - * - * @throws IOException - */ - public void remove() throws IOException { - in.skip(elementLength); - } - - /** - * start peek - * - * @throws IOException - */ - private void beginPeek() throws IOException { - elementLength = 0; - in.mark(); - } - - /** - * end peek - * - * @throws IOException - */ - private void endPeek() throws IOException { - elementLength = in.readSinceMark(); - in.reset(); - } - - /** - * Read block text, block text have same indentation and is continu (no - * blank line) - * - * @param minLeftMargin - * min left blank needed to accept to read block - * @return String[] - * @throws IOException - */ - private String[] readBlock(int minLeftMargin) throws IOException { - String[] result = new String[0]; - String firstLine = in.readLine(); - if (firstLine != null) { - in.unread(firstLine, true); - int level = level(firstLine); - if (level >= minLeftMargin) { - result = in.readWhile("^\\s{" + level + "}\\S+.*"); - } - } - - return result; - } - - /** - * All lines are joined and left and right spaces are removed during join - * - * @param String - * [] lines - * @return String - */ - private String joinBlock(String[] lines) { - String result = joinBlock(lines, " ", true); - return result; - } - - /** - * All lines are joined whith the String joinSep and left and right spaces - * are removed if trim - * - * @param String - * [] lines - * @param String - * joinSep - * @param Boolean - * trim - * @return String - */ - private String joinBlock(String[] lines, String joinSep, boolean trim) { - String result = ""; - String sep = ""; - for (String line : lines) { - if (trim) { - line = line.trim(); - } - result += sep + line; - sep = joinSep; - } - return result; - } - - /** - * search if the doc have an header - * - * <pre> - * .. header:: This space for rent. aaaa **aaaa** - * </pre> - * - * @return Element - * @throws IOException - */ - public Element peekHeader() throws IOException { - beginPeek(); - Element result = null; - String[] line = in.readAll(); - if (line != null) { - int i = 0; - for (String l : line) { - i++; - if (l.matches("^\\s*.. " + HEADER + ":: .*")) { - int level = level(l); - l = l.replaceAll("^\\s*.. " + HEADER + ":: ", ""); - result = DocumentHelper.createElement(HEADER).addAttribute( - LEVEL, String.valueOf(level)); - result.addAttribute(LINE, "" + i); - result.setText(l); - } - - } - } - endPeek(); - return result; - - } - - /** - * search if the doc have an header - * - * <pre> - * .. footer:: design by **LETELLIER Sylvain** - * </pre> - * - * @return Element - * @throws IOException - */ - public Element peekFooter() throws IOException { - beginPeek(); - Element result = null; - String[] line = in.readAll(); - if (line != null) { - int i = 0; - for (String l : line) { - i++; - - if (l.matches("^\\s*.. " + FOOTER + ":: .*")) { - int level = level(l); - l = l.replaceAll("^\\s*.. " + FOOTER + ":: ", ""); - result = DocumentHelper.createElement(FOOTER).addAttribute( - LEVEL, String.valueOf(level)); - result.addAttribute(LINE, "" + i); - result.setText(l); - } - } - } - endPeek(); - return result; - - } - - /** - * <pre> - * .. __: http://www.python.org - * </pre> - * - * @return Element - * @throws IOException - */ - public LinkedList<Element> peekTargetAnonymous() throws IOException { - beginPeek(); - LinkedList<Element> result = new LinkedList<Element>(); - String[] line = in.readAll(); - if (line != null) { - int i = 0; - for (String l : line) { - i++; - - if (l.matches("^\\s*__ .+$|^\\s*\\.\\. __\\:.+$")) { - log.debug(l); - Element resultTmp = DocumentHelper - .createElement(TARGETANONYMOUS); - resultTmp.addAttribute(LEVEL, "" + level(l)); - Matcher matcher = Pattern.compile("__ |.. __: ").matcher(l); - - if (matcher.find()) { - resultTmp.addAttribute(REFURI, l.substring(matcher - .end(), l.length())); - } - - result.add(resultTmp); - } - } - - } - endPeek(); - return result; - } - - /** - * Return title or para - * - * @return Element - * @throws IOException - */ - public Element peekTitleOrBodyElement() throws IOException { - Element result = null; - if (result == null) { - result = peekTitle(); - } - if (result == null) { - result = peekBodyElement(); - } - - return result; - } - - /** - * read doc info author, date, version, ... or field list element - * - * <pre> - * :author: Benjamin Poussin - * :address: - * Quelque part - * Dans le monde - * </pre> - * - * @return Element - * @throws IOException - */ - public Element peekDocInfo() throws IOException { - Element result = null; - if (result == null) { - result = peekDocInfoItem(); - - } - if (result == null) { - result = peekFieldList(); - } - - return result; - - } - - /** - * Return para - * - * @return Element - * @throws IOException - */ - public Element peekBodyElement() throws IOException { - Element result = null; - if (result == null) { - result = peekInclude(); - } - if (result == null) { - result = peekDoctestBlock(); - } - if (result == null) { - result = peekAdmonition(); - } - if (result == null) { - result = peekSidebar(); - } - if (result == null) { - result = peekTopic(); - } - if (result == null) { - result = peekRemove(); - } - if (result == null) { - result = peekDirectiveOrReference(); - } - if (result == null) { - result = peekTransition(); - } - if (result == null) { - result = peekTable(); - } - if (result == null) { - result = peekLineBlock(); - } - if (result == null) { - result = peekBulletList(); - } - if (result == null) { - result = peekOption(); - } - if (result == null) { - result = peekEnumeratedList(); - } - if (result == null) { - result = peekTarget(); - } - if (result == null) { - result = peekFootnote(); - } - // comment must be read after peekDirectiveOrReference() - // and peekFootnote() - if (result == null) { - result = peekComment(); - } - if (result == null) { - result = peekDefinitionList(); - } - if (result == null) { - result = peekFieldList(); - } - if (result == null) { - result = peekTargetAnonymousBody(); - } - if (result == null) { - result = peekLiteralBlock(); - } - if (result == null) { - result = peekBlockQuote(); - } - if (result == null) { - result = peekBlankLine(); - } - if (result == null) { - result = peekPara(); - } - - return result; - } - - /** - * Remove already read elements - * - * @return Element - * @throws IOException - */ - public Element peekRemove() throws IOException { - beginPeek(); - Element result = null; - String line = in.readLine(); - if (line != null) { - // Le header est parse des le debut - if (line.matches("^\\s*.. " + HEADER + ":: .*")) { - result = DocumentHelper.createElement(REMOVE).addAttribute( - LEVEL, "" + level(line)); - } - // Le footer - if (line.matches("^\\s*.. " + FOOTER + ":: .*")) { - result = DocumentHelper.createElement(REMOVE).addAttribute( - LEVEL, "" + level(line)); - } - - } - endPeek(); - return result; - } - - /** - * read include - * - * <pre> - * .. include:: text.txt - * or - * .. include:: literal - * text.txt - * - * </pre> - * - * @return Element - * @throws IOException - */ - private Element peekInclude() throws IOException { - beginPeek(); - Element result = null; - String line = in.readLine(); - if (line != null) { - if (line.matches("^\\s*\\.\\.\\sinclude\\:\\:.+$")) { - result = DocumentHelper.createElement(INCLUDE); - result.addAttribute(LEVEL, "" + level(line)); - String option = line.substring(line.indexOf("::") + 2).trim(); - result.addAttribute(OPTION, ""); - if (option.trim().equalsIgnoreCase(LITERAL)) { - result.addAttribute(OPTION, LITERAL); - line = in.readLine(); - result.setText(line.trim()); - } else { - result.setText(option); - } - - } - } - endPeek(); - return result; - } - - /** - * read options - * - * <pre> - * Ex : -a command-line option "a" - * -1 file, --one=file, --two file - * Multiple options with arguments. - * Schéma : ________________________________ - * v | | - * -{1,2}\w+ ->|',' | - * |'='-----|-> \w+ --->|',' - * |' '-----| |' '---+ - * |" " -----> \w+ ---> end | - * ˆ | - * |_________________________| - * Légende : - * - * -{1,2} --> 1 or 2 tirets - * \w+ -----> word characters one or more times - * </pre> - * - * @return Element - * @throws IOException - */ - public Element peekOption() throws IOException { - - beginPeek(); - Element result = null; - String line = in.readLine(); - if (line != null) { - if (line.matches("^(\\s*((--?)|(//?))\\w+([ =][<a-zA-Z][\\w-><]*)?)\\s*.*$")) { - result = DocumentHelper.createElement(OPTION_LIST) - .addAttribute(LEVEL, "" + level(line)); - char delimiter; - do { - Matcher matcher = Pattern.compile("[-/][-/]?.+").matcher(line); - matcher.find(); - Element option = result.addElement(OPTION); - String option_stringTmp = matcher.group(); - matcher = Pattern.compile("^[-/][-/]?\\w+").matcher(option_stringTmp); - matcher.find(); - String option_string = matcher.group(); - option.addAttribute(OPTIONSTRING, option_string); - - boolean done = false; - // Delimiteur bidon - delimiter = '.'; - if (option_stringTmp.length() > matcher.end()) { - delimiter = option_stringTmp.charAt(matcher.end()); - option_stringTmp = option_stringTmp.substring( - matcher.end(), option_stringTmp.length()); - } else { - done = true; - } - option.addAttribute(DELIMITEREXISTE, FALSE); - - if (delimiter == ' ') { // S'il y a 2 espaces a suivre, - // l'option est finie - if (option_stringTmp.charAt(1) == ' ') { - done = true; - } - } - String option_argument = null; - if ((delimiter == '=' || delimiter == ' ') && !done) { - option.addAttribute(DELIMITEREXISTE, TRUE); - option.addAttribute(DELIMITER, "" + delimiter); - matcher = Pattern.compile(delimiter + "(([a-zA-Z][\\w-]+)|(<[a-zA-Z][^>]*>))").matcher( - option_stringTmp); - if (matcher.find()) { - option_argument = matcher.group().substring(1, - matcher.group().length()); - option.addAttribute(OPTIONARGUMENT, option_argument); - int size = option_argument.length() + 1; - if (option_stringTmp.length() < size && option_stringTmp.charAt(size) == ',') { - delimiter = ','; - } else { - done = true; - } - } else { // Si la description n'est pas sur la meme - // ligne - option_argument = option_stringTmp; - option.addAttribute(OPTIONARGUMENT, - option_argument); - line = in.readLine(); - if (line != null) { - result.setText(line.trim()); - } - } - } - if (delimiter == ',') { - line = line.substring(option_string.length() + 1 - + (option_argument == null ? 0 : option_argument.length())); - } - if (done) { - result.setText(option_stringTmp.substring(matcher.end(), option_stringTmp.length()).trim() - + " " + joinBlock(readBlock(1))); - } - } while (delimiter == ','); - } - } - endPeek(); - return result; - } - - /** - * read topic - * - * <pre> - * -.. topic:: Title - * Body. - * </pre> - * - * @return Element - * @throws IOException - */ - private Element peekTopic() throws IOException { - beginPeek(); - Element result = null; - String line = in.readLine(); - if (line != null) { - if (line.matches("^\\.\\.\\s+(" + TOPIC + ")::\\s+(.*)$")) { - Matcher matcher = Pattern.compile(TOPIC + "::").matcher(line); - matcher.find(); - result = DocumentHelper.createElement(TOPIC).addAttribute( - LEVEL, "" + level(line)); - String title = line.substring(matcher.end(), line.length()); - result.addAttribute(TITLE, title); - line = in.readLine(); - if (line.matches("\\s*")) { - line = in.readLine(); - } - int level = level(line); - String[] lines = null; - if (level != 0) { - lines = in.readWhile("(^ {" + level + "}.*)|(\\s*)"); - String txt = line; - for (String txtTmp : lines) { - txt += "\n" + txtTmp.trim(); - } - result.setText(txt); - } - - } - } - - endPeek(); - return result; - } - - /** - * read sidebar - * - * <pre> - * .. sidebar:: Title - * :subtitle: If Desired - * Body. - * </pre> - * - * @return Element - * @throws IOException - */ - private Element peekSidebar() throws IOException { - beginPeek(); - Element result = null; - String line = in.readLine(); - if (line != null) { - if (line.matches("^\\.\\.\\s*(" + SIDEBAR + ")::\\s*(.*)$")) { - Matcher matcher = Pattern.compile(SIDEBAR + "::").matcher(line); - matcher.find(); - result = DocumentHelper.createElement(SIDEBAR).addAttribute( - LEVEL, "" + level(line)); - String title = line.substring(matcher.end(), line.length()); - result.addAttribute(TITLE, title); - line = in.readLine(); - if (line.matches("^\\s+:subtitle:\\s*(.*)$*")) { - matcher = Pattern.compile(":subtitle:\\s*").matcher(line); - matcher.find(); - String subTitle = line.substring(matcher.end(), line - .length()); - result.addAttribute(SUBEXISTE, TRUE); - result.addAttribute(SUBTITLE, subTitle); - line = in.readLine(); - } else { - result.addAttribute(SUBEXISTE, FALSE); - } - String txt = joinBlock(readBlock(level(line))); - result.setText(txt); - - } - } - - endPeek(); - return result; - } - - /** - * read line block - * - * <pre> - * | A one, two, a one two three four - * | - * | Half a bee, philosophically, - * | must, *ipso facto*, half not be. - * | But half the bee has got to be, - * | *vis a vis* its entity. D'you see? - * </pre> - * - * @return Element - * @throws IOException - */ - private Element peekLineBlock() throws IOException { - beginPeek(); - Element result = null; - String line = in.readLine(); - if (line != null) { - if (line.matches("\\|\\s.*")) { - String[] linesTmp = readBlock(0); - String[] lines = new String[linesTmp.length + 1]; - lines[0] = line; - for (int i = 0; i < linesTmp.length; i++) { - lines[i + 1] = linesTmp[i]; - } - int[] levelsTmp = new int[lines.length]; - int levelmin = 999; - result = DocumentHelper.createElement(LINE_BLOCK).addAttribute( - LEVEL, 0 + ""); - for (int i = 0; i < levelsTmp.length; i++) { - // on enleve | - lines[i] = lines[i].replaceAll("\\|\\s?", ""); - } - for (int i = 0; i < levelsTmp.length; i++) { - // determination des levels - levelsTmp[i] = level(lines[i]); - } - for (int i : levelsTmp) { - // level minimal - levelmin = Math.min(levelmin, i); - } - int cnt = 0; - String lineAv = ""; - int[] levels = new int[levelsTmp.length]; - for (String l : lines) { - if (!l.matches("\\s*")) { // Si la ligne courante n'est - // pas vide - int level = levelsTmp[cnt] - levelmin; - if (level != 0) { - if (cnt != 0) { - if (!lineAv.matches("\\s*")) { // Si la ligne - // d'avant n'est - // pas vide - int levelAv = levelsTmp[cnt - 1] - levelmin; - if (levelAv < level) { - levels[cnt] = levels[cnt - 1] + 1; - if (cnt != levels.length) { - int levelAp = levelsTmp[cnt + 1] - - levelmin; - if (levelAp < level - && levelAv < levelAp) { - levels[cnt]++; - } - } - } else { - levels[cnt] = levels[cnt - 1] - 1; - } - } else { - levels[cnt] = 1; - } - } else { - levels[cnt] = 1; - } - } else { - levels[cnt] = 0; - } - } else { - if (cnt != 0) { - levels[cnt] = levels[cnt - 1]; - } - else { - levels[cnt] = 0; - } - } - cnt++; - lineAv = l; - } - for (int i = 0; i < levels.length; i++) { - Element eLine = result.addElement(LINE); - eLine.addAttribute(LEVEL, "" + levels[i]); - eLine.setText(lines[i].trim()); - } - } - } - endPeek(); - return result; - } - - /** - * read doctest block - * - * <pre> - * >>> print 'this is a Doctest block' - * this is a Doctest block - * </pre> - * - * @return Element - * @throws IOException - */ - private Element peekDoctestBlock() throws IOException { - beginPeek(); - Element result = null; - String line = in.readLine(); - if (line != null) { - if (line.matches("^\\s*>>>\\s.*")) { - int level = level(line); - result = DocumentHelper.createElement(DOCTEST_BLOCK) - .addAttribute(LEVEL, String.valueOf(level)); - result.addAttribute(XMLSPACE, "preserve"); - line += "\n" + joinBlock(readBlock(level)); - result.setText(line); - } - } - endPeek(); - return result; - } - - /** - * read block quote - * - * <pre> - * As a great paleontologist once said, - * - * This theory, that is mine, is mine. - * - * -- Anne Elk (Miss) - * </pre> - * - * @return Element - * @throws IOException - */ - private Element peekBlockQuote() throws IOException { - beginPeek(); - Element result = null; - String line = in.readLine(); - if (line != null) { - if (line.matches("\\s.*")) { - int level = level(line); - String savedLine = line + " " + joinBlock(readBlock(level)); - line = in.readLine(); - - if (line != null) { - level = level(line); - String blockQuote = null; - if (level != 0) { - String txt = line; - String[] lines = in.readWhile("(^ {" + level - + "}.*)|(\\s*)"); - for (String l : lines) { - if (l.matches("^ {" + level + "}--\\s*.*")) { - blockQuote = l; - blockQuote = blockQuote.replaceAll("--", "") - .trim(); - } else { - txt += "\n" + l; - } - } - result = DocumentHelper.createElement(BLOCK_QUOTE) - .addAttribute(LEVEL, String.valueOf(level)); - if (blockQuote != null) { - result.addAttribute(ATTRIBUTION, blockQuote); - } - result.setText(savedLine + txt); - } - } - } - } - endPeek(); - return result; - } - - /** - * read admonitions : - * admonition|attention|caution|danger|error|hint|important|note|tip|warning - * - * <pre> - * .. Attention:: All your base are belong to us. - * .. admonition:: And, by the way... - * - * You can make up your own admonition too. - * </pre> - * - * @return Element - * @throws IOException - */ - protected Element peekAdmonition() throws IOException { - beginPeek(); - Element result = null; - String line = in.readLine(); - if (line != null) { - String lineTest = line.toLowerCase(); - Pattern pAdmonition = Pattern.compile("^\\s*\\.\\.\\s(" - + ADMONITION_PATTERN + ")::\\s*(.*)$"); - Matcher matcher = pAdmonition.matcher(lineTest); - - if (matcher.matches()) { - - boolean admonition = false; - matcher = Pattern.compile(ADMONITION_PATTERN).matcher(lineTest); - matcher.find(); - int level = level(line); - result = DocumentHelper.createElement(ADMONITION).addAttribute( - LEVEL, "" + level); - - if (matcher.group().equals(ADMONITION)) { // Il y a un titre - // pour un - // admonition - // general - admonition = true; - result.addAttribute(TYPE, ADMONITION); - String title = line.substring(matcher.end() + 2, line - .length()); - - result.addAttribute(TITLEATTR, title); - } else { - result.addAttribute(TYPE, matcher.group()); - } - - String firstLine = ""; - if (!admonition && matcher.end() + 2 < line.length()) { - firstLine = line - .substring(matcher.end() + 2, line.length()); - } - line = in.readLine(); - if (line != null) { - if (line.matches("\\s*")) { - line = in.readLine(); - } - if (line != null && !line.matches("\\s*")) { - level = level(line); - String txt = firstLine.trim() + "\n" + line + "\n"; - txt += "\n" + readBlockWithBlankLine(level); - result.setText(txt); - } else { - result.setText(firstLine); - } - } else { - result.setText(firstLine); - } - } - } - endPeek(); - return result; - } - - /** - * read blank line - * - * @return Element - * @throws IOException - */ - public Element peekBlankLine() throws IOException { - beginPeek(); - Element result = null; - - // must have one blank line before - String line = in.readLine(); - if (line != null && line.matches("\\s*")) { - int level = level(line); - result = DocumentHelper.createElement(BLANK_LINE).addAttribute( - LEVEL, String.valueOf(level)); - } - - endPeek(); - return result; - } - - /** - * read directive or reference - * - * @return Element - * @throws IOException - */ - public Element peekDirectiveOrReference() throws IOException { - beginPeek(); - Element result = null; - String line = in.readLine(); - if (line != null) { - Pattern pImage = Pattern - .compile("^\\.\\.\\s*(?:\\|([^|]+)\\|)?\\s*(\\w+)::\\s*(.*)$"); - Matcher matcher = pImage.matcher(line); - if (matcher.matches()) { - String ref = matcher.group(1); - String directiveType = matcher.group(2); - String directiveValue = matcher.group(3); - Element directive = null; - if (ref != null && !"".equals(ref)) { - result = DocumentHelper - .createElement(SUBSTITUTION_DEFINITION); - result.addAttribute(NAME, ref); - directive = result.addElement(DIRECTIVE); - } else { - result = DocumentHelper.createElement(DIRECTIVE); - directive = result; - } - result.addAttribute(LEVEL, "0"); - - directive.addAttribute(DIRECTIVE_TYPE, directiveType); - directive.addAttribute(DIRECTIVE_VALUE, directiveValue); - - String[] lines = readBlock(1); - String text = joinBlock(lines, "\n", false); - - directive.setText(text); - } - } - endPeek(); - return result; - } - - /** - * read transition - * - * @return Element - * @throws IOException - */ - public Element peekTransition() throws IOException { - beginPeek(); - - Element result = null; - // no eat blank line, see next comment - - // must have one blank line before - String line = in.readLine(); - if (line != null && line.matches("\\s*")) { - // in.skipBlankLines(); - line = in.readLine(); - if (line != null && line.matches("-{3,}\\s*")) { - line = in.readLine(); - // must have one blank line after - if (line != null && line.matches("\\s*")) { - result = DocumentHelper.createElement(TRANSITION) - .addAttribute(LEVEL, String.valueOf(0)); - } - } - } - endPeek(); - return result; - } - - /** - * read paragraph with attribut level that represente the space numbers at - * left side - * - * @return <paragraph level="[int]">[text]</paragraph> - * @throws IOException - */ - public Element peekPara() throws IOException { - beginPeek(); - - Element result = null; - // in.skipBlankLines(); - - String[] lines; - do { - lines = readBlock(0); - if (lines.length > 0) { - int level = level(lines[0]); - String para = joinBlock(lines); - - boolean literal = false; - if (para.endsWith(": ::")) { - para = para.substring(0, para.length() - " ::".length()); - - in.unread("::", true); - for(int i=0;i<level;i++) { - in.add(' '); - } - - literal = true; - } else if (para.endsWith("::")) { - para = para.substring(0, para.length() - ":".length()); // keep - // one - // : - - in.unread("::", true); - - for(int i=0;i<level;i++) { - in.add(' '); - } - - literal = true; - } - - if (para.length() == 0 || ":".equals(para)) { - if (literal) { - in.readLine(); // eat "::" - } - } else { - // if para is empty, there are error and possible - // infiny loop on para, force read next line - result = DocumentHelper.createElement(PARAGRAPH) - .addAttribute(LEVEL, String.valueOf(level)) - .addText(para); - } - } - } while (result == null && lines.length > 0); - - endPeek(); - return result; - } - - /** - * read literal block - * - * <pre> - * :: - * - * LiteralBlock - * </pre> - * - * @return Element - * @throws IOException - */ - public Element peekLiteralBlock() throws IOException { - beginPeek(); - - Element result = null; - // in.skipBlankLines(); - - - String[] prefix = in.readLines(2); - if (prefix.length == 2 && prefix[0].matches("\\s*::\\s*") - && prefix[1].matches("\\s*")) { - - int level = level(prefix[0]); - - String para = in.readLine(); - if (para != null) { - level=level+1; - para = para.substring(level) + "\n"; - - // it's literal block until level is down - String[] lines = in.readWhile("(^ {" + level + "}.*|\\s*)"); - while (lines.length > 0) { - for (String line : lines) { - if (!line.matches("\\s*")) { - para += line.substring(level) + "\n"; - } - else { - para += "\n"; - } - } - lines = in.readWhile("(^ {" + level + "}.*|\\s*)"); - } - - result = DocumentHelper.createElement(LITERAL_BLOCK) - .addAttribute(LEVEL, String.valueOf(level)).addText( - para); - } - } - - endPeek(); - return result; - } - - /** - * read doc info author, date, version, ... - * - * <pre> - * :author: Benjamin Poussin - * :address: - * Quelque part - * Dans le monde - * </pre> - * - * @return Element - * @throws IOException - */ - public Element peekDocInfoItem() throws IOException { - beginPeek(); - - Element result = null; - // in.skipBlankLines(); - String line = in.readLine(); - // (?i) case inensitive on docinfo item - if (line != null && line.matches("^:((?i)" + DOCINFO_ITEM + "):.*$")) { - - result = DocumentHelper.createElement(DOCINFO); - result.addAttribute(LEVEL, "0"); - String infotype = line.substring(1, line.indexOf(":", 1)); - - /* - * if (!in.eof()) { String [] content = readBlock(1); line += - * joinBlock(content); } - */ - String text = line.substring(line.indexOf(":", 1) + 1).trim(); - String[] textTmp = in.readWhile("^\\s+.*"); - if (textTmp.length != 0) { - in.mark(); - } - - for (String txt : textTmp) { - text += "\n" + txt.trim(); - } - - // CVS, RCS support - text = text.replaceAll("\\$\\w+: (.+?)\\$", "$1"); - - result.addAttribute(TYPE, infotype).addText(text); - } - endPeek(); - return result; - } - - /** - * read table simple and complexe - * - * <pre> - * +------------------------+------------+----------+----------+ - * | Header row, column 1 | Header 2 | Header 3 | Header 4 | - * | (header rows optional) | | | | - * +========================+============+==========+==========+ - * | body row 1, column 1 | column 2 | column 3 | column 4 | - * +------------------------+------------+----------+----------+ - * | body row 2 | Cells may span columns. | - * +------------------------+------------+---------------------+ - * </pre> - * - * @return Element - * @throws IOException - */ - @SuppressWarnings("unchecked") - public Element peekTable() throws IOException { - beginPeek(); - - Element result = null; - // in.skipBlankLines(); - String line = in.readLine(); - - if (line != null) { - Pattern pTableBegin = Pattern.compile("^\\s*(\\+-+)+\\+\\s*$"); - Matcher matcher = null; - - matcher = pTableBegin.matcher(line); - if (matcher.matches()) { // complexe table - result = DocumentHelper.createElement(TABLE); - result.addAttribute(TABLE_HEADER, FALSE); - int level = level(line); - result.addAttribute(LEVEL, String.valueOf(level)); - line = line.trim(); - int tableWidth = line.length(); - result.addAttribute(TABLE_WIDTH, String.valueOf(tableWidth)); - - Pattern pCellEnd = Pattern - .compile("^\\s{" - + level - + "}(\\+-+\\+|\\|(?:[^+]+))([^+]+(?:\\+|\\|\\s*$)|-+\\+)*\\s*"); // fin - // de - // ligne - Pattern pCell = Pattern.compile("^\\s{" + level - + "}(\\|[^|]+)+\\|\\s*$"); // une ligne - Pattern pHeader = Pattern.compile("^\\s{" + level - + "}(\\+=+)+\\+\\s*$"); // fin du header - Pattern pEnd = Pattern.compile("^\\s{" + level - + "}(\\+-+)+\\+\\s*$"); // fin de table - - // used to know if | is cell separator or not - String lastSeparationLine = line; - String lastLine = line; - - Element row = DocumentHelper.createElement(ROW); - String[] table = in.readUntilBlank(); - - boolean done = false; - for (String l : table) { - done = false; - l = l.trim(); - if (l.length() != tableWidth) { - // Erreur dans la table, peut-etre lever une exception ? - result = null; - break; - } - matcher = pEnd.matcher(l); - if (!done && matcher.matches()) { - // fin normale de ligne, on peut directement l'assigner - lastSeparationLine = l; - for (Element cell : (List<Element>) row.elements()) { - cell.addAttribute(CELL_END, TRUE); - } - row.addAttribute(ROW_END_HEADER, FALSE); - result.add(row); - row = DocumentHelper.createElement(ROW); - done = true; - } - matcher = pHeader.matcher(l); - if (!done && matcher.matches()) { - // fin de du header, on peut directement l'assigner - lastSeparationLine = l; - for (Element cell : (List<Element>) row.elements()) { - cell.addAttribute(CELL_END, TRUE); - } - row.addAttribute(ROW_END_HEADER, TRUE); - result.add(row); - result.addAttribute(TABLE_HEADER, TRUE); - row = DocumentHelper.createElement(ROW); - done = true; - } - matcher = pCell.matcher(l); - if (!done && matcher.matches()) { - // debug - row.addAttribute("debug", "pCell"); - // recuperation des textes des cellules - int start = -1; - String content = ""; - matcher = Pattern.compile("([^|]+)\\|").matcher(l); - for (int cellNumber = 0; matcher.find(); cellNumber++) { - int tmpstart = matcher.start(1); - int end = matcher.end(1); - String tmpcontent = matcher.group(1); - // on a forcement un | ou un + au dessus du + - // et forcement un + sur lastSeparationLine - // sinon ca veut dire qu'il y avait un | dans la - // cell - if ((lastLine.charAt(end) == '|' || lastLine - .charAt(end) == '+') - && lastSeparationLine.charAt(end) == '+') { - if ("".equals(content)) { - content = tmpcontent; - } - else { - content += tmpcontent; - } - if (start == -1) { - start = tmpstart; - } - Element cell = null; - if (row.nodeCount() <= cellNumber) { - cell = row.addElement(CELL); - cell.addAttribute(CELL_END, FALSE); - } else { - cell = (Element) row.node(cellNumber); - } - cell.addAttribute(CELL_INDEX_START, String - .valueOf(start)); - cell.addAttribute(CELL_INDEX_END, String - .valueOf(end)); - cell.setText(cell.getText() + content + "\n"); - start = end + 1; // +1 to pass + or | at end - // of cell - content = ""; - } else { - // start = tmpstart; - if (start == -1) { - start = tmpstart; - } - content += tmpcontent + "|"; - cellNumber--; - } - } - done = true; - } - matcher = pCellEnd.matcher(l); - if (!done && matcher.matches()) { - // debug - row.addAttribute("debug", "pCellEnd"); - // fin d'une ligne, on ne peut pas l'assigner - // directement - // pour chaque continuation de cellule, il faut copier - // l'ancienne valeur - - // mais on commence tout de meme par fermer tout les - // cells - for (Element cell : (List<Element>) row.elements()) { - cell.addAttribute(CELL_END, TRUE); - } - - StringBuffer tmp = new StringBuffer(l); - int start = -1; - String content = ""; - matcher = Pattern.compile("([^+|]+|-+)([+|])").matcher( - l); - for (int cellNumber = 0; matcher.find(); cellNumber++) { - int tmpstart = matcher.start(1); - int end = matcher.end(1); - String tmpcontent = matcher.group(1); - String ender = matcher.group(2); - if (!tmpcontent.matches("-+")) { - // on a forcement un | au dessus du + ou du | - // sinon ca veut dire qu'il y avait un + dans la - // cell - if (lastLine.charAt(end) == '|') { - if (start == -1) { - start = tmpstart; - } - // -1 and +1 to take the + or | at begin and - // end - String old = lastSeparationLine.substring( - start - 1, end + 1); - tmp.replace(start - 1, end + 1, old); - if ("".equals(content)) { - content = tmpcontent; - } - Element cell = null; - if (row.nodeCount() <= cellNumber) { - cell = row.addElement(CELL); - } else { - cell = (Element) row.node(cellNumber); - - } - cell.setText(cell.getText() + content - + "\n"); - // on a ajouter des choses dans la cell, - // donc - // ce n'est pas la fin - cell.addAttribute(CELL_END, FALSE); - cell.addAttribute(CELL_INDEX_START, String - .valueOf(start)); - cell.addAttribute(CELL_INDEX_END, String - .valueOf(end)); - start = end + 1; // +1 to pass + or | at - // end of cell - content = ""; - } else { - // start = tmpstart; - content += tmpcontent + ender; - } - } - } - lastSeparationLine = tmp.toString(); - row.addAttribute(ROW_END_HEADER, FALSE); - result.add(row); - row = DocumentHelper.createElement(ROW); - done = true; - } - if (!done) { - log.warn("Bad table format line " + in.getLineNumber()); - } - lastLine = l; - } - - // - // line += "\n" + joinBlock(table, "\n", false); - // - // result.addText(line); - } else if (line.matches("^\\s*(=+ +)+=+\\s*$")) { - // Les donnees de la table peuvent depasser de celle-ci - /* - * ===== ===== ====== Inputs Output ------------ ------ A B A or - * B ===== ===== ====== False False Second column of row 1. True - * False Second column of row 2. - * - * True 2 - Second column of row 3. - * - * - Second item in bullet list (row 3, column 2). ============ - * ====== - */ - - result = DocumentHelper.createElement(TABLE); - line = line.trim(); - Pattern pBordersEquals = Pattern.compile("^\\s*(=+ +)+=+\\s*$"); // Separation - // = - Pattern pBordersTiret = Pattern.compile("^\\s*(-+ +)+-+\\s*$"); // Separation - // - - Pattern pBorders = Pattern.compile("^\\s*([=-]+ +)+[=-]+\\s*$"); // = - // ou - // - - String[] table = in.readUntilBlank(); // Recuperation de la - // table - - int tableWidth = line.length(); - int nbSeparations = 0; - for (String l : table) { - if (l.length() > tableWidth) { - tableWidth = l.length(); // Determination de la - } // Determination de la - // longueur max - matcher = pBordersEquals.matcher(l); - if (matcher.matches()) { - nbSeparations++; - } - - } - // Header if the table contains 3 equals separations - result.addAttribute(TABLE_HEADER, "" + (nbSeparations == 2)); - int level = level(line); - result.addAttribute(LEVEL, String.valueOf(level)); - result - .addAttribute(TABLE_WIDTH, String - .valueOf(tableWidth + 1)); - Element row = DocumentHelper.createElement(ROW); - // Determination of the columns positions - List<Integer> columns = new LinkedList<Integer>(); - matcher = Pattern.compile("=+\\s+").matcher(line); - for (int cellNumber = 0; matcher.find(); cellNumber++) { - columns.add(matcher.end()); - } - columns.add(tableWidth); - - // Traitement du tbl - /* - * ===== ===== ====== Inputs Output ------------ ------ A B A or - * B ===== ===== ====== False False Second column of row 1. True - * False Second column of row 2. - * - * True 2 - Second column of row 3. - * - * - Second item in bullet list (row 3, column 2). ============ - * ====== devient l'equivalent : ===== ===== ====== Inputs - * Output ------------ ------ A B A or B ===== ===== ====== - * False False Second column of row 1. ----- ----- ------ True - * False Second column of row 2. ----- ----- ------ True 2 - - * Second column of row 3. - Second item in bullet list (row 3, - * column 2). ============ ====== - */ - String lineRef = line.replace('=', '-'); - Matcher matcher2; - List<String> tableTmp = new LinkedList<String>(); - - for (int i = 0; i < table.length - 1; i++) { - tableTmp.add(table[i]); - if (!table[i].equals("")) { - if (!table[i + 1] - .substring(0, columns.get(0)) - .matches("\\s*")) { - matcher = pBorders.matcher(table[i]); - matcher2 = pBorders.matcher(table[i + 1]); - if (!matcher.matches() && !matcher2.matches() - && !table[i + 1].equals("")) { - tableTmp.add(lineRef); - } - } - } - } - tableTmp.add(table[table.length - 1]); - table = new String[tableTmp.size()]; - for (int i = 0; i < tableTmp.size(); i++) { - table[i] = tableTmp.get(i); - } - - boolean done = false; - LinkedList<String> lastLines = new LinkedList<String>(); - int separation = 1; - for (String l : table) { - if (l != null) { - done = false; - matcher = pBordersTiret.matcher(l); - matcher2 = pBordersEquals.matcher(l); - if (matcher.matches() || matcher2.matches()) { // Intermediate - // separation - while (!lastLines.isEmpty()) { - matcher = Pattern.compile("[-=]+\\s*").matcher( - l); - String tmpLine = lastLines.getLast(); - lastLines.removeLast(); - int cellNumber; - for (cellNumber = 0; matcher.find(); cellNumber++) { - Element cell = null; - if (row.nodeCount() <= cellNumber) { - cell = row.addElement(CELL); - } else { - cell = (Element) row.node(cellNumber); - } - if (matcher.start() < tmpLine.length()) { - if (columns.size() - 1 == cellNumber) { - cell.setText(tmpLine.substring( - matcher.start(), tmpLine - .length()) - + "\n"); - } else { - if (matcher.end() < tmpLine - .length()) { - cell.setText(tmpLine.substring(matcher.start(), matcher.end()) + "\n"); - } - else { - cell.setText(tmpLine.substring(matcher.start(), tmpLine.length()) + "\n"); - } - } - } - - if (lastLines.size() == 0) { - row.addAttribute("debug", "pCell"); - cell.addAttribute(CELL_END, TRUE); - } else { - row.addAttribute("debug", "pCellEnd"); - cell.addAttribute(CELL_END, FALSE); - } - cell.addAttribute(CELL_INDEX_START, String - .valueOf(matcher.start() + 1)); - if (line.length() == matcher.end()) { - cell.addAttribute(CELL_INDEX_END, String.valueOf(columns.get(columns.size() - 1))); - } - else { - cell.addAttribute(CELL_INDEX_END, String.valueOf(matcher.end())); - } - } - - if (matcher2.matches()) { - separation++; - row.addAttribute(ROW_END_HEADER, "" - + (separation == 2)); - } else { - row.addAttribute(ROW_END_HEADER, FALSE); - } - - result.add(row); - row = DocumentHelper.createElement(ROW); - done = true; - } - } - if (!done && l.matches("^\\s*(.+ +)+.+\\s*$")) { - // Data - lastLines.addFirst(l); // Les donnees sont stoquee - // dans une file d'attente - // lastLines (FIFO) - done = true; - } - if (!done) { - log.warn("Bad table format line " - + in.getLineNumber()); - } - } - } - } - } - endPeek(); - - return result; - } - - /** - * read list - * - * <pre> - * - first line - * - next line - * </pre> - * - * @return <bullet_list level="[int]" - * bullet="char"><[text];</bullet_list> - * @throws IOException - */ - public Element peekBulletList() throws IOException { - beginPeek(); - - Element result = null; - // in.skipBlankLines(); - String line = in.readLine(); - if (line != null - && line.matches("^\\s*[" + escapeRegex(BULLET_CHAR) - + "] +\\S.*")) { - int level = level(line); - String bullet = line.substring(level, level + 1); - - result = DocumentHelper.createElement(BULLET_LIST).addAttribute( - LEVEL, String.valueOf(level)).addAttribute(BULLET, - bullet); - - if (!in.eof()) { - String[] content = readBlock(level + 1); - line += " " + joinBlock(content); - } - String text = line.substring(level + 1).trim(); - - result.addText(text); - in.skipBlankLines(); - } - - endPeek(); - return result; - } - - /** - * read field list - * - * <pre> - * :first: text - * :second: text - * and other text - * :last empty: - * </pre> - * - * @return <field_list level="[int]" - * name="[text]">[text]</field_list> - * @throws IOException - */ - public Element peekFieldList() throws IOException { - beginPeek(); - - Element result = null; - // in.skipBlankLines(); - String line = in.readLine(); - if (line != null) { - Pattern pattern = Pattern.compile("^\\s*:([^:]+): [^\\s].*"); - Matcher matcher = pattern.matcher(line); - if (matcher.matches()) { - int level = level(line); - String name = matcher.group(1); - int begin = matcher.end(1) + 1; - - result = DocumentHelper.createElement(FIELD_LIST).addAttribute( - LEVEL, String.valueOf(level)).addAttribute(NAME, - name); - - if (!in.eof()) { - String[] content = readBlock(level + 1); - line += " " + joinBlock(content); - } - String text = line.substring(begin).trim(); - - result.addText(text); - } - } - - endPeek(); - return result; - } - - /** - * read definition list - * - * <pre> - * un autre mot - * une autre definition - * le mot : la classe - * la definition - * le mot : la classe 1 : la classe 2 - * la definition - * </pre> - * - * @return <definition_list level="[int]" term="[text]" - * classifiers="[text]">[text]</definition_list> - * @throws IOException - */ - public Element peekDefinitionList() throws IOException { - beginPeek(); - - Element result = null; - // in.skipBlankLines(); - String[] lines = in.readLines(2); - if (lines.length == 2) { - int level = level(lines[0]); - int levelDef = level(lines[1]); - if ((levelDef != lines[1].length()) && (level < levelDef)) { - in.unread(lines[1], true); - Pattern pattern = Pattern.compile("^\\s*([^:]+)(?: : (.*))?"); - Matcher matcher = pattern.matcher(lines[0]); - if (matcher.matches()) { - String term = matcher.group(1); - String classifiers = matcher.group(2); - - result = DocumentHelper.createElement(DEFINITION_LIST) - .addAttribute(LEVEL, String.valueOf(level)) - .addAttribute(TERM, term).addAttribute( - CLASSIFIERS, classifiers); - - // poussin 20070207 don't read block here because can't - // interpret it correctly in JRSTReader - // if (!in.eof()) { - // String [] content = readBlock(level + 1); - // String text = joinBlock(content); - // result.addText(text); - // } - } - } - } - - endPeek(); - return result; - } - - /** - * read enumarted list - * - * can be: <li>1, 2, 3, ... <li>a, b, c, ... <li>A, B, C, ... <li>i, ii, - * iii, iv, ... <li>I, II, III, IV, ... - * - * or # for auto-numbered - * - * <pre> - * - * 1. next line 1) next line (1) first line - * - * </pre> - * - * @return <enumerated_list level="[int]" start="[number]" - * prefix="[char]" suffix="[char]" - * enumtype="[(arabic|loweralpha|upperalpha|lowerroman|upperroman]"> - * ;[text]</enumerated_list> - * @throws IOException - */ - public Element peekEnumeratedList() throws IOException { - beginPeek(); - - Element result = null; - // in.skipBlankLines(); - - String line = in.readLine(); - if (line != null) { - Pattern pattern = Pattern - .compile("^\\s*(\\(?)(#|\\d+|[a-z]|[A-Z]|[ivxlcdm]+|[IVXLCDM]+)([\\.)]) [^\\s].*"); - Matcher matcher = pattern.matcher(line); - if (matcher.matches()) { - int level = level(line); - String prefix = matcher.group(1); - String start = matcher.group(2); - String suffix = matcher.group(3); - int begin = matcher.end(3); - - // arabic|loweralpha|upperalpha|lowerroman|upperroman - String enumtype = "auto"; - if (start.matches("\\d+")) { - enumtype = "arabic"; - } else if (start.matches("(i|[ivxlcdm][ivxlcdm]+)")) { - enumtype = "lowerroman"; - start = "1"; // TODO transform romain to arabic - } else if (start.matches("(I|[IVXLCDM][IVXLCDM]+)")) { - enumtype = "upperroman"; - start = "1"; // TODO transform romain to arabic - } else if (start.matches("[a-z]+")) { - enumtype = "loweralpha"; - start = String.valueOf((int) start.charAt(0) - (int) 'a'); - } else if (start.matches("[A-Z]+")) { - enumtype = "upperalpha"; - start = String.valueOf((int) start.charAt(0) - (int) 'A'); - } - - result = DocumentHelper.createElement(ENUMERATED_LIST) - .addAttribute(LEVEL, String.valueOf(level)) - .addAttribute(START, start).addAttribute(PREFIX, - prefix).addAttribute(SUFFIX, suffix) - .addAttribute(ENUMTYPE, enumtype); - - if (line.endsWith(": ::")) { - line = line.substring(0, line.length() - " ::".length()); - in.unread("::", true); - - } else if (line.endsWith("::")) { - line = line.substring(0, line.length() - ":".length()); // keep - // one - // : - in.unread("::", true); - } - - - if (!in.eof()) { - String[] content = readBlock(level + 1); - String tempLine = " " + joinBlock(content); - - if (tempLine.endsWith(": ::")) { - tempLine = tempLine.substring(0, tempLine.length() - " ::".length()); - in.unread("::", true); - - } else if (tempLine.endsWith("::")) { - tempLine = tempLine.substring(0, tempLine.length() - ":".length()); // keep - // one - // : - in.unread("::", true); - } - - line+=tempLine; - - - } - String text = line.substring(begin).trim(); - - result.addText(text); - in.skipBlankLines(); - } - } - - endPeek(); - return result; - } - - /** - * Parse un titre simple ou double - * - * simple: - * - * <pre> - * - * Le titre ======== - * - * </pre> - * - * double: - * - * <pre> - * - * ============ le titre ============ - * - * </pre> - * - * @return <title level="[int]" type="[simple|double]" char="[underline - * char]"> - * @throws IOException - */ - public Element peekTitle() throws IOException { - beginPeek(); - - Element result = null; - // in.skipBlankLines(); - String line = in.readLine(); - - if (line != null) { - if (startsWithTitleChar(line)) { - String[] titles = in.readLines(2); - if (titles.length == 2 && line.length() >= titles[0].length() - && line.length() == titles[1].length() - && line.equals(titles[1])) { - result = DocumentHelper.createElement(TITLE).addAttribute( - TYPE, "double").addAttribute(CHAR, - titles[1].substring(0, 1)).addText(titles[0]); - } - } else { - String title = in.readLine(); - if (title != null - && startsWithTitleChar(title) - && line.replaceFirst("\\s*$", "").length() == title - .length()) { - - result = DocumentHelper.createElement(TITLE).addAttribute( - TYPE, "simple").addAttribute(CHAR, - title.substring(0, 1)).addText( - line.replaceFirst("\\s*$", "")); - } - } - } - - if (result != null) { - // add level information - String titleLevel = result.attributeValue(CHAR); - - if ("double".equals(result.attributeValue(TYPE))) { - titleLevel += titleLevel; - } - int level = titleLevels.indexOf(titleLevel); - if (level == -1) { - level = titleLevels.size(); - titleLevels.add(titleLevel); - } - result.addAttribute(LEVEL, String - .valueOf(JRSTReader.MAX_SECTION_DEPTH + level)); - } - - endPeek(); - return result; - } - - public Element peekTarget() throws IOException { - beginPeek(); - - String line = in.readLine(); - Element result = null; - if (line != null) { - if (line.matches("^\\s*\\.\\.\\s_[^_:].+:.*")) { - result = DocumentHelper.createElement(TARGET); - Matcher matcher = Pattern.compile("\\.\\.\\s_").matcher(line); - if (matcher.find()) { - int i = line.indexOf(':'); - result.addAttribute(ID, URLEncoder.encode(line.substring(matcher.end(), i) - .toLowerCase().replaceAll(" ", "-"), "UTF-8")); - result.addAttribute(LEVEL, "" + level(line)); - } - } - } - endPeek(); - return result; - } - - /** - * .. _frungible doodads: http://www.example.org/ - * - * @return Element - * @throws IOException - */ - public LinkedList<Element> refTarget() throws IOException { - beginPeek(); - - String[] lines = in.readAll(); - LinkedList<Element> result = new LinkedList<Element>(); - for (String line : lines) { - if (line.matches("^\\s*\\.\\.\\s_[^_:].+:.*")) { - result.add(DocumentHelper.createElement(TARGET)); - Matcher matcher = Pattern.compile("\\.\\.\\s_").matcher(line); - if (matcher.find()) { - boolean done = false; - for (int i = matcher.end(); i < line.length() && !done; i++) { - if (line.charAt(i) == ':') { - result.getLast().addAttribute(LEVEL, - "" + level(line)); - result.getLast().addAttribute( - ID, - URLEncoder.encode(line.substring(matcher.end(), i) - .replaceAll(" ", "-").toLowerCase(), "UTF-8")); - result.getLast().addAttribute( - NAME, - line.substring(matcher.end(), i) - .toLowerCase()); - if (i + 2 > line.length()) { - line = in.readLine(); - // FIXME 20071129 chatellier - // line = null if link is non well formed - // .. _Unifying types and classes in Python: - // miss uri - if (line == null) { - line = ""; - } - result.getLast().addAttribute(REFURI, - line.trim()); - } else { - result.getLast().addAttribute(REFURI, line.substring(i + 2, line.length())); - } - - done = true; - } - } - } - } - } - endPeek(); - return result; - } - - /** - * .. __: http://www.python.org - * - * @return Element - * @throws IOException - */ - private Element peekTargetAnonymousBody() throws IOException { - beginPeek(); - Element result = null; - String line = in.readLine(); - if (line != null) { - if (line.matches("^\\s*__ .+$|^\\s*\\.\\. __\\:.+$")) { - result = DocumentHelper.createElement(TARGETANONYMOUS); - result.addAttribute(LEVEL, "" + level(line)); - - } - } - - endPeek(); - return result; - } - - /** - * .. comment - * - * @return Element - * @throws IOException - */ - private Element peekComment() throws IOException { - beginPeek(); - Element result = null; - String line = in.readLine(); - if (line != null) { - if (line.matches("^\\.\\.\\s+.*$")) { - result = DocumentHelper.createElement(COMMENT); - result.addAttribute(LEVEL, "0"); - result.addAttribute(XMLSPACE, "preserve"); - - // first line is part of comment - result.setText(line.substring(2).trim()); - line = in.readLine(); - if(line != null) { - int level = level(line); - if (level > 0) { - String[] lines = readBlock(level); - String text = line.substring(level); - for (String l : lines) { - text += "\n" + l.substring(level); - } - result.addText(text); - } - } - } - } - - endPeek(); - return result; - } - - /** - * .. comment - * - * @return Element - * @throws IOException - */ - public List<Element> peekAllComment() throws IOException { - beginPeek(); - List<Element> result = new ArrayList<Element>(); - String[] lines = in.readWhile("^\\.\\.\\s*.*$"); - if (lines != null) { -// int levelRef = level(line); - for (String line : lines) { - Element comment = DocumentHelper.createElement(COMMENT); - comment.addAttribute(LEVEL, "0"); - comment.addAttribute(XMLSPACE, "preserve"); - - // first line is part of comment - comment.setText(line.substring(2).trim()); - result.add(comment); - -// int level = level(line); -// if (level == levelRef) { -// String[] lines = readBlock(level); -// String text = line.substring(level); -// for (String l : lines) { -// text += "\n" + l.substring(level); -// } -// result.addText(text); -// } - } - in.mark(); - } - - endPeek(); - return result; - } - - /** - * .. _frungible doodads: http://www.example.org/ - * - * @return Element - * @throws IOException - */ - public Element peekFootnote() throws IOException { - beginPeek(); - Element result = null; - String line = in.readLine(); - if (line != null) { - if (line.matches("^\\s*\\.\\.\\s\\[(#|[0-9]|\\*).*\\]\\s.+$")) { - result = DocumentHelper.createElement(FOOTNOTES); - boolean bLine = false; - do { - - bLine = false; - Element footnote = result.addElement(FOOTNOTE); - Matcher matcher = Pattern.compile("\\.\\.\\s\\[").matcher( - line); - - if (matcher.find()) { - - boolean done = false; - for (int i = matcher.end(); i < line.length() && !done; i++) { - if (line.charAt(i) == ']') { - - result.addAttribute(LEVEL, "" + level(line)); - String id = line.substring(matcher.end(), i); - if (id.matches("\\*")) { - footnote.addAttribute(TYPE, AUTOSYMBOL); - } else if (id.matches("[0-9]")) { - footnote.addAttribute(TYPE, NUM); - footnote.addAttribute(NAME, id); - } else if (id.equals("#")) { - footnote.addAttribute(TYPE, AUTONUM); - } else { - footnote.addAttribute(TYPE, - AUTONUMLABEL); - footnote.addAttribute(NAME, id - .substring(1)); - } - String text = line.substring(i + 2, line - .length()); - - int levelAv = level(line); - line = in.readLine(); - if (line != null) { - if (line - .matches("^\\s*\\.\\.\\s\\[(#|[0-9]|\\*).*\\]\\s.+$")) { - bLine = true; - } else { - - int level = level(line); - if (levelAv < level) { - String[] lines = in - .readWhile("(^ {" + level - + "}.*)|(\\s*)"); - text += "\n" + line.trim(); - for (String l : lines) { - text += "\n" + l.trim(); - } - - } else if (line.matches("\\s*")) { - level = levelAv + 1; - String[] lines = in - .readWhile("(^ {" + level - + "}.*)|(\\s*)"); - text += "\n" + line.trim(); - for (String l : lines) { - text += "\n" + l.trim(); - } - - } - } - if (!bLine) { - in.skipBlankLines(); - String[] linesTmp = in - .readWhile("^\\s*\\.\\.\\s\\[(#|[0-9]|\\*).*\\]\\s.+$"); - - if (linesTmp.length > 0) { - line = linesTmp[0]; - bLine = true; - } - } - - } - if (line == null) { - line = ""; - } - footnote.setText(text); - done = true; - } - - } - } - - } while (bLine); - } - } - endPeek(); - return result; - } - - /** - * Read block text, block text have same indentation - * - * @param minLeftMargin - * min left blank needed to accept to read block - * @return String - * @throws IOException - */ - private String readBlockWithBlankLine(int level) throws IOException { - String txt = ""; - String[] lines = in.readWhile("(^ {" + level + "}.*)|(\\s*)"); - while (lines.length > 0) { - for (String l : lines) { - l = l.trim(); - txt += l + "\n"; - - } - lines = in.readWhile("(^ {" + level + "}.*)|(\\s*)"); - } - return txt; - } - - /** - * Lit les premieres ligne non vide et les retourne, rien n'est modifier par - * rapport aux positions dans le fichier. Util pour afficher a l'utilisateur - * les lignes qui ont produit une erreur - * - * @return les lignes non vides - * @throws IOException - */ - public String readNotBlanckLine() throws IOException { - beginPeek(); - in.skipBlankLines(); - String line = joinBlock(in.readUntilBlank(), "\n", false); - endPeek(); - return line; - } - - /** - * return the number of line read - * - * @return int - */ - public int getLineNumber() { - return in.getLineNumber(); - } - - /** - * return the number of char read - * - * @return int - */ - public int getCharNumber() { - return in.getCharNumber(); - } - - /** - * return true if line can be underline or overline for title - * - * @param line - * @return boolean - */ - private boolean startsWithTitleChar(String line) { - if (line == null || line.length() < 2) { - return false; - } - // est-ce que la ligne est constituer entierement du meme caractere et - // qu'il y en a au moins 2 - boolean result = line - .matches("([" + escapeRegex(TITLE_CHAR) + "])\\1+"); - return result; - } - - /** - * @param title_charescapeRegex - * @return String - */ - private String escapeRegex(String text) { - String result = text.replaceAll("([()[\\\\]*+?.])", "\\\\$1"); - return result; - } - - /** - * @param String - * line - * @return int - * @throws IOException - */ - private int level(String line) { - int result = 0; - String sTmp = line.replaceAll("\\s", " "); - while (sTmp.length() > result && sTmp.charAt(result) == ' ') { - result++; - } - return result; - } -} Deleted: branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/JRSTReader.java =================================================================== --- branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/JRSTReader.java 2012-06-04 16:16:06 UTC (rev 695) +++ branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/JRSTReader.java 2012-06-05 14:44:35 UTC (rev 696) @@ -1,2418 +0,0 @@ -/* - * #%L - * JRst :: Api - * - * $Id: JRSTReader.java 638 2011-12-23 10:35:21Z jruchaud $ - * $HeadURL: http://svn.nuiton.org/svn/jrst/branches/jrst-docutils-jython/jrst/src/main/j... $ - * %% - * Copyright (C) 2004 - 2010 CodeLutin - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -/* * - * JRSTReader.java - * - * Created: 27 oct. 06 00:15:34 - * - * @author poussin - * @version $Revision: 638 $ - * - * Last update: $Date: 2011-12-23 11:35:21 +0100 (ven. 23 déc. 2011) $ - * by : $Author: jruchaud $ - */ - -package org.nuiton.jrst; - -import static org.nuiton.i18n.I18n._; -import static org.nuiton.jrst.ReStructuredText.ADDRESS; -import static org.nuiton.jrst.ReStructuredText.ADMONITION; -import static org.nuiton.jrst.ReStructuredText.ATTRIBUTION; -import static org.nuiton.jrst.ReStructuredText.AUTHOR; -import static org.nuiton.jrst.ReStructuredText.AUTHORS; -import static org.nuiton.jrst.ReStructuredText.BLOCK_QUOTE; -import static org.nuiton.jrst.ReStructuredText.BULLET_LIST; -import static org.nuiton.jrst.ReStructuredText.COLSPEC; -import static org.nuiton.jrst.ReStructuredText.COMMENT; -import static org.nuiton.jrst.ReStructuredText.CONTACT; -import static org.nuiton.jrst.ReStructuredText.COPYRIGHT; -import static org.nuiton.jrst.ReStructuredText.DATE; -import static org.nuiton.jrst.ReStructuredText.DECORATION; -import static org.nuiton.jrst.ReStructuredText.DEFINITION; -import static org.nuiton.jrst.ReStructuredText.DEFINITION_LIST; -import static org.nuiton.jrst.ReStructuredText.DEFINITION_LIST_ITEM; -import static org.nuiton.jrst.ReStructuredText.DESCRIPTION; -import static org.nuiton.jrst.ReStructuredText.DOCINFO; -import static org.nuiton.jrst.ReStructuredText.DOCTEST_BLOCK; -import static org.nuiton.jrst.ReStructuredText.DOCUMENT; -import static org.nuiton.jrst.ReStructuredText.EMPHASIS; -import static org.nuiton.jrst.ReStructuredText.ENTRY; -import static org.nuiton.jrst.ReStructuredText.ENUMERATED_LIST; -import static org.nuiton.jrst.ReStructuredText.FIELD; -import static org.nuiton.jrst.ReStructuredText.FIELD_BODY; -import static org.nuiton.jrst.ReStructuredText.FIELD_LIST; -import static org.nuiton.jrst.ReStructuredText.FIELD_NAME; -import static org.nuiton.jrst.ReStructuredText.FOOTER; -import static org.nuiton.jrst.ReStructuredText.FOOTNOTE; -import static org.nuiton.jrst.ReStructuredText.FOOTNOTE_REFERENCE; -import static org.nuiton.jrst.ReStructuredText.FOOTNOTE_SYMBOL; -import static org.nuiton.jrst.ReStructuredText.GENERATED; -import static org.nuiton.jrst.ReStructuredText.HEADER; -import static org.nuiton.jrst.ReStructuredText.IMAGE; -import static org.nuiton.jrst.ReStructuredText.LABEL; -import static org.nuiton.jrst.ReStructuredText.LINE; -import static org.nuiton.jrst.ReStructuredText.LINE_BLOCK; -import static org.nuiton.jrst.ReStructuredText.LIST_ITEM; -import static org.nuiton.jrst.ReStructuredText.LITERAL; -import static org.nuiton.jrst.ReStructuredText.LITERAL_BLOCK; -import static org.nuiton.jrst.ReStructuredText.OPTION; -import static org.nuiton.jrst.ReStructuredText.OPTION_ARGUMENT; -import static org.nuiton.jrst.ReStructuredText.OPTION_GROUP; -import static org.nuiton.jrst.ReStructuredText.OPTION_LIST; -import static org.nuiton.jrst.ReStructuredText.OPTION_LIST_ITEM; -import static org.nuiton.jrst.ReStructuredText.OPTION_STRING; -import static org.nuiton.jrst.ReStructuredText.ORGANIZATION; -import static org.nuiton.jrst.ReStructuredText.PARAGRAPH; -import static org.nuiton.jrst.ReStructuredText.REFERENCE; -import static org.nuiton.jrst.ReStructuredText.REGEX_ANONYMOUS_HYPERLINK_REFERENCE; -import static org.nuiton.jrst.ReStructuredText.REGEX_EMAIL; -import static org.nuiton.jrst.ReStructuredText.REGEX_EMPHASIS; -import static org.nuiton.jrst.ReStructuredText.REGEX_FOOTNOTE_REFERENCE; -import static org.nuiton.jrst.ReStructuredText.REGEX_HYPERLINK_REFERENCE; -import static org.nuiton.jrst.ReStructuredText.REGEX_INLINE_REFERENCE; -import static org.nuiton.jrst.ReStructuredText.REGEX_LITERAL; -import static org.nuiton.jrst.ReStructuredText.REGEX_REFERENCE; -import static org.nuiton.jrst.ReStructuredText.REGEX_STRONG; -import static org.nuiton.jrst.ReStructuredText.REGEX_SUBSTITUTION_REFERENCE; -import static org.nuiton.jrst.ReStructuredText.REVISION; -import static org.nuiton.jrst.ReStructuredText.ROW; -import static org.nuiton.jrst.ReStructuredText.SECTION; -import static org.nuiton.jrst.ReStructuredText.SIDEBAR; -import static org.nuiton.jrst.ReStructuredText.STATUS; -import static org.nuiton.jrst.ReStructuredText.STRONG; -import static org.nuiton.jrst.ReStructuredText.SUBSTITUTION_DEFINITION; -import static org.nuiton.jrst.ReStructuredText.SUBTITLE; -import static org.nuiton.jrst.ReStructuredText.TABLE; -import static org.nuiton.jrst.ReStructuredText.TARGET; -import static org.nuiton.jrst.ReStructuredText.TBODY; -import static org.nuiton.jrst.ReStructuredText.TERM; -import static org.nuiton.jrst.ReStructuredText.TGROUP; -import static org.nuiton.jrst.ReStructuredText.THEAD; -import static org.nuiton.jrst.ReStructuredText.TITLE; -import static org.nuiton.jrst.ReStructuredText.TOPIC; -import static org.nuiton.jrst.ReStructuredText.TRANSITION; -import static org.nuiton.jrst.ReStructuredText.VERSION; - - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.Reader; -import java.io.StringReader; -import java.io.UnsupportedEncodingException; -import java.net.URL; -import java.net.URLEncoder; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.TreeSet; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.NoSuchElementException; - -import org.apache.commons.lang.ObjectUtils; -import org.apache.commons.lang.StringEscapeUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.nuiton.jrst.directive.ContentDirective; -import org.nuiton.jrst.directive.DateDirective; -import org.nuiton.jrst.directive.ImageDirective; -import org.nuiton.jrst.directive.SectnumDirective; -import org.nuiton.util.StringUtil; -import org.dom4j.Document; -import org.dom4j.DocumentException; -import org.dom4j.DocumentHelper; -import org.dom4j.Element; -import org.dom4j.IllegalAddException; -import org.dom4j.Node; -import org.dom4j.VisitorSupport; - -/* - * - * <pre> +--------------------------------------------------------------------+ | - * document [may begin with a title, subtitle, decoration, docinfo] | | - * +--------------------------------------+ | | sections [each begins with a - * title] | - * +-----------------------------+-------------------------+------------+ | - * [body elements:] | (sections) | | | - literal | - lists | | - hyperlink - * +------------+ | | blocks | - tables | | targets | | para- | - doctest | - - * block | foot- | - sub. defs | | graphs | blocks | quotes | notes | - comments | - * +---------+-----------+----------+-------+--------------+ | [text]+ | [text] | - * (body elements) | [text] | | (inline - * +-----------+------------------+--------------+ | markup) | +---------+ - * </pre> - * - * - * Inline support: http://docutils.sourceforge.net/docs/user/rst/quickref.html - * - * <li> STRUCTURAL ELEMENTS: document, section, topic, sidebar <li> STRUCTURAL - * SUBELEMENTS: title, subtitle, decoration, docinfo, transition <li> docinfo: - * address, author, authors, contact, copyright, date, field, organization, - * revision, status, version <li> decoration: footer, header <li> BODY ELEMENTS: - * admonition, attention, block_quote, bullet_list, caution, citation, comment, - * compound, container, danger, definition_list, doctest_block, enumerated_list, - * error, field_list, figure, footnote, hint, image, important, line_block, - * literal_block, note, option_list, paragraph, pending, raw, rubric, - * substitution_definition, system_message, table, target, tip, warning <li> - * SIMPLE BODY ELEMENTS: comment, doctest_block, image, literal_block, - * paragraph, pending, raw, rubric, substitution_definition, target <li> - * COMPOUND BODY ELEMENTS: admonition, attention, block_quote, bullet_list, - * caution, citation, compound, container, danger, definition_list, - * enumerated_list, error, field_list, figure, footnote, hint, important, - * line_block, note, option_list, system_message, table, tip, warning <li> BODY - * SUBELEMENTS: attribution, caption, classifier, colspec, field_name, label, - * line, option_argument, option_string, term definition, definition_list_item, - * description, entry, field, field_body, legend, list_item, option, - * option_group, option_list_item, row, tbody, tgroup, thead <li> INLINE - * ELEMENTS: abbreviation, acronym, citation_reference, emphasis, - * footnote_reference, generated, image, inline, literal, problematic, - * reference, strong, subscript, substitution_reference, superscript, target, - * title_reference, raw - * - * <pre> DOCUMENT :: ( (title, subtitle?)?, decoration?, (docinfo, - * transition?)?, STRUCTURE.MODEL; ) decoration :: (header?, footer?) header, - * footer, definition, description, attention, caution, danger, error, hint, - * important, note, tip, warning :: (BODY.ELEMENTS;)+ transition :: EMPTY - * docinfo :: (BIBLIOGRAPHIC.ELEMENTS;)+ BIBLIOGRAPHIC.ELEMENTS :: author | - * authors | organization | contact | address | version | revision | status | - * date | copyright | field authors :: ( (author)+ ) field :: (field_name, - * field_body) field_body, list_item :: (BODY.ELEMENTS;)* STRUCTURE.MODEL :: ( ( - * (BODY.ELEMENTS; | topic | sidebar)+, transition? )*, ( (section), - * (transition?, (section) )* )? ) BODY.ELEMENTS :: paragraph | compound | - * container | literal_block | doctest_block | line_block | block_quote | table | - * figure | image | footnote | citation | rubric | bullet_list | enumerated_list | - * definition_list | field_list | option_list | attention | caution | danger | - * error | hint | important | note | tip | warning | admonition | reference | - * target | substitution_definition | comment | pending | system_message | raw - * topic :: (title?, (BODY.ELEMENTS;)+) sidebar :: (title, subtitle?, - * (BODY.ELEMENTS; | topic)+) section :: (title, STRUCTURE.MODEL;) line_block :: - * (line | line_block)+ block_quote:: ((BODY.ELEMENTS;)+, attribution?) - * bullet_list, enumerated_list :: (list_item +) definition_list :: - * (definition_list_item +) definition_list_item :: (term, classifier?, - * definition) field_list :: (field +) option_list :: (option_list_item +) - * option_list_item :: (option_string, option_argument *, description) - * option_string, option_argument :: (#PCDATA) admonition :: (title, - * (BODY.ELEMENTS;)+) - * - * title, subtitle, author, organization, contact, address, version, revision, - * status, date, copyright, field_name, paragraph, compound, container, - * literal_block, doctest_block, attribution, line, term, classifier :: - * TEXT.MODEL; - * - * TEXT.MODEL :: (#PCDATA | INLINE.ELEMENTS;)* INLINE.ELEMENTS :: emphasis | - * strong | literal | reference | footnote_reference | citation_reference | - * substitution_reference | title_reference | abbreviation | acronym | subscript | - * superscript | inline | problematic | generated | target | image | raw - * emphasis :: '*' #PCDATA '*' strong :: '**' #PCDATA '**' literal :: '``' - * #PCDATA '``' footnote_reference :: '[' ([0-9]+|#) ']' citation_reference :: - * '[' [a-zA-Z]+ ']' - * - * </pre> - */ - -/** - * Le principe est d'utiliser les methodes peek* {@link JRSTLexer} pour - * prendre l'element que l'on attend, si la methode retourne null ou un autre - * element et bien c que ce n'est pas le bon choix, cela veut dire que l'element - * courant est fini d'etre lu (plus de paragraphe dans la section par exemple) - * ou qu'il y a une erreur dans le fichier en entre. - * <p> - * On construit un arbre XML representant le RST au fur et a mesure, on peut - * ensuite appliquer une feuille de style ou autre chose avec - * {@link JRSTGenerator} - * - * <p> - * Tous les elements ont un attribut level qui permet de savoir on il est dans - * la hierarchie. Le Document a le level -1001, et les sections/titres on pour - * level les valeurs 1000, -999, -998, ... - * <p> - * de cette facon les methods isUpperLevel et isSameLevel fonctionne pour tous - * les elements de la meme facon - * - * <pre> - * abbreviation - * acronym - * address (done) - * admonition (done) - * attention (done) - * attribution - * author (done) - * authors (done) - * block_quote (done) - * bullet_list (done) - * caption - * caution (done) - * citation - * citation_reference - * classifier (done) - * colspec (done) - * comment - * compound - * contact (done) - * container - * copyright (done) - * danger (done) - * date (done) - * decoration (done) - * definition (done) - * definition_list (done) - * definition_list_item (done) - * description (done) - * docinfo (done) - * doctest_block (done) - * document (done) - * emphasis (done) - * entry (done) - * enumerated_list (done) - * error (done) - * field (done) - * field_body (done) - * field_list (done) - * field_name (done) - * figure - * footer (done) - * footnote (done) - * footnote_reference (done) - * generated - * header (done) - * hint (done) - * image (done) - * important (done) - * inline - * label - * legend - * line (done) - * line_block (done) - * list_item (done) - * literal (done) - * literal_block (done) - * note (done) - * option (done) - * option_argument (done) - * option_group (done) - * option_list (done) - * option_list_item (done) - * option_string (done) - * organization (done) - * paragraph (done) - * pending - * problematic - * raw - * reference (done) - * revision (done) - * row (done) - * rubric - * section (done) - * sidebar (done) - * status (done) - * strong (done) - * subscript - * substitution_definition - * substitution_reference - * subtitle (done) - * superscript - * system_message - * table (done) - * target (done) - * tbody (done) - * term (done) - * tgroup (done) - * thead (done) - * tip (done) - * title (done) - * title_reference - * topic (done) - * transition (done) - * version (done) - * warning (done) - * </pre> - * - * Created: 27 oct. 06 00:15:34 - * - * @author poussin, letellier - * @version $Revision: 638 $ - * - * Last update: $Date: 2011-12-23 11:35:21 +0100 (ven. 23 déc. 2011) $ - * by : $Author: jruchaud $ - */ -public class JRSTReader { - - /** to use log facility, just put in your code: log.info(\"...\"); */ - private static Log log = LogFactory.getLog(JRSTReader.class); - - protected static final String ANONYMOUS = "anonymous"; - - protected static final String AUTO = "auto"; - - protected static final String AUTONUM = "autoNum"; - - protected static final String AUTONUMLABEL = "autoNumLabel"; - - protected static final String AUTOSYMBOL = "autoSymbol"; - - protected static final String ATTR_REFID = "refid"; - - protected static final String ATTR_INLINE = "inline"; - - protected static final String ATTR_IDS = "ids"; - - protected static final String BACKREFS = "backrefs"; - - protected static final String BULLET = "bullet"; - - protected static final String CLASS = "class"; - - protected static final String CONTENTS = "contents"; - - protected static final String DELIMITER = "delimiter"; - - protected static final String DELIMITEREXISTE ="delimiterExiste"; - - protected static final String ENUMTYPE = "enumtype"; - - protected static final String FOOTNOTES = "footnotes"; - - protected static final String ID = "id"; - - protected static final String INCLUDE = "include"; - - protected static final String LEVEL = "level"; - - protected static final String NAME = "name"; - - protected static final String NAMES = "names"; - - protected static final String NUM = "num"; - - protected static final String REFURI = "refuri"; - - protected static final String PREFIX = "prefix"; - - protected static final String REMOVE = "remove"; - - protected static final String START = "start"; - - protected static final String SECTNUM = "sectnum"; - - protected static final String SUBEXISTE = "subExiste"; - - protected static final String SUFFIX = "suffix"; - - protected static final String TRUE = "true"; - - protected static final String TYPE = "type"; - - protected static final String TARGETANONYMOUS = "targetAnonymous"; - - protected static final String VALUE = "value"; - - protected boolean ERROR_MISSING_ITEM; - - protected static int MAX_SECTION_DEPTH = -1000; - - protected static Map<String, JRSTDirective> defaultDirectives; - - protected Map<String, JRSTDirective> directives = new HashMap<String, JRSTDirective>(); - - private boolean sectnum; - - private Element footer; - - private int idMax; - - private int symbolMax; - - private int symbolMaxRef; - - private LinkedList<Integer> lblFootnotes = new LinkedList<Integer>(); - - private LinkedList<Integer> lblFootnotesRef = new LinkedList<Integer>(); - - private LinkedList<Element> eFootnotes = new LinkedList<Element>(); - - private LinkedList<Element> eTarget = new LinkedList<Element>(); - - private LinkedList<Element> eTargetAnonymous = new LinkedList<Element>(); - - private LinkedList<Element> eTargetAnonymousCopy = new LinkedList<Element>(); - - private LinkedList<Element> eTitle = new LinkedList<Element>(); - - static { - defaultDirectives = new HashMap<String, JRSTDirective>(); - defaultDirectives.put(IMAGE, new ImageDirective()); - defaultDirectives.put(DATE, new DateDirective()); - defaultDirectives.put("time", new DateDirective()); - defaultDirectives.put(CONTENTS, new ContentDirective()); - // defaultDirectives.put("calc", new CalcDirective()); - defaultDirectives.put(SECTNUM, new SectnumDirective()); - // TODO put here all other directive - } - - /** - * - */ - public JRSTReader() { - } - - /** - * @param name - * @return the defaultDirectives - */ - public static JRSTDirective getDefaultDirective(String name) { - return defaultDirectives.get(name); - } - - /** - * @param name - * @param directive the defaultDirectives to set - */ - public static void addDefaultDirectives(String name, JRSTDirective directive) { - JRSTReader.defaultDirectives.put(name, directive); - } - - /** - * @param name - * @return the defaultDirectives - */ - public JRSTDirective getDirective(String name) { - return directives.get(name); - } - - /** - * @param name - * @param directive the defaultDirectives to set - */ - public void addDirectives(String name, JRSTDirective directive) { - directives.put(name, directive); - } - - /** - * On commence par decouper tout le document en Element, puis on construit - * l'article a partir de ces elements. - * - * @param reader - * @return le document cree - * @throws Exception - */ - public Document read(Reader reader) throws Exception { - JRSTLexer lexer = new JRSTLexer(reader); - try { - Element root = composeDocument(lexer); - - Document result = DocumentHelper.createDocument(); - result.setRootElement(root); - - root.accept(new VisitorSupport() { - @Override - public void visit(Element e) { - // remove all level attribute - e.addAttribute(LEVEL, null); - // Constrution du sommaire - String type = e.attributeValue(TYPE); - if (type != null) { - if (type.equals(CONTENTS)) { - composeContents(e); - e.addAttribute(TYPE, null); - } - } - - if (TRUE.equalsIgnoreCase(e.attributeValue(ATTR_INLINE))) { - e.addAttribute(ATTR_INLINE, null); - try { - inline(e); - } catch (DocumentException eee) { - if (log.isWarnEnabled()) { - log.warn("Can't inline text for " + e, eee); - } - } catch (UnsupportedEncodingException ee) { - if (log.isWarnEnabled()) { - log.warn("Unsupported encoding " + e, ee); - } - } - } - } - }); - - return result; - } catch (Exception eee) { - log.error(_("JRST parsing error line %d char %s:\n%s", lexer - .getLineNumber(), lexer.getCharNumber(), lexer - .readNotBlanckLine())); - throw eee; - } - } - - /** - * <p> - * exemple : - * </p> - * - * <pre> - * ..contents : Sommaire - * depth: 3 - * </pre> - * - * <p> - * depth sert a limiter la profondeur du sommaire - * </p> - * - * @param Element - * - */ - private void composeContents(Element e) { - Element result = DocumentHelper.createElement(TOPIC); - String option = e.getText(); - int depth = -1; - // depth: 3 - Pattern pattern = Pattern.compile("\\s*\\:depth\\:\\s*\\p{Digit}+"); - Matcher matcher = pattern.matcher(option); - if (matcher.matches()) { - pattern = Pattern.compile("\\p{Digit}+"); - matcher = pattern.matcher(matcher.group()); - if (matcher.find()) { - depth = Integer.parseInt(matcher.group()); - } - } - int levelInit = 0; - boolean noTitle = false; - - try { - levelInit = Integer.parseInt(eTitle.getFirst().attributeValue( - LEVEL)); - } catch (NumberFormatException eee) { - log.error("Can't parse level in: " - + eTitle.getFirst().asXML(), eee); - return; - } catch (NoSuchElementException eee) { - noTitle = true; - } - - LinkedList<Element> title = new LinkedList<Element>(); - // on rajoute les refid - for (int i = 0; i < eTitle.size(); i++) { - idMax++; - eTitle.get(i).addAttribute(ATTR_REFID, ID + idMax); - } - // on enleve les titres limites par depth - for (Element el : eTitle) { - int level = Integer.parseInt(el.attributeValue(LEVEL)); - level = level - levelInit; - el.addAttribute(LEVEL, "" + level); - if (depth == -1) { - title.add(el); - } - else { - if (depth > level) { - title.add(el); - } - } - } - e.addAttribute(CLASS, CONTENTS); - String titleValue = e.attributeValue(VALUE); - e.addAttribute(VALUE, null); - String value = titleValue.trim().toLowerCase(); - // sans titre c "contents" par default - if (value.matches("\\s*")) { - value = CONTENTS; - titleValue = "Contents"; - } - e.addAttribute(ATTR_IDS, value); - e.addAttribute(NAMES, value); - result.addElement(TITLE).setText(titleValue); - // on compose les lignes - if (!noTitle) { //Si il y a des titres à lier à la table des matières - result.add(composeLineContent(title, "")); - } - e.setText(""); - e.appendContent(result); - } - - /** - * @param title - * <Element> title, String num - * @return Element - */ - private Element composeLineContent(LinkedList<Element> title, String num) { - Element result = DocumentHelper.createElement(BULLET_LIST); - if (sectnum) { - result.addAttribute(CLASS, "auto-toc"); - } - Element item = null; - int cnt = 0; - while (!title.isEmpty()) { - - Element e = title.getFirst(); - int level = Integer.parseInt(e.attributeValue(LEVEL)); - LinkedList<Element> child = new LinkedList<Element>(); - - if (level <= 0) { - cnt++; - title.removeFirst(); - item = result.addElement(LIST_ITEM); - Element para = item.addElement(PARAGRAPH); - Element reference = para.addElement(REFERENCE); - String text = e.getText(); - String id = e.attributeValue(ATTR_REFID); - reference.addAttribute(ATTR_IDS, id); - reference.addAttribute(ATTR_REFID, text.replaceAll("\\W+", " ") - .trim().toLowerCase().replaceAll("\\W+", "-")); - // si l'on doit les numeroter - if (sectnum) { - Element generated = reference.addElement(GENERATED) - .addAttribute(CLASS, SECTNUM); - generated.setText(num + cnt + " "); - for (int i = 0; i < eTitle.size(); i++) { - if (eTitle.get(i).attributeValue(ATTR_REFID).equals(id)) { - Element generatedTitle = eTitle.get(i).addElement( - GENERATED); - generatedTitle.addAttribute(CLASS, SECTNUM); - generatedTitle.setText(num + cnt + " "); - } - - } - } - - text = text.trim(); - text = text.replaceAll("_", ""); - - text = REGEX_STRONG.matcher(text).replaceAll( - "<" + STRONG + ">$1</" + STRONG + ">"); - text = REGEX_EMPHASIS.matcher(text).replaceAll( - "<" + EMPHASIS + ">$1</" + EMPHASIS + ">"); - - try { - Element textElement = DocumentHelper.parseText("<TMP>" + text + "</TMP>").getRootElement(); - reference.appendContent(textElement); - - } catch (DocumentException eee) { - if (log.isWarnEnabled()) { - log.warn("Can't inline text for " + e, eee); - } - } - - } else { - do { - e.addAttribute(LEVEL, "" + (level - 1)); - child.add(e); - title.removeFirst(); - if (!title.isEmpty()) { - e = title.getFirst(); - level = Integer.parseInt(e.attributeValue(LEVEL)); - } - } while (!title.isEmpty() && level > 0); - String numTmp = ""; - // numerotation - if (sectnum) { - numTmp = num + cnt + "."; - } - if (item != null) { - item.add(composeLineContent(child, numTmp)); // Appel - // recursif - } else { - result.add(composeLineContent(child, numTmp)); // Appel - // recursif - } - } - } - return result; - } - - /** - * @param lexer - * @return Element - * @throws Exception - */ - private Element composeDocument(JRSTLexer lexer) throws Exception { - Element result = DocumentHelper.createElement(DOCUMENT); - result.addAttribute(LEVEL, String.valueOf(MAX_SECTION_DEPTH - 1)); - - Element item = null; - - // skip blank line - skipBlankLine(lexer); - - // les liens anonymes - LinkedList<Element> items = lexer.refTarget(); - for (Element e : items) { - eTarget.add(e); - - } - - // le header - item = lexer.peekHeader(); - if (itemEquals(HEADER, item)) { - Element decoration = result.addElement(DECORATION); - Element header = decoration.addElement(HEADER); - header.addAttribute(ATTR_INLINE, TRUE).setText(item.getText()); - } - - // le footer - item = lexer.peekFooter(); - if (itemEquals(FOOTER, item)) { - footer = DocumentHelper.createElement(DECORATION); - Element header = footer.addElement(FOOTER); - header.addAttribute(ATTR_INLINE, TRUE).setText(item.getText()); - } - - // les hyperlinks - LinkedList<Element> listItem = lexer.peekTargetAnonymous(); - if (listItem != null) { - for (Element e : listItem) { - Element anonym = DocumentHelper.createElement(TARGET); - anonym.addAttribute(ANONYMOUS, "1"); - idMax++; - anonym.addAttribute(ATTR_IDS, ID + idMax); - - anonym.addAttribute(REFURI, e.attributeValue(REFURI).trim()); - - eTargetAnonymous.add(anonym); - eTargetAnonymousCopy.add(anonym); - } - } - - // les eléments a enlever (deja parser : header, footer...) - item = lexer.peekRemove(); - if (itemEquals(REMOVE, item)) { - lexer.remove(); - } - - // skip blank line - skipBlankLine(lexer); - - // les commentaires - List<Element> comments = lexer.peekAllComment(); - - // le titre du doc - item = lexer.peekTitle(); - if (itemEquals(TITLE, item)) { - lexer.remove(); - Element title = result.addElement(TITLE); - String txt = item.getText(); - result.addAttribute(ATTR_IDS, txt.replaceAll("[(\\W+)_]", " ") - .toLowerCase().trim().replaceAll("\\s+", "-")); - result.addAttribute(NAMES, txt.toLowerCase().replaceAll( - "[(\\W+)_&&[^\\:]]+", " ").trim()); - copyLevel(item, title); - title.addAttribute(ATTR_INLINE, TRUE).setText(txt.trim()); - } - - // skip blank line - skipBlankLine(lexer); - - // le sous titre du doc - item = lexer.peekTitle(); - if (itemEquals(TITLE, item)) { - lexer.remove(); - Element subtitle = result.addElement(SUBTITLE); - String txt = item.getText(); - subtitle.addAttribute(ATTR_IDS, txt.replaceAll("[(\\W+)_]", " ") - .toLowerCase().trim().replaceAll("\\s+", "-")); - subtitle.addAttribute(NAMES, txt.toLowerCase().replaceAll( - "[(\\W+)_]", " ").trim()); - copyLevel(item, subtitle); - DocumentHelper.createElement(FOOTNOTES); - subtitle.addAttribute(ATTR_INLINE, TRUE).setText(txt.trim()); - } - - // skip blank line - skipBlankLine(lexer); - - // les infos du doc - item = lexer.peekDocInfo(); - Element documentinfo = null; - while (itemEquals(DOCINFO, item) || itemEquals(FIELD_LIST, item)) { - - if (documentinfo == null) { - documentinfo = result.addElement(DOCINFO); - } - skipBlankLine(lexer); - if (itemEquals(FIELD_LIST, item)) { - Element field = composeFieldItemList(lexer); - documentinfo.add(field); - } else { - if ("author".equalsIgnoreCase(item.attributeValue(TYPE))) { - documentinfo.addElement(AUTHOR).addAttribute(ATTR_INLINE, - TRUE).setText(item.getText()); - } else if ("date".equalsIgnoreCase(item.attributeValue(TYPE))) { - documentinfo.addElement(DATE) - .addAttribute(ATTR_INLINE, TRUE).setText( - item.getText().trim()); - } else if ("organization".equalsIgnoreCase(item - .attributeValue(TYPE))) { - documentinfo.addElement(ORGANIZATION).addAttribute( - ATTR_INLINE, TRUE).setText(item.getText().trim()); - } else if ("contact".equalsIgnoreCase(item - .attributeValue(TYPE))) { - documentinfo.addElement(CONTACT).addAttribute(ATTR_INLINE, - TRUE).setText(item.getText().trim()); - } else if ("address".equalsIgnoreCase(item - .attributeValue(TYPE))) { - documentinfo.addElement(ADDRESS).addAttribute(ATTR_INLINE, - TRUE).setText(item.getText().trim()); - } else if ("version".equalsIgnoreCase(item - .attributeValue(TYPE))) { - documentinfo.addElement(VERSION).addAttribute(ATTR_INLINE, - TRUE).setText(item.getText().trim()); - } else if ("revision".equalsIgnoreCase(item - .attributeValue(TYPE))) { - documentinfo.addElement(REVISION).addAttribute(ATTR_INLINE, - TRUE).setText(item.getText().trim()); - } else if ("status".equalsIgnoreCase(item - .attributeValue(TYPE))) { - documentinfo.addElement(STATUS).addAttribute(ATTR_INLINE, - TRUE).setText(item.getText().trim()); - } else if ("copyright".equalsIgnoreCase(item - .attributeValue(TYPE))) { - documentinfo.addElement(COPYRIGHT).addAttribute(ATTR_INLINE, - TRUE).setText(item.getText().trim()); - } else if ("authors".equalsIgnoreCase(item - .attributeValue(TYPE))) { - Element authors = documentinfo.addElement(AUTHORS); - int t = 0; - String line = item.getText(); - for (int i = 0; i < line.length(); i++) { - if (line.charAt(i) == ';' || line.charAt(i) == ',') { - authors.addElement(AUTHOR).addAttribute(ATTR_INLINE, - TRUE) - .setText(line.substring(t, i).trim()); - t = i + 1; - } - - } - authors.addElement(AUTHOR).addAttribute(ATTR_INLINE, TRUE) - .setText(line.substring(t, line.length()).trim()); - } - lexer.remove(); - } - // skip blank line - // skipBlankLine(lexer); - item = lexer.peekDocInfo(); - - } - - // Ajout des commentaires - // System.out.println(comment.asXML()); - for (Element comment : comments){ - result.add(composeComment(comment)); - } - - // l'abstract du doc - item = lexer.peekTitle(); - while (itemNotEquals(TITLE, item) && !lexer.eof()) { - composeBody(lexer, result); - item = lexer.peekTitle(); - } - - // les sections - item = lexer.peekTitle(); - while (itemEquals(TITLE, item, true, lexer.eof())) { - Element section = composeSection(lexer); - result.add(section); - item = lexer.peekTitle(); - } - - // on ajoute le footer a la fin - if (footer != null) { - result.add(footer); - } - - return result; - } - - /** - * <p> - * skip blank line - * </p> - * - * @param lexer - * @throws DocumentException - * @throws IOException - */ - private void skipBlankLine(JRSTLexer lexer) throws IOException, - DocumentException { - Element item = lexer.peekBlankLine(); - // skip blank line - while (itemEquals(JRSTLexer.BLANK_LINE, item)) { - // go to the next element - lexer.remove(); - item = lexer.peekBlankLine(); - } - } - - /** - * * - * <p> - * Corps du document - * </p> - * - * @param lexer - * @return Element - * @throws DocumentException - * @throws IOException - */ - private Element composeBody(JRSTLexer lexer, Element parent) - throws Exception { - - Element item = lexer.peekTitleOrBodyElement(); - if (item == null && !lexer.eof()) { - item = lexer.peekTitleOrBodyElement(); - } - - while (!lexer.eof() && itemNotEquals(TITLE, item) - && isUpperLevel(item, parent)) { - if (itemEquals(JRSTLexer.BLANK_LINE, item)) { - // go to the next element - lexer.remove(); - } else if (itemEquals(REMOVE, item)) { - lexer.remove(); - } else if (itemEquals(INCLUDE, item)) { - lexer.remove(); - Element list = composeInclude(item); - parent.add(list); - } else if (itemEquals(DOCTEST_BLOCK, item)) { - lexer.remove(); - Element list = composeDoctestBlock(item); - parent.add(list); - } else if (itemEquals(ADMONITION, item)) { - lexer.remove(); - Element list = composeAdmonition(item); - parent.add(list); - } else if (itemEquals(SIDEBAR, item)) { - lexer.remove(); - Element list = composeSidebar(item); - parent.add(list); - } else if (itemEquals(TOPIC, item)) { - lexer.remove(); - Element list = composeTopic(item); - parent.add(list); - } else if (itemEquals(TRANSITION, item)) { - lexer.remove(); - Element para = parent.addElement(TRANSITION); - copyLevel(item, para); - } else if (itemEquals(PARAGRAPH, item)) { - lexer.remove(); - Element para = parent.addElement(PARAGRAPH); - copyLevel(item, para); - para.addAttribute(ATTR_INLINE, TRUE).setText(item.getText()); - } else if (itemEquals(JRSTLexer.DIRECTIVE, item)) { - lexer.remove(); - Node directive = composeDirective(item); - parent.add(directive); - } else if (itemEquals(SUBSTITUTION_DEFINITION, item)) { - lexer.remove(); - Element subst = composeSubstitutionDefinition(item); - parent.add(subst); - } else if (itemEquals(LITERAL_BLOCK, item)) { - lexer.remove(); - Element para = parent.addElement(LITERAL_BLOCK); - copyLevel(item, para); - para.setText(item.getText()); - } else if (itemEquals(JRSTLexer.TABLE, item)) { - lexer.remove(); - Element table = composeTable(item); - parent.add(table); - // Element para = parent.addElement(TABLE); - // copyLevel(item, para); - // para.setText(item.getText()); - } else if (itemEquals(LINE_BLOCK, item)) { - lexer.remove(); - Element list = composeLineBlock(lexer, item); - parent.add(list); - } else if (itemEquals(BULLET_LIST, item)) { - Element list = composeBulletList(lexer); - parent.add(list); - } else if (itemEquals(ENUMERATED_LIST, item)) { - Element list = composeEnumeratedList(lexer); - parent.add(list); - } else if (itemEquals(DEFINITION_LIST, item)) { - Element list = composeDefinitionList(lexer); - parent.add(list); - } else if (itemEquals(FIELD_LIST, item)) { - Element list = composeFieldList(lexer); - parent.add(list); - } else if (itemEquals(BLOCK_QUOTE, item)) { - lexer.remove(); - Element list = composeBlockQuote(item); - parent.add(list); - } else if (itemEquals(OPTION_LIST, item)) { - Element list = composeOptionList(lexer); - parent.add(list); - } else if (itemEquals(TARGET, item)) { - lexer.remove(); - Element list = composeTarget(item); - if (list != null) { - try { - parent.add(list); - } catch (IllegalAddException e) {} - } else - System.err.println("Unknown target name : \"" + item.attributeValue(ATTR_IDS) + "\""); - } else if (itemEquals(TARGETANONYMOUS, item)) { - lexer.remove(); - Element list = composeTargetAnonymous(item); - parent.add(list); - } else if (itemEquals(FOOTNOTES, item)) { - lexer.remove(); - Element[] list = composeFootnote(item); - for (Element l : list) { - parent.add(l); - } - } else if (itemEquals(COMMENT, item)) { - lexer.remove(); - Element list = composeComment(item); - parent.add(list); - } - - else { - if (ERROR_MISSING_ITEM) { - throw new DocumentException("Unknow item type: " - + item.getName()); - } else { - lexer.remove(); - } - } - - // Pour afficher le "PseudoXML" - // if (item!=null) System.out.println(item.asXML()); - - item = lexer.peekTitleOrBodyElement(); - } - - return parent; - } - - /** - * <p> - * include un document rst - * </p> - * - * <pre> - * .. include:: doc.rst - * </pre> - * - * <p> - * include un document literal (code...) - * </p> - * - * <pre> - * .. include:: literal - * doc.rst - * </pre> - * - * @param item - * @return Element - * @throws Exception - */ - private Element composeInclude(Element item) throws Exception { - String option = item.attributeValue(OPTION); - String path = item.getText(); - Element result = null; - if (option.equals(LITERAL)) { - result = DocumentHelper.createElement(LITERAL_BLOCK); - FileReader reader = new FileReader(path); - BufferedReader bf = new BufferedReader(reader); - String line = ""; - String lineTmp = bf.readLine(); - while (lineTmp != null) { - line += '\n' + lineTmp; - lineTmp = bf.readLine(); - } - result.setText(line); - } else { - File fileIn = new File(path); - URL url = fileIn.toURI().toURL(); - Reader in = new InputStreamReader(url.openStream()); - - Document doc = newJRSTReader(in); - - result = doc.getRootElement(); - } - return result; - } - - /** - * <pre> - * .. - * So this block is not "lost", - * despite its indentation. - * </pre> - * - * @param item - * @return Element - */ - private Element composeComment(Element item) { - - return item; - } - - /** - * <pre> - * __ http://truc.html - * </pre> - * - * @param item - * @return Element - */ - private Element composeTargetAnonymous(Element item) { - Element result = null; - result = eTargetAnonymousCopy.getFirst(); - eTargetAnonymousCopy.removeFirst(); - return result; - } - - /** - * <pre _ target: target.html </pre> - * - * @param item - * @return Element - */ - private Element composeTarget(Element item) { - Element result = null; - for (Element e : eTarget) { - if (e.attributeValue(ID).equals(item.attributeValue(ID))) { - result = e; - } - } - return result; - } - - /** - * <pre> - * .. [#] This is a footnote - * </pre> - * - * @param item - * @return Element - * @throws Exception - */ - private Element[] composeFootnote(Element item) throws Exception { - Element[] result = null; - if (itemEquals(FOOTNOTES, item)) { - List<Element> footnotes = (List<Element>) item - .selectNodes(FOOTNOTE); - result = new Element[footnotes.size()]; - int cnt = 0; - for (Element footnote : footnotes) { - result[cnt] = DocumentHelper.createElement(FOOTNOTE); - Element efootnote = DocumentHelper.createElement(FOOTNOTE); - int labelMax = 0; - - for (int i = 0; i < lblFootnotes.size(); i++) { - int lbl = lblFootnotes.get(i); - labelMax = Math.max(lbl, labelMax); - } - - boolean[] labels = new boolean[labelMax]; - for (int i = 0; i < labels.length; i++) { - labels[i] = false; - } - for (int i = 0; i < lblFootnotes.size(); i++) { - labels[lblFootnotes.get(i) - 1] = true; - } - idMax++; - String name = null; - String id = ""; - String label = null; - String type = footnote.attributeValue(TYPE); - if (type.equals(AUTONUM) || type.equals(AUTONUMLABEL)) { - result[cnt].addAttribute(AUTO, "1"); - } - if (type.equals(AUTOSYMBOL)) { - result[cnt].addAttribute(AUTO, "*"); - } - result[cnt].addAttribute(BACKREFS, ID + idMax); - efootnote.addAttribute(BACKREFS, ID + idMax); - if (type.equals(NUM) || type.equals(AUTONUMLABEL)) { - name = footnote.attributeValue(NAME); - if (type.equals(AUTONUMLABEL)) { - id = name; - } - else { - label = name; - } - } - if (type.equals(AUTONUM) || type.equals(AUTONUMLABEL)) { - boolean done = false; - - for (int i = 0; i < labels.length && !done; i++) { - if (!labels[i]) { - done = true; - label = "" + (i + 1); - } - } - if (!done) { - label = "" + (labels.length + 1); - } - if (type.equals(AUTONUM)) { - name = label; - } - } - if (type.equals(AUTOSYMBOL)) { - - int nb = Math.abs(symbolMax / 10) + 1; - char symbol = FOOTNOTE_SYMBOL.charAt(symbolMax % 10); - label = ""; - for (int j = 0; j < nb; j++) { - label += symbol; - } - symbolMax++; - - } - result[cnt].addAttribute(ATTR_IDS, "" + id); - efootnote.addAttribute(ATTR_IDS, "" + id); - if (!type.equals(AUTOSYMBOL)) { - result[cnt].addAttribute(NAME, "" + name); - efootnote.addAttribute(NAME, "" + name); - } - result[cnt].addElement(LABEL).setText("" + label); - efootnote.addAttribute(LABEL, "" + label); - if (!type.equals(AUTOSYMBOL)) { - lblFootnotes.add(Integer.parseInt(label)); - } - efootnote.addAttribute(TYPE, type); - eFootnotes.add(efootnote); - String text = footnote.getText(); - Document doc = newJRSTReader(new StringReader(text)); - result[cnt].appendContent(doc.getRootElement()); - - cnt++; - } - } - for (int i = 0; i < result.length; i++) { - if (result[i].attributeValue(ATTR_IDS).equals("")) { - idMax++; - result[i].addAttribute(ATTR_IDS, ID + idMax); - (eFootnotes.get(i)).addAttribute(ATTR_IDS, ID + idMax); - } - - } - - return result; - } - - /** - * <pre> - * -a command-line option "a" -1 file, --one=file, --two file Multiple - * options with arguments. - * </pre> - * - * @param lexer - * @return Element - * @throws Exception - * @throws DocumentException - */ - private Element composeOptionList(JRSTLexer lexer) - throws DocumentException, Exception { - Element item = lexer.peekOption(); - Element result = DocumentHelper.createElement(OPTION_LIST); - while (itemEquals(OPTION_LIST, item)) { - lexer.remove(); - Element optionListItem = result.addElement(OPTION_LIST_ITEM); - Element optionGroup = optionListItem.addElement(OPTION_GROUP); - List<Element> option = (List<Element>) item.selectNodes(OPTION); - for (Element e : option) { - Element eOption = optionGroup.addElement(OPTION); - eOption.addElement(OPTION_STRING).setText( - e.attributeValue(OPTION_STRING)); - if (e.attributeValue(DELIMITEREXISTE).equals(TRUE)) { - eOption.addElement(OPTION_ARGUMENT).addAttribute( - DELIMITER, e.attributeValue(DELIMITER)) - .setText(e.attributeValue(OPTION_ARGUMENT)); - } - } - Element description = optionListItem.addElement(DESCRIPTION); - - String text = item.getText(); - Document doc = newJRSTReader(new StringReader(text)); - description.appendContent(doc.getRootElement()); - - item = lexer.peekOption(); - } - return result; - } - - /** - * <pre> - * .. topic:: Title - * - * Body. - * </pre> - * - * @param Element - * item - * @return Element - * @throws Exception - */ - - private Element composeTopic(Element item) throws Exception { - Element result = null; - result = DocumentHelper.createElement(TOPIC); - result.addElement(TITLE).addAttribute(ATTR_INLINE, TRUE).setText( - item.attributeValue(TITLE)); - String text = item.getText(); - Document doc = newJRSTReader(new StringReader(text)); - result.appendContent(doc.getRootElement()); - - return result; - } - - /** - * <pre> - * .. sidebar:: Title - * :subtitle: If Desired - * - * Body. - * </pre> - * - * @param Element - * @return Element - * @throws Exception - */ - - private Element composeSidebar(Element item) throws Exception { - Element result = null; - result = DocumentHelper.createElement(SIDEBAR); - result.addElement(TITLE).addAttribute(ATTR_INLINE, TRUE).setText( - item.attributeValue(TITLE)); - if (item.attributeValue(SUBEXISTE).equals(TRUE)) { - result.addElement(SUBTITLE).addAttribute(ATTR_INLINE, TRUE).setText( - item.attributeValue(SUBTITLE)); - } - - String text = item.getText(); - Document doc = newJRSTReader(new StringReader(text)); - result.appendContent(doc.getRootElement()); - - return result; - } - - /** - * <pre> - * | line block - * | - * | indent - * </pre> - * - * @param lexer - * @param item - * @return Element - * @throws Exception - */ - private Element composeLineBlock(JRSTLexer lexer, Element item) - throws Exception { - Element result = null; - result = DocumentHelper.createElement(LINE_BLOCK); - List<Element> lines = (List<Element>) item.selectNodes(LINE); - int[] levels = new int[lines.size()]; - int cnt = 0; - for (Element l : lines) { - levels[cnt] = Integer.parseInt(l.attributeValue(LEVEL)); - cnt++; - } - cnt = 0; - boolean[] lineDone = new boolean[lines.size()]; - for (int i = 0; i < lineDone.length; i++) { - lineDone[i] = false; - } - for (Element l : lines) { - if (levels[cnt] == 0) { - result.addElement(LINE).addAttribute(ATTR_INLINE, TRUE).setText( - l.getText()); - } - else { - if (!lineDone[cnt]) { - Element newItem = DocumentHelper.createElement(LINE_BLOCK); - Boolean done = false; - for (int i = cnt; i < lines.size() && !done; i++) { - if (levels[i] > 0) { - Element eLine = newItem.addElement(LINE); - eLine.addAttribute(LEVEL, "" + (levels[i] - 1)); - eLine.setText(lines.get(i).getText()); - lineDone[i] = true; - } else { - done = true; - } - - } - Element eLineBlock = result.addElement(LINE_BLOCK); - // Appel recursif - eLineBlock.appendContent(composeLineBlock(lexer, newItem)); - } - } - cnt++; - - } - return result; - } - - /** - * <pre> - * >>> print 'this is a Doctest block' - * this is a Doctest block - * </pre> - * - * @param Element - * @return Element - */ - private Element composeDoctestBlock(Element item) { - return item; - } - - /** - * <pre> - * As a great paleontologist once said, - * - * This theory, that is mine, is mine. - * - * -- Anne Elk (Miss) - * </pre> - * - * @param Element - * @return Element - * @throws Exception - * - */ - private Element composeBlockQuote(Element item) throws Exception { - Element result = null; - result = DocumentHelper.createElement(BLOCK_QUOTE); - - String text = item.getText(); - Document doc = newJRSTReader(new StringReader(text)); - result.appendContent(doc.getRootElement()); - String sAttribution = item.attributeValue(ATTRIBUTION); - if (sAttribution != null) { - Element attribution = result.addElement(ATTRIBUTION); - attribution.setText(sAttribution); - attribution.addAttribute(ATTR_INLINE, TRUE); - } - return result; - } - - /** - * <pre> - * .. admonition:: And, by the way... - * - * You can make up your own admonition too. - * </pre> - * - * @param Element - * @return Element - * @throws Exception - * - */ - private Element composeAdmonition(Element item) throws Exception { - Element result = null; - if (item.attributeValue(TYPE).equalsIgnoreCase(ADMONITION)) { - result = DocumentHelper.createElement(ADMONITION); - String title = item.attributeValue(TITLE); - String admonitionClass = "admonition_" + title; - admonitionClass = admonitionClass.toLowerCase().replaceAll( - "\\p{Punct}", ""); - admonitionClass = admonitionClass.replace(' ', '-'); - admonitionClass = admonitionClass.replace('\n', '-'); - result.addAttribute(CLASS, admonitionClass); - result.addElement(TITLE).addAttribute(ATTR_INLINE, TRUE).setText( - title.trim()); - } else { - result = DocumentHelper.createElement(item.attributeValue(TYPE) - .toLowerCase()); - } - - String text = item.getText(); - Document doc = newJRSTReader(new StringReader(text)); - result.appendContent(doc.getRootElement()); - return result; - } - - /** - * parse all directives - * - * @param Element - * @return Node - */ - private Node composeDirective(Element item) { - Node result = item; - String type = item.attributeValue(JRSTLexer.DIRECTIVE_TYPE); - if (type.equals(SECTNUM)) { - sectnum = true; - } - JRSTDirective directive = getDirective(type); - if (directive == null) { - directive = getDefaultDirective(type); - } - if (directive != null) { - result = directive.parse(item); - } else { - log.warn("Unknow directive type '" + type + "' in: " + item); - } - return result; - } - - /** - * <pre> - * .. |biohazard| image:: biohazard.png - * </pre> - * - * @param Element - * @return Element - */ - private Element composeSubstitutionDefinition(Element item) { - Element result = item; - Element child = (Element) item.selectSingleNode("*"); - Node newChild = composeDirective(child); - result.remove(child); // remove old after composeDirective, because - // directive can be used this parent - result.add(newChild); - return result; - } - - /** - * <p> - * Complexe Table - * </p> - * - * <pre> - * +------------------------+------------+---------------------+ - * | body row 3 | Cells may | - Table cells | - * +------------------------+ span rows. | - contain | - * | body row 4 | | - body elements. | - * +------------------------+------------+---------------------+ - * </pre> - * - * <p> - * And simple table - * </p> - * - * <pre> - * ===== ===== ====== - * Inputs Output - * ============ ====== - * A B A or B - * ------------ ------ - * A B A or B - * ===== ===== ====== - * </pre> - * - * @param Element - * @return Element - * - */ - private Element composeTable(Element item) throws Exception { - - Element result = DocumentHelper.createElement(TABLE); - - int tableWidth = Integer.parseInt(item - .attributeValue(JRSTLexer.TABLE_WIDTH)); - - TreeSet<Integer> beginCellList = new TreeSet<Integer>(); - - for (Element cell : (List<Element>) item.selectNodes(JRSTLexer.ROW - + "/" + JRSTLexer.CELL)) { - Integer begin = Integer.valueOf(cell - .attributeValue(JRSTLexer.CELL_INDEX_START)); - beginCellList.add(begin); - } - - int[] beginCell = new int[beginCellList.size() + 1]; // + 1 to put - // table width - // to simulate - // new cell - int[] lengthCell = new int[beginCellList.size()]; - - int cellNumber = 0; - for (int b : beginCellList) { - beginCell[cellNumber] = b; - if (cellNumber > 0) { - lengthCell[cellNumber - 1] = beginCell[cellNumber] - - beginCell[cellNumber - 1]; - } - cellNumber++; - } - beginCell[cellNumber] = tableWidth; - lengthCell[cellNumber - 1] = beginCell[cellNumber] - - beginCell[cellNumber - 1]; - - Element tgroup = result.addElement(TGROUP).addAttribute("cols", - String.valueOf(cellNumber)); - for (int width : lengthCell) { - tgroup.addElement(COLSPEC).addAttribute("colwidth", - String.valueOf(width)); - } - - Element rowList = null; - if (TRUE.equals(item.attributeValue(JRSTLexer.TABLE_HEADER))) { - rowList = tgroup.addElement(THEAD); - } else { - rowList = tgroup.addElement(TBODY); - } - List<Element> rows = (List<Element>) item.selectNodes(JRSTLexer.ROW); - for (int r = 0; r < rows.size(); r++) { - Element row = rowList.addElement(ROW); - List<Element> cells = (List<Element>) rows.get(r).selectNodes( - JRSTLexer.CELL); - for (int c = 0; c < cells.size(); c++) { - Element cell = cells.get(c); - // si la cellule a ete utilise pour un regroupement vertical on - // la passe - if (!TRUE.equals(cell.attributeValue("used"))) { - Element entry = row.addElement(ENTRY); - String text = ""; - - // on regroupe les cellules verticalement - int morerows = -1; - Element tmpCell = null; - String cellStart = cell - .attributeValue(JRSTLexer.CELL_INDEX_START); - do { - morerows++; - tmpCell = (Element) rows.get(r + morerows) - .selectSingleNode( - JRSTLexer.CELL + "[@" - + JRSTLexer.CELL_INDEX_START - + "=" + cellStart + "]"); - text += tmpCell.getText(); - // on marque la cellule comme utilise - tmpCell.addAttribute("used", TRUE); - } while (!TRUE.equals(tmpCell - .attributeValue(JRSTLexer.CELL_END))); - - if (morerows > 0) { - entry - .addAttribute("morerows", String - .valueOf(morerows)); - } - - // on compte le nombre de cellules regroupees - // horizontalement - int morecols = 0; - tmpCell = cells.get(c + morecols); - int cellEnd = Integer.parseInt(tmpCell - .attributeValue(JRSTLexer.CELL_INDEX_END)); - while (cellEnd + 1 != beginCell[c + morecols + 1]) { - morecols++; - // tmpCell = cells.get(c + morecols); - // cellEnd = - // Integer.parseInt(tmpCell.attributeValue(JRSTLexer. - // CELL_INDEX_END)); - } - if (morecols > 0) { - entry - .addAttribute("morecols", String - .valueOf(morecols)); - } - // parse entry text in table - Document doc = newJRSTReader(new StringReader(text)); - entry.appendContent(doc.getRootElement()); - } - } - if (TRUE.equals(rows.get(r).attributeValue( - JRSTLexer.ROW_END_HEADER))) { - rowList = tgroup.addElement(TBODY); - } - } - - return result; - } - - /** - * <p> - * items begin with "-", "+", or "*" - * </p> - * - * <pre> - * * aaa - * - bbb - * * ccc - * - ddd - * + eee - * </pre> - * - * @param lexer - * @return Element - * @throws Exception - */ - private Element composeBulletList(JRSTLexer lexer) throws Exception { - Element item = lexer.peekBulletList(); - Element result = DocumentHelper.createElement(BULLET_LIST); - copyLevel(item, result); - result.addAttribute(BULLET, item.attributeValue(BULLET)); - while (itemEquals(BULLET_LIST, item) && isSameLevel(item, result) - && hasSameAttribute(item, result, BULLET)) { - lexer.remove(); - Element bullet = result.addElement(LIST_ITEM); - copyLevel(item, bullet); - bullet.addElement(PARAGRAPH).addAttribute(ATTR_INLINE, TRUE) - .setText(item.getText()); - composeBody(lexer, bullet); - - item = lexer.peekBulletList(); - } - return result; - } - - /** - * <pre> - * 3. et meme - * * #. pour voir - * * I) de tout - * (a) pour tout - * (#) vraiment tout - * </pre> - * - * @param lexer - * @return Element - * @throws Exception - */ - private Element composeEnumeratedList(JRSTLexer lexer) throws Exception { - Element item = lexer.peekEnumeratedList(); - Element result = DocumentHelper.createElement(ENUMERATED_LIST); - copyLevel(item, result); - String enumType = item.attributeValue(ENUMTYPE); - if (!enumType.equals("arabic")) { - result.addAttribute(START, item.attributeValue(START)); - } - result.addAttribute(PREFIX, item.attributeValue(PREFIX)); - result.addAttribute(SUFFIX, item.attributeValue(SUFFIX)); - result.addAttribute(ENUMTYPE, enumType); - while (itemEquals(ENUMERATED_LIST, item) - && isSameLevel(item, result) - && hasSameAttribute(item, result, PREFIX, SUFFIX) - && (AUTO.equals(item.attributeValue(ENUMTYPE)) || hasSameAttribute( - item, result, ENUMTYPE))) { - lexer.remove(); - Element e = result.addElement(LIST_ITEM); - copyLevel(item, e); - e.addElement(PARAGRAPH).addAttribute(ATTR_INLINE, TRUE).setText( - item.getText()); - composeBody(lexer, e); - - item = lexer.peekEnumeratedList(); - } - return result; - } - - /** - * <pre> - * le mot : la classe - * la definition - * </pre> - * - * @param lexer - * @return Element - * @throws Exception - */ - private Element composeDefinitionList(JRSTLexer lexer) throws Exception { - Element item = lexer.peekBodyElement(); - Element result = DocumentHelper.createElement(DEFINITION_LIST); - copyLevel(item, result); - while (itemEquals(DEFINITION_LIST, item) && isSameLevel(item, result)) { - lexer.remove(); - Element def = result.addElement(DEFINITION_LIST_ITEM); - copyLevel(item, def); - - Element term = def.addElement(TERM); - copyLevel(item, term); - term.addAttribute(ATTR_INLINE, TRUE).setText( - item.attributeValue("term")); - - String[] classifiers = StringUtil.split(item - .attributeValue("classifiers"), " : "); - for (String classifierText : classifiers) { - Element classifier = def.addElement("classifier"); - copyLevel(item, classifier); - classifier.addAttribute(ATTR_INLINE, TRUE).setText( - classifierText); - } - - Element definition = def.addElement(DEFINITION); - definition.addElement(PARAGRAPH).addAttribute(ATTR_INLINE, TRUE) - .setText(item.getText()); - copyLevel(item, definition); - - composeBody(lexer, definition); - - item = lexer.peekBodyElement(); - } - return result; - } - - /** - * <pre> - * :un peu: de field - * ca ne fait pas - * de mal - * </pre> - * - * @param lexer - * @return Element - * @throws Exception - */ - private Element composeFieldList(JRSTLexer lexer) throws Exception { - Element item = lexer.peekBodyElement(); - Element result = DocumentHelper.createElement(FIELD_LIST); - copyLevel(item, result); - while (itemEquals(FIELD_LIST, item) && isSameLevel(item, result)) { - Element field = composeFieldItemList(lexer); - result.add(field); - item = lexer.peekBodyElement(); - } - return result; - } - - /** - * <pre> - * :field1: avec un - * petit texte - * - et meme un - * - debut - * - de list - * </pre> - * - * @param lexer - * @return Element - * @throws Exception - */ - private Element composeFieldItemList(JRSTLexer lexer) throws Exception { - Element item = lexer.peekFieldList(); - if (itemEquals(FIELD_LIST, item)) { - lexer.remove(); - Element field = DocumentHelper.createElement(FIELD); - copyLevel(item, field); - Element fieldName = field.addElement(FIELD_NAME); - copyLevel(item, fieldName); - fieldName.addAttribute(ATTR_INLINE, TRUE).setText( - item.attributeValue(NAME)); - Element fieldBody = field.addElement(FIELD_BODY); - fieldBody.addElement(PARAGRAPH).addAttribute(ATTR_INLINE, TRUE) - .setText(item.getText()); - copyLevel(item, fieldBody); - composeBody(lexer, fieldBody); - - return field; - } else { - throw new DocumentException("Waiting for " + FIELD_LIST - + " and found " + item.getName()); - } - } - - /** - * <pre> - * DEFINITIONS - * ----------- - * </pre> - * - * @param lexer - * @return Element - * @throws Exception - */ - private Element composeSection(JRSTLexer lexer) throws Exception { - Element result = DocumentHelper.createElement(SECTION); - Element firstTitle = null; - - Element item = null; - - // le titre de la section - item = lexer.peekTitle(); - if (itemEquals(TITLE, item, true, lexer.eof())) { - lexer.remove(); - firstTitle = item; - Element title = result.addElement(TITLE); - copyLevel(item, result); - copyLevel(item, title); - title.addAttribute(ATTR_INLINE, TRUE).setText(item.getText().trim()); - result.addAttribute(ID, item.getText().replaceAll("\\W+", " ") - .trim().toLowerCase().replaceAll("\\W+", "-")); - result.addAttribute(NAME, item.getText().toLowerCase().trim()); - eTitle.add(title); - } - - // le contenu de la section - item = lexer.peekTitle(); - while (itemNotEquals(TITLE, item) && !lexer.eof()) { - composeBody(lexer, result); - item = lexer.peekTitle(); - } - - // les sous sections - item = lexer.peekTitle(); - while (itemEquals(TITLE, item) && isUpperLevel(item, firstTitle)) { - Element section = composeSection(lexer); - result.add(section); - item = lexer.peekTitle(); - } - - return result; - } - - /** - * Indique si la sous section est bien une sous section, c-a-d dire que son - * level est superieur a celui de la section - * - * @param item - * @param firstTitle - * @return boolean - * @throws DocumentException - */ - private boolean isUpperLevel(Element subSection, Element section) - throws DocumentException { - // if (!(itemEquals(SECTION, subSection) && itemEquals(SECTION, - // section)) - // || itemEquals(DOCUMENT, section) || itemEquals(SECTION, section)) { - // // all element is upper than Document or section - // return true; - // } - int subSectionLevel = Integer.parseInt(subSection - .attributeValue(LEVEL)); - int sectionLevel = Integer.parseInt(section.attributeValue(LEVEL)); - boolean result = subSectionLevel > sectionLevel; - return result; - } - - /** - * Indique si les deux elements sont au meme niveau - * - * @param item - * @param firstTitle - * @return boolean - * @throws DocumentException - */ - private boolean isSameLevel(Element subSection, Element section) - throws DocumentException { - // if (itemEquals(DOCUMENT, section) || itemEquals(SECTION, section)) { - // // all element is upper than Document or section - // return false; - // } - int subSectionLevel = Integer.parseInt(subSection - .attributeValue(LEVEL)); - int sectionLevel = Integer.parseInt(section.attributeValue(LEVEL)); - boolean result = subSectionLevel == sectionLevel; - return result; - } - - /** - * @param Element - * e1 - * @param Element - * e2 - * @param String - * ... attnames - * @return boolean - */ - private boolean hasSameAttribute(Element e1, Element e2, String... attnames) { - boolean result = true; - for (String attname : attnames) { - String a1 = e1.attributeValue(attname); - String a2 = e2.attributeValue(attname); - if (!ObjectUtils.equals(a1, a2)) { - result = false; - break; - } - } - return result; - } - - /** - * @param Element - * from - * @param Element - * to - * @throws DocumentException - */ - private void copyLevel(Element from, Element to) throws DocumentException { - String level = from.attributeValue(LEVEL); - if (level == null) { - throw new DocumentException("Element without level: " + from); - } - to.addAttribute(LEVEL, level); - } - - /** - * @param String - * name - * @param Element - * e - * @return boolean - * @throws DocumentException - */ - private boolean itemEquals(String name, Element e) throws DocumentException { - boolean result = itemEquals(name, e, false, false); - return result; - } - - /** - * @param String - * name - * @param Element - * e - * @param throwError - * @param eof - * @return boolean - * @throws DocumentException - */ - private boolean itemEquals(String name, Element e, boolean throwError, - boolean eof) throws DocumentException { - boolean result = e != null && name.equals(e.getName()); - if (ERROR_MISSING_ITEM && !result && throwError && !eof) { - throw new DocumentException("Malformed document waiting " + name - + " and found " + (e != null ? e.getName() : "null")); - } - return result; - } - - /** - * @param String - * name - * @param Element - * e - * @return boolean - */ - private boolean itemNotEquals(String name, Element e) { - boolean result = e == null || !name.equals(e.getName()); - return result; - } - - private Document newJRSTReader(Reader r) throws Exception { - JRSTReader reader = new JRSTReader(); - reader.setVariable(idMax, symbolMax, symbolMaxRef, lblFootnotes, - lblFootnotesRef, eFootnotes, eTarget, eTargetAnonymous, - eTargetAnonymousCopy); - - return reader.read(r); - - } - - /** - * <p> - * Initialises les variables d'environements par ex, les hyperlinks peuvent - * etre referencer dans tous le document - * </p> - * - * @param idMax - * @param symbolMax - * @param symbolMaxRef - * @param lblFootnotes - * @param lblFootnotesRef - * @param eFootnotes - * @param eTarget - * @param eTargetAnonymous - * @param eTargetAnonymousCopy - */ - public void setVariable(int idMax, int symbolMax, int symbolMaxRef, - LinkedList<Integer> lblFootnotes, - LinkedList<Integer> lblFootnotesRef, - LinkedList<Element> eFootnotes, LinkedList<Element> eTarget, - LinkedList<Element> eTargetAnonymous, - LinkedList<Element> eTargetAnonymousCopy) { - this.idMax = idMax; - this.symbolMax = symbolMax; - this.symbolMaxRef = symbolMaxRef; - this.lblFootnotes = lblFootnotes; - this.lblFootnotesRef = lblFootnotesRef; - this.eFootnotes = eFootnotes; - this.eTarget = eTarget; - this.eTargetAnonymous = eTargetAnonymous; - this.eTargetAnonymousCopy = eTargetAnonymousCopy; - } - - /** - * Parse text in element and replace text with parse result - * - * @param Element - * e - * @throws DocumentException - * @throws UnsupportedEncodingException - */ - - private void inline(Element e) throws DocumentException, UnsupportedEncodingException { - String text = e.getText(); - - text = StringEscapeUtils.escapeXml(text); - // search all LITERAL and replace it with special mark - // this prevent substitution in literal, example **something** must not - // change in literal - Map<String, String> temporaries = new HashMap<String, String>(); - Matcher matcher = REGEX_LITERAL.matcher(text); - int index = 0; - while (matcher.find()) { - int start = matcher.start(); - int end = matcher.end(); - String literal = "<" + LITERAL + ">" + matcher.group(1) + "</" - + LITERAL + ">"; - String key = LITERAL + index++; - temporaries.put(key, literal); - text = text.substring(0, start) + "<tmp>" + key + "</tmp>" - + text.substring(end); - matcher = REGEX_LITERAL.matcher(text); - } - // search all REGEX_INLINE_REFERENCE and replace it with special mark - // this prevent substitution of URL with REGEX_REFERENCE. Use same - // mechanisme as literal for that - matcher = REGEX_INLINE_REFERENCE.matcher(text); - index = 0; - while (matcher.find()) { - int start = matcher.start(); - int end = matcher.end(); - Element ref = DocumentHelper.createElement(REFERENCE); - ref.addAttribute(REFURI, StringEscapeUtils.unescapeXml(matcher.group(2))); - ref.setText(StringEscapeUtils.unescapeXml(matcher.group(1))); - String key = "inlineReference" + index++; - temporaries.put(key, ref.asXML()); - text = text.substring(0, start) + "<tmp>" + key + "</tmp>" - + text.substring(end); - matcher = REGEX_INLINE_REFERENCE.matcher(text); - - } - // do all substitution inline - text = REGEX_EMAIL.matcher(text).replaceAll( - "$1<" + REFERENCE + " refuri='mailto:$2'>$2</" + REFERENCE - + ">$3"); - text = REGEX_STRONG.matcher(text).replaceAll( - "<" + STRONG + ">$1</" + STRONG + ">"); - text = REGEX_EMPHASIS.matcher(text).replaceAll( - "<" + EMPHASIS + ">$1</" + EMPHASIS + ">"); - text = REGEX_REFERENCE.matcher(text).replaceAll( - "<" + REFERENCE + " refuri='$1'>$1</" + REFERENCE + ">$2"); - // _[#]truc - matcher = REGEX_FOOTNOTE_REFERENCE.matcher(text); - while (matcher.find()) { - String txtDebut = text.substring(0, matcher.start()); - String txtFin = text.substring(matcher.end()-1, text.length()-1); - Element footnote = DocumentHelper.createElement(FOOTNOTE_REFERENCE); - String sFootnote = matcher.group(); - boolean done = false; - for (int i = 0; i < sFootnote.length() && !done; i++) { - if (sFootnote.charAt(i) == ']') { - String id = sFootnote.substring(1, i); - if (id.equals("*")) { - int nb = Math.abs(symbolMaxRef / 10) + 1; - char symbol = FOOTNOTE_SYMBOL.charAt(symbolMaxRef % 10); - String label = ""; - for (int j = 0; j < nb; j++) { - label += symbol; - } - symbolMaxRef++; - footnote.addAttribute(AUTO, "*"); - for (int j = 0; j < eFootnotes.size(); j++) { - Element eFootnote = eFootnotes.get(j); - if (eFootnote.attributeValue(LABEL).equals(label)) { - - footnote.addAttribute(ATTR_IDS, eFootnote - .attributeValue(BACKREFS)); - footnote.addAttribute(ATTR_REFID, eFootnote - .attributeValue(ATTR_IDS)); - - } - } - footnote.setText(label); - - } else if (id.matches("[1-9]+")) { - - for (int j = 0; j < eFootnotes.size(); j++) { - Element eFootnote = eFootnotes.get(j); - if (eFootnote.attributeValue(LABEL).equals(id)) { - footnote.addAttribute(ATTR_IDS, eFootnote - .attributeValue(BACKREFS)); - footnote.addAttribute(ATTR_REFID, eFootnote - .attributeValue(ATTR_IDS)); - } - } - footnote.setText(id); - lblFootnotesRef.add(Integer.parseInt(id)); - - } else if (id.equals("#")) { - int lblMax = 0; - for (int j = 0; j < lblFootnotesRef.size(); j++) { - lblMax = Math.max(lblMax, lblFootnotesRef.get(j)); - } - - boolean[] lbls = new boolean[lblMax]; - for (int j = 0; j < lbls.length; j++) { - lbls[j] = false; - } - for (int j = 0; j < lblFootnotesRef.size(); j++) { - lbls[lblFootnotesRef.get(j) - 1] = true; - } - boolean valide = false; - do { - boolean trouve = false; - String label = null; - for (int j = 0; j < lbls.length && !trouve; j++) { - - if (!lbls[j]) { - trouve = true; - label = "" + (j + 1); - } - } - if (!trouve) { - label = "" + (lbls.length + 1); - } - footnote.addAttribute(AUTO, "1"); - for (int j = 0; j < eFootnotes.size(); j++) { - Element eFootnote = eFootnotes.get(j); - if (eFootnote.attributeValue(LABEL).equals( - label)) { - if (!(eFootnote.attributeValue(TYPE) - .equals(AUTONUMLABEL))) { - footnote.addAttribute(ATTR_IDS, eFootnote - .attributeValue(BACKREFS)); - footnote.addAttribute(ATTR_REFID, - eFootnote.attributeValue(ATTR_IDS)); - footnote.setText(label); - lblFootnotesRef.add(Integer - .parseInt(label)); - valide = true; - } else { - valide = false; - lbls[Integer.parseInt(label) - 1] = true; - } - } - } - } while (!valide); - - } - - else { - footnote.addAttribute(AUTO, "1"); - - String name = id.substring(1); - boolean trouve = false; - for (int j = 0; j < eFootnotes.size() && !trouve; j++) { - Element eFootnote = eFootnotes.get(j); - if (eFootnote.attributeValue(NAMES).equals(name)) { - footnote.addAttribute(ATTR_IDS, eFootnote - .attributeValue(BACKREFS)); - footnote.addAttribute(ATTR_REFID, eFootnote - .attributeValue(ATTR_IDS)); - String label = eFootnote - .attributeValue(LABEL); - footnote.setText(label); - lblFootnotesRef.add(Integer.parseInt(label)); - trouve = true; - } - } - - footnote.addAttribute(NAMES, name); - } - done = true; - } - } - text = txtDebut + footnote.asXML() + txtFin; - matcher = REGEX_FOOTNOTE_REFERENCE.matcher(text); - } - // .. __http://truc.html - matcher = REGEX_ANONYMOUS_HYPERLINK_REFERENCE.matcher(text); - while (matcher.find()) { - String txtDebut = text.substring(0, matcher.start()); - String txtFin = text.substring(matcher.end(), text.length()); - String ref = text.substring(matcher.start(), matcher.end() - 2); - ref = ref.replaceAll("`", ""); - Element anonym = DocumentHelper.createElement(REFERENCE); - anonym.addAttribute(ANONYMOUS, "1"); - anonym.addAttribute(NAME, ref.trim()); - if (!eTargetAnonymous.isEmpty()) { - Element target = eTargetAnonymous.getFirst(); - eTargetAnonymous.removeFirst(); - anonym.addAttribute(REFURI, target.attributeValue(REFURI)); - } - anonym.setText(ref); - text = txtDebut + anonym.asXML() + txtFin; - matcher = REGEX_ANONYMOUS_HYPERLINK_REFERENCE.matcher(text); - } - // .. _truc: http://truc.html - matcher = REGEX_HYPERLINK_REFERENCE.matcher(text); - while (matcher.find()) { - String txtDebut = text.substring(0, matcher.start()); - String txtFin = text.substring(matcher.end(), text.length()); - String ref = text.substring(matcher.start(), matcher.end() - 1); - ref = StringEscapeUtils.unescapeXml(ref); - ref = ref.replaceAll("('|_)", ""); - ref = ref.replaceAll("`", ""); - Element hyper = DocumentHelper.createElement(REFERENCE); - hyper.addAttribute(NAME, ref); - boolean trouve = false; - for (int i = 0; i < eTarget.size() && !trouve; i++) { - Element el = eTarget.get(i); - String refTmp = URLEncoder.encode(ref.replaceAll("\\s", "-").toLowerCase(), "UTF-8"); - if (el.attributeValue(ID).equalsIgnoreCase((refTmp))) { - hyper.addAttribute(REFURI, el.attributeValue(REFURI)); - trouve = true; - } - } - if (!trouve) { - hyper.addAttribute(ATTR_REFID, ref); - } - hyper.setText(ref); - text = txtDebut + hyper.asXML() + " " + txtFin; - matcher = REGEX_HYPERLINK_REFERENCE.matcher(text); - - } - - // substitution reference - matcher = REGEX_SUBSTITUTION_REFERENCE.matcher(text); - int begin = 0; - while (matcher.find(begin)) { - String start = text.substring(0, matcher.start()); - String end = text.substring(matcher.end()); - String ref = matcher.group(1); - - Node subst = e.selectSingleNode("//" + SUBSTITUTION_DEFINITION - + "[@name='" + ref + "']/child::node()"); - - if (subst == null) { - text = start + "|" + ref + "|"; - } else { - text = start + subst.asXML(); - } - - begin = text.length(); - text += end; - matcher = REGEX_SUBSTITUTION_REFERENCE.matcher(text); - - } - // undo substitution in LITERAL - Pattern p = Pattern.compile("<tmp>([^<>]+)</tmp>"); - - matcher = p.matcher(text); - while (matcher.find()) { - String start = text.substring(0, matcher.start()); - String end = text.substring(matcher.end()); - - String tempKey = matcher.group(1); - text = start + temporaries.get(tempKey) + end; - matcher = p.matcher(text); - } - - String resultElementText = text.trim(); - Element result = DocumentHelper.parseText( - "<TMP>" + resultElementText + "</TMP>").getRootElement(); - - e.setText(""); - e.appendContent(result); - } -} Deleted: branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/ReStructuredText.java =================================================================== --- branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/ReStructuredText.java 2012-06-04 16:16:06 UTC (rev 695) +++ branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/ReStructuredText.java 2012-06-05 14:44:35 UTC (rev 696) @@ -1,215 +0,0 @@ -/* - * #%L - * JRst :: Api - * - * $Id$ - * $HeadURL$ - * %% - * Copyright (C) 2004 - 2010 CodeLutin - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ - -package org.nuiton.jrst; - -import java.util.regex.Pattern; - -/** - * ReStructuredText. - * - * Created: 27 oct. 06 11:10:30 - * - * @author poussin - * @version $Revision$ - * - * Last update: $Date$ - * by : $Author$ - */ -public class ReStructuredText { - - public static final String DTD = "http://docutils.sourceforge.net/docs/ref/docutils.dtd"; - - public static final String TITLE_CHAR = "-=-~'`^+:!\"#$%&*,./;|?@\\_[\\]{}<>()"; - public static final String QUOTED_CHAR = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"; - public static final String BULLET_CHAR = "*" + "+" + "-" + "\u2022" - + "\u2023" + "\u2043"; - public static final String DOCINFO_ITEM = "author|authors|organization|address|contact|version|revision|status|date|copyright"; - public static final String FOOTNOTE_SYMBOL = "\u002A" + "\u2020" + "\u2021" - + "\u00A7" + "\u00B6" + "\u0023" + "\u2660" + "\u2665" + "\u2666" - + "\u2663"; - // public static final String ADMONITION = - // "admonition|caution|danger|error|hint|important|note|tip|warning"; - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // Root Element - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - public static final String DOCUMENT = "document"; - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // Title Elements - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - public static final String TITLE = "title"; - public static final String SUBTITLE = "subtitle"; - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // Bibliographic Elements - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - public static final String DOCINFO = "docinfo"; - // public static final String INFO = "info"; - public static final String AUTHOR = "author"; - public static final String AUTHORS = "authors"; - public static final String ORGANIZATION = "organization"; - public static final String ADDRESS = "address"; - public static final String CONTACT = "contact"; - public static final String VERSION = "version"; - public static final String REVISION = "revision"; - public static final String STATUS = "status"; - public static final String DATE = "date"; - public static final String COPYRIGHT = "copyright"; - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // Decoration Elements - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - public static final String DECORATION = "decoration"; - public static final String HEADER = "header"; - public static final String FOOTER = "footer"; - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // Structural Elements - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - public static final String SECTION = "section"; - public static final String TOPIC = "topic"; - public static final String SIDEBAR = "sidebar"; - public static final String TRANSITION = "transition"; - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // Body Elements - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - public static final String PARAGRAPH = "paragraph"; - public static final String COMPOUND = "compound"; - public static final String CONTAINER = "container"; - public static final String BULLET_LIST = "bullet_list"; - public static final String ENUMERATED_LIST = "enumerated_list"; - public static final String LIST_ITEM = "list_item"; - public static final String DEFINITION_LIST = "definition_list"; - public static final String DEFINITION_LIST_ITEM = "definition_list_item"; - public static final String TERM = "term"; - public static final String CLASSIFIER = "classifier"; - public static final String DEFINITION = "definition"; - public static final String FIELD_LIST = "field_list"; - public static final String FIELD = "field"; - public static final String FIELD_NAME = "field_name"; - public static final String FIELD_BODY = "field_body"; - public static final String OPTION_LIST = "option_list"; - public static final String OPTION_LIST_ITEM = "option_list_item"; - public static final String OPTION_GROUP = "option_group"; - public static final String OPTION = "option"; - public static final String OPTION_STRING = "option_string"; - public static final String OPTION_ARGUMENT = "option_argument"; - public static final String DESCRIPTION = "description"; - public static final String LITERAL_BLOCK = "literal_block"; - public static final String LINE_BLOCK = "line_block"; - public static final String LINE = "line"; - public static final String BLOCK_QUOTE = "block_quote"; - public static final String ATTRIBUTION = "attribution"; - public static final String DOCTEST_BLOCK = "doctest_block"; - public static final String ATTENTION = "attention"; - public static final String CAUTION = "caution"; - public static final String DANGER = "danger"; - public static final String ERROR = "error"; - public static final String HINT = "hint"; - public static final String IMPORTANT = "important"; - public static final String NOTE = "note"; - public static final String TIP = "tip"; - public static final String WARNING = "warning"; - public static final String ADMONITION = "admonition"; - public static final String FOOTNOTE = "footnote"; - public static final String CITATION = "citation"; - public static final String LABEL = "label"; - public static final String RUBRIC = "rubric"; - public static final String TARGET = "target"; - public static final String SUBSTITUTION_DEFINITION = "substitution_definition"; - public static final String COMMENT = "comment"; - public static final String PENDING = "pending"; - public static final String FIGURE = "figure"; - public static final String IMAGE = "image"; - public static final String CAPTION = "caption"; - public static final String LEGEND = "legend"; - public static final String SYSTEM_MESSAGE = "system_message"; - public static final String RAW = "raw"; - - // table - public static final String TABLE = "table"; - public static final String TGROUP = "tgroup"; - public static final String COLSPEC = "colspec"; - public static final String THEAD = "thead"; - public static final String TBODY = "tbody"; - public static final String ROW = "row"; - public static final String ENTRY = "entry"; - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // Inline Elements - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - public static final String EMPHASIS = "emphasis"; - public static final String STRONG = "strong"; - public static final String LITERAL = "literal"; - public static final String REFERENCE = "reference"; - public static final String FOOTNOTE_REFERENCE = "footnote_reference"; - public static final String CITATION_REFERENCE = "citation_reference"; - public static final String SUBSTITUTION_REFERENCE = "substitution_reference"; - public static final String TITLE_REFERENCE = "title_reference"; - public static final String ABBREVIATION = "abbreviation"; - public static final String ACRONYM = "acronym"; - public static final String SUPERSCRIPT = "superscript"; - public static final String SUBSCRIPT = "subscript"; - public static final String INLINE = "inline"; - public static final String PROBLEMATIC = "problematic"; - public static final String GENERATED = "generated"; - - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // Inline Elements Regex - // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - public static final Pattern REGEX_EMPHASIS = Pattern - .compile("\\*([^*(\\]_.+\\[)].+?)\\*"); - public static final Pattern REGEX_STRONG = Pattern - .compile("\\*\\*(.+?)\\*\\*"); - public static final Pattern REGEX_LITERAL = Pattern.compile("``([^`]+)``"); - public static final Pattern REGEX_REFERENCE = Pattern - .compile("(https?://[-/%#[\\&&&[^(>)]]\\._\\w:]+\\w+)((\\W|&|$)+)"); - public static final Pattern REGEX_INLINE_REFERENCE = Pattern - .compile("`(.+?) \\<\\;((https?://)?[-/%#&\\._\\w:[^ ]]+)(\\>\\;)`_"); - public static final Pattern REGEX_EMAIL = Pattern - .compile("(^|[^_\\w])([-\\._\\w]+@[-\\._\\w]+)([^-\\._\\w]|$)"); - public static final Pattern REGEX_FOOTNOTE_REFERENCE = Pattern - .compile("\\[(#|[0-9]|\\*)\\w*\\]_"); - // "\\[([0-9]+?|#)\\]"); - public static final Pattern REGEX_CITATION_REFERENCE = Pattern - .compile("\\[([^\\]]+?)\\]"); - public static final Pattern REGEX_SUBSTITUTION_REFERENCE = Pattern - .compile("\\|([^|]+?)\\|"); - public static final Pattern REGEX_ABBREVIATION = Pattern.compile("(.*?)"); - public static final Pattern REGEX_ACRONYM = Pattern.compile("(.*?)"); - public static final Pattern REGEX_SUPERSCRIPT = Pattern.compile("(.*?)"); - public static final Pattern REGEX_SUBSCRIPT = Pattern.compile("(.*?)"); - public static final Pattern REGEX_INLINE = Pattern.compile("(.*?)"); - public static final Pattern REGEX_PROBLEMATIC = Pattern.compile("(.*?)"); - public static final Pattern REGEX_GENERATED = Pattern.compile("(.*?)"); - // `truc truc`_ - public static final Pattern REGEX_HYPERLINK_REFERENCE = Pattern - .compile("(\\`[^_<>]+\\`_(\\W|$))|(('|`)[^_<`(')>]+('|`)_(\\W|$))|([\\S]+[^\\s<>\\.`]+_(\\W|$))"); - // `trux truc`__ - public static final Pattern REGEX_ANONYMOUS_HYPERLINK_REFERENCE = Pattern - .compile("(\\`[^<>`\\]\\[]+\\`__)|(\\w+[^()`\\s<>]+__)"); -} Modified: branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/convertisor/DocUtils2RST.java =================================================================== --- branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/convertisor/DocUtils2RST.java 2012-06-04 16:16:06 UTC (rev 695) +++ branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/convertisor/DocUtils2RST.java 2012-06-05 14:44:35 UTC (rev 696) @@ -29,9 +29,9 @@ import org.apache.commons.logging.LogFactory; import org.dom4j.Element; -import static org.nuiton.jrst.ReStructuredText.PARAGRAPH; -import static org.nuiton.jrst.ReStructuredText.TITLE; -import static org.nuiton.jrst.ReStructuredText.TITLE_CHAR; +import static org.nuiton.jrst.legacy.ReStructuredText.PARAGRAPH; +import static org.nuiton.jrst.legacy.ReStructuredText.TITLE; +import static org.nuiton.jrst.legacy.ReStructuredText.TITLE_CHAR; /** * Modified: branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/convertisor/DocUtilsVisitor.java =================================================================== --- branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/convertisor/DocUtilsVisitor.java 2012-06-04 16:16:06 UTC (rev 695) +++ branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/convertisor/DocUtilsVisitor.java 2012-06-05 14:44:35 UTC (rev 696) @@ -30,7 +30,7 @@ import org.apache.commons.logging.LogFactory; import org.dom4j.Element; import org.dom4j.VisitorSupport; -import org.nuiton.jrst.ReStructuredText; +import org.nuiton.jrst.legacy.ReStructuredText; /** * Copied: branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/legacy/AdvancedReader.java (from rev 695, branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/AdvancedReader.java) =================================================================== --- branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/legacy/AdvancedReader.java (rev 0) +++ branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/legacy/AdvancedReader.java 2012-06-05 14:44:35 UTC (rev 696) @@ -0,0 +1,406 @@ +/* + * #%L + * JRst :: Api + * + * $Id: AdvancedReader.java 601 2011-06-09 16:31:45Z kcardineaud $ + * $HeadURL: http://svn.nuiton.org/svn/jrst/branches/jrst-docutils-jython/jrst/src/main/j... $ + * %% + * Copyright (C) 2004 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jrst.legacy; + +import org.apache.commons.collections.primitives.ArrayCharList; +import org.apache.commons.collections.primitives.CharList; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.LineNumberReader; +import java.io.PushbackReader; +import java.io.Reader; +import java.util.ArrayList; + +/** + * Le principe est d'avoir dans cette classe le moyen de lire, et de retourner + * la ou on etait avant la lecture (mark et reset de {@link BufferedReader}). + * <p> + * Mais il faut aussi pouvoir dire qu'en fin de compte on ne souhaite pas lire + * les caracteres que l'on vient de lire ({@link #unread(int)} a peu pres egal a + * {@link PushbackReader}) + * <p> + * Le pointer nextChar pointe toujours sur le prochain caractere qui sera lu + * <p> + * Lorsque l'on appelle la method {@link #mark()} on vide aussi le buffer pour + * liberer de la place, car on a plus le moyen de retourner avant le mark que + * l'on vient de positionner. + * <p> + * On contraire du mark de {@link BufferedReader} ou {@link LineNumberReader} il + * n'y a pas a specifier le nombre de caractere a garder au maximum, seul la + * memoire nous limite. Du coup si l'on utilise cette classe sans mark, au final + * on aura dans le buffer tout le contenu du reader, il faut donc utiliser mark + * avec cette classe + * + * buffer + * + * <pre> + * ######################### + * 0 ˆ ˆ + * | | + * | + nextChar + * + markChar + * </pre> + * + * Created: 27 oct. 06 00:24:57 + * + * @author poussin + * @version $Revision: 601 $ + * + * Last update: $Date: 2011-06-09 18:31:45 +0200 (jeu. 09 juin 2011) $ + * by : $Author: kcardineaud $ + */ +public class AdvancedReader { + + /** le nombre d'espace pour remplacer les tabulations */ + protected static final String TAB = " "; + /** nombre de caractere lu au minimum sur le vrai reader */ + protected static final int READ_AHEAD = 80; + + protected Reader in; + protected CharList buffer; + + protected int charNumber; + protected int charNumberMark; + protected int lineNumber; + protected int lineNumberMark; + + protected int nextChar; + protected int markChar; + + protected int readInMark; + + protected boolean nlTwoCtrlChars = false; + protected boolean noNlAtEOF = false; + + /** + * + * @param in the io reader + */ + public AdvancedReader(Reader in) { + this.in = new LineNumberReader(in); + buffer = new ArrayCharList(); + } + + public void mark() throws IOException { + markChar = nextChar; + charNumberMark = charNumber; + lineNumberMark = lineNumber; + + free(markChar); + } + + public void reset() throws IOException { + nextChar = markChar; + charNumber = charNumberMark; + lineNumber = lineNumberMark; + + } + + public int readSinceMark() { + return nextChar - markChar; + } + + /** + * @return the charNumber + */ + public int getCharNumber() { + return charNumber; + } + + /** + * @return the lineNumber + */ + public int getLineNumber() { + return lineNumber; + } + + /** + * remove number of char in buffer + * + * @param number + * @return the real number of char removed from the head of buffer + * @throws IOException + */ + private int free(int number) throws IOException { + // fill(number); + int result = Math.min(buffer.size(), number); + buffer.subList(0, result).clear(); + + nextChar -= result; + markChar -= result; + + return result; + } + + /** + * ensure that have number char available and not already read + * + * @param number ? + * @throws IOException + */ + private void fill(int number) throws IOException { + int needed = nextChar + number - buffer.size(); + if (needed > 0) { + char[] cbuf = new char[needed + READ_AHEAD]; + int read = in.read(cbuf); + if (read != -1) { + for (int i = 0; i < read; i++) { + buffer.add(cbuf[i]); + } + } + } + } + + public boolean eof() throws IOException { + boolean result = -1 == read(); + if (!result) { + unread(1); + } + return result; + } + + public int skip(int number) throws IOException { + int result = 0; + while (result < number && read() != -1) { + result++; + } + return result; + } + + /** + * Add a character at the current position + * @param character that you want to add + */ + public void add(char character) { + buffer.add(nextChar,character); + } + + + /** + * go left in reading char buffer + * + * @param number + * @return realy unread char number + */ + public int unread(int number) { + int result = Math.min(number, nextChar); + + nextChar -= result; + charNumber -= result; + for (int i = nextChar; i < nextChar + result; i++) { + if (buffer.get(i) == '\n' || (buffer.get(i) == '\r' && i + 1 < nextChar + result && buffer.get(i + 1) != '\n')) { + lineNumber--; + } + } + + return result; + } + + /** + * Unread the line length + * + * @param line + * line used to know the length to unread + * @param addNewLine + * if true then add +1 to unread lenght for not present '\n' + * @return number of unread char + */ + public int unread(String line, boolean addNewLine) { + int result = unread(line.length() + (addNewLine ? (nlTwoCtrlChars ? 2 : 1) : 0)); + return result; + } + + /** + * Unread the line length + * + * @param lines + * lines used to know the length to unread + * @param addNewLine + * if true then add +1 for each line to unread lenght for not + * present '\n' + * @return number of unread char + */ + public int unread(String[] lines, boolean addNewLine) { + int result = 0; + for (String line : lines) { + result += unread(line, addNewLine); + } + return result; + } + + /** + * read one char in buffer + * + * @return the next char + * @throws IOException pour tout pb de lecture + */ + public int read() throws IOException { + fill(1); + int result = -1; + if (nextChar < buffer.size()) { + result = buffer.get(nextChar++); + charNumber++; + if ((char)result == '\n' || ((char)result == '\r' && nextChar < buffer.size() && buffer.get(nextChar) != '\n')) { + lineNumber++; + } + } + return result; + } + + /** + * read one line + * + * @return one line without '\n' or null if end of file + * @throws IOException pour tout pb de lecture + */ + public String readLine() throws IOException { + StringBuffer result = new StringBuffer(READ_AHEAD); + int c = read(); + while (c != -1 && c != '\n' && c != '\r') { + result.append((char) c); + c = read(); + } + nlTwoCtrlChars = false; + if (c == '\r') { + c = read(); + if (c != '\n' && c != -1) { + unread(1); + } else { + nlTwoCtrlChars = true; + } + } + noNlAtEOF = false; + if (c == -1 && result.length() >= 0) { + if (c == -1 && result.length() == 0) { + return null; + } else { + noNlAtEOF = true; + return result.toString(); + } + } else { + return result.toString(); + } + } + + + + + /** + * passe les lignes blanches + * + * @throws IOException + */ + public void skipBlankLines() throws IOException { + readUntil("^\\s*\\S+.*"); + } + + /** + * lit toutes les lignes du fichier + * + * @return toutes les lignes du fichier + * @throws IOException pour tout pb de lecture + */ + String[] readAll() throws IOException { + String[] result = readLines(-1); + return result; + } + + /** + * lit un certain nombre de lignes + * + * @param count + * si negatif lit toutes les lignes + * @return un certain nombre de lignes + * @throws IOException pour tout pb de lecture + */ + public String[] readLines(int count) throws IOException { + ArrayList<String> result = new ArrayList<String>(); + + String tmp = ""; + for (int i = count; tmp != null && i != 0; i--) { + tmp = readLine(); + if (tmp != null) { + result.add(tmp); + } + } + return result.toArray(new String[result.size()]); + } + + /** + * lit les lignes jusqu'a la premiere ligne blanche (non retournée) + * + * @return toutes les ligne jusqu'à la première ligne blanche (non incluse) + * @throws IOException pour tout pb de lecture + */ + public String[] readUntilBlank() throws IOException { + String[] result = readUntil("\\s*"); + return result; + } + + /** + * lit les lignes jusqu'a la ligne qui correspond pas au pattern, cette + * ligne n'est pas mise dans le resultat retourne + * + * @param pattern ? + * @return les lignes jusqu'a la ligne qui correspond pas au pattern, cette + * ligne n'est pas mise dans le resultat retourne + * @throws IOException pour tout pb de lecture + */ + public String[] readUntil(String pattern) throws IOException { + ArrayList<String> result = new ArrayList<String>(); + String tmp = readLine(); + while (tmp != null && !tmp.matches(pattern)) { + result.add(tmp); + tmp = readLine(); + } + if (tmp != null) { + unread(tmp.length() + (!noNlAtEOF ? (nlTwoCtrlChars ? 2 : 1) : 0)); // +1 for '\n' not in line + } + return result.toArray(new String[result.size()]); + } + + /** + * lit les lignes tant que les lignes correspondent au pattern + * + * @param pattern ? + * @return les lignes tant que les lignes correspondent au pattern + * @throws IOException pour tout pb de lecture + */ + public String[] readWhile(String pattern) throws IOException { + ArrayList<String> result = new ArrayList<String>(); + String tmp = readLine(); + while (tmp != null && tmp.matches(pattern)) { + result.add(tmp); + tmp = readLine(); + } + if (tmp != null) { + unread(tmp.length() + (!noNlAtEOF ? (nlTwoCtrlChars ? 2 : 1) : 0)); // +1 for '\n' not in line + } + return result.toArray(new String[result.size()]); + } + +} Copied: branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/legacy/DocumentHandler.java (from rev 695, branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/DocumentHandler.java) =================================================================== --- branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/legacy/DocumentHandler.java (rev 0) +++ branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/legacy/DocumentHandler.java 2012-06-05 14:44:35 UTC (rev 696) @@ -0,0 +1,55 @@ +/* + * #%L + * JRst :: Api + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2004 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jrst.legacy; + +import org.dom4j.Document; +import org.dom4j.Element; +import org.dom4j.Text; + +/** + * DocumentHandler.java + * + * Created: 30 oct. 06 10:22:52 + * + * @author poussin + * @version $Revision$ + * + * Last update: $Date$ + * by : $Author$ + */ +public interface DocumentHandler { + + void startDocument(Document doc); + + void endDocument(Document doc); + + void startElement(Element e); + + void endElement(Element e); + + void text(Text t); + +} Property changes on: branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/legacy/DocumentHandler.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Copied: branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/legacy/DocumentWalker.java (from rev 695, branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/DocumentWalker.java) =================================================================== --- branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/legacy/DocumentWalker.java (rev 0) +++ branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/legacy/DocumentWalker.java 2012-06-05 14:44:35 UTC (rev 696) @@ -0,0 +1,85 @@ +/* + * #%L + * JRst :: Api + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2004 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jrst.legacy; + +import java.util.List; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.dom4j.Document; +import org.dom4j.Element; +import org.dom4j.Node; +import org.dom4j.Text; + +/** + * DocumentWalker. + * + * Created: 30 oct. 06 10:28:10 + * + * @author poussin + * @version $Revision$ + * + * Last update: $Date$ + * by : $Author$ + */ +public class DocumentWalker { + + static private Log log = LogFactory.getLog(DocumentWalker.class); + + protected DocumentHandler handler; + + /** + * + */ + public DocumentWalker(DocumentHandler handler) { + this.handler = handler; + } + + public void walk(Document doc) { + handler.startDocument(doc); + Element elem = doc.getRootElement(); + walk(elem); + handler.endDocument(doc); + } + + public void walk(Element elem) { + handler.startElement(elem); + for (Node node : (List<Node>) elem.content()) { + switch (node.getNodeType()) { + case Node.ELEMENT_NODE: + walk((Element) node); + break; + case Node.TEXT_NODE: + handler.text((Text) node); + break; + default: + log.warn("Not supported element type: " + + node.getNodeTypeName()); + break; + } + } + handler.endElement(elem); + } +} Property changes on: branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/legacy/DocumentWalker.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Copied: branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/legacy/JRSTLexer.java (from rev 695, branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/JRSTLexer.java) =================================================================== --- branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/legacy/JRSTLexer.java (rev 0) +++ branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/legacy/JRSTLexer.java 2012-06-05 14:44:35 UTC (rev 696) @@ -0,0 +1,2514 @@ +/* + * #%L + * JRst :: Api + * + * $Id: JRSTLexer.java 623 2011-10-28 14:10:56Z sletellier $ + * $HeadURL: http://svn.nuiton.org/svn/jrst/branches/jrst-docutils-jython/jrst/src/main/j... $ + * %% + * Copyright (C) 2004 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jrst.legacy; + +import static org.nuiton.jrst.legacy.ReStructuredText.BLOCK_QUOTE; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.dom4j.DocumentHelper; +import org.dom4j.Element; + +import java.io.IOException; +import java.io.Reader; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Le principe est de positionner la mark du {@link AdvancedReader} lors du + * debut d'une methode peek*, puis a la fin de la methode de regarder le nombre + * de caractere utilisé pour la methode et de faire un reset. + * <p> + * Le nombre de caractere utilisé servira pour le remove lorsque l'utilisateur + * indiquera qu'il utilise l'element retourné, si l'utilisateur n'appelle pas + * remove alors il peut relire autant de fois qu'il veut le meme element, ou + * essayer d'en lire un autre. + * <p> + * Pour mettre en place ce mecanisme le plus simple est d'utiliser les methodes + * {@link JRSTLexer#beginPeek()} et {@link JRSTLexer#endPeek()} + * + * Created: 28 oct. 06 00:44:20 + * + * @author poussin, letellier + * @version $Revision: 623 $ + * + * Last update: $Date: 2011-10-28 16:10:56 +0200 (ven. 28 oct. 2011) $ + * by : $Author: sletellier $ + */ +public class JRSTLexer { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + private static Log log = LogFactory.getLog(JRSTLexer.class); + + public static final String BULLET_CHAR = "*" + "+" + "-"/* + * + "\u2022" + + * "\u2023" + + * "\u2043" + */; + + public static final String TITLE_CHAR = "-=-~'`^+:!\"#$%&*,./;|?@\\_[\\]{}<>()"; + + public static final String DOCINFO_ITEM = "author|authors|organization|address|contact|version|revision|status|date|copyright"; + + public static final String ADMONITION_PATTERN = "admonition|attention|caution|danger|error|hint|important|note|tip|warning"; + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Title Elements + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + public static final String TITLE = "title"; + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Bibliographic Elements + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + public static final String DOCINFO = "docinfo"; + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Decoration Elements + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + public static final String DECORATION = "decoration"; + + public static final String HEADER = "header"; + + public static final String FOOTER = "footer"; + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Structural Elements + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + public static final String TRANSITION = "transition"; + + public static final String SIDEBAR = "sidebar"; + + public static final String TOPIC = "topic"; + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Body Elements + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + static final public String LITERAL_BLOCK = "literal_block"; + + static final public String PARAGRAPH = "paragraph"; + + static final public String BLANK_LINE = "blankLine"; + + static final public String COMMENT = "comment"; + + static final public String SUBSTITUTION_DEFINITION = "substitution_definition"; + + static final public String BULLET_LIST = "bullet_list"; + + static final public String FIELD_LIST = "field_list"; + + static final public String DEFINITION_LIST = "definition_list"; + + static final public String ENUMERATED_LIST = "enumerated_list"; + + static final public String OPTION_LIST = "option_list"; + + public static final String LINE_BLOCK = "line_block"; + + public static final String LINE = "line"; + + public static final String ATTRIBUTION = "attribution"; + + public static final String DOCTEST_BLOCK = "doctest_block"; + + public static final String ADMONITION = "admonition"; + + public static final String TARGET = "target"; + + public static final String FOOTNOTE = "footnote"; + + public static final String FOOTNOTES = "footnotes"; + + public static final String LEVEL = "level"; + + public static final String TARGETANONYMOUS = "targetAnonymous"; + + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Table Elements + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + static final public String TABLE = "table"; + + static final public String ROW = "row"; + + static final public String CELL = "cell"; + + static final public String TABLE_HEADER = "header"; + + static final public String TABLE_WIDTH = "width"; + + static final public String ROW_END_HEADER = "endHeader"; + + static final public String CELL_INDEX_START = "indexStart"; + + static final public String CELL_INDEX_END = "indexEnd"; + + static final public String CELL_BEGIN = "begin"; + + static final public String CELL_END = "end"; + + static final public String REMOVE = "remove"; + + static final public String INCLUDE = "include"; + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Directive Elements + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + static final public String DIRECTIVE = "directive"; + + static final public String DIRECTIVE_TYPE = "type"; + + static final public String DIRECTIVE_VALUE = "value"; + + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Attributs + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + static final public String AUTONUM = "autoNum"; + + static final public String AUTONUMLABEL = "autoNumLabel"; + + static final public String AUTOSYMBOL = "autoSymbol"; + + static final public String BULLET = "bullet"; + + static final public String CHAR = "char"; + + static final public String ID = "id"; + + static final public String CLASSIFIERS = "classifiers"; + + static final public String DELIMITER = "delimiter"; + + static final public String DELIMITEREXISTE ="delimiterExiste"; + + static final public String ENUMTYPE = "enumtype"; + + static final public String REFURI = "refuri"; + + static final public String OPTION = "option"; + + static final public String LITERAL = "literal"; + + static final public String NAME = "name"; + + static final public String NUM ="num"; + + static final public String OPTIONARGUMENT = "option_argument"; + + static final public String OPTIONSTRING = "option_string"; + + static final public String PREFIX = "prefix"; + + static final public String START = "start"; + + static final public String SUBEXISTE = "subExiste"; + + static final public String SUFFIX = "suffix"; + + static final public String SUBTITLE = "subtitle"; + + static final public String TERM = "term"; + + static final public String TITLEATTR = "title"; + + static final public String XMLSPACE = "xml:space"; + + static final public String TYPE = "type"; + + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + protected static final String TRUE = "true"; + + protected static final String FALSE = "false"; + + + /** + * retient le niveau du titre, pour un titre de type double, on met deux + * fois le caratere dans la chaine, sinon on le met une seul fois. + * + * <pre> + * ===== + * Super + * ===== + * titre + * ----- + * </pre> + * + * donnera dans la liste ["==", "-"] + */ + private List<String> titleLevels; + + private AdvancedReader in; + + /** + * length of the last element returned (number of char need to this element) + */ + private int elementLength; + + + + + public JRSTLexer(Reader reader) { + titleLevels = new ArrayList<String>(); + in = new AdvancedReader(reader); + } + + /** + * true if no more element to read + * + * @return boolean + * @throws IOException + */ + public boolean eof() throws IOException { + in.mark(); + in.skipBlankLines(); + boolean result = in.eof(); + in.reset(); + return result; + } + + /** + * remove one element from list of element already read + * + * @throws IOException + */ + public void remove() throws IOException { + in.skip(elementLength); + } + + /** + * start peek + * + * @throws IOException + */ + private void beginPeek() throws IOException { + elementLength = 0; + in.mark(); + } + + /** + * end peek + * + * @throws IOException + */ + private void endPeek() throws IOException { + elementLength = in.readSinceMark(); + in.reset(); + } + + /** + * Read block text, block text have same indentation and is continu (no + * blank line) + * + * @param minLeftMargin + * min left blank needed to accept to read block + * @return String[] + * @throws IOException + */ + private String[] readBlock(int minLeftMargin) throws IOException { + String[] result = new String[0]; + String firstLine = in.readLine(); + if (firstLine != null) { + in.unread(firstLine, true); + int level = level(firstLine); + if (level >= minLeftMargin) { + result = in.readWhile("^\\s{" + level + "}\\S+.*"); + } + } + + return result; + } + + /** + * All lines are joined and left and right spaces are removed during join + * + * @param String + * [] lines + * @return String + */ + private String joinBlock(String[] lines) { + String result = joinBlock(lines, " ", true); + return result; + } + + /** + * All lines are joined whith the String joinSep and left and right spaces + * are removed if trim + * + * @param String + * [] lines + * @param String + * joinSep + * @param Boolean + * trim + * @return String + */ + private String joinBlock(String[] lines, String joinSep, boolean trim) { + String result = ""; + String sep = ""; + for (String line : lines) { + if (trim) { + line = line.trim(); + } + result += sep + line; + sep = joinSep; + } + return result; + } + + /** + * search if the doc have an header + * + * <pre> + * .. header:: This space for rent. aaaa **aaaa** + * </pre> + * + * @return Element + * @throws IOException + */ + public Element peekHeader() throws IOException { + beginPeek(); + Element result = null; + String[] line = in.readAll(); + if (line != null) { + int i = 0; + for (String l : line) { + i++; + if (l.matches("^\\s*.. " + HEADER + ":: .*")) { + int level = level(l); + l = l.replaceAll("^\\s*.. " + HEADER + ":: ", ""); + result = DocumentHelper.createElement(HEADER).addAttribute( + LEVEL, String.valueOf(level)); + result.addAttribute(LINE, "" + i); + result.setText(l); + } + + } + } + endPeek(); + return result; + + } + + /** + * search if the doc have an header + * + * <pre> + * .. footer:: design by **LETELLIER Sylvain** + * </pre> + * + * @return Element + * @throws IOException + */ + public Element peekFooter() throws IOException { + beginPeek(); + Element result = null; + String[] line = in.readAll(); + if (line != null) { + int i = 0; + for (String l : line) { + i++; + + if (l.matches("^\\s*.. " + FOOTER + ":: .*")) { + int level = level(l); + l = l.replaceAll("^\\s*.. " + FOOTER + ":: ", ""); + result = DocumentHelper.createElement(FOOTER).addAttribute( + LEVEL, String.valueOf(level)); + result.addAttribute(LINE, "" + i); + result.setText(l); + } + } + } + endPeek(); + return result; + + } + + /** + * <pre> + * .. __: http://www.python.org + * </pre> + * + * @return Element + * @throws IOException + */ + public LinkedList<Element> peekTargetAnonymous() throws IOException { + beginPeek(); + LinkedList<Element> result = new LinkedList<Element>(); + String[] line = in.readAll(); + if (line != null) { + int i = 0; + for (String l : line) { + i++; + + if (l.matches("^\\s*__ .+$|^\\s*\\.\\. __\\:.+$")) { + log.debug(l); + Element resultTmp = DocumentHelper + .createElement(TARGETANONYMOUS); + resultTmp.addAttribute(LEVEL, "" + level(l)); + Matcher matcher = Pattern.compile("__ |.. __: ").matcher(l); + + if (matcher.find()) { + resultTmp.addAttribute(REFURI, l.substring(matcher + .end(), l.length())); + } + + result.add(resultTmp); + } + } + + } + endPeek(); + return result; + } + + /** + * Return title or para + * + * @return Element + * @throws IOException + */ + public Element peekTitleOrBodyElement() throws IOException { + Element result = null; + if (result == null) { + result = peekTitle(); + } + if (result == null) { + result = peekBodyElement(); + } + + return result; + } + + /** + * read doc info author, date, version, ... or field list element + * + * <pre> + * :author: Benjamin Poussin + * :address: + * Quelque part + * Dans le monde + * </pre> + * + * @return Element + * @throws IOException + */ + public Element peekDocInfo() throws IOException { + Element result = null; + if (result == null) { + result = peekDocInfoItem(); + + } + if (result == null) { + result = peekFieldList(); + } + + return result; + + } + + /** + * Return para + * + * @return Element + * @throws IOException + */ + public Element peekBodyElement() throws IOException { + Element result = null; + if (result == null) { + result = peekInclude(); + } + if (result == null) { + result = peekDoctestBlock(); + } + if (result == null) { + result = peekAdmonition(); + } + if (result == null) { + result = peekSidebar(); + } + if (result == null) { + result = peekTopic(); + } + if (result == null) { + result = peekRemove(); + } + if (result == null) { + result = peekDirectiveOrReference(); + } + if (result == null) { + result = peekTransition(); + } + if (result == null) { + result = peekTable(); + } + if (result == null) { + result = peekLineBlock(); + } + if (result == null) { + result = peekBulletList(); + } + if (result == null) { + result = peekOption(); + } + if (result == null) { + result = peekEnumeratedList(); + } + if (result == null) { + result = peekTarget(); + } + if (result == null) { + result = peekFootnote(); + } + // comment must be read after peekDirectiveOrReference() + // and peekFootnote() + if (result == null) { + result = peekComment(); + } + if (result == null) { + result = peekDefinitionList(); + } + if (result == null) { + result = peekFieldList(); + } + if (result == null) { + result = peekTargetAnonymousBody(); + } + if (result == null) { + result = peekLiteralBlock(); + } + if (result == null) { + result = peekBlockQuote(); + } + if (result == null) { + result = peekBlankLine(); + } + if (result == null) { + result = peekPara(); + } + + return result; + } + + /** + * Remove already read elements + * + * @return Element + * @throws IOException + */ + public Element peekRemove() throws IOException { + beginPeek(); + Element result = null; + String line = in.readLine(); + if (line != null) { + // Le header est parse des le debut + if (line.matches("^\\s*.. " + HEADER + ":: .*")) { + result = DocumentHelper.createElement(REMOVE).addAttribute( + LEVEL, "" + level(line)); + } + // Le footer + if (line.matches("^\\s*.. " + FOOTER + ":: .*")) { + result = DocumentHelper.createElement(REMOVE).addAttribute( + LEVEL, "" + level(line)); + } + + } + endPeek(); + return result; + } + + /** + * read include + * + * <pre> + * .. include:: text.txt + * or + * .. include:: literal + * text.txt + * + * </pre> + * + * @return Element + * @throws IOException + */ + private Element peekInclude() throws IOException { + beginPeek(); + Element result = null; + String line = in.readLine(); + if (line != null) { + if (line.matches("^\\s*\\.\\.\\sinclude\\:\\:.+$")) { + result = DocumentHelper.createElement(INCLUDE); + result.addAttribute(LEVEL, "" + level(line)); + String option = line.substring(line.indexOf("::") + 2).trim(); + result.addAttribute(OPTION, ""); + if (option.trim().equalsIgnoreCase(LITERAL)) { + result.addAttribute(OPTION, LITERAL); + line = in.readLine(); + result.setText(line.trim()); + } else { + result.setText(option); + } + + } + } + endPeek(); + return result; + } + + /** + * read options + * + * <pre> + * Ex : -a command-line option "a" + * -1 file, --one=file, --two file + * Multiple options with arguments. + * Schéma : ________________________________ + * v | | + * -{1,2}\w+ ->|',' | + * |'='-----|-> \w+ --->|',' + * |' '-----| |' '---+ + * |" " -----> \w+ ---> end | + * ˆ | + * |_________________________| + * Légende : + * + * -{1,2} --> 1 or 2 tirets + * \w+ -----> word characters one or more times + * </pre> + * + * @return Element + * @throws IOException + */ + public Element peekOption() throws IOException { + + beginPeek(); + Element result = null; + String line = in.readLine(); + if (line != null) { + if (line.matches("^(\\s*((--?)|(//?))\\w+([ =][<a-zA-Z][\\w-><]*)?)\\s*.*$")) { + result = DocumentHelper.createElement(OPTION_LIST) + .addAttribute(LEVEL, "" + level(line)); + char delimiter; + do { + Matcher matcher = Pattern.compile("[-/][-/]?.+").matcher(line); + matcher.find(); + Element option = result.addElement(OPTION); + String option_stringTmp = matcher.group(); + matcher = Pattern.compile("^[-/][-/]?\\w+").matcher(option_stringTmp); + matcher.find(); + String option_string = matcher.group(); + option.addAttribute(OPTIONSTRING, option_string); + + boolean done = false; + // Delimiteur bidon + delimiter = '.'; + if (option_stringTmp.length() > matcher.end()) { + delimiter = option_stringTmp.charAt(matcher.end()); + option_stringTmp = option_stringTmp.substring( + matcher.end(), option_stringTmp.length()); + } else { + done = true; + } + option.addAttribute(DELIMITEREXISTE, FALSE); + + if (delimiter == ' ') { // S'il y a 2 espaces a suivre, + // l'option est finie + if (option_stringTmp.charAt(1) == ' ') { + done = true; + } + } + String option_argument = null; + if ((delimiter == '=' || delimiter == ' ') && !done) { + option.addAttribute(DELIMITEREXISTE, TRUE); + option.addAttribute(DELIMITER, "" + delimiter); + matcher = Pattern.compile(delimiter + "(([a-zA-Z][\\w-]+)|(<[a-zA-Z][^>]*>))").matcher( + option_stringTmp); + if (matcher.find()) { + option_argument = matcher.group().substring(1, + matcher.group().length()); + option.addAttribute(OPTIONARGUMENT, option_argument); + int size = option_argument.length() + 1; + if (option_stringTmp.length() < size && option_stringTmp.charAt(size) == ',') { + delimiter = ','; + } else { + done = true; + } + } else { // Si la description n'est pas sur la meme + // ligne + option_argument = option_stringTmp; + option.addAttribute(OPTIONARGUMENT, + option_argument); + line = in.readLine(); + if (line != null) { + result.setText(line.trim()); + } + } + } + if (delimiter == ',') { + line = line.substring(option_string.length() + 1 + + (option_argument == null ? 0 : option_argument.length())); + } + if (done) { + result.setText(option_stringTmp.substring(matcher.end(), option_stringTmp.length()).trim() + + " " + joinBlock(readBlock(1))); + } + } while (delimiter == ','); + } + } + endPeek(); + return result; + } + + /** + * read topic + * + * <pre> + * -.. topic:: Title + * Body. + * </pre> + * + * @return Element + * @throws IOException + */ + private Element peekTopic() throws IOException { + beginPeek(); + Element result = null; + String line = in.readLine(); + if (line != null) { + if (line.matches("^\\.\\.\\s+(" + TOPIC + ")::\\s+(.*)$")) { + Matcher matcher = Pattern.compile(TOPIC + "::").matcher(line); + matcher.find(); + result = DocumentHelper.createElement(TOPIC).addAttribute( + LEVEL, "" + level(line)); + String title = line.substring(matcher.end(), line.length()); + result.addAttribute(TITLE, title); + line = in.readLine(); + if (line.matches("\\s*")) { + line = in.readLine(); + } + int level = level(line); + String[] lines = null; + if (level != 0) { + lines = in.readWhile("(^ {" + level + "}.*)|(\\s*)"); + String txt = line; + for (String txtTmp : lines) { + txt += "\n" + txtTmp.trim(); + } + result.setText(txt); + } + + } + } + + endPeek(); + return result; + } + + /** + * read sidebar + * + * <pre> + * .. sidebar:: Title + * :subtitle: If Desired + * Body. + * </pre> + * + * @return Element + * @throws IOException + */ + private Element peekSidebar() throws IOException { + beginPeek(); + Element result = null; + String line = in.readLine(); + if (line != null) { + if (line.matches("^\\.\\.\\s*(" + SIDEBAR + ")::\\s*(.*)$")) { + Matcher matcher = Pattern.compile(SIDEBAR + "::").matcher(line); + matcher.find(); + result = DocumentHelper.createElement(SIDEBAR).addAttribute( + LEVEL, "" + level(line)); + String title = line.substring(matcher.end(), line.length()); + result.addAttribute(TITLE, title); + line = in.readLine(); + if (line.matches("^\\s+:subtitle:\\s*(.*)$*")) { + matcher = Pattern.compile(":subtitle:\\s*").matcher(line); + matcher.find(); + String subTitle = line.substring(matcher.end(), line + .length()); + result.addAttribute(SUBEXISTE, TRUE); + result.addAttribute(SUBTITLE, subTitle); + line = in.readLine(); + } else { + result.addAttribute(SUBEXISTE, FALSE); + } + String txt = joinBlock(readBlock(level(line))); + result.setText(txt); + + } + } + + endPeek(); + return result; + } + + /** + * read line block + * + * <pre> + * | A one, two, a one two three four + * | + * | Half a bee, philosophically, + * | must, *ipso facto*, half not be. + * | But half the bee has got to be, + * | *vis a vis* its entity. D'you see? + * </pre> + * + * @return Element + * @throws IOException + */ + private Element peekLineBlock() throws IOException { + beginPeek(); + Element result = null; + String line = in.readLine(); + if (line != null) { + if (line.matches("\\|\\s.*")) { + String[] linesTmp = readBlock(0); + String[] lines = new String[linesTmp.length + 1]; + lines[0] = line; + for (int i = 0; i < linesTmp.length; i++) { + lines[i + 1] = linesTmp[i]; + } + int[] levelsTmp = new int[lines.length]; + int levelmin = 999; + result = DocumentHelper.createElement(LINE_BLOCK).addAttribute( + LEVEL, 0 + ""); + for (int i = 0; i < levelsTmp.length; i++) { + // on enleve | + lines[i] = lines[i].replaceAll("\\|\\s?", ""); + } + for (int i = 0; i < levelsTmp.length; i++) { + // determination des levels + levelsTmp[i] = level(lines[i]); + } + for (int i : levelsTmp) { + // level minimal + levelmin = Math.min(levelmin, i); + } + int cnt = 0; + String lineAv = ""; + int[] levels = new int[levelsTmp.length]; + for (String l : lines) { + if (!l.matches("\\s*")) { // Si la ligne courante n'est + // pas vide + int level = levelsTmp[cnt] - levelmin; + if (level != 0) { + if (cnt != 0) { + if (!lineAv.matches("\\s*")) { // Si la ligne + // d'avant n'est + // pas vide + int levelAv = levelsTmp[cnt - 1] - levelmin; + if (levelAv < level) { + levels[cnt] = levels[cnt - 1] + 1; + if (cnt != levels.length) { + int levelAp = levelsTmp[cnt + 1] + - levelmin; + if (levelAp < level + && levelAv < levelAp) { + levels[cnt]++; + } + } + } else { + levels[cnt] = levels[cnt - 1] - 1; + } + } else { + levels[cnt] = 1; + } + } else { + levels[cnt] = 1; + } + } else { + levels[cnt] = 0; + } + } else { + if (cnt != 0) { + levels[cnt] = levels[cnt - 1]; + } + else { + levels[cnt] = 0; + } + } + cnt++; + lineAv = l; + } + for (int i = 0; i < levels.length; i++) { + Element eLine = result.addElement(LINE); + eLine.addAttribute(LEVEL, "" + levels[i]); + eLine.setText(lines[i].trim()); + } + } + } + endPeek(); + return result; + } + + /** + * read doctest block + * + * <pre> + * >>> print 'this is a Doctest block' + * this is a Doctest block + * </pre> + * + * @return Element + * @throws IOException + */ + private Element peekDoctestBlock() throws IOException { + beginPeek(); + Element result = null; + String line = in.readLine(); + if (line != null) { + if (line.matches("^\\s*>>>\\s.*")) { + int level = level(line); + result = DocumentHelper.createElement(DOCTEST_BLOCK) + .addAttribute(LEVEL, String.valueOf(level)); + result.addAttribute(XMLSPACE, "preserve"); + line += "\n" + joinBlock(readBlock(level)); + result.setText(line); + } + } + endPeek(); + return result; + } + + /** + * read block quote + * + * <pre> + * As a great paleontologist once said, + * + * This theory, that is mine, is mine. + * + * -- Anne Elk (Miss) + * </pre> + * + * @return Element + * @throws IOException + */ + private Element peekBlockQuote() throws IOException { + beginPeek(); + Element result = null; + String line = in.readLine(); + if (line != null) { + if (line.matches("\\s.*")) { + int level = level(line); + String savedLine = line + " " + joinBlock(readBlock(level)); + line = in.readLine(); + + if (line != null) { + level = level(line); + String blockQuote = null; + if (level != 0) { + String txt = line; + String[] lines = in.readWhile("(^ {" + level + + "}.*)|(\\s*)"); + for (String l : lines) { + if (l.matches("^ {" + level + "}--\\s*.*")) { + blockQuote = l; + blockQuote = blockQuote.replaceAll("--", "") + .trim(); + } else { + txt += "\n" + l; + } + } + result = DocumentHelper.createElement(BLOCK_QUOTE) + .addAttribute(LEVEL, String.valueOf(level)); + if (blockQuote != null) { + result.addAttribute(ATTRIBUTION, blockQuote); + } + result.setText(savedLine + txt); + } + } + } + } + endPeek(); + return result; + } + + /** + * read admonitions : + * admonition|attention|caution|danger|error|hint|important|note|tip|warning + * + * <pre> + * .. Attention:: All your base are belong to us. + * .. admonition:: And, by the way... + * + * You can make up your own admonition too. + * </pre> + * + * @return Element + * @throws IOException + */ + protected Element peekAdmonition() throws IOException { + beginPeek(); + Element result = null; + String line = in.readLine(); + if (line != null) { + String lineTest = line.toLowerCase(); + Pattern pAdmonition = Pattern.compile("^\\s*\\.\\.\\s(" + + ADMONITION_PATTERN + ")::\\s*(.*)$"); + Matcher matcher = pAdmonition.matcher(lineTest); + + if (matcher.matches()) { + + boolean admonition = false; + matcher = Pattern.compile(ADMONITION_PATTERN).matcher(lineTest); + matcher.find(); + int level = level(line); + result = DocumentHelper.createElement(ADMONITION).addAttribute( + LEVEL, "" + level); + + if (matcher.group().equals(ADMONITION)) { // Il y a un titre + // pour un + // admonition + // general + admonition = true; + result.addAttribute(TYPE, ADMONITION); + String title = line.substring(matcher.end() + 2, line + .length()); + + result.addAttribute(TITLEATTR, title); + } else { + result.addAttribute(TYPE, matcher.group()); + } + + String firstLine = ""; + if (!admonition && matcher.end() + 2 < line.length()) { + firstLine = line + .substring(matcher.end() + 2, line.length()); + } + line = in.readLine(); + if (line != null) { + if (line.matches("\\s*")) { + line = in.readLine(); + } + if (line != null && !line.matches("\\s*")) { + level = level(line); + String txt = firstLine.trim() + "\n" + line + "\n"; + txt += "\n" + readBlockWithBlankLine(level); + result.setText(txt); + } else { + result.setText(firstLine); + } + } else { + result.setText(firstLine); + } + } + } + endPeek(); + return result; + } + + /** + * read blank line + * + * @return Element + * @throws IOException + */ + public Element peekBlankLine() throws IOException { + beginPeek(); + Element result = null; + + // must have one blank line before + String line = in.readLine(); + if (line != null && line.matches("\\s*")) { + int level = level(line); + result = DocumentHelper.createElement(BLANK_LINE).addAttribute( + LEVEL, String.valueOf(level)); + } + + endPeek(); + return result; + } + + /** + * read directive or reference + * + * @return Element + * @throws IOException + */ + public Element peekDirectiveOrReference() throws IOException { + beginPeek(); + Element result = null; + String line = in.readLine(); + if (line != null) { + Pattern pImage = Pattern + .compile("^\\.\\.\\s*(?:\\|([^|]+)\\|)?\\s*(\\w+)::\\s*(.*)$"); + Matcher matcher = pImage.matcher(line); + if (matcher.matches()) { + String ref = matcher.group(1); + String directiveType = matcher.group(2); + String directiveValue = matcher.group(3); + Element directive = null; + if (ref != null && !"".equals(ref)) { + result = DocumentHelper + .createElement(SUBSTITUTION_DEFINITION); + result.addAttribute(NAME, ref); + directive = result.addElement(DIRECTIVE); + } else { + result = DocumentHelper.createElement(DIRECTIVE); + directive = result; + } + result.addAttribute(LEVEL, "0"); + + directive.addAttribute(DIRECTIVE_TYPE, directiveType); + directive.addAttribute(DIRECTIVE_VALUE, directiveValue); + + String[] lines = readBlock(1); + String text = joinBlock(lines, "\n", false); + + directive.setText(text); + } + } + endPeek(); + return result; + } + + /** + * read transition + * + * @return Element + * @throws IOException + */ + public Element peekTransition() throws IOException { + beginPeek(); + + Element result = null; + // no eat blank line, see next comment + + // must have one blank line before + String line = in.readLine(); + if (line != null && line.matches("\\s*")) { + // in.skipBlankLines(); + line = in.readLine(); + if (line != null && line.matches("-{3,}\\s*")) { + line = in.readLine(); + // must have one blank line after + if (line != null && line.matches("\\s*")) { + result = DocumentHelper.createElement(TRANSITION) + .addAttribute(LEVEL, String.valueOf(0)); + } + } + } + endPeek(); + return result; + } + + /** + * read paragraph with attribut level that represente the space numbers at + * left side + * + * @return <paragraph level="[int]">[text]</paragraph> + * @throws IOException + */ + public Element peekPara() throws IOException { + beginPeek(); + + Element result = null; + // in.skipBlankLines(); + + String[] lines; + do { + lines = readBlock(0); + if (lines.length > 0) { + int level = level(lines[0]); + String para = joinBlock(lines); + + boolean literal = false; + if (para.endsWith(": ::")) { + para = para.substring(0, para.length() - " ::".length()); + + in.unread("::", true); + for(int i=0;i<level;i++) { + in.add(' '); + } + + literal = true; + } else if (para.endsWith("::")) { + para = para.substring(0, para.length() - ":".length()); // keep + // one + // : + + in.unread("::", true); + + for(int i=0;i<level;i++) { + in.add(' '); + } + + literal = true; + } + + if (para.length() == 0 || ":".equals(para)) { + if (literal) { + in.readLine(); // eat "::" + } + } else { + // if para is empty, there are error and possible + // infiny loop on para, force read next line + result = DocumentHelper.createElement(PARAGRAPH) + .addAttribute(LEVEL, String.valueOf(level)) + .addText(para); + } + } + } while (result == null && lines.length > 0); + + endPeek(); + return result; + } + + /** + * read literal block + * + * <pre> + * :: + * + * LiteralBlock + * </pre> + * + * @return Element + * @throws IOException + */ + public Element peekLiteralBlock() throws IOException { + beginPeek(); + + Element result = null; + // in.skipBlankLines(); + + + String[] prefix = in.readLines(2); + if (prefix.length == 2 && prefix[0].matches("\\s*::\\s*") + && prefix[1].matches("\\s*")) { + + int level = level(prefix[0]); + + String para = in.readLine(); + if (para != null) { + level=level+1; + para = para.substring(level) + "\n"; + + // it's literal block until level is down + String[] lines = in.readWhile("(^ {" + level + "}.*|\\s*)"); + while (lines.length > 0) { + for (String line : lines) { + if (!line.matches("\\s*")) { + para += line.substring(level) + "\n"; + } + else { + para += "\n"; + } + } + lines = in.readWhile("(^ {" + level + "}.*|\\s*)"); + } + + result = DocumentHelper.createElement(LITERAL_BLOCK) + .addAttribute(LEVEL, String.valueOf(level)).addText( + para); + } + } + + endPeek(); + return result; + } + + /** + * read doc info author, date, version, ... + * + * <pre> + * :author: Benjamin Poussin + * :address: + * Quelque part + * Dans le monde + * </pre> + * + * @return Element + * @throws IOException + */ + public Element peekDocInfoItem() throws IOException { + beginPeek(); + + Element result = null; + // in.skipBlankLines(); + String line = in.readLine(); + // (?i) case inensitive on docinfo item + if (line != null && line.matches("^:((?i)" + DOCINFO_ITEM + "):.*$")) { + + result = DocumentHelper.createElement(DOCINFO); + result.addAttribute(LEVEL, "0"); + String infotype = line.substring(1, line.indexOf(":", 1)); + + /* + * if (!in.eof()) { String [] content = readBlock(1); line += + * joinBlock(content); } + */ + String text = line.substring(line.indexOf(":", 1) + 1).trim(); + String[] textTmp = in.readWhile("^\\s+.*"); + if (textTmp.length != 0) { + in.mark(); + } + + for (String txt : textTmp) { + text += "\n" + txt.trim(); + } + + // CVS, RCS support + text = text.replaceAll("\\$\\w+: (.+?)\\$", "$1"); + + result.addAttribute(TYPE, infotype).addText(text); + } + endPeek(); + return result; + } + + /** + * read table simple and complexe + * + * <pre> + * +------------------------+------------+----------+----------+ + * | Header row, column 1 | Header 2 | Header 3 | Header 4 | + * | (header rows optional) | | | | + * +========================+============+==========+==========+ + * | body row 1, column 1 | column 2 | column 3 | column 4 | + * +------------------------+------------+----------+----------+ + * | body row 2 | Cells may span columns. | + * +------------------------+------------+---------------------+ + * </pre> + * + * @return Element + * @throws IOException + */ + @SuppressWarnings("unchecked") + public Element peekTable() throws IOException { + beginPeek(); + + Element result = null; + // in.skipBlankLines(); + String line = in.readLine(); + + if (line != null) { + Pattern pTableBegin = Pattern.compile("^\\s*(\\+-+)+\\+\\s*$"); + Matcher matcher = null; + + matcher = pTableBegin.matcher(line); + if (matcher.matches()) { // complexe table + result = DocumentHelper.createElement(TABLE); + result.addAttribute(TABLE_HEADER, FALSE); + int level = level(line); + result.addAttribute(LEVEL, String.valueOf(level)); + line = line.trim(); + int tableWidth = line.length(); + result.addAttribute(TABLE_WIDTH, String.valueOf(tableWidth)); + + Pattern pCellEnd = Pattern + .compile("^\\s{" + + level + + "}(\\+-+\\+|\\|(?:[^+]+))([^+]+(?:\\+|\\|\\s*$)|-+\\+)*\\s*"); // fin + // de + // ligne + Pattern pCell = Pattern.compile("^\\s{" + level + + "}(\\|[^|]+)+\\|\\s*$"); // une ligne + Pattern pHeader = Pattern.compile("^\\s{" + level + + "}(\\+=+)+\\+\\s*$"); // fin du header + Pattern pEnd = Pattern.compile("^\\s{" + level + + "}(\\+-+)+\\+\\s*$"); // fin de table + + // used to know if | is cell separator or not + String lastSeparationLine = line; + String lastLine = line; + + Element row = DocumentHelper.createElement(ROW); + String[] table = in.readUntilBlank(); + + boolean done = false; + for (String l : table) { + done = false; + l = l.trim(); + if (l.length() != tableWidth) { + // Erreur dans la table, peut-etre lever une exception ? + result = null; + break; + } + matcher = pEnd.matcher(l); + if (!done && matcher.matches()) { + // fin normale de ligne, on peut directement l'assigner + lastSeparationLine = l; + for (Element cell : (List<Element>) row.elements()) { + cell.addAttribute(CELL_END, TRUE); + } + row.addAttribute(ROW_END_HEADER, FALSE); + result.add(row); + row = DocumentHelper.createElement(ROW); + done = true; + } + matcher = pHeader.matcher(l); + if (!done && matcher.matches()) { + // fin de du header, on peut directement l'assigner + lastSeparationLine = l; + for (Element cell : (List<Element>) row.elements()) { + cell.addAttribute(CELL_END, TRUE); + } + row.addAttribute(ROW_END_HEADER, TRUE); + result.add(row); + result.addAttribute(TABLE_HEADER, TRUE); + row = DocumentHelper.createElement(ROW); + done = true; + } + matcher = pCell.matcher(l); + if (!done && matcher.matches()) { + // debug + row.addAttribute("debug", "pCell"); + // recuperation des textes des cellules + int start = -1; + String content = ""; + matcher = Pattern.compile("([^|]+)\\|").matcher(l); + for (int cellNumber = 0; matcher.find(); cellNumber++) { + int tmpstart = matcher.start(1); + int end = matcher.end(1); + String tmpcontent = matcher.group(1); + // on a forcement un | ou un + au dessus du + + // et forcement un + sur lastSeparationLine + // sinon ca veut dire qu'il y avait un | dans la + // cell + if ((lastLine.charAt(end) == '|' || lastLine + .charAt(end) == '+') + && lastSeparationLine.charAt(end) == '+') { + if ("".equals(content)) { + content = tmpcontent; + } + else { + content += tmpcontent; + } + if (start == -1) { + start = tmpstart; + } + Element cell = null; + if (row.nodeCount() <= cellNumber) { + cell = row.addElement(CELL); + cell.addAttribute(CELL_END, FALSE); + } else { + cell = (Element) row.node(cellNumber); + } + cell.addAttribute(CELL_INDEX_START, String + .valueOf(start)); + cell.addAttribute(CELL_INDEX_END, String + .valueOf(end)); + cell.setText(cell.getText() + content + "\n"); + start = end + 1; // +1 to pass + or | at end + // of cell + content = ""; + } else { + // start = tmpstart; + if (start == -1) { + start = tmpstart; + } + content += tmpcontent + "|"; + cellNumber--; + } + } + done = true; + } + matcher = pCellEnd.matcher(l); + if (!done && matcher.matches()) { + // debug + row.addAttribute("debug", "pCellEnd"); + // fin d'une ligne, on ne peut pas l'assigner + // directement + // pour chaque continuation de cellule, il faut copier + // l'ancienne valeur + + // mais on commence tout de meme par fermer tout les + // cells + for (Element cell : (List<Element>) row.elements()) { + cell.addAttribute(CELL_END, TRUE); + } + + StringBuffer tmp = new StringBuffer(l); + int start = -1; + String content = ""; + matcher = Pattern.compile("([^+|]+|-+)([+|])").matcher( + l); + for (int cellNumber = 0; matcher.find(); cellNumber++) { + int tmpstart = matcher.start(1); + int end = matcher.end(1); + String tmpcontent = matcher.group(1); + String ender = matcher.group(2); + if (!tmpcontent.matches("-+")) { + // on a forcement un | au dessus du + ou du | + // sinon ca veut dire qu'il y avait un + dans la + // cell + if (lastLine.charAt(end) == '|') { + if (start == -1) { + start = tmpstart; + } + // -1 and +1 to take the + or | at begin and + // end + String old = lastSeparationLine.substring( + start - 1, end + 1); + tmp.replace(start - 1, end + 1, old); + if ("".equals(content)) { + content = tmpcontent; + } + Element cell = null; + if (row.nodeCount() <= cellNumber) { + cell = row.addElement(CELL); + } else { + cell = (Element) row.node(cellNumber); + + } + cell.setText(cell.getText() + content + + "\n"); + // on a ajouter des choses dans la cell, + // donc + // ce n'est pas la fin + cell.addAttribute(CELL_END, FALSE); + cell.addAttribute(CELL_INDEX_START, String + .valueOf(start)); + cell.addAttribute(CELL_INDEX_END, String + .valueOf(end)); + start = end + 1; // +1 to pass + or | at + // end of cell + content = ""; + } else { + // start = tmpstart; + content += tmpcontent + ender; + } + } + } + lastSeparationLine = tmp.toString(); + row.addAttribute(ROW_END_HEADER, FALSE); + result.add(row); + row = DocumentHelper.createElement(ROW); + done = true; + } + if (!done) { + log.warn("Bad table format line " + in.getLineNumber()); + } + lastLine = l; + } + + // + // line += "\n" + joinBlock(table, "\n", false); + // + // result.addText(line); + } else if (line.matches("^\\s*(=+ +)+=+\\s*$")) { + // Les donnees de la table peuvent depasser de celle-ci + /* + * ===== ===== ====== Inputs Output ------------ ------ A B A or + * B ===== ===== ====== False False Second column of row 1. True + * False Second column of row 2. + * + * True 2 - Second column of row 3. + * + * - Second item in bullet list (row 3, column 2). ============ + * ====== + */ + + result = DocumentHelper.createElement(TABLE); + line = line.trim(); + Pattern pBordersEquals = Pattern.compile("^\\s*(=+ +)+=+\\s*$"); // Separation + // = + Pattern pBordersTiret = Pattern.compile("^\\s*(-+ +)+-+\\s*$"); // Separation + // - + Pattern pBorders = Pattern.compile("^\\s*([=-]+ +)+[=-]+\\s*$"); // = + // ou + // - + String[] table = in.readUntilBlank(); // Recuperation de la + // table + + int tableWidth = line.length(); + int nbSeparations = 0; + for (String l : table) { + if (l.length() > tableWidth) { + tableWidth = l.length(); // Determination de la + } // Determination de la + // longueur max + matcher = pBordersEquals.matcher(l); + if (matcher.matches()) { + nbSeparations++; + } + + } + // Header if the table contains 3 equals separations + result.addAttribute(TABLE_HEADER, "" + (nbSeparations == 2)); + int level = level(line); + result.addAttribute(LEVEL, String.valueOf(level)); + result + .addAttribute(TABLE_WIDTH, String + .valueOf(tableWidth + 1)); + Element row = DocumentHelper.createElement(ROW); + // Determination of the columns positions + List<Integer> columns = new LinkedList<Integer>(); + matcher = Pattern.compile("=+\\s+").matcher(line); + for (int cellNumber = 0; matcher.find(); cellNumber++) { + columns.add(matcher.end()); + } + columns.add(tableWidth); + + // Traitement du tbl + /* + * ===== ===== ====== Inputs Output ------------ ------ A B A or + * B ===== ===== ====== False False Second column of row 1. True + * False Second column of row 2. + * + * True 2 - Second column of row 3. + * + * - Second item in bullet list (row 3, column 2). ============ + * ====== devient l'equivalent : ===== ===== ====== Inputs + * Output ------------ ------ A B A or B ===== ===== ====== + * False False Second column of row 1. ----- ----- ------ True + * False Second column of row 2. ----- ----- ------ True 2 - + * Second column of row 3. - Second item in bullet list (row 3, + * column 2). ============ ====== + */ + String lineRef = line.replace('=', '-'); + Matcher matcher2; + List<String> tableTmp = new LinkedList<String>(); + + for (int i = 0; i < table.length - 1; i++) { + tableTmp.add(table[i]); + if (!table[i].equals("")) { + if (!table[i + 1] + .substring(0, columns.get(0)) + .matches("\\s*")) { + matcher = pBorders.matcher(table[i]); + matcher2 = pBorders.matcher(table[i + 1]); + if (!matcher.matches() && !matcher2.matches() + && !table[i + 1].equals("")) { + tableTmp.add(lineRef); + } + } + } + } + tableTmp.add(table[table.length - 1]); + table = new String[tableTmp.size()]; + for (int i = 0; i < tableTmp.size(); i++) { + table[i] = tableTmp.get(i); + } + + boolean done = false; + LinkedList<String> lastLines = new LinkedList<String>(); + int separation = 1; + for (String l : table) { + if (l != null) { + done = false; + matcher = pBordersTiret.matcher(l); + matcher2 = pBordersEquals.matcher(l); + if (matcher.matches() || matcher2.matches()) { // Intermediate + // separation + while (!lastLines.isEmpty()) { + matcher = Pattern.compile("[-=]+\\s*").matcher( + l); + String tmpLine = lastLines.getLast(); + lastLines.removeLast(); + int cellNumber; + for (cellNumber = 0; matcher.find(); cellNumber++) { + Element cell = null; + if (row.nodeCount() <= cellNumber) { + cell = row.addElement(CELL); + } else { + cell = (Element) row.node(cellNumber); + } + if (matcher.start() < tmpLine.length()) { + if (columns.size() - 1 == cellNumber) { + cell.setText(tmpLine.substring( + matcher.start(), tmpLine + .length()) + + "\n"); + } else { + if (matcher.end() < tmpLine + .length()) { + cell.setText(tmpLine.substring(matcher.start(), matcher.end()) + "\n"); + } + else { + cell.setText(tmpLine.substring(matcher.start(), tmpLine.length()) + "\n"); + } + } + } + + if (lastLines.size() == 0) { + row.addAttribute("debug", "pCell"); + cell.addAttribute(CELL_END, TRUE); + } else { + row.addAttribute("debug", "pCellEnd"); + cell.addAttribute(CELL_END, FALSE); + } + cell.addAttribute(CELL_INDEX_START, String + .valueOf(matcher.start() + 1)); + if (line.length() == matcher.end()) { + cell.addAttribute(CELL_INDEX_END, String.valueOf(columns.get(columns.size() - 1))); + } + else { + cell.addAttribute(CELL_INDEX_END, String.valueOf(matcher.end())); + } + } + + if (matcher2.matches()) { + separation++; + row.addAttribute(ROW_END_HEADER, "" + + (separation == 2)); + } else { + row.addAttribute(ROW_END_HEADER, FALSE); + } + + result.add(row); + row = DocumentHelper.createElement(ROW); + done = true; + } + } + if (!done && l.matches("^\\s*(.+ +)+.+\\s*$")) { + // Data + lastLines.addFirst(l); // Les donnees sont stoquee + // dans une file d'attente + // lastLines (FIFO) + done = true; + } + if (!done) { + log.warn("Bad table format line " + + in.getLineNumber()); + } + } + } + } + } + endPeek(); + + return result; + } + + /** + * read list + * + * <pre> + * - first line + * - next line + * </pre> + * + * @return <bullet_list level="[int]" + * bullet="char"><[text];</bullet_list> + * @throws IOException + */ + public Element peekBulletList() throws IOException { + beginPeek(); + + Element result = null; + // in.skipBlankLines(); + String line = in.readLine(); + if (line != null + && line.matches("^\\s*[" + escapeRegex(BULLET_CHAR) + + "] +\\S.*")) { + int level = level(line); + String bullet = line.substring(level, level + 1); + + result = DocumentHelper.createElement(BULLET_LIST).addAttribute( + LEVEL, String.valueOf(level)).addAttribute(BULLET, + bullet); + + if (!in.eof()) { + String[] content = readBlock(level + 1); + line += " " + joinBlock(content); + } + String text = line.substring(level + 1).trim(); + + result.addText(text); + in.skipBlankLines(); + } + + endPeek(); + return result; + } + + /** + * read field list + * + * <pre> + * :first: text + * :second: text + * and other text + * :last empty: + * </pre> + * + * @return <field_list level="[int]" + * name="[text]">[text]</field_list> + * @throws IOException + */ + public Element peekFieldList() throws IOException { + beginPeek(); + + Element result = null; + // in.skipBlankLines(); + String line = in.readLine(); + if (line != null) { + Pattern pattern = Pattern.compile("^\\s*:([^:]+): [^\\s].*"); + Matcher matcher = pattern.matcher(line); + if (matcher.matches()) { + int level = level(line); + String name = matcher.group(1); + int begin = matcher.end(1) + 1; + + result = DocumentHelper.createElement(FIELD_LIST).addAttribute( + LEVEL, String.valueOf(level)).addAttribute(NAME, + name); + + if (!in.eof()) { + String[] content = readBlock(level + 1); + line += " " + joinBlock(content); + } + String text = line.substring(begin).trim(); + + result.addText(text); + } + } + + endPeek(); + return result; + } + + /** + * read definition list + * + * <pre> + * un autre mot + * une autre definition + * le mot : la classe + * la definition + * le mot : la classe 1 : la classe 2 + * la definition + * </pre> + * + * @return <definition_list level="[int]" term="[text]" + * classifiers="[text]">[text]</definition_list> + * @throws IOException + */ + public Element peekDefinitionList() throws IOException { + beginPeek(); + + Element result = null; + // in.skipBlankLines(); + String[] lines = in.readLines(2); + if (lines.length == 2) { + int level = level(lines[0]); + int levelDef = level(lines[1]); + if ((levelDef != lines[1].length()) && (level < levelDef)) { + in.unread(lines[1], true); + Pattern pattern = Pattern.compile("^\\s*([^:]+)(?: : (.*))?"); + Matcher matcher = pattern.matcher(lines[0]); + if (matcher.matches()) { + String term = matcher.group(1); + String classifiers = matcher.group(2); + + result = DocumentHelper.createElement(DEFINITION_LIST) + .addAttribute(LEVEL, String.valueOf(level)) + .addAttribute(TERM, term).addAttribute( + CLASSIFIERS, classifiers); + + // poussin 20070207 don't read block here because can't + // interpret it correctly in JRSTReader + // if (!in.eof()) { + // String [] content = readBlock(level + 1); + // String text = joinBlock(content); + // result.addText(text); + // } + } + } + } + + endPeek(); + return result; + } + + /** + * read enumarted list + * + * can be: <li>1, 2, 3, ... <li>a, b, c, ... <li>A, B, C, ... <li>i, ii, + * iii, iv, ... <li>I, II, III, IV, ... + * + * or # for auto-numbered + * + * <pre> + * + * 1. next line 1) next line (1) first line + * + * </pre> + * + * @return <enumerated_list level="[int]" start="[number]" + * prefix="[char]" suffix="[char]" + * enumtype="[(arabic|loweralpha|upperalpha|lowerroman|upperroman]"> + * ;[text]</enumerated_list> + * @throws IOException + */ + public Element peekEnumeratedList() throws IOException { + beginPeek(); + + Element result = null; + // in.skipBlankLines(); + + String line = in.readLine(); + if (line != null) { + Pattern pattern = Pattern + .compile("^\\s*(\\(?)(#|\\d+|[a-z]|[A-Z]|[ivxlcdm]+|[IVXLCDM]+)([\\.)]) [^\\s].*"); + Matcher matcher = pattern.matcher(line); + if (matcher.matches()) { + int level = level(line); + String prefix = matcher.group(1); + String start = matcher.group(2); + String suffix = matcher.group(3); + int begin = matcher.end(3); + + // arabic|loweralpha|upperalpha|lowerroman|upperroman + String enumtype = "auto"; + if (start.matches("\\d+")) { + enumtype = "arabic"; + } else if (start.matches("(i|[ivxlcdm][ivxlcdm]+)")) { + enumtype = "lowerroman"; + start = "1"; // TODO transform romain to arabic + } else if (start.matches("(I|[IVXLCDM][IVXLCDM]+)")) { + enumtype = "upperroman"; + start = "1"; // TODO transform romain to arabic + } else if (start.matches("[a-z]+")) { + enumtype = "loweralpha"; + start = String.valueOf((int) start.charAt(0) - (int) 'a'); + } else if (start.matches("[A-Z]+")) { + enumtype = "upperalpha"; + start = String.valueOf((int) start.charAt(0) - (int) 'A'); + } + + result = DocumentHelper.createElement(ENUMERATED_LIST) + .addAttribute(LEVEL, String.valueOf(level)) + .addAttribute(START, start).addAttribute(PREFIX, + prefix).addAttribute(SUFFIX, suffix) + .addAttribute(ENUMTYPE, enumtype); + + if (line.endsWith(": ::")) { + line = line.substring(0, line.length() - " ::".length()); + in.unread("::", true); + + } else if (line.endsWith("::")) { + line = line.substring(0, line.length() - ":".length()); // keep + // one + // : + in.unread("::", true); + } + + + if (!in.eof()) { + String[] content = readBlock(level + 1); + String tempLine = " " + joinBlock(content); + + if (tempLine.endsWith(": ::")) { + tempLine = tempLine.substring(0, tempLine.length() - " ::".length()); + in.unread("::", true); + + } else if (tempLine.endsWith("::")) { + tempLine = tempLine.substring(0, tempLine.length() - ":".length()); // keep + // one + // : + in.unread("::", true); + } + + line+=tempLine; + + + } + String text = line.substring(begin).trim(); + + result.addText(text); + in.skipBlankLines(); + } + } + + endPeek(); + return result; + } + + /** + * Parse un titre simple ou double + * + * simple: + * + * <pre> + * + * Le titre ======== + * + * </pre> + * + * double: + * + * <pre> + * + * ============ le titre ============ + * + * </pre> + * + * @return <title level="[int]" type="[simple|double]" char="[underline + * char]"> + * @throws IOException + */ + public Element peekTitle() throws IOException { + beginPeek(); + + Element result = null; + // in.skipBlankLines(); + String line = in.readLine(); + + if (line != null) { + if (startsWithTitleChar(line)) { + String[] titles = in.readLines(2); + if (titles.length == 2 && line.length() >= titles[0].length() + && line.length() == titles[1].length() + && line.equals(titles[1])) { + result = DocumentHelper.createElement(TITLE).addAttribute( + TYPE, "double").addAttribute(CHAR, + titles[1].substring(0, 1)).addText(titles[0]); + } + } else { + String title = in.readLine(); + if (title != null + && startsWithTitleChar(title) + && line.replaceFirst("\\s*$", "").length() == title + .length()) { + + result = DocumentHelper.createElement(TITLE).addAttribute( + TYPE, "simple").addAttribute(CHAR, + title.substring(0, 1)).addText( + line.replaceFirst("\\s*$", "")); + } + } + } + + if (result != null) { + // add level information + String titleLevel = result.attributeValue(CHAR); + + if ("double".equals(result.attributeValue(TYPE))) { + titleLevel += titleLevel; + } + int level = titleLevels.indexOf(titleLevel); + if (level == -1) { + level = titleLevels.size(); + titleLevels.add(titleLevel); + } + result.addAttribute(LEVEL, String + .valueOf(JRSTReader.MAX_SECTION_DEPTH + level)); + } + + endPeek(); + return result; + } + + public Element peekTarget() throws IOException { + beginPeek(); + + String line = in.readLine(); + Element result = null; + if (line != null) { + if (line.matches("^\\s*\\.\\.\\s_[^_:].+:.*")) { + result = DocumentHelper.createElement(TARGET); + Matcher matcher = Pattern.compile("\\.\\.\\s_").matcher(line); + if (matcher.find()) { + int i = line.indexOf(':'); + result.addAttribute(ID, URLEncoder.encode(line.substring(matcher.end(), i) + .toLowerCase().replaceAll(" ", "-"), "UTF-8")); + result.addAttribute(LEVEL, "" + level(line)); + } + } + } + endPeek(); + return result; + } + + /** + * .. _frungible doodads: http://www.example.org/ + * + * @return Element + * @throws IOException + */ + public LinkedList<Element> refTarget() throws IOException { + beginPeek(); + + String[] lines = in.readAll(); + LinkedList<Element> result = new LinkedList<Element>(); + for (String line : lines) { + if (line.matches("^\\s*\\.\\.\\s_[^_:].+:.*")) { + result.add(DocumentHelper.createElement(TARGET)); + Matcher matcher = Pattern.compile("\\.\\.\\s_").matcher(line); + if (matcher.find()) { + boolean done = false; + for (int i = matcher.end(); i < line.length() && !done; i++) { + if (line.charAt(i) == ':') { + result.getLast().addAttribute(LEVEL, + "" + level(line)); + result.getLast().addAttribute( + ID, + URLEncoder.encode(line.substring(matcher.end(), i) + .replaceAll(" ", "-").toLowerCase(), "UTF-8")); + result.getLast().addAttribute( + NAME, + line.substring(matcher.end(), i) + .toLowerCase()); + if (i + 2 > line.length()) { + line = in.readLine(); + // FIXME 20071129 chatellier + // line = null if link is non well formed + // .. _Unifying types and classes in Python: + // miss uri + if (line == null) { + line = ""; + } + result.getLast().addAttribute(REFURI, + line.trim()); + } else { + result.getLast().addAttribute(REFURI, line.substring(i + 2, line.length())); + } + + done = true; + } + } + } + } + } + endPeek(); + return result; + } + + /** + * .. __: http://www.python.org + * + * @return Element + * @throws IOException + */ + private Element peekTargetAnonymousBody() throws IOException { + beginPeek(); + Element result = null; + String line = in.readLine(); + if (line != null) { + if (line.matches("^\\s*__ .+$|^\\s*\\.\\. __\\:.+$")) { + result = DocumentHelper.createElement(TARGETANONYMOUS); + result.addAttribute(LEVEL, "" + level(line)); + + } + } + + endPeek(); + return result; + } + + /** + * .. comment + * + * @return Element + * @throws IOException + */ + private Element peekComment() throws IOException { + beginPeek(); + Element result = null; + String line = in.readLine(); + if (line != null) { + if (line.matches("^\\.\\.\\s+.*$")) { + result = DocumentHelper.createElement(COMMENT); + result.addAttribute(LEVEL, "0"); + result.addAttribute(XMLSPACE, "preserve"); + + // first line is part of comment + result.setText(line.substring(2).trim()); + line = in.readLine(); + if(line != null) { + int level = level(line); + if (level > 0) { + String[] lines = readBlock(level); + String text = line.substring(level); + for (String l : lines) { + text += "\n" + l.substring(level); + } + result.addText(text); + } + } + } + } + + endPeek(); + return result; + } + + /** + * .. comment + * + * @return Element + * @throws IOException + */ + public List<Element> peekAllComment() throws IOException { + beginPeek(); + List<Element> result = new ArrayList<Element>(); + String[] lines = in.readWhile("^\\.\\.\\s*.*$"); + if (lines != null) { +// int levelRef = level(line); + for (String line : lines) { + Element comment = DocumentHelper.createElement(COMMENT); + comment.addAttribute(LEVEL, "0"); + comment.addAttribute(XMLSPACE, "preserve"); + + // first line is part of comment + comment.setText(line.substring(2).trim()); + result.add(comment); + +// int level = level(line); +// if (level == levelRef) { +// String[] lines = readBlock(level); +// String text = line.substring(level); +// for (String l : lines) { +// text += "\n" + l.substring(level); +// } +// result.addText(text); +// } + } + in.mark(); + } + + endPeek(); + return result; + } + + /** + * .. _frungible doodads: http://www.example.org/ + * + * @return Element + * @throws IOException + */ + public Element peekFootnote() throws IOException { + beginPeek(); + Element result = null; + String line = in.readLine(); + if (line != null) { + if (line.matches("^\\s*\\.\\.\\s\\[(#|[0-9]|\\*).*\\]\\s.+$")) { + result = DocumentHelper.createElement(FOOTNOTES); + boolean bLine = false; + do { + + bLine = false; + Element footnote = result.addElement(FOOTNOTE); + Matcher matcher = Pattern.compile("\\.\\.\\s\\[").matcher( + line); + + if (matcher.find()) { + + boolean done = false; + for (int i = matcher.end(); i < line.length() && !done; i++) { + if (line.charAt(i) == ']') { + + result.addAttribute(LEVEL, "" + level(line)); + String id = line.substring(matcher.end(), i); + if (id.matches("\\*")) { + footnote.addAttribute(TYPE, AUTOSYMBOL); + } else if (id.matches("[0-9]")) { + footnote.addAttribute(TYPE, NUM); + footnote.addAttribute(NAME, id); + } else if (id.equals("#")) { + footnote.addAttribute(TYPE, AUTONUM); + } else { + footnote.addAttribute(TYPE, + AUTONUMLABEL); + footnote.addAttribute(NAME, id + .substring(1)); + } + String text = line.substring(i + 2, line + .length()); + + int levelAv = level(line); + line = in.readLine(); + if (line != null) { + if (line + .matches("^\\s*\\.\\.\\s\\[(#|[0-9]|\\*).*\\]\\s.+$")) { + bLine = true; + } else { + + int level = level(line); + if (levelAv < level) { + String[] lines = in + .readWhile("(^ {" + level + + "}.*)|(\\s*)"); + text += "\n" + line.trim(); + for (String l : lines) { + text += "\n" + l.trim(); + } + + } else if (line.matches("\\s*")) { + level = levelAv + 1; + String[] lines = in + .readWhile("(^ {" + level + + "}.*)|(\\s*)"); + text += "\n" + line.trim(); + for (String l : lines) { + text += "\n" + l.trim(); + } + + } + } + if (!bLine) { + in.skipBlankLines(); + String[] linesTmp = in + .readWhile("^\\s*\\.\\.\\s\\[(#|[0-9]|\\*).*\\]\\s.+$"); + + if (linesTmp.length > 0) { + line = linesTmp[0]; + bLine = true; + } + } + + } + if (line == null) { + line = ""; + } + footnote.setText(text); + done = true; + } + + } + } + + } while (bLine); + } + } + endPeek(); + return result; + } + + /** + * Read block text, block text have same indentation + * + * @param minLeftMargin + * min left blank needed to accept to read block + * @return String + * @throws IOException + */ + private String readBlockWithBlankLine(int level) throws IOException { + String txt = ""; + String[] lines = in.readWhile("(^ {" + level + "}.*)|(\\s*)"); + while (lines.length > 0) { + for (String l : lines) { + l = l.trim(); + txt += l + "\n"; + + } + lines = in.readWhile("(^ {" + level + "}.*)|(\\s*)"); + } + return txt; + } + + /** + * Lit les premieres ligne non vide et les retourne, rien n'est modifier par + * rapport aux positions dans le fichier. Util pour afficher a l'utilisateur + * les lignes qui ont produit une erreur + * + * @return les lignes non vides + * @throws IOException + */ + public String readNotBlanckLine() throws IOException { + beginPeek(); + in.skipBlankLines(); + String line = joinBlock(in.readUntilBlank(), "\n", false); + endPeek(); + return line; + } + + /** + * return the number of line read + * + * @return int + */ + public int getLineNumber() { + return in.getLineNumber(); + } + + /** + * return the number of char read + * + * @return int + */ + public int getCharNumber() { + return in.getCharNumber(); + } + + /** + * return true if line can be underline or overline for title + * + * @param line + * @return boolean + */ + private boolean startsWithTitleChar(String line) { + if (line == null || line.length() < 2) { + return false; + } + // est-ce que la ligne est constituer entierement du meme caractere et + // qu'il y en a au moins 2 + boolean result = line + .matches("([" + escapeRegex(TITLE_CHAR) + "])\\1+"); + return result; + } + + /** + * @param title_charescapeRegex + * @return String + */ + private String escapeRegex(String text) { + String result = text.replaceAll("([()[\\\\]*+?.])", "\\\\$1"); + return result; + } + + /** + * @param String + * line + * @return int + * @throws IOException + */ + private int level(String line) { + int result = 0; + String sTmp = line.replaceAll("\\s", " "); + while (sTmp.length() > result && sTmp.charAt(result) == ' ') { + result++; + } + return result; + } +} Copied: branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/legacy/JRSTReader.java (from rev 695, branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/JRSTReader.java) =================================================================== --- branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/legacy/JRSTReader.java (rev 0) +++ branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/legacy/JRSTReader.java 2012-06-05 14:44:35 UTC (rev 696) @@ -0,0 +1,2419 @@ +/* + * #%L + * JRst :: Api + * + * $Id: JRSTReader.java 638 2011-12-23 10:35:21Z jruchaud $ + * $HeadURL: http://svn.nuiton.org/svn/jrst/branches/jrst-docutils-jython/jrst/src/main/j... $ + * %% + * Copyright (C) 2004 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +/* * + * JRSTReader.java + * + * Created: 27 oct. 06 00:15:34 + * + * @author poussin + * @version $Revision: 638 $ + * + * Last update: $Date: 2011-12-23 11:35:21 +0100 (ven. 23 déc. 2011) $ + * by : $Author: jruchaud $ + */ + +package org.nuiton.jrst.legacy; + +import static org.nuiton.i18n.I18n._; +import static org.nuiton.jrst.legacy.ReStructuredText.ADDRESS; +import static org.nuiton.jrst.legacy.ReStructuredText.ADMONITION; +import static org.nuiton.jrst.legacy.ReStructuredText.ATTRIBUTION; +import static org.nuiton.jrst.legacy.ReStructuredText.AUTHOR; +import static org.nuiton.jrst.legacy.ReStructuredText.AUTHORS; +import static org.nuiton.jrst.legacy.ReStructuredText.BLOCK_QUOTE; +import static org.nuiton.jrst.legacy.ReStructuredText.BULLET_LIST; +import static org.nuiton.jrst.legacy.ReStructuredText.COLSPEC; +import static org.nuiton.jrst.legacy.ReStructuredText.COMMENT; +import static org.nuiton.jrst.legacy.ReStructuredText.CONTACT; +import static org.nuiton.jrst.legacy.ReStructuredText.COPYRIGHT; +import static org.nuiton.jrst.legacy.ReStructuredText.DATE; +import static org.nuiton.jrst.legacy.ReStructuredText.DECORATION; +import static org.nuiton.jrst.legacy.ReStructuredText.DEFINITION; +import static org.nuiton.jrst.legacy.ReStructuredText.DEFINITION_LIST; +import static org.nuiton.jrst.legacy.ReStructuredText.DEFINITION_LIST_ITEM; +import static org.nuiton.jrst.legacy.ReStructuredText.DESCRIPTION; +import static org.nuiton.jrst.legacy.ReStructuredText.DOCINFO; +import static org.nuiton.jrst.legacy.ReStructuredText.DOCTEST_BLOCK; +import static org.nuiton.jrst.legacy.ReStructuredText.DOCUMENT; +import static org.nuiton.jrst.legacy.ReStructuredText.EMPHASIS; +import static org.nuiton.jrst.legacy.ReStructuredText.ENTRY; +import static org.nuiton.jrst.legacy.ReStructuredText.ENUMERATED_LIST; +import static org.nuiton.jrst.legacy.ReStructuredText.FIELD; +import static org.nuiton.jrst.legacy.ReStructuredText.FIELD_BODY; +import static org.nuiton.jrst.legacy.ReStructuredText.FIELD_LIST; +import static org.nuiton.jrst.legacy.ReStructuredText.FIELD_NAME; +import static org.nuiton.jrst.legacy.ReStructuredText.FOOTER; +import static org.nuiton.jrst.legacy.ReStructuredText.FOOTNOTE; +import static org.nuiton.jrst.legacy.ReStructuredText.FOOTNOTE_REFERENCE; +import static org.nuiton.jrst.legacy.ReStructuredText.FOOTNOTE_SYMBOL; +import static org.nuiton.jrst.legacy.ReStructuredText.GENERATED; +import static org.nuiton.jrst.legacy.ReStructuredText.HEADER; +import static org.nuiton.jrst.legacy.ReStructuredText.IMAGE; +import static org.nuiton.jrst.legacy.ReStructuredText.LABEL; +import static org.nuiton.jrst.legacy.ReStructuredText.LINE; +import static org.nuiton.jrst.legacy.ReStructuredText.LINE_BLOCK; +import static org.nuiton.jrst.legacy.ReStructuredText.LIST_ITEM; +import static org.nuiton.jrst.legacy.ReStructuredText.LITERAL; +import static org.nuiton.jrst.legacy.ReStructuredText.LITERAL_BLOCK; +import static org.nuiton.jrst.legacy.ReStructuredText.OPTION; +import static org.nuiton.jrst.legacy.ReStructuredText.OPTION_ARGUMENT; +import static org.nuiton.jrst.legacy.ReStructuredText.OPTION_GROUP; +import static org.nuiton.jrst.legacy.ReStructuredText.OPTION_LIST; +import static org.nuiton.jrst.legacy.ReStructuredText.OPTION_LIST_ITEM; +import static org.nuiton.jrst.legacy.ReStructuredText.OPTION_STRING; +import static org.nuiton.jrst.legacy.ReStructuredText.ORGANIZATION; +import static org.nuiton.jrst.legacy.ReStructuredText.PARAGRAPH; +import static org.nuiton.jrst.legacy.ReStructuredText.REFERENCE; +import static org.nuiton.jrst.legacy.ReStructuredText.REGEX_ANONYMOUS_HYPERLINK_REFERENCE; +import static org.nuiton.jrst.legacy.ReStructuredText.REGEX_EMAIL; +import static org.nuiton.jrst.legacy.ReStructuredText.REGEX_EMPHASIS; +import static org.nuiton.jrst.legacy.ReStructuredText.REGEX_FOOTNOTE_REFERENCE; +import static org.nuiton.jrst.legacy.ReStructuredText.REGEX_HYPERLINK_REFERENCE; +import static org.nuiton.jrst.legacy.ReStructuredText.REGEX_INLINE_REFERENCE; +import static org.nuiton.jrst.legacy.ReStructuredText.REGEX_LITERAL; +import static org.nuiton.jrst.legacy.ReStructuredText.REGEX_REFERENCE; +import static org.nuiton.jrst.legacy.ReStructuredText.REGEX_STRONG; +import static org.nuiton.jrst.legacy.ReStructuredText.REGEX_SUBSTITUTION_REFERENCE; +import static org.nuiton.jrst.legacy.ReStructuredText.REVISION; +import static org.nuiton.jrst.legacy.ReStructuredText.ROW; +import static org.nuiton.jrst.legacy.ReStructuredText.SECTION; +import static org.nuiton.jrst.legacy.ReStructuredText.SIDEBAR; +import static org.nuiton.jrst.legacy.ReStructuredText.STATUS; +import static org.nuiton.jrst.legacy.ReStructuredText.STRONG; +import static org.nuiton.jrst.legacy.ReStructuredText.SUBSTITUTION_DEFINITION; +import static org.nuiton.jrst.legacy.ReStructuredText.SUBTITLE; +import static org.nuiton.jrst.legacy.ReStructuredText.TABLE; +import static org.nuiton.jrst.legacy.ReStructuredText.TARGET; +import static org.nuiton.jrst.legacy.ReStructuredText.TBODY; +import static org.nuiton.jrst.legacy.ReStructuredText.TERM; +import static org.nuiton.jrst.legacy.ReStructuredText.TGROUP; +import static org.nuiton.jrst.legacy.ReStructuredText.THEAD; +import static org.nuiton.jrst.legacy.ReStructuredText.TITLE; +import static org.nuiton.jrst.legacy.ReStructuredText.TOPIC; +import static org.nuiton.jrst.legacy.ReStructuredText.TRANSITION; +import static org.nuiton.jrst.legacy.ReStructuredText.VERSION; + + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.StringReader; +import java.io.UnsupportedEncodingException; +import java.net.URL; +import java.net.URLEncoder; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.TreeSet; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.NoSuchElementException; + +import org.apache.commons.lang.ObjectUtils; +import org.apache.commons.lang.StringEscapeUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.nuiton.jrst.JRSTDirective; +import org.nuiton.jrst.legacy.directive.ContentDirective; +import org.nuiton.jrst.legacy.directive.DateDirective; +import org.nuiton.jrst.legacy.directive.ImageDirective; +import org.nuiton.jrst.legacy.directive.SectnumDirective; +import org.nuiton.util.StringUtil; +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.DocumentHelper; +import org.dom4j.Element; +import org.dom4j.IllegalAddException; +import org.dom4j.Node; +import org.dom4j.VisitorSupport; + +/* + * + * <pre> +--------------------------------------------------------------------+ | + * document [may begin with a title, subtitle, decoration, docinfo] | | + * +--------------------------------------+ | | sections [each begins with a + * title] | + * +-----------------------------+-------------------------+------------+ | + * [body elements:] | (sections) | | | - literal | - lists | | - hyperlink + * +------------+ | | blocks | - tables | | targets | | para- | - doctest | - + * block | foot- | - sub. defs | | graphs | blocks | quotes | notes | - comments | + * +---------+-----------+----------+-------+--------------+ | [text]+ | [text] | + * (body elements) | [text] | | (inline + * +-----------+------------------+--------------+ | markup) | +---------+ + * </pre> + * + * + * Inline support: http://docutils.sourceforge.net/docs/user/rst/quickref.html + * + * <li> STRUCTURAL ELEMENTS: document, section, topic, sidebar <li> STRUCTURAL + * SUBELEMENTS: title, subtitle, decoration, docinfo, transition <li> docinfo: + * address, author, authors, contact, copyright, date, field, organization, + * revision, status, version <li> decoration: footer, header <li> BODY ELEMENTS: + * admonition, attention, block_quote, bullet_list, caution, citation, comment, + * compound, container, danger, definition_list, doctest_block, enumerated_list, + * error, field_list, figure, footnote, hint, image, important, line_block, + * literal_block, note, option_list, paragraph, pending, raw, rubric, + * substitution_definition, system_message, table, target, tip, warning <li> + * SIMPLE BODY ELEMENTS: comment, doctest_block, image, literal_block, + * paragraph, pending, raw, rubric, substitution_definition, target <li> + * COMPOUND BODY ELEMENTS: admonition, attention, block_quote, bullet_list, + * caution, citation, compound, container, danger, definition_list, + * enumerated_list, error, field_list, figure, footnote, hint, important, + * line_block, note, option_list, system_message, table, tip, warning <li> BODY + * SUBELEMENTS: attribution, caption, classifier, colspec, field_name, label, + * line, option_argument, option_string, term definition, definition_list_item, + * description, entry, field, field_body, legend, list_item, option, + * option_group, option_list_item, row, tbody, tgroup, thead <li> INLINE + * ELEMENTS: abbreviation, acronym, citation_reference, emphasis, + * footnote_reference, generated, image, inline, literal, problematic, + * reference, strong, subscript, substitution_reference, superscript, target, + * title_reference, raw + * + * <pre> DOCUMENT :: ( (title, subtitle?)?, decoration?, (docinfo, + * transition?)?, STRUCTURE.MODEL; ) decoration :: (header?, footer?) header, + * footer, definition, description, attention, caution, danger, error, hint, + * important, note, tip, warning :: (BODY.ELEMENTS;)+ transition :: EMPTY + * docinfo :: (BIBLIOGRAPHIC.ELEMENTS;)+ BIBLIOGRAPHIC.ELEMENTS :: author | + * authors | organization | contact | address | version | revision | status | + * date | copyright | field authors :: ( (author)+ ) field :: (field_name, + * field_body) field_body, list_item :: (BODY.ELEMENTS;)* STRUCTURE.MODEL :: ( ( + * (BODY.ELEMENTS; | topic | sidebar)+, transition? )*, ( (section), + * (transition?, (section) )* )? ) BODY.ELEMENTS :: paragraph | compound | + * container | literal_block | doctest_block | line_block | block_quote | table | + * figure | image | footnote | citation | rubric | bullet_list | enumerated_list | + * definition_list | field_list | option_list | attention | caution | danger | + * error | hint | important | note | tip | warning | admonition | reference | + * target | substitution_definition | comment | pending | system_message | raw + * topic :: (title?, (BODY.ELEMENTS;)+) sidebar :: (title, subtitle?, + * (BODY.ELEMENTS; | topic)+) section :: (title, STRUCTURE.MODEL;) line_block :: + * (line | line_block)+ block_quote:: ((BODY.ELEMENTS;)+, attribution?) + * bullet_list, enumerated_list :: (list_item +) definition_list :: + * (definition_list_item +) definition_list_item :: (term, classifier?, + * definition) field_list :: (field +) option_list :: (option_list_item +) + * option_list_item :: (option_string, option_argument *, description) + * option_string, option_argument :: (#PCDATA) admonition :: (title, + * (BODY.ELEMENTS;)+) + * + * title, subtitle, author, organization, contact, address, version, revision, + * status, date, copyright, field_name, paragraph, compound, container, + * literal_block, doctest_block, attribution, line, term, classifier :: + * TEXT.MODEL; + * + * TEXT.MODEL :: (#PCDATA | INLINE.ELEMENTS;)* INLINE.ELEMENTS :: emphasis | + * strong | literal | reference | footnote_reference | citation_reference | + * substitution_reference | title_reference | abbreviation | acronym | subscript | + * superscript | inline | problematic | generated | target | image | raw + * emphasis :: '*' #PCDATA '*' strong :: '**' #PCDATA '**' literal :: '``' + * #PCDATA '``' footnote_reference :: '[' ([0-9]+|#) ']' citation_reference :: + * '[' [a-zA-Z]+ ']' + * + * </pre> + */ + +/** + * Le principe est d'utiliser les methodes peek* {@link JRSTLexer} pour + * prendre l'element que l'on attend, si la methode retourne null ou un autre + * element et bien c que ce n'est pas le bon choix, cela veut dire que l'element + * courant est fini d'etre lu (plus de paragraphe dans la section par exemple) + * ou qu'il y a une erreur dans le fichier en entre. + * <p> + * On construit un arbre XML representant le RST au fur et a mesure, on peut + * ensuite appliquer une feuille de style ou autre chose avec + * {@link org.nuiton.jrst.JRSTGenerator} + * + * <p> + * Tous les elements ont un attribut level qui permet de savoir on il est dans + * la hierarchie. Le Document a le level -1001, et les sections/titres on pour + * level les valeurs 1000, -999, -998, ... + * <p> + * de cette facon les methods isUpperLevel et isSameLevel fonctionne pour tous + * les elements de la meme facon + * + * <pre> + * abbreviation + * acronym + * address (done) + * admonition (done) + * attention (done) + * attribution + * author (done) + * authors (done) + * block_quote (done) + * bullet_list (done) + * caption + * caution (done) + * citation + * citation_reference + * classifier (done) + * colspec (done) + * comment + * compound + * contact (done) + * container + * copyright (done) + * danger (done) + * date (done) + * decoration (done) + * definition (done) + * definition_list (done) + * definition_list_item (done) + * description (done) + * docinfo (done) + * doctest_block (done) + * document (done) + * emphasis (done) + * entry (done) + * enumerated_list (done) + * error (done) + * field (done) + * field_body (done) + * field_list (done) + * field_name (done) + * figure + * footer (done) + * footnote (done) + * footnote_reference (done) + * generated + * header (done) + * hint (done) + * image (done) + * important (done) + * inline + * label + * legend + * line (done) + * line_block (done) + * list_item (done) + * literal (done) + * literal_block (done) + * note (done) + * option (done) + * option_argument (done) + * option_group (done) + * option_list (done) + * option_list_item (done) + * option_string (done) + * organization (done) + * paragraph (done) + * pending + * problematic + * raw + * reference (done) + * revision (done) + * row (done) + * rubric + * section (done) + * sidebar (done) + * status (done) + * strong (done) + * subscript + * substitution_definition + * substitution_reference + * subtitle (done) + * superscript + * system_message + * table (done) + * target (done) + * tbody (done) + * term (done) + * tgroup (done) + * thead (done) + * tip (done) + * title (done) + * title_reference + * topic (done) + * transition (done) + * version (done) + * warning (done) + * </pre> + * + * Created: 27 oct. 06 00:15:34 + * + * @author poussin, letellier + * @version $Revision: 638 $ + * + * Last update: $Date: 2011-12-23 11:35:21 +0100 (ven. 23 déc. 2011) $ + * by : $Author: jruchaud $ + */ +public class JRSTReader { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + private static Log log = LogFactory.getLog(JRSTReader.class); + + protected static final String ANONYMOUS = "anonymous"; + + protected static final String AUTO = "auto"; + + protected static final String AUTONUM = "autoNum"; + + protected static final String AUTONUMLABEL = "autoNumLabel"; + + protected static final String AUTOSYMBOL = "autoSymbol"; + + protected static final String ATTR_REFID = "refid"; + + protected static final String ATTR_INLINE = "inline"; + + protected static final String ATTR_IDS = "ids"; + + protected static final String BACKREFS = "backrefs"; + + protected static final String BULLET = "bullet"; + + protected static final String CLASS = "class"; + + protected static final String CONTENTS = "contents"; + + protected static final String DELIMITER = "delimiter"; + + protected static final String DELIMITEREXISTE ="delimiterExiste"; + + protected static final String ENUMTYPE = "enumtype"; + + protected static final String FOOTNOTES = "footnotes"; + + protected static final String ID = "id"; + + protected static final String INCLUDE = "include"; + + protected static final String LEVEL = "level"; + + protected static final String NAME = "name"; + + protected static final String NAMES = "names"; + + protected static final String NUM = "num"; + + protected static final String REFURI = "refuri"; + + protected static final String PREFIX = "prefix"; + + protected static final String REMOVE = "remove"; + + protected static final String START = "start"; + + protected static final String SECTNUM = "sectnum"; + + protected static final String SUBEXISTE = "subExiste"; + + protected static final String SUFFIX = "suffix"; + + protected static final String TRUE = "true"; + + protected static final String TYPE = "type"; + + protected static final String TARGETANONYMOUS = "targetAnonymous"; + + protected static final String VALUE = "value"; + + protected boolean ERROR_MISSING_ITEM; + + protected static int MAX_SECTION_DEPTH = -1000; + + protected static Map<String, JRSTDirective> defaultDirectives; + + protected Map<String, JRSTDirective> directives = new HashMap<String, JRSTDirective>(); + + private boolean sectnum; + + private Element footer; + + private int idMax; + + private int symbolMax; + + private int symbolMaxRef; + + private LinkedList<Integer> lblFootnotes = new LinkedList<Integer>(); + + private LinkedList<Integer> lblFootnotesRef = new LinkedList<Integer>(); + + private LinkedList<Element> eFootnotes = new LinkedList<Element>(); + + private LinkedList<Element> eTarget = new LinkedList<Element>(); + + private LinkedList<Element> eTargetAnonymous = new LinkedList<Element>(); + + private LinkedList<Element> eTargetAnonymousCopy = new LinkedList<Element>(); + + private LinkedList<Element> eTitle = new LinkedList<Element>(); + + static { + defaultDirectives = new HashMap<String, JRSTDirective>(); + defaultDirectives.put(IMAGE, new ImageDirective()); + defaultDirectives.put(DATE, new DateDirective()); + defaultDirectives.put("time", new DateDirective()); + defaultDirectives.put(CONTENTS, new ContentDirective()); + // defaultDirectives.put("calc", new CalcDirective()); + defaultDirectives.put(SECTNUM, new SectnumDirective()); + // TODO put here all other directive + } + + /** + * + */ + public JRSTReader() { + } + + /** + * @param name + * @return the defaultDirectives + */ + public static JRSTDirective getDefaultDirective(String name) { + return defaultDirectives.get(name); + } + + /** + * @param name + * @param directive the defaultDirectives to set + */ + public static void addDefaultDirectives(String name, JRSTDirective directive) { + JRSTReader.defaultDirectives.put(name, directive); + } + + /** + * @param name + * @return the defaultDirectives + */ + public JRSTDirective getDirective(String name) { + return directives.get(name); + } + + /** + * @param name + * @param directive the defaultDirectives to set + */ + public void addDirectives(String name, JRSTDirective directive) { + directives.put(name, directive); + } + + /** + * On commence par decouper tout le document en Element, puis on construit + * l'article a partir de ces elements. + * + * @param reader + * @return le document cree + * @throws Exception + */ + public Document read(Reader reader) throws Exception { + JRSTLexer lexer = new JRSTLexer(reader); + try { + Element root = composeDocument(lexer); + + Document result = DocumentHelper.createDocument(); + result.setRootElement(root); + + root.accept(new VisitorSupport() { + @Override + public void visit(Element e) { + // remove all level attribute + e.addAttribute(LEVEL, null); + // Constrution du sommaire + String type = e.attributeValue(TYPE); + if (type != null) { + if (type.equals(CONTENTS)) { + composeContents(e); + e.addAttribute(TYPE, null); + } + } + + if (TRUE.equalsIgnoreCase(e.attributeValue(ATTR_INLINE))) { + e.addAttribute(ATTR_INLINE, null); + try { + inline(e); + } catch (DocumentException eee) { + if (log.isWarnEnabled()) { + log.warn("Can't inline text for " + e, eee); + } + } catch (UnsupportedEncodingException ee) { + if (log.isWarnEnabled()) { + log.warn("Unsupported encoding " + e, ee); + } + } + } + } + }); + + return result; + } catch (Exception eee) { + log.error(_("JRST parsing error line %d char %s:\n%s", lexer + .getLineNumber(), lexer.getCharNumber(), lexer + .readNotBlanckLine())); + throw eee; + } + } + + /** + * <p> + * exemple : + * </p> + * + * <pre> + * ..contents : Sommaire + * depth: 3 + * </pre> + * + * <p> + * depth sert a limiter la profondeur du sommaire + * </p> + * + * @param Element + * + */ + private void composeContents(Element e) { + Element result = DocumentHelper.createElement(TOPIC); + String option = e.getText(); + int depth = -1; + // depth: 3 + Pattern pattern = Pattern.compile("\\s*\\:depth\\:\\s*\\p{Digit}+"); + Matcher matcher = pattern.matcher(option); + if (matcher.matches()) { + pattern = Pattern.compile("\\p{Digit}+"); + matcher = pattern.matcher(matcher.group()); + if (matcher.find()) { + depth = Integer.parseInt(matcher.group()); + } + } + int levelInit = 0; + boolean noTitle = false; + + try { + levelInit = Integer.parseInt(eTitle.getFirst().attributeValue( + LEVEL)); + } catch (NumberFormatException eee) { + log.error("Can't parse level in: " + + eTitle.getFirst().asXML(), eee); + return; + } catch (NoSuchElementException eee) { + noTitle = true; + } + + LinkedList<Element> title = new LinkedList<Element>(); + // on rajoute les refid + for (int i = 0; i < eTitle.size(); i++) { + idMax++; + eTitle.get(i).addAttribute(ATTR_REFID, ID + idMax); + } + // on enleve les titres limites par depth + for (Element el : eTitle) { + int level = Integer.parseInt(el.attributeValue(LEVEL)); + level = level - levelInit; + el.addAttribute(LEVEL, "" + level); + if (depth == -1) { + title.add(el); + } + else { + if (depth > level) { + title.add(el); + } + } + } + e.addAttribute(CLASS, CONTENTS); + String titleValue = e.attributeValue(VALUE); + e.addAttribute(VALUE, null); + String value = titleValue.trim().toLowerCase(); + // sans titre c "contents" par default + if (value.matches("\\s*")) { + value = CONTENTS; + titleValue = "Contents"; + } + e.addAttribute(ATTR_IDS, value); + e.addAttribute(NAMES, value); + result.addElement(TITLE).setText(titleValue); + // on compose les lignes + if (!noTitle) { //Si il y a des titres à lier à la table des matières + result.add(composeLineContent(title, "")); + } + e.setText(""); + e.appendContent(result); + } + + /** + * @param title + * <Element> title, String num + * @return Element + */ + private Element composeLineContent(LinkedList<Element> title, String num) { + Element result = DocumentHelper.createElement(BULLET_LIST); + if (sectnum) { + result.addAttribute(CLASS, "auto-toc"); + } + Element item = null; + int cnt = 0; + while (!title.isEmpty()) { + + Element e = title.getFirst(); + int level = Integer.parseInt(e.attributeValue(LEVEL)); + LinkedList<Element> child = new LinkedList<Element>(); + + if (level <= 0) { + cnt++; + title.removeFirst(); + item = result.addElement(LIST_ITEM); + Element para = item.addElement(PARAGRAPH); + Element reference = para.addElement(REFERENCE); + String text = e.getText(); + String id = e.attributeValue(ATTR_REFID); + reference.addAttribute(ATTR_IDS, id); + reference.addAttribute(ATTR_REFID, text.replaceAll("\\W+", " ") + .trim().toLowerCase().replaceAll("\\W+", "-")); + // si l'on doit les numeroter + if (sectnum) { + Element generated = reference.addElement(GENERATED) + .addAttribute(CLASS, SECTNUM); + generated.setText(num + cnt + " "); + for (int i = 0; i < eTitle.size(); i++) { + if (eTitle.get(i).attributeValue(ATTR_REFID).equals(id)) { + Element generatedTitle = eTitle.get(i).addElement( + GENERATED); + generatedTitle.addAttribute(CLASS, SECTNUM); + generatedTitle.setText(num + cnt + " "); + } + + } + } + + text = text.trim(); + text = text.replaceAll("_", ""); + + text = REGEX_STRONG.matcher(text).replaceAll( + "<" + STRONG + ">$1</" + STRONG + ">"); + text = REGEX_EMPHASIS.matcher(text).replaceAll( + "<" + EMPHASIS + ">$1</" + EMPHASIS + ">"); + + try { + Element textElement = DocumentHelper.parseText("<TMP>" + text + "</TMP>").getRootElement(); + reference.appendContent(textElement); + + } catch (DocumentException eee) { + if (log.isWarnEnabled()) { + log.warn("Can't inline text for " + e, eee); + } + } + + } else { + do { + e.addAttribute(LEVEL, "" + (level - 1)); + child.add(e); + title.removeFirst(); + if (!title.isEmpty()) { + e = title.getFirst(); + level = Integer.parseInt(e.attributeValue(LEVEL)); + } + } while (!title.isEmpty() && level > 0); + String numTmp = ""; + // numerotation + if (sectnum) { + numTmp = num + cnt + "."; + } + if (item != null) { + item.add(composeLineContent(child, numTmp)); // Appel + // recursif + } else { + result.add(composeLineContent(child, numTmp)); // Appel + // recursif + } + } + } + return result; + } + + /** + * @param lexer + * @return Element + * @throws Exception + */ + private Element composeDocument(JRSTLexer lexer) throws Exception { + Element result = DocumentHelper.createElement(DOCUMENT); + result.addAttribute(LEVEL, String.valueOf(MAX_SECTION_DEPTH - 1)); + + Element item = null; + + // skip blank line + skipBlankLine(lexer); + + // les liens anonymes + LinkedList<Element> items = lexer.refTarget(); + for (Element e : items) { + eTarget.add(e); + + } + + // le header + item = lexer.peekHeader(); + if (itemEquals(HEADER, item)) { + Element decoration = result.addElement(DECORATION); + Element header = decoration.addElement(HEADER); + header.addAttribute(ATTR_INLINE, TRUE).setText(item.getText()); + } + + // le footer + item = lexer.peekFooter(); + if (itemEquals(FOOTER, item)) { + footer = DocumentHelper.createElement(DECORATION); + Element header = footer.addElement(FOOTER); + header.addAttribute(ATTR_INLINE, TRUE).setText(item.getText()); + } + + // les hyperlinks + LinkedList<Element> listItem = lexer.peekTargetAnonymous(); + if (listItem != null) { + for (Element e : listItem) { + Element anonym = DocumentHelper.createElement(TARGET); + anonym.addAttribute(ANONYMOUS, "1"); + idMax++; + anonym.addAttribute(ATTR_IDS, ID + idMax); + + anonym.addAttribute(REFURI, e.attributeValue(REFURI).trim()); + + eTargetAnonymous.add(anonym); + eTargetAnonymousCopy.add(anonym); + } + } + + // les eléments a enlever (deja parser : header, footer...) + item = lexer.peekRemove(); + if (itemEquals(REMOVE, item)) { + lexer.remove(); + } + + // skip blank line + skipBlankLine(lexer); + + // les commentaires + List<Element> comments = lexer.peekAllComment(); + + // le titre du doc + item = lexer.peekTitle(); + if (itemEquals(TITLE, item)) { + lexer.remove(); + Element title = result.addElement(TITLE); + String txt = item.getText(); + result.addAttribute(ATTR_IDS, txt.replaceAll("[(\\W+)_]", " ") + .toLowerCase().trim().replaceAll("\\s+", "-")); + result.addAttribute(NAMES, txt.toLowerCase().replaceAll( + "[(\\W+)_&&[^\\:]]+", " ").trim()); + copyLevel(item, title); + title.addAttribute(ATTR_INLINE, TRUE).setText(txt.trim()); + } + + // skip blank line + skipBlankLine(lexer); + + // le sous titre du doc + item = lexer.peekTitle(); + if (itemEquals(TITLE, item)) { + lexer.remove(); + Element subtitle = result.addElement(SUBTITLE); + String txt = item.getText(); + subtitle.addAttribute(ATTR_IDS, txt.replaceAll("[(\\W+)_]", " ") + .toLowerCase().trim().replaceAll("\\s+", "-")); + subtitle.addAttribute(NAMES, txt.toLowerCase().replaceAll( + "[(\\W+)_]", " ").trim()); + copyLevel(item, subtitle); + DocumentHelper.createElement(FOOTNOTES); + subtitle.addAttribute(ATTR_INLINE, TRUE).setText(txt.trim()); + } + + // skip blank line + skipBlankLine(lexer); + + // les infos du doc + item = lexer.peekDocInfo(); + Element documentinfo = null; + while (itemEquals(DOCINFO, item) || itemEquals(FIELD_LIST, item)) { + + if (documentinfo == null) { + documentinfo = result.addElement(DOCINFO); + } + skipBlankLine(lexer); + if (itemEquals(FIELD_LIST, item)) { + Element field = composeFieldItemList(lexer); + documentinfo.add(field); + } else { + if ("author".equalsIgnoreCase(item.attributeValue(TYPE))) { + documentinfo.addElement(AUTHOR).addAttribute(ATTR_INLINE, + TRUE).setText(item.getText()); + } else if ("date".equalsIgnoreCase(item.attributeValue(TYPE))) { + documentinfo.addElement(DATE) + .addAttribute(ATTR_INLINE, TRUE).setText( + item.getText().trim()); + } else if ("organization".equalsIgnoreCase(item + .attributeValue(TYPE))) { + documentinfo.addElement(ORGANIZATION).addAttribute( + ATTR_INLINE, TRUE).setText(item.getText().trim()); + } else if ("contact".equalsIgnoreCase(item + .attributeValue(TYPE))) { + documentinfo.addElement(CONTACT).addAttribute(ATTR_INLINE, + TRUE).setText(item.getText().trim()); + } else if ("address".equalsIgnoreCase(item + .attributeValue(TYPE))) { + documentinfo.addElement(ADDRESS).addAttribute(ATTR_INLINE, + TRUE).setText(item.getText().trim()); + } else if ("version".equalsIgnoreCase(item + .attributeValue(TYPE))) { + documentinfo.addElement(VERSION).addAttribute(ATTR_INLINE, + TRUE).setText(item.getText().trim()); + } else if ("revision".equalsIgnoreCase(item + .attributeValue(TYPE))) { + documentinfo.addElement(REVISION).addAttribute(ATTR_INLINE, + TRUE).setText(item.getText().trim()); + } else if ("status".equalsIgnoreCase(item + .attributeValue(TYPE))) { + documentinfo.addElement(STATUS).addAttribute(ATTR_INLINE, + TRUE).setText(item.getText().trim()); + } else if ("copyright".equalsIgnoreCase(item + .attributeValue(TYPE))) { + documentinfo.addElement(COPYRIGHT).addAttribute(ATTR_INLINE, + TRUE).setText(item.getText().trim()); + } else if ("authors".equalsIgnoreCase(item + .attributeValue(TYPE))) { + Element authors = documentinfo.addElement(AUTHORS); + int t = 0; + String line = item.getText(); + for (int i = 0; i < line.length(); i++) { + if (line.charAt(i) == ';' || line.charAt(i) == ',') { + authors.addElement(AUTHOR).addAttribute(ATTR_INLINE, + TRUE) + .setText(line.substring(t, i).trim()); + t = i + 1; + } + + } + authors.addElement(AUTHOR).addAttribute(ATTR_INLINE, TRUE) + .setText(line.substring(t, line.length()).trim()); + } + lexer.remove(); + } + // skip blank line + // skipBlankLine(lexer); + item = lexer.peekDocInfo(); + + } + + // Ajout des commentaires + // System.out.println(comment.asXML()); + for (Element comment : comments){ + result.add(composeComment(comment)); + } + + // l'abstract du doc + item = lexer.peekTitle(); + while (itemNotEquals(TITLE, item) && !lexer.eof()) { + composeBody(lexer, result); + item = lexer.peekTitle(); + } + + // les sections + item = lexer.peekTitle(); + while (itemEquals(TITLE, item, true, lexer.eof())) { + Element section = composeSection(lexer); + result.add(section); + item = lexer.peekTitle(); + } + + // on ajoute le footer a la fin + if (footer != null) { + result.add(footer); + } + + return result; + } + + /** + * <p> + * skip blank line + * </p> + * + * @param lexer + * @throws DocumentException + * @throws IOException + */ + private void skipBlankLine(JRSTLexer lexer) throws IOException, + DocumentException { + Element item = lexer.peekBlankLine(); + // skip blank line + while (itemEquals(JRSTLexer.BLANK_LINE, item)) { + // go to the next element + lexer.remove(); + item = lexer.peekBlankLine(); + } + } + + /** + * * + * <p> + * Corps du document + * </p> + * + * @param lexer + * @return Element + * @throws DocumentException + * @throws IOException + */ + private Element composeBody(JRSTLexer lexer, Element parent) + throws Exception { + + Element item = lexer.peekTitleOrBodyElement(); + if (item == null && !lexer.eof()) { + item = lexer.peekTitleOrBodyElement(); + } + + while (!lexer.eof() && itemNotEquals(TITLE, item) + && isUpperLevel(item, parent)) { + if (itemEquals(JRSTLexer.BLANK_LINE, item)) { + // go to the next element + lexer.remove(); + } else if (itemEquals(REMOVE, item)) { + lexer.remove(); + } else if (itemEquals(INCLUDE, item)) { + lexer.remove(); + Element list = composeInclude(item); + parent.add(list); + } else if (itemEquals(DOCTEST_BLOCK, item)) { + lexer.remove(); + Element list = composeDoctestBlock(item); + parent.add(list); + } else if (itemEquals(ADMONITION, item)) { + lexer.remove(); + Element list = composeAdmonition(item); + parent.add(list); + } else if (itemEquals(SIDEBAR, item)) { + lexer.remove(); + Element list = composeSidebar(item); + parent.add(list); + } else if (itemEquals(TOPIC, item)) { + lexer.remove(); + Element list = composeTopic(item); + parent.add(list); + } else if (itemEquals(TRANSITION, item)) { + lexer.remove(); + Element para = parent.addElement(TRANSITION); + copyLevel(item, para); + } else if (itemEquals(PARAGRAPH, item)) { + lexer.remove(); + Element para = parent.addElement(PARAGRAPH); + copyLevel(item, para); + para.addAttribute(ATTR_INLINE, TRUE).setText(item.getText()); + } else if (itemEquals(JRSTLexer.DIRECTIVE, item)) { + lexer.remove(); + Node directive = composeDirective(item); + parent.add(directive); + } else if (itemEquals(SUBSTITUTION_DEFINITION, item)) { + lexer.remove(); + Element subst = composeSubstitutionDefinition(item); + parent.add(subst); + } else if (itemEquals(LITERAL_BLOCK, item)) { + lexer.remove(); + Element para = parent.addElement(LITERAL_BLOCK); + copyLevel(item, para); + para.setText(item.getText()); + } else if (itemEquals(JRSTLexer.TABLE, item)) { + lexer.remove(); + Element table = composeTable(item); + parent.add(table); + // Element para = parent.addElement(TABLE); + // copyLevel(item, para); + // para.setText(item.getText()); + } else if (itemEquals(LINE_BLOCK, item)) { + lexer.remove(); + Element list = composeLineBlock(lexer, item); + parent.add(list); + } else if (itemEquals(BULLET_LIST, item)) { + Element list = composeBulletList(lexer); + parent.add(list); + } else if (itemEquals(ENUMERATED_LIST, item)) { + Element list = composeEnumeratedList(lexer); + parent.add(list); + } else if (itemEquals(DEFINITION_LIST, item)) { + Element list = composeDefinitionList(lexer); + parent.add(list); + } else if (itemEquals(FIELD_LIST, item)) { + Element list = composeFieldList(lexer); + parent.add(list); + } else if (itemEquals(BLOCK_QUOTE, item)) { + lexer.remove(); + Element list = composeBlockQuote(item); + parent.add(list); + } else if (itemEquals(OPTION_LIST, item)) { + Element list = composeOptionList(lexer); + parent.add(list); + } else if (itemEquals(TARGET, item)) { + lexer.remove(); + Element list = composeTarget(item); + if (list != null) { + try { + parent.add(list); + } catch (IllegalAddException e) {} + } else + System.err.println("Unknown target name : \"" + item.attributeValue(ATTR_IDS) + "\""); + } else if (itemEquals(TARGETANONYMOUS, item)) { + lexer.remove(); + Element list = composeTargetAnonymous(item); + parent.add(list); + } else if (itemEquals(FOOTNOTES, item)) { + lexer.remove(); + Element[] list = composeFootnote(item); + for (Element l : list) { + parent.add(l); + } + } else if (itemEquals(COMMENT, item)) { + lexer.remove(); + Element list = composeComment(item); + parent.add(list); + } + + else { + if (ERROR_MISSING_ITEM) { + throw new DocumentException("Unknow item type: " + + item.getName()); + } else { + lexer.remove(); + } + } + + // Pour afficher le "PseudoXML" + // if (item!=null) System.out.println(item.asXML()); + + item = lexer.peekTitleOrBodyElement(); + } + + return parent; + } + + /** + * <p> + * include un document rst + * </p> + * + * <pre> + * .. include:: doc.rst + * </pre> + * + * <p> + * include un document literal (code...) + * </p> + * + * <pre> + * .. include:: literal + * doc.rst + * </pre> + * + * @param item + * @return Element + * @throws Exception + */ + private Element composeInclude(Element item) throws Exception { + String option = item.attributeValue(OPTION); + String path = item.getText(); + Element result = null; + if (option.equals(LITERAL)) { + result = DocumentHelper.createElement(LITERAL_BLOCK); + FileReader reader = new FileReader(path); + BufferedReader bf = new BufferedReader(reader); + String line = ""; + String lineTmp = bf.readLine(); + while (lineTmp != null) { + line += '\n' + lineTmp; + lineTmp = bf.readLine(); + } + result.setText(line); + } else { + File fileIn = new File(path); + URL url = fileIn.toURI().toURL(); + Reader in = new InputStreamReader(url.openStream()); + + Document doc = newJRSTReader(in); + + result = doc.getRootElement(); + } + return result; + } + + /** + * <pre> + * .. + * So this block is not "lost", + * despite its indentation. + * </pre> + * + * @param item + * @return Element + */ + private Element composeComment(Element item) { + + return item; + } + + /** + * <pre> + * __ http://truc.html + * </pre> + * + * @param item + * @return Element + */ + private Element composeTargetAnonymous(Element item) { + Element result = null; + result = eTargetAnonymousCopy.getFirst(); + eTargetAnonymousCopy.removeFirst(); + return result; + } + + /** + * <pre _ target: target.html </pre> + * + * @param item + * @return Element + */ + private Element composeTarget(Element item) { + Element result = null; + for (Element e : eTarget) { + if (e.attributeValue(ID).equals(item.attributeValue(ID))) { + result = e; + } + } + return result; + } + + /** + * <pre> + * .. [#] This is a footnote + * </pre> + * + * @param item + * @return Element + * @throws Exception + */ + private Element[] composeFootnote(Element item) throws Exception { + Element[] result = null; + if (itemEquals(FOOTNOTES, item)) { + List<Element> footnotes = (List<Element>) item + .selectNodes(FOOTNOTE); + result = new Element[footnotes.size()]; + int cnt = 0; + for (Element footnote : footnotes) { + result[cnt] = DocumentHelper.createElement(FOOTNOTE); + Element efootnote = DocumentHelper.createElement(FOOTNOTE); + int labelMax = 0; + + for (int i = 0; i < lblFootnotes.size(); i++) { + int lbl = lblFootnotes.get(i); + labelMax = Math.max(lbl, labelMax); + } + + boolean[] labels = new boolean[labelMax]; + for (int i = 0; i < labels.length; i++) { + labels[i] = false; + } + for (int i = 0; i < lblFootnotes.size(); i++) { + labels[lblFootnotes.get(i) - 1] = true; + } + idMax++; + String name = null; + String id = ""; + String label = null; + String type = footnote.attributeValue(TYPE); + if (type.equals(AUTONUM) || type.equals(AUTONUMLABEL)) { + result[cnt].addAttribute(AUTO, "1"); + } + if (type.equals(AUTOSYMBOL)) { + result[cnt].addAttribute(AUTO, "*"); + } + result[cnt].addAttribute(BACKREFS, ID + idMax); + efootnote.addAttribute(BACKREFS, ID + idMax); + if (type.equals(NUM) || type.equals(AUTONUMLABEL)) { + name = footnote.attributeValue(NAME); + if (type.equals(AUTONUMLABEL)) { + id = name; + } + else { + label = name; + } + } + if (type.equals(AUTONUM) || type.equals(AUTONUMLABEL)) { + boolean done = false; + + for (int i = 0; i < labels.length && !done; i++) { + if (!labels[i]) { + done = true; + label = "" + (i + 1); + } + } + if (!done) { + label = "" + (labels.length + 1); + } + if (type.equals(AUTONUM)) { + name = label; + } + } + if (type.equals(AUTOSYMBOL)) { + + int nb = Math.abs(symbolMax / 10) + 1; + char symbol = FOOTNOTE_SYMBOL.charAt(symbolMax % 10); + label = ""; + for (int j = 0; j < nb; j++) { + label += symbol; + } + symbolMax++; + + } + result[cnt].addAttribute(ATTR_IDS, "" + id); + efootnote.addAttribute(ATTR_IDS, "" + id); + if (!type.equals(AUTOSYMBOL)) { + result[cnt].addAttribute(NAME, "" + name); + efootnote.addAttribute(NAME, "" + name); + } + result[cnt].addElement(LABEL).setText("" + label); + efootnote.addAttribute(LABEL, "" + label); + if (!type.equals(AUTOSYMBOL)) { + lblFootnotes.add(Integer.parseInt(label)); + } + efootnote.addAttribute(TYPE, type); + eFootnotes.add(efootnote); + String text = footnote.getText(); + Document doc = newJRSTReader(new StringReader(text)); + result[cnt].appendContent(doc.getRootElement()); + + cnt++; + } + } + for (int i = 0; i < result.length; i++) { + if (result[i].attributeValue(ATTR_IDS).equals("")) { + idMax++; + result[i].addAttribute(ATTR_IDS, ID + idMax); + (eFootnotes.get(i)).addAttribute(ATTR_IDS, ID + idMax); + } + + } + + return result; + } + + /** + * <pre> + * -a command-line option "a" -1 file, --one=file, --two file Multiple + * options with arguments. + * </pre> + * + * @param lexer + * @return Element + * @throws Exception + * @throws DocumentException + */ + private Element composeOptionList(JRSTLexer lexer) + throws DocumentException, Exception { + Element item = lexer.peekOption(); + Element result = DocumentHelper.createElement(OPTION_LIST); + while (itemEquals(OPTION_LIST, item)) { + lexer.remove(); + Element optionListItem = result.addElement(OPTION_LIST_ITEM); + Element optionGroup = optionListItem.addElement(OPTION_GROUP); + List<Element> option = (List<Element>) item.selectNodes(OPTION); + for (Element e : option) { + Element eOption = optionGroup.addElement(OPTION); + eOption.addElement(OPTION_STRING).setText( + e.attributeValue(OPTION_STRING)); + if (e.attributeValue(DELIMITEREXISTE).equals(TRUE)) { + eOption.addElement(OPTION_ARGUMENT).addAttribute( + DELIMITER, e.attributeValue(DELIMITER)) + .setText(e.attributeValue(OPTION_ARGUMENT)); + } + } + Element description = optionListItem.addElement(DESCRIPTION); + + String text = item.getText(); + Document doc = newJRSTReader(new StringReader(text)); + description.appendContent(doc.getRootElement()); + + item = lexer.peekOption(); + } + return result; + } + + /** + * <pre> + * .. topic:: Title + * + * Body. + * </pre> + * + * @param Element + * item + * @return Element + * @throws Exception + */ + + private Element composeTopic(Element item) throws Exception { + Element result = null; + result = DocumentHelper.createElement(TOPIC); + result.addElement(TITLE).addAttribute(ATTR_INLINE, TRUE).setText( + item.attributeValue(TITLE)); + String text = item.getText(); + Document doc = newJRSTReader(new StringReader(text)); + result.appendContent(doc.getRootElement()); + + return result; + } + + /** + * <pre> + * .. sidebar:: Title + * :subtitle: If Desired + * + * Body. + * </pre> + * + * @param Element + * @return Element + * @throws Exception + */ + + private Element composeSidebar(Element item) throws Exception { + Element result = null; + result = DocumentHelper.createElement(SIDEBAR); + result.addElement(TITLE).addAttribute(ATTR_INLINE, TRUE).setText( + item.attributeValue(TITLE)); + if (item.attributeValue(SUBEXISTE).equals(TRUE)) { + result.addElement(SUBTITLE).addAttribute(ATTR_INLINE, TRUE).setText( + item.attributeValue(SUBTITLE)); + } + + String text = item.getText(); + Document doc = newJRSTReader(new StringReader(text)); + result.appendContent(doc.getRootElement()); + + return result; + } + + /** + * <pre> + * | line block + * | + * | indent + * </pre> + * + * @param lexer + * @param item + * @return Element + * @throws Exception + */ + private Element composeLineBlock(JRSTLexer lexer, Element item) + throws Exception { + Element result = null; + result = DocumentHelper.createElement(LINE_BLOCK); + List<Element> lines = (List<Element>) item.selectNodes(LINE); + int[] levels = new int[lines.size()]; + int cnt = 0; + for (Element l : lines) { + levels[cnt] = Integer.parseInt(l.attributeValue(LEVEL)); + cnt++; + } + cnt = 0; + boolean[] lineDone = new boolean[lines.size()]; + for (int i = 0; i < lineDone.length; i++) { + lineDone[i] = false; + } + for (Element l : lines) { + if (levels[cnt] == 0) { + result.addElement(LINE).addAttribute(ATTR_INLINE, TRUE).setText( + l.getText()); + } + else { + if (!lineDone[cnt]) { + Element newItem = DocumentHelper.createElement(LINE_BLOCK); + Boolean done = false; + for (int i = cnt; i < lines.size() && !done; i++) { + if (levels[i] > 0) { + Element eLine = newItem.addElement(LINE); + eLine.addAttribute(LEVEL, "" + (levels[i] - 1)); + eLine.setText(lines.get(i).getText()); + lineDone[i] = true; + } else { + done = true; + } + + } + Element eLineBlock = result.addElement(LINE_BLOCK); + // Appel recursif + eLineBlock.appendContent(composeLineBlock(lexer, newItem)); + } + } + cnt++; + + } + return result; + } + + /** + * <pre> + * >>> print 'this is a Doctest block' + * this is a Doctest block + * </pre> + * + * @param Element + * @return Element + */ + private Element composeDoctestBlock(Element item) { + return item; + } + + /** + * <pre> + * As a great paleontologist once said, + * + * This theory, that is mine, is mine. + * + * -- Anne Elk (Miss) + * </pre> + * + * @param Element + * @return Element + * @throws Exception + * + */ + private Element composeBlockQuote(Element item) throws Exception { + Element result = null; + result = DocumentHelper.createElement(BLOCK_QUOTE); + + String text = item.getText(); + Document doc = newJRSTReader(new StringReader(text)); + result.appendContent(doc.getRootElement()); + String sAttribution = item.attributeValue(ATTRIBUTION); + if (sAttribution != null) { + Element attribution = result.addElement(ATTRIBUTION); + attribution.setText(sAttribution); + attribution.addAttribute(ATTR_INLINE, TRUE); + } + return result; + } + + /** + * <pre> + * .. admonition:: And, by the way... + * + * You can make up your own admonition too. + * </pre> + * + * @param Element + * @return Element + * @throws Exception + * + */ + private Element composeAdmonition(Element item) throws Exception { + Element result = null; + if (item.attributeValue(TYPE).equalsIgnoreCase(ADMONITION)) { + result = DocumentHelper.createElement(ADMONITION); + String title = item.attributeValue(TITLE); + String admonitionClass = "admonition_" + title; + admonitionClass = admonitionClass.toLowerCase().replaceAll( + "\\p{Punct}", ""); + admonitionClass = admonitionClass.replace(' ', '-'); + admonitionClass = admonitionClass.replace('\n', '-'); + result.addAttribute(CLASS, admonitionClass); + result.addElement(TITLE).addAttribute(ATTR_INLINE, TRUE).setText( + title.trim()); + } else { + result = DocumentHelper.createElement(item.attributeValue(TYPE) + .toLowerCase()); + } + + String text = item.getText(); + Document doc = newJRSTReader(new StringReader(text)); + result.appendContent(doc.getRootElement()); + return result; + } + + /** + * parse all directives + * + * @param Element + * @return Node + */ + private Node composeDirective(Element item) { + Node result = item; + String type = item.attributeValue(JRSTLexer.DIRECTIVE_TYPE); + if (type.equals(SECTNUM)) { + sectnum = true; + } + JRSTDirective directive = getDirective(type); + if (directive == null) { + directive = getDefaultDirective(type); + } + if (directive != null) { + result = directive.parse(item); + } else { + log.warn("Unknow directive type '" + type + "' in: " + item); + } + return result; + } + + /** + * <pre> + * .. |biohazard| image:: biohazard.png + * </pre> + * + * @param Element + * @return Element + */ + private Element composeSubstitutionDefinition(Element item) { + Element result = item; + Element child = (Element) item.selectSingleNode("*"); + Node newChild = composeDirective(child); + result.remove(child); // remove old after composeDirective, because + // directive can be used this parent + result.add(newChild); + return result; + } + + /** + * <p> + * Complexe Table + * </p> + * + * <pre> + * +------------------------+------------+---------------------+ + * | body row 3 | Cells may | - Table cells | + * +------------------------+ span rows. | - contain | + * | body row 4 | | - body elements. | + * +------------------------+------------+---------------------+ + * </pre> + * + * <p> + * And simple table + * </p> + * + * <pre> + * ===== ===== ====== + * Inputs Output + * ============ ====== + * A B A or B + * ------------ ------ + * A B A or B + * ===== ===== ====== + * </pre> + * + * @param Element + * @return Element + * + */ + private Element composeTable(Element item) throws Exception { + + Element result = DocumentHelper.createElement(TABLE); + + int tableWidth = Integer.parseInt(item + .attributeValue(JRSTLexer.TABLE_WIDTH)); + + TreeSet<Integer> beginCellList = new TreeSet<Integer>(); + + for (Element cell : (List<Element>) item.selectNodes(JRSTLexer.ROW + + "/" + JRSTLexer.CELL)) { + Integer begin = Integer.valueOf(cell + .attributeValue(JRSTLexer.CELL_INDEX_START)); + beginCellList.add(begin); + } + + int[] beginCell = new int[beginCellList.size() + 1]; // + 1 to put + // table width + // to simulate + // new cell + int[] lengthCell = new int[beginCellList.size()]; + + int cellNumber = 0; + for (int b : beginCellList) { + beginCell[cellNumber] = b; + if (cellNumber > 0) { + lengthCell[cellNumber - 1] = beginCell[cellNumber] + - beginCell[cellNumber - 1]; + } + cellNumber++; + } + beginCell[cellNumber] = tableWidth; + lengthCell[cellNumber - 1] = beginCell[cellNumber] + - beginCell[cellNumber - 1]; + + Element tgroup = result.addElement(TGROUP).addAttribute("cols", + String.valueOf(cellNumber)); + for (int width : lengthCell) { + tgroup.addElement(COLSPEC).addAttribute("colwidth", + String.valueOf(width)); + } + + Element rowList = null; + if (TRUE.equals(item.attributeValue(JRSTLexer.TABLE_HEADER))) { + rowList = tgroup.addElement(THEAD); + } else { + rowList = tgroup.addElement(TBODY); + } + List<Element> rows = (List<Element>) item.selectNodes(JRSTLexer.ROW); + for (int r = 0; r < rows.size(); r++) { + Element row = rowList.addElement(ROW); + List<Element> cells = (List<Element>) rows.get(r).selectNodes( + JRSTLexer.CELL); + for (int c = 0; c < cells.size(); c++) { + Element cell = cells.get(c); + // si la cellule a ete utilise pour un regroupement vertical on + // la passe + if (!TRUE.equals(cell.attributeValue("used"))) { + Element entry = row.addElement(ENTRY); + String text = ""; + + // on regroupe les cellules verticalement + int morerows = -1; + Element tmpCell = null; + String cellStart = cell + .attributeValue(JRSTLexer.CELL_INDEX_START); + do { + morerows++; + tmpCell = (Element) rows.get(r + morerows) + .selectSingleNode( + JRSTLexer.CELL + "[@" + + JRSTLexer.CELL_INDEX_START + + "=" + cellStart + "]"); + text += tmpCell.getText(); + // on marque la cellule comme utilise + tmpCell.addAttribute("used", TRUE); + } while (!TRUE.equals(tmpCell + .attributeValue(JRSTLexer.CELL_END))); + + if (morerows > 0) { + entry + .addAttribute("morerows", String + .valueOf(morerows)); + } + + // on compte le nombre de cellules regroupees + // horizontalement + int morecols = 0; + tmpCell = cells.get(c + morecols); + int cellEnd = Integer.parseInt(tmpCell + .attributeValue(JRSTLexer.CELL_INDEX_END)); + while (cellEnd + 1 != beginCell[c + morecols + 1]) { + morecols++; + // tmpCell = cells.get(c + morecols); + // cellEnd = + // Integer.parseInt(tmpCell.attributeValue(JRSTLexer. + // CELL_INDEX_END)); + } + if (morecols > 0) { + entry + .addAttribute("morecols", String + .valueOf(morecols)); + } + // parse entry text in table + Document doc = newJRSTReader(new StringReader(text)); + entry.appendContent(doc.getRootElement()); + } + } + if (TRUE.equals(rows.get(r).attributeValue( + JRSTLexer.ROW_END_HEADER))) { + rowList = tgroup.addElement(TBODY); + } + } + + return result; + } + + /** + * <p> + * items begin with "-", "+", or "*" + * </p> + * + * <pre> + * * aaa + * - bbb + * * ccc + * - ddd + * + eee + * </pre> + * + * @param lexer + * @return Element + * @throws Exception + */ + private Element composeBulletList(JRSTLexer lexer) throws Exception { + Element item = lexer.peekBulletList(); + Element result = DocumentHelper.createElement(BULLET_LIST); + copyLevel(item, result); + result.addAttribute(BULLET, item.attributeValue(BULLET)); + while (itemEquals(BULLET_LIST, item) && isSameLevel(item, result) + && hasSameAttribute(item, result, BULLET)) { + lexer.remove(); + Element bullet = result.addElement(LIST_ITEM); + copyLevel(item, bullet); + bullet.addElement(PARAGRAPH).addAttribute(ATTR_INLINE, TRUE) + .setText(item.getText()); + composeBody(lexer, bullet); + + item = lexer.peekBulletList(); + } + return result; + } + + /** + * <pre> + * 3. et meme + * * #. pour voir + * * I) de tout + * (a) pour tout + * (#) vraiment tout + * </pre> + * + * @param lexer + * @return Element + * @throws Exception + */ + private Element composeEnumeratedList(JRSTLexer lexer) throws Exception { + Element item = lexer.peekEnumeratedList(); + Element result = DocumentHelper.createElement(ENUMERATED_LIST); + copyLevel(item, result); + String enumType = item.attributeValue(ENUMTYPE); + if (!enumType.equals("arabic")) { + result.addAttribute(START, item.attributeValue(START)); + } + result.addAttribute(PREFIX, item.attributeValue(PREFIX)); + result.addAttribute(SUFFIX, item.attributeValue(SUFFIX)); + result.addAttribute(ENUMTYPE, enumType); + while (itemEquals(ENUMERATED_LIST, item) + && isSameLevel(item, result) + && hasSameAttribute(item, result, PREFIX, SUFFIX) + && (AUTO.equals(item.attributeValue(ENUMTYPE)) || hasSameAttribute( + item, result, ENUMTYPE))) { + lexer.remove(); + Element e = result.addElement(LIST_ITEM); + copyLevel(item, e); + e.addElement(PARAGRAPH).addAttribute(ATTR_INLINE, TRUE).setText( + item.getText()); + composeBody(lexer, e); + + item = lexer.peekEnumeratedList(); + } + return result; + } + + /** + * <pre> + * le mot : la classe + * la definition + * </pre> + * + * @param lexer + * @return Element + * @throws Exception + */ + private Element composeDefinitionList(JRSTLexer lexer) throws Exception { + Element item = lexer.peekBodyElement(); + Element result = DocumentHelper.createElement(DEFINITION_LIST); + copyLevel(item, result); + while (itemEquals(DEFINITION_LIST, item) && isSameLevel(item, result)) { + lexer.remove(); + Element def = result.addElement(DEFINITION_LIST_ITEM); + copyLevel(item, def); + + Element term = def.addElement(TERM); + copyLevel(item, term); + term.addAttribute(ATTR_INLINE, TRUE).setText( + item.attributeValue("term")); + + String[] classifiers = StringUtil.split(item + .attributeValue("classifiers"), " : "); + for (String classifierText : classifiers) { + Element classifier = def.addElement("classifier"); + copyLevel(item, classifier); + classifier.addAttribute(ATTR_INLINE, TRUE).setText( + classifierText); + } + + Element definition = def.addElement(DEFINITION); + definition.addElement(PARAGRAPH).addAttribute(ATTR_INLINE, TRUE) + .setText(item.getText()); + copyLevel(item, definition); + + composeBody(lexer, definition); + + item = lexer.peekBodyElement(); + } + return result; + } + + /** + * <pre> + * :un peu: de field + * ca ne fait pas + * de mal + * </pre> + * + * @param lexer + * @return Element + * @throws Exception + */ + private Element composeFieldList(JRSTLexer lexer) throws Exception { + Element item = lexer.peekBodyElement(); + Element result = DocumentHelper.createElement(FIELD_LIST); + copyLevel(item, result); + while (itemEquals(FIELD_LIST, item) && isSameLevel(item, result)) { + Element field = composeFieldItemList(lexer); + result.add(field); + item = lexer.peekBodyElement(); + } + return result; + } + + /** + * <pre> + * :field1: avec un + * petit texte + * - et meme un + * - debut + * - de list + * </pre> + * + * @param lexer + * @return Element + * @throws Exception + */ + private Element composeFieldItemList(JRSTLexer lexer) throws Exception { + Element item = lexer.peekFieldList(); + if (itemEquals(FIELD_LIST, item)) { + lexer.remove(); + Element field = DocumentHelper.createElement(FIELD); + copyLevel(item, field); + Element fieldName = field.addElement(FIELD_NAME); + copyLevel(item, fieldName); + fieldName.addAttribute(ATTR_INLINE, TRUE).setText( + item.attributeValue(NAME)); + Element fieldBody = field.addElement(FIELD_BODY); + fieldBody.addElement(PARAGRAPH).addAttribute(ATTR_INLINE, TRUE) + .setText(item.getText()); + copyLevel(item, fieldBody); + composeBody(lexer, fieldBody); + + return field; + } else { + throw new DocumentException("Waiting for " + FIELD_LIST + + " and found " + item.getName()); + } + } + + /** + * <pre> + * DEFINITIONS + * ----------- + * </pre> + * + * @param lexer + * @return Element + * @throws Exception + */ + private Element composeSection(JRSTLexer lexer) throws Exception { + Element result = DocumentHelper.createElement(SECTION); + Element firstTitle = null; + + Element item = null; + + // le titre de la section + item = lexer.peekTitle(); + if (itemEquals(TITLE, item, true, lexer.eof())) { + lexer.remove(); + firstTitle = item; + Element title = result.addElement(TITLE); + copyLevel(item, result); + copyLevel(item, title); + title.addAttribute(ATTR_INLINE, TRUE).setText(item.getText().trim()); + result.addAttribute(ID, item.getText().replaceAll("\\W+", " ") + .trim().toLowerCase().replaceAll("\\W+", "-")); + result.addAttribute(NAME, item.getText().toLowerCase().trim()); + eTitle.add(title); + } + + // le contenu de la section + item = lexer.peekTitle(); + while (itemNotEquals(TITLE, item) && !lexer.eof()) { + composeBody(lexer, result); + item = lexer.peekTitle(); + } + + // les sous sections + item = lexer.peekTitle(); + while (itemEquals(TITLE, item) && isUpperLevel(item, firstTitle)) { + Element section = composeSection(lexer); + result.add(section); + item = lexer.peekTitle(); + } + + return result; + } + + /** + * Indique si la sous section est bien une sous section, c-a-d dire que son + * level est superieur a celui de la section + * + * @param item + * @param firstTitle + * @return boolean + * @throws DocumentException + */ + private boolean isUpperLevel(Element subSection, Element section) + throws DocumentException { + // if (!(itemEquals(SECTION, subSection) && itemEquals(SECTION, + // section)) + // || itemEquals(DOCUMENT, section) || itemEquals(SECTION, section)) { + // // all element is upper than Document or section + // return true; + // } + int subSectionLevel = Integer.parseInt(subSection + .attributeValue(LEVEL)); + int sectionLevel = Integer.parseInt(section.attributeValue(LEVEL)); + boolean result = subSectionLevel > sectionLevel; + return result; + } + + /** + * Indique si les deux elements sont au meme niveau + * + * @param item + * @param firstTitle + * @return boolean + * @throws DocumentException + */ + private boolean isSameLevel(Element subSection, Element section) + throws DocumentException { + // if (itemEquals(DOCUMENT, section) || itemEquals(SECTION, section)) { + // // all element is upper than Document or section + // return false; + // } + int subSectionLevel = Integer.parseInt(subSection + .attributeValue(LEVEL)); + int sectionLevel = Integer.parseInt(section.attributeValue(LEVEL)); + boolean result = subSectionLevel == sectionLevel; + return result; + } + + /** + * @param Element + * e1 + * @param Element + * e2 + * @param String + * ... attnames + * @return boolean + */ + private boolean hasSameAttribute(Element e1, Element e2, String... attnames) { + boolean result = true; + for (String attname : attnames) { + String a1 = e1.attributeValue(attname); + String a2 = e2.attributeValue(attname); + if (!ObjectUtils.equals(a1, a2)) { + result = false; + break; + } + } + return result; + } + + /** + * @param Element + * from + * @param Element + * to + * @throws DocumentException + */ + private void copyLevel(Element from, Element to) throws DocumentException { + String level = from.attributeValue(LEVEL); + if (level == null) { + throw new DocumentException("Element without level: " + from); + } + to.addAttribute(LEVEL, level); + } + + /** + * @param String + * name + * @param Element + * e + * @return boolean + * @throws DocumentException + */ + private boolean itemEquals(String name, Element e) throws DocumentException { + boolean result = itemEquals(name, e, false, false); + return result; + } + + /** + * @param String + * name + * @param Element + * e + * @param throwError + * @param eof + * @return boolean + * @throws DocumentException + */ + private boolean itemEquals(String name, Element e, boolean throwError, + boolean eof) throws DocumentException { + boolean result = e != null && name.equals(e.getName()); + if (ERROR_MISSING_ITEM && !result && throwError && !eof) { + throw new DocumentException("Malformed document waiting " + name + + " and found " + (e != null ? e.getName() : "null")); + } + return result; + } + + /** + * @param String + * name + * @param Element + * e + * @return boolean + */ + private boolean itemNotEquals(String name, Element e) { + boolean result = e == null || !name.equals(e.getName()); + return result; + } + + private Document newJRSTReader(Reader r) throws Exception { + JRSTReader reader = new JRSTReader(); + reader.setVariable(idMax, symbolMax, symbolMaxRef, lblFootnotes, + lblFootnotesRef, eFootnotes, eTarget, eTargetAnonymous, + eTargetAnonymousCopy); + + return reader.read(r); + + } + + /** + * <p> + * Initialises les variables d'environements par ex, les hyperlinks peuvent + * etre referencer dans tous le document + * </p> + * + * @param idMax + * @param symbolMax + * @param symbolMaxRef + * @param lblFootnotes + * @param lblFootnotesRef + * @param eFootnotes + * @param eTarget + * @param eTargetAnonymous + * @param eTargetAnonymousCopy + */ + public void setVariable(int idMax, int symbolMax, int symbolMaxRef, + LinkedList<Integer> lblFootnotes, + LinkedList<Integer> lblFootnotesRef, + LinkedList<Element> eFootnotes, LinkedList<Element> eTarget, + LinkedList<Element> eTargetAnonymous, + LinkedList<Element> eTargetAnonymousCopy) { + this.idMax = idMax; + this.symbolMax = symbolMax; + this.symbolMaxRef = symbolMaxRef; + this.lblFootnotes = lblFootnotes; + this.lblFootnotesRef = lblFootnotesRef; + this.eFootnotes = eFootnotes; + this.eTarget = eTarget; + this.eTargetAnonymous = eTargetAnonymous; + this.eTargetAnonymousCopy = eTargetAnonymousCopy; + } + + /** + * Parse text in element and replace text with parse result + * + * @param Element + * e + * @throws DocumentException + * @throws UnsupportedEncodingException + */ + + private void inline(Element e) throws DocumentException, UnsupportedEncodingException { + String text = e.getText(); + + text = StringEscapeUtils.escapeXml(text); + // search all LITERAL and replace it with special mark + // this prevent substitution in literal, example **something** must not + // change in literal + Map<String, String> temporaries = new HashMap<String, String>(); + Matcher matcher = REGEX_LITERAL.matcher(text); + int index = 0; + while (matcher.find()) { + int start = matcher.start(); + int end = matcher.end(); + String literal = "<" + LITERAL + ">" + matcher.group(1) + "</" + + LITERAL + ">"; + String key = LITERAL + index++; + temporaries.put(key, literal); + text = text.substring(0, start) + "<tmp>" + key + "</tmp>" + + text.substring(end); + matcher = REGEX_LITERAL.matcher(text); + } + // search all REGEX_INLINE_REFERENCE and replace it with special mark + // this prevent substitution of URL with REGEX_REFERENCE. Use same + // mechanisme as literal for that + matcher = REGEX_INLINE_REFERENCE.matcher(text); + index = 0; + while (matcher.find()) { + int start = matcher.start(); + int end = matcher.end(); + Element ref = DocumentHelper.createElement(REFERENCE); + ref.addAttribute(REFURI, StringEscapeUtils.unescapeXml(matcher.group(2))); + ref.setText(StringEscapeUtils.unescapeXml(matcher.group(1))); + String key = "inlineReference" + index++; + temporaries.put(key, ref.asXML()); + text = text.substring(0, start) + "<tmp>" + key + "</tmp>" + + text.substring(end); + matcher = REGEX_INLINE_REFERENCE.matcher(text); + + } + // do all substitution inline + text = REGEX_EMAIL.matcher(text).replaceAll( + "$1<" + REFERENCE + " refuri='mailto:$2'>$2</" + REFERENCE + + ">$3"); + text = REGEX_STRONG.matcher(text).replaceAll( + "<" + STRONG + ">$1</" + STRONG + ">"); + text = REGEX_EMPHASIS.matcher(text).replaceAll( + "<" + EMPHASIS + ">$1</" + EMPHASIS + ">"); + text = REGEX_REFERENCE.matcher(text).replaceAll( + "<" + REFERENCE + " refuri='$1'>$1</" + REFERENCE + ">$2"); + // _[#]truc + matcher = REGEX_FOOTNOTE_REFERENCE.matcher(text); + while (matcher.find()) { + String txtDebut = text.substring(0, matcher.start()); + String txtFin = text.substring(matcher.end()-1, text.length()-1); + Element footnote = DocumentHelper.createElement(FOOTNOTE_REFERENCE); + String sFootnote = matcher.group(); + boolean done = false; + for (int i = 0; i < sFootnote.length() && !done; i++) { + if (sFootnote.charAt(i) == ']') { + String id = sFootnote.substring(1, i); + if (id.equals("*")) { + int nb = Math.abs(symbolMaxRef / 10) + 1; + char symbol = FOOTNOTE_SYMBOL.charAt(symbolMaxRef % 10); + String label = ""; + for (int j = 0; j < nb; j++) { + label += symbol; + } + symbolMaxRef++; + footnote.addAttribute(AUTO, "*"); + for (int j = 0; j < eFootnotes.size(); j++) { + Element eFootnote = eFootnotes.get(j); + if (eFootnote.attributeValue(LABEL).equals(label)) { + + footnote.addAttribute(ATTR_IDS, eFootnote + .attributeValue(BACKREFS)); + footnote.addAttribute(ATTR_REFID, eFootnote + .attributeValue(ATTR_IDS)); + + } + } + footnote.setText(label); + + } else if (id.matches("[1-9]+")) { + + for (int j = 0; j < eFootnotes.size(); j++) { + Element eFootnote = eFootnotes.get(j); + if (eFootnote.attributeValue(LABEL).equals(id)) { + footnote.addAttribute(ATTR_IDS, eFootnote + .attributeValue(BACKREFS)); + footnote.addAttribute(ATTR_REFID, eFootnote + .attributeValue(ATTR_IDS)); + } + } + footnote.setText(id); + lblFootnotesRef.add(Integer.parseInt(id)); + + } else if (id.equals("#")) { + int lblMax = 0; + for (int j = 0; j < lblFootnotesRef.size(); j++) { + lblMax = Math.max(lblMax, lblFootnotesRef.get(j)); + } + + boolean[] lbls = new boolean[lblMax]; + for (int j = 0; j < lbls.length; j++) { + lbls[j] = false; + } + for (int j = 0; j < lblFootnotesRef.size(); j++) { + lbls[lblFootnotesRef.get(j) - 1] = true; + } + boolean valide = false; + do { + boolean trouve = false; + String label = null; + for (int j = 0; j < lbls.length && !trouve; j++) { + + if (!lbls[j]) { + trouve = true; + label = "" + (j + 1); + } + } + if (!trouve) { + label = "" + (lbls.length + 1); + } + footnote.addAttribute(AUTO, "1"); + for (int j = 0; j < eFootnotes.size(); j++) { + Element eFootnote = eFootnotes.get(j); + if (eFootnote.attributeValue(LABEL).equals( + label)) { + if (!(eFootnote.attributeValue(TYPE) + .equals(AUTONUMLABEL))) { + footnote.addAttribute(ATTR_IDS, eFootnote + .attributeValue(BACKREFS)); + footnote.addAttribute(ATTR_REFID, + eFootnote.attributeValue(ATTR_IDS)); + footnote.setText(label); + lblFootnotesRef.add(Integer + .parseInt(label)); + valide = true; + } else { + valide = false; + lbls[Integer.parseInt(label) - 1] = true; + } + } + } + } while (!valide); + + } + + else { + footnote.addAttribute(AUTO, "1"); + + String name = id.substring(1); + boolean trouve = false; + for (int j = 0; j < eFootnotes.size() && !trouve; j++) { + Element eFootnote = eFootnotes.get(j); + if (eFootnote.attributeValue(NAMES).equals(name)) { + footnote.addAttribute(ATTR_IDS, eFootnote + .attributeValue(BACKREFS)); + footnote.addAttribute(ATTR_REFID, eFootnote + .attributeValue(ATTR_IDS)); + String label = eFootnote + .attributeValue(LABEL); + footnote.setText(label); + lblFootnotesRef.add(Integer.parseInt(label)); + trouve = true; + } + } + + footnote.addAttribute(NAMES, name); + } + done = true; + } + } + text = txtDebut + footnote.asXML() + txtFin; + matcher = REGEX_FOOTNOTE_REFERENCE.matcher(text); + } + // .. __http://truc.html + matcher = REGEX_ANONYMOUS_HYPERLINK_REFERENCE.matcher(text); + while (matcher.find()) { + String txtDebut = text.substring(0, matcher.start()); + String txtFin = text.substring(matcher.end(), text.length()); + String ref = text.substring(matcher.start(), matcher.end() - 2); + ref = ref.replaceAll("`", ""); + Element anonym = DocumentHelper.createElement(REFERENCE); + anonym.addAttribute(ANONYMOUS, "1"); + anonym.addAttribute(NAME, ref.trim()); + if (!eTargetAnonymous.isEmpty()) { + Element target = eTargetAnonymous.getFirst(); + eTargetAnonymous.removeFirst(); + anonym.addAttribute(REFURI, target.attributeValue(REFURI)); + } + anonym.setText(ref); + text = txtDebut + anonym.asXML() + txtFin; + matcher = REGEX_ANONYMOUS_HYPERLINK_REFERENCE.matcher(text); + } + // .. _truc: http://truc.html + matcher = REGEX_HYPERLINK_REFERENCE.matcher(text); + while (matcher.find()) { + String txtDebut = text.substring(0, matcher.start()); + String txtFin = text.substring(matcher.end(), text.length()); + String ref = text.substring(matcher.start(), matcher.end() - 1); + ref = StringEscapeUtils.unescapeXml(ref); + ref = ref.replaceAll("('|_)", ""); + ref = ref.replaceAll("`", ""); + Element hyper = DocumentHelper.createElement(REFERENCE); + hyper.addAttribute(NAME, ref); + boolean trouve = false; + for (int i = 0; i < eTarget.size() && !trouve; i++) { + Element el = eTarget.get(i); + String refTmp = URLEncoder.encode(ref.replaceAll("\\s", "-").toLowerCase(), "UTF-8"); + if (el.attributeValue(ID).equalsIgnoreCase((refTmp))) { + hyper.addAttribute(REFURI, el.attributeValue(REFURI)); + trouve = true; + } + } + if (!trouve) { + hyper.addAttribute(ATTR_REFID, ref); + } + hyper.setText(ref); + text = txtDebut + hyper.asXML() + " " + txtFin; + matcher = REGEX_HYPERLINK_REFERENCE.matcher(text); + + } + + // substitution reference + matcher = REGEX_SUBSTITUTION_REFERENCE.matcher(text); + int begin = 0; + while (matcher.find(begin)) { + String start = text.substring(0, matcher.start()); + String end = text.substring(matcher.end()); + String ref = matcher.group(1); + + Node subst = e.selectSingleNode("//" + SUBSTITUTION_DEFINITION + + "[@name='" + ref + "']/child::node()"); + + if (subst == null) { + text = start + "|" + ref + "|"; + } else { + text = start + subst.asXML(); + } + + begin = text.length(); + text += end; + matcher = REGEX_SUBSTITUTION_REFERENCE.matcher(text); + + } + // undo substitution in LITERAL + Pattern p = Pattern.compile("<tmp>([^<>]+)</tmp>"); + + matcher = p.matcher(text); + while (matcher.find()) { + String start = text.substring(0, matcher.start()); + String end = text.substring(matcher.end()); + + String tempKey = matcher.group(1); + text = start + temporaries.get(tempKey) + end; + matcher = p.matcher(text); + } + + String resultElementText = text.trim(); + Element result = DocumentHelper.parseText( + "<TMP>" + resultElementText + "</TMP>").getRootElement(); + + e.setText(""); + e.appendContent(result); + } +} Copied: branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/legacy/ReStructuredText.java (from rev 695, branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/ReStructuredText.java) =================================================================== --- branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/legacy/ReStructuredText.java (rev 0) +++ branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/legacy/ReStructuredText.java 2012-06-05 14:44:35 UTC (rev 696) @@ -0,0 +1,215 @@ +/* + * #%L + * JRst :: Api + * + * $Id$ + * $HeadURL$ + * %% + * Copyright (C) 2004 - 2010 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. + * #L% + */ + +package org.nuiton.jrst.legacy; + +import java.util.regex.Pattern; + +/** + * ReStructuredText. + * + * Created: 27 oct. 06 11:10:30 + * + * @author poussin + * @version $Revision$ + * + * Last update: $Date$ + * by : $Author$ + */ +public class ReStructuredText { + + public static final String DTD = "http://docutils.sourceforge.net/docs/ref/docutils.dtd"; + + public static final String TITLE_CHAR = "-=-~'`^+:!\"#$%&*,./;|?@\\_[\\]{}<>()"; + public static final String QUOTED_CHAR = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"; + public static final String BULLET_CHAR = "*" + "+" + "-" + "\u2022" + + "\u2023" + "\u2043"; + public static final String DOCINFO_ITEM = "author|authors|organization|address|contact|version|revision|status|date|copyright"; + public static final String FOOTNOTE_SYMBOL = "\u002A" + "\u2020" + "\u2021" + + "\u00A7" + "\u00B6" + "\u0023" + "\u2660" + "\u2665" + "\u2666" + + "\u2663"; + // public static final String ADMONITION = + // "admonition|caution|danger|error|hint|important|note|tip|warning"; + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Root Element + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + public static final String DOCUMENT = "document"; + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Title Elements + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + public static final String TITLE = "title"; + public static final String SUBTITLE = "subtitle"; + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Bibliographic Elements + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + public static final String DOCINFO = "docinfo"; + // public static final String INFO = "info"; + public static final String AUTHOR = "author"; + public static final String AUTHORS = "authors"; + public static final String ORGANIZATION = "organization"; + public static final String ADDRESS = "address"; + public static final String CONTACT = "contact"; + public static final String VERSION = "version"; + public static final String REVISION = "revision"; + public static final String STATUS = "status"; + public static final String DATE = "date"; + public static final String COPYRIGHT = "copyright"; + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Decoration Elements + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + public static final String DECORATION = "decoration"; + public static final String HEADER = "header"; + public static final String FOOTER = "footer"; + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Structural Elements + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + public static final String SECTION = "section"; + public static final String TOPIC = "topic"; + public static final String SIDEBAR = "sidebar"; + public static final String TRANSITION = "transition"; + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Body Elements + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + public static final String PARAGRAPH = "paragraph"; + public static final String COMPOUND = "compound"; + public static final String CONTAINER = "container"; + public static final String BULLET_LIST = "bullet_list"; + public static final String ENUMERATED_LIST = "enumerated_list"; + public static final String LIST_ITEM = "list_item"; + public static final String DEFINITION_LIST = "definition_list"; + public static final String DEFINITION_LIST_ITEM = "definition_list_item"; + public static final String TERM = "term"; + public static final String CLASSIFIER = "classifier"; + public static final String DEFINITION = "definition"; + public static final String FIELD_LIST = "field_list"; + public static final String FIELD = "field"; + public static final String FIELD_NAME = "field_name"; + public static final String FIELD_BODY = "field_body"; + public static final String OPTION_LIST = "option_list"; + public static final String OPTION_LIST_ITEM = "option_list_item"; + public static final String OPTION_GROUP = "option_group"; + public static final String OPTION = "option"; + public static final String OPTION_STRING = "option_string"; + public static final String OPTION_ARGUMENT = "option_argument"; + public static final String DESCRIPTION = "description"; + public static final String LITERAL_BLOCK = "literal_block"; + public static final String LINE_BLOCK = "line_block"; + public static final String LINE = "line"; + public static final String BLOCK_QUOTE = "block_quote"; + public static final String ATTRIBUTION = "attribution"; + public static final String DOCTEST_BLOCK = "doctest_block"; + public static final String ATTENTION = "attention"; + public static final String CAUTION = "caution"; + public static final String DANGER = "danger"; + public static final String ERROR = "error"; + public static final String HINT = "hint"; + public static final String IMPORTANT = "important"; + public static final String NOTE = "note"; + public static final String TIP = "tip"; + public static final String WARNING = "warning"; + public static final String ADMONITION = "admonition"; + public static final String FOOTNOTE = "footnote"; + public static final String CITATION = "citation"; + public static final String LABEL = "label"; + public static final String RUBRIC = "rubric"; + public static final String TARGET = "target"; + public static final String SUBSTITUTION_DEFINITION = "substitution_definition"; + public static final String COMMENT = "comment"; + public static final String PENDING = "pending"; + public static final String FIGURE = "figure"; + public static final String IMAGE = "image"; + public static final String CAPTION = "caption"; + public static final String LEGEND = "legend"; + public static final String SYSTEM_MESSAGE = "system_message"; + public static final String RAW = "raw"; + + // table + public static final String TABLE = "table"; + public static final String TGROUP = "tgroup"; + public static final String COLSPEC = "colspec"; + public static final String THEAD = "thead"; + public static final String TBODY = "tbody"; + public static final String ROW = "row"; + public static final String ENTRY = "entry"; + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Inline Elements + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + public static final String EMPHASIS = "emphasis"; + public static final String STRONG = "strong"; + public static final String LITERAL = "literal"; + public static final String REFERENCE = "reference"; + public static final String FOOTNOTE_REFERENCE = "footnote_reference"; + public static final String CITATION_REFERENCE = "citation_reference"; + public static final String SUBSTITUTION_REFERENCE = "substitution_reference"; + public static final String TITLE_REFERENCE = "title_reference"; + public static final String ABBREVIATION = "abbreviation"; + public static final String ACRONYM = "acronym"; + public static final String SUPERSCRIPT = "superscript"; + public static final String SUBSCRIPT = "subscript"; + public static final String INLINE = "inline"; + public static final String PROBLEMATIC = "problematic"; + public static final String GENERATED = "generated"; + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Inline Elements Regex + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + public static final Pattern REGEX_EMPHASIS = Pattern + .compile("\\*([^*(\\]_.+\\[)].+?)\\*"); + public static final Pattern REGEX_STRONG = Pattern + .compile("\\*\\*(.+?)\\*\\*"); + public static final Pattern REGEX_LITERAL = Pattern.compile("``([^`]+)``"); + public static final Pattern REGEX_REFERENCE = Pattern + .compile("(https?://[-/%#[\\&&&[^(>)]]\\._\\w:]+\\w+)((\\W|&|$)+)"); + public static final Pattern REGEX_INLINE_REFERENCE = Pattern + .compile("`(.+?) \\<\\;((https?://)?[-/%#&\\._\\w:[^ ]]+)(\\>\\;)`_"); + public static final Pattern REGEX_EMAIL = Pattern + .compile("(^|[^_\\w])([-\\._\\w]+@[-\\._\\w]+)([^-\\._\\w]|$)"); + public static final Pattern REGEX_FOOTNOTE_REFERENCE = Pattern + .compile("\\[(#|[0-9]|\\*)\\w*\\]_"); + // "\\[([0-9]+?|#)\\]"); + public static final Pattern REGEX_CITATION_REFERENCE = Pattern + .compile("\\[([^\\]]+?)\\]"); + public static final Pattern REGEX_SUBSTITUTION_REFERENCE = Pattern + .compile("\\|([^|]+?)\\|"); + public static final Pattern REGEX_ABBREVIATION = Pattern.compile("(.*?)"); + public static final Pattern REGEX_ACRONYM = Pattern.compile("(.*?)"); + public static final Pattern REGEX_SUPERSCRIPT = Pattern.compile("(.*?)"); + public static final Pattern REGEX_SUBSCRIPT = Pattern.compile("(.*?)"); + public static final Pattern REGEX_INLINE = Pattern.compile("(.*?)"); + public static final Pattern REGEX_PROBLEMATIC = Pattern.compile("(.*?)"); + public static final Pattern REGEX_GENERATED = Pattern.compile("(.*?)"); + // `truc truc`_ + public static final Pattern REGEX_HYPERLINK_REFERENCE = Pattern + .compile("(\\`[^_<>]+\\`_(\\W|$))|(('|`)[^_<`(')>]+('|`)_(\\W|$))|([\\S]+[^\\s<>\\.`]+_(\\W|$))"); + // `trux truc`__ + public static final Pattern REGEX_ANONYMOUS_HYPERLINK_REFERENCE = Pattern + .compile("(\\`[^<>`\\]\\[]+\\`__)|(\\w+[^()`\\s<>]+__)"); +} Property changes on: branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/legacy/ReStructuredText.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Added: svn:eol-style + native Modified: branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/legacy/directive/ContentDirective.java =================================================================== --- branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/directive/ContentDirective.java 2012-06-04 16:16:06 UTC (rev 695) +++ branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/legacy/directive/ContentDirective.java 2012-06-05 14:44:35 UTC (rev 696) @@ -23,7 +23,7 @@ * #L% */ -package org.nuiton.jrst.directive; +package org.nuiton.jrst.legacy.directive; import org.nuiton.jrst.JRSTDirective; import org.dom4j.DocumentHelper; Modified: branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/legacy/directive/DateDirective.java =================================================================== --- branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/directive/DateDirective.java 2012-06-04 16:16:06 UTC (rev 695) +++ branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/legacy/directive/DateDirective.java 2012-06-05 14:44:35 UTC (rev 696) @@ -23,7 +23,7 @@ * #L% */ -package org.nuiton.jrst.directive; +package org.nuiton.jrst.legacy.directive; import org.nuiton.jrst.JRSTDirective; import org.dom4j.DocumentHelper; Modified: branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/legacy/directive/ImageDirective.java =================================================================== --- branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/directive/ImageDirective.java 2012-06-04 16:16:06 UTC (rev 695) +++ branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/legacy/directive/ImageDirective.java 2012-06-05 14:44:35 UTC (rev 696) @@ -23,12 +23,12 @@ * #L% */ -package org.nuiton.jrst.directive; +package org.nuiton.jrst.legacy.directive; import org.nuiton.jrst.JRSTDirective; -import org.nuiton.jrst.JRSTLexer; -import static org.nuiton.jrst.ReStructuredText.IMAGE; -import static org.nuiton.jrst.ReStructuredText.SUBSTITUTION_DEFINITION; +import org.nuiton.jrst.legacy.JRSTLexer; +import static org.nuiton.jrst.legacy.ReStructuredText.IMAGE; +import static org.nuiton.jrst.legacy.ReStructuredText.SUBSTITUTION_DEFINITION; import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.dom4j.Node; Modified: branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/legacy/directive/SectnumDirective.java =================================================================== --- branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/directive/SectnumDirective.java 2012-06-04 16:16:06 UTC (rev 695) +++ branches/jrst-docutils-jython/jrst/src/main/java/org/nuiton/jrst/legacy/directive/SectnumDirective.java 2012-06-05 14:44:35 UTC (rev 696) @@ -23,7 +23,7 @@ * #L% */ -package org.nuiton.jrst.directive; +package org.nuiton.jrst.legacy.directive; import org.nuiton.jrst.JRSTDirective; import org.dom4j.DocumentHelper; Modified: branches/jrst-docutils-jython/jrst-doc/src/site/en/rst/devel/developerDoc.rst =================================================================== --- branches/jrst-docutils-jython/jrst-doc/src/site/en/rst/devel/developerDoc.rst 2012-06-04 16:16:06 UTC (rev 695) +++ branches/jrst-docutils-jython/jrst-doc/src/site/en/rst/devel/developerDoc.rst 2012-06-05 14:44:35 UTC (rev 696) @@ -38,14 +38,14 @@ The first method uses DocUtils_ to generate intermediate XML document. However, scripts are written in Python, so we have to use Jython_ to launch them in the java virtual machine. This is the best way if RST documents are complex and structured. -For further information, please visit this page_. +For further information, please visit this page_ . Use of our own parser --------------------- The second method allows a simpler and faster generation but the whole ReStructuredText specification_ is not available. It could be used with simple documents. To use this mode, just add the argument "--simple". -You can visit `this page`_ if you want more informations. +You can visit this page there_ if you want more informations. Uses external XSL ================= @@ -66,7 +66,7 @@ .. _here: presentationXSL.html .. _page: developerDocDocutils.html -.. _`this page`: developerDocJRSTParser.html +.. _there: developerDocJRSTParser.html .. _DocUtils: http://docutils.sourceforge.net/docs/ref/doctree.html .. _Jython: http://jython.org/index.html .. _specification: http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html Modified: branches/jrst-docutils-jython/jrst-doc/src/site/en/rst/index.rst =================================================================== --- branches/jrst-docutils-jython/jrst-doc/src/site/en/rst/index.rst 2012-06-04 16:16:06 UTC (rev 695) +++ branches/jrst-docutils-jython/jrst-doc/src/site/en/rst/index.rst 2012-06-05 14:44:35 UTC (rev 696) @@ -27,12 +27,11 @@ reStructuredText_ parser : JRst =============================== +.. contents:: + User Documentation ================== -.. contents:: - - Presentation ------------ Modified: branches/jrst-docutils-jython/jrst-doc/src/site/rst/devel/docDevDocutils.rst =================================================================== --- branches/jrst-docutils-jython/jrst-doc/src/site/rst/devel/docDevDocutils.rst 2012-06-04 16:16:06 UTC (rev 695) +++ branches/jrst-docutils-jython/jrst-doc/src/site/rst/devel/docDevDocutils.rst 2012-06-05 14:44:35 UTC (rev 696) @@ -27,7 +27,7 @@ Documentation développeur ========================= -Le mode par défaut de génération de JRST utilise Jython_ pour exécuter les scripts de DocUtils_ pour produire le document XML intermédiaire, qui est l'implémentation de référence de la spécification_ de ReStructuredText. Cette méthode est adaptée lorsque les fichiers RST sont plus complexes ou lorsque les fonctionnalités ne sont pas encore implémentées dans `notre parseur`_. +Le mode par défaut de génération de JRST utilise Jython_ pour exécuter les scripts de DocUtils_ pour produire le document XML intermédiaire, qui est l'implémentation de référence de la spécification_ de ReStructuredText. Cette méthode est adaptée lorsque les fichiers RST sont plus complexes ou lorsque les fonctionnalités ne sont pas encore implémentées dans notre parseur_ . .. contents:: Sommaire @@ -128,4 +128,4 @@ .. _DocUtils: http://docutils.sourceforge.net/docs/ref/doctree.html .. _Jython: http://jython.org/index.html .. _spécification: http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html -.. _`notre parseur`: docDevJRSTParser.html +.. _parseur: docDevJRSTParser.html Modified: branches/jrst-docutils-jython/jrst-doc/src/site/rst/devel/docDevJRSTParser.rst =================================================================== --- branches/jrst-docutils-jython/jrst-doc/src/site/rst/devel/docDevJRSTParser.rst 2012-06-04 16:16:06 UTC (rev 695) +++ branches/jrst-docutils-jython/jrst-doc/src/site/rst/devel/docDevJRSTParser.rst 2012-06-05 14:44:35 UTC (rev 696) @@ -28,7 +28,7 @@ ======================================================= Parmi les options de lancement de JRST, il est possible d'activer un mode de génération simple ( --simple ) qui utilise notre propre parseur JRST. L'avantage est de permettre une génération simplifiée et rapide qui convient parfaitement aux documents classiques. -Si jamais une fonctionnalité_ n'est pas disponible pour votre document, il est toujours possible d'utiliser l'`autre mode`_. +Si jamais une fonctionnalité_ n'est pas disponible pour votre document, il est toujours possible d'utiliser l'autre mode_ . .. contents:: Sommaire @@ -140,4 +140,4 @@ .. _RST: http://docutils.sourceforge.net/rst.html .. _DocUtils: http://docutils.sourceforge.net/docs/ref/doctree.html .. _fonctionnalité: ../user/fonctionnalites.html -.. _`autre mode`: docDevDocutils.html +.. _mode: docDevDocutils.html Modified: branches/jrst-docutils-jython/jrst-doc/src/site/rst/devel/docDeveloppeur.rst =================================================================== --- branches/jrst-docutils-jython/jrst-doc/src/site/rst/devel/docDeveloppeur.rst 2012-06-04 16:16:06 UTC (rev 695) +++ branches/jrst-docutils-jython/jrst-doc/src/site/rst/devel/docDeveloppeur.rst 2012-06-05 14:44:35 UTC (rev 696) @@ -38,7 +38,7 @@ La première méthode utilise DocUtils_ pour générer le document XML intermédiaire. Cependant, les scripts étant écrits en Python, il nous faut passer par Jython_ pour les lancer dans la machine virtuelle java. Cette méthode est la plus adaptée pour la génération de documents complexes et très structurés. -Pour plus d'informations, vous pouvez visiter cette page_. +Pour plus d'informations, vous pouvez visiter cette page_ . Utilisation de notre propre parseur @@ -47,7 +47,7 @@ La seconde méthode propose une génération plus simple et plus rapide mais celle-ci a l'inconvénient de proposer une implémentation incomplète de la spécification de ReStructuredText_. Elle peut être utilisée dans le cadre de documents simples. L'argument pour passer dans ce mode là est "--simple". -Vous pouvez accéder à `cette page`_ pour des compléments d'information. +Vous pouvez accéder à cette page la_ pour des compléments d'information. Utilisation de XSL externe @@ -69,7 +69,7 @@ .. [1] Une documentation sur le XSL est diponible ici_. .. _page: docDevDocutils.html -.. _`cette page`: docDevJRSTParser.html +.. _la: docDevJRSTParser.html .. _ici: presentationXSL.html .. _DocUtils: http://docutils.sourceforge.net/docs/ref/doctree.html .. _Jython: http://jython.org/index.html Modified: branches/jrst-docutils-jython/jrst-doc/src/site/rst/index.rst =================================================================== --- branches/jrst-docutils-jython/jrst-doc/src/site/rst/index.rst 2012-06-04 16:16:06 UTC (rev 695) +++ branches/jrst-docutils-jython/jrst-doc/src/site/rst/index.rst 2012-06-05 14:44:35 UTC (rev 696) @@ -27,12 +27,11 @@ Parseur reStructuredText_ : le JRst =================================== +.. contents:: Sommaire + Documentation utilisateur ========================= -.. contents:: Sommaire - - Présentation ------------ Modified: branches/jrst-docutils-jython/jrst-doc/src/site/site_en.xml =================================================================== --- branches/jrst-docutils-jython/jrst-doc/src/site/site_en.xml 2012-06-04 16:16:06 UTC (rev 695) +++ branches/jrst-docutils-jython/jrst-doc/src/site/site_en.xml 2012-06-05 14:44:35 UTC (rev 696) @@ -50,12 +50,12 @@ </menu> <menu name="Language"> - <item name="Français" href="index.html"/> - <item name="English" href="en/index.html"/> + <item name="Français" href="../index.html"/> + <item name="English" href="index.html"/> </menu> <menu name="User"> - <item href="/user/index.html" name="About"/> + <item href="index.html" name="About"/> <item href="/user/RSTpresentation.html" name="A ReStructuredText Primer"/> </menu> Modified: branches/jrst-docutils-jython/jrst-doc/src/site/site_fr.xml =================================================================== --- branches/jrst-docutils-jython/jrst-doc/src/site/site_fr.xml 2012-06-04 16:16:06 UTC (rev 695) +++ branches/jrst-docutils-jython/jrst-doc/src/site/site_fr.xml 2012-06-05 14:44:35 UTC (rev 696) @@ -53,7 +53,7 @@ </menu> <menu name="Utilisateur"> - <item href="/user/index.html" name="Présentation de JRST"/> + <item href="index.html" name="Présentation de JRST"/> <item href="/user/presentationRST.html" name="Introduction à ReStructuredText"/> </menu> Modified: branches/jrst-docutils-jython/pom.xml =================================================================== --- branches/jrst-docutils-jython/pom.xml 2012-06-04 16:16:06 UTC (rev 695) +++ branches/jrst-docutils-jython/pom.xml 2012-06-05 14:44:35 UTC (rev 696) @@ -45,6 +45,7 @@ <!-- Evolution #35: Suppression du module "maven-jrst-plugin" --> <!--<module>maven-jrst-plugin</module>--> <module>doxia-module-jrst</module> + <module>doxia-module-jrst-legacy</module> <module>jrst-doc</module> </modules>
participants (1)
-
jpages@users.nuiton.org