├── .buildpacks ├── .documentup.yml ├── .gitignore ├── .rspec ├── .travis.yml ├── Gemfile ├── Gemfile.lock ├── Procfile.dev ├── README.md ├── Rakefile ├── app ├── assets │ ├── .DS_Store │ ├── images │ │ ├── icon-github.png │ │ ├── icon-homescreen-non-retina.png │ │ ├── icon-homescreen-retina.png │ │ ├── icon-toc.png │ │ ├── icon-toc@2x.png │ │ ├── logo.png │ │ ├── startup-retina.png │ │ ├── startup.png │ │ └── v1.png │ └── stylesheets │ │ ├── _base.scss │ │ ├── application.css.scss.erb │ │ ├── lib │ │ ├── _normalize.scss │ │ └── _reset.scss │ │ ├── syntax │ │ └── _tomorrow.scss │ │ └── themes │ │ ├── flatdoc.css.scss │ │ └── v1.css.scss ├── controllers │ ├── application_controller.rb │ ├── concerns │ │ └── .keep │ ├── errors_controller.rb │ ├── github_controller.rb │ ├── pages_controller.rb │ └── repositories_controller.rb ├── helpers │ └── errors_helper.rb ├── models │ ├── .keep │ ├── page.rb │ ├── repository.rb │ └── repository │ │ └── configuration.rb └── views │ ├── errors │ ├── internal_server_error.html.slim │ └── not_found.html.slim │ ├── layouts │ ├── application.html.slim │ └── error.html.slim │ └── pages │ └── show.html.slim ├── bin ├── bundle ├── rails ├── rake └── setup ├── config.ru ├── config ├── application.rb ├── boot.rb ├── database.yml ├── database.yml.travis ├── 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 │ ├── octokit.rb │ ├── raygun.rb │ ├── session_store.rb │ └── wrap_parameters.rb ├── locales │ └── en.yml ├── routes.rb └── secrets.yml ├── db ├── migrate │ ├── 20150605193408_create_repositories.rb │ ├── 20150605193513_create_pages.rb │ ├── 20150615124922_add_html_to_pages.rb │ ├── 20150615160017_add_timestamps_to_pages.rb │ ├── 20150615160026_add_timestamps_to_repositories.rb │ └── 20150617124754_add_repository_to_page.rb ├── schema.rb └── seeds.rb ├── lib ├── assets │ └── .keep ├── documentup │ └── filters │ │ ├── absolute_links.rb │ │ └── table_of_contents.rb ├── subdomain.rb └── tasks │ └── .keep ├── log └── .keep ├── newrelic.yml ├── public ├── documentup.js ├── documentup.min.js ├── favicon.ico └── robots.txt ├── spec ├── controllers │ └── github_controller_spec.rb ├── models │ └── repository_spec.rb ├── rails_helper.rb ├── spec_helper.rb └── support │ ├── fake_github.rb │ └── fixtures │ ├── contents_readme_md.json │ ├── push_webhook_changes.json │ ├── push_webhook_changes_config.json │ ├── push_webhook_changes_markdown.json │ ├── push_webhook_no_changes.json │ └── repos │ └── jeromegn │ ├── documentup.json │ └── documentup │ ├── contents │ ├── .documentup.json │ ├── .documentup.yml │ └── README.md │ └── git │ └── tree │ └── master.json └── vendor └── assets └── stylesheets └── .keep /.buildpacks: -------------------------------------------------------------------------------- 1 | https://github.com/rcaught/heroku-buildpack-cmake/ 2 | https://github.com/webandtech/heroku-buildpack-ruby/ -------------------------------------------------------------------------------- /.documentup.yml: -------------------------------------------------------------------------------- 1 | name: DocumentUp 2 | twitter: 3 | - jeromegn 4 | - DocumentUp 5 | google_analytics: UA-5201171-14 6 | travis: true -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files for more about ignoring files. 2 | # 3 | # If you find yourself ignoring temporary files generated by your text editor 4 | # or operating system, you probably want to add a global ignore instead: 5 | # git config --global core.excludesfile '~/.gitignore_global' 6 | 7 | # Ignore bundler config. 8 | /.bundle 9 | 10 | # Ignore the default SQLite database. 11 | /db/*.sqlite3 12 | /db/*.sqlite3-journal 13 | 14 | # Ignore all logfiles and tempfiles. 15 | /log/* 16 | !/log/.keep 17 | /tmp 18 | 19 | .rbenv-vars -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | --require spec_helper 3 | --format documentation 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | 3 | rvm: 4 | - 2.1.6 5 | 6 | addons: 7 | postgresql: "9.4" 8 | 9 | before_script: 10 | - psql -c 'create database travis_ci_test;' -U postgres 11 | - cp config/database.yml.travis config/database.yml 12 | 13 | # deploy: 14 | # provider: heroku 15 | # api_key: 16 | # secure: jEiECnyMzA0TtJ8mQhY6lGJIroksSMIg8bhjhM4Y8UxtnMbfrhPb7T3T+3s0MdiNFFEi/P4OKinv4ErofBdz10AKrO5XTcEHorhoQoKoQK2E4iPNQnm9abI+Z2IbcU7z1hExoh2QzpR243vA4oWZSLQd9yLmIxudzM0qJ8UUD9s= 17 | # run: 18 | # - "rake db:migrate" -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | ruby "2.1.6" 4 | 5 | # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' 6 | gem 'rails', '4.2.1' 7 | gem "pg", "~> 0.18.2" 8 | 9 | gem "virtus", "~> 1.0.5" 10 | 11 | gem "octokit", "~> 3.8.0" 12 | 13 | gem "slim-rails", "~> 3.0.1" 14 | gem "puma", "~> 2.11.3" 15 | 16 | gem "sprockets", "~> 3.2.0" 17 | gem "sass-rails", github: "rails/sass-rails" #"~> 5.0.3" 18 | 19 | gem "rails_12factor" 20 | 21 | gem 'raygun4ruby' 22 | gem 'newrelic_rpm' 23 | 24 | gem "autoprefixer-rails" 25 | 26 | # HTML::Pipeline needs those 27 | gem "pygments.rb", "~> 0.6.3" 28 | 29 | gem 'html-pipeline' 30 | gem "task_list" 31 | gem "rinku", "~> 1.7", :require => false 32 | gem "gemoji", "~> 2.0", :require => false 33 | gem "github-markdown", "~> 0.5", :require => false 34 | gem "sanitize", "~> 4.0", :require => false 35 | gem "escape_utils", "~> 1.0", :require => false 36 | gem "github-linguist", "~> 4.5", :require => false 37 | 38 | group :development, :test do 39 | gem 'byebug' 40 | gem 'spring' 41 | end 42 | 43 | group :development do 44 | gem 'better_errors' 45 | gem 'binding_of_caller' 46 | end 47 | 48 | group :test do 49 | gem 'rspec-rails', '~> 3.0' 50 | gem 'webmock' 51 | gem 'sinatra' 52 | end 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GIT 2 | remote: git://github.com/rails/sass-rails.git 3 | revision: 8e68c5f24ed6487277e9df531ec57b375ad1bea2 4 | specs: 5 | sass-rails (5.0.3) 6 | railties (>= 4.0.0, < 5.0) 7 | sass (~> 3.1) 8 | sprockets (>= 2.8, < 4.0) 9 | sprockets-rails (>= 2.0, < 4.0) 10 | tilt (>= 1.1, < 3) 11 | 12 | GEM 13 | remote: https://rubygems.org/ 14 | specs: 15 | actionmailer (4.2.1) 16 | actionpack (= 4.2.1) 17 | actionview (= 4.2.1) 18 | activejob (= 4.2.1) 19 | mail (~> 2.5, >= 2.5.4) 20 | rails-dom-testing (~> 1.0, >= 1.0.5) 21 | actionpack (4.2.1) 22 | actionview (= 4.2.1) 23 | activesupport (= 4.2.1) 24 | rack (~> 1.6) 25 | rack-test (~> 0.6.2) 26 | rails-dom-testing (~> 1.0, >= 1.0.5) 27 | rails-html-sanitizer (~> 1.0, >= 1.0.1) 28 | actionview (4.2.1) 29 | activesupport (= 4.2.1) 30 | builder (~> 3.1) 31 | erubis (~> 2.7.0) 32 | rails-dom-testing (~> 1.0, >= 1.0.5) 33 | rails-html-sanitizer (~> 1.0, >= 1.0.1) 34 | activejob (4.2.1) 35 | activesupport (= 4.2.1) 36 | globalid (>= 0.3.0) 37 | activemodel (4.2.1) 38 | activesupport (= 4.2.1) 39 | builder (~> 3.1) 40 | activerecord (4.2.1) 41 | activemodel (= 4.2.1) 42 | activesupport (= 4.2.1) 43 | arel (~> 6.0) 44 | activesupport (4.2.1) 45 | i18n (~> 0.7) 46 | json (~> 1.7, >= 1.7.7) 47 | minitest (~> 5.1) 48 | thread_safe (~> 0.3, >= 0.3.4) 49 | tzinfo (~> 1.1) 50 | addressable (2.3.8) 51 | arel (6.0.0) 52 | autoprefixer-rails (5.1.7) 53 | execjs 54 | json 55 | axiom-types (0.1.1) 56 | descendants_tracker (~> 0.0.4) 57 | ice_nine (~> 0.11.0) 58 | thread_safe (~> 0.3, >= 0.3.1) 59 | better_errors (2.1.1) 60 | coderay (>= 1.0.0) 61 | erubis (>= 2.6.6) 62 | rack (>= 0.9.0) 63 | binding_of_caller (0.7.2) 64 | debug_inspector (>= 0.0.1) 65 | builder (3.2.2) 66 | byebug (5.0.0) 67 | columnize (= 0.9.0) 68 | charlock_holmes (0.7.3) 69 | coderay (1.1.0) 70 | coercible (1.0.0) 71 | descendants_tracker (~> 0.0.1) 72 | columnize (0.9.0) 73 | crack (0.4.2) 74 | safe_yaml (~> 1.0.0) 75 | crass (1.0.2) 76 | debug_inspector (0.0.2) 77 | descendants_tracker (0.0.4) 78 | thread_safe (~> 0.3, >= 0.3.1) 79 | diff-lcs (1.2.5) 80 | equalizer (0.0.11) 81 | erubis (2.7.0) 82 | escape_utils (1.1.0) 83 | execjs (2.5.2) 84 | faraday (0.9.1) 85 | multipart-post (>= 1.2, < 3) 86 | gemoji (2.1.0) 87 | github-linguist (4.5.5) 88 | charlock_holmes (~> 0.7.3) 89 | escape_utils (~> 1.1.0) 90 | mime-types (>= 1.19) 91 | rugged (~> 0.23.0b1) 92 | github-markdown (0.6.8) 93 | globalid (0.3.5) 94 | activesupport (>= 4.1.0) 95 | html-pipeline (1.11.0) 96 | activesupport (>= 2) 97 | nokogiri (~> 1.4) 98 | httparty (0.13.3) 99 | json (~> 1.8) 100 | multi_xml (>= 0.5.2) 101 | i18n (0.7.0) 102 | ice_nine (0.11.1) 103 | json (1.8.3) 104 | loofah (2.0.2) 105 | nokogiri (>= 1.5.9) 106 | mail (2.6.3) 107 | mime-types (>= 1.16, < 3) 108 | mime-types (2.6.1) 109 | mini_portile (0.6.2) 110 | minitest (5.7.0) 111 | multi_xml (0.5.5) 112 | multipart-post (2.0.0) 113 | newrelic_rpm (3.11.2.286) 114 | nokogiri (1.6.6.2) 115 | mini_portile (~> 0.6.0) 116 | nokogumbo (1.4.1) 117 | nokogiri 118 | octokit (3.8.0) 119 | sawyer (~> 0.6.0, >= 0.5.3) 120 | pg (0.18.2) 121 | posix-spawn (0.3.11) 122 | puma (2.11.3) 123 | rack (>= 1.1, < 2.0) 124 | pygments.rb (0.6.3) 125 | posix-spawn (~> 0.3.6) 126 | yajl-ruby (~> 1.2.0) 127 | rack (1.6.1) 128 | rack-protection (1.5.3) 129 | rack 130 | rack-test (0.6.3) 131 | rack (>= 1.0) 132 | rails (4.2.1) 133 | actionmailer (= 4.2.1) 134 | actionpack (= 4.2.1) 135 | actionview (= 4.2.1) 136 | activejob (= 4.2.1) 137 | activemodel (= 4.2.1) 138 | activerecord (= 4.2.1) 139 | activesupport (= 4.2.1) 140 | bundler (>= 1.3.0, < 2.0) 141 | railties (= 4.2.1) 142 | sprockets-rails 143 | rails-deprecated_sanitizer (1.0.3) 144 | activesupport (>= 4.2.0.alpha) 145 | rails-dom-testing (1.0.6) 146 | activesupport (>= 4.2.0.beta, < 5.0) 147 | nokogiri (~> 1.6.0) 148 | rails-deprecated_sanitizer (>= 1.0.1) 149 | rails-html-sanitizer (1.0.2) 150 | loofah (~> 2.0) 151 | rails_12factor (0.0.3) 152 | rails_serve_static_assets 153 | rails_stdout_logging 154 | rails_serve_static_assets (0.0.4) 155 | rails_stdout_logging (0.0.3) 156 | railties (4.2.1) 157 | actionpack (= 4.2.1) 158 | activesupport (= 4.2.1) 159 | rake (>= 0.8.7) 160 | thor (>= 0.18.1, < 2.0) 161 | rake (10.4.2) 162 | raygun4ruby (1.1.5) 163 | httparty (~> 0.11) 164 | json 165 | rack 166 | rinku (1.7.3) 167 | rspec-core (3.3.0) 168 | rspec-support (~> 3.3.0) 169 | rspec-expectations (3.3.0) 170 | diff-lcs (>= 1.2.0, < 2.0) 171 | rspec-support (~> 3.3.0) 172 | rspec-mocks (3.3.0) 173 | diff-lcs (>= 1.2.0, < 2.0) 174 | rspec-support (~> 3.3.0) 175 | rspec-rails (3.3.1) 176 | actionpack (>= 3.0, < 4.3) 177 | activesupport (>= 3.0, < 4.3) 178 | railties (>= 3.0, < 4.3) 179 | rspec-core (~> 3.3.0) 180 | rspec-expectations (~> 3.3.0) 181 | rspec-mocks (~> 3.3.0) 182 | rspec-support (~> 3.3.0) 183 | rspec-support (3.3.0) 184 | rugged (0.23.0b2) 185 | safe_yaml (1.0.4) 186 | sanitize (4.0.0) 187 | crass (~> 1.0.2) 188 | nokogiri (>= 1.4.4) 189 | nokogumbo (= 1.4.1) 190 | sass (3.4.14) 191 | sawyer (0.6.0) 192 | addressable (~> 2.3.5) 193 | faraday (~> 0.8, < 0.10) 194 | sinatra (1.4.6) 195 | rack (~> 1.4) 196 | rack-protection (~> 1.4) 197 | tilt (>= 1.3, < 3) 198 | slim (3.0.6) 199 | temple (~> 0.7.3) 200 | tilt (>= 1.3.3, < 2.1) 201 | slim-rails (3.0.1) 202 | actionmailer (>= 3.1, < 5.0) 203 | actionpack (>= 3.1, < 5.0) 204 | activesupport (>= 3.1, < 5.0) 205 | railties (>= 3.1, < 5.0) 206 | slim (~> 3.0) 207 | spring (1.3.6) 208 | sprockets (3.2.0) 209 | rack (~> 1.0) 210 | sprockets-rails (2.3.1) 211 | actionpack (>= 3.0) 212 | activesupport (>= 3.0) 213 | sprockets (>= 2.8, < 4.0) 214 | task_list (1.0.2) 215 | html-pipeline 216 | temple (0.7.6) 217 | thor (0.19.1) 218 | thread_safe (0.3.5) 219 | tilt (2.0.1) 220 | tzinfo (1.2.2) 221 | thread_safe (~> 0.1) 222 | virtus (1.0.5) 223 | axiom-types (~> 0.1) 224 | coercible (~> 1.0) 225 | descendants_tracker (~> 0.0, >= 0.0.3) 226 | equalizer (~> 0.0, >= 0.0.9) 227 | webmock (1.21.0) 228 | addressable (>= 2.3.6) 229 | crack (>= 0.3.2) 230 | yajl-ruby (1.2.1) 231 | 232 | PLATFORMS 233 | ruby 234 | 235 | DEPENDENCIES 236 | autoprefixer-rails 237 | better_errors 238 | binding_of_caller 239 | byebug 240 | escape_utils (~> 1.0) 241 | gemoji (~> 2.0) 242 | github-linguist (~> 4.5) 243 | github-markdown (~> 0.5) 244 | html-pipeline 245 | newrelic_rpm 246 | octokit (~> 3.8.0) 247 | pg (~> 0.18.2) 248 | puma (~> 2.11.3) 249 | pygments.rb (~> 0.6.3) 250 | rails (= 4.2.1) 251 | rails_12factor 252 | raygun4ruby 253 | rinku (~> 1.7) 254 | rspec-rails (~> 3.0) 255 | sanitize (~> 4.0) 256 | sass-rails! 257 | sinatra 258 | slim-rails (~> 3.0.1) 259 | spring 260 | sprockets (~> 3.2.0) 261 | task_list 262 | virtus (~> 1.0.5) 263 | webmock 264 | 265 | BUNDLED WITH 266 | 1.10.2 267 | -------------------------------------------------------------------------------- /Procfile.dev: -------------------------------------------------------------------------------- 1 | web: bundle exec rails s 2 | pg: postgres -D /usr/local/var/postgres 3 | #redis: redis-server /usr/local/etc/redis.conf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |  2 | 3 | **This site has been generated with DocumentUp** (eat your own dog food, people) 4 | 5 | Automatically generated documentation sites for your markdown files! There are various ways of getting your documentation going: 6 | 7 | * [Hosted](#hosted) 8 | * [gh-pages](#gh-pages) 9 | 10 | ## Hosted 11 | 12 | DocumentUp hosts your documentation sites. Just visit `http://documentup.com/username/repository` to generate a site from your `README.md`. 13 | 14 | Recommended if you have a public Github repository. 15 | 16 | ### CNAME 17 | 18 | You can point a CNAME to `project.username.documentup.com`. 19 | 20 | ### Post-Receive Hook 21 | 22 | If you want your readme to be recompiled, please add a [Post-Receive Hook](http://help.github.com/post-receive-hooks/) to your Github repository pointing to: `http://documentup.com/recompile` 23 | 24 | ### Manual Recompile 25 | 26 | Visit `http://documentup.com/username/repository/__recompile` to manually tell the server to recompile your readme. 27 | 28 | Useful when changes are made to the stylesheets on the server but the compilation hasn't been triggered for a while. 29 | 30 | ### Configuration 31 | 32 | Add a `.documentup.yml` dotfile file to the root of your repository. Refer to the [options](#options) section below for its contents. Feel free to consult this repository's [`.documentup.yml`](.documentup.yml) 33 | 34 | ### JSONP example with jQuery 35 | 36 | ```javascript 37 | $.ajax({ 38 | url: "http://documentup.com/compiled", 39 | dataType: "jsonp", 40 | data: { 41 | content: "# test", 42 | name: "Test JSONP!" 43 | }, 44 | success: function(resp){ 45 | // `status` is always provided 46 | if (resp.status == 200) { 47 | // Write to your document 48 | document.open(); 49 | document.write(resp.html); 50 | document.close(); 51 | } 52 | } 53 | }); 54 | ``` 55 | 56 | ## gh-pages 57 | 58 | For those wanting to stay within the comfort of their gh-pages branch, it's still possible by using an `index.html` file similar to this: 59 | 60 | ```html 61 | 62 | 63 |
64 | 65 | 68 | 69 | 70 | 71 | ``` 72 | 73 | Make sure to change the `"username/repository"` to the repository's name and user's username. 74 | 75 | Use the [`documentup.min.js`](public/documentup.min.js) file in this repository, not the one what used to be on cdnjs.com, it's deprecated. 76 | 77 | ### Configuration 78 | 79 | `DocumentUp.document` accepts either a String or an Object representing your desired configuration. If an object is used, remember to add a `repo` option containing the path `"username/repository"` to your github repository. 80 | 81 | All options detailed in the [options](#options) section are available. 82 | 83 | In addition to those, one special option is available to "gh-pages version" of DocumentUp: 84 | 85 | **afterRender** (Function) 86 | A function to be executed after the document has been replaced with the compiled HTML. 87 | 88 | ### Example 89 | 90 | ```javascript 91 | DocumentUp.document({ 92 | repo: "jeromegn/documentup", 93 | name: "DocumentUp", 94 | twitter: [ 95 | "jeromegn", 96 | "DocumentUp" 97 | ], 98 | afterRender: function(){ 99 | alert("rendered"); 100 | } 101 | }); 102 | ``` 103 | 104 | ### What this script does 105 | 106 | It does what's written in the JSONP section, without the jQuery dependency. It uses a endpoint like: `http://documentup.com/username/repository?callback=` to fetch the cached copy of the repository and then replaces the page's html with the generated documentation. 107 | 108 | ## Formatting guide 109 | 110 | Just like you normally would. DocumentUp also supports "Github Flavored Markdown" and we recommend you use it for syntax highlighting. 111 | 112 | It doesn't support tables as it is supported on Github, but you can use inline HTML. 113 | 114 | h1's (# in markdown) will appear as first level navigation in the sidebar while h2's (##) will appear under them as sub-navigation. 115 | 116 | Example: 117 | 118 | ```markdown 119 | # Project name / Title (won't appear in the sidebar) 120 | 121 | Some intro text if you want. 122 | 123 | ## Top level-navigation 124 | 125 | ### Sub-navigation 126 | 127 | #### This wouldn't show up in the sidebar 128 | ``` 129 | 130 | ## Options 131 | 132 | ### name 133 | 134 | *String, default: repository name* 135 | 136 | Name of your project. It'll appear in the header of the sidebar. Defaults to the `repository` substring of the `repo` option. 137 | 138 | ### color 139 | 140 | *String, default: "#336699"* 141 | 142 | CSS-like color representing the color for the links both in the sidebar and the content. 143 | 144 | ### theme 145 | 146 | *String, default: null* 147 | 148 | Name of the theme to use. Refer to the [themes](#themes) sections. 149 | 150 | ### issues 151 | 152 | *Boolean, default: true* 153 | 154 | Adds a link to the sidebar for the issues tab of the repository if `true`. Also accepts a string if your issues are managed elsewhere. 155 | 156 | ### travis 157 | 158 | *Boolean, default: false* 159 | 160 | Indicate if the project is being tested by [Travis-CI](http://travis-ci.org/). If `true`, it'll add the small travis badge in the sidebar. 161 | 162 | ### twitter 163 | 164 | *String / Array of strings, default: null* 165 | 166 | Add follow buttons for one or more Twitter accounts to your sidebar. Useful to gather followers. 167 | 168 | ### google_analytics 169 | 170 | *String default: null* 171 | 172 | This is your Google Analytics "UA" unique ID. Adds GA tracking to your generated documentation. 173 | e.g.: "UA-5201171-14" 174 | 175 | ## Themes 176 | 177 | ### Default 178 | 179 | The one you're looking at now. 180 | 181 | ### V1 182 | 183 | For the nostalgic. Use `v1` in your `theme` config option. 184 | 185 |  186 | 187 | ## Roadmap 188 | 189 | * Private repositories 190 | * Multi-page aggregation 191 | 192 | ## Thank you 193 | 194 | * Thanks to [Jean-Marc Denis](http://jeanmarcdenis.me/) for the freely downloadable bow tie I used in the logo. 195 | 196 | ## Changelog 197 | 198 | #### 2.0 (June 15, 2015) 199 | 200 | Full rewrite of the app: 201 | - Deprecated on-demand `/compiled` endpoint 202 | - Renamed manual recompile endpoint to `username/repo/__recompile` 203 | - Uses Ruby on Rails 204 | - Uses SASS 205 | - Laid the foundation for multiple pages (it works right now, just not linked or explained, needs some work) 206 | - Uses PostgreSQL 207 | 208 | #### Hosted version (Feb 2, 2012) 209 | 210 | Versioning is going to be difficult now since this is now a service. Deployment will be continuous. 211 | 212 | #### 0.1.1 (Jan 26, 2012) 213 | 214 | * Files now parsed in UTF-8 215 | * Namespaced repositories in localStorage (thanks to [tbranyen](https://github.com/tbranyen)) 216 | * A few README fixes 217 | 218 | #### 0.1.0 (Jan 25, 2012) 219 | 220 | * Initial release 221 | 222 | ## License 223 | 224 | Copyright (c) 2015 Jerome Gravel-Niquet 225 | 226 | Permission is hereby granted, free of charge, to any person obtaining 227 | a copy of this software and associated documentation files (the 228 | "Software"), to deal in the Software without restriction, including 229 | without limitation the rights to use, copy, modify, merge, publish, 230 | distribute, sublicense, and/or sell copies of the Software, and to 231 | permit persons to whom the Software is furnished to do so, subject to 232 | the following conditions: 233 | 234 | The above copyright notice and this permission notice shall be 235 | included in all copies or substantial portions of the Software. 236 | 237 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 238 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 239 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 240 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 241 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 242 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 243 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 244 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # Add your own tasks in files placed in lib/tasks ending in .rake, 2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 3 | 4 | require File.expand_path('../config/application', __FILE__) 5 | 6 | Rails.application.load_tasks 7 | -------------------------------------------------------------------------------- /app/assets/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeromegn/DocumentUp/36ff103e233c77f54d9010aff4a8430397eb81b4/app/assets/.DS_Store -------------------------------------------------------------------------------- /app/assets/images/icon-github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeromegn/DocumentUp/36ff103e233c77f54d9010aff4a8430397eb81b4/app/assets/images/icon-github.png -------------------------------------------------------------------------------- /app/assets/images/icon-homescreen-non-retina.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeromegn/DocumentUp/36ff103e233c77f54d9010aff4a8430397eb81b4/app/assets/images/icon-homescreen-non-retina.png -------------------------------------------------------------------------------- /app/assets/images/icon-homescreen-retina.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeromegn/DocumentUp/36ff103e233c77f54d9010aff4a8430397eb81b4/app/assets/images/icon-homescreen-retina.png -------------------------------------------------------------------------------- /app/assets/images/icon-toc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeromegn/DocumentUp/36ff103e233c77f54d9010aff4a8430397eb81b4/app/assets/images/icon-toc.png -------------------------------------------------------------------------------- /app/assets/images/icon-toc@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeromegn/DocumentUp/36ff103e233c77f54d9010aff4a8430397eb81b4/app/assets/images/icon-toc@2x.png -------------------------------------------------------------------------------- /app/assets/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeromegn/DocumentUp/36ff103e233c77f54d9010aff4a8430397eb81b4/app/assets/images/logo.png -------------------------------------------------------------------------------- /app/assets/images/startup-retina.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeromegn/DocumentUp/36ff103e233c77f54d9010aff4a8430397eb81b4/app/assets/images/startup-retina.png -------------------------------------------------------------------------------- /app/assets/images/startup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeromegn/DocumentUp/36ff103e233c77f54d9010aff4a8430397eb81b4/app/assets/images/startup.png -------------------------------------------------------------------------------- /app/assets/images/v1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeromegn/DocumentUp/36ff103e233c77f54d9010aff4a8430397eb81b4/app/assets/images/v1.png -------------------------------------------------------------------------------- /app/assets/stylesheets/_base.scss: -------------------------------------------------------------------------------- 1 | @import "lib/normalize"; 2 | 3 | html { 4 | height: 100%; 5 | } 6 | 7 | body { 8 | padding: 0; 9 | margin: 0; 10 | font: 16px/24px "Alegreya", serif; 11 | font-size-adjust:none; 12 | font-style:normal; 13 | font-variant:normal; 14 | font-weight:normal; 15 | background: #F4F6EC; 16 | } 17 | 18 | a { 19 | color: #369; 20 | } 21 | 22 | @mixin inline-block() { 23 | display: -moz-inline-box; 24 | -moz-box-orient: vertical; 25 | display: inline-block; 26 | vertical-align: top; 27 | if support-for-ie { 28 | & { 29 | *display: inline; 30 | } 31 | } 32 | } 33 | 34 | @mixin clearfix { 35 | &:after { 36 | content: ""; 37 | display: table; 38 | clear: both; 39 | } 40 | } -------------------------------------------------------------------------------- /app/assets/stylesheets/application.css.scss.erb: -------------------------------------------------------------------------------- 1 | @import "syntax/tomorrow"; 2 | @import "base"; 3 | 4 | // Layout 5 | 6 | #container { 7 | width: 922px; 8 | margin: 0 auto; 9 | } 10 | 11 | #header { 12 | border-bottom: 3px solid rgba(black, 0.1); 13 | padding-bottom: 10px; 14 | margin-bottom: 10px; 15 | #logo { 16 | color: #111; 17 | font-size: 25px; 18 | font-weight: bold; 19 | padding: 10px 0; 20 | text-decoration: none; 21 | } 22 | } 23 | 24 | #nav { 25 | float: left; 26 | width: 230px; 27 | margin-right: 30px; 28 | margin-top: 40px; 29 | a { 30 | display: block; 31 | font-weight: bold; 32 | text-decoration: none; 33 | } 34 | #sections > ul { 35 | list-style-type: none; 36 | border-bottom: 3px solid rgba(black, 0.1); 37 | padding-bottom: 10px; 38 | margin-bottom: 10px; 39 | li { 40 | a { 41 | padding: 3px 0; 42 | color: #444; 43 | font-size: 16px; 44 | } 45 | } 46 | li.h2 { 47 | margin-top: 0.5em; 48 | } 49 | li.h3 { 50 | list-style-type: none; 51 | a { 52 | padding: 1px 15px; 53 | font-size: 13px; 54 | color: #369; 55 | font-weight: normal; 56 | } 57 | } 58 | } 59 | .extra { 60 | padding: 5px 0; 61 | min-height: 1.4em; 62 | a { 63 | color: #555; 64 | font-size: 14px; 65 | } 66 | } 67 | #travis { 68 | img {margin-top: 10px; display: block;} 69 | } 70 | 71 | > *:last-child { 72 | margin-bottom: 20px; 73 | } 74 | } 75 | 76 | #github-ribbon { 77 | position: absolute; 78 | top: 0; 79 | right: 0; 80 | img { 81 | border: 0; 82 | } 83 | } 84 | 85 | #content { 86 | padding: 30px 30px 20px 30px; 87 | min-height: 100px; 88 | width: 600px; 89 | background: #fff; 90 | float: left; 91 | border: 1px solid rgba(black, 0.2); 92 | border-radius: 3px 3px 0 0; 93 | margin-top: 15px; 94 | 95 | #loader { 96 | color: #888; 97 | width: 300px; 98 | height: 24px; 99 | line-height: 24px; 100 | position: absolute; 101 | top: 30px; 102 | left: 30px; 103 | background: url(unquote('data:image/gif;base64,R0lGODlhGAAYAPYAAP///5mZmfn5+dvb27i4uKmpqaCgoNra2v39/c/Pz6CgoJmZmfT09K+vr66urvb29qWlpaSkpPPz8/v7+87Ozvj4+NXV1dTU1Li4uKysrJubm52dnaqqqu7u7uPj46Ojo8LCwvb29ra2tqenp7q6utzc3JycnNfX1/Ly8uzs7J6ensbGxs3NzeDg4MvLy9LS0r+/v/r6+qysrOrq6t7e3tnZ2cTExLS0tLOzs6ioqLGxsefn57W1tcvLy7y8vMHBwd7e3qKiovHx8cfHx+Hh4QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH+GkNyZWF0ZWQgd2l0aCBhamF4bG9hZC5pbmZvACH5BAAFAAAAIf8LTkVUU0NBUEUyLjADAQAAACwAAAAAGAAYAAAHmoAAgoOEhYaHgxUWBA4aCxwkJwKIhBMJBguZmpkqLBOUDw2bo5kKEogMEKSkLYgIoqubK5QJsZsNCIgCCraZBiiUA72ZJZQABMMgxgAFvRyfxpixGx3LANKxHtbNth8hy8i9IssHwwsXxgLYsSYpxrXDz5QIDubKlAwR5q2UErC2poxNoLBukwoX0IxVuIAhQ6YRBC5MskaxUCAAIfkEAAUAAQAsAAAAABgAGAAAB6GAAIKDhIWGh4MVFgQOGhsOGAcxiIQTCQYLmZqZGwkIlA8Nm6OaMgyHDBCkqwsjEoUIoqykNxWFCbOkNoYCCrmaJjWHA7+ZHzOIBMUND5QFvzATlACYsy/TgtWsIpPTz7kyr5TKv8eUB8ULGzSIAtq/CYi46Qswn7AO9As4toUMEfRcHZIgC9wpRBMovNvU6d60ChcwZFigwYGIAwKwaUQUCAAh+QQABQACACwAAAAAGAAYAAAHooAAgoOEhYaHgxUWBA4aCzkkJwKIhBMJBguZmpkqLAiUDw2bo5oyEocMEKSrCxCnhAiirKs3hQmzsy+DAgq4pBogKIMDvpvAwoQExQvHhwW+zYiYrNGU06wNHpSCz746O5TKyzwzhwfLmgQphQLX6D4dhLfomgmwDvQLOoYMEegRyApJkIWLQ0BDEyi426Six4RtgipcwJAhUwQCFypA3IgoEAAh+QQABQADACwAAAAAGAAYAAAHrYAAgoOEhYaHgxUWBA4aCxwkJzGIhBMJBguZmpkGLAiUDw2bo5oZEocMEKSrCxCnhAiirKsZn4MJs7MJgwIKuawqFYIDv7MnggTFozlDLZMABcpBPjUMhpisJiIJKZQA2KwfP0DPh9HFGjwJQobJypoQK0S2B++kF4IC4PbBt/aaPWA5+CdjQiEGEd5FQHFIgqxcHF4dmkBh3yYVLmx5q3ABQ4ZMBUhYEOCtpLdAACH5BAAFAAQALAAAAAAYABgAAAeegACCg4SFhoeDFRYEDhoaDgQWFYiEEwkGC5mamQYJE5QPDZujmg0PhwwQpKsLEAyFCKKsqw0IhAmzswmDAgq5rAoCggO/sxaCBMWsBIIFyqsRgpjPoybS1KMqzdibBcjcmswAB+CZxwAC09gGwoK43LuDCA7YDp+EDBHPEa+GErK5GkigNIGCulEGKNyjBKDCBQwZMmXAcGESw4uUAgEAIfkEAAUABQAsAAAAABgAGAAAB62AAIKDhIWGh4MVFgQOGgscJCcxiIQTCQYLmZqZBiwIlA8Nm6OaGRKHDBCkqwsQp4QIoqyrGZ+DCbOzCYMCCrmsKhWCA7+zJ4IExaM5Qy2TAAXKQT41DIaYrCYiCSmUANisHz9Az4fRxRo8CUKGycqaECtEtgfvpBeCAuD2wbf2mj1gOfgnY0IhBhHeRUBxSIKsXBxeHZpAYd8mFS5seatwAUOGTAVIWBDgraS3QAAh+QQABQAGACwAAAAAGAAYAAAHooAAgoOEhYaHgxUWBA4aCzkkJwKIhBMJBguZmpkqLAiUDw2bo5oyEocMEKSrCxCnhAiirKs3hQmzsy+DAgq4pBogKIMDvpvAwoQExQvHhwW+zYiYrNGU06wNHpSCz746O5TKyzwzhwfLmgQphQLX6D4dhLfomgmwDvQLOoYMEegRyApJkIWLQ0BDEyi426Six4RtgipcwJAhUwQCFypA3IgoEAAh+QQABQAHACwAAAAAGAAYAAAHoYAAgoOEhYaHgxUWBA4aGw4YBzGIhBMJBguZmpkbCQiUDw2bo5oyDIcMEKSrCyMShQiirKQ3FYUJs6Q2hgIKuZomNYcDv5kfM4gExQ0PlAW/MBOUAJizL9OC1awik9PPuTKvlMq/x5QHxQsbNIgC2r8JiLjpCzCfsA70Czi2hQwR9FwdkiAL3ClEEyi829Tp3rQKFzBkWKDBgYgDArBpRBQIADsAAAAAAAAAAAA=')) no-repeat center left; 104 | padding-left: 32px; 105 | font-size: 18px; 106 | } 107 | 108 | > p { 109 | @include clearfix; 110 | } 111 | p { padding:0 0 0.8125em 0; color:#444; } 112 | 113 | p img { margin: 0.5em 0.8125em 0.8125em 0; padding: 0; } 114 | img { max-width: 100%; } 115 | 116 | 117 | h1,h2,h3,h4,h5,h6 { font-weight:bold; line-height: 1.2em; } 118 | 119 | h1 { font-size: 2.125em; margin-bottom: 0.4em; } 120 | h2 { font-size: 1.7em; margin: 0.855em 0 0.4em; color: #CC333F; } 121 | h3 { font-size: 1.3em; margin: 0.956em 0 0.4em; } 122 | h4 { font-size: 1.1em; margin: 1.161em 0 0.4em; } 123 | h5,h6 { font-size: 1em; font-weight: bold; margin: 1.238em 0 0.4em; } 124 | 125 | > h1, > h2 {margin-top: 0} 126 | 127 | ul{list-style-position:outside;} 128 | li ul, 129 | li ol { margin:0 1.625em; } 130 | ul, ol { margin: 0 0 1.625em 1.25em; } 131 | 132 | 133 | dl { margin: 0 0 1.625em 0; } 134 | dl dt { font-weight: bold; } 135 | dl dd { margin-left: 1.625em; } 136 | 137 | a { text-decoration:none; } 138 | a:hover { text-decoration: underline; } 139 | 140 | 141 | table { margin-bottom:1.625em; border-collapse: collapse; } 142 | th { font-weight:bold; } 143 | tr,th,td { margin:0; padding:0 1.625em 0 1em; height:26px; } 144 | tfoot { font-style: italic; } 145 | caption { text-align:center; font-family:Georgia, serif; } 146 | 147 | 148 | abbr, acronym { border-bottom:1px dotted #000; } 149 | address { margin-top:1.625em; font-style: italic; } 150 | del {color:#000;} 151 | 152 | 153 | blockquote { padding:1em 1em 1.625em 1em; font-family:georgia,serif;font-style: italic; } 154 | blockquote:before { content:"\201C";font-size:3em;margin-left:-.625em; font-family:georgia,serif;color:#aaa;line-height:0;}/* From Tripoli */ 155 | blockquote > p {padding:0; margin:0; } 156 | 157 | strong { font-weight: bold; } 158 | em, dfn { font-style: italic; } 159 | dfn { font-weight: bold; } 160 | pre, code { margin: 0 0 1.625em; white-space: pre; } 161 | pre, code, tt { 162 | font-family: "Source Code Pro", monospace; 163 | line-height: 1.5; 164 | } 165 | code { font-size: 0.8em; background: #f7f8f1; padding: 1px 2px; border: 1px solid #CCCCCC; } 166 | pre { font-size: 0.8em; background: #f7f8f1; border: 1px solid #CCCCCC; padding: 10px 12px; word-wrap: normal; overflow-y: auto; } 167 | tt { display: block; margin: 1.625em 0; } 168 | hr { margin-bottom:1.625em; } 169 | 170 | table { 171 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 172 | width: 100%; 173 | } 174 | th, td { 175 | padding: 5px 10px; 176 | border: 1px solid #ccc; 177 | } 178 | th { 179 | background: #eee; 180 | padding: 7px 10px; 181 | } 182 | td { 183 | font-size: 0.9em; 184 | border-color: #ddd; 185 | } 186 | tbody tr:nth-child(2n) { 187 | background: #f5f5f5; 188 | } 189 | } 190 | 191 | @media only screen and (max-width : 480px) { 192 | #container { 193 | width: 100%; 194 | } 195 | #nav { 196 | width: 100%; 197 | margin-top: 10px; 198 | float: none; 199 | #sections, #header, .extra { 200 | padding-left: 30px; 201 | padding-right: 30px; 202 | } 203 | } 204 | #content { 205 | border-radius: 0; 206 | border-width: 1px; 207 | float: none; 208 | margin: 0; 209 | width: 100%; 210 | -moz-box-sizing: border-box; 211 | -webkit-box-sizing: border-box; 212 | box-sizing: border-box; 213 | } 214 | } 215 | @media only screen and (min-device-pixel-ratio: 1.5), only screen and (min-resolution : 1.5dppx){ 216 | #github-ribbon { 217 | img { 218 | width: 100px; 219 | } 220 | } 221 | } 222 | 223 | .error .header { 224 | width: 240px; 225 | margin: 100px auto 0; 226 | } 227 | .error .header img { 228 | width: 100%; 229 | } 230 | .error-message { 231 | width: 300px; 232 | padding: 30px; 233 | margin: 10px auto 0; 234 | text-align: center; 235 | background: #fff; 236 | -webkit-border-radius: 3px; 237 | -moz-border-radius: 3px; 238 | border-radius: 3px; 239 | border: 1px solid #ccc; 240 | } 241 | .error-message p { 242 | margin-bottom: 10px; 243 | } 244 | h1 { 245 | font-size: 24px; 246 | margin: 0 0 20px; 247 | font-weight: bold; 248 | } 249 | .login.github { 250 | height: 24px; 251 | line-height: 24px; 252 | display: -moz-inline-box; 253 | -moz-box-orient: vertical; 254 | display: inline-block; 255 | vertical-align: top; 256 | background: #eee url(<%= image_path "icon-github.png" %>) no-repeat 5px 0; 257 | background: url(<%= image_path "icon-github.png" %>) no-repeat 5px 0, -webkit-gradient(linear, left top, left bottom, color-stop(0, #eee), color-stop(1, #ddd)); 258 | background: url(<%= image_path "icon-github.png" %>) no-repeat 5px 0, -webkit-linear-gradient(top, #eee 0%, #ddd 100%); 259 | background: url(<%= image_path "icon-github.png" %>) no-repeat 5px 0, -moz-linear-gradient(top, #eee 0%, #ddd 100%); 260 | background: url(<%= image_path "icon-github.png" %>) no-repeat 5px 0, linear-gradient(top, #eee 0%, #ddd 100%); 261 | -webkit-border-radius: 3px; 262 | -moz-border-radius: 3px; 263 | border-radius: 3px; 264 | border: 1px solid #ccc; 265 | padding: 0 5px 0 26px; 266 | font-weight: bold; 267 | color: #333; 268 | text-decoration: none; 269 | font-size: 13px; 270 | } 271 | .login.github { 272 | *display: inline; 273 | } 274 | .login.github:hover { 275 | background: #599bdc url(<%= image_path "icon-github.png" %>) no-repeat 5px -24px; 276 | background: url(<%= image_path "icon-github.png" %>) no-repeat 5px -24px, -webkit-gradient(linear, left top, left bottom, color-stop(0, #599bdc), color-stop(1, #3072b3)); 277 | background: url(<%= image_path "icon-github.png" %>) no-repeat 5px -24px, -webkit-linear-gradient(top, #599bdc 0%, #3072b3 100%); 278 | background: url(<%= image_path "icon-github.png" %>) no-repeat 5px -24px, -moz-linear-gradient(top, #599bdc 0%, #3072b3 100%); 279 | background: url(<%= image_path "icon-github.png" %>) no-repeat 5px -24px, linear-gradient(top, #599bdc 0%, #3072b3 100%); 280 | color: #fff; 281 | border-color: #518cc6; 282 | } 283 | .login.github:active { 284 | background: #3072b3 url(<%= image_path "icon-github.png" %>) no-repeat 5px -24px; 285 | background: url(<%= image_path "icon-github.png" %>) no-repeat 5px -24px, -webkit-gradient(linear, left top, left bottom, color-stop(0, #3072b3), color-stop(1, #599bdc)); 286 | background: url(<%= image_path "icon-github.png" %>) no-repeat 5px -24px, -webkit-linear-gradient(top, #3072b3 0%, #599bdc 100%); 287 | background: url(<%= image_path "icon-github.png" %>) no-repeat 5px -24px, -moz-linear-gradient(top, #3072b3 0%, #599bdc 100%); 288 | background: url(<%= image_path "icon-github.png" %>) no-repeat 5px -24px, linear-gradient(top, #3072b3 0%, #599bdc 100%); 289 | border-color: #2a65a0; 290 | } -------------------------------------------------------------------------------- /app/assets/stylesheets/lib/_normalize.scss: -------------------------------------------------------------------------------- 1 | html, body, div, span, object, iframe, 2 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 3 | a, abbr, acronym, address, code, 4 | del, dfn, em, img, q, dl, dt, dd, ol, ul, li, 5 | fieldset, form, label, legend, 6 | table, caption, tbody, tfoot, thead, tr, th, td { 7 | margin: 0; 8 | padding: 0; 9 | border: 0; 10 | font-weight: inherit; 11 | font-style: inherit; 12 | font-size: 100%; 13 | font-family: inherit; 14 | vertical-align: baseline; 15 | } 16 | 17 | 18 | /* Tables still need 'cellspacing="0"' in the markup. */ 19 | table { border-collapse: separate; border-spacing: 0; } 20 | caption, th, td { text-align: left; font-weight: normal; } 21 | table, td, th { vertical-align: middle; } 22 | 23 | /* Remove possible quote marks (") from,. */ 24 | blockquote:before, blockquote:after, q:before, q:after { content: ""; } 25 | blockquote, q { quotes: "" ""; } 26 | 27 | /* Remove annoying border on linked images. */ 28 | a img { border: none; } 29 | 30 | 31 | body { 32 | 33 | margin: 10px; 34 | } 35 | 36 | -------------------------------------------------------------------------------- /app/assets/stylesheets/lib/_reset.scss: -------------------------------------------------------------------------------- 1 | /* http://meyerweb.com/eric/tools/css/reset/ 2 | v2.0 | 20110126 3 | License: none (public domain) 4 | */ 5 | 6 | html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video { 7 | margin: 0; 8 | padding: 0; 9 | border: 0; 10 | font-size: 100%; 11 | font: inherit; 12 | vertical-align: baseline; } 13 | 14 | /* HTML5 display-role reset for older browsers */ 15 | 16 | article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section { 17 | display: block; } 18 | 19 | body { 20 | line-height: 1; } 21 | 22 | ol, ul { 23 | list-style: none; } 24 | 25 | blockquote, q { 26 | quotes: none; } 27 | 28 | blockquote { 29 | &:before, &:after { 30 | content: ''; 31 | content: none; } } 32 | 33 | q { 34 | &:before, &:after { 35 | content: ''; 36 | content: none; } } 37 | 38 | table { 39 | border-collapse: collapse; 40 | border-spacing: 0; } -------------------------------------------------------------------------------- /app/assets/stylesheets/syntax/_tomorrow.scss: -------------------------------------------------------------------------------- 1 | .highlight .hll { background-color: #d6d6d6 } 2 | .highlight { background: #ffffff; color: #4d4d4c } 3 | .highlight .c { color: #8e908c } /* Comment */ 4 | .highlight .err { color: #c82829 } /* Error */ 5 | .highlight .k { color: #8959a8 } /* Keyword */ 6 | .highlight .l { color: #f5871f } /* Literal */ 7 | .highlight .n { color: #4d4d4c } /* Name */ 8 | .highlight .o { color: #3e999f } /* Operator */ 9 | .highlight .p { color: #4d4d4c } /* Punctuation */ 10 | .highlight .cm { color: #8e908c } /* Comment.Multiline */ 11 | .highlight .cp { color: #8e908c } /* Comment.Preproc */ 12 | .highlight .c1 { color: #8e908c } /* Comment.Single */ 13 | .highlight .cs { color: #8e908c } /* Comment.Special */ 14 | .highlight .gd { color: #c82829 } /* Generic.Deleted */ 15 | .highlight .ge { font-style: italic } /* Generic.Emph */ 16 | .highlight .gh { color: #4d4d4c; font-weight: bold } /* Generic.Heading */ 17 | .highlight .gi { color: #718c00 } /* Generic.Inserted */ 18 | .highlight .gp { color: #8e908c; font-weight: bold } /* Generic.Prompt */ 19 | .highlight .gs { font-weight: bold } /* Generic.Strong */ 20 | .highlight .gu { color: #3e999f; font-weight: bold } /* Generic.Subheading */ 21 | .highlight .kc { color: #8959a8 } /* Keyword.Constant */ 22 | .highlight .kd { color: #8959a8 } /* Keyword.Declaration */ 23 | .highlight .kn { color: #3e999f } /* Keyword.Namespace */ 24 | .highlight .kp { color: #8959a8 } /* Keyword.Pseudo */ 25 | .highlight .kr { color: #8959a8 } /* Keyword.Reserved */ 26 | .highlight .kt { color: #eab700 } /* Keyword.Type */ 27 | .highlight .ld { color: #718c00 } /* Literal.Date */ 28 | .highlight .m { color: #f5871f } /* Literal.Number */ 29 | .highlight .s { color: #718c00 } /* Literal.String */ 30 | .highlight .na { color: #4271ae } /* Name.Attribute */ 31 | .highlight .nb { color: #4d4d4c } /* Name.Builtin */ 32 | .highlight .nc { color: #eab700 } /* Name.Class */ 33 | .highlight .no { color: #c82829 } /* Name.Constant */ 34 | .highlight .nd { color: #3e999f } /* Name.Decorator */ 35 | .highlight .ni { color: #4d4d4c } /* Name.Entity */ 36 | .highlight .ne { color: #c82829 } /* Name.Exception */ 37 | .highlight .nf { color: #4271ae } /* Name.Function */ 38 | .highlight .nl { color: #4d4d4c } /* Name.Label */ 39 | .highlight .nn { color: #eab700 } /* Name.Namespace */ 40 | .highlight .nx { color: #4271ae } /* Name.Other */ 41 | .highlight .py { color: #4d4d4c } /* Name.Property */ 42 | .highlight .nt { color: #3e999f } /* Name.Tag */ 43 | .highlight .nv { color: #c82829 } /* Name.Variable */ 44 | .highlight .ow { color: #3e999f } /* Operator.Word */ 45 | .highlight .w { color: #4d4d4c } /* Text.Whitespace */ 46 | .highlight .mf { color: #f5871f } /* Literal.Number.Float */ 47 | .highlight .mh { color: #f5871f } /* Literal.Number.Hex */ 48 | .highlight .mi { color: #f5871f } /* Literal.Number.Integer */ 49 | .highlight .mo { color: #f5871f } /* Literal.Number.Oct */ 50 | .highlight .sb { color: #718c00 } /* Literal.String.Backtick */ 51 | .highlight .sc { color: #4d4d4c } /* Literal.String.Char */ 52 | .highlight .sd { color: #8e908c } /* Literal.String.Doc */ 53 | .highlight .s2 { color: #718c00 } /* Literal.String.Double */ 54 | .highlight .se { color: #f5871f } /* Literal.String.Escape */ 55 | .highlight .sh { color: #718c00 } /* Literal.String.Heredoc */ 56 | .highlight .si { color: #f5871f } /* Literal.String.Interpol */ 57 | .highlight .sx { color: #718c00 } /* Literal.String.Other */ 58 | .highlight .sr { color: #718c00 } /* Literal.String.Regex */ 59 | .highlight .s1 { color: #718c00 } /* Literal.String.Single */ 60 | .highlight .ss { color: #718c00 } /* Literal.String.Symbol */ 61 | .highlight .bp { color: #4d4d4c } /* Name.Builtin.Pseudo */ 62 | .highlight .vc { color: #c82829 } /* Name.Variable.Class */ 63 | .highlight .vg { color: #c82829 } /* Name.Variable.Global */ 64 | .highlight .vi { color: #c82829 } /* Name.Variable.Instance */ 65 | .highlight .il { color: #f5871f } /* Literal.Number.Integer.Long */ -------------------------------------------------------------------------------- /app/assets/stylesheets/themes/flatdoc.css.scss: -------------------------------------------------------------------------------- 1 | @import '../lib/reset'; 2 | 3 | // Fonts 4 | $body-font: Helvetica Neue, Open Sans, sans-serif; 5 | $mono-font: Menlo, monospace; 6 | 7 | // Margins 8 | $pad: 40px; // Space between things 9 | $sidepad: 30px; // Padding to the left of the sidebar 10 | $minipad: 20px; // Space for mobile 11 | $vmargin: 10px; // Margin between blocks 12 | 13 | // Colors 14 | $offwhite: #f3f6fb; 15 | $grey: #9090aa; 16 | $txt: #505050; 17 | $accent: #3cc * 0.85; 18 | $line: #e4e7ec * 0.98; 19 | 20 | // Misc 21 | $shadow-str: 0.1; 22 | 23 | // Dimensions 24 | $sidebar-width: 230px; 25 | $content-width: 550px; 26 | $pre-width: 380px; 27 | 28 | /* ---------------------------------------------------------------------------- 29 | * Fonts 30 | */ 31 | 32 | @import url('//fonts.googleapis.com/css?family=Montserrat:700|Open+Sans:300'); 33 | 34 | // ---------------------------------------------------------------------------- 35 | // Mixins 36 | 37 | @mixin clearfix { 38 | &:after { 39 | content: ""; 40 | display: table; 41 | clear: both; 42 | } 43 | } 44 | 45 | @mixin scrollbar($bg: white) { 46 | & { 47 | -webkit-overflow-scrolling: touch; 48 | } 49 | &::-webkit-scrollbar { 50 | width: 15px; 51 | height: 15px; 52 | } 53 | &::-webkit-scrollbar-thumb { 54 | background: #ddd; 55 | border-radius: 8px; 56 | border: solid 4px $bg; 57 | } 58 | 59 | &:hover::-webkit-scrollbar-thumb { 60 | background: #999; 61 | box-shadow: inset 2px 2px 3px rgba(0, 0, 0, 0.2); 62 | } 63 | 64 | } 65 | 66 | @mixin antialias() { 67 | -webkit-font-smoothing: antialiased; 68 | text-rendering: optimizeLegibility; 69 | } 70 | 71 | /* ---------------------------------------------------------------------------- 72 | * Base 73 | */ 74 | 75 | 76 | 77 | html, body { 78 | height: 100%; 79 | } 80 | 81 | html { 82 | overflow-x: hidden; 83 | } 84 | 85 | body, td, textarea, input { 86 | font-family: $body-font; 87 | line-height: 1.6; 88 | font-size: 13px; 89 | color: $txt; 90 | 91 | @media (max-width: 480px) {/* Mobile */ 92 | font-size: 12px; 93 | } 94 | } 95 | 96 | a { 97 | color: $accent; 98 | text-decoration: none; 99 | &:hover { 100 | color: $accent * 0.8; 101 | } 102 | } 103 | 104 | /* ---------------------------------------------------------------------------- 105 | * Content styling 106 | */ 107 | 108 | #content { 109 | p, ul, ol, h1, h2, h3, h4, h5, h6, pre, blockquote { 110 | padding: $vmargin 0; 111 | box-sizing: border-box; 112 | } 113 | 114 | h1, h2, h3, h4, h5, h6 { 115 | font-weight: bold; 116 | @include antialias(); 117 | } 118 | 119 | pre { 120 | font-family: $mono-font; 121 | } 122 | 123 | ul > li { 124 | list-style-type: disc; 125 | } 126 | 127 | ol > li { 128 | list-style-type: decimal; 129 | } 130 | 131 | ul, ol { 132 | margin-left: 20px; 133 | } 134 | 135 | ul > li { 136 | list-style-type: none; 137 | position: relative; 138 | &:before { 139 | content: ''; 140 | display: block; 141 | absolute: left -17px top 7px; 142 | width: 5px; 143 | height: 5px; 144 | border-radius: 4px; 145 | box-sizing: border-box; 146 | background: white; 147 | border: solid 1px $grey; 148 | } 149 | } 150 | 151 | li > :first-child { 152 | padding-top: 0 153 | } 154 | 155 | strong, b { 156 | font-weight: bold; 157 | } 158 | 159 | i, em { 160 | font-style: italic; 161 | color: $grey; 162 | } 163 | 164 | code, .highlight pre { 165 | font-family: $mono-font; 166 | background: $offwhite; 167 | padding: 1px 3px; 168 | font-size: 0.95em; 169 | } 170 | 171 | .highlight pre { 172 | display: block; 173 | background: transparent; 174 | font-size: 0.85em; 175 | letter-spacing: -1px; 176 | } 177 | 178 | blockquote { 179 | :first-child { 180 | padding-top: 0; 181 | } 182 | :last-child { 183 | padding-bottom: 0; 184 | } 185 | } 186 | 187 | table { 188 | 189 | margin-top: $vmargin; 190 | margin-bottom: $vmargin; 191 | padding: 0; 192 | border-collapse: collapse; 193 | clear: both; 194 | 195 | tr { 196 | border-top: 1px solid #cccccc; 197 | background-color: white; 198 | margin: 0; 199 | padding: 0; 200 | 201 | :nth-child(2n) { 202 | background-color: #f8f8f8; 203 | } 204 | 205 | th { 206 | text-align: auto; 207 | font-weight: bold; 208 | border: 1px solid #cccccc; 209 | margin: 0; 210 | padding: 6px 13px; 211 | } 212 | td { 213 | text-align: auto; 214 | border: 1px solid #cccccc; 215 | margin: 0; 216 | padding: 6px 13px; 217 | } 218 | th, td { 219 | :first-child { 220 | margin-top: 0; 221 | } 222 | :last-child { 223 | margin-bottom: 0; 224 | } 225 | } 226 | } 227 | } 228 | 229 | } 230 | 231 | /* ---------------------------------------------------------------------------- 232 | * Content 233 | */ 234 | 235 | #container { 236 | min-height: 90%; 237 | position: relative; 238 | } 239 | 240 | #content { 241 | padding-top: $pad - $vmargin; 242 | padding-bottom: $pad; 243 | padding-left: $pad; 244 | padding-right: $pad; 245 | @include clearfix; 246 | max-width: 700px; 247 | blockquote { 248 | color: $grey; 249 | text-shadow: 0 1px 0 rgba(white, 0.5); 250 | } 251 | h1, h2, h3 { 252 | @include antialias; 253 | font-family: montserrat; 254 | padding-bottom: 0; 255 | + p, ul, ol { 256 | padding-top: 10px; 257 | } 258 | } 259 | h1, h2 { 260 | text-transform: uppercase; 261 | letter-spacing: 1px; 262 | font-size: 1.5em; 263 | } 264 | h3 { 265 | font-size: 1.2em; 266 | } 267 | // Lines 268 | h1, h2, .big-heading { 269 | padding-top: $pad * 2; 270 | &:before { 271 | display: block; 272 | content: ""; 273 | background: linear-gradient(left, rgba($line, 1) 80%, rgba($line, 0)); 274 | box-shadow: 0 1px 0 rgba(white, 0.4); 275 | height: 1px; 276 | position: relative; 277 | top: $pad * -1; 278 | left: $pad * -1; 279 | width: 100%; 280 | } 281 | @media (max-width: 768px) { 282 | padding-top: $minipad * 2; 283 | &:before { 284 | background: $line; 285 | left: $pad * -1; 286 | top: $minipad * -1; 287 | width: 120%; 288 | } 289 | } 290 | } 291 | // Small headings 292 | h4, h5, .small-heading { 293 | border-bottom: solid 1px rgba(black, 0.07); 294 | color: $grey; 295 | padding-top: $vmargin * 3; 296 | padding-bottom: 10px; 297 | } 298 | body:not(.big-h3) & h3 { 299 | @extends #content .small-heading; 300 | font-size: 0.9em; 301 | } 302 | body.big-h3 & h3 { 303 | @extends #content .big-heading; 304 | } 305 | h1:first-child { 306 | padding-top: 0; 307 | &, a, a:visited { 308 | color: $txt; 309 | } 310 | &:before { 311 | display: none; 312 | } 313 | } 314 | } 315 | 316 | @media (max-width: 768px) { 317 | #content { 318 | h4, h5, .small-heading, body:not(.big-h3) & h3 { 319 | padding-top: $vmargin * 2; 320 | } 321 | } 322 | } 323 | 324 | @media (max-width: 480px) { 325 | #content { 326 | padding: $minipad; 327 | padding-top: $minipad * 2; 328 | h4, h5, .small-heading, body:not(.big-h3) & h3 { 329 | padding-top: $vmargin; 330 | } 331 | } 332 | } 333 | 334 | // ---------------------------------------------------------------------------- 335 | // Code blocks 336 | 337 | @mixin inset-box { 338 | background: $offwhite; 339 | border: solid 1px $offwhite * 0.95; 340 | border-top: solid 1px $offwhite * 0.9; 341 | border-left: solid 1px $offwhite * 0.93; 342 | display: block; 343 | padding: 10px; 344 | border-radius: 2px; 345 | overflow: auto; 346 | @include scrollbar($offwhite); 347 | } 348 | 349 | body.no-literate #content .highlight pre { 350 | @include inset-box; 351 | } 352 | 353 | @media (max-width: 1180px) { 354 | #content .highlight pre { 355 | @include inset-box; 356 | } 357 | } 358 | 359 | // ---------------------------------------------------------------------------- 360 | // Buttons 361 | 362 | .button { 363 | @include antialias; 364 | font-family: montserrat, sans-serif; 365 | letter-spacing: -1px; 366 | font-weight: bold; 367 | display: inline-block; 368 | padding: 3px 25px; 369 | border: solid 2px $accent; 370 | border-radius: 20px; 371 | margin-right: 15px; 372 | &, &:visited { 373 | background: $accent; 374 | color: white; 375 | text-shadow: none; 376 | } 377 | &:hover { 378 | border-color: #111111; 379 | background: #111111; 380 | color: white; 381 | } 382 | &.light { 383 | &, &:visited { 384 | background: transparent; 385 | color: $grey; 386 | border-color: $grey; 387 | text-shadow: none; 388 | } 389 | &:hover { 390 | border-color: $grey; 391 | background: $grey; 392 | color: white; 393 | } 394 | } 395 | } 396 | 397 | #content { 398 | .button + em { 399 | color: $grey; 400 | } 401 | } 402 | 403 | // ---------------------------------------------------------------------------- 404 | // Literate mode content 405 | 406 | @media (min-width: 1180px) { 407 | body:not(.no-literate) { 408 | #container { 409 | background-color: $offwhite; 410 | $w: $sidebar-width + $content-width; 411 | box-shadow: inset $w 0 white, inset $w + 1 0 $line, inset $w + 10 0 5px -10px rgba(black, $shadow-str); 412 | } 413 | } 414 | } 415 | 416 | // Literate mode 417 | @media (min-width: 1180px) { 418 | @mixin small-heading { 419 | margin-left: $pad; 420 | width: $content-width - $pad * 2; 421 | margin-bottom: 3px; 422 | padding-left: 0; 423 | padding-right: 0; 424 | } 425 | body:not(.no-literate) { 426 | #content { 427 | padding-left: 0; 428 | padding-right: 0; 429 | width: $content-width + $pre-width; 430 | max-width: none; 431 | > { 432 | p, ul, ol, h1, h2, h3, h4, h5, h6, pre, blockquote { 433 | width: $content-width; 434 | box-sizing: border-box; 435 | padding-right: $pad; 436 | padding-left: $pad; 437 | } 438 | h1, h2, h3 { 439 | clear: both; 440 | width: 100%; 441 | } 442 | pre, blockquote { 443 | width: $pre-width; 444 | padding-left: $pad / 2; 445 | padding-right: $pad / 2; 446 | float: right; 447 | clear: right; 448 | + { 449 | p, ul, ol, h4, h5, h6 { 450 | clear: both; 451 | } 452 | } 453 | } 454 | p, ul, ol, h4, h5, h6 { 455 | float: left; 456 | clear: left; 457 | } 458 | h4, h5, .small-heading, body:not(.big-h3) & h3 { 459 | @include small-heading; 460 | } 461 | table { 462 | margin-left: $pad; 463 | margin-right: $pad; 464 | max-width: $content-width - $pad * 2; 465 | } 466 | } 467 | } 468 | } 469 | body:not(.no-literate):not(.big-h3) { 470 | #content > h3 { 471 | @include small-heading; 472 | } 473 | } 474 | } 475 | 476 | // ---------------------------------------------------------------------------- 477 | // Header 478 | 479 | #header { 480 | background: $offwhite; 481 | text-shadow: 0 1px 0 rgba(white, 0.5); 482 | border-bottom: solid 1px $line; 483 | padding: 15px 15px 15px $sidepad; 484 | @include clearfix; 485 | line-height: 20px; 486 | position: relative; 487 | .left { 488 | float: left; 489 | } 490 | .right { 491 | text-align: right; 492 | position: absolute; 493 | right: 15px; 494 | top: 15px; 495 | iframe { 496 | display: inline-block; 497 | vertical-align: middle; 498 | } 499 | } 500 | h1 { 501 | @include antialias; 502 | font-weight: bold; 503 | font-family: montserrat, sans-serif; 504 | font-size: 13px; 505 | &, a, a:visited { 506 | color: $grey; 507 | } 508 | a:hover { 509 | color: $txt; 510 | } 511 | } 512 | li a { 513 | font-size: 0.88em; 514 | color: $grey; 515 | display: block; 516 | &:hover { 517 | color: $grey * 0.4; 518 | } 519 | } 520 | @media (min-width: 480px) { 521 | h1 { 522 | float: left; 523 | } 524 | ul, li { 525 | display: block; 526 | float: left; 527 | } 528 | ul { 529 | margin-left: -15px; 530 | } 531 | h1 + ul { 532 | border-left: solid 1px $line; 533 | margin-left: 15px; 534 | } 535 | li { 536 | border-left: solid 1px rgba(white, 0.5); 537 | border-right: solid 1px $line; 538 | &:last-child { 539 | border-right: 0; 540 | } 541 | } 542 | li a { 543 | padding: 0 15px; 544 | } 545 | } 546 | } 547 | 548 | @media (max-width: 480px) { 549 | // Hide extra stuff on mobile 550 | .right { 551 | display: none; 552 | } 553 | } 554 | 555 | // ---------------------------------------------------------------------------- 556 | // Sidebar 557 | 558 | #nav { 559 | @include antialias; 560 | .section { 561 | padding: $sidepad $sidepad; 562 | box-sizing: border-box; 563 | } 564 | .section + .section { 565 | border-top: solid 1px $line; 566 | } 567 | .section.no-line { 568 | border-top: 0; 569 | padding-top: 0; 570 | } 571 | } 572 | 573 | a.big.button { 574 | display: block; 575 | box-sizing: border-box; 576 | width: 100%; 577 | padding: 10px 20px; 578 | text-align: center; 579 | font-weight: bold; 580 | font-size: 1.1em; 581 | background: transparent; 582 | border: solid 3px $accent; 583 | border-radius: 30px; 584 | font-family: montserrat, sans-serif; 585 | &, &:visited { 586 | color: $accent; 587 | text-decoration: none; 588 | } 589 | &:hover { 590 | background: $accent; 591 | &, &:visited { 592 | color: white; 593 | } 594 | } 595 | } 596 | 597 | @media (max-width: 480px) { 598 | #nav { 599 | padding: $minipad; 600 | border-bottom: solid 1px $line; 601 | } 602 | } 603 | 604 | @media (max-width: 768px) { 605 | #nav { 606 | display: none; 607 | } 608 | } 609 | 610 | @media (min-width: 768px) { 611 | #container { 612 | padding-left: $sidebar-width; 613 | } 614 | #nav { 615 | position: absolute; 616 | left: 0; 617 | top: 0; 618 | bottom: 0; 619 | width: $sidebar-width; 620 | border-right: solid 1px $line; 621 | } 622 | #nav.fixed { 623 | position: fixed; 624 | @include scrollbar; 625 | overflow-y: auto; 626 | } 627 | } 628 | 629 | #nav { 630 | font-size: 0.9em; 631 | } 632 | 633 | // Menu items 634 | #nav { 635 | .h2 { 636 | margin-top: 20px; 637 | } 638 | a { 639 | box-sizing: border-box; 640 | position: relative; 641 | display: block; 642 | padding-top: 1px; 643 | padding-bottom: 1px; 644 | margin-right: $sidepad * -1; 645 | &, &:visited { 646 | color: $accent; 647 | } 648 | &:hover { 649 | color: $accent * 0.8; 650 | } 651 | } 652 | .h2 a { 653 | font-family: montserrat, sans-serif; 654 | text-transform: uppercase; 655 | font-size: 0.9em; 656 | font-weight: bold; 657 | &, &:visited { 658 | color: $grey; 659 | } 660 | &:hover { 661 | color: $grey * 0.6; 662 | } 663 | } 664 | .h3 a { 665 | font-weight: normal; 666 | } 667 | .h4 a { 668 | font-weight: normal; 669 | font-size: 0.9em; 670 | padding-left: 10px; 671 | } 672 | a.active { 673 | &, &:visited, &:hover { 674 | color: $txt !important; 675 | } 676 | font-weight: bold !important; 677 | // Indicator 678 | &:after { 679 | content: ""; 680 | display: block; 681 | box-sizing: border-box; 682 | absolute: top 10px right $sidepad; 683 | width: 9px; 684 | height: 3px; 685 | border-radius: 2px; 686 | background: $accent; 687 | } 688 | } 689 | } 690 | 691 | // ---------------------------------------------------------------------------- 692 | // Syntax highlighting 693 | 694 | // code { 695 | // .string, .number { 696 | // color: #33aacc; 697 | // } 698 | // .init { 699 | // color: #338833; 700 | // } 701 | // .keyword { 702 | // font-weight: bold; 703 | // } 704 | // .comment { 705 | // color: $grey * 1.2; 706 | // } 707 | // } 708 | 709 | .highlight .hll { background-color: #d6d6d6 } 710 | .highlight .c { color: $grey * 1.2; } /* Comment */ 711 | .highlight .k { font-weight: bold; } /* Keyword */ 712 | .highlight .l { color: #33aacc } /* Literal */ 713 | .highlight .n { color: #4d4d4c } /* Name */ 714 | .highlight .o { color: #3e999f } /* Operator */ 715 | .highlight .p { color: #4d4d4c } /* Punctuation */ 716 | .highlight .cm { color: #8e908c } /* Comment.Multiline */ 717 | .highlight .cp { color: #8e908c } /* Comment.Preproc */ 718 | .highlight .c1 { color: #8e908c } /* Comment.Single */ 719 | .highlight .cs { color: #8e908c } /* Comment.Special */ 720 | .highlight .gd { color: #c82829 } /* Generic.Deleted */ 721 | .highlight .ge { font-style: italic } /* Generic.Emph */ 722 | .highlight .gh { color: #4d4d4c; font-weight: bold } /* Generic.Heading */ 723 | .highlight .gi { color: #718c00 } /* Generic.Inserted */ 724 | .highlight .gp { color: #8e908c; font-weight: bold } /* Generic.Prompt */ 725 | .highlight .gs { font-weight: bold } /* Generic.Strong */ 726 | .highlight .gu { color: #3e999f; font-weight: bold } /* Generic.Subheading */ 727 | .highlight .kc { color: #8959a8 } /* Keyword.Constant */ 728 | .highlight .kd { color: #8959a8 } /* Keyword.Declaration */ 729 | .highlight .kn { color: #3e999f } /* Keyword.Namespace */ 730 | .highlight .kp { color: #8959a8 } /* Keyword.Pseudo */ 731 | .highlight .kr { color: #8959a8 } /* Keyword.Reserved */ 732 | .highlight .kt { color: #eab700 } /* Keyword.Type */ 733 | .highlight .ld { color: #718c00 } /* Literal.Date */ 734 | .highlight .m { color: #33aacc } /* Literal.Number */ 735 | .highlight .s { color: #33aacc } /* Literal.String */ 736 | .highlight .na { color: #4271ae } /* Name.Attribute */ 737 | .highlight .nb { color: #4d4d4c } /* Name.Builtin */ 738 | .highlight .nc { color: #eab700 } /* Name.Class */ 739 | .highlight .no { color: #c82829 } /* Name.Constant */ 740 | .highlight .nd { color: #3e999f } /* Name.Decorator */ 741 | .highlight .ni { color: #4d4d4c } /* Name.Entity */ 742 | .highlight .ne { color: #c82829 } /* Name.Exception */ 743 | .highlight .nf { color: #4271ae } /* Name.Function */ 744 | .highlight .nl { color: #4d4d4c } /* Name.Label */ 745 | .highlight .nn { color: #eab700 } /* Name.Namespace */ 746 | .highlight .nx { color: #4271ae } /* Name.Other */ 747 | .highlight .py { color: #4d4d4c } /* Name.Property */ 748 | .highlight .nt { color: #3e999f } /* Name.Tag */ 749 | .highlight .nv { color: #c82829 } /* Name.Variable */ 750 | .highlight .ow { color: #3e999f } /* Operator.Word */ 751 | .highlight .w { color: #4d4d4c } /* Text.Whitespace */ 752 | .highlight .mf { color: #33aacc } /* Literal.Number.Float */ 753 | .highlight .mh { color: #33aacc } /* Literal.Number.Hex */ 754 | .highlight .mi { color: #33aacc } /* Literal.Number.Integer */ 755 | .highlight .mo { color: #33aacc } /* Literal.Number.Oct */ 756 | .highlight .sb { color: #33aacc } /* Literal.String.Backtick */ 757 | .highlight .sc { color: #4d4d4c } /* Literal.String.Char */ 758 | .highlight .sd { color: #8e908c } /* Literal.String.Doc */ 759 | .highlight .s2 { color: #33aacc } /* Literal.String.Double */ 760 | .highlight .se { color: #33aacc } /* Literal.String.Escape */ 761 | .highlight .sh { color: #33aacc } /* Literal.String.Heredoc */ 762 | .highlight .si { color: #33aacc } /* Literal.String.Interpol */ 763 | .highlight .sx { color: #33aacc } /* Literal.String.Other */ 764 | .highlight .sr { color: #33aacc } /* Literal.String.Regex */ 765 | .highlight .s1 { color: #33aacc } /* Literal.String.Single */ 766 | .highlight .ss { color: #33aacc } /* Literal.String.Symbol */ 767 | .highlight .bp { color: #4d4d4c } /* Name.Builtin.Pseudo */ 768 | .highlight .vc { color: #c82829 } /* Name.Variable.Class */ 769 | .highlight .vg { color: #c82829 } /* Name.Variable.Global */ 770 | .highlight .vi { color: #c82829 } /* Name.Variable.Instance */ 771 | .highlight .il { color: #33aacc } /* Literal.Number.Integer.Long */ 772 | 773 | // ---------------------------------------------------------------------------- 774 | 775 | #content { 776 | .large-brief & > h1:first-child + p, 777 | > p.brief { 778 | font-size: 1.3em; 779 | font-family: Open Sans, sans-serif; 780 | font-weight: 300; 781 | } 782 | } 783 | 784 | // ---------------------------------------------------------------------------- 785 | 786 | .title-area { 787 | min-height: 100px; 788 | box-sizing: border-box; 789 | @include antialias; 790 | text-align: center; 791 | border-bottom: solid 1px $line; 792 | overflow: hidden; 793 | > img.bg { 794 | z-index: 0; 795 | // Start it off screen 796 | position: absolute; 797 | left: -9999px; 798 | } 799 | > div { 800 | position: relative; 801 | z-index: 1; 802 | } 803 | } 804 | 805 | #github-ribbon { 806 | position: absolute; 807 | top: 0; 808 | right: 0; 809 | img { 810 | border: 0; 811 | } 812 | } -------------------------------------------------------------------------------- /app/assets/stylesheets/themes/v1.css.scss: -------------------------------------------------------------------------------- 1 | @import "../lib/normalize"; 2 | @import "../syntax/tomorrow"; 3 | 4 | @mixin clearfix { 5 | &:after { 6 | content: ""; 7 | display: table; 8 | clear: both; 9 | } 10 | } 11 | 12 | html { 13 | height: 100%; 14 | } 15 | 16 | body { 17 | padding: 0; 18 | margin: 0; 19 | font: 16px/1.4em Constantia, "Lucida Bright", Lucidabright, "Lucida Serif", Lucida, "DejaVu Serif", "Bitstream Vera Serif", "Liberation Serif", Georgia, serif; 20 | font-size-adjust:none; 21 | font-style:normal; 22 | font-variant:normal; 23 | font-weight:normal; 24 | } 25 | 26 | h1, h2, h3, h4, #header, #nav, #loader { 27 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 28 | } 29 | 30 | a { 31 | color: #369; 32 | } 33 | 34 | // Layout 35 | 36 | #header { 37 | border-bottom: 1px solid #ccc; 38 | #logo { 39 | color: #333; 40 | font-size: 18px; 41 | font-weight: bold; 42 | padding: 10px 15px; 43 | line-height: 1.2em; 44 | text-decoration: none; 45 | } 46 | } 47 | 48 | #nav { 49 | position: fixed; 50 | top: 0; 51 | left: 0; 52 | width: 250px; 53 | height: 100%; 54 | background: #f9f9f9; 55 | background: rgba(black, 0.1); 56 | border-right: 1px solid rgba(black, 0.2); 57 | box-shadow: rgba(black, 0.1) -1px 0 3px 0 inset; 58 | text-shadow: rgba(white, 0.7) 0 1px 0; 59 | overflow-x: hidden; 60 | overflow-y: auto; 61 | a { 62 | display: block; 63 | font-weight: bold; 64 | text-decoration: none; 65 | } 66 | #sections { 67 | margin-bottom: 5px; 68 | border-bottom: 1px solid #ccc; 69 | background: #f1f1f1; 70 | box-shadow: rgba(black, 0.15) 0 0 5px; 71 | li.h2 { 72 | border-bottom: 1px solid rgba(black, 0.05); 73 | border-top: 1px solid rgba(white, 0.5); 74 | > a { 75 | padding: 5px 15px; 76 | color: #555; 77 | font-size: 14px; 78 | &:hover { 79 | background: #ddd; 80 | background: rgba(black, 0.05); 81 | } 82 | } 83 | } 84 | li.h2 { 85 | // margin-top: 6px; 86 | } 87 | li.h3 { 88 | a { 89 | padding: 1px 25px; 90 | font-size: 13px; 91 | &:hover { 92 | background: #ddd; 93 | background: rgba(black, 0.05); 94 | } 95 | } 96 | } 97 | } 98 | .extra { 99 | padding: 5px 15px; 100 | min-height: 1.4em; 101 | a { 102 | color: #555; 103 | font-size: 14px; 104 | } 105 | } 106 | #travis { 107 | img {margin-top: 10px; display: block;} 108 | } 109 | 110 | > *:last-child { 111 | margin-bottom: 20px; 112 | } 113 | } 114 | 115 | #github-ribbon { 116 | position: absolute; 117 | top: 0; 118 | right: 0; 119 | img { 120 | border: 0; 121 | } 122 | } 123 | 124 | #refresh { 125 | z-index: 3; 126 | position: fixed; 127 | display: block; 128 | top: 0; 129 | left: 50%; 130 | width: 320px; 131 | margin-left: -160px; 132 | font-family: "Helvetica Neue", "Helvetica", arial, sans-serif; 133 | line-height: 1.4em; 134 | padding: 10px; 135 | color: #fff; 136 | text-shadow: rgba(black, 0.3) 0 1px 1px; 137 | font-weight: bold; 138 | font-size: 13px; 139 | text-decoration: none; 140 | text-align: center; 141 | background: #666; 142 | border-radius: bottom 5px; 143 | } 144 | 145 | #content { 146 | margin: 0 40px 0 290px; 147 | padding: 30px 0 20px; 148 | min-height: 100px; 149 | max-width: 688px; 150 | #loader { 151 | color: #888; 152 | width: 300px; 153 | height: 24px; 154 | line-height: 24px; 155 | position: absolute; 156 | top: 30px; 157 | left: 30px; 158 | background: url(unquote('data:image/gif;base64,R0lGODlhGAAYAPYAAP///5mZmfn5+dvb27i4uKmpqaCgoNra2v39/c/Pz6CgoJmZmfT09K+vr66urvb29qWlpaSkpPPz8/v7+87Ozvj4+NXV1dTU1Li4uKysrJubm52dnaqqqu7u7uPj46Ojo8LCwvb29ra2tqenp7q6utzc3JycnNfX1/Ly8uzs7J6ensbGxs3NzeDg4MvLy9LS0r+/v/r6+qysrOrq6t7e3tnZ2cTExLS0tLOzs6ioqLGxsefn57W1tcvLy7y8vMHBwd7e3qKiovHx8cfHx+Hh4QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH+GkNyZWF0ZWQgd2l0aCBhamF4bG9hZC5pbmZvACH5BAAFAAAAIf8LTkVUU0NBUEUyLjADAQAAACwAAAAAGAAYAAAHmoAAgoOEhYaHgxUWBA4aCxwkJwKIhBMJBguZmpkqLBOUDw2bo5kKEogMEKSkLYgIoqubK5QJsZsNCIgCCraZBiiUA72ZJZQABMMgxgAFvRyfxpixGx3LANKxHtbNth8hy8i9IssHwwsXxgLYsSYpxrXDz5QIDubKlAwR5q2UErC2poxNoLBukwoX0IxVuIAhQ6YRBC5MskaxUCAAIfkEAAUAAQAsAAAAABgAGAAAB6GAAIKDhIWGh4MVFgQOGhsOGAcxiIQTCQYLmZqZGwkIlA8Nm6OaMgyHDBCkqwsjEoUIoqykNxWFCbOkNoYCCrmaJjWHA7+ZHzOIBMUND5QFvzATlACYsy/TgtWsIpPTz7kyr5TKv8eUB8ULGzSIAtq/CYi46Qswn7AO9As4toUMEfRcHZIgC9wpRBMovNvU6d60ChcwZFigwYGIAwKwaUQUCAAh+QQABQACACwAAAAAGAAYAAAHooAAgoOEhYaHgxUWBA4aCzkkJwKIhBMJBguZmpkqLAiUDw2bo5oyEocMEKSrCxCnhAiirKs3hQmzsy+DAgq4pBogKIMDvpvAwoQExQvHhwW+zYiYrNGU06wNHpSCz746O5TKyzwzhwfLmgQphQLX6D4dhLfomgmwDvQLOoYMEegRyApJkIWLQ0BDEyi426Six4RtgipcwJAhUwQCFypA3IgoEAAh+QQABQADACwAAAAAGAAYAAAHrYAAgoOEhYaHgxUWBA4aCxwkJzGIhBMJBguZmpkGLAiUDw2bo5oZEocMEKSrCxCnhAiirKsZn4MJs7MJgwIKuawqFYIDv7MnggTFozlDLZMABcpBPjUMhpisJiIJKZQA2KwfP0DPh9HFGjwJQobJypoQK0S2B++kF4IC4PbBt/aaPWA5+CdjQiEGEd5FQHFIgqxcHF4dmkBh3yYVLmx5q3ABQ4ZMBUhYEOCtpLdAACH5BAAFAAQALAAAAAAYABgAAAeegACCg4SFhoeDFRYEDhoaDgQWFYiEEwkGC5mamQYJE5QPDZujmg0PhwwQpKsLEAyFCKKsqw0IhAmzswmDAgq5rAoCggO/sxaCBMWsBIIFyqsRgpjPoybS1KMqzdibBcjcmswAB+CZxwAC09gGwoK43LuDCA7YDp+EDBHPEa+GErK5GkigNIGCulEGKNyjBKDCBQwZMmXAcGESw4uUAgEAIfkEAAUABQAsAAAAABgAGAAAB62AAIKDhIWGh4MVFgQOGgscJCcxiIQTCQYLmZqZBiwIlA8Nm6OaGRKHDBCkqwsQp4QIoqyrGZ+DCbOzCYMCCrmsKhWCA7+zJ4IExaM5Qy2TAAXKQT41DIaYrCYiCSmUANisHz9Az4fRxRo8CUKGycqaECtEtgfvpBeCAuD2wbf2mj1gOfgnY0IhBhHeRUBxSIKsXBxeHZpAYd8mFS5seatwAUOGTAVIWBDgraS3QAAh+QQABQAGACwAAAAAGAAYAAAHooAAgoOEhYaHgxUWBA4aCzkkJwKIhBMJBguZmpkqLAiUDw2bo5oyEocMEKSrCxCnhAiirKs3hQmzsy+DAgq4pBogKIMDvpvAwoQExQvHhwW+zYiYrNGU06wNHpSCz746O5TKyzwzhwfLmgQphQLX6D4dhLfomgmwDvQLOoYMEegRyApJkIWLQ0BDEyi426Six4RtgipcwJAhUwQCFypA3IgoEAAh+QQABQAHACwAAAAAGAAYAAAHoYAAgoOEhYaHgxUWBA4aGw4YBzGIhBMJBguZmpkbCQiUDw2bo5oyDIcMEKSrCyMShQiirKQ3FYUJs6Q2hgIKuZomNYcDv5kfM4gExQ0PlAW/MBOUAJizL9OC1awik9PPuTKvlMq/x5QHxQsbNIgC2r8JiLjpCzCfsA70Czi2hQwR9FwdkiAL3ClEEyi829Tp3rQKFzBkWKDBgYgDArBpRBQIADsAAAAAAAAAAAA=')) no-repeat center left; 159 | padding-left: 32px; 160 | font-size: 18px; 161 | } 162 | 163 | p { padding:0 0 0.8125em 0; color:#111; font-weight:300; @include clearfix();} 164 | 165 | p img { float: left; margin: 0.5em 0.8125em 0.8125em 0; padding: 0; } 166 | img { max-width: 100%; } 167 | 168 | 169 | h1,h2,h3,h4,h5,h6 { font-weight:normal; color: #333; line-height: 1.2em; } 170 | 171 | h1 { font-size: 2.125em; margin-bottom: 0.765em; } 172 | h2 { font-size: 1.7em; margin: 0.855em 0; } 173 | h3 { font-size: 1.3em; margin: 0.956em 0; } 174 | h4 { font-size: 1.1em; margin: 1.161em 0; } 175 | h5,h6 { font-size: 1em; font-weight: bold; margin: 1.238em 0; } 176 | 177 | 178 | 179 | ul{list-style-position:outside;} 180 | li ul, 181 | li ol { margin:0 1.625em; } 182 | ul, ol { margin: 0 0 1.625em 1em; } 183 | 184 | 185 | dl { margin: 0 0 1.625em 0; } 186 | dl dt { font-weight: bold; } 187 | dl dd { margin-left: 1.625em; } 188 | 189 | a { text-decoration:none; } 190 | a:hover { text-decoration: underline; } 191 | 192 | 193 | table { margin-bottom:1.625em; border-collapse: collapse; } 194 | th { font-weight:bold; } 195 | tr,th,td { margin:0; padding:0 1.625em 0 1em; height:26px; } 196 | tfoot { font-style: italic; } 197 | caption { text-align:center; font-family:Georgia, serif; } 198 | 199 | 200 | abbr, acronym { border-bottom:1px dotted #000; } 201 | address { margin-top:1.625em; font-style: italic; } 202 | del {color:#000;} 203 | 204 | 205 | blockquote { padding:1em 1em 1.625em 1em; font-family:georgia,serif;font-style: italic; } 206 | blockquote:before { content:"\201C";font-size:3em;margin-left:-.625em; font-family:georgia,serif;color:#aaa;line-height:0;}/* From Tripoli */ 207 | blockquote > p {padding:0; margin:0; } 208 | 209 | strong { font-weight: bold; } 210 | em, dfn { font-style: italic; } 211 | dfn { font-weight: bold; } 212 | pre, code { margin: 0 0 1.625em; white-space: pre; } 213 | pre, code, tt { 214 | font-size: 0.9em; 215 | font-family: Consolas, "Andale Mono WT", "Andale Mono", "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", Monaco, "Courier New", Courier, monospace; 216 | line-height: 1.5; 217 | } 218 | code { background: #f8f8ff; padding: 1px 2px; border: 1px solid #ddd; } 219 | pre code {padding: 10px 12px; word-wrap: normal; } 220 | tt { display: block; margin: 1.625em 0; } 221 | hr { margin-bottom:1.625em; } 222 | 223 | table { 224 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 225 | width: 100%; 226 | } 227 | th, td { 228 | padding: 5px 10px; 229 | border: 1px solid #ccc; 230 | } 231 | th { 232 | background: #eee; 233 | padding: 7px 10px; 234 | } 235 | td { 236 | font-size: 0.9em; 237 | border-color: #ddd; 238 | } 239 | tbody tr:nth-child(2n) { 240 | background: #f5f5f5; 241 | } 242 | } 243 | 244 | @media only screen and (max-width : 480px) { 245 | #nav { 246 | position: static; 247 | width: 100%; 248 | height: auto; 249 | box-shadow: none; 250 | border-bottom: 1px solid #aaa; 251 | } 252 | #content { 253 | margin: 0; 254 | padding: 30px; 255 | position: relative; 256 | } 257 | } 258 | 259 | @media only screen and (min-device-pixel-ratio: 1.5), only screen and (min-resolution : 1.5dppx){ 260 | #github-ribbon { 261 | img { 262 | width: 100px; 263 | } 264 | } 265 | } 266 | -------------------------------------------------------------------------------- /app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | class ApplicationController < ActionController::Base 2 | # Prevent CSRF attacks by raising an exception. 3 | # For APIs, you may want to use :null_session instead. 4 | protect_from_forgery with: :exception 5 | before_action :ensure_repository!, :ensure_page! 6 | helper_method :current_page, :current_repository, :current_config 7 | 8 | def full_repository 9 | if Subdomain.matches? request 10 | splitted = request.subdomain.split('.') 11 | params[:user_login] = splitted.pop 12 | params[:repository_name] = splitted.join(".") 13 | end 14 | "#{params[:user_login]}/#{params[:repository_name] || params[:name]}".downcase 15 | end 16 | 17 | def current_repository 18 | @current_repository ||= Repository.where('LOWER(full_name) = ?', full_repository).first_or_create(full_name: full_repository) 19 | rescue Octokit::NotFound => exception 20 | Rails.logger.info "Could not find repository #{full_repository}" 21 | nil 22 | end 23 | 24 | def current_config 25 | @current_config ||= params[:config].present? ? Repository::Configuration.new(params[:config].is_a?(String) ? JSON.parse(params[:config]) : params[:config]) : current_repository.config 26 | end 27 | 28 | def ensure_repository! 29 | raise ActionController::RoutingError.new('Not Found') if current_repository.blank? 30 | end 31 | 32 | def current_page 33 | @current_page ||= Page.find_or_create_by(repository: current_repository, path: params[:page_path] || params[:path] || '') 34 | rescue Octokit::NotFound => exception 35 | Rails.logger.info "Could not find page #{params[:page_path] || params[:path]}" 36 | nil 37 | end 38 | 39 | def ensure_page! 40 | raise ActionController::RoutingError.new('Not Found') if current_page.blank? 41 | end 42 | 43 | def render_page 44 | respond_to do |format| 45 | format.json do 46 | html = render_to_string(template: 'pages/show.html.slim', layout: 'application') 47 | render json: { status: 200, html: html }, callback: params[:callback] 48 | end 49 | format.html { render 'pages/show' } 50 | end 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /app/controllers/concerns/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeromegn/DocumentUp/36ff103e233c77f54d9010aff4a8430397eb81b4/app/controllers/concerns/.keep -------------------------------------------------------------------------------- /app/controllers/errors_controller.rb: -------------------------------------------------------------------------------- 1 | class ErrorsController < ApplicationController 2 | skip_before_action :ensure_repository!, :ensure_page! 3 | 4 | layout 'error' 5 | 6 | def not_found 7 | render status: 404 8 | end 9 | 10 | def internal_server_error 11 | render status: 500 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /app/controllers/github_controller.rb: -------------------------------------------------------------------------------- 1 | class GithubController < ActionController::Base 2 | def push 3 | return render nothing: true unless commits? 4 | current_repository.refresh if reconfig? 5 | to_recompile.each do |filename| 6 | page = Page.find_or_create_by(repository: current_repository, path: filename) 7 | page.refresh 8 | end 9 | render nothing: true 10 | end 11 | 12 | private 13 | 14 | def current_repository 15 | @current_repository ||= Repository.where('LOWER(full_name) = ?', full_repository).first_or_create(full_name: full_repository) 16 | end 17 | 18 | def full_repository 19 | payload.repository.full_name.downcase 20 | end 21 | 22 | def payload 23 | @payload ||= Sawyer::Resource.new(Octokit.client.agent, Octokit.client.agent.class.decode(params[:payload])) 24 | end 25 | 26 | def commits 27 | @commits ||= payload.commits 28 | end 29 | 30 | def added_filenames 31 | commits.flat_map(&:added) 32 | end 33 | 34 | def modified_filenames 35 | commits.flat_map(&:modified) 36 | end 37 | 38 | def filenames 39 | @filenames ||= (added_filenames + modified_filenames).uniq 40 | end 41 | 42 | def commits? 43 | commits.present? 44 | end 45 | 46 | def reconfig? 47 | filenames.any? { |f| !(f =~ /\A\.{0,1}documentup\.(json|yml|yaml)\Z/i).nil? } 48 | end 49 | 50 | def to_recompile 51 | filenames.select {|f| !(f =~ /((?:\/README)?)\.(md|mdown|markdown)\Z/i).nil? } 52 | end 53 | end -------------------------------------------------------------------------------- /app/controllers/pages_controller.rb: -------------------------------------------------------------------------------- 1 | class PagesController < ApplicationController 2 | def show 3 | render_page 4 | end 5 | end -------------------------------------------------------------------------------- /app/controllers/repositories_controller.rb: -------------------------------------------------------------------------------- 1 | class RepositoriesController < ApplicationController 2 | protect_from_forgery except: :show 3 | def show 4 | render_page 5 | end 6 | def recompile 7 | current_page.refresh 8 | redirect_to user_repository_page_path(path: '') 9 | end 10 | end -------------------------------------------------------------------------------- /app/helpers/errors_helper.rb: -------------------------------------------------------------------------------- 1 | module ErrorsHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/models/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeromegn/DocumentUp/36ff103e233c77f54d9010aff4a8430397eb81b4/app/models/.keep -------------------------------------------------------------------------------- /app/models/page.rb: -------------------------------------------------------------------------------- 1 | require 'task_list/filter' 2 | 3 | class Page < ActiveRecord::Base 4 | belongs_to :repository 5 | 6 | before_create :fetch_source 7 | 8 | after_save :parse, if: :source_changed? 9 | 10 | def parse 11 | Rails.cache.write "page:#{id}:html", parsed[:output] 12 | Rails.cache.write "page:#{id}:toc", parsed[:toc] 13 | end 14 | 15 | def html 16 | Rails.cache.fetch("page:#{id}:html") { parsed[:output] } 17 | # parsed[:output] 18 | end 19 | def toc 20 | Rails.cache.fetch("page:#{id}:toc") { parsed[:toc] } 21 | # parsed[:toc] 22 | end 23 | 24 | def parsed(source = self.source) 25 | @parsed ||= html_pipeline.call(source) 26 | end 27 | 28 | def fetch_source 29 | if s = repository.page_source(path) 30 | self.source = s 31 | else 32 | self.source = nil 33 | false 34 | end 35 | end 36 | 37 | def blank? 38 | self.source.blank? 39 | end 40 | 41 | def refresh 42 | fetch_source 43 | save 44 | end 45 | 46 | private 47 | 48 | def html_pipeline 49 | @pipeline ||= HTML::Pipeline.new [ 50 | HTML::Pipeline::MarkdownFilter, 51 | TaskList::Filter, 52 | HTML::Pipeline::SanitizationFilter, 53 | DocumentUp::Filters::TableOfContents, 54 | HTML::Pipeline::ImageMaxWidthFilter, 55 | HTML::Pipeline::SyntaxHighlightFilter, 56 | HTML::Pipeline::EmojiFilter, 57 | HTML::Pipeline::AbsoluteSourceFilter, 58 | DocumentUp::Filters::AbsoluteLinks, 59 | HTML::Pipeline::MentionFilter, 60 | HTML::Pipeline::AutolinkFilter 61 | ], { 62 | base_url: "https://github.com/", 63 | asset_root: "https://assets-cdn.github.com/images/icons", 64 | image_base_url: "https://cdn.rawgit.com/#{repository.full_name}/#{repository.branch}/", 65 | image_subpage_url: "https://cdn.rawgit.com/#{repository.full_name}/#{repository.branch}/", 66 | link_subpage_url: "https://github.com/#{repository.full_name}/blob/#{repository.branch}/" 67 | } 68 | end 69 | 70 | end -------------------------------------------------------------------------------- /app/models/repository.rb: -------------------------------------------------------------------------------- 1 | class Repository < ActiveRecord::Base 2 | has_many :pages, dependent: :destroy 3 | after_create :refresh 4 | 5 | serialize :config, Repository::Configuration 6 | 7 | def tree 8 | @tree ||= Octokit.tree(full_name, branch, recursive: true) 9 | end 10 | 11 | def name 12 | full_name.split("/").last 13 | end 14 | def display_name 15 | config.name || name 16 | end 17 | 18 | def login 19 | full_name.split("/").first 20 | end 21 | 22 | def github_url 23 | "https://github.com/#{full_name}" 24 | end 25 | def github_issues_url 26 | "https://github.com/#{full_name}/issues" 27 | end 28 | def travis_url 29 | "http://travis-ci.org/#{full_name}" 30 | end 31 | def travis_image_url 32 | "https://travis-ci.org/#{full_name}.svg?branch=#{branch}" 33 | end 34 | 35 | def refresh_config 36 | file = tree.tree.detect do |obj| 37 | obj[:type] == 'blob' && !(obj[:path] =~ /\A.{0,1}documentup.(json|yml|yaml)/).nil? 38 | end 39 | config = if file.present? 40 | path = file[:path] 41 | contents = Octokit.contents(full_name, path: path, accept: 'application/vnd.github.raw') 42 | if path.ends_with?('yml') || path.ends_with?('yaml') 43 | YAML.load(contents) 44 | elsif path.ends_with?('json') 45 | JSON.parse(contents) 46 | end 47 | else 48 | {} 49 | end 50 | self.config = Repository::Configuration.new(config) 51 | end 52 | 53 | def find_in_tree(path) 54 | path = 'readme' if path.blank? 55 | tree.tree.detect do |obj| 56 | obj[:type] == 'blob' && !(obj[:path] =~ /(#{path}(?:\/README)?)\.(md|mdown|markdown)\z/i).nil? 57 | end 58 | end 59 | 60 | def page_source(path) 61 | if found = find_in_tree(path) 62 | Octokit.contents(full_name, path: found[:path], accept: 'application/vnd.github.raw') 63 | else 64 | false 65 | end 66 | end 67 | 68 | def refresh 69 | response = Octokit.repository(full_name) 70 | self.full_name = response.full_name 71 | self.branch = response.default_branch 72 | refresh_config 73 | save 74 | end 75 | 76 | end -------------------------------------------------------------------------------- /app/models/repository/configuration.rb: -------------------------------------------------------------------------------- 1 | class Repository::Configuration 2 | include Virtus.model 3 | attribute :name, String 4 | attribute :color, String 5 | attribute :theme, String 6 | attribute :issues, Boolean, default: true 7 | attribute :travis, Boolean, default: false 8 | attribute :twitter, String, default: "" 9 | attribute :google_analytics, String, default: nil 10 | attribute :github_ribbon, Boolean, default: true 11 | 12 | def self.load(obj) 13 | new(obj) 14 | end 15 | 16 | def twitter 17 | t = super 18 | return [] if t.blank? 19 | t.is_a?(Array) ? t : [JSON.parse(t)].flatten 20 | rescue JSON::ParserError => exception 21 | [t] 22 | end 23 | 24 | def self.dump(obj) 25 | unless obj.is_a?(self) 26 | raise ::ActiveRecord::SerializationTypeMismatch, 27 | "Attribute was supposed to be a #{self}, but was a #{obj.class}. -- #{obj.inspect}" 28 | end 29 | obj.to_h 30 | end 31 | end -------------------------------------------------------------------------------- /app/views/errors/internal_server_error.html.slim: -------------------------------------------------------------------------------- 1 | h1 Server error 2 | p My bad! 3 | a href="/" Return home -------------------------------------------------------------------------------- /app/views/errors/not_found.html.slim: -------------------------------------------------------------------------------- 1 | h1 Not found 2 | p Maybe there's a typo in there? 3 | a href="/" Return home -------------------------------------------------------------------------------- /app/views/layouts/application.html.slim: -------------------------------------------------------------------------------- 1 | 2 | html 3 | head 4 | meta charset="utf-8" 5 | meta name="apple-mobile-web-app-capable" content="yes" 6 | meta name="viewport" content="width=device-width, initial-scale=1.0" 7 | title= current_config.name || current_repository.full_name 8 | link href='//fonts.googleapis.com/css?family=Source+Code+Pro:400,700|Alegreya:400italic,700italic,400,700' rel='stylesheet' type='text/css' 9 | link rel="stylesheet" type="text/css" href=stylesheet_url(current_config.theme && "themes/#{current_config.theme}" || 'application') media="all" 10 | = csrf_meta_tags 11 | - if current_config.color.present? 12 | css: 13 | a {color: '#{current_config.color}'} 14 | 15 | body.no-literate 16 | = yield 17 | - if current_config.google_analytics.present? 18 | javascript: 19 | var _gaq = _gaq || []; 20 | _gaq.push(['_setAccount', '#{current_config.google_analytics}']); 21 | _gaq.push(['_trackPageview']); 22 | 23 | (function() { 24 | var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; 25 | ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; 26 | var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); 27 | })(); -------------------------------------------------------------------------------- /app/views/layouts/error.html.slim: -------------------------------------------------------------------------------- 1 | 2 | html 3 | head 4 | title Error | DocumentUp 5 | link href='//fonts.googleapis.com/css?family=Source+Code+Pro:400,700|Alegreya:400italic,700italic,400,700' rel='stylesheet' type='text/css' 6 | = stylesheet_link_tag 'application', media: 'all' 7 | = csrf_meta_tags 8 | 9 | body.error class="error" 10 | .header 11 | a href="/" 12 | = image_tag "logo.png", alt: 'DocumentUp' 13 | .error-message 14 | = yield -------------------------------------------------------------------------------- /app/views/pages/show.html.slim: -------------------------------------------------------------------------------- 1 | #container 2 | #nav 3 | #header 4 | a href="#" id="logo" = current_repository.display_name 5 | 6 | #sections.section 7 | == current_page.toc 8 | 9 | .extra.section#github 10 | a href=current_repository.github_url Source on Github 11 | - if current_config.issues 12 | .extra.section#github-issues 13 | a href=current_repository.github_issues_url Issues 14 | - if current_config.travis 15 | .extra.section#travis 16 | a href=current_repository.travis_url 17 | img src=current_repository.travis_image_url 18 | - current_config.twitter.each do |handle| 19 | .extra.section.twitter 20 | 21 | 22 | #content 23 | - if current_config.github_ribbon 24 | a#github-ribbon href=current_repository.github_url 25 | img src="https://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png" alt="Fork me on GitHub" 26 | == current_page.html -------------------------------------------------------------------------------- /bin/bundle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) 3 | load Gem.bin_path('bundler', 'bundle') 4 | -------------------------------------------------------------------------------- /bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | APP_PATH = File.expand_path('../../config/application', __FILE__) 3 | require_relative '../config/boot' 4 | require 'rails/commands' 5 | -------------------------------------------------------------------------------- /bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require_relative '../config/boot' 3 | require 'rake' 4 | Rake.application.run 5 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'pathname' 3 | 4 | # path to your application root. 5 | APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) 6 | 7 | Dir.chdir APP_ROOT do 8 | # This script is a starting point to setup your application. 9 | # Add necessary setup steps to this file: 10 | 11 | puts "== Installing dependencies ==" 12 | system "gem install bundler --conservative" 13 | system "bundle check || bundle install" 14 | 15 | # puts "\n== Copying sample files ==" 16 | # unless File.exist?("config/database.yml") 17 | # system "cp config/database.yml.sample config/database.yml" 18 | # end 19 | 20 | puts "\n== Preparing database ==" 21 | system "bin/rake db:setup" 22 | 23 | puts "\n== Removing old logs and tempfiles ==" 24 | system "rm -f log/*" 25 | system "rm -rf tmp/cache" 26 | 27 | puts "\n== Restarting application server ==" 28 | system "touch tmp/restart.txt" 29 | end 30 | -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | # This file is used by Rack-based servers to start the application. 2 | 3 | require ::File.expand_path('../config/environment', __FILE__) 4 | run Rails.application 5 | -------------------------------------------------------------------------------- /config/application.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../boot', __FILE__) 2 | 3 | require "rails" 4 | # Pick the frameworks you want: 5 | require "active_model/railtie" 6 | require "active_job/railtie" 7 | require "active_record/railtie" 8 | require "action_controller/railtie" 9 | require "action_mailer/railtie" 10 | require "action_view/railtie" 11 | require "sprockets/railtie" 12 | # require "rails/test_unit/railtie" 13 | 14 | # Require the gems listed in Gemfile, including any gems 15 | # you've limited to :test, :development, or :production. 16 | Bundler.require(*Rails.groups) 17 | 18 | module DocumentUp 19 | class Application < Rails::Application 20 | # Settings in config/environments/* take precedence over those specified here. 21 | # Application configuration should go into files in config/initializers 22 | # -- all .rb files in that directory are automatically loaded. 23 | 24 | # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. 25 | # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. 26 | # config.time_zone = 'Central Time (US & Canada)' 27 | 28 | # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. 29 | # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] 30 | # config.i18n.default_locale = :de 31 | 32 | config.autoload_paths << Rails.root.join('lib') 33 | 34 | # Do not swallow errors in after_commit/after_rollback callbacks. 35 | config.active_record.raise_in_transactional_callbacks = true 36 | 37 | config.exceptions_app = self.routes 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /config/boot.rb: -------------------------------------------------------------------------------- 1 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) 2 | 3 | require 'bundler/setup' # Set up gems listed in the Gemfile. 4 | -------------------------------------------------------------------------------- /config/database.yml: -------------------------------------------------------------------------------- 1 | # PostgreSQL. Versions 8.2 and up are supported. 2 | # 3 | # Install the pg driver: 4 | # gem install pg 5 | # On OS X with Homebrew: 6 | # gem install pg -- --with-pg-config=/usr/local/bin/pg_config 7 | # On OS X with MacPorts: 8 | # gem install pg -- --with-pg-config=/opt/local/lib/postgresql84/bin/pg_config 9 | # On Windows: 10 | # gem install pg 11 | # Choose the win32 build. 12 | # Install PostgreSQL and put its /bin directory on your path. 13 | # 14 | # Configure Using Gemfile 15 | # gem 'pg' 16 | # 17 | default: &default 18 | adapter: postgresql 19 | encoding: unicode 20 | # For details on connection pooling, see rails configuration guide 21 | # http://guides.rubyonrails.org/configuring.html#database-pooling 22 | pool: 5 23 | 24 | development: 25 | <<: *default 26 | database: documentup 27 | 28 | # The specified database role being used to connect to postgres. 29 | # To create additional roles in postgres see `$ createuser --help`. 30 | # When left blank, postgres will use the default role. This is 31 | # the same name as the operating system user that initialized the database. 32 | username: documentup 33 | 34 | # The password associated with the postgres role (username). 35 | password: documentup 36 | 37 | # Connect on a TCP socket. Omitted by default since the client uses a 38 | # domain socket that doesn't need configuration. Windows does not have 39 | # domain sockets, so uncomment these lines. 40 | #host: localhost 41 | 42 | # The TCP port the server listens on. Defaults to 5432. 43 | # If your server runs on a different port number, change accordingly. 44 | #port: 5432 45 | 46 | # Schema search path. The server defaults to $user,public 47 | #schema_search_path: myapp,sharedapp,public 48 | 49 | # Minimum log levels, in increasing order: 50 | # debug5, debug4, debug3, debug2, debug1, 51 | # log, notice, warning, error, fatal, and panic 52 | # Defaults to warning. 53 | #min_messages: notice 54 | 55 | # Warning: The database defined as "test" will be erased and 56 | # re-generated from your development database when you run "rake". 57 | # Do not set this db to the same as development or production. 58 | test: 59 | <<: *default 60 | database: documentup_test 61 | 62 | 63 | production: 64 | <<: *default 65 | database: documentup-prod -------------------------------------------------------------------------------- /config/database.yml.travis: -------------------------------------------------------------------------------- 1 | test: 2 | adapter: postgresql 3 | database: travis_ci_test 4 | username: postgres -------------------------------------------------------------------------------- /config/environment.rb: -------------------------------------------------------------------------------- 1 | # Load the Rails application. 2 | require File.expand_path('../application', __FILE__) 3 | 4 | # Initialize the Rails application. 5 | Rails.application.initialize! 6 | -------------------------------------------------------------------------------- /config/environments/development.rb: -------------------------------------------------------------------------------- 1 | Rails.application.configure do 2 | # Settings specified here will take precedence over those in config/application.rb. 3 | 4 | # In the development environment your application's code is reloaded on 5 | # every request. This slows down response time but is perfect for development 6 | # since you don't have to restart the web server when you make code changes. 7 | config.cache_classes = false 8 | 9 | # Do not eager load code on boot. 10 | config.eager_load = false 11 | 12 | # Show full error reports and disable caching. 13 | config.consider_all_requests_local = true 14 | config.action_controller.perform_caching = false 15 | 16 | # Don't care if the mailer can't send. 17 | config.action_mailer.raise_delivery_errors = false 18 | 19 | # Print deprecation notices to the Rails logger. 20 | config.active_support.deprecation = :log 21 | 22 | # Raise an error on page load if there are pending migrations. 23 | config.active_record.migration_error = :page_load 24 | 25 | 26 | # Raises error for missing translations 27 | # config.action_view.raise_on_missing_translations = true 28 | end 29 | -------------------------------------------------------------------------------- /config/environments/production.rb: -------------------------------------------------------------------------------- 1 | Rails.application.configure do 2 | # Settings specified here will take precedence over those in config/application.rb. 3 | 4 | # Code is not reloaded between requests. 5 | config.cache_classes = true 6 | 7 | # Eager load code on boot. This eager loads most of Rails and 8 | # your application in memory, allowing both threaded web servers 9 | # and those relying on copy on write to perform better. 10 | # Rake tasks automatically ignore this option for performance. 11 | config.eager_load = true 12 | 13 | config.assets.digest = true 14 | 15 | # Full error reports are disabled and caching is turned on. 16 | config.consider_all_requests_local = false 17 | config.action_controller.perform_caching = true 18 | 19 | # Enable Rack::Cache to put a simple HTTP cache in front of your application 20 | # Add `rack-cache` to your Gemfile before enabling this. 21 | # For large-scale production use, consider using a caching reverse proxy like 22 | # NGINX, varnish or squid. 23 | # config.action_dispatch.rack_cache = true 24 | 25 | # Disable serving static files from the `/public` folder by default since 26 | # Apache or NGINX already handles this. 27 | config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present? 28 | 29 | 30 | # Specifies the header that your server uses for sending files. 31 | # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache 32 | # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX 33 | 34 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. 35 | # config.force_ssl = true 36 | 37 | # Use the lowest log level to ensure availability of diagnostic information 38 | # when problems arise. 39 | config.log_level = :debug 40 | 41 | # Prepend all log lines with the following tags. 42 | # config.log_tags = [ :subdomain, :uuid ] 43 | 44 | # Use a different logger for distributed setups. 45 | # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new) 46 | 47 | # Use a different cache store in production. 48 | # config.cache_store = :mem_cache_store 49 | 50 | # Enable serving of images, stylesheets, and JavaScripts from an asset server. 51 | # config.action_controller.asset_host = 'http://assets.example.com' 52 | 53 | # Ignore bad email addresses and do not raise email delivery errors. 54 | # Set this to true and configure the email server for immediate delivery to raise delivery errors. 55 | # config.action_mailer.raise_delivery_errors = false 56 | 57 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to 58 | # the I18n.default_locale when a translation cannot be found). 59 | config.i18n.fallbacks = true 60 | 61 | # Send deprecation notices to registered listeners. 62 | config.active_support.deprecation = :notify 63 | 64 | # Use default logging formatter so that PID and timestamp are not suppressed. 65 | config.log_formatter = ::Logger::Formatter.new 66 | 67 | # Do not dump schema after migrations. 68 | config.active_record.dump_schema_after_migration = false 69 | end 70 | -------------------------------------------------------------------------------- /config/environments/test.rb: -------------------------------------------------------------------------------- 1 | Rails.application.configure do 2 | # Settings specified here will take precedence over those in config/application.rb. 3 | 4 | # The test environment is used exclusively to run your application's 5 | # test suite. You never need to work with it otherwise. Remember that 6 | # your test database is "scratch space" for the test suite and is wiped 7 | # and recreated between test runs. Don't rely on the data there! 8 | config.cache_classes = true 9 | 10 | # Do not eager load code on boot. This avoids loading your whole application 11 | # just for the purpose of running a single test. If you are using a tool that 12 | # preloads Rails for running tests, you may have to set it to true. 13 | config.eager_load = false 14 | 15 | # Configure static file server for tests with Cache-Control for performance. 16 | config.serve_static_files = true 17 | config.static_cache_control = 'public, max-age=3600' 18 | 19 | # Show full error reports and disable caching. 20 | config.consider_all_requests_local = true 21 | config.action_controller.perform_caching = false 22 | 23 | # Raise exceptions instead of rendering exception templates. 24 | config.action_dispatch.show_exceptions = false 25 | 26 | # Disable request forgery protection in test environment. 27 | config.action_controller.allow_forgery_protection = false 28 | 29 | # Tell Action Mailer not to deliver emails to the real world. 30 | # The :test delivery method accumulates sent emails in the 31 | # ActionMailer::Base.deliveries array. 32 | config.action_mailer.delivery_method = :test 33 | 34 | # Randomize the order test cases are executed. 35 | config.active_support.test_order = :random 36 | 37 | # Print deprecation notices to the stderr. 38 | config.active_support.deprecation = :stderr 39 | 40 | config.log_level = :info 41 | 42 | # Raises error for missing translations 43 | # config.action_view.raise_on_missing_translations = true 44 | end 45 | -------------------------------------------------------------------------------- /config/initializers/assets.rb: -------------------------------------------------------------------------------- 1 | Rails.application.config.assets.precompile += ['themes/v1.css', 'themes/flatdoc.css'] -------------------------------------------------------------------------------- /config/initializers/backtrace_silencers.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. 4 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } 5 | 6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. 7 | # Rails.backtrace_cleaner.remove_silencers! 8 | -------------------------------------------------------------------------------- /config/initializers/cookies_serializer.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | Rails.application.config.action_dispatch.cookies_serializer = :json 4 | -------------------------------------------------------------------------------- /config/initializers/filter_parameter_logging.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Configure sensitive parameters which will be filtered from the log file. 4 | Rails.application.config.filter_parameters += [:password] 5 | -------------------------------------------------------------------------------- /config/initializers/inflections.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new inflection rules using the following format. Inflections 4 | # are locale specific, and you may define rules for as many different 5 | # locales as you wish. All of these examples are active by default: 6 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 7 | # inflect.plural /^(ox)$/i, '\1en' 8 | # inflect.singular /^(ox)en/i, '\1' 9 | # inflect.irregular 'person', 'people' 10 | # inflect.uncountable %w( fish sheep ) 11 | # end 12 | 13 | # These inflection rules are supported but not enabled by default: 14 | ActiveSupport::Inflector.inflections(:en) do |inflect| 15 | inflect.acronym 'DocumentUp' 16 | end 17 | -------------------------------------------------------------------------------- /config/initializers/mime_types.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new mime types for use in respond_to blocks: 4 | # Mime::Type.register "text/richtext", :rtf 5 | -------------------------------------------------------------------------------- /config/initializers/octokit.rb: -------------------------------------------------------------------------------- 1 | Octokit.auto_paginate = true 2 | Octokit.client_id = ENV['GH_CLIENT_ID'] 3 | Octokit.client_secret = ENV['GH_CLIENT_SECRET'] -------------------------------------------------------------------------------- /config/initializers/raygun.rb: -------------------------------------------------------------------------------- 1 | Raygun.setup do |config| 2 | config.api_key = ENV['RAYGUN_APIKEY'] 3 | config.filter_parameters = Rails.application.config.filter_parameters 4 | 5 | # The default is Rails.env.production? 6 | # config.enable_reporting = !Rails.env.development? && !Rails.env.test? 7 | end 8 | -------------------------------------------------------------------------------- /config/initializers/session_store.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | Rails.application.config.session_store :cookie_store, key: '_documentup_session' 4 | -------------------------------------------------------------------------------- /config/initializers/wrap_parameters.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # This file contains settings for ActionController::ParamsWrapper which 4 | # is enabled by default. 5 | 6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. 7 | ActiveSupport.on_load(:action_controller) do 8 | wrap_parameters format: [:json] if respond_to?(:wrap_parameters) 9 | end 10 | 11 | # To enable root element in JSON for ActiveRecord objects. 12 | # ActiveSupport.on_load(:active_record) do 13 | # self.include_root_in_json = true 14 | # end 15 | -------------------------------------------------------------------------------- /config/locales/en.yml: -------------------------------------------------------------------------------- 1 | # Files in the config/locales directory are used for internationalization 2 | # and are automatically loaded by Rails. If you want to use locales other 3 | # than English, add the necessary files in this directory. 4 | # 5 | # To use the locales, use `I18n.t`: 6 | # 7 | # I18n.t 'hello' 8 | # 9 | # In views, this is aliased to just `t`: 10 | # 11 | # <%= t('hello') %> 12 | # 13 | # To use a different locale, set it with `I18n.locale`: 14 | # 15 | # I18n.locale = :es 16 | # 17 | # This would use the information in config/locales/es.yml. 18 | # 19 | # To learn more, please read the Rails Internationalization guide 20 | # available at http://guides.rubyonrails.org/i18n.html. 21 | 22 | en: 23 | hello: "Hello world" 24 | -------------------------------------------------------------------------------- /config/routes.rb: -------------------------------------------------------------------------------- 1 | Rails.application.routes.draw do 2 | constraints Subdomain do 3 | get '/', to: 'repositories#show' 4 | get :__recompile, to: 'repositories#recompile', as: :recompile 5 | resources :pages, param: :path, path: '', constraints: {path: /.*/}, only: [:show] 6 | end 7 | 8 | get '/', to: redirect('/jeromegn/documentup') 9 | post :recompile, to: 'github#push', as: :github_push 10 | 11 | get '/stylesheets/screen.css', to: redirect('/assets/application.css') 12 | 13 | resources :users, path: '', param: :login, only: [] do 14 | resources :repositories, path: '', param: :name, constraints: {name: /([A-Za-z0-9\._-]*)/}, only: [:show] do 15 | get :__recompile, to: 'repositories#recompile', as: :recompile 16 | resources :pages, param: :path, path: '', constraints: {path: /.*/}, only: [:show] 17 | end 18 | end 19 | 20 | get '404', to: "errors#not_found" 21 | get '500', to: "errors#internal_server_error" 22 | end 23 | -------------------------------------------------------------------------------- /config/secrets.yml: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Your secret key is used for verifying the integrity of signed cookies. 4 | # If you change this key, all old signed cookies will become invalid! 5 | 6 | # Make sure the secret is at least 30 characters and all random, 7 | # no regular words or you'll be exposed to dictionary attacks. 8 | # You can use `rake secret` to generate a secure secret key. 9 | 10 | # Make sure the secrets in this file are kept private 11 | # if you're sharing your code publicly. 12 | 13 | development: 14 | secret_key_base: 16586fc410f84ef74bb6e1787619cb2dd46fc16729310af2d76f981a7e14bf3e89e621f68df5e265e999a1da50df7790a021addbbd1825b7f2992f1a87d7ae84 15 | 16 | test: 17 | secret_key_base: 7f5dd0855219f313780f20e3f6735f29af230ffad4007f717e4e42f39b85447694f8e8f93d6661ec2ba8bc92d65df921189f3ce03138609491912cf3e16b1d7d 18 | 19 | # Do not keep production secrets in the repository, 20 | # instead read values from the environment. 21 | production: 22 | secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> 23 | -------------------------------------------------------------------------------- /db/migrate/20150605193408_create_repositories.rb: -------------------------------------------------------------------------------- 1 | class CreateRepositories < ActiveRecord::Migration 2 | def change 3 | enable_extension 'hstore' unless extension_enabled?('hstore') 4 | 5 | create_table :repositories do |t| 6 | t.string :full_name 7 | t.string :branch, default: 'master' 8 | t.hstore :config 9 | end 10 | 11 | add_index :repositories, :full_name 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /db/migrate/20150605193513_create_pages.rb: -------------------------------------------------------------------------------- 1 | class CreatePages < ActiveRecord::Migration 2 | def change 3 | create_table :pages do |t| 4 | t.string :path, default: '' 5 | t.references :repository 6 | t.string :source 7 | end 8 | add_index :pages, :path 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20150615124922_add_html_to_pages.rb: -------------------------------------------------------------------------------- 1 | class AddHtmlToPages < ActiveRecord::Migration 2 | def change 3 | add_column :pages, :html, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20150615160017_add_timestamps_to_pages.rb: -------------------------------------------------------------------------------- 1 | class AddTimestampsToPages < ActiveRecord::Migration 2 | def change 3 | add_column :pages, :created_at, :datetime 4 | add_column :pages, :updated_at, :datetime 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20150615160026_add_timestamps_to_repositories.rb: -------------------------------------------------------------------------------- 1 | class AddTimestampsToRepositories < ActiveRecord::Migration 2 | def change 3 | add_column :repositories, :created_at, :datetime 4 | add_column :repositories, :updated_at, :datetime 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20150617124754_add_repository_to_page.rb: -------------------------------------------------------------------------------- 1 | class AddRepositoryToPage < ActiveRecord::Migration 2 | def change 3 | add_foreign_key :pages, :repositories, index: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/schema.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | # This file is auto-generated from the current state of the database. Instead 3 | # of editing this file, please use the migrations feature of Active Record to 4 | # incrementally modify your database, and then regenerate this schema definition. 5 | # 6 | # Note that this schema.rb definition is the authoritative source for your 7 | # database schema. If you need to create the application database on another 8 | # system, you should be using db:schema:load, not running all the migrations 9 | # from scratch. The latter is a flawed and unsustainable approach (the more migrations 10 | # you'll amass, the slower it'll run and the greater likelihood for issues). 11 | # 12 | # It's strongly recommended that you check this file into your version control system. 13 | 14 | ActiveRecord::Schema.define(version: 20150617124754) do 15 | 16 | # These are extensions that must be enabled in order to support this database 17 | enable_extension "plpgsql" 18 | enable_extension "hstore" 19 | 20 | create_table "pages", force: :cascade do |t| 21 | t.string "path", default: "" 22 | t.integer "repository_id" 23 | t.string "source" 24 | t.string "html" 25 | t.datetime "created_at" 26 | t.datetime "updated_at" 27 | end 28 | 29 | add_index "pages", ["path"], name: "index_pages_on_path", using: :btree 30 | 31 | create_table "repositories", force: :cascade do |t| 32 | t.string "full_name" 33 | t.string "branch", default: "master" 34 | t.hstore "config" 35 | t.datetime "created_at" 36 | t.datetime "updated_at" 37 | end 38 | 39 | add_index "repositories", ["full_name"], name: "index_repositories_on_full_name", using: :btree 40 | 41 | add_foreign_key "pages", "repositories" 42 | end 43 | -------------------------------------------------------------------------------- /db/seeds.rb: -------------------------------------------------------------------------------- 1 | # This file should contain all the record creation needed to seed the database with its default values. 2 | # The data can then be loaded with the rake db:seed (or created alongside the db with db:setup). 3 | # 4 | # Examples: 5 | # 6 | # cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }]) 7 | # Mayor.create(name: 'Emanuel', city: cities.first) 8 | -------------------------------------------------------------------------------- /lib/assets/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeromegn/DocumentUp/36ff103e233c77f54d9010aff4a8430397eb81b4/lib/assets/.keep -------------------------------------------------------------------------------- /lib/documentup/filters/absolute_links.rb: -------------------------------------------------------------------------------- 1 | require 'uri' 2 | 3 | class DocumentUp::Filters::AbsoluteLinks < HTML::Pipeline::Filter 4 | 5 | def call 6 | doc.search("a").each do |element| 7 | href = (element['href'] || '').strip 8 | next if href.nil? || href.blank? 9 | unless href.start_with?('http') || href.start_with?('//') || href.start_with?('#') 10 | element['href'] = URI.join(link_subpage_url, href).to_s 11 | end 12 | end 13 | doc 14 | end 15 | 16 | # Private: the relative url you want to use 17 | def link_subpage_url 18 | context[:link_subpage_url] or raise "Missing context :link_subpage_url for #{self.class.name}" 19 | end 20 | 21 | end -------------------------------------------------------------------------------- /lib/documentup/filters/table_of_contents.rb: -------------------------------------------------------------------------------- 1 | class DocumentUp::Filters::TableOfContents < HTML::Pipeline::Filter 2 | PUNCTUATION_REGEXP = RUBY_VERSION > "1.9" ? /[^\p{Word}\- ]/u : /[^\w\- ]/ 3 | 4 | def call 5 | result[:toc] = "" 6 | 7 | headers = Hash.new(0) 8 | doc.css('h2, h3').each do |node| 9 | text = node.text 10 | id = text.downcase 11 | id.gsub!(PUNCTUATION_REGEXP, '') # remove punctuation 12 | id.gsub!(' ', '-') # replace spaces with dash 13 | 14 | uniq = (headers[id] > 0) ? "-#{headers[id]}" : '' 15 | headers[id] += 1 16 | if header_content = node.children.first 17 | result[:toc] << %Q{#{text} \n} 18 | header_content.add_previous_sibling(%Q{}) 19 | end 20 | end 21 | result[:toc] = %Q{\n#{result[:toc]}
} unless result[:toc].empty? 22 | doc 23 | end 24 | end -------------------------------------------------------------------------------- /lib/subdomain.rb: -------------------------------------------------------------------------------- 1 | class Subdomain 2 | def self.matches?(request) 3 | case request.subdomain 4 | when 'www', '', nil 5 | false 6 | else 7 | true 8 | end 9 | end 10 | end -------------------------------------------------------------------------------- /lib/tasks/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeromegn/DocumentUp/36ff103e233c77f54d9010aff4a8430397eb81b4/lib/tasks/.keep -------------------------------------------------------------------------------- /log/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeromegn/DocumentUp/36ff103e233c77f54d9010aff4a8430397eb81b4/log/.keep -------------------------------------------------------------------------------- /newrelic.yml: -------------------------------------------------------------------------------- 1 | # 2 | # This file configures the New Relic Agent. New Relic monitors Ruby, Java, 3 | # .NET, PHP, Python and Node applications with deep visibility and low 4 | # overhead. For more information, visit www.newrelic.com. 5 | # 6 | # Generated June 15, 2015 7 | # 8 | # This configuration file is custom generated for app37859291@heroku.com 9 | # 10 | # For full documentation of agent configuration options, please refer to 11 | # https://docs.newrelic.com/docs/agents/ruby-agent/installation-configuration/ruby-agent-configuration 12 | 13 | common: &default_settings 14 | # Required license key associated with your New Relic account. 15 | license_key: 89877a23533515785deafc97c6954b616576fd6e 16 | 17 | # Your application name. Renaming here affects where data displays in New 18 | # Relic. For more details, see https://docs.newrelic.com/docs/apm/new-relic-apm/maintenance/renaming-applications 19 | app_name: DocumentUp 20 | 21 | # To disable the agent regardless of other settings, uncomment the following: 22 | # agent_enabled: false 23 | 24 | # Logging level for log/newrelic_agent.log 25 | log_level: info 26 | 27 | 28 | # Environment-specific settings are in this section. 29 | # RAILS_ENV or RACK_ENV (as appropriate) is used to determine the environment. 30 | # If your application has other named environments, configure them here. 31 | development: 32 | <<: *default_settings 33 | app_name: DocumentUp (Development) 34 | 35 | # NOTE: There is substantial overhead when running in developer mode. 36 | # Do not use for production or load testing. 37 | developer_mode: true 38 | 39 | test: 40 | <<: *default_settings 41 | # It doesn't make sense to report to New Relic from automated test runs. 42 | monitor_mode: false 43 | 44 | staging: 45 | <<: *default_settings 46 | app_name: DocumentUp (Staging) 47 | 48 | production: 49 | <<: *default_settings 50 | -------------------------------------------------------------------------------- /public/documentup.js: -------------------------------------------------------------------------------- 1 | this.DocumentUp = {}; 2 | 3 | DocumentUp.document = function (opts) { 4 | var repo; 5 | if ("string" === typeof opts) { 6 | repo = opts; 7 | opts = null; 8 | } else { 9 | repo = opts.repo; 10 | delete opts.repo; 11 | } 12 | 13 | window.callback = function (resp) { 14 | if (resp.status === 200) { 15 | document.open(); 16 | document.write(resp.html); 17 | document.close(); 18 | if (opts && opts.afterRender && typeof opts.afterRender === "function") 19 | opts.afterRender() 20 | } 21 | } 22 | 23 | var script = document.createElement('script'); 24 | script.src = '//documentup.com/'+repo 25 | if (opts) 26 | script.src += "?config="+encodeURIComponent(JSON.stringify(opts))+'&callback=callback'; 27 | else 28 | script.src += "?callback=callback"; 29 | 30 | document.getElementsByTagName('head')[0].appendChild(script); 31 | } -------------------------------------------------------------------------------- /public/documentup.min.js: -------------------------------------------------------------------------------- 1 | this.DocumentUp={},DocumentUp.document=function(a){var b;"string"==typeof a?(b=a,a=null):(b=a.repo,delete a.repo),window.callback=function(b){b.status===200&&(document.open(),document.write(b.html),document.close(),a&&a.afterRender&&typeof a.afterRender=="function"&&a.afterRender())};var c=document.createElement("script");c.src="//documentup.com/"+b,a?c.src+="?config="+encodeURIComponent(JSON.stringify(a))+"&callback=callback":c.src+="?callback=callback",document.getElementsByTagName("head")[0].appendChild(c)} -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeromegn/DocumentUp/36ff103e233c77f54d9010aff4a8430397eb81b4/public/favicon.ico -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: -------------------------------------------------------------------------------- /spec/controllers/github_controller_spec.rb: -------------------------------------------------------------------------------- 1 | require 'rails_helper' 2 | 3 | describe GithubController do 4 | 5 | let!(:repo) { Repository.find_or_create_by(full_name: "jeromegn/documentup") } 6 | let!(:page) { Page.find_or_create_by(repository: repo, path: '') } 7 | 8 | describe "POST /recompile" do 9 | 10 | context "w/ markdown changes" do 11 | before { expect_any_instance_of(Page).to receive(:refresh) } 12 | before { expect_any_instance_of(Repository).not_to receive(:refresh) } 13 | before { post :push, payload('push_webhook_changes_markdown') } 14 | it { expect(response.body).to be_blank } 15 | it { expect(response.status).to eq(200) } 16 | end 17 | 18 | context "w/ config changes" do 19 | before { expect_any_instance_of(Page).not_to receive(:refresh) } 20 | before { expect_any_instance_of(Repository).to receive(:refresh) } 21 | before { post :push, payload('push_webhook_changes_config') } 22 | it { expect(response.body).to be_blank } 23 | it { expect(response.status).to eq(200) } 24 | end 25 | 26 | context "w/ both markdown and config changes" do 27 | before { expect_any_instance_of(Page).to receive(:refresh) } 28 | before { expect_any_instance_of(Repository).to receive(:refresh) } 29 | before { post :push, payload('push_webhook_changes') } 30 | it { expect(response.body).to be_blank } 31 | it { expect(response.status).to eq(200) } 32 | end 33 | 34 | context "w/o relevant changes" do 35 | before { expect_any_instance_of(Page).not_to receive(:refresh) } 36 | before { expect_any_instance_of(Repository).not_to receive(:refresh) } 37 | before { post :push, payload('push_webhook_no_changes') } 38 | it { expect(response.body).to be_blank } 39 | it { expect(response.status).to eq(200) } 40 | end 41 | 42 | end 43 | 44 | end 45 | 46 | def payload(filename) 47 | { payload: JSON.parse(File.open(File.dirname(__FILE__) + "/../support/fixtures/#{filename}.json", 'rb').read)['payload'].to_json } 48 | end -------------------------------------------------------------------------------- /spec/models/repository_spec.rb: -------------------------------------------------------------------------------- 1 | require 'rails_helper' 2 | 3 | describe Repository do 4 | 5 | let(:repo) { Repository.create!(full_name: 'jeromegn/documentup') } 6 | 7 | describe '#refresh_config' do 8 | before { repo.refresh_config } 9 | end 10 | 11 | end -------------------------------------------------------------------------------- /spec/rails_helper.rb: -------------------------------------------------------------------------------- 1 | # This file is copied to spec/ when you run 'rails generate rspec:install' 2 | ENV['RAILS_ENV'] ||= 'test' 3 | require File.expand_path('../../config/environment', __FILE__) 4 | # Prevent database truncation if the environment is production 5 | abort("The Rails environment is running in production mode!") if Rails.env.production? 6 | require 'spec_helper' 7 | require 'rspec/rails' 8 | # Add additional requires below this line. Rails is not loaded until this point! 9 | 10 | require 'webmock/rspec' 11 | WebMock.disable_net_connect!(allow_localhost: true) 12 | 13 | Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f } 14 | 15 | ActiveRecord::Migration.maintain_test_schema! 16 | 17 | RSpec.configure do |config| 18 | # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures 19 | config.fixture_path = "#{::Rails.root}/spec/fixtures" 20 | 21 | config.before(:each) do 22 | stub_request(:any, /api.github.com/).to_rack(FakeGitHub) 23 | end 24 | 25 | config.use_transactional_fixtures = true 26 | 27 | config.infer_spec_type_from_file_location! 28 | end 29 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # This file was generated by the `rails generate rspec:install` command. Conventionally, all 2 | # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. 3 | # The generated `.rspec` file contains `--require spec_helper` which will cause 4 | # this file to always be loaded, without a need to explicitly require it in any 5 | # files. 6 | # 7 | # Given that it is always loaded, you are encouraged to keep this file as 8 | # light-weight as possible. Requiring heavyweight dependencies from this file 9 | # will add to the boot time of your test suite on EVERY test run, even for an 10 | # individual file that may not need all of that loaded. Instead, consider making 11 | # a separate helper file that requires the additional dependencies and performs 12 | # the additional setup, and require it from the spec files that actually need 13 | # it. 14 | # 15 | # The `.rspec` file also contains a few flags that are not defaults but that 16 | # users commonly want. 17 | # 18 | # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration 19 | RSpec.configure do |config| 20 | config.expect_with :rspec do |expectations| 21 | expectations.include_chain_clauses_in_custom_matcher_descriptions = true 22 | end 23 | 24 | config.mock_with :rspec do |mocks| 25 | mocks.verify_partial_doubles = true 26 | end 27 | end -------------------------------------------------------------------------------- /spec/support/fake_github.rb: -------------------------------------------------------------------------------- 1 | require 'sinatra/base' 2 | 3 | class FakeGitHub < Sinatra::Base 4 | set :show_exceptions, false 5 | set :dump_errors, true 6 | 7 | get '/repos/:login/:repo' do 8 | json_response 200, "repos/#{params[:login].downcase}/#{params[:repo].downcase}" 9 | end 10 | 11 | get '/repos/:login/:repo/git/trees/:branch' do 12 | json_response 200, "repos/#{params[:login].downcase}/#{params[:repo].downcase}/git/tree/#{params[:branch]}" 13 | end 14 | 15 | get '/repos/:login/:repo/contents/*' do 16 | content_type :text 17 | fixture("repos/#{params[:login].downcase}/#{params[:repo].downcase}/contents/#{params[:splat].join('/')}") 18 | end 19 | 20 | private 21 | 22 | def fixture(file_name) 23 | File.open(File.dirname(__FILE__) + '/fixtures/' + file_name, 'rb').read 24 | end 25 | 26 | def json_fixture(file_name) 27 | file_name += ".json" unless file_name.ends_with?('.json') 28 | fixture(file_name) 29 | end 30 | 31 | def json_response(response_code, file_name) 32 | content_type :json 33 | status response_code 34 | json_fixture(file_name) 35 | end 36 | end -------------------------------------------------------------------------------- /spec/support/fixtures/contents_readme_md.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeromegn/DocumentUp/36ff103e233c77f54d9010aff4a8430397eb81b4/spec/support/fixtures/contents_readme_md.json -------------------------------------------------------------------------------- /spec/support/fixtures/push_webhook_changes.json: -------------------------------------------------------------------------------- 1 | { 2 | "payload": { 3 | "commits": [ 4 | { 5 | "added": [ 6 | 7 | ], 8 | "modified": [ 9 | "README.md", ".documentup.json" 10 | ] 11 | } 12 | ], 13 | "repository": { 14 | "full_name": "jeromegn/DocumentUp" 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /spec/support/fixtures/push_webhook_changes_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "payload": { 3 | "commits": [ 4 | { 5 | "added": [ 6 | 7 | ], 8 | "modified": [ 9 | ".documentup.json" 10 | ] 11 | } 12 | ], 13 | "repository": { 14 | "full_name": "jeromegn/DocumentUp" 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /spec/support/fixtures/push_webhook_changes_markdown.json: -------------------------------------------------------------------------------- 1 | { 2 | "payload": { 3 | "commits": [ 4 | { 5 | "added": [ 6 | 7 | ], 8 | "modified": [ 9 | "README.md" 10 | ] 11 | } 12 | ], 13 | "repository": { 14 | "full_name": "jeromegn/DocumentUp" 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /spec/support/fixtures/push_webhook_no_changes.json: -------------------------------------------------------------------------------- 1 | { 2 | "payload": { 3 | "commits": [ 4 | { 5 | "added": [ 6 | 7 | ], 8 | "modified": [ 9 | 10 | ] 11 | } 12 | ], 13 | "repository": { 14 | "full_name": "jeromegn/DocumentUp" 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /spec/support/fixtures/repos/jeromegn/documentup.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 123, 3 | "owner": { 4 | "login": "jeromegn", 5 | "id": 1, 6 | "avatar_url": "https://github.com/images/error/jeromegn_happy.gif", 7 | "gravatar_id": "", 8 | "url": "https://api.github.com/users/jeromegn", 9 | "html_url": "https://github.com/jeromegn", 10 | "followers_url": "https://api.github.com/users/jeromegn/followers", 11 | "following_url": "https://api.github.com/users/jeromegn/following{/other_user}", 12 | "gists_url": "https://api.github.com/users/jeromegn/gists{/gist_id}", 13 | "starred_url": "https://api.github.com/users/jeromegn/starred{/owner}{/repo}", 14 | "subscriptions_url": "https://api.github.com/users/jeromegn/subscriptions", 15 | "organizations_url": "https://api.github.com/users/jeromegn/orgs", 16 | "repos_url": "https://api.github.com/users/jeromegn/repos", 17 | "events_url": "https://api.github.com/users/jeromegn/events{/privacy}", 18 | "received_events_url": "https://api.github.com/users/jeromegn/received_events", 19 | "type": "User", 20 | "site_admin": false 21 | }, 22 | "name": "DocumentUp", 23 | "full_name": "jeromegn/DocumentUp", 24 | "description": "This your first repo!", 25 | "private": false, 26 | "fork": false, 27 | "url": "https://api.github.com/repos/jeromegn/DocumentUp", 28 | "html_url": "https://github.com/jeromegn/DocumentUp", 29 | "clone_url": "https://github.com/jeromegn/DocumentUp.git", 30 | "git_url": "git://github.com/jeromegn/DocumentUp.git", 31 | "ssh_url": "git@github.com:jeromegn/DocumentUp.git", 32 | "svn_url": "https://svn.github.com/jeromegn/DocumentUp", 33 | "mirror_url": "git://git.example.com/jeromegn/DocumentUp", 34 | "homepage": "https://github.com", 35 | "language": null, 36 | "forks_count": 9, 37 | "stargazers_count": 80, 38 | "watchers_count": 80, 39 | "size": 108, 40 | "default_branch": "master", 41 | "open_issues_count": 0, 42 | "has_issues": true, 43 | "has_wiki": true, 44 | "has_pages": false, 45 | "has_downloads": true, 46 | "pushed_at": "2011-01-26T19:06:43Z", 47 | "created_at": "2011-01-26T19:01:12Z", 48 | "updated_at": "2011-01-26T19:14:43Z", 49 | "permissions": { 50 | "admin": false, 51 | "push": false, 52 | "pull": true 53 | }, 54 | "subscribers_count": 42, 55 | "organization": { 56 | "login": "jeromegn", 57 | "id": 1, 58 | "avatar_url": "https://github.com/images/error/jeromegn_happy.gif", 59 | "gravatar_id": "", 60 | "url": "https://api.github.com/users/jeromegn", 61 | "html_url": "https://github.com/jeromegn", 62 | "followers_url": "https://api.github.com/users/jeromegn/followers", 63 | "following_url": "https://api.github.com/users/jeromegn/following{/other_user}", 64 | "gists_url": "https://api.github.com/users/jeromegn/gists{/gist_id}", 65 | "starred_url": "https://api.github.com/users/jeromegn/starred{/owner}{/repo}", 66 | "subscriptions_url": "https://api.github.com/users/jeromegn/subscriptions", 67 | "organizations_url": "https://api.github.com/users/jeromegn/orgs", 68 | "repos_url": "https://api.github.com/users/jeromegn/repos", 69 | "events_url": "https://api.github.com/users/jeromegn/events{/privacy}", 70 | "received_events_url": "https://api.github.com/users/jeromegn/received_events", 71 | "type": "Organization", 72 | "site_admin": false 73 | }, 74 | "parent": { 75 | "id": 123, 76 | "owner": { 77 | "login": "jeromegn", 78 | "id": 1, 79 | "avatar_url": "https://github.com/images/error/jeromegn_happy.gif", 80 | "gravatar_id": "", 81 | "url": "https://api.github.com/users/jeromegn", 82 | "html_url": "https://github.com/jeromegn", 83 | "followers_url": "https://api.github.com/users/jeromegn/followers", 84 | "following_url": "https://api.github.com/users/jeromegn/following{/other_user}", 85 | "gists_url": "https://api.github.com/users/jeromegn/gists{/gist_id}", 86 | "starred_url": "https://api.github.com/users/jeromegn/starred{/owner}{/repo}", 87 | "subscriptions_url": "https://api.github.com/users/jeromegn/subscriptions", 88 | "organizations_url": "https://api.github.com/users/jeromegn/orgs", 89 | "repos_url": "https://api.github.com/users/jeromegn/repos", 90 | "events_url": "https://api.github.com/users/jeromegn/events{/privacy}", 91 | "received_events_url": "https://api.github.com/users/jeromegn/received_events", 92 | "type": "User", 93 | "site_admin": false 94 | }, 95 | "name": "DocumentUp", 96 | "full_name": "jeromegn/DocumentUp", 97 | "description": "This your first repo!", 98 | "private": false, 99 | "fork": false, 100 | "url": "https://api.github.com/repos/jeromegn/DocumentUp", 101 | "html_url": "https://github.com/jeromegn/DocumentUp", 102 | "clone_url": "https://github.com/jeromegn/DocumentUp.git", 103 | "git_url": "git://github.com/jeromegn/DocumentUp.git", 104 | "ssh_url": "git@github.com:jeromegn/DocumentUp.git", 105 | "svn_url": "https://svn.github.com/jeromegn/DocumentUp", 106 | "mirror_url": "git://git.example.com/jeromegn/DocumentUp", 107 | "homepage": "https://github.com", 108 | "language": null, 109 | "forks_count": 9, 110 | "stargazers_count": 80, 111 | "watchers_count": 80, 112 | "size": 108, 113 | "default_branch": "master", 114 | "open_issues_count": 0, 115 | "has_issues": true, 116 | "has_wiki": true, 117 | "has_pages": false, 118 | "has_downloads": true, 119 | "pushed_at": "2011-01-26T19:06:43Z", 120 | "created_at": "2011-01-26T19:01:12Z", 121 | "updated_at": "2011-01-26T19:14:43Z", 122 | "permissions": { 123 | "admin": false, 124 | "push": false, 125 | "pull": true 126 | } 127 | }, 128 | "source": { 129 | "id": 123, 130 | "owner": { 131 | "login": "jeromegn", 132 | "id": 1, 133 | "avatar_url": "https://github.com/images/error/jeromegn_happy.gif", 134 | "gravatar_id": "", 135 | "url": "https://api.github.com/users/jeromegn", 136 | "html_url": "https://github.com/jeromegn", 137 | "followers_url": "https://api.github.com/users/jeromegn/followers", 138 | "following_url": "https://api.github.com/users/jeromegn/following{/other_user}", 139 | "gists_url": "https://api.github.com/users/jeromegn/gists{/gist_id}", 140 | "starred_url": "https://api.github.com/users/jeromegn/starred{/owner}{/repo}", 141 | "subscriptions_url": "https://api.github.com/users/jeromegn/subscriptions", 142 | "organizations_url": "https://api.github.com/users/jeromegn/orgs", 143 | "repos_url": "https://api.github.com/users/jeromegn/repos", 144 | "events_url": "https://api.github.com/users/jeromegn/events{/privacy}", 145 | "received_events_url": "https://api.github.com/users/jeromegn/received_events", 146 | "type": "User", 147 | "site_admin": false 148 | }, 149 | "name": "DocumentUp", 150 | "full_name": "jeromegn/DocumentUp", 151 | "description": "This your first repo!", 152 | "private": false, 153 | "fork": false, 154 | "url": "https://api.github.com/repos/jeromegn/DocumentUp", 155 | "html_url": "https://github.com/jeromegn/DocumentUp", 156 | "clone_url": "https://github.com/jeromegn/DocumentUp.git", 157 | "git_url": "git://github.com/jeromegn/DocumentUp.git", 158 | "ssh_url": "git@github.com:jeromegn/DocumentUp.git", 159 | "svn_url": "https://svn.github.com/jeromegn/DocumentUp", 160 | "mirror_url": "git://git.example.com/jeromegn/DocumentUp", 161 | "homepage": "https://github.com", 162 | "language": null, 163 | "forks_count": 9, 164 | "stargazers_count": 80, 165 | "watchers_count": 80, 166 | "size": 108, 167 | "default_branch": "master", 168 | "open_issues_count": 0, 169 | "has_issues": true, 170 | "has_wiki": true, 171 | "has_pages": false, 172 | "has_downloads": true, 173 | "pushed_at": "2011-01-26T19:06:43Z", 174 | "created_at": "2011-01-26T19:01:12Z", 175 | "updated_at": "2011-01-26T19:14:43Z", 176 | "permissions": { 177 | "admin": false, 178 | "push": false, 179 | "pull": true 180 | } 181 | } 182 | } -------------------------------------------------------------------------------- /spec/support/fixtures/repos/jeromegn/documentup/contents/.documentup.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "DocumentUp", 3 | "twitter": [ 4 | "jeromegn", 5 | "DocumentUp" 6 | ], 7 | "google_analytics": "UA-5201171-14", 8 | "travis": true 9 | } -------------------------------------------------------------------------------- /spec/support/fixtures/repos/jeromegn/documentup/contents/.documentup.yml: -------------------------------------------------------------------------------- 1 | name: DocumentUp 2 | twitter: 3 | - jeromegn 4 | - DocumentUp 5 | google_analytics: UA-5201171-14 6 | travis: true -------------------------------------------------------------------------------- /spec/support/fixtures/repos/jeromegn/documentup/contents/README.md: -------------------------------------------------------------------------------- 1 |  2 | 3 | **This site has been generated with DocumentUp** (eat your own dog food, people) 4 | 5 | Automatically generated documentation sites for your markdown files! There are various ways of getting your documentation going: 6 | 7 | * [Hosted](#hosted) 8 | * [On-Demand API](#on-demand-api) 9 | * [gh-pages](#gh-pages) 10 | 11 | ## Hosted 12 | 13 | DocumentUp hosts your documentation sites. Just visit `http://documentup.com/username/repository` to generate a site from your `README.md`. 14 | 15 | Recommended if you have a public Github repository. 16 | 17 | [](https://www.gittip.com/jeromegn/) 18 | 19 | ### Post-Receive Hook 20 | 21 | If you want your readme to be recompiled, please add a [Post-Receive Hook](http://help.github.com/post-receive-hooks/) to your Github repository pointing to: `http://documentup.com/recompile` 22 | 23 | ### Manual Recompile 24 | 25 | Visit `http://documentup.com/username/repository/recompile` to manually tell the server to recompile your readme. 26 | 27 | Useful when changes are made to the stylesheets on the server but the compilation hasn't been triggered for a while. 28 | 29 | ### Configuration 30 | 31 | Add a `.documentup.json` dotfile file to the root of your repository. Refer to the [options](#options) section below for its contents. Feel free to consult this repository's [`.documentup.json`](https://github.com/jeromegn/DocumentUp/blob/master/.documentup.json) 32 | 33 | ## On-Demand API 34 | 35 | POST or JSONP called on `http://documentup.com/compiled` 36 | 37 | Generates a standalone documentation HTML file. 38 | 39 | Recommended for private Github repositories or local projects. 40 | 41 | ### Parameters 42 | 43 | **content** (String) *required* 44 | Markdown content you want converted 45 | 46 | All the configuration parameters detailed [options](#options) are also valid. 47 | 48 | ### POST example 49 | 50 | Pipe the response HTML into a file and open it. Example using `curl`: 51 | 52 | ```bash 53 | curl -X POST --data-urlencode content@README.md \ 54 | http://documentup.com/compiled > index.html && open index.html 55 | ``` 56 | 57 | **Note:** If the file you're trying to pass contain ampersands, you need to manually change them to %26. Otherwise the URL will break. 58 | 59 | ### JSONP example with jQuery 60 | 61 | ```javascript 62 | $.ajax({ 63 | url: "http://documentup.com/compiled", 64 | dataType: "jsonp", 65 | data: { 66 | content: "# test", 67 | name: "Test JSONP!" 68 | }, 69 | success: function(resp){ 70 | // `status` is always provided 71 | if (resp.status == 200) { 72 | // Write to your document 73 | document.open(); 74 | document.write(resp.html); 75 | document.close(); 76 | } 77 | } 78 | }); 79 | ``` 80 | 81 | ## gh-pages 82 | 83 | For those wanting to stay within the comfort of their gh-pages branch, it's still possible by using an `index.html` file similar to this: 84 | 85 | ```html 86 | 87 | 88 | 89 | 90 | 93 | 94 | 95 | 96 | ``` 97 | 98 | Make sure to change the `"username/repository"` to the repository's name and user's username. 99 | 100 | Use the `documentup.min.js` file in this repository, not the one what used to be on cdnjs.com, it's deprecated. 101 | 102 | ### Configuration 103 | 104 | `DocumentUp.document` accepts either a String or an Object representing your desired configuration. If an object is used, remember to add a `repo` option containing the path `"username/repository"` to your github repository. 105 | 106 | All options detailed in the [options](#options) section are available. 107 | 108 | In addition to those, one special option is available to "gh-pages version" of DocumentUp: 109 | 110 | **afterRender** (Function) 111 | A function to be executed after the document has been replaced with the compiled HTML. 112 | 113 | ### Example 114 | 115 | ```javascript 116 | DocumentUp.document({ 117 | repo: "jeromegn/documentup", 118 | name: "DocumentUp", 119 | twitter: [ 120 | "jeromegn", 121 | "DocumentUp" 122 | ], 123 | afterRender: function(){ 124 | alert("rendered"); 125 | } 126 | }); 127 | ``` 128 | 129 | ### What this script does 130 | 131 | It does what's written in the JSONP section, without the jQuery dependency. It uses a endpoint like: `http://documentup.com/username/repository?callback=` to fetch the cached copy of the repository and then replaces the page's html with the generated documentation. 132 | 133 | ## Formatting guide 134 | 135 | Just like you normally would. DocumentUp also supports "Github Flavored Markdown" and we recommend you use it for syntax highlighting. 136 | 137 | It doesn't support tables as it is supported on Github, but you can use inline HTML. 138 | 139 | h1's (# in markdown) will appear as first level navigation in the sidebar while h2's (##) will appear under them as sub-navigation. 140 | 141 | Example: 142 | 143 | ```markdown 144 | # Project name / Title (won't appear in the sidebar) 145 | 146 | Some intro text if you want. 147 | 148 | ## Top level-navigation 149 | 150 | ### Sub-navigation 151 | 152 | #### This wouldn't show up in the sidebar 153 | ``` 154 | 155 | ## Options 156 | 157 | ### name 158 | 159 | *String, default: repository name* 160 | 161 | Name of your project. It'll appear in the header of the sidebar. Defaults to the `repository` substring of the `repo` option. 162 | 163 | ### color 164 | 165 | *String, default: "#336699"* 166 | 167 | CSS-like color representing the color for the links both in the sidebar and the content. 168 | 169 | ### theme 170 | 171 | *String, default: null* 172 | 173 | Name of the theme to use. Refer to the [themes](#themes) sections. 174 | 175 | ### issues 176 | 177 | *Boolean, default: true* 178 | 179 | Adds a link to the sidebar for the issues tab of the repository if `true`. Also accepts a string if your issues are managed elsewhere. 180 | 181 | ### travis 182 | 183 | *Boolean, default: false* 184 | 185 | Indicate if the project is being tested by [Travis-CI](http://travis-ci.org/). If `true`, it'll add the small travis badge in the sidebar. 186 | 187 | ### twitter 188 | 189 | *String / Array of strings, default: null* 190 | 191 | Add follow buttons for one or more Twitter accounts to your sidebar. Useful to gather followers. 192 | 193 | ### google_analytics 194 | 195 | *String default: null* 196 | 197 | This is your Google Analytics "UA" unique ID. Adds GA tracking to your generated documentation. 198 | e.g.: "UA-5201171-14" 199 | 200 | ## Themes 201 | 202 | ### Default 203 | 204 | The one you're looking at now. 205 | 206 | ### V1 207 | 208 | For the nostalgic. Use `v1` in your `theme` config option. 209 | 210 |  211 | 212 | ## Roadmap 213 | 214 | * Private repositories 215 | * Multi-page aggregation 216 | 217 | ## Thank you 218 | 219 | * Thanks for, the few, well documented project sites out there for the inspiration. 220 | * Thanks to [CDNJS](http://cdnjs.com) who **originally** offered hosting for this project. 221 | * Thanks to [Jean-Marc Denis](http://jeanmarcdenis.me/) for the freely downloadable bow tie I used in the logo. 222 | 223 | ## Changelog 224 | 225 | #### Hosted version (Feb 2, 2012) 226 | 227 | Versioning is going to be difficult now since this is now a service. Deployment will be continuous. 228 | 229 | #### 0.1.1 (Jan 26, 2012) 230 | 231 | * Files now parsed in UTF-8 232 | * Namespaced repositories in localStorage (thanks to [tbranyen](https://github.com/tbranyen)) 233 | * A few README fixes 234 | 235 | #### 0.1.0 (Jan 25, 2012) 236 | 237 | * Initial release 238 | 239 | ## License 240 | 241 | Copyright (c) 2012 Jerome Gravel-Niquet 242 | 243 | Permission is hereby granted, free of charge, to any person obtaining 244 | a copy of this software and associated documentation files (the 245 | "Software"), to deal in the Software without restriction, including 246 | without limitation the rights to use, copy, modify, merge, publish, 247 | distribute, sublicense, and/or sell copies of the Software, and to 248 | permit persons to whom the Software is furnished to do so, subject to 249 | the following conditions: 250 | 251 | The above copyright notice and this permission notice shall be 252 | included in all copies or substantial portions of the Software. 253 | 254 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 255 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 256 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 257 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 258 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 259 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 260 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /spec/support/fixtures/repos/jeromegn/documentup/git/tree/master.json: -------------------------------------------------------------------------------- 1 | { 2 | "sha": "test123", 3 | "url": "https://api.github.com/repos/jeromegn/DocumentUp/trees/test123", 4 | "tree": [ 5 | { 6 | "path": ".documentup.json", 7 | "mode": "100755", 8 | "type": "blob", 9 | "size": 30, 10 | "sha": "documentup_json", 11 | "url": "https://api.github.com/repos/jeromegn/DocumentUp/git/blobs/documentup_json" 12 | }, 13 | { 14 | "path": "README.md", 15 | "mode": "100755", 16 | "type": "blob", 17 | "size": 75, 18 | "sha": "readme", 19 | "url": "https://api.github.com/repos/jeromegn/DocumentUp/git/blobs/readme" 20 | } 21 | ], 22 | "truncated": false 23 | } -------------------------------------------------------------------------------- /vendor/assets/stylesheets/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeromegn/DocumentUp/36ff103e233c77f54d9010aff4a8430397eb81b4/vendor/assets/stylesheets/.keep --------------------------------------------------------------------------------