├── .gitignore ├── .rubocop.yml ├── Gemfile ├── Gemfile.lock ├── MIT-LICENSE ├── README.md ├── app ├── assets │ ├── images │ │ └── documentation │ │ │ ├── link.svg │ │ │ ├── logo-black.svg │ │ │ ├── logo-white.svg │ │ │ ├── page.svg │ │ │ ├── pin.svg │ │ │ ├── recommendation.svg │ │ │ ├── search.svg │ │ │ ├── unhappy.svg │ │ │ └── warning.svg │ ├── javascripts │ │ └── documentation │ │ │ ├── application.coffee │ │ │ ├── jquery-ui.js │ │ │ └── jquery.autosize.js │ └── stylesheets │ │ └── documentation │ │ ├── application.scss │ │ ├── markdown.scss │ │ ├── page_form.scss │ │ └── reset.scss ├── controllers │ └── documentation │ │ ├── application_controller.rb │ │ └── pages_controller.rb ├── helpers │ └── documentation │ │ └── application_helper.rb ├── models │ └── documentation │ │ ├── page.rb │ │ └── screenshot.rb └── views │ ├── documentation │ ├── pages │ │ ├── _admin_buttons.html.haml │ │ ├── form.html.haml │ │ ├── index.html.haml │ │ ├── positioning.html.haml │ │ ├── screenshot.html.haml │ │ ├── search.html.haml │ │ └── show.html.haml │ └── shared │ │ ├── access_denied.html.haml │ │ └── not_found.html.haml │ └── layouts │ └── documentation │ ├── _footer.html.haml │ ├── _head.html.haml │ ├── _header.html.haml │ ├── _search.html.haml │ └── application.html.haml ├── config ├── locales │ └── en.yml └── routes.rb ├── db ├── migrate │ ├── 20140711185212_create_documentation_pages.rb │ ├── 20140724111844_create_nifty_attachments_table.rb │ └── 20140724114255_create_documentation_screenshots.rb └── seeds.rb ├── doc ├── developers-guide │ ├── authorization.md │ ├── building-views │ │ ├── accessing-pages.md │ │ ├── helpers.md │ │ └── overview.md │ ├── customization.md │ ├── overview.md │ └── search-backends.md └── markdown │ └── overview.md ├── documentation.gemspec ├── lib ├── documentation.rb ├── documentation │ ├── authorizer.rb │ ├── config.rb │ ├── engine.rb │ ├── errors.rb │ ├── generators │ │ └── setup_generator.rb │ ├── markdown_renderer.rb │ ├── search_result.rb │ ├── searchers │ │ ├── abstract.rb │ │ └── simple.rb │ ├── version.rb │ └── view_helpers.rb └── tasks │ └── documentation.rake └── test ├── .gitignore ├── Rakefile ├── app ├── assets │ ├── images │ │ └── .keep │ ├── javascripts │ │ └── application.js │ └── stylesheets │ │ └── application.css ├── controllers │ ├── application_controller.rb │ └── concerns │ │ └── .keep ├── helpers │ └── application_helper.rb ├── mailers │ └── .keep ├── models │ ├── .keep │ └── concerns │ │ └── .keep └── views │ └── layouts │ └── application.html.erb ├── bin ├── bundle ├── rails ├── rake └── spring ├── config.ru ├── config ├── application.rb ├── boot.rb ├── database.yml ├── environment.rb ├── environments │ ├── development.rb │ ├── production.rb │ └── test.rb ├── initializers │ ├── assets.rb │ ├── backtrace_silencers.rb │ ├── cookies_serializer.rb │ ├── filter_parameter_logging.rb │ ├── inflections.rb │ ├── mime_types.rb │ ├── session_store.rb │ └── wrap_parameters.rb ├── locales │ └── en.yml ├── routes.rb └── secrets.yml ├── db └── schema.rb ├── lib └── assets │ └── .keep ├── log └── .keep └── public ├── 404.html ├── 422.html ├── 500.html ├── favicon.ico └── robots.txt /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | test/db/*.sqlite3 3 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | inherit_from: 2 | - https://dev.k.io/rubocop.yml 3 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | gemspec 3 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: . 3 | specs: 4 | documentation (2.0.0) 5 | coffee-rails (>= 5) 6 | dynamic_form (~> 1.1.4) 7 | haml (>= 4.0) 8 | jquery-rails (>= 3.0) 9 | nifty-attachments (>= 1.0.3) 10 | nifty-dialog (~> 1) 11 | pygments.rb (>= 0.5) 12 | rails (>= 6.0, < 7.0) 13 | redcarpet (>= 3.1.0) 14 | sass-rails (>= 4.0) 15 | uglifier (>= 2.2) 16 | 17 | GEM 18 | remote: https://rubygems.org/ 19 | specs: 20 | actioncable (6.0.2.2) 21 | actionpack (= 6.0.2.2) 22 | nio4r (~> 2.0) 23 | websocket-driver (>= 0.6.1) 24 | actionmailbox (6.0.2.2) 25 | actionpack (= 6.0.2.2) 26 | activejob (= 6.0.2.2) 27 | activerecord (= 6.0.2.2) 28 | activestorage (= 6.0.2.2) 29 | activesupport (= 6.0.2.2) 30 | mail (>= 2.7.1) 31 | actionmailer (6.0.2.2) 32 | actionpack (= 6.0.2.2) 33 | actionview (= 6.0.2.2) 34 | activejob (= 6.0.2.2) 35 | mail (~> 2.5, >= 2.5.4) 36 | rails-dom-testing (~> 2.0) 37 | actionpack (6.0.2.2) 38 | actionview (= 6.0.2.2) 39 | activesupport (= 6.0.2.2) 40 | rack (~> 2.0, >= 2.0.8) 41 | rack-test (>= 0.6.3) 42 | rails-dom-testing (~> 2.0) 43 | rails-html-sanitizer (~> 1.0, >= 1.2.0) 44 | actiontext (6.0.2.2) 45 | actionpack (= 6.0.2.2) 46 | activerecord (= 6.0.2.2) 47 | activestorage (= 6.0.2.2) 48 | activesupport (= 6.0.2.2) 49 | nokogiri (>= 1.8.5) 50 | actionview (6.0.2.2) 51 | activesupport (= 6.0.2.2) 52 | builder (~> 3.1) 53 | erubi (~> 1.4) 54 | rails-dom-testing (~> 2.0) 55 | rails-html-sanitizer (~> 1.1, >= 1.2.0) 56 | activejob (6.0.2.2) 57 | activesupport (= 6.0.2.2) 58 | globalid (>= 0.3.6) 59 | activemodel (6.0.2.2) 60 | activesupport (= 6.0.2.2) 61 | activerecord (6.0.2.2) 62 | activemodel (= 6.0.2.2) 63 | activesupport (= 6.0.2.2) 64 | activestorage (6.0.2.2) 65 | actionpack (= 6.0.2.2) 66 | activejob (= 6.0.2.2) 67 | activerecord (= 6.0.2.2) 68 | marcel (~> 0.3.1) 69 | activesupport (6.0.2.2) 70 | concurrent-ruby (~> 1.0, >= 1.0.2) 71 | i18n (>= 0.7, < 2) 72 | minitest (~> 5.1) 73 | tzinfo (~> 1.1) 74 | zeitwerk (~> 2.2) 75 | builder (3.2.4) 76 | coffee-rails (5.0.0) 77 | coffee-script (>= 2.2.0) 78 | railties (>= 5.2.0) 79 | coffee-script (2.4.1) 80 | coffee-script-source 81 | execjs 82 | coffee-script-source (1.12.2) 83 | concurrent-ruby (1.1.6) 84 | crass (1.0.6) 85 | dynamic_form (1.1.4) 86 | erubi (1.9.0) 87 | execjs (2.7.0) 88 | ffi (1.12.2) 89 | globalid (0.4.2) 90 | activesupport (>= 4.2.0) 91 | haml (5.1.2) 92 | temple (>= 0.8.0) 93 | tilt 94 | i18n (1.8.2) 95 | concurrent-ruby (~> 1.0) 96 | jquery-rails (4.3.5) 97 | rails-dom-testing (>= 1, < 3) 98 | railties (>= 4.2.0) 99 | thor (>= 0.14, < 2.0) 100 | loofah (2.5.0) 101 | crass (~> 1.0.2) 102 | nokogiri (>= 1.5.9) 103 | mail (2.7.1) 104 | mini_mime (>= 0.1.1) 105 | marcel (0.3.3) 106 | mimemagic (~> 0.3.2) 107 | method_source (1.0.0) 108 | mimemagic (0.3.4) 109 | mini_mime (1.0.2) 110 | mini_portile2 (2.4.0) 111 | minitest (5.14.0) 112 | multi_json (1.14.1) 113 | nifty-attachments (1.0.4) 114 | nifty-dialog (1.1.1) 115 | nio4r (2.5.2) 116 | nokogiri (1.10.9) 117 | mini_portile2 (~> 2.4.0) 118 | pygments.rb (1.2.1) 119 | multi_json (>= 1.0.0) 120 | rack (2.2.2) 121 | rack-test (1.1.0) 122 | rack (>= 1.0, < 3) 123 | rails (6.0.2.2) 124 | actioncable (= 6.0.2.2) 125 | actionmailbox (= 6.0.2.2) 126 | actionmailer (= 6.0.2.2) 127 | actionpack (= 6.0.2.2) 128 | actiontext (= 6.0.2.2) 129 | actionview (= 6.0.2.2) 130 | activejob (= 6.0.2.2) 131 | activemodel (= 6.0.2.2) 132 | activerecord (= 6.0.2.2) 133 | activestorage (= 6.0.2.2) 134 | activesupport (= 6.0.2.2) 135 | bundler (>= 1.3.0) 136 | railties (= 6.0.2.2) 137 | sprockets-rails (>= 2.0.0) 138 | rails-dom-testing (2.0.3) 139 | activesupport (>= 4.2.0) 140 | nokogiri (>= 1.6) 141 | rails-html-sanitizer (1.3.0) 142 | loofah (~> 2.3) 143 | railties (6.0.2.2) 144 | actionpack (= 6.0.2.2) 145 | activesupport (= 6.0.2.2) 146 | method_source 147 | rake (>= 0.8.7) 148 | thor (>= 0.20.3, < 2.0) 149 | rake (13.0.1) 150 | redcarpet (3.5.0) 151 | sass-rails (6.0.0) 152 | sassc-rails (~> 2.1, >= 2.1.1) 153 | sassc (2.3.0) 154 | ffi (~> 1.9) 155 | sassc-rails (2.1.2) 156 | railties (>= 4.0.0) 157 | sassc (>= 2.0) 158 | sprockets (> 3.0) 159 | sprockets-rails 160 | tilt 161 | sprockets (4.0.0) 162 | concurrent-ruby (~> 1.0) 163 | rack (> 1, < 3) 164 | sprockets-rails (3.2.1) 165 | actionpack (>= 4.0) 166 | activesupport (>= 4.0) 167 | sprockets (>= 3.0.0) 168 | sqlite3 (1.3.9) 169 | temple (0.8.2) 170 | thor (1.0.1) 171 | thread_safe (0.3.6) 172 | tilt (2.0.10) 173 | tzinfo (1.2.7) 174 | thread_safe (~> 0.1) 175 | uglifier (4.2.0) 176 | execjs (>= 0.3.0, < 3) 177 | websocket-driver (0.7.1) 178 | websocket-extensions (>= 0.1.0) 179 | websocket-extensions (0.1.4) 180 | zeitwerk (2.3.0) 181 | 182 | PLATFORMS 183 | ruby 184 | 185 | DEPENDENCIES 186 | documentation! 187 | sqlite3 (~> 1.3) 188 | 189 | BUNDLED WITH 190 | 1.17.2 191 | -------------------------------------------------------------------------------- /MIT-LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2014 Adam Cooke. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Documentation 2 | 3 | Documentation is a Rails engine which provides a complete system for managing a set of hierarchical documentation. Once installed in an application, you'll have a complete user interface for viewing as well as editing a set of markdown pages. 4 | 5 | ![Screenshot](http://s.adamcooke.io/14/VGaMe.png) 6 | 7 | ## Installation 8 | 9 | To get started, you need to add Documentation to your Gemfile and run `bundle`. 10 | 11 | ```ruby 12 | gem 'documentation', '~> 1.0.0' 13 | ``` 14 | 15 | [![Gem Version](https://badge.fury.io/rb/documentation.svg)](http://badge.fury.io/rb/documentation) 16 | 17 | Next, you'll need to run the setup generator which will add a route to your `config/routes.rb` file for the Documentation interface. 18 | 19 | ``` 20 | bundle exec rails generate documentation:setup 21 | ``` 22 | 23 | You now need to populate your database schema and load the initial documentation pages. 24 | 25 | ``` 26 | bundle exec rake db:migrate documentation:install_guides 27 | ``` 28 | 29 | Once this is done, you can go ahead and start up your Rails application and browse to `/docs` to view your documentation system. 30 | -------------------------------------------------------------------------------- /app/assets/images/documentation/link.svg: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 28 | 29 | -------------------------------------------------------------------------------- /app/assets/images/documentation/logo-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 18 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/assets/images/documentation/logo-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 18 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/assets/images/documentation/page.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/assets/images/documentation/pin.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 15 | 16 | -------------------------------------------------------------------------------- /app/assets/images/documentation/recommendation.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 11 | -------------------------------------------------------------------------------- /app/assets/images/documentation/search.svg: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 10 | 11 | -------------------------------------------------------------------------------- /app/assets/images/documentation/unhappy.svg: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 12 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /app/assets/images/documentation/warning.svg: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /app/assets/javascripts/documentation/application.coffee: -------------------------------------------------------------------------------- 1 | #= require jquery 2 | #= require jquery_ujs 3 | #= require documentation/jquery-ui 4 | #= require documentation/jquery.autosize 5 | #= require nifty/dialog 6 | 7 | $ -> 8 | $('form.pageForm textarea').autosize({append: '\n\n'}) 9 | $('form.reordering ul').sortable 10 | containment: 'parent' 11 | update: -> 12 | form = $(this).parents('form') 13 | url = form.attr('action') 14 | $.post(url, form.serialize()); 15 | 16 | $('.js-screenshot').on 'click', (e)-> 17 | e.preventDefault() 18 | openUploadDialog() 19 | 20 | $('.edit-article').on 'drop', (e)-> 21 | e.stopPropagation() 22 | e.preventDefault() 23 | 24 | file = e.originalEvent.dataTransfer.files[0] 25 | 26 | openUploadDialog(file) 27 | 28 | openUploadDialog = (file)-> 29 | editForm = $('.edit-article').find('form') 30 | contentArea = editForm.find('#page_content') 31 | caretPosition = contentArea.get(0).selectionStart 32 | content = contentArea.val() 33 | 34 | uploadFormUrl = editForm.find('.js-screenshot').attr('href') 35 | uploadFormUrl = uploadFormUrl + "?filename=#{file.name}" if file? 36 | 37 | Nifty.Dialog.open 38 | url: uploadFormUrl 39 | afterLoad: (dialog)-> 40 | form = dialog.find('form') 41 | form.find('#screenshot_alt_text').focus() 42 | 43 | dialog.on 'submit', 'form', (e)-> 44 | form = $(this) 45 | formData = new FormData(form.get(0)) 46 | 47 | if file? 48 | filename = file.name 49 | formData.append('screenshot[upload_file]', file) 50 | else 51 | filename = form.find('#screenshot_upload_file').val() 52 | 53 | fileExt = filename.split('.').pop().toLowerCase() 54 | if $.inArray(fileExt, ['gif','png','jpg','jpeg']) == -1 55 | alert("Invalid file extension (allowed: gif, png, jpg, jpeg)") 56 | return false 57 | 58 | $.ajax 59 | url: form.attr('action') 60 | type: form.attr('method') 61 | data: formData 62 | processData: false 63 | contentType: false 64 | success: (data)-> 65 | screenshotLink = "![#{data.title}*centre](#{data.path})" 66 | newContent = content.substring(0, caretPosition) + screenshotLink + content.substring(caretPosition) 67 | newCaretPosition = (content.substring(0, caretPosition) + screenshotLink).length 68 | contentArea.val(newContent) 69 | 70 | contentArea.focus() 71 | contentArea.get(0).setSelectionRange(newCaretPosition, newCaretPosition) 72 | 73 | Nifty.Dialog.closeTopDialog() 74 | 75 | error: (xhr, status, errorThrown)-> 76 | console.log xhr.responseText 77 | 78 | false 79 | -------------------------------------------------------------------------------- /app/assets/javascripts/documentation/jquery.autosize.js: -------------------------------------------------------------------------------- 1 | /*! 2 | Autosize v1.18.4 - 2014-01-11 3 | Automatically adjust textarea height based on user input. 4 | (c) 2014 Jack Moore - http://www.jacklmoore.com/autosize 5 | license: http://www.opensource.org/licenses/mit-license.php 6 | */ 7 | (function ($) { 8 | var 9 | defaults = { 10 | className: 'autosizejs', 11 | append: '', 12 | callback: false, 13 | resizeDelay: 10, 14 | placeholder: true 15 | }, 16 | 17 | // border:0 is unnecessary, but avoids a bug in Firefox on OSX 18 | copy = '