papaya-markdown

  1. markdown-styles with sidebar navigation. This is a combination of
    • markdown-styles, markdown-to-html library
    • simple-sidebar, a bootstrap sidebar stylesheet (modified)
    • my sidebar-popover.js code that will give you a preview of the content as you hover over the sidebar or any of the local links
    • default syntax-highlighting support via highlight.js.

For examples of files that use other templates, check out the layouts folder in the markdown-styles website or Github page. I've kept mainly the mixu-themed ones here just to keep things stupid simple.

Just kidding. There's no such thing as stupid simple.

See it in action here, or just download this and go through the supplied example.

Features

  • Ready-made CSS stylesheets for Markdown, just copy the assets folder you want
  • Bundled with generate-md, a small tool that converts a folder of Markdown documents into a output folder of HTML documents, preserving the directory structure
  • Use your own custom markup and CSS via --layout.
  • Support for relative paths to the assets folder via {{assetsRelative}} and document table of content generation via {{toc}}.
  • Support for generic metadata via a meta.json file.

Quickstart

Install papaya-markdown via npm. You'll need to grab the folder from github though since I haven't published it to npm (privacy and all that jazz.)

This will install it into your node_modules library

cd /usr/local/lib/node_modules/
sudo npm install -g git://gh.apple.com/adilapapaya/papaya-markdown.git

Alternatively, you can install it in some other folder, but then you'll need to keep track of where your folder is and adding it to your path and and yada yada yada headache.

cd into your project directory. Place your markdown files into a folder named input inside your project directory. You can now convert all your markdown files in that input directory into html files by typing

generate-md

The resulting html files will be placed in the output folder by default. You can also customize things a little more by setting some of the options.

Options

papaya-markdown comes with some customizable options.


--input

Determines where your markdown files are stored. You can have as many nested subdirectories as you want -- it will just recurse through all of them, preserving relative paths..

 generate-md --input ./myCustomInput

Default value: ./input.


--output

Determines where your output (compiled) html files will be stored. The directory structure mirrors what you have in your input folder.

 generate-md --output ./myCustomOutput

Default value: ./output.


--layout

Determines what layout to use. You can try out different layouts by changing the --layout parameter.

Examples:

  1. Use the inbuilt mixu-gray layout:

    generate-md --layout gray

    Note that if you also have a mixu-gray folder in your current working directory, that will get used instead.

  2. Use your own myLayout layout:

    generate-md --layout myLayout/page.html

Default value: papaya.


Aside

Any time you specify a custom layout folder, you need to also include an assets folder containing the css, js, images, fonts and what have yous. Hence, running a command like:

  generate-md --layout ./myLayout/page.html --input ./inputFolder/ --output ./outputFolder/

will:

  1. convert all Markdown files in ./input to HTML files under ./output, preserving paths in ./input.
  2. use the template ./myLayout/page.html, replacing values such as {{content}}, {{toc}} and {{assetsRelative}} (see the layouts for examples on this)
  3. (recursively) copy over the assets from ./myLayout/assets to ./test/assets.

If you would like to specify a different assets directory, then use the --asset-dir command.


--asset-dir

--asset-dir <path>: Normally, the asset directory is assumed to be ./assets/ in the same folder the --layout file is. You can override it to a different asset directory explicitly with --asset-dir, which is useful for builds where several directories use the same layout but different asset directories. For example,

generate-md --layout papaya ---asset-dir ./custom-assets

--command

--command <cmd>: Pipe each Markdown file through a shell command and capture the output before converting. Useful for filtering the file, for example.


Examples

