documentation 0.0.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/images/documentation/link.svg +28 -0
  3. data/app/assets/images/documentation/logo-black.svg +23 -0
  4. data/app/assets/images/documentation/logo-white.svg +23 -0
  5. data/app/assets/images/documentation/page.svg +16 -0
  6. data/app/assets/images/documentation/pin.svg +15 -0
  7. data/app/assets/images/documentation/recommendation.svg +11 -0
  8. data/app/assets/images/documentation/search.svg +10 -0
  9. data/app/assets/images/documentation/unhappy.svg +15 -0
  10. data/app/assets/images/documentation/warning.svg +16 -0
  11. data/app/assets/javascripts/documentation/application.coffee +14 -0
  12. data/app/assets/javascripts/documentation/jquery-ui.js +4146 -0
  13. data/app/assets/javascripts/documentation/jquery.autosize.js +263 -0
  14. data/app/assets/stylesheets/documentation/application.scss +320 -0
  15. data/app/assets/stylesheets/documentation/markdown.scss +168 -0
  16. data/app/assets/stylesheets/documentation/page_form.scss +38 -0
  17. data/app/assets/stylesheets/documentation/reset.scss +101 -0
  18. data/app/controllers/documentation/application_controller.rb +21 -0
  19. data/app/controllers/documentation/pages_controller.rb +74 -0
  20. data/app/helpers/documentation/application_helper.rb +13 -0
  21. data/app/models/documentation/page.rb +213 -0
  22. data/app/views/documentation/pages/_admin_buttons.html.haml +18 -0
  23. data/app/views/documentation/pages/form.html.haml +12 -0
  24. data/app/views/documentation/pages/index.html.haml +13 -0
  25. data/app/views/documentation/pages/positioning.html.haml +22 -0
  26. data/app/views/documentation/pages/search.html.haml +26 -0
  27. data/app/views/documentation/pages/show.html.haml +14 -0
  28. data/app/views/documentation/shared/access_denied.html.haml +10 -0
  29. data/app/views/documentation/shared/not_found.html.haml +10 -0
  30. data/app/views/layouts/documentation/_header.html.haml +3 -0
  31. data/app/views/layouts/documentation/_search.html.haml +5 -0
  32. data/app/views/layouts/documentation/application.html.haml +18 -0
  33. data/config/locales/en.yml +56 -0
  34. data/config/routes.rb +10 -0
  35. data/db/migrate/20140711185212_create_documentation_pages.rb +10 -0
  36. data/db/seeds.rb +15 -0
  37. data/lib/documentation.rb +16 -0
  38. data/lib/documentation/authorizer.rb +52 -0
  39. data/lib/documentation/config.rb +31 -0
  40. data/lib/documentation/engine.rb +29 -0
  41. data/lib/documentation/errors.rb +7 -0
  42. data/lib/documentation/generators/setup_generator.rb +13 -0
  43. data/lib/documentation/markdown_renderer.rb +62 -0
  44. data/lib/documentation/search_result.rb +84 -0
  45. data/lib/documentation/searchers/abstract.rb +47 -0
  46. data/lib/documentation/searchers/simple.rb +40 -0
  47. data/lib/documentation/version.rb +1 -1
  48. data/lib/documentation/view_helpers.rb +113 -0
  49. data/lib/tasks/documentation.rake +6 -0
  50. 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,3 @@
1
+ %header
2
+ %h1= link_to t('.title'), root_path
3
+ %p.back= link_to "← #{t('.back_to_site')}".html_safe, "/", :class => ''
@@ -0,0 +1,5 @@
1
+ - if authorizer.can_search?
2
+ = form_tag search_path, :method => :get do
3
+ %p.searchForm
4
+ = text_field_tag 'query', params[:query], :placeholder => t('.query_placeholder')
5
+
@@ -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
@@ -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
@@ -0,0 +1,10 @@
1
+ class CreateDocumentationPages < ActiveRecord::Migration
2
+ def up
3
+ create_table "documentation_pages" do |t|
4
+ t.string :title, :permalink
5
+ t.text :content, :compiled_content
6
+ t.integer :parent_id, :position
7
+ t.timestamps
8
+ end
9
+ end
10
+ end
@@ -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'))
@@ -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,7 @@
1
+ module Documentation
2
+ class Error < StandardError
3
+ end
4
+
5
+ class AccessDeniedError < Error
6
+ end
7
+ end
@@ -0,0 +1,13 @@
1
+ require 'rails/generators'
2
+
3
+ module Documentation
4
+ module Generators
5
+ class SetupGenerator < Rails::Generators::Base
6
+
7
+ def create_route
8
+ route 'mount Documentation::Engine => "/docs"'
9
+ end
10
+
11
+ end
12
+ end
13
+ 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!(/ ([^ ]+)$/, '&nbsp;\1')
58
+ "<p class='#{klass.downcase}'>#{text}</p>"
59
+ end
60
+
61
+ end
62
+ end