motyl

Opinionated blog-aware static site generator written in Ruby
Log | Files | Refs | README | LICENSE

commit db4823a8ce8914abeab532b92b442d8145846057
parent e23b601e57c3e2649ae386c2d40d86c0e6ea0fe4
Author: Frederic Cambus <fred@statdns.com>
Date:   Tue, 13 Mar 2018 11:05:26 +0100

Import initial Ruby version

Diffstat:
Dsrc/motyl.lua | 159-------------------------------------------------------------------------------
Asrc/motyl.rb | 137+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 137 insertions(+), 159 deletions(-)

diff --git a/src/motyl.lua b/src/motyl.lua @@ -1,159 +0,0 @@ -#!/usr/bin/env lua ---[[ -############################################################################### -# # -# Motyl # -# Copyright (c) 2016-2018, Frederic Cambus # -# https://github.com/fcambus/motyl # -# # -# Created: 2016-02-16 # -# Last Updated: 2018-03-04 # -# # -# Motyl is released under the BSD 2-Clause license. # -# See LICENSE file for details. # -# # -############################################################################### -]]-- - -local lfs = require "lfs" -local lyaml = require "lyaml" -local lunamark = require "lunamark" -local lustache = require "lustache" - --- Read data from file -local function readFile(path) - local file = assert(io.open(path, "rb")) - - local data = file:read "*all" - file:close() - - return data -end - --- Write data to file -local function writeFile(path, data) - local file = assert(io.open(path, "wb")) - - file:write(data) - file:close() -end - --- Load YAML from file -local function loadYAML(path) - return lyaml.load(readFile(path)) -end - --- Load and process Markdown file -local function loadMD(path) - local writer = lunamark.writer.html.new() - local parse = lunamark.reader.markdown.new(writer, { fenced_code_blocks = true }) - return parse(readFile(path)) -end - --- Sorting function to sort posts by date -local function sortDates(a,b) - return a.date > b.date -end - --- Display status message -local function status(message) - print("[" .. os.date("%X") .. "] " .. message) -end - --- Loading configuration -local data = {} -data.version = "Motyl 1.00" -data.updated = os.date("%Y-%m-%dT%XZ") -data.site = loadYAML("motyl.conf") -data.site.feed = {} -data.site.posts = {} -data.site.categories = {} - --- Loading templates -local templates = { - categories = readFile("themes/templates/categories.mustache"), - header = readFile("themes/templates/header.mustache"), - atom = readFile("themes/templates/atom.mustache"), - pages = readFile("themes/templates/page.mustache"), - posts = readFile("themes/templates/post.mustache"), - footer = readFile("themes/templates/footer.mustache") -} - -local function render(directory) - for file in lfs.dir(directory) do - if file ~= "." and file ~= ".." then - local extension = file:match "[^.]+$" - - if extension == "md" then - local path = file:match "(.*).md$" - data.page = loadYAML(directory .. "/" .. path .. ".yaml") - data.page.content = lustache:render(loadMD(directory .. "/" .. file), data) - if data.page.url == nil then - data.page.url = path .. "/" - end - - status("Rendering " .. data.page.url) - - if directory == "posts" then - local year, month, day, hour, min = data.page.date:match("(%d+)%-(%d+)%-(%d+) (%d+)%:(%d+)") - data.page.datetime = os.date("%Y-%m-%dT%XZ", os.time{year=year, month=month, day=day, hour=hour, min=min}) - - table.insert(data.site.posts, data.page) - - data.page.categoryDisplay = {} - - -- Populate category table - for _, category in ipairs(data.page.categories) do - if not data.site.categories[category] then - data.site.categories[category] = {} - end - - table.insert(data.site.categories[category], data.page) - table.insert(data.page.categoryDisplay, { category = category, url = data.site.categoryMap[category]}) - end - end - - lfs.mkdir("public/" .. data.page.url) - writeFile("public/" .. data.page.url .. "index.html", lustache:render(templates[directory], data, templates)) - - data.page = {} - end - end - end -end - --- Render posts -lfs.mkdir("public") -render("posts") - --- Sort post archives -table.sort(data.site.posts, sortDates) - --- Renger pages -render("pages") - --- Feed -for loop=1, data.site.feedItems do - data.site.feed[loop] = data.site.posts[loop] -end - -writeFile("public/atom.xml", lustache:render(templates.atom, data, templates)) -status("Rendering atom.xml") -data.page = {} - --- Categories -lfs.mkdir("public/categories") - -for category in pairs(data.site.categories) do - local categoryURL = data.site.categoryMap[category] .. "/" - - table.sort(data.site.categories[category], sortDates) - - data.page.title = category - data.page.url = "categories/" .. categoryURL - data.site.posts = data.site.categories[category] - - lfs.mkdir("public/categories/" .. categoryURL) - writeFile("public/categories/" .. categoryURL .. "index.html", lustache:render(templates.categories, data, templates)) - status("Rendering " .. categoryURL) -end diff --git a/src/motyl.rb b/src/motyl.rb @@ -0,0 +1,137 @@ +#!/usr/bin/env ruby +############################################################################### +# # +# Motyl # +# Copyright (c) 2016-2018, Frederic Cambus # +# https://github.com/fcambus/motyl # +# # +# Created: 2016-02-16 # +# Last Updated: 2018-03-13 # +# # +# Motyl is released under the BSD 2-Clause license. # +# See LICENSE file for details. # +# # +############################################################################### + +require 'kramdown' +require 'mustache' +require 'yaml' + +# Read data from file +def readFile(path) + return File.read(path) +end + +# Write data to file +def writeFile(path, data) + File.write(path, data) +end + +# Load YAML from file +def loadYAML(path) + return YAML.load_file(path) +end + +# Load and process Markdown file +def loadMD(path) + return Kramdown::Document.new(readFile(path)).to_html +end + +# Display status message +def status(message) + puts("[" + Time.now.strftime("%X") + "] " + message) +end + +# Loading configuration +data = {} +data["version"] = "Motyl 1.00" +data["updated"] = Time.now.strftime("%Y-%m-%dT%XZ") +data["site"] = loadYAML("motyl.conf") +data["site"]["feed"] = {} +data["site"]["posts"] = [] +data["site"]["categories"] = {} + +# Loading templates +templates = { + "categories" => readFile("themes/templates/categories.mustache"), + "atom" => readFile("themes/templates/atom.mustache"), + "pages" => readFile("themes/templates/page.mustache"), + "posts" => readFile("themes/templates/post.mustache"), +} + +class Mustache + self.template_path = "themes/templates/" +end + +def render(directory, templates, data) + Dir.foreach(directory) do |file| + next if file == '.' or file == '..' + extension = File.extname(file) + + if extension == ".md" + basename = File.basename(file, extension) + data["page"] = loadYAML(directory + "/" + basename + ".yaml") + data["page"]["content"] = Mustache.render(loadMD(directory + "/" + file), data) + if data["page"]["url"].nil? + data["page"]["url"] = basename + "/" + end + + status("Rendering " + data["page"]["url"]) + + if directory == "posts" then + data["page"]["datetime"] = DateTime.parse(data["page"]["date"]) + + data["site"]["posts"].push(data["page"]) + + data["page"]["categoryDisplay"] = [] + + # Populate category table + data["page"]["categories"].each do |category| + if data["site"]["categories"][category].nil? + data["site"]["categories"][category] = [] + end + data["site"]["categories"][category].push(data["page"]) + data["page"]["categoryDisplay"].push({ "category" => category, "url" => data["site"]["categoryMap"][category]}) + end + end + + Dir.mkdir("public/" + data["page"]["url"]) unless Dir.exist?("public/" + data["page"]["url"]) + writeFile("public/" + data["page"]["url"] + "index.html", Mustache.render(templates[directory], data)) + + data["page"] = {} + end + end +end + +# Render posts +Dir.mkdir("public") unless Dir.exist?("public") +render("posts", templates, data) + +# Sort post archives +data["site"]["posts"] = data["site"]["posts"].sort { |a,b| b["date"] <=> a["date"] } + +# Renger pages +render("pages", templates, data) + +# Feed +data["site"]["feed"] = data["site"]["posts"][0..20] + +writeFile("public/atom.xml", Mustache.render(templates["atom"], data)) +status("Rendering atom.xml") +data["page"] = {} + +# Categories +Dir.mkdir("public/categories") unless Dir.exist?("public/categories") + +data["site"]["categories"].keys.each do |category| + categoryURL = data["site"]["categoryMap"][category] + "/" + + data["site"]["categories"][category] = data["site"]["categories"][category].sort { |a,b| b["date"] <=> a["date"] } + data["page"]["title"] = category + data["page"]["url"] = "categories/" + categoryURL + data["site"]["posts"] = data["site"]["categories"][category] + + Dir.mkdir("public/categories/" + categoryURL) unless Dir.exist?("public/categories/" + categoryURL) + writeFile("public/categories/" + categoryURL + "index.html", Mustache.render(templates["categories"], data)) + status("Rendering " + categoryURL) +end