documentation 0.0.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/images/documentation/link.svg +28 -0
- data/app/assets/images/documentation/logo-black.svg +23 -0
- data/app/assets/images/documentation/logo-white.svg +23 -0
- data/app/assets/images/documentation/page.svg +16 -0
- data/app/assets/images/documentation/pin.svg +15 -0
- data/app/assets/images/documentation/recommendation.svg +11 -0
- data/app/assets/images/documentation/search.svg +10 -0
- data/app/assets/images/documentation/unhappy.svg +15 -0
- data/app/assets/images/documentation/warning.svg +16 -0
- data/app/assets/javascripts/documentation/application.coffee +14 -0
- data/app/assets/javascripts/documentation/jquery-ui.js +4146 -0
- data/app/assets/javascripts/documentation/jquery.autosize.js +263 -0
- data/app/assets/stylesheets/documentation/application.scss +320 -0
- data/app/assets/stylesheets/documentation/markdown.scss +168 -0
- data/app/assets/stylesheets/documentation/page_form.scss +38 -0
- data/app/assets/stylesheets/documentation/reset.scss +101 -0
- data/app/controllers/documentation/application_controller.rb +21 -0
- data/app/controllers/documentation/pages_controller.rb +74 -0
- data/app/helpers/documentation/application_helper.rb +13 -0
- data/app/models/documentation/page.rb +213 -0
- data/app/views/documentation/pages/_admin_buttons.html.haml +18 -0
- data/app/views/documentation/pages/form.html.haml +12 -0
- data/app/views/documentation/pages/index.html.haml +13 -0
- data/app/views/documentation/pages/positioning.html.haml +22 -0
- data/app/views/documentation/pages/search.html.haml +26 -0
- data/app/views/documentation/pages/show.html.haml +14 -0
- data/app/views/documentation/shared/access_denied.html.haml +10 -0
- data/app/views/documentation/shared/not_found.html.haml +10 -0
- data/app/views/layouts/documentation/_header.html.haml +3 -0
- data/app/views/layouts/documentation/_search.html.haml +5 -0
- data/app/views/layouts/documentation/application.html.haml +18 -0
- data/config/locales/en.yml +56 -0
- data/config/routes.rb +10 -0
- data/db/migrate/20140711185212_create_documentation_pages.rb +10 -0
- data/db/seeds.rb +15 -0
- data/lib/documentation.rb +16 -0
- data/lib/documentation/authorizer.rb +52 -0
- data/lib/documentation/config.rb +31 -0
- data/lib/documentation/engine.rb +29 -0
- data/lib/documentation/errors.rb +7 -0
- data/lib/documentation/generators/setup_generator.rb +13 -0
- data/lib/documentation/markdown_renderer.rb +62 -0
- data/lib/documentation/search_result.rb +84 -0
- data/lib/documentation/searchers/abstract.rb +47 -0
- data/lib/documentation/searchers/simple.rb +40 -0
- data/lib/documentation/version.rb +1 -1
- data/lib/documentation/view_helpers.rb +113 -0
- data/lib/tasks/documentation.rake +6 -0
- metadata +219 -3
@@ -0,0 +1,18 @@
|
|
1
|
+
- canAdd = authorizer.can_add_page?(@page)
|
2
|
+
- canEdit = authorizer.can_edit_page?(@page)
|
3
|
+
- canReposition = authorizer.can_reposition_page?(@page)
|
4
|
+
- canDelete = authorizer.can_delete_page?(@page)
|
5
|
+
|
6
|
+
- if canAdd || canEdit || canReposition || canDelete
|
7
|
+
%p.adminButtons
|
8
|
+
- if canAdd
|
9
|
+
= link_to t('.new'), new_page_path(@page.full_permalink), :class => 'button new'
|
10
|
+
|
11
|
+
- if canEdit
|
12
|
+
= link_to t('.edit'), edit_page_path(@page.full_permalink), :class => 'button edit'
|
13
|
+
|
14
|
+
- if canReposition
|
15
|
+
= link_to t('.reorder'), page_positioning_path(@page.parents[-1].try(:full_permalink)), :class => 'button edit'
|
16
|
+
|
17
|
+
- if canDelete
|
18
|
+
= link_to t('.delete'), delete_page_path(@page.full_permalink), :class => 'button delete', :method => :delete, :data => {:confirm => "Are you sure you wish to remove this page?"}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
- @page_title = @page.breadcrumb.reverse.map(&:title).join(" - ")
|
2
|
+
|
3
|
+
%section.content
|
4
|
+
= documentation_breadcrumb_for @page
|
5
|
+
= form_for @page, :url => @page.new_record? ? new_page_path(@page.parent ? @page.parent.full_permalink : nil) : edit_page_path(@page.full_permalink), :html => {:class => 'pageForm'} do |f|
|
6
|
+
= error_messages_for @page
|
7
|
+
%p.title= f.text_field :title, :placeholder => t('.title_placeholder')
|
8
|
+
%p.content= f.text_area :content, :placeholder => t('.content_placeholder')
|
9
|
+
%dl
|
10
|
+
%dt= f.label :permalink
|
11
|
+
%dd= f.text_field :permalink, :placeholder => t('.permalink_placeholder')
|
12
|
+
%p.submit= f.submit t('.save'), :class => 'button'
|
@@ -0,0 +1,13 @@
|
|
1
|
+
%section.welcome
|
2
|
+
%h1= t('.welcome_title')
|
3
|
+
%h2= t('.welcome_text')
|
4
|
+
|
5
|
+
- if Documentation.config.developer_tips
|
6
|
+
.override
|
7
|
+
%p= t('.developer_tip').html_safe
|
8
|
+
|
9
|
+
%p.new
|
10
|
+
- if authorizer.can_add_page?(nil)
|
11
|
+
= link_to t('.create_root_page'), new_page_path, :class => 'button new'
|
12
|
+
- if authorizer.can_reposition_page?(nil)
|
13
|
+
= link_to t('.reorder_root_pages'), page_positioning_path, :class => 'button'
|
@@ -0,0 +1,22 @@
|
|
1
|
+
- if @page
|
2
|
+
- @page_title = @page.breadcrumb.reverse.map(&:title).join(" - ")
|
3
|
+
= documentation_breadcrumb_for @page
|
4
|
+
- else
|
5
|
+
- @page_title = t('.reorder_root_pages_title')
|
6
|
+
= documentation_breadcrumb_for nil
|
7
|
+
|
8
|
+
%section.page
|
9
|
+
%h1= @page ? @page.title : t('.reorder_root_pages_title')
|
10
|
+
|
11
|
+
= form_tag page_positioning_path(@page.try(:full_permalink)), :class => 'reordering' do
|
12
|
+
%ul
|
13
|
+
- for child in @pages
|
14
|
+
%li
|
15
|
+
= child.title
|
16
|
+
= hidden_field_tag 'order[]', child.id
|
17
|
+
|
18
|
+
%p.adminButtons
|
19
|
+
- if @page
|
20
|
+
= link_to t('.back_to_page'), page_path(@page.full_permalink), :class => 'button edit'
|
21
|
+
- else
|
22
|
+
= link_to t('.back_to_homepage'), root_path, :class => 'button edit'
|
@@ -0,0 +1,26 @@
|
|
1
|
+
- @page_title = t('.title', :query => params[:query])
|
2
|
+
|
3
|
+
%section.page
|
4
|
+
|
5
|
+
- if @result.empty?
|
6
|
+
%p.noSearchResults= t('.no_results', :query => params[:query])
|
7
|
+
- else
|
8
|
+
%h1= t('.title', :query => params[:query])
|
9
|
+
%p.searchSummary= t('.summary', :total_results => @result.total_results, :start_result => @result.start_result_number, :end_result => @result.end_result_number)
|
10
|
+
|
11
|
+
%ul.searchResults
|
12
|
+
- for page in @result.results
|
13
|
+
%li
|
14
|
+
%h4= link_to page.title, page_path(page.full_permalink)
|
15
|
+
- unless page.parents.empty?
|
16
|
+
%p.in
|
17
|
+
= t('.in')
|
18
|
+
= page.parents.map { |c| link_to(h(c.title), page_path(c.full_permalink))}.join(" ⇒ ").html_safe
|
19
|
+
%p.excerpt= @result.excerpt_for(page)
|
20
|
+
|
21
|
+
|
22
|
+
%p.pagination
|
23
|
+
- unless @result.first_page?
|
24
|
+
= link_to t('.previous_page'), search_path(:query => params[:query], :page => @result.page - 1), :class => 'button'
|
25
|
+
- unless @result.last_page?
|
26
|
+
= link_to t('.next_page'), search_path(:query => params[:query], :page => @result.page + 1), :class => 'button'
|
@@ -0,0 +1,14 @@
|
|
1
|
+
- @page_title = @page.breadcrumb.reverse.map(&:title).join(" - ")
|
2
|
+
|
3
|
+
= documentation_breadcrumb_for @page
|
4
|
+
|
5
|
+
%section.page
|
6
|
+
- if @page.preview_path
|
7
|
+
%p.previewLink= link_to t('.view_in_website'), @page.preview_path, :class => 'button preview'
|
8
|
+
|
9
|
+
%h1= @page.title
|
10
|
+
%p.updated= t('.last_updated', :timestamp => @page.updated_at.to_s(:long))
|
11
|
+
.documentationMarkdown
|
12
|
+
~ preserve(documentation_content_for(@page))
|
13
|
+
|
14
|
+
= render 'admin_buttons'
|
@@ -0,0 +1,10 @@
|
|
1
|
+
!!!
|
2
|
+
%html.errorPage
|
3
|
+
%head
|
4
|
+
%title= @page_title
|
5
|
+
= stylesheet_link_tag 'documentation/application'
|
6
|
+
= csrf_meta_tags
|
7
|
+
%body
|
8
|
+
%section.errorMessage
|
9
|
+
%h2 Access Denied
|
10
|
+
%p You are not permitted to view this page. If you believe you have received this message in error, please contact the site admin.
|
@@ -0,0 +1,10 @@
|
|
1
|
+
!!!
|
2
|
+
%html.errorPage
|
3
|
+
%head
|
4
|
+
%title= @page_title
|
5
|
+
= stylesheet_link_tag 'documentation/application'
|
6
|
+
= csrf_meta_tags
|
7
|
+
%body
|
8
|
+
%section.errorMessage
|
9
|
+
%h2 Page Not Found
|
10
|
+
%p No page was found at the path you have entered. Please ensure you have entered the correct URL otherwise contact the site admin.
|
@@ -0,0 +1,18 @@
|
|
1
|
+
!!!
|
2
|
+
%html
|
3
|
+
%head
|
4
|
+
%title #{@page_title} - #{t('.title')}
|
5
|
+
= stylesheet_link_tag 'documentation/application'
|
6
|
+
= javascript_include_tag 'documentation/application'
|
7
|
+
= csrf_meta_tags
|
8
|
+
%body
|
9
|
+
= render 'layouts/documentation/header'
|
10
|
+
%nav.pages
|
11
|
+
.inner
|
12
|
+
= render 'layouts/documentation/search'
|
13
|
+
= documentation_navigation_tree_for(@page)
|
14
|
+
%section.content
|
15
|
+
.inner
|
16
|
+
= flash_messages
|
17
|
+
= yield
|
18
|
+
|
@@ -0,0 +1,56 @@
|
|
1
|
+
en:
|
2
|
+
layouts:
|
3
|
+
documentation:
|
4
|
+
application:
|
5
|
+
title: Documentation
|
6
|
+
header:
|
7
|
+
title: Documentation
|
8
|
+
back_to_site: Back to site
|
9
|
+
search:
|
10
|
+
query_placeholder: Search Documentation...
|
11
|
+
|
12
|
+
documentation:
|
13
|
+
|
14
|
+
helpers:
|
15
|
+
documentation_breadcrumb_for:
|
16
|
+
default_root_link: Home
|
17
|
+
|
18
|
+
pages:
|
19
|
+
index:
|
20
|
+
welcome_title: Welcome to Documentation
|
21
|
+
welcome_text: Choose a page from the menu on the left of the screen to begin.
|
22
|
+
developer_tip:
|
23
|
+
You can override this page by adding a new view in <code>app/views/documentation/pages/index</code>.
|
24
|
+
Alternatively, you can disable this message by setting <code>developer_tips</code> to false in the
|
25
|
+
Documentation configuration.
|
26
|
+
create_root_page: Create new root page
|
27
|
+
reorder_root_pages: Re-order root pages
|
28
|
+
|
29
|
+
show:
|
30
|
+
view_in_website: View in website
|
31
|
+
last_updated: Last updated on %{timestamp}
|
32
|
+
|
33
|
+
admin_buttons:
|
34
|
+
new: New page
|
35
|
+
edit: Edit page
|
36
|
+
reorder: Re-order children
|
37
|
+
delete: Delete page
|
38
|
+
|
39
|
+
form:
|
40
|
+
title_placeholder: Enter a title for this page
|
41
|
+
content_placeholder: 'Use Markdown to enter page content'
|
42
|
+
permalink_placeholder: Automatically generated if left blank
|
43
|
+
save: Save Page
|
44
|
+
|
45
|
+
positioning:
|
46
|
+
reorder_root_pages_title: Re-order root pages
|
47
|
+
back_to_page: Back to page
|
48
|
+
back_to_homepage: Back to homepage
|
49
|
+
|
50
|
+
search:
|
51
|
+
title: "Search results for '%{query}'"
|
52
|
+
no_results: "No pages were found matching '%{query}'"
|
53
|
+
summary: "Found %{total_results} pages matching your query. Showing results %{start_result} to %{end_result}"
|
54
|
+
in: in
|
55
|
+
next_page: Next page
|
56
|
+
previous_page: Previous page
|
data/config/routes.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
Documentation::Engine.routes.draw do
|
2
|
+
|
3
|
+
match 'new(/*path)', :to => 'pages#new', :as => 'new_page', :via => [:get, :post]
|
4
|
+
match 'positioning(/*path)', :to => 'pages#positioning', :as => 'page_positioning', :via => [:get, :post]
|
5
|
+
match 'edit(/*path)', :to => 'pages#edit', :as => 'edit_page', :via => [:get, :patch]
|
6
|
+
match 'delete(/*path)', :to => 'pages#destroy', :as => 'delete_page', :via => [:delete]
|
7
|
+
get 'search', :to => 'pages#search', :as => 'search'
|
8
|
+
get '*path' => 'pages#show', :as => 'page'
|
9
|
+
root :to => 'pages#index'
|
10
|
+
end
|
data/db/seeds.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
$doc_root = File.join(File.expand_path(File.join('..', '..'), __FILE__), 'doc')
|
2
|
+
|
3
|
+
def doc(*path)
|
4
|
+
File.read(File.join($doc_root, *path))
|
5
|
+
end
|
6
|
+
|
7
|
+
guide = Documentation::Page.create(:title => "Developers' Guide", :content => doc('developers-guide', 'overview.md'))
|
8
|
+
guide.children.create(:title => 'Authorization', :content => doc('developers-guide', 'authorization.md'))
|
9
|
+
guide.children.create(:title => 'Search Backends', :content => doc('developers-guide', 'search-backends.md'))
|
10
|
+
guide.children.create(:title => 'Customization', :content => doc('developers-guide', 'customization.md'))
|
11
|
+
views = guide.children.create(:title => 'Building your own views', :content => doc('developers-guide', 'building-views', 'overview.md'))
|
12
|
+
views.children.create(:title => 'Accessing Pages', :content => doc('developers-guide', 'building-views', 'accessing-pages.md'))
|
13
|
+
views.children.create(:title => 'Helpers', :content => doc('developers-guide', 'building-views', 'helpers.md'))
|
14
|
+
|
15
|
+
markdown = Documentation::Page.create(:title => "Using Markdown", :content => doc('markdown', 'overview.md'))
|
data/lib/documentation.rb
CHANGED
@@ -1,2 +1,18 @@
|
|
1
|
+
require 'haml'
|
2
|
+
require 'coffee-rails'
|
3
|
+
require 'sass-rails'
|
4
|
+
require 'jquery-rails'
|
5
|
+
require 'dynamic_form'
|
6
|
+
require 'ostruct'
|
7
|
+
|
8
|
+
require 'documentation/version'
|
9
|
+
require 'documentation/errors'
|
10
|
+
require 'documentation/engine'
|
11
|
+
require 'documentation/markdown_renderer'
|
12
|
+
require 'documentation/view_helpers'
|
13
|
+
require 'documentation/searchers/abstract'
|
14
|
+
require 'documentation/search_result'
|
15
|
+
require 'documentation/config'
|
16
|
+
|
1
17
|
module Documentation
|
2
18
|
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Documentation
|
2
|
+
class Authorizer
|
3
|
+
|
4
|
+
def initialize(controller)
|
5
|
+
@controller = controller
|
6
|
+
end
|
7
|
+
|
8
|
+
def can_view_page?(page)
|
9
|
+
true
|
10
|
+
end
|
11
|
+
|
12
|
+
def can_add_page?(page)
|
13
|
+
true
|
14
|
+
end
|
15
|
+
|
16
|
+
def can_reposition_page?(page)
|
17
|
+
true
|
18
|
+
end
|
19
|
+
|
20
|
+
def can_delete_page?(page)
|
21
|
+
true
|
22
|
+
end
|
23
|
+
|
24
|
+
def can_edit_page?(page)
|
25
|
+
true
|
26
|
+
end
|
27
|
+
|
28
|
+
def can_search?
|
29
|
+
true
|
30
|
+
end
|
31
|
+
|
32
|
+
def check!(action, object = :none)
|
33
|
+
action_method_name = "can_#{action}?"
|
34
|
+
if self.respond_to?(action_method_name)
|
35
|
+
result = object == :none ? self.send(action_method_name) : self.send(action_method_name, object)
|
36
|
+
if result != true
|
37
|
+
raise Documentation::AccessDeniedError, "You are not permitted to perform this action."
|
38
|
+
end
|
39
|
+
else
|
40
|
+
raise Documentation::Error, "Invalid authorizer check (#{action})"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def request
|
47
|
+
controller.request
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'documentation/authorizer'
|
2
|
+
require 'documentation/searchers/simple'
|
3
|
+
|
4
|
+
module Documentation
|
5
|
+
|
6
|
+
#
|
7
|
+
# Sets the default configuration
|
8
|
+
#
|
9
|
+
DEFAULT_CONFIGURATION = {
|
10
|
+
# This defines the at path where a page can be viewed in
|
11
|
+
# the source website. For example, /docs/
|
12
|
+
:preview_path_prefix => nil,
|
13
|
+
|
14
|
+
# Should we display developer tips in the UI?
|
15
|
+
:developer_tips => true,
|
16
|
+
|
17
|
+
# The authorizer to use
|
18
|
+
:authorizer => Documentation::Authorizer,
|
19
|
+
|
20
|
+
# The searcher to use
|
21
|
+
:searcher => Documentation::Searchers::Simple.new
|
22
|
+
}
|
23
|
+
|
24
|
+
#
|
25
|
+
# Return configuration options
|
26
|
+
#
|
27
|
+
def self.config
|
28
|
+
@config ||= OpenStruct.new(DEFAULT_CONFIGURATION)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Documentation
|
2
|
+
class Engine < Rails::Engine
|
3
|
+
|
4
|
+
isolate_namespace Documentation
|
5
|
+
|
6
|
+
initializer 'shoppe.initialize' do |app|
|
7
|
+
|
8
|
+
config.paths["db/migrate"].expanded.each do |expanded_path|
|
9
|
+
app.config.paths["db/migrate"] << expanded_path
|
10
|
+
end
|
11
|
+
|
12
|
+
# Load view helpers for the base application
|
13
|
+
ActiveSupport.on_load(:action_view) do
|
14
|
+
ActionView::Base.send :include, Documentation::ViewHelpers
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
generators do
|
19
|
+
require 'documentation/generators/setup_generator'
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.mounted_path
|
23
|
+
if route = Rails.application.routes.routes.select { |r| r.app == self }.first
|
24
|
+
route.path.spec.to_s
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'redcarpet'
|
2
|
+
require 'pygments'
|
3
|
+
|
4
|
+
module Documentation
|
5
|
+
class MarkdownRenderer < Redcarpet::Render::HTML
|
6
|
+
|
7
|
+
attr_accessor :page
|
8
|
+
|
9
|
+
include ActionView::Helpers::TagHelper
|
10
|
+
|
11
|
+
def block_code(code, language)
|
12
|
+
title = nil
|
13
|
+
code.gsub!(/\A\:\:(.*)$/) { title = $1 ; nil }
|
14
|
+
String.new.tap do |s|
|
15
|
+
s << "<p class='codeTitle'>#{title}</p>" if title
|
16
|
+
s << Pygments.highlight(code, :lexer => language)
|
17
|
+
end
|
18
|
+
rescue
|
19
|
+
"<div class='highlight'><pre>#{code}</pre></div>"
|
20
|
+
end
|
21
|
+
|
22
|
+
def link(link, title, content)
|
23
|
+
if link =~ /\A\^/
|
24
|
+
case link
|
25
|
+
when /\A\^\.\/(.*)/
|
26
|
+
# ^./pagename
|
27
|
+
# Links to pages on the same level as the current page
|
28
|
+
link = "{{docRoot}}/#{page.parents.map(&:permalink).join('/')}/#{$1}"
|
29
|
+
when /\A\^\/(.*)/
|
30
|
+
# ^/full/path
|
31
|
+
# Links to a page frmo the root of the docs
|
32
|
+
link = "{{docRoot}}/#{$1}"
|
33
|
+
when /\A\^(.*)/
|
34
|
+
# ^child/item
|
35
|
+
# Links to a child of the current page
|
36
|
+
link = "{{docRoot}}/#{page.full_permalink}/#{$1}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
"<a href='#{link}' title='#{title}'>#{content}</a>"
|
40
|
+
end
|
41
|
+
|
42
|
+
def image(src, title, alt)
|
43
|
+
if alt.gsub!(/\*([\w\-\s]+)\z/, '')
|
44
|
+
klass = "imgcontainer #{$1}"
|
45
|
+
else
|
46
|
+
klass = nil
|
47
|
+
end
|
48
|
+
content_tag :span, tag(:img, :src => src, :title => title, :alt => alt), :class => klass
|
49
|
+
end
|
50
|
+
|
51
|
+
def paragraph(text)
|
52
|
+
klass = ''
|
53
|
+
text.gsub!(/\A(\w+)\:/) do
|
54
|
+
klass = $1
|
55
|
+
nil
|
56
|
+
end
|
57
|
+
text.sub!(/ ([^ ]+)$/, ' \1')
|
58
|
+
"<p class='#{klass.downcase}'>#{text}</p>"
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|