documentation 0.0.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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