Implementing a glossary in Jekyll - jekyll

Am porting a doc site from Madcap Flare to GitHub Pages using Jekyll. One thing I'm wondering about is that is there a way of implementing an automatic glossary similar to Flare's:
https://www.madcapsoftware.com/blog/guest-post-madcap-flare-101-7-the-glossary/
In summary: I want to have a glossary file comprised of terms and definitions. Then if a term occurs in a topic, it automatically becomes a link or pop-up link to the definition.
If anyone has done this or knows a way to do it I would appreciate it.

Yes, this is possible. Pop-over elements are also possible but I have chosen the link example.
This plugin can create links to the glossary:
module GlossaryData
def glossary
self['glossary']
end
end
module Jekyll
class GlossaryLinkGenerator < Generator
def generate(site)
site.data.extend(GlossaryData)
glossary_terms = {}
site.data.glossary.each do |entry|
glossary_terms[entry['term'].downcase] = entry['definition']
glossary_terms[entry['term']] = entry['definition']
end
# pages
site.pages.each do |page|
glossary_terms.each do |term, definition|
page.content = page.content.gsub(term) do |match|
"<a href='/glossary.html##{term}'>#{term}</a>"
end
end
end
# posts
site.posts.docs.each do |post|
glossary_terms.each do |term, definition|
post.content = post.content.gsub(term) do |match|
"<a href='/glossary.html##{term}'>#{term}</a>"
end
end
end
# Notes
# For all content, use site.documents instead of the two code blocks for posts and pages above
# The site.documents attribute is an array of all the documents in your site,
# including pages, posts, and any other collections that you have defined in your configuration.
# You can use this attribute if you want to apply the glossary link generator to all types of documents in your site.
# You can also use site.collections[COLLECTION_NAME].docs if you want to apply it to a specific collection of documents.
# Just replace COLLECTION_NAME with the name of the collection you want to use.
# You can also use site.collections['posts'].docs for the posts instead of site.posts.
# site.collections is a hash of all the collections defined in your site's configuration,
# and each collection has a 'docs' attribute that returns an array of all the documents in the collection.
# This is useful if you want to apply the glossary link generator to a collection other than 'posts',
# or if you want to apply it to multiple collections.
end
end
end
Define your glossary in _data/glossary.yml:
- term: Jekyll
definition: A static site generator written in Ruby.
- term: Liquid
definition: A template language used by Jekyll to generate dynamic content.
- term: Markdown
definition: A lightweight markup language used to format plain text.
The test page to see that the glossary is working:
---
layout: post
---
jekyll or Jekyll? Both are matched due to downcasing.

Related

Applying multiple layouts to same collection item in jekyll

I have a jekyll collection _persons, with multiple peoples' profiles. Now I want to create multiple layouts for each person, e.g., a "Publications", and a "Bio" subpage for the same person.
How can I associate different layouts with the same person object? I'd also like to use sub-urls, such as:
\personA\publications\
\personA\bio\
Assuming that "bios" are the content type that you will be editing, you might create a symlink in your project root from _bios to _publications:
# Unix/Linux
ln -s _bios _publications
If you use windows, you'll need to check out mklink.
Then set up your config.yml like this:
collections:
bios:
output: true
publications:
output: true
defaults:
-
scope:
path: "_bios"
values:
layout: bio
permalink: /biographies/:title/
-
scope:
path: "_publications"
values:
layout: publication
permalink: /publications/:title/
Edit markdown files for your people in the _bios directory, and do not specify layout or permalink in their frontmatter.
When your site builds, you'll get permalinks like example.com/publications/personA and example.com/bios/personA. You can loop through site.publications and site.bios as usual.
You'll need to define the bio and publication layouts, and these will have access to any data you define in the frontmatter of your bio collection items.
Credit for this idea: https://github.com/jekyll/jekyll/issues/3041#issuecomment-267730851
It might be more semantic to have a collection _persons as a single point of truth and make two symlinks from this collection.
Good luck!

Is there a way to add another variable to site object in jekyll?

