Skip to content

Commit

Permalink
Improve how documentation pages are rendered
Browse files Browse the repository at this point in the history
* Extracts an object to encapsulate rendering a given page (which also
  allows us to explicitly test it),
* Allows us to render pages without the YAML frontmatter, which was
  making a mess of the README and Contributing Guide.
  • Loading branch information
nickcharlton committed Nov 13, 2020
1 parent f048ff4 commit 563995c
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 87 deletions.
4 changes: 1 addition & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
---
title: Contributing Guide
---
# Contributing Guide

## Code of Conduct

Expand Down
5 changes: 1 addition & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
---
title: Administrate
home: true
---
# Administrate

[![CircleCI](https://img.shields.io/circleci/project/github/thoughtbot/administrate.svg)](https://circleci.com/gh/thoughtbot/administrate/tree/master)
[![Gem Version](https://badge.fury.io/rb/administrate.svg)](https://badge.fury.io/rb/administrate)
Expand Down
91 changes: 13 additions & 78 deletions spec/example_app/app/controllers/docs_controller.rb
Original file line number Diff line number Diff line change
@@ -1,97 +1,32 @@
class DocsController < ApplicationController
SPECIAL_FILES = [
{
file: 'CONTRIBUTING',
page: 'contributing'
}
].freeze

REDCARPET_CONFIG = {
fenced_code_blocks: true,
autolink: true,
}.freeze

def index
render_page "README"
render_page("README")
end

def show
render_correct_page
end

private

def find_special_file
SPECIAL_FILES.select { |page| page[:page] == params[:page] }.first
end

def render_correct_page
if !find_special_file.nil?
render_page(find_special_file[:file])
case params[:page]
when "contributing"
render_page("CONTRIBUTING", "Contributing Guide")
else
render_page("docs/#{params[:page]}")
end
end

def render_page(name)
path = full_page_path(name)
private

def render_page(name, title = nil)
page = DocPage.find(name)

if File.exist?(path)
contents = parse_document(path)
@page_title = contents.title
@page_title_suffix = contents.title_suffix
if page
title = title || page.title
@page_title = [title, "Administrate"].compact.join(" - ")
# rubocop:disable Rails/OutputSafety
render layout: "docs", html: contents.body.html_safe
render layout: "docs", html: page.body.html_safe
# rubocop:enable Rails/OutputSafety
else
render file: "#{Rails.root}/public/404.html",
render file: Rails.root.join("public", "404.html"),
layout: false,
status: :not_found
end
end

def full_page_path(page)
Rails.root + "../../#{page}.md"
end

def parse_document(path)
text = File.read(path)
DocumentParser.new(text)
end

class DocumentParser
def initialize(source_text)
front_matter_parsed = FrontMatterParser::Parser.new(:md).call(source_text)
@source_text = front_matter_parsed.content
@metadata = front_matter_parsed.front_matter
end

def body
@body ||=
begin
renderer = Redcarpet::Render::HTML
markdown = Redcarpet::Markdown.new(renderer, REDCARPET_CONFIG)

source_text_with_heading = <<~MARKDOWN
# #{title}
#{source_text}
MARKDOWN

markdown.render(source_text_with_heading)
end
end

def title
metadata["title"]
end

def title_suffix
metadata["home"] ? "" : " - Administrate"
end

private

attr_reader :source_text, :metadata
end
end
69 changes: 69 additions & 0 deletions spec/example_app/app/models/doc_page.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
class DocPage
REDCARPET_CONFIG = {
fenced_code_blocks: true,
autolink: true,
}.freeze

class << self
def find(page)
full_path = Rails.root + "../../#{page}.md"

if File.exist?(full_path)
text = File.read(full_path)
new(text)
end
end
end

def initialize(text)
@text = text
end

def title
document.title
end

def body
document.body
end

private

attr_reader :text

def document
@document ||= DocumentParser.new(text)
end

class DocumentParser
def initialize(source_text)
parsed_document = FrontMatterParser::Parser.new(:md).call(source_text)
@source_text = parsed_document.content
@metadata = parsed_document.front_matter
end

def body
@body ||=
begin
renderer = Redcarpet::Render::HTML
markdown = Redcarpet::Markdown.new(renderer, REDCARPET_CONFIG)

source_text_with_heading = <<~MARKDOWN
# #{title}
#{source_text}
MARKDOWN

markdown.render(source_text_with_heading)
end
end

def title
metadata["title"]
end

private

attr_reader :source_text, :metadata
end
end
2 changes: 1 addition & 1 deletion spec/example_app/app/views/layouts/docs.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="utf-8" />
<title><%= @page_title %><%= @page_title_suffix %></title>
<title><%= @page_title %></title>
<%= stylesheet_link_tag "docs", media: "all" %>
<link href='//fonts.googleapis.com/css?family=Lato|Source+Code+Pro|Fjalla+One' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/8.4/styles/default.min.css">
Expand Down
27 changes: 26 additions & 1 deletion spec/features/documentation_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,31 @@
expect(page).to have_http_status(:not_found)
end

it "shows the README" do
visit(root_path)

expect(page).to have_css("h1", text: "Administrate")
expect(page).to have_content(
"A framework for creating flexible, powerful admin dashboards in Rails",
)
end

it "shows the Contributing Guides" do
visit("/contributing")

expect(page).to have_css("h1", text: "Contributing Guide")
expect(page).to have_content(
"We welcome pull requests from everyone.",
)
end

it "shows other docs pages" do
visit("/getting_started")

expect(page).to have_css("h1", text: "Getting Started")
expect(page).to have_content("Administrate is released as a Ruby gem")
end

it "links to each documentation page" do
visit root_path
links = internal_documentation_links
Expand All @@ -19,7 +44,7 @@
end
end

it "links to the Github repo" do
it "links to the GitHub repo" do
visit root_path

expect(github_link[:href]).
Expand Down
34 changes: 34 additions & 0 deletions spec/models/doc_page_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
require "rails_helper"

RSpec.describe DocPage do
describe ".find" do
it "is nil if the page doesn't exist" do
page = DocPage.find("not_a_page")

expect(page).to be_nil
end

it "renders pages without metadata" do
page = DocPage.find("README")

expect(page).to have_attributes(
title: nil,
body: a_string_matching(
/A framework for creating flexible, powerful admin dashboards/,
),
)
end

it "renders pages with metadata" do
page = DocPage.find("docs/getting_started")

expect(page).to have_attributes(
title: "Getting Started",
body: a_string_starting_with(
"<h1>Getting Started</h1>\n\n<p>Administrate is " \
"released as a Ruby gem",
),
)
end
end
end

0 comments on commit 563995c

Please sign in to comment.