', 'Path of the markdown file to convert')
9 | .option('-c, --cwd [path]', 'Current working directory')
10 | .option('-p, --phantom-path [path]', 'Path to phantom binary')
11 | .option('-h, --runnings-path [path]', 'Path to runnings (header, footer)')
12 | .option('-s, --css-path [path]', 'Path to custom CSS file')
13 | .option('-z, --highlight-css-path [path]', 'Path to custom highlight-CSS file')
14 | .option('-m, --remarkable-options [json-options]', 'Options to pass to remarkable')
15 | .option('-f, --paper-format [format]', '"A3", "A4", "A5", "Legal", "Letter" or "Tabloid"')
16 | .option('-r, --paper-orientation [orientation]', '"portrait" or "landscape"')
17 | .option('-b, --paper-border [measurement]', 'Supported dimension units are: "mm", "cm", "in", "px"')
18 | .option('-d, --render-delay [millis]', 'Delay before rendering the PDF')
19 | .option('-t, --load-timeout [millis]', 'Timeout before the page is rendered in case `page.onLoadFinished` isn\'t fired')
20 | .option('-o, --out [path]', 'Path of where to save the PDF')
21 | .parse(process.argv)
22 |
23 | if (program.args.length === 0) program.help()
24 |
25 | program.out = program.out || program.args[0].replace(/\.m(ark)?d(own)?/gi, '') + '.pdf'
26 |
27 | var opts = {
28 | cwd: program.cwd,
29 | phantomPath: program.phantomPath,
30 | runningsPath: program.runningsPath,
31 | cssPath: program.cssPath,
32 | highlightCssPath: program.highlightCssPath,
33 | remarkable: program.remarkableOptions ? JSON.parse(program.remarkableOptions) : null,
34 | paperFormat: program.paperFormat,
35 | paperOrientation: program.paperOrientation,
36 | paperBorder: program.paperBorder,
37 | renderDelay: program.renderDelay,
38 | loadTimeout: program.loadTimeout
39 | }
40 |
41 | markdownpdf(opts).concat.from(program.args).to(program.out, function (err) {
42 | if (err) throw err
43 | })
44 |
--------------------------------------------------------------------------------
/css/highlight.css:
--------------------------------------------------------------------------------
1 | .hljs{display:block;overflow-x:auto;padding:0.5em;background:#f0f0f0;-webkit-text-size-adjust:none}.hljs,.hljs-subst,.hljs-tag .hljs-title,.nginx .hljs-title{color:black}.hljs-string,.hljs-title,.hljs-constant,.hljs-parent,.hljs-tag .hljs-value,.hljs-rules .hljs-value,.hljs-preprocessor,.hljs-pragma,.haml .hljs-symbol,.ruby .hljs-symbol,.ruby .hljs-symbol .hljs-string,.hljs-template_tag,.django .hljs-variable,.smalltalk .hljs-class,.hljs-addition,.hljs-flow,.hljs-stream,.bash .hljs-variable,.apache .hljs-tag,.apache .hljs-cbracket,.tex .hljs-command,.tex .hljs-special,.erlang_repl .hljs-function_or_atom,.asciidoc .hljs-header,.markdown .hljs-header,.coffeescript .hljs-attribute{color:#800}.smartquote,.hljs-comment,.hljs-annotation,.diff .hljs-header,.hljs-chunk,.asciidoc .hljs-blockquote,.markdown .hljs-blockquote{color:#888}.hljs-number,.hljs-date,.hljs-regexp,.hljs-literal,.hljs-hexcolor,.smalltalk .hljs-symbol,.smalltalk .hljs-char,.go .hljs-constant,.hljs-change,.lasso .hljs-variable,.makefile .hljs-variable,.asciidoc .hljs-bullet,.markdown .hljs-bullet,.asciidoc .hljs-link_url,.markdown .hljs-link_url{color:#080}.hljs-label,.hljs-javadoc,.ruby .hljs-string,.hljs-decorator,.hljs-filter .hljs-argument,.hljs-localvars,.hljs-array,.hljs-attr_selector,.hljs-important,.hljs-pseudo,.hljs-pi,.haml .hljs-bullet,.hljs-doctype,.hljs-deletion,.hljs-envvar,.hljs-shebang,.apache .hljs-sqbracket,.nginx .hljs-built_in,.tex .hljs-formula,.erlang_repl .hljs-reserved,.hljs-prompt,.asciidoc .hljs-link_label,.markdown .hljs-link_label,.vhdl .hljs-attribute,.clojure .hljs-attribute,.asciidoc .hljs-attribute,.lasso .hljs-attribute,.coffeescript .hljs-property,.hljs-phony{color:#88f}.hljs-keyword,.hljs-id,.hljs-title,.hljs-built_in,.css .hljs-tag,.hljs-javadoctag,.hljs-phpdoc,.hljs-dartdoc,.hljs-yardoctag,.smalltalk .hljs-class,.hljs-winutils,.bash .hljs-variable,.apache .hljs-tag,.hljs-type,.hljs-typename,.tex .hljs-command,.asciidoc .hljs-strong,.markdown .hljs-strong,.hljs-request,.hljs-status{font-weight:bold}.asciidoc .hljs-emphasis,.markdown .hljs-emphasis{font-style:italic}.nginx .hljs-built_in{font-weight:normal}.coffeescript .javascript,.javascript .xml,.lasso .markup,.tex .hljs-formula,.xml .javascript,.xml .vbscript,.xml .css,.xml .hljs-cdata{opacity:0.5}
--------------------------------------------------------------------------------
/html5bp/README.md:
--------------------------------------------------------------------------------
1 | # [HTML5 Boilerplate](http://html5boilerplate.com)
2 |
3 | HTML5 Boilerplate is a professional front-end template for building fast,
4 | robust, and adaptable web apps or sites.
5 |
6 | This project is the product of many years of iterative development and combined
7 | community knowledge. It does not impose a specific development philosophy or
8 | framework, so you're free to architect your code in the way that you want.
9 |
10 | * Source: [https://github.com/h5bp/html5-boilerplate](https://github.com/h5bp/html5-boilerplate)
11 | * Homepage: [http://html5boilerplate.com](http://html5boilerplate.com)
12 | * Twitter: [@h5bp](http://twitter.com/h5bp)
13 |
14 |
15 | ## Quick start
16 |
17 | Choose one of the following options:
18 |
19 | 1. Download the latest stable release from
20 | [html5boilerplate.com](http://html5boilerplate.com/) or a custom build from
21 | [Initializr](http://www.initializr.com).
22 | 2. Clone the git repo — `git clone
23 | https://github.com/h5bp/html5-boilerplate.git` - and checkout the tagged
24 | release you'd like to use.
25 |
26 |
27 | ## Features
28 |
29 | * HTML5 ready. Use the new elements with confidence.
30 | * Cross-browser compatible (Chrome, Opera, Safari, Firefox 3.6+, IE6+).
31 | * Designed with progressive enhancement in mind.
32 | * Includes [Normalize.css](http://necolas.github.com/normalize.css/) for CSS
33 | normalizations and common bug fixes.
34 | * The latest [jQuery](http://jquery.com/) via CDN, with a local fallback.
35 | * The latest [Modernizr](http://modernizr.com/) build for feature detection.
36 | * IE-specific classes for easier cross-browser control.
37 | * Placeholder CSS Media Queries.
38 | * Useful CSS helpers.
39 | * Default print CSS, performance optimized.
40 | * Protection against any stray `console.log` causing JavaScript errors in
41 | IE6/7.
42 | * An optimized Google Analytics snippet.
43 | * Apache server caching, compression, and other configuration defaults for
44 | Grade-A performance.
45 | * Cross-domain Ajax and Flash.
46 | * "Delete-key friendly." Easy to strip out parts you don't need.
47 | * Extensive inline and accompanying documentation.
48 |
49 |
50 | ## Documentation
51 |
52 | Take a look at the [documentation table of contents](doc/TOC.md). This
53 | documentation is bundled with the project, which makes it readily available for
54 | offline reading and provides a useful starting point for any documentation you
55 | want to write about your project.
56 |
57 |
58 | ## Contributing
59 |
60 | Anyone and everyone is welcome to [contribute](CONTRIBUTING.md). Hundreds of
61 | developers have helped make the HTML5 Boilerplate what it is today.
62 |
--------------------------------------------------------------------------------
/test/fixtures/ipsum.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | This is a paragraph. Cupcake ipsum dolor sit amet. Tiramisu liquorice gummies powder. Biscuit pastry pastry cake candy gummies carrot cake gingerbread. Gummi bears tart cupcake bonbon sugar plum biscuit. Icing marzipan tootsie roll. Pie gingerbread dragée wypas cookie. Faworki bonbon topping sweet soufflé jelly.
8 | And another paragraph. Jelly beans tootsie roll fruitcake toffee wypas chupa chups pudding. Soufflé muffin halvah powder sugar plum cake. Toffee cookie biscuit faworki pastry. Bonbon gummi bears topping caramels marshmallow. Chupa chups candy canes toffee. Powder powder candy canes pastry. Tootsie roll marshmallow powder.
9 | These words are emphasized Also these words are emphasized
10 | These words are strong emphasized Also these words are strong emphasized
11 |
12 | This is a very simple blockquote
13 |
14 |
15 | This
16 | is
17 | an
18 | unordered
19 | list.
20 |
21 | And...
22 |
23 | This
24 | is
25 | an
26 | ordered
27 | list.
28 |
29 | This is an example link .This is an example link with a title .
30 | This is a image
31 | this is a line of code
32 | And these are several lines of code. Pudding sesame snaps cupcake bonbon cupcake. Icing macaroon donut.
33 |
34 | More code. Donut cheesecake chocolate cake. Tart pudding wafer dessert chocolate bar jelly-o apple pie dessert. Carrot cake apple pie pie liquorice oat cake lollipop pastry caramels. Jelly-o sesame snaps gummi bears.
35 |
36 | And more. Sugar plum lemon drops chupa chups chocolate pastry. Faworki applicake applicake brownie topping liquorice chocolate liquorice icing. Cake pudding pudding cake candy sugar plum soufflé.`
37 | And that's all ...
38 | This is an extremely simple and basic guide. To understand a lot better this kind of dark magic called markdown, logically I recommend the official wiki of the creator. Go, run, jump to the site of John Gruber .
39 |
--------------------------------------------------------------------------------
/phantom/render.js:
--------------------------------------------------------------------------------
1 | var system = require('system')
2 | var page = require('webpage').create()
3 | var fs = require('fs')
4 | var os = require('system').os
5 |
6 | // Read in arguments
7 | var args = ['in', 'out', 'cwd', 'runningsPath', 'cssPath', 'highlightCssPath', 'paperFormat', 'paperOrientation', 'paperBorder', 'renderDelay', 'loadTimeout'].reduce(function (args, name, i) {
8 | args[name] = system.args[i + 1]
9 | return args
10 | }, {})
11 |
12 | var html5bpPath = page.libraryPath + '/../html5bp'
13 |
14 | // Resources don't load in windows with file protocol
15 | var isWin = os.name === 'windows'
16 | var protocol = isWin ? 'file:///' : 'file://'
17 |
18 | var html = fs.read(html5bpPath + '/index.html')
19 | .replace(/\{\{baseUrl\}\}/g, protocol + html5bpPath)
20 | .replace('{{content}}', fs.read(args.in))
21 |
22 | page.setContent(html, protocol + args.cwd + '/markdown-pdf.html')
23 |
24 | // Add custom CSS to the page
25 | page.evaluate(function (cssPaths) {
26 | var head = document.querySelector('head')
27 |
28 | cssPaths.forEach(function (cssPath) {
29 | var css = document.createElement('link')
30 | css.rel = 'stylesheet'
31 | css.href = cssPath
32 |
33 | head.appendChild(css)
34 | })
35 | }, [args.cssPath, args.highlightCssPath].map(function (cssPath) {
36 | return (isWin ? protocol : '') + cssPath
37 | }))
38 |
39 | // Set the PDF paper size
40 | page.paperSize = paperSize(args.runningsPath, { format: args.paperFormat, orientation: args.paperOrientation, border: isJson(args.paperBorder) ? JSON.parse(args.paperBorder) : args.paperBorder })
41 |
42 | args.renderDelay = parseInt(args.renderDelay, 10)
43 |
44 | if (args.renderDelay) {
45 | setTimeout(render, args.renderDelay)
46 | } else {
47 | var loadTimeout = setTimeout(render, parseInt(args.loadTimeout, 10))
48 | page.onLoadFinished = function () {
49 | clearTimeout(loadTimeout)
50 | render()
51 | }
52 | }
53 |
54 | function render () {
55 | page.render(args.out)
56 | page.close()
57 | window.phantom.exit(0)
58 | }
59 |
60 | function paperSize (runningsPath, obj) {
61 | var runnings = require(runningsPath)
62 |
63 | // encapsulate .contents into phantom.callback()
64 | // Why does phantomjs not support Array.prototype.forEach?!
65 | var keys = ['header', 'footer']
66 |
67 | for (var i = 0; i < keys.length; i++) {
68 | var which = keys[i]
69 |
70 | if (runnings[which] && runnings[which].contents && typeof runnings[which].contents === 'function') {
71 | obj[which] = {
72 | contents: window.phantom.callback(runnings[which].contents)
73 | }
74 |
75 | if (runnings[which].height) {
76 | obj[which].height = runnings[which].height
77 | }
78 | }
79 | }
80 |
81 | return obj
82 | }
83 |
84 | function isJson (str) { try { JSON.parse(str) } catch (e) { return false } return true }
85 |
--------------------------------------------------------------------------------
/test/fixtures/ipsum.md:
--------------------------------------------------------------------------------
1 | # A First Level Header
2 | ## A Second Level Header
3 | ### A Third Level Header
4 | #### A Fourth Level Header
5 | ##### A Fifth Level Header
6 | ###### A Sixth Level Header
7 |
8 |
9 |
10 | This is a paragraph. Cupcake ipsum dolor sit amet. Tiramisu liquorice gummies powder. Biscuit pastry pastry cake candy gummies carrot cake gingerbread. Gummi bears tart cupcake bonbon sugar plum biscuit. Icing marzipan tootsie roll. Pie gingerbread dragée wypas cookie. Faworki bonbon topping sweet soufflé jelly.
11 |
12 | And another paragraph. Jelly beans tootsie roll fruitcake toffee wypas chupa chups pudding. Soufflé muffin halvah powder sugar plum cake. Toffee cookie biscuit faworki pastry. Bonbon gummi bears topping caramels marshmallow. Chupa chups candy canes toffee. Powder powder candy canes pastry. Tootsie roll marshmallow powder.
13 |
14 |
15 |
16 | *These words are emphasized*
17 | _Also these words are emphasized_
18 |
19 | **These words are strong emphasized**
20 | __Also these words are strong emphasized__
21 |
22 |
23 | > This is a very simple blockquote
24 |
25 |
26 |
27 | * This
28 | * is
29 | * an
30 | * unordered
31 | * list.
32 |
33 | And...
34 |
35 | 1. This
36 | 2. is
37 | 3. an
38 | 4. ordered
39 | 5. list.
40 |
41 |
42 |
43 | [This is an example link](http://example.com/).
44 | [This is an example link with a title](http://example.com/ "¡Buenos días!").
45 |
46 |
47 |
48 | This is a image
49 | 
50 |
51 |
52 |
53 | `this is a line of code`
54 |
55 | And these are several lines of code. Pudding sesame snaps cupcake bonbon cupcake. Icing macaroon donut.
56 |
57 | More code. Donut cheesecake chocolate cake. Tart pudding wafer dessert chocolate bar jelly-o apple pie dessert. Carrot cake apple pie pie liquorice oat cake lollipop pastry caramels. Jelly-o sesame snaps gummi bears.
58 |
59 | And more. Sugar plum lemon drops chupa chups chocolate pastry. Faworki applicake applicake brownie topping liquorice chocolate liquorice icing. Cake pudding pudding cake candy sugar plum soufflé.`
60 |
61 |
62 | ```js
63 | var Remarkable = require('remarkable');
64 | var hljs = require('highlight.js') // https://highlightjs.org/
65 |
66 | // Actual default values
67 | var md = new Remarkable({
68 | highlight: function (str, language) {
69 | if (language && hljs.getLanguage(language)) {
70 | try {
71 | return hljs.highlight(str, { language }).value;
72 | } catch (err) {}
73 | }
74 |
75 | try {
76 | return hljs.highlightAuto(str).value;
77 | } catch (err) {}
78 |
79 | return ''; // use external default escaping
80 | }
81 | });
82 | ```
83 |
84 |
85 | And that's all ...
86 | This is an **extremely simple and basic** guide. To understand a lot better this kind of dark magic called markdown, logically I recommend the official wiki of the creator. Go, run, jump to [the site of John Gruber](http://daringfireball.net/projects/markdown/).
87 |
--------------------------------------------------------------------------------
/html5bp/doc/faq.md:
--------------------------------------------------------------------------------
1 | [HTML5 Boilerplate homepage](http://html5boilerplate.com) | [Documentation
2 | table of contents](TOC.md)
3 |
4 | # Frequently asked questions
5 |
6 | ### Why is the URL for jQuery without "http"?
7 |
8 | This is an intentional use of [protocol-relative
9 | URLs](http://paulirish.com/2010/the-protocol-relative-url/)
10 |
11 | **N.B.** Using a protocol-relative URL for files that exist on a CDN is
12 | problematic when you try to view your local files directly in the browser. The
13 | browser will attempt to fetch the file from your local file system. We
14 | recommend that you use a local server to test your pages (or Dropbox). This can
15 | be done using Python 2.x by running `python -m SimpleHTTPServer` or Python 3.x
16 | with `python -m http.server` from your local directory, using Ruby by installing
17 | and running [asdf](https://rubygems.org/gems/asdf), and by installing any one of
18 | XAMPP, MAMP, or WAMP.
19 |
20 | ### Why don't you automatically load the latest version of jQuery from the Google CDN?
21 |
22 | 1. The latest version of jQuery may not be compatible with the existing
23 | plugins/code on the site. Version updating should be an intentional
24 | decision.
25 | 2. The latest version has a very short `max-age=3600` compares to the specific
26 | version of `max-age=31536000`, which means you won't get the benefits of
27 | long-term caching.
28 |
29 |
30 | ### Why is the Google Analytics code at the bottom? Google recommends it be placed the `head`.
31 |
32 | The advantage to placing it in the `head` is that you will track a user's
33 | pageview even if they leave the page before it has been fully loaded. However,
34 | putting the code at the bottom keeps all the scripts together and reinforces
35 | that scripts at the bottom are the right move.
36 |
37 |
38 | ### How can I integrate [Twitter Bootstrap](http://twitter.github.com/bootstrap/) with HTML5 Boilerplate?
39 |
40 | You can use [Initializr](http://initializr.com) to create a custom build that
41 | includes HTML5 Boilerplate with Twitter Bootstrap.
42 |
43 | Read more about how [HTML5 Boilerplate and Twitter Bootstrap complement each
44 | other](http://www.quora.com/Is-Bootstrap-a-complement-OR-an-alternative-to-HTML5-Boilerplate-or-viceversa/answer/Nicolas-Gallagher).
45 |
46 |
47 | ### How do I prevent phone numbers looking twice as large and having a Skype highlight?
48 |
49 | If this is occurring, it is because a user has the Skype browser extension
50 | installed.
51 |
52 | Use the following CSS to prevent Skype from formatting the numbers on your
53 | page:
54 |
55 | ```css
56 | span.skype_pnh_container {
57 | display: none !important;
58 | }
59 |
60 | span.skype_pnh_print_container {
61 | display: inline !important;
62 | }
63 | ```
64 |
65 |
66 | ### Do I need to upgrade my sites each time a new version of HTML5 Boilerplate is released?
67 |
68 | No. You don't normally replace the foundations of a house once it has been
69 | built. There is nothing stopping you from trying to work in the latest changes
70 | but you'll have to assess the costs/benefits of doing so.
71 |
72 |
73 | ### Where can I get help for support questions?
74 |
75 | Please ask for help on
76 | [StackOverflow](http://stackoverflow.com/questions/tagged/html5boilerplate).
77 |
--------------------------------------------------------------------------------
/html5bp/doc/usage.md:
--------------------------------------------------------------------------------
1 | [HTML5 Boilerplate homepage](http://html5boilerplate.com) | [Documentation
2 | table of contents](TOC.md)
3 |
4 | # Usage
5 |
6 | Once you have cloned or downloaded HTML5 Boilerplate, creating a site or app
7 | usually involves the following:
8 |
9 | 1. Set up the basic structure of the site.
10 | 2. Add some content, style, and functionality.
11 | 3. Run your site locally to see how it looks.
12 | 4. (Optionally run a build script to automate the optimization of your site -
13 | e.g. [ant build script](https://github.com/h5bp/ant-build-script) or [node
14 | build script](https://github.com/h5bp/node-build-script)).
15 | 5. Deploy your site.
16 |
17 |
18 | ## Basic structure
19 |
20 | A basic HTML5 Boilerplate site initially looks something like this:
21 |
22 | ```
23 | .
24 | ├── css
25 | │ ├── main.css
26 | │ └── normalize.css
27 | ├── doc
28 | ├── img
29 | ├── js
30 | │ ├── main.js
31 | │ ├── plugins.js
32 | │ └── vendor
33 | │ ├── jquery.min.js
34 | │ └── modernizr.min.js
35 | ├── .htaccess
36 | ├── 404.html
37 | ├── apple-touch-icon-precomposed.png
38 | ├── index.html
39 | ├── humans.txt
40 | ├── robots.txt
41 | ├── crossdomain.xml
42 | └── favicon.ico
43 | ```
44 |
45 | What follows is a general overview of each major part and how to use them.
46 |
47 | ### css
48 |
49 | This directory should contain all your project's CSS files. It includes some
50 | initial CSS to help get you started from a solid foundation. [About the
51 | CSS](css.md).
52 |
53 | ### doc
54 |
55 | This directory contains all the HTML5 Boilerplate documentation. You can use it
56 | as the location and basis for your own project's documentation.
57 |
58 | ### js
59 |
60 | This directory should contain all your project's JS files. Libraries, plugins,
61 | and custom code can all be included here. It includes some initial JS to help
62 | get you started. [About the JavaScript](js.md).
63 |
64 | ### .htaccess
65 |
66 | The default web server configs are for Apache. For more information, please
67 | refer to the [Apache Server Configs
68 | documentation](https://github.com/h5bp/server-configs-apache/tree/master/doc).
69 |
70 | Host your site on a server other than Apache? You're likely to find the
71 | corresponding server configs project listed in our [Server Configs
72 | ](https://github.com/h5bp/server-configs/blob/master/README.md) repository.
73 |
74 | ### 404.html
75 |
76 | A helpful custom 404 to get you started.
77 |
78 | ### index.html
79 |
80 | This is the default HTML skeleton that should form the basis of all pages on
81 | your site. If you are using a server-side templating framework, then you will
82 | need to integrate this starting HTML with your setup.
83 |
84 | Make sure that you update the URLs for the referenced CSS and JavaScript if you
85 | modify the directory structure at all.
86 |
87 | If you are using Google Analytics, make sure that you edit the corresponding
88 | snippet at the bottom to include your analytics ID.
89 |
90 | ### humans.txt
91 |
92 | Edit this file to include the team that worked on your site/app, and the
93 | technology powering it.
94 |
95 | ### robots.txt
96 |
97 | Edit this file to include any pages you need hidden from search engines.
98 |
99 | ### crossdomain.xml
100 |
101 | A template for working with cross-domain requests. [About
102 | crossdomain.xml](crossdomain.md).
103 |
104 | ### Icons
105 |
106 | Replace the default `favicon.ico` and Apple Touch Icon with your own.
107 |
108 | If you want to use different Apple Touch Icons for different resolutions please
109 | refer to the [according documentation](extend.md#apple-touch-icons).
110 |
111 | You might want to check out Hans' handy [HTML5 Boilerplate Favicon and Apple
112 | Touch Icon
113 | PSD-Template](http://drublic.de/blog/html5-boilerplate-favicons-psd-template/).
114 |
--------------------------------------------------------------------------------
/html5bp/404.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Page Not Found :(
6 |
141 |
142 |
143 |
144 |
Not found :(
145 |
Sorry, but the page you were trying to view does not exist.
146 |
It looks like this was the result of either:
147 |
148 | a mistyped address
149 | an out-of-date link
150 |
151 |
154 |
155 |
156 |
157 |
158 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | var fs = require('fs')
2 | var path = require('path')
3 | var childProcess = require('child_process')
4 | var through = require('through2')
5 | var extend = require('extend')
6 | var { Remarkable } = require('remarkable')
7 | var hljs = require('highlight.js')
8 | var tmp = require('tmp')
9 | var duplexer = require('duplexer')
10 | var streamft = require('stream-from-to')
11 |
12 | tmp.setGracefulCleanup()
13 |
14 | function markdownpdf (opts) {
15 | opts = opts || {}
16 | opts.cwd = opts.cwd ? path.resolve(opts.cwd) : process.cwd()
17 | opts.phantomPath = opts.phantomPath || require('phantomjs-prebuilt').path
18 | opts.runningsPath = opts.runningsPath ? path.resolve(opts.runningsPath) : path.join(__dirname, 'runnings.js')
19 | opts.cssPath = opts.cssPath ? path.resolve(opts.cssPath) : path.join(__dirname, 'css', 'pdf.css')
20 | opts.highlightCssPath = opts.highlightCssPath ? path.resolve(opts.highlightCssPath) : path.join(__dirname, 'css', 'highlight.css')
21 | opts.paperFormat = opts.paperFormat || 'A4'
22 | opts.paperOrientation = opts.paperOrientation || 'portrait'
23 | opts.paperBorder = opts.paperBorder || '2cm'
24 | opts.renderDelay = opts.renderDelay == null ? 0 : opts.renderDelay
25 | opts.loadTimeout = opts.loadTimeout == null ? 10000 : opts.loadTimeout
26 | opts.preProcessMd = opts.preProcessMd || function () { return through() }
27 | opts.preProcessHtml = opts.preProcessHtml || function () { return through() }
28 | opts.remarkable = extend({ breaks: true }, opts.remarkable)
29 | opts.remarkable.preset = opts.remarkable.preset || 'default'
30 | opts.remarkable.plugins = opts.remarkable.plugins || []
31 | opts.remarkable.syntax = opts.remarkable.syntax || []
32 |
33 | var md = ''
34 |
35 | var mdToHtml = through(
36 | function transform (chunk, enc, cb) {
37 | md += chunk
38 | cb()
39 | },
40 | function flush (cb) {
41 | var self = this
42 |
43 | var mdParser = new Remarkable(opts.remarkable.preset, extend({
44 | highlight: function (str, language) {
45 | if (language && hljs.getLanguage(language)) {
46 | try {
47 | return hljs.highlight(str, { language }).value
48 | } catch (err) {}
49 | }
50 |
51 | try {
52 | return hljs.highlightAuto(str).value
53 | } catch (err) {}
54 |
55 | return ''
56 | }
57 | }, opts.remarkable))
58 |
59 | opts.remarkable.plugins.forEach(function (plugin) {
60 | if (plugin && typeof plugin === 'function') {
61 | mdParser.use(plugin)
62 | }
63 | })
64 |
65 | opts.remarkable.syntax.forEach(function (rule) {
66 | try {
67 | mdParser.core.ruler.enable([rule])
68 | } catch (err) {}
69 | try {
70 | mdParser.block.ruler.enable([rule])
71 | } catch (err) {}
72 | try {
73 | mdParser.inline.ruler.enable([rule])
74 | } catch (err) {}
75 | })
76 |
77 | self.push(mdParser.render(md))
78 | self.push(null)
79 | }
80 | )
81 |
82 | var inputStream = through()
83 | var outputStream = through()
84 |
85 | // Stop input stream emitting data events until we're ready to read them
86 | inputStream.pause()
87 |
88 | // Create tmp file to save HTML for phantom to process
89 | tmp.file({ postfix: '.html' }, function (err, tmpHtmlPath, tmpHtmlFd) {
90 | if (err) return outputStream.emit('error', err)
91 | fs.closeSync(tmpHtmlFd)
92 |
93 | // Create tmp file to save PDF to
94 | tmp.file({ postfix: '.pdf' }, function (err, tmpPdfPath, tmpPdfFd) {
95 | if (err) return outputStream.emit('error', err)
96 | fs.closeSync(tmpPdfFd)
97 |
98 | var htmlToTmpHtmlFile = fs.createWriteStream(tmpHtmlPath)
99 |
100 | htmlToTmpHtmlFile.on('finish', function () {
101 | // Invoke phantom to generate the PDF
102 | var childArgs = [
103 | path.join(__dirname, 'phantom', 'render.js'),
104 | tmpHtmlPath,
105 | tmpPdfPath,
106 | opts.cwd,
107 | opts.runningsPath,
108 | opts.cssPath,
109 | opts.highlightCssPath,
110 | opts.paperFormat,
111 | opts.paperOrientation,
112 | typeof opts.paperBorder === 'object' ? JSON.stringify(opts.paperBorder) : opts.paperBorder,
113 | opts.renderDelay,
114 | opts.loadTimeout
115 | ]
116 |
117 | childProcess.execFile(opts.phantomPath, childArgs, function (err, stdout, stderr) {
118 | // if (stdout) console.log(stdout)
119 | // if (stderr) console.error(stderr)
120 | if (err) return outputStream.emit('error', err)
121 | fs.createReadStream(tmpPdfPath).pipe(outputStream)
122 | })
123 | })
124 |
125 | // Setup the pipeline
126 | inputStream
127 | .pipe(opts.preProcessMd())
128 | .pipe(mdToHtml)
129 | .pipe(opts.preProcessHtml())
130 | .pipe(htmlToTmpHtmlFile)
131 |
132 | inputStream.resume()
133 | })
134 | })
135 |
136 | return extend(
137 | duplexer(inputStream, outputStream),
138 | streamft(function () {
139 | return markdownpdf(opts)
140 | })
141 | )
142 | }
143 |
144 | module.exports = markdownpdf
145 |
--------------------------------------------------------------------------------
/html5bp/doc/css.md:
--------------------------------------------------------------------------------
1 | [HTML5 Boilerplate homepage](http://html5boilerplate.com) | [Documentation
2 | table of contents](TOC.md)
3 |
4 | # The CSS
5 |
6 | The HTML5 Boilerplate starting CSS includes:
7 |
8 | * [Normalize.css](https://github.com/necolas/normalize.css).
9 | * Useful HTML5 Boilerplate defaults.
10 | * Common helpers.
11 | * Placeholder media queries.
12 | * Print styles.
13 |
14 | This starting CSS does not rely on the presence of conditional classnames,
15 | conditional style sheets, or Modernizr. It is ready to use whatever your
16 | development preferences happen to be.
17 |
18 |
19 | ## Normalize.css
20 |
21 | Normalize.css is a modern, HTML5-ready alternative to CSS resets. It contains
22 | extensive inline documentation. Please refer to the [Normalize.css
23 | project](http://necolas.github.com/normalize.css/) for more information.
24 |
25 |
26 | ## HTML5 Boilerplate defaults
27 |
28 | This project includes a handful of base styles that build upon Normalize.css.
29 | These include:
30 |
31 | * Basic typography settings to provide improved text readability by default.
32 | * Protection against unwanted `text-shadow` during text highlighting.
33 | * Tweaks to default image alignment, fieldsets, and textareas.
34 | * A pretty Chrome Frame prompt.
35 |
36 | You are free to modify or add to these base styles as your project requires.
37 |
38 |
39 | ## Common helpers
40 |
41 | #### `.ir`
42 |
43 | Add the `.ir` class to any element you are applying image-replacement to. When
44 | replacing an element's content with an image, make sure to also set a specific
45 | `background-image: url(pathtoimage.png);`, `width`, and `height` so that your
46 | replacement image appears.
47 |
48 | #### `.hidden`
49 |
50 | Add the `.hidden` class to any elements that you want to hide from all
51 | presentations, including screen readers. It could be an element that will be
52 | populated later with JavaScript or an element you will hide with JavaScript. Do
53 | not use this for SEO keyword stuffing. That is just not cool.
54 |
55 | #### `.visuallyhidden`
56 |
57 | Add the `.visuallyhidden` class to hide text from browsers but make it
58 | available for screen readers. You can use this to hide text that is specific to
59 | screen readers but that other users should not see. [About invisible
60 | content](http://www.webaim.org/techniques/css/invisiblecontent/), [Hiding
61 | content for
62 | accessibility](http://snook.ca/archives/html_and_css/hiding-content-for-accessibility),
63 | [HTML5 Boilerplate
64 | issue/research](https://github.com/h5bp/html5-boilerplate/issues/194/).
65 |
66 | #### `.invisible`
67 |
68 | Add the `.invisible` class to any element you want to hide without affecting
69 | layout. When you use `display: none` an element is effectively removed from the
70 | layout. But in some cases you want the element to simply be invisible while
71 | remaining in the flow and not affecting the positioning of surrounding
72 | content.
73 |
74 | #### `.clearfix`
75 |
76 | Adding `.clearfix` to an element will ensure that it always fully contains its
77 | floated children. There have been many variants of the clearfix hack over the
78 | years, and there are other hacks that can also help you to contain floated
79 | children, but the HTML5 Boilerplate currently uses the [micro
80 | clearfix](http://nicolasgallagher.com/micro-clearfix-hack/).
81 |
82 |
83 | ## Media Queries
84 |
85 | The boilerplate makes it easy to get started with a "Mobile First" and
86 | [Responsive Web
87 | Design](http://www.alistapart.com/articles/responsive-web-design/) approach to
88 | development. But it's worth remembering that there are [no silver
89 | bullets](http://www.cloudfour.com/css-media-query-for-mobile-is-fools-gold/).
90 |
91 | We include a placeholder Media Queries to build up your mobile styles for wider
92 | viewports and high-resolution displays. It's recommended that you adapt these
93 | Media Queries based on the content of your site rather than mirroring the fixed
94 | dimensions of specific devices.
95 |
96 | If you do not want to take a "Mobile First" approach, you can simply edit or
97 | remove these placeholder Media Queries. One possibility would be to work from
98 | wide viewports down and use `max-width` MQs instead, e.g., `@media only screen
99 | and (max-width: 480px)`.
100 |
101 | Take a look into the [Mobile
102 | Boilerplate](https://github.com/h5bp/mobile-boilerplate) for features that are
103 | useful when developing mobile wep apps.
104 |
105 |
106 | ## Print styles
107 |
108 | * Print styles are inlined to [reduce the number of page
109 | requests](http://www.phpied.com/delay-loading-your-print-css/).
110 | * We strip all background colors, change the font color to black and remove
111 | text-shadow. This is meant to [help save printer ink and make the printing
112 | process much faster](http://www.sanbeiji.com/archives/953).
113 | * Anchors do not need colors to indicate they are linked. They are underlined
114 | to indicate so.
115 | * Anchors and Abbreviations are expanded to indicate where users reading the
116 | printed page can refer to.
117 | * But we do not want to show link text for image replaced elements (given that
118 | they are primarily images).
119 |
120 | ### Paged media styles
121 |
122 | * Paged media is supported only in a [few
123 | browsers](http://en.wikipedia.org/wiki/Comparison_of_layout_engines_%28Cascading_Style_Sheets%29#Grammar_and_rules).
124 | * Paged media support means browsers would know how to interpret instructions
125 | on breaking content into pages and on orphans/widows.
126 | * We use `page-break-inside: avoid;` to prevent an image and table row from
127 | being split into two different pages, so use the same `page-break-inside:
128 | avoid;` for that as well.
129 | * Headings should always appear with the text they are titles for. So, we
130 | ensure headings never appear in a different page than the text they describe
131 | by using `page-break-after: avoid;`.
132 | * We also apply a default margin for the page specified in `cm`.
133 | * We do not want [orphans and
134 | widows](http://en.wikipedia.org/wiki/Widows_and_orphans) to appear on pages
135 | you print. So, by defining `orphans: 3` and `widows: 3` you define the minimal
136 | number of words that every line should contain.
137 |
--------------------------------------------------------------------------------
/html5bp/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to HTML5 Boilerplate
2 |
3 | ♥ [HTML5 Boilerplate](http://html5boilerplate.com) and want to get involved?
4 | Thanks! There are plenty of ways you can help!
5 |
6 | Please take a moment to review this document in order to make the contribution
7 | process easy and effective for everyone involved.
8 |
9 | Following these guidelines helps to communicate that you respect the time of
10 | the developers managing and developing this open source project. In return,
11 | they should reciprocate that respect in addressing your issue or assessing
12 | patches and features.
13 |
14 |
15 | ## Using the issue tracker
16 |
17 | The [issue tracker](https://github.com/h5bp/html5-boilerplate/issues) is
18 | the preferred channel for [bug reports](#bugs), [features requests](#features)
19 | and [submitting pull requests](#pull-requests), but please respect the following
20 | restrictions:
21 |
22 | * Please **do not** use the issue tracker for personal support requests (use
23 | [Stack Overflow](http://stackoverflow.com/questions/tagged/html5boilerplate)
24 | or IRC).
25 |
26 | * Please **do not** derail or troll issues. Keep the discussion on topic and
27 | respect the opinions of others.
28 |
29 | * Please **do not** open issues or pull requests regarding the code in
30 | [`.htaccess`](https://github.com/h5bp/server-configs-apache),
31 | [`jQuery`](https://github.com/jquery/jquery/),
32 | [`Modernizr`](https://github.com/Modernizr/Modernizr) or
33 | [`Normalize.css`](https://github.com/necolas/normalize.css) (open them in
34 | their respective repositories).
35 |
36 |
37 |
38 | ## Bug reports
39 |
40 | A bug is a _demonstrable problem_ that is caused by the code in the repository.
41 | Good bug reports are extremely helpful - thank you!
42 |
43 | Guidelines for bug reports:
44 |
45 | 1. **Use the GitHub issue search** — check if the issue has already been
46 | reported.
47 |
48 | 2. **Check if the issue has been fixed** — try to reproduce it using the
49 | latest `master` or development branch in the repository.
50 |
51 | 3. **Isolate the problem** — ideally create a [reduced test
52 | case](http://css-tricks.com/6263-reduced-test-cases/) and a live example.
53 |
54 | A good bug report shouldn't leave others needing to chase you up for more
55 | information. Please try to be as detailed as possible in your report. What is
56 | your environment? What steps will reproduce the issue? What browser(s) and OS
57 | experience the problem? What would you expect to be the outcome? All these
58 | details will help people to fix any potential bugs.
59 |
60 | Example:
61 |
62 | > Short and descriptive example bug report title
63 | >
64 | > A summary of the issue and the browser/OS environment in which it occurs. If
65 | > suitable, include the steps required to reproduce the bug.
66 | >
67 | > 1. This is the first step
68 | > 2. This is the second step
69 | > 3. Further steps, etc.
70 | >
71 | > `` - a link to the reduced test case
72 | >
73 | > Any other information you want to share that is relevant to the issue being
74 | > reported. This might include the lines of code that you have identified as
75 | > causing the bug, and potential solutions (and your opinions on their
76 | > merits).
77 |
78 |
79 |
80 | ## Feature requests
81 |
82 | Feature requests are welcome. But take a moment to find out whether your idea
83 | fits with the scope and aims of the project. It's up to *you* to make a strong
84 | case to convince the project's developers of the merits of this feature. Please
85 | provide as much detail and context as possible.
86 |
87 |
88 |
89 | ## Pull requests
90 |
91 | Good pull requests - patches, improvements, new features - are a fantastic
92 | help. They should remain focused in scope and avoid containing unrelated
93 | commits.
94 |
95 | **Please ask first** before embarking on any significant pull request (e.g.
96 | implementing features, refactoring code, porting to a different language),
97 | otherwise you risk spending a lot of time working on something that the
98 | project's developers might not want to merge into the project.
99 |
100 | Please adhere to the coding conventions used throughout a project (indentation,
101 | accurate comments, etc.) and any other requirements (such as test coverage).
102 |
103 | Adhering to the following this process is the best way to get your work
104 | included in the project:
105 |
106 | 1. [Fork](http://help.github.com/fork-a-repo/) the project, clone your fork,
107 | and configure the remotes:
108 |
109 | ```bash
110 | # Clone your fork of the repo into the current directory
111 | git clone https://github.com//html5-boilerplate.git
112 | # Navigate to the newly cloned directory
113 | cd html5-boilerplate
114 | # Assign the original repo to a remote called "upstream"
115 | git remote add upstream https://github.com/h5bp/html5-boilerplate.git
116 | ```
117 |
118 | 2. If you cloned a while ago, get the latest changes from upstream:
119 |
120 | ```bash
121 | git checkout master
122 | git pull upstream master
123 | ```
124 |
125 | 3. Create a new topic branch (off the main project development branch) to
126 | contain your feature, change, or fix:
127 |
128 | ```bash
129 | git checkout -b
130 | ```
131 |
132 | 4. Commit your changes in logical chunks. Please adhere to these [git commit
133 | message guidelines](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html)
134 | or your code is unlikely be merged into the main project. Use Git's
135 | [interactive rebase](https://help.github.com/articles/interactive-rebase)
136 | feature to tidy up your commits before making them public.
137 |
138 | 5. Locally merge (or rebase) the upstream development branch into your topic branch:
139 |
140 | ```bash
141 | git pull [--rebase] upstream master
142 | ```
143 |
144 | 6. Push your topic branch up to your fork:
145 |
146 | ```bash
147 | git push origin
148 | ```
149 |
150 | 7. [Open a Pull Request](https://help.github.com/articles/using-pull-requests/)
151 | with a clear title and description.
152 |
153 | **IMPORTANT**: By submitting a patch, you agree to allow the project owners to
154 | license your work under the the terms of the [MIT License](LICENSE.md).
155 |
--------------------------------------------------------------------------------
/html5bp/css/main.css:
--------------------------------------------------------------------------------
1 | /*! HTML5 Boilerplate v4.3.0 | MIT License | http://h5bp.com/ */
2 |
3 | /*
4 | * What follows is the result of much research on cross-browser styling.
5 | * Credit left inline and big thanks to Nicolas Gallagher, Jonathan Neal,
6 | * Kroc Camen, and the H5BP dev community and team.
7 | */
8 |
9 | /* ==========================================================================
10 | Base styles: opinionated defaults
11 | ========================================================================== */
12 |
13 | html,
14 | button,
15 | input,
16 | select,
17 | textarea {
18 | color: #222;
19 | }
20 |
21 | html {
22 | font-size: 1em;
23 | line-height: 1.4;
24 | }
25 |
26 | /*
27 | * Remove text-shadow in selection highlight: h5bp.com/i
28 | * These selection rule sets have to be separate.
29 | * Customize the background color to match your design.
30 | */
31 |
32 | ::-moz-selection {
33 | background: #b3d4fc;
34 | text-shadow: none;
35 | }
36 |
37 | ::selection {
38 | background: #b3d4fc;
39 | text-shadow: none;
40 | }
41 |
42 | /*
43 | * A better looking default horizontal rule
44 | */
45 |
46 | hr {
47 | display: block;
48 | height: 1px;
49 | border: 0;
50 | border-top: 1px solid #ccc;
51 | margin: 1em 0;
52 | padding: 0;
53 | }
54 |
55 | /*
56 | * Remove the gap between images, videos, audio and canvas and the bottom of
57 | * their containers: h5bp.com/i/440
58 | */
59 |
60 | audio,
61 | canvas,
62 | img,
63 | video {
64 | vertical-align: middle;
65 | }
66 |
67 | /*
68 | * Remove default fieldset styles.
69 | */
70 |
71 | fieldset {
72 | border: 0;
73 | margin: 0;
74 | padding: 0;
75 | }
76 |
77 | /*
78 | * Allow only vertical resizing of textareas.
79 | */
80 |
81 | textarea {
82 | resize: vertical;
83 | }
84 |
85 | /* ==========================================================================
86 | Browse Happy prompt
87 | ========================================================================== */
88 |
89 | .browsehappy {
90 | margin: 0.2em 0;
91 | background: #ccc;
92 | color: #000;
93 | padding: 0.2em 0;
94 | }
95 |
96 | /* ==========================================================================
97 | Author's custom styles
98 | ========================================================================== */
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 | /* ==========================================================================
117 | Helper classes
118 | ========================================================================== */
119 |
120 | /*
121 | * Image replacement
122 | */
123 |
124 | .ir {
125 | background-color: transparent;
126 | border: 0;
127 | overflow: hidden;
128 | /* IE 6/7 fallback */
129 | *text-indent: -9999px;
130 | }
131 |
132 | .ir:before {
133 | content: "";
134 | display: block;
135 | width: 0;
136 | height: 150%;
137 | }
138 |
139 | /*
140 | * Hide from both screenreaders and browsers: h5bp.com/u
141 | */
142 |
143 | .hidden {
144 | display: none !important;
145 | visibility: hidden;
146 | }
147 |
148 | /*
149 | * Hide only visually, but have it available for screenreaders: h5bp.com/v
150 | */
151 |
152 | .visuallyhidden {
153 | border: 0;
154 | clip: rect(0 0 0 0);
155 | height: 1px;
156 | margin: -1px;
157 | overflow: hidden;
158 | padding: 0;
159 | position: absolute;
160 | width: 1px;
161 | }
162 |
163 | /*
164 | * Extends the .visuallyhidden class to allow the element to be focusable
165 | * when navigated to via the keyboard: h5bp.com/p
166 | */
167 |
168 | .visuallyhidden.focusable:active,
169 | .visuallyhidden.focusable:focus {
170 | clip: auto;
171 | height: auto;
172 | margin: 0;
173 | overflow: visible;
174 | position: static;
175 | width: auto;
176 | }
177 |
178 | /*
179 | * Hide visually and from screenreaders, but maintain layout
180 | */
181 |
182 | .invisible {
183 | visibility: hidden;
184 | }
185 |
186 | /*
187 | * Clearfix: contain floats
188 | *
189 | * For modern browsers
190 | * 1. The space content is one way to avoid an Opera bug when the
191 | * `contenteditable` attribute is included anywhere else in the document.
192 | * Otherwise it causes space to appear at the top and bottom of elements
193 | * that receive the `clearfix` class.
194 | * 2. The use of `table` rather than `block` is only necessary if using
195 | * `:before` to contain the top-margins of child elements.
196 | */
197 |
198 | .clearfix:before,
199 | .clearfix:after {
200 | content: " "; /* 1 */
201 | display: table; /* 2 */
202 | }
203 |
204 | .clearfix:after {
205 | clear: both;
206 | }
207 |
208 | /*
209 | * For IE 6/7 only
210 | * Include this rule to trigger hasLayout and contain floats.
211 | */
212 |
213 | .clearfix {
214 | *zoom: 1;
215 | }
216 |
217 | /* ==========================================================================
218 | EXAMPLE Media Queries for Responsive Design.
219 | These examples override the primary ('mobile first') styles.
220 | Modify as content requires.
221 | ========================================================================== */
222 |
223 | @media only screen and (min-width: 35em) {
224 | /* Style adjustments for viewports that meet the condition */
225 | }
226 |
227 | @media print,
228 | (-o-min-device-pixel-ratio: 5/4),
229 | (-webkit-min-device-pixel-ratio: 1.25),
230 | (min-resolution: 120dpi) {
231 | /* Style adjustments for high resolution devices */
232 | }
233 |
234 | /* ==========================================================================
235 | Print styles.
236 | Inlined to avoid required HTTP connection: h5bp.com/r
237 | ========================================================================== */
238 |
239 | @media print {
240 |
241 | a,
242 | a:visited {
243 | text-decoration: underline;
244 | }
245 |
246 | a[href]:after {
247 | content: " (" attr(href) ")";
248 | }
249 |
250 | abbr[title]:after {
251 | content: " (" attr(title) ")";
252 | }
253 |
254 | /*
255 | * Don't show links for images, or javascript/internal links
256 | */
257 |
258 | .ir a:after,
259 | a[href^="javascript:"]:after,
260 | a[href^="#"]:after {
261 | content: "";
262 | }
263 |
264 | pre,
265 | blockquote {
266 | border: 1px solid #999;
267 | page-break-inside: avoid;
268 | }
269 |
270 | thead {
271 | display: table-header-group; /* h5bp.com/t */
272 | }
273 |
274 | tr,
275 | img {
276 | page-break-inside: avoid;
277 | }
278 |
279 | img {
280 | max-width: 100%;
281 | }
282 |
283 | @page {
284 | margin: 0.5cm;
285 | }
286 |
287 | p,
288 | h2,
289 | h3 {
290 | orphans: 3;
291 | widows: 3;
292 | }
293 |
294 | h2,
295 | h3 {
296 | page-break-after: avoid;
297 | }
298 | }
299 |
--------------------------------------------------------------------------------
/test/index.js:
--------------------------------------------------------------------------------
1 | var fs = require('fs')
2 | var path = require('path')
3 | var test = require('tape')
4 | var markdownpdf = require('../')
5 | var tmp = require('tmp')
6 | var through = require('through2')
7 | var pdfText = require('pdf-text')
8 |
9 | tmp.setGracefulCleanup()
10 |
11 | test('generate a nonempty PDF from ipsum.md', function (t) {
12 | t.plan(4)
13 |
14 | tmp.file({ postfix: '.pdf' }, function (er, tmpPdfPath, tmpPdfFd) {
15 | t.ifError(er)
16 | fs.closeSync(tmpPdfFd)
17 |
18 | markdownpdf().from(path.join(__dirname, '/fixtures/ipsum.md')).to(tmpPdfPath, function (er) {
19 | t.ifError(er)
20 |
21 | // Read the file
22 | fs.readFile(tmpPdfPath, { encoding: 'utf8' }, function (er, data) {
23 | t.ifError(er)
24 | // Test not empty
25 | t.ok(data.length > 0)
26 | t.end()
27 | })
28 | })
29 | })
30 | })
31 |
32 | test('generate PDF with CSS from ipsum.md and style.css', function (t) {
33 | t.plan(6)
34 |
35 | tmp.file({ postfix: '.pdf' }, function (er, tmpPdfPath, tmpPdfFd) {
36 | t.ifError(er)
37 | fs.closeSync(tmpPdfFd)
38 |
39 | markdownpdf({
40 | cssPath: path.join(__dirname, '/fixtures/style.css')
41 | }).from(path.join(__dirname, '/fixtures/ipsum.md')).to(tmpPdfPath, function (er) {
42 | t.ifError(er)
43 |
44 | // Read the file
45 | fs.readFile(tmpPdfPath, { encoding: 'utf8' }, function (er, data) {
46 | t.ifError(er)
47 | // Test not empty
48 | t.ok(data.length > 0)
49 |
50 | pdfText(tmpPdfPath, function (er, chunks) {
51 | t.ifError(er)
52 |
53 | t.ok(/forty-two/.test(chunks.join('')), 'contains h1::after injected content')
54 | t.end()
55 | })
56 | })
57 | })
58 | })
59 | })
60 |
61 | test('output should have a header and footer', function (t) {
62 | t.plan(7)
63 |
64 | tmp.file({ postfix: '.pdf' }, function (er, tmpPdfPath, tmpPdfFd) {
65 | t.ifError(er)
66 | fs.closeSync(tmpPdfFd)
67 |
68 | markdownpdf({ runningsPath: path.join(__dirname, '/fixtures/runnings.js') }).from(path.join(__dirname, '/fixtures/ipsum.md')).to(tmpPdfPath, function (er) {
69 | t.ifError(er)
70 |
71 | // Read the file
72 | fs.readFile(tmpPdfPath, { encoding: 'utf8' }, function (er, data) {
73 | t.ifError(er)
74 | // Test not empty
75 | t.ok(data.length > 0)
76 |
77 | // Header and footer included?
78 | pdfText(tmpPdfPath, function (er, chunks) {
79 | t.ifError(er)
80 |
81 | t.ok(/Some\s?Header/.test(chunks.join('')))
82 | t.ok(/Some\s?Footer/.test(chunks.join('')))
83 | t.end()
84 | })
85 | })
86 | })
87 | })
88 | })
89 |
90 | test('should call preProcessMd hook', function (t) {
91 | t.plan(3)
92 |
93 | var writeCount = 0
94 | var preProcessMd = function () { return through(function (data, enc, cb) { writeCount++; this.push(data); cb() }) }
95 |
96 | markdownpdf({ preProcessMd: preProcessMd }).from(path.join(__dirname, '/fixtures/ipsum.md')).to.string(function (er, pdfStr) {
97 | t.ifError(er)
98 |
99 | // Test not empty
100 | t.ok(pdfStr.length > 0)
101 | t.ok(writeCount > 0, 'Write count expected to be > 0')
102 | t.end()
103 | })
104 | })
105 |
106 | test('should call preProcessHtml hook', function (t) {
107 | t.plan(3)
108 |
109 | var writeCount = 0
110 | var preProcessHtml = function () { return through(function (data, enc, cb) { writeCount++; this.push(data); cb() }) }
111 |
112 | markdownpdf({ preProcessHtml: preProcessHtml }).from(path.join(__dirname, '/fixtures/ipsum.md')).to.string(function (er, pdfStr) {
113 | t.ifError(er)
114 |
115 | // Test not empty
116 | t.ok(pdfStr.length > 0)
117 | t.ok(writeCount > 0, 'Write count expected to be > 0')
118 | t.end()
119 | })
120 | })
121 |
122 | test('should concatenate source files', function (t) {
123 | t.plan(4)
124 |
125 | var files = [
126 | path.join(__dirname, '/fixtures/first.md'),
127 | path.join(__dirname, '/fixtures/second.md')
128 | ]
129 |
130 | tmp.file({ postfix: '.pdf' }, function (er, tmpPdfPath, tmpPdfFd) {
131 | t.ifError(er)
132 | fs.closeSync(tmpPdfFd)
133 |
134 | markdownpdf().concat.from(files).to(tmpPdfPath, function (er) {
135 | t.ifError(er)
136 |
137 | // Read the file
138 | fs.readFile(tmpPdfPath, { encoding: 'utf8' }, function (er, data) {
139 | t.ifError(er)
140 | // Test not empty
141 | t.ok(data.length > 0)
142 | t.end()
143 | })
144 | })
145 | })
146 | })
147 |
148 | test('should write to multiple paths when converting multiple files', function (t) {
149 | t.plan(6)
150 |
151 | var files = [
152 | path.join(__dirname, '/fixtures/first.md'),
153 | path.join(__dirname, '/fixtures/second.md')
154 | ]
155 |
156 | tmp.file({ postfix: '.pdf' }, function (er, tmpPdfPath0, tmpPdfFd0) {
157 | t.ifError(er)
158 | fs.closeSync(tmpPdfFd0)
159 |
160 | tmp.file({ postfix: '.pdf' }, function (er, tmpPdfPath1, tmpPdfFd1) {
161 | t.ifError(er)
162 | fs.closeSync(tmpPdfFd1)
163 |
164 | markdownpdf().from.paths(files).to.paths([tmpPdfPath0, tmpPdfPath1], function (er) {
165 | t.ifError(er)
166 |
167 | // Read the file
168 | var content0 = fs.readFileSync(tmpPdfPath0, { encoding: 'utf8' })
169 | var content1 = fs.readFileSync(tmpPdfPath1, { encoding: 'utf8' })
170 |
171 | t.ok(content0.length > 0)
172 | t.ok(content1.length > 0)
173 | t.ok(content0.length !== content1.length)
174 |
175 | t.end()
176 | })
177 | })
178 | })
179 | })
180 |
181 | test('should accept remarkable preset', function (t) {
182 | t.plan(2)
183 |
184 | var html = ''
185 | var opts = {
186 | remarkable: { preset: 'full' },
187 | preProcessHtml: function () {
188 | return through(
189 | function transform (chunk, enc, cb) {
190 | html += chunk
191 | cb()
192 | },
193 | function flush (cb) {
194 | var htmlSupTagFound = (html.indexOf('st ') > -1)
195 | t.ok(htmlSupTagFound, 'html tag not found for preset "full"')
196 | cb()
197 | }
198 | )
199 | }
200 | }
201 |
202 | // Preset 'full' - expecting -tag in html
203 | markdownpdf(opts).from.string('1^st^ of January').to.string(function (er, pdfStr) {
204 | t.ifError(er)
205 | t.end()
206 | })
207 | })
208 |
209 | test('should initialize remarkable plugins', function (t) {
210 | t.plan(2)
211 |
212 | var pluginInit = false
213 |
214 | var remarkableOpts = {
215 | plugins: [
216 | // should skip non-functions
217 | undefined,
218 | 'test',
219 | function (md, opts) {
220 | pluginInit = true
221 | }
222 | ]
223 | }
224 |
225 | markdownpdf({ remarkable: remarkableOpts }).from(path.join(__dirname, '/fixtures/ipsum.md')).to.string(function (er, pdfStr) {
226 | t.ifError(er)
227 |
228 | t.assert(pluginInit, 'check plugin init')
229 | t.end()
230 | })
231 | })
232 |
--------------------------------------------------------------------------------
/html5bp/doc/html.md:
--------------------------------------------------------------------------------
1 | [HTML5 Boilerplate homepage](http://html5boilerplate.com) | [Documentation
2 | table of contents](TOC.md)
3 |
4 | # The HTML
5 |
6 | ## Conditional `html` classes
7 |
8 | A series of IE conditional comments apply the relevant IE-specific classes to
9 | the `html` tag. This provides one method of specifying CSS fixes for specific
10 | legacy versions of IE. While you may or may not choose to use this technique in
11 | your project code, HTML5 Boilerplate's default CSS does not rely on it.
12 |
13 | When using the conditional classes technique, applying classes to the `html`
14 | element has several benefits:
15 |
16 | * It avoids a [file blocking
17 | issue](http://webforscher.wordpress.com/2010/05/20/ie-6-slowing-down-ie-8/)
18 | discovered by Stoyan Stefanov and Markus Leptien.
19 | * It avoids the need for an empty comment that also fixes the above issue.
20 | * CMSes like WordPress and Drupal use the body class more heavily. This makes
21 | integrating there a touch simpler.
22 | * It still validates as HTML5.
23 | * It uses the same element as Modernizr (and Dojo). That feels nice.
24 | * It can improve the clarity of code in multi-developer teams.
25 |
26 |
27 | ## The `no-js` class
28 |
29 | Allows you to more easily explicitly add custom styles when JavaScript is
30 | disabled (`no-js`) or enabled (`js`). More here: [Avoiding the
31 | FOUC](http://paulirish.com/2009/avoiding-the-fouc-v3/).
32 |
33 |
34 | ## The order of meta tags, and ``
35 |
36 | As recommended by [the HTML5
37 | spec](http://www.whatwg.org/specs/web-apps/current-work/complete/semantics.html#charset)
38 | (4.2.5.5 Specifying the document's character encoding), add your charset
39 | declaration early (before any ASCII art ;) to avoid a potential
40 | [encoding-related security
41 | issue](http://code.google.com/p/doctype-mirror/wiki/ArticleUtf7) in IE. It
42 | should come in the first [1024
43 | bytes](http://www.whatwg.org/specs/web-apps/current-work/multipage/semantics.html#charset).
44 |
45 | The charset should also come before the `` tag, due to [potential XSS
46 | vectors](http://code.google.com/p/doctype-mirror/wiki/ArticleUtf7).
47 |
48 | The meta tag for compatibility mode [needs to be before all elements except
49 | title and meta](http://h5bp.com/f "Defining Document Compatibility - MSDN").
50 | And that same meta tag can only be invoked for Google Chrome Frame if it is
51 | within the [first 1024
52 | bytes](http://code.google.com/p/chromium/issues/detail?id=23003).
53 |
54 |
55 | ## X-UA-Compatible
56 |
57 | This makes sure the latest version of IE is used in versions of IE that contain
58 | multiple rendering engines. Even if a site visitor is using IE8 or IE9, it's
59 | possible that they're not using the latest rendering engine their browser
60 | contains. To fix this, use:
61 |
62 | ```html
63 |
64 | ```
65 |
66 | The `meta` tag tells the IE rendering engine it should use the latest, or edge,
67 | version of the IE rendering environment.
68 |
69 | This `meta` tag ensures that anyone browsing your site in IE is treated to the
70 | best possible user experience that their browser can offer.
71 |
72 | This line breaks validation. To avoid this edge case issue it is recommended
73 | that you **remove this line and use the `.htaccess`** (or other server config)
74 | to send these headers instead. You also might want to read [Validating:
75 | X-UA-Compatible](http://groups.google.com/group/html5boilerplate/browse_thread/thread/6d1b6b152aca8ed2).
76 |
77 | If you are serving your site on a non-standard port, you will need to set this
78 | header on the server-side. This is because the IE preference option 'Display
79 | intranet sites in Compatibility View' is checked by default.
80 |
81 |
82 | ## Mobile viewport
83 |
84 | There are a few different options that you can use with the [`viewport` meta
85 | tag](https://docs.google.com/present/view?id=dkx3qtm_22dxsrgcf4 "Viewport and
86 | Media Queries - The Complete Idiot's Guide"). You can find out more in [the
87 | Apple developer docs](http://j.mp/mobileviewport). HTML5 Boilerplate comes with
88 | a simple setup that strikes a good balance for general use cases.
89 |
90 | ```html
91 |
92 | ```
93 |
94 | ## Favicons and Touch Icon
95 |
96 | The shortcut icons should be put in the root directory of your site. HTML5
97 | Boilerplate comes with a default set of icons (include favicon and one Apple
98 | Touch Icon) that you can use as a baseline to create your own.
99 |
100 | Please refer to the more detailed description in the [Extend section](extend.md)
101 | of these docs.
102 |
103 | ## Modernizr
104 |
105 | HTML5 Boilerplate uses a custom build of Modernizr.
106 |
107 | [Modernizr](http://modernizr.com) is a JavaScript library which adds classes to
108 | the `html` element based on the results of feature test and which ensures that
109 | all browsers can make use of HTML5 elements (as it includes the HTML5 Shiv).
110 | This allows you to target parts of your CSS and JavaScript based on the
111 | features supported by a browser.
112 |
113 | In general, in order to keep page load times to a minimum, it's best to call
114 | any JavaScript at the end of the page because if a script is slow to load
115 | from an external server it may cause the whole page to hang. That said, the
116 | Modernizr script *needs* to run *before* the browser begins rendering the page,
117 | so that browsers lacking support for some of the new HTML5 elements are able to
118 | handle them properly. Therefore the Modernizr script is the only JavaScript
119 | file synchronously loaded at the top of the document.
120 |
121 |
122 | ## The content area
123 |
124 | The central part of the boilerplate template is pretty much empty. This is
125 | intentional, in order to make the boilerplate suitable for both web page and
126 | web app development.
127 |
128 | ### Google Chrome Frame
129 |
130 | The main content area of the boilerplate includes a prompt to install Chrome
131 | Frame (which no longer requires administrative rights) for users of IE 6. If
132 | you intended to support IE 6, then you should remove the snippet of code.
133 |
134 | ### Google CDN for jQuery
135 |
136 | The Google CDN version of the jQuery JavaScript library is referenced towards
137 | the bottom of the page using a protocol-independent path (read more about this
138 | in the [FAQ](faq.md)). A local fallback of jQuery is included for rare instances
139 | when the CDN version might not be available, and to facilitate offline
140 | development.
141 |
142 | Regardless of which JavaScript library you choose to use, it is well worth the
143 | time and effort to look up and reference the Google CDN (Content Delivery
144 | Network) version. Your users may already have this version cached in their
145 | browsers, and Google's CDN is likely to deliver the asset faster than your
146 | server.
147 |
148 | ### Google Analytics Tracking Code
149 |
150 | Finally, an optimized version of the latest Google Analytics tracking code is
151 | included. Google recommends that this script be placed at the top of the page.
152 | Factors to consider: if you place this script at the top of the page, you’ll be
153 | able to count users who don’t fully load the page, and you’ll incur the max
154 | number of simultaneous connections of the browser.
155 |
156 | Further information:
157 |
158 | * [Optimizing the asynchronous Google Analytics
159 | snippet](http://mathiasbynens.be/notes/async-analytics-snippet).
160 | * [Tracking Site Activity - Google
161 | Analytics](http://code.google.com/apis/analytics/docs/tracking/asyncTracking.html).
162 |
--------------------------------------------------------------------------------
/html5bp/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ### HEAD
2 |
3 | ### 4.3.0 (September 10, 2013)
4 |
5 | * Use one apple-touch-icon instead of six ([#1367](https://github.com/h5bp/html5-boilerplate/issues/1367)).
6 | * Move font-related declarations from `body` to `html` ([#1411](https://github.com/h5bp/html5-boilerplate/issues/1411)).
7 | * Update to Apache Server Configs 1.1.0.
8 | * Add `initial-scale=1` to the viewport `meta` ([#1398](https://github.com/h5bp/html5-boilerplate/pull/1398)).
9 | * Vertical centering for audio-, canvas- and video-tags ([#1326](https://github.com/h5bp/html5-boilerplate/issues/1326)).
10 | * Remove Google Chrome Frame related code ([#1379](https://github.com/h5bp/html5-boilerplate/pull/1379), [#1396](https://github.com/h5bp/html5-boilerplate/pull/1396)).
11 | * Update to Google Universal Analytics ([#1347](https://github.com/h5bp/html5-boilerplate/issues/1347)).
12 | * Update to jQuery 1.10.2.
13 | * Update to Normalize.css 1.1.3.
14 |
15 | ### 4.2.0 (April 8, 2013)
16 |
17 | * Remove Google Analytics protocol check ([#1319](https://github.com/h5bp/html5-boilerplate/pull/1319)).
18 | * Update to Normalize.css 1.1.1.
19 | * Update Apache configurations to include the latest changes in the canonical
20 | [`.htaccess`](https://github.com/h5bp/server-configs-apache) file.
21 | * Use a protocol relative URL for the 404 template script.
22 | * Update to jQuery 1.9.1.
23 |
24 | ### 4.1.0 (January 21, 2013)
25 |
26 | * Update to Normalize.css 1.1.0.
27 | * Update to jQuery 1.9.0.
28 |
29 | ### 4.0.3 (January 12, 2013)
30 |
31 | * Use 32x32 favicon.ico ([#1286](https://github.com/h5bp/html5-boilerplate/pull/1286)).
32 | * Remove named function expression in plugins.js ([#1280](https://github.com/h5bp/html5-boilerplate/pull/1280)).
33 | * Adjust CSS image-replacement code ([#1239](https://github.com/h5bp/html5-boilerplate/issues/1239)).
34 | * Update HiDPI example media query ([#1127](https://github.com/h5bp/html5-boilerplate/issues/1127)).
35 |
36 | ### 4.0.2 (December 9, 2012)
37 |
38 | * Update placeholder icons.
39 | * Update to Normalize.css 1.0.2.
40 | * Update to jQuery 1.8.3.
41 |
42 | ### 4.0.1 (October 20, 2012)
43 |
44 | * Further improvements to `console` method stubbing ([#1206](https://github.com/h5bp/html5-boilerplate/issues/1206), [#1229](https://github.com/h5bp/html5-boilerplate/pull/1229)).
45 | * Update to jQuery 1.8.2.
46 | * Update to Modernizr 2.6.2.
47 | * Minor additions to the documentation.
48 |
49 | ### 4.0.0 (August 28, 2012)
50 |
51 | * Improve the Apache compression configuration ([#1012](https://github.com/h5bp/html5-boilerplate/issues/1012), [#1173](https://github.com/h5bp/html5-boilerplate/issues/1173)).
52 | * Add a HiDPI example media query ([#1127](https://github.com/h5bp/html5-boilerplate/issues/1127)).
53 | * Add bundled docs ([#1154](https://github.com/h5bp/html5-boilerplate/issues/1154)).
54 | * Add MIT license ([#1139](https://github.com/h5bp/html5-boilerplate/issues/1139)).
55 | * Update to Normalize.css 1.0.1.
56 | * Separate Normalize.css from the rest of the CSS ([#1160](https://github.com/h5bp/html5-boilerplate/issues/1160)).
57 | * Improve `console.log` protection ([#1107](https://github.com/h5bp/html5-boilerplate/issues/1107)).
58 | * Replace hot pink text selection color with a neutral color.
59 | * Change image replacement technique ([#1149](https://github.com/h5bp/html5-boilerplate/issues/1149)).
60 | * Code format and consistency changes ([#1112](https://github.com/h5bp/html5-boilerplate/issues/1112)).
61 | * Rename CSS file and rename JS files and subdirectories.
62 | * Update to jQuery 1.8 ([#1161](https://github.com/h5bp/html5-boilerplate/issues/1161)).
63 | * Update to Modernizr 2.6.1 ([#1086](https://github.com/h5bp/html5-boilerplate/issues/1086)).
64 | * Remove uncompressed jQuery ([#1153](https://github.com/h5bp/html5-boilerplate/issues/1153)).
65 | * Remove superfluous inline comments ([#1150](https://github.com/h5bp/html5-boilerplate/issues/1150)).
66 |
67 | ### 3.0.2 (February 19, 2012)
68 |
69 | * Update to Modernizr 2.5.3.
70 |
71 | ### 3.0.1 (February 08, 2012).
72 |
73 | * Update to Modernizr 2.5.2 (includes html5shiv 3.3).
74 |
75 | ### 3.0.0 (February 06, 2012)
76 |
77 | * Improvements to `.htaccess`.
78 | * Improve 404 design.
79 | * Simplify JS folder structure.
80 | * Change `html` IE class names changed to target ranges rather than specific versions of IE.
81 | * Update CSS to include latest normalize.css changes and better typographic defaults ([#825](https://github.com/h5bp/html5-boilerplate/issues/825)).
82 | * Update to Modernizr 2.5 (includes yepnope 1.5 and html5shiv 3.2).
83 | * Update to jQuery 1.7.1.
84 | * Revert to async snippet for the Google Analytics script.
85 | * Remove the ant build script ([#826](https://github.com/h5bp/html5-boilerplate/issues/826)).
86 | * Remove Respond.js ([#816](https://github.com/h5bp/html5-boilerplate/issues/816)).
87 | * Remove the `demo/` directory ([#808](https://github.com/h5bp/html5-boilerplate/issues/808)).
88 | * Remove the `test/` directory ([#808](https://github.com/h5bp/html5-boilerplate/issues/808)).
89 | * Remove Google Chrome Frame script for IE6 users; replace with links to Chrome Frame and options for alternative browsers.
90 | * Remove `initial-scale=1` from the viewport `meta` ([#824](https://github.com/h5bp/html5-boilerplate/issues/824)).
91 | * Remove `defer` from all scripts to avoid legacy IE bugs.
92 | * Remove explicit Site Speed tracking for Google Analytics. It's now enabled by default.
93 |
94 | ### 2.0.0 (August 10, 2011)
95 |
96 | * Change starting CSS to be based on normalize.css instead of reset.css ([#500](https://github.com/h5bp/html5-boilerplate/issues/500)).
97 | * Add Respond.js media query polyfill.
98 | * Add Google Chrome Frame script prompt for IE6 users.
99 | * Simplify the `html` conditional comments for modern browsers and add an `oldie` class.
100 | * Update clearfix to use "micro clearfix".
101 | * Add placeholder CSS MQs for mobile-first approach.
102 | * Add `textarea { resize: vertical; }` to only allow vertical resizing.
103 | * Add `img { max-width: 100%; }` to the print styles; prevents images being truncated.
104 | * Add Site Speed tracking for Google Analytics.
105 | * Update to jQuery 1.6.2 (and use minified by default).
106 | * Update to Modernizr 2.0 Complete, Production minified (includes yepnope, html5shiv, and Respond.js).
107 | * Use `Modernizr.load()` to load the Google Analytics script.
108 | * Much faster build process.
109 | * Add build script options for CSSLint, JSLint, JSHint tools.
110 | * Build script now compresses all images in subfolders.
111 | * Build script now versions files by SHA hash.
112 | * Many `.htaccess` improvements including: disable directory browsing, improved support for all versions of Apache, more robust and extensive HTTP compression rules.
113 | * Remove `handheld.css` as it has very poor device support.
114 | * Remove touch-icon `link` elements from the HTML and include improved touch-icon support.
115 | * Remove the cache-busting query paramaters from files references in the HTML.
116 | * Remove IE6 PNGFix.
117 |
118 | ### 1.0.0 (March 21, 2011)
119 |
120 | * Rewrite build script to make it more customizable and flexible.
121 | * Add a humans.txt.
122 | * Numerous `.htaccess` improvements (including inline documentation).
123 | * Move the alternative server configurations to the H5BP server configs repo.
124 | * Use a protocol-relative url to reference jQuery and prevent mixed content warnings.
125 | * Optimize the Google Analytics snippet.
126 | * Use Eric Meyer's recent CSS reset update and the HTML5 Doctor reset.
127 | * More robust `sub`/`sup` CSS styles.
128 | * Add keyboard `.focusable` helper class that extends `.visuallyhidden`.
129 | * Print styles no longer print hash or JavaScript links.
130 | * Add a print reset for IE's proprietary filters.
131 | * Remove IE9-specific conditional class on the `html` element.
132 | * Remove margins from lists within `nav` elements.
133 | * Remove YUI profiling.
134 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | markdown-pdf [](https://travis-ci.org/alanshaw/markdown-pdf) [](https://david-dm.org/alanshaw/markdown-pdf) [](https://coveralls.io/r/alanshaw/markdown-pdf?branch=master)
2 | ===
3 |
4 | Node module that converts Markdown files to PDFs.
5 |
6 | The PDF looks great because it is styled by HTML5 Boilerplate. What? - Yes! Your Markdown is first converted to HTML, then pushed into the HTML5 Boilerplate `index.html`. Phantomjs renders the page and saves it to a PDF. You can even customise the style of the PDF by passing an optional path to your CSS _and_ you can pre-process your markdown file before it is converted to a PDF by passing in a pre-processing function, for templating.
7 |
8 | ## Install
9 |
10 | ```sh
11 | npm install -g markdown-pdf --ignore-scripts
12 | ```
13 |
14 | Note: elevated (sudo) permissions may be needed for `npm install -g`
15 |
16 | ## Usage
17 |
18 | ```
19 | Usage: markdown-pdf [options]
20 |
21 | Options:
22 |
23 | -h, --help output usage information
24 | -V, --version output the version number
25 | Path of the markdown file to convert
26 | -c, --cwd [path] Current working directory
27 | -p, --phantom-path [path] Path to phantom binary
28 | -h, --runnings-path [path] Path to runnings (header, footer)
29 | -s, --css-path [path] Path to custom CSS file
30 | -z, --highlight-css-path [path] Path to custom highlight-CSS file
31 | -m, --remarkable-options [json] Options to pass to Remarkable
32 | -f, --paper-format [format] 'A3', 'A4', 'A5', 'Legal', 'Letter' or 'Tabloid'
33 | -r, --paper-orientation [orientation] 'portrait' or 'landscape'
34 | -b, --paper-border [measurement] Supported dimension units are: 'mm', 'cm', 'in', 'px'
35 | -d, --render-delay [millis] Delay before rendering the PDF
36 | -t, --load-timeout [millis] Timeout before the page is rendered in case `page.onLoadFinished` isn't fired
37 | -o, --out [path] Path of where to save the PDF
38 | ```
39 |
40 | `markdown-pdf` can also be used programmatically:
41 |
42 | ```javascript
43 | var markdownpdf = require("markdown-pdf")
44 | , fs = require("fs")
45 |
46 | fs.createReadStream("/path/to/document.md")
47 | .pipe(markdownpdf())
48 | .pipe(fs.createWriteStream("/path/to/document.pdf"))
49 |
50 | // --- OR ---
51 |
52 | markdownpdf().from("/path/to/document.md").to("/path/to/document.pdf", function () {
53 | console.log("Done")
54 | })
55 | ```
56 |
57 | ### Options
58 |
59 | Pass an options object (`markdownpdf({/* options */})`) to configure the output.
60 |
61 | #### options.cwd
62 | Type: `String`
63 | Default value: `process.cwd()`
64 |
65 | Current working directory.
66 |
67 | #### options.phantomPath
68 | Type: `String`
69 | Default value: Path provided by phantomjs module
70 |
71 | Path to the phantomjs binary.
72 |
73 | #### options.cssPath
74 | Type: `String`
75 | Default value: `[module path]/markdown-pdf/css/pdf.css`
76 |
77 | Path to custom CSS file, relative to the current directory.
78 |
79 | #### options.highlightCssPath
80 | Type: `String`
81 | Default value: `[module path]/markdown-pdf/css/highlight.css`
82 |
83 | Path to custom highlight CSS file (for code highlighting with [highlight.js](https://highlightjs.org)), relative to the current directory.
84 |
85 | #### options.paperFormat
86 | Type: `String`
87 | Default value: `A4`
88 |
89 | 'A3', 'A4', 'A5', 'Legal', 'Letter' or 'Tabloid'.
90 |
91 | #### options.paperOrientation
92 | Type: `String`
93 | Default value: `portrait`
94 |
95 | 'portrait' or 'landscape'.
96 |
97 | #### options.paperBorder
98 | Type: `String`
99 | Default value: `2cm`
100 |
101 | Supported dimension units are: 'mm', 'cm', 'in', 'px'
102 |
103 | #### options.runningsPath
104 | Type: `String`
105 | Default value: `runnings.js`
106 |
107 | Path to CommonJS module which sets the page header and footer (see [runnings.js](runnings.js)).
108 |
109 | #### options.renderDelay
110 | Type: `Number`
111 | Default value: Time until [`page.onLoadFinished`](http://phantomjs.org/api/webpage/handler/on-load-finished.html) event fired
112 |
113 | Delay (in ms) before the PDF is rendered.
114 |
115 | #### options.loadTimeout
116 | Type: `Number`
117 | Default value: `10000`
118 |
119 | If `renderDelay` option isn't set, this is the timeout (in ms) before the page is rendered in case the `page.onLoadFinished` event doesn't fire.
120 |
121 | #### options.preProcessMd
122 | Type: `Function`
123 | Default value: `function () { return through() }`
124 |
125 | A function that returns a [through2 stream](https://npmjs.org/package/through2) that transforms the markdown before it is converted to HTML.
126 |
127 | #### options.preProcessHtml
128 | Type: `Function`
129 | Default value: `function () { return through() }`
130 |
131 | A function that returns a [through2 stream](https://npmjs.org/package/through2) that transforms the HTML before it is converted to PDF.
132 |
133 | #### options.remarkable
134 | Type: `object`
135 | Default value: `{ breaks: true }`
136 |
137 | A config object that is passed to [remarkable](https://www.npmjs.com/package/remarkable#options), the underlying markdown parser.
138 |
139 | ##### options.remarkable.preset
140 | Type: `String`
141 | Default value: `default`
142 |
143 | Use remarkable [presets](https://www.npmjs.com/package/remarkable#presets) as a convenience to quickly enable/disable active syntax rules and options for common use cases.
144 |
145 | Supported values are `default`, `commonmark` and `full`
146 |
147 | ##### options.remarkable.plugins
148 | Type: `Array` of remarkable-plugin `Function`s
149 | Default value: `[]`
150 |
151 | An array of Remarkable plugin functions, that extend the markdown parser functionality.
152 |
153 | ##### options.remarkable.syntax
154 | Type: `Array` of optional remarkable syntax `Strings`s
155 | Default value: `[]`
156 |
157 | An array of [optional Remarkable syntax extensions](https://github.com/jonschlinkert/remarkable#syntax-extensions), disabled by default, that extend the markdown parser functionality.
158 |
159 | ## API
160 |
161 | ### from.path(path, opts) / from(path, opts)
162 |
163 | Create a readable stream from `path` and pipe to markdown-pdf. `path` can be a single path or array of paths.
164 |
165 | ### from.string(string)
166 |
167 | Create a readable stream from `string` and pipe to markdown-pdf. `string` can be a single string or array of strings.
168 |
169 | ### concat.from.paths(paths, opts)
170 |
171 | Create and concatenate readable streams from `paths` and pipe to markdown-pdf.
172 |
173 | ### concat.from.strings(strings, opts)
174 |
175 | Create and concatenate readable streams from `strings` and pipe to markdown-pdf.
176 |
177 | ### to.path(path, cb) / to(path, cb)
178 |
179 | Create a writeable stream to `path` and pipe output from markdown-pdf to it. `path` can be a single path, or array of output paths if you specified an array of inputs. The callback function `cb` will be invoked when data has finished being written.
180 |
181 | ### to.buffer(opts, cb)
182 |
183 | Create a [concat-stream](https://npmjs.org/package/concat-stream) and pipe output from markdown-pdf to it. The callback function `cb` will be invoked when the buffer has been created.
184 |
185 | ### to.string(opts, cb)
186 |
187 | Create a [concat-stream](https://npmjs.org/package/concat-stream) and pipe output from markdown-pdf to it. The callback function `cb` will be invoked when the string has been created.
188 |
189 | ## More examples
190 |
191 | ### From string to path
192 |
193 | ```javascript
194 | var markdownpdf = require("markdown-pdf")
195 |
196 | var md = "foo===\n* bar\n* baz\n\nLorem ipsum dolor sit"
197 | , outputPath = "/path/to/doc.pdf"
198 |
199 | markdownpdf().from.string(md).to(outputPath, function () {
200 | console.log("Created", outputPath)
201 | })
202 | ```
203 |
204 | ### From multiple paths to multiple paths
205 |
206 | ```javascript
207 | var markdownpdf = require("markdown-pdf")
208 |
209 | var mdDocs = ["home.md", "about.md", "contact.md"]
210 | , pdfDocs = mdDocs.map(function (d) { return "out/" + d.replace(".md", ".pdf") })
211 |
212 | markdownpdf().from(mdDocs).to(pdfDocs, function () {
213 | pdfDocs.forEach(function (d) { console.log("Created", d) })
214 | })
215 | ```
216 |
217 | ### Concat from multiple paths to single path
218 |
219 | ```javascript
220 | var markdownpdf = require("markdown-pdf")
221 |
222 | var mdDocs = ["chapter1.md", "chapter2.md", "chapter3.md"]
223 | , bookPath = "/path/to/book.pdf"
224 |
225 | markdownpdf().concat.from(mdDocs).to(bookPath, function () {
226 | console.log("Created", bookPath)
227 | })
228 | ```
229 |
230 | ### Transform markdown before conversion
231 |
232 | ```javascript
233 | var markdownpdf = require("markdown-pdf")
234 | , split = require("split")
235 | , through = require("through")
236 | , duplexer = require("duplexer")
237 |
238 | function preProcessMd () {
239 | // Split the input stream by lines
240 | var splitter = split()
241 |
242 | // Replace occurences of "foo" with "bar"
243 | var replacer = through(function (data) {
244 | this.queue(data.replace(/foo/g, "bar") + "\n")
245 | })
246 |
247 | splitter.pipe(replacer)
248 | return duplexer(splitter, replacer)
249 | }
250 |
251 | markdownpdf({preProcessMd: preProcessMd})
252 | .from("/path/to/document.md")
253 | .to("/path/to/document.pdf", function () { console.log("Done") })
254 | ```
255 |
256 | ### Remarkable options and plugins
257 |
258 | Example using [remarkable-classy](https://www.npmjs.com/package/remarkable-classy) plugin:
259 |
260 | ```javascript
261 | var markdownpdf = require("markdown-pdf")
262 |
263 | var options = {
264 | remarkable: {
265 | html: true,
266 | breaks: true,
267 | plugins: [ require('remarkable-classy') ],
268 | syntax: [ 'footnote', 'sup', 'sub' ]
269 | }
270 | }
271 |
272 | markdownpdf(options)
273 | .from("/path/to/document.md")
274 | .to("/path/to/document.pdf", function () { console.log("Done") })
275 | ```
276 |
277 | ## Contribute
278 |
279 | Feel free to dive in! [Open an issue](https://github.com/alanshaw/markdown-pdf/issues/new) or submit PRs.
280 |
281 | ## License
282 |
283 | [MIT](LICENCE) © Alan Shaw
284 |
--------------------------------------------------------------------------------
/html5bp/css/normalize.css:
--------------------------------------------------------------------------------
1 | /*! normalize.css v1.1.3 | MIT License | git.io/normalize */
2 |
3 | /* ==========================================================================
4 | HTML5 display definitions
5 | ========================================================================== */
6 |
7 | /**
8 | * Correct `block` display not defined in IE 6/7/8/9 and Firefox 3.
9 | */
10 |
11 | article,
12 | aside,
13 | details,
14 | figcaption,
15 | figure,
16 | footer,
17 | header,
18 | hgroup,
19 | main,
20 | nav,
21 | section,
22 | summary {
23 | display: block;
24 | }
25 |
26 | /**
27 | * Correct `inline-block` display not defined in IE 6/7/8/9 and Firefox 3.
28 | */
29 |
30 | audio,
31 | canvas,
32 | video {
33 | display: inline-block;
34 | *display: inline;
35 | *zoom: 1;
36 | }
37 |
38 | /**
39 | * Prevent modern browsers from displaying `audio` without controls.
40 | * Remove excess height in iOS 5 devices.
41 | */
42 |
43 | audio:not([controls]) {
44 | display: none;
45 | height: 0;
46 | }
47 |
48 | /**
49 | * Address styling not present in IE 7/8/9, Firefox 3, and Safari 4.
50 | * Known issue: no IE 6 support.
51 | */
52 |
53 | [hidden] {
54 | display: none;
55 | }
56 |
57 | /* ==========================================================================
58 | Base
59 | ========================================================================== */
60 |
61 | /**
62 | * 1. Correct text resizing oddly in IE 6/7 when body `font-size` is set using
63 | * `em` units.
64 | * 2. Prevent iOS text size adjust after orientation change, without disabling
65 | * user zoom.
66 | */
67 |
68 | html {
69 | font-size: 100%; /* 1 */
70 | -ms-text-size-adjust: 100%; /* 2 */
71 | -webkit-text-size-adjust: 100%; /* 2 */
72 | }
73 |
74 | /**
75 | * Address `font-family` inconsistency between `textarea` and other form
76 | * elements.
77 | */
78 |
79 | html,
80 | button,
81 | input,
82 | select,
83 | textarea {
84 | font-family: sans-serif;
85 | }
86 |
87 | /**
88 | * Address margins handled incorrectly in IE 6/7.
89 | */
90 |
91 | body {
92 | margin: 0;
93 | }
94 |
95 | /* ==========================================================================
96 | Links
97 | ========================================================================== */
98 |
99 | /**
100 | * Address `outline` inconsistency between Chrome and other browsers.
101 | */
102 |
103 | a:focus {
104 | outline: thin dotted;
105 | }
106 |
107 | /**
108 | * Improve readability when focused and also mouse hovered in all browsers.
109 | */
110 |
111 | a:active,
112 | a:hover {
113 | outline: 0;
114 | }
115 |
116 | /* ==========================================================================
117 | Typography
118 | ========================================================================== */
119 |
120 | /**
121 | * Address font sizes and margins set differently in IE 6/7.
122 | * Address font sizes within `section` and `article` in Firefox 4+, Safari 5,
123 | * and Chrome.
124 | */
125 |
126 | h1 {
127 | font-size: 2em;
128 | margin: 0.67em 0;
129 | }
130 |
131 | h2 {
132 | font-size: 1.5em;
133 | margin: 0.83em 0;
134 | }
135 |
136 | h3 {
137 | font-size: 1.17em;
138 | margin: 1em 0;
139 | }
140 |
141 | h4 {
142 | font-size: 1em;
143 | margin: 1.33em 0;
144 | }
145 |
146 | h5 {
147 | font-size: 0.83em;
148 | margin: 1.67em 0;
149 | }
150 |
151 | h6 {
152 | font-size: 0.67em;
153 | margin: 2.33em 0;
154 | }
155 |
156 | /**
157 | * Address styling not present in IE 7/8/9, Safari 5, and Chrome.
158 | */
159 |
160 | abbr[title] {
161 | border-bottom: 1px dotted;
162 | }
163 |
164 | /**
165 | * Address style set to `bolder` in Firefox 3+, Safari 4/5, and Chrome.
166 | */
167 |
168 | b,
169 | strong {
170 | font-weight: bold;
171 | }
172 |
173 | blockquote {
174 | margin: 1em 40px;
175 | }
176 |
177 | /**
178 | * Address styling not present in Safari 5 and Chrome.
179 | */
180 |
181 | dfn {
182 | font-style: italic;
183 | }
184 |
185 | /**
186 | * Address differences between Firefox and other browsers.
187 | * Known issue: no IE 6/7 normalization.
188 | */
189 |
190 | hr {
191 | -moz-box-sizing: content-box;
192 | box-sizing: content-box;
193 | height: 0;
194 | }
195 |
196 | /**
197 | * Address styling not present in IE 6/7/8/9.
198 | */
199 |
200 | mark {
201 | background: #ff0;
202 | color: #000;
203 | }
204 |
205 | /**
206 | * Address margins set differently in IE 6/7.
207 | */
208 |
209 | p,
210 | pre {
211 | margin: 1em 0;
212 | }
213 |
214 | /**
215 | * Correct font family set oddly in IE 6, Safari 4/5, and Chrome.
216 | */
217 |
218 | code,
219 | kbd,
220 | pre,
221 | samp {
222 | font-family: monospace, serif;
223 | _font-family: 'courier new', monospace;
224 | font-size: 1em;
225 | }
226 |
227 | /**
228 | * Improve readability of pre-formatted text in all browsers.
229 | */
230 |
231 | pre {
232 | white-space: pre;
233 | white-space: pre-wrap;
234 | word-wrap: break-word;
235 | }
236 |
237 | /**
238 | * Address CSS quotes not supported in IE 6/7.
239 | */
240 |
241 | q {
242 | quotes: none;
243 | }
244 |
245 | /**
246 | * Address `quotes` property not supported in Safari 4.
247 | */
248 |
249 | q:before,
250 | q:after {
251 | content: '';
252 | content: none;
253 | }
254 |
255 | /**
256 | * Address inconsistent and variable font size in all browsers.
257 | */
258 |
259 | small {
260 | font-size: 80%;
261 | }
262 |
263 | /**
264 | * Prevent `sub` and `sup` affecting `line-height` in all browsers.
265 | */
266 |
267 | sub,
268 | sup {
269 | font-size: 75%;
270 | line-height: 0;
271 | position: relative;
272 | vertical-align: baseline;
273 | }
274 |
275 | sup {
276 | top: -0.5em;
277 | }
278 |
279 | sub {
280 | bottom: -0.25em;
281 | }
282 |
283 | /* ==========================================================================
284 | Lists
285 | ========================================================================== */
286 |
287 | /**
288 | * Address margins set differently in IE 6/7.
289 | */
290 |
291 | dl,
292 | menu,
293 | ol,
294 | ul {
295 | margin: 1em 0;
296 | }
297 |
298 | dd {
299 | margin: 0 0 0 40px;
300 | }
301 |
302 | /**
303 | * Address paddings set differently in IE 6/7.
304 | */
305 |
306 | menu,
307 | ol,
308 | ul {
309 | padding: 0 0 0 40px;
310 | }
311 |
312 | /**
313 | * Correct list images handled incorrectly in IE 7.
314 | */
315 |
316 | nav ul,
317 | nav ol {
318 | list-style: none;
319 | list-style-image: none;
320 | }
321 |
322 | /* ==========================================================================
323 | Embedded content
324 | ========================================================================== */
325 |
326 | /**
327 | * 1. Remove border when inside `a` element in IE 6/7/8/9 and Firefox 3.
328 | * 2. Improve image quality when scaled in IE 7.
329 | */
330 |
331 | img {
332 | border: 0; /* 1 */
333 | -ms-interpolation-mode: bicubic; /* 2 */
334 | }
335 |
336 | /**
337 | * Correct overflow displayed oddly in IE 9.
338 | */
339 |
340 | svg:not(:root) {
341 | overflow: hidden;
342 | }
343 |
344 | /* ==========================================================================
345 | Figures
346 | ========================================================================== */
347 |
348 | /**
349 | * Address margin not present in IE 6/7/8/9, Safari 5, and Opera 11.
350 | */
351 |
352 | figure {
353 | margin: 0;
354 | }
355 |
356 | /* ==========================================================================
357 | Forms
358 | ========================================================================== */
359 |
360 | /**
361 | * Correct margin displayed oddly in IE 6/7.
362 | */
363 |
364 | form {
365 | margin: 0;
366 | }
367 |
368 | /**
369 | * Define consistent border, margin, and padding.
370 | */
371 |
372 | fieldset {
373 | border: 1px solid #c0c0c0;
374 | margin: 0 2px;
375 | padding: 0.35em 0.625em 0.75em;
376 | }
377 |
378 | /**
379 | * 1. Correct color not being inherited in IE 6/7/8/9.
380 | * 2. Correct text not wrapping in Firefox 3.
381 | * 3. Correct alignment displayed oddly in IE 6/7.
382 | */
383 |
384 | legend {
385 | border: 0; /* 1 */
386 | padding: 0;
387 | white-space: normal; /* 2 */
388 | *margin-left: -7px; /* 3 */
389 | }
390 |
391 | /**
392 | * 1. Correct font size not being inherited in all browsers.
393 | * 2. Address margins set differently in IE 6/7, Firefox 3+, Safari 5,
394 | * and Chrome.
395 | * 3. Improve appearance and consistency in all browsers.
396 | */
397 |
398 | button,
399 | input,
400 | select,
401 | textarea {
402 | font-size: 100%; /* 1 */
403 | margin: 0; /* 2 */
404 | vertical-align: baseline; /* 3 */
405 | *vertical-align: middle; /* 3 */
406 | }
407 |
408 | /**
409 | * Address Firefox 3+ setting `line-height` on `input` using `!important` in
410 | * the UA stylesheet.
411 | */
412 |
413 | button,
414 | input {
415 | line-height: normal;
416 | }
417 |
418 | /**
419 | * Address inconsistent `text-transform` inheritance for `button` and `select`.
420 | * All other form control elements do not inherit `text-transform` values.
421 | * Correct `button` style inheritance in Chrome, Safari 5+, and IE 6+.
422 | * Correct `select` style inheritance in Firefox 4+ and Opera.
423 | */
424 |
425 | button,
426 | select {
427 | text-transform: none;
428 | }
429 |
430 | /**
431 | * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
432 | * and `video` controls.
433 | * 2. Correct inability to style clickable `input` types in iOS.
434 | * 3. Improve usability and consistency of cursor style between image-type
435 | * `input` and others.
436 | * 4. Remove inner spacing in IE 7 without affecting normal text inputs.
437 | * Known issue: inner spacing remains in IE 6.
438 | */
439 |
440 | button,
441 | html input[type="button"], /* 1 */
442 | input[type="reset"],
443 | input[type="submit"] {
444 | -webkit-appearance: button; /* 2 */
445 | cursor: pointer; /* 3 */
446 | *overflow: visible; /* 4 */
447 | }
448 |
449 | /**
450 | * Re-set default cursor for disabled elements.
451 | */
452 |
453 | button[disabled],
454 | html input[disabled] {
455 | cursor: default;
456 | }
457 |
458 | /**
459 | * 1. Address box sizing set to content-box in IE 8/9.
460 | * 2. Remove excess padding in IE 8/9.
461 | * 3. Remove excess padding in IE 7.
462 | * Known issue: excess padding remains in IE 6.
463 | */
464 |
465 | input[type="checkbox"],
466 | input[type="radio"] {
467 | box-sizing: border-box; /* 1 */
468 | padding: 0; /* 2 */
469 | *height: 13px; /* 3 */
470 | *width: 13px; /* 3 */
471 | }
472 |
473 | /**
474 | * 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome.
475 | * 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome
476 | * (include `-moz` to future-proof).
477 | */
478 |
479 | input[type="search"] {
480 | -webkit-appearance: textfield; /* 1 */
481 | -moz-box-sizing: content-box;
482 | -webkit-box-sizing: content-box; /* 2 */
483 | box-sizing: content-box;
484 | }
485 |
486 | /**
487 | * Remove inner padding and search cancel button in Safari 5 and Chrome
488 | * on OS X.
489 | */
490 |
491 | input[type="search"]::-webkit-search-cancel-button,
492 | input[type="search"]::-webkit-search-decoration {
493 | -webkit-appearance: none;
494 | }
495 |
496 | /**
497 | * Remove inner padding and border in Firefox 3+.
498 | */
499 |
500 | button::-moz-focus-inner,
501 | input::-moz-focus-inner {
502 | border: 0;
503 | padding: 0;
504 | }
505 |
506 | /**
507 | * 1. Remove default vertical scrollbar in IE 6/7/8/9.
508 | * 2. Improve readability and alignment in all browsers.
509 | */
510 |
511 | textarea {
512 | overflow: auto; /* 1 */
513 | vertical-align: top; /* 2 */
514 | }
515 |
516 | /* ==========================================================================
517 | Tables
518 | ========================================================================== */
519 |
520 | /**
521 | * Remove most spacing between table cells.
522 | */
523 |
524 | table {
525 | border-collapse: collapse;
526 | border-spacing: 0;
527 | }
528 |
--------------------------------------------------------------------------------
/html5bp/js/vendor/modernizr-2.6.2.min.js:
--------------------------------------------------------------------------------
1 | /* Modernizr 2.6.2 (Custom Build) | MIT & BSD
2 | * Build: http://modernizr.com/download/#-fontface-backgroundsize-borderimage-borderradius-boxshadow-flexbox-hsla-multiplebgs-opacity-rgba-textshadow-cssanimations-csscolumns-generatedcontent-cssgradients-cssreflections-csstransforms-csstransforms3d-csstransitions-applicationcache-canvas-canvastext-draganddrop-hashchange-history-audio-video-indexeddb-input-inputtypes-localstorage-postmessage-sessionstorage-websockets-websqldatabase-webworkers-geolocation-inlinesvg-smil-svg-svgclippaths-touch-webgl-shiv-mq-cssclasses-addtest-prefixed-teststyles-testprop-testallprops-hasevent-prefixes-domprefixes-load
3 | */
4 | ;window.Modernizr=function(a,b,c){function D(a){j.cssText=a}function E(a,b){return D(n.join(a+";")+(b||""))}function F(a,b){return typeof a===b}function G(a,b){return!!~(""+a).indexOf(b)}function H(a,b){for(var d in a){var e=a[d];if(!G(e,"-")&&j[e]!==c)return b=="pfx"?e:!0}return!1}function I(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:F(f,"function")?f.bind(d||b):f}return!1}function J(a,b,c){var d=a.charAt(0).toUpperCase()+a.slice(1),e=(a+" "+p.join(d+" ")+d).split(" ");return F(b,"string")||F(b,"undefined")?H(e,b):(e=(a+" "+q.join(d+" ")+d).split(" "),I(e,b,c))}function K(){e.input=function(c){for(var d=0,e=c.length;d',a,""].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},z=function(b){var c=a.matchMedia||a.msMatchMedia;if(c)return c(b).matches;var d;return y("@media "+b+" { #"+h+" { position: absolute; } }",function(b){d=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle)["position"]=="absolute"}),d},A=function(){function d(d,e){e=e||b.createElement(a[d]||"div"),d="on"+d;var f=d in e;return f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=F(e[d],"function"),F(e[d],"undefined")||(e[d]=c),e.removeAttribute(d))),e=null,f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),B={}.hasOwnProperty,C;!F(B,"undefined")&&!F(B.call,"undefined")?C=function(a,b){return B.call(a,b)}:C=function(a,b){return b in a&&F(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=w.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(w.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(w.call(arguments)))};return e}),s.flexbox=function(){return J("flexWrap")},s.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},s.canvastext=function(){return!!e.canvas&&!!F(b.createElement("canvas").getContext("2d").fillText,"function")},s.webgl=function(){return!!a.WebGLRenderingContext},s.touch=function(){var c;return"ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch?c=!0:y(["@media (",n.join("touch-enabled),("),h,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(a){c=a.offsetTop===9}),c},s.geolocation=function(){return"geolocation"in navigator},s.postmessage=function(){return!!a.postMessage},s.websqldatabase=function(){return!!a.openDatabase},s.indexedDB=function(){return!!J("indexedDB",a)},s.hashchange=function(){return A("hashchange",a)&&(b.documentMode===c||b.documentMode>7)},s.history=function(){return!!a.history&&!!history.pushState},s.draganddrop=function(){var a=b.createElement("div");return"draggable"in a||"ondragstart"in a&&"ondrop"in a},s.websockets=function(){return"WebSocket"in a||"MozWebSocket"in a},s.rgba=function(){return D("background-color:rgba(150,255,150,.5)"),G(j.backgroundColor,"rgba")},s.hsla=function(){return D("background-color:hsla(120,40%,100%,.5)"),G(j.backgroundColor,"rgba")||G(j.backgroundColor,"hsla")},s.multiplebgs=function(){return D("background:url(https://),url(https://),red url(https://)"),/(url\s*\(.*?){3}/.test(j.background)},s.backgroundsize=function(){return J("backgroundSize")},s.borderimage=function(){return J("borderImage")},s.borderradius=function(){return J("borderRadius")},s.boxshadow=function(){return J("boxShadow")},s.textshadow=function(){return b.createElement("div").style.textShadow===""},s.opacity=function(){return E("opacity:.55"),/^0.55$/.test(j.opacity)},s.cssanimations=function(){return J("animationName")},s.csscolumns=function(){return J("columnCount")},s.cssgradients=function(){var a="background-image:",b="gradient(linear,left top,right bottom,from(#9f9),to(white));",c="linear-gradient(left top,#9f9, white);";return D((a+"-webkit- ".split(" ").join(b+a)+n.join(c+a)).slice(0,-a.length)),G(j.backgroundImage,"gradient")},s.cssreflections=function(){return J("boxReflect")},s.csstransforms=function(){return!!J("transform")},s.csstransforms3d=function(){var a=!!J("perspective");return a&&"webkitPerspective"in g.style&&y("@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}",function(b,c){a=b.offsetLeft===9&&b.offsetHeight===3}),a},s.csstransitions=function(){return J("transition")},s.fontface=function(){var a;return y('@font-face {font-family:"font";src:url("https://")}',function(c,d){var e=b.getElementById("smodernizr"),f=e.sheet||e.styleSheet,g=f?f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"":"";a=/src/i.test(g)&&g.indexOf(d.split(" ")[0])===0}),a},s.generatedcontent=function(){var a;return y(["#",h,"{font:0/0 a}#",h,':after{content:"',l,'";visibility:hidden;font:3px/1 a}'].join(""),function(b){a=b.offsetHeight>=3}),a},s.video=function(){var a=b.createElement("video"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('video/ogg; codecs="theora"').replace(/^no$/,""),c.h264=a.canPlayType('video/mp4; codecs="avc1.42E01E"').replace(/^no$/,""),c.webm=a.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,"")}catch(d){}return c},s.audio=function(){var a=b.createElement("audio"),c=!1;try{if(c=!!a.canPlayType)c=new Boolean(c),c.ogg=a.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),c.mp3=a.canPlayType("audio/mpeg;").replace(/^no$/,""),c.wav=a.canPlayType('audio/wav; codecs="1"').replace(/^no$/,""),c.m4a=(a.canPlayType("audio/x-m4a;")||a.canPlayType("audio/aac;")).replace(/^no$/,"")}catch(d){}return c},s.localstorage=function(){try{return localStorage.setItem(h,h),localStorage.removeItem(h),!0}catch(a){return!1}},s.sessionstorage=function(){try{return sessionStorage.setItem(h,h),sessionStorage.removeItem(h),!0}catch(a){return!1}},s.webworkers=function(){return!!a.Worker},s.applicationcache=function(){return!!a.applicationCache},s.svg=function(){return!!b.createElementNS&&!!b.createElementNS(r.svg,"svg").createSVGRect},s.inlinesvg=function(){var a=b.createElement("div");return a.innerHTML=" ",(a.firstChild&&a.firstChild.namespaceURI)==r.svg},s.smil=function(){return!!b.createElementNS&&/SVGAnimate/.test(m.call(b.createElementNS(r.svg,"animate")))},s.svgclippaths=function(){return!!b.createElementNS&&/SVGClipPath/.test(m.call(b.createElementNS(r.svg,"clipPath")))};for(var L in s)C(s,L)&&(x=L.toLowerCase(),e[x]=s[L](),v.push((e[x]?"":"no-")+x));return e.input||K(),e.addTest=function(a,b){if(typeof a=="object")for(var d in a)C(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" "+(b?"":"no-")+a),e[a]=b}return e},D(""),i=k=null,function(a,b){function k(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function l(){var a=r.elements;return typeof a=="string"?a.split(" "):a}function m(a){var b=i[a[g]];return b||(b={},h++,a[g]=h,i[h]=b),b}function n(a,c,f){c||(c=b);if(j)return c.createElement(a);f||(f=m(c));var g;return f.cache[a]?g=f.cache[a].cloneNode():e.test(a)?g=(f.cache[a]=f.createElem(a)).cloneNode():g=f.createElem(a),g.canHaveChildren&&!d.test(a)?f.frag.appendChild(g):g}function o(a,c){a||(a=b);if(j)return a.createDocumentFragment();c=c||m(a);var d=c.frag.cloneNode(),e=0,f=l(),g=f.length;for(;e",f="hidden"in a,j=a.childNodes.length==1||function(){b.createElement("a");var a=b.createDocumentFragment();return typeof a.cloneNode=="undefined"||typeof a.createDocumentFragment=="undefined"||typeof a.createElement=="undefined"}()}catch(c){f=!0,j=!0}})();var r={elements:c.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:c.shivCSS!==!1,supportsUnknownElements:j,shivMethods:c.shivMethods!==!1,type:"default",shivDocument:q,createElement:n,createDocumentFragment:o};a.html5=r,q(b)}(this,b),e._version=d,e._prefixes=n,e._domPrefixes=q,e._cssomPrefixes=p,e.mq=z,e.hasEvent=A,e.testProp=function(a){return H([a])},e.testAllProps=J,e.testStyles=y,e.prefixed=function(a,b,c){return b?J(a,b,c):J(a,"pfx")},g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+v.join(" "):""),e}(this,this.document),function(a,b,c){function d(a){return"[object Function]"==o.call(a)}function e(a){return"string"==typeof a}function f(){}function g(a){return!a||"loaded"==a||"complete"==a||"uninitialized"==a}function h(){var a=p.shift();q=1,a?a.t?m(function(){("c"==a.t?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){"img"!=a&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l=b.createElement(a),o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};1===y[c]&&(r=1,y[c]=[]),"object"==a?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),"img"!=a&&(r||2===y[c]?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i("c"==b?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),1==p.length&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&"[object Opera]"==o.call(a.opera),l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return"[object Array]"==o.call(a)},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;f
37 | ```
38 |
39 | Even with X-DNS-Prefetch-Control meta tag (or http header) browsers will still
40 | prefetch any explicit dns-prefetch links.
41 |
42 | **_WARNING:_** THIS MAY MAKE YOUR SITE SLOWER IF YOU RELY ON RESOURCES FROM
43 | FOREIGN DOMAINS.
44 |
45 | ### Explicit prefetches
46 |
47 | Typically the browser only scans the HTML for foreign domains. If you have
48 | resources that are outside of your HTML (a javascript request to a remote
49 | server or a CDN that hosts content that may not be present on every page of
50 | your site, for example) then you can queue up a domain name to be prefetched.
51 |
52 | ```html
53 |
54 |
55 | ```
56 |
57 | You can use as many of these as you need, but it's best if they are all
58 | immediately after the [Meta
59 | Charset](https://developer.mozilla.org/en/HTML/Element/meta#attr-charset)
60 | element (which should go right at the top of the `head`), so the browser can
61 | act on them ASAP.
62 |
63 | #### Common Prefetch Links
64 |
65 | Amazon S3:
66 |
67 | ```html
68 |
69 | ```
70 |
71 | Google APIs:
72 |
73 | ```html
74 |
75 | ```
76 |
77 | Microsoft Ajax Content Delivery Network:
78 |
79 | ```html
80 |
81 |
82 | ```
83 |
84 | ### Browser support for DNS prefetching
85 |
86 | Chrome, Firefox 3.5+, Safari 5+, Opera (Unknown), IE 9 (called "Pre-resolution"
87 | on blogs.msdn.com)
88 |
89 | ### Further reading about DNS prefetching
90 |
91 | * https://developer.mozilla.org/En/Controlling_DNS_prefetching
92 | * http://dev.chromium.org/developers/design-documents/dns-prefetching
93 | * http://www.apple.com/safari/whats-new.html
94 | * http://blogs.msdn.com/b/ie/archive/2011/03/17/internet-explorer-9-network-performance-improvements.aspx
95 | * http://dayofjs.com/videos/22158462/web-browsers_alex-russel
96 |
97 |
98 | ## Search
99 |
100 | ### Direct search spiders to your sitemap
101 |
102 | [Learn how to make a sitemap](http://www.sitemaps.org/protocol.php)
103 |
104 | ```html
105 |
106 | ```
107 |
108 | ### Hide pages from search engines
109 |
110 | According to Heather Champ, former community manager at Flickr, you should not
111 | allow search engines to index your "Contact Us" or "Complaints" page if you
112 | value your sanity. This is an HTML-centric way of achieving that.
113 |
114 | ```html
115 |
116 | ```
117 |
118 | **_WARNING:_** DO NOT INCLUDE ON PAGES THAT SHOULD APPEAR IN SEARCH ENGINES.
119 |
120 | ### Firefox and IE Search Plugins
121 |
122 | Sites with in-site search functionality should be strongly considered for a
123 | browser search plugin. A "search plugin" is an XML file which defines how your
124 | plugin behaves in the browser. [How to make a browser search
125 | plugin](http://www.google.com/search?ie=UTF-8&q=how+to+make+browser+search+plugin).
126 |
127 | ```html
128 |
129 | ```
130 |
131 |
132 | ## Internet Explorer
133 |
134 | ### Prompt users to switch to "Desktop Mode" in IE10 Metro
135 |
136 | IE10 does not support plugins, such as Flash, in Metro mode. If your site
137 | requires plugins, you can let users know that via the X-UA-Compatible meta
138 | element, which will prompt them to switch to Desktop Mode.
139 |
140 | ```html
141 |
142 | ```
143 |
144 | Here's what it looks like alongside H5BP's default X-UA-Compatible values:
145 |
146 | ```html
147 |
148 | ```
149 |
150 | You can find more information in [Microsoft's IEBlog post about prompting for
151 | plugin use in IE10 Metro
152 | Mode](http://blogs.msdn.com/b/ie/archive/2012/01/31/web-sites-and-a-plug-in-free-web.aspx).
153 |
154 | ### IE Pinned Sites (IE9+)
155 |
156 | Enabling your application for pinning will allow IE9 users to add it to their
157 | Windows Taskbar and Start Menu. This comes with a range of new tools that you
158 | can easily configure with the elements below. See more [documentation on IE9
159 | Pinned Sites](http://msdn.microsoft.com/en-us/library/gg131029.aspx).
160 |
161 | ### Name the Pinned Site for Windows
162 |
163 | Without this rule, Windows will use the page title as the name for your
164 | application.
165 |
166 | ```html
167 |
168 | ```
169 |
170 | ### Give your Pinned Site a tooltip
171 |
172 | You know — a tooltip. A little textbox that appears when the user holds their
173 | mouse over your Pinned Site's icon.
174 |
175 | ```html
176 |
177 | ```
178 |
179 | ### Set a default page for your Pinned Site
180 |
181 | If the site should go to a specific URL when it is pinned (such as the
182 | homepage), enter it here. One idea is to send it to a special URL so you can
183 | track the number of pinned users, like so:
184 | `http://www.example.com/index.html?pinned=true`
185 |
186 | ```html
187 |
188 | ```
189 |
190 | ### Recolor IE's controls manually for a Pinned Site
191 |
192 | IE9+ will automatically use the overall color of your Pinned Site's favicon to
193 | shade its browser buttons. UNLESS you give it another color here. Only use
194 | named colors (`red`) or hex colors (`#ff0000`).
195 |
196 | ```html
197 |
198 | ```
199 |
200 | ### Manually set the window size of a Pinned Site
201 |
202 | If the site should open at a certain window size once pinned, you can specify
203 | the dimensions here. It only supports static pixel dimensions. 800x600
204 | minimum.
205 |
206 | ```html
207 |
208 | ```
209 |
210 | ### Jump List "Tasks" for Pinned Sites
211 |
212 | Add Jump List Tasks that will appear when the Pinned Site's icon gets a
213 | right-click. Each Task goes to the specified URL, and gets its own mini icon
214 | (essentially a favicon, a 16x16 .ICO). You can add as many of these as you
215 | need.
216 |
217 | ```html
218 |
219 |
220 | ```
221 |
222 | ### (Windows 8) High quality visuals for Pinned Sites
223 |
224 | Windows 8 adds the ability for you to provide a PNG tile image and specify the
225 | tile's background color. [Full details on the IE
226 | blog](http://blogs.msdn.com/b/ie/archive/2012/06/08/high-quality-visuals-for-pinned-sites-in-windows-8.aspx).
227 |
228 | * Create a 144x144 image of your site icon, filling all of the canvas, and
229 | using a transparent background.
230 | * Save this image as a 32-bit PNG and optimize it without reducing
231 | colour-depth. It can be named whatever you want (e.g. `metro-tile.png`).
232 | * To reference the tile and its color, add the HTML `meta` elements described
233 | in the IE Blog post.
234 |
235 | ### (Windows 8) Badges for Pinned Sites
236 |
237 | IE10 will poll an XML document for badge information to display on your app's
238 | tile in the Start screen. The user will be able to receive these badge updates
239 | even when your app isn't actively running. The badge's value can be a number,
240 | or one of a predefined list of glyphs.
241 |
242 | * [Tutorial on IEBlog with link to badge XML schema](http://blogs.msdn.com/b/ie/archive/2012/04/03/pinned-sites-in-windows-8.aspx)
243 | * [Available badge values](http://msdn.microsoft.com/en-us/library/ie/br212849.aspx)
244 |
245 | ```html
246 |
247 | ```
248 |
249 | ### Disable link highlighting upon tap in IE10
250 |
251 | Similar to [-webkit-tap-highlight-color](http://davidwalsh.name/mobile-highlight-color)
252 | in iOS Safari. Unlike that CSS property, this is an HTML meta element, and it's
253 | value is boolean rather than a color. It's all or nothing.
254 |
255 | ```html
256 |
257 | ```
258 |
259 | You can read about this useful element and more techniques in
260 | [Microsoft's documentation on adapting WebKit-oriented apps for IE10](http://blogs.windows.com/windows_phone/b/wpdev/archive/2012/11/15/adapting-your-webkit-optimized-site-for-internet-explorer-10.aspx).
261 |
262 | ### Suppress IE6 image toolbar
263 |
264 | Kill IE6's pop-up-on-mouseover toolbar for images that can interfere with
265 | certain designs and be pretty distracting in general.
266 |
267 | ```html
268 |
269 | ```
270 |
271 |
272 | ## Social Networks
273 |
274 | ### Facebook Open Graph data
275 |
276 | You can control the information that Facebook and others display when users
277 | share your site. Below are just the most basic data points you might need. For
278 | specific content types (including "website"), see [Facebook's built-in Open
279 | Graph content
280 | templates](https://developers.facebook.com/docs/opengraph/objects/builtin/).
281 | Take full advantage of Facebook's support for complex data and activity by
282 | following the [Open Graph
283 | tutorial](https://developers.facebook.com/docs/opengraph/tutorial/).
284 |
285 | ```html
286 |
287 |
288 |
289 | ```
290 |
291 | ### Twitter Cards
292 |
293 | Twitter provides a snippet specification that serves a similar purpose to Open
294 | Graph. In fact, Twitter will use Open Graph when Cards is not available. Note
295 | that, as of this writing, Twitter requires that app developers activate Cards
296 | on a per-domain basis. You can read more about the various snippet formats
297 | and application process in the [official Twitter Cards
298 | documentation](https://dev.twitter.com/docs/cards).
299 |
300 | ```html
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 | ```
309 |
310 |
311 | ## URLs
312 |
313 | ### Canonical URL
314 |
315 | Signal to search engines and others "Use this URL for this page!" Useful when
316 | parameters after a `#` or `?` is used to control the display state of a page.
317 | `http://www.example.com/cart.html?shopping-cart-open=true` can be indexed as
318 | the cleaner, more accurate `http://www.example.com/cart.html`.
319 |
320 | ```html
321 |
322 | ```
323 |
324 | ### Official shortlink
325 |
326 | Signal to the world "This is the shortened URL to use this page!" Poorly
327 | supported at this time. Learn more by reading the [article about shortlinks on
328 | the Microformats wiki](http://microformats.org/wiki/rel-shortlink).
329 |
330 | ```html
331 |
332 | ```
333 |
334 |
335 | ## News Feeds
336 |
337 | ### RSS
338 |
339 | Have an RSS feed? Link to it here. Want to [learn how to write an RSS feed from
340 | scratch](http://www.rssboard.org/rss-specification)?
341 |
342 | ```html
343 |
344 | ```
345 |
346 | ### Atom
347 |
348 | Atom is similar to RSS, and you might prefer to use it instead of or in
349 | addition to it. [See what Atom's all
350 | about](http://www.atomenabled.org/developers/syndication/).
351 |
352 | ```html
353 |
354 | ```
355 |
356 | ### Pingbacks
357 |
358 | Your server may be notified when another site links to yours. The href
359 | attribute should contain the location of your pingback service.
360 |
361 | ```html
362 |
363 | ```
364 |
365 | * High-level explanation: http://codex.wordpress.org/Introduction_to_Blogging#Pingbacks
366 | * Step-by-step example case: http://www.hixie.ch/specs/pingback/pingback-1.0#TOC5
367 | * PHP pingback service: http://blog.perplexedlabs.com/2009/07/15/xmlrpc-pingbacks-using-php/
368 |
369 |
370 | ## App Stores
371 |
372 | ### Install a Chrome Web Store app
373 |
374 | Users can install a Chrome app directly from your website, as long as the app
375 | and site have been associated via Google's Webmaster Tools. Read more on
376 | [Chrome Web Store's Inline Installation
377 | docs](https://developers.google.com/chrome/web-store/docs/inline_installation).
378 |
379 | ```html
380 |
381 | ```
382 |
383 | ### Smart App Banners in iOS 6 Safari
384 |
385 | Stop bothering everyone with gross modals advertising your entry in the App Store.
386 | This bit of code will unintrusively allow the user the option to download your iOS
387 | app, or open it with some data about the user's current state on the website.
388 |
389 | ```html
390 |
391 | ```
392 |
393 | ## Google Analytics augments
394 |
395 | ### More tracking settings
396 |
397 | The [optimized Google Analytics
398 | snippet](http://mathiasbynens.be/notes/async-analytics-snippet) included with
399 | HTML5 Boilerplate includes something like this:
400 |
401 | ```js
402 | var _gaq = [['_setAccount', 'UA-XXXXX-X'], ['_trackPageview']];
403 | ```
404 |
405 | In case you need more settings, just extend the array literal instead of
406 | [`.push()`ing to the
407 | array](http://mathiasbynens.be/notes/async-analytics-snippet#dont-push-it)
408 | afterwards:
409 |
410 | ```js
411 | var _gaq = [['_setAccount', 'UA-XXXXX-X'], ['_trackPageview'], ['_setAllowAnchor', true]];
412 | ```
413 |
414 | ### Anonymize IP addresses
415 |
416 | In some countries, no personal data may be transferred outside jurisdictions
417 | that do not have similarly strict laws (i.e. from Germany to outside the EU).
418 | Thus a webmaster using the Google Analytics script may have to ensure that no
419 | personal (trackable) data is transferred to the US. You can do that with [the
420 | `_gat.anonymizeIp`
421 | option](http://code.google.com/apis/analytics/docs/gaJS/gaJSApi_gat.html#_gat._anonymizeIp).
422 | In use it looks like this:
423 |
424 | ```js
425 | var _gaq = [['_setAccount', 'UA-XXXXX-X'], ['_gat._anonymizeIp'], ['_trackPageview']];
426 | ```
427 |
428 | ### Track jQuery AJAX requests in Google Analytics
429 |
430 | An article by @JangoSteve explains how to [track jQuery AJAX requests in Google
431 | Analytics](http://www.alfajango.com/blog/track-jquery-ajax-requests-in-google-analytics/).
432 |
433 | Add this to `plugins.js`:
434 |
435 | ```js
436 | /*
437 | * Log all jQuery AJAX requests to Google Analytics
438 | * See: http://www.alfajango.com/blog/track-jquery-ajax-requests-in-google-analytics/
439 | */
440 | if (typeof _gaq !== "undefined" && _gaq !== null) {
441 | $(document).ajaxSend(function(event, xhr, settings){
442 | _gaq.push(['_trackPageview', settings.url]);
443 | });
444 | }
445 | ```
446 |
447 | ### Track JavaScript errors in Google Analytics
448 |
449 | Add this function after `_gaq` is defined:
450 |
451 | ```js
452 | (function(window){
453 | var undefined,
454 | link = function (href) {
455 | var a = window.document.createElement('a');
456 | a.href = href;
457 | return a;
458 | };
459 | window.onerror = function (message, file, line, column) {
460 | var host = link(file).hostname;
461 | _gaq.push([
462 | '_trackEvent',
463 | (host == window.location.hostname || host == undefined || host == '' ? '' : 'external ') + 'error',
464 | message, file + ' LINE: ' + line + (column ? ' COLUMN: ' + column : ''), undefined, undefined, true
465 | ]);
466 | };
467 | }(window));
468 | ```
469 |
470 | ### Track page scroll
471 |
472 | Add this function after `_gaq` is defined:
473 |
474 | ```js
475 | $(function(){
476 | var isDuplicateScrollEvent,
477 | scrollTimeStart = new Date,
478 | $window = $(window),
479 | $document = $(document),
480 | scrollPercent;
481 |
482 | $window.scroll(function() {
483 | scrollPercent = Math.round(100 * ($window.height() + $window.scrollTop())/$document.height());
484 | if (scrollPercent > 90 && !isDuplicateScrollEvent) { //page scrolled to 90%
485 | isDuplicateScrollEvent = 1;
486 | _gaq.push(['_trackEvent', 'scroll',
487 | 'Window: ' + $window.height() + 'px; Document: ' + $document.height() + 'px; Time: ' + Math.round((new Date - scrollTimeStart )/1000,1) + 's',
488 | undefined, undefined, true
489 | ]);
490 | }
491 | });
492 | });
493 | ```
494 |
495 | ## iOS Web Apps
496 |
497 | There are a couple of meta tags that provide information about a web app when
498 | added to the Home Screen on iOS.
499 |
500 | Adding `apple-mobile-web-app-capable` will make your web app chrome-less and
501 | provide the default iOS app view. You can control the color scheme of the
502 | default view by adding `apple-mobile-web-app-status-bar-style`.
503 |
504 | ```html
505 |
506 |
507 | ```
508 |
509 | You can use `apple-mobile-web-app-title` to add a specific sites name for the
510 | Home Screen icon. This works since iOS 6.
511 |
512 | ```html
513 |
514 | ```
515 |
516 | For further information please read the [official documentation](http://developer.apple.com/library/safari/#documentation/AppleApplications/Reference/SafariHTMLRef/Articles/MetaTags.html)
517 | on Apple's site.
518 |
519 | ### Apple Touch Icons
520 |
521 | Touch Icons can be seen as the favicons of mobile devices and tablets.
522 |
523 | If your site or icons are in a sub-directory, you will need to reference the
524 | icons using `link` elements placed in the HTML `head` of your document.
525 |
526 | ```html
527 |
528 | ```
529 |
530 | The main sizes of the icons on iOS are:
531 |
532 | * iPad, high-resolution display, iOS 7: 152x152
533 | * iPad, high-resolution display, iOS ≤ 6: 144x144
534 | * iPhone, high-resolution display, iOS 7: 120x120
535 | * iPhone, high-resolution display, iOS ≤ 6: 114x114
536 | * iPad, non-Retina, iOS ≤ 6: 72x72
537 |
538 | For non-Retina iPhone, iPod Touch, and Android 2.1+ devices you can use the
539 | example from above or replace the `apple-touch-icon-precomposed.png` within this
540 | project's root folder.
541 |
542 | Please refer to Mathias' [article on Touch
543 | Icons](http://mathiasbynens.be/notes/touch-icons) for a comprehensive overview.
544 |
545 | ### Apple Touch Startup Image
546 |
547 | Apart from that it is possible to add start-up screens for web apps on iOS. This
548 | basically works by defining `apple-touch-startup-image` with an according link
549 | to the image. Since iOS devices have different screen resolutions it is
550 | necessary to add media queries to detect which image to load. Here is an
551 | example for a retina iPhone:
552 |
553 | ```html
554 |
555 | ```
556 |
557 | However, it is possible to detect which start-up image to use with JavaScript.
558 | The Mobile Boilerplate provides a useful function for this. Please see
559 | [helpers.js](https://github.com/h5bp/mobile-boilerplate/blob/master/js/helper.js#L354)
560 | for the implementation.
561 |
562 | ## Miscellaneous
563 |
564 | * Use [HTML5
565 | polyfills](https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-browser-Polyfills).
566 |
567 | * Use [Microformats](http://microformats.org/wiki/Main_Page) (via
568 | [microdata](http://microformats.org/wiki/microdata)) for optimum search
569 | results
570 | [visibility](http://googlewebmastercentral.blogspot.com/2009/05/introducing-rich-snippets.html).
571 |
572 | * If you're building a web app you may want [native style momentum scrolling in
573 | iOS5](http://johanbrook.com/browsers/native-momentum-scrolling-ios-5/) using
574 | `-webkit-overflow-scrolling: touch`.
575 |
576 | * Avoid development/stage websites "leaking" into SERPs (search engine results
577 | page) by [implementing X-Robots-tag
578 | headers](https://github.com/h5bp/html5-boilerplate/issues/804).
579 |
580 | * Screen readers currently have less-than-stellar support for HTML5 but the JS
581 | script [accessifyhtml5.js](https://github.com/yatil/accessifyhtml5.js) can
582 | help increase accessibility by adding ARIA roles to HTML5 elements.
583 |
584 |
585 | *Many thanks to [Brian Blakely](https://github.com/brianblakely) for
586 | contributing much of this information.*
587 |
--------------------------------------------------------------------------------
/html5bp/.htaccess:
--------------------------------------------------------------------------------
1 | # Apache Server Configs v1.1.0 | MIT License
2 | # https://github.com/h5bp/server-configs-apache
3 |
4 | # (!) Using `.htaccess` files slows down Apache, therefore, if you have access
5 | # to the main server config file (usually called `httpd.conf`), you should add
6 | # this logic there: http://httpd.apache.org/docs/current/howto/htaccess.html.
7 |
8 | # ##############################################################################
9 | # # CROSS-ORIGIN RESOURCE SHARING (CORS) #
10 | # ##############################################################################
11 |
12 | # ------------------------------------------------------------------------------
13 | # | Cross-domain AJAX requests |
14 | # ------------------------------------------------------------------------------
15 |
16 | # Enable cross-origin AJAX requests.
17 | # http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity
18 | # http://enable-cors.org/
19 |
20 | #
21 | # Header set Access-Control-Allow-Origin "*"
22 | #
23 |
24 | # ------------------------------------------------------------------------------
25 | # | CORS-enabled images |
26 | # ------------------------------------------------------------------------------
27 |
28 | # Send the CORS header for images when browsers request it.
29 | # https://developer.mozilla.org/en/CORS_Enabled_Image
30 | # http://blog.chromium.org/2011/07/using-cross-domain-images-in-webgl-and.html
31 | # http://hacks.mozilla.org/2011/11/using-cors-to-load-webgl-textures-from-cross-domain-images/
32 |
33 |
34 |
35 |
36 | SetEnvIf Origin ":" IS_CORS
37 | Header set Access-Control-Allow-Origin "*" env=IS_CORS
38 |
39 |
40 |
41 |
42 | # ------------------------------------------------------------------------------
43 | # | Web fonts access |
44 | # ------------------------------------------------------------------------------
45 |
46 | # Allow access from all domains for web fonts
47 |
48 |
49 |
50 | Header set Access-Control-Allow-Origin "*"
51 |
52 |
53 |
54 |
55 | # ##############################################################################
56 | # # ERRORS #
57 | # ##############################################################################
58 |
59 | # ------------------------------------------------------------------------------
60 | # | 404 error prevention for non-existing redirected folders |
61 | # ------------------------------------------------------------------------------
62 |
63 | # Prevent Apache from returning a 404 error for a rewrite if a directory
64 | # with the same name does not exist.
65 | # http://httpd.apache.org/docs/current/content-negotiation.html#multiviews
66 | # http://www.webmasterworld.com/apache/3808792.htm
67 |
68 | Options -MultiViews
69 |
70 | # ------------------------------------------------------------------------------
71 | # | Custom error messages / pages |
72 | # ------------------------------------------------------------------------------
73 |
74 | # You can customize what Apache returns to the client in case of an error (see
75 | # http://httpd.apache.org/docs/current/mod/core.html#errordocument), e.g.:
76 |
77 | ErrorDocument 404 /404.html
78 |
79 |
80 | # ##############################################################################
81 | # # INTERNET EXPLORER #
82 | # ##############################################################################
83 |
84 | # ------------------------------------------------------------------------------
85 | # | Better website experience |
86 | # ------------------------------------------------------------------------------
87 |
88 | # Force IE to render pages in the highest available mode in the various
89 | # cases when it may not: http://hsivonen.iki.fi/doctype/ie-mode.pdf.
90 |
91 |
92 | Header set X-UA-Compatible "IE=edge"
93 | # `mod_headers` can't match based on the content-type, however, we only
94 | # want to send this header for HTML pages and not for the other resources
95 |
96 | Header unset X-UA-Compatible
97 |
98 |
99 |
100 | # ------------------------------------------------------------------------------
101 | # | Cookie setting from iframes |
102 | # ------------------------------------------------------------------------------
103 |
104 | # Allow cookies to be set from iframes in IE.
105 |
106 | #
107 | # Header set P3P "policyref=\"/w3c/p3p.xml\", CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\""
108 | #
109 |
110 | # ------------------------------------------------------------------------------
111 | # | Screen flicker |
112 | # ------------------------------------------------------------------------------
113 |
114 | # Stop screen flicker in IE on CSS rollovers (this only works in
115 | # combination with the `ExpiresByType` directives for images from below).
116 |
117 | # BrowserMatch "MSIE" brokenvary=1
118 | # BrowserMatch "Mozilla/4.[0-9]{2}" brokenvary=1
119 | # BrowserMatch "Opera" !brokenvary
120 | # SetEnvIf brokenvary 1 force-no-vary
121 |
122 |
123 | # ##############################################################################
124 | # # MIME TYPES AND ENCODING #
125 | # ##############################################################################
126 |
127 | # ------------------------------------------------------------------------------
128 | # | Proper MIME types for all files |
129 | # ------------------------------------------------------------------------------
130 |
131 |
132 |
133 | # Audio
134 | AddType audio/mp4 m4a f4a f4b
135 | AddType audio/ogg oga ogg
136 |
137 | # JavaScript
138 | # Normalize to standard type (it's sniffed in IE anyways):
139 | # http://tools.ietf.org/html/rfc4329#section-7.2
140 | AddType application/javascript js
141 | AddType application/json json
142 |
143 | # Video
144 | AddType video/mp4 mp4 m4v f4v f4p
145 | AddType video/ogg ogv
146 | AddType video/webm webm
147 | AddType video/x-flv flv
148 |
149 | # Web fonts
150 | AddType application/font-woff woff
151 | AddType application/vnd.ms-fontobject eot
152 |
153 | # Browsers usually ignore the font MIME types and sniff the content,
154 | # however, Chrome shows a warning if other MIME types are used for the
155 | # following fonts.
156 | AddType application/x-font-ttf ttc ttf
157 | AddType font/opentype otf
158 |
159 | # Make SVGZ fonts work on iPad:
160 | # https://twitter.com/FontSquirrel/status/14855840545
161 | AddType image/svg+xml svg svgz
162 | AddEncoding gzip svgz
163 |
164 | # Other
165 | AddType application/octet-stream safariextz
166 | AddType application/x-chrome-extension crx
167 | AddType application/x-opera-extension oex
168 | AddType application/x-shockwave-flash swf
169 | AddType application/x-web-app-manifest+json webapp
170 | AddType application/x-xpinstall xpi
171 | AddType application/xml atom rdf rss xml
172 | AddType image/webp webp
173 | AddType image/x-icon ico
174 | AddType text/cache-manifest appcache manifest
175 | AddType text/vtt vtt
176 | AddType text/x-component htc
177 | AddType text/x-vcard vcf
178 |
179 |
180 |
181 | # ------------------------------------------------------------------------------
182 | # | UTF-8 encoding |
183 | # ------------------------------------------------------------------------------
184 |
185 | # Use UTF-8 encoding for anything served as `text/html` or `text/plain`.
186 | AddDefaultCharset utf-8
187 |
188 | # Force UTF-8 for certain file formats.
189 |
190 | AddCharset utf-8 .atom .css .js .json .rss .vtt .webapp .xml
191 |
192 |
193 |
194 | # ##############################################################################
195 | # # URL REWRITES #
196 | # ##############################################################################
197 |
198 | # ------------------------------------------------------------------------------
199 | # | Rewrite engine |
200 | # ------------------------------------------------------------------------------
201 |
202 | # Turning on the rewrite engine and enabling the `FollowSymLinks` option is
203 | # necessary for the following directives to work.
204 |
205 | # If your web host doesn't allow the `FollowSymlinks` option, you may need to
206 | # comment it out and use `Options +SymLinksIfOwnerMatch` but, be aware of the
207 | # performance impact: http://httpd.apache.org/docs/current/misc/perf-tuning.html#symlinks
208 |
209 | # Also, some cloud hosting services require `RewriteBase` to be set:
210 | # http://www.rackspace.com/knowledge_center/frequently-asked-question/why-is-mod-rewrite-not-working-on-my-site
211 |
212 |
213 | Options +FollowSymlinks
214 | # Options +SymLinksIfOwnerMatch
215 | RewriteEngine On
216 | # RewriteBase /
217 |
218 |
219 | # ------------------------------------------------------------------------------
220 | # | Suppressing / Forcing the "www." at the beginning of URLs |
221 | # ------------------------------------------------------------------------------
222 |
223 | # The same content should never be available under two different URLs especially
224 | # not with and without "www." at the beginning. This can cause SEO problems
225 | # (duplicate content), therefore, you should choose one of the alternatives and
226 | # redirect the other one.
227 |
228 | # By default option 1 (no "www.") is activated:
229 | # http://no-www.org/faq.php?q=class_b
230 |
231 | # If you'd prefer to use option 2, just comment out all the lines from option 1
232 | # and uncomment the ones from option 2.
233 |
234 | # IMPORTANT: NEVER USE BOTH RULES AT THE SAME TIME!
235 |
236 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
237 |
238 | # Option 1: rewrite www.example.com → example.com
239 |
240 |
241 | RewriteCond %{HTTPS} !=on
242 | RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
243 | RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L]
244 |
245 |
246 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
247 |
248 | # Option 2: rewrite example.com → www.example.com
249 |
250 | # Be aware that the following might not be a good idea if you use "real"
251 | # subdomains for certain parts of your website.
252 |
253 | #
254 | # RewriteCond %{HTTPS} !=on
255 | # RewriteCond %{HTTP_HOST} !^www\..+$ [NC]
256 | # RewriteCond %{HTTP_HOST} !=localhost [NC]
257 | # RewriteCond %{HTTP_HOST} !=127.0.0.1
258 | # RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
259 | #
260 |
261 |
262 | # ##############################################################################
263 | # # SECURITY #
264 | # ##############################################################################
265 |
266 | # ------------------------------------------------------------------------------
267 | # | Content Security Policy (CSP) |
268 | # ------------------------------------------------------------------------------
269 |
270 | # You can mitigate the risk of cross-site scripting and other content-injection
271 | # attacks by setting a Content Security Policy which whitelists trusted sources
272 | # of content for your site.
273 |
274 | # The example header below allows ONLY scripts that are loaded from the current
275 | # site's origin (no inline scripts, no CDN, etc). This almost certainly won't
276 | # work as-is for your site!
277 |
278 | # To get all the details you'll need to craft a reasonable policy for your site,
279 | # read: http://html5rocks.com/en/tutorials/security/content-security-policy (or
280 | # see the specification: http://w3.org/TR/CSP).
281 |
282 | #
283 | # Header set Content-Security-Policy "script-src 'self'; object-src 'self'"
284 | #
285 | # Header unset Content-Security-Policy
286 | #
287 | #
288 |
289 | # ------------------------------------------------------------------------------
290 | # | File access |
291 | # ------------------------------------------------------------------------------
292 |
293 | # Block access to directories without a default document.
294 | # Usually you should leave this uncommented because you shouldn't allow anyone
295 | # to surf through every directory on your server (which may includes rather
296 | # private places like the CMS's directories).
297 |
298 |
299 | Options -Indexes
300 |
301 |
302 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
303 |
304 | # Block access to hidden files and directories.
305 | # This includes directories used by version control systems such as Git and SVN.
306 |
307 |
308 | RewriteCond %{SCRIPT_FILENAME} -d [OR]
309 | RewriteCond %{SCRIPT_FILENAME} -f
310 | RewriteRule "(^|/)\." - [F]
311 |
312 |
313 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
314 |
315 | # Block access to backup and source files.
316 | # These files may be left by some text editors and can pose a great security
317 | # danger when anyone has access to them.
318 |
319 |
320 | Order allow,deny
321 | Deny from all
322 | Satisfy All
323 |
324 |
325 | # ------------------------------------------------------------------------------
326 | # | Secure Sockets Layer (SSL) |
327 | # ------------------------------------------------------------------------------
328 |
329 | # Rewrite secure requests properly to prevent SSL certificate warnings, e.g.:
330 | # prevent `https://www.example.com` when your certificate only allows
331 | # `https://secure.example.com`.
332 |
333 | #
334 | # RewriteCond %{SERVER_PORT} !^443
335 | # RewriteRule ^ https://example-domain-please-change-me.com%{REQUEST_URI} [R=301,L]
336 | #
337 |
338 | # ------------------------------------------------------------------------------
339 | # | HTTP Strict Transport Security (HSTS) |
340 | # ------------------------------------------------------------------------------
341 |
342 | # Force client-side SSL redirection.
343 |
344 | # If a user types "example.com" in his browser, the above rule will redirect
345 | # him to the secure version of the site. That still leaves a window of oppor-
346 | # tunity (the initial HTTP connection) for an attacker to downgrade or redirect
347 | # the request. The following header ensures that browser will ONLY connect to
348 | # your server via HTTPS, regardless of what the users type in the address bar.
349 | # http://tools.ietf.org/html/draft-ietf-websec-strict-transport-sec-14#section-6.1
350 | # http://www.html5rocks.com/en/tutorials/security/transport-layer-security/
351 |
352 | # (!) Remove the `includeSubDomains` optional directive if the subdomains are
353 | # not using HTTPS.
354 |
355 | #
356 | # Header set Strict-Transport-Security "max-age=16070400; includeSubDomains"
357 | #
358 |
359 | # ------------------------------------------------------------------------------
360 | # | Server software information |
361 | # ------------------------------------------------------------------------------
362 |
363 | # Avoid displaying the exact Apache version number, the description of the
364 | # generic OS-type and the information about Apache's compiled-in modules.
365 |
366 | # ADD THIS DIRECTIVE IN THE `httpd.conf` AS IT WILL NOT WORK IN THE `.htaccess`!
367 |
368 | # ServerTokens Prod
369 |
370 |
371 | # ##############################################################################
372 | # # WEB PERFORMANCE #
373 | # ##############################################################################
374 |
375 | # ------------------------------------------------------------------------------
376 | # | Compression |
377 | # ------------------------------------------------------------------------------
378 |
379 |
380 |
381 | # Force compression for mangled headers.
382 | # http://developer.yahoo.com/blogs/ydn/posts/2010/12/pushing-beyond-gzipping
383 |
384 |
385 | SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\s*,?\s*)+|[X~-]{4,13}$ HAVE_Accept-Encoding
386 | RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding
387 |
388 |
389 |
390 | # Compress all output labeled with one of the following MIME-types
391 | # (for Apache versions below 2.3.7, you don't need to enable `mod_filter`
392 | # and can remove the `` and ` ` lines
393 | # as `AddOutputFilterByType` is still in the core directives).
394 |
395 | AddOutputFilterByType DEFLATE application/atom+xml \
396 | application/javascript \
397 | application/json \
398 | application/rss+xml \
399 | application/vnd.ms-fontobject \
400 | application/x-font-ttf \
401 | application/x-web-app-manifest+json \
402 | application/xhtml+xml \
403 | application/xml \
404 | font/opentype \
405 | image/svg+xml \
406 | image/x-icon \
407 | text/css \
408 | text/html \
409 | text/plain \
410 | text/x-component \
411 | text/xml
412 |
413 |
414 |
415 |
416 | # ------------------------------------------------------------------------------
417 | # | Content transformations |
418 | # ------------------------------------------------------------------------------
419 |
420 | # Prevent some of the mobile network providers from modifying the content of
421 | # your site: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.5.
422 |
423 | #
424 | # Header set Cache-Control "no-transform"
425 | #
426 |
427 | # ------------------------------------------------------------------------------
428 | # | ETag removal |
429 | # ------------------------------------------------------------------------------
430 |
431 | # Since we're sending far-future expires headers (see below), ETags can
432 | # be removed: http://developer.yahoo.com/performance/rules.html#etags.
433 |
434 | # `FileETag None` is not enough for every server.
435 |
436 | Header unset ETag
437 |
438 |
439 | FileETag None
440 |
441 | # ------------------------------------------------------------------------------
442 | # | Expires headers (for better cache control) |
443 | # ------------------------------------------------------------------------------
444 |
445 | # The following expires headers are set pretty far in the future. If you don't
446 | # control versioning with filename-based cache busting, consider lowering the
447 | # cache time for resources like CSS and JS to something like 1 week.
448 |
449 |
450 |
451 | ExpiresActive on
452 | ExpiresDefault "access plus 1 month"
453 |
454 | # CSS
455 | ExpiresByType text/css "access plus 1 year"
456 |
457 | # Data interchange
458 | ExpiresByType application/json "access plus 0 seconds"
459 | ExpiresByType application/xml "access plus 0 seconds"
460 | ExpiresByType text/xml "access plus 0 seconds"
461 |
462 | # Favicon (cannot be renamed!)
463 | ExpiresByType image/x-icon "access plus 1 week"
464 |
465 | # HTML components (HTCs)
466 | ExpiresByType text/x-component "access plus 1 month"
467 |
468 | # HTML
469 | ExpiresByType text/html "access plus 0 seconds"
470 |
471 | # JavaScript
472 | ExpiresByType application/javascript "access plus 1 year"
473 |
474 | # Manifest files
475 | ExpiresByType application/x-web-app-manifest+json "access plus 0 seconds"
476 | ExpiresByType text/cache-manifest "access plus 0 seconds"
477 |
478 | # Media
479 | ExpiresByType audio/ogg "access plus 1 month"
480 | ExpiresByType image/gif "access plus 1 month"
481 | ExpiresByType image/jpeg "access plus 1 month"
482 | ExpiresByType image/png "access plus 1 month"
483 | ExpiresByType video/mp4 "access plus 1 month"
484 | ExpiresByType video/ogg "access plus 1 month"
485 | ExpiresByType video/webm "access plus 1 month"
486 |
487 | # Web feeds
488 | ExpiresByType application/atom+xml "access plus 1 hour"
489 | ExpiresByType application/rss+xml "access plus 1 hour"
490 |
491 | # Web fonts
492 | ExpiresByType application/font-woff "access plus 1 month"
493 | ExpiresByType application/vnd.ms-fontobject "access plus 1 month"
494 | ExpiresByType application/x-font-ttf "access plus 1 month"
495 | ExpiresByType font/opentype "access plus 1 month"
496 | ExpiresByType image/svg+xml "access plus 1 month"
497 |
498 |
499 |
500 | # ------------------------------------------------------------------------------
501 | # | Filename-based cache busting |
502 | # ------------------------------------------------------------------------------
503 |
504 | # If you're not using a build process to manage your filename version revving,
505 | # you might want to consider enabling the following directives to route all
506 | # requests such as `/css/style.12345.css` to `/css/style.css`.
507 |
508 | # To understand why this is important and a better idea than `*.css?v231`, read:
509 | # http://stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring
510 |
511 | #
512 | # RewriteCond %{REQUEST_FILENAME} !-f
513 | # RewriteRule ^(.+)\.(\d+)\.(js|css|png|jpg|gif)$ $1.$3 [L]
514 | #
515 |
516 | # ------------------------------------------------------------------------------
517 | # | File concatenation |
518 | # ------------------------------------------------------------------------------
519 |
520 | # Allow concatenation from within specific CSS and JS files, e.g.:
521 | # Inside of `script.combined.js` you could have
522 | #
523 | #
524 | # and they would be included into this single file.
525 |
526 | #
527 | #
528 | # Options +Includes
529 | # AddOutputFilterByType INCLUDES application/javascript application/json
530 | # SetOutputFilter INCLUDES
531 | #
532 | #
533 | # Options +Includes
534 | # AddOutputFilterByType INCLUDES text/css
535 | # SetOutputFilter INCLUDES
536 | #
537 | #
538 |
539 | # ------------------------------------------------------------------------------
540 | # | Persistent connections |
541 | # ------------------------------------------------------------------------------
542 |
543 | # Allow multiple requests to be sent over the same TCP connection:
544 | # http://httpd.apache.org/docs/current/en/mod/core.html#keepalive.
545 |
546 | # Enable if you serve a lot of static content but, be aware of the
547 | # possible disadvantages!
548 |
549 | #
550 | # Header set Connection Keep-Alive
551 | #
552 |
--------------------------------------------------------------------------------