20

It turns out that custom ruby plugins don't work on GitHub pages because of security concerns.

I'm trying to add a plugin (this one) to the _plugins folder of my Jekyll project, but when I deploy it to GitHub it is ignored.

Question: Is there a way to workaround this? Has anyone found a solution?

Note: Obviously I can generate html files locally and commit them to my repository. But that's not what I want.

Sasha Shpota
  • 9,436
  • 14
  • 75
  • 148

5 Answers5

19

If you want to make Jekyll site run as if it were local, such as let the custom plugins work properly, here is a way really convenient to build and deploy the Jekyll site to Github Pages.

A Github Action to deploy the Jekyll site conveniently for GitHub Pages. https://github.com/jeffreytse/jekyll-deploy-action

With this action, I think your issues can be settled perfectly.

J.T.
  • 864
  • 9
  • 17
  • 1
    Nice! Gave it a star. – Sasha Shpota Jul 04 '20 at 15:27
  • Thanks for your good support! Hope this can help you. – J.T. Jul 04 '20 at 15:29
  • 2
    I solved my original issue without a plugin. But if I add something new I will keep your solution in mind. – Sasha Shpota Jul 04 '20 at 15:31
  • Yap, when your Github Page has been limited such as some plugins not working, you can use this action, otherwise no need to add this action. – J.T. Feb 10 '21 at 04:19
  • 1
    Nice one! +1 for the answer and a star for the repo... – Romeo Sierra Feb 13 '21 at 09:23
  • 1
    I spent so much time getting plugins for my stuff to render properly for a blog post I was writing. Worked on docker where I did bundle install && jekyll build. Then I was devastated when it didn't render properly on my site. But then I found this answer and your documentation helped me get it work on the first attempt. Starred! – David Söderlund Apr 05 '23 at 23:24
7

Without a plugin

A reading time script does not require a plugin. I have created a collection of scripts that can be added without using a plugin. You can find them here. A reading time script is one of them.

Here you find the code:

{% capture words %}
{{ content | number_of_words | minus: 180 }}
{% endcapture %}
{% unless words contains '-' %}
{{ words | plus: 180 | divided_by: 180 | append: ' minutes to read' }}
{% endunless %}

Note that this code contains only Liquid and no Ruby. Therefore it can be used in your layout or in an include (without a plugin).

Optimizing the script

Suppose you have something like this:

<p>lorem ipsum</p>
<p>lorem ipsum</p>
<code>lorem ipsum</code>
<p>lorem ipsum</p>
<code>lorem ipsum</code>
<p>lorem ipsum</p>

Then you could remove the above code blocks like this:

{% assign preprocessed_content=post.content | replace: '<p>', '__p__' %}
{% assign preprocessed_content=preprocessed_content | replace: '</p>', '__/p__' %}
{% assign truncated_content=preprocessed_content | strip_html %}
{% assign cleaned_content=truncated_content | replace: '__p__', '<p>' %}
{% assign cleaned_content=cleaned_content | replace: '__/p__', '</p>' %}

Ofcourse this can be extended to support more tags.

Using the plugin anyway

If you REALLY want to use a plugin you can let your local machine or CloudCannon build your site and push the result to Github Pages. See also: https://learn.cloudcannon.com/jekyll/using-jekyll-plugins/

Mr. Hugo
  • 11,887
  • 3
  • 42
  • 60
  • Thank you. `number_of_words` was the first thing I tried. Unfortunately it doesn't satisfy my needs. My articles often contain code blocks but `number_of_words` doesn't provide any mechanism to filter page content. Excluding `code`, `pre`, `script` etc might help but it is currently not possible. That's why for some articles it shows 2-3times more words than needed. Do you know how to fix this? – Sasha Shpota Nov 11 '18 at 18:12
  • You could try to split your content on code blocks. Are you sure that you can read code faster than normal words? I would say the opposite is true. – Mr. Hugo Nov 11 '18 at 19:05
  • It is not about performance. I don't want my code to be included to words count, it doesn't make sense. For instance, this article of mine http://sashashpota.com/2018/10/30/why-you-need-to-implement-a-plugin.html contains around 800 words, but `number_of_words` shows 1400 words as it counts code blocks as well. – Sasha Shpota Nov 11 '18 at 19:20
  • No, it is not about performance. It is about the speed at which humans read text and code. I do not think that you can read code faster than normal words/text. Code blocks are no images and should not be considered as such (IMO). – Mr. Hugo Nov 11 '18 at 19:30
  • I see your point and probably it works in many cases. But I think that in my case a user doesn't need to read the code word-by-word, they might just copy and paste it. Or in case if there is a log it is also nor required to read it, you can just quickly go through. But there is more than just code - if I remove images from my article `number_of_words` shows 25 symbols less. Did I remove some words? I guess not. I think `number_of_words` is good for some very basic cases, but not in my case. At the same time the plugin I mentioned in the question covers all corner cases. I wish I could use it. – Sasha Shpota Nov 11 '18 at 20:02
  • Only 25 characters? Probably in one word. That adds less than 1 second to the reading time. I think you are trying very hard to find a reason to use a plugin. However, you can easily use plugins if you let your local machine or CloudCannon build your site/plugin code and push the result to Github Pages. See also: https://learn.cloudcannon.com/jekyll/using-jekyll-plugins/ – Mr. Hugo Nov 11 '18 at 21:40
  • 1
    Thank you for suggesting `replace` and `strip_html`. I solved my problem using your suggestion https://github.com/Shpota/shpota.github.io/commit/36b6cc3cfc3041456f5a1da8ee82e404f3444f47 It is not ideal but it works. – Sasha Shpota Nov 15 '18 at 10:02
