From 21e30c4d28253259fd06ac1302d82ffd7a520ee7 Mon Sep 17 00:00:00 2001 From: Stéphane Bégaudeau Date: Thu, 19 May 2016 15:31:35 +0200 Subject: Improve the documentation 1) The css of the image has now a version number to ensure that future update of the documentation will not create any issue. 2) A breadcrumb is now added during the export. This breadcrumb is computed from the toc.xml file from the documentation bundle. Change-Id: I4637dba0fe4a0ab61dd2953dbb4797045e206d05 Signed-off-by: Stéphane Bégaudeau --- .../documentation/export/internal/Exporter.java | 123 ++++++++++++++++++++- .../export/internal/ExporterTests.java | 6 +- .../documentation/export/internal/TocReader.java | 113 +++++++++++++++++++ .../eef/documentation/export/internal/Topic.java | 119 ++++++++++++++++++++ 4 files changed, 357 insertions(+), 4 deletions(-) create mode 100644 doc/org.eclipse.eef.documentation.export/src/org/eclipse/eef/documentation/export/internal/TocReader.java create mode 100644 doc/org.eclipse.eef.documentation.export/src/org/eclipse/eef/documentation/export/internal/Topic.java (limited to 'doc/org.eclipse.eef.documentation.export') diff --git a/doc/org.eclipse.eef.documentation.export/src/org/eclipse/eef/documentation/export/internal/Exporter.java b/doc/org.eclipse.eef.documentation.export/src/org/eclipse/eef/documentation/export/internal/Exporter.java index 52f199112..59de08bf2 100644 --- a/doc/org.eclipse.eef.documentation.export/src/org/eclipse/eef/documentation/export/internal/Exporter.java +++ b/doc/org.eclipse.eef.documentation.export/src/org/eclipse/eef/documentation/export/internal/Exporter.java @@ -13,6 +13,7 @@ package org.eclipse.eef.documentation.export.internal; import static org.junit.Assert.fail; import com.google.common.base.Charsets; +import com.google.common.collect.Lists; import com.google.common.io.ByteStreams; import com.google.common.io.CharStreams; import com.google.common.io.Closeables; @@ -28,6 +29,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Enumeration; +import java.util.Iterator; import java.util.List; import org.eclipse.core.runtime.Platform; @@ -110,6 +112,11 @@ public class Exporter { */ public static final String ROOT_DOCUMENTATION_ASSET_URL = "sections/documentation/"; //$NON-NLS-1$ + /** + * The path of the toc.xml file. + */ + public static final String TOC_XML_PATH = "/pages/toc.xml"; //$NON-NLS-1$ + /** * Exports the documentation for the website. */ @@ -118,6 +125,7 @@ public class Exporter { Bundle bundle = Platform.getBundle("org.eclipse.eef.documentation"); //$NON-NLS-1$ if (bundle != null) { String version = this.getVersion(bundle); + List topics = this.getTopics(bundle); // Find all the documentation pages recursively in the documentation bundle Enumeration entries = bundle.findEntries(DOCUMENTATION_PAGES_ROOT_PATH, "*.*", true); //$NON-NLS-1$ @@ -125,10 +133,12 @@ public class Exporter { URL entry = entries.nextElement(); String path = entry.getPath().substring((DOCUMENTATION_PAGES_ROOT_PATH + "/").length()); //$NON-NLS-1$ + List breadcrumbTopics = this.getBreadcrumbTopics(topics, path); + if (entry.getFile().endsWith(HTML_EXTENSION)) { // Read, process and write the processed HTML files List lines = this.readLines(entry); - List linesToKeep = this.getBody(lines, path, version); + List linesToKeep = this.getBody(lines, path, version, breadcrumbTopics); this.writeLines(linesToKeep, path, version); } else if (this.shouldCopy(path)) { // Let's copy other resources directly at its new location (images, video, etc) @@ -138,6 +148,68 @@ public class Exporter { } } + public List getBreadcrumbTopics(List topics, String path) { + List breadcrumbTopics = new ArrayList<>(); + + // Find the topic matching the path + Topic topic = this.find(topics, path); + + // Compute its parent topics + if (topic != null) { + breadcrumbTopics.addAll(this.getParents(topic)); + } + + return Lists.reverse(breadcrumbTopics); + } + + private List getParents(Topic topic) { + List parents = new ArrayList<>(); + + if (topic.getParent() != null) { + parents.add(topic.getParent()); + parents.addAll(this.getParents(topic.getParent())); + } + + return parents; + } + + private Topic find(List topics, String path) { + Topic topic = null; + + Iterator iterator = topics.iterator(); + while (topic == null && iterator.hasNext()) { + Topic next = iterator.next(); + if (("pages/" + path).equals(next.getHref())) { //$NON-NLS-1$ + topic = next; + } else { + topic = this.find(next.getTopics(), path); + } + } + return topic; + } + + public List getTopics(Bundle bundle) { + List topics = new ArrayList<>(); + // Find the toc.xml file + URL tocXmlEntry = bundle.getEntry(TOC_XML_PATH); + if (tocXmlEntry != null) { + InputStream inputStream = null; + try { + inputStream = tocXmlEntry.openStream(); + topics.addAll(new TocReader().getTopics(inputStream)); + } catch (IOException e) { + fail(e.getMessage()); + } finally { + try { + Closeables.close(inputStream, false); + } catch (IOException e) { + fail(e.getMessage()); + } + } + } + return topics; + } + /** * Indicates if we should copy the resource with the given path. * @@ -206,12 +278,18 @@ public class Exporter { * The path of the file * @param documentationVersion * The version of the documentation + * @param breadcrumbTopics + * The breadcrumb topics * @return The content of the file to save */ - public List getBody(List lines, String path, String documentationVersion) { + public List getBody(List lines, String path, String documentationVersion, List breadcrumbTopics) { List linesToKeep = new ArrayList<>(); linesToKeep.add(ROOT_ELEMENT_START); + if (!"index.html".equalsIgnoreCase(path)) { //$NON-NLS-1$ + List breadcrumb = this.createBreadcrumb(breadcrumbTopics, documentationVersion); + linesToKeep.addAll(breadcrumb); + } boolean hasFoundStartBody = false; boolean hasFoundStopBody = false; for (String line : lines) { @@ -226,6 +304,45 @@ public class Exporter { return linesToKeep; } + /** + * @param breadcrumbTopics + * @return + */ + private List createBreadcrumb(List breadcrumbTopics, String documentationVersion) { + List lines = new ArrayList<>(); + + lines.add("
    "); //$NON-NLS-1$ + if (breadcrumbTopics.size() > 0) { + lines.add("
  • " + documentationVersion + " /
  • "); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } else { + lines.add("
  • " + documentationVersion + "
  • "); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } + int i = 0; + for (Topic topic : breadcrumbTopics) { + String href = topic.getHref(); + + if (href.startsWith(DOCUMENTATION_PAGES_ROOT_PATH.substring(1))) { + href = href.substring(DOCUMENTATION_PAGES_ROOT_PATH.substring(1).length()); + } + if (href.endsWith(HTML_EXTENSION)) { + href = href.substring(0, href.length() - HTML_EXTENSION.length()); + } + + href = ROOT_DOCUMENTATION_URL + '/' + documentationVersion + href; + + if (i + 1 < breadcrumbTopics.size()) { + lines.add("
  • " + topic.getLabel() + " /
  • "); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } else { + lines.add("
  • " + topic.getLabel() + "
  • "); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + } + + i = i + 1; + } + lines.add("
"); //$NON-NLS-1$ + + return lines; + } + /** * Fixes the links that can be found in the line. * @@ -277,7 +394,7 @@ public class Exporter { /** * Handles the image. - * + * * @param builder * The builder * @param line diff --git a/doc/org.eclipse.eef.documentation.export/src/org/eclipse/eef/documentation/export/internal/ExporterTests.java b/doc/org.eclipse.eef.documentation.export/src/org/eclipse/eef/documentation/export/internal/ExporterTests.java index 7c84aa11b..31f729f79 100644 --- a/doc/org.eclipse.eef.documentation.export/src/org/eclipse/eef/documentation/export/internal/ExporterTests.java +++ b/doc/org.eclipse.eef.documentation.export/src/org/eclipse/eef/documentation/export/internal/ExporterTests.java @@ -18,6 +18,7 @@ import static org.junit.Assert.assertTrue; import com.google.common.collect.Lists; +import java.util.ArrayList; import java.util.List; import org.junit.Test; @@ -66,11 +67,14 @@ public class ExporterTests { //@formatter:on // Version and path can be null since we do not have any links - List actual = new Exporter().getBody(lines, null, null); + List actual = new Exporter().getBody(lines, "/pages/language/page.html", "1.6.0", new ArrayList<>()); //$NON-NLS-1$ //$NON-NLS-2$ // The result must have a specific first and last line with only the body inside List expected = lines.subList(5, 9); expected.add(0, Exporter.ROOT_ELEMENT_START); + expected.add(1, "
    "); //$NON-NLS-1$ + expected.add(2, "
  • 1.6.0
  • "); //$NON-NLS-1$ + expected.add(3, "
"); //$NON-NLS-1$ expected.add(Exporter.ROOT_ELEMENT_END); assertThat(actual, contains(expected.toArray(new String[expected.size()]))); diff --git a/doc/org.eclipse.eef.documentation.export/src/org/eclipse/eef/documentation/export/internal/TocReader.java b/doc/org.eclipse.eef.documentation.export/src/org/eclipse/eef/documentation/export/internal/TocReader.java new file mode 100644 index 000000000..ee30b3d7e --- /dev/null +++ b/doc/org.eclipse.eef.documentation.export/src/org/eclipse/eef/documentation/export/internal/TocReader.java @@ -0,0 +1,113 @@ +/******************************************************************************* + * Copyright (c) 2016 Obeo. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.eef.documentation.export.internal; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +/** + * Utility class used to parse the toc.xml to create the breadcrumb. + * + * @author sbegaudeau + */ +public class TocReader { + /** + * The name of the topic element. + */ + public static final String TOPIC = "topic"; //$NON-NLS-1$ + /** + * The URL of the topic. + */ + public static final String HREF = "href"; //$NON-NLS-1$ + + /** + * The label of the topic. + */ + public static final String LABEL = "label"; //$NON-NLS-1$ + + /** + * Parse the given XML content and return the list of topics found. + * + * @param inputStream + * The XML content of the toc.xml file + * @return The list of topics found in the toc.xml file + */ + public List getTopics(InputStream inputStream) { + List topics = new ArrayList<>(); + + DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); + try { + DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); + Document document = documentBuilder.parse(inputStream); + document.getDocumentElement().normalize(); + + Element element = document.getDocumentElement(); + NodeList nodeList = element.getChildNodes(); + + topics.addAll(this.visitChildNodes(nodeList)); + } catch (ParserConfigurationException | SAXException | IOException e) { + e.printStackTrace(); + } + + return topics; + } + + /** + * @param nodeList + * @return + */ + private Collection visitChildNodes(NodeList nodeList) { + List topics = new ArrayList<>(); + + for (int i = 0; i < nodeList.getLength(); i++) { + Node node = nodeList.item(i); + if (node.getNodeType() == Node.ELEMENT_NODE) { + Topic topic = new Topic(); + + if (node.hasAttributes()) { + NamedNodeMap attributes = node.getAttributes(); + for (int j = 0; j < attributes.getLength(); j++) { + Node attribute = attributes.item(j); + if (HREF.equals(attribute.getNodeName())) { + topic.setHref(attribute.getNodeValue()); + } else if (LABEL.equals(attribute.getNodeName())) { + topic.setLabel(attribute.getNodeValue()); + } + } + } + + if (node.hasChildNodes()) { + Collection childTopics = this.visitChildNodes(node.getChildNodes()); + topic.getTopics().addAll(childTopics); + childTopics.forEach(child -> child.setParent(topic)); + } + + topics.add(topic); + } + } + + return topics; + } +} diff --git a/doc/org.eclipse.eef.documentation.export/src/org/eclipse/eef/documentation/export/internal/Topic.java b/doc/org.eclipse.eef.documentation.export/src/org/eclipse/eef/documentation/export/internal/Topic.java new file mode 100644 index 000000000..35d69610c --- /dev/null +++ b/doc/org.eclipse.eef.documentation.export/src/org/eclipse/eef/documentation/export/internal/Topic.java @@ -0,0 +1,119 @@ +/******************************************************************************* + * Copyright (c) 2016 Obeo. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Obeo - initial API and implementation + *******************************************************************************/ +package org.eclipse.eef.documentation.export.internal; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * A POJO used to parse the toc.xml to create the breadcrumb of the website. + * + * @author sbegaudeau + */ +public class Topic { + + /** + * The URL of the topic. + */ + private String href; + + /** + * The label of the topic. + */ + private String label; + + /** + * The parent topic. + */ + private Topic parent; + + /** + * The child topics. + */ + private List topics = new ArrayList<>(); + + /** + * Return the href. + * + * @return the href + */ + public String getHref() { + return this.href; + } + + /** + * Sets the href. + * + * @param href + * the href to set + */ + public void setHref(String href) { + this.href = href; + } + + /** + * Return the label. + * + * @return the label + */ + public String getLabel() { + return this.label; + } + + /** + * Sets the label. + * + * @param label + * the label to set + */ + public void setLabel(String label) { + this.label = label; + } + + /** + * Return the topics. + * + * @return the topics + */ + public List getTopics() { + return this.topics; + } + + /** + * Sets the parent. + * + * @param parent + * the parent to set + */ + public void setParent(Topic parent) { + this.parent = parent; + } + + /** + * Return the parent. + * + * @return the parent + */ + public Topic getParent() { + return this.parent; + } + + /** + * {@inheritDoc} + * + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return "Topic [href=" + this.href + ", label=" + this.label + ", children=" + this.topics.stream().map(Object::toString).collect(Collectors.toList()) + "]"; //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ //$NON-NLS-4$ + } +} -- cgit v1.2.3