Merge pull request #345 from maxim-belkin/margin0
authorRaniere Silva <raniere@rgaiacs.com>
Fri, 24 Aug 2018 15:41:47 +0000 (16:41 +0100)
committerGitHub <noreply@github.com>
Fri, 24 Aug 2018 15:41:47 +0000 (16:41 +0100)
Code/callout/prereq/etc blocks: set left and right margins to 0

16 files changed:
_includes/all_keypoints.html
_includes/base_path.html [new file with mode: 0644]
_includes/carpentries.html
_includes/episode_navbar.html
_includes/favicons.html
_includes/javascript.html
_includes/main_title.html
_includes/navbar.html
_includes/syllabus.html
_layouts/base.html
_layouts/workshop.html
assets/css/lesson.scss
bin/boilerplate/_extras/figures.md
bin/boilerplate/aio.md
bin/chunk-options.R
bin/generate_md_episodes.R

index 8563df340a8df11ffb4a23e27c15f31be15ed56b..2af59005fae82283f72968406e61dea5e9c87b9b 100644 (file)
@@ -7,7 +7,7 @@
   {% unless episode.break %}
     <tr>
       <td class="col-md-3">
-        <a href="{{ page.root }}{{ episode.url }}">{{ episode.title }}</a>
+        <a href="{{ relative_root_path }}{{ episode.url }}">{{ episode.title }}</a>
       </td>
       <td class="col-md-9">
         <ul>
diff --git a/_includes/base_path.html b/_includes/base_path.html
new file mode 100644 (file)
index 0000000..0acf4b9
--- /dev/null
@@ -0,0 +1,27 @@
+{% comment %}
+This is adapated from: https://ricostacruz.com/til/relative-paths-in-jekyll
+
+`page.url` gives the URL of the current page with a leading /:
+
+- when the URL ends with the extension (e.g., /foo/bar.html) then we can get
+  the depth by counting the number of / and remove - 1
+- when the URL ends with a / (e.g. /foo/bar/) then the number / gives the depth
+  directly
+{% endcomment %}
+
+{% assign relative_root_path = '' %}
+
+{% assign last_char = page.url | slice: -1 %}
+
+{% if last_char == "/"}
+{% assign offset = 0 %}
+{% else %}
+{% assign offset = 1 %}
+{% endif %}
+
+{% assign depth = page.url | split: '/' | size | minus: offset %}
+{% if    depth <= 1 %}{% assign relative_root_path = '.' %}
+{% elsif depth == 2 %}{% assign relative_root_path = '..' %}
+{% elsif depth == 3 %}{% assign relative_root_path = '../..' %}
+{% elsif depth == 4 %}{% assign relative_root_path = '../../..' %}
+{% endif %}
index 0a6953df9860e0025ce8bf0e093d2cfe8c87643c..37cd16e04d394ad90c2d70554b191f90ad632668 100644 (file)
@@ -3,7 +3,7 @@
 {% endcomment %}
 <div class="row">
   <div class="col-md-2" align="center">
-    <a href="{{ site.carpentries_site }}"><img src="{{ page.root }}/assets/img/cp-logo-blue.svg" alt="The Carpentries logo" /></a>
+    <a href="{{ site.carpentries_site }}"><img src="{{ relative_root_path }}/assets/img/cp-logo-blue.svg" alt="The Carpentries logo" /></a>
   </div>
   <div class="col-md-8">
     <p><a href="{{ site.carpentries_site }}">The Carpentries</a> comprises
@@ -23,7 +23,7 @@
 </div>
 <div class="row">
   <div class="col-md-2" align="center">
-    <a href="{{ site.swc_site }}"><img src="{{ page.root }}/assets/img/swc-icon-blue.svg" alt="Software Carpentry logo" /></a>
+    <a href="{{ site.swc_site }}"><img src="{{ relative_root_path }}/assets/img/swc-icon-blue.svg" alt="Software Carpentry logo" /></a>
   </div>
   <div class="col-md-8">
      <p>Since 1998, <a href="{{ site.swc_site }}">Software Carpentry</a> has
