diff --git a/source/_layouts/bootstrap.html b/_layouts/bootstrap.html similarity index 99% rename from source/_layouts/bootstrap.html rename to _layouts/bootstrap.html index b491ae1..dec5312 100644 --- a/source/_layouts/bootstrap.html +++ b/_layouts/bootstrap.html @@ -56,6 +56,7 @@ page_title: The Ardour Manual

{{ page.title }}

{{ content }} + {% prevnext %}
diff --git a/source/_layouts/default.html b/_layouts/default.html similarity index 100% rename from source/_layouts/default.html rename to _layouts/default.html diff --git a/_plugins/manual.rb b/_plugins/manual.rb deleted file mode 100644 index 2a5d905..0000000 --- a/_plugins/manual.rb +++ /dev/null @@ -1,262 +0,0 @@ -require 'erb' -require 'fileutils' -require 'tmpdir' -require 'pp' - -module Manual - - DIRECTORY_ENTRIES = {} - - def self.traverse_data(entries, directory_sort = false, paths = [], key_paths = [], &block) - - entries.map do |entry| - - entry = entry.dup - - if entry[:type] == 'directory' - entry[:children] = traverse_data(entry[:children], directory_sort, paths + [entry[:name]], key_paths + [entry[:key]], &block) - end - block_given? ? block.call(entry) : entry - end - end - - def self.traverse(path, directory_sort = false, paths = [], key_paths = [], &block) - - entries = Dir.glob(File.join(path,'*')).sort - - entries.sort_by! { |e| File.directory?(e) ? 1 : 0 } if directory_sort - - entries.map do |entry| - is_dir = File.directory?(entry) - - data = extract_data(is_dir ? "#{entry}.html" : entry) - - short_title = data['menu_title'] || data['title'] - - name = entry[/[^\/]+$/] # filename - key = name.sub(/^[0-9]+(\-|_)/,'').sub(/\.[^\.]+$/,'') # slug - my_paths = paths + [name] - my_key_paths = key_paths + [key] - url = '/' + my_key_paths.join('/') + '/' - - without_extension = entry.sub(/\.[^\/\/]+$/,'') - - h = { - name: name, - title: data['title'] || key, - menu_title: short_title || key, - key: key, - filename: entry, - type: is_dir ? 'directory' : 'file', - url: url - } - - if is_dir - h.update \ - children: traverse(entry, directory_sort, my_paths, my_key_paths, &block) - else - h.update extension: File.extname(name), has_dir: File.directory?(without_extension) - end - - if is_dir - DIRECTORY_ENTRIES[url] = h - end - - block_given? ? block.call(h) : h - end.compact - end - - def self.extract_data(filename) - if File.exists?(filename) and !File.directory?(filename) and first3 = File.open(filename) { |fd| fd.read(3) } and first3 == '---' - blah = filename.sub(/^_manual\//,'') - page = Jekyll::Page.new(@site, '_manual', File.dirname(blah), File.basename(blah)) - page.data - else - {} - end - end - - class ManualPage < Jekyll::Page - def initialize(*args) - super - end - end - - class ManualGenerator < Jekyll::Generator - - safe true - - def generate(site) - source = site.config['source'] - destination = site.config['destination'] - - manual_dir = '_manual' - - # now we need to turn our raw input files into something for jekyll to process - # everything is in a directory with it's name and all content is in index.html files - # the tmpdir gets removed at the end of this block automatically - - Dir.mktmpdir do |tmpdir| - - Manual.traverse manual_dir, true do |entry| - output_filename = File.join(tmpdir, entry[:url], "index#{entry[:extension]}") - - FileUtils.mkdir_p File.dirname(output_filename) - - next unless entry[:type] == 'file' - - File.open(output_filename, 'w+') do |f| - f << File.read(entry[:filename]) - end - - relative_filename = File.join(entry[:url], "index#{entry[:extension]}") - - site.pages << Jekyll::Page.new(site, tmpdir, File.dirname(relative_filename), File.basename(relative_filename)) - end - - end - end - - end - - class ManualChildPageTag < Liquid::Tag - def render(context) - current = context['page.url'].sub(/[^\/]+$/,'') - - if entry = DIRECTORY_ENTRIES[current] - - path = File.join(entry[:filename], '*') - - entries = entry[:children].map do |child| - "
  • #{child[:title]}
  • " - end.uniq - - "
    -

    This chapter covers the following topics:

    - -
    - " - end - end - end - - # generates a big
    list of the manual page stucture - - class ManualTOCTag < Liquid::Tag - - def process_hierarchy(items_a, items_b) - current = true - position = nil - level = -1 - - [items_a.length,items_b.length].max.times do |i| - a = items_a[i] - b = items_b[i] - - current = false if a != b - - # start incrementing this when we don't have either a or b - level += 1 if !a || !b - - if a && b - return [false] if a != b - elsif a - position = :parent - elsif b - position = :child - end - end - position ? [current, position, level + 1] : [current] - end - - def render(context) - - @source = '_manual' #context.registers[:site].source - - @@data_tree ||= Manual.traverse(@source) - - @site = context.registers[:site] - current = context['page.url'].sub(/[^\/]+$/,'') - - current_a = current.split('/').reject(&:empty?) - - tree = Manual.traverse_data(@@data_tree) do |entry| - - url = entry[:url] - - url_a = url.split('/').reject(&:empty?) - - depth = url_a.length - is_current, position, level = *process_hierarchy(current_a, url_a) - - # this massively speeds up build time by not including the whole menu tree for each page - next if depth > 1 && current_a[0] != url_a[0] - - css_classes = [] - css_classes << 'active' if is_current - css_classes << position.to_s if position - css_classes << "#{position}-#{level}" if position && level - css_classes << 'other' unless is_current || position || level - - css_classes << "level-#{depth}" - css_classes = css_classes.join(' ') - - if entry[:type] == 'directory' - - erb = ::ERB.new <<-HTML -
    - <%= entry[:menu_title] %> -
    -
    - <% if entry[:children].any? %> -
    - <%= entry[:children].join %> -
    - <% end %> -
    - HTML - - erb.result(binding) - else - - directory_filename = entry[:filename].sub(/\.[^\/\.]+$/,'') - - unless entry[:has_dir] - - erb = ::ERB.new <<-HTML -
    - <%= entry[:menu_title] %> -
    -
    -
    - HTML - - erb.result(binding) - end - end - - - end - - "
    #{tree.join}
    - " - - end - - - end - -end - -Liquid::Template.register_tag('tree', Manual::ManualTOCTag) -Liquid::Template.register_tag('children', Manual::ManualChildPageTag) diff --git a/build.rb b/build.rb new file mode 100644 index 0000000..4932925 --- /dev/null +++ b/build.rb @@ -0,0 +1,231 @@ +require 'pathname' +require 'fileutils' +require 'yaml' +require 'liquid' + +def split_frontmatter(txt) + re = /\A---[ \t\r]*\n(?.*?)^---[ \t\r]*\n(?.*)\z/m + match = re.match txt + match ? [match['frontmatter'], match['content']] : nil +end + +def child_url?(a, b) + a.start_with?(b) && b.count('/') + 1 == a.count('/') +end + +class Site + attr_reader :pages + + def initialize() + @pages = [] + @config = { + 'pages_dir' => '_manual', + 'layouts_dir' => '_layouts', + 'static_dir' => 'source', + 'output_dir' => '_site' + } + @layouts = {} + end + + def read_layouts() + layouts_dir = Pathname(@config['layouts_dir']) + Pathname.glob(layouts_dir + Pathname('*.html')) do |path| + next if !path.file? + layout = Layout.new(self, path) + layout.read + @layouts[path.basename('.html').to_s] = layout + end + end + + def find_layout(name) + @layouts[name] + end + + def read_pages() + pages_dir = Pathname.new(@config['pages_dir']) + pages_dir.find do |path| + if path.file? && path.extname == '.html' + page = Page.new(self, path) + page.read + @pages << page + end + end + end + + def find_children(url) + @pages.select{ |p| child_url?(p.url, url) }.sort_by{ |p| p.path.basename } + end + + def process_pages() + @pages.each {|page| page.process} + end + + def copy_static() + # http://ruby-doc.org/stdlib-2.2.1/libdoc/fileutils/rdoc/index.html + end + + def pages_dir() + Pathname(@config['pages_dir']) + end + + def output_dir() + Pathname(@config['output_dir']) + end + + def run() + #read_config() + read_layouts() + read_pages() + copy_static() + process_pages() + end +end + +class Page + attr_reader :path, :out_path, :url, :sort_url + + def initialize(site, path) + @site = site + @path = path + + canon = canonical + @out_path = @site.output_dir + canon + Pathname("index.html") + @url = '/' + canon + '/' + @sort_url = @path.to_s.sub(/\.html$/, '') + end + + def canonical() + remove_numbers = lambda {|x| x.sub(/^[0-9]*[-_]/, '') } + path = @path.relative_path_from(@site.pages_dir) + a = path.each_filename.map(&remove_numbers) + a[-1] = a[-1].sub(/\.html$/, '') + a.join('/') + end + + def related_to?(p) + # should we show p in the index on selfs page? + url.start_with?(p.url) || child_url?(url, p.url) + end + + def title() + if !@page_context + puts 'nil page context: ' + @path.to_s + end + @page_context['title'] || "" + end + + def read() + content = @path.read + split = split_frontmatter content + split || abort("Not a Jekyll-formatted file: #{@path}") + frontmatter, @content = split + @page_context = YAML.load(frontmatter) + @template = Liquid::Template.parse(@content) + end + + def find_layout() + @site.find_layout(@page_context['layout'] || 'default') + end + + def children() + @site.find_children(@url) + end + + def render() + registers = {page: self, site: @site} + context = {'page' => @page_context} + content = @template.render!(context, registers: registers) + find_layout.render(context.merge({'content' => content}), registers) + end + + def process() + path = out_path + path.dirname.mkpath + path.write(render) + end +end + +class Layout < Page + def render(context, registers) + context = context.dup + context['page'] = @page_context.merge(context['page']) + content = @template.render!(context, registers: registers) + if @page_context.has_key?('layout') + find_layout.render(context.merge({'content' => content}), registers) + else + content + end + end +end + +class Tag_tree < Liquid::Tag + def join(children_html) + children_html.empty? ? "" : "
    \n" + children_html.join + "
    \n" + end + + def render(context) + current = context.registers[:page] + site = context.registers[:site] + + format_entry = lambda do |page| + children = page.children + + css = (page == current) ? ' class="active"' : "" + children_html = current.related_to?(page) ? join(children.map(&format_entry)) : "" + + %{ + + #{page.title} + + + #{children_html} + + } + end + + join(site.find_children('/').map(&format_entry)) + end +end + +class Tag_children < Liquid::Tag + def render(context) + children = context.registers[:page].children + entries = children.map {|p| "
  • #{p.title}
  • " } + + "
    +

    This chapter covers the following topics:

    +
      + #{entries.join} +
    +
    + " + end +end + +class Tag_prevnext < Liquid::Tag + def render(context) + site = context.registers[:site] + current = context.registers[:page] + + pages = site.pages.sort_by{ |p| p.sort_url } + + ind = pages.index { |page| page == current } + return '' if !ind + + lnk = lambda do |p, cls, txt| + "
  • #{txt}
  • " + end + prev_link = ind > 0 ? lnk.call(pages[ind-1], "previous", " < Previous ") : "" + next_link = ind < pages.length-1 ? lnk.call(pages[ind+1], "next", " Next > ") : "" + + "
      #{prev_link}#{next_link}
    " + end +end + +Liquid::Template.register_tag('tree', Tag_tree) +Liquid::Template.register_tag('children', Tag_children) +Liquid::Template.register_tag('prevnext', Tag_prevnext) + +Liquid::Template.error_mode = :strict + +Site.new.run diff --git a/source/index.html b/source/index.html index 07dd8c4..2c68f8b 100644 --- a/source/index.html +++ b/source/index.html @@ -1,8 +1,3 @@ ---- -layout: default -title: Welcome to Ardour! ---- -