Merge pull request #109 from gvwilson/adding-jquery-debugging
authorRaniere Silva <raniere@rgaiacs.com>
Sat, 18 Feb 2017 17:01:39 +0000 (17:01 +0000)
committerGitHub <noreply@github.com>
Sat, 18 Feb 2017 17:01:39 +0000 (17:01 +0000)
Adding JQuery debugging

19 files changed:
LICENSE.md
Makefile
_includes/carpentries.html
_includes/episode_keypoints.html
_includes/episode_navbar.html
_includes/javascript.html
_includes/lesson_footer.html
_includes/main_title.html
_includes/navbar.html
_includes/syllabus.html
_includes/workshop_ad.html
_includes/workshop_footer.html
_layouts/base.html
_layouts/workshop.html
assets/css/lesson.scss
assets/img/lc-icon-black.svg [new file with mode: 0644]
bin/lesson_check.py
bin/lesson_initialize.py
favicon-lc.ico [new file with mode: 0644]

index 566ce55338b25f92a6332c505cc765c0f77faa30..179758a7e987f1a075ab394a104ba2bdf129c302 100644 (file)
@@ -73,7 +73,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 ## Trademark
 
-"Software Carpentry" an "Data Carpentry" and their respective logos
+"Software Carpentry" and "Data Carpentry" and their respective logos
 are registered trademarks of [NumFOCUS][numfocus].
 
 [cc-by-human]: https://creativecommons.org/licenses/by/4.0/
index 0f395a310aeb0d795abed5ef50a77ee745337236..b5dfe2fa455b72c0bd029122cdc129a71cbd5d66 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -9,6 +9,7 @@ DST=_site
 
 # Controls
 .PHONY : commands clean files
+.NOTPARALLEL:
 all : commands
 
 ## commands         : show all commands.
@@ -16,11 +17,11 @@ commands :
        @grep -h -E '^##' ${MAKEFILES} | sed -e 's/## //g'
 
 ## serve            : run a local server.
-serve : lesson-rmd
+serve : lesson-md
        ${JEKYLL} serve
 
 ## site             : build files but do not run a server.
-site : lesson-rmd
+site : lesson-md
        ${JEKYLL} build
 
 # repo-check        : check repository settings.
@@ -53,7 +54,7 @@ workshop-check :
 ## ----------------------------------------
 ## Commands specific to lesson websites.
 
-.PHONY : lesson-check lesson-rmd lesson-files lesson-fixme
+.PHONY : lesson-check lesson-md lesson-files lesson-fixme
 
 # RMarkdown files
 RMD_SRC = $(wildcard _episodes_rmd/??-*.Rmd)
