├── CNAME ├── .gitignore ├── .Rprofile ├── _layouts ├── page.html ├── default.html └── post.html ├── blogdown-jekyll.Rproj ├── about.md ├── _includes ├── head.html ├── header.html └── footer.html ├── index.html ├── _config.yml ├── R ├── build.R └── build_one.R ├── LICENSE ├── css └── main.scss ├── _posts ├── 2014-09-27-welcome-to-jekyll.markdown ├── 2014-09-28-jekyll-with-knitr.Rmd └── 2014-09-28-jekyll-with-knitr.md ├── feed.xml ├── README.md └── _sass ├── _syntax-highlighting.scss ├── _base.scss └── _layout.scss /CNAME: -------------------------------------------------------------------------------- 1 | jekyll.yihui.name 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | _site/ 5 | .sass-cache/ 6 | -------------------------------------------------------------------------------- /.Rprofile: -------------------------------------------------------------------------------- 1 | options( 2 | blogdown.generator = 'jekyll', blogdown.method = 'custom', 3 | blogdown.subdir = '_posts', servr.daemon = TRUE 4 | ) 5 | -------------------------------------------------------------------------------- /_layouts/page.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | --- 4 |
5 | 6 |
7 |

{{ page.title }}

8 |
9 | 10 |
11 | {{ content }} 12 |
13 | 14 |
15 | -------------------------------------------------------------------------------- /_layouts/default.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {% include head.html %} 5 | 6 | 7 | 8 | {% include header.html %} 9 | 10 |
11 |
12 | {{ content }} 13 |
14 |
15 | 16 | {% include footer.html %} 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /blogdown-jekyll.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: knitr 13 | LaTeX: pdfLaTeX 14 | 15 | AutoAppendNewline: Yes 16 | StripTrailingWhitespace: Yes 17 | 18 | BuildType: Website 19 | -------------------------------------------------------------------------------- /_layouts/post.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | --- 4 |
5 | 6 |
7 |

{{ page.title }}

