[cc-by-human]: https://creativecommons.org/licenses/by/4.0/
[cc-by-legal]: https://creativecommons.org/licenses/by/4.0/legalcode
-[mit-license]: http://opensource.org/licenses/mit-license.html
-[numfocus]: http://numfocus.org/
-[osi]: http://opensource.org
+[mit-license]: https://opensource.org/licenses/mit-license.html
+[numfocus]: https://numfocus.org/
+[osi]: https://opensource.org
<li>Plain text formats</li>
<li>Naming files</li>
<li>Regular expressions</li>
- <li><a href="http://data-lessons.github.io/library-data-intro/reference/">Reference...</a></li>
+ <li><a href="https://data-lessons.github.io/library-data-intro/reference/">Reference...</a></li>
</ul>
</div>
<div class="col-md-6">
<li>Counting and sorting contents in files</li>
<li>Pipes and redirection</li>
<li>Mining or searching in files</li>
- <li><a href="http://data-lessons.github.io/library-shell/reference/">Reference...</a></li>
+ <li><a href="https://data-lessons.github.io/library-shell/reference/">Reference...</a></li>
</ul>
</div>
<li>Viewing state changes with <code>status</code></li>
<li>Working on the web: <code>clone</code>, <code>pull</code>, <code>push</code>, ...</li>
<li>Where to host work, and why</li>
- <li><a href="http://data-lessons.github.io/library-git/reference">Reference...</a></li>
+ <li><a href="https://data-lessons.github.io/library-git/reference">Reference...</a></li>
</ul>
</div>
<div class="col-md-6">
<li>Importing data</li>
<li>Basic functions</li>
<li>Advanced Functions</li>
- <li><a href="http://data-lessons.github.io/library-openrefine/reference">Reference...</a></li>
+ <li><a href="https://data-lessons.github.io/library-openrefine/reference">Reference...</a></li>
</ul>
</div>
</div>
<li>Filtering with <code>where</code></li>
<li>Combining values using aggregation</li>
<li>Combining information from multiple tables using <code>join</code></li>
- <li><a href="http://data-lessons.github.io//library-sql/reference/">Reference...</a></li>
+ <li><a href="https://data-lessons.github.io//library-sql/reference/">Reference...</a></li>
</ul>
</div>
</div>
[cc-by-human]: https://creativecommons.org/licenses/by/4.0/
[cc-by-legal]: https://creativecommons.org/licenses/by/4.0/legalcode
-[concept-maps]: http://carpentries.github.io/instructor-training/05-memory/
+[concept-maps]: https://carpentries.github.io/instructor-training/05-memory/
[email]: mailto:lessons@software-carpentry.org
-[contrib-covenant]: http://contributor-covenant.org/
+[contrib-covenant]: https://contributor-covenant.org/
[contributing]: {{ site.github.repository_url }}/blob/gh-pages/CONTRIBUTING.md
[cran-checkpoint]: https://cran.r-project.org/web/packages/checkpoint/index.html
[cran-knitr]: https://cran.r-project.org/web/packages/knitr/index.html
[jekyll-windows]: http://jekyll-windows.juthilo.com/
[jekyll]: https://jekyllrb.com/
[jupyter]: https://jupyter.org/
-[mit-license]: http://opensource.org/licenses/mit-license.html
+[mit-license]: https://opensource.org/licenses/mit-license.html
[morea]: https://morea-framework.github.io/
-[numfocus]: http://numfocus.org/
-[osi]: http://opensource.org
+[numfocus]: https://numfocus.org/
+[osi]: https://opensource.org
[pandoc]: https://pandoc.org/
[paper-now]: https://github.com/PeerJ/paper-now
[python-gapminder]: https://swcarpentry.github.io/python-novice-gapminder/
[r-markdown]: http://rmarkdown.rstudio.com/
[rstudio]: https://www.rstudio.com/
[ruby-install-guide]: https://www.ruby-lang.org/en/downloads/
-[ruby-installer]: http://rubyinstaller.org/
+[ruby-installer]: https://rubyinstaller.org/
[rubygems]: https://rubygems.org/pages/download/
[styles]: https://github.com/swcarpentry/styles/
-[training]: http://swcarpentry.github.io/instructor-training/
+[training]: https://swcarpentry.github.io/instructor-training/
[workshop-repo]: {{ site.workshop_repo }}
[yaml]: http://yaml.org/
[coc]: https://software-carpentry.org/conduct/
{% endif %}
{% comment %} Show extras for lessons or if this is the main workshop-template repo (where they contain documentation). {% endcomment %}
- {% if site.kind == "lesson" or site.github.repository_name == "workshop-template" %}
+ {% 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>
<ul class="dropdown-menu">
<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 }}/setup">Setup</a></td>
+ <td class="col-md-3"><a href="{{ page.root }}{% link setup.md %}">Setup</a></td>
<td class="col-md-7">Download files required for the lesson</td>
</tr>
{% for episode in site.episodes %}
<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" />
{% if site.carpentry == "swc" %}
<link rel="shortcut icon" type="image/x-icon" href="/favicon-swc.ico" />
{% elsif site.carpentry == "dc" %}
.output { @include cdSetup($color-output); }
.source { @include cdSetup($color-source); }
-.bash { @include cdSetup($color-source); }
-.make { @include cdSetup($color-source); }
-.matlab { @include cdSetup($color-source); }
-.python { @include cdSetup($color-source); }
-.r { @include cdSetup($color-source); }
-.sql { @include cdSetup($color-source); }
+.bash, .language-bash { @include cdSetup($color-source); }
+.make, .language-make { @include cdSetup($color-source); }
+.matlab, .language-matlab { @include cdSetup($color-source); }
+.python, .language-python { @include cdSetup($color-source); }
+.r, .language-r { @include cdSetup($color-source); }
+.sql, .langauge-sql { @include cdSetup($color-source); }
.error pre,
.output pre,
.source pre,
.bash pre,
+.language-bash pre,
.make pre,
+.language-make pre,
.matlab pre,
+.language-matlab pre,
.python pre,
+.language-python pre,
.r pre,
+.language-r pre,
.sql pre {
+.language-sql pre {
border-radius: 0 4px 4px 0;
}
--- /dev/null
+.highlight .hll { background-color: #ffffcc }
+.highlight { background: #f8f8f8; }
+.highlight .c { color: #408080; font-style: italic } /* Comment */
+.highlight .err { border: 1px solid #FF0000 } /* Error */
+.highlight .k { color: #008000; font-weight: bold } /* Keyword */
+.highlight .o { color: #666666 } /* Operator */
+.highlight .ch { color: #408080; font-style: italic } /* Comment.Hashbang */
+.highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */
+.highlight .cp { color: #BC7A00 } /* Comment.Preproc */
+.highlight .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */
+.highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */
+.highlight .cs { color: #408080; font-style: italic } /* Comment.Special */
+.highlight .gd { color: #A00000 } /* Generic.Deleted */
+.highlight .ge { font-style: italic } /* Generic.Emph */
+.highlight .gr { color: #FF0000 } /* Generic.Error */
+.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
+.highlight .gi { color: #00A000 } /* Generic.Inserted */
+.highlight .go { color: #888888 } /* Generic.Output */
+.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
+.highlight .gs { font-weight: bold } /* Generic.Strong */
+.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
+.highlight .gt { color: #0044DD } /* Generic.Traceback */
+.highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
+.highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
+.highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
+.highlight .kp { color: #008000 } /* Keyword.Pseudo */
+.highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
+.highlight .kt { color: #B00040 } /* Keyword.Type */
+.highlight .m { color: #666666 } /* Literal.Number */
+.highlight .s { color: #BA2121 } /* Literal.String */
+.highlight .na { color: #7D9029 } /* Name.Attribute */
+.highlight .nb { color: #008000 } /* Name.Builtin */
+.highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */
+.highlight .no { color: #880000 } /* Name.Constant */
+.highlight .nd { color: #AA22FF } /* Name.Decorator */
+.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */
+.highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
+.highlight .nf { color: #0000FF } /* Name.Function */
+.highlight .nl { color: #A0A000 } /* Name.Label */
+.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
+.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */
+.highlight .nv { color: #19177C } /* Name.Variable */
+.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
+.highlight .w { color: #bbbbbb } /* Text.Whitespace */
+.highlight .mb { color: #666666 } /* Literal.Number.Bin */
+.highlight .mf { color: #666666 } /* Literal.Number.Float */
+.highlight .mh { color: #666666 } /* Literal.Number.Hex */
+.highlight .mi { color: #666666 } /* Literal.Number.Integer */
+.highlight .mo { color: #666666 } /* Literal.Number.Oct */
+.highlight .sa { color: #BA2121 } /* Literal.String.Affix */
+.highlight .sb { color: #BA2121 } /* Literal.String.Backtick */
+.highlight .sc { color: #BA2121 } /* Literal.String.Char */
+.highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */
+.highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
+.highlight .s2 { color: #BA2121 } /* Literal.String.Double */
+.highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
+.highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */
+.highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
+.highlight .sx { color: #008000 } /* Literal.String.Other */
+.highlight .sr { color: #BB6688 } /* Literal.String.Regex */
+.highlight .s1 { color: #BA2121 } /* Literal.String.Single */
+.highlight .ss { color: #19177C } /* Literal.String.Symbol */
+.highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */
+.highlight .fm { color: #0000FF } /* Name.Function.Magic */
+.highlight .vc { color: #19177C } /* Name.Variable.Class */
+.highlight .vg { color: #19177C } /* Name.Variable.Global */
+.highlight .vi { color: #19177C } /* Name.Variable.Instance */
+.highlight .vm { color: #19177C } /* Name.Variable.Magic */
+.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */
hook_in <- function(x, options) {
stringr::str_c("\n\n~~~\n",
paste0(x, collapse="\n"),
- "\n~~~\n{: .r}\n\n")
+ "\n~~~\n{: .language-r}\n\n")
}
hook_out <- function(x, options) {
## find all the Rmd files, and generate the paths for their respective outputs
src_rmd <- list.files(pattern = "??-*.Rmd$", path = "_episodes_rmd", full.names = TRUE)
dest_md <- file.path("_episodes", gsub("Rmd$", "md", basename(src_rmd)))
-
+
## knit the Rmd into markdown
mapply(function(x, y) {
knitr::knit(x, output = y)
}, src_rmd, dest_md)
-
+
+ # Read the generated md files and add comments advising not to edit them
+ vapply(dest_md, function(y) {
+ con <- file(y)
+ mdfile <- readLines(con)
+ 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",
+ basename(y), "in _episodes_rmd/"), after = 2)
+ writeLines(mdfile, con)
+ close(con)
+ return(paste("Warning added to YAML header of", y))
+ },
+ character(1))
}
generate_md_episodes()
'%/LICENSE.md': True,
'%/README.md': False,
'%/_extras/discuss.md': True,
- '%/_extras/figures.md': True,
'%/_extras/guide.md': True,
'%/index.md': True,
'%/reference.md': True,
'error',
'output',
'source',
- 'bash',
- 'make',
- 'matlab',
- 'python',
- 'r',
- 'sql'
+ 'language-bash',
+ 'html',
+ 'language-make',
+ 'language-matlab',
+ 'language-python',
+ 'language-r',
+ 'language-shell',
+ 'language-sql'
}
# What fields are required in teaching episode metadata?
for filename in docs.keys():
checker = create_checker(args, filename, docs[filename])
checker.check()
- check_figures(args.source_dir, args.reporter)
args.reporter.report()
seen)
-def check_figures(source_dir, reporter):
- """Check that all figures are present and referenced."""
-
- # Get references.
- try:
- all_figures_html = os.path.join(source_dir, '_includes', 'all_figures.html')
- with open(all_figures_html, 'r') as reader:
- text = reader.read()
- figures = P_FIGURE_REFS.findall(text)
- referenced = [os.path.split(f)[1] for f in figures if '/fig/' in f]
- except FileNotFoundError as e:
- reporter.add(all_figures_html,
- 'File not found')
- return
-
- # Get actual image files (ignore non-image files).
- fig_dir_path = os.path.join(source_dir, 'fig')
- actual = [f for f in os.listdir(fig_dir_path) if os.path.splitext(f)[1] in IMAGE_FILE_SUFFIX]
-
- # Report differences.
- unexpected = set(actual) - set(referenced)
- reporter.check(not unexpected,
- None,
- 'Unexpected image files: {0}',
- ', '.join(sorted(unexpected)))
- missing = set(referenced) - set(actual)
- reporter.check(not missing,
- None,
- 'Missing image files: {0}',
- ', '.join(sorted(missing)))
-
-
def create_checker(args, filename, info):
"""Create appropriate checker for file."""
[dc-lessons]: http://datacarpentry.org/lessons/
[dc-site]: http://datacarpentry.org/
[discuss-list]: http://lists.software-carpentry.org/listinfo/discuss
-[github]: http://github.com
+[github]: https://github.com
[github-flow]: https://guides.github.com/introduction/flow/
[github-join]: https://github.com/join
[how-contribute]: https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github
[issues]: https://guides.github.com/features/issues/
[swc-issues]: https://github.com/issues?q=user%3Aswcarpentry
-[swc-lessons]: http://software-carpentry.org/lessons/
-[swc-site]: http://software-carpentry.org/
+[swc-lessons]: https://software-carpentry.org/lessons/
+[swc-site]: https://software-carpentry.org/
'''
ROOT_CONFIG_YML = '''\
swc_github: "https://github.com/swcarpentry"
swc_site: "https://software-carpentry.org"
swc_pages: "https://swcarpentry.github.io"
-lc_site: "http://librarycarpentry.github.io/"
+lc_site: "https://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"
- Makefile
- bin
-# Turn off built-in syntax highlighting.
-highlighter: false
+# Turn on built-in syntax highlighting.
+highlighter: rouge
'''
ROOT_INDEX_MD = '''\
CARPENTRIES = ("dc", "swc")
DEFAULT_CONTACT_EMAIL = 'admin@software-carpentry.org'
-USAGE = 'Usage: "check-workshop path/to/root/directory"'
+USAGE = 'Usage: "workshop_check.py path/to/root/directory"'
# Country and language codes. Note that codes mean different things: 'ar'
# is 'Arabic' as a language but 'Argentina' as a country.
@look_for_fixme
def check_email(email):
"""
- 'email' must be a valid email address consisting of characters,
- an '@', and more characters. It should not be the default contact
- email address 'admin@software-carpentry.org'.
+ 'email' must be a comma-separated list of valid email addresses.
+ The list may be empty. A valid email address consists of characters,
+ an '@', and more characters. It should not contain the default contact
"""
- return bool(re.match(EMAIL_PATTERN, email)) and \
- (email != DEFAULT_CONTACT_EMAIL)
+ # YAML automatically loads list-like strings as lists.
+ if (isinstance(emails, list) and len(emails) >= 0):
+ for email in emails:
+ if ((not bool(re.match(EMAIL_PATTERN, email))) or (email == DEFAULT_CONTACT_EMAIL)):
+ return False
+ else:
+ return False
+
+ return True
def check_eventbrite(eventbrite):
'helper list isn\'t a valid list of format ' +
'["First helper", "Second helper",..]'),
- 'email': (True, check_email,
- 'contact email invalid or still set to ' +
+ 'email': (True, check_emails,
+ 'contact email list isn\'t a valid list of format ' +
+ '["me@example.org", "you@example.org",..] or contains incorrectly formatted email addresses or ' +
'"{0}".'.format(DEFAULT_CONTACT_EMAIL)),
'eventbrite': (False, check_eventbrite, 'Eventbrite key appears invalid'),