Skip to content

Commit ab2f72b

Browse files
Added support for jupyter notebooks alshedivat#417 (alshedivat#1511)
Implemented alshedivat#417. --------- Signed-off-by: George Araújo <george.gcac@gmail.com> Co-authored-by: Amir Pourmand <pourmand1376@gmail.com>
1 parent 554ab34 commit ab2f72b

File tree

8 files changed

+134
-7
lines changed

8 files changed

+134
-7
lines changed

.github/workflows/deploy.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ permissions:
1616

1717
jobs:
1818
deploy:
19+
# available images: https://github.com/actions/runner-images#available-images
1920
runs-on: ubuntu-latest
2021
steps:
2122
- name: Checkout 🛎️
@@ -27,6 +28,7 @@ jobs:
2728
bundler-cache: true
2829
- name: Install and Build 🔧
2930
run: |
31+
pip3 install --upgrade jupyter
3032
npm install -g mermaid.cli
3133
export JEKYLL_ENV=production
3234
bundle exec jekyll build

Dockerfile

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,35 @@
11
FROM bitnami/minideb:latest
22
Label MAINTAINER Amir Pourmand
33
RUN apt-get update -y
4+
45
# add locale
56
RUN apt-get -y install locales
67
# Set the locale
78
RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && \
89
locale-gen
9-
ENV LANG en_US.UTF-8
10-
ENV LANGUAGE en_US:en
11-
ENV LC_ALL en_US.UTF-8
10+
ENV LANG en_US.UTF-8
11+
ENV LANGUAGE en_US:en
12+
ENV LC_ALL en_US.UTF-8
1213

1314
# add ruby and jekyll
14-
RUN apt-get install --no-install-recommends ruby-full build-essential zlib1g-dev -y
15-
RUN apt-get install imagemagick -y
15+
RUN apt-get install --no-install-recommends ruby-full build-essential zlib1g-dev -y
16+
RUN apt-get install imagemagick -y
17+
18+
# install python3 and jupyter
19+
RUN apt-get install python3-pip -y
20+
RUN python3 -m pip install jupyter --break-system-packages
21+
22+
# clean everything
1623
RUN apt-get clean \
1724
&& rm -rf /var/lib/apt/lists/
25+
RUN pip3 cache purge
26+
1827
# ENV GEM_HOME='root/gems' \
1928
# PATH="root/gems/bin:${PATH}"
29+
30+
# install jekyll and dependencies
2031
RUN gem install jekyll bundler
2132
RUN mkdir /srv/jekyll
2233
ADD Gemfile /srv/jekyll
2334
WORKDIR /srv/jekyll
24-
RUN bundle install
35+
RUN bundle install

Gemfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ group :jekyll_plugins do
77
gem 'jekyll-email-protect'
88
gem 'jekyll-feed'
99
gem 'jekyll-imagemagick'
10+
gem 'jekyll-jupyter-notebook'
1011
gem 'jekyll-link-attributes'
1112
gem 'jekyll-minifier'
1213
gem 'jekyll-paginate-v2'

_config.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ plugins:
222222
- jekyll-email-protect
223223
- jekyll-feed
224224
- jekyll-imagemagick
225+
- jekyll-jupyter-notebook
225226
- jekyll-link-attributes
226227
- jekyll-minifier
227228
- jekyll-paginate-v2

_plugins/file-exists.rb

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
module Jekyll
2+
class FileExistsTag < Liquid::Tag
3+
4+
def initialize(tag_name, path, tokens)
5+
super
6+
@path = path
7+
end
8+
9+
def render(context)
10+
# Pipe parameter through Liquid to make additional replacements possible
11+
url = Liquid::Template.parse(@path).render context
12+
13+
# Adds the site source, so that it also works with a custom one
14+
site_source = context.registers[:site].config['source']
15+
file_path = site_source + '/' + url
16+
17+
# Check if file exists (returns true or false)
18+
"#{File.exist?(file_path.strip!)}"
19+
end
20+
end
21+
end
22+
23+
Liquid::Template.register_tag('file_exists', Jekyll::FileExistsTag)