@@ -79,13 +80,16 @@ HTML_DST = \
   $(patsubst _extras/%.md,${DST}/%/index.html,$(wildcard _extras/*.md)) \
   ${DST}/license/index.html
 
-## lesson-rmd       : convert Rmarkdown files to markdown
-lesson-rmd: $(RMD_SRC)
-       @bin/knit_lessons.sh $(RMD_SRC)
+## lesson-md        : convert Rmarkdown files to markdown
+lesson-md : ${RMD_DST}
+
+# Use of .NOTPARALLEL makes rule execute only once
+${RMD_DST} : ${RMD_SRC}
+       @bin/knit_lessons.sh ${RMD_SRC}
 
 ## lesson-check     : validate lesson Markdown.
 lesson-check :
-       @bin/lesson_check.py -s . -p ${PARSER}
+       @bin/lesson_check.py -s . -p ${PARSER} -r _includes/links.md
 
 ## lesson-check-all : validate lesson Markdown, checking line lengths and trailing whitespace.
 lesson-check-all :
index 69e2e1cc59b859a60245e02ffb3e9f3eeafd3f4e..a0e0181fc7bf984d7b95a9c0b70e1230d6e350a4 100644 (file)
@@ -1,3 +1,6 @@
+{% comment %}
+  General description of Software and Data Carpentry.
+{% endcomment %}
 <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>
     building on learners' existing knowledge to enable them to quickly apply skills learned to their own research.
   </div>
 </div>
-
-
+<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.svg" alt="Library Carpentry logo" /></a>
+  </div>
+  <div class="col-md-8">
+    Library Carpentry is made by librarians to help librarians
+    automate repetitive, boring, error-prone tasks;
+    create, maintain and analyse sustainable and reusable data;
+    work effectively with IT and systems colleagues;
+    better understand the use of software in research;
+    and much more.
+    Library Carpentry was the winner of the 2016
+    <a href="http://labs.bl.uk/British+Library+Labs+Awards">British Library Labs Teaching and Learning Award</a>.
+  </div>
+</div>
index 85378a568bca3cc554ee32a2e324e17f9382461b..2baa53ef0c4f4be23a0d291e60c44341f816be81 100644 (file)
@@ -1,3 +1,6 @@
+{% comment %}
+  Display key points for an episode.
+{% endcomment %}
 <blockquote class="keypoints">
   <h2>Key Points</h2>
   <ul>
index a789d3d9908eca4b6a61a1588259b26006c35982..1f6e033dc7825788fc159e3c5f085da20f61bef3 100644 (file)
@@ -1,26 +1,11 @@
 {% comment %}
-  Find previous and next episodes (if any).
-{% endcomment %}
-{% for episode in site.episodes  %}
-  {% if episode.url == page.url %}
-    {% unless forloop.first %}
-      {% assign prev_episode = prev %}
-    {% endunless %}
-    {% unless forloop.last %}
-      {% assign next_episode = site.episodes[forloop.index] %}
-    {% endunless %}
-  {% endif %}
-  {% assign prev = episode %}
-{% endfor %}
-
-{% comment %}
-  Display title and prev/next links.
+  Navigation bar for an episode.
 {% endcomment %}
 <div class="row">
   <div class="col-md-1">
     <h3>
-      {% if prev_episode %}
-      <a href="{{ page.root }}{{ prev_episode.url }}"><span class="glyphicon glyphicon-menu-left" aria-hidden="true"></span><span class="sr-only">previous episode</span></a>
+      {% 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>
       {% else %}
       <a href="{{ page.root }}/"><span class="glyphicon glyphicon-menu-up" aria-hidden="true"></span><span class="sr-only">lesson home</span></a>
       {% endif %}
@@ -34,8 +19,8 @@
   </div>
   <div class="col-md-1">
     <h3>
-      {% if next_episode %}
-      <a href="{{ page.root }}{{ next_episode.url }}"><span class="glyphicon glyphicon-menu-right" aria-hidden="true"></span><span class="sr-only">next episode</span></a>
+      {% 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>
       {% else %}
       <a href="{{ page.root }}/"><span class="glyphicon glyphicon-menu-up" aria-hidden="true"></span><span class="sr-only">lesson home</span></a>
       {% endif %}
index 010ae4af13d0e3b8c1c10e36d5a91527e3e51bf0..a2066c202809b465acc364e63211461f435bbc8f 100644 (file)
@@ -1,3 +1,6 @@
+{% 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>
index beef2cb38479f75cbf633044956afda873a837a5..be46c2d46d59e182b9c99d8aedfa2a4e989ccb3d 100644 (file)
@@ -1,10 +1,18 @@
+{% comment %}
+  Footer for lesson pages.
+{% endcomment %}
 <footer>
   <div class="row">
     <div class="col-md-6" align="left">
       <h4>
        Copyright &copy; 2016
-       {% if site.carpentry == "swc" %}<a href="{{ site.swc_site }}">Software Carpentry Foundation</a>{% endif %}
-       {% if site.carpentry == "dc" %}<a href="{{ site.dc_site }}">Data Carpentry</a>{% endif %}
+       {% if site.carpentry == "swc" %}
+       <a href="{{ site.swc_site }}">Software Carpentry Foundation</a>
+       {% elsif site.carpentry == "dc" %}
+       <a href="{{ site.dc_site }}">Data Carpentry</a>
+       {% elsif site.carpentry == "lc" %}
+       <a href="{{ site.lc_site }}">Library Carpentry</a>
+       {% endif %}
       </h4>
     </div>
     <div class="col-md-6" align="right">
@@ -13,7 +21,9 @@
        /
        <a href="{{ site.github.repository_url }}/blob/gh-pages/CONTRIBUTING.md">Contributing</a>
        /
-       <a href="mailto:{{ site.email }}">Contact</a>
+       <a href="{{ site.github.repository_url }}/blob/gh-pages/CITATION">Cite</a>
+       /
+       <a href="{{ site.contact }}">Contact</a>
       </h4>
     </div>
   </div>
index 60b8b06937c72e5125f392ba34c7327db92de906..8e22ced110926139022b54a201d66a46c34d491d 100644 (file)
@@ -1 +1,4 @@
+{% comment %}
+  Main title for lesson pages.
+{% endcomment %}
 <h1 class="maintitle"><a href="{{ page.root }}/">{{ site.title }}</a>{% if page.title %}: {{ page.title }}{% endif %}</h1>
index b0a2c3d83055b5105d0175106b01e85027efbd84..effea29dbd061db10d1b68d47a3a4ca82e45f4a9 100644 (file)
@@ -1,3 +1,6 @@
+{% comment %}
+  Lesson navigation bar.
+{% endcomment %}
 <nav class="navbar navbar-default">
   <div class="container-fluid">
     <div class="navbar-header">
       <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" />
       </a>
+      {% elsif page.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" />
+      </a>
       {% elsif 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" />
       <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" />
       </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" />
+      </a>
       {% endif %}
 
       {% comment %} Always show link to home page. {% endcomment %}
index bd520ed16c3c80b476b2f10de58e4970d395fbd9..0b206cc11959b0fa3cb7c93ee866b9971b6eed9c 100644 (file)
   {% assign current = site.start_time %}
 
   <table class="table table-striped">
+  <tr>
+    <td class="col-md-1"></td>
+    <td class="col-md-1"></td>
+    <td class="col-md-3"><a href="{{ page.root }}/setup">Setup</a></td>
+    <td class="col-md-7">Dowload files used on the lesson.</td>
+  </tr>
   {% for episode in site.episodes %}
     {% if episode.start %} {% comment %} Starting a new day? {% endcomment %}
       {% assign day = day | plus: 1 %}
index bffe9b9e25a088782f65e92408d5d26867b67cd8..e8e72e34db7bdb3f44955e76c7c13ec1fddbfdc1 100644 (file)
@@ -1,3 +1,6 @@
+{% comment %}
+  Advertising box at the top of a workshop website home page.
+{% endcomment %}
 <div class="jumbotron">
   <div class="row">
     <div class="col-md-10 col-md-offset-1">
index 31e5f37f36c83c88ac522c3d77b7e1d8894af690..3ae63e6dc8f48dd341532e0fd95582e72e50c6e5 100644 (file)
@@ -1,10 +1,16 @@
+{% comment %}
+  Footer for a standard workshop.
+{% endcomment %}
 <footer>
   <div class="row">
-    <div class="col-md-6" align="left">
+    <div class="col-md-4" align="left">
       <h4><a href="{{ site.swc_site }}">Software Carpentry</a></h4>
     </div>
-    <div class="col-md-6" align="right">
+    <div class="col-md-4" align="right">
       <h4><a href="{{ site.dc_site }}">Data Carpentry</a></h4>
     </div>
+    <div class="col-md-4" align="right">
+      <h4><a href="{{ site.lc_site }}">Library Carpentry</a></h4>
+    </div>
   </div>
 </footer>
index 06f316df83824a4f5baa29cb0e8972de0f441acc..365d2e50fcb0f226f37f02e54d7b6ac3503ad815 100644 (file)
     <link rel="stylesheet" type="text/css" href="{{ page.root }}/assets/css/lesson.css" />
     {% if site.carpentry == "swc" %}
     <link rel="shortcut icon" type="image/x-icon" href="/favicon-swc.ico" />
-    {% endif %}
-    {% if site.carpentry == "dc" %}
+    {% elsif site.carpentry == "dc" %}
     <link rel="shortcut icon" type="image/x-icon" href="/favicon-dc.ico" />
+    {% elsif site.carpentry == "lc" %}
+    <link rel="shortcut icon" type="image/x-icon" href="/favicon-lc.ico" />
     {% endif %}
     <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
     <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
index f29e3ce117ccce3dd5cf6837e203169c692166b0..2f4cd3040f92ddf477a539171b23fe83a06734d1 100644 (file)
     <link rel="stylesheet" type="text/css" href="{{ page.root }}/assets/css/lesson.css" />
     {% if site.carpentry == "swc" %}
     <link rel="shortcut icon" type="image/x-icon" href="/favicon-swc.ico" />
-    {% endif %}
-    {% if site.carpentry == "dc" %}
+    {% elsif site.carpentry == "dc" %}
     <link rel="shortcut icon" type="image/x-icon" href="/favicon-dc.ico" />
+    {% elsif site.carpentry == "lc" %}
+    <link rel="shortcut icon" type="image/x-icon" href="/favicon-lc.ico" />
     {% endif %}
     <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
     <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
index 752d7c9602fc36e2a3ccc0a4ce5c43f35aa0aee8..0c5f86e1fa7c8729ee91f55e362402039d65ba55 100644 (file)
@@ -100,9 +100,9 @@ $codeblock-padding: 5px !default;
 //----------------------------------------
 
 code {
-  padding: 0 0;
-  color: inherit;
-  background-color: inherit;
+  padding: 2px 5px;
+  color: #3d90d9;
+  background-color: #e7e7e7;
 }
 
 img {
@@ -133,7 +133,7 @@ div.branding {
 
 ul,
 ol {
-  padding-left: 1em;
+  padding-left: 2em;
 }
 
 span.fold-unfold {
diff --git a/assets/img/lc-icon-black.svg b/assets/img/lc-icon-black.svg
new file mode 100644 (file)
index 0000000..df71189
--- /dev/null
@@ -0,0 +1,76 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+ "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
+ width="600.000000pt" height="200.000000pt" viewBox="0 0 600.000000 200.000000"
+ preserveAspectRatio="xMidYMid meet">
+
+<g transform="translate(0.000000,200.000000) scale(0.100000,-0.100000)"
+fill="#000000" stroke="none">
+<path d="M1005 1355 l0 -325 248 0 247 0 0 83 0 82 -152 0 -153 0 0 243 0 242
+-95 0 -95 0 0 -325z"/>
+<path d="M1545 1355 l0 -325 98 0 97 0 0 325 0 325 -97 0 -98 0 0 -325z"/>
+<path d="M1835 1356 l0 -326 190 0 c105 0 208 5 229 10 81 18 128 74 133 157
+5 75 -18 120 -75 148 -23 11 -41 22 -42 25 0 3 14 11 31 19 35 15 68 77 69
+126 0 51 -40 116 -85 139 -36 19 -61 21 -245 24 l-205 3 0 -325z m326 164 c22
+-12 26 -59 7 -78 -7 -7 -40 -12 -80 -12 l-68 0 0 50 0 50 61 0 c33 0 69 -5 80
+-10z m9 -233 c17 -9 26 -22 28 -44 5 -46 -26 -63 -110 -63 l-68 0 0 60 0 60
+63 0 c34 0 73 -6 87 -13z"/>
+<path d="M2465 1355 l0 -325 96 0 95 0 -4 115 -5 115 47 0 c64 0 85 -24 122
+-137 l29 -93 103 0 c56 0 102 3 102 8 0 8 -82 202 -102 240 -7 13 -23 29 -36
+36 l-24 13 35 22 c45 27 68 78 68 146 0 91 -37 145 -120 173 -21 8 -106 12
+-220 12 l-186 0 0 -325z m309 165 c21 -8 26 -16 26 -43 0 -47 -15 -57 -87 -57
+l-63 0 0 55 0 55 49 0 c27 0 61 -4 75 -10z"/>
+<path d="M3290 1665 c0 -8 -47 -151 -105 -319 -58 -167 -105 -307 -105 -310 0
+-3 46 -6 103 -6 l103 0 14 68 15 67 100 0 100 0 15 -67 14 -68 103 0 c57 0
+103 3 103 7 0 3 -47 143 -105 310 -58 167 -105 310 -105 318 0 12 -22 15 -125
+15 -103 0 -125 -3 -125 -15z m174 -317 l6 -28 -55 0 c-30 0 -55 1 -55 3 0 2 6
+26 14 53 8 27 20 69 27 94 l12 45 22 -70 c12 -38 25 -82 29 -97z"/>
+<path d="M3805 1355 l0 -325 96 0 95 0 -4 115 -5 115 47 0 c64 0 85 -24 122
+-137 l29 -93 103 0 c56 0 102 3 102 8 0 8 -82 202 -102 240 -7 13 -23 29 -36
+36 l-24 13 35 22 c45 27 68 78 68 146 0 91 -37 145 -120 173 -21 8 -106 12
+-220 12 l-186 0 0 -325z m309 165 c21 -8 26 -16 26 -43 0 -47 -15 -57 -87 -57
+l-63 0 0 55 0 55 49 0 c27 0 61 -4 75 -10z"/>
+<path d="M4380 1674 c0 -3 13 -24 28 -47 16 -23 68 -108 115 -189 l87 -146 0
+-131 0 -131 95 0 95 0 0 130 0 130 115 192 c63 105 115 193 115 195 0 1 -49 3
+-109 3 l-108 0 -53 -107 -52 -108 -52 107 -51 107 -112 0 c-62 1 -113 -2 -113
+-5z"/>
+<path d="M357 999 c-160 -38 -254 -197 -228 -386 18 -121 73 -203 169 -250 50
+-25 68 -28 152 -28 84 0 102 3 152 28 59 29 96 68 122 131 26 62 22 73 -29 80
+-148 20 -132 22 -148 -15 -18 -45 -38 -60 -85 -66 -88 -12 -142 56 -142 177 0
+39 6 85 14 104 39 94 169 104 206 16 14 -35 12 -34 113 -15 43 8 80 15 82 15
+6 0 -12 55 -28 87 -24 46 -95 102 -151 118 -54 16 -140 18 -199 4z"/>
+<path d="M2995 1003 l-230 -3 0 -325 0 -325 253 0 252 0 0 80 0 79 -157 3
+-158 3 -3 48 -3 48 138 -2 138 -2 0 78 0 79 -138 -3 -138 -3 3 44 3 43 153 0
+152 0 0 83 c0 72 -2 82 -17 80 -10 -2 -121 -4 -248 -5z"/>
+<path d="M4000 923 l0 -83 100 0 100 0 0 -245 0 -245 98 0 97 0 -3 245 -4 245
+106 0 106 0 0 83 0 82 -300 0 -300 0 0 -82z"/>
+<path d="M990 985 c0 -8 -47 -151 -105 -319 -58 -167 -105 -307 -105 -310 0
+-3 46 -6 103 -6 l103 0 14 68 15 67 100 0 100 0 15 -67 14 -68 103 0 c57 0
+103 3 103 7 0 3 -47 143 -105 310 -58 167 -105 310 -105 318 0 12 -22 15 -125
+15 -103 0 -125 -3 -125 -15z m174 -317 l6 -28 -55 0 c-30 0 -55 1 -55 3 0 2 6
+26 14 53 8 27 20 69 27 94 l12 45 22 -70 c12 -38 25 -82 29 -97z"/>
+<path d="M1505 675 l0 -325 96 0 95 0 -4 115 -5 115 47 0 c64 0 85 -24 122
+-137 l29 -93 103 0 c56 0 102 3 102 8 0 8 -82 202 -102 240 -7 13 -23 29 -36
+36 l-24 13 35 22 c45 27 68 78 68 146 0 91 -37 145 -120 173 -21 8 -106 12
+-220 12 l-186 0 0 -325z m309 165 c21 -8 26 -16 26 -43 0 -47 -15 -57 -87 -57
+l-63 0 0 55 0 55 49 0 c27 0 61 -4 75 -10z"/>
+<path d="M2155 675 l0 -325 97 0 97 0 -6 98 -6 99 89 6 c100 7 145 19 190 53
+97 72 100 276 4 344 -57 41 -111 50 -294 50 l-171 0 0 -325z m320 159 c25 -10
+36 -49 24 -81 -14 -38 -25 -43 -96 -43 l-63 0 0 65 0 65 59 0 c33 0 67 -3 76
+-6z"/>
+<path d="M3345 675 l0 -325 95 0 95 0 -3 177 -3 178 24 -40 c13 -22 50 -80 83
+-130 34 -49 73 -111 88 -137 l28 -48 96 0 97 0 0 325 0 325 -95 0 -95 0 3
+-177 4 -178 -111 169 c-61 93 -111 173 -111 178 0 4 -44 8 -97 8 l-98 0 0
+-325z"/>
+<path d="M4655 675 l0 -325 96 0 95 0 -4 115 -5 115 47 0 c64 0 85 -24 122
+-137 l29 -93 103 0 c56 0 102 3 102 8 0 8 -82 202 -102 240 -7 13 -23 29 -36
+36 l-24 13 35 22 c45 27 68 78 68 146 0 91 -37 145 -120 173 -21 8 -106 12
+-220 12 l-186 0 0 -325z m309 165 c21 -8 26 -16 26 -43 0 -47 -15 -57 -87 -57
+l-63 0 0 55 0 55 49 0 c27 0 61 -4 75 -10z"/>
+<path d="M5230 994 c0 -3 13 -24 28 -47 16 -23 68 -108 115 -189 l87 -146 0
+-131 0 -131 95 0 95 0 0 130 0 130 115 192 c63 105 115 193 115 195 0 1 -49 3
+-109 3 l-108 0 -53 -107 -52 -108 -52 107 -51 107 -112 0 c-62 1 -113 -2 -113
+-5z"/>
+</g>
+</svg>
index 311687e92ac851ba3c5c5af2720ce45d03490902..8244222b5bd30e80516666d1dde76756c9c9300a 100755 (executable)
@@ -14,7 +14,7 @@ from optparse import OptionParser
 
 from util import Reporter, read_markdown, load_yaml, check_unwanted_files, require, IMAGE_FILE_SUFFIX
 
-__version__ = '0.2'
+__version__ = '0.3'
 
 # Where to look for source Markdown files.
 SOURCE_DIRS = ['', '_episodes', '_extras']
@@ -48,7 +48,10 @@ P_TRAILING_WHITESPACE = re.compile(r'\s+$')
 P_FIGURE_REFS = re.compile(r'<img[^>]+src="([^"]+)"[^>]*>')
 
 # Pattern to match internally-defined Markdown links.
-P_INTERNALLY_DEFINED_LINK = re.compile(r'\[[^\]]+\]\[[^\]]+\]')
+P_INTERNAL_LINK_REF = re.compile(r'\[([^\]]+)\]\[([^\]]+)\]')
+
+# Pattern to match reference links (to resolve internally-defined references).
+P_INTERNAL_LINK_DEF = re.compile(r'^\[([^\]]+)\]:\s*(.+)')
 
 # What kinds of blockquotes are allowed?
 KNOWN_BLOCKQUOTES = {
@@ -103,6 +106,8 @@ def main():
     args = parse_args()
     args.reporter = Reporter()
     check_config(args.reporter, args.source_dir)
+    args.references = read_references(args.reporter, args.reference_path)
+
     docs = read_all_markdown(args.source_dir, args.parser)
     check_fileset(args.source_dir, args.reporter, docs.keys())
     check_unwanted_files(args.source_dir, args.reporter)
@@ -110,6 +115,7 @@ def main():
         checker = create_checker(args, filename, docs[filename])
         checker.check()
     check_figures(args.source_dir, args.reporter)
+
     args.reporter.report()
 
 
@@ -126,6 +132,10 @@ def parse_args():
                       default=None,
                       dest='parser',
                       help='path to Markdown parser')
+    parser.add_option('-r', '--references',
+                      default=None,
+                      dest='reference_path',
+                      help='path to Markdown file of external references')
     parser.add_option('-s', '--source',
                       default=os.curdir,
                       dest='source_dir',
@@ -151,15 +161,46 @@ def check_config(reporter, source_dir):
     config_file = os.path.join(source_dir, '_config.yml')
     config = load_yaml(config_file)
     reporter.check_field(config_file, 'configuration', config, 'kind', 'lesson')
-    reporter.check_field(config_file, 'configuration', config, 'carpentry', ('swc', 'dc'))
+    reporter.check_field(config_file, 'configuration', config, 'carpentry', ('swc', 'dc', 'lc'))
     reporter.check_field(config_file, 'configuration', config, 'title')
-    reporter.check_field(config_file, 'configuration', config, 'email')
+    reporter.check_field(config_file, 'configuration', config, 'contact')
 
     reporter.check({'values': {'root': '..'}} in config.get('defaults', []),
                    'configuration',
                    '"root" not set to ".." in configuration')
 
 
+def read_references(reporter, ref_path):
+    """Read shared file of reference links, returning dictionary of valid references
+    {symbolic_name : URL}
+    """
+
+    result = {}
+    urls_seen = set()
+    if ref_path:
+        with open(ref_path, 'r') as reader:
+            for (num, line) in enumerate(reader):
+                line_num = num + 1
+                m = P_INTERNAL_LINK_DEF.search(line)
+                require(m,
+                        '{0}:{1} not valid reference:\n{2}'.format(ref_path, line_num, line.rstrip()))
+                name = m.group(1)
+                url = m.group(2)
+                require(name,
+                        'Empty reference at {0}:{1}'.format(ref_path, line_num))
+                reporter.check(name not in result,
+                               ref_path,
+                               'Duplicate reference {0} at line {1}',
+                               name, line_num)
+                reporter.check(url not in urls_seen,
+                               ref_path,
+                               'Duplicate definition of URL {0} at line {1}',
+                               url, line_num)
+                result[name] = url
+                urls_seen.add(url)
+    return result
+
+
 def read_all_markdown(source_dir, parser):
     """Read source files, returning
     {path : {'metadata':yaml, 'metadata_len':N, 'text':text, 'lines':[(i, line, len)], 'doc':doc}}
@@ -274,7 +315,7 @@ class CheckBase(object):
 
 
     def check(self):
-        """Run tests on metadata."""
+        """Run tests."""
 
         self.check_metadata()
         self.check_line_lengths()
@@ -342,17 +383,16 @@ class CheckBase(object):
     def check_defined_link_references(self):
         """Check that defined links resolve in the file.
 
-        Internally-defined links match the pattern [text][label].  If
-        the label contains '{{...}}', it is hopefully a references to
-        a configuration value - we should check that, but don't right
-        now.
+        Internally-defined links match the pattern [text][label].
         """
 
         result = set()
         for node in self.find_all(self.doc, {'type' : 'text'}):
-            for match in P_INTERNALLY_DEFINED_LINK.findall(node['value']):
-                if '{{' not in match:
-                    result.add(match)
+            for match in P_INTERNAL_LINK_REF.findall(node['value']):
+                text = match[0]
+                link = match[1]
+                if link not in self.args.references:
+                    result.add('"{0}"=>"{1}"'.format(text, link))
         self.reporter.check(not result,
                             self.filename,
                             'Internally-defined links may be missing definitions: {0}',
@@ -441,6 +481,14 @@ class CheckEpisode(CheckBase):
     def __init__(self, args, filename, metadata, metadata_len, text, lines, doc):
         super(CheckEpisode, self).__init__(args, filename, metadata, metadata_len, text, lines, doc)
 
+
+    def check(self):
+        """Run extra tests."""
+
+        super(CheckEpisode, self).check()
+        self.check_reference_inclusion()
+
+
     def check_metadata(self):
         super(CheckEpisode, self).check_metadata()
         if self.metadata:
@@ -467,6 +515,26 @@ class CheckEpisode(CheckBase):
                                   name, type(self.metadata[name]), type_)
 
 
+    def check_reference_inclusion(self):
+        """Check that links file has been included."""
+
+        if not self.args.reference_path:
+            return
+
+        for (i, last_line, line_len) in reversed(self.lines):
+            if last_line:
+                break
+
+        require(last_line,
+                'No non-empty lines in {0}'.format(self.filename))
+
+        include_filename = os.path.split(self.args.reference_path)[-1]
+        if include_filename not in last_line:
+            self.reporter.add(self.filename,
+                              'episode does not include "{0}"',
+                              include_filename)
+
+
 class CheckReference(CheckBase):
     """Check the reference page."""
 
index e0c2881bf80d35a1a0550ec29b9c497da2d90ad9..540bb08c83724f964570874b1b6e796640ac99d9 100755 (executable)
@@ -158,7 +158,6 @@ You can also [reach us by email][contact].
 [dc-lessons]: http://datacarpentry.org/lessons/
 [dc-site]: http://datacarpentry.org/
 [discuss-list]: http://lists.software-carpentry.org/listinfo/discuss
-[example-site]: https://swcarpentry.github.io/lesson-example/
 [github]: http://github.com
 [github-flow]: https://guides.github.com/introduction/flow/
 [github-join]: https://github.com/join
@@ -175,14 +174,16 @@ ROOT_CONFIG_YML = '''\
 # Values for this lesson.
 #------------------------------------------------------------
 
-# Which carpentry is this ("swc" or "dc")?
+# Which carpentry is this ("swc", "dc", or "lc")?
 carpentry: "swc"
 
 # Overall title for pages.
 title: "Lesson Title"
 
-# Contact email address.
-email: lessons@software-carpentry.org
+# Contact.  This *must* include the protocol: if it's an email
+# address, it must look like "mailto:lessons@software-carpentry.org",
+# or if it's a URL, "https://gitter.im/username/ProjectName".
+contact: "mailto:lessons@software-carpentry.org"
 
 #------------------------------------------------------------
 # Generic settings (should not need to change).
@@ -201,6 +202,7 @@ dc_site: "http://datacarpentry.org"
 swc_github: "https://github.com/swcarpentry"
 swc_site: "https://software-carpentry.org"
 swc_pages: "https://swcarpentry.github.io"
+lc_site: "http://librarycarpentry.github.io/"
 template_repo: "https://github.com/swcarpentry/styles"
 example_repo: "https://github.com/swcarpentry/lesson-example"
 example_site: "https://swcarpentry.github.com/lesson-example"
diff --git a/favicon-lc.ico b/favicon-lc.ico
new file mode 100644 (file)
index 0000000..f4f3c93
Binary files /dev/null and b/favicon-lc.ico differ