I'm creating a blog just to dump my notes in. I love how far I can go with site.tags and site.categories. All I really need now is the ability to have another filter option. Something li site.sublog it would help me create exactly what I need
So here's a post
---
layout: post
title: "Angular.js With Codeschool:part five"
date: 2015-05-14 07:57:01 +0100
category: [Angularjs-codeschool, basics]
tags: [angular with codeschool]
sublog: [web]
---
Basically I want to write notes on everything I am interested in: web, general tech, history ... and sort of create sub blogs
There are ways around it but now that I am here I just wanted to know if such a thing was possible
Categories and tags are treated specially by Jekyll, so you won't find that other front matter entries from a post will be collected into a site-wide variable like site.categories and site.tags are.
The Jekyll documentation has a tutorial on retrieving items based on front matter properties, which shows how to iterate over an entire collection and do some per-item processing based on a front matter variable's value.
You could iterate over your collection, inspecting the sublog values of each item and concat-ing them to a list of all known sublog values (perhaps removing duplicates using uniq afterwards, and optionally sort-ing them before further processing).
This would enable you to create a list of all sub blogs, and for each sub blog, create a list of posts within it (which is presumably your end goal).
You can store Sitewide information + configuration settings in _config.yml.
Your example shows Page specific information in the YAML front matter!
Read the Jekyll Documentation, please.

How can I have articles in Wintersmith not in their own subdirectory?

