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%; +}