org.asciidoctor.maven.site.AsciidoctorDoxiaParser.java Source code

Java tutorial

Introduction

Here is the source code for org.asciidoctor.maven.site.AsciidoctorDoxiaParser.java

Source

/*
 * Copyright 2015 The Ascidoctor Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.asciidoctor.maven.site;

import org.apache.maven.doxia.module.xhtml.XhtmlParser;
import org.apache.maven.doxia.parser.ParseException;
import org.apache.maven.doxia.parser.Parser;
import org.apache.maven.doxia.sink.Sink;
import org.apache.maven.project.MavenProject;
import org.asciidoctor.Asciidoctor;
import org.asciidoctor.AttributesBuilder;
import org.asciidoctor.OptionsBuilder;
import org.asciidoctor.SafeMode;
import org.asciidoctor.maven.AsciidoctorHelper;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.util.IOUtil;
import org.codehaus.plexus.util.xml.Xpp3Dom;

import javax.inject.Inject;
import javax.inject.Provider;
import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * This class is used by <a href="https://maven.apache.org/doxia/overview.html">the Doxia framework</a>
 * to handle the actual parsing of the AsciiDoc input files into HTML to be consumed/wrapped
 * by the Maven site generation process
 * (see <a href="https://maven.apache.org/plugins/maven-site-plugin/">maven-site-plugin</a>).
 *
 * @author jdlee
 * @author mojavelinux
 */
@Component(role = Parser.class, hint = AsciidoctorDoxiaParser.ROLE_HINT)
public class AsciidoctorDoxiaParser extends XhtmlParser {

    @Inject
    protected Provider<MavenProject> mavenProjectProvider;

    /**
     * The role hint for the {@link AsciidoctorDoxiaParser} Plexus component.
     */
    public static final String ROLE_HINT = "asciidoc";

    protected final Asciidoctor asciidoctor = Asciidoctor.Factory.create();

    /**
     * {@inheritDoc}
     */
    @Override
    public void parse(Reader reader, Sink sink) throws ParseException {
        String source = null;
        try {
            if ((source = IOUtil.toString(reader)) == null) {
                source = "";
            }
        } catch (IOException ex) {
            getLog().error("Could not read AsciiDoc source: " + ex.getLocalizedMessage());
            return;
        }

        MavenProject project = mavenProjectProvider.get();

        Xpp3Dom siteConfig = getSiteConfig(project);
        File siteDirectory = resolveSiteDirectory(project, siteConfig);
        OptionsBuilder options = processAsciiDocConfig(project, siteConfig, initOptions(project, siteDirectory),
                initAttributes(project, siteDirectory));
        // QUESTION should we keep OptionsBuilder & AttributesBuilder separate for call to convertAsciiDoc?
        sink.rawText(convertAsciiDoc(source, options));
    }

    protected Xpp3Dom getSiteConfig(MavenProject project) {
        return project.getGoalConfiguration("org.apache.maven.plugins", "maven-site-plugin", "site", "site");
    }

    protected File resolveSiteDirectory(MavenProject project, Xpp3Dom siteConfig) {
        File siteDirectory = new File(project.getBasedir(), "src/site");
        if (siteConfig != null) {
            Xpp3Dom siteDirectoryNode = siteConfig.getChild("siteDirectory");
            if (siteDirectoryNode != null) {
                siteDirectory = new File(siteDirectoryNode.getValue());
            }
        }
        return siteDirectory;
    }

    protected OptionsBuilder initOptions(MavenProject project, File siteDirectory) {
        return OptionsBuilder.options().backend("xhtml").safe(SafeMode.UNSAFE)
                .baseDir(new File(siteDirectory, ROLE_HINT));
    }

    protected AttributesBuilder initAttributes(MavenProject project, File siteDirectory) {
        return AttributesBuilder.attributes().attribute("idprefix", "@").attribute("showtitle", "@");
    }

    protected OptionsBuilder processAsciiDocConfig(MavenProject project, Xpp3Dom siteConfig, OptionsBuilder options,
            AttributesBuilder attributes) {
        if (siteConfig == null) {
            return options.attributes(attributes);
        }

        Xpp3Dom asciidocConfig = siteConfig.getChild("asciidoc");
        if (asciidocConfig == null) {
            return options.attributes(attributes);
        }

        if (project.getProperties() != null) {
            for (Map.Entry<Object, Object> entry : project.getProperties().entrySet()) {
                attributes.attribute(((String) entry.getKey()).replaceAll("\\.", "-"), entry.getValue());
            }
        }

        for (Xpp3Dom asciidocOpt : asciidocConfig.getChildren()) {
            String optName = asciidocOpt.getName();
            if ("attributes".equals(optName)) {
                for (Xpp3Dom asciidocAttr : asciidocOpt.getChildren()) {
                    AsciidoctorHelper.addAttribute(asciidocAttr.getName(), asciidocAttr.getValue(), attributes);
                }
            } else if ("requires".equals(optName)) {
                Xpp3Dom[] requires = asciidocOpt.getChildren("require");
                // supports variant:
                // <requires>
                //     <require>time</require>
                // </requires>
                if (requires.length > 0) {
                    for (Xpp3Dom require : requires) {
                        requireLibrary(require.getValue());
                    }
                } else {
                    // supports variant:
                    // <requires>time, base64</requires>
                    for (String require : asciidocOpt.getValue().split(",")) {
                        requireLibrary(require);
                    }
                }
            } else if ("templateDir".equals(optName) || "template_dir".equals(optName)) {
                options.templateDir(resolveProjectDir(project, asciidocOpt.getValue()));
            } else if ("templateDirs".equals(optName) || "template_dirs".equals(optName)) {
                List<File> templateDirs = new ArrayList<File>();
                for (Xpp3Dom dir : asciidocOpt.getChildren("dir")) {
                    templateDirs.add(resolveProjectDir(project, dir.getValue()));
                }
                if (!templateDirs.isEmpty()) {
                    options.templateDirs(templateDirs.toArray(new File[templateDirs.size()]));
                }
            } else if ("baseDir".equals(optName)) {
                options.baseDir(resolveProjectDir(project, asciidocOpt.getValue()));
            } else {
                options.option(optName.replaceAll("(?<!_)([A-Z])", "_$1").toLowerCase(), asciidocOpt.getValue());
            }
        }
        return options.attributes(attributes);
    }

    protected String convertAsciiDoc(String source, OptionsBuilder options) {
        return asciidoctor.convert(source, options);
    }

    protected File resolveProjectDir(MavenProject project, String path) {
        File filePath = new File(path);
        if (!filePath.isAbsolute()) {
            filePath = new File(project.getBasedir(), filePath.toString());
        }
        return filePath;
    }

    private void requireLibrary(String require) {
        if (!(require = require.trim()).isEmpty()) {
            try {
                asciidoctor.requireLibrary(require);
            } catch (Exception ex) {
                getLog().error(ex.getLocalizedMessage());
            }
        }
    }
}