diff --git a/solr/solr-ref-guide/src/css/customstyles.css b/solr/solr-ref-guide/src/css/customstyles.css index 8e38402a436..7b992e380b5 100755 --- a/solr/solr-ref-guide/src/css/customstyles.css +++ b/solr/solr-ref-guide/src/css/customstyles.css @@ -446,7 +446,6 @@ div#toc ul li ul li { .tab-content { padding: 15px; - background-color: #FAFAFA; } span.tagTitle {font-weight: 500;} diff --git a/solr/solr-ref-guide/src/css/lavish-bootstrap.css b/solr/solr-ref-guide/src/css/lavish-bootstrap.css index e4c7395358a..d0c30db1589 100755 --- a/solr/solr-ref-guide/src/css/lavish-bootstrap.css +++ b/solr/solr-ref-guide/src/css/lavish-bootstrap.css @@ -3071,10 +3071,13 @@ textarea.input-group-sm > .input-group-btn > .btn { clear: both; } .tab-content > .tab-pane, -.pill-content > .pill-pane { +.tab-content > .content > .tab-pane, +.pill-content > .pill-pane, +.tab-content > .content > .tab-pane { display: none; } .tab-content > .active, +.tab-content > .content > .active, .pill-content > .active { display: block; } diff --git a/solr/solr-ref-guide/src/css/ref-guide.css b/solr/solr-ref-guide/src/css/ref-guide.css index 0fe26d13d21..4bd4da3425e 100644 --- a/solr/solr-ref-guide/src/css/ref-guide.css +++ b/solr/solr-ref-guide/src/css/ref-guide.css @@ -1109,6 +1109,16 @@ body.toc2 #header > h1:nth-last-child(2) border: none; max-width: 300px; } + #toc.toc-column + { + -moz-column-count: 3; + -moz-column-gap: 20px; + -webkit-column-count: 3; + -webkit-column-gap: 20px; + column-count: 3; + column-gap: 20px; + margin-top: 1em; + } } .toc > ul { @@ -1149,7 +1159,7 @@ body.toc2 #header > h1:nth-last-child(2) div.toc ul li { margin: 8px 0 8px 22px; - list-style: square; + list-style: disc; line-height: 1.25; } @@ -2646,7 +2656,7 @@ p.tableblock .exampleblock > .content { border-color: #e0e0dc; - background-color: #fffef7; + background-color: transparent; -webkit-box-shadow: 0 1px 4px #e0e0dc; box-shadow: 0 1px 4px #e0e0dc; } diff --git a/solr/solr-ref-guide/src/css/theme-solr.css b/solr/solr-ref-guide/src/css/theme-solr.css index daa8fbef607..ccfed1beba5 100644 --- a/solr/solr-ref-guide/src/css/theme-solr.css +++ b/solr/solr-ref-guide/src/css/theme-solr.css @@ -4,11 +4,6 @@ font-size:16px; } -.nav-tabs > li.active > a, .nav-tabs > li.active > a:hover, .nav-tabs > li.active > a:focus { - background-color: #FF833D; - color: white; -} - .nav > li.active > a { background-color: #262130; } @@ -17,6 +12,17 @@ background-color: #FF833D; } +.nav-tabs > li.active > a, +.nav-tabs > li.active > a:hover, +.nav-tabs > li.active > a:focus, +.nav-pills > li.active > a, +.nav-pills > li.active > a:hover, +.nav-pills > li.active > a:focus + { + background-color: #FF833D; + color: white; +} + div.navbar-collapse .dropdown-menu > li > a:hover { background-color: #D9411E; } @@ -52,6 +58,15 @@ a[data-toggle="tooltip"] { border-color: #248ec2 !important; } +.btn-info, +a[data-toggle].btn-info { + background-color: #FF833D; + font-size: 16px; + text-decoration: none; + color: #FFFFFF; + border: none; +} + /* Used for nav buttons */ .btn-primary { color: #ffffff; diff --git a/solr/solr-ref-guide/src/js/customscripts.js b/solr/solr-ref-guide/src/js/customscripts.js index 19156c5a83e..64fa03145c9 100755 --- a/solr/solr-ref-guide/src/js/customscripts.js +++ b/solr/solr-ref-guide/src/js/customscripts.js @@ -22,6 +22,53 @@ $( document ).ready(function() { */ anchors.add('h2,h3,h4,h5'); + // "Bootstrap Bootstrap" + // NOTE: by default, we use "dynamic-tabs" in our wrapper instead of "tab-content" + // so that if javascript is disabled, bootstrap's CSS doesn't hide all non-active "tab-pane" divs + $(".dynamic-tabs").each(function(ignored) { + $(this).addClass("tab-content"); + var nav_ul = $(" - * - * + * + * * TODO: build a list of all known external links so that some other tool could (optionally) ping them all for 200 status? * * @see https://github.com/asciidoctor/asciidoctor/issues/1865 * @see https://github.com/asciidoctor/asciidoctor/issues/1866 */ -public class CheckLinksAndAnchors { +public class CheckLinksAndAnchors { // TODO: rename this class now that it does more then just links & anchors public static final class HtmlFileFilter implements FileFilter { public boolean accept(File pathname) { return pathname.getName().toLowerCase().endsWith("html"); } } - + public static void main(String[] args) throws Exception { int problems = 0; - + if (args.length < 1 || 2 < args.length ) { System.err.println("usage: CheckLinksAndAnchors []"); System.exit(-1); } final File htmlDir = new File(args[0]); final boolean bareBones = (2 == args.length) ? Boolean.parseBoolean(args[1]) : false; - + final File[] pages = htmlDir.listFiles(new HtmlFileFilter()); if (0 == pages.length) { System.err.println("No HTML Files found, wrong htmlDir? forgot to built the site?"); @@ -116,17 +133,17 @@ public class CheckLinksAndAnchors { int totalLinks = 0; int totalRelativeLinks = 0; - + for (File file : pages) { //System.out.println("input File URI: " + file.toURI().toString()); assert ! filesToRelativeLinks.containsKey(file); final List linksInThisFile = new ArrayList(17); filesToRelativeLinks.put(file, linksInThisFile); - + final String fileContents = readFile(file.getPath()); final Document doc = Jsoup.parse(fileContents); - + // For Jekyll, we only care about class='main-content' -- we don't want to worry // about ids/links duplicated in the header/footer of every page, final String mainContentSelector = bareBones ? "body" : ".main-content"; @@ -145,10 +162,10 @@ public class CheckLinksAndAnchors { nodesWithIds.add(new Element(Tag.valueOf("body"), "").attr("id", file.getName().replaceAll("\\.html$",""))); } else { // We have to add Jekyll's to the nodesWithIds so we check the main section anchor as well - // since we've already + // since we've already nodesWithIds.addAll(doc.select("body[id]")); } - + boolean foundPreamble = false; for (Element node : nodesWithIds) { final String id = node.id(); @@ -168,7 +185,7 @@ public class CheckLinksAndAnchors { continue; } } - + if (idsToFiles.containsKey(id)) { idsInMultiFiles.add(id); } else { @@ -217,6 +234,8 @@ public class CheckLinksAndAnchors { } } } + + problems += validateHtmlStructure(file, mainContent); } // if there are problematic ids, report them @@ -242,7 +261,7 @@ public class CheckLinksAndAnchors { System.err.println(" ... source: " + source.toURI().toString()); } else if ( ( ! idsToFiles.containsKey(frag) ) || // no file contains this id, or... // id exists, but not in linked file - ( ! idsToFiles.get(frag).get(0).getName().equals(path) )) { + ( ! idsToFiles.get(frag).get(0).getName().equals(path) )) { problems++; System.err.println("Relative link points at id that doesn't exist in dest: " + link); System.err.println(" ... source: " + source.toURI().toString()); @@ -276,6 +295,102 @@ public class CheckLinksAndAnchors { br.close(); } } - -} + /** + * returns the number of problems found with this file + */ + private static int validateHtmlStructure(final File f, final Element mainContent) { + final String file = f.toURI().toString(); + int problems = 0; + + for (Element tab : mainContent.select(".dynamic-tabs")) { + // must be at least two tab-pane decendents of each dynamic-tabs + final Elements panes = tab.select(".tab-pane"); + final int numPanes = panes.size(); + if (numPanes < 2) { + System.err.println(file + " contains a 'dynamic-tabs' with "+ numPanes+" 'tab-pane' decendents -- must be at least 2"); + problems++; + } + + // must not have any decendents of a dynamic-tabs that are not part of tab-pane + // + // this is kind of tricky, because asciidoctor creates wrapper divs around the tab-panes + // so we can't make assumptions about direct children + // + final Elements elementsToIgnore = panes.parents(); + for (Element pane : panes) { + elementsToIgnore.addAll(pane.select("*")); + } + final Elements nonPaneDecendents = tab.select("*"); + nonPaneDecendents.removeAll(elementsToIgnore); + if (0 != nonPaneDecendents.size()) { + System.err.println(file + " contains a 'dynamic-tabs' with content outside of a 'tab-pane': " + + shortStr(nonPaneDecendents.text())); + problems++; + } + } + + // Now fetch all tab-panes, even if they aren't in a dynamic-tabs instance + // (that's a type of error we want to check for) + final Elements validPanes = mainContent.select(".dynamic-tabs .tab-pane"); + final Elements allPanes = mainContent.select(".tab-pane"); + + for (Element pane : allPanes) { + // every tab-pane must have an id + if (pane.id().trim().isEmpty()) { + System.err.println(file + " contains a 'tab-pane' that does not have a (unique) '#id'"); + problems++; + } + final String debug = "'tab-pane" + (pane.id().isEmpty() ? "" : "#" + pane.id()) + "'"; + + // no 'active' class on any tab-pane + if (pane.classNames​().contains("active")) { + System.err.println(file + " contains " + debug + " with 'active' defined -- this must be removed"); + problems++; + } + + // every tab-pane must be a decendent of a dynamic-tabs + if (! validPanes.contains(pane)) { + System.err.println(file + " contains " + debug + " that is not a decendent of a 'dynamic-tabs'"); + problems++; + } + + // every tab-pane must have exactly 1 tab-label which is + Elements labels = pane.select(".tab-label"); + if (1 != labels.size()) { + System.err.println(file + " contains " + debug + " with " + labels.size() + " 'tab-label' decendents -- must be exactly 1"); + problems++; + } else { + Element label = labels.first(); + if (! label.tagName().equals("strong")) { + System.err.println(file + " contains " + debug + " with a 'tab-label' using <" + + labels.first().tagName() + "> -- each 'tab-label' must be (example: '[.tab-label]*Text*')"); + problems++; + } + final String labelText = label.text().trim(); + // if the tab-label is the empty string, asciidoctor should optimize it away -- but let's check for it anyway + if (labelText.isEmpty()) { + System.err.println(file + " contains " + debug + " with a blank 'tab-label'"); + problems++; + } + // validate label must be first paragraph? first text content? + if (! pane.text().trim().startsWith(labelText)) { + System.err.println(file + " contains " + debug + " with text before the 'tab-label' ('" + labelText + "')"); + problems++; + } + + } + + } + + return problems; + } + + public static final String shortStr(String s) { + if (s.length() < 20) { + return s; + } + return s.substring(0, 17) + "..."; + } + +}