diff --git a/404.md b/404.md new file mode 100644 index 0000000..a7b58c0 --- /dev/null +++ b/404.md @@ -0,0 +1,6 @@ +--- +title: "Page Not Found" +search: exclude +--- + +Sorry, but the page you were trying to view does not exist. Try searching for it or looking at the URL to see if it looks correct. diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..2fdc308 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,14 @@ +FROM jekyll/builder + +WORKDIR /tmp +ADD Gemfile /tmp/ +ADD Gemfile.lock /tmp/ +RUN bundle install + +FROM jekyll/jekyll + +VOLUME /src +EXPOSE 4000 + +WORKDIR /src +ENTRYPOINT ["jekyll", "serve", "-H", "0.0.0.0"] diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..33d9d3b --- /dev/null +++ b/Gemfile @@ -0,0 +1,3 @@ +source "https://rubygems.org" + +gem 'github-pages', group: :jekyll_plugins diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..83d8d45 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,238 @@ +GEM + remote: https://rubygems.org/ + specs: + activesupport (4.2.9) + i18n (~> 0.7) + minitest (~> 5.1) + thread_safe (~> 0.3, >= 0.3.4) + tzinfo (~> 1.1) + addressable (2.5.2) + public_suffix (>= 2.0.2, < 4.0) + coffee-script (2.4.1) + coffee-script-source + execjs + coffee-script-source (1.11.1) + colorator (1.1.0) + commonmarker (0.17.7.1) + ruby-enum (~> 0.5) + concurrent-ruby (1.0.5) + ethon (0.11.0) + ffi (>= 1.3.0) + execjs (2.7.0) + faraday (0.14.0) + multipart-post (>= 1.2, < 3) + ffi (1.9.18) + forwardable-extended (2.6.0) + gemoji (3.0.0) + github-pages (175) + activesupport (= 4.2.9) + github-pages-health-check (= 1.3.5) + jekyll (= 3.6.2) + jekyll-avatar (= 0.5.0) + jekyll-coffeescript (= 1.0.2) + jekyll-commonmark-ghpages (= 0.1.3) + jekyll-default-layout (= 0.1.4) + jekyll-feed (= 0.9.2) + jekyll-gist (= 1.4.1) + jekyll-github-metadata (= 2.9.3) + jekyll-mentions (= 1.2.0) + jekyll-optional-front-matter (= 0.3.0) + jekyll-paginate (= 1.1.0) + jekyll-readme-index (= 0.2.0) + jekyll-redirect-from (= 0.12.1) + jekyll-relative-links (= 0.5.2) + jekyll-remote-theme (= 0.2.3) + jekyll-sass-converter (= 1.5.0) + jekyll-seo-tag (= 2.3.0) + jekyll-sitemap (= 1.1.1) + jekyll-swiss (= 0.4.0) + jekyll-theme-architect (= 0.1.0) + jekyll-theme-cayman (= 0.1.0) + jekyll-theme-dinky (= 0.1.0) + jekyll-theme-hacker (= 0.1.0) + jekyll-theme-leap-day (= 0.1.0) + jekyll-theme-merlot (= 0.1.0) + jekyll-theme-midnight (= 0.1.0) + jekyll-theme-minimal (= 0.1.0) + jekyll-theme-modernist (= 0.1.0) + jekyll-theme-primer (= 0.5.2) + jekyll-theme-slate (= 0.1.0) + jekyll-theme-tactile (= 0.1.0) + jekyll-theme-time-machine (= 0.1.0) + jekyll-titles-from-headings (= 0.5.0) + jemoji (= 0.8.1) + kramdown (= 1.16.2) + liquid (= 4.0.0) + listen (= 3.0.6) + mercenary (~> 0.3) + minima (= 2.1.1) + rouge (= 2.2.1) + terminal-table (~> 1.4) + github-pages-health-check (1.3.5) + addressable (~> 2.3) + net-dns (~> 0.8) + octokit (~> 4.0) + public_suffix (~> 2.0) + typhoeus (~> 0.7) + html-pipeline (2.7.1) + activesupport (>= 2) + nokogiri (>= 1.4) + i18n (0.9.3) + concurrent-ruby (~> 1.0) + jekyll (3.6.2) + addressable (~> 2.4) + colorator (~> 1.0) + jekyll-sass-converter (~> 1.0) + jekyll-watch (~> 1.1) + kramdown (~> 1.14) + liquid (~> 4.0) + mercenary (~> 0.3.3) + pathutil (~> 0.9) + rouge (>= 1.7, < 3) + safe_yaml (~> 1.0) + jekyll-avatar (0.5.0) + jekyll (~> 3.0) + jekyll-coffeescript (1.0.2) + coffee-script (~> 2.2) + coffee-script-source (~> 1.11.1) + jekyll-commonmark (1.1.0) + commonmarker (~> 0.14) + jekyll (>= 3.0, < 4.0) + jekyll-commonmark-ghpages (0.1.3) + commonmarker (~> 0.17.6) + jekyll-commonmark (~> 1) + rouge (~> 2) + jekyll-default-layout (0.1.4) + jekyll (~> 3.0) + jekyll-feed (0.9.2) + jekyll (~> 3.3) + jekyll-gist (1.4.1) + octokit (~> 4.2) + jekyll-github-metadata (2.9.3) + jekyll (~> 3.1) + octokit (~> 4.0, != 4.4.0) + jekyll-mentions (1.2.0) + activesupport (~> 4.0) + html-pipeline (~> 2.3) + jekyll (~> 3.0) + jekyll-optional-front-matter (0.3.0) + jekyll (~> 3.0) + jekyll-paginate (1.1.0) + jekyll-readme-index (0.2.0) + jekyll (~> 3.0) + jekyll-redirect-from (0.12.1) + jekyll (~> 3.3) + jekyll-relative-links (0.5.2) + jekyll (~> 3.3) + jekyll-remote-theme (0.2.3) + jekyll (~> 3.5) + rubyzip (>= 1.2.1, < 3.0) + typhoeus (>= 0.7, < 2.0) + jekyll-sass-converter (1.5.0) + sass (~> 3.4) + jekyll-seo-tag (2.3.0) + jekyll (~> 3.3) + jekyll-sitemap (1.1.1) + jekyll (~> 3.3) + jekyll-swiss (0.4.0) + jekyll-theme-architect (0.1.0) + jekyll (~> 3.5) + jekyll-seo-tag (~> 2.0) + jekyll-theme-cayman (0.1.0) + jekyll (~> 3.5) + jekyll-seo-tag (~> 2.0) + jekyll-theme-dinky (0.1.0) + jekyll (~> 3.5) + jekyll-seo-tag (~> 2.0) + jekyll-theme-hacker (0.1.0) + jekyll (~> 3.5) + jekyll-seo-tag (~> 2.0) + jekyll-theme-leap-day (0.1.0) + jekyll (~> 3.5) + jekyll-seo-tag (~> 2.0) + jekyll-theme-merlot (0.1.0) + jekyll (~> 3.5) + jekyll-seo-tag (~> 2.0) + jekyll-theme-midnight (0.1.0) + jekyll (~> 3.5) + jekyll-seo-tag (~> 2.0) + jekyll-theme-minimal (0.1.0) + jekyll (~> 3.5) + jekyll-seo-tag (~> 2.0) + jekyll-theme-modernist (0.1.0) + jekyll (~> 3.5) + jekyll-seo-tag (~> 2.0) + jekyll-theme-primer (0.5.2) + jekyll (~> 3.5) + jekyll-github-metadata (~> 2.9) + jekyll-seo-tag (~> 2.2) + jekyll-theme-slate (0.1.0) + jekyll (~> 3.5) + jekyll-seo-tag (~> 2.0) + jekyll-theme-tactile (0.1.0) + jekyll (~> 3.5) + jekyll-seo-tag (~> 2.0) + jekyll-theme-time-machine (0.1.0) + jekyll (~> 3.5) + jekyll-seo-tag (~> 2.0) + jekyll-titles-from-headings (0.5.0) + jekyll (~> 3.3) + jekyll-watch (1.5.1) + listen (~> 3.0) + jemoji (0.8.1) + activesupport (~> 4.0, >= 4.2.9) + gemoji (~> 3.0) + html-pipeline (~> 2.2) + jekyll (>= 3.0) + kramdown (1.16.2) + liquid (4.0.0) + listen (3.0.6) + rb-fsevent (>= 0.9.3) + rb-inotify (>= 0.9.7) + mercenary (0.3.6) + mini_portile2 (2.3.0) + minima (2.1.1) + jekyll (~> 3.3) + minitest (5.11.3) + multipart-post (2.0.0) + net-dns (0.8.0) + nokogiri (1.8.2) + mini_portile2 (~> 2.3.0) + octokit (4.8.0) + sawyer (~> 0.8.0, >= 0.5.3) + pathutil (0.16.1) + forwardable-extended (~> 2.6) + public_suffix (2.0.5) + rb-fsevent (0.10.2) + rb-inotify (0.9.10) + ffi (>= 0.5.0, < 2) + rouge (2.2.1) + ruby-enum (0.7.1) + i18n + rubyzip (1.2.1) + safe_yaml (1.0.4) + sass (3.5.5) + sass-listen (~> 4.0.0) + sass-listen (4.0.0) + rb-fsevent (~> 0.9, >= 0.9.4) + rb-inotify (~> 0.9, >= 0.9.7) + sawyer (0.8.1) + addressable (>= 2.3.5, < 2.6) + faraday (~> 0.8, < 1.0) + terminal-table (1.8.0) + unicode-display_width (~> 1.1, >= 1.1.1) + thread_safe (0.3.6) + typhoeus (0.8.0) + ethon (>= 0.8.0) + tzinfo (1.2.4) + thread_safe (~> 0.1) + unicode-display_width (1.3.0) + +PLATFORMS + ruby + +DEPENDENCIES + github-pages + +BUNDLED WITH + 1.16.1 diff --git a/README.md b/README.md new file mode 100644 index 0000000..787ad6f --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# Sparc Docs + +This site is hosted by [GitHub pages](https://help.github.com/articles/setting-up-your-github-pages-site-locally-with-jekyll/) diff --git a/_config.yml b/_config.yml new file mode 100644 index 0000000..0a04134 --- /dev/null +++ b/_config.yml @@ -0,0 +1,115 @@ +repository: tomjoht/documentation-theme-jekyll + +output: web +# this property is useful for conditional filtering of content that is separate from the PDF. + +topnav_title: Jekyll Documentation Theme +# this appears on the top navigation bar next to the home button + +site_title: Jekyll theme for documentation +# this appears in the html browser tab for the site title (seen mostly by search engines, not users) + +company_name: Your company +# this appears in the footer + +github_editme_path: tomjoht/documentation-theme-jekyll/blob/gh-pages/ +# if you're using Github, provide the basepath to the branch you've created for reviews, following the sample here. if not, leave this value blank. + +# gitlab_editme_path: tomjoht/documentation-theme-jekyll/blob/gh-pages/ +# if you're using GitLab, provide the basepath to the branch you've created for reviews, following the sample here. if not, leave this value blank. + +disqus_shortname: idratherbewriting +# if you're using disqus for comments, add the shortname here. if not, leave this value blank. + +google_analytics: UA-66296557-1 +# if you have google-analytics ID, put it in. if not, edit this value to blank. + +host: 127.0.0.1 +# the preview server used. Leave as is. + +port: 4000 +# the port where the preview is rendered. You can leave this as is unless you have other Jekyll builds using this same port that might cause conflicts. in that case, use another port such as 4006. + +exclude: + - .idea/ + - .gitignore +# these are the files and directories that jekyll will exclude from the build + +feedback_subject_line: Jekyll documentation theme + +feedback_email: tomjoht@gmail.com +# used as a contact email for the Feedback link in the top navigation bar + +# feedback_disable: true +# if you uncomment the previous line, the Feedback link gets removed + +# feedback_text: "Need help?" +# if you uncomment the previous line, it changes the Feedback text + +# feedback_link: "http://helpy.io/" +# if you uncomment the previous line, it changes where the feedback link points to + +highlighter: rouge +# library used for syntax highlighting + +markdown: kramdown +kramdown: + input: GFM + auto_ids: true + hard_wrap: false + syntax_highlighter: rouge + +# filter used to process markdown. note that kramdown differs from github-flavored markdown in some subtle ways + +collections: + tooltips: + output: false +# collections are declared here. this renders the content in _tooltips and processes it, but doesn't output it as actual files in the output unless you change output to true + +defaults: + - + scope: + path: "" + type: "pages" + values: + layout: "page" + comments: true + search: true + sidebar: home_sidebar + topnav: topnav + - + scope: + path: "" + type: "tooltips" + values: + layout: "page" + comments: true + search: true + tooltip: true + + - + scope: + path: "" + type: "posts" + values: + layout: "post" + comments: true + search: true + sidebar: home_sidebar + topnav: topnav + +# these are defaults used for the frontmatter for these file types + +sidebars: +- home_sidebar +- mydoc_sidebar +- product1_sidebar +- product2_sidebar +- other + +description: "Intended as a documentation theme based on Jekyll for technical writers documenting software and other technical products, this theme has all the elements you would need to handle multiple products with both multi-level sidebar navigation, tags, and other documentation features." +# the description is used in the feed.xml file + +# needed for sitemap.xml file only +# url: http://idratherbewriting.com +# baseurl: /documentation-theme-jekyll diff --git a/_data/alerts.yml b/_data/alerts.yml new file mode 100644 index 0000000..157e162 --- /dev/null +++ b/_data/alerts.yml @@ -0,0 +1,15 @@ +tip: '
{% assign series_pages = site.tags.series_acme %} + {% for p in pages %} + {% if p.series == "Getting Started" %} + {% assign nextTopic = page.weight | plus: "1" %} + {% if p.weight == nextTopic %} + + {% endif %} + {% endif %} + {% endfor %} +
\ No newline at end of file diff --git a/_includes/custom/series_acme.html b/_includes/custom/series_acme.html new file mode 100644 index 0000000..b9ebf44 --- /dev/null +++ b/_includes/custom/series_acme.html @@ -0,0 +1,19 @@ +The following pages and posts are tagged with
+Title | Type | Excerpt |
---|---|---|
{{page.title}} | +Page | +{% if page.summary %} {{ page.summary | strip_html | strip_newlines | truncate: 160 }} {% else %} {{ page.content | truncatewords: 50 | strip_html }} {% endif %} | +
{{post.title}} | +Post | +{% if post.summary %} {{ post.summary | strip_html | strip_newlines | truncate: 160 }} {% else %} {{ post.content | truncatewords: 50 | strip_html }} {% endif %} | +
Sorry, but the page you were trying to view does not exist. Try searching for it or looking at the URL to see if it looks correct.
+ + + + + + + + + + + + + +Follow these instructions to build the theme.
+ +First download or clone the theme from the Github repo. Most likely you won’t be pulling in updates once you start customizing the theme, so downloading the theme (instead of cloning it) probably makes the most sense. In Github, click the Clone or download button, and then click Download ZIP.
+ +If you’ve never installed or run a Jekyll site locally on your computer, follow these instructions to install Jekyll:
+ + + +In case you haven’t installed Bundler, install it:
+ +gem install bundler
+
You’ll want Bundler to make sure all the Ruby gems needed work well with your project. Bundler sorts out dependencies and installs missing gems or matches up gems with the right versions based on gem dependencies.
+ +Use this option if you’re not planning to publish your Jekyll site using Github Pages.
+ +Bundler’s Gemfile is how it specifies and manages project dependencies are managed. Although this project includes a Gemfile, this theme doesn’t have any dependencies beyond core Jekyll. The Gemfile is used to specify gems needed for publishing on Github Pages. If you’re not planning to have Github Pages build your Jekyll project, delete these two files from the theme’s root directory:
+ +If you’ve never run Jekyll on your computer (you can check with jekyll --version
), you may need to install the jekyll gem:
gem install jekyll
+
Now run jekyll serve (first change directories (cd
) to where you downloaded the project):
jekyll serve
+
If you are in fact publishing on Github Pages, leave the Gemfile and Gemfile.lock files in the theme.The Gemfile tells Jekyll to use the github-pages gem. However, note that you cannot use the normal jekyll serve
command with this gem due to dependency conflicts between the latest version of Jekyll and Github Pages (which are noted briefly here).
You need Bundler to resolve these dependency conflicts. Use Bundler to install all the needed Ruby gems:
+ +bundle update
+
Then always use this command to build Jekyll:
+ +bundle exec jekyll serve
+
If you want to shorten this long command, you can put this code in a file such as jekyll.sh (on a Mac) and then simply type . jekyll.sh
to build Jekyll.
You can also use Docker to directly build and run the site on your local machine. Just clone the repo and run the following from your working dir:
+docker-compose build --no-cache && docker-compose up
+
The site should now be running at http://localhost:4000/.
+ +This is perhaps the easiest way to see how your site would actually look.
+ +There are several products in this theme. Each product uses a different sidebar. This is the essence of what makes this theme unique – different sidebars for different product documentation. The idea is that when users are reading documentation for a specific product, the sidebar navigation should be specific to that product. (You can read more of my thoughts on why multiple sidebars are important in this blog post.)
+ +The top navigation usually remains the same, because it allows users to navigate across products. But the sidebar navigation adapts to the product.
+ +In each page’s frontmatter, you must specify the sidebar you want that page to use. Here’s an example of the page frontmatter showing the sidebar property:
+ +
+---
+title: Alerts
+tags: [formatting]
+keywords: notes, tips, cautions, warnings, admonitions
+last_updated: July 3, 2016
+summary: "You can insert notes, tips, warnings, and important alerts in your content. These notes are stored as shortcodes made available through the linksrefs.hmtl include."
+sidebar: mydoc_sidebar
+permalink: mydoc_alerts
+---
+
+
+The sidebar: mydoc_sidebar
refers to the _data/sidebars/mydoc_sidebar.yml file.
Note that your sidebar can only have 2 levels (expand the Tag archives option to see an example of the second level). Given that each product has its own sidebar, this depth should be sufficient (it’s really like 3 levels). Deeper nesting goes against usability recommendations.
+ +You can optionally turn off the sidebar on any page (e.g. landing pages). To turn off the sidebar for a page, you should set the page frontmatter tag as hide_sidebar: true
.
If you don’t declare a sidebar, the home_sidebar
file gets used as the default because this is the default specified in the config file:
-
+ scope:
+ path: ""
+ type: "pages"
+ values:
+ layout: "page"
+ comments: true
+ search: true
+ sidebar: home_sidebar
+ topnav: topnav
+
If you want to set different sidebar defaults based on different folders for your pages, specify your defaults like this:
+ +-
+ scope:
+ path: "pages/mydoc"
+ type: "pages"
+ values:
+ layout: "page"
+ comments: true
+ search: true
+ sidebar: mydoc_sidebar
+ topnav: topnav
+
This would load the mydoc_sidebar
for each file in pages/mydoc. You could set different defaults for different path scopes.
For more detail on the sidebar, see Sidebar navigation.
+ +The top navigation works just like the sidebar. You can specify which topnav data file should load by adding a topnav
property in your page, like this:
topnav: topnav
+
Here the topnav refers to the _data/topnav.yml file.
+ +Because most topnav options will be the same, the _config.yml file specifies the topnav file as a default:
+ +-
+ scope:
+ path: ""
+ type: "pages"
+ values:
+ layout: "page"
+ comments: true
+ search: true
+ sidebar: home_sidebar
+ topnav: topnav
+
The sidebar data file uses a specific YAML syntax that you must follow. Follow the sample pattern shown in the theme, specically looking at mydoc_sidebar.yml as an example: Here’s a code sample showing all levels:
+ +entries:
+- title: sidebar
+ product: Jekyll Doc Theme
+ version: 6.0
+ folders:
+ - title: Overview
+ output: web, pdf
+ folderitems:
+
+ - title: Get started
+ url: /index.html
+ output: web, pdf
+ type: homepage
+
+ - title: Introduction
+ url: /mydoc_introduction.html
+ output: web, pdf
+
+ - title: Release Notes
+ output: web, pdf
+ folderitems:
+
+ - title: 6.0 Release notes
+ url: /mydoc_release_notes_60.html
+ output: web, pdf
+
+ - title: 5.0 Release notes
+ url: /mydoc_release_notes_50.html
+ output: web, pdf
+
+ - title: Tag archives
+ output: web
+ folderitems:
+
+ - title: Tag archives overview
+ url: /mydoc_tag_archives_overview.html
+ output: web
+
+ subfolders:
+ - title: Tag archive pages
+ output: web
+ subfolderitems:
+
+ - title: Formatting pages
+ url: /tag_formatting.html
+ output: web
+
+ - title: Navigation pages
+ url: /tag_navigation.html
+ output: web
+
+ - title: Content types pages
+ url: /tag_content_types.html
+ output: web
+
Each folder
or subfolder
must contain a title
and output
property. Each folderitem
or subfolderitem
must contain a title
, url
, and output
property.
The two outputs available are web
and pdf
. (Even if you aren’t publishing PDF, you still need to specify output: web
).
The YAML syntax depends on exact spacing, so make sure you follow the pattern shown in the sample sidebars. See my YAML tutorial for more details about how YAML works.
+ +Each level must have at least one topic before the next level starts. You can’t have a second level that contains multiple third levels without having at least one standalone topic in the second level. If you need a hierarchy that has a folder that contains other folders and no loose topics, use a blank -
item like this:
entries:
+- title: sidebar
+ product: Jekyll Doc Theme
+ version: 6.0
+ folders:
+ - title: Overview
+ output: web, pdf
+ folderitems:
+
+ -
+
+ - title: Release Notes
+ output: web, pdf
+ folderitems:
+
+ - title: 6.0 Release notes
+ url: /mydoc_release_notes_60.html
+ output: web, pdf
+
+ - title: 5.0 Release notes
+ url: /mydoc_release_notes_50.html
+ output: web, pdf
+
+ - title: Installation
+ output: web, pdf
+ folderitems:
+
+ - title: About Ruby, Gems, Bundler, etc.
+ url: /mydoc_about_ruby_gems_etc.html
+ output: web, pdf
+
+ - title: Install Jekyll on Mac
+ url: /mydoc_install_jekyll_on_mac.html
+ output: web, pdf
+
+ - title: Install Jekyll on Windows
+ url: /mydoc_install_jekyll_on_windows.html
+ output: web, pdf
+
+
+To accommodate the title page and table of contents in PDF outputs, each product sidebar must list these pages before any other:
+ +- title:
+ output: pdf
+ type: frontmatter
+ folderitems:
+ - title:
+ url: /titlepage
+ output: pdf
+ type: frontmatter
+ - title:
+ url: /tocpage
+ output: pdf
+ type: frontmatter
+
Leave the output as output: pdf
for these frontmatter pages so that they don’t appear in the web output.
For more detail on the sidebar, see Sidebar navigation and YAML tutorial.
+ +This theme uses relative links throughout so that you can view the site offline and not worry about which server or directory you’re hosting it. It’s common with tech docs to push content to an internal server for review prior to pushing the content to an external server for publication. Because of the need for seamless transferrence from one host to another, the site has to use relative links.
+ +To view pages locally on your machine (without the Jekyll preview server), they need to have the .html
extension. The permalink
property in the page’s frontmatter (without surrounding slashes) is what pushes the files into the root directory when the site builds.
When you write pages, include these same frontmatter properties with each page:
+ +---
+title: "Some title"
+tags: [sample1, sample2]
+keywords: keyword1, keyword2, keyword3
+last_updated: Month day, year
+summary: "optional summary here"
+sidebar: sidebarname
+permalink: filename.html
+---
+
(You will customize the values for each of these properties, of course.)
+ +For titles, surrounding the title in quotes is optional, but if you have a colon in the title, you must surround the title with quotation marks. If you have a quotation mark inside the title, escape it first with a backlash \
.
Values for keywords
get populated into the metadata of the page for SEO.
Values for tags
must be defined in your _data/tags.yml list. You also need a corresponding tag file inside the tags folder that follows the same pattern as the other tag files shown in the tags folder. (Jekyll won’t auto-create these tag files.)
If you don’t want the mini-TOC to show on a page (such as for the homepage or landing pages), add toc: false
in the frontmatter.
The permalink
value should be the same as your filename and include the “.html” file extension.
For more detail, see Pages.
+ +You can store your files for each product inside subfolders following the pattern shown in the theme. For example, product1, product2, etc, can be stored in their own subfolders inside the _pages directory. Inside _pages, you can store your topics inside sub-subfolders or sub-sub-folders to your heart’s content. When Jekyll builds your site, it will pull the topics into the root directory and use the permalink for the URL.
+ +Note that product1, product2, and mydoc are all just sample content to demonstrate how to add multiple products into the theme. You can freely delete that content.
+ +For more information, see Pages and Posts.
+ +The top navigation bar’s menu items are set through the _data/topnav.yml file. Use the top navigation bar to provide links for navigating from one product to another, or to navigate to external resources.
+ +For external URLs, use external_url
in the item property, as shown in the example topnav.yml file. For internal links, use url
the same was you do in the sidebar data files.
Note that the topnav has two sections: topnav
and topnav_dropdowns
. The topnav section contains single links, while the topnav_dropdowns
section contains dropdown menus. The two sections are independent of each other.
If you want to generate PDF, you’ll need a license for Prince XML. You will also need to install Prince. You can generate PDFs by product (but not for every product on the site combined together into one massive PDF). Prince will work even without a license, but it will imprint a small Prince image on the first page, and you’re supposed to buy the license to use it.
+ +If you’re on Windows, install Git Bash client rather than using the default Windows command prompt.
+ +Open up the css/printstyles.css file and customize the email address (youremail@domain.com
) that is listed there. This email address appears in the bottom left footer of the PDF output. You’ll also need to create a PDF configuration file following the examples shown in the pdfconfigs folder, and also customize some build scripts following the same pattern shown in the root: pdf-product1.sh
See the section on Generating PDFs for more details about setting the theme up for this output.
+ +For blog posts, create your markdown files in the _posts folder following the sample formats. Post file names always begin with the date (YYYY-MM-DD-title).
+ +The news/news.html file displays the posts, and the news_archive.html file shows a yearly history of posts. In documentation, you might use the news to highlight product features outside of your documentation, or to provide release notes and other updates.
+ +See Posts for more information.
+ +This theme uses kramdown markdown. kramdown is similar to Github-flavored Markdown, except that when you have text that intercepts list items, the spacing of the intercepting text must align with the spacing of the first character after the space of a numbered list item. Basically, with your list item numbering, use two spaces after the dot in the number, like this:
+ +1. First item
+2. Second item
+3. Third item
+
When you want to insert paragraphs, notes, code snippets, or other matter in between the list items, use four spaces to indent. The four spaces will line up with the first letter of the list item (the First or Second or Third).
+ +1. First item
+
+ ```
+ alert("hello");
+ ```
+
+2. Second item
+
+ Some pig!
+
+3. Third item
+
See the topics under “Formatting” in the sidebar for more information.
+ +If you want to use an automated system for managing links, see Automated Links. This approach automatically creates a list of Markdown references to simplify linking.
+ +The content here is just a getting started guide only. For other details in working with the theme, see the various sections in the sidebar.
+ + + + + + + + + + + + + + +My name is Tom Johnson, and I’m a technical writer, blogger, and podcaster based in San Jose, California. For more details, see my technical writing blog and my course on API documentation. See my blog’s about page for more details about me.
+ +I have used this theme and variations of it for various documentation projects. This theme has undergone several major iterations, and now it’s fairly stable and full of all the features that I need. You are welcome to use it for your documentation projects for free.
+ +I think this theme does pretty much everything that you can do with something like OxygenXML, but without the constraints of structured authoring. Everything is completely open and changeable, so if you start tinkering around with the theme’s files, you can break things. But it’s completely empowering as well!
+ +With a completely open architecture and code base, you can modify the code to make it do exactly what you want, without having to jump through all kinds of confusing or proprietary code.
+ +If there’s a feature you need but it isn’t available here, let me know and I might add it. Alternatively, if you fork the theme, I would love to see your modifications and enhancements. Thanks for using Jekyll.
+ + + + + + + + + + + + + + +Jekyll runs on Ruby, a programming language. You have to have Ruby on your computer in order to run Ruby-based programs like Jekyll. Ruby is installed on the Mac by default, but you must add it to Windows.
+ +Ruby has a number of plugins referred to as “gems.” Just because you have Ruby doesn’t mean you have all the necessary Ruby gems that your program needs to run. Gems provide additional functionality for Ruby programs. There are thousands of Rubygems available for you to use.
+ +Some gems depend on other gems for functionality. For example, the Jekyll gem might depend on 20 other gems that must also be installed.
+ +Each gem has a version associated with it, and not all gem versions are compatible with each other.
+ +Bundler is a gem package manager for Ruby, which means it goes out and gets all the gems you need for your Ruby programs. If you tell Bundler you need the jekyll gem, it will retrieve all the dependencies on the jekyll gem as well – automatically.
+ +Not only does Bundler retrieve the right gem dependencies, but it’s smart enough to retrieve the right versions of each gem. For example, if you get the github-pages gem, it will retrieve all of these other gems:
+ +github-pages-health-check = 1.1.0
+jekyll = 3.0.3
+jekyll-coffeescript = 1.0.1
+jekyll-feed = 0.4.0
+jekyll-gist = 1.4.0
+jekyll-github-metadata = 1.9.0
+jekyll-mentions = 1.1.2
+jekyll-paginate = 1.1.0
+jekyll-redirect-from = 0.10.0
+jekyll-sass-converter = 1.3.0
+jekyll-seo-tag = 1.3.2
+jekyll-sitemap = 0.10.0
+jekyll-textile-converter = 0.1.0
+jemoji = 0.6.2
+kramdown = 1.10.0
+liquid = 3.0.6
+mercenary ~> 0.3
+rdiscount = 2.1.8
+redcarpet = 3.3.3
+RedCloth = 4.2.9
+rouge = 1.10.1
+terminal-table ~> 1.
+
See how Bundler retrieved version 3.0.3 of the jekyll gem, even though (as of this writing) the latest version of the jekyll gem is 3.1.2? That’s because github-pages is only compatible up to jekyll 3.0.3. Bundler handles all of this dependency and version compatibility for you.
+ +Trying to keep track of which gems and versions are appropriate for your project can be a nightmare. This is the problem Bundler solves. As explained on Bundler.io:
+ +++ +Bundler provides a consistent environment for Ruby projects by tracking and installing the exact gems and versions that are needed.
+ +Bundler is an exit from dependency hell, and ensures that the gems you need are present in development, staging, and production. Starting work on a project is as simple as bundle install.
+
Bundler looks in a project’s “Gemfile” (no file extension) to see which gems are required by the project. The Gemfile lists the source and then any gems, like this:
+ +source "https://rubygems.org"
+
+gem 'github-pages'
+gem 'jekyll'
+
The source indicates the site where Bundler will retrieve the gems: https://rubygems.org.
+ +The gems it retrieves are listed separately on each line.
+ +Here no versions are specified. Sometimes gemfiles will specify the versions like this:
+ +gem 'kramdown', '1.0'
+
This means Bundler should get version 1.0 of the kramdown gem.
+ +To specify a subset of versions, the Gemfile looks like this:
+ +gem 'jekyll', '~> 2.3'
+
The ~>
sign means greater than or equal to the last digit before the last period in the number.
Here it will get any gem equal to 2.3 but less than 3.0.
+ +If it adds another digit, the scope is affected:
+ +gem `jekyll`, `~>2.3.1'
+
This means to get any gem equal to 2.3.1 but less than 2.4.
+ +If it looks like this:
+ +gem 'jekyll', '~> 3.0', '>= 3.0.3'
+
This will get any Jekyll gem between versions 3.0 and up to 3.0.3.
+ +See this Stack Overflow post for more details.
+ +After Bundler retrieves and installs the gems, it makes a detailed list of all the gems and versions it has installed for your project. The snapshot of all gems + versions installed is stored in your Gemfile.lock file, which might look like this:
+ +GEM
+ remote: https://rubygems.org/
+ specs:
+ RedCloth (4.2.9)
+ activesupport (4.2.5.1)
+ i18n (~> 0.7)
+ json (~> 1.7, >= 1.7.7)
+ minitest (~> 5.1)
+ thread_safe (~> 0.3, >= 0.3.4)
+ tzinfo (~> 1.1)
+ addressable (2.3.8)
+ coffee-script (2.4.1)
+ coffee-script-source
+ execjs
+ coffee-script-source (1.10.0)
+ colorator (0.1)
+ ethon (0.8.1)
+ ffi (>= 1.3.0)
+ execjs (2.6.0)
+ faraday (0.9.2)
+ multipart-post (>= 1.2, < 3)
+ ffi (1.9.10)
+ gemoji (2.1.0)
+ github-pages (52)
+ RedCloth (= 4.2.9)
+ github-pages-health-check (= 1.0.1)
+ jekyll (= 3.0.3)
+ jekyll-coffeescript (= 1.0.1)
+ jekyll-feed (= 0.4.0)
+ jekyll-gist (= 1.4.0)
+ jekyll-mentions (= 1.0.1)
+ jekyll-paginate (= 1.1.0)
+ jekyll-redirect-from (= 0.9.1)
+ jekyll-sass-converter (= 1.3.0)
+ jekyll-seo-tag (= 1.3.1)
+ jekyll-sitemap (= 0.10.0)
+ jekyll-textile-converter (= 0.1.0)
+ jemoji (= 0.5.1)
+ kramdown (= 1.9.0)
+ liquid (= 3.0.6)
+ mercenary (~> 0.3)
+ rdiscount (= 2.1.8)
+ redcarpet (= 3.3.3)
+ rouge (= 1.10.1)
+ terminal-table (~> 1.4)
+ github-pages-health-check (1.0.1)
+ addressable (~> 2.3)
+ net-dns (~> 0.8)
+ octokit (~> 4.0)
+ public_suffix (~> 1.4)
+ typhoeus (~> 0.7)
+ html-pipeline (2.3.0)
+ activesupport (>= 2, < 5)
+ nokogiri (>= 1.4)
+ i18n (0.7.0)
+ jekyll (3.0.3)
+ colorator (~> 0.1)
+ jekyll-sass-converter (~> 1.0)
+ jekyll-watch (~> 1.1)
+ kramdown (~> 1.3)
+ liquid (~> 3.0)
+ mercenary (~> 0.3.3)
+ rouge (~> 1.7)
+ safe_yaml (~> 1.0)
+ jekyll-coffeescript (1.0.1)
+ coffee-script (~> 2.2)
+ jekyll-feed (0.4.0)
+ jekyll-gist (1.4.0)
+ octokit (~> 4.2)
+ jekyll-mentions (1.0.1)
+ html-pipeline (~> 2.3)
+ jekyll (~> 3.0)
+ jekyll-paginate (1.1.0)
+ jekyll-redirect-from (0.9.1)
+ jekyll (>= 2.0)
+ jekyll-sass-converter (1.3.0)
+ sass (~> 3.2)
+ jekyll-seo-tag (1.3.1)
+ jekyll (~> 3.0)
+ jekyll-sitemap (0.10.0)
+ jekyll-textile-converter (0.1.0)
+ RedCloth (~> 4.0)
+ jekyll-watch (1.3.1)
+ listen (~> 3.0)
+ jemoji (0.5.1)
+ gemoji (~> 2.0)
+ html-pipeline (~> 2.2)
+ jekyll (>= 2.0)
+ json (1.8.3)
+ kramdown (1.9.0)
+ liquid (3.0.6)
+ listen (3.0.6)
+ rb-fsevent (>= 0.9.3)
+ rb-inotify (>= 0.9.7)
+ mercenary (0.3.5)
+ mini_portile2 (2.0.0)
+ minitest (5.8.4)
+ multipart-post (2.0.0)
+ net-dns (0.8.0)
+ nokogiri (1.6.7.2)
+ mini_portile2 (~> 2.0.0.rc2)
+ octokit (4.2.0)
+ sawyer (~> 0.6.0, >= 0.5.3)
+ public_suffix (1.5.3)
+ rb-fsevent (0.9.7)
+ rb-inotify (0.9.7)
+ ffi (>= 0.5.0)
+ rdiscount (2.1.8)
+ redcarpet (3.3.3)
+ rouge (1.10.1)
+ safe_yaml (1.0.4)
+ sass (3.4.21)
+ sawyer (0.6.0)
+ addressable (~> 2.3.5)
+ faraday (~> 0.8, < 0.10)
+ terminal-table (1.5.2)
+ thread_safe (0.3.5)
+ typhoeus (0.8.0)
+ ethon (>= 0.8.0)
+ tzinfo (1.2.2)
+ thread_safe (~> 0.1)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ github-pages
+ jekyll
+
+BUNDLED WITH
+ 1.11.2
+
You can always delete the Gemlock file and run Bundle install again to get the latest versions. You can also run bundle update
, which will ignore the Gemlock file to get the latest versions of each gem.
To learn more about Bundler, see Bundler’s Purpose and Rationale.
+ + + + + + + + + + + + + + +Because this theme is built on Bootstrap, you can simply use a specific attribute on an element to insert a tooltip.
+ +Suppose you have a glossary.yml file inside your _data folder. You could pull in that glossary definition like this:
+ +<a href="#" data-toggle="tooltip" data-original-title="{{site.data.glossary.jekyll_platform}}">Jekyll</a> is my favorite tool for building websites.
+
This renders to the following:
+ +Jekyll is my favorite tool for building websites.
+ + + + + + + + + + + + + + +Alerts are little warnings, info, or other messages that you have called out in special formatting. In order to use these alerts or callouts, reference the appropriate value stored in the alerts.yml file as described in the following sections.
+ +Similar to inserting images, you insert alerts through various includes that have been developed. These includes provide templates through which you pass parameters to easily populate the right HTML code.
+ +{% include note.html content="This is my note. All the content I type here is treated as a single paragraph." %}
+
Here’s the result:
+ +With alerts, there’s just one include property:
+ +Property | +description | +
---|---|
content | +The content for the alert. | +
If you need multiple paragraphs, enter <br/><br/>
tags. This is because block level tags aren’t allowed here, as Kramdown is processing the content as Markdown despite the fact that the content is surrounded by HTML tags. Here’s an example with a break:
{% include note.html content="This is my note. All the content I type here is treated as a single paragraph. <br/><br/> Now I'm typing on a new line." %}
+
Here’s the result:
+ +The include uses markdown="span"
as an attribute, which means kramdown will process the entire content
as a span. You can’t use block elements such as p
or div
or pre
. If you need these elements, you can either manually surround the content with the HTML from the include, or you can use these tags:
{{site.data.alerts.note}}
+<p>This is my note.</p>
+<pre>
+def foo(x):<br>
+ return x+1
+</pre>
+{{site.data.alerts.end}}
+
Result:
+ +This is my note.
++def foo(x):+
+ return x+1 +
The same Bootstrap code from the alert is stored in yaml files inside the _data folder. (This was how I previously implemented this code, but since this method was prone to error and didn’t trigger any build warnings or failures when incorrectly coded, I changed the approach to use includes instead.)
+ +There are four types of alerts you can leverage:
+ +They function the same except they have a different color, icon, and alert word. You include the different types by selecting the include template you want. Here are samples of each alert:
+ +These alerts leverage includes stored in the _include folder. The content
option is a parameter that you pass to the include. In the include, the parameter is passed like this:
<div markdown="span" class="alert alert-info" role="alert"><i class="fa fa-info-circle"></i> <b>Note:</b> {{include.content}}</div>
+
The content in content="This is my note."
gets inserted into the {{include.content}}}
part of the template. You can follow this same pattern to build additional includes. See this Jekyll screencast on includes or this screencast for more information.
There’s another type of callout available called callouts. This format is typically used for longer callout that spans more than one or two paragraphs, but really it’s just a stylistic preference whether to use an alert or callout.
+ +Here’s the syntax for a callout:
+ +{% include callout.html content="This is my callout. It has a border on the left whose color you define by passing a type parameter. I typically use this style of callout when I have more information that I want to share, often spanning multiple paragraphs. " type="primary" %}
+
Here’s the result:
+ +The available properties for callouts are as follows:
+ +Property | +description | +
---|---|
content | +The content for the callout. | +
type | +The style for the callout. Options are danger , default , primary , success , info , and warning . |
+
The types just define the color of the left border. Each of these callout types get inserted as a class name in the callout template. These class names correspond with styles in Bootstrap. These classes are common Bootstrap class names whose style attributes differ depending on your Bootstrap theme and style definitions.
+ +Here’s an example of each different type of callout:
+ +Now that in contrast to alerts, callouts don’t include the alert word (note, tip, warning, or important). You have to manually include it inside content
if you want it.
To include paragraph breaks, use <br/><br/>
inside the callout:
{% include callout.html content="**Important information**: This is my callout. It has a border on the left whose color you define by passing a type parameter. I typically use this style of callout when I have more information that I want to share, often spanning multiple paragraphs. <br/><br/>Here I am starting a new paragraph, because I have lots of information to share. You may wonder why I'm using line breaks instead of paragraph tags. This is because Kramdown processes the Markdown here as a span rather than a div (for whatever reason). Be grateful that you can be using Markdown at all inside of HTML. That's usually not allowed in Markdown syntax, but it's allowed here." type="primary" %}
+
Here’s the result:
+ +Suppose you have a product name or some other property that you’re storing as a variable in your configuration file (_config.yml), and you want to use this variable in the content
parameter for your alert or callout. You will get an error if you use Liquid syntax inside a include parameter. For example, this syntax will produce an error:
{% include note.html content="The {{site.company}} is pleased to announce an upcoming release." %}
+
The error will say something like this:
+ +Liquid Exception: Invalid syntax for include tag. File contains invalid characters or sequences: ... Valid syntax: {% include file.ext param='value' param2='value' %}
+
To use variables in your include parameters, you must use the “variable parameter” approach. First you use a capture
tag to capture some content. Then you reference this captured tag in your include. Here’s an example.
In my site configuration file (_congfig.yml), I have a property called company_name
.
company_name: Your company
+
I want to use this variable in my note include.
+ +First, before the note I capture the content for my note’s include like this:
+ +{% capture company_note %}The {{site.company_name}} company is pleased to announce an upcoming release.{% endcapture %}
+
Now reference the company_note
in your include
parameter like this:
{% include note.html content=company_note}
+
Here’s the result:
+ +Note the omission of quotation marks with variable parameters.
+ +Also note that instead of storing the variable in your site’s configuration file, you could also put the variable in your page’s frontmatter. Then instead of using {{site.company_name}}
you would use {{page.company_name}}
.
You can use Markdown inside of callouts and alerts, even though this content actually gets inserted inside of HTML in the include. This is one of the advantages of kramdown Markdown. The include template has an attribute of markdown="span"
that allows for the processor to parse Markdown inside of HTML.
If you have some of the syntax wrong with an alert or callout, you’ll see an error when Jekyll tries to build your site. The error may look like this:
+ +Liquid Exception: Invalid syntax for include tag: content="This is my **info** type callout. It has a border on the left whose color you define by passing a type parameter. type="info" Valid syntax: {% include file.ext param='value' param2='value' %} in mydoc/mydoc_alerts.md
+
These errors are a good thing, because it lets you know there’s an error in your syntax. Without the errors, you may not realize that you coded something incorrectly until you see the lack of alert or callout styling in your output.
+ +In this case, the quotation marks aren’t set correctly. I forgot the closing quotation mark for the content parameter include.
+ +If you want to blast a warning to users on every page, add the alert or callout to the _layouts/page.html page right below the frontmatter. Every page using the page layout (all, by default) will show this message.
+ + + + + + + + + + + + + + +If you haven’t downloaded Atom, download and install it. Use this as your editor when working with Jekyll. The syntax highlighting is probably the best among the available editors, as it was designed with Jekyll-authoring in mind. However, if you prefer Sublime Text, WebStorm, or some other editor, you can also use that.
+ +Customize the invisibles and tab spacing in Atom:
+ +Turn off auto-complete:
+ +(For Windows, replace “Cmd” with “Ctrl”.)
+ + + + + + + + + + + + + +The normal way to build the Jekyll site is through the build command:
+ +jekyll build
+
To build the site and view it in a live server so that Jekyll rebuilds that site each time you make a change, use the serve
command:
jekyll serve
+
By default, the _config.yml in the root directory will be used, Jekyll will scan the current directory for files, and the folder _site
will be used as the output. You can customize these build commands like this:
jekyll serve --config configs/myspecialconfig.yml --destination ../doc_outputs
+
Here the configs/myspecialconfig.yml
file is used instead of _config.yml
. The destination directory is ../doc_outputs
, which would be one level up from your current directory.
If you have a long build argument and don’t want to enter it every time in Jekyll, noting all your configuration details, you can create a shell script and then just run the script. Simply put the build argument into a text file and save it with the .sh extension (for Mac) or .bat extension (for Windows). Then run it like this:
+ +. myscript.sh
+
My preference is to add the scripts to profiles in iTerm. See iTerm Profiles for more details.
+ +When you’re done with the preview server, press Ctrl+C to exit out of it. If you exit iTerm or Terminal without shutting down the server, the next time you build your site, or if you build multiple sites with the same port, you may get a server-already-in-use message.
+ +You can kill the server process using these commands:
+ +ps aux | grep jekyll
+
Find the PID (for example, it looks like “22298”).
+ +Then type kill -9 22298
where “22298” is the PID.
To kill all Jekyll instances, use this:
+ +kill -9 $(ps aux | grep '[j]ekyll' | awk '{print $2}')
+
I recommend creating a profile in iTerm that stores this command. Here’s what the iTerm settings look like:
+ + + + + + + + + + + + + + + + +The mydoc project has 5 build scripts and a script that runs them all. These scripts will require a bit of detail to configure. Every team member who is publishing on the project should set up their folder structure in the way described here.
+ +Your command-line terminal opens up to your user name (for example, Users/tjohnson
). I like to put all of my projects from repositories into a subfolder under my username called “projects.” This makes it easy to get to the projects from the command line. You can vary from the project organization I describe here, but following the pattern I outline will make configuration easier.
To set up your projects:
+ +In the same root directory where the docs folder is, create another directory parallel to docs called doc_outputs.
+ +Thus, your folder structure should be something like this:
+ +projects
+- docs
+- doc_outputs
+
The docs folder contains the source of all your files, while the doc_outputs contains the site outputs.
+For the mydocs project, you’ll see a series of build scripts for each project. There are 5 build scripts, described in the following sections. Note that you really only need to run the last one, e.g., mydoc_all.sh, because it runs all of the build scripts. But you have to make sure each script is correctly configured so that they all build successfully.
+ +Here’s what this script looks like:
+ +echo 'Killing all Jekyll instances'
+kill -9 $(ps aux | grep '[j]ekyll' | awk '{print $2}')
+clear
+
+
+echo "Building PDF-friendly HTML site for Mydoc Writers ..."
+jekyll serve --detach --config configs/mydoc/config_writers.yml,configs/mydoc/config_writers_pdf.yml
+echo "done"
+
+echo "Building PDF-friendly HTML site for Mydoc Designers ..."
+jekyll serve --detach --config configs/mydoc/config_designers.yml,configs/mydoc/config_designers_pdf.yml
+echo "done"
+
+echo "All done serving up the PDF-friendly sites. Now let's generate the PDF files from these sites."
+echo "Now run . mydoc_2_multibuild_pdf.sh"
+
After killing all existing Jekyll instances that may be running, this script serves up a PDF friendly version of the docs (in HTML format) at the destination specified in the configuration file.
+ +Each of your configuration files needs to have a destination like this: ../doc_outputs/mydoc/adtruth-java
. That is, the project should build in the doc_outputs folder, in a subfolder that matches the project name.
The purpose of this script is to make a version of the HTML output that is friendly to the Prince XML PDF generator. This version of the output strips out the sidebar, topnav, and other components to just render a bare-bones HTML representation of the content.
+ +Customize the script with your own PDF configuration file names.
+ +Here’s what this script looks like:
+ +# Doc Writers
+echo "Building the Mydoc Writers PDF ..."
+prince --javascript --input-list=../doc_outputs/mydoc/writers-pdf/prince-file-list.txt -o mydoc/files/mydoc_writers_pdf.pdf;
+echo "done"
+
+# Doc Designers
+echo "Building Mydoc Designers PDF ..."
+prince --javascript --input-list=../doc_outputs/mydoc/designers-pdf/prince-file-list.txt -o mydoc/files/mydoc_designers_pdf.pdf;
+echo "done"
+
+echo "All done building the PDFs!"
+echo "Now build the web outputs: . mydoc_3_multibuild_web.sh"
+
This script builds the PDF output using the Prince command. The script reads the location of the prince-file-list.txt file in the PDF friendly output folder (as defined in the previous script) and builds a PDF.
+ +The Prince build command takes an input parameter (--input-list=
) that lists where all the pages are (prince-file-list.txt), and then combines all the pages into a PDF, including cross-references and other details. The Prince build command also specifies the output folder (-o
).
The prince-file-list.txt file (which simply contains a list of URLs to HTML pages) is generated by iterating through the table of contents (mydoc_sidebar.yml) and creating a list of URLs. You can open up prince-file-list.txt in the doc output to ensure that it has a list of absolute URLs (not relative) in order for Prince to build the PDF.
+ +This is one way the configuration file for the PDF-friendly output differs from the HTML output. (If the PDF isn’t building, it’s because the prince-file-list.txt in the output is empty or it contains relative URLs.)
+ +The Prince build script puts the output PDF into the mydoc/mydoc/files directory. Now you can reference the PDF file in your HTML site. For example, on the homepage you can allow people to download a PDF of the content at files/adtruth_dotnet_pdf.pdf.
+ +Here’s what this script looks like:
+ +kill -9 $(ps aux | grep '[j]ekyll' | awk '{print $2}')
+clear
+
+echo "Building Mydoc Writers website..."
+jekyll build --config configs/doc/config_writers.yml
+# jekyll serve --config configs/doc/config_writers.yml
+echo "done"
+
+echo "Building Mydoc Designers website..."
+jekyll build --config configs/doc/config_designers.yml
+# jekyll serve --config configs/doc/config_designers.yml
+echo "done"
+
+echo "All finished building all the web outputs!!!"
+echo "Now push the builds to the server with . mydoc_4_publish.sh"
+
After killing all Jekyll instances, this script builds an HTML version of the projects and puts the output into the doc_outputs folder. This is the version of the content that users will mainly navigate. Since the sites are built with relative links, you can browse to the folder on your local machine, double-click the index.html file, and see the site.
+ +The #
part below the jekyll build
commands contains a serve command that is there for mere convenience in case you want to serve up just one site among many that you’re building. For example, if you don’t want to build everything — just one site — you might just use the serve command instead. (Anything after # in a YAML file comments out the content.)
Here’s what this script looks like:
+ +echo "remove previous directory and any subdirectories without a warning prompt"
+ssh yourusername@yourdomain.com 'rm -rf /var/www/html/yourpublishingdirectory'
+
+echo "push new content into the remote directory"
+scp -r -vrC ../mydoc_outputs/doc-writers yourusername@yourdomain:/var/www/html/yourpublishingdirectory
+
+echo "All done pushing doc outputs to the server"
+
+
This script assumes you’re publishing content onto a Linux server.
+ +Change yourusername
to your own user name.
This script first removes the project folder on /var/www/html/yourpublishingdirectory site and then transfers the content from doc_outputs over to the appropriate folder in /var/www/html/yourpublishingdirectory.
+ +Note that the delete part of the script (rm -rf
) works really well. It annihilates a folder in a heartbeat and doesn’t give you any warning prompts, so make sure you have it set up correctly.
Also, in case you haven’t set up the SSH publishing without a password, see [Getting around the password prompts in SCP][mydoc_no_password_prompts_scp]. Otherwise the script will stop and ping you to enter your password for each directory it transfers.
+ +This script isn’t included in the theme, but you might optionally decide to push the built sites into another github repository. For example, if you’re using Cloud Cannon to deploy your sites, you can have Cloud Cannon read files from a specific Github repository.
+ +Here’s what this script looks like:
+ +cd doc_outputs/mydoc/designers
+git add --all
+git commit -m "publishing latest version of docs"
+git push
+echo "All done pushing to Github"
+echo "Here's the link to download the guides..."
+cd ../../docs
+
This final script simply makes a commit into a Github repo for one of your outputs.
+ +The doc_outputs/mydoc/designers contains the site output from mydoc, so when you push content from this folder into Github, you’re actually pushing the HTML site output into Github, not the mydoc source files.
+ +Your delivery team can also grab the site output from these repos. After downloading it, the person unzips the folder and sees the website folders inside.
+ +Here’s what this script looks like:
+ +. deviceinsight_1_multiserve_pdf.sh; . deviceinsight_2_multibuild_pdf.sh; . deviceinsight_3_multibuild_web.sh; . deviceinsight_4_publish.sh;
+
This script simply runs the other scripts. To sequence the commands, you just separate them with semicolons. (If you added the optional script, be sure to include it here.)
+ +After you’ve configured all the scripts, you can run them all by running . mydoc_all.sh
. You might want to run this script at lunchtime, since it may take about 10 to 20 minutes to completely build the scripts. But note that since everything is now automated, you don’t have to do anything at all after executing the script. After the script finishes, everything is published and in the right location.
After setting up and customizing the build scripts, run a few tests to make sure everything is generating correctly. Getting this part right is somewhat difficult and may likely require you to tinker around with the scripts a while before it works flawlessly.
+ ++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + +Use fenced code blocks with the language specified, like this:
+ +```js
+console.log('hello');
+````
+
Result:
+ +console.log('hello');
+
For the list of supported languages you can use (similar to js
for JavaScript), see Supported languages.
Collections are custom content types different from pages and posts. You might create a collection if you want to treat a specific set of articles in a unique way, such as with a custom layout or listing. For more detail on collections, see Ben Balter’s explanation of collections here.
+ +To create a collection, add the following in your configuration file:
+ +collections:
+ tooltips:
+ output: true
+
In this example, “tooltips”” is the name of the collection.
+ +You can interact with collections by using the site.collectionname
namespace, where collectionname
is what you’ve configured. In this case, if I wanted to loop through all tooltips, I would use site.tooltips
instead of site.pages
or site.posts
.
See Collections in the Jekyll documentation for more information.
+ +I haven’t found a huge use for collections in normal documentation. However, I did find a use for collections in generating a tooltip file that would be used for delivering tooltips to a user interface from text files in the documentation. See Help APIs and UI tooltips for details.
+ +See this video tutorial on Jekyll.tips for more details on collections.
+ + + + + + + + + + + + + + +If you’re using the doc as code approach, you might also consider using the same techniques for reviewing the doc as people use in reviewing code. This approach will involve using Github to edit the files.
+ +There’s an Edit me button on each page on this theme. This button allows collaborators to edit the content on Github.
+ +Here’s the code for that button on the page.html layout for GitHub:
+ +{% if site.github_editme_path %}
+
+<a target="_blank" href="https://github.com/{{site.github_editme_path}}/{{page.folder}}{{page.url | append: ".md"}}{% endif %}" class="btn btn-default githubEditButton" role="button"><i class="fa fa-github fa-lg"></i> Edit me</a>
+
+{% endif %}
+
and here for GitLab:
+ +{% if site.gitlab_editme_path %}
+
+<a target="_blank" href="https://github.com/{{site.gitlab_editme_path}}/{{page.folder}}{{page.url | append: ".md"}}{% endif %}" class="btn btn-default githubEditButton" role="button"><i class="fa fa-gitlab fa-lg"></i> Edit me</a>
+
+{% endif %}
+
In your configuration file, edit the value for github_editme_path
(or for Gitlab: gitlab_editme_path
). For example, you might create a branch called “reviews” on your Github repo. Then you would add something like this in your configuration file for the ‘github_editme_path’: tomjoht/documentation-theme-jekyll/edit/reviews. Here “tomjoht” is my github account name. The repo name is “documentation-theme-jekyll”. The “reviews” name is the branch.
To suppress this button, comment out the github_editme_path
in the _config.yml file.
If you want people to collaborate on your project so that their edits get committed to a branch on your project, you need to add them as collaborators. For your Github repo, click Settings and add the collaborators on the Collaborators tab using their Github usernames.
+ +If you don’t want to allow anyone to commit to your Github branch, don’t add the reviewers as collaborators. When someone makes an edit, Github will fork the theme. The person’s edit then will appear as a pull request to your repo. You can then choose to merge the change indicated in the pull or not.
+ +Users will make edits in your “reviews” branch (or whatever you want to call it). You can then commit those edits as you make updates.
+ +When you’re finished making all updates in the branch, you can merge the branch into the master.
+ +Note that if you’re making updates online, those updates will be out of sync with any local edits.
+ +Prose.io is an overlay on Github that would allow people to make comments in an easier interface. If you simply go to prose.io, it asks to authorize your Github account, and so it will read files directly from Github but in the Prose.io interface.
+ + + + + + + + + + + + + + +If you want to create different outputs for different audiences, you can do all of this using a combination of Jekyll’s Liquid markup and values in your configuration file. This is how I previously configured the theme. I had different configuration files for each output. Each configuration file specified different values for product, audience, version, and so on. Then I had different build processes that would leverage the different configuration files. It seemed like a perfect implementation of DITA-like techniques with Jekyll.
+ +But I soon found that having lots of separate outputs for a project was undesirable. If you have 10 different outputs that have different nuances for different audiences, it’s hard to manage and maintain. In this latest version of the theme, I consolidated all information into the same output to explicitly do away with the multi-output approach.
+ +As such, the conditional logic won’t have as much play as it previously did. Instead of conditions, you’ll probably want to incorporate navtabs to split up the information.
+ +However, you can still of course use conditional logic as needed.
+ +You can filter content based on values that you have set either in your page’s frontmatter, a config file, or in a file in your _data folder. If you set the attribute in your config file, you need to restart the Jekyll server to see the changes. If you set the value in a file in your _data folder or page frontmatter, you don’t need to restart the server when you make changes.
+ +Here’s an example of conditional logic based on a value in the page’s frontmatter. Suppose you have the following in your frontmatter:
+ +platform: mac
+
On a page in my site (it can be HTML or markdown), you can conditionalize content using the following:
+ +{% if page.platform == "mac" %}
+Here's some info about the Mac.
+{% elsif page.platform == "windows" %}
+Here's some info about Windows ...
+{% endif %}
+
This uses simple if-elsif
logic to determine what is shown (note the spelling of elsif
). The else
statement handles all other conditions not handled by the if
statements.
Here’s an example of if-else
logic inside a list:
To bake a casserole:
+
+1. Gather the ingredients.
+{% if page.audience == "writer" %}
+2. Add in a pound of meat.
+{% elsif page.audience == "designer" %}
+3. Add in an extra can of beans.
+{% endif %}
+3. Bake in oven for 45 min.
+
You don’t need the elsif
or else
. You could just use an if
(but be sure to close it with endif
).
You can use more advanced Liquid markup for conditional logic, such as an or
command. See Shopify’s Liquid documentation for more details.
For example, here’s an example using or
:
{% if page.audience contains "vegan" or page.audience == "vegetarian" %}
+ Then run this...
+{% endif %}
+
Note that you have to specify the full condition each time. You can’t shorten the above logic to the following:
+ +{% if page.audience contains "vegan" or "vegetarian" %}
+ // run this.
+{% endif %}
+
This won’t work.
+ +You can also use unless
in your logic, like this:
{% unless site.output == "pdf" %}
+...do this
+{% endunless %}
+
When figuring out this logic, read it like this: “Run the code here unless this condition is satisfied.”.”
+ +Don’t read it the other way around or you’ll get confused. (It’s not executing the code only if the condition is satisfied.)
+ +Here’s an example of using conditional logic based on a value in a data file:
+ +{% if site.data.options.output == "alpha" %}
+show this content...
+{% elsif site.data.options.output == "beta" %}
+show this content...
+{% else %}
+this shows if neither of the above two if conditions are met.
+{% endif %}
+
To use this, I would need to have a _data folder called options where the output
property is stored.
You can also specify a data_source
for your data location in your configuration file. Then you aren’t limited to simply using _data
to store your data files.
For example, suppose you have 2 projects: alpha and beta. You might store all the data files for alpha inside data_alpha, and all the data files for beta inside data_beta.
+ +In your alpha configuration file, specify the data source like this:
+ +data_source: data_alpha
+
Then create a folder called _data_alpha.
+ +For your beta configuration file, specify the data source like this:
+ +data_source: data_beta
+
Then create a folder called _data_beta.
+ +If you have a lot of conditions in your text, it can get confusing. As a best practice, whenever you insert an if
condition, add the endif
at the same time. This will reduce the chances of forgetting to close the if statement. Jekyll won’t build if there are problems with the liquid logic.
If your text is getting busy with a lot of conditional statements, consider putting a lot of content into includes so that you can more easily see where the conditions begin and end.
+ + + + + + + + + + + + + + +You can embed content from one file inside another using includes. Put the file containing content you want to reuse (e.g., mypage.html) inside the _includes/custom folder and then use a tag like this:
+ +{% include custom/mypage.html %}
+
With content in your _includes folder, you don’t add any frontmatter to these pages because they will be included on other pages already containing frontmatter.
+ +Also, when you include a file, all of the file’s contents get included. You can’t specify that you only want a specific part of the file included. However, you can use parameters with includes.
+ +See the following Jekyll cast for more info about using parameters with includes:
+ + + +You can also create custom variables in your frontmatter like this:
+ +---
+title: Page-level variables
+permalink: page_level_variables/
+thing1: Joe
+thing2: Dave
+---
+
You can then access the values in those custom variables using the page
namespace, like this:
thing1: {{page.thing1}}
+thing2: {{page.thing2}}
+
I use includes all the time. Most of the includes in the _includes directory are pulled into the theme layouts. For those includes that change, I put them inside custom and then inside a specific project folder.
+ + + + + + + + + + + + + + +By default, all files in your project are included in your output (regardless of whether they’re listed in the sidebar_doc.yml file or not). To exclude files, note them in the exclude
section in the configuration file. Here’s a sample:
+exclude:
+ - mydoc_writers_*
+ - bower_components
+ - Gemfile
+
If you have different outputs for your site, you’ll want to customize the exclude sections in your various configuration files.
+ +Here’s the process I recommend. Put all files in the root directory of your project. Suppose one project’s name is alpha and the other is beta. Then name each file as follows:
+ +In your exclude list for your beta project, specify it as follows:
+ +exclude:
+- alpha_*
+
In your exclude list for your alpha project, specify it as follows:
+ +exclude:
+- beta_*
+
If you have more sophisticated exclusion, add another level to your file names. For example, if you have different programming languages you want to filter by, add this:
+ +Then you exclude files for your Alpha C++ project as follows:
+ +exclude:
+
+- alpha_java_*
+- beta_*
+
And you exclude files for your Alpha Java project as follows:
+ +exclude:
+
+- alpha_cpp_*
+- alpha_beta_*
+
When you exclude folders, include the trailing slash at the end of the folder name:
+ +exclude:
+- images/alpha/
+
There isn’t a way to automatically exclude anything. By default, everything is included unless you explicitly list it under the exclude section.
+ +If you’re working on a draft, put it inside the _drafts folder or add published: false
in the frontmatter. The _drafts folder is excluded by default, so you don’t have to specify it in your exclude list.
What if a file should appear in two projects but not the third? This can get tricky. For some files, rather than using a wildcard, you may need to manually specify the entire filename that you’re excluding instead of excluding it by way of a wildcard pattern.
+ + + + + + + + + + + + + + +If you want to use an FAQ format, use the syntax shown on the faq.html page. Rather than including code samples here (which are bulky with a lot of nested div
tags), just look at the source in the mydoc_faq.html theme file.
This process for creating a PDF relies on Prince XML to transform the HTML content into PDF. Prince costs about $500 per license. That might seem like a lot, but if you’re creating a PDF, you’re probably working for a company that sells a product, so you likely have access to some resources. There’s also a free license that prints a small “P” watermark on your title page, so if you’re fine with that, great.
+ +The basic approach is to generate a list of all web pages that need to be added to the PDF, and then add leverage Prince to package them up into a PDF. Once you set it up, building a pdf is just a matter of running a couple of commands. Also, creating a PDF this way gives you a lot more control and customization capabilities than with other methods for creating PDFs. If you know CSS, you can entirely customize the output.
+ +You can see an example of the finished product here:
+ + + +To generate the PDF, browse to the theme’s directory in your terminal and run this script:
+ +. pdf-mydoc.sh
+
This builds a PDF for the documentation in the theme. Look in the pdf folder for the output, and see the “last generated date” to confirm that you generated the PDF.
+ +To build a PDF for the other sample projects, run these commands:
+ +. pdf-product1.sh
+
or
+ +. pdf-product2.sh
+
You can see the details of the script in these files in the theme’s root directory. For example, open pdf-mydoc.sh. It contains the following:
+ +# Note that .sh scripts work only on Mac. If you're on Windows, install Git Bash and use that as your client.
+
+echo 'Kill all Jekyll instances'
+kill -9 $(ps aux | grep '[j]ekyll' | awk '{print $2}')
+clear
+
+echo "Building PDF-friendly HTML site for Mydoc ...";
+bundle exec jekyll serve --detach --config _config.yml,pdfconfigs/config_mydoc_pdf.yml;
+echo "done";
+
+echo "Building the PDF ...";
+prince --javascript --input-list=_site/pdfconfigs/prince-list.txt -o pdf/mydoc.pdf;
+
+echo "Done. Look in the pdf directory to see if it printed successfully."
+
After stopping all Jekyll instances, we build Jekyll using a special configuration file that specifies a unique stylesheet. The build contains a file (prince-list.txt) that contains a list of all pages to be included in the PDF. We feed this list into a Prince command to build the PDF.
+ +The following sections explain more about the setup.
+ +Download and install Prince.
+ +You can install a fully functional trial version. The only difference is that the title page will have a small Prince PDF watermark.
+ +The PDF configuration file will build on the settings in the regular configuration file but will some additional fields. Here’s the configuration file for the mydoc product within this theme. This configuration file is located in the pdfconfigs folder.
+ +destination: _site/
+url: "http://127.0.0.1:4010"
+baseurl: "/mydoc-pdf"
+port: 4010
+output: pdf
+product: mydoc
+print_title: Jekyll theme for documentation — mydoc product
+print_subtitle: version 5.0
+output: pdf
+defaults:
+ -
+ scope:
+ path: ""
+ type: "pages"
+ values:
+ layout: "page_print"
+ comments: true
+ search: true
+
+pdf_sidebar: mydoc_sidebar
+
Note that the default page layout specified by this configuration file is page_print
. This layout strips out all the sections that shouldn’t appear in the print PDF, such as the sidebar and top navigation bar.
Also note that there’s a output: pdf
property in case you want to make some of your content unique to PDF output. For example, you could add conditional logic that checks whether site.output
is pdf
or web
. If it’s pdf
, then include information only for the PDF, and so on. If you’re using nav tabs, you’ll definitely want to create an alternative experience in the PDF.
In the configuration file, customize the values for the print_title
and print_subtitle
that you want. These will appear on the title page of the PDF.
We will access this configure file in the PDF generation script.
+ +There are two template pages in the root directory that are critical to the PDF:
+ +These pages should appear in your sidebar YML file (in this product, mydoc_sidebar.yml):
+ +- title:
+ output: pdf
+ type: frontmatter
+ folderitems:
+ - title:
+ url: /titlepage.html
+ output: pdf
+ type: frontmatter
+ - title:
+ url: /tocpage.html
+ output: pdf
+ type: frontmatter
+
Leave these pages here in your sidebar. (The output: pdf
property means they won’t appear in your online TOC because the conditional logic of the sidebar.html checks whether web
is equal to pdf
or not before including the item in the web version of the content.)
The code in the tocpage.html is mostly identical to that of the sidebar.html page. This is essential for Prince to create the page numbers correctly with cross references.
+ +There’s another file (in the root directory of the theme) that is critical to the PDF generation process: prince-list.txt. This file simply iterates through the items in your sidebar and creates a list of links. Prince will consume the list of links from prince-list.txt and create a running PDF that contains all of the pages listed, with appropriate cross references and styling for them all.
+ +output: web
(rather than output: pdf
) in the list of attributes in your sidebar. The prince-list.txt file that loops through the mydoc_sidebar.yml file to grab the URLs of each page that should appear in the PDF will skip over any items that do not list output: pdf
in the item attributes. For example, you might not want your tag archives to appear in the PDF, but you probably will want to list them in the online help navigation.Open up the css/printstyles.css file and customize what you want for the headers and footers. At the very least, customize the email address (youremail@domain.com
) that appears in the bottom left.
Exactly how the print styling works here is pretty nifty. You don’t need to understand the rest of the content in this section unless you want to customize your PDFs to look different from what I’ve configured. But I’m adding this information here in case you want to understand how to customize the look and feel of the PDF output.
+ +This style creates a page reference for a link:
+ +a[href]::after {
+ content: " (page " target-counter(attr(href), page) ")"
+}
+
You don’t want cross references for any link that doesn’t reference another page, so this style specifies that the content after should be blank:
+ +a[href*="mailto"]::after, a[data-toggle="tooltip"]::after, a[href].noCrossRef::after {
+ content: "";
+}
+
noCrossRef
as a class to the link to avoid having it say “page 0” in the cross reference.This style specifies that after links to web resources, the URL should be inserted instead of the page number:
+ +a[href^="http:"]::after, a[href^="https:"]::after {
+ content: " (" attr(href) ")";
+}
+
This style sets the page margins:
+ +@page {
+ margin: 60pt 90pt 60pt 90pt;
+ font-family: sans-serif;
+ font-style:none;
+ color: gray;
+
+}
+
To set a specific style property for a particular page, you have to name the page. This allows Prince to identify the page.
+ +First you add frontmatter to the page that specifies the type. For the titlepage.html, here’s the frontmatter:
+ +---
+type: title
+---
+
For the tocpage, here’s the frontmatter:
+ +---
+type: frontmatter
+---
+
For the index.html page, we have this type tag (among others):
+ +---
+type: first_page
+---
+
The default_print.html layout will change the class of the body
element based on the type value in the page’s frontmatter:
<body class="{% if page.type == "title"%}title{% elsif page.type == "frontmatter" %}frontmatter{% elsif page.type == "first_page" %}first_page{% endif %} print">
+
Now in the css/printstyles.css file, you can assign a page name based on a specific class:
+ +body.title { page: title }
+
This means that for content inside of body class="title"
, we can style this page in our stylesheet using @page title
.
Here’s how that title page is styled:
+ +@page title {
+ @top-left {
+ content: " ";
+ }
+ @top-right {
+ content: " "
+ }
+ @bottom-right {
+ content: " ";
+ }
+ @bottom-left {
+ content: " ";
+ }
+}
+
As you can see, we don’t have any header or footer content, because it’s the title page.
+ +For the tocpage.html, which has the type: frontmatter
, this is specified in the stylesheet:
body.frontmatter { page: frontmatter }
+body.frontmatter {counter-reset: page 1}
+
+
+@page frontmatter {
+ @top-left {
+ content: prince-script(guideName);
+ }
+ @top-right {
+ content: prince-script(datestamp);
+ }
+ @bottom-right {
+ content: counter(page, lower-roman);
+ }
+ @bottom-left {
+ content: "youremail@domain.com"; }
+}
+
With counter(page, lower-roman)
, we reset the page count to 1 so that the title page doesn’t start the count. Then we also add some header and footer info. The page numbers start counting in lower-roman numerals.
Finally, for the first page (which doesn’t have a specific name), we restart the counting to 1 again and this time use regular numbers.
+ +body.first_page {counter-reset: page 1}
+
+h1 { string-set: doctitle content() }
+
+@page {
+ @top-left {
+ content: string(doctitle);
+ font-size: 11px;
+ font-style: italic;
+ }
+ @top-right {
+ content: prince-script(datestamp);
+ font-size: 11px;
+ }
+
+ @bottom-right {
+ content: "Page " counter(page);
+ font-size: 11px;
+ }
+ @bottom-left {
+ content: prince-script(guideName);
+ font-size: 11px;
+ }
+}
+
You’ll see some other items in there such as prince-script
. This means we’re using JavaScript to run some functions to dynamically generate that content. These JavaScript functions are located in the _includes/head_print.html:
<script>
+ Prince.addScriptFunc("datestamp", function() {
+ return "PDF last generated: September 06, 2018";
+ });
+</script>
+
+<script>
+ Prince.addScriptFunc("guideName", function() {
+ return " User Guide";
+ });
+</script>
+
There are a couple of Prince functions that are default functions from Prince. This gets the heading title of the page:
+ + content: string(doctitle);
+
This gets the current page:
+ + content: "Page " counter(page);
+
Because the theme uses JavaScript in the CSS, you have to add the --javascript
tag in the Prince command (detailed later on this page).
Duplicate the pdf-mydoc.sh file in the root directory and customize it for your specific configuration files.
+ +echo 'Killing all Jekyll instances'
+kill -9 $(ps aux | grep '[j]ekyll' | awk '{print $2}')
+clear
+
+echo "Building PDF-friendly HTML site for Mydoc ...";
+jekyll serve --detach --config _config.yml,pdfconfigs/config_mydoc_pdf.yml;
+echo "done";
+
+echo "Building the PDF ...";
+prince --javascript --input-list=_site/pdfconfigs/prince-list.txt -o pdf/mydoc.pdf;
+echo "done";
+
Note that the first part kills all Jekyll instances. This way you won’t try to serve Jekyll at a port that is already occupied.
+ +The jekyll serve
command serves up the HTML-friendly PDF configurations for our two projects. This web version is where Prince will go to get its content.
The prince script issues a command to the Prince utility. JavaScript is enabled (--javascript
), and we tell it exactly where to find the list of files (--input-list
) — just point to the prince-list.txt file. Then we tell it where and what to output (-o
).
Make sure that the path to the prince-list.txt is correct. For the output directory, I like to output the PDF file into my project’s source (into the files folder). Then when I build the web output, the PDF is included and something I can refer to.
+ +In the PDF configuration file, there’s a section that looks like this:
+ +{% if site.product == "mydoc" %}
+pdf_sidebar: product2_sidebar
+{% endif %}
+
Point to the sidebar you want here.
+ +What this does is allow the prince-list.txt and toc.html files to iterate through the right sidebar. Otherwise, you would need to create a unique prince-list.txt and toc.html file for each separate PDF output you have.
+ +You can add a download button for your PDF using some Bootstrap button code:
+ +<a target="_blank" class="noCrossRef" href="/pdf/mydoc.pdf"><button type="button" class="btn btn-default" aria-label="Left Align"><span class="glyphicon glyphicon-download-alt" aria-hidden="true"></span> PDF Download</button></a>
+
Here’s what that looks like:
+ +<a target=”_blank” class=”noCrossRef” href={{ “pdf/mydoc.pdf”}}”></a>
+ +If you have JavaScript on any of your pages, Prince will note errors in Terminal like this:
+ +error: TypeError: value is not an object
+
However, the PDF will still build.
+ +You need to conditionalize out any JavaScript from your PDF web output before building your PDFs. Make sure that the PDF configuration files have the output: pdf
property.
Then surround the JavaScript with conditional tags like this:
+ +{% raw %}{% unless site.output == "pdf" %}
+javascript content here ...
+{% endunless %}
+
For more detail about using unless
in conditional logic, see Conditional logic. What this code means is “run this code unless this value is the case.”
The theme relies on Bootstrap’s CSS for styling. However, for print media, Bootstrap applies the following style:
+ +@media print{*,:after,:before{color:#000!important;text-shadow:none!important;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important}
+
This is minified, but basically the *
(asterisk) means select all, and applied the color #000 (black). As a result, the Bootstrap style strips out all color from the PDF (for Bootstrap elements).
This is problematic for code snippets that have syntax highlighting. I decided to remove this de-coloring from the print output. I commented out the Bootstrap style:
+ +@media print{*,:after,:before{/*color:#000!important;*/text-shadow:none!important;/*background:0 0!important*/;-webkit-box-shadow:none!important;box-shadow:none!important}
+
If you update Bootrap, make sure you make this edit. (Sorry, admittedly I couldn’t figure out how to simply overwrite the *
selector with a later style.)
I did, however, remove the color from the alerts and lighten the background shading for pre
elements. The printstyles.css has this setting.
You can create a glossary for your content. First create your glossary items in a data file such as glossary.yml.
+ +Then create a page and use definition list formatting, like this:
+ +Here’s the code:
+ +fractious
+: {{site.data.glossary.fractious}}
+
+gratuitous
+: {{site.data.glossary.gratuitous}}
+
+haughty
+: {{site.data.glossary.haughty}}
+
+gratuitous
+: {{site.data.glossary.gratuitous}}
+
+impertinent
+: {{site.data.glossary.intrepid}}
+
The glossary works well as a link in the top navigation bar.
+ +You can also change the definition list (dl
) class to dl-horizontal
. This is a Bootstrap specific class. If you do, the styling looks like this:
For this type of list, you must use HTML. The list would then look like this:
+ +<dl class="dl-horizontal">
+
+<dt id="fractious">fractious</dt>
+<dd>{{site.data.glossary.fractious}}</dd>
+
+<dt id="gratuitous">gratuitous</dt>
+<dd>{{site.data.glossary.gratuitous}}</dd>
+
+<dt id="haughty">haughty</dt>
+<dd>{{site.data.glossary.haughty}}</dd>
+
+<dt id="benchmark_id">gratuitous</dt>
+<dd>{{site.data.glossary.gratuitous}}</dd>
+
+<dt id="impertinent">impertinent</dt>
+<dd>{{site.data.glossary.impertinent}}</dd>
+
+<dt id="intrepid">intrepid</dt>
+<dd>{{site.data.glossary.intrepid}}</dd>
+
+</dl>
+
If you squish your screen small enough, at a certain breakpoint this style reverts to the regular dl
class.
Although I like the side-by-side view for shorter definitions, I found it problematic with longer definitions.
+ + + + + + + + + + + + + + +You can create a help API that developers can use to pull in content.
+ +For the full code demo, see the notes in the Tooltips file.
+ +In this demo, the popovers pull in and display content from the information in a tooltips.json file located in the same directory.
+ +Instead of placing the JSON source in the same directory, you could also host the JSON file on another site.
+ +Additionally, instead of tooltip popovers, you could also print content directly to the page. Basically, whatever you can stuff into a JSON file, developers can integrate it onto a page.
+ +Here’s a diagram showing the basic idea of the help API:
+ + + +Is this really an API? Well, sort of. The help content is pushed out into a JSON file that other websites and applications can easily consume. The endpoints don’t deliver different data based on parameters added to a URL. But the overall concept is similar to an API: you have a client requesting resources from a server.
+ +Note that in this scenario, the help is openly accessible on the web. If you have a private system, it’s more complicated.
+ +To deliver help this way using Jekyll, follow the steps in each of the sections below.
+ +A collection is another content type that extends Jekyll beyond the use of pages and posts. Call the collection “tooltips.”
+ +Add the following information to your configuration file to declare your collection:
+ +collections:
+ tooltips:
+ output: false
+
In your Jekyll project’s root directory, create a new folder called “_tooltips” and put every page that you want to be part of that tooltips collection inside that folder.
+ +In Jekyll, folders that begin with an underscore (“_”) aren’t included in the output. However, in the collection information that you add to your configuration file, if you change output
to true
, the tooltips folder will appear in the output, and each page inside tooltips will be generated. You most likely don’t want this for tooltips (you just want the JSON file), so make the output
setting false
.
Inside the _data folder, create a YAML file called something like definitions.yml. Add the definitions for each of your tooltips here like this:
+ +basketball: "Basketball is a sport involving two teams of five players each competing to put a ball through a small circular rim 10 feet above the ground. Basketball requires players to be in top physical condition, since they spend most of the game running back and forth along a 94-foot-long floor."
+
The definition of basketball is stored this data file so that you can re-use it in other parts of the help as well. You’ll likely want the definition to appear not only in the tooltip in the UI, but also in the regular documentation as well.
+ +Create pages inside your new tooltips collection (that is, inside the _tooltips folder). Each page needs to have a unique id
in the frontmatter as well as a product
. Then reference the definition you created in the definitions.yml file.
Here’s an example:
+ +
+---
+doc_id: basketball
+product: mydoc
+---
+
+{{site.data.definitions.basketball}}
+
(Note: Avoid using id
, as it seems to generate out as /tooltips/basketball
instead of just `basketball.)
You need to create a separate file for each tooltip you want to deliver.
+ +The product attribute is required in the frontmatter to distinguish the tooltips produced here from the tooltips for other products in the same _tooltips folder. When creating the JSON file, Jekyll will iterate through all the pages inside _tooltips, regardless of any subfolders included here.
+ +Now it’s time to create a JSON file with Liquid code that iterates through our tooltip collection and grabs the information from each tooltip file.
+ +Inside your project’s pages directory (e.g., mydoc), add a file called “tooltips.json.” (You can use whatever name you want.) Add the following to your JSON file:
+ +---
+layout: null
+search: exclude
+---
+
+{
+"entries":
+[
+{% for page in site.tooltips %}
+{
+"doc_id": "{{ page.doc_id }}",
+"body": "{{ page.content | strip_newlines | replace: '\', '\\\\' | replace: '"', '\\"' }}"
+} {% unless forloop.last %},{% endunless %}
+{% endfor %}
+]
+}
+
+
This code will loop through all pages in the tooltips collection and insert the id
and body
into key-value pairs for the JSON code. Here’s an example of what that looks like after it’s processed by Jekyll in the site build:
{
+ "entries": [
+ {
+ "doc_id": "baseball",
+ "body": "Baseball is considered America's pasttime sport, though that may be more of a historical term than a current one. There's a lot more excitement about football than baseball. A baseball game is somewhat of a snooze to watch, for the most part."
+ },
+ {
+ "doc_id": "basketball",
+ "body": "Basketball is a sport involving two teams of five players each competing to put a ball through a small circular rim 10 feet above the ground. Basketball requires players to be in top physical condition, since they spend most of the game running back and forth along a 94-foot-long floor."
+ },
+ {
+ "doc_id": "football",
+ "body": "No doubt the most fun sport to watch, football also manages to accrue the most injuries with the players. From concussions to blown knees, football players have short sport lives."
+ },
+ {
+ "doc_id": "soccer",
+ "body": "If there's one sport that dominates the world landscape, it's soccer. However, US soccer fans are few and far between. Apart from the popularity of soccer during the World Cup, most people don't even know the name of the professional soccer organization in their area."
+ }
+ ]
+}
+
You can also view the same JSON file here: tooltips.json.
+ +You can add different fields depending on how you want the JSON to be structured. Here we just have to fields: doc_id
and body
. And the JSON is looking just in the tooltips collection that we created.
Note that you can create different JSON files that specialize in different content. For example, suppose you have some getting started information. You could put that into a different JSON file. Using the same structure, you might add an if
tag that checks whether the page has frontmatter that says type: getting_started
or something. Or you could put the content into separate collection entirely (different from tooltips).
By chunking up your JSON files, you can provide a quicker lookup. (I’m not sure how big the JSON file can be before you experience any latency with the jQuery lookup.)
+ +When you build your site, Jekyll will iterate through every page in your _tooltips folder and put the page id and body into this format. In the output, look for the JSON file in the tooltips.json file. You’ll see that Jekyll has populated it with content. This is because of the triple hyphen lines in the JSON file — this instructs Jekyll to process the file.
+ +You can simply deliver the JSON file to devs to add to the project. But if you have the option, it’s best to keep the JSON file stored in your own help system. Assuming you have the ability to update your content on the fly, this will give you completely control over the tooltips without being tied to a specific release window.
+ +When people make calls to your site from other domains, you must allow them access to get the content. To do this, you have to enable something called CORS (cross origin resource sharing) within the server where your help resides.
+ +In other words, people are going to be executing calls to reach into your site and grab your content. Just like the door on your house, you have to unlock it so people can get in. Enabling CORS is unlocking it.
+ +How you enable CORS depends on the type of server.
+ +If your server setup allows htaccess files to override general server permissions, create an .htaccess file and add the following:
+ +Header set Access-Control-Allow-Origin "*"
+
Store this in the same directory as your project. This is what I’ve done in a directory on my web host (bluehost.com). Inside http://idratherassets.com/wp-content/apidemos/, I uploaded a file called “.htaccess” with the preceding code.
+ +After I uploaded it, I renamed it to .htaccess, right-clicked the file and set the permissions to 774.
+ +To test whether your server permissions are set correctly, open a terminal and run the following curl command pointing to your tooltips.json file:
+ +curl -I http://idratherassets.com/wp-content/apidemos/tooltips.json
+
The -I
command tells cURL to return the request header only.
If the server permissions are set correctly, you should see the following line somewhere in the response:
+ +Access-Control-Allow-Origin: *
+
If you don’t see this response, CORS isn’t allowed for the file.
+ +If you have an AWS S3 bucket, you can supposedly add a CORS configuration to the bucket permissions. Log into AWS S3 and click your bucket. On the right, in the Permissions section, click Add CORS Configuration. In that space, add the following policy:
+ +<CORSConfiguration>
+ <CORSRule>
+ <AllowedOrigin>*</AllowedOrigin>
+ <AllowedMethod>GET</AllowedMethod>
+ </CORSRule>
+</CORSConfiguration>
+
(Although this should work, in my experiment it doesn’t. And I’m not sure why…)
+ +In other server setups, you may need to edit one of your Apache configuration files. See Enable CORS or search online for ways to allow CORS for your server.
+ +If you don’t have CORS enabled, users will see a CORS error/warning message in the console of the page making the request.
+ +Developers can access the help using the .get
method from jQuery, among other methods. Here’s an example of how to get tooltips for basketball, baseball, football, and soccer:
var url = "tooltips.json";
+
+ $.get( url, function( data ) {
+
+ /* Bootstrap popover text is defined inside a data-content attribute inside an element. That's
+ why I'm using attr here. If you just want to insert content on the page, use append and remove the data-content argument from the parentheses.*/
+
+ $.each(data.entries, function(i, page) {
+ if (page.doc_id == "basketball") {
+ $( "#basketball" ).attr( "data-content", page.body );
+ }
+
+ if (page.doc_id == "baseball") {
+ $( "#baseball" ).attr( "data-content", page.body );
+ }
+ if (page.doc_id == "football") {
+ $( "#football" ).attr( "data-content", page.body );
+ }
+
+ if (page.doc_id == "soccer") {
+ $( "#soccer" ).attr( "data-content", page.body );
+ }
+
+
+ });
+ });
+
View the tooltip demo for a demonstration. See the source code for full code details.
+ +The url
in the demo is relative, but you could equally point it to an absolute path on a remote host assuming CORS is enabled on the host.
The each
method looks through all the JSON content to find the item whose page.id
is equal to basketball
. It then looks for an element on the page named #basketball
and adds a data-content
attribute to that element.
Why data-content
? Well, in this case, I’m using Bootstrap popovers to display the tooltip content. The data-content
attribute is how Bootstrap injects popovers.
Here’s the section on the page where the popover is inserted:
+ +<p>Basketball <span class="glyphicon glyphicon-info-sign" id="basketball" data-toggle="popover"></span></p>
+
Notice that I just have id="basketball"
added to this popover element. Developers merely need to add a unique ID to each tooltip they want to pull in the help content. Either you tell developers the unique ID they should add, or ask them what IDs they added (or just tell them to use an ID that matches the field’s name).
In order to use jQuery and Bootstrap, you’ll need to add the appropriate references in the head tags of your page:
+ +<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
+<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
+<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
+
+<script type="text/javascript">
+$(document).ready(function(){
+ $('[data-toggle="popover"]').popover({
+ placement : 'right',
+ trigger: 'hover',
+ html: true
+ });
+
Again, see the Tooltip Demo for a demo of the full code.
+ +Note that even though you reference a Bootstrap JS script, Bootstrap’s popovers require you to initialize them using the above code as well — they aren’t turned on by default.
+ +View the source code of the tooltip demo for the full comments.
+ +You might also want to insert the same content into different parts of your help site. For example, if you have tooltips providing definitions for fields, you’ll probably want to create a page in your help that lists those same definitions.
+ +You could use the same method developers use to pull help content into their applications. But it will probably be easier to simply use Jekyll’s tags for doing it.
+ +Here’s how you would reuse the content:
+ +<h2>Reuse Demo</h2>
+
+
+<table>
+<thead>
+<tr>
+<th>Sport</th>
+<th>Comments</th>
+</tr>
+</thead>
+<tbody>
+
+<tr>
+<td>Basketball</td>
+<td>{{site.data.definitions.basketball}}</td>
+</tr>
+
+<tr>
+<td>Baseball</td>
+<td>{{site.data.definitions.baseball}}</td>
+</tr>
+
+<tr>
+<td>Football</td>
+<td>{{site.data.definitions.football}}</td>
+</tr>
+
+<tr>
+<td>Soccer</td>
+<td>{{site.data.definitions.soccer}}</td>
+</tr>
+</tbody>
+</table>
+
And here’s the code:
+ +Sport | +Comments | +
---|---|
Basketball | +Basketball is a sport involving two teams of five players each competing to put a ball through a small circular rim 10 feet above the ground. Basketball requires players to be in top physical condition, since they spend most of the game running back and forth along a 94-foot-long floor. | +
Baseball | +Baseball is considered America's pasttime sport, though that may be more of a historical term than a current one. There's a lot more excitement about football than baseball. A baseball game is somewhat of a snooze to watch, for the most part. | +
Football | +No doubt the most fun sport to watch, football also manages to accrue the most injuries with the players. From concussions to blown knees, football players have short sport lives. | +
Soccer | +If there's one sport that dominates the world landscape, it's soccer. However, US soccer fans are few and far between. Apart from the popularity of soccer during the World Cup, most people don't even know the name of the professional soccer organization in their area. | +
Now you have both documentation and UI tooltips generated from the same definitions file.
+ + + + + + + + + + + + + + +When linking to an external site, use Markdown formatting because it’s simplest:
+ +[Google](http://google.com)
+
When linking to internal pages, you can manually link to the pages like this:
+ +[Icons](mydoc_icons.html)
+
However, if you change the file name, you’ll have to update all of your links. It’s much easier to use Automated links, as described in the next section.
+ +This method for automated links creates a master list of all links in a Markdown reference format based on entries in your sidebar table of contents.
+ +With this Automated links method, make sure all your pages are referenced in a sidebar or topnav data file (inside _data > sidebars). If they’re not in a sidebar or top nav (such as links to headings on a page), list them in the other.yml
file (which is in the _data/sidebars folder).
The links.html file (in _includes) will iterate through all your sidebars and create a list of reference-style markdown links based on the url
properties in the sidebar items.
permalink
property in the frontmatter. The permalink
property must match the file name. For example, if the file name is somefile.html
, your permalink property would be somefile.html
. See Pages for more details.To implement managed links:
+ +In your _config.yml file, list each sidebar in the sidebars
property — including the other.yml file too:
sidebars:
+- home_sidebar
+- mydoc_sidebar
+- product1_sidebar
+- product2_sidebar
+- other
+
At the bottom of each topic where you plan to include links, include the links.html file:
+ +{% include links.html %}
+
To link to a topic, use reference-style Markdown links, with the referent using the file name (without the file extension). For example:
+ +See the [Icon][mydoc_icons] file.
+
Here’s the result:
+ +See the Icon file.
+ +If the link doesn’t render, check to make sure the page is correctly listed in the sidebar.
+If you’re linking to the specific heading from another page, first give the heading an ID:
+ +## Some heading {#someheading}
+
Then add a property into the other.yml file in your _data/sidebars folder:
+ + - title: Some link bookmark
+ url: /mydoc_pages.html#someIdTag
+
And reference it like this:
+ +This is [Some link][mydoc_pages.html#someIdTag].
+
Result:
+ +This is Some link.
+ +It’s a little strange having the .html#
in a reference like this, but it works.
The theme has two font icon sets integrated: Font Awesome and Glyphicons Halflings. The latter is part of Bootstrap, while the former is independent. Font icons allow you to insert icons drawn as vectors from a CDN (so you don’t have any local images on your own site).
+ +When you link to an external site, like Jekyll, an icon appears after the link. If you want to remove this icon, comment out this style in css/customstyles.css.
+ +/* this part adds an icon after external links, using FontAwesome*/
+a[href^="http://"]:after, a[href^="https://"]:after {
+ content: "\f08e";
+ font-family: FontAwesome;
+ font-weight: normal;
+ font-style: normal;
+ display: inline-block;
+ text-decoration: none;
+ padding-left: 3px;
+}
+
Go to the Font Awesome library to see the available icons.
+ +The Font Awesome icons allow you to adjust their size by simply adding fa-2x
, fa-3x
and so forth as a class to the icon to adjust their size to two times or three times the original size. As vector icons, they scale crisply at any size.
Here’s an example of how to scale up a camera icon:
+ +<i class="fa fa-camera-retro"></i> normal size (1x)
+<i class="fa fa-camera-retro fa-lg"></i> fa-lg
+<i class="fa fa-camera-retro fa-2x"></i> fa-2x
+<i class="fa fa-camera-retro fa-3x"></i> fa-3x
+<i class="fa fa-camera-retro fa-4x"></i> fa-4x
+<i class="fa fa-camera-retro fa-5x"></i> fa-5x
+
Here’s what they render to:
+ +1x + fa-lg + fa-2x + fa-3x + fa-4x + fa-5x
+ +With Font Awesome, you always use the i
tag with the appropriate class. You also implement fa
as a base class first. You can use font awesome icons inside other elements. Here I’m using a Font Awesome class inside a Bootstrap alert:
<div class="alert alert-danger" role="alert"><i class="fa fa-exclamation-circle"></i> <b>Warning: </b>This is a special warning message.
+
Here’s the result:
+ +The notes, tips, warnings, etc., are pre-coded with Font Awesome and stored in the alerts.yml file. That file includes the following:
+ +tip: '<div class="alert alert-success" role="alert"><i class="fa fa-check-square-o"></i> <b>Tip: </b>'
+note: '<div class="alert alert-info" role="alert"><i class="fa fa-info-circle"></i> <b>Note: </b>'
+important: '<div class="alert alert-warning" role="alert"><i class="fa fa-warning"></i> <b>Important: </b>'
+warning: '<div class="alert alert-danger" role="alert"><i class="fa fa-exclamation-circle"></i> <b>Warning: </b>'
+end: '</div>'
+
+callout_danger: '<div class="bs-callout bs-callout-danger">'
+callout_default: '<div class="bs-callout bs-callout-default">'
+callout_primary: '<div class="bs-callout bs-callout-primary">'
+callout_success: '<div class="bs-callout bs-callout-success">'
+callout_info: '<div class="bs-callout bs-callout-info">'
+callout_warning: '<div class="bs-callout bs-callout-warning">'
+
+hr_faded: '<hr class="faded"/>'
+hr_shaded: '<hr class="shaded"/>'
+
This means you can insert a tip, note, warning, or important alert simply by using these tags.
+ +{% include note.html content="Add your note here." %}
+
{% include tip.html content="Add your tip here." %}
+
{% include important.html content="Add your important info here." %}
+
{% include warning.html content="Add your warning here." %}
+
Here’s the result:
+ +The color scheme is the default colors from Bootstrap. You can modify the icons or colors as needed.
+ +You can innovate with your own combinations. Here’s a similar approach with a file download icon:
+ +<div class="alert alert-success" role="alert"><i class="fa fa-download fa-lg"></i> This is a special tip about some file to download....</div>
+
And the result:
+ +Grab the right class name from the Font Awesome library and then implement it by following the pattern shown previously.
+ +If you want to make your fonts even larger than the 5x style, add a custom style to your stylesheet like this:
+ +.fa-10x{font-size:1700%;}
+
Then any element with the attribute fa-10x
will be enlarged 1700%.
Glyphicons work similarly to Font Awesome. Go to the Glyphicons library to see the icons available.
+ +Although the Glyphicon Halflings library doesn’t provide the scalable classes like Font Awesome, there’s a StackOverflow trick to make the icons behave in a similar way. This theme’s stylesheet (customstyles.css) includes the following to the stylesheet:
+ +.gi-2x{font-size: 2em;}
+.gi-3x{font-size: 3em;}
+.gi-4x{font-size: 4em;}
+.gi-5x{font-size: 5em;}
+
Now you just add gi-5x
or whatever to change the size of the font icon:
<span class="glyphicon glyphicon-globe gi-5x"></span>
+
And here’s the result:
+ ++ +
Glypicons use the span
element instead of i
to attach their classes.
Here’s another example:
+ +<span class="glyphicon glyphicon-download"></span>
+
+ +
And magnified:
+ +<span class="glyphicon glyphicon-download gi-3x"></span>
+
+ +
You can also put glyphicons inside other elements:
+ +<div class="alert alert-danger" role="alert">
+ <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
+ <b>Error:</b> Enter a valid email address
+</div>
+
The previously shown alerts might be fine for short messages, but with longer notes, the solid color takes up a bit of space. In this theme, you also have the option of using callouts, which are pretty common in Bootstrap’s documentation but surprisingly not offered as an explicit element. Their styles have been copied into this theme, in a way similar to the alerts:
+ +<div class="bs-callout bs-callout-info">
+ This is a special info message. This is a special info message. This is a special info message. This is a special info message. This is a special info message. This is a special info message. This is a special info message. This is a special info message. This is a special info message. </div>
+
And here’s the shortcode:
+ +{{site.data.alerts.callout_info}This is a special callout information message.{{site.data.alerts.end}}
+
+
Here’s the result:
+ +You can use any of the following:
+ +{{site.data.alerts.callout_default}}
+{{site.data.alerts.callout_primary}}
+{{site.data.alerts.callout_success}}
+{{site.data.alerts.callout_info}}
+{{site.data.alerts.callout_warning}}
+
The only difference is the color of the left bar.
+ +Callouts are explained in a bit more detail in Alerts.
+ + + + + + + + + + + + + + +Instead of using Markdown or HTML syntax directly in your page for images, the syntax for images has been extracted out into an image include that allows you to pass the parameters you need. Include the image.html like this:
+ +
+{% include image.html file="jekyll.png" url="http://jekyllrb.com" alt="Jekyll" caption="This is a sample caption" %}
+
+
The available include properties are as follows:
+ +Property | +description | +
---|---|
file | +The name of the file. Store it in the /images folder. If you want to organize your images in subfolders, reference the subfolder path here, like this: mysubfolder/jekyllrb.png |
+
url | +Whether to link the image to a URL | +
alt | +Alternative image text for accessibility and SEO | +
caption | +A caption for the image | +
max-width | +a maximum width for the image (in pixels). Just specify the number, not px. | +
The properties of the include get populated into the image.html template.
+ +Here’s the result:
+ + + +For inline images, such as with a button that you want to appear inline with text, use the inline_image.html include, like this:
+ +Click the **Android SDK Manager** button {% include inline_image.html
+file="androidsdkmanagericon.png" alt="SDK button" %}
+
Click the Android SDK Manager button
+ +The inline_image.html include properties are as follows:
+ +Property | +description | +
---|---|
file | +The name of the file | +
type | +The type of file (png, svg, and so on) | +
alt | +Alternative image text for accessibility and SEO | +
You can also embed SVG graphics. If you use SVG, you need to use the HTML syntax so that you can define a width/container for the graphic. Here’s a sample embed:
+ +{% include image.html file="helpapi.svg" url="http://idratherbewriting.com/documentation-theme-jekyll/mydoc_help_api/" alt="Building a Help API" caption="A help API provides a JSON file at a web URL with content that can be pulled into different targets" max-width="600" %}
+
Here’s the result:
+ + + +The stylesheet even handles SVG display in IE 9 and earlier through the following style (based on this gist):
+ +/*
+ * Let's target IE to respect aspect ratios and sizes for img tags containing SVG files
+ *
+ * [1] IE9
+ * [2] IE10+
+ */
+/* 1 */
+.ie9 img[src$=".svg"] {
+ width: 100%;
+}
+/* 2 */
+@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {
+ img[src$=".svg"] {
+ width: 100%;
+ }
+}
+
Also, if you’re working with SVG graphics, note that Firefox does not support SVG fonts. In Illustrator, when you do a Save As with your AI file and choose SVG, to preserve your fonts, in the Font section, select “Convert to outline” as the Type (don’t choose SVG in the Font section).
+ +Also, remove the check box for “Use textpath element for text on a path”. And select “Embed” rather than “Link.” The following screenshot shows the settings I use. Your graphics will look great in Firefox.
+ + + + + + + + + + + + + + + + +Ruby and RubyGems are usually installed by default on Macs. Open your Terminal and type which ruby
and which gem
to confirm that you have Ruby and Rubygems. You should get a response indicating the location of Ruby and Rubygems.
If you get responses that look like this:
+ +/usr/local/bin/ruby
+
and
+ +/usr/local/bin/gem
+
Great! Skip down to the Bundler section.
+ +However, if your location is something like /Users/MacBookPro/.rvm/rubies/ruby-2.2.1/bin/gem
, which points to your system location of Rubygems, you will likely run into permissions errors when trying to get a gem. A sample permissions error (triggered when you try to install the jekyll gem such as gem install jekyll
) might look like this for Rubygems:
>ERROR: While executing gem ... (Gem::FilePermissionError)
+ You don't have write permissions for the /Library/Ruby/Gems/2.0.0 directory.
+
Instead of changing the write permissions on your operating system’s version of Ruby and Rubygems (which could pose security issues), you can install another instance of Ruby (one that is writable) to get around this.
+ +Homebrew is a package manager for the Mac, and you can use it to install an alternative instance of Ruby code. To install Homebrew, run this command:
+ +/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
+
If you already had Homebrew installed on your computer, be sure to update it:
+ +brew update
+
Now use Homebrew to install Ruby:
+ +brew install ruby
+
Log out of terminal, and then then log back in.
+ +When you type which ruby
and which gem
, you should get responses like this:
/usr/local/bin/ruby
+
And this:
+ +/usr/local/bin/gem
+
Now Ruby and Rubygems are installed under your username, so these directories are writeable.
+ +Note that if you don’t see these paths, try restarting your computer or try installing rbenv, which is a Ruby version management tool. If you still have issues getting a writeable version of Ruby, you need to resolve them before installing Bundler.
+ +At this point you should have a writeable version of Ruby and Rubygem on your machine.
+ +Now use gem
to install Jekyll:
gem install jekyll
+
You can now use Jekyll to create new Jekyll sites following the quick-start instructions on Jekyllrb.com.
+ +Some Jekyll themes will require certain Ruby gem dependencies. These dependencies are stored in something called a Gemfile, which is packaged with the Jekyll theme. You can install these dependencies through Bundler. (Although you don’t need to install Bundler for this Documentation theme, it’s a good idea to do so.)
+ +Bundler is a package manager for RubyGems. You can use it to get all the gems (or Ruby plugins) that you need for your Jekyll project.
+ +You install Bundler by using the gem command with RubyGems:
+ +gem install bundler
+
If you’re prompted to switch to superuser mode (sudo
) to get the correct permissions to install Bundler in that directory, avoid doing this. All other applications that need to use Bundler will likely not have the needed permissions to run.
Bundler goes out and retreives all the gems that are specified in a Jekyll project’s Gemfile. If you have a gem that depends on other gems to work, Bundler will go out and retrieve all of the dependencies as well. (To learn more about Bundler, see About Ruby Gems.
+ +The vanilla Jekyll site you create through jekyll new my-awesome-site
doesn’t have a Gemfile, but many other themes (including the Documentation theme for Jekyll) do have a Gemfile.
jekyll serve
/
at the end.)After making an edit, Jekyll auto-rebuilds the site. If you have the Gemfile in the theme with the github-pages gem, you may see the following error:
+ +GitHub Metadata: No GitHub API authentication could be found. Some fields may be missing or have incorrect data.
+
If you see this error, you will need to take some additional steps to resolve it. (Note that this error only appears if you have the github-pages gem in your gemfile.) The resolution involves adding a Github token and a cert file.
+ +To resolve the “No Github API authentication” error:
+ +Open the .bash_profile file in your user directory:
+ +open ~/.bash_profile
+
The file will open in your default terminal editor. If you don’t have a .bash_profile file, you can just create a file with this name. Note that files that begin with .
are hidden, so if you’re looking in your user directory for the file, use ls -a
to see hidden files.
In your .bash_profile file, reference your token as a system variable like this:
+ +export JEKYLL_GITHUB_TOKEN=abc123abc123abc123abc123abc123abc123abc123abc123
+
Replace abc123...
with your own token that you generated in step 1.
Open your .bash_profile file again and add this line, replacing Users/johndoe/projects/
with the path to your cacert.pem file:
export SSL_CERT_FILE=/Users/johndoe/projects/cacert.pem
+
Browse to your jekyll project and run bundle exec jekyll serve
. Make an edit to a file and observe that no Github API errors appear when Jekyll rebuilds the project.
First you must install Ruby because Jekyll is a Ruby-based program and needs Ruby to run.
+ +Some extensions Jekyll uses require you to natively build the code using the Ruby Development Kit.
+ +Browse to the RubyDevKit location on your C drive using your Command Line Prompt.
+ +To see the contents of your current directory, type dir
. To move into a directory, type cd foldername
, where “foldername” is the name of the folder you want to enter. To move up a directory, type cd ../
one or more times depending on how many levels you want to move up. To move into your user’s directory, type /users
. The /
at the beginning of the path automatically starts you at the root.
ruby dk.rb init
ruby dk.rb install
If you get stuck, see the official instructions for installing Ruby Dev Kit.
+ +At this point you should have Ruby and Rubygem on your machine.
+ +Now use gem
to install Jekyll:
gem install jekyll
+
You can now use Jekyll to create new Jekyll sites following the quick-start instructions on Jekyllrb.com.
+ +Some Jekyll themes will require certain Ruby gem dependencies. These dependencies are stored in something called a Gemfile, which is packaged with the Jekyll theme. You can install these dependencies through Bundler. (Although you don’t need to install Bundler for this Documentation theme, it’s a good idea to do so.)
+ +Bundler is a package manager for RubyGems. You can use it to get all the gems (or Ruby plugins) that you need for your Jekyll project.
+ +You install Bundler by using the gem command with RubyGems:
+ +gem install bundler
Initialize Bundler: bundle init
This will create a new Gemfile.
+Open the Gemfile in a text editor.
+ +Typically you can open files from the Command Prompt by just typing the filename, but because Gemfile doesn’t have a file extension, no program will automatically open it. You may need to use your File Explorer and browse to the directory, and then open the Gemfile in a text editor such as Notepad.
+Remove the existing contents. Then paste in the following:
+ +source "https://rubygems.org"
+
+gem 'wdm'
+gem 'jekyll'
+
The wdm gem allows for the polling of the directory and rebuilding of the Jekyll site when you make changes. This gem is needed for Windows users, not Mac users.
+Type bundle install
.
Bundle retrieves all the needed gems and gem dependencies and downloads them to your computer. At this time, Bundle also takes a snapshot of all the gems used in your project and creates a Gemfile.lock file to store this information.
+Although you can use the default command prompt with Windows, it’s recommended that you use Git Bash instead. The Git Bash client will allow you to run shell scripts and execute other Unix commands.
+ +jekyll serve
Go to the preview address in the browser. (Make sure you include the /
at the end.)
Unfortunately, the Command Prompt doesn’t allow you to easily copy and paste the URL, so you’ll have to type it manually.
+After making an edit, Jekyll auto-rebuilds the site. If you have the Gemfile in the theme with the github-pages gem, you may see the following error:
+ +GitHub Metadata: No GitHub API authentication could be found. Some fields may be missing or have incorrect data.
+
If so, you will need to take some additional steps to resolve it. (Note that this error only appears if you have the github-pages gem in your gemfile.) The resolution involves adding a Github token and a cert file.
+ +See this post on Knight Codes for instructions on how to fix the error. You basically generate a personal token on Github and set it as a system variable. You also download a certification file and set it as a system variable. This resolves the issue.
+ + + + + + + + + + + + + + +This site provides documentation, training, and other notes for the Jekyll Documentation theme. There’s a lot of information about how to do a variety of things here, and it’s not all unique to this theme. But by and large, understanding how to do things in Jekyll depends on how your theme is coded. As a result, these additional details are provided.
+ +The instructions here are geared towards technical writers working on documentation. You may have a team of one or more technical writers working on documentation for multiple projects. You can use this same theme to author all of your documentation for each of your products. The theme is built to accommodate documentation for multiple products on the same site.
+ +Some of the more prominent features of this theme include the following:
+ +To get started, see Getting Started.
+ + + + + + + + + + + + + + +When you’re working with tech docs, a lot of times you have builds that push files onto different servers, or that build the content for different environments. It can be a hassle to type out these commands each time. Instead, it’s easier to configure iTerm with profiles that initiate the scripts.
+ +Doc theme -- designers
.In the Send text at start field, type the command for the build script, such as this:
+ +JEKYLL_ENV=production jekyll serve
+
Leave the Login shell option selected.
+Here’s an example:
+ + + +Here’s the sample knowledge-base style layout:
+ +If you don’t want to link to a tag archive index, but instead want to list all pages that have a certain tag, you could use this code:
+ +Getting started pages:
+<ul>
+{% assign sorted_pages = site.pages | sort: 'title' %}
+{% for page in sorted_pages %}
+{% for tag in page.tags %}
+{% if tag == "getting_started" %}
+<li><a href="{{ page.url | remove: "/" }}">{{page.title}}</a></li>
+{% endif %}
+{% endfor %}
+{% endfor %}
+</ul>
+
Here’s the result:
+ +Getting started pages:
+ +Labels might come in handy for adding button-like tags next to elements, such as POST, DELETE, UPDATE methods for endpoints. You can use any classes from Bootstrap in your content.
+ +<span class="label label-default">Default</span>
+<span class="label label-primary">Primary</span>
+<span class="label label-success">Success</span>
+<span class="label label-info">Info</span>
+<span class="label label-warning">Warning</span>
+<span class="label label-danger">Danger</span>
+
Default +Primary +Success +Info +Warning +Danger
+ +You can have a label appear within a heading simply by including the span tag in the heading. However, you can’t mix Markdown syntax with HTML, so you’d have to hard-code the heading ID for the auto-TOC to work.
+ + + + + + + + + + + + + + +This is a bulleted list:
+ +* first item
+* second item
+* third item
+
Result:
+ +This is a simple numbered list:
+ +1. First item.
+1. Second item.
+1. Third item.
+
Result:
+ +You can use whatever numbers you want — when the Markdown filter processes the content, it will assign the correct numbers to the list items.
+ +Here’s a more complex list:
+ +1. Sample first item.
+
+ * sub-bullet one
+ * sub-bullet two
+
+2. Continuing the list
+
+ 1. sub-list numbered one
+ 2. sub-list numbered two
+
+3. Another list item.
+
Result:
+ +Sample first item.
+ +Continuing the list
+ +Another list item.
+Here’s a list with some intercepting text:
+ +1. Sample first item.
+
+ This is a result statement that talks about something....
+
+2. Continuing the list
+
+ <div markdown="span" class="alert alert-info" role="alert"><i class="fa fa-info-circle"></i> <b>Note:</b> Remember to do this. If you have "quotes", you must escape them.</div>
+
+
+ Here's a list in here:
+
+ * first item
+ * second item
+
+3. Another list item.
+
+ ```js
+ function alert("hello");
+ ```
+
+4. Another item.
+
Result:
+ +Sample first item.
+ +This is a result statement that talks about something….
+Continuing the list
+ +Here’s a list in here:
+ +Another list item.
+ +function alert("hello");
+
Another item.
+The key principle is to line up the first character after the dot following the number:
+ + + +For the sake of simplicity, use two spaces after the dot for numbers 1 through 9. Use one space for numbers 10 and up. If any part of your list doesn’t align symmetrically on this left edge, the list will not render correctly. Also note that this is characteristic of kramdown-flavored Markdown and may not yield the same results in other Markdown flavors.
+ + + + + + + + + + + + + +Navtabs are particularly useful for scenarios where you want to show a variety of options, such as code samples for Java, .NET, or PHP, on the same page.
+ +While you could resort to single-source publishing to provide different outputs for each unique programming language or role, you could also use navtabs to allow users to select the content you want.
+ +Navtabs are better for SEO since you avoid duplicate content and drive users to the same page.
+ +The following is a demo of a navtab. Refresh your page to see the tab you selected remain active.
+ + +Praesent sit amet fermentum leo. Aliquam feugiat,
+ +++Proin venenatis leo id urna cursus blandit. Vivamus sit amet hendrerit metus.
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam vel sollicitudin felis. Sed eu arcu sed ipsum semper luctus eu a tortor. Suspendisse id leo eu metus laoreet varius. Mauris consequat accumsan ex, a iaculis metus fermentum a. Praesent sit amet fermentum leo. Aliquam feugiat, nibh in u ltrices mattis, felis ipsum venenatis metus, vel vehicula libero mauris a enim. Sed placerat est ac lectus vestibulum tempor. Quisque ut condimentum massa. Proin venenatis leo id urna cursus blandit. Vivamus sit amet hendrerit metus.about
Vel vehicula libero mauris a enim. Sed placerat est ac lectus vestibulum tempor. Quisque ut condimentum massa. Proin venenatis leo id urna cursus blandit. Vivamus sit amet hendrerit metus.
+Here’s the code for the above (with the filler text abbreviated):
+ +<ul id="profileTabs" class="nav nav-tabs">
+ <li class="active"><a href="#profile" data-toggle="tab">Profile</a></li>
+ <li><a href="#about" data-toggle="tab">About</a></li>
+ <li><a href="#match" data-toggle="tab">Match</a></li>
+</ul>
+ <div class="tab-content">
+<div role="tabpanel" class="tab-pane active" id="profile">
+ <h2>Profile</h2>
+<p>Praesent sit amet fermentum leo....</p>
+</div>
+
+<div role="tabpanel" class="tab-pane" id="about">
+ <h2>About</h2>
+ <p>Lorem ipsum ...</p></div>
+
+<div role="tabpanel" class="tab-pane" id="match">
+ <h2>Match</h2>
+ <p>Vel vehicula ....</p>
+</div>
+</div>
+
Bootstrap automatically clears any floats after the navtab. Make sure you aren’t trying to float any element to the right of your navtabs, or there will be some awkward space in your layout.
+ +If you put a heading in the navtab content, that heading will appear in the mini-TOC as long as the heading tag has an ID. If you don’t want the headings for each navtab section to appear in the mini-TOC, omit the ID attribute from the heading tag. Without this ID attribute in the heading, the mini-TOC won’t insert the heading title into the mini-TOC.
+ +You must use HTML within the navtab content because each navtab section is surrounded with HTML, and you can’t use Markdown inside of HTML.
+ +Each tab’s href
attribute must match the id
attribute of the tab content’s div
section. So if your tab has href="#acme"
, then you add acme
as the ID attribute in <div role="tabpanel" class="tab-pane" id="acme">
.
One of the tabs needs to be set as active, depending on what tab you want to be open by default (usually the first one).
+ +<div role="tabpanel" class="tab-pane active" id="acme">
+
The navtabs are part of Bootstrap, but this theme sets a cookie to remember the last tab’s state. The js/customscripts.js file has a long chunk of JavaScript that sets the cookie. The JavaScript comes from this StackOverflow thread.
+ +By setting a cookie, if the user refreshes the page, the active tab is the tab the user last selected (rather than defaulting to the default active tab).
+ +One piece of functionality I’d like to implement is the ability to set site-wide nav tab options. For example, if the user always chooses PHP instead of Java in the code samples, it would be great to set this option site-wide by default. However, this functionality isn’t yet coded.
+ + + + + + + + + + + + + + +Use a text editor such as Sublime Text, WebStorm, IntelliJ, or Atom to create pages. Atom is recommended because it’s created by Github, which is driving some of the Jekyll development through Github Pages.
+ +You can store your pages in any folder structures you want, with any level of folder nesting. The site output will pull all of those pages out of their folders and put them into the root directory. Check out the _site folder, which is where Jekyll is generated, to see the difference between your project’s structure and the resulting site output.
+ +The listing of all pages in the root directory (which happens when you add a permalink property to the pages) is what allows the relative linking and offline viewing of the site to work.
+ +Make sure each page has frontmatter at the top like this:
+ +---
+title: Alerts
+tags: [formatting]
+keywords: notes, tips, cautions, warnings, admonitions
+last_updated: July 3, 2016
+summary: "You can insert notes, tips, warnings, and important alerts in your content."
+sidebar: mydoc_sidebar
+permalink: mydoc_alerts.html
+---
+
Frontmatter is always formatted with three hyphens at the top and bottom. Your frontmatter must have a title
and permalink
value. All the other values are optional.
Note that you cannot use variables in frontmatter.
+ +The following table describes each of the frontmatter that you can use with this theme:
+ +Frontmatter | +Required? | +Description | +
---|---|---|
title | +Required | +The title for the page | +
tags | +Optional | +Tags for the page. Make all tags single words, with underscores if needed (rather than spaces). Separate them with commas. Enclose the whole list within brackets. Also, note that tags must be added to _data/tags_doc.yml to be allowed entrance into the page. This prevents tags from becoming somewhat random and unstructured. You must create a tag page for each one of your tags following the pattern shown in the tags folder. (Tag pages aren’t automatically created.) | +
keywords | +Optional | +Synonyms and other keywords for the page. This information gets stuffed into the page’s metadata to increase SEO. The user won’t see the keywords, but if you search for one of the keywords, it will be picked up by the search engine. | +
last_updated | +Optional | +The date the page was last updated. This information could helpful for readers trying to evaluate how current and authoritative information is. If included, the last_updated date appears in the footer of the page in small font. | +
sidebar | +Required | +Refers to the sidebar data file for this page. Don’t include the “.yml” file extension for the sidebar — just provide the file name. If no sidebar is specified, this value will inherit the default property set in your _config.yml file for the page’s frontmatter. |
+
summary | +Optional | +A 1-2 word sentence summarizing the content on the page. This gets formatted into the summary section in the page layout. Adding summaries is a key way to make your content more scannable by users (check out Jakob Nielsen’s site for a great example of page summaries.) The only drawback with summaries is that you can’t use variables in them. | +
permalink | +Required | +The permalink must match the filename in order for automated links to work. Additionally, you must include the “.html” in the filename. Do not put forward slashes around the permalink (this makes Jekyll put the file inside a folder in the output). When Jekyll builds the site, it will put the page into the root directory rather than leaving it in a subdirectory or putting it inside a folder and naming the file index.html. Having all files flattened in the root directory is essential for relative linking to work and for all paths to JS and CSS files to be valid. | +
datatable | +Optional | +‘true’. If you add datatable: true in the frontmatter, scripts for the jQuery Datatables plugin get included on the page. You can see the scripts that conditionally appear by looking in the _layouts/default.html page. |
+
toc | +Optional | +If you specify toc: false in the frontmatter, the page won’t have the table of contents that appears below the title. The toc refers to the list of jump links below the page title, not the sidebar navigation. You probably want to hide the TOC on the homepage and product landing pages. |
+
If you want to use a colon in your page title, you must enclose the title’s value in quotation marks.
+ +By default, everything in your project is included in the output. You can exclude all files that don’t belong to that project by specifying the file name, the folder name, or by using wildcards in your configuration file:
+ +exclude:
+
+- filename.md
+- subfolder_name/
+- mydoc_*
+- gitignore
+
Wildcards will exclude every match after the *
.
If you add published: false
in the frontmatter, your page won’t be published. You can also move draft pages into the _drafts folder to exclude them from the build. With posts, you can also keep them as drafts by omitting the date in the title.
Pages can be either Markdown or HTML format (specified through either an .md or .html file extension).
+ +If you use Markdown, you can also include HTML formatting where needed. But if your format is HTML, you must add a markdown="1"
attribute to the element in order to use Markdown inside that HTML element:
<div markdown="1">This is a [link](http://exmaple.com).</div>
+
For your Markdown files, note that a space or two indent will set text off as code or blocks, so avoid spacing indents unless intentional.
+ +If you have a lot of HTML, as long as the top and bottom tags of the HTML are flush left in a Markdown file, all the tags inside those bookend HTML tags will render as HTML, regardless of their indentation. (This can be especially useful for tables.)
+ +I recommend prefixing your page names with the product, such as “mydoc_pages” instead of just “pages.” This way if you have other products that also have topics with generic names such as “pages,” there won’t be naming conflicts.
+ +Additionally, consider adding the product name in parentheses after the title, such as “Pages (Mydoc)” so that users can clearly navigate different topics for each product.
+ +Kramdown is the Markdown flavor used in the theme. This mostly aligns with Github-flavored Markdown, but with some differences in the indentation allowed within lists. Basically, Kramdown requires you to line up the indent between list items with the first starting character after the space in your list item numbering. See this blog post on Kramdown and Rouge for more details.
+ +You can use standard Multimarkdown syntax for tables. You can also use fenced code blocks with lexers specifying the type of code. The configuration file shows the Markdown processor and extension:
+ +highlighter: rouge
+markdown: kramdown
+kramdown:
+ input: GFM
+ auto_ids: true
+ hard_wrap: false
+ syntax_highlighter: rouge
+
By default, a TOC appears at the top of your pages and posts. If you don’t want the TOC to appear for a specific page, such as for a landing page or other homepage, add toc: false
in the frontmatter of the page.
The mini-TOC requires you to use the ##
Markdown syntax for headings. If you use <h2>
elements, you must add an ID attribute for the heading element in order for it to appear in the mini-TOC (for example, <h2 id="mysampleid">Heading</h2>
.
Use pound signs before the heading title to designate the level. Note that kramdown requires headings to have one space before and after the heading. Without this space above and below, the heading won’t render into HTML.
+ +## Second-level heading
+
Result:
+ +### Third-level heading
+
Result:
+ +#### Fourth-level heading
+
Result:
+ +If you want to use a specific ID tag with your heading, add it like this:
+ +## Headings with ID Tags {#someIdTag}
+
Then you can reference it with a link like this on the same page:
+ +[Some link](#someIdTag)
+
Result:
+ + + +For details about linking to headings on different pages, see Automated links to headings on pages.
+ +The configuration file sets the default layout for pages as the “page” layout.
+ +You can create other layouts inside the layouts folder. If you create a new layout, you can specify that your page use your new layout by adding layout: mylayout.html
in the page’s frontmatter. Whatever layout you specify in the frontmatter of a page will override the layout default set in the configuration file.
Disqus, a commenting system, is integrated into the theme. In the configuration file, specify the Disqus code for the universal code, and Disqus will appear. If you don’t add a Disqus value, the Disqus form isn’t included.
+ + + + + + + + + + + + + + +Posts are typically used for blogs or other news information because they contain a date and are sorted in reverse chronological order.
+ +You create a post by adding a file in the _posts folder that is named yyyy-mm-dddd-permalink.md, which might be 2016-02-25-my-latest-updates.md. You can use any number of subfolders here that you want.
+ +Posts use the post.html layout in the _layouts folder when you are viewing the post.
+ +The news.html file in the root directory shows a reverse chronological listing of the 10 latest posts
+ +The frontmatter you can use with posts is as follows:
+ +---
+title: My sample post
+tags: content_types
+keywords: pages, authoring, exclusion, frontmatter
+sidebar: mydoc_sidebar
+permalink: mydoc_pages.html
+summary: "This is some summary frontmatter for my sample post."
+---
+
Frontmatter | +Required? | +Description | +
---|---|---|
title | +Required | +The title for the page | +
tags | +Optional | +Tags for the page. Make all tags single words, with underscores if needed. Separate them with commas. Enclose the whole list within brackets. Also, note that tags must be added to _data/tags_doc.yml to be allowed entrance into the page. This prevents tags from becoming somewhat random and unstructured. You must create a tag page for each one of your tags following the sample pattern in the tabs folder. (Tag pages aren’t automatically created.) | +
keywords | +Optional | +Synonyms and other keywords for the page. This information gets stuffed into the page’s metadata to increase SEO. The user won’t see the keywords, but if you search for one of the keywords, it will be picked up by the search engine. | +
sidebar | +Required | +Refers to the sidebar data file for this page. Don’t include the “.yml” file extension for the sidebar — just provide the file name. If no sidebar is specified, this value will inherit the default property set in your _config.yml file for the page’s frontmatter. |
+
permalink | +Required | +This theme uses permalinks to facilitate the linking. You specify the permalink want for the page, and the _site output will put the page into the root directory when you publish. Follow the same convention here as you do with page permalinks – list the file name followed by the .html extension. | +
summary | +Optional | +A 1-2 word sentence summarizing the content on the page. This gets formatted into the summary section in the page layout. Adding summaries is a key way to make your content more scannable by users (check out Jakob Nielsen’s site for a great example of page summaries.) The only drawback with summaries is that you can’t use variables in them. | +
which git
.git clone https://github.com/tomjoht/myreponame.git
, replacing the https://github.com/tomjoht/myreponame.git
with your repository’s https clone URL that you copied. url: tomjoht.github.io
+ baseurl: /myreponame
+
Change the url to your github account name, and the baseurl to your repo name.
+ +Bundler is a package manager for Ruby that will install all dependencies you might need to build your site locally. I recommend installing Bundler through homebrew. (Sorry, these instructions apply to Mac only.)
+ +Install homebrew:
+ +/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
+
Install Bundler:
+ +gem install bundler
+
bundle init
. This creates a Gemfile and Gemfile.lock in your project.open gemfile
. This opens the gemfile in your default text editor.Add the following in the gemfile (replacing the existing contents):
+ +source 'https://rubygems.org'
+gem 'github-pages'
+
bundle install
.git add --all
.git commit -m "committing my jekyll theme"
.git push
.Github Pages will now automatically build your site. Wait a minute or two, and then visit tomjoht.github.io/yourreponame, replacing this path with your github account and branch.
+ +You can also customize your Github URL. More instructions on this later….
+ + + + + + + + + + + + + + +If you have the AWS Command Line Interface installed and are pushing your builds to AWS, the following commands show how you can build and push to an AWS location from the command line:
+ +aws s3 cp ~/users/tjohnson/projects/mydocproject/ s3://[aws path]docpath/mydocproject --recursive
+
+aws s3 cp ~/users/tjohnson/projects/anotherdocproject2/ s3://[aws path]docpath/anotherdocproject --recursive
+
The first path in the argument is the local location; the second path is the destination.
+ +If you’re pushing to a regular server that you can ssh into, you can use scp
commands to push your build. Here’s an example:
scp -r /users/tjohnson/projects/mydocproject/ name@domain:/var/www/html/mydocproject
+
Similar to the above, the first path is the local location; the second path is the destination.
+ + + + + + + + + + + + + + +In previous versions of the theme, I built the theme to generate different outputs for different scenarios based on various filtering attributes that might include product, version, platform, and audience variants.
+ +However, this model results in siloed outputs and lots of separate file directories to manage. Instead of having 30 separate sites for your content (or however many variants you might have been producing), in this version of the theme I’ve moved towards a strategy of having one site with multiple products.
+ +For each product, you can associate a unique sidebar with each of the product’s pages. This allows you to have all your documentation on one site, but with separate navigation that is tailored to a view of that product.
+ +You can still output to both web and PDF. And if you really need multiple site outputs, you can still do so by using multiple configuration files that trigger different builds. But my conclusion after using the multiple site output model for some years is that it’s a bad practice for tech comm.
+ +With this theme, since you’ll be publishing to one site, I’ve implement permalinks instead of relative links. Using permalinks means the way you store pages is much more flexible. You can store topics in folders and subfolders, etc., to any degree. But note that with permalinks you can’t view the content offline (outside of Jekyll’s preview server) nor on a separate site other than the one specified in the configuration file. Permalinks are how Jekyll was designed to work, and the sites just work better that way.
+ +I also switched from redcarpet and Pygments to Kramdown and Rouge to align with the current direction of Jekyll 3.0. Kramdown is a Markdown filter (it’s slightly different from Github-flavored Markdown). Rouge is a syntax highlighter. Pygments had some dependencies on Python, which made it more cumbersome for Windows users.
+ +I included a blog feature with this version of the theme. You can write posts and view them through the News link. There’s also an archive for blog posts that sorts posts by year.
+ +Additionally, the tagging system works across both the blog and pages, so your tags allow users to move laterally across the site based on topics they’re interested in. When you view a tag archive, the sidebar shows a list of tags.
+ +I updated the documentation for the theme. The switch from the multi-site outputs to the single-site with multiple sidebars required updating a lot of different parts of the documentation and code.
+ +Previously I had some errors with the HTML that showed up in w3c HTML validator analyses. This caused some small problems in certain browsers or systems less tolerant of the errors. I fixed all of the errors.
+ +If you want to access the old theme, you can still find it here.
+ + + + + + + + + + + + + + +You can now view the site offline rather than solely through the Jekyll preview server or deployed on a web server. The linking approach in both the sidebar and with inline links uses relative linking throughout.
+ +You can creates folders and subfolders for your pages, similar to how you can store posts in folders and subfolders. When Jekyll builds the site, all pages get pushed into the root directory as single html files (rather than being pushed inside folders, or remaining in subfolders). See Pages for more details.
+ +You can use include templates for notes, tips, and warnings. These include templates make it easier to insert notes. If you make an error, you’re immediately made aware since the site won’t build. See Alerts for more details.
+ +Similar to alerts, images also have include templates. You can insert both regular images and inline images, such as images that are a button or icon. See Images for more details.
+ +Instead of using YAML references to handle links, I’ve switched to a Markdown reference style approach. A links.html file iterates through the sidebar files and formats the content in the Markdown reference. You then just use Markdown syntax for the links. See Links for more details.
+ +If you want to display a workflow map for a process, you can do so by adding some properties in your frontmatter. The workflow map helps guide users through a process. Both simple and complex workflow maps are available. For more details, see Workflow maps.
+ +If you want to upgrade from an earlier version of the theme, I recommend that you download the new theme and copy of your Markdown files into the new theme. You’ll then need to make adjustments to your page frontmatter, to the sidebar table of contents, links, image references, and alert references. In short, there’s no easy upgrade path. But all of this won’t take too long if you don’t have mountains of content.
+ + + + + + + + + + + + + + +The search is configured through the search.json file in the root directory. The search is a simple search that looks at content in pages. It looks at titles, summaries, keywords, and tags.
+ +However, the search doesn’t work like google — you can’t hit return and see a list of results on the search results page, with the keywords in bold. Instead, this search shows a list of page titles that contain keyword matches. It’s fast, but simple.
+ +By default, every page is included in the search. Depending on the type of content you’re including, you may find that some pages will break the JSON formatting. If that happens, then the search will no longer work.
+ +If you want to exclude a page from search add search: exclude
in the page’s frontmatter.
You should exclude any files from search that you don’t want appearing in the search results. For example, if you have a tooltips.json file or prince-list.txt, don’t include it, as the formatting will break the JSON format.
+ +If any formatting in the search.json file is invalid (in the build), search won’t work. You’ll know that search isn’t working if no results appear when you start typing in the search box.
+ +If this happens, point your browser to your build’s search.json file at http://localhost:4000/search.json (or your public github pages site), copy the entire search.json page as it’s output on the browser, and then use a JSON validator to validate the output by pasting what you copied into the validator. Look for the line causing trouble. It will be highlighted. Edit the file that’s causing the problem to either exclude it from the search or fix the syntax so that it doesn’t invalidate the JSON. (Note that tabs in the body will invalidate JSON, as will certain characters in the file’s front matter. For example, the summary: cannot have “ quotes in it.
+ +The search.json file already tries to strip out content that would otherwise make the JSON invalid.
+ +I’ve found that including the body
field in the search creates too many problems, and so I’ve removed body
from the search. You can see the results of including the body
by adding this along with the other fields in search.json:
"body": "{{ page.content | strip_html | strip_newlines | replace: '\', '\\\\' | replace: '"', '\\"' | replace: ' ', ' ' }}",
+
Note that the last replace, | replace: '^t', ' '
, looks for any tab character and replaces it with four spaces. (Tab characters invalidate JSON.) If you run into other problematic formatting, you can use regex expressions to find and replace the content. See Regular Expressions for details on finding and replacing code.
It’s possible that the formatting may not account for all the scenarios that would invalidate the JSON. (Sometimes it’s an extra comma after the last item that makes it invalid.)
+ +Note that including the body in the search creates other problems as well. The search results show the most immediate matches in the JSON file. If several topics have matches for the keyword in the body, these matches might appear before other files that have matches in the title, summary, or keywords. This is because this simple search does not provide any weighting mechanisms for the content.
+ +At some point, you may want to customize the search results more. Here’s a little more detail that will be helpful. The search.json file retrieves various page values:
+ +---
+title: search
+layout: none
+search: exclude
+---
+
+[
+{% for page in site.pages %}
+{% unless page.search == "exclude" %}
+{
+"title": "{{ page.title | escape }}",
+"tags": "{{ page.tags }}",
+"keywords": "{{page.keywords}}",
+"url": "{{ page.url | remove: "/"}}",
+"summary": "{{page.summary | strip }}"
+},
+{% endunless %}
+{% endfor %}
+
+{% for post in site.posts %}
+
+{
+"title": "{{ post.title | escape }}",
+"tags": "{{ post.tags }}",
+"keywords": "{{post.keywords}}",
+"url": "{{ post.url }}",
+"summary": "{{post.summary | strip }}"
+}
+{% unless forloop.last %},{% endunless %}
+{% endfor %}
+
+]
+
+
The _includes/topnav.html file then makes use of these values:
+ +<li>
+ <!--start search-->
+ <div id="search-demo-container">
+ <input type="text" id="search-input" placeholder="search...">
+ <ul id="results-container"></ul>
+ </div>
+ <script src="js/jekyll-search.js" type="text/javascript"></script>
+ <script type="text/javascript">
+ SimpleJekyllSearch.init({
+ searchInput: document.getElementById('search-input'),
+ resultsContainer: document.getElementById('results-container'),
+ dataSource: 'search.json',
+ searchResultTemplate: '<li><a href="{url}" title="Search configuration">{title}</a></li>',
+ noResultsText: 'No results found.',
+ limit: 10,
+ fuzzy: true,
+ })
+ </script>
+ <!--end search-->
+</li>
+
Where you see {url}
and {title}
, the search is retrieving the values for these as specified in the search.json file.
Overall, the built-in search only works for small documentation projects. If you have more robust search needs, consider integrating Google Custom Search, Algolia, or Swifttype.
+ + + + + + + + + + + + + + +You create a series by looking for all pages within a tag namespace that contain certain frontmatter. Here’s a demo.
+ +First create an include that contains your series button:
+ +<div class="seriesContext">
+ <div class="btn-group">
+ <button type="button" data-toggle="dropdown" class="btn btn-primary dropdown-toggle">Series Demo <span class="caret"></span></button>
+ <ol class="dropdown-menu">
+ {% assign pages = site.pages | sort:"weight" %}
+ {% for p in pages %}
+ {% if p.series == "ACME series" %}
+ {% if p.url == page.url %}
+ <li class="active"> → {{p.weight}}. {{p.title}}</li>
+ {% else %}
+ <li>
+ <a href="{{p.url | remove: "/"}}">{{p.weight}}. {{p.title}}</a>
+ </li>
+ {% endif %}
+ {% endif %}
+ {% endfor %}
+ </ol>
+ </div>
+</div>
+
Change “ACME series” to the name of your series.
+ +Save this in your _includes/custom folder as something like series_acme.html.
+ +Now create another include for the Next button at the bottom of the page. Copy the following code, changing the series name to your series’name:
+ +<p>{% assign series_pages = site.tags.series_acme %}
+ {% for p in pages %}
+ {% if p.series == "ACME series" %}
+ {% assign nextTopic = page.weight | plus: "1" %}
+ {% if p.weight == nextTopic %}
+ <a href="{{p.url}}"><button type="button" class="btn btn-primary">Next: {{p.weight}} {{p.title}}</button></a>
+ {% endif %}
+ {% endif %}
+ {% endfor %}
+</p>
+
Change “acme” to the name of your series.
+ +Save this in your _includes/custom/mydoc folder as series_acme_next.html.
+ +Now add the following frontmatter to each page in the series:
+ +series: "ACME series"
+weight: 1.0
+
With weights, Jekyll will treat 10 as coming after 1. If you have more than 10 items, consider changing plus: "1.0"
to plus: "0.1"
.
Additionally, if your page names are prefaced with numbers, such as “1. Download the code,” then the {{p.weight}}
will create a duplicate number. In that case, just remove the {{p.weight}}
from both code samples here.
On each series page, add a link to the series button at the top and a link to the next button at the bottom.
+ +<!-- your frontmatter goes here -->
+
+{% include custom/series_acme.html %}
+
+<!-- your page content goes here ... -->
+
+{% include custom/series_acme_next.html %}
+
The Bootstrap menu uses the primary
class for styling. If you change this class in your theme, the Bootstrap menu should automatically change color as well. You can also just use another Bootstrap class in your button code. Instead of btn-primary
, use btn-info
or btn-warning
. See Labels for more Bootstrap button classes.
Instead of copying and pasting the button includes on each of your series, you could also create a collection and define a layout for the collection that has the include code. For more information on creating collections, see Collections for more details.
+ + + + + + + + + + + + + + +This is the first post in the series.
+ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam vel sollicitudin felis. Sed eu arcu sed ipsum semper luctus eu a tortor. Suspendisse id leo eu metus laoreet varius. Mauris consequat accumsan ex, a iaculis metus fermentum a. Praesent sit amet fermentum leo. Aliquam feugiat, nibh in ultrices mattis, felis ipsum venenatis metus, vel vehicula libero mauris a enim. Sed placerat est ac lectus vestibulum tempor. Quisque ut condimentum massa. Proin venenatis leo id urna cursus blandit. Vivamus sit amet hendrerit metus.
+ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam vel sollicitudin felis. Sed eu arcu sed ipsum semper luctus eu a tortor. Suspendisse id leo eu metus laoreet varius. Mauris consequat accumsan ex, a iaculis metus fermentum a. Praesent sit amet fermentum leo. Aliquam feugiat, nibh in ultrices mattis, felis ipsum venenatis metus, vel vehicula libero mauris a enim. Sed placerat est ac lectus vestibulum tempor. Quisque ut condimentum massa. Proin venenatis leo id urna cursus blandit. Vivamus sit amet hendrerit metus.
+ + + + + + + + + + + + + + +This is the second post in the series.
+ +Aliquam feugiat, nibh in ultrices mattis, felis ipsum venenatis metus, vel vehicula libero mauris a enim. Sed placerat est ac lectus vestibulum tempor. Quisque ut condimentum massa. Proin venenatis leo id urna cursus blandit. Vivamus sit amet hendrerit metus.
+ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam vel sollicitudin felis. Sed eu arcu sed ipsum semper luctus eu a tortor. Suspendisse id leo eu metus laoreet varius. Mauris consequat accumsan ex, a iaculis metus fermentum a. Praesent sit amet fermentum leo. Aliquam feugiat, nibh in ultrices mattis, felis ipsum venenatis metus, vel vehicula libero mauris a enim. Sed placerat est ac lectus vestibulum tempor. Quisque ut condimentum massa. Proin venenatis leo id urna cursus blandit. Vivamus sit amet hendrerit metus.
+ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam vel sollicitudin felis. Sed eu arcu sed ipsum semper luctus eu a tortor. Suspendisse id leo eu metus laoreet varius. Mauris consequat accumsan ex, a iaculis metus fermentum a. Praesent sit amet fermentum leo.
+ + + + + + + + + + + + + + +This is the third post in the series.
+ +Mauris consequat accumsan ex, a iaculis metus fermentum a. Praesent sit amet fermentum leo. Aliquam feugiat, nibh in ultrices mattis, felis ipsum venenatis metus, vel vehicula libero mauris a enim. Sed placerat est ac lectus vestibulum tempor. Quisque ut condimentum massa. Proin venenatis leo id urna cursus blandit. Vivamus sit amet hendrerit metus.
+ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam vel sollicitudin felis. Sed eu arcu sed ipsum semper luctus eu a tortor. Suspendisse id leo eu metus laoreet varius.
+ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam vel sollicitudin felis. Sed eu arcu sed ipsum semper luctus eu a tortor. Suspendisse id leo eu metus laoreet varius. Mauris consequat accumsan ex, a iaculis metus fermentum a. Praesent sit amet fermentum leo. Aliquam feugiat, nibh in ultrices mattis, felis ipsum venenatis metus, vel vehicula libero mauris a enim. Sed placerat est ac lectus vestibulum tempor. Quisque ut condimentum massa. Proin venenatis leo id urna cursus blandit. Vivamus sit amet hendrerit metus.
+ + + + + + + + + + + + + + +This is the fourth post in the series.
+ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam vel sollicitudin felis. Sed eu arcu sed ipsum semper luctus eu a tortor. Suspendisse id leo eu metus laoreet varius. Mauris consequat accumsan ex, a iaculis metus fermentum a. Praesent sit amet fermentum leo. Aliquam feugiat, nibh in ultrices mattis, felis ipsum venenatis metus, vel vehicula libero mauris a enim. Sed placerat est ac lectus vestibulum tempor. Quisque ut condimentum massa. Proin venenatis leo id urna cursus blandit. Vivamus sit amet hendrerit metus.
+ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam vel sollicitudin felis. Sed eu arcu sed ipsum semper luctus eu a tortor. Suspendisse id leo eu metus laoreet varius. Mauris consequat accumsan ex, a iaculis metus fermentum a. Praesent sit amet fermentum leo. Aliquam feugiat, nibh in ultrices mattis, felis ipsum venenatis metus, vel vehicula libero mauris a enim. Sed placerat est ac lectus vestibulum tempor. Quisque ut condimentum massa. Proin venenatis leo id urna cursus blandit. Vivamus sit amet hendrerit metus.
+ +Mauris consequat accumsan ex, a iaculis metus fermentum a. Praesent sit amet fermentum leo. Aliquam feugiat, nibh in ultrices mattis, felis ipsum venenatis metus, vel vehicula libero mauris a enim. Sed placerat est ac lectus vestibulum tempor. Quisque ut condimentum massa. Proin venenatis leo id urna cursus blandit. Vivamus sit amet hendrerit metus.
+ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam vel sollicitudin felis. Sed eu arcu sed ipsum semper luctus eu a tortor. Suspendisse id leo eu metus laoreet varius.
+ + + + + + + + + + + + + + +The sidebar uses the Navgoco jQuery plugin as its basis. Why not use Bootstrap? Navgoco provides a few features that I couldn’t find in Bootstrap:
+ +active
class based on the navigation option that’s open. This is essential for keeping the accordion open.In short, the sidebar has some complex logic here. I’ve integrated Navgoco’s features with the sidebar.html and sidebar data files to build the sidebar. It’s probably the most impressive part of this theme. (Other themes usually aren’t focused on creating hierarchies of pages, but this kind of hierarchy is important in a documentation site.)
+ +The sidebar.html file (inside the _includes folder) contains the .navgoco
method called on the #mysidebar
element.
There are some options to set within the .navgoco
method. The only noteworthy option is accordion
. This option makes it so when you expand a section, the other sections collapse. It’s a way of keeping your navigation controls condensed.
The value for accordion
is a Boolean (true
or false
). By default, the accordion
option is set as true
. If you don’t want the accordion, set it to false
. Note that there’s also a block of code near the bottom of sidebar.html that is commented out. Uncomment out that section to have the Collapse all and Expand All buttons appear.
There’s a danger with setting the accordion to false
. If you click Expand All and the sidebar expands beyond the dimensions of the browser, users will be stuck. When that happens, it’s hard to collapse it. As a best practice, leave the sidebar’s accordion option set to true
.
The sidebar has one other feature — this one from Bootstrap. If the user’s viewport is tall enough, the sidebar remains fixed on the page. This allows the user to scroll down the page and still keep the sidebar in view.
+ +In the customsscripts.js file in the js folder, there’s a function that adds an affix
class if the height of the browser window is greater than 800 pixels. If the browser’s height is less than 800 pixels, the nav affix
class does not get inserted. As a result, the sidebar can slide up and down as the user scrolls up and down the page.
Depending on your content, you may need to adjust 800
pixel number. If your sidebar is so long that having it in a fixed position makes it so the bottom of the sidebar gets cut off, increase the 800
pixel number here to a higher number.
In the attributes for each sidebar item, if you use external_url
instead of url
, the theme will insert the link into an a href
element that opens in a blank target.
For example, the sidebar.html file contains the following code:
+ +{% if folderitem.external_url %}
+ <li><a href="{{folderitem.external_url}}" target="_blank">{{folderitem.title}}</a></li>```
+
+
+You can see that the `external_url` is a condition that applies a different formatting. Although this feature is available, I recommend putting any external navigation links in the top navigation bar instead of the side navigation bar.
+
+## Sidebar item highlighting
+
+The sidebar.html file inserts an `active` class into the sidebar element when the `url` attribute in the sidebar data file matches the page URL.
+
+For example, the sidebar.html file contains the following code:
+
+
+```liquid
+{% elsif page.url == folderitem.url %}
+ <li class="active"><a href="{{folderitem.url | remove: "/"}}">{{folderitem.title}}</a></li>
+
If the page.url
matches the subfolderitem.url
, then an active
class gets applied. If not, the active
class does not get applied.
The page.url
in Jekyll is a site-wide variable. If you insert {{page.url}}
on a page, it will render as follows: /mydoc_sidebar_navigation.html. The url
attribute in the sidebar item must match the page URL in order to get the active
class applied.
This is why the url
value in the sidebar data file looks something like this:
- title: Understanding how the sidebar works
+ permalink: mydoc_understand_sidebar.html
+ output: web, pdf
+
Note that the url does not include the project folder where the file is stored. This is because the site uses permalinks, which pulls the topics out of subfolders and places them into the root directory when the site builds.
+ +Now the page.url and the item.url can match and the active
class can get applied. With the active
class applied, the sidebar section remains open.
See for an example of the FAQ format, which follows an accordion, collapse/expand format. This code is from Bootstrap.
+ +See for a possible layout for knowledge base articles. This layout looks for pages containing specific tags.
+ +If you want a dynamic card layout that allows you to filter the cards, see . This uses the Shuffle JS library.
+ + + + + + + + + + + + + + +Let me know about any bugs or other issues that you find. Just email me at tomjoht@gmail.com. You can also create issues directly within the Github repository here.
+ + + + + + + + + + + + + + +Before you get into exploring Jekyll as a potential platform for help content, you may be wondering if it supports some basic features needed to fulfill your tech doc requirements. The following table shows what is supported in Jekyll and this theme.
+ +Features | +Supported | +Notes | +
---|---|---|
Content re-use | +Yes | +Supports re-use through Liquid. You can re-use variables, snippets of code, entire pages, and more. In DITA speak, this includes conref and keyref. See Content reuse for more details. | +
Markdown | +Yes | +You can author content using Markdown syntax, specifically kramdown. This is a wiki-like syntax for HTML that you can probably pick up in 10 minutes. Where Markdown falls short, you can use HTML. Where HTML falls short, you use Liquid, which is a scripting that allows you to incorporate more advanced logic. | +
Responsive design | +Yes | +Uses Bootstrap framework for responsive design. | +
Translation | +Yes | +To translate content, send the generated HTML to your translation group. You can translate the Markdown source if your translator accepts the format, but usually Markdown is problematic. Note that this theme isn’t structured well to accommodate translation projects. | +
Collaboration | +Yes | +You collaborate with Jekyll projects the same way that developers collaborate with software projects. (You don’t need a CMS.) Because you’re working with text file formats, you can use any version control software (Git, Mercurial, Perforce, Bitbucket, etc.) as a CMS for your files. | +
Scalability | +Yes | +Your site can scale to any size. It’s up to you to determine how you will design the information architecture for your pages. You can choose what you display at first, second, third, fourth, and more levels, etc. Note that when your project has thousands of pages, the build time will be longer (maybe 1 minute per thousand pages?). It really depends on how many for loops you have iterating through the pages. I recommend that you use smaller repos in your content architecture. | +
Lightweight architecture | +Yes | +You don’t need a LAMP stack (Linux, Apache, MySQL, PHP) architecture to get your site running. All of the building is done on your own machine, and you then push the static HTML files onto a server. | +
Skinnability | +Yes | +You can skin your Jekyll site to look identical to pretty much any other site online. If you have a UX team, they can really skin and design the site using all the tools familiar to the modern designer – JavaScript, HTML5, CSS, jQuery, and more. Jekyll is built on the modern web development stack rather than the XML stack (XSLT, XPath, XQuery). See this tutorial for details on how to create your own Jekyll theme. | +
Support | +Yes | +The community for your Jekyll site isn’t so much other tech writers (as is the case with DITA) but rather the wider web development community. Jekyll Talk is a great resource. So is Stack Overflow. See the Getting Help section of Jekyll. | +
Blogging features | +Yes | +There is a simple blogging feature. This appears as news and is intended to promote news that applies across products. | +
Versioning | +Yes | +Jekyll doesn’t version your files. You upload your files to a version control system such as Github. Your files are versioned there. | +
PC platform | +Yes | +Jekyll runs on Windows. Although the experience working on the command line is better on a Mac, Windows also works, especially now that Jekyll 3.0 dropped dependencies on Python, which wasn’t available by default on Windows. | +
jQuery plugins | +Yes | +You can use any jQuery plugins you and other JavaScript, CMS, or templating tools. However, note that if you use Ruby plugins, you can’t directly host the source files on Github Pages because Github Pages doesn’t allow Ruby plugins. Instead, you can just push your output to any web server. If you’re not planning to use Github Pages, there are no restrictions on any plugins of any sort. Jekyll makes it super easy to integrate every kind of plugin imaginable. This theme doesn’t actually use any plugins, so you can publish on Github if you want. | +
Bootstrap integration | +Yes | +This theme is built on Bootstrap. If you don’t know what Bootstrap is, basically this means there are hundreds of pre-built components, styles, and other elements that you can simply drop into your site. For example, the responsive quality of the site comes about from the Bootstrap code base. | +
Fast-loading pages | +Yes | +This is one of the Jekyll’s strengths. Because the files are static, they loading extremely fast, approximately 0.5 seconds per page. You can’t beat this for performance. (A typically database-driven site like WordPress averages about 2.5 + seconds loading time per page.) Because the pages are all static, it means they are also extremely secure. You won’t get hacked like you might with a WordPress site. | +
Themes | +Yes | +You can have different themes for different outputs. If you know CSS, theming both the web and print outputs is pretty easy. | +
Open source | +Yes | +This theme is entirely open source. Every piece of code is open, viewable, and editable. Note that this openness comes at a price — it’s easy to make changes that break the theme or otherwise cause errors. | +
Offline viewing | +Yes | +This theme uses relative linking throughout, so you can view the content offline and on any webserver without configuring urls and baseurls in your configuration file. | +
The following features are not available.
+ +Features | +Supported | +Notes | +
---|---|---|
CMS interface | +No | +Unlike with WordPress, you don’t log into an interface and navigate to your files. You work with text files and preview the site dynamically in your browser. Don’t worry – this is part of the simplicy that makes Jekyll awesome. I recommend using WebStorm as your text editor. | +
WYSIWYG interface | +No | +I use WebStorm to author content, because I like working in text file formats. But you can use any Markdown editor you want (e.g., Lightpaper for Mac, Marked) to author your content. | +
Different outputs | +No | +This theme provides a single website output that contains documentation for multiple products. Unlike previous iterations of the theme, it’s not intended to support different outputs from the same content. However, you can easily set things up to do this by simply creating multiple configuration files and running different builds for each configuration file. | +
Robust search | +No | +The search feature is a simplistic JSON search. For more robust search, you should integrate Swiftype or Algolia. However, those services aren’t currently integrated into the theme. | +
Standardized templates | +No | +You can create pages with any structure you want. The theme does not enforce topic types such as a task or concept as the DITA specification does. | +
Integration with Swagger | +No | +You can link to a SwaggerUI output, but there is no built-in integration of SwaggerUI into this documentation theme. | +
Templates for endpoints | +No | +Although static site generators work well with API documentation, there aren’t any built-in templates specific to endpoints in this theme. You could construct your own, though. | +
eBook output | +No | +There isn’t an eBook output for the content. | +
For syntax highlighting, use fenced code blocks optionally followed by the language syntax you want:
+ ++```java +import java.util.Scanner; + +public class ScannerAndKeyboard +{ + + public static void main(String[] args) + { Scanner s = new Scanner(System.in); + System.out.print( "Enter your name: " ); + String name = s.nextLine(); + System.out.println( "Hello " + name + "!" ); + } +} +``` ++ +
This looks as follows:
+ +import java.util.Scanner;
+
+public class ScannerAndKeyboard
+{
+
+ public static void main(String[] args)
+ { Scanner s = new Scanner(System.in);
+ System.out.print( "Enter your name: " );
+ String name = s.nextLine();
+ System.out.println( "Hello " + name + "!" );
+ }
+}
+
Fenced code blocks require a blank line before and after.
+ +If you’re using an HTML file, you can also use the highlight
command with Liquid markup.
+{% highlight java %} +import java.util.Scanner; + +public class ScannerAndKeyboard +{ + + public static void main(String[] args) + { Scanner s = new Scanner(System.in); + System.out.print( "Enter your name: " ); + String name = s.nextLine(); + System.out.println( "Hello " + name + "!" ); + } +} +{% endhighlight %} ++ +
Result:
+ + + +The theme has syntax highlighting specified in the configuration file as follows:
+ +highlighter: rouge
+
The syntax highlighting is done via the css/syntax.css file.
+ +The keywords you must add to specify the highlighting (in the previous example, ruby
) are called “lexers.” You can search for “lexers.” Here are some common ones I use:
You can use Multimarkdown syntax for tables. The following shows a sample:
+ +| Priority apples | Second priority | Third priority |
+|-------|--------|---------|
+| ambrosia | gala | red delicious |
+| pink lady | jazz | macintosh |
+| honeycrisp | granny smith | fuji |
+
Result:
+ +Priority apples | +Second priority | +Third priority | +
---|---|---|
ambrosia | +gala | +red delicious | +
pink lady | +jazz | +macintosh | +
honeycrisp | +granny smith | +fuji | +
<br/><br/>
.If you need a more sophisticated table syntax, use HTML syntax for the table. Although you’re using HTML, you can use Markdown inside the table cells by adding markdown="span"
as an attribute for the td
tag, as shown in the following table. You can also control the column widths.
<table>
+<colgroup>
+<col width="30%" />
+<col width="70%" />
+</colgroup>
+<thead>
+<tr class="header">
+<th>Field</th>
+<th>Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td markdown="span">First column **fields**</td>
+<td markdown="span">Some descriptive text. This is a markdown link to [Google](http://google.com). Or see [some link][mydoc_tags].</td>
+</tr>
+<tr>
+<td markdown="span">Second column **fields**</td>
+<td markdown="span">Some more descriptive text.
+</td>
+</tr>
+</tbody>
+</table>
+
Result:
+Field | +Description | +
---|---|
First column fields | +Some descriptive text. This is a markdown link to Google. Or see some link. | +
Second column fields | +Some more descriptive text. + | +
You also have the option of using a jQuery DataTable, which gives you some additional capabilities. To use a jQuery DataTable in a page, include datatable: true
in a page’s frontmatter. This tells the default layout to load the necessary CSS and javascript bits and to include a $(document).ready()
function that initializes the DataTables library.
You can change the options used to initialize the DataTables library by editing the call to $('table.display').DataTable()
in the default layout. The available options for Datatables are described in the DataTable documentation, which is excellent.
You also must add a class of display
to your tables. You can change the class, but then you’ll need to change the trigger defined in the $(document).ready()
function in the default layout from table.display
to the class you prefer.
You can also add page-specific triggers (by copying the <script></script>
block from the default layout into the page) and classes, which lets you use different options on different tables.
If you use an HTML table, adding class="display"
to the <table>
tag is sufficient.
Markdown, however, doesn’t allow you to add classes to tables, so you’ll need to use a trick: add <div class="datatable-begin"></div>
before the table and <div class="datatable-end"></div>
after the table. The default layout includes a jQuery snippet that automagically adds the display
class to any table it finds between those two markers. So you can start with this (we’ve trimmed the descriptions for display):
<div class="datatable-begin"></div>
+
+Food | Description | Category | Sample type
+------- | ------------------------------------- | -------- | -----------
+Apples | A small, somewhat round ... | Fruit | Fuji
+Bananas | A long and curved, often-yellow ... | Fruit | Snow
+Kiwis | A small, hairy-skinned sweet ... | Fruit | Golden
+Oranges | A spherical, orange-colored sweet ... | Fruit | Navel
+
+<div class="datatable-end"></div>
+
and get this:
+ + + +Food | +Description | +Category | +Sample type | +
---|---|---|---|
Apples | +A small, somewhat round and often red-colored, crispy fruit grown on trees. | +Fruit | +Fuji | +
Bananas | +A long and curved, often-yellow, sweet and soft fruit that grows in bunches in tropical climates. | +Fruit | +Snow | +
Kiwis | +A small, hairy-skinned sweet fruit with green-colored insides and seeds. | +Fruit | +Golden | +
Oranges | +A spherical, orange-colored sweet fruit commonly grown in Florida and California. | +Fruit | +Navel | +
Notice a few features:
+ +Read more of the DataTable documentation to get a sense of the options you can configure. You should probably only use DataTables when you have long, massive tables full of information.
+ +Tags provide alternate groupings for your content. In the documentation for this theme, there are a number of equally plausible ways I could have grouped the content. The folder names and items I chose for each item could have been grouped in other ways with good reason.
+ +Tags allow you to go beyond the traditional hierarchical classification and provide other groupings. For example, the same item can belong to two different groups. You can also introduce other dimensions not used in your table of contents, such as platform-specific tags or audience-specific tags.
+ + + + + + + + + + + + + + +You can add tags to pages by adding tags
in the frontmatter with values inside brackets, like this:
---
+title: 5.0 Release Notes
+permalink: release_notes_5_0.html
+tags: [formatting, single_sourcing]
+---
+
posts.tags.tagname
, where tagname
is the name of the tag. You can then list all posts in that tag namespace. But pages don’t off this same tag namespace, so you could actually use another key instead of tags
. Nevertheless, I’m using the same tags
approach for posts as with pages.To prevent tags from getting out of control and inconsistent, first make sure the tag appears in the _data/tags.yml file. If it’s not there, the tag you add to a page won’t be read. I added this check just to make sure I’m using the same tags consistently and not adding new tags that don’t have tag archive pages.
+ +Additionally, you must create a tag archive page similar to the other pages named tag_{tagname}.html folder. This theme doesn’t auto-create tag archive pages.
+ +For simplicity, make all your tags single words (connect them with hyphens if necessary).
+ +Tags have a few components.
+ +In the _data/tags.yml file, add the tag names you want to allow. For example:
+ +allowed-tags:
+ - getting_started
+ - overview
+ - formatting
+ - publishing
+ - single_sourcing
+ - special_layouts
+ - content types
+
Create a tag archive file for each tag in your tags_doc.yml list. Name the file following the same pattern in the tags folder, like this: tag_collaboration.html.
+ +Each tag archive file needs only this:
+ +---
+title: "Collaboration pages"
+tagName: collaboration
+search: exclude
+permalink: tag_collaboration.html
+sidebar: mydoc_sidebar
+---
+{% include taglogic.html %}
+
Change the title, tagName, and permalink values to be specific to the tag name you just created.
+ +By default, the _layouts/page.html file will look for any tags on a page and insert them at the bottom of the page using this code:
+<div class="tags">
+{% if page.tags != null %}
+<b>Tags: </b>
+{% assign projectTags = site.data.tags.allowed-tags %}
+{% for tag in page.tags %}
+{% if projectTags contains tag %}
+<a href="{{ "tag_" | append: tag | append: ".html" }}" class="btn btn-default navbar-btn cursorNorm" role="button">{{page.tagName}}{{tag}}</a>
+{% endif %}
+{% endfor %}
+{% endif %}
+</div>
+
Because this code appears on the _layouts/page.html file by default, you don’t need to do anything in your page to get the tags to appear. However, if you want to alter the placement or change the button color, you can do so within the _includes/taglogic.html file.
+ +You can change the button color by changing the class on the button from btn-info
to one of the other button classes bootstrap provides. See Labels for more options on button class names.
If you want to retrieve pages outside of a particular tag_archive page, you could use this code:
+ +Getting started pages:
+<ul>
+{% for page in site.pages %}
+{% for tag in page.tags %}
+{% if tag == "getting_started" %}
+<li><a href="{{page.url | remove: "/" }}">{{page.title}}</a></li>
+{% endif %}
+{% endfor %}
+{% endfor %}
+</ul>
+
Here’s how that code renders:
+ +Getting started pages:
+If you want to sort the pages alphabetically, you have to apply a sort
filter:
+Getting started pages:
+<ul>
+{% assign sorted_pages = site.pages | sort: 'title' %}
+{% for page in sorted_pages %}
+{% for tag in page.tags %}
+{% if tag == "getting_started" %}
+<li><a href="{{page.url | remove: "/" }}">{{page.title}}</a></li>
+{% endif %}
+{% endfor %}
+{% endfor %}
+</ul>
+
+
Here’s how that code renders:
+ +Getting started pages:
+Although the tag approach here uses for
loops, these are somewhat inefficient on a large site. Most of my tech doc projects don’t have hundreds of pages (like my blog does). If your project does have hundreds of pages, this for
loop approach with tags is going to slow down your build times.
Without the ability to access pages inside a universal namespace with the page type, there aren’t many workarounds here for faster looping.
+ +With posts (instead of pages), since you can access just the posts inside posts.tag.tagname
, you can be a lot more efficient with the looping.
Still, if the build times are getting long (e.g., 1 or 2 minutes per build), look into reducing the number of for
loops on your site.
If your page shows “tags:” at the bottom without any value, it could mean a couple of things:
+ +tags: []
property in your frontmatter.If you don’t want tags to appear at all on your page, remove the tags property from your frontmatter.
+ +Since you may have many tags and find it difficult to remember what tags are allowed, I recommend creating a template that prepopulates all your frontmatter with all possible tags. Then just remove the tags that don’t apply.
+ +See WebStorm Text Editor for tips on creating file templates in WebStorm.
+ + + + + + + + + + + + + + +You can choose a green or blue theme, or you can create your own. In the css folder, there are two theme files: theme-blue.css and theme-green.css. These files have the most common CSS elements extracted in their own CSS file. Just change the hex colors to the ones you want.
+ +In the _includes/head.html file, specify the theme file you want the output to use — for example, theme_file: theme-green.css
. See this line:
<link rel="stylesheet" href="css/theme-green.css" />
+
The differences between the themes is fairly minimal. The main navigation bar, sidebar, buttons, and heading colors change color. That’s about it.
+ +In a more sophisticated theming approach, you could use Sass files to generate rules based on options set in a data file, but I kept things simple here.
+ + + + + + + + + + + + + + +When you try to build the site, you get this error in iTerm:
+ +jekyll 2.5.3 | Error: Address already in use - bind(2)
+
This happens if a server is already in use. To fix this, edit your config file and change the port to a unique number.
+ +If the previous server wasn’t shut down properly, you can kill the server process using these commands:
+ +ps aux | grep jekyll
Find the PID (for example, it looks like “22298”).
+ +Then type kill -9 22298
where “22298” is the PID.
Alternatively, type the following to stop all Jekyll servers:
+ +kill -9 $(ps aux | grep '[j]ekyll' | awk '{print $2}')
+
If you run into permissions errors trying to run a shell script file (such as mydoc_multibuild_web.sh), you may need to change the file permissions to make the sh file executable. Browse to the directory containing the shell script and run the following:
+ +chmod +x build_writer.sh
+
If you’re using a PC, rename your shell files with a .bat extension.
+ +If you see “page 0” cross-references in the PDF, the URL doesn’t exist. Check to make sure you actually included this page in the build.
+ +If it’s not a page but rather a file, you need to add a noCrossRef
class to the file so that your print stylesheet excludes the counter from it. Add class="noCrossRef"
as an attribute to the link. In the css/printstyles.css file, there is a style that should remove the counter from anchor elements with this class.
Check the prince-list.txt file in the output to see if it contains links. If not, you have something wrong with the logic in the prince-list.txt file. Check the conditions.html file in your _includes to see if the audience specified in your configuration file aligns with the buildAudience in the conditions.html file
+ +If you build your site but the sidebar doesn’t appear, check the following:
+ +Look in your PDF config file and make sure you have a sidebar property, such as this:
+ +pdf_sidebar: product2_sidebar
+
Make sure each TOC item has an output property that specifies web or pdf.
+ +Understanding how the theme works can be helpful in troubleshooting. The _includes/sidebar.html file loops through the values in the _data/sidebar.yml file. There are if
statements that check whether the conditions (as specified in the conditions.html file) are met. If the sidebar.yml item doesn’t have the right output, then it won’t get displayed in the sidebar. It would instead get skipped.
If the sidebar levels aren’t collapsed, usually your JavaScript is broken somewhere. Open the JavaScript Console and look to see where the problem is. If one script breaks, then other scripts will break too, so troubleshooting it is a little tricky.
+ +If the search isn’t working, check the JSON validity in the search.json file in your output folder. Usually something is invalid. Identify the problematic line, fix the file, or put search: exclude
in the frontmatter of the file to exclude it from search.
There are a variety of text editors available, but I like WebStorm the best because it groups files into projects, which makes it easy to find all instances of a text string, to do find and replace operations across the project, and more.
+ +If you decide to use WebStorm, here are a few tips on configuring the editor.
+ +By default, WebStorm comes packaged with a lot more functionality than you probably need. You can lighten the editor by removing some of the plugins. Go to WebStorm > Preferences > Plugins and clear the check boxes of plugins you don’t need.
+ +You can set the way the tab works, and whether it uses spaces or a tab character. For details, see Code Style. JavaScript in WebStorm’s help.
+ +On a Mac, go to WebStorm > Preferences > Editor > Code Style > Other File Types. Don’t select the “Use tab character” check box. Set 4 for the Tab size and Indent check boxes.
+ +On Windows, go to File > Settings > Editor > Code Style > Other File Types to access the same menu.
+ +Since you’ll be writing in Markdown, having color coding and other support for Markdown is important. Install the Markdown Support plugin by going to WebStorm > Preferences > Plugins and clicking Install JetBrains Plugin. Search for Markdown Support. You can also implement the Markdown Navigator plugin.
+ +Most likely you’ll want to enable soft wraps, which wraps lines rather than extending them out forever and requiring you to scroll horizontally to see the text. To enable softwrapping, go to WebStorm > Preferences > Editor > General and see the Soft Wraps section. Select the Use soft wraps in editor check box.
+ +When you’re searching for content, you don’t want to edit any file that appears in the _site directory. You can exclude a directory from Webstorm by right-clicking the directory and choosing Mark Directory As and then selecting Excluded.
+ +You can set the default number of spaces a tab sets, including whether Webstorm uses a tab character or spaces. You want spaces, and you want to set this to default number of spaces to 4
. Note that this is due to the way Kramdown handles the continuation
+of lists.
To set the indentation, see the “Tabs and Indents” topic in this Code Style. Javascript topic in Webstorm’s help.
+ +It can help to learn a few key shortcuts:
+ +Command | +Shortcuts | +
---|---|
Shift + Shift | +Allows you to find a file by searching for its name. | +
Shift + Command + F | +Find in whole project. (WebStorm uses the term “Find in path”.) | +
Shift + Command + R | +Replace in whole project. (Again, WebStorm calls it “Replace in path.”) | +
Command + F | +Find on page | +
Shift + R | +Replace on page | +
Right-click > Add to Favorites | +Allows you to add files to a Favorites section, which expands below the list of files in the project pane. | +
Shift + tab | +Applies outdenting (opposite of tabbing) | +
Shift + Function + F6 | +Rename a file | +
Command + Delete | +Delete a file | +
Command + 2 | +Show Favorites pane | +
Shift + Option + F | +Add to Favorites | +
When I want to find a file, I browse to the file in the preview site and copy the page name in the URL. Then in Webstorm I press Shift twice and paste in the file name. The search feature automatically highlights the file I want, and I press Enter.
+ +When you have the Git and Github integration, changed files appear in blue. This lets you know what needs to be committed to your repository.
+ +Rather than insert the frontmatter by hand each time, it’s much faster to simply create a Jekyll template. To create a Jekyll template in WebStorm:
+ +Right-click a file in the list of project files, and select New > Edit File Templates.
+ +If you don’t see the Edit File Templates option, you may need to create a file template first. Go to File > Default Settings > Editor > File and Code Templates. Create a new file template with an md extension, and then close and restart WebStorm. Then repeat this step and you will see the File Templates option appear in the right context menu.
+Name it something like Jekyll page. Insert the frontmatter you want, and save it.
+ +To use the Jekyll template, when you create a new file in your WebStorm project, you can select your Jekyll file template.
+By default, each time you type '
, WebStorm will pair the quote (creating two quotes). You can disable this by going to WebStorm > Preferences > Editor > Smartkeys. Clear the Insert pair quotes check box.
You can implement workflow maps at the top of your pages. This is helpful if you’re describing a process that involves multiple topics. See the following demos:
+ + + +Create an include at _includes/custom/usermap.html, where usermap.html contains the workflow and links you want. See the usermap.html as an example. It should look something like this:
+ +<div id="userMap">
+<div class="content"><a href="p2_sample1.html"><div class="box box1">Connect to ADB</div></a></div>
+<div class="arrow">→</div>
+<div class="content"><a href="p2_sample2.html"><div class="box box2">Download and Build the Starter Kit</div></a></div>
+<div class="arrow">→</div>
+<div class="content"><a href="p2_sample3.html"><div class="box box3">Take a Tour</div></a></div>
+<div class="arrow">→</div>
+<div class="content"><a href="p2_sample4.html"><div class="box box4">Load Your Widgets</div></a></div>
+<div class="arrow">→</div>
+<div class="content"><a href="p2_sample5.html"><div class="box box5">Query for Something</div></a></div>
+<div class="clearfix"></div>
+</div>
+
You can have only 5 possible workflow squares across. Also, the links must be manually coded HTML like those shown, not automated Markdown links. (This is because the boxes are linked.)
+Where you want the user maps to appear, add the sidebar properties shown in red below:
+ ++--- +title: Sample 1 Topic +keywords: sample +summary: "This is just a sample topic..." +sidebar: product2_sidebar +permalink: p2_sample1 +folder: product2 +simple_map: true +map_name: usermap +box_number: 1 +--- ++ +
In the page.html layout, the following code gets activated when simple_map
equals true
:
{% if page.simple_map == true %}
+
+<script>
+ $(document).ready ( function(){
+ $('.box{{page.box_number}}').addClass('active');
+ });
+</script>
+
+{% include custom/{{page.map_name}}.html %}
+
+{% endif %}
+
The script adds an active
class to the box number, which automatically makes the active workflow box become highlighted based on the page you’re viewing.
The map_name
gets used as the name of the included file.
The simpler user workflow allows for 5 workflow steps. If you have a more complex workflow, with multiple possible steps, branching, and more, consider using a complex workflow map. This map uses modals to show a list of instructions and links for each step.
+ +Create an include at _includes/custom/usermapcomplex.html, where usermapcomplex.html contains the workflow and links you want. See the usermapcomplex.html as an example. The code in that file simply implements Bootstrap modals to create the pop-up boxes. Add your custom content inside the modal body:
+ +<div class="modal-body">
+<p>This is just dummy text ... Your first steps should be to get started. You will need to do the following:</p>
+
+ <ul>
+ <li><a href="p2_sample6.html">Sample 6</a></li>
+ <li><a href="p2_sample7.html">Sample 7</a></li>
+ <li><a href="p2_sample8.html">Sample 8</a></li>
+ </ul>
+ <p>If you run into any of these setup issues, you must solve them before you can continue on.</p>
+
+ </div>
+
The existing usermapcomplex.html file just has 3 workflow square modals. If you need more, duplicate the modal code. In the duplicated code, make sure you make the following values in red unique (but the same within the same modal):
+ ++ <button type="button" class="btn btn-default btn-lg modalButton3" data-toggle="modal" data-target="#myModal3">Publish your app</button> + + <div class="modal fade" id="myModal3" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"> ++
For each topic where you want the modal to appear, insert the following properties in your frontmatter:
+ ++--- +title: Sample 6 Topic +keywords: sample +summary: "This is just a sample topic..." +sidebar: product2_sidebar +permalink: p2_sample6 +complex_map: true +map_name: usermapcomplex +box_number: 1 +toc: false +folder: product2 +--- ++ +
When your frontmatter contains complex_map
equal to true
, the following code gets activated in the page layout.html file:
In the page.html layout, the following code gets activated when `map` equals `true`:
+
+
{% if page.complex_map == true %}
+
+<script>
+ $(document).ready ( function(){
+ $('.modalButton{{page.box_number}}').addClass('active');
+ });
+</script>
+
+{% include custom/{{page.map_name}}.html %}
+
+{% endif %}
+``` ```
+
One of the most interesting features of Jekyll is the ability to separate out data elements from formatting elements using a combination of YAML and Liquid. This setup is most common when you’re trying to create a table of contents.
+ +Not many Jekyll themes actually have a robust table of contents, which is critical when you are creating any kind of documentation or reference material that has a lot of pages.
+ +Here’s the basic approach in creating a table of contents. You store your data items in a YAML file using YAML syntax. (I’ll go over more about YAML syntax in a later section.) You then create your HTML structure in another file, such as sidebar.html. You might leverage one of the many different table of content frameworks (such as Navgoco) that have been created for this HTML structure.
+ +Then, using Liquid syntax for loops and conditions, you access all of those values from the data file and splice them into HTML formatting. This will become more clear as we go through some examples.
+ +Rather than just jump into YAML at the most advanced level, I’m going to start from ground zero with an introduction to YAML and how you access basic values in your data files using Jekyll.
+ +Note that you don’t actually have to use Jekyll when using YAML. YAML is used in a lot of other systems and is a format completely independent of Jekyll. However, because Jekyll uses Liquid, it gives you a lot of power to parse through your YAML data and make use of it.
+ +YAML itself doesn’t do anything on its own — it’s just a way of storing your data in a specific structure that other utilities can parse.
+ +You can read about YAML from a lot of different sources. Here are some basic characteristics of YAML:
+ +I realize a lot of this vague and general; however, it will become a lot more clear as we go through some concrete examples.
+ +In the _data/mydoc folder, there’s a file called samplelist.yml. All of these examples come from that file.
+ +YAML:
+ +name:
+ husband: Tom
+ wife: Shannon
+
Markdown + Liquid:
+ +<p>Husband's name: {{site.data.samplelist.name.husband}}</p>
+<p>Wife's name: {{site.data.samplelist.name.wife}}</p>
+
Notice that in order to access the data file, you use site.data.samplelist
. mydoc
is the folder, and samplelist
is the name of the YAML file.
Result:
+ +Husband's name: Tom
+Wife's name: Shannon
+YAML:
+ +feedback: >
+ This is my feedback to you.
+ Even if I include linebreaks here,
+ all of the linebreaks will be removed when the value is inserted.
+
+block: |
+ This pipe does something a little different.
+ It preserves the breaks.
+ This is really helpful for code samples,
+ since you can format the code samples with
+ the appropriate
+
Markdown:
+ +<p><b>Feedback</b></p>
+<p>{{site.data.samplelist.feedback}}</p>
+
+<p><b>Block</b></p>
+<p>{{site.data.samplelist.block}}</p>
+
Result:
+ +Feedback
+This is my feedback to you. Even if I include linebreaks here, all of the linebreaks will be removed when the value is inserted. + +
+ +Block
+This pipe does something a little different. +It preserves the breaks. +This is really helpful for code samples, +since you can format the code samples with + the appropriate + white spacing.
+The right angle bracket >
allows you to put the value on the next lines (which must be indented). Even if you create a line break, the output will remove all of those line breaks, creating one paragraph.
The pipe |
functions like the angle bracket in that it allows you to put the values for the mapping on the next lines (which again must be indented). However, the pipe does preserve all of the line breaks that you use. This makes the pipe method ideal for storing code samples.
YAML:
+ +bikes:
+ - title: mountain bikes
+ - title: road bikes
+ - title: hybrid bikes
+
Markdown + Liquid:
+ +<ul>
+{% for item in site.data.samplelist.bikes %}
+<li>{{item.title}}</li>
+{% endfor %}
+</ul>
+
Result:
+ +Here we use a “for” loop to get each item in the bikes list. By using .title
we only get the title
property from each list item.
YAML:
+ +salesteams:
+- title: Regions
+ subfolderitems:
+ - location: US
+ - location: Spain
+ - location: France
+
Markdown + Liquid:
+ +{% for item in site.data.samplelist.salesteams %}
+<h3>{{item.title}}</h3>
+<ul>
+{% for entry in item.subitems %}
+<li>{{entry.location}}</li>
+{% endfor %}
+</ul>
+{% endfor %}
+
Result:
+ +Hopefully you can start to see how to wrap more complex formatting around the YAML content. When you use a “for” loop, you choose the variable of what to call the list items. The variable you choose to use becomes how you access the properties of each list item. In this case, I decided to use the variable item
. In order to get each property of the list item, I used item.subitems
.
Each list item starts with the hyphen –
. You cannot directly access the list item by referring to a mapping. You only loop through the list items. If you wanted to access the list item, you would have to use something like [1]
, which is how you access the position in an array. You cannot access a list item like you can access a mapping key.
YAML:
+ +toc:
+ - title: Group 1
+ subfolderitems:
+ - page: Thing 1
+ - page: Thing 2
+ - page: Thing 3
+ - title: Group 2
+ subfolderitems:
+ - page: Piece 1
+ - page: Piece 2
+ - page: Piece 3
+ - title: Group 3
+ subfolderitems:
+ - page: Widget 1
+ - page: Widget 2 it's
+ - page: Widget 3
+
Markdown + Liquid:
+ +{% for item in site.data.samplelist.toc %}
+<h3>{{item.title}}</h3>
+<ul>
+{% for entry in item.subfolderitems %}
+<li>{{entry.page}}</li>
+{% endfor %}
+</ul>
+{% endfor %}
+
Result:
+ +This example is similar to the previous one, but it’s more developed as a real table of contents.
+ +YAML:
+ +something: &hello Greetings earthling!
+myref: *hello
+
Markdown:
+ +{{ site.data.samplelist.myref }}
+
Result:
+ +This example is notably different. Here I’m showing how to reuse content in YAML file. If you have the same value that you want to repeat in other mappings, you can create a variable using the &
symbol. Then when you want to refer to that variable’s value, you use an asterisk *
followed by the name of the variable.
In this case the variable is &hello
and its value is Greetings earthling!
In order to reuse that same value, you just type *hello
.
I don’t use variables much, but that’s not to say they couldn’t be highly useful. For example, let’s say you put name of the product in parentheses after each title (because you have various products that you’re providing documentation for in the same site). You could create a variable for that product name so that if you change how you’re referring to it, you wouldn’t have to change all instances of it in your YAML file.
+ +YAML:
+ +about:
+ - zero
+ - one
+ - two
+ - three
+
Markdown:
+ +{{ site.data.samplelist.about[0] }}
+
Result:
+You can see that I’m accessing one of the items in the list using [0]
. This refers to the position in the array where a list item is. Like most programming languages, you start counting at zero, not one.
I wanted to include this example because it points to the challenge in getting a value from a specific list item. You can’t just call out a specific item in a list like you can with a mapping. This is why you usually iterate through the list items using a “for” loop.
+ +YAML:
+ +numbercolors:
+ - zero:
+ properties: red
+ - one:
+ properties: yellow
+ - two:
+ properties: green
+ - three:
+ properties: blue
+
Markdown + Liquid:
+ +{{ site.data.samplelist.numbercolors[0].properties }}
+
Result:
+This example is similar as before; however, in this case were getting a specific property from the list item in the zero position.
+ +YAML:
+ +mypages:
+- section1: Section 1
+ audience: developers
+ product: acme
+ url: facebook.com
+- section2: Section 2
+ audience: writers
+ product: acme
+ url: google.com
+- section3: Section 3
+ audience: developers
+ product: acme
+ url: amazon.com
+- section4: Section 4
+ audience: writers
+ product: gizmo
+ url: apple.com
+- section5: Section 5
+ audience: writers
+ product: acme
+ url: microsoft.com
+
Markdown + Liquid:
+ +<ul>
+{% for sec in site.data.samplelist.mypages %}
+{% if sec.audience == "writers" %}
+<li>{{sec.url}}</li>
+{% endif %}
+{% endfor %}
+</ul>
+
+
Result:
+This example shows how you can use conditions in order to selectively get the YAML content. In your table of contents, you might have a lot of different pages. However, you might only want to get the pages for a particular audience. Conditions lets you get only the items that meet those audience attributes.
+ +Now let’s adjust the condition just a little. Let’s add a second condition so that the audience
property has to be writers
and the product
property has to be gizmo. This is how you would write it:
<ul>
+{% for sec in site.data.samplelist.mypages %}
+{% if sec.audience == "writers" and sec.product == "gizmo" %}
+<li>{{sec.url}}</li>
+{% endif %}
+{% endfor %}
+</ul>
+
And here is the result:
+ +For more examples and explanations, see this helpful post on tournemille.com: How to create data-driven navigation in Jekyll.
+ + + + + + + + + + + + + + +Theme updates:
+ +Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry’s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries...
+ + + + +Theme updates: + + + Permalinks + Kramdown + URL specified in config file + removed PDF output + removed some of the alternative layouts + added blog feature + sidebars configurable per page + + +
+ + + + +This is just a test post from the previous year. + +
+ + + + + +See more posts from the News Archive.
+ +Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quae repudiandae fugiat illo cupiditate excepturi esse officiis consectetur, laudantium qui voluptatem. Ad necessitatibus velit, accusantium expedita debitis impedit rerum totam id. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Natus quibusdam recusandae illum, nesciunt, architecto, saepe facere, voluptas eum incidunt dolores magni itaque autem neque velit in. At quia quaerat asperiores.
+Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quae repudiandae fugiat illo cupiditate excepturi esse officiis consectetur, laudantium qui voluptatem. Ad necessitatibus velit, accusantium expedita debitis impedit rerum totam id. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Natus quibusdam recusandae illum, nesciunt, architecto, saepe facere, voluptas eum incidunt dolores magni itaque autem neque velit in. At quia quaerat asperiores.
+Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quae repudiandae fugiat illo cupiditate excepturi esse officiis consectetur, laudantium qui voluptatem. Ad necessitatibus velit, accusantium expedita debitis impedit rerum totam id. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Natus quibusdam recusandae illum, nesciunt, architecto, saepe facere, voluptas eum incidunt dolores magni itaque autem neque velit in. At quia quaerat asperiores.
+Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quae repudiandae fugiat illo cupiditate excepturi esse officiis consectetur, laudantium qui voluptatem. Ad necessitatibus velit, accusantium expedita debitis impedit rerum totam id. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Natus quibusdam recusandae illum, nesciunt, architecto, saepe facere, voluptas eum incidunt dolores magni itaque autem neque velit in. At quia quaerat asperiores.
+Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quae repudiandae fugiat illo cupiditate excepturi esse officiis consectetur, laudantium qui voluptatem. Ad necessitatibus velit, accusantium expedita debitis impedit rerum totam id. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Natus quibusdam recusandae illum, nesciunt, architecto, saepe facere, voluptas eum incidunt dolores magni itaque autem neque velit in. At quia quaerat asperiores.
+Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quae repudiandae fugiat illo cupiditate excepturi esse officiis consectetur, laudantium qui voluptatem. Ad necessitatibus velit, accusantium expedita debitis impedit rerum totam id. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Natus quibusdam recusandae illum, nesciunt, architecto, saepe facere, voluptas eum incidunt dolores magni itaque autem neque velit in. At quia quaerat asperiores.
+Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quae repudiandae fugiat illo cupiditate excepturi esse officiis consectetur, laudantium qui voluptatem. Ad necessitatibus velit, accusantium expedita debitis impedit rerum totam id. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Natus quibusdam recusandae illum, nesciunt, architecto, saepe facere, voluptas eum incidunt dolores magni itaque autem neque velit in. At quia quaerat asperiores.
+Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quae repudiandae fugiat illo cupiditate excepturi esse officiis consectetur, laudantium qui voluptatem. Ad necessitatibus velit, accusantium expedita debitis impedit rerum totam id. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Natus quibusdam recusandae illum, nesciunt, architecto, saepe facere, voluptas eum incidunt dolores magni itaque autem neque velit in. At quia quaerat asperiores.
+Lorem ipsum dolor sit amet, consectetur adipisicing elit. Illo itaque ipsum sit harum.
+Lorem ipsum dolor sit amet, consectetur adipisicing elit. Illo itaque ipsum sit harum.
+Lorem ipsum dolor sit amet, consectetur adipisicing elit. Illo itaque ipsum sit harum.
+Lorem ipsum dolor sit amet, consectetur adipisicing elit. Illo itaque ipsum sit harum.
+Lorem ipsum dolor sit amet, consectetur adipisicing elit. Illo itaque ipsum sit harum.
+Lorem ipsum dolor sit amet, consectetur adipisicing elit. Illo itaque ipsum sit harum.
+Lorem ipsum dolor sit amet, consectetur adipisicing elit. Illo itaque ipsum sit harum.
+Lorem ipsum dolor sit amet, consectetur adipisicing elit. Illo itaque ipsum sit harum.
+Lorem ipsum dolor sit amet, consectetur adipisicing elit. Illo itaque ipsum sit harum.
+“Lorem Ipsum” is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry’s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
+ +It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using ‘Content here, content here’, making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for ‘lorem ipsum’ will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).
+ +Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of “de Finibus Bonorum et Malorum” (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, “Lorem ipsum dolor sit amet..”, comes from a line in section 1.10.32.
+ +The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from “de Finibus Bonorum et Malorum” by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham.
+ +There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don’t look even slightly believable. If you are going to use a passage of Lorem Ipsum, you need to be sure there isn’t anything embarrassing hidden in the middle of text. All the Lorem Ipsum generators on the Internet tend to repeat predefined chunks as necessary, making this the first true generator on the Internet. It uses a dictionary of over 200 Latin words, combined with a handful of model sentence structures, to generate Lorem Ipsum which looks reasonable. The generated Lorem Ipsum is therefore always free from repetition, injected humour, or non-characteristic words etc.
+ + + + + + + + + + + + + + +Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry’s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
+ +It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using ‘Content here, content here’, making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for ‘lorem ipsum’ will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).
+ +Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of “de Finibus Bonorum et Malorum” (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, “Lorem ipsum dolor sit amet..”, comes from a line in section 1.10.32.
+ +The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from “de Finibus Bonorum et Malorum” by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham.
+ +There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don’t look even slightly believable. If you are going to use a passage of Lorem Ipsum, you need to be sure there isn’t anything embarrassing hidden in the middle of text. All the Lorem Ipsum generators on the Internet tend to repeat predefined chunks as necessary, making this the first true generator on the Internet. It uses a dictionary of over 200 Latin words, combined with a handful of model sentence structures, to generate Lorem Ipsum which looks reasonable. The generated Lorem Ipsum is therefore always free from repetition, injected humour, or non-characteristic words etc.
+ + + + + + + + + + + + + + +Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry’s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
+ +It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using ‘Content here, content here’, making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for ‘lorem ipsum’ will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).
+ +Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of “de Finibus Bonorum et Malorum” (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, “Lorem ipsum dolor sit amet..”, comes from a line in section 1.10.32.
+ +The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from “de Finibus Bonorum et Malorum” by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham.
+ +There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don’t look even slightly believable. If you are going to use a passage of Lorem Ipsum, you need to be sure there isn’t anything embarrassing hidden in the middle of text. All the Lorem Ipsum generators on the Internet tend to repeat predefined chunks as necessary, making this the first true generator on the Internet. It uses a dictionary of over 200 Latin words, combined with a handful of model sentence structures, to generate Lorem Ipsum which looks reasonable. The generated Lorem Ipsum is therefore always free from repetition, injected humour, or non-characteristic words etc.
+ + + + + + + + + + + + + + +Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry’s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
+ +It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using ‘Content here, content here’, making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for ‘lorem ipsum’ will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).
+ +Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of “de Finibus Bonorum et Malorum” (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, “Lorem ipsum dolor sit amet..”, comes from a line in section 1.10.32.
+ +The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from “de Finibus Bonorum et Malorum” by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham.
+ +There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don’t look even slightly believable. If you are going to use a passage of Lorem Ipsum, you need to be sure there isn’t anything embarrassing hidden in the middle of text. All the Lorem Ipsum generators on the Internet tend to repeat predefined chunks as necessary, making this the first true generator on the Internet. It uses a dictionary of over 200 Latin words, combined with a handful of model sentence structures, to generate Lorem Ipsum which looks reasonable. The generated Lorem Ipsum is therefore always free from repetition, injected humour, or non-characteristic words etc.
+ + + + + + + + + + + + + + +Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry’s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
+ +It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using ‘Content here, content here’, making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for ‘lorem ipsum’ will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).
+ +Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of “de Finibus Bonorum et Malorum” (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, “Lorem ipsum dolor sit amet..”, comes from a line in section 1.10.32.
+ +The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from “de Finibus Bonorum et Malorum” by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham.
+ +There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don’t look even slightly believable. If you are going to use a passage of Lorem Ipsum, you need to be sure there isn’t anything embarrassing hidden in the middle of text. All the Lorem Ipsum generators on the Internet tend to repeat predefined chunks as necessary, making this the first true generator on the Internet. It uses a dictionary of over 200 Latin words, combined with a handful of model sentence structures, to generate Lorem Ipsum which looks reasonable. The generated Lorem Ipsum is therefore always free from repetition, injected humour, or non-characteristic words etc.
+ + + + + + + + + + + + + + +Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry’s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
+ +It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using ‘Content here, content here’, making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for ‘lorem ipsum’ will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).
+ +Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of “de Finibus Bonorum et Malorum” (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, “Lorem ipsum dolor sit amet..”, comes from a line in section 1.10.32.
+ +The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from “de Finibus Bonorum et Malorum” by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham.
+ +There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don’t look even slightly believable. If you are going to use a passage of Lorem Ipsum, you need to be sure there isn’t anything embarrassing hidden in the middle of text. All the Lorem Ipsum generators on the Internet tend to repeat predefined chunks as necessary, making this the first true generator on the Internet. It uses a dictionary of over 200 Latin words, combined with a handful of model sentence structures, to generate Lorem Ipsum which looks reasonable. The generated Lorem Ipsum is therefore always free from repetition, injected humour, or non-characteristic words etc.
+ + + + + + + + + + + + + + +Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry’s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
+ +It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using ‘Content here, content here’, making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for ‘lorem ipsum’ will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).
+ +Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of “de Finibus Bonorum et Malorum” (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, “Lorem ipsum dolor sit amet..”, comes from a line in section 1.10.32.
+ +The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from “de Finibus Bonorum et Malorum” by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham.
+ +There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don’t look even slightly believable. If you are going to use a passage of Lorem Ipsum, you need to be sure there isn’t anything embarrassing hidden in the middle of text. All the Lorem Ipsum generators on the Internet tend to repeat predefined chunks as necessary, making this the first true generator on the Internet. It uses a dictionary of over 200 Latin words, combined with a handful of model sentence structures, to generate Lorem Ipsum which looks reasonable. The generated Lorem Ipsum is therefore always free from repetition, injected humour, or non-characteristic words etc.
+ + + + + + + + + + + + + + +Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quae repudiandae fugiat illo cupiditate excepturi esse officiis consectetur, laudantium qui voluptatem. Ad necessitatibus velit, accusantium expedita debitis impedit rerum totam id. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Natus quibusdam recusandae illum, nesciunt, architecto, saepe facere, voluptas eum incidunt dolores magni itaque autem neque velit in. At quia quaerat asperiores.
+Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quae repudiandae fugiat illo cupiditate excepturi esse officiis consectetur, laudantium qui voluptatem. Ad necessitatibus velit, accusantium expedita debitis impedit rerum totam id. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Natus quibusdam recusandae illum, nesciunt, architecto, saepe facere, voluptas eum incidunt dolores magni itaque autem neque velit in. At quia quaerat asperiores.
+Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quae repudiandae fugiat illo cupiditate excepturi esse officiis consectetur, laudantium qui voluptatem. Ad necessitatibus velit, accusantium expedita debitis impedit rerum totam id. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Natus quibusdam recusandae illum, nesciunt, architecto, saepe facere, voluptas eum incidunt dolores magni itaque autem neque velit in. At quia quaerat asperiores.
+Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quae repudiandae fugiat illo cupiditate excepturi esse officiis consectetur, laudantium qui voluptatem. Ad necessitatibus velit, accusantium expedita debitis impedit rerum totam id. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Natus quibusdam recusandae illum, nesciunt, architecto, saepe facere, voluptas eum incidunt dolores magni itaque autem neque velit in. At quia quaerat asperiores.
+Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quae repudiandae fugiat illo cupiditate excepturi esse officiis consectetur, laudantium qui voluptatem. Ad necessitatibus velit, accusantium expedita debitis impedit rerum totam id. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Natus quibusdam recusandae illum, nesciunt, architecto, saepe facere, voluptas eum incidunt dolores magni itaque autem neque velit in. At quia quaerat asperiores.
+Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quae repudiandae fugiat illo cupiditate excepturi esse officiis consectetur, laudantium qui voluptatem. Ad necessitatibus velit, accusantium expedita debitis impedit rerum totam id. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Natus quibusdam recusandae illum, nesciunt, architecto, saepe facere, voluptas eum incidunt dolores magni itaque autem neque velit in. At quia quaerat asperiores.
+Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quae repudiandae fugiat illo cupiditate excepturi esse officiis consectetur, laudantium qui voluptatem. Ad necessitatibus velit, accusantium expedita debitis impedit rerum totam id. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Natus quibusdam recusandae illum, nesciunt, architecto, saepe facere, voluptas eum incidunt dolores magni itaque autem neque velit in. At quia quaerat asperiores.
+Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quae repudiandae fugiat illo cupiditate excepturi esse officiis consectetur, laudantium qui voluptatem. Ad necessitatibus velit, accusantium expedita debitis impedit rerum totam id. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Natus quibusdam recusandae illum, nesciunt, architecto, saepe facere, voluptas eum incidunt dolores magni itaque autem neque velit in. At quia quaerat asperiores.
+Lorem ipsum dolor sit amet, consectetur adipisicing elit. Illo itaque ipsum sit harum.
+Lorem ipsum dolor sit amet, consectetur adipisicing elit. Illo itaque ipsum sit harum.
+Lorem ipsum dolor sit amet, consectetur adipisicing elit. Illo itaque ipsum sit harum.
+Lorem ipsum dolor sit amet, consectetur adipisicing elit. Illo itaque ipsum sit harum.
+Lorem ipsum dolor sit amet, consectetur adipisicing elit. Illo itaque ipsum sit harum.
+Lorem ipsum dolor sit amet, consectetur adipisicing elit. Illo itaque ipsum sit harum.
+Lorem ipsum dolor sit amet, consectetur adipisicing elit. Illo itaque ipsum sit harum.
+Lorem ipsum dolor sit amet, consectetur adipisicing elit. Illo itaque ipsum sit harum.
+Lorem ipsum dolor sit amet, consectetur adipisicing elit. Illo itaque ipsum sit harum.
+Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry’s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
+ +It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using ‘Content here, content here’, making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for ‘lorem ipsum’ will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).
+ +Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of “de Finibus Bonorum et Malorum” (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, “Lorem ipsum dolor sit amet..”, comes from a line in section 1.10.32.
+ +The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from “de Finibus Bonorum et Malorum” by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham.
+ +There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don’t look even slightly believable. If you are going to use a passage of Lorem Ipsum, you need to be sure there isn’t anything embarrassing hidden in the middle of text. All the Lorem Ipsum generators on the Internet tend to repeat predefined chunks as necessary, making this the first true generator on the Internet. It uses a dictionary of over 200 Latin words, combined with a handful of model sentence structures, to generate Lorem Ipsum which looks reasonable. The generated Lorem Ipsum is therefore always free from repetition, injected humour, or non-characteristic words etc.
+ + + + + + + + + + + + + + +Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry’s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
+ +It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using ‘Content here, content here’, making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for ‘lorem ipsum’ will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).
+ +Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of “de Finibus Bonorum et Malorum” (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, “Lorem ipsum dolor sit amet..”, comes from a line in section 1.10.32.
+ +The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from “de Finibus Bonorum et Malorum” by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham.
+ +There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don’t look even slightly believable. If you are going to use a passage of Lorem Ipsum, you need to be sure there isn’t anything embarrassing hidden in the middle of text. All the Lorem Ipsum generators on the Internet tend to repeat predefined chunks as necessary, making this the first true generator on the Internet. It uses a dictionary of over 200 Latin words, combined with a handful of model sentence structures, to generate Lorem Ipsum which looks reasonable. The generated Lorem Ipsum is therefore always free from repetition, injected humour, or non-characteristic words etc.
+ + + + + + + + + + + + + + +Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry’s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
+ +It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using ‘Content here, content here’, making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for ‘lorem ipsum’ will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).
+ +Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of “de Finibus Bonorum et Malorum” (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, “Lorem ipsum dolor sit amet..”, comes from a line in section 1.10.32.
+ +The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from “de Finibus Bonorum et Malorum” by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham.
+ +There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don’t look even slightly believable. If you are going to use a passage of Lorem Ipsum, you need to be sure there isn’t anything embarrassing hidden in the middle of text. All the Lorem Ipsum generators on the Internet tend to repeat predefined chunks as necessary, making this the first true generator on the Internet. It uses a dictionary of over 200 Latin words, combined with a handful of model sentence structures, to generate Lorem Ipsum which looks reasonable. The generated Lorem Ipsum is therefore always free from repetition, injected humour, or non-characteristic words etc.
+ + + + + + + + + + + + + + +Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry’s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
+ +It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using ‘Content here, content here’, making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for ‘lorem ipsum’ will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).
+ +Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of “de Finibus Bonorum et Malorum” (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, “Lorem ipsum dolor sit amet..”, comes from a line in section 1.10.32.
+ +The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from “de Finibus Bonorum et Malorum” by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham.
+ +There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don’t look even slightly believable. If you are going to use a passage of Lorem Ipsum, you need to be sure there isn’t anything embarrassing hidden in the middle of text. All the Lorem Ipsum generators on the Internet tend to repeat predefined chunks as necessary, making this the first true generator on the Internet. It uses a dictionary of over 200 Latin words, combined with a handful of model sentence structures, to generate Lorem Ipsum which looks reasonable. The generated Lorem Ipsum is therefore always free from repetition, injected humour, or non-characteristic words etc.
+ + + + + + + + + + + + + + +Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry’s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
+ +It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using ‘Content here, content here’, making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for ‘lorem ipsum’ will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).
+ +Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of “de Finibus Bonorum et Malorum” (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, “Lorem ipsum dolor sit amet..”, comes from a line in section 1.10.32.
+ +The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from “de Finibus Bonorum et Malorum” by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham.
+ +There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don’t look even slightly believable. If you are going to use a passage of Lorem Ipsum, you need to be sure there isn’t anything embarrassing hidden in the middle of text. All the Lorem Ipsum generators on the Internet tend to repeat predefined chunks as necessary, making this the first true generator on the Internet. It uses a dictionary of over 200 Latin words, combined with a handful of model sentence structures, to generate Lorem Ipsum which looks reasonable. The generated Lorem Ipsum is therefore always free from repetition, injected humour, or non-characteristic words etc.
+ + + + + + + + + + + + + + +Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry’s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
+ +It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using ‘Content here, content here’, making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for ‘lorem ipsum’ will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).
+ +Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of “de Finibus Bonorum et Malorum” (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, “Lorem ipsum dolor sit amet..”, comes from a line in section 1.10.32.
+ +The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from “de Finibus Bonorum et Malorum” by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham.
+ +There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don’t look even slightly believable. If you are going to use a passage of Lorem Ipsum, you need to be sure there isn’t anything embarrassing hidden in the middle of text. All the Lorem Ipsum generators on the Internet tend to repeat predefined chunks as necessary, making this the first true generator on the Internet. It uses a dictionary of over 200 Latin words, combined with a handful of model sentence structures, to generate Lorem Ipsum which looks reasonable. The generated Lorem Ipsum is therefore always free from repetition, injected humour, or non-characteristic words etc.
+ + + + + + + + + + + + + + +Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry’s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
+ +It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using ‘Content here, content here’, making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for ‘lorem ipsum’ will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).
+ +Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of “de Finibus Bonorum et Malorum” (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, “Lorem ipsum dolor sit amet..”, comes from a line in section 1.10.32.
+ +The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from “de Finibus Bonorum et Malorum” by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham.
+ +There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don’t look even slightly believable. If you are going to use a passage of Lorem Ipsum, you need to be sure there isn’t anything embarrassing hidden in the middle of text. All the Lorem Ipsum generators on the Internet tend to repeat predefined chunks as necessary, making this the first true generator on the Internet. It uses a dictionary of over 200 Latin words, combined with a handful of model sentence structures, to generate Lorem Ipsum which looks reasonable. The generated Lorem Ipsum is therefore always free from repetition, injected humour, or non-characteristic words etc.
+ + + + + + + + + + + + + + +Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry’s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
+ +It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using ‘Content here, content here’, making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for ‘lorem ipsum’ will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).
+ +Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of “de Finibus Bonorum et Malorum” (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, “Lorem ipsum dolor sit amet..”, comes from a line in section 1.10.32.
+ +The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from “de Finibus Bonorum et Malorum” by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham.
+ +There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don’t look even slightly believable. If you are going to use a passage of Lorem Ipsum, you need to be sure there isn’t anything embarrassing hidden in the middle of text. All the Lorem Ipsum generators on the Internet tend to repeat predefined chunks as necessary, making this the first true generator on the Internet. It uses a dictionary of over 200 Latin words, combined with a handful of model sentence structures, to generate Lorem Ipsum which looks reasonable. The generated Lorem Ipsum is therefore always free from repetition, injected humour, or non-characteristic words etc.
+ + + + + + + + + + + + + + +Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry’s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
+ +It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using ‘Content here, content here’, making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for ‘lorem ipsum’ will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).
+ +Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of “de Finibus Bonorum et Malorum” (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, “Lorem ipsum dolor sit amet..”, comes from a line in section 1.10.32.
+ +The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from “de Finibus Bonorum et Malorum” by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham.
+ +There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don’t look even slightly believable. If you are going to use a passage of Lorem Ipsum, you need to be sure there isn’t anything embarrassing hidden in the middle of text. All the Lorem Ipsum generators on the Internet tend to repeat predefined chunks as necessary, making this the first true generator on the Internet. It uses a dictionary of over 200 Latin words, combined with a handful of model sentence structures, to generate Lorem Ipsum which looks reasonable. The generated Lorem Ipsum is therefore always free from repetition, injected humour, or non-characteristic words etc.
+ + + + + + + + + + + + + + +Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry’s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
+ +It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using ‘Content here, content here’, making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for ‘lorem ipsum’ will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).
+ +Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of “de Finibus Bonorum et Malorum” (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, “Lorem ipsum dolor sit amet..”, comes from a line in section 1.10.32.
+ +The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from “de Finibus Bonorum et Malorum” by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham.
+ +There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don’t look even slightly believable. If you are going to use a passage of Lorem Ipsum, you need to be sure there isn’t anything embarrassing hidden in the middle of text. All the Lorem Ipsum generators on the Internet tend to repeat predefined chunks as necessary, making this the first true generator on the Internet. It uses a dictionary of over 200 Latin words, combined with a handful of model sentence structures, to generate Lorem Ipsum which looks reasonable. The generated Lorem Ipsum is therefore always free from repetition, injected humour, or non-characteristic words etc.
+ + + + + + + + + + + + + + +Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry’s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
+ +It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using ‘Content here, content here’, making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for ‘lorem ipsum’ will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).
+ +Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of “de Finibus Bonorum et Malorum” (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, “Lorem ipsum dolor sit amet..”, comes from a line in section 1.10.32.
+ +The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from “de Finibus Bonorum et Malorum” by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham.
+ +There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don’t look even slightly believable. If you are going to use a passage of Lorem Ipsum, you need to be sure there isn’t anything embarrassing hidden in the middle of text. All the Lorem Ipsum generators on the Internet tend to repeat predefined chunks as necessary, making this the first true generator on the Internet. It uses a dictionary of over 200 Latin words, combined with a handful of model sentence structures, to generate Lorem Ipsum which looks reasonable. The generated Lorem Ipsum is therefore always free from repetition, injected humour, or non-characteristic words etc.
+ + + + + + + + + + + + + + +Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry’s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
+ +It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using ‘Content here, content here’, making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for ‘lorem ipsum’ will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).
+ +Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of “de Finibus Bonorum et Malorum” (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, “Lorem ipsum dolor sit amet..”, comes from a line in section 1.10.32.
+ +The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from “de Finibus Bonorum et Malorum” by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham.
+ +There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don’t look even slightly believable. If you are going to use a passage of Lorem Ipsum, you need to be sure there isn’t anything embarrassing hidden in the middle of text. All the Lorem Ipsum generators on the Internet tend to repeat predefined chunks as necessary, making this the first true generator on the Internet. It uses a dictionary of over 200 Latin words, combined with a handful of model sentence structures, to generate Lorem Ipsum which looks reasonable. The generated Lorem Ipsum is therefore always free from repetition, injected humour, or non-characteristic words etc.
+ + + + + + + + + + + + + + +Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry’s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
+ +It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using ‘Content here, content here’, making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for ‘lorem ipsum’ will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).
+ +Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of “de Finibus Bonorum et Malorum” (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, “Lorem ipsum dolor sit amet..”, comes from a line in section 1.10.32.
+ +The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from “de Finibus Bonorum et Malorum” by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham.
+ +There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don’t look even slightly believable. If you are going to use a passage of Lorem Ipsum, you need to be sure there isn’t anything embarrassing hidden in the middle of text. All the Lorem Ipsum generators on the Internet tend to repeat predefined chunks as necessary, making this the first true generator on the Internet. It uses a dictionary of over 200 Latin words, combined with a handful of model sentence structures, to generate Lorem Ipsum which looks reasonable. The generated Lorem Ipsum is therefore always free from repetition, injected humour, or non-characteristic words etc.
+ + + + + + + + + + + + + + +Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry’s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
+ +It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using ‘Content here, content here’, making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for ‘lorem ipsum’ will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).
+ +Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of “de Finibus Bonorum et Malorum” (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, “Lorem ipsum dolor sit amet..”, comes from a line in section 1.10.32.
+ +The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from “de Finibus Bonorum et Malorum” by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham.
+ +There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don’t look even slightly believable. If you are going to use a passage of Lorem Ipsum, you need to be sure there isn’t anything embarrassing hidden in the middle of text. All the Lorem Ipsum generators on the Internet tend to repeat predefined chunks as necessary, making this the first true generator on the Internet. It uses a dictionary of over 200 Latin words, combined with a handful of model sentence structures, to generate Lorem Ipsum which looks reasonable. The generated Lorem Ipsum is therefore always free from repetition, injected humour, or non-characteristic words etc.
+ + + + + + + + + + + + + + +Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry’s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries
+ +but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
+ +Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry’s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries
+ + +The following pages and posts are tagged with
+Title | Type | Excerpt |
---|
The following pages and posts are tagged with
+Title | Type | Excerpt |
---|---|---|
Collections | +Page | +Collections are useful if you want to loop through a special folder of pages that you make available in a content API. You could also use collections if you ... | +
Generating PDFs | +Page | +You can generate a PDF from your Jekyll project. You do this by creating a web version of your project that is printer friendly. You then use utility called ... | +
Help APIs and UI tooltips | +Page | +You can loop through files and generate a JSON file that developers can consume like a help API. Developers can pull in values from the JSON into interface e... | +
Pages | +Page | +This theme primarily uses pages. You need to make sure your pages have the appropriate frontmatter. One frontmatter tag your users might find helpful is the ... | +
Posts | +Page | +You can use posts when you want to create blogs or news type of content. | +
Series | +Page | +You can automatically link together topics belonging to the same series. This helps users know the context within a particular process. | +
The following pages and posts are tagged with
+Title | Type | Excerpt |
---|---|---|
Tooltips | +Page | +You can add tooltips to any word, such as an acronym or specialized term. Tooltips work well for glossary definitions, because you don't have to keep repeati... | +
Alerts | +Page | +You can insert notes, tips, warnings, and important alerts in your content. These notes make use of Bootstrap styling and are available through data referenc... | +
Code samples | +Page | +You can use fenced code blocks with the language specified after the first set of backtick fences. | +
Glossary layout | +Page | +Your glossary page can take advantage of definitions stored in a data file. This gives you the ability to reuse the same definition in multiple places. Addit... | +
Links | +Page | +When creating links, you can use standard HTML or Markdown formatting. However, you can also implement an automated approach to linking that makes linking mu... | +
Icons | +Page | +You can integrate font icons through the Font Awesome and Glyphical Halflings libraries. These libraries allow you to embed icons through their libraries del... | +
Images | +Page | +Store images in the images folder and use the image.html include to insert images. This include has several options, including figcaptions, that extract the ... | +
Labels | +Page | +Labels are just a simple Bootstrap component that you can include in your pages as needed. They represent one of many Bootstrap options you can include in yo... | +
Lists | +Page | +This page shows how to create both bulleted and numbered lists | +
Navtabs | +Page | +Navtabs provide a tab-based navagation directly in your content, allowing users to click from tab to tab to see different panels of content. Navtabs are espe... | +
Pages | +Page | +This theme primarily uses pages. You need to make sure your pages have the appropriate frontmatter. One frontmatter tag your users might find helpful is the ... | +
Posts | +Page | +You can use posts when you want to create blogs or news type of content. | +
Syntax highlighting | +Page | +You can apply syntax highlighting to your code. This theme uses pygments and applies color coding based on the lexer you specify. | +
Tables | +Page | +You can format tables using either multimarkdown syntax or HTML. You can also use jQuery datatables (a plugin) if you need more robust tables. | +
Workflow maps | +Page | +Version 6.0 of the Documentation theme for Jekyll reverts back to relative links so you can view the files offline. Additionally, you can store pages in subd... | +
YAML tutorial in the context of Jekyll | +Page | +YAML is a format that relies on white spacing to separate out the various elements of content. Jekyll lets you use Liquid with YAML as a way to parse through... | +
The following pages and posts are tagged with
+Title | Type | Excerpt |
---|---|---|
Getting started with the Documentation Theme for Jekyll | +Page | +These brief instructions will help you get started quickly with the theme. The other topics in this help provide additional information and detail about work... | +
About the theme's author | +Page | +I have used this theme for projects that I've worked on as a professional technical writer. | +
About Ruby, Gems, Bundler, and other prerequisites | +Page | +Ruby is a programming language you must have on your computer in order to build Jekyll locally. Ruby has various gems (or plugins) that provide various funct... | +
Install Jekyll on Mac | +Page | +Installation of Jekyll on Mac is usually less problematic than on Windows. However, you may run into permissions issues with Ruby that you must overcome. You... | +
Pages | +Page | +This theme primarily uses pages. You need to make sure your pages have the appropriate frontmatter. One frontmatter tag your users might find helpful is the ... | +
Posts | +Page | +You can use posts when you want to create blogs or news type of content. | +
Release notes 5.0 | +Page | +Version 5.0 of the Documentation theme for Jekyll changes some fundamental ways the theme works to provide product-specific sidebars, intended to accommodate... | +
Release notes 6.0 | +Page | +Version 6.0 of the Documentation theme for Jekyll, released July 4, 2016, implements relative links so you can view the files offline or on any server withou... | +
Sidebar Navigation | +Page | +The sidebar navigation uses a jQuery component called Navgoco. The sidebar is a somewhat complex part of the theme that remembers your current page, highligh... | +
Support | +Page | +Contact me for any support issues. | +
Supported features | +Page | +If you're not sure whether Jekyll and this theme will support your requirements, this list provides a semi-comprehensive overview of available features. | +
Sample post | +Post | +This is some summary frontmatter for my sample post. | +
The following pages and posts are tagged with
+Title | Type | Excerpt |
---|
The following pages and posts are tagged with
+Title | Type | Excerpt |
---|---|---|
Commenting on files | +Page | +You can add a button to your pages that allows people to add comments. | +
Links | +Page | +When creating links, you can use standard HTML or Markdown formatting. However, you can also implement an automated approach to linking that makes linking mu... | +
Search configuration | +Page | +The search feature uses JavaScript to look for keyword matches in a JSON file. The results show instant matches, but it doesn't provide a search results page... | +
Tag archives overview | +Page | +This is an overview to the tag archives section. Really the only reason this section is listed explicitly in the TOC here is to demonstrate how to add a thir... | +
Tags | +Page | +Tags provide another means of navigation for your content. Unlike the table of contents, tags can show the content in a variety of arrangements and groupings... | +
The following pages and posts are tagged with
+Title | Type | Excerpt |
---|---|---|
Sample post | +Post | +This is some summary frontmatter for my sample post. | +
Welcome to Jekyll! | +Post | +Theme updates: + + + Permalinks + Kramdown + URL specified in config file + removed PDF output + removed some of the alternative layouts + added blog feature + sidebars configurable per page + + + | +
Test post from last year | +Post | +This is just a test post from the previous year. + + | +
The following pages and posts are tagged with
+Title | Type | Excerpt |
---|---|---|
Build arguments | +Page | +You use various build arguments with your Jekyll project. You can also create shell scripts to act as shortcuts for long build commands. You can store the co... | +
10. Configure the build scripts | +Page | +You need to customize the build scripts. These script automate the publishing of your PDFs and web outputs through shell scripts on the command line. | +
Generating PDFs | +Page | +You can generate a PDF from your Jekyll project. You do this by creating a web version of your project that is printer friendly. You then use utility called ... | +
Help APIs and UI tooltips | +Page | +You can loop through files and generate a JSON file that developers can consume like a help API. Developers can pull in values from the JSON into interface e... | +
iTerm profiles | +Page | +You can set up profiles in iTerm to facilitate the build process with just a few clicks. This can make it a lot easier to quickly build multiple outputs. | +
Pushing builds to server | +Page | +You can push your build to AWS using commands from the command line. By including your copy commands in commands, you can package all of the build and deploy... | +
Search configuration | +Page | +The search feature uses JavaScript to look for keyword matches in a JSON file. The results show instant matches, but it doesn't provide a search results page... | +
Themes | +Page | +You can choose between two different themes (one green, the other blue) for your projects. The theme CSS is stored in the CSS folder and configured in the co... | +
The following pages and posts are tagged with
+Title | Type | Excerpt |
---|---|---|
Conditional logic | +Page | +You can implement advanced conditional logic that includes if statements, or statements, unless, and more. This conditional logic facilitates single sourcing... | +
Content reuse | +Page | +You can reuse chunks of content by storing these files in the includes folder. You then choose to include the file where you need it. This works similar to c... | +
Excluding files | +Page | +By default, all the files in your Jekyll project are included in the output (this differs from DITA projects, which don't include files unless noted on the m... | +
Generating PDFs | +Page | +You can generate a PDF from your Jekyll project. You do this by creating a web version of your project that is printer friendly. You then use utility called ... | +
Help APIs and UI tooltips | +Page | +You can loop through files and generate a JSON file that developers can consume like a help API. Developers can pull in values from the JSON into interface e... | +
The following pages and posts are tagged with
+Title | Type | Excerpt |
---|---|---|
FAQ layout | +Page | +You can use an accordion-layout that takes advantage of Bootstrap styling. This is useful for an FAQ page. | +
Glossary layout | +Page | +Your glossary page can take advantage of definitions stored in a data file. This gives you the ability to reuse the same definition in multiple places. Addit... | +
Knowledge-base layout | +Page | +This shows a sample layout for a knowledge base. Each square could link to a tag archive page. In this example, font icons from Font Awesome are used for the... | +
Shuffle layout | +Page | +This layout shows an example of a knowledge-base style navigation system, where there is no hierarchy, just groups of pages that have certain tags. | +
Special layouts overview | +Page | +This theme has a few special layouts. Special layouts include the JS files they need directly in the page. The JavaScript for each special layout does not lo... | +
The following pages and posts are tagged with
+Title | Type | Excerpt |
---|---|---|
About Ruby, Gems, Bundler, and other prerequisites | +Page | +Ruby is a programming language you must have on your computer in order to build Jekyll locally. Ruby has various gems (or plugins) that provide various funct... | +
Install Jekyll on Mac | +Page | +Installation of Jekyll on Mac is usually less problematic than on Windows. However, you may run into permissions issues with Ruby that you must overcome. You... | +
Support | +Page | +Contact me for any support issues. | +
Troubleshooting | +Page | +This page lists common errors and the steps needed to troubleshoot them. | +
This is just a test post from the previous year.
+ + +© 2018 Your company. This is a boilerplate copyright statement... All rights reserved. No part of this publication may be reproduced, distributed, or transmitted in any form or by any means, including photocopying, recording, or other electronic or mechanical methods, without the prior written permission of the publisher, except in the case of brief quotations embodied in critical reviews and certain other noncommercial uses permitted by copyright law. +
+ +This page is purposely separated out from the rest of theme so you can see the bare minimum code to add to a page, without all the other theme's code getting in the way.
+ +Content in the tooltips (actually "popovers" according to Bootstrap lingo) can be pulled in dynamically by placing the JSON file on a remote host.
+ +Basketball
+ +Baseball
+ +Football
+ +Soccer
+ diff --git a/_site/tooltips.json b/_site/tooltips.json new file mode 100644 index 0000000..73773c9 --- /dev/null +++ b/_site/tooltips.json @@ -0,0 +1,29 @@ +{ +"entries": +[ + +{ +"doc_id": "baseball", +"body": "Baseball is considered America's pasttime sport, though that may be more of a historical term than a current one. There's a lot more excitement about football than baseball. A baseball game is somewhat of a snooze to watch, for the most part." +} , + +{ +"doc_id": "basketball", +"body": "Basketball is a sport involving two teams of five players each competing to put a ball through a small circular rim 10 feet above the ground. Basketball requires players to be in top physical condition, since they spend most of the game running back and forth along a 94-foot-long floor." +} , + +{ +"doc_id": "football", +"body": "No doubt the most fun sport to watch, football also manages to accrue the most injuries with the players. From concussions to blown knees, football players have short sport lives." +} , + +{ +"doc_id": "soccer", +"body": "If there's one sport that dominates the world landscape, it's soccer. However, US soccer fans are few and far between. Apart from the popularity of soccer during the World Cup, most people don't even know the name of the professional soccer organization in their area." +} + +] +} + + + diff --git a/_site/update.sh b/_site/update.sh new file mode 100755 index 0000000..42a3bec --- /dev/null +++ b/_site/update.sh @@ -0,0 +1,4 @@ +git add . +git status +git commit -m "content update" +git push \ No newline at end of file diff --git a/_site/var/build.sh b/_site/var/build.sh new file mode 100644 index 0000000..137b92c --- /dev/null +++ b/_site/var/build.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +apt-get update && \ +apt-get install -y libfontconfig zip npm git apt-transport-https ca-certificates curl openssl && \ +npm i -g npm && \ +npm cache clean -f && \ +npm install -g n && \ +n stable && \ +node --version && \ +npm --version && \ +bundle install \ No newline at end of file diff --git a/_tooltips/baseball.html b/_tooltips/baseball.html new file mode 100644 index 0000000..c229636 --- /dev/null +++ b/_tooltips/baseball.html @@ -0,0 +1,6 @@ +--- +doc_id: baseball +product: mydoc +--- + +{{site.data.definitions.baseball}} diff --git a/_tooltips/basketball.html b/_tooltips/basketball.html new file mode 100644 index 0000000..c029485 --- /dev/null +++ b/_tooltips/basketball.html @@ -0,0 +1,6 @@ +--- +doc_id: basketball +product: mydoc +--- + +{{site.data.definitions.basketball}} diff --git a/_tooltips/football.html b/_tooltips/football.html new file mode 100644 index 0000000..52ae352 --- /dev/null +++ b/_tooltips/football.html @@ -0,0 +1,6 @@ +--- +doc_id: football +product: mydoc +--- + +{{site.data.definitions.football}} \ No newline at end of file diff --git a/_tooltips/soccer.html b/_tooltips/soccer.html new file mode 100644 index 0000000..19fd5bd --- /dev/null +++ b/_tooltips/soccer.html @@ -0,0 +1,6 @@ +--- +doc_id: soccer +product: mydoc +--- + +{{site.data.definitions.soccer}} \ No newline at end of file diff --git a/createtag b/createtag new file mode 100644 index 0000000..4766b6e --- /dev/null +++ b/createtag @@ -0,0 +1,54 @@ +#!/bin/sh + +# Using a 'cat' here document, create a file for jekyll +# website containing what's required for tag pages. + +# Pass in tag name(s) +# ./createtag linux bsd + +CMDLINEPARAM=1 # Takes at least one param. +TAGDIR="pages/tags" + +if [ $# -ge $CMDLINEPARAM ] +then + tags=$@ +else + echo "Atleast ${CMDLINEPARAM} tag name is required." + exit 1 +fi + +if [ -d "${TAGDIR}" ]; then + + echo "Creating tag(s) for ${tags}" + + for tag in ${tags}; do + echo "Title for $tag:" + read title + # Cannot indent here string. +cat <
+---
+title: Alerts
+tags: [formatting]
+keywords: notes, tips, cautions, warnings, admonitions
+last_updated: July 3, 2016
+summary: "You can insert notes, tips, warnings, and important alerts in your content. These notes are stored as shortcodes made available through the linksrefs.hmtl include."
+sidebar: mydoc_sidebar
+permalink: mydoc_alerts
+---
+
+
+The `sidebar: mydoc_sidebar` refers to the \_data/sidebars/mydoc_sidebar.yml file.
+
+Note that your sidebar can only have 2 levels (expand the **Tag archives** option to see an example of the second level). Given that each product has its own sidebar, this depth should be sufficient (it's really like 3 levels). Deeper nesting goes against usability recommendations.
+
+You can optionally turn off the sidebar on any page (e.g. landing pages). To turn off the sidebar for a page, you should set the page frontmatter tag as `hide_sidebar: true`.
+
+If you don't declare a sidebar, the `home_sidebar` file gets used as the default because this is the default specified in the config file:
+
+```yaml
+-
+ scope:
+ path: ""
+ type: "pages"
+ values:
+ layout: "page"
+ comments: true
+ search: true
+ sidebar: home_sidebar
+ topnav: topnav
+```
+
+If you want to set different sidebar defaults based on different folders for your pages, specify your defaults like this:
+
+```
+-
+ scope:
+ path: "pages/mydoc"
+ type: "pages"
+ values:
+ layout: "page"
+ comments: true
+ search: true
+ sidebar: mydoc_sidebar
+ topnav: topnav
+```
+
+This would load the `mydoc_sidebar` for each file in **pages/mydoc**. You could set different defaults for different path scopes.
+
+For more detail on the sidebar, see [Sidebar navigation][mydoc_sidebar_navigation].
+
+## Top navigation
+
+The top navigation works just like the sidebar. You can specify which topnav data file should load by adding a `topnav` property in your page, like this:
+
+```yaml
+topnav: topnav
+```
+
+Here the topnav refers to the \_data/topnav.yml file.
+
+Because most topnav options will be the same, the \_config.yml file specifies the topnav file as a default:
+
+```yaml
+-
+ scope:
+ path: ""
+ type: "pages"
+ values:
+ layout: "page"
+ comments: true
+ search: true
+ sidebar: home_sidebar
+ topnav: topnav
+```
+
+## Sidebar syntax
+
+The sidebar data file uses a specific YAML syntax that you must follow. Follow the sample pattern shown in the theme, specically looking at mydoc_sidebar.yml as an example: Here's a code sample showing all levels:
+
+```yaml
+entries:
+- title: sidebar
+ product: Jekyll Doc Theme
+ version: 6.0
+ folders:
+ - title: Overview
+ output: web, pdf
+ folderitems:
+
+ - title: Get started
+ url: /index.html
+ output: web, pdf
+ type: homepage
+
+ - title: Introduction
+ url: /mydoc_introduction.html
+ output: web, pdf
+
+ - title: Release Notes
+ output: web, pdf
+ folderitems:
+
+ - title: 6.0 Release notes
+ url: /mydoc_release_notes_60.html
+ output: web, pdf
+
+ - title: 5.0 Release notes
+ url: /mydoc_release_notes_50.html
+ output: web, pdf
+
+ - title: Tag archives
+ output: web
+ folderitems:
+
+ - title: Tag archives overview
+ url: /mydoc_tag_archives_overview.html
+ output: web
+
+ subfolders:
+ - title: Tag archive pages
+ output: web
+ subfolderitems:
+
+ - title: Formatting pages
+ url: /tag_formatting.html
+ output: web
+
+ - title: Navigation pages
+ url: /tag_navigation.html
+ output: web
+
+ - title: Content types pages
+ url: /tag_content_types.html
+ output: web
+```
+
+Each `folder` or `subfolder` must contain a `title` and `output` property. Each `folderitem` or `subfolderitem` must contain a `title`, `url`, and `output` property.
+
+The two outputs available are `web` and `pdf`. (Even if you aren't publishing PDF, you still need to specify `output: web`).
+
+The YAML syntax depends on exact spacing, so make sure you follow the pattern shown in the sample sidebars. See my [YAML tutorial](mydoc_yaml_tutorial) for more details about how YAML works.
+
+{% include note.html content="If you have just one character of spacing off, Jekyll won't build due to the YAML syntax error. You'll see an error message in your console that says \"Error ... did not find expected key while parsing a block mapping at line 22 column 5. Error: Run jekyll build --trace for more information.\" If you encounter this, it usually refers to incorrect indentation or spacing in the YAML file. See the example mydoc_sidebar.yml file to see where your formatting went wrong." %}
+
+Each level must have at least one topic before the next level starts. You can't have a second level that contains multiple third levels without having at least one standalone topic in the second level. If you need a hierarchy that has a folder that contains other folders and no loose topics, use a blank `-` item like this:
+
+```yamll
+entries:
+- title: sidebar
+ product: Jekyll Doc Theme
+ version: 6.0
+ folders:
+ - title: Overview
+ output: web, pdf
+ folderitems:
+
+ -
+
+ - title: Release Notes
+ output: web, pdf
+ folderitems:
+
+ - title: 6.0 Release notes
+ url: /mydoc_release_notes_60.html
+ output: web, pdf
+
+ - title: 5.0 Release notes
+ url: /mydoc_release_notes_50.html
+ output: web, pdf
+
+ - title: Installation
+ output: web, pdf
+ folderitems:
+
+ - title: About Ruby, Gems, Bundler, etc.
+ url: /mydoc_about_ruby_gems_etc.html
+ output: web, pdf
+
+ - title: Install Jekyll on Mac
+ url: /mydoc_install_jekyll_on_mac.html
+ output: web, pdf
+
+ - title: Install Jekyll on Windows
+ url: /mydoc_install_jekyll_on_windows.html
+ output: web, pdf
+```
+
+To accommodate the title page and table of contents in PDF outputs, each product sidebar must list these pages before any other:
+
+```yaml
+- title:
+ output: pdf
+ type: frontmatter
+ folderitems:
+ - title:
+ url: /titlepage
+ output: pdf
+ type: frontmatter
+ - title:
+ url: /tocpage
+ output: pdf
+ type: frontmatter
+```
+
+Leave the output as `output: pdf` for these frontmatter pages so that they don't appear in the web output.
+
+For more detail on the sidebar, see [Sidebar navigation][mydoc_sidebar_navigation] and [YAML tutorial][mydoc_yaml_tutorial].
+
+## Relative links and offline viewing
+
+This theme uses relative links throughout so that you can view the site offline and not worry about which server or directory you're hosting it. It's common with tech docs to push content to an internal server for review prior to pushing the content to an external server for publication. Because of the need for seamless transferrence from one host to another, the site has to use relative links.
+
+To view pages locally on your machine (without the Jekyll preview server), they need to have the `.html` extension. The `permalink` property in the page's frontmatter (without surrounding slashes) is what pushes the files into the root directory when the site builds.
+
+## Page frontmatter
+
+When you write pages, include these same frontmatter properties with each page:
+
+```yaml
+---
+title: "Some title"
+tags: [sample1, sample2]
+keywords: keyword1, keyword2, keyword3
+last_updated: Month day, year
+summary: "optional summary here"
+sidebar: sidebarname
+permalink: filename.html
+---
+```
+
+(You will customize the values for each of these properties, of course.)
+
+For titles, surrounding the title in quotes is optional, but if you have a colon in the title, you must surround the title with quotation marks. If you have a quotation mark inside the title, escape it first with a backlash `\`.
+
+Values for `keywords` get populated into the metadata of the page for SEO.
+
+Values for `tags` must be defined in your \_data/tags.yml list. You also need a corresponding tag file inside the tags folder that follows the same pattern as the other tag files shown in the tags folder. (Jekyll won't auto-create these tag files.)
+
+If you don't want the mini-TOC to show on a page (such as for the homepage or landing pages), add `toc: false` in the frontmatter.
+
+The `permalink` value should be the same as your filename and include the ".html" file extension.
+
+For more detail, see [Pages][mydoc_pages].
+
+## Where to store your documentation topics
+
+You can store your files for each product inside subfolders following the pattern shown in the theme. For example, product1, product2, etc, can be stored in their own subfolders inside the \_pages directory. Inside \_pages, you can store your topics inside sub-subfolders or sub-sub-folders to your heart's content. When Jekyll builds your site, it will pull the topics into the root directory and use the permalink for the URL.
+
+Note that product1, product2, and mydoc are all just sample content to demonstrate how to add multiple products into the theme. You can freely delete that content.
+
+For more information, see [Pages][mydoc_pages] and [Posts][mydoc_posts].
+
+## Configure the top navigation
+
+The top navigation bar's menu items are set through the \_data/topnav.yml file. Use the top navigation bar to provide links for navigating from one product to another, or to navigate to external resources.
+
+For external URLs, use `external_url` in the item property, as shown in the example topnav.yml file. For internal links, use `url` the same was you do in the sidebar data files.
+
+Note that the topnav has two sections: `topnav` and `topnav_dropdowns`. The topnav section contains single links, while the `topnav_dropdowns` section contains dropdown menus. The two sections are independent of each other.
+
+## Generating PDF
+
+If you want to generate PDF, you'll need a license for [Prince XML](http://www.princexml.com/). You will also need to [install Prince](http://www.princexml.com/doc/installing/). You can generate PDFs by product (but not for every product on the site combined together into one massive PDF). Prince will work even without a license, but it will imprint a small Prince image on the first page, and you're supposed to buy the license to use it.
+
+If you're on Windows, install [Git Bash client](https://git-for-windows.github.io/) rather than using the default Windows command prompt.
+
+Open up the css/printstyles.css file and customize the email address (`youremail@domain.com`) that is listed there. This email address appears in the bottom left footer of the PDF output. You'll also need to create a PDF configuration file following the examples shown in the pdfconfigs folder, and also customize some build scripts following the same pattern shown in the root: pdf-product1.sh
+
+See the section on [Generating PDFs][mydoc_generating_pdfs] for more details about setting the theme up for this output.
+
+## Blogs / News
+
+For blog posts, create your markdown files in the \_posts folder following the sample formats. Post file names always begin with the date (YYYY-MM-DD-title).
+
+The news/news.html file displays the posts, and the news_archive.html file shows a yearly history of posts. In documentation, you might use the news to highlight product features outside of your documentation, or to provide release notes and other updates.
+
+See [Posts][mydoc_posts] for more information.
+
+## Markdown
+
+This theme uses [kramdown markdown](http://kramdown.gettalong.org/). kramdown is similar to Github-flavored Markdown, except that when you have text that intercepts list items, the spacing of the intercepting text must align with the spacing of the first character after the space of a numbered list item. Basically, with your list item numbering, use two spaces after the dot in the number, like this:
+
+```
+1. First item
+2. Second item
+3. Third item
+```
+
+When you want to insert paragraphs, notes, code snippets, or other matter in between the list items, use four spaces to indent. The four spaces will line up with the first letter of the list item (the First or Second or Third).
+
+```
+1. First item
+
+ ```
+ alert("hello");
+ ```
+
+2. Second item
+
+ Some pig!
+
+3. Third item
+```
+
+See the topics under "Formatting" in the sidebar for more information.
+
+## Automated links
+
+If you want to use an automated system for managing links, see [Automated Links][mydoc_hyperlinks.html#automatedlinks]. This approach automatically creates a list of Markdown references to simplify linking.
+
+## Other instructions
+
+The content here is just a getting started guide only. For other details in working with the theme, see the various sections in the sidebar.
+
+{% include links.html %}
diff --git a/js/customscripts.js b/js/customscripts.js
new file mode 100644
index 0000000..27701a3
--- /dev/null
+++ b/js/customscripts.js
@@ -0,0 +1,54 @@
+$('#mysidebar').height($(".nav").height());
+
+
+$( document ).ready(function() {
+
+ //this script says, if the height of the viewport is greater than 800px, then insert affix class, which makes the nav bar float in a fixed
+ // position as your scroll. if you have a lot of nav items, this height may not work for you.
+ var h = $(window).height();
+ //console.log (h);
+ if (h > 800) {
+ $( "#mysidebar" ).attr("class", "nav affix");
+ }
+ // activate tooltips. although this is a bootstrap js function, it must be activated this way in your theme.
+ $('[data-toggle="tooltip"]').tooltip({
+ placement : 'top'
+ });
+
+ /**
+ * AnchorJS
+ */
+ anchors.add('h2,h3,h4,h5');
+
+});
+
+// needed for nav tabs on pages. See Formatting > Nav tabs for more details.
+// script from http://stackoverflow.com/questions/10523433/how-do-i-keep-the-current-tab-active-with-twitter-bootstrap-after-a-page-reload
+$(function() {
+ var json, tabsState;
+ $('a[data-toggle="pill"], a[data-toggle="tab"]').on('shown.bs.tab', function(e) {
+ var href, json, parentId, tabsState;
+
+ tabsState = localStorage.getItem("tabs-state");
+ json = JSON.parse(tabsState || "{}");
+ parentId = $(e.target).parents("ul.nav.nav-pills, ul.nav.nav-tabs").attr("id");
+ href = $(e.target).attr('href');
+ json[parentId] = href;
+
+ return localStorage.setItem("tabs-state", JSON.stringify(json));
+ });
+
+ tabsState = localStorage.getItem("tabs-state");
+ json = JSON.parse(tabsState || "{}");
+
+ $.each(json, function(containerId, href) {
+ return $("#" + containerId + " a[href=" + href + "]").tab('show');
+ });
+
+ $("ul.nav.nav-pills, ul.nav.nav-tabs").each(function() {
+ var $this = $(this);
+ if (!json[$this.attr("id")]) {
+ return $this.find("a[data-toggle=tab]:first, a[data-toggle=pill]:first").tab("show");
+ }
+ });
+});
diff --git a/js/jekyll-search.js b/js/jekyll-search.js
new file mode 100644
index 0000000..d884a24
--- /dev/null
+++ b/js/jekyll-search.js
@@ -0,0 +1 @@
+!function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a="function"==typeof require&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}for(var i="function"==typeof require&&require,o=0;oThis is my note.
++def foo(x):+{{site.data.alerts.end}}{% endraw %} +``` + +**Result:** + +{{site.data.alerts.note}} +
+ return x+1 +
This is my note.
++def foo(x):+{{site.data.alerts.end}} + +The same Bootstrap code from the alert is stored in yaml files inside the \_data folder. (This was how I previously implemented this code, but since this method was prone to error and didn't trigger any build warnings or failures when incorrectly coded, I changed the approach to use includes instead.) + +## Types of alerts available + +There are four types of alerts you can leverage: + +* note.html +* tip.html +* warning.html +* important.html + +They function the same except they have a different color, icon, and alert word. You include the different types by selecting the include template you want. Here are samples of each alert: + +{% include note.html content="This is my note." %} + +{% include tip.html content="This is my tip." %} + +{% include warning.html content="This is my warning." %} + +{% include important.html content="This is my important info." %} + +These alerts leverage includes stored in the \_include folder. The `content` option is a parameter that you pass to the include. In the include, the parameter is passed like this: + +``` +{% raw %}
+ return x+1 +
If you want to use an FAQ format, use the syntax shown on the faq.html page. Rather than including code samples here (which are bulky with a lot of nested div
tags), just look at the source in the mydoc_faq.html theme file.
output: web
(rather than output: pdf
) in the list of attributes in your sidebar. The prince-list.txt file that loops through the mydoc_sidebar.yml file to grab the URLs of each page that should appear in the PDF will skip over any items that do not list output: pdf
in the item attributes. For example, you might not want your tag archives to appear in the PDF, but you probably will want to list them in the online help navigation." %}
+
+## 4. Customize your headers and footers
+
+Open up the css/printstyles.css file and customize what you want for the headers and footers. At the very least, customize the email address (`youremail@domain.com`) that appears in the bottom left.
+
+Exactly how the print styling works here is pretty nifty. You don't need to understand the rest of the content in this section unless you want to customize your PDFs to look different from what I've configured. But I'm adding this information here in case you want to understand how to customize the look and feel of the PDF output.
+
+This style creates a page reference for a link:
+
+{% raw %}
+```css
+a[href]::after {
+ content: " (page " target-counter(attr(href), page) ")"
+}
+```
+
+You don't want cross references for any link that doesn't reference another page, so this style specifies that the content after should be blank:
+
+```css
+a[href*="mailto"]::after, a[data-toggle="tooltip"]::after, a[href].noCrossRef::after {
+ content: "";
+}
+```
+{% endraw %}
+
+{% include tip.html content="If you have a link to a file download, or some other link that shouldn't have a cross reference (such as link used in JavaScript for navtabs or collapsible sections, for example, add `noCrossRef` as a class to the link to avoid having it say \"page 0\" in the cross reference." %}
+
+This style specifies that after links to web resources, the URL should be inserted instead of the page number:
+
+```css
+a[href^="http:"]::after, a[href^="https:"]::after {
+ content: " (" attr(href) ")";
+}
+```
+
+This style sets the page margins:
+
+```css
+@page {
+ margin: 60pt 90pt 60pt 90pt;
+ font-family: sans-serif;
+ font-style:none;
+ color: gray;
+
+}
+```
+
+To set a specific style property for a particular page, you have to name the page. This allows Prince to identify the page.
+
+First you add frontmatter to the page that specifies the type. For the titlepage.html, here's the frontmatter:
+
+```yaml
+---
+type: title
+---
+```
+
+For the tocpage, here's the frontmatter:
+
+```yaml
+---
+type: frontmatter
+---
+```
+
+For the index.html page, we have this type tag (among others):
+
+```yaml
+---
+type: first_page
+---
+```
+
+The default_print.html layout will change the class of the `body` element based on the type value in the page's frontmatter:
+
+{% raw %}
+```liquid
+
+```
+{% endraw %}
+
+Now in the css/printstyles.css file, you can assign a page name based on a specific class:
+
+```css
+body.title { page: title }
+```
+
+This means that for content inside of `body class="title"`, we can style this page in our stylesheet using `@page title`.
+
+Here's how that title page is styled:
+
+```css
+@page title {
+ @top-left {
+ content: " ";
+ }
+ @top-right {
+ content: " "
+ }
+ @bottom-right {
+ content: " ";
+ }
+ @bottom-left {
+ content: " ";
+ }
+}
+```
+
+As you can see, we don't have any header or footer content, because it's the title page.
+
+For the tocpage.html, which has the `type: frontmatter`, this is specified in the stylesheet:
+
+```css
+body.frontmatter { page: frontmatter }
+body.frontmatter {counter-reset: page 1}
+
+
+@page frontmatter {
+ @top-left {
+ content: prince-script(guideName);
+ }
+ @top-right {
+ content: prince-script(datestamp);
+ }
+ @bottom-right {
+ content: counter(page, lower-roman);
+ }
+ @bottom-left {
+ content: "youremail@domain.com"; }
+}
+```
+
+With `counter(page, lower-roman)`, we reset the page count to 1 so that the title page doesn't start the count. Then we also add some header and footer info. The page numbers start counting in lower-roman numerals.
+
+Finally, for the first page (which doesn't have a specific name), we restart the counting to 1 again and this time use regular numbers.
+
+```css
+body.first_page {counter-reset: page 1}
+
+h1 { string-set: doctitle content() }
+
+@page {
+ @top-left {
+ content: string(doctitle);
+ font-size: 11px;
+ font-style: italic;
+ }
+ @top-right {
+ content: prince-script(datestamp);
+ font-size: 11px;
+ }
+
+ @bottom-right {
+ content: "Page " counter(page);
+ font-size: 11px;
+ }
+ @bottom-left {
+ content: prince-script(guideName);
+ font-size: 11px;
+ }
+}
+```
+
+You'll see some other items in there such as `prince-script`. This means we're using JavaScript to run some functions to dynamically generate that content. These JavaScript functions are located in the \_includes/head_print.html:
+
+```js
+
+
+
+```
+
+There are a couple of Prince functions that are default functions from Prince. This gets the heading title of the page:
+
+```js
+ content: string(doctitle);
+```
+
+This gets the current page:
+
+```js
+ content: "Page " counter(page);
+```
+
+Because the theme uses JavaScript in the CSS, you have to add the `--javascript` tag in the Prince command (detailed later on this page).
+
+## 5. Customize and run the PDF script
+
+Duplicate the pdf-mydoc.sh file in the root directory and customize it for your specific configuration files.
+
+```
+echo 'Killing all Jekyll instances'
+kill -9 $(ps aux | grep '[j]ekyll' | awk '{print $2}')
+clear
+
+echo "Building PDF-friendly HTML site for Mydoc ...";
+jekyll serve --detach --config _config.yml,pdfconfigs/config_mydoc_pdf.yml;
+echo "done";
+
+echo "Building the PDF ...";
+prince --javascript --input-list=_site/pdfconfigs/prince-list.txt -o pdf/mydoc.pdf;
+echo "done";
+```
+
+Note that the first part kills all Jekyll instances. This way you won't try to serve Jekyll at a port that is already occupied.
+
+The `jekyll serve` command serves up the HTML-friendly PDF configurations for our two projects. This web version is where Prince will go to get its content.
+
+The prince script issues a command to the Prince utility. JavaScript is enabled (`--javascript`), and we tell it exactly where to find the list of files (`--input-list`) — just point to the prince-list.txt file. Then we tell it where and what to output (`-o`).
+
+Make sure that the path to the prince-list.txt is correct. For the output directory, I like to output the PDF file into my project's source (into the files folder). Then when I build the web output, the PDF is included and something I can refer to.
+
+{% include note.html content="You might not want to include the PDF in your project files, since you're likely committing the PDF to Github and as a result saving the changes from one PDF version to another with each save." %}
+
+## 6. Add conditions for your new builds in the PDF config file
+
+In the PDF configuration file, there's a section that looks like this:
+
+```
+{% raw %}{% if site.product == "mydoc" %}
+pdf_sidebar: product2_sidebar
+{% endif %}
+```
+
+Point to the sidebar you want here.
+
+What this does is allow the prince-list.txt and toc.html files to iterate through the right sidebar. Otherwise, you would need to create a unique prince-list.txt and toc.html file for each separate PDF output you have.
+
+## 7. Add a download button for the PDF
+
+You can add a download button for your PDF using some Bootstrap button code:
+
+```html
+
+```
+
+Here's what that looks like:
+
+
+
+## JavaScript conflicts
+
+If you have JavaScript on any of your pages, Prince will note errors in Terminal like this:
+
+```
+error: TypeError: value is not an object
+```
+
+However, the PDF will still build.
+
+You need to conditionalize out any JavaScript from your PDF web output before building your PDFs. Make sure that the PDF configuration files have the `output: pdf` property.
+
+Then surround the JavaScript with conditional tags like this:
+
+```
+{% raw %}{% unless site.output == "pdf" %}
+javascript content here ...
+{% endunless %}{% endraw %}
+```
+
+For more detail about using `unless` in conditional logic, see [Conditional logic][mydoc_conditional_logic]. What this code means is "run this code unless this value is the case."
+
+## Overriding Bootstrap Print Styles
+
+The theme relies on Bootstrap's CSS for styling. However, for print media, Bootstrap applies the following style:
+
+```
+@media print{*,:after,:before{color:#000!important;text-shadow:none!important;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important}
+```
+This is minified, but basically the `*` (asterisk) means select all, and applied the color #000 (black). As a result, the Bootstrap style strips out all color from the PDF (for Bootstrap elements).
+
+This is problematic for code snippets that have syntax highlighting. I decided to remove this de-coloring from the print output. I commented out the Bootstrap style:
+
+```
+@media print{*,:after,:before{/*color:#000!important;*/text-shadow:none!important;/*background:0 0!important*/;-webkit-box-shadow:none!important;box-shadow:none!important}
+```
+
+If you update Bootrap, make sure you make this edit. (Sorry, admittedly I couldn't figure out how to simply overwrite the `*` selector with a later style.)
+
+I did, however, remove the color from the alerts and lighten the background shading for `pre` elements. The printstyles.css has this setting.
+
+{% include links.html %}
diff --git a/pages/mydoc/mydoc_git_collaboration.md b/pages/mydoc/mydoc_git_collaboration.md
new file mode 100644
index 0000000..ae0e511
--- /dev/null
+++ b/pages/mydoc/mydoc_git_collaboration.md
@@ -0,0 +1,185 @@
+---
+title: Git notes and tips
+summary: "If you're interacting with your team using Git, the notes and tips will help you collaborate efficiently."
+tags: collaboration
+keywords: git, github, collaboration, interaction, file sharing, push
+published: false
+sidebar: mydoc_sidebar
+permalink: mydoc_git_collaboration.html
+folder: mydoc
+---
+
+
+hg fetch does a pull and update at the same time
+you're prompted about any conflicts
+you fix them. then you do this:
+
+
+hg pull -u (i think this is pull and then update)
+
+$ hg [COMMAND] [ARGUMENTS]
+
+hg init
+hg add
+hg log
+hg diff
+hg revert
+hg remove
+hg update
+You have seen that it is possible to switch revision using hg update.
+clone
+
+commit
+
+The first feature of the diff command is to show the differences between the last revision of a file (the state at the last commit command) and the current version. It can also show the differences between any two specified revisions. For example, on apache2.conf, the diff command can be used as follows:
+$ hg diff -r 1 -r 2 apache2.conf
+
+To print each line of a file with the revision at which the line was created (and with the --user option, we come to know who committed this revision), type:
+$ hg annotate [FILE] or $ hg blame [FILE]
+
+To search for a pattern in version controlled files, use hg grep; it will search this pattern in every version of the file and it will print the first one in which it appears, such as hg annotate. For example:
+$ hg grep new apache2.conf
+
+You can also print the content of a file at a given revision even without changing the current working directory using hg cat -r REVISION.
+
+Whenever changes have been committed but not yet pushed, the outgoing command lists all the changesets that are present in the current repository but not yet found in the destination (the ones that are candidates to be pushed), whereas the incoming command shows you the changesets that are found in the source repository but have not been pulled yet. So here, if you use the outgoing command, you will see
+
+push
+pull
+fetch
+merge
+resolve --mark
+
+As you can see, you have added John's change to your repository because hg log is listing it. But it is not yet present in your working copy; you need to update the working directory to the tip revision, which is the default of the update command, when no revision is passed as argument:
+
+You can now see John's change in the working directory. If some files had been modified, either committed or not, the modifications would have been seamlessly merged with that of John's. If there was a conflict, Mercurial would have told us.
+
+hg pull --update or -u: This option combines both the pull and the update commands, not only pulling new changesets into the local repository, but also updating the working directory to the head of these new changes.
+
+| annotate, blame | show changeset information by line for each file |
+| diff | diff repository (or selected files) |
+| forget {filename} | forget the specified files on the next commit |
+
+
+hg fetch. This extension acts as a combination of hg pull -u, hg merge and hg commit. It begins by pulling changes from another repository into the current repository. If it finds that the changes added a new head to the repository, it updates to the new head, begins a merge, then (if the merge succeeded) commits the result of the merge with an automatically-generated commit message. If no new heads were added, it updates the working directory to the new tip changeset.
+
+
+
+i like
+
+hg fetch does a pull and update at the same time
+you're prompted about any conflicts
+you fix them. then you do this: hg resolve --mark
+
+
+hg pull -u (i think this is pull and then update)
+
+$ hg [COMMAND] [ARGUMENTS]
+
+hg init
+hg add
+hg log
+hg diff
+hg revert
+hg remove
+hg update
+You have seen that it is possible to switch revision using hg update.
+clone
+addremove, which allows you to automatically add all new files and remove (from version control) files that have been deleted.
+log
+commit
+
+The first feature of the diff command is to show the differences between the last revision of a file (the state at the last commit command) and the current version. It can also show the differences between any two specified revisions. For example, on apache2.conf, the diff command can be used as follows:
+$ hg diff -r 1 -r 2 apache2.conf
+
+To print each line of a file with the revision at which the line was created (and with the --user option, we come to know who committed this revision), type:
+$ hg annotate [FILE] or $ hg blame [FILE]
+
+To search for a pattern in version controlled files, use hg grep; it will search this pattern in every version of the file and it will print the first one in which it appears, such as hg annotate. For example:
+$ hg grep new apache2.conf
+
+You can also print the content of a file at a given revision even without changing the current working directory using hg cat -r REVISION.
+
+Whenever changes have been committed but not yet pushed, the outgoing command lists all the changesets that are present in the current repository but not yet found in the destination (the ones that are candidates to be pushed), whereas the incoming command shows you the changesets that are found in the source repository but have not been pulled yet. So here, if you use the outgoing command, you will see
+
+push
+pull
+fetch
+merge
+resolve --mark
+
+As you can see, you have added John's change to your repository because hg log is listing it. But it is not yet present in your working copy; you need to update the working directory to the tip revision, which is the default of the update command, when no revision is passed as argument:
+
+You can now see John's change in the working directory. If some files had been modified, either committed or not, the modifications would have been seamlessly merged with that of John's. If there was a conflict, Mercurial would have told us.
+
+hg pull --update or -u: This option combines both the pull and the update commands, not only pulling new changesets into the local repository, but also updating the working directory to the head of these new changes.
+
+Bookmarks are tags that move forward automatically to subsequent changes, leaving no mark on the changesets that previously had that bookmark pointing toward them. Named branches, on the other hand, are indelible marks that are part of a changeset. Multiple heads can be on the same branch, but only one head at a time can be pointed to by the same bookmark. Named branches are pushed/pulled from repo to repo, and bookmarks don't travel.
+
+The default branch name in Mercurial is “default”.
+
+The slowest, safest way to create a branch with Mercurial is to make a new clone of the repository. this is really fascinating -- a clone is merely a branch.
+
+Discarding a branch you don’t want any more is very easy with cloned branches. It’s as simple as rm -rf test-project-feature-branch. There’s no need to mess around with editing repository history, you just delete the damn thing.
+
+The next way to branch is to use a bookmark. For example:
+
+$ cd ~/src/test-project
+$ hg bookmark main
+$ hg bookmark feature
+Now you’ve got two bookmarks (essentially a tag) for your two branches at the current changeset.
+
+To switch to one of these branches you can use hg update feature to update to the tip changeset of that branch and mark yourself as working on that branch. When you commit, it will move the bookmark to the newly created changeset.
+
+
+## Git
+HEAD is a reference to the last commit in the current checked out branch.
+
+This is a good tutorial: https://www.digitalocean.com/community/tutorials/how-to-use-git-branches.
+
+
+## Branching
+
+| Commands | Description |
+|------|-------|
+| List all branches | `git branch a` (the * indicates the branch you're on) |
+| Create new branch | `git -b branchname` or `git branch branchname` |
+| Checkout a branch | `git checkout branchname` |
+| Create new branch and checkout at the same time| `git checkout -b branchname` |
+| Merge into current branch | First go into the branch you want to merge changes into. Then do `git merge branchname`. For example, to merge branch b into branch master, first checkout branch master: `git checkout a`. Now merge b into master: `git merge b`.|
+
+git lg
+
+git checkout master
+git merge search | git merge --no-ff search
+
+the latter (--no-ff) keeps the additional information that these commits were made on a branch.
+then type a commit message (:wq)
+git branch -d search
+
+git add . (works same as add --all)
+git commit am "my commit message" (this performs both adding and commit message at same time)
+
+with merge conflicts:
+
+git status (shows you all the files that can't be added due to merge conflicts)
+fix the conflicts
+then git add . (tells git you fixed the conflicts)
+then git status
+git commit
+
+From the interface, you can also create a pull request to merge all of the changes from a specific branch into another branch.
+
+
+
+## General commands
+
+| Commands | Description |
+|------|-------|
+| start tracking files | `git add` |
+| see what has changed since last commit | `git diff` |
+| commit changes | `git commit` |
+| | |
+
+
+{% include links.html %}
diff --git a/pages/mydoc/mydoc_glossary.md b/pages/mydoc/mydoc_glossary.md
new file mode 100644
index 0000000..264fed7
--- /dev/null
+++ b/pages/mydoc/mydoc_glossary.md
@@ -0,0 +1,111 @@
+---
+title: Glossary layout
+tags: [formatting, special_layouts]
+keywords: definitions, glossaries, terms, style guide
+last_updated: July 3, 2016
+summary: "Your glossary page can take advantage of definitions stored in a data file. This gives you the ability to reuse the same definition in multiple places. Additionally, you can use Bootstrap classes to arrange your definition list horizontally."
+sidebar: mydoc_sidebar
+permalink: mydoc_glossary.html
+toc: false
+folder: mydoc
+---
+
+
+You can create a glossary for your content. First create your glossary items in a data file such as glossary.yml.
+
+Then create a page and use definition list formatting, like this:
+
+fractious
+: {{site.data.glossary.fractious}}
+
+gratuitous
+: {{site.data.glossary.gratuitous}}
+
+haughty
+: {{site.data.glossary.haughty}}
+
+gratuitous
+: {{site.data.glossary.gratuitous}}
+
+impertinent
+: {{site.data.glossary.intrepid}}
+
+Here's the code:
+
+```
+{% raw %}fractious
+: {{site.data.glossary.fractious}}
+
+gratuitous
+: {{site.data.glossary.gratuitous}}
+
+haughty
+: {{site.data.glossary.haughty}}
+
+gratuitous
+: {{site.data.glossary.gratuitous}}
+
+impertinent
+: {{site.data.glossary.intrepid}}{% endraw %}
+```
+
+The glossary works well as a link in the top navigation bar.
+
+## Horizontally styled definiton lists
+
+You can also change the definition list (`dl`) class to `dl-horizontal`. This is a Bootstrap specific class. If you do, the styling looks like this:
+
+Basketball
+``` + +Notice that I just have `id="basketball"` added to this popover element. Developers merely need to add a unique ID to each tooltip they want to pull in the help content. Either you tell developers the unique ID they should add, or ask them what IDs they added (or just tell them to use an ID that matches the field's name). + +In order to use jQuery and Bootstrap, you'll need to add the appropriate references in the head tags of your page: + +```js + + + + + + + +{% assign series_pages = site.tags.series_acme %} + {% for p in pages %} + {% if p.series == "ACME series" %} + {% assign nextTopic = page.weight | plus: "1" %} + {% if p.weight == nextTopic %} + + {% endif %} + {% endif %} + {% endfor %} +
+``` +{% endraw %} + +Change "acme" to the name of your series. + +Save this in your \_includes/custom/mydoc folder as series\_acme\_next.html. + +## 3. Add the correct frontmatter to each of your series pages + +Now add the following frontmatter to each page in the series: + +```json +series: "ACME series" +weight: 1.0 +``` + +With weights, Jekyll will treat 10 as coming after 1. If you have more than 10 items, consider changing `plus: "1.0"` to `plus: "0.1"`. + +Additionally, if your page names are prefaced with numbers, such as "1. Download the code," then the {% raw %}`{{p.weight}}`{% endraw %} will create a duplicate number. In that case, just remove the {% raw %}`{{p.weight}}`{% endraw %} from both code samples here. + +## 4. Add links to the series button and next button on each page. + +On each series page, add a link to the series button at the top and a link to the next button at the bottom. + +{% raw %} +```liquid + + +{% include custom/series_acme.html %} + + + +{% include custom/series_acme_next.html %} +``` +{% endraw %} + +## Changing the series drop-down color + +The Bootstrap menu uses the `primary` class for styling. If you change this class in your theme, the Bootstrap menu should automatically change color as well. You can also just use another Bootstrap class in your button code. Instead of `btn-primary`, use `btn-info` or `btn-warning`. See [Labels][mydoc_labels] for more Bootstrap button classes. + +## Using a collection with your series + +Instead of copying and pasting the button includes on each of your series, you could also create a collection and define a layout for the collection that has the include code. For more information on creating collections, see [Collections][mydoc_collections] for more details. + +{% include links.html %} diff --git a/pages/mydoc/mydoc_seriesdemo1.md b/pages/mydoc/mydoc_seriesdemo1.md new file mode 100644 index 0000000..5a4ec16 --- /dev/null +++ b/pages/mydoc/mydoc_seriesdemo1.md @@ -0,0 +1,22 @@ +--- +title: Series demo 1 +summary: "This is the first post in the series." +series: "ACME series" +weight: 1 +last_updated: July 3, 2016 +sidebar: mydoc_sidebar +permalink: mydoc_seriesdemo1.html +folder: mydoc +--- + +{% include custom/series_acme_next.html %} + +This is the first post in the series. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam vel sollicitudin felis. Sed eu arcu sed ipsum semper luctus eu a tortor. Suspendisse id leo eu metus laoreet varius. Mauris consequat accumsan ex, a iaculis metus fermentum a. Praesent sit amet fermentum leo. Aliquam feugiat, nibh in ultrices mattis, felis ipsum venenatis metus, vel vehicula libero mauris a enim. Sed placerat est ac lectus vestibulum tempor. Quisque ut condimentum massa. Proin venenatis leo id urna cursus blandit. Vivamus sit amet hendrerit metus. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam vel sollicitudin felis. Sed eu arcu sed ipsum semper luctus eu a tortor. Suspendisse id leo eu metus laoreet varius. Mauris consequat accumsan ex, a iaculis metus fermentum a. Praesent sit amet fermentum leo. Aliquam feugiat, nibh in ultrices mattis, felis ipsum venenatis metus, vel vehicula libero mauris a enim. Sed placerat est ac lectus vestibulum tempor. Quisque ut condimentum massa. Proin venenatis leo id urna cursus blandit. Vivamus sit amet hendrerit metus. + + + +{% include links.html %} diff --git a/pages/mydoc/mydoc_seriesdemo2.md b/pages/mydoc/mydoc_seriesdemo2.md new file mode 100644 index 0000000..048e735 --- /dev/null +++ b/pages/mydoc/mydoc_seriesdemo2.md @@ -0,0 +1,24 @@ +--- +title: Series demo 2 +summary: "This is the second post in the series." +series: "ACME series" +weight: 2 +last_updated: July 3, 2016 +sidebar: mydoc_sidebar +permalink: mydoc_seriesdemo2.html +folder: mydoc +--- + + +{% include custom/series_acme_next.html %} + +This is the second post in the series. + +Aliquam feugiat, nibh in ultrices mattis, felis ipsum venenatis metus, vel vehicula libero mauris a enim. Sed placerat est ac lectus vestibulum tempor. Quisque ut condimentum massa. Proin venenatis leo id urna cursus blandit. Vivamus sit amet hendrerit metus. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam vel sollicitudin felis. Sed eu arcu sed ipsum semper luctus eu a tortor. Suspendisse id leo eu metus laoreet varius. Mauris consequat accumsan ex, a iaculis metus fermentum a. Praesent sit amet fermentum leo. Aliquam feugiat, nibh in ultrices mattis, felis ipsum venenatis metus, vel vehicula libero mauris a enim. Sed placerat est ac lectus vestibulum tempor. Quisque ut condimentum massa. Proin venenatis leo id urna cursus blandit. Vivamus sit amet hendrerit metus. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam vel sollicitudin felis. Sed eu arcu sed ipsum semper luctus eu a tortor. Suspendisse id leo eu metus laoreet varius. Mauris consequat accumsan ex, a iaculis metus fermentum a. Praesent sit amet fermentum leo. + + +{% include links.html %} diff --git a/pages/mydoc/mydoc_seriesdemo3.md b/pages/mydoc/mydoc_seriesdemo3.md new file mode 100644 index 0000000..dcf2ddb --- /dev/null +++ b/pages/mydoc/mydoc_seriesdemo3.md @@ -0,0 +1,24 @@ +--- +title: Series demo 3 +last_updated: May 17, 2016 +summary: "This is the third post in the series." +series: "ACME series" +weight: 3 +last_updated: July 3, 2016 +sidebar: mydoc_sidebar +permalink: mydoc_seriesdemo3.html +folder: mydoc +--- + +{% include custom/series_acme_next.html %} + +This is the third post in the series. + +Mauris consequat accumsan ex, a iaculis metus fermentum a. Praesent sit amet fermentum leo. Aliquam feugiat, nibh in ultrices mattis, felis ipsum venenatis metus, vel vehicula libero mauris a enim. Sed placerat est ac lectus vestibulum tempor. Quisque ut condimentum massa. Proin venenatis leo id urna cursus blandit. Vivamus sit amet hendrerit metus. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam vel sollicitudin felis. Sed eu arcu sed ipsum semper luctus eu a tortor. Suspendisse id leo eu metus laoreet varius. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam vel sollicitudin felis. Sed eu arcu sed ipsum semper luctus eu a tortor. Suspendisse id leo eu metus laoreet varius. Mauris consequat accumsan ex, a iaculis metus fermentum a. Praesent sit amet fermentum leo. Aliquam feugiat, nibh in ultrices mattis, felis ipsum venenatis metus, vel vehicula libero mauris a enim. Sed placerat est ac lectus vestibulum tempor. Quisque ut condimentum massa. Proin venenatis leo id urna cursus blandit. Vivamus sit amet hendrerit metus. + + +{% include links.html %} diff --git a/pages/mydoc/mydoc_seriesdemo4.md b/pages/mydoc/mydoc_seriesdemo4.md new file mode 100644 index 0000000..57ea639 --- /dev/null +++ b/pages/mydoc/mydoc_seriesdemo4.md @@ -0,0 +1,26 @@ +--- +title: Series demo 4 +summary: "This is the fourth post in the series." +series: "ACME series" +weight: 4 +last_updated: July 3, 2016 +sidebar: mydoc_sidebar +permalink: mydoc_seriesdemo4.html +folder: mydoc +--- + + +{% include custom/series_acme_next.html %} + +This is the fourth post in the series. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam vel sollicitudin felis. Sed eu arcu sed ipsum semper luctus eu a tortor. Suspendisse id leo eu metus laoreet varius. Mauris consequat accumsan ex, a iaculis metus fermentum a. Praesent sit amet fermentum leo. Aliquam feugiat, nibh in ultrices mattis, felis ipsum venenatis metus, vel vehicula libero mauris a enim. Sed placerat est ac lectus vestibulum tempor. Quisque ut condimentum massa. Proin venenatis leo id urna cursus blandit. Vivamus sit amet hendrerit metus. + + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam vel sollicitudin felis. Sed eu arcu sed ipsum semper luctus eu a tortor. Suspendisse id leo eu metus laoreet varius. Mauris consequat accumsan ex, a iaculis metus fermentum a. Praesent sit amet fermentum leo. Aliquam feugiat, nibh in ultrices mattis, felis ipsum venenatis metus, vel vehicula libero mauris a enim. Sed placerat est ac lectus vestibulum tempor. Quisque ut condimentum massa. Proin venenatis leo id urna cursus blandit. Vivamus sit amet hendrerit metus. + +Mauris consequat accumsan ex, a iaculis metus fermentum a. Praesent sit amet fermentum leo. Aliquam feugiat, nibh in ultrices mattis, felis ipsum venenatis metus, vel vehicula libero mauris a enim. Sed placerat est ac lectus vestibulum tempor. Quisque ut condimentum massa. Proin venenatis leo id urna cursus blandit. Vivamus sit amet hendrerit metus. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam vel sollicitudin felis. Sed eu arcu sed ipsum semper luctus eu a tortor. Suspendisse id leo eu metus laoreet varius. + +{% include links.html %} diff --git a/pages/mydoc/mydoc_shuffle.html b/pages/mydoc/mydoc_shuffle.html new file mode 100644 index 0000000..3987037 --- /dev/null +++ b/pages/mydoc/mydoc_shuffle.html @@ -0,0 +1,167 @@ +--- +title: Shuffle layout +tags: [special_layouts] +last_updated: November 30, 2015 +keywords: shuffle, card layout, dynamic grid, doc portal, support portal +summary: "This layout shows an example of a knowledge-base style navigation system, where there is no hierarchy, just groups of pages that have certain tags." +permalink: mydoc_shuffle.html +sidebar: mydoc_sidebar +folder: mydoc +--- + + + +{% if site.output == "pdf" %} +{{site.data.alerts.note}} The content on this page doesn't display well on PDF, but I included it anyway so you could see the problems this layout poses if you're including it in PDF. {{site.data.alerts.end}} +{% endif %} + +{% unless site.output == "pdf" %} + + +{% endunless %} + + + ++```java +import java.util.Scanner; + +public class ScannerAndKeyboard +{ + + public static void main(String[] args) + { Scanner s = new Scanner(System.in); + System.out.print( "Enter your name: " ); + String name = s.nextLine(); + System.out.println( "Hello " + name + "!" ); + } +} +``` ++ +This looks as follows: + +```java +import java.util.Scanner; + +public class ScannerAndKeyboard +{ + + public static void main(String[] args) + { Scanner s = new Scanner(System.in); + System.out.print( "Enter your name: " ); + String name = s.nextLine(); + System.out.println( "Hello " + name + "!" ); + } +} +``` + +Fenced code blocks require a blank line before and after. + +If you're using an HTML file, you can also use the `highlight` command with Liquid markup. + +
+{% raw %}{% highlight java %} +import java.util.Scanner; + +public class ScannerAndKeyboard +{ + + public static void main(String[] args) + { Scanner s = new Scanner(System.in); + System.out.print( "Enter your name: " ); + String name = s.nextLine(); + System.out.println( "Hello " + name + "!" ); + } +} +{% endhighlight %}{% endraw %} ++ +Result: + +{% highlight java %} +import java.util.Scanner; + +public class ScannerAndKeyboard +{ + + public static void main(String[] args) + { Scanner s = new Scanner(System.in); + System.out.print( "Enter your name: " ); + String name = s.nextLine(); + System.out.println( "Hello " + name + "!" ); + } +} +{% endhighlight %} + +The theme has syntax highlighting specified in the configuration file as follows: + +``` +highlighter: rouge +``` + +The syntax highlighting is done via the css/syntax.css file. + +## Available lexers + +The keywords you must add to specify the highlighting (in the previous example, `ruby`) are called "lexers." You can search for "lexers." Here are some common ones I use: + +* js +* html +* yaml +* css +* json +* php +* java +* cpp +* dotnet +* xml +* http + +{% include links.html %} diff --git a/pages/mydoc/mydoc_tables.md b/pages/mydoc/mydoc_tables.md new file mode 100644 index 0000000..952a078 --- /dev/null +++ b/pages/mydoc/mydoc_tables.md @@ -0,0 +1,141 @@ +--- +title: Tables +tags: [formatting] +keywords: datatables, tables, grids, markdown, multimarkdown, jquery plugins +last_updated: July 16, 2016 +datatable: true +summary: "You can format tables using either multimarkdown syntax or HTML. You can also use jQuery datatables (a plugin) if you need more robust tables." +sidebar: mydoc_sidebar +permalink: mydoc_tables.html +folder: mydoc +--- + +## Multimarkdown Tables + +You can use Multimarkdown syntax for tables. The following shows a sample: + +``` +| Priority apples | Second priority | Third priority | +|-------|--------|---------| +| ambrosia | gala | red delicious | +| pink lady | jazz | macintosh | +| honeycrisp | granny smith | fuji | +``` + +**Result:** + +| Priority apples | Second priority | Third priority | +|-------|--------|---------| +| ambrosia | gala | red delicious | +| pink lady | jazz | macintosh | +| honeycrisp | granny smith | fuji | + +{% include note.html content="You can't use block level tags (paragraphs or lists) inside Markdown tables, so if you need separate paragraphs inside a cell, use `
Field | +Description | +
---|---|
First column **fields** | +Some descriptive text. This is a markdown link to [Google](http://google.com). Or see [some link][mydoc_tags]. | +
Second column **fields** | +Some more descriptive text. + | +
Field | +Description | +
---|---|
First column **fields** | +Some descriptive text. This is a markdown link to [Google](http://google.com). Or see [some link][mydoc_tags]. | +
Second column **fields** | +Some more descriptive text. + | +