In Wintersmith, the default blog template generates posts from content/articles/<article>/index.md. This is fine as it allows associated files like images to be included with the article. But in practice, most "blog posts" are just text content associated with a template. Having to create subdirs is a minor annoyance, and if editing multiple entries in a tabbed editor, it's annoying having everything named index.md.
The site generator will spit out articles/basic-post.html files, but does not include these in the generated index or archive pages. How can I get the latter to work without breaking anything?
This may or may not be a simple problem, but I'm new to Wintersmith and haven't seen how to do this. I'm not sure it's as trivial as editing the default paginator (and I am not that used to CoffeeScript, which maybe it's time to address that :)
In paginator.coffee:
getArticles = (contents) ->
# helper that returns a list of articles found in *contents*
# note that each article is assumed to have its own directory in the articles directory
articles = contents[options.articles]._.directories.map (item) -> item.index
articles.sort (a, b) -> b.date - a.date
return articles
This looks like the place, however it seems like a bad idea to directly edit a plugin, for potential future updates to work.
Wintersmith is pretty awesome btw.
You were right: theanswer lies into the paginator plugin.
Wintersmith will constently watch the contents folder, building a ContentTree array.
That objet array will contain a descriptor for each file and folder within contents.
The getArticles just filter this possible candidates, and you just need to enhance it to get plain markdown files in the contents/articles folder.
getArticles = (contents) ->
# helper that returns a list of articles found in *contents*
# include articles with dedicated directory
articles = contents[options.articles]._.directories.map (item) -> item.index
# add articles that are in the *contents/articles* folder
articles = articles.concat contents[options.articles]._.pages
articles.sort (a, b) -> b.date - a.date
return articles

Rails : Benefit of URL path modification vs Namespace?

Many people talk about namespace as a way to change the URL that lead to their controller with a prefix (i.e. : /admin/movies instead of /movies)
Changing the URL path
The official doc explains that if we want to change the URL that lead to our controller with a prefix, we just have to change our resource in config/route.rb.
From this :
resources :movies
to this :
resources :movies, :path => "/admin/movies"
Implementing namespace
After a lot of googsearches, I'm wondering why so many people like to have namespace and what are the adavantages of namespace versus just modifying the URL path leading to a specific controller in the router file : myapp/config/route.rb
To implement a namespace, the official doc explains that you need rather the following modifications. You will see that this is a lot of work :
namespace :admin do
resources :movies
end
...and moves your movies_controller.rb controller to app/controllers/admin directory.
But if you follow these instructions, you'll get this error :
*"Expected /var/www/myapp/app/controllers/admin/movies_controller.rb to define Admin::MoviesController"*
*Then you realized that Rails expect this 'alien' writing at the begining of your movies_controller.rb : "Admin::"*
So you change the first line of your movies_controller.rb with :
class admin::MoviesController < ApplicationController
instead of :
class MoviesController < ApplicationController
But you again get another error :
"undefined local variable or method `admin' for main:Object"
Then you realized you forgot Ruby classes MUST be declared with a starting uppercase.
So you add a starting uppercase to your Ruby class :
class Admin::MoviesController < ApplicationController
But you still get an error :
*Missing template admin/movies/index, application/index with {:locale=>[:"fr-CH"], :formats=>[:html], :handlers=>[:erb, :builder, :rxls, :coffee, :haml]}. Searched in: * "/var/www/myapp/app/views"*
What the hell...? Oh did the doc forgot to say as well that controller's corresponding views must as well be moved to an admin directory within the app/view/ ?
So you create a directory and move your views to app/view/admin/
And you still get the same error.
Then you realized you forgot to include the movies folder itself within app/view/admin
So you did it.
You still got an error message :
*undefined method `movies_path' for #<#:0xa817c0c>*
This time you know that routing, controller and view work but you still have to change the pathes on all your views...
Moreover, if you are using the "respond_with" method in your controller file, you have to include the namespace as parameter. This is an example for the index operation :
def index
#movies = Movie.all
respond_with(:admin, #movies)
end
Moreover if you are using declarative_authentification gem (similar as cancan gem), you have to prefix the argument of your permited_to? method with the namespace. For example (with HAML syntax) :
- if permitted_to? :index, :admin_movies
// And prefix as well your path
= link_to 'Show all my movie", admin_movies_path
- if permitted_to? :show, :admin_movies
// And prefix as well your path
= link_to 'Show selected movie", admin_movie_path(#movie)
You realize you were going to create a namespace just for the url path conveniance, so you decide to give up, roll back your modif, and just add the following line in your route.rb file :
resources :movies, :path => "/admin/movies"
Which works immediately like a charm.
As testing purpose I created a new fake project "testapp" including namespace with the generator.
I performed a "rails generate scaffold admin/movie title:string" to check how does the generator handle namespace.
The resulting app/controller/admin/movies_controller.rb is rather different from what we expected it to be.
There are additionnal prefix "Admin::" in front of each instance variable declaration.
Here for instance the index method :
def index
#admin_movies = Admin::Movie.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #admin_movies }
end
end
I guess that this is because the generator as well moved the model movie.rb into app/models/admin directory
Moreover I see that there is another model in app/models : admin.rb
Which contains :
module Admin
def self.table_name_prefix
'admin_'
end
end
I have no idea how this method will be used nor by who ?
I notice as well that my table will be named "admin_movies" in the /db/migrate/2012blabla_create_admin_movies.rb
class CreateAdminMovies < ActiveRecord::Migration
def change
create_table :admin_movies do |t|
t.timestamps
end
end
end
Well, it seems there will have a lot more work (and mess-up) than I expected in order to put in place a namespace...
For what benefit/advantage ???
To use another url path ? This small modification in my controller
would be far more easier : resources :movies, :path =>
"/admin/movies"
To make it possible to use two different controllers using a same name ? Wouldn't it be easier to just put a prefix to my controler name than do all this mess-up ?
Of course some of the above errors could have been avoided by being more vigilant. But you know, we are just human, and when it's late in the evening while coding, maybe you wished this part of rails would have been, let's say, more human adapted...
I really don't understand why people get so excited to have namespace.
I woudld be gratefull, if an expert could explain what am I missing.
Many Thanks
If you have two different controllers with the same name but different functionality then you can use namespaced routes. You don't have to rename the controller for it. Check out "2.6 Controller Namespaces and Routing" at http://guides.rubyonrails.org/routing.html.
The idea is not to have a ton of controllers in one directory. Namespaces help you do that by grouping controllers in directories.
And as far doing all that work, it's a lot easier just to generate the controllers you need using the namespace paths, eg:
rake generate controller "Foo/Bars"
Then rails does all that heavy lifting so you don't have to.

html.haml vs haml in Rails view templates

What is the difference between using view templates in Rails as '.html.haml' and as simply '.haml'?
For example,
show.html.haml
vs
show.haml
Are there any particular advantages of using one over the other? Or is one of them a standard practice? The same question goes for other types of templates as well, like '.erb'.
The format matters when you're using Rails' automatic responders. See http://api.rubyonrails.org/classes/ActionController/MimeResponds.html#method-i-respond_with.
So for example, with:
class CarsController < ActionController::Base
respond_to :html, :js
def index
respond_with Car.all
end
end
The app will render app/views/cars/index.html.erb and app/views/index.js.erb when viewing http://localhost:3000/cars and http://localhost:3000/cars.js, respectively.
Additionally, this is an established convention in Rails-land, so it's just a good idea to do this anyway, even if you're not using the auto-responders.