From 7edb003cd1c9b53ffdff11ef85532e39f08db16d Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Fri, 6 Jan 2017 19:50:45 -0500 Subject: wip --- Makefile | 9 +- bin/index | 2 +- bin/index.atom.erb | 26 ----- bin/index.md.erb | 12 --- bin/page | 2 +- bin/page.html.erb | 37 ------- bin/pandoc.rb | 95 ----------------- bin/util.rb | 302 ---------------------------------------------------- config.yaml | 26 +++++ lib/.gitignore | 1 + lib/config.rb | 48 +++++++++ lib/license.rb | 17 +++ lib/page.rb | 83 +++++++++++++++ lib/page_index.rb | 63 +++++++++++ lib/page_local.rb | 114 ++++++++++++++++++++ lib/page_remote.rb | 56 ++++++++++ lib/pandoc.rb | 96 +++++++++++++++++ lib/person.rb | 32 ++++++ lib/sitegen.rb | 0 lib/tag.rb | 17 +++ lib/util.rb | 23 ++++ tmpl/index.atom.erb | 27 +++++ tmpl/index.md.erb | 12 +++ tmpl/page.html.erb | 37 +++++++ 24 files changed, 661 insertions(+), 476 deletions(-) delete mode 100644 bin/index.atom.erb delete mode 100644 bin/index.md.erb delete mode 100644 bin/page.html.erb delete mode 100644 bin/pandoc.rb delete mode 100644 bin/util.rb create mode 100644 config.yaml create mode 100644 lib/.gitignore create mode 100644 lib/config.rb create mode 100644 lib/license.rb create mode 100644 lib/page.rb create mode 100644 lib/page_index.rb create mode 100644 lib/page_local.rb create mode 100644 lib/page_remote.rb create mode 100644 lib/pandoc.rb create mode 100644 lib/person.rb create mode 100644 lib/sitegen.rb create mode 100644 lib/tag.rb create mode 100644 lib/util.rb create mode 100644 tmpl/index.atom.erb create mode 100644 tmpl/index.md.erb create mode 100644 tmpl/page.html.erb diff --git a/Makefile b/Makefile index 28677ff..9eb8c00 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ SHELL = bash -o pipefail -RUBYLIB=$(realpath .)/bin +RUBYLIB := $(realpath .)/lib$(if $(RUBYLIB),:$(RUBYLIB)) export RUBYLIB # Usage: $(call patsubst,PATTERN1 PATTERN2...,REPLACEMENT,TEXT) @@ -21,7 +21,7 @@ html.dirs = $(sort $(patsubst src%,out%, \ html.out += out/index.atom $(addsuffix /index.html,$(html.dirs)) all: $(html.out) out/main.css -.PHONY: all +.PHONY: all out/tags bin/page = bin/page bin/util.rb bin/pandoc.rb bin/index = bin/index bin/util.rb bin/pandoc.rb @@ -70,6 +70,11 @@ serve-%: all @printf '%s' $(call quote.shell,$($*)) | sed 's/^/#/' | bin/write-ifchanged $@ -include $(wildcard .var.*) + +irb: + irb +.PHONY: irb + .PHONY: FORCE .DELETE_ON_ERROR: .SECONDARY: diff --git a/bin/index b/bin/index index c04618d..c3ac2ff 100755 --- a/bin/index +++ b/bin/index @@ -1,6 +1,6 @@ #!/usr/bin/env ruby # -*- coding: utf-8 -*- -load 'util.rb' +require 'util' require 'yaml' # ARGV[0] diff --git a/bin/index.atom.erb b/bin/index.atom.erb deleted file mode 100644 index 5b0ef36..0000000 --- a/bin/index.atom.erb +++ /dev/null @@ -1,26 +0,0 @@ - - - - AndrewDM.me <%= @title %> - - - - <%= @pages.map{|p|p.updated}.sort.last.rfc3339 %> - <%= Person.new("Andrew Murrell").atom %> - <%= $url %> - - <% @pages.sort_by{|p| p.updated}.reverse.each do |page| %> - - - <%= page.url %> - <%= page.updated.rfc3339 %> - <%= page.published.rfc3339 %> - <%= page.title %> - <%= page.author.atom %> -<% if page.content %> - <%= html_escape(page.content) %> - <%= html_escape(page.rights) %> -<% end %> - - <% end %> - diff --git a/bin/index.md.erb b/bin/index.md.erb deleted file mode 100644 index a3ec547..0000000 --- a/bin/index.md.erb +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: "<%= @title %>" -class: "index" ---- - -<% @sections.keys.sort.each do |path| %> -<% unless path.empty? %>## [<%= @sections[path]['head'] %>](<%= path %>)<% end %> - -<% @sections[path]['body'].sort_by{|a|a.published}.reverse.each do |a| %> - * class="external" <% end %>href="<%= @url.route_to(a.url) %>" title="Published on <%= a.published.strftime('%Y-%m-%d') %><% if a.updated != a.published %> (updated on<%= a.updated.strftime('%Y-%m-%d') %>)<% end %>"><%= a.title %><% a.tags.each do |t| %><%= t.html %><% end %><% end %> - -<% end %> diff --git a/bin/page b/bin/page index ee62a95..e2d4f38 100755 --- a/bin/page +++ b/bin/page @@ -1,6 +1,6 @@ #!/usr/bin/env ruby # -*- coding: utf-8 -*- -load 'util.rb' +require 'util' require 'uri' template = "bin/page.#{ARGV[0]}.erb" diff --git a/bin/page.html.erb b/bin/page.html.erb deleted file mode 100644 index e2dc9fe..0000000 --- a/bin/page.html.erb +++ /dev/null @@ -1,37 +0,0 @@ - - - - - <%= @page.title %><% unless @page.title.empty? %> — <% end %>AndrewDM - - - <%= @page.head %> - - class="<%= @page.class %>"<% end %>> -
-