The console tool used in this library to convert your markdown files into their html counterparts, is the papaya-markdown version of generate-md (which is a modification of the original markdown-styles generate-md script. Some example commands using the options specifed above follor.


  1. Input files in input, output files in output, your custom layout files in /layout/:

    generate-md --layout ./layout/page.html

  2. Input files in my-input-files-top-secret/, output files in test-output, layout files use the in-built papaya layout.

    generate-md --layout papaya --output ./test-output/ --input ./my-input-files-top-secret/

  3. Template file MyTemplate.html using the assets in the papaya layout folder

    generate-md --layout MyTemplate.html --asset-dir papaya

  4. Template file is MyTemplate.html, asset files are in MyAssets/assets

    generate-md --layout ./MyTemplate.html --asset-dir ./MyAssets/assets

Installing a custom layout into root

Here's how you can do things if you'd rather just have your layout installed directly into your root papaya-markdown folder. I'll assume your custom layout library is going to be called potato.

  • Navigate to the papaya-markdown root folder

    cd /usr/local/lib/node_modules/papaya-markdown/
  • Create folder named potato in the ./output/ folder

    mkdir output/potato
  • If you want to add default headers/footers and or run javascript code in the file (e.g. bootstrap navbars, etc), then create and specify that in the ./layouts/potato/page.html template html file. Otherwise, if no page.html file exists, the default footer and header in ./layouts/papaya/ are used.

For example, here's the page.html file for the papaya layout theme:

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>{{title}}</title>

    <link type="text/css" rel="stylesheet" href="{{assetsRelative}}/css/bootstrap.css"/>
    <link type="text/css" rel="stylesheet" href="{{assetsRelative}}/css/bootstrap-sidebar-nav-nav-list.css"/>
    <link type="text/css" rel="stylesheet" href="{{assetsRelative}}/css/github.css"/>

    <!-- My additional styles global styles class -->
    <link type="text/css" rel="stylesheet" href="{{assetsRelative}}/css/papaya-style.css"/>
    <!-- highlight style (style.css file in lib/highlight) -->
    {{styles}}

    <!-- Your custom styles go here -->
    {{customstyles}}

    <!-- These come BEFORE body or the sidebar will load wonky -->
    <script type="text/javascript" src="{{assetsRelative}}/js/jquery.min.js"></script>
    <script type="text/javascript" src="{{assetsRelative}}/js/bootstrap.min.js"></script>

  </head>
<body>

<div id="wrapper">
  <!-- Sidebar -->
    <div id="sidebar-wrapper">
        <div class='nav nav-list'>
          <div class='sidebar-brand'>
             Table of Contents
          </div>
        </div>
        {{toc}}
    </div>

    <div id="page-content-wrapper">
      <div class="page-content inset">
        {{content}}
      </div>
    </div>
</div>

<!-- sidebar-popover js code -->
<script type="text/javascript" src="{{assetsRelative}}/js/sidebar-popover.js"></script> 

<!-- your custom scripts -->
{{customscripts}}

</body>
</html>

The bootstrap files are from bootstrap 3.0, the bootstrap-sidebar-nav-nav-list.css file is a modification of simple-sidebar, the github.css file is from highlight.js and styles the file according the the styles previously set by highlightjs, and the papaya-style.css file is some additional styles custom to papaya. papaya also uses my custom sidebar-popover.js script that gives you a preview of the text when you hover over the sidebar.

You'll also notice the following placeholders:

  • {{toc}} Table of Contents will go here
  • {{content}} Markdown content will go here
  • {{title}} Page title will go here. This can be set in the meta.json file.
  • {{customstyles}} Your additional style sheets will go here. This can be set in the meta.json file.
  • {{customscripts}} Your additional scripts will go here. This can be set in the meta.json file.

Language-specific syntax highlighting and custom highlighters

papaya-markdown uses the highlightjs syntax highlighter. The papaya template uses the github.css css file but you can change it to something else by using your own custom template + asset directory. For example, if you wanted to use the solarized-light theme instead of the github theme with the papaya layout, then you would use

<link type="text/css" rel="stylesheet" href="{{assetsRelative}}/css/bootstrap.css"/>
<link type="text/css" rel="stylesheet" href="{{assetsRelative}}/css/bootstrap-sidebar-nav-nav-list.css"/>
<link type="text/css" rel="stylesheet" href="{{assetsRelative}}/css/solarized_light.css"/>

in your template file as opposed to

<link type="text/css" rel="stylesheet" href="{{assetsRelative}}/css/bootstrap.css"/>
<link type="text/css" rel="stylesheet" href="{{assetsRelative}}/css/bootstrap-sidebar-nav-nav-list.css"/>
<link type="text/css" rel="stylesheet" href="{{assetsRelative}}/css/github.css"/>

You would also need to include the solarized-light.css style file in your assets directory before compiling everything.

generate-md  --layout ./customLayout/page.html --output ./customLayoutOutput/

Take a look at the customLayout folder in the examples folder for an example of this in action.


Aside:

The full list of highlightjs themse available is shown below. Just click on any one of the links to get the source code.

Default, Dark, FAR, IDEA, Sunburst, Zenburn, Visual Studio, Ascetic, Magula, GitHub, Google Code, Brown Paper, School Book, IR Black, Solarized - Dark, Solarized - Light, Arta, Monokai, Monokai Sublime, XCode, Pojoaque, Rainbow, Tomorrow, Tomorrow Night, Tomorrow Night Bright, Tomorrow Night Blue, Tomorrow Night Eighties, Railscasts, Obsidian, Docco, Mono Blue, Foundation, Atelier Dun - Dark, Atelier Dun - Light, Atelier Forest - Dark, Atelier Forest - Light, Atelier Heath - Dark, Atelier Heath - Light, Atelier Lakeside - Dark, Atelier Lakeside - Light, Atelier Seaside - Dark, Atelier Seaside - Light, Paraíso - Dark, Paraíso - Light

Overriding the syntax highlighter

You can use --highlight-<language> <module> to override the syntax highlighter for a specific language. <module> can also be a path to a file. These come in two flavors:

Asynchronous (three parameters):

module.exports = function(code, lang, onDone) {
    return onDone(null, result);
};

Synchronous (two parameters):

module.exports = function(code, lang) {
    return require('highlight.js').highlightAuto(code).value;
};

Take a look at mds-hljs for an example of writing your own syntax highlighter wrapper. You can also take a look at the source code in /lib/highlight/hl.js. Both of these are synchronous.

To use mds-hljs, for example, you would type

generate-md --highlight mds-hljs --layout ./layout/page.html --output ./output/ --input ./input/

Metadata support

You can also add a file named meta.json to the folder from which you run generate-md. The metadata in that directory will be read and replacements will be made for corresponding {{names}} in the template. The metadata is scoped by the top-level directory in ./input.

For example,

{
  "README.md": {
    "title": "README"
    ,"customscripts":[
      "<script type='text/javascript' src='main.js'></script>"
      ,"<script type='text/javascript' src='main2.js'></script>"
      ]
    ,"customstyles":["<link type='text/css' rel='stylesheet' href='custom.css'/>"]
  }
  ,"subfolder/index.md"{
    "title":"This cat video will change your life!"
  }
}

will set the metadata value {{title}} of README.html to README and that of subfolder/index.html to 'This cat video will change your life!'. In addition, it will also set the {{customscripts}} and {{customstyles}} in the README.html to the specified values, assuming that you've specified those placeholders in your template layout file.

As an example, if you would like to set custom header content for each different file, then you would need to specify that as a field in the meta.json file,

{
  "index.md": {
    "title": "Main Page"
    ,"MySpecialHeaderContent":"<h1>This is the header for the main page</h1>"
  }
  ,"subfolder/index.md"{
    "title":"This cat video will change your life!"
    "MySpecialHeaderContent":"<h1>This is the header for the cats page</h1>"
  }
}

as well as as a placeholder in your custom template,

<!DOCTYPE html>
<html>
  <head>
    <title>{{title}}</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>

  <!-- CUSTOM HEADER CONTENT WILL GO HERE!! -->
  {{MySpecialHeaderContent}}

  <!-- Remaining content is pulled from the Markdown file -->
  {{content}}
  </body>
</html>

In addition, if you have an array of contents, then just specify it as an array in the meta-json file,

{
  "index.md": {
    "customscripts": [
      "<script type="text/javascript" src="custom/main.js"></script>"
      ,"<script type="text/javascript" src="custom/main_for_real.js"></script>"
    ]
  }

and make sure you use the same placeholder in your template html.

  <body>
  <!-- Markdown file content goes here -->
  {{content}}

  <!-- CUSTOM SCRIPTS -->
  {{customscripts}
  </body>

Running generate-md programmatically

The easiest way of doing this is to use nodemon.

  1. Add a nodemon.json file to your project folder.

       |–– project-folder
       |   |–– inputs
       |   |   |–– index.md
       |   |   |–– otherpage.md
       |   |–– nodemon.json
  2. Specify your preferences in the file. Your command gets entered into the execMap portion. You can also tell it what folders to watch and what ext-ensions to consider, ignoring everything else. Here is an example nodemon.json file.

    {
     "restartable": "rs",
     "ignore": [
       ".git"
       ,".DS_Store"
       ,".svn"
       ,"node_modules/*/node_modules"
     ],
     "verbose": true,
     "execMap": {
       "md": "generate-md"
     },
     "watch": [
       "input/"
       ,"/usr/local/lib/node_modules/papaya-markdown/layouts/papaya/*"
     ],
     "env": {
       "NODE_ENV": "development"
     },
     "ext": "js json md scss less css png jpg jpeg pdf gif"
    }

    Check out also the section on running non-node scripts on the github nodemon page.

  3. cd into your project folder and run nodemon using

    nodemon generate-md

    Your output folder will now be updated every time any of the js, json, md, css, etc, etc, etc, files (mentioned above in ext) in the .\input folder is modified.

Building your own project

I'd just skip this altogether and cd into the usr/local/lib/node_modules/papaya-markdown folder. Then type this into terminal since there's already a Makefile in there.

sudo make

Alternatively, if you want to redo all your hard work and **rewrite over whatever changes you made have made to the papaya-markdown folder (!),

git clone https://gh.apple.com/adilapapaya/papaya-markdown.git
npm install
make build

Example

An example is included that contains a sample nodemon.json and meta.json file. There is also a Makefile containing some sample commands you can run that will cover the different options mentioned above.

To run the nodemon file, first type this into terminal:

generate-md

This will create an index.html file in your output folder as well as copy the papaya assets folder into it.

Then, type

nodemon generate.md

and it will recompile anytime you make any change.

To run the Makefile, type this into terminal:

make