5

If you want to use your custom plugins, you have to "build" your site locally and then deploy it to the gh-pages branch yourself, as a collection of HTML, CSS and other files (not Markdown files anymore). You may want to try jgd command line to to help you do it all automatically. Just install it and then run:

$ jgd

The site will be packaged and then deployed to the gh-pages branch of your repo. More about it in this blog post of mine: Deploy Jekyll to GitHub Pages

yegor256
  • 102,010
  • 123
  • 446
  • 597
1

If you don't what a local solution because it's time consuming, you could automate a process so that when you push changes to master it will automatically build your website locally and push the changes to the gh-pages branch.

You can achieve this by creating a pre-push hook in your repo (.git/hooks/pre-push) with the following content:

#!/bin/sh

# If any command fails in the bellow script, exit with error
set -e

# Set the name of the folder that will be created in the parent
# folder of your repo folder, and which will temporarily
# hold the generated content.
temp_folder="_gh-pages-temp"

# Make sure our main code runs only if we push the master branch
if [ "$(git rev-parse --symbolic-full-name --abbrev-ref HEAD)" == "master" ]; then
    # Store the last commit message from master branch
    last_message=$(git show -s --format=%s master)

    # Build our Jekyll site
    jekyll build

    # Move the generated site in our temp folder
    mv _site ../${temp_folder}

    # Checkout the gh-pages branch and clean it's contents
    git checkout gh-pages
    rm -rf *

    # Copy the site content from the temp folder and remove the temp folder
    cp -r ../${temp_folder}/* .
    rm -rf ../${temp_folder}

    # Commit and push our generated site to GitHub
    git add -A
    git commit -m "Built \`$last_message\`"
    git push

    # Go back to the master branch
    git checkout master
else
    echo "Not master branch. Skipping build"
fi

For more details please see my blog post.

Nicu Surdu
  • 8,172
  • 9
  • 68
  • 108
0

You need an alternative to those plugins.

As detailed in "Building a Series List with Hugo Shortcodes":

Ruby plugin execution is disabled altogether on Github pages:

Plugins on GitHub Pages GitHub Pages is powered by Jekyll.
However, all Pages sites are generated using the -safe option to disable custom plugins for security reasons. Unfortunately, this means your plugins won’t work if you’re deploying to GitHub Pages.

You can still use GitHub Pages to publish your site, but you’ll need to convert the site locally and push the generated static files to your GitHub repository instead of the Jekyll source files.

I understand you mention:

Obviously I can generate html files locally and commit them to my repository. But that's not what I want.

Still, a static website generator (compatible with GitHub pages) like Hugo is to be considered in your case.

R.J Lorimer adds:

Hugo has the concept of Shortcodes, which are much like “Liquid Tags” in Jekyll.
Also like Jekyll, you can create custom shortcode tags.

However, the major difference is that in Hugo you can create them without resorting to actually writing Go code - see Create Your Own Shortcodes.
Because Hugo uses Go Templates for rendering the pages, shortcodes can use any and all Go template functions inside of them, as well as a whole list of custom Hugo functions added to help. This makes it arguably more powerful than a liquid-template solution, but still in a template file that can be easily updated on the fly.

Plus, Hugo does support MathJax, as seen in this article.

Update Nov. 2018: with Hugo 0.52, this tweet confirms (referencing this thread):

The inline shortcode is similar to the way Jekyll allows you to use Liquid tags within Markdown

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • Thank you for proposing an alternative solution. But I'm afraid switching from Jekyll to Hugo is even bigger pain. Alternatively I could host my blog on GitLab where custom plugins are supported. – Sasha Shpota Nov 11 '18 at 08:08