AndrewDM

- - -
-
- <% if @page.tags.count > 0 %>

Tags: <% @page.tags.each do |t| %><%= t.html %><% end %>

<% end %> - <% if @page.showtitle %>

<%= @page.title %>

<% end %> - <%= @page.content %> -
- - - diff --git a/bin/pandoc.rb b/bin/pandoc.rb deleted file mode 100644 index 155ddde..0000000 --- a/bin/pandoc.rb +++ /dev/null @@ -1,95 +0,0 @@ -require 'open3' -require 'json' - -module Pandoc - def self.prog - @prog ||= 'pandoc' - end - def self.prog=(val) - @prog = val - end - def self.load(fmt, input) - cmd = Pandoc::prog + " -t json" - unless fmt.nil? - cmd += " -f " + fmt - end - str = input - if str.respond_to? :read - str = str.read - end - json = '' - errors = '' - Open3::popen3(cmd) do |stdin, stdout, stderr| - stdin.puts(str) - stdin.close - json = stdout.read - errors = stderr.read - end - unless errors.empty? - raise errors - end - return Pandoc::AST::new(json) - end - - class AST - def initialize(json) - @js = JSON::parse(json) - end - - def [](key) - Pandoc::AST::js2sane(@js["meta"][key]) - end - - def js - @js - end - - def to(format) - cmd = Pandoc::prog + " -f json -t " + format.to_s - output = '' - errors = '' - Open3::popen3(cmd) do |stdin, stdout, stderr| - stdin.puts @js.to_json - stdin.close - output = stdout.read - errors = stderr.read - end - unless errors.empty? - raise errors - end - return output - end - - def self.js2sane(js) - if js.nil? - return js - end - case js["t"] - when "MetaMap" - Hash[js["c"].map{|k,v| [k, js2sane(v)]}] - when "MetaList" - js["c"].map{|c| js2sane(c)} - when "MetaBool" - js["c"] - when "MetaString" - js["c"] - when "MetaInlines" - js["c"].map{|c| js2sane(c)}.join() - when "MetaBlocks" - js["c"].map{|c| js2sane(c)}.join("\n") - when "Str" - js["c"] - when "Space" - " " - when "RawInline" - js["c"][1] - when "RawBlock" - js["c"][1] - when "Para" - js["c"].map{|c| js2sane(c)}.join() - else - throw js["t"] - end - end - end -end diff --git a/bin/util.rb b/bin/util.rb deleted file mode 100644 index cd7974b..0000000 --- a/bin/util.rb +++ /dev/null @@ -1,302 +0,0 @@ -# coding: utf-8 -load 'pandoc.rb' -require 'erb' -require 'date' -require 'set' -require 'uri' - -$license_urls = { - "CC BY-SA-3.0" => 'https://creativecommons.org/licenses/by-sa/3.0/', - 'WTFPL-2' => "http://www.wtfpl.net/txt/copying/", -} -$person_uris = { - "Luke Shumaker" => "https://lukeshu.com/", - "Andrew Murrell" => "https://andrewdm.me/", -} -$person_emails = { - "Luke Shumaker" => "lukeshu@parabola.nu", - "Andrew Murrell" => "ImFromNASA@gmail.com", -} - -$tag_names = { - "DM" => "DMing Resource", - "ES" => "Essay", - "FF" => "Flash Fiction", - "HB" => "Homebrew", - "SS" => "Short Story", - "WP" => "WIP", -} - -$url = URI::parse('https://www.andrewdm.me') - -class Tag - def initialize(abbr) - @abbr = abbr - end - def abbr - @abbr - end - def name - $tag_names[@abbr] - end - def html - return "#{name}" - end -end - -class Person - def initialize(name) - @name = name - end - def name - @name - end - def uri - $person_uris[@name] - end - def email - $person_emails[@name] - end - def html - if not email.nil? - return "#{name}" - elsif not uri.nil? - return "#{name}" - else - return @name - end - end - def atom - ret = "" - ret += "#{name}" unless name.nil? - ret += "#{uri}" unless uri.nil? - ret += "#{email}" unless email.nil? - end -end - -class License - def initialize(name) - @name = name - end - def name - @name - end - def url - $license_urls[@name] - end - def html - "#{name}" - end -end - -class Page - def initialize(infile) - @infile = infile - end - - def infile ; @infile ; end - def input ; @input ||= File.read(infile) ; end - def pandoc - if @pandoc.nil? - types = { - 'md' => 'markdown' - } - - ext = File.extname(infile).gsub(/^[.]/, '') - type = types[ext] || ext - @pandoc = Pandoc::load(type, input) - - if @pandoc['pandoc_format'] - @pandoc = Pandoc::load(@pandoc['pandoc_format'], input) - end - end - @pandoc - end - - def title ; @title ||= pandoc['title'] || input.split("\n",2).first ; end - def showtitle ; @showtitle ||= ! pandoc['title'].nil? ; end - - def author ; @author ||= Person.new( pandoc['author'] || "Andrew Murrell") ; end - def license ; @license ||= License.new(pandoc['license'] || "CC BY-SA-3.0") ; end - def content ; @content ||= pandoc.to('html5 '+(pandoc['pandoc_flags']||'')) ; end - def head ; @head ||= pandoc['html_head_extra'] ; end - def class ; @class ||= pandoc['class'] ; end - - def tags - if @tags.nil? - raw = pandoc['tags'] || [] - if raw.is_a?(String) - raw = raw.split - end - @tags = raw.map{|tag|Tag.new(tag)} - end - @tags - end - - def _published - if @_published.nil? - raw = pandoc['published'] - @_published = Date.parse(raw) unless raw.nil? - end - if @_published.nil? - raw = `git log -n1 --reverse --format='%cI' -- #{infile}` - @_published = DateTime.iso8601(raw) unless raw.empty? - end - @_published - end - - def _updated - if @_updated.nil? - raw = pandoc['updated'] - @_updated = Date.parse(raw) unless raw.nil? - end - if @_updated.nil? - raw = `git log -n1 --format='%cI' -- #{infile}` - @_updated = DateTime.iso8601(raw) unless raw.empty? - end - @_updated - end - - def published - if @published.nil? - unless _published.nil? - @published = _published - else - unless _updated.nil? - @published = _updated - end - end - # sanity check - unless _published.nil? or _updated.nil? - if _updated < _published - @published = _updated - end - end - end - @published - end - - def updated - if @updated.nil? - unless _updated.nil? - @updated = _updated - else - unless _published.nil? - @updated = _published - end - end - end - @updated - end - - def rights - if published.nil? || updated.nil? - years = '' - else - first = published.year - last = updated.year - - years = `git log --date=format:'%Y' --format='%cd' -- .config/login.sh`.split('\n').map{|s|s.to_i} - years.unshift(first) - years.unshift(last) - - # Remove dups and git years outside of [first,last] - # TODO: simplify year spans - years = Set[*years.select{|i|i > first && i < last}].sort.join(', ') - end - @rights ||= "