@@ -38,7 +38,7 @@
 <br/>
 <div class="row">
   <div class="col-md-2" align="center">
-    <a href="{{ site.dc_site }}"><img src="{{ page.root }}/assets/img/dc-icon-black.svg" alt="Data Carpentry logo" /></a>
+    <a href="{{ site.dc_site }}"><img src="{{ relative_root_path }}/assets/img/dc-icon-black.svg" alt="Data Carpentry logo" /></a>
   </div>
   <div class="col-md-8">
     <p><a href="{{ site.dc_site }}">Data Carpentry</a> develops and teaches
@@ -53,7 +53,7 @@
 <br/>
 <div class="row">
   <div class="col-md-2" align="center">
-    <a href="{{ site.lc_site }}"><img src="{{ page.root }}/assets/img/lc-icon-black.png" alt="Library Carpentry logo" /></a>
+    <a href="{{ site.lc_site }}"><img src="{{ relative_root_path }}/assets/img/lc-icon-black.png" alt="Library Carpentry logo" /></a>
   </div>
   <div class="col-md-8">
     <p><a href="{{ site.lc_site }}">Library Carpentry</a> is in discussions with
index c2bc80e84105e5d6c2bef7c830e23ea01f264c02..ea368eba204cfc0dc00dedd9176104a0f89d4c3b 100644 (file)
@@ -1,27 +1,35 @@
+{% comment %}
+For some reason, the relative_root_path seems out of scope in this file, so we
+need to re-assign it here
+{% endcomment %}
+
+{% include base_path.html %}
+
 {% comment %}
   Navigation bar for an episode.
 {% endcomment %}
+
 <div class="row">
   <div class="col-xs-1">
     <h3 class="text-left">
       {% if page.previous.url %}
-      <a href="{{ page.root }}{{ page.previous.url }}"><span class="glyphicon glyphicon-menu-left" aria-hidden="true"></span><span class="sr-only">previous episode</span></a>
+      <a href="{{ relative_root_path }}{{ page.previous.url }}"><span class="glyphicon glyphicon-menu-left" aria-hidden="true"></span><span class="sr-only">previous episode</span></a>
       {% else %}
-      <a href="{{ page.root }}/"><span class="glyphicon glyphicon-menu-up" aria-hidden="true"></span><span class="sr-only">lesson home</span></a>
+      <a href="{{ relative_root_path }}/"><span class="glyphicon glyphicon-menu-up" aria-hidden="true"></span><span class="sr-only">lesson home</span></a>
       {% endif %}
     </h3>
   </div>
   <div class="col-xs-10">
     {% if include.episode_navbar_title %}
-    <h3 class="maintitle"><a href="{{ page.root }}/">{{ site.title }}</a></h3>
+    <h3 class="maintitle"><a href="{{ relative_root_path }}/">{{ site.title }}</a></h3>
     {% endif %}
   </div>
   <div class="col-xs-1">
     <h3 class="text-right">
       {% if page.next.url %}
-      <a href="{{ page.root }}{{ page.next.url }}"><span class="glyphicon glyphicon-menu-right" aria-hidden="true"></span><span class="sr-only">next episode</span></a>
+      <a href="{{ relative_root_path }}{{ page.next.url }}"><span class="glyphicon glyphicon-menu-right" aria-hidden="true"></span><span class="sr-only">next episode</span></a>
       {% else %}
-      <a href="{{ page.root }}/"><span class="glyphicon glyphicon-menu-up" aria-hidden="true"></span><span class="sr-only">lesson home</span></a>
+      <a href="{{ relative_root_path }}/"><span class="glyphicon glyphicon-menu-up" aria-hidden="true"></span><span class="sr-only">lesson home</span></a>
       {% endif %}
     </h3>
   </div>
