Markdown: recognize special multi-column layout blocks
Documentation writers may want to organize clusters of information
and/or links into a multi-column based layout to help readers find
material quickly.
Extend the supported markdown syntax with a new multi-column region.
A multi-column region is delineated by |||---||| with other markdown
contained within it:
|||---|||
## Markdown is easy
You can write simple text.
* [Basic markdown](http://...)
* [GitHub flavor](http://github.com/...)
* [This kind](kind.md)
## Safe
No HTML found.
## Fast
Well, faster than you can get coffee.
|||---|||
Headers within the region define the columns. For each header a new
column is started and the following content is placed below it into
the same column.
The above will render as three divs next to each other:
Markdown is easy Safe Fast
You can write simple No HTML found. Well, faster than
text. you can get coffee.
* Basic markdown
* GitHub flavor
* This kind
At present up to 4 columns may be fit across a page of documentation.
Additional columns should be placed into a new |||---||| block and
will appear below these columns.
The column widths are not configurable.
Change-Id: I088115bf4d4569817aca736cb0ce02f9d777d61b
diff --git a/gitiles-servlet/src/main/java/com/google/gitiles/doc/ColsNode.java b/gitiles-servlet/src/main/java/com/google/gitiles/doc/ColsNode.java
new file mode 100644
index 0000000..00945ef
--- /dev/null
+++ b/gitiles-servlet/src/main/java/com/google/gitiles/doc/ColsNode.java
@@ -0,0 +1,36 @@
+// Copyright 2015 Google Inc. All Rights Reserved.
+//
+// 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 com.google.gitiles.doc;
+
+import org.pegdown.ast.Node;
+import org.pegdown.ast.SuperNode;
+
+import java.util.List;
+
+/**
+ * Multi-column layout delineated by {@code |||---|||}.
+ * <p>
+ * Each header within the layout creates a new column in the HTML.
+ */
+public class ColsNode extends SuperNode {
+ ColsNode(List<Node> children) {
+ super(children);
+ }
+
+ @Override
+ public void accept(org.pegdown.ast.Visitor visitor) {
+ ((Visitor) visitor).visit(this);
+ }
+}
diff --git a/gitiles-servlet/src/main/java/com/google/gitiles/doc/GitilesMarkdown.java b/gitiles-servlet/src/main/java/com/google/gitiles/doc/GitilesMarkdown.java
index 43c589f..512d320 100644
--- a/gitiles-servlet/src/main/java/com/google/gitiles/doc/GitilesMarkdown.java
+++ b/gitiles-servlet/src/main/java/com/google/gitiles/doc/GitilesMarkdown.java
@@ -30,12 +30,7 @@
import java.util.List;
-/**
- * Additional markdown extensions known to Gitiles.
- * <p>
- * {@code [TOC]} as a stand-alone block will insert a table of contents
- * for the current document.
- */
+/** Parses Gitiles extensions to markdown. */
class GitilesMarkdown extends Parser implements BlockPluginParser {
private static final Logger log = LoggerFactory.getLogger(MarkdownHelper.class);
@@ -78,7 +73,8 @@
@Override
public Rule[] blockPluginRules() {
- return new Rule[]{
+ return new Rule[] {
+ cols(),
note(),
toc(),
};
@@ -108,6 +104,21 @@
sequence(string("aside"), push(match())));
}
+ public Rule cols() {
+ StringBuilderVar body = new StringBuilderVar();
+ return NodeSequence(
+ colsTag(), Newline(),
+ oneOrMore(
+ testNot(colsTag(), Newline()),
+ Line(body)),
+ colsTag(), Newline(),
+ push(new ColsNode(parse(body))));
+ }
+
+ public Rule colsTag() {
+ return string("|||---|||");
+ }
+
public List<Node> parse(StringBuilderVar body) {
// The pegdown code doesn't provide enough visibility to directly
// use its existing parsing rules. Recurse manually for inner text
diff --git a/gitiles-servlet/src/main/java/com/google/gitiles/doc/MarkdownToHtml.java b/gitiles-servlet/src/main/java/com/google/gitiles/doc/MarkdownToHtml.java
index 1086bab..a11c0e2 100644
--- a/gitiles-servlet/src/main/java/com/google/gitiles/doc/MarkdownToHtml.java
+++ b/gitiles-servlet/src/main/java/com/google/gitiles/doc/MarkdownToHtml.java
@@ -107,6 +107,26 @@
}
@Override
+ public void visit(ColsNode node) {
+ html.open("div").attribute("class", "cols");
+ boolean open = false;
+ for (Node n : node.getChildren()) {
+ if (n instanceof HeaderNode || n instanceof DivNode) {
+ if (open) {
+ html.close("div");
+ }
+ html.open("div").attribute("class", "col-3");
+ open = true;
+ }
+ n.accept(this);
+ }
+ if (open) {
+ html.close("div");
+ }
+ html.close("div");
+ }
+
+ @Override
public void visit(HeaderNode node) {
String tag = "h" + node.getLevel();
html.open(tag);
diff --git a/gitiles-servlet/src/main/java/com/google/gitiles/doc/Visitor.java b/gitiles-servlet/src/main/java/com/google/gitiles/doc/Visitor.java
index 19a68cc..8e9ea60 100644
--- a/gitiles-servlet/src/main/java/com/google/gitiles/doc/Visitor.java
+++ b/gitiles-servlet/src/main/java/com/google/gitiles/doc/Visitor.java
@@ -15,6 +15,7 @@
package com.google.gitiles.doc;
public interface Visitor extends org.pegdown.ast.Visitor {
+ void visit(ColsNode node);
void visit(DivNode node);
void visit(TocNode node);
}
diff --git a/gitiles-servlet/src/main/resources/com/google/gitiles/static/doc.css b/gitiles-servlet/src/main/resources/com/google/gitiles/static/doc.css
index c324786..198f8f6 100644
--- a/gitiles-servlet/src/main/resources/com/google/gitiles/static/doc.css
+++ b/gitiles-servlet/src/main/resources/com/google/gitiles/static/doc.css
@@ -45,7 +45,7 @@
.nav li a:hover {
color: #0000f9;
}
-.nav ul:after {
+.nav ul:after, .cols:after {
clear: both;
content: "";
display: block;
@@ -184,9 +184,9 @@
background: #f9f9f9;
border-color: #f2f2f2;
}
-.note p:first-child,
-.promo p:first-child,
-.aside p:first-child {
+.note :first-child,
+.promo :first-child,
+.aside :first-child {
margin-top: 0;
}
.note p:last-child,
@@ -194,3 +194,16 @@
.aside p:last-child {
margin-bottom: 0;
}
+
+.cols {
+ margin: 0 -1.533%;
+ width: 103.067%;
+}
+.col-3 {
+ float: left;
+ margin: 0 1.488% 20px;
+}
+.col-3 { width: 22.023%; }
+.cols hr {
+ width: 80%;
+}