How I migrated this website articles from Jekyll to Hugo
So you moved your Jekyll posts to Hugo, what's next?
Overview
After having created a new hugo website hugo new site my_new_web
and
developed a new theme, I copied all the posts of my old Jekyll
instance to the /content
directory.
This is a list of issues that I needed to adjust in Jekyll posts to fit the new Hugo structure and concepts.
Most of the issues were due to the differences between Kramdown and Blackfriday, which are the markdown processors used by default by each program.
kramdown is a free MIT-licensed Ruby library for parsing and converting a superset of Markdown.
Blackfriday is a Markdown processor implemented in Go
Remove posts folders
You can now get rid of the old and ugly _posts
folder, Hugo handles
it beautifully having the indexes files at the same level of the
posts.
# | Jekyll (kramdown) | Hugo (Blackfriday) |
---|---|---|
Posts location | /docs/emacs/_posts/2018-08-08-best-editor-ever.md | /content/docs/emacs/2018-08-08-best-editor-ever.md |
use index.md or _index.md
Hugo has the concept of Page
Bundles, there
may be index.md
and _index.md
files in Hugo, depending on its role:
- Leaf
Bundle
- A directory in the last position of the
/content
tree that contains anindex.md
file (note the absence of_
) that may contain images or associated documents at the same directory level.
- A directory in the last position of the
- Branch Bundles
- A directory withing the
/content
tree, that contains an_index.md
and may contain more subdirectories.
- A directory withing the
# | Jekyll (kramdown) | Hugo (Blackfriday) |
---|---|---|
index | /docs/index.md | /content/docs/_index.md |
simple post | /_posts/2018-08-09-my-post.md | /content/my-post.md |
post with images (or docs) | /_posts/2018-08-09-my-post.md | /content/my-post/index.md |
Filenames doesn’t require dates
As regular Jekyll posts, filenames included the typical date prefix as part of the filename because it was born as a blogging platform. For me this was never something I wanted to have in filenames, now you can have the date in front-matter.
Newer Hugo versions are able to process these filenames but I prefer
to get rid of them completely and add them as metadata in front
matter, e.g.: date: 2018-08-09
.
# | Jekyll (kramdown) | Hugo (Blackfriday) |
---|---|---|
filenames | /_posts/2018-08-09-uruguay.md | /uruguay.md |
Add aliases of old URLs
You old Jekyll URLs may differ from the new website structure, if this
is the case use aliases
key in front matter with a list of the old
URLs that should redirect to this new post.
IALs not supported
Blackfriday doesn’t support IALs.
One of the features I missed more from Kramdown was the absence of block inline attribute list. They are very handy to quickly assign classes to a paragraph for example.
Your posts are probably full of {: .myclass}
or {: class="myclass"}
.
In Blackfriday you have two choices:
- manually write HTML
- Create a shortcode to assign a paragraph a custom class
I prefer to manually write HTML as creating a shortcode for this task creates more noise than writing plain HTML.
It also gives you greater control to apply styles like Bootstrap classes.
# | Jekyll (kramdown) | Hugo (Blackfriday) |
---|---|---|
IALs | Lorem Ipsum | <div class="info-alert">Lorem Ipsum</div> |
Lorem Ipsum |
Detecting IALs
An easy approach for detecting them is to look for {:
in your posts
folder (e.g.: docs or _posts) with grep: grep “{:” -R docs
$ grep "{\:" -R docs
docs/lisp/emacs/_posts/2017-06-23-jump-to-function-definitions-in-emacs.md:{: .alert .alert-info}
docs/lisp/emacs/_posts/2017-06-17-writing-alternating-between-english-and-spanish-in-emacs.md:{: class="blockquote"}
Remove markdown inside HTML tags
In Kramdown you can have *foobar*
or [foo](http://example.com)
embedded in an HTML <div> </div>
block and they would be converted
to their respective HTML equivalents: <em>foobar</em>
and <a href="http://example.com>foo</a>"
.
In Blackfriday, if you start writing HTML, then everything inside that block should be valid HTML.
# | Jekyll (kramdown) | Hugo (Blackfriday) |
---|---|---|
Markdown inside HTML | <div>*foobar*</div> | <div><em>foobar</em></div> |
Detecting code inside HTML tags
This is a little trickier than before as you should not check the unprocessed posts because it will contain all the markdown outside and inside HTML blocks.
In this case you can check them at the final site, i.e.: in the
public
folder after building the website with $ hugo.
Then you can use grep to find unprocessed markdown elements:
__
and**
: the strong HTML element](
: part of the markdown link notation[foo](http://bar)
Looking for _
or *
would be very difficult, so I chose to leave
them there as they don’t look so bad anyway.(may be just a little SEO
drawback as not being natural words from English or any other language)
So we can run $ grep “](” -R public to detect markdown
links in the public
, and grep “**” -R public to detect
unprocessed emphasis markdown code:
$ hugo $ grep "](" -R docs public/writing-in-emacs-checking-spelling-style-and-grammar/index.html: answer to [How to add a hook to only run in a particular mode?](https://stackoverflow.com/a/6141681/1165509) public/lisp/index.html:- [Common Lisp - A gentle introduction to symbolic computation]({% link _books/common-lisp-a-gentle-introduction-to-symbolic-computation-david-touretzky %}) by David Touretzky $ grep "\*\*" -R public public/lisp/emacs/jump-to-function-definitions-in-emacs.html:which is bound to **xref-find-definitions** and it will look for the
Removing quotes
In Jekyll (Kramdown), blockquotes can be started with the >
marker, and it will generate <blockquote></blockquote>
tags.
In Blackfriday, as with IALs, we can have blockquotes by manually setting them up in plain HTML or with shortcodes.
Again I used plain HTML so I had greater control to apply Bootstrap classes and organize its content.
# | Jekyll (kramdown) | Hugo (Blackfriday) |
---|---|---|
blockquote | > To be | <blockquote>to be or not to be</blockquote> |
Detecting blockqoutes
To detect unprocessed blockquotes look for lines starting with >
in the Jekyll posts folder.
$ grep "^>" -R _posts_
docs/php/joomla/_posts/2017-01-26-find-out-if-your-joomla-site-has-been-hacked.md:> Compares the timestamp
docs/python/language/_posts/2016-05-30-python.md:> The rule of thumb is
Why not use a migration tool
Hugo comes with a handy hugo import jekyll command but there were two issues that made me avoid it:
- Jekyll flexibility
- Jekyll fast development iterations
Flexibility
Jekyll is very flexible, and that flexibility has a price when migrating to another static website generator.
Chances are that your website doesn’t look like a standard Jekyll
instance, i.e.: just a project with a _posts_
directory at root with
posts in YYYY-MM-DD-title.md
format.
In my case I use collections
, data
files, and custom layouts that
get information from them. All custom is impossible to cover beforehand by any migration tool, so a
manual migration is my choice.
Rapid development
Jekyll, as Hugo does, moves forward fast, and you are probably continuously adopting new ways to do things and incorporating them into your toolbox.
A migration tool is something that you do once and forget about it, migration scripts doesn’t get much involvement so they are probably not in sync with other distribution status, i.e.: with your website design.
Summary
Putting it all together:
# | Jekyll (kramdown) | Hugo (Blackfriday) |
---|---|---|
Posts location | /docs/emacs/_posts/2018-08-08-best-editor-ever.md | /content/docs/emacs/2018-08-08-best-editor-ever.md |
index | /docs/index.md | /content/docs/_index.md |
simple post | /_posts/2018-08-09-my-post.md | /content/my-post.md |
post with images (or docs) | /_posts/2018-08-09-my-post.md | /content/my-post/index.md |
filenames | /_posts/2018-08-09-uruguay.md | /uruguay.md |
IALs | Lorem Ipsum | <div class="info-alert">Lorem Ipsum</div> |
Lorem Ipsum | ||
Markdown inside HTML | <div>*foobar*</div> | <div><em>foobar</em></div> |
blockquote | > To be | <blockquote>to be or not to be</blockquote> |
Conclusion
Migration can be time consuming depending on the amount of features you used from Jekyll and more specifically kramdown, if you just had a simple Jekyll website with plain markdown posts, moving to Hugo should be straightforward.
References
- https://github.com/russross/blackfriday
- https://kramdown.gettalong.org/
- https://gohugo.io/documentation/
- Have Different Portions Of Code For Production And DevelopmentAugust 14, 2018
- Deploying a Hugo website to AWS in 6 steps (CDN+HTTPS)August 12, 2018
- Customizing Bootstrap 4 with Hugo pipesAugust 7, 2018
- A first approach to Hugo for Jekyll developersAugust 4, 2018
- How I migrated this website articles from Jekyll to Hugo
- Hugo overview and basic conceptsOctober 10, 2017
Articles
Except as otherwise noted, the content of this page is licensed under CC BY-NC-ND 4.0 . Terms and Policy.
Powered by SimpleIT Hugo Theme
·