index 4ea6742d530460e08517cfabbd912c69f937b1d4..8a50b4d911591886ed90c11bb23a5cee5cfd7d6b 100644 (file)
@@ -1,4 +1,4 @@
-{% assign favicon_url = site.baseurl | append: '/assets/favicons/' | append: site.carpentry | prepend: site.url %}
+{% assign favicon_url = relative_root_path | append: '/assets/favicons/' | append: site.carpentry  %}
 
 {% if site.carpentry == 'swc' %}
 {% assign carpentry = 'Software Carpentry' %}
index a2066c202809b465acc364e63211461f435bbc8f..ac8f16d0e04c6b79976ee5e533340e82f123d0e4 100644 (file)
@@ -1,9 +1,9 @@
 {% comment %}
   Javascript used in lesson and workshop pages.
 {% endcomment %}
-<script src="{{ page.root }}/assets/js/jquery.min.js"></script>
-<script src="{{ page.root }}/assets/js/bootstrap.min.js"></script>
-<script src="{{ page.root }}/assets/js/lesson.js"></script>
+<script src="{{ relative_root_path }}/assets/js/jquery.min.js"></script>
+<script src="{{ relative_root_path }}/assets/js/bootstrap.min.js"></script>
+<script src="{{ relative_root_path }}/assets/js/lesson.js"></script>
 <script>
   (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
   (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
index d007abae203592c924f78bd178f2d22538214e07..592f880b04d7722eda544cdc07abecd9de304c99 100644 (file)
@@ -1,4 +1,4 @@
 {% comment %}
   Main title for lesson pages.
 {% endcomment %}
-<h1 class="maintitle"><a href="{{ page.root }}{% link index.md %}">{{ site.title }}</a>{% if page.title %}: {{ page.title }}{% endif %}</h1>
+<h1 class="maintitle"><a href="{{ relative_root_path }}{% link index.md %}">{{ site.title }}</a>{% if page.title %}: {{ page.title }}{% endif %}</h1>
index 868bce8dac32f877df39aa7a55d6337f09748b85..529a83c63979c6ae4c05b6c06bc30dff2268d4f2 100644 (file)
       {% comment %} Select what logo to display. {% endcomment %}
       {% if site.carpentry == "swc" %}
       <a href="{{ site.swc_site }}" class="pull-left">
-        <img class="navbar-logo" src="{{ page.root }}/assets/img/swc-icon-blue.svg" alt="Software Carpentry logo" />
+        <img class="navbar-logo" src="{{ relative_root_path }}{% link /assets/img/swc-icon-blue.svg %}" alt="Software Carpentry logo" />
       </a>
       {% elsif site.carpentry == "dc" %}
       <a href="{{ site.dc_site }}" class="pull-left">
-        <img class="navbar-logo" src="{{ page.root }}/assets/img/dc-icon-black.svg" alt="Data Carpentry logo" />
+        <img class="navbar-logo" src="{{ relative_root_path }}{% link /assets/img/dc-icon-black.svg %}" alt="Data Carpentry logo" />
       </a>
       {% elsif site.carpentry == "lc" %}
       <a href="{{ site.lc_site }}" class="pull-left">
-        <img class="navbar-logo" src="{{ page.root }}/assets/img/lc-icon-black.svg" alt="Library Carpentry logo" />
+        <img class="navbar-logo" src="{{ relative_root_path }}{% link /assets/img/lc-icon-black.svg %}" alt="Library Carpentry logo" />
       </a>
       {% elsif site.carpentry == "cp" %}
       <a href="{{ site.carpentries_site }}" class="pull-left">
-        <img class="navbar-logo" src="{{ page.root }}/assets/img/cp-logo-blue.svg" alt="The Carpentries logo" />
+        <img class="navbar-logo" src="{{ relative_root_path }}{% link /assets/img/cp-logo-blue.svg %}" alt="The Carpentries logo" />
       </a>
       {% endif %}
 
       {% comment %} Always show link to home page. {% endcomment %}
-      <a class="navbar-brand" href="{{ page.root }}{% link index.md %}">Home</a>
+      <a class="navbar-brand" href="{{ relative_root_path }}{% link index.md %}">Home</a>
 
     </div>
     <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
       <ul class="nav navbar-nav">
 
        {% comment %} Always show code of conduct. {% endcomment %}
-        <li><a href="{{ page.root }}{% link CODE_OF_CONDUCT.md %}">Code of Conduct</a></li>
+        <li><a href="{{ relative_root_path }}{% link CODE_OF_CONDUCT.md %}">Code of Conduct</a></li>
 
         {% if site.kind == "lesson" %}
        {% comment %} Show setup instructions. {% endcomment %}
-        <li><a href="{{ page.root }}{% link setup.md %}">Setup</a></li>
+        <li><a href="{{ relative_root_path }}{% link setup.md %}">Setup</a></li>
 
         {% comment %} Show lesson episodes for lessons. {% endcomment %}
         <li class="dropdown">
-          <a href="{{ page.root }}/" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Episodes <span class="caret"></span></a>
+          <a href="{{ relative_root_path }}/" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Episodes <span class="caret"></span></a>
           <ul class="dropdown-menu">
             {% for episode in site.episodes %}
-            <li><a href="{{ page.root }}{{ episode.url }}">{{ episode.title }}</a></li>
+            <li><a href="{{ relative_root_path }}{{ episode.url }}">{{ episode.title }}</a></li>
             {% endfor %}
            <li role="separator" class="divider"></li>
-            <li><a href="{{ page.root }}{% link aio.md %}">All in one page (Beta)</a></li>
+            <li><a href="{{ relative_root_path }}{% link aio.md %}">All in one page (Beta)</a></li>
           </ul>
         </li>
        {% endif %}
        {% comment %} Show extras for lessons or if this is the main workshop-template repo (where they contain documentation). {% endcomment %}
        {% if site.kind == "lesson" %}
         <li class="dropdown">
-          <a href="{{ page.root }}/" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Extras <span class="caret"></span></a>
+          <a href="{{ relative_root_path }}/" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Extras <span class="caret"></span></a>
           <ul class="dropdown-menu">
-            <li><a href="{{ page.root }}{% link reference.md %}">Reference</a></li>
+            <li><a href="{{ relative_root_path }}{% link reference.md %}">Reference</a></li>
             {% for extra in site.extras %}
-            <li><a href="{{ page.root }}{{ extra.url }}">{{ extra.title }}</a></li>
+            <li><a href="{{ relative_root_path }}{{ extra.url }}">{{ extra.title }}</a></li>
             {% endfor %}
           </ul>
         </li>
        {% endif %}
 
        {% comment %} Always show license. {% endcomment %}
-        <li><a href="{{ page.root }}{% link LICENSE.md %}">License</a></li>
+        <li><a href="{{ relative_root_path }}{% link LICENSE.md %}">License</a></li>
        {% if page.source %}
        {% if page.source == "Rmd" %}
        <li><a href="{{site.github.repository_url}}/edit/gh-pages/{{page.path|replace: "_episodes", "_episodes_rmd" | replace: ".md", ".Rmd"}}">Improve this page <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span></a></li>
index 92270f835e6f799412411a2aeda03a5b26e94c2a..2bc607eca9e42c6c63cfd30af653c34c3a5647a2 100644 (file)
@@ -1,3 +1,5 @@
+{% include base_path.html %}
+
 {% comment %}
   Display syllabus in tabular form.
   Days are displayed if at least one episode has 'start = true'.
@@ -17,7 +19,7 @@
   <tr>
     {% if multiday %}<td class="col-md-1"></td>{% endif %}
     <td class="{% if multiday %}col-md-1{% else %}col-md-2{% endif %}"></td>
-    <td class="col-md-3"><a href="{{ page.root }}{% link setup.md %}">Setup</a></td>
+    <td class="col-md-3"><a href="{{ relative_root_path }}{% link setup.md %}">Setup</a></td>
     <td class="col-md-7">Download files required for the lesson</td>
   </tr>
   {% for episode in site.episodes %}
@@ -42,7 +44,7 @@
       <td class="{% if multiday %}col-md-1{% else %}col-md-2{% endif %}">{% if hours < 10 %}0{% endif %}{{ hours }}:{% if minutes < 10 %}0{% endif %}{{ minutes }}</td>
       <td class="col-md-3">
         {% assign lesson_number = lesson_number | plus: 1 %}
-       {{ lesson_number }}. <a href="{{ page.root }}{{ episode.url }}">{{ episode.title }}</a>
+       {{ lesson_number }}. <a href="{{ relative_root_path }}{{ episode.url }}">{{ episode.title }}</a>
       </td>
       <td class="col-md-7">
         {% if episode.break %}
index d8fefd6b1c93db26d5283550659beac2c7eba053..a083eb1f7bd8658f4f93d2bc5c3ba71ab7ac4c5d 100644 (file)
@@ -1,6 +1,5 @@
 ---
 ---
-
 {% comment %}
 When rendering websites locally, `site.github.url` doesn't get resolved
 properly unless GitHub PAT are set up and available in the environment.
@@ -16,6 +15,8 @@ GitHub where `site.github.url` will be defined.
 {% assign search_domain_url = site.github.url  %}
 {% endif %}
 
+{% include base_path.html %}
+
 <!doctype html>
 <html lang="en">
   <head>
@@ -25,10 +26,10 @@ GitHub where `site.github.url` will be defined.
     <meta name="viewport" content="width=device-width, initial-scale=1">
     <!-- meta "search-domain" used for google site search function google_search() -->
     <meta name="search-domain" value="{{ search_domain_url }}">
-    <link rel="stylesheet" type="text/css" href="{{ page.root }}/assets/css/bootstrap.css" />
-    <link rel="stylesheet" type="text/css" href="{{ page.root }}/assets/css/bootstrap-theme.css" />
-    <link rel="stylesheet" type="text/css" href="{{ page.root }}/assets/css/lesson.css" />
-    <link rel="stylesheet" type="text/css" href="{{ page.root }}/assets/css/syntax.css" />
+    <link rel="stylesheet" type="text/css" href="{{ relative_root_path }}/assets/css/bootstrap.css" />
+    <link rel="stylesheet" type="text/css" href="{{ relative_root_path }}/assets/css/bootstrap-theme.css" />
+    <link rel="stylesheet" type="text/css" href="{{ relative_root_path }}/assets/css/lesson.css" />
+    <link rel="stylesheet" type="text/css" href="{{ relative_root_path }}/assets/css/syntax.css" />
 
     {% include favicons.html %}
 
index 3525da390ded29b56c2c7270038f2a690f553384..1143b6b287207eb5a703072f13da8b8289da93cd 100644 (file)
     <meta http-equiv="X-UA-Compatible" content="IE=edge">
     <meta http-equiv="last-modified" content="{{ site.time }}">
     <meta name="viewport" content="width=device-width, initial-scale=1">
-    <link rel="stylesheet" type="text/css" href="{{ page.root }}/assets/css/bootstrap.css" />
-    <link rel="stylesheet" type="text/css" href="{{ page.root }}/assets/css/bootstrap-theme.css" />
-    <link rel="stylesheet" type="text/css" href="{{ page.root }}/assets/css/lesson.css" />
+    <link rel="stylesheet" type="text/css" href="{{ relative_root_path }}/assets/css/bootstrap.css" />
+
+    <link rel="stylesheet" type="text/css" href="{{ relative_root_path }}/assets/css/bootstrap-theme.css" />
+    <link rel="stylesheet" type="text/css" href="{{ relative_root_path }}/assets/css/lesson.css" />
 
     {% include favicons.html %}
 
index 20d1cde239ca5cbd3248d79585924d131ec028ac..522e4fde6b0aa1910a54053926d6ef220f064e7e 100644 (file)
@@ -163,6 +163,8 @@ article h3 { margin: 40px 0 16px; }
 // Miscellaneous.
 //----------------------------------------
 
+.figures h2 { margin-top: 100px; }
+
 .maintitle {
   text-align: center;
 }
index c1511e8ca174c9a2da451276c86e9864f87e1e82..7287088ba4522b8c08a2c6fab2266727a806247c 100644 (file)
@@ -5,26 +5,51 @@ title: Figures
   window.onload = function() {
     var lesson_episodes = [
     {% for episode in site.episodes %}
-    "{{ episode.url}}"{% unless forloop.last %},{% endunless %}
+    "{{ episode.url }}"{% unless forloop.last %},{% endunless %}
     {% endfor %}
     ];
+
     var xmlHttp = [];  /* Required since we are going to query every episode. */
     for (i=0; i < lesson_episodes.length; i++) {
+
       xmlHttp[i] = new XMLHttpRequest();
       xmlHttp[i].episode = lesson_episodes[i];  /* To enable use this later. */
       xmlHttp[i].onreadystatechange = function() {
+
         if (this.readyState == 4 && this.status == 200) {
-          var article_here = document.getElementById(this.episode);
           var parser = new DOMParser();
           var htmlDoc = parser.parseFromString(this.responseText,"text/html");
           var htmlDocArticle = htmlDoc.getElementsByTagName("article")[0];
-          article_here.appendChild(htmlDocArticle.getElementsByTagName("h1")[0]);
-          for (let image of htmlDocArticle.getElementsByTagName("img")) {
-            article_here.appendChild(image);
+
+          var article_here = document.getElementById(this.episode);
+          var images = htmlDocArticle.getElementsByTagName("img");
+
+          if (images.length > 0) {
+            var h1text = htmlDocArticle.getElementsByTagName("h1")[0].innerHTML;
+
+            var htitle = document.createElement('h2');
+            htitle.innerHTML = h1text;
+            article_here.appendChild(htitle);
+
+            var image_num = 0;
+            for (let image of images) {
+              image_num++;
+
+              var title = document.createElement('p');
+              title.innerHTML = "<strong>Figure " + image_num + ".</strong> " + image.alt;
+              article_here.appendChild(title);
+
+              article_here.appendChild(image.cloneNode(false));
+
+              if (image_num < images.length) {
+                var hr = document.createElement('hr');
+                article_here.appendChild(hr);
+              }
+            }
           }
         }
       }
-      episode_url = "{{ page.root }}" + lesson_episodes[i];
+      episode_url = "{{ relative_root_path }}" + lesson_episodes[i];
       xmlHttp[i].open("GET", episode_url);
       xmlHttp[i].send(null);
     }
@@ -34,7 +59,7 @@ title: Figures
 Create anchor for each one of the episodes.
 {% endcomment %}
 {% for episode in site.episodes %}
-<article id="{{ episode.url }}"></article>
+<article id="{{ episode.url }}" class="figures"></article>
 {% endfor %}
 
 {% include links.md %}
index a418f3b45ee2c3a59950a49e5f5434cbd7dada46..ec4c6a4021108457e9a14eede6ee1bda04d9c51a 100644 (file)
@@ -20,7 +20,7 @@
         article_here.innerHTML = htmlDocArticle.innerHTML;
         }
       }
-      episode_url = "{{ page.root }}" + lesson_episodes[i];
+      episode_url = "{{ relative_root_path }}" + lesson_episodes[i];
       xmlHttp[i].open("GET", episode_url);
       xmlHttp[i].send(null);
     }
index f9435842034b264d147ef9549eab7ed94b595dff..8ac95729372ae9cf1ddb8a4aa32ee1cc608ec84d 100644 (file)
@@ -29,7 +29,9 @@ knitr_fig_path <- function(prefix) {
 
 opts_chunk$set(tidy = FALSE, results = "markup", comment = NA,
                fig.align = "center", fig.path = "fig/rmd-",
-               fig.process = fix_fig_path)
+               fig.process = fix_fig_path,
+               fig.width = 8.5, fig.height = 8.5,
+               fig.retina = 2)
 
 # The hooks below add html tags to the code chunks and their output so that they
 # are properly formatted when the site is built.
@@ -43,7 +45,7 @@ hook_in <- function(x, options) {
 hook_out <- function(x, options) {
   x <- gsub("\n$", "", x)
   stringr::str_c("\n\n~~~\n",
-                   paste0(x, collapse="\n"),
+                 paste0(x, collapse="\n"),
                  "\n~~~\n{: .output}\n\n")
 }
 
index 2f4e1f93e063fa5789ce0a3b45a5092b13f85fa3..e2592c22ea4b4e2f3318c08376abfb52f0f2eb77 100644 (file)
@@ -1,40 +1,44 @@
 generate_md_episodes <- function() {
 
-    library("methods")
-    
-    if (require("knitr") && packageVersion("knitr") < '1.9.19')
-        stop("knitr must be version 1.9.20 or higher")
-
-    if (!require("stringr"))
-        stop("The package stringr is required for generating the lessons.")
-
-    if (require("checkpoint") && packageVersion("checkpoint") >=  '0.4.0') {
-        required_pkgs <-
-             checkpoint:::scanForPackages(project = "_episodes_rmd",
-                                          verbose=FALSE, use.knitr = TRUE)$pkgs
-    } else {
-        stop("The checkpoint package (>= 0.4.0) is required to build the lessons.")
-    }
-
-    missing_pkgs <- required_pkgs[!(required_pkgs %in% rownames(installed.packages()))]
-
-    if (length(missing_pkgs)) {
-        message("Installing missing required packages: ",
-                paste(missing_pkgs, collapse=", "))
-        install.packages(missing_pkgs)
-    }
-
-    ## get the Rmd file to process from the command line, and generate the path for their respective outputs
-    args  <- commandArgs(trailingOnly = TRUE)
-    if (!identical(length(args), 2L)) {
-      stop("input and output file must be passed to the script")
-    }
-    
-    src_rmd <- args[1]
-    dest_md <- args[2]
-
-    ## knit the Rmd into markdown
-    knitr::knit(src_rmd, output = dest_md)
+  library("methods")
+  
+  if (!require("remotes")) {
+    stop("The `remotes` package is needed.")
+  }
+
+  if (!require("requirements")) {
+    remotes::install_github("hadley/requirements")
+  }
+
+  required_pkgs <- unique(c(
+    ## Packages for episodes
+    requirements:::req_dir("_episodes_rmd"),
+    ## Pacakges for tools
+    requirements:::req_dir("bin")
+  ))
+
+  missing_pkgs <- setdiff(required_pkgs, rownames(installed.packages()))
+
+  if (length(missing_pkgs)) {
+    message("Installing missing required packages: ",
+            paste(missing_pkgs, collapse=", "))
+    install.packages(missing_pkgs)
+  }
+
+  if (require("knitr") && packageVersion("knitr") < '1.9.19')
+    stop("knitr must be version 1.9.20 or higher")
+
+  ## get the Rmd file to process from the command line, and generate the path for their respective outputs
+  args  <- commandArgs(trailingOnly = TRUE)
+  if (!identical(length(args), 2L)) {
+    stop("input and output file must be passed to the script")
+  }
+
+  src_rmd <- args[1]
+  dest_md <- args[2]
+
+  ## knit the Rmd into markdown
+  knitr::knit(src_rmd, output = dest_md)
 
     # Read the generated md files and add comments advising not to edit them
     vapply(dest_md, function(y) {
@@ -43,7 +47,7 @@ generate_md_episodes <- function() {
       if (mdfile[1] != "---")
         stop("Input file does not have a valid header")
       mdfile <- append(mdfile, "# Please do not edit this file directly; it is auto generated.", after = 1)
-      mdfile <- append(mdfile, paste("# Instead, please edit", 
+      mdfile <- append(mdfile, paste("# Instead, please edit",
                                      basename(y), "in _episodes_rmd/"), after = 2)
       writeLines(mdfile, con)
       close(con)