The content of this page is Copyright © #{years} #{author.html}.

\n" + - "

This page is licensed under the #{license.html} license.

" - end - - def abssrcpath - @srcpath ||= infile.sub(/^(src|out)\//, '/') - end - def absoutpath - @outpath ||= abssrcpath.sub(/\.[^\/.]*$/, '.html').sub(/\/index[.]html$/, '') - end - - def url - @url ||= $url + absoutpath - end - def srcurl - @srcurl ||= $url + abssrcpath - end - - def breadcrumbs - if @breadcrumbs.nil? - bc = [] - u = url.path - u = "/" if u == "" - while u != "/" - bc.unshift("#{File.basename(u, File.extname(u))}") - u = File.dirname(u) - end - bc.unshift("Andrew D. Murrell") - @breadcrumbs = bc.join(' » ') - end - @breadcrumbs - end - - def section - return nil - end -end - -def html_escape(html) - html - .gsub('&', '&') - .gsub('>', '>') - .gsub('<', '<') -end - -class ExternPage - def initialize(metadata) - @metadata = metadata - end - - def title - @metadata['title'] - end - - def content - nil - end - - def tags - if @tags.nil? - raw = @metadata['tags'] || [] - if raw.is_a?(String) - raw = raw.split - end - @tags = raw.map{|tag|Tag.new(tag)} - end - return @tags - end - - def url - return $url + @metadata['url'] - end - - def author - Person.new(@metadata['author'] || "Andrew Murrell") - end - - def published - str = @metadata['published'] - if str.nil? and ! @metadata['updated'].nil? - str = @metadata['updated'] - end - return Date.parse(str) - end - def updated - str = @metadata['updated'] - if str.nil? and ! @metadata['published'].nil? - str = @metadata['published'] - end - return Date.parse(str) - end - - def section - return @metadata['section'] - end -end diff --git a/config.yaml b/config.yaml new file mode 100644 index 0000000..b2eb53e --- /dev/null +++ b/config.yaml @@ -0,0 +1,26 @@ +url: "https://www.andrewdm.me/" +html_suffixes: ["md", "org"] + +# Licenses +default_license: "CC BS-SA-3.0" +license_uris: + "CC BY-SA-3.0": "https://creativecommons.org/licenses/by-sa/3.0/" + "WTFPL-2": "http://www.wtfpl.net/txt/copying/" + +# People +defualt_author: "Andrew Murrell" +person_uris: + "Luke Shumaker": "https://lukeshu.com/" + "Andrew Murrell": "https://andrewdm.me/" +person_emails: + "Luke Shumaker": "lukeshu@parabola.nu" + "Andrew Murrell": "ImFromNASA@gmail.com" + +# Tags +tag_names: + "DM": "DMing Resource" + "ES": "Essay" + "FF": "Flash Fiction" + "HB": "Homebrew" + "SS": "Short Story" + "WP": "WIP" diff --git a/lib/.gitignore b/lib/.gitignore new file mode 100644 index 0000000..e8db6e5 --- /dev/null +++ b/lib/.gitignore @@ -0,0 +1 @@ +/page.rb.txt \ No newline at end of file diff --git a/lib/config.rb b/lib/config.rb new file mode 100644 index 0000000..b22eedf --- /dev/null +++ b/lib/config.rb @@ -0,0 +1,48 @@ +# coding: utf-8 +require 'yaml' + +require 'uri' + +class Config + def self.get + return @config ||= Config::new('config.yaml') + end + def initialize(filename) + @data = YAML::load(File::read(filename)) + end + def url + return @url ||= URI::parse(@data['url']) + end + def html_suffixes + return @data['html_suffixes'] + end + # Licenses + def default_license + return @default_license ||= @data['default_license'] + end + def license_uri(name) + str = @data['license_uris'][name] + if str.nil? + return nil + end + return URI::parse(str) + end + # People + def default_author + return @default_person ||= @data['default_author'] + end + def person_uri(name) + str = @data['person_uris'][name] + if str.nil? + return nil + end + return URI::parse(str) + end + def person_email(name) + return @data['person_emails'][name] + end + # Tags + def tag_name(abbr) + return @data['tag_names'][abbr] + end +end diff --git a/lib/license.rb b/lib/license.rb new file mode 100644 index 0000000..da68f30 --- /dev/null +++ b/lib/license.rb @@ -0,0 +1,17 @@ +# coding: utf-8 +require 'config' + +class License + def initialize(name) + @name = name + end + def name + @name + end + def url + Config::get.license_uri(@name) + end + def html + "#{name}" + end +end diff --git a/lib/page.rb b/lib/page.rb new file mode 100644 index 0000000..d0b18ef --- /dev/null +++ b/lib/page.rb @@ -0,0 +1,83 @@ +# coding: utf-8 +require 'set' + +require 'tag' + +class Page + # Page is an abstract class. + # + # Implementors must implement several methods: + # + # def url => URI + # def title => String + # def author => Person + # def content => html | nil + # def rights => html | nil + # + # def _tags => String | Enumerable + # + # def _published => DateTime | nil + # def _updated => DateTime | nil + # def _years => Enumerable + + def tags # => Enumerable + if @tags.nil? + raw = _tags + if raw.is_a?(String) + raw = raw.split + end + @tags = raw.map{|tag|Tag.new(tag)} + end + @tags + end + + def published # => DateTime | nil + if @published.nil? + unless _published.nil? + @published = _published + else + unless _updated.nil? + @published = _updated + end + end + # sanity check + unless _published.nil? or _updated.nil? + if _updated < _published + @published = _updated + end + end + end + @published + end + + def updated # => DateTime | nil + if @updated.nil? + unless _updated.nil? + @updated = _updated + else + unless _published.nil? + @updated = _published + end + end + end + @updated + end + + def years # => Enumerable + if @years.nil? + if published.nil? || updated.nil? + @years = Set[] + else + first = published.year + last = updated.year + + years = _years + years.add(first) + years.add(last) + + @years = Set[*years.select{|i|i >= first && i <= last}] + end + end + @years + end +end diff --git a/lib/page_index.rb b/lib/page_index.rb new file mode 100644 index 0000000..073537e --- /dev/null +++ b/lib/page_index.rb @@ -0,0 +1,63 @@ +# coding: utf-8 +require 'erb' +require 'set' +require 'yaml' + +require 'page_local' +require 'page_remote' +require 'config' + +class IndexPage < LocalPage + def initialize(dirname) + super(dirname) + end + + def _metadata + if @metadata.nil? + yamlfile = _infile+"/index.yaml" + if File::exist?(yamlfile) + @metadata = YAML::load(File::read(yamlfile)) + else + @metadata = {} + end + end + @metadata + end + def _ls + @ls ||= Dir::entries(_infile) + .select{|fname|not fname.start_with?(".")} + .map{|fname|"#{_infile}/#{fname}"} + .select{|path|Dir::exist?(path) or Config::get.html_suffixes.include?(File::extname(path).gsub(/^[.]/, ''))} + end + def pages + if @pages.nil? + @pages = [] + for path in _ls + if Dir::exist?(path) + page = IndexPage::new(path) + @pages.unshift(page) + @pages += page.pages + else + @pages.unshift(LocalPage::new(path)) + end + end + for data in _metadata['external'] + @pages.unshift(RemotePage::new(data)) + end + end + @pages + end + + def _published + return nil + end + def _updated + return nil + end + def _years + return Set[] + end +end + +ERB::new(File::read("tmpl/index.atom.erb")).def_method(IndexPage, 'atom()', "tmpl/index.atom.erb") +ERB::new(File::read("tmpl/index.md.erb")).def_method(IndexPage, '_input()', "tmpl/index.md.erb") diff --git a/lib/page_local.rb b/lib/page_local.rb new file mode 100644 index 0000000..1ca14f0 --- /dev/null +++ b/lib/page_local.rb @@ -0,0 +1,114 @@ +# coding: utf-8 +require 'date' +require 'erb' +require 'set' + +require 'config' +require 'license' +require 'page' +require 'pandoc' +require 'person' + +class LocalPage < Page + def initialize(infile) + @infile = infile + end + + # Some of this code looks a little weird because it is + # super-aggressively lazy-evaluated and cached. + + def _infile ; @infile ; end + def _input ; @input ||= File::read(_infile) ; end + def _pandoc + if @pandoc.nil? + types = { + 'md' => 'markdown' + } + + ext = File::extname(_infile).gsub(/^[.]/, '') + type = types[ext] || ext + @pandoc = Pandoc::load(type, _input) + + if @pandoc['pandoc_format'] + @pandoc = Pandoc::load(@pandoc['pandoc_format'], _input) + end + end + @pandoc + end + + # Query simple document metadata + def title ; @title ||= _pandoc['title'] || _input.split("\n",2).first ; end + def author ; @author ||= Person::new( _pandoc['author'] || Config::get.default_author) ; end + def license ; @license ||= License::new(_pandoc['license'] || Config::get.default_license); end + def head ; @head ||= _pandoc['html_head_extra'] ; end + def class ; @class ||= _pandoc['class'] ; end + def _tags ; @_tags ||= _pandoc['tags'] || [] ; end + + def content + if @content.nil? + @content = '' + # Only insert the title if it came from Pandoc metadata; + # if the title was inferred from the the body content, + # then it is already in the page. + unless _pandoc['title'].nil? + @content += "

