diff --git a/HISTORY.md b/HISTORY.md index d2b59459..695aef55 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,3 +1,17 @@ +# 3.1 / 2014-11-28 + +* New features + * Drag-and-drop uploading in the editor [@lucas-clemente](https://github.com/lucas-clemente) + * Latest changes view [@etienneCharignon](https://github.com/etienneCharignon) (#707) + * Option `--no-edit` to disable editing from the web interface [@bambycha](https://github.com/bambycha) (#879) + * Option `--mathjax-config` to specify custom mathjax configuration [@hardywu](https://github.com/hardywu) (#842) +* Major enhancements + * Made the Gollum theme responsive [@rtrvrtg](https://github.com/rtrvrtg) (#831) + * Depends on new [gollum-lib](https://github.com/gollum/gollum-lib) `4.0.0` + * Allows specifiying [git adapter](https://github.com/gollum/gollum/wiki/Git-adapters) with `--adapter` [@bartkamphorst](https://github.com/bartkamphorst), [@dometto](https://github.com/dometto) +* Numerous bugfixes + * **NB**: please pass `--h1-title` if you do not want page titles to default to the page's filepath. See [here](https://github.com/gollum/gollum/wiki/Page-titles). + # 2.4.11 / 2013-01-08 * Numerous security issues have been fixed. Please update to `2.4.11` diff --git a/README.md b/README.md index 1bb66241..cb6f862a 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ Gollum follows the rules of [Semantic Versioning](http://semver.org/) and uses ## SECURITY -Don't enable `--custom-css` or `--custom-js` unless you trust every user who has the ability to edit the wiki. +Don't enable `--custom-css`, `--custom-js` or `--mathjax-config` unless you trust every user who has the ability to edit the wiki. A better solution with more security is being tracked in [#665](https://github.com/gollum/gollum/issues/665). ## INSTALLATION @@ -99,24 +99,26 @@ Options: --port [PORT] Bind port (default 4567). --host [HOST] Hostname or IP address to listen on (default 0.0.0.0). --version Display current version. - --config [CONFIG] Path to additional configuration file + --config [CONFIG] Path to additional configuration file. + --adapter [ADAPTER] Git adapter to use in the backend. Defaults to grit. --irb Start an irb process with gollum loaded for the current wiki. - --css Inject custom css. Uses custom.css from root repository - --js Inject custom js. Uses custom.js from root repository - --template-dir [PATH] Specify custom template directory + --css Inject custom css. Uses custom.css from root repository. + --js Inject custom js. Uses custom.js from root repository. + --template-dir [PATH] Specify custom template directory. --page-file-dir [PATH] Specify the sub directory for all page files (default: repository root). - --base-path [PATH] Specify the base path. - --gollum-path [PATH] Specify the gollum path. + --base-path [PATH] Specify the base path for the served pages (default: /) Example: --base-path wiki yields the home page accessible at http://localhost:4567/wiki/. + --gollum-path [PATH] Specify the path to the git repository to be served. --ref [REF] Specify the repository ref to use (default: master). + --no-edit Restricts editing capability through frontend. --no-live-preview Disables livepreview. --live-preview Enables livepreview. --allow-uploads [MODE] Allows file uploads. Modes: dir (default, store all uploads in the same directory), page (store each upload at the same location as the page). - --mathjax Enables mathjax. - --mathjax-config [SOURCE] Inject custom mathjax config. Uses mathjax.config.js from root repository by default + --mathjax Enables mathjax for rendering mathematical equations. Uses the TeX-AMS-MML_HTMLorMML config with the autoload-all extension by default. + --mathjax-config [SOURCE] Inject custom mathjax config file. Uses mathjax.config.js from root repository by default. --user-icons [SOURCE] Set the history user icons. Valid values: gravatar, identicon, none. Default: none. --show-all Shows all files in file view. By default only valid pages are shown. --collapse-tree Collapse file view tree. By default, expanded tree is shown. - --h1-title Sets page title to value of first h1 + --h1-title Sets page title to value of first h1. ``` Note that the gollum server will not run on Windows because of [an issue](https://github.com/rtomayko/posix-spawn/issues/9) with posix-spawn (which is used by Grit). diff --git a/bin/gollum b/bin/gollum index 4a5c1f4a..9a5f32cc 100755 --- a/bin/gollum +++ b/bin/gollum @@ -22,6 +22,7 @@ options = { 'port' => 4567, 'bind' => '0.0.0.0' } wiki_options = { :live_preview => false, :allow_uploads => false, + :allow_editing => true, } opts = OptionParser.new do |opts| @@ -44,6 +45,10 @@ opts = OptionParser.new do |opts| options['config'] = config end + opts.on("--adapter [ADAPTER]", "Git adapter to use in the backend. Defaults to grit.") do |adapter| + Gollum::GIT_ADAPTER = adapter + end + opts.on("--irb", "Start an irb process with gollum loaded for the current wiki.") do options['irb'] = true end @@ -64,11 +69,11 @@ opts = OptionParser.new do |opts| wiki_options[:page_file_dir] = path end - opts.on("--base-path [PATH]", "Specify the base path.") do |path| + opts.on("--base-path [PATH]", "Specify the base path for the served pages (default: /) Example: --base-path wiki yields the home page accessible at http://localhost:4567/wiki/.") do |path| wiki_options[:base_path] = path end - opts.on("--gollum-path [PATH]", "Specify the gollum path.") do |path| + opts.on("--gollum-path [PATH]", "Specify the path to the git repository to be served.") do |path| wiki_options[:gollum_path] = path end @@ -76,6 +81,10 @@ opts = OptionParser.new do |opts| wiki_options[:ref] = ref end + opts.on("--no-edit", "Restricts editing capability through frontend.") do + wiki_options[:allow_editing] = false + end + opts.on("--no-live-preview", "Disables livepreview.") do wiki_options[:live_preview] = false end @@ -89,7 +98,7 @@ opts = OptionParser.new do |opts| wiki_options[:per_page_uploads] = true if mode == :page end - opts.on("--mathjax", "Enables mathjax.") do + opts.on("--mathjax", "Enables mathjax for rendering mathematical equations. Uses the TeX-AMS-MML_HTMLorMML config with the autoload-all extension by default.") do wiki_options[:mathjax] = true end @@ -215,4 +224,4 @@ else # Rack::Handler does not work with Ctrl + C. Use Rack::Server instead. Rack::Server.new(:app => MapGollum.new(base_path), :Port => options['port'], :Host => options['bind']).start end -end \ No newline at end of file +end diff --git a/openrc/conf.d/gollum b/contrib/openrc/conf.d/gollum similarity index 100% rename from openrc/conf.d/gollum rename to contrib/openrc/conf.d/gollum diff --git a/openrc/init.d/gollum b/contrib/openrc/init.d/gollum similarity index 100% rename from openrc/init.d/gollum rename to contrib/openrc/init.d/gollum diff --git a/contrib/systemd/gollum@.service b/contrib/systemd/gollum@.service new file mode 100644 index 00000000..1761f650 --- /dev/null +++ b/contrib/systemd/gollum@.service @@ -0,0 +1,12 @@ +[Unit] +Description=Gollum wiki server +After=network.target + +[Service] +Type=simple +User=%i +ExecStart=/usr/bin/gollum +Restart=on-abort + +[Install] +WantedBy=multi-user.target diff --git a/gollum.gemspec b/gollum.gemspec index ae5947c6..0de31bda 100644 --- a/gollum.gemspec +++ b/gollum.gemspec @@ -5,8 +5,8 @@ Gem::Specification.new do |s| s.required_ruby_version = '>= 1.9' s.name = 'gollum' - s.version = '3.0.0' - s.date = '2014-04-05' + s.version = '3.1.0' + s.date = '2014-11-27' s.rubyforge_project = 'gollum' s.license = 'MIT' @@ -24,7 +24,7 @@ Gem::Specification.new do |s| s.rdoc_options = ['--charset=UTF-8'] s.extra_rdoc_files = %w[README.md LICENSE] - s.add_dependency 'gollum-lib', '~> 3.0' + s.add_dependency 'gollum-lib', '~> 4.0' s.add_dependency 'github-markdown', '~> 0.6.5' s.add_dependency 'sinatra', '~> 1.4', '>= 1.4.4' s.add_dependency 'mustache', ['>= 0.99.5', '< 1.0.0'] @@ -45,10 +45,14 @@ Gem::Specification.new do |s| Rakefile bin/gollum config.rb + contrib/openrc/conf.d/gollum + contrib/openrc/init.d/gollum + contrib/systemd/gollum@.service docs/sanitization.md gollum.gemspec lib/gollum.rb lib/gollum/app.rb + lib/gollum/editing_auth.rb lib/gollum/helpers.rb lib/gollum/public/gollum/css/_styles.css lib/gollum/public/gollum/css/dialog.css @@ -538,8 +542,6 @@ Gem::Specification.new do |s| licenses/css_tree_menu_thecssninja/license.txt licenses/licenses.txt licenses/unity_asset_pool/COPYRIGHT - openrc/conf.d/gollum - openrc/init.d/gollum ] # = MANIFEST = diff --git a/lib/gollum.rb b/lib/gollum.rb index 70a2378a..179640ca 100644 --- a/lib/gollum.rb +++ b/lib/gollum.rb @@ -16,7 +16,7 @@ require File.expand_path('../gollum/uri_encode_component', __FILE__) $KCODE = 'U' if RUBY_VERSION[0, 3] == '1.8' module Gollum - VERSION = '3.0.0' + VERSION = '3.1.0' def self.assets_path ::File.expand_path('gollum/public', ::File.dirname(__FILE__)) diff --git a/lib/gollum/app.rb b/lib/gollum/app.rb index d5000efe..3d12f168 100644 --- a/lib/gollum/app.rb +++ b/lib/gollum/app.rb @@ -13,6 +13,8 @@ require 'gollum/views/has_page' require File.expand_path '../helpers', __FILE__ +require 'gollum/editing_auth' + #required to upload bigger binary files Gollum::set_git_timeout(120) Gollum::set_git_max_filesize(190 * 10**6) @@ -42,6 +44,7 @@ module Precious class App < Sinatra::Base register Mustache::Sinatra include Precious::Helpers + use Precious::EditingAuth dir = File.dirname(File.expand_path(__FILE__)) @@ -92,6 +95,7 @@ module Precious @css = settings.wiki_options[:css] @js = settings.wiki_options[:js] @mathjax_config = settings.wiki_options[:mathjax_config] + @allow_editing = settings.wiki_options[:allow_editing] end get '/' do @@ -106,7 +110,6 @@ module Precious # name, path, version def wiki_page(name, path = nil, version = nil, exact = true) wiki = wiki_new - path = name if path.nil? name = extract_name(name) || wiki.index_page path = extract_path(path) @@ -127,11 +130,14 @@ module Precious end get '/edit/*' do + forbid unless @allow_editing wikip = wiki_page(params[:splat].first) @name = wikip.name @path = wikip.path + @upload_dest = find_upload_dest(@path) wiki = wikip.wiki + @allow_uploads = wiki.allow_uploads if page = wikip.page if wiki.live_preview && page.format.to_s.include?('markdown') && supported_useragent?(request.user_agent) live_preview_url = '/livepreview/index.html?page=' + encodeURIComponent(@name) @@ -252,21 +258,27 @@ module Precious end get '/delete/*' do + forbid unless @allow_editing wikip = wiki_page(params[:splat].first) name = wikip.name wiki = wikip.wiki page = wikip.page unless page.nil? - wiki.delete_page(page, { :message => "Destroyed #{name} (#{page.format})" }) + commit = commit_message + commit[:message] = "Destroyed #{name} (#{page.format})" + wiki.delete_page(page, commit) end redirect to('/') end get '/create/*' do + forbid unless @allow_editing wikip = wiki_page(params[:splat].first.gsub('+', '-')) @name = wikip.name.to_url @path = wikip.path + @allow_uploads = wikip.wiki.allow_uploads + @upload_dest = find_upload_dest(@path) page_dir = settings.wiki_options[:page_file_dir].to_s unless page_dir.empty? @@ -352,6 +364,13 @@ module Precious end end + get '/latest_changes' do + @wiki = wiki_new + max_count = settings.wiki_options.fetch(:latest_changes_count, 10) + @versions = @wiki.latest_changes({:max_count => max_count}) + mustache :latest_changes + end + post '/compare/*' do @file = params[:splat].first @versions = params[:versions] || [] @@ -397,6 +416,8 @@ module Precious @content = page.formatted_data @version = version mustache :page + elsif file = wikip.wiki.file("#{file_path}", version, true) + show_file(file) else halt 404 end @@ -454,10 +475,7 @@ module Precious @page = page @name = name @content = page.formatted_data - @upload_dest = settings.wiki_options[:allow_uploads] ? - (settings.wiki_options[:per_page_uploads] ? - "#{path}/#{@name}".sub(/^\/\//, '') : 'uploads' - ) : '' + @upload_dest = find_upload_dest(path) # Extensions and layout data @editable = true @@ -470,18 +488,24 @@ module Precious mustache :page elsif file = wiki.file(fullpath, wiki.ref, true) - if file.on_disk? - send_file file.on_disk_path, :disposition => 'inline' - else - content_type file.mime_type - file.raw_data - end + show_file(file) else + not_found unless @allow_editing page_path = [path, name].compact.join('/') redirect to("/create/#{clean_url(encodeURIComponent(page_path))}") end end + def show_file(file) + return unless file + if file.on_disk? + send_file file.on_disk_path, :disposition => 'inline' + else + content_type file.mime_type + file.raw_data + end + end + def update_wiki_page(wiki, page, content, commit, name = nil, format = nil) return if !page || ((!content || page.raw_data == content) && page.format == format) @@ -506,5 +530,12 @@ module Precious commit_message.merge! author_parameters unless author_parameters.nil? commit_message end + + def find_upload_dest(path) + settings.wiki_options[:allow_uploads] ? + (settings.wiki_options[:per_page_uploads] ? + "#{path}/#{@name}".sub(/^\/\//, '') : 'uploads' + ) : '' + end end end diff --git a/lib/gollum/editing_auth.rb b/lib/gollum/editing_auth.rb new file mode 100644 index 00000000..9d502658 --- /dev/null +++ b/lib/gollum/editing_auth.rb @@ -0,0 +1,34 @@ +module Precious + class EditingAuth < Sinatra::Base + def initialize(app) + @app = app + end + + def call(env) + @env = env + # Blocks all potentially editable pages. Use EditingAuth::whitelist_pages to unblock pages. + unless (env["REQUEST_METHOD"] == "GET") || App::settings.wiki_options[:allow_editing] + return block unless excluded_page? + end + @app.call(env) + end + + def block + [403, {'Content-Type' => 'text/html', 'Content-Length' => '9'}, ['Forbidden']] + end + + def excluded_page? + return false if env["REQUEST_PATH"].nil? + whitelist_pages.any? do |whitelisted_page| + env["REQUEST_PATH"].include? whitelisted_page + end + end + + private + # List pages paths as str that you want to whitelist. + # Pages will be compared with env["REQUEST_PATH"] using String::include? method. + def whitelist_pages + return ["/compare/"] + end + end +end \ No newline at end of file diff --git a/lib/gollum/helpers.rb b/lib/gollum/helpers.rb index 4fba20bf..ccda58e5 100644 --- a/lib/gollum/helpers.rb +++ b/lib/gollum/helpers.rb @@ -39,5 +39,17 @@ module Precious url.gsub('%2F', '/').gsub(/^\/+/, '').gsub('//', '/') end + def forbid(msg = "Forbidden.") + @message = msg + status 403 + halt mustache :error + end + + def not_found(msg = nil) + @message = msg || "The requested page does not exist." + status 404 + return mustache :error + end + end end diff --git a/lib/gollum/public/gollum/css/dialog.css b/lib/gollum/public/gollum/css/dialog.css index dfbd7938..8cfca2aa 100755 --- a/lib/gollum/public/gollum/css/dialog.css +++ b/lib/gollum/public/gollum/css/dialog.css @@ -4,8 +4,11 @@ display: block; overflow: visible; position: absolute; - top: 50%; - left: 50%; + top: 0; + left: 0; + z-index: 999999; + width: 100%; + height: 100%; } #gollum-dialog-dialog.active { @@ -13,24 +16,117 @@ } #gollum-dialog-dialog-inner { - margin: 0 0 0 -225px; - position: relative; - width: 450px; - - border: 7px solid #999; - border: 7px solid rgba(0, 0, 0, 0.3); - border-radius: 5px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; + margin: 0px; + top: 0px; + right: 0px; + bottom: 0px; + left: 0px; + width: 100%; + height: 100%; } #gollum-dialog-dialog-bg { background-color: #fff; - overflow: hidden; padding: 1em; - background: -webkit-gradient(linear, left top, left bottom, from(#f7f7f7), to(#ffffff)); - background: -moz-linear-gradient(top, #f7f7f7, #ffffff); + height: 100%; + box-sizing: border-box; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; +} + +@media all and (min-width: 480px) { + #gollum-dialog-dialog { + display: block; + overflow: visible; + position: absolute; + position: fixed; + top: 0; + left: 0; + z-index: 999999; + width: auto; + height: auto; + } + + #gollum-dialog-dialog.active { + display: block; + } + + #gollum-dialog-dialog-inner { + margin: auto; + position: fixed; + + width: auto; + height: auto; + + min-width: 280px; + min-height: 380px; + + max-width: 450px; + max-height: 450px; + + top: 10px; + right: 10px; + bottom: 10px; + left: 10px; + + border: 7px solid #999; + border: 7px solid rgba(0, 0, 0, 0.3); + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + } + + #gollum-dialog-dialog-bg { + background-color: #fff; + overflow: hidden; + padding: 1em; + + background: -webkit-gradient(linear, left top, left bottom, from(#f7f7f7), to(#ffffff)); + background: -moz-linear-gradient(top, #f7f7f7, #ffffff); + + height: 100%; + box-sizing: border-box; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + } +} + +@media all and (min-width: 940px) { + #gollum-dialog-dialog { + position: absolute; + top: 50%; + left: 50%; + width: auto; + height: auto; + } + + #gollum-dialog-dialog-inner { + margin: 0 0 0 -225px; + position: relative; + + width: 450px; + height: auto; + + top: auto; + right: auto; + bottom: auto; + left: auto; + + border: 7px solid #999; + border: 7px solid rgba(0, 0, 0, 0.3); + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + } + + #gollum-dialog-dialog-bg { + height: auto; + + box-sizing: content-box; + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + } } #gollum-dialog-dialog-inner h4 { @@ -52,10 +148,16 @@ display: block; border: 0; margin: 0; - overflow: hidden; padding: 0; } +#gollum-dialog-dialog-body fieldset:after { + content: "."; + display: block; + clear: both; + visibility: hidden; +} + #gollum-dialog-dialog-body fieldset .field { margin: 0 0 1.5em 0; padding: 0; diff --git a/lib/gollum/public/gollum/css/editor.css b/lib/gollum/public/gollum/css/editor.css index d743778d..73a0915e 100755 --- a/lib/gollum/public/gollum/css/editor.css +++ b/lib/gollum/public/gollum/css/editor.css @@ -19,15 +19,15 @@ a { } #gollum-editor { - border: 1px solid #e4e4e4; - background: #f9f9f9; - margin: 1em 0 5em; - overflow: hidden; - padding: 1em 1em 0.4em; + margin: 0 0 5em; + padding: 0em 1em 0.4em; +} - border-radius: 1em; - -moz-border-radius: 1em; - -webkit-border-radius: 1em; +#gollum-editor:after { + content: "."; + display: block; + visibility: hidden; + clear: both; } .ff #gollum-editor, @@ -35,6 +35,18 @@ a { padding-bottom: 1em; } +@media all and (min-width: 940px) { + #gollum-editor { + border: 1px solid #e4e4e4; + background: #f9f9f9; + margin: 1em 0 5em; + + border-radius: 1em; + -moz-border-radius: 1em; + -webkit-border-radius: 1em; + } +} + #gollum-editor form fieldset { border: 0; margin: 0; @@ -45,7 +57,13 @@ a { #gollum-editor .singleline { display: block; margin: 0 0 0.7em 0; - overflow: hidden; +} + +#gollum-editor .singleline:after { + content: "."; + display: block; + visibility: hidden; + clear: both; } #gollum-editor .singleline input { @@ -94,7 +112,6 @@ a { /* @control function-bar */ #gollum-editor #gollum-editor-function-bar { border-bottom: 1px solid #ddd; - overflow: hidden; padding: 0; } @@ -109,9 +126,21 @@ a { #gollum-editor #gollum-editor-function-bar.active #gollum-editor-function-buttons { display: block; - float: left; - overflow: hidden; - padding: 0 0 1.1em 0; + margin: 0; + padding: 0; +} + +@media all and (min-width: 940px) { + #gollum-editor #gollum-editor-function-bar { + overflow: hidden; + } + + #gollum-editor #gollum-editor-function-bar.active #gollum-editor-function-buttons { + overflow: hidden; + margin: 0; + padding: 0 0 1.1em 0; + float: left; + } } #gollum-editor #gollum-editor-function-bar a.function-button { @@ -120,12 +149,12 @@ a { color: #333; display: block; float: left; - height: 25px; + height: 32px; overflow: hidden; - margin: 0.2em 0.5em 0 0; + margin: 1px 1px 0 0; /* text-indent: -5000px; */ text-shadow: 0 1px 0 #fff; - width: 25px; + width: 32px; border-radius: 0.3em; -moz-border-radius: 0.3em; @@ -150,41 +179,84 @@ a { background-image: url(../images/icon-sprite.png); background-repeat: no-repeat; display: block; - height: 25px; + height: 32px; overflow: hidden; text-indent: -5000px; - width: 25px; + width: 32px; } -a#function-bold span { background-position: 0 0; } -a#function-italic span { background-position: -27px 0; } -a#function-underline span { background-position: -54px 0; } -a#function-code span { background-position: -82px 0; } -a#function-ul span { background-position: -109px 0; } -a#function-ol span { background-position: -136px 0; } -a#function-blockquote span { background-position: -163px 0; } -a#function-hr span { background-position: -190px 0; } -a#function-h1 span { background-position: -217px 0; } -a#function-h2 span { background-position: -244px 0; } -a#function-h3 span { background-position: -271px 0; } -a#function-link span { background-position: -298px 0; } -a#function-image span { background-position: -324px 0; } -a#function-help span { background-position: -405px 0; } +a#function-bold span { background-position: 3px 3px; } +a#function-italic span { background-position: -24px 3px; } +a#function-underline span { background-position: -51px 3px; } +a#function-code span { background-position: -79px 3px; } +a#function-ul span { background-position: -106px 3px; } +a#function-ol span { background-position: -133px 3px; } +a#function-blockquote span { background-position: -160px 3px; } +a#function-hr span { background-position: -187px 3px; } +a#function-h1 span { background-position: -214px 3px; } +a#function-h2 span { background-position: -241px 3px; } +a#function-h3 span { background-position: -268px 3px; } +a#function-link span { background-position: -295px 3px; } +a#function-image span { background-position: -321px 3px; } +a#function-help span { background-position: -402px 3px; } -a#function-bold:hover span { background-position: 0 -28px; } -a#function-italic:hover span { background-position: -27px -28px; } -a#function-underline:hover span { background-position: -54px -28px; } -a#function-code:hover span { background-position: -82px -28px; } -a#function-ul:hover span { background-position: -109px -28px; } -a#function-ol:hover span { background-position: -136px -28px; } -a#function-blockquote:hover span { background-position: -163px -28px; } -a#function-hr:hover span { background-position: -190px -28px; } -a#function-h1:hover span { background-position: -217px -28px; } -a#function-h2:hover span { background-position: -244px -28px; } -a#function-h3:hover span { background-position: -271px -28px; } -a#function-link:hover span { background-position: -298px -28px; } -a#function-image:hover span { background-position: -324px -28px; } -a#function-help:hover span { background-position: -405px -28px; } +a#function-bold:hover span { background-position: 3px -25px; } +a#function-italic:hover span { background-position: -24px -25px; } +a#function-underline:hover span { background-position: -51px -25px; } +a#function-code:hover span { background-position: -79px -25px; } +a#function-ul:hover span { background-position: -106px -25px; } +a#function-ol:hover span { background-position: -133px -25px; } +a#function-blockquote:hover span { background-position: -160px -25px; } +a#function-hr:hover span { background-position: -187px -25px; } +a#function-h1:hover span { background-position: -214px -25px; } +a#function-h2:hover span { background-position: -241px -25px; } +a#function-h3:hover span { background-position: -268px -25px; } +a#function-link:hover span { background-position: -295px -25px; } +a#function-image:hover span { background-position: -321px -25px; } +a#function-help:hover span { background-position: -402px -25px; } + +@media all and (min-width: 940px) { + #gollum-editor #gollum-editor-function-bar a.function-button { + height: 25px; + width: 25px; + margin: 0.2em 0.5em 0 0; + } + + #gollum-editor #gollum-editor-function-bar a span { + width: 25px; + height: 25px; + } + + a#function-bold span { background-position: 0 0; } + a#function-italic span { background-position: -27px 0; } + a#function-underline span { background-position: -54px 0; } + a#function-code span { background-position: -82px 0; } + a#function-ul span { background-position: -109px 0; } + a#function-ol span { background-position: -136px 0; } + a#function-blockquote span { background-position: -163px 0; } + a#function-hr span { background-position: -190px 0; } + a#function-h1 span { background-position: -217px 0; } + a#function-h2 span { background-position: -244px 0; } + a#function-h3 span { background-position: -271px 0; } + a#function-link span { background-position: -298px 0; } + a#function-image span { background-position: -324px 0; } + a#function-help span { background-position: -405px 0; } + + a#function-bold:hover span { background-position: 0 -28px; } + a#function-italic:hover span { background-position: -27px -28px; } + a#function-underline:hover span { background-position: -54px -28px; } + a#function-code:hover span { background-position: -82px -28px; } + a#function-ul:hover span { background-position: -109px -28px; } + a#function-ol:hover span { background-position: -136px -28px; } + a#function-blockquote:hover span { background-position: -163px -28px; } + a#function-hr:hover span { background-position: -190px -28px; } + a#function-h1:hover span { background-position: -217px -28px; } + a#function-h2:hover span { background-position: -244px -28px; } + a#function-h3:hover span { background-position: -271px -28px; } + a#function-link:hover span { background-position: -298px -28px; } + a#function-image:hover span { background-position: -324px -28px; } + a#function-help:hover span { background-position: -405px -28px; } +} #gollum-editor #gollum-editor-function-bar a.disabled { @@ -192,14 +264,19 @@ a#function-help:hover span { background-position: -405px -28px; } } #gollum-editor #gollum-editor-function-bar span.function-divider { - display: block; - float: left; - width: 0.5em; + display: none; } #gollum-editor #gollum-editor-function-bar #gollum-editor-format-selector { - overflow: hidden; - padding: .2em 0 .5em 0; + padding: 0.2em 0 0.5em 0; + clear: both; +} + +#gollum-editor #gollum-editor-function-bar #gollum-editor-format-selector:after { + content: "."; + display: block; + clear: both; + visibility: hidden; } #gollum-editor #gollum-editor-function-bar @@ -208,13 +285,12 @@ a#function-help:hover span { background-position: -405px -28px; } border: 1px solid #ddd; color: #333; - float: right; font-size: 1em; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-weight: bold; line-height: 1.6em; padding: 0.3em 0.4em; - + display: inline-block; border-radius: 0.5em; -moz-border-radius: 0.5em; @@ -224,11 +300,11 @@ a#function-help:hover span { background-position: -405px -28px; } #gollum-editor #gollum-editor-function-bar #gollum-editor-format-selector label { color: #999; - float: right; font-size: 1em; font-weight: bold; line-height: 1.6em; padding: .3em 0.5em 0 0; + display: inline-block; } #gollum-editor #gollum-editor-function-bar @@ -236,6 +312,56 @@ a#function-help:hover span { background-position: -405px -28px; } content: ':'; } +@media all and (min-width: 940px) { + #gollum-editor #gollum-editor-function-bar span.function-divider { + display: block; + width: 0.5em; + } + + #gollum-editor #gollum-editor-function-bar span.function-divider { + float: left; + } + + #gollum-editor #gollum-editor-function-bar + #gollum-editor-format-selector { + clear: none; + text-align: right; + } + + #gollum-editor #gollum-editor-function-bar + #gollum-editor-format-selector select { + } + + #gollum-editor #gollum-editor-function-bar + #gollum-editor-format-selector label { + } +} + + +/* @section uploads */ + +#gollum-editor-body.dragging { + box-shadow: 0 0 10px #AAE000; +} + +#gollum-editor-body.uploading { + opacity: 0.5; +} + +#gollum-editor-body + div { + display: none; + font-size: 1.5em; +} + +#gollum-editor-body + div > i { + font-size: 1em; +} + +#gollum-editor-body.uploading + div { + display: block; +} + + /* @section form-fields */ @@ -245,12 +371,18 @@ a#function-help:hover span { background-position: -405px -28px; } font-size: 1em; font-family: Consolas, "Liberation Mono", Courier, monospace; line-height: 1.4em; - margin: 1em 0 0.4em; + margin: 0 0 0.4em; padding: 0.5em; width: 98%; height: 20em; } +@media all and (min-width: 940px) { + #gollum-editor textarea { + margin: 1em 0 0.4em; + } +} + #gollum-editor input#gollum-editor-submit { background-color: #f7f7f7; border: 1px solid #d4d4d4; @@ -445,6 +577,7 @@ a#function-help:hover span { background-position: -405px -28px; } /* @section help */ #gollum-editor-help { + clear: both; margin: 0; overflow: hidden; padding: 0; @@ -455,13 +588,13 @@ a#function-help:hover span { background-position: -405px -28px; } #gollum-editor-help-parent, #gollum-editor-help-list { display: block; - float: left; - height: 17em; list-style-type: none; - overflow: auto; margin: 0; - padding: 1em 0; - width: 18%; + float: left; + width: 50%; + box-sizing: border-box; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; } #gollum-editor-help-parent { @@ -491,6 +624,7 @@ a#function-help:hover span { background-position: -405px -28px; } width: auto; padding: 0.2em 1em; text-shadow: 0 -1px 0 #fff; + font-size: 0.8em; } #gollum-editor-help-parent li a:hover, @@ -518,6 +652,7 @@ a#function-help:hover span { background-position: -405px -28px; } overflow: auto; height: 17em; padding: 1em; + clear: both; } #gollum-editor-help-content { @@ -532,6 +667,29 @@ a#function-help:hover span { background-position: -405px -28px; } padding: 0; } + @media all and (min-width: 940px) { + #gollum-editor-help { + clear: none; + } + + #gollum-editor-help-parent, + #gollum-editor-help-list { + height: 17em; + width: 18%; + overflow: auto; + padding: 1em 0; + } + + #gollum-editor-help-parent li a, + #gollum-editor-help-list li a { + font-size: 1em; + } + + #gollum-editor-help-wrapper { + clear: none; + } + } + /* IE */ .ie #gollum-editor .singleline input { padding-top: 0.25em; diff --git a/lib/gollum/public/gollum/css/gollum.css b/lib/gollum/public/gollum/css/gollum.css index 4b582fec..cd577b78 100755 --- a/lib/gollum/public/gollum/css/gollum.css +++ b/lib/gollum/public/gollum/css/gollum.css @@ -21,9 +21,15 @@ body, html { #wiki-wrapper { margin: 0 auto; overflow: visible; - width: 920px; - padding-left:20px; - padding-right:20px; + width: 100%; +} + +@media all and (min-width: 940px) { + #wiki-wrapper { + max-width: 920px; + padding-left:20px; + padding-right:20px; + } } a:link { @@ -39,22 +45,41 @@ a:hover, a:visited { /* @section head */ #head { - border-bottom: 1px solid #ddd; - margin: 4em 0 1.5em; - padding-bottom: 0.3em; + margin: 1em 0 0; + padding: 0; overflow: hidden; } #head h1 { - font-size: 2.5em; + font-size: 1.5em; float: left; line-height: normal; margin: 0; - padding: 2px 0 0 0; + padding: 0 0 0 0.667em; } #head ul.actions { - float: right; + clear: both; + margin: 0 1em; +} + +@media all and (min-width: 940px) { + #head { + border-bottom: 1px solid #ddd; + padding-bottom: 0.3em; + margin: 4em 0 1.5em; + } + + #head h1 { + font-size: 2.5em; + padding: 2px 0 0 0; + } + + #head ul.actions { + clear: none; + float: right; + margin: 0; + } } /* @section content */ @@ -89,6 +114,12 @@ a:hover, a:visited { width: 100%; } +#wiki-body table { + display: block; + overflow: auto; + border: 0; +} + .has-sidebar #wiki-body { width: 68%; } @@ -244,6 +275,16 @@ a:hover, a:visited { font-weight: bold; } +#footer .actions { + margin-left: 1em; +} + +@media all and (min-width: 940px) { + #footer .actions { + margin: 0; + } +} + /* @section history */ .history h1 { @@ -257,7 +298,7 @@ a:hover, a:visited { } #wiki-history { - margin-top: 2em; + margin: 2em 1em 0 1em; } #wiki-history fieldset { @@ -283,7 +324,8 @@ a:hover, a:visited { } #wiki-history table tr td { - border: 1px solid #c0dce9; + border-top: 1px solid #c0dce9; + border-bottom: 1px solid #c0dce9; font-size: 1em; line-height: 1.6em; margin: 0; @@ -291,8 +333,8 @@ a:hover, a:visited { } #wiki-history table tr td.checkbox { - width: 4em; - padding: 0.3em; + width: auto; + padding: 0 0.2em 0 0; } #wiki-history table tr td.checkbox input { @@ -364,6 +406,25 @@ a:hover, a:visited { margin: 0 0.6em 0 0; } +@media all and (min-width: 940px) { + #wiki-history { + margin: 2em 0 0 0; + } + + #wiki-history table tr td { + border: 1px solid #c0dce9; + font-size: 1em; + line-height: 1.6em; + margin: 0; + padding: 0.3em 0.7em; + } + + #wiki-history table tr td.checkbox { + width: 4em; + padding: 0.3em; + } +} + /* @section edit */ .edit h1 { @@ -378,6 +439,7 @@ a:hover, a:visited { /* @section search */ + .results h1 { color: #999; font-weight: normal; @@ -390,6 +452,8 @@ a:hover, a:visited { .results #results { border-bottom: 1px solid #ccc; + margin-left: 1em; + margin-right: 1em; margin-bottom: 2em; padding-bottom: 2em; } @@ -400,12 +464,33 @@ a:hover, a:visited { } .results #results ul li { - font-size: 1.2em; - line-height: 1.6em; - list-style-position: outside; + list-style: none; padding: 0.2em 0; } +.results #results ul li a { + word-wrap: break-word; +} + +@media all and (min-width: 640px) { + .results #results ul li { + font-size: 1.2em; + } +} + +@media all and (min-width: 940px) { + .results #results { + margin-left: 0; + margin-right: 0; + } + + .results #results ul li { + list-style: disc; + list-style-position: outside; + line-height: 1.6em; + } +} + .results #results ul li span.count { color: #999; } @@ -522,8 +607,8 @@ ul.actions { ul.actions li { float: left; font-size: 0.9em; - margin-left: 0.6em; - margin-bottom: 0.6em; + margin-left: 1px; + margin-bottom: 1px; } .minibutton a { @@ -533,7 +618,7 @@ ul.actions { display: block; font-weight: bold; margin: 0; - padding: 0.4em 1em; + padding: 0.6em 1em; height: 1.4em; text-shadow: 0 1px 0 #fff; @@ -547,6 +632,18 @@ ul.actions { -webkit-border-radius: 3px; } +@media all and (min-width: 940px) { + ul.actions li { + margin-left: 0.6em; + margin-bottom: 0.6em; + } + + .minibutton a { + padding: 0.4em 1em; + height: 1.4em; + } +} + #search-submit { background-color: #f7f7f7; border: 1px solid #d4d4d4; @@ -627,7 +724,7 @@ ul.actions { /* @control searchbar */ #head #searchbar { float: right; - padding: 0; + padding: 2px 0 0 0; overflow: hidden; } @@ -684,7 +781,7 @@ ul.actions { height: inherit; overflow: hidden; text-indent: -5000px; - width: 28px; + width: 32px; } .ff #head #searchbar #searchbar-fauxtext #search-submit span, @@ -697,11 +794,31 @@ ul.actions { padding: 0; } +@media all and (min-width: 940px) { + #head #searchbar { + padding: 0; + } + + #head #searchbar #searchbar-fauxtext #search-submit span { + width: 28px; + } + + #head #searchbar #searchbar-fauxtext #search-submit:hover span { + background-position: -431px -28px; + } +} + /* @section pages */ #pages { font-size: 1.2em; - margin-bottom: 20px; + margin: 0 1em 20px 1em; +} + +@media all and (min-width: 940px) { + #pages { + margin: 0 0 20px 0; + } } #pages ul { diff --git a/lib/gollum/public/gollum/css/ie7.css b/lib/gollum/public/gollum/css/ie7.css index 31bf7e49..112d33a2 100755 --- a/lib/gollum/public/gollum/css/ie7.css +++ b/lib/gollum/public/gollum/css/ie7.css @@ -1,5 +1,11 @@ /* IE7-specific styles */ +.ie #wiki-wrapper { + width: 920px; + padding-left:20px; + padding-right:20px; +} + .ie #head #searchbar #searchbar-fauxtext input#search-query { border: 0; float: left; diff --git a/lib/gollum/public/gollum/css/template.css b/lib/gollum/public/gollum/css/template.css index cfd6f478..6bde233e 100644 --- a/lib/gollum/public/gollum/css/template.css +++ b/lib/gollum/public/gollum/css/template.css @@ -27,6 +27,51 @@ content: "\f0c1"; } +.fa-spinner:before { + content: "\f110"; +} + +.fa-spin { + -webkit-animation: spin 2s infinite linear; + -moz-animation: spin 2s infinite linear; + -o-animation: spin 2s infinite linear; + animation: spin 2s infinite linear; +} +@-moz-keyframes spin { + 0% { + -moz-transform: rotate(0deg); + } + 100% { + -moz-transform: rotate(359deg); + } +} +@-webkit-keyframes spin { + 0% { + -webkit-transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + } +} +@-o-keyframes spin { + 0% { + -o-transform: rotate(0deg); + } + 100% { + -o-transform: rotate(359deg); + } +} +@keyframes spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} + /* margin & padding reset*/ * { margin: 0; @@ -52,7 +97,6 @@ body { font: 13.34px Helvetica, arial, freesans, clean, sans-serif; font-size: small; line-height: 1.4; - min-width: 980px; } img { @@ -86,13 +130,19 @@ a:active, a:hover { } .markdown-body { - padding: 30px; + padding: 1em; font-size: 15px; line-height: 1.7; overflow: hidden; word-wrap: break-word; } +@media all and (min-width: 940px) { + .markdown-body { + padding: 30px; + } +} + .markdown-body > *:first-child { margin-top: 0 !important; } diff --git a/lib/gollum/public/gollum/javascript/editor/gollum.editor.js b/lib/gollum/public/gollum/javascript/editor/gollum.editor.js index 3b281e7f..b389f7a3 100755 --- a/lib/gollum/public/gollum/javascript/editor/gollum.editor.js +++ b/lib/gollum/public/gollum/javascript/editor/gollum.editor.js @@ -98,6 +98,52 @@ $('#gollum-editor-help').removeClass('jaws'); } } // EditorHas.functionBar + + if ( EditorHas.dragDropUpload() ) { + var $editorBody = $('#gollum-editor-body'); + var editorBody = $('#gollum-editor-body')[0]; + editorBody.ondragover = function(e) { + $editorBody.addClass('dragging'); + return false; + }; + editorBody.ondragleave = function() { + $editorBody.removeClass('dragging'); + return false; + }; + editorBody.ondrop = function(e) { + debug("dropped file"); + e.preventDefault(); + $editorBody.removeClass('dragging').addClass('uploading'); + + var file = e.dataTransfer.files[0], + formData = new FormData(); + formData.append('upload_dest', uploadDest); + formData.append('file', file); + + $.ajax({ + url: '/uploadFile', + data: formData, + cache: false, + contentType: false, + processData: false, + type: 'POST', + success: function(){ + $editorBody.removeClass('uploading'); + var text = '[[' + uploadDest + '/' + file.name + ']]'; + var pos = editorBody.selectionStart || 0; + editorBody.value = editorBody.value.substring(0, pos) + text + editorBody.value.substring(pos); + editorBody.selectionStart = pos + text.length; + editorBody.selectionEnd = pos + text.length; + }, + error: function(r, textStatus) { + alert('Error uploading file: ' + textStatus); + $editorBody.removeClass('uploading'); + } + }); + + return false; + }; + } // EditorHas.dragDropUpload } // EditorHas.baseEditorMarkup }; @@ -444,6 +490,17 @@ */ titleDisplayed: function() { return ( ActiveOptions.NewFile ); + }, + + + /** + * EditorHas.dragDropUpload + * True if the editor is supports drag and drop file uploads, false otherwise. + * + * @return boolean + */ + dragDropUpload: function() { + return $('#gollum-editor.uploads-allowed').length; } }; diff --git a/lib/gollum/public/gollum/javascript/editor/langs/asciidoc.js b/lib/gollum/public/gollum/javascript/editor/langs/asciidoc.js index 31322c06..8703bbee 100644 --- a/lib/gollum/public/gollum/javascript/editor/langs/asciidoc.js +++ b/lib/gollum/public/gollum/javascript/editor/langs/asciidoc.js @@ -1,11 +1,11 @@ /** - * ASCIIDoc Language Definition + * AsciiDoc Language Definition * */ (function($) { -var ASCIIDoc = { +var AsciiDoc = { 'function-bold' : { search: /(^[\n]+)([\n\s]*)/g, @@ -19,7 +19,7 @@ var ASCIIDoc = { 'function-code' : { search: /(^[\n]+)([\n\s]*)/g, - replace: "+$1+$2" + replace: "`$1`$2" }, 'function-ul' : { @@ -37,6 +37,21 @@ var ASCIIDoc = { replace: "----\n$1$2\n----\n" }, + 'function-h1' : { + search: /(.+)([\n]?)/g, + replace: "= $1$2" + }, + + 'function-h2' : { + search: /(.+)([\n]?)/g, + replace: "== $1$2" + }, + + 'function-h3' : { + search: /(.+)([\n]?)/g, + replace: "=== $1$2" + }, + 'function-link' : { exec: function( txt, selText, $field ) { var results = null; @@ -102,20 +117,20 @@ var ASCIIDoc = { }; -$.GollumEditor.defineLanguage('asciidoc', ASCIIDoc); +$.GollumEditor.defineLanguage('asciidoc', AsciiDoc); -var ASCIIDocHelp = [ +var AsciiDocHelp = [ { menuName: 'Text Formatting', content: [ { menuName: 'Headers', - data: '
ASCIIDoc headers can be written in two ways: with differing underlines or with different indentation using = (equals sign). ASCIIDoc supports headings 1-4. The editor will automatically use the = notation. To create a level one header, prefix your line with one =. Level two headers are created with == and so on.
AsciiDoc headers can be written in two ways: with differing underlines or with different indentation using = (equals sign). AsciiDoc supports headings 1-4. The editor will automatically use the = notation. To create a level one header, prefix your line with one =. Level two headers are created with == and so on.
To display text as bold, wrap the text in * (asterisks). To display text as italic, wrap the text in _ (underscores). To create monospace text, wrap the text in + (plus signs).'
+ data: '
To display text as bold, wrap the text in * (asterisks). To display text as italic, wrap the text in _ (underscores). To create monospace text, wrap the text in ` (backtick).'
},
{
menuName: 'Scripts',
@@ -123,7 +138,7 @@ var ASCIIDocHelp = [
},
{
menuName: 'Special Characters',
- data: '
ASCIIDoc will automatically convert textual representations of commonly-used special characters. For example, (R) becomes ®, (C) becomes © and (TM) becomes ™.
AsciiDoc will automatically convert textual representations of commonly-used special characters. For example, (R) becomes ®, (C) becomes © and (TM) becomes ™.
ASCIIDoc allows paragraphs to have optional titles or icons to denote special sections. To make a normal paragraph, simply add a line between blocks and a new paragraph will start. If you want to title your paragraphs, adda line prefixed by . (full stop). An example paragraph with optional title is displayed below:.Optional Title
This is my paragraph. It is two sentences long.
AsciiDoc allows paragraphs to have optional titles or icons to denote special sections. To make a normal paragraph, simply add a line between blocks and a new paragraph will start. If you want to title your paragraphs, adda line prefixed by . (full stop). An example paragraph with optional title is displayed below:.Optional Title
This is my paragraph. It is two sentences long.
Images in ASCIIDoc work much like hyperlinks, but image URLs are prefixed with image:. For example, to link to an image at images/icons/home.png, write image:images/icons/home.png. Alt text can be added by appending the text to the URI in [ (brackets).
Images in AsciiDoc work much like hyperlinks, but image URLs are prefixed with image:. For example, to link to an image at images/icons/home.png, write image:images/icons/home.png. Alt text can be added by appending the text to the URI in [ (brackets).