diff --git a/_layouts/default.html b/_layouts/default.html index 23b9581ac3..423089cd63 100644 --- a/_layouts/default.html +++ b/_layouts/default.html @@ -68,6 +68,7 @@ + {% if page.markdown_url %}{% endif %} diff --git a/_plugins/markdown_alternates.rb b/_plugins/markdown_alternates.rb new file mode 100644 index 0000000000..139896c154 --- /dev/null +++ b/_plugins/markdown_alternates.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true + +# Publishes the Markdown source of every page and news post next to its +# HTML page, so /en/about/ can also be fetched as /en/about.md. The copy +# is the source with the front matter stripped and Liquid evaluated, +# matching what the HTML page was rendered from. +module MarkdownAlternates + FRONT_MATTER = Jekyll::Document::YAML_FRONT_MATTER_REGEXP + + def self.documents(site) + site.pages + site.posts.docs + end + + def self.alternate_url(page) + return unless File.extname(page.relative_path) == ".md" + return unless page.url.end_with?("/") + + page.url == "/" ? "/index.md" : "#{page.url.chomp("/")}.md" + end + + def self.markdown_for(site, page) + raw = File.read(site.in_source_dir(page.path), encoding: "bom|utf-8") + raw = Regexp.last_match.post_match if raw =~ FRONT_MATTER + + payload = site.site_payload + payload["page"] = page.to_liquid + site.liquid_renderer.file(page.path) + .parse(raw) + .render!(payload, registers: { site: site, page: page }) + end +end + +# Runs before generators, so only hand-written pages and posts are +# tagged; pages generated later (news archives) get no alternate. +Jekyll::Hooks.register :site, :post_read do |site| + MarkdownAlternates.documents(site).each do |page| + url = MarkdownAlternates.alternate_url(page) + page.data["markdown_url"] = url if url + end +end + +Jekyll::Hooks.register :site, :post_write do |site| + MarkdownAlternates.documents(site).each do |page| + url = page.data["markdown_url"] + next unless url + + path = site.in_dest_dir(url.delete_prefix("/")) + FileUtils.mkdir_p(File.dirname(path)) + File.write(path, MarkdownAlternates.markdown_for(site, page)) + end +end