#{title}

\n" + end + + # Insert the body + @content = _pandoc.to('html5 '+(_pandoc['pandoc_flags']||'')) + end + @content + end + + def rights + # TODO: simplify year spans + @rights ||= "

The content of this page is Copyright © #{years.sort.join(', ')} #{author.html}.

\n" + + "

This page is licensed under the #{license.html} license.

" + end + + def _gitdates + @gitdates ||= `git log --format='%cI' -- #{_infile}`.split('\n').select{|s|!s.empty?}.map{|s|DateTime::iso8601(s)} + end + + def _published + if @_published.nil? + raw = _pandoc['published'] + @_published = Datetime::parse(raw) unless raw.nil? + end + if @_published.nil? + @_published = _gitdates.sort.first + end + @_published + end + + def _updated + if @_updated.nil? + raw = _pandoc['updated'] + @_updated = DateTime::parse(raw) unless raw.nil? + end + if @_updated.nil? + @updated = _gitdates.sort.last + end + @_updated + end + + def _years + @years ||= Set[*_gitdates.map{|dt|dt.year}] + end + + def abssrcpath + @srcpath ||= _infile.sub(/^(src|out)\//, '/') + end + def absoutpath + @outpath ||= abssrcpath.sub(/\.[^\/.]*$/, '.html').sub(/\/index[.]html$/, '') + end + + def url + @url ||= Config::get.url + absoutpath + end + def srcurl + @srcurl ||= Config::get.url + abssrcpath + end +end + +ERB::new(File::read("tmpl/page.html.erb")).def_method(LocalPage, 'html()', "tmpl/page.html.erb") diff --git a/lib/page_remote.rb b/lib/page_remote.rb new file mode 100644 index 0000000..a754af6 --- /dev/null +++ b/lib/page_remote.rb @@ -0,0 +1,56 @@ +# coding: utf-8 +require 'date' + +require 'config' +require 'page' +require 'tag' + +class RemotePage < Page + def initialize(metadata) + @metadata = metadata + end + + def url + return Config::get.url + @metadata['url'] + end + + def title + @metadata['title'] + end + + def author + Person::new(@metadata['author'] || Config::get.default_author) + end + + def content + return nil + end + + def rights + return nil + end + + def _tags + @metadata['tags'] || [] + end + + def _published + str = @metadata['published'] + if str.nil? + return nil + end + return Date::parse(str) + end + + def _updated + str = @metadata['updated'] + if str.nil? + return nil + end + return Date::parse(str) + end + + def _years + return [] + end +end diff --git a/lib/pandoc.rb b/lib/pandoc.rb new file mode 100644 index 0000000..f0bf3f6 --- /dev/null +++ b/lib/pandoc.rb @@ -0,0 +1,96 @@ +# coding: utf-8 +require 'open3' +require 'json' + +module Pandoc + def self.prog + @prog ||= 'pandoc' + end + def self.prog=(val) + @prog = val + end + def self.load(fmt, input) + cmd = Pandoc::prog + " -t json" + unless fmt.nil? + cmd += " -f " + fmt + end + str = input + if str.respond_to? :read + str = str.read + end + json = '' + errors = '' + Open3::popen3(cmd) do |stdin, stdout, stderr| + stdin.puts(str) + stdin.close + json = stdout.read + errors = stderr.read + end + unless errors.empty? + raise errors + end + return Pandoc::AST::new(json) + end + + class AST + def initialize(json) + @js = JSON::parse(json) + end + + def [](key) + Pandoc::AST::js2sane(@js["meta"][key]) + end + + def js + @js + end + + def to(format) + cmd = Pandoc::prog + " -f json -t " + format.to_s + output = '' + errors = '' + Open3::popen3(cmd) do |stdin, stdout, stderr| + stdin.puts @js.to_json + stdin.close + output = stdout.read + errors = stderr.read + end + unless errors.empty? + raise errors + end + return output + end + + def self.js2sane(js) + if js.nil? + return js + end + case js["t"] + when "MetaMap" + Hash[js["c"].map{|k,v| [k, js2sane(v)]}] + when "MetaList" + js["c"].map{|c| js2sane(c)} + when "MetaBool" + js["c"] + when "MetaString" + js["c"] + when "MetaInlines" + js["c"].map{|c| js2sane(c)}.join() + when "MetaBlocks" + js["c"].map{|c| js2sane(c)}.join("\n") + when "Str" + js["c"] + when "Space" + " " + when "RawInline" + js["c"][1] + when "RawBlock" + js["c"][1] + when "Para" + js["c"].map{|c| js2sane(c)}.join() + else + throw js["t"] + end + end + end +end diff --git a/lib/person.rb b/lib/person.rb new file mode 100644 index 0000000..6882dd2 --- /dev/null +++ b/lib/person.rb @@ -0,0 +1,32 @@ +# coding: utf-8 +require 'config' + +class Person + def initialize(name) + @name = name + end + def name + @name + end + def uri + Config::get.person_uri(@name) + end + def email + Config::get.person_email(@name) + end + def html + if not email.nil? + return "#{name}" + elsif not uri.nil? + return "#{name}" + else + return @name + end + end + def atom + ret = "" + ret += "#{name}" unless name.nil? + ret += "#{uri}" unless uri.nil? + ret += "#{email}" unless email.nil? + end +end diff --git a/lib/sitegen.rb b/lib/sitegen.rb new file mode 100644 index 0000000..e69de29 diff --git a/lib/tag.rb b/lib/tag.rb new file mode 100644 index 0000000..4009f67 --- /dev/null +++ b/lib/tag.rb @@ -0,0 +1,17 @@ +# coding: utf-8 +require 'config' + +class Tag + def initialize(abbr) + @abbr = abbr + end + def abbr + @abbr + end + def name + Config::get.tag_name(@abbr) + end + def html + return "#{name}" + end +end diff --git a/lib/util.rb b/lib/util.rb new file mode 100644 index 0000000..075ebb8 --- /dev/null +++ b/lib/util.rb @@ -0,0 +1,23 @@ +# coding: utf-8 + +module Util + def self.html_escape(html) + html + .gsub('&', '&') + .gsub('>', '>') + .gsub('<', '<') + end + + def self.breadcrumbs(url) + # TODO + bc = [] + u = url.path + u = "/" if u == "" + while u != "/" + bc.unshift("#{File::basename(u, File::extname(u))}") + u = File::dirname(u) + end + bc.unshift("Andrew D. Murrell") + return bc.join(' » ') + end +end diff --git a/tmpl/index.atom.erb b/tmpl/index.atom.erb new file mode 100644 index 0000000..cd70f7e --- /dev/null +++ b/tmpl/index.atom.erb @@ -0,0 +1,27 @@ + + + + AndrewDM.me <%= @title %> + + + + <%= @pages.map{|p|p.updated}.sort.last.rfc3339 %> + <%= Person.new("Andrew Murrell").atom %> + <%= $url %> + + <% @pages.sort_by{|p| p.updated}.reverse.each do |page| %> + + + <%= page.url %> + <%= page.updated.rfc3339 %> + <%= page.published.rfc3339 %> + <%= page.title %> + <%= page.author.atom %> +<% if page.content %> + <%= html_escape(page.content) %> +<% end %><% if page.rights %> + <%= html_escape(page.rights) %> +<% end %> + + <% end %> + diff --git a/tmpl/index.md.erb b/tmpl/index.md.erb new file mode 100644 index 0000000..a3ec547 --- /dev/null +++ b/tmpl/index.md.erb @@ -0,0 +1,12 @@ +--- +title: "<%= @title %>" +class: "index" +--- + +<% @sections.keys.sort.each do |path| %> +<% unless path.empty? %>## [<%= @sections[path]['head'] %>](<%= path %>)<% end %> + +<% @sections[path]['body'].sort_by{|a|a.published}.reverse.each do |a| %> + * class="external" <% end %>href="<%= @url.route_to(a.url) %>" title="Published on <%= a.published.strftime('%Y-%m-%d') %><% if a.updated != a.published %> (updated on<%= a.updated.strftime('%Y-%m-%d') %>)<% end %>"><%= a.title %><% a.tags.each do |t| %><%= t.html %><% end %><% end %> + +<% end %> diff --git a/tmpl/page.html.erb b/tmpl/page.html.erb new file mode 100644 index 0000000..e2dc9fe --- /dev/null +++ b/tmpl/page.html.erb @@ -0,0 +1,37 @@ + + + + + <%= @page.title %><% unless @page.title.empty? %> — <% end %>AndrewDM + + + <%= @page.head %> + + class="<%= @page.class %>"<% end %>> +
+

AndrewDM

+ + +
+
+ <% if @page.tags.count > 0 %>

Tags: <% @page.tags.each do |t| %><%= t.html %><% end %>

<% end %> + <% if @page.showtitle %>

<%= @page.title %>

<% end %> + <%= @page.content %> +
+ + + -- cgit v1.2.3