8 | 9 |
10 | 11 |
12 | {{ content }} 13 |
14 | 15 |
16 | -------------------------------------------------------------------------------- /about.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: About 4 | permalink: /about/ 5 | --- 6 | 7 | This is the base Jekyll theme. You can find out more info about customizing your Jekyll theme, as well as basic Jekyll usage documentation at [jekyllrb.com](http://jekyllrb.com/) 8 | 9 | You can find the source code for the Jekyll new theme at: [github.com/jglovier/jekyll-new](https://github.com/jglovier/jekyll-new) 10 | 11 | You can find the source code for Jekyll at [github.com/jekyll/jekyll](https://github.com/jekyll/jekyll) 12 | -------------------------------------------------------------------------------- /_includes/head.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | {% if page.title %}{{ page.title }}{% else %}{{ site.title }}{% endif %} 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | --- 4 | 5 |
6 | 7 |

Posts

8 | 9 | 20 | 21 |

subscribe via RSS

22 | 23 |
24 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | # Site settings 2 | title: Your awesome title 3 | email: your-email@example.com 4 | description: > # this means to ignore newlines until "baseurl:" 5 | Write an awesome description for your new site here. You can edit this 6 | line in _config.yml. It will appear in your document head meta (for 7 | Google search results) and in your feed.xml site description. 8 | url: "http://example.com" # the base hostname & protocol for your site 9 | twitter_username: xieyihui 10 | github_username: yihui/knitr-jekyll 11 | permalink: /:year/:month/:title.html 12 | 13 | # Build settings 14 | markdown: kramdown 15 | exclude: ['*.Rmd'] 16 | -------------------------------------------------------------------------------- /R/build.R: -------------------------------------------------------------------------------- 1 | build_one = function(io) { 2 | # if output is not older than input, skip the compilation 3 | if (!blogdown:::require_rebuild(io[2], io[1])) return() 4 | 5 | message('* knitting ', io[1]) 6 | if (blogdown:::Rscript(shQuote(c('R/build_one.R', io))) != 0) { 7 | unlink(io[2]) 8 | stop('Failed to compile ', io[1], ' to ', io[2]) 9 | } 10 | } 11 | 12 | # Rmd files under the root directory 13 | rmds = list.files('.', '[.]Rmd$', recursive = TRUE, full.names = TRUE) 14 | files = cbind(rmds, blogdown:::with_ext(rmds, '.md')) 15 | 16 | for (i in seq_len(nrow(files))) build_one(files[i, ]) 17 | 18 | system2('jekyll', 'build') 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014-2017 Yihui Xie 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /css/main.scss: -------------------------------------------------------------------------------- 1 | --- 2 | # Only the main Sass file needs front matter (the dashes are enough) 3 | --- 4 | @charset "utf-8"; 5 | 6 | 7 | 8 | // Our variables 9 | $base-font-family: Helvetica, Arial, sans-serif; 10 | $base-font-size: 16px; 11 | $small-font-size: $base-font-size * 0.875; 12 | $base-line-height: 1.5; 13 | 14 | $spacing-unit: 30px; 15 | 16 | $text-color: #111; 17 | $background-color: #fdfdfd; 18 | $brand-color: #2a7ae2; 19 | 20 | $grey-color: #828282; 21 | $grey-color-light: lighten($grey-color, 40%); 22 | $grey-color-dark: darken($grey-color, 25%); 23 | 24 | $on-palm: 600px; 25 | $on-laptop: 800px; 26 | 27 | 28 | 29 | // Using media queries with like this: 30 | // @include media-query($palm) { 31 | // .wrapper { 32 | // padding-right: $spacing-unit / 2; 33 | // padding-left: $spacing-unit / 2; 34 | // } 35 | // } 36 | @mixin media-query($device) { 37 | @media screen and (max-width: $device) { 38 | @content; 39 | } 40 | } 41 | 42 | 43 | 44 | // Import partials from `sass_dir` (defaults to `_sass`) 45 | @import 46 | "base", 47 | "layout", 48 | "syntax-highlighting" 49 | ; 50 | -------------------------------------------------------------------------------- /_includes/header.html: -------------------------------------------------------------------------------- 1 | 28 | -------------------------------------------------------------------------------- /_posts/2014-09-27-welcome-to-jekyll.markdown: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: "Welcome to Jekyll!" 4 | date: 2014-09-27 23:16:53 5 | categories: jekyll update 6 | --- 7 | You’ll find this post in your `_posts` directory. Go ahead and edit it and re-build the site to see your changes. You can rebuild the site in many different ways, but the most common way is to run `jekyll serve --watch`, which launches a web server and auto-regenerates your site when a file is updated. 8 | 9 | To add new posts, simply add a file in the `_posts` directory that follows the convention `YYYY-MM-DD-name-of-post.ext` and includes the necessary front matter. Take a look at the source for this post to get an idea about how it works. 10 | 11 | Jekyll also offers powerful support for code snippets: 12 | 13 | {% highlight ruby %} 14 | def print_hi(name) 15 | puts "Hi, #{name}" 16 | end 17 | print_hi('Tom') 18 | #=> prints 'Hi, Tom' to STDOUT. 19 | {% endhighlight %} 20 | 21 | Check out the [Jekyll docs][jekyll] for more info on how to get the most out of Jekyll. File all bugs/feature requests at [Jekyll’s GitHub repo][jekyll-gh]. If you have questions, you can ask them on [Jekyll’s dedicated Help repository][jekyll-help]. 22 | 23 | [jekyll]: http://jekyllrb.com 24 | [jekyll-gh]: https://github.com/jekyll/jekyll 25 | [jekyll-help]: https://github.com/jekyll/jekyll-help 26 | -------------------------------------------------------------------------------- /feed.xml: -------------------------------------------------------------------------------- 1 | --- 2 | layout: null 3 | --- 4 | 5 | 6 | 7 | {{ site.title | xml_escape }} 8 | {{ site.description | xml_escape }} 9 | {{ site.url }}{{ site.baseurl }}/ 10 | 11 | {{ site.time | date_to_rfc822 }} 12 | {{ site.time | date_to_rfc822 }} 13 | Jekyll v{{ jekyll.version }} 14 | {% for post in site.posts limit:10 %} 15 | 16 | {{ post.title | xml_escape }} 17 | {{ post.content | xml_escape }} 18 | {{ post.date | date_to_rfc822 }} 19 | {{ post.url | prepend: site.baseurl | prepend: site.url }} 20 | {{ post.url | prepend: site.baseurl | prepend: site.url }} 21 | {% for tag in post.tags %} 22 | {{ tag | xml_escape }} 23 | {% endfor %} 24 | {% for cat in post.categories %} 25 | {{ cat | xml_escape }} 26 | {% endfor %} 27 | 28 | {% endfor %} 29 | 30 | 31 | -------------------------------------------------------------------------------- /R/build_one.R: -------------------------------------------------------------------------------- 1 | local({ 2 | # fall back on '/' if baseurl is not specified 3 | baseurl = blogdown:::get_config2('baseurl', '/') 4 | knitr::opts_knit$set(base.url = baseurl) 5 | # fall back on 'kramdown' if markdown engine is not specified 6 | markdown = blogdown:::get_config2('markdown', 'kramdown') 7 | # see if we need to use the Jekyll renderer in knitr 8 | if (markdown == 'kramdown') knitr::render_jekyll() else knitr::render_markdown() 9 | 10 | # input/output filenames are passed as two additional arguments to Rscript 11 | a = commandArgs(TRUE) 12 | d = gsub('^_|[.][a-zA-Z]+$', '', a[1]) 13 | knitr::opts_chunk$set( 14 | fig.path = sprintf('figure/%s/', d), 15 | cache.path = sprintf('cache/%s/', d) 16 | ) 17 | # set where you want to host the figures (I store them in my Dropbox folder 18 | # served via Updog.co, but you might prefer putting them in GIT) 19 | if (Sys.getenv('USER') == 'yihui') { 20 | # these settings are only for myself, and they will not apply to you, but 21 | # you may want to adapt them to your own website 22 | knitr::opts_chunk$set(fig.path = sprintf('%s/', gsub('^.+/', '', d))) 23 | knitr::opts_knit$set( 24 | base.dir = '~/Dropbox/Apps/updog/drop/jekyll/', 25 | base.url = 'https://db.yihui.name/jekyll/' 26 | ) 27 | } 28 | options(digits = 4) 29 | knitr::opts_knit$set(width = 70) 30 | knitr::knit(a[1], a[2], quiet = TRUE, encoding = 'UTF-8', envir = .GlobalEnv) 31 | }) 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This is a minimal example of a Jekyll-based website using [**knitr**](https://yihui.name/knitr/), [**blogdown**](https://github.com/rstudio/blogdown), and R Markdown, briefly documented at . 2 | 3 | You can actually serve the Jekyll website locally with R, and R Markdown posts can be compiled automatically, with the web pages being automatically refreshed in your web browser as well. To build the serve the website locally, you need to install **blogdown** (and Jekyll, of course) and call the `serve_site()` function: 4 | 5 | ```r 6 | devtools::install_github("rstudio/blogdown") 7 | blogdown::serve_site() 8 | ``` 9 | 10 | After you are satisfied with the local preview, you can either just push the Markdown blog posts to your Github repo (e.g. the `gh-pages` branch), and let Github generate the website for you, or host the HTML files generated under the `_site/` directory on your own server. 11 | 12 | The original website was created from `jekyll new .` under the root directory, which was part of the [official Jekyll repo](https://github.com/jekyll/jekyll). The additional code (mainly R code) in this repo is under the MIT License, and the [blog post](https://jekyll.yihui.name/2014/09/jekyll-with-knitr.html) I wrote is under the [CC-BY 4.0](http://creativecommons.org/licenses/by/4.0/) International License. 13 | 14 | The support for Jekyll is limitted in **blogdown**, and you may want to switch to Hugo, which is much better supported in **blogdown**. 15 | -------------------------------------------------------------------------------- /_includes/footer.html: -------------------------------------------------------------------------------- 1 | 56 | -------------------------------------------------------------------------------- /_sass/_syntax-highlighting.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Syntax highlighting styles 3 | */ 4 | .highlight { 5 | background: #fff; 6 | @extend %vertical-rhythm; 7 | 8 | .c { color: #998; font-style: italic } // Comment 9 | .err { color: #a61717; background-color: #e3d2d2 } // Error 10 | .k { font-weight: bold } // Keyword 11 | .o { font-weight: bold } // Operator 12 | .cm { color: #998; font-style: italic } // Comment.Multiline 13 | .cp { color: #999; font-weight: bold } // Comment.Preproc 14 | .c1 { color: #998; font-style: italic } // Comment.Single 15 | .cs { color: #999; font-weight: bold; font-style: italic } // Comment.Special 16 | .gd { color: #000; background-color: #fdd } // Generic.Deleted 17 | .gd .x { color: #000; background-color: #faa } // Generic.Deleted.Specific 18 | .ge { font-style: italic } // Generic.Emph 19 | .gr { color: #a00 } // Generic.Error 20 | .gh { color: #999 } // Generic.Heading 21 | .gi { color: #000; background-color: #dfd } // Generic.Inserted 22 | .gi .x { color: #000; background-color: #afa } // Generic.Inserted.Specific 23 | .go { color: #888 } // Generic.Output 24 | .gp { color: #555 } // Generic.Prompt 25 | .gs { font-weight: bold } // Generic.Strong 26 | .gu { color: #aaa } // Generic.Subheading 27 | .gt { color: #a00 } // Generic.Traceback 28 | .kc { font-weight: bold } // Keyword.Constant 29 | .kd { font-weight: bold } // Keyword.Declaration 30 | .kp { font-weight: bold } // Keyword.Pseudo 31 | .kr { font-weight: bold } // Keyword.Reserved 32 | .kt { color: #458; font-weight: bold } // Keyword.Type 33 | .m { color: #099 } // Literal.Number 34 | .s { color: #d14 } // Literal.String 35 | .na { color: #008080 } // Name.Attribute 36 | .nb { color: #0086B3 } // Name.Builtin 37 | .nc { color: #458; font-weight: bold } // Name.Class 38 | .no { color: #008080 } // Name.Constant 39 | .ni { color: #800080 } // Name.Entity 40 | .ne { color: #900; font-weight: bold } // Name.Exception 41 | .nf { color: #900; font-weight: bold } // Name.Function 42 | .nn { color: #555 } // Name.Namespace 43 | .nt { color: #000080 } // Name.Tag 44 | .nv { color: #008080 } // Name.Variable 45 | .ow { font-weight: bold } // Operator.Word 46 | .w { color: #bbb } // Text.Whitespace 47 | .mf { color: #099 } // Literal.Number.Float 48 | .mh { color: #099 } // Literal.Number.Hex 49 | .mi { color: #099 } // Literal.Number.Integer 50 | .mo { color: #099 } // Literal.Number.Oct 51 | .sb { color: #d14 } // Literal.String.Backtick 52 | .sc { color: #d14 } // Literal.String.Char 53 | .sd { color: #d14 } // Literal.String.Doc 54 | .s2 { color: #d14 } // Literal.String.Double 55 | .se { color: #d14 } // Literal.String.Escape 56 | .sh { color: #d14 } // Literal.String.Heredoc 57 | .si { color: #d14 } // Literal.String.Interpol 58 | .sx { color: #d14 } // Literal.String.Other 59 | .sr { color: #009926 } // Literal.String.Regex 60 | .s1 { color: #d14 } // Literal.String.Single 61 | .ss { color: #990073 } // Literal.String.Symbol 62 | .bp { color: #999 } // Name.Builtin.Pseudo 63 | .vc { color: #008080 } // Name.Variable.Class 64 | .vg { color: #008080 } // Name.Variable.Global 65 | .vi { color: #008080 } // Name.Variable.Instance 66 | .il { color: #099 } // Literal.Number.Integer.Long 67 | } 68 | -------------------------------------------------------------------------------- /_sass/_base.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Reset some basic elements 3 | */ 4 | body, h1, h2, h3, h4, h5, h6, 5 | p, blockquote, pre, hr, 6 | dl, dd, ol, ul, figure { 7 | margin: 0; 8 | padding: 0; 9 | } 10 | 11 | 12 | 13 | /** 14 | * Basic styling 15 | */ 16 | body { 17 | font-family: $base-font-family; 18 | font-size: $base-font-size; 19 | line-height: $base-line-height; 20 | font-weight: 300; 21 | color: $text-color; 22 | background-color: $background-color; 23 | -webkit-text-size-adjust: 100%; 24 | } 25 | 26 | 27 | 28 | /** 29 | * Set `margin-bottom` to maintain vertical rhythm 30 | */ 31 | h1, h2, h3, h4, h5, h6, 32 | p, blockquote, pre, 33 | ul, ol, dl, figure, 34 | %vertical-rhythm { 35 | margin-bottom: $spacing-unit / 2; 36 | } 37 | 38 | 39 | 40 | /** 41 | * Images 42 | */ 43 | img { 44 | max-width: 100%; 45 | vertical-align: middle; 46 | } 47 | 48 | 49 | 50 | /** 51 | * Figures 52 | */ 53 | figure > img { 54 | display: block; 55 | } 56 | 57 | figcaption { 58 | font-size: $small-font-size; 59 | } 60 | 61 | 62 | 63 | /** 64 | * Lists 65 | */ 66 | ul, ol { 67 | margin-left: $spacing-unit; 68 | } 69 | 70 | li { 71 | > ul, 72 | > ol { 73 | margin-bottom: 0; 74 | } 75 | } 76 | 77 | 78 | 79 | /** 80 | * Headings 81 | */ 82 | h1, h2, h3, h4, h5, h6 { 83 | font-weight: 300; 84 | } 85 | 86 | 87 | 88 | /** 89 | * Links 90 | */ 91 | a { 92 | color: $brand-color; 93 | text-decoration: none; 94 | 95 | &:visited { 96 | color: darken($brand-color, 15%); 97 | } 98 | 99 | &:hover { 100 | color: $text-color; 101 | text-decoration: underline; 102 | } 103 | } 104 | 105 | 106 | 107 | /** 108 | * Blockquotes 109 | */ 110 | blockquote { 111 | color: $grey-color; 112 | border-left: 4px solid $grey-color-light; 113 | padding-left: $spacing-unit / 2; 114 | font-size: 18px; 115 | letter-spacing: -1px; 116 | font-style: italic; 117 | 118 | > :last-child { 119 | margin-bottom: 0; 120 | } 121 | } 122 | 123 | 124 | 125 | /** 126 | * Code formatting 127 | */ 128 | pre, 129 | code { 130 | font-size: 15px; 131 | border: 1px solid $grey-color-light; 132 | border-radius: 3px; 133 | background-color: #eef; 134 | } 135 | 136 | code { 137 | padding: 1px 5px; 138 | } 139 | 140 | pre { 141 | padding: 8px 12px; 142 | overflow-x: auto; 143 | 144 | > code { 145 | border: 0; 146 | padding-right: 0; 147 | padding-left: 0; 148 | } 149 | } 150 | 151 | 152 | 153 | /** 154 | * Wrapper 155 | */ 156 | .wrapper { 157 | max-width: -webkit-calc(800px - (#{$spacing-unit} * 2)); 158 | max-width: calc(800px - (#{$spacing-unit} * 2)); 159 | margin-right: auto; 160 | margin-left: auto; 161 | padding-right: $spacing-unit; 162 | padding-left: $spacing-unit; 163 | @extend %clearfix; 164 | 165 | @include media-query($on-laptop) { 166 | max-width: -webkit-calc(800px - (#{$spacing-unit})); 167 | max-width: calc(800px - (#{$spacing-unit})); 168 | padding-right: $spacing-unit / 2; 169 | padding-left: $spacing-unit / 2; 170 | } 171 | } 172 | 173 | 174 | 175 | /** 176 | * Clearfix 177 | */ 178 | %clearfix { 179 | 180 | &:after { 181 | content: ""; 182 | display: table; 183 | clear: both; 184 | } 185 | } 186 | 187 | 188 | 189 | /** 190 | * Icons 191 | */ 192 | .icon { 193 | 194 | > svg { 195 | display: inline-block; 196 | width: 16px; 197 | height: 16px; 198 | vertical-align: middle; 199 | 200 | path { 201 | fill: $grey-color; 202 | } 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /_sass/_layout.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Site header 3 | */ 4 | .site-header { 5 | border-top: 5px solid $grey-color-dark; 6 | border-bottom: 1px solid $grey-color-light; 7 | min-height: 56px; 8 | 9 | // Positioning context for the mobile navigation icon 10 | position: relative; 11 | } 12 | 13 | .site-title { 14 | font-size: 26px; 15 | line-height: 56px; 16 | letter-spacing: -1px; 17 | margin-bottom: 0; 18 | float: left; 19 | 20 | &, 21 | &:visited { 22 | color: $grey-color-dark; 23 | } 24 | } 25 | 26 | .site-nav { 27 | float: right; 28 | line-height: 56px; 29 | 30 | .menu-icon { 31 | display: none; 32 | } 33 | 34 | .page-link { 35 | color: $text-color; 36 | line-height: $base-line-height; 37 | 38 | // Gaps between nav items, but not on the first one 39 | &:not(:first-child) { 40 | margin-left: 20px; 41 | } 42 | } 43 | 44 | @include media-query($on-palm) { 45 | position: absolute; 46 | top: 9px; 47 | right: 30px; 48 | background-color: $background-color; 49 | border: 1px solid $grey-color-light; 50 | border-radius: 5px; 51 | text-align: right; 52 | 53 | .menu-icon { 54 | display: block; 55 | float: right; 56 | width: 36px; 57 | height: 26px; 58 | line-height: 0; 59 | padding-top: 10px; 60 | text-align: center; 61 | 62 | > svg { 63 | width: 18px; 64 | height: 15px; 65 | 66 | path { 67 | fill: $grey-color-dark; 68 | } 69 | } 70 | } 71 | 72 | .trigger { 73 | clear: both; 74 | display: none; 75 | } 76 | 77 | &:hover .trigger { 78 | display: block; 79 | padding-bottom: 5px; 80 | } 81 | 82 | .page-link { 83 | display: block; 84 | padding: 5px 10px; 85 | } 86 | } 87 | } 88 | 89 | 90 | 91 | /** 92 | * Site footer 93 | */ 94 | .site-footer { 95 | border-top: 1px solid $grey-color-light; 96 | padding: $spacing-unit 0; 97 | } 98 | 99 | .footer-heading { 100 | font-size: 18px; 101 | margin-bottom: $spacing-unit / 2; 102 | } 103 | 104 | .contact-list, 105 | .social-media-list { 106 | list-style: none; 107 | margin-left: 0; 108 | } 109 | 110 | .footer-col-wrapper { 111 | font-size: 15px; 112 | color: $grey-color; 113 | margin-left: -$spacing-unit / 2; 114 | @extend %clearfix; 115 | } 116 | 117 | .footer-col { 118 | float: left; 119 | margin-bottom: $spacing-unit / 2; 120 | padding-left: $spacing-unit / 2; 121 | } 122 | 123 | .footer-col-1 { 124 | width: -webkit-calc(35% - (#{$spacing-unit} / 2)); 125 | width: calc(35% - (#{$spacing-unit} / 2)); 126 | } 127 | 128 | .footer-col-2 { 129 | width: -webkit-calc(20% - (#{$spacing-unit} / 2)); 130 | width: calc(20% - (#{$spacing-unit} / 2)); 131 | } 132 | 133 | .footer-col-3 { 134 | width: -webkit-calc(45% - (#{$spacing-unit} / 2)); 135 | width: calc(45% - (#{$spacing-unit} / 2)); 136 | } 137 | 138 | @include media-query($on-laptop) { 139 | .footer-col-1, 140 | .footer-col-2 { 141 | width: -webkit-calc(50% - (#{$spacing-unit} / 2)); 142 | width: calc(50% - (#{$spacing-unit} / 2)); 143 | } 144 | 145 | .footer-col-3 { 146 | width: -webkit-calc(100% - (#{$spacing-unit} / 2)); 147 | width: calc(100% - (#{$spacing-unit} / 2)); 148 | } 149 | } 150 | 151 | @include media-query($on-palm) { 152 | .footer-col { 153 | float: none; 154 | width: -webkit-calc(100% - (#{$spacing-unit} / 2)); 155 | width: calc(100% - (#{$spacing-unit} / 2)); 156 | } 157 | } 158 | 159 | 160 | 161 | /** 162 | * Page content 163 | */ 164 | .page-content { 165 | padding: $spacing-unit 0; 166 | } 167 | 168 | .page-heading { 169 | font-size: 20px; 170 | } 171 | 172 | .post-list { 173 | margin-left: 0; 174 | list-style: none; 175 | 176 | > li { 177 | margin-bottom: $spacing-unit; 178 | } 179 | } 180 | 181 | .post-meta { 182 | font-size: $small-font-size; 183 | color: $grey-color; 184 | } 185 | 186 | .post-link { 187 | display: block; 188 | font-size: 24px; 189 | } 190 | 191 | 192 | 193 | /** 194 | * Posts 195 | */ 196 | .post-header { 197 | margin-bottom: $spacing-unit; 198 | } 199 | 200 | .post-title { 201 | font-size: 42px; 202 | letter-spacing: -1px; 203 | line-height: 1; 204 | 205 | @include media-query($on-laptop) { 206 | font-size: 36px; 207 | } 208 | } 209 | 210 | .post-content { 211 | margin-bottom: $spacing-unit; 212 | 213 | h2 { 214 | font-size: 32px; 215 | 216 | @include media-query($on-laptop) { 217 | font-size: 28px; 218 | } 219 | } 220 | 221 | h3 { 222 | font-size: 26px; 223 | 224 | @include media-query($on-laptop) { 225 | font-size: 22px; 226 | } 227 | } 228 | 229 | h4 { 230 | font-size: 20px; 231 | 232 | @include media-query($on-laptop) { 233 | font-size: 18px; 234 | } 235 | } 236 | } 237 | 238 | .footnotes { 239 | border-top: darkgray 1px solid; 240 | padding-top: 1em; 241 | } 242 | -------------------------------------------------------------------------------- /_posts/2014-09-28-jekyll-with-knitr.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: "Build Jekyll Websites with knitr and blogdown" 4 | categories: [jekyll, rstats] 5 | tags: [blogdown, knitr, servr, httpuv, websocket] 6 | --- 7 | 8 | The R package [**blogdown**](https://github.com/rstudio/blogdown) was designed mainly for the static site generator [Hugo](https://gohugo.io), but it can also be used to build websites based on Jekyll and R Markdown. The main features are: 9 | 10 | 1. R Markdown source files are re-compiled through [**knitr**](https://yihui.name/knitr/) when their corresponding Markdown output files become older[^1] than source files; 11 | 1. The web page will refresh itself automatically in the above case as well; 12 | 13 | [^1]: Determined by the modification time of files, i.e., `file.info(x)[, 'mtime']`. 14 | 15 | As a result, all you need to do is write your blog posts (R Markdown documents). You do not need to explicitly re-build the website or call **knitr** commands. Whenever you save a blog post in your text editor, the web page will be updated on the fly. This is particularly handy in the [RStudio IDE](https://www.rstudio.com), because after you run `servr::jekyll()` in the console, you can start writing or editing your R Markdown posts, and the HTML output, displayed in the RStudio viewer pane, will be in sync with your source post in the source panel (see the screenshot below). 16 | 17 | [![Jekyll with servr and knitr](//i.imgur.com/gKVGhiP.png)](//i.imgur.com/gKVGhiP.png) 18 | 19 | ## Prerequisites 20 | 21 | You must have installed the packages **blogdown** (>= 0.0.55). 22 | 23 | ```{r eval=FALSE} 24 | devtools::install_github('rstudio/blogdown') 25 | ``` 26 | 27 | Of course, you have to install [Jekyll](http://jekyllrb.com) as well. For Windows users, you have to make sure `jekyll` can be found from your environment variable `PATH`, i.e., R can call it via `system('jekyll')`. This is normally not an issue for Linux or macOS users (`gem install jekyll` is enough). 28 | 29 | ## R code chunks 30 | 31 | Now we write some R code chunks in this post. For example, 32 | 33 | ```{r} 34 | options(digits = 3) 35 | cat("hello world!") 36 | set.seed(123) 37 | (x = rnorm(40) + 10) 38 | # generate a table 39 | knitr::kable(head(mtcars)) 40 | (function() { 41 | if (TRUE) 1 + 1 # a boring comment 42 | })() 43 | names(formals(servr::jekyll)) # arguments of the jekyll() function 44 | ``` 45 | 46 | Just to test inline R expressions[^2] in **knitr**, we know the first element in `x` (created in the code chunk above) is `r x[1]`. You can certainly draw some graphs as well: 47 | 48 | [^2]: The syntax in R Markdown for inline expressions is `` ` r code` ``, where `code` is the R expression that you want to evaluate, e.g. `x[1]`. 49 | 50 | ```{r cars, fig.height=5, fig.width=7, fig.cap='A scatterplot of the cars data'} 51 | par(mar = c(4, 4, .1, .1)) 52 | plot(cars, pch = 19, col = 'red') # a scatterplot 53 | ``` 54 | 55 | ## The build script 56 | 57 | You can define all your **knitr** options and any other options in an R script. See the script [`R/build.R`](https://github.com/yihui/knitr-jekyll/blob/gh-pages/R/build.R) in the knitr-jekyll repository for an example: it calls the script [`R/build_one.R`](https://github.com/yihui/knitr-jekyll/blob/gh-pages/R/build_one.R) that will automatically set up the output renderers for **knitr**, e.g., when the Jekyll Markdown engine is `kramdown`, this script will call `knitr::render_jekyll()` so that the code chunk output will be put inside the Liquid tag `{% raw %}{% highlight lang %} {% endhighlight %}{% endraw %}`; it also sets up some **knitr** chunk and package options so that figures can be displayed correctly. For those who do not wish to store images in GIT (because normally they are binary files), you may check out how I host my images in Dropbox for this repository (see the code below `Sys.getenv('USER') == 'yihui'`). 58 | 59 | ## On the Markdown renderers 60 | 61 | Jekyll supports a number of Markdown renderers, such as kramdown, redcarpet, rdiscount, and so on. At the moment, it is a little annoying that kramdown supports LaTeX math expressions via `$$ math $$`[^4], but does not support syntax highlighting of code blocks using the three backticks syntax (you must write the awkward Liquid tags); on the other hand, redcarpet does not support LaTeX math but does support three backticks. In my opinion, all the different flavors and implementations of Markdown is the biggest problem of Markdown, since there is not an unambiguous spec for Markdown. [CommonMark](http://commonmark.org) looks like a promising project to set up a common spec for Markdown, and [Pandoc](http://pandoc.org) is a great implementation that has brought almost all the features that you may ever need in Markdown. You may find some Pandoc plugins for Jekyll by searching online. However, GitHub Pages does not support arbitrary Jekyll plugins, so you cannot just use a Pandoc plugin there, but that does not mean you cannot use Pandoc locally, nor does it mean you cannot push locally compiled HTML pages to GitHub Pages[^5]. 62 | 63 | [^4]: Unfortunately, kramdown does not support math expressions in single dollars, e.g. `$ \alpha $`. 64 | 65 | [^5]: If you choose to generate your Jekyll website locally, and push the HTML files to GitHub, you will need the file [`.nojekyll`](https://help.github.com/articles/using-jekyll-with-pages) in the root directory of your website. 66 | 67 | I'd love you to [fork](https://github.com/yihui/knitr-jekyll) this repository, make some (hopefully minor) changes, and [let me know](https://github.com/yihui/knitr-jekyll/issues) your success of using Pandoc with Jekyll. Happy hacking, and good luck! 68 | -------------------------------------------------------------------------------- /_posts/2014-09-28-jekyll-with-knitr.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: "Build Jekyll Websites with knitr and blogdown" 4 | categories: [jekyll, rstats] 5 | tags: [blogdown, knitr, servr, httpuv, websocket] 6 | --- 7 | 8 | The R package [**blogdown**](https://github.com/rstudio/blogdown) was designed mainly for the static site generator [Hugo](https://gohugo.io), but it can also be used to build websites based on Jekyll and R Markdown. The main features are: 9 | 10 | 1. R Markdown source files are re-compiled through [**knitr**](https://yihui.name/knitr/) when their corresponding Markdown output files become older[^1] than source files; 11 | 1. The web page will refresh itself automatically in the above case as well; 12 | 13 | [^1]: Determined by the modification time of files, i.e., `file.info(x)[, 'mtime']`. 14 | 15 | As a result, all you need to do is write your blog posts (R Markdown documents). You do not need to explicitly re-build the website or call **knitr** commands. Whenever you save a blog post in your text editor, the web page will be updated on the fly. This is particularly handy in the [RStudio IDE](https://www.rstudio.com), because after you run `servr::jekyll()` in the console, you can start writing or editing your R Markdown posts, and the HTML output, displayed in the RStudio viewer pane, will be in sync with your source post in the source panel (see the screenshot below). 16 | 17 | [![Jekyll with servr and knitr](//i.imgur.com/gKVGhiP.png)](//i.imgur.com/gKVGhiP.png) 18 | 19 | ## Prerequisites 20 | 21 | You must have installed the packages **blogdown** (>= 0.0.55). 22 | 23 | 24 | {% highlight r %} 25 | devtools::install_github("rstudio/blogdown") 26 | {% endhighlight %} 27 | 28 | Of course, you have to install [Jekyll](http://jekyllrb.com) as well. For Windows users, you have to make sure `jekyll` can be found from your environment variable `PATH`, i.e., R can call it via `system('jekyll')`. This is normally not an issue for Linux or macOS users (`gem install jekyll` is enough). 29 | 30 | ## R code chunks 31 | 32 | Now we write some R code chunks in this post. For example, 33 | 34 | 35 | {% highlight r %} 36 | options(digits = 3) 37 | cat("hello world!") 38 | {% endhighlight %} 39 | 40 | 41 | 42 | {% highlight text %} 43 | ## hello world! 44 | {% endhighlight %} 45 | 46 | 47 | 48 | {% highlight r %} 49 | set.seed(123) 50 | (x = rnorm(40) + 10) 51 | {% endhighlight %} 52 | 53 | 54 | 55 | {% highlight text %} 56 | ## [1] 9.44 9.77 11.56 10.07 10.13 11.72 10.46 8.73 9.31 9.55 11.22 57 | ## [12] 10.36 10.40 10.11 9.44 11.79 10.50 8.03 10.70 9.53 8.93 9.78 58 | ## [23] 8.97 9.27 9.37 8.31 10.84 10.15 8.86 11.25 10.43 9.70 10.90 59 | ## [34] 10.88 10.82 10.69 10.55 9.94 9.69 9.62 60 | {% endhighlight %} 61 | 62 | 63 | 64 | {% highlight r %} 65 | # generate a table 66 | knitr::kable(head(mtcars)) 67 | {% endhighlight %} 68 | 69 | 70 | 71 | | | mpg| cyl| disp| hp| drat| wt| qsec| vs| am| gear| carb| 72 | |:-----------------|----:|---:|----:|---:|----:|----:|----:|--:|--:|----:|----:| 73 | |Mazda RX4 | 21.0| 6| 160| 110| 3.90| 2.62| 16.5| 0| 1| 4| 4| 74 | |Mazda RX4 Wag | 21.0| 6| 160| 110| 3.90| 2.88| 17.0| 0| 1| 4| 4| 75 | |Datsun 710 | 22.8| 4| 108| 93| 3.85| 2.32| 18.6| 1| 1| 4| 1| 76 | |Hornet 4 Drive | 21.4| 6| 258| 110| 3.08| 3.21| 19.4| 1| 0| 3| 1| 77 | |Hornet Sportabout | 18.7| 8| 360| 175| 3.15| 3.44| 17.0| 0| 0| 3| 2| 78 | |Valiant | 18.1| 6| 225| 105| 2.76| 3.46| 20.2| 1| 0| 3| 1| 79 | 80 | 81 | 82 | {% highlight r %} 83 | (function() { 84 | if (TRUE) 85 | 1 + 1 # a boring comment 86 | })() 87 | {% endhighlight %} 88 | 89 | 90 | 91 | {% highlight text %} 92 | ## [1] 2 93 | {% endhighlight %} 94 | 95 | 96 | 97 | {% highlight r %} 98 | names(formals(servr::jekyll)) # arguments of the jekyll() function 99 | {% endhighlight %} 100 | 101 | 102 | 103 | {% highlight text %} 104 | ## [1] "dir" "input" "output" "script" "serve" "command" 105 | ## [7] "..." 106 | {% endhighlight %} 107 | 108 | Just to test inline R expressions[^2] in **knitr**, we know the first element in `x` (created in the code chunk above) is 9.44. You can certainly draw some graphs as well: 109 | 110 | [^2]: The syntax in R Markdown for inline expressions is `` ` r code` ``, where `code` is the R expression that you want to evaluate, e.g. `x[1]`. 111 | 112 | 113 | {% highlight r %} 114 | par(mar = c(4, 4, 0.1, 0.1)) 115 | plot(cars, pch = 19, col = "red") # a scatterplot 116 | {% endhighlight %} 117 | 118 | ![A scatterplot of the cars data](https://db.yihui.name/jekyll/2014-09-28-jekyll-with-knitr/cars-1.png) 119 | 120 | ## The build script 121 | 122 | You can define all your **knitr** options and any other options in an R script. See the script [`R/build.R`](https://github.com/yihui/knitr-jekyll/blob/gh-pages/R/build.R) in the knitr-jekyll repository for an example: it calls the script [`R/build_one.R`](https://github.com/yihui/knitr-jekyll/blob/gh-pages/R/build_one.R) that will automatically set up the output renderers for **knitr**, e.g., when the Jekyll Markdown engine is `kramdown`, this script will call `knitr::render_jekyll()` so that the code chunk output will be put inside the Liquid tag `{% raw %}{% highlight lang %} {% endhighlight %}{% endraw %}`; it also sets up some **knitr** chunk and package options so that figures can be displayed correctly. For those who do not wish to store images in GIT (because normally they are binary files), you may check out how I host my images in Dropbox for this repository (see the code below `Sys.getenv('USER') == 'yihui'`). 123 | 124 | ## On the Markdown renderers 125 | 126 | Jekyll supports a number of Markdown renderers, such as kramdown, redcarpet, rdiscount, and so on. At the moment, it is a little annoying that kramdown supports LaTeX math expressions via `$$ math $$`[^4], but does not support syntax highlighting of code blocks using the three backticks syntax (you must write the awkward Liquid tags); on the other hand, redcarpet does not support LaTeX math but does support three backticks. In my opinion, all the different flavors and implementations of Markdown is the biggest problem of Markdown, since there is not an unambiguous spec for Markdown. [CommonMark](http://commonmark.org) looks like a promising project to set up a common spec for Markdown, and [Pandoc](http://pandoc.org) is a great implementation that has brought almost all the features that you may ever need in Markdown. You may find some Pandoc plugins for Jekyll by searching online. However, GitHub Pages does not support arbitrary Jekyll plugins, so you cannot just use a Pandoc plugin there, but that does not mean you cannot use Pandoc locally, nor does it mean you cannot push locally compiled HTML pages to GitHub Pages[^5]. 127 | 128 | [^4]: Unfortunately, kramdown does not support math expressions in single dollars, e.g. `$ \alpha $`. 129 | 130 | [^5]: If you choose to generate your Jekyll website locally, and push the HTML files to GitHub, you will need the file [`.nojekyll`](https://help.github.com/articles/using-jekyll-with-pages) in the root directory of your website. 131 | 132 | I'd love you to [fork](https://github.com/yihui/knitr-jekyll) this repository, make some (hopefully minor) changes, and [let me know](https://github.com/yihui/knitr-jekyll/issues) your success of using Pandoc with Jekyll. Happy hacking, and good luck! 133 | --------------------------------------------------------------------------------