diff --git a/bin/generate-md b/bin/generate-md index 3e0dad4..1601915 100755 --- a/bin/generate-md +++ b/bin/generate-md @@ -8,13 +8,14 @@ var fs = require('fs'), opts.options({ 'layouts': { }, 'help': { }, + 'header-links': { 'default': true }, 'layout': { }, 'input': { }, 'output': { }, 'v': { }, 'version': { } }) - .boolean('layouts').boolean('help').boolean('v').boolean('version'); + .boolean('layouts').boolean('help').boolean('v').boolean('version').boolean('header-links'); var argv = opts.parse(process.argv); diff --git a/changelog.md b/changelog.md new file mode 100644 index 0000000..9670bf8 --- /dev/null +++ b/changelog.md @@ -0,0 +1,20 @@ +## Changes in 2.3: + +- Added the new header hover links feature, along with the relevant CSS for each built in layout. +- Added the `--no-header-links` flag. + +## Changes in 2.2: + +- Added support for Windows, thanks @AaronJan + +## Changes in 2.1: + +- Better single file handling, previously the output path was a bit wonky if you only had one file as the `--input` target. + +## Changes in 2.0: + +- `v2.0` is a major rewrite, with significant usability improvements; the core has been rewritten to use object mode streams via [pipe-iterators](https://github.com/mixu/pipe-iterators). +- Deprecated `--command`, `{{styles}}`, `--template`, `--asset-dir`, `--partials`, `--helpers`, `--runner`. Most of this functionality can be easily replicated much more cleanly with the new features. +- Improved highlighter support. Every built in layout now includes a default highlight.js CSS stylesheet and you no longer need to add extra CLI options to enable highlighting. +- Layout partials and helpers have been renamed: `{{content}}` -> `{{> content}}`, `{{toc}}` -> `{{> toc}}`, `{{assetsRelative}}` -> `{{asset 'path'}}` +- The default layout is now `github`, which looks a lot like Github readmes. diff --git a/layouts/bootstrap3/assets/css/pilcrow.css b/layouts/bootstrap3/assets/css/pilcrow.css new file mode 100644 index 0000000..769196f --- /dev/null +++ b/layouts/bootstrap3/assets/css/pilcrow.css @@ -0,0 +1,42 @@ +h1, +h2, +h3, +h4, +h5, +h6 { + position: relative; +} + +h1:hover .header-link:before, +h2:hover .header-link:before, +h3:hover .header-link:before, +h4:hover .header-link:before, +h5:hover .header-link:before, +h6:hover .header-link:before { + content: "\00B6";/* pilcrow */ + color: #888; + font-size: smaller; +} + +.header-link { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + + position: absolute; + top: 0; + left: -0.7em; + display: block; + padding-right: 1em; +} + +h1:hover .header-link, +h2:hover .header-link, +h3:hover .header-link, +h4:hover .header-link, +h5:hover .header-link, +h6:hover .header-link { + display: inline-block; + text-decoration: none; +} diff --git a/layouts/bootstrap3/page.html b/layouts/bootstrap3/page.html index eec78aa..74a040e 100644 --- a/layouts/bootstrap3/page.html +++ b/layouts/bootstrap3/page.html @@ -4,6 +4,7 @@ {{title}} + diff --git a/layouts/github/assets/css/pilcrow.css b/layouts/github/assets/css/pilcrow.css new file mode 100644 index 0000000..347bef3 --- /dev/null +++ b/layouts/github/assets/css/pilcrow.css @@ -0,0 +1,47 @@ +/* needed because the container has overflow: hidden, but the pilcrows overflow */ +.markdown-body { + padding-left: 30px; +} + +.markdown-body h1, +.markdown-body h2, +.markdown-body h3, +.markdown-body h4, +.markdown-body h5, +.markdown-body h6 { + position: relative; +} + +.markdown-body h1:hover .header-link:before, +.markdown-body h2:hover .header-link:before, +.markdown-body h3:hover .header-link:before, +.markdown-body h4:hover .header-link:before, +.markdown-body h5:hover .header-link:before, +.markdown-body h6:hover .header-link:before { + content: "\00B6";/* pilcrow */ + color: #888; + font-size: smaller; +} + +.markdown-body .header-link { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + + position: absolute; + top: 0; + left: -0.7em; + display: block; + padding-right: 1em; +} + +.markdown-body h1:hover .header-link, +.markdown-body h2:hover .header-link, +.markdown-body h3:hover .header-link, +.markdown-body h4:hover .header-link, +.markdown-body h5:hover .header-link, +.markdown-body h6:hover .header-link { + display: inline-block; + text-decoration: none; +} diff --git a/layouts/github/page.html b/layouts/github/page.html index c34a8b3..0c3db4a 100644 --- a/layouts/github/page.html +++ b/layouts/github/page.html @@ -5,6 +5,7 @@ {{title}} + + diff --git a/layouts/mixu-bootstrap/assets/css/pilcrow.css b/layouts/mixu-bootstrap/assets/css/pilcrow.css new file mode 100644 index 0000000..769196f --- /dev/null +++ b/layouts/mixu-bootstrap/assets/css/pilcrow.css @@ -0,0 +1,42 @@ +h1, +h2, +h3, +h4, +h5, +h6 { + position: relative; +} + +h1:hover .header-link:before, +h2:hover .header-link:before, +h3:hover .header-link:before, +h4:hover .header-link:before, +h5:hover .header-link:before, +h6:hover .header-link:before { + content: "\00B6";/* pilcrow */ + color: #888; + font-size: smaller; +} + +.header-link { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + + position: absolute; + top: 0; + left: -0.7em; + display: block; + padding-right: 1em; +} + +h1:hover .header-link, +h2:hover .header-link, +h3:hover .header-link, +h4:hover .header-link, +h5:hover .header-link, +h6:hover .header-link { + display: inline-block; + text-decoration: none; +} diff --git a/layouts/mixu-bootstrap/page.html b/layouts/mixu-bootstrap/page.html index aa49fdc..4605660 100644 --- a/layouts/mixu-bootstrap/page.html +++ b/layouts/mixu-bootstrap/page.html @@ -10,6 +10,7 @@ } + diff --git a/layouts/mixu-gray/assets/css/pilcrow.css b/layouts/mixu-gray/assets/css/pilcrow.css new file mode 100644 index 0000000..769196f --- /dev/null +++ b/layouts/mixu-gray/assets/css/pilcrow.css @@ -0,0 +1,42 @@ +h1, +h2, +h3, +h4, +h5, +h6 { + position: relative; +} + +h1:hover .header-link:before, +h2:hover .header-link:before, +h3:hover .header-link:before, +h4:hover .header-link:before, +h5:hover .header-link:before, +h6:hover .header-link:before { + content: "\00B6";/* pilcrow */ + color: #888; + font-size: smaller; +} + +.header-link { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + + position: absolute; + top: 0; + left: -0.7em; + display: block; + padding-right: 1em; +} + +h1:hover .header-link, +h2:hover .header-link, +h3:hover .header-link, +h4:hover .header-link, +h5:hover .header-link, +h6:hover .header-link { + display: inline-block; + text-decoration: none; +} diff --git a/layouts/mixu-gray/page.html b/layouts/mixu-gray/page.html index 9e01c13..fd9c5fa 100644 --- a/layouts/mixu-gray/page.html +++ b/layouts/mixu-gray/page.html @@ -28,6 +28,7 @@ } + diff --git a/layouts/mixu-page/assets/css/pilcrow.css b/layouts/mixu-page/assets/css/pilcrow.css new file mode 100644 index 0000000..769196f --- /dev/null +++ b/layouts/mixu-page/assets/css/pilcrow.css @@ -0,0 +1,42 @@ +h1, +h2, +h3, +h4, +h5, +h6 { + position: relative; +} + +h1:hover .header-link:before, +h2:hover .header-link:before, +h3:hover .header-link:before, +h4:hover .header-link:before, +h5:hover .header-link:before, +h6:hover .header-link:before { + content: "\00B6";/* pilcrow */ + color: #888; + font-size: smaller; +} + +.header-link { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + + position: absolute; + top: 0; + left: -0.7em; + display: block; + padding-right: 1em; +} + +h1:hover .header-link, +h2:hover .header-link, +h3:hover .header-link, +h4:hover .header-link, +h5:hover .header-link, +h6:hover .header-link { + display: inline-block; + text-decoration: none; +} diff --git a/layouts/mixu-page/page.html b/layouts/mixu-page/page.html index d951f28..38bfe89 100644 --- a/layouts/mixu-page/page.html +++ b/layouts/mixu-page/page.html @@ -3,9 +3,9 @@ {{title}} - + + - diff --git a/layouts/mixu-radar/assets/css/pilcrow.css b/layouts/mixu-radar/assets/css/pilcrow.css new file mode 100644 index 0000000..769196f --- /dev/null +++ b/layouts/mixu-radar/assets/css/pilcrow.css @@ -0,0 +1,42 @@ +h1, +h2, +h3, +h4, +h5, +h6 { + position: relative; +} + +h1:hover .header-link:before, +h2:hover .header-link:before, +h3:hover .header-link:before, +h4:hover .header-link:before, +h5:hover .header-link:before, +h6:hover .header-link:before { + content: "\00B6";/* pilcrow */ + color: #888; + font-size: smaller; +} + +.header-link { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + + position: absolute; + top: 0; + left: -0.7em; + display: block; + padding-right: 1em; +} + +h1:hover .header-link, +h2:hover .header-link, +h3:hover .header-link, +h4:hover .header-link, +h5:hover .header-link, +h6:hover .header-link { + display: inline-block; + text-decoration: none; +} diff --git a/layouts/mixu-radar/page.html b/layouts/mixu-radar/page.html index 0bdee03..adc07e7 100644 --- a/layouts/mixu-radar/page.html +++ b/layouts/mixu-radar/page.html @@ -3,7 +3,8 @@ {{title}} - + + diff --git a/layouts/roryg-ghostwriter/assets/css/pilcrow.css b/layouts/roryg-ghostwriter/assets/css/pilcrow.css new file mode 100644 index 0000000..769196f --- /dev/null +++ b/layouts/roryg-ghostwriter/assets/css/pilcrow.css @@ -0,0 +1,42 @@ +h1, +h2, +h3, +h4, +h5, +h6 { + position: relative; +} + +h1:hover .header-link:before, +h2:hover .header-link:before, +h3:hover .header-link:before, +h4:hover .header-link:before, +h5:hover .header-link:before, +h6:hover .header-link:before { + content: "\00B6";/* pilcrow */ + color: #888; + font-size: smaller; +} + +.header-link { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + + position: absolute; + top: 0; + left: -0.7em; + display: block; + padding-right: 1em; +} + +h1:hover .header-link, +h2:hover .header-link, +h3:hover .header-link, +h4:hover .header-link, +h5:hover .header-link, +h6:hover .header-link { + display: inline-block; + text-decoration: none; +} diff --git a/layouts/roryg-ghostwriter/page.html b/layouts/roryg-ghostwriter/page.html index 13f1fee..542c64e 100644 --- a/layouts/roryg-ghostwriter/page.html +++ b/layouts/roryg-ghostwriter/page.html @@ -11,6 +11,7 @@ + diff --git a/layouts/thomasf-solarizedcssdark/assets/pilcrow.css b/layouts/thomasf-solarizedcssdark/assets/pilcrow.css new file mode 100644 index 0000000..769196f --- /dev/null +++ b/layouts/thomasf-solarizedcssdark/assets/pilcrow.css @@ -0,0 +1,42 @@ +h1, +h2, +h3, +h4, +h5, +h6 { + position: relative; +} + +h1:hover .header-link:before, +h2:hover .header-link:before, +h3:hover .header-link:before, +h4:hover .header-link:before, +h5:hover .header-link:before, +h6:hover .header-link:before { + content: "\00B6";/* pilcrow */ + color: #888; + font-size: smaller; +} + +.header-link { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + + position: absolute; + top: 0; + left: -0.7em; + display: block; + padding-right: 1em; +} + +h1:hover .header-link, +h2:hover .header-link, +h3:hover .header-link, +h4:hover .header-link, +h5:hover .header-link, +h6:hover .header-link { + display: inline-block; + text-decoration: none; +} diff --git a/layouts/thomasf-solarizedcssdark/page.html b/layouts/thomasf-solarizedcssdark/page.html index d6e25dc..9fdbccb 100644 --- a/layouts/thomasf-solarizedcssdark/page.html +++ b/layouts/thomasf-solarizedcssdark/page.html @@ -3,7 +3,8 @@ {{title}} - + + diff --git a/layouts/thomasf-solarizedcsslight/assets/pilcrow.css b/layouts/thomasf-solarizedcsslight/assets/pilcrow.css new file mode 100644 index 0000000..769196f --- /dev/null +++ b/layouts/thomasf-solarizedcsslight/assets/pilcrow.css @@ -0,0 +1,42 @@ +h1, +h2, +h3, +h4, +h5, +h6 { + position: relative; +} + +h1:hover .header-link:before, +h2:hover .header-link:before, +h3:hover .header-link:before, +h4:hover .header-link:before, +h5:hover .header-link:before, +h6:hover .header-link:before { + content: "\00B6";/* pilcrow */ + color: #888; + font-size: smaller; +} + +.header-link { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + + position: absolute; + top: 0; + left: -0.7em; + display: block; + padding-right: 1em; +} + +h1:hover .header-link, +h2:hover .header-link, +h3:hover .header-link, +h4:hover .header-link, +h5:hover .header-link, +h6:hover .header-link { + display: inline-block; + text-decoration: none; +} diff --git a/layouts/thomasf-solarizedcsslight/page.html b/layouts/thomasf-solarizedcsslight/page.html index 7874b25..c7654fd 100644 --- a/layouts/thomasf-solarizedcsslight/page.html +++ b/layouts/thomasf-solarizedcsslight/page.html @@ -3,7 +3,8 @@ {{title}} - + + diff --git a/layouts/witex/assets/css/pilcrow.css b/layouts/witex/assets/css/pilcrow.css new file mode 100644 index 0000000..769196f --- /dev/null +++ b/layouts/witex/assets/css/pilcrow.css @@ -0,0 +1,42 @@ +h1, +h2, +h3, +h4, +h5, +h6 { + position: relative; +} + +h1:hover .header-link:before, +h2:hover .header-link:before, +h3:hover .header-link:before, +h4:hover .header-link:before, +h5:hover .header-link:before, +h6:hover .header-link:before { + content: "\00B6";/* pilcrow */ + color: #888; + font-size: smaller; +} + +.header-link { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + + position: absolute; + top: 0; + left: -0.7em; + display: block; + padding-right: 1em; +} + +h1:hover .header-link, +h2:hover .header-link, +h3:hover .header-link, +h4:hover .header-link, +h5:hover .header-link, +h6:hover .header-link { + display: inline-block; + text-decoration: none; +} diff --git a/layouts/witex/page.html b/layouts/witex/page.html index 2c66d51..20fe9b6 100644 --- a/layouts/witex/page.html +++ b/layouts/witex/page.html @@ -3,7 +3,8 @@ {{title}} - + + diff --git a/lib/pipeline.js b/lib/pipeline.js index 0ffaaa7..cc34dcf 100644 --- a/lib/pipeline.js +++ b/lib/pipeline.js @@ -6,6 +6,26 @@ var fs = require('fs'), mergeMeta = require('./merge-meta'); module.exports = function(argv) { + // custom rendered for headings + var renderer = new md.marked.Renderer(); + // if we want to generate header links, override the default header renderer + if (argv['header-links']) { + renderer.heading = function(text, level, raw) { + var id = this.options.headerPrefix + raw.trim().toLowerCase().replace(/[^\w]+/g, '-'); + return '' + + '' + + text + + '\n'; + }; + } return pi.pipeline([ md.parseHeader(), md.parseMd(), @@ -16,7 +36,9 @@ module.exports = function(argv) { } return false; }), - md.convertMd(), + md.convertMd({ + renderer: renderer + }), // map paths setOutputPath({ diff --git a/package.json b/package.json index 4100d21..4af5613 100644 --- a/package.json +++ b/package.json @@ -29,8 +29,8 @@ }, "dependencies": { "handlebars": "~2.0.0", - "markdown-stream-utils": "~1.0.2", - "mkdirp": "0.3.5", + "markdown-stream-utils": "~1.1.0", + "mkdirp": "~0.5.1", "pipe-iterators": "~1.1.0", "resolve": "~0.6.1", "wildglob": "0.0.2", diff --git a/readme.md b/readme.md index 339788e..d1f2eb3 100644 --- a/readme.md +++ b/readme.md @@ -6,28 +6,30 @@ Looking for something to generate a blog from Markdown files? Check out [ghost-r ## Features -- `v2.0` is a major rewrite, with significant usability improvements; the core has been rewritten to use object mode streams via [pipe-iterators](https://github.com/mixu/pipe-iterators). +- `v2.3` adds one new feature: header hover anchor links. When you hover over a header, a hover anchor link appears to the side of the header. Clicking on that link or coyping its URL produces a link to that specific location on the page. All built-in layouts support this feature by default. +- `v2.2` added Windows support (!) - Includes 15+ ready-made CSS stylesheets for Markdown, see the bottom of the readme for screenshots. - Reuse the stylesheets or use the `generate-md` tool to convert a folder of Markdown files to HTML using one of the built-in layouts or a custom layout. - Completely static output is easy to host anywhere. -- Metadata support: Each file can include additional metadata in a header section (new in 2.0!), such as the page title and author name which can then be used in the layout. -- Layout features: - - Built in support for code syntax highlighting via highlight.js (new in 2.0!) - - All layouts now include a Github-style code highlighting theme by default (new v2.0!) - - Built in table of contents generation from Markdown headings, now fully customizable by replacing the `{{> toc}}` partial in custom layout (new in 2.0!). - - Automatically detects the document title from the first heading in the Markdown markup (new in 2.0!) -- Easier to get started with a custom layout via `--exports`, which exports a built in layout as a starting point for your custom layout (new in 2.0). -- Create your own layout based on an existing layout via `--layout` with: - - Full [Handlebars](http://handlebarsjs.com/) support for layouts, helpers and partials (new in 2.0!) - - Fully customizable table of contents template via the `toc` partial (new in 2.0!) - - Support for relative path generation via the `{{asset 'path'}}` helper -- API support: `markdown-styles` now has a public API (new in 2.0!) -- Changes in 2.0: - - Deprecated `--command`, `{{styles}}`, `--template`, `--asset-dir`, `--partials`, `--helpers`, `--runner`. Most of this functionality can be easily replicated much more cleanly with the new features. - - Improved highlighter support. Every built in layout now includes a default highlight.js CSS stylesheet and you no longer need to add extra CLI options to enable highlighting. - - Layout partials and helpers have been renamed: `{{content}}` -> `{{> content}}`, `{{toc}}` -> `{{> toc}}`, `{{assetsRelative}}` -> `{{asset 'path'}}` - - The default layout is now `github`, which looks a lot like Github readmes. +- Metadata support: Each file can include additional metadata in a header section, such as the page title and author name which can then be used in the layout. +### Layout features + +- Built in support for code syntax highlighting via highlight.js +- All layouts now include a Github-style code highlighting theme by default (new v2.0!) +- Built in table of contents generation from Markdown headings, now fully customizable by replacing the `{{> toc}}` partial in custom layout . +- Automatically detects the document title from the first heading in the Markdown markup + +## Features for creating your own layout + +- Easier to get started with a custom layout via `--exports`, which exports a built in layout as a starting point for your custom layout. +- Create your own layout based on an existing layout via `--layout` with: + - Full [Handlebars](http://handlebarsjs.com/) support for layouts, helpers and partials + - Fully customizable table of contents template via the `toc` partial + - Support for relative path generation via the `{{asset 'path'}}` helper +- API support: `markdown-styles` now has a public API + +For changes, see [the changelog](changelog.md). ----- @@ -63,6 +65,7 @@ Try out different layouts by changing the `--layout` parameter; screenshots are - Note that `--template`, `--asset-dir`, `--partials` and `--helpers` are deprecated. This simplifies the loading logic. You need to put each of those resources in the same layout folder. - `--export `: Exports a built-in layout to a directory. Use `--output ` to specify the location to write the built-in layout. For example, `--export github --output ./custom-layout` will copy the `github` builtin layout to `./custom-layout`. - `--highlight- `: Specifies a custom highlighter module to use for a specific language. For example, `--highlight-csv mds-csv` will highlight any `csv` code blocks using the `mds-csv` module. +- `--no-header-links`: If this flag is passed, the HTML for header links will not be generated. The hover links are enabled by default. ## The resulting output @@ -95,6 +98,10 @@ These are mostly templates that have a sensible place to put this table of conte The `{{~> toc}}` partial generates a table of contents list. The list contains links to every header in your Markdown file. In addition, every Markdown header is automatically converted to a linkable anchor (e.g. `#table_of_contents`) when the page is generated. You can customize the table of contents markup by overriding the ./partials/[toc.hbs](https://github.com/mixu/markdown-styles/blob/master/builtin/partials/toc.hbs) partial in your custom layout. +## Header hover links (v2.1) + +If you are reading this on Github, hover over the header above. You'll see a link appear on the side of the header. The same feature is supported by all of the layouts. The feature is implemented purely with CSS, and you can find the details in `pilcrow.css` in each layout's assets folder. To disable the feature, pass the `--no-header-links` flag. + ## Metadata sections Each markdown file can have metadata associated with it. To set the metadata, start your markdown file with a metadata block that looks like this: