motyl (3792B)
1 #!/usr/bin/env ruby 2 3 # 4 # Motyl 1.0.3 5 # Copyright (c) 2016-2022, Frederic Cambus 6 # https://github.com/fcambus/motyl 7 # 8 # Created: 2016-02-16 9 # Last Updated: 2022-07-28 10 # 11 # Motyl is released under the BSD 2-Clause license. 12 # See LICENSE file for details. 13 # 14 # SPDX-License-Identifier: BSD-2-Clause 15 # 16 17 require 'date' 18 require 'fileutils' 19 require 'kramdown' 20 require 'mustache' 21 require 'yaml' 22 23 # Enforce UTF-8 character encoding 24 Encoding.default_internal = Encoding::UTF_8 25 Encoding.default_external = Encoding::UTF_8 26 27 # Load and process Markdown file 28 def markdown(path) 29 Kramdown::Document.new( 30 File.read(path), 31 smart_quotes: %w[apos apos quot quot], 32 syntax_highlighter: 'rouge' 33 ).to_html 34 end 35 36 # Display status message 37 def status(message) 38 puts('[' + Time.now.strftime('%X') + '] ' + message) 39 end 40 41 # Loading configuration 42 data = { 43 'version' => 'Motyl 1.0.3', 44 'updated' => Time.now.strftime('%Y-%m-%dT%XZ'), 45 'site' => YAML.load_file('motyl.conf'), 46 'posts' => [], 47 'categories' => {} 48 } 49 50 theme = 'themes/' + data['site']['theme'] + '/' 51 52 # Loading templates 53 templates = { 54 'categories' => File.read(theme + 'templates/categories.mustache'), 55 'atom' => File.read(theme + 'templates/atom.mustache'), 56 'pages' => File.read(theme + 'templates/page.mustache'), 57 'posts' => File.read(theme + 'templates/post.mustache') 58 } 59 60 Mustache.template_path = theme + 'templates/' 61 62 def render(directory, templates, data) 63 Dir.foreach(directory) do |file| 64 next if ['.', '..'].include?(file) 65 66 extension = File.extname(file) 67 68 if extension == '.md' 69 basename = File.basename(file, extension) 70 data['page'] = YAML.load_file(directory + '/' + basename + '.yaml') 71 data['page']['content'] = Mustache.render( 72 markdown(directory + '/' + file), 73 data 74 ) 75 data['page']['url'] ||= basename + '/' 76 77 status('Rendering ' + data['page']['url']) 78 79 if directory == 'posts' 80 data['page']['datetime'] = 81 DateTime.parse(data['page']['date']).strftime('%Y-%m-%dT%XZ') 82 83 data['posts'].push(data['page']) 84 85 data['page']['categoryDisplay'] = [] 86 87 # Populate category table 88 data['page']['categories'].each do |category| 89 data['categories'][category] ||= [] 90 data['categories'][category].push(data['page']) 91 data['page']['categoryDisplay'].push( 92 'category' => category, 93 'url' => data['site']['categoryMap'][category] 94 ) 95 end 96 end 97 98 FileUtils.mkdir_p('public/' + data['page']['url']) 99 File.write('public/' + data['page']['url'] + 'index.html', 100 Mustache.render(templates[directory], data)) 101 102 data['page'] = {} 103 end 104 end 105 end 106 107 # Render posts 108 FileUtils.rm_rf('public') 109 render('posts', templates, data) 110 111 # Sort post archives 112 data['posts'].sort! { |a, b| b['date'] <=> a['date'] } 113 114 # Renger pages 115 render('pages', templates, data) 116 117 # Feed 118 data['feed'] = data['posts'][0..29] 119 120 File.write('public/atom.xml', Mustache.render(templates['atom'], data)) 121 status('Rendering atom.xml') 122 data['page'] = {} 123 124 # Categories 125 data['categories'].keys.each do |category| 126 category_url = data['site']['categoryMap'][category] + '/' 127 128 data['categories'][category].sort! { |a, b| b['date'] <=> a['date'] } 129 data['page']['title'] = category 130 data['page']['url'] = 'categories/' + category_url 131 data['posts'] = data['categories'][category] 132 133 FileUtils.mkdir_p('public/categories/' + category_url) 134 File.write('public/categories/' + category_url + 'index.html', 135 Mustache.render(templates['categories'], data)) 136 status('Rendering ' + category_url) 137 end 138 139 # Copy static assets 140 status('Copying assets and static files') 141 FileUtils.cp_r(Dir.glob(theme + 'assets/*'), 'public') 142 FileUtils.cp_r(Dir.glob('assets/*'), 'public')