_posts/2015-07-15-code.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ By default, it does not display line numbers. If you want to display line number
6464

6565
If you want to display line numbers for a specific code block, all you have to do is wrap your code in a liquid tag:
6666

67-
{% raw %}
67+
{% raw %}
6868
{% highlight c++ linenos %} <br/> code code code <br/> {% endhighlight %}
6969
{% endraw %}
7070

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
---
2+
layout: post
3+
title: a post with jupyter notebook
4+
date: 2023-07-04 08:57:00-0400
5+
description: an example of a blog post with jupyter notebook
6+
categories: sample-posts jupyter-notebook
7+
giscus_comments: true
8+
related_posts: false
9+
---
10+
11+
To include a jupyter notebook in a post, you can use the following code:
12+
13+
{% raw %}
14+
15+
```html
16+
{::nomarkdown}
17+
{% assign jupyter_path = "assets/jupyter/blog.ipynb" | relative_url %}
18+
{% capture notebook_exists %}{% file_exists assets/jupyter/blog.ipynb %}{% endcapture %}
19+
{% if notebook_exists == "true" %}
20+
{% jupyter_notebook jupyter_path %}
21+
{% else %}
22+
<p>Sorry, the notebook you are looking for does not exist.</p>
23+
{% endif %}
24+
{:/nomarkdown}
25+
```
26+
27+
{% endraw %}
28+
29+
Let's break it down: this is possible thanks to [Jekyll Jupyter Notebook plugin](https://github.com/red-data-tools/jekyll-jupyter-notebook) that allows you to embed jupyter notebooks in your posts. It basically calls [`jupyter nbconvert --to html`](https://nbconvert.readthedocs.io/en/latest/usage.html#convert-html) to convert the notebook to an html page and then includes it in the post. Since [Kramdown](https://jekyllrb.com/docs/configuration/markdown/) is the default Markdown renderer for Jekyll, we need to surround the call to the plugin with the [::nomarkdown](https://kramdown.gettalong.org/syntax.html#extensions) tag so that it stops processing this part with Kramdown and outputs the content as-is.
30+
31+
The plugin takes as input the path to the notebook, but it assumes the file exists. If you want to check if the file exists before calling the plugin, you can use the `file_exists` filter. This avoids getting a 404 error from the plugin and ending up displaying the main page inside of it instead. If the file does not exist, you can output a message to the user. The code displayed above outputs the following:
32+
33+
{::nomarkdown}
34+
{% assign jupyter_path = "assets/jupyter/blog.ipynb" | relative_url %}
35+
{% capture notebook_exists %}{% file_exists assets/jupyter/blog.ipynb %}{% endcapture %}
36+
{% if notebook_exists == "true" %}
37+
{% jupyter_notebook jupyter_path %}
38+
{% else %}
39+
<p>Sorry, the notebook you are looking for does not exist.</p>
40+
{% endif %}
41+
{:/nomarkdown}

assets/jupyter/blog.ipynb

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "code",
5+
"execution_count": 1,
6+
"metadata": {
7+
"collapsed": false
8+
},
9+
"outputs": [
10+
{
11+
"data": {
12+
"text/plain": [
13+
"sys.version_info(major=3, minor=6, micro=2, releaselevel='final', serial=0)"
14+
]
15+
},
16+
"execution_count": 1,
17+
"metadata": {},
18+
"output_type": "execute_result"
19+
}
20+
],
21+
"source": [
22+
"import sys\n",
23+
"sys.version_info"
24+
]
25+
}
26+
],
27+
"metadata": {
28+
"kernelspec": {
29+
"display_name": "Python 3",
30+
"language": "python",
31+
"name": "python3"
32+
},
33+
"language_info": {
34+
"codemirror_mode": {
35+
"name": "ipython",
36+
"version": 3
37+
},
38+
"file_extension": ".py",
39+
"mimetype": "text/x-python",
40+
"name": "python",
41+
"nbconvert_exporter": "python",
42+
"pygments_lexer": "ipython3",
43+
"version": "3.6.2"
44+
}
45+
},
46+
"nbformat": 4,
47+
"nbformat_minor": 2
48+
}

0 commit comments

Comments
 (0)