Merge branch 'rc'

This commit is contained in:
Dawa Ometto
2014-11-28 13:38:33 +01:00
38 changed files with 1211 additions and 202 deletions
+14
View File
@@ -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 # 2.4.11 / 2013-01-08
* Numerous security issues have been fixed. Please update to `2.4.11` * Numerous security issues have been fixed. Please update to `2.4.11`
+12 -10
View File
@@ -29,7 +29,7 @@ Gollum follows the rules of [Semantic Versioning](http://semver.org/) and uses
## SECURITY ## 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). A better solution with more security is being tracked in [#665](https://github.com/gollum/gollum/issues/665).
## INSTALLATION ## INSTALLATION
@@ -99,24 +99,26 @@ Options:
--port [PORT] Bind port (default 4567). --port [PORT] Bind port (default 4567).
--host [HOST] Hostname or IP address to listen on (default 0.0.0.0). --host [HOST] Hostname or IP address to listen on (default 0.0.0.0).
--version Display current version. --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. --irb Start an irb process with gollum loaded for the current wiki.
--css Inject custom css. Uses custom.css from root repository --css Inject custom css. Uses custom.css from root repository.
--js Inject custom js. Uses custom.js from root repository --js Inject custom js. Uses custom.js from root repository.
--template-dir [PATH] Specify custom template directory --template-dir [PATH] Specify custom template directory.
--page-file-dir [PATH] Specify the sub directory for all page files (default: repository root). --page-file-dir [PATH] Specify the sub directory for all page files (default: repository root).
--base-path [PATH] Specify the base 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 gollum path. --gollum-path [PATH] Specify the path to the git repository to be served.
--ref [REF] Specify the repository ref to use (default: master). --ref [REF] Specify the repository ref to use (default: master).
--no-edit Restricts editing capability through frontend.
--no-live-preview Disables livepreview. --no-live-preview Disables livepreview.
--live-preview Enables 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). --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 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. Uses mathjax.config.js from root repository 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. --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. --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. --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). 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).
+13 -4
View File
@@ -22,6 +22,7 @@ options = { 'port' => 4567, 'bind' => '0.0.0.0' }
wiki_options = { wiki_options = {
:live_preview => false, :live_preview => false,
:allow_uploads => false, :allow_uploads => false,
:allow_editing => true,
} }
opts = OptionParser.new do |opts| opts = OptionParser.new do |opts|
@@ -44,6 +45,10 @@ opts = OptionParser.new do |opts|
options['config'] = config options['config'] = config
end 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 opts.on("--irb", "Start an irb process with gollum loaded for the current wiki.") do
options['irb'] = true options['irb'] = true
end end
@@ -64,11 +69,11 @@ opts = OptionParser.new do |opts|
wiki_options[:page_file_dir] = path wiki_options[:page_file_dir] = path
end 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 wiki_options[:base_path] = path
end 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 wiki_options[:gollum_path] = path
end end
@@ -76,6 +81,10 @@ opts = OptionParser.new do |opts|
wiki_options[:ref] = ref wiki_options[:ref] = ref
end 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 opts.on("--no-live-preview", "Disables livepreview.") do
wiki_options[:live_preview] = false wiki_options[:live_preview] = false
end end
@@ -89,7 +98,7 @@ opts = OptionParser.new do |opts|
wiki_options[:per_page_uploads] = true if mode == :page wiki_options[:per_page_uploads] = true if mode == :page
end 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 wiki_options[:mathjax] = true
end end
@@ -215,4 +224,4 @@ else
# Rack::Handler does not work with Ctrl + C. Use Rack::Server instead. # 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 Rack::Server.new(:app => MapGollum.new(base_path), :Port => options['port'], :Host => options['bind']).start
end end
end end
+12
View File
@@ -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
+7 -5
View File
@@ -5,8 +5,8 @@ Gem::Specification.new do |s|
s.required_ruby_version = '>= 1.9' s.required_ruby_version = '>= 1.9'
s.name = 'gollum' s.name = 'gollum'
s.version = '3.0.0' s.version = '3.1.0'
s.date = '2014-04-05' s.date = '2014-11-27'
s.rubyforge_project = 'gollum' s.rubyforge_project = 'gollum'
s.license = 'MIT' s.license = 'MIT'
@@ -24,7 +24,7 @@ Gem::Specification.new do |s|
s.rdoc_options = ['--charset=UTF-8'] s.rdoc_options = ['--charset=UTF-8']
s.extra_rdoc_files = %w[README.md LICENSE] 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 'github-markdown', '~> 0.6.5'
s.add_dependency 'sinatra', '~> 1.4', '>= 1.4.4' s.add_dependency 'sinatra', '~> 1.4', '>= 1.4.4'
s.add_dependency 'mustache', ['>= 0.99.5', '< 1.0.0'] s.add_dependency 'mustache', ['>= 0.99.5', '< 1.0.0']
@@ -45,10 +45,14 @@ Gem::Specification.new do |s|
Rakefile Rakefile
bin/gollum bin/gollum
config.rb config.rb
contrib/openrc/conf.d/gollum
contrib/openrc/init.d/gollum
contrib/systemd/gollum@.service
docs/sanitization.md docs/sanitization.md
gollum.gemspec gollum.gemspec
lib/gollum.rb lib/gollum.rb
lib/gollum/app.rb lib/gollum/app.rb
lib/gollum/editing_auth.rb
lib/gollum/helpers.rb lib/gollum/helpers.rb
lib/gollum/public/gollum/css/_styles.css lib/gollum/public/gollum/css/_styles.css
lib/gollum/public/gollum/css/dialog.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/css_tree_menu_thecssninja/license.txt
licenses/licenses.txt licenses/licenses.txt
licenses/unity_asset_pool/COPYRIGHT licenses/unity_asset_pool/COPYRIGHT
openrc/conf.d/gollum
openrc/init.d/gollum
] ]
# = MANIFEST = # = MANIFEST =
+1 -1
View File
@@ -16,7 +16,7 @@ require File.expand_path('../gollum/uri_encode_component', __FILE__)
$KCODE = 'U' if RUBY_VERSION[0, 3] == '1.8' $KCODE = 'U' if RUBY_VERSION[0, 3] == '1.8'
module Gollum module Gollum
VERSION = '3.0.0' VERSION = '3.1.0'
def self.assets_path def self.assets_path
::File.expand_path('gollum/public', ::File.dirname(__FILE__)) ::File.expand_path('gollum/public', ::File.dirname(__FILE__))
+43 -12
View File
@@ -13,6 +13,8 @@ require 'gollum/views/has_page'
require File.expand_path '../helpers', __FILE__ require File.expand_path '../helpers', __FILE__
require 'gollum/editing_auth'
#required to upload bigger binary files #required to upload bigger binary files
Gollum::set_git_timeout(120) Gollum::set_git_timeout(120)
Gollum::set_git_max_filesize(190 * 10**6) Gollum::set_git_max_filesize(190 * 10**6)
@@ -42,6 +44,7 @@ module Precious
class App < Sinatra::Base class App < Sinatra::Base
register Mustache::Sinatra register Mustache::Sinatra
include Precious::Helpers include Precious::Helpers
use Precious::EditingAuth
dir = File.dirname(File.expand_path(__FILE__)) dir = File.dirname(File.expand_path(__FILE__))
@@ -92,6 +95,7 @@ module Precious
@css = settings.wiki_options[:css] @css = settings.wiki_options[:css]
@js = settings.wiki_options[:js] @js = settings.wiki_options[:js]
@mathjax_config = settings.wiki_options[:mathjax_config] @mathjax_config = settings.wiki_options[:mathjax_config]
@allow_editing = settings.wiki_options[:allow_editing]
end end
get '/' do get '/' do
@@ -106,7 +110,6 @@ module Precious
# name, path, version # name, path, version
def wiki_page(name, path = nil, version = nil, exact = true) def wiki_page(name, path = nil, version = nil, exact = true)
wiki = wiki_new wiki = wiki_new
path = name if path.nil? path = name if path.nil?
name = extract_name(name) || wiki.index_page name = extract_name(name) || wiki.index_page
path = extract_path(path) path = extract_path(path)
@@ -127,11 +130,14 @@ module Precious
end end
get '/edit/*' do get '/edit/*' do
forbid unless @allow_editing
wikip = wiki_page(params[:splat].first) wikip = wiki_page(params[:splat].first)
@name = wikip.name @name = wikip.name
@path = wikip.path @path = wikip.path
@upload_dest = find_upload_dest(@path)
wiki = wikip.wiki wiki = wikip.wiki
@allow_uploads = wiki.allow_uploads
if page = wikip.page if page = wikip.page
if wiki.live_preview && page.format.to_s.include?('markdown') && supported_useragent?(request.user_agent) if wiki.live_preview && page.format.to_s.include?('markdown') && supported_useragent?(request.user_agent)
live_preview_url = '/livepreview/index.html?page=' + encodeURIComponent(@name) live_preview_url = '/livepreview/index.html?page=' + encodeURIComponent(@name)
@@ -252,21 +258,27 @@ module Precious
end end
get '/delete/*' do get '/delete/*' do
forbid unless @allow_editing
wikip = wiki_page(params[:splat].first) wikip = wiki_page(params[:splat].first)
name = wikip.name name = wikip.name
wiki = wikip.wiki wiki = wikip.wiki
page = wikip.page page = wikip.page
unless page.nil? 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 end
redirect to('/') redirect to('/')
end end
get '/create/*' do get '/create/*' do
forbid unless @allow_editing
wikip = wiki_page(params[:splat].first.gsub('+', '-')) wikip = wiki_page(params[:splat].first.gsub('+', '-'))
@name = wikip.name.to_url @name = wikip.name.to_url
@path = wikip.path @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 page_dir = settings.wiki_options[:page_file_dir].to_s
unless page_dir.empty? unless page_dir.empty?
@@ -352,6 +364,13 @@ module Precious
end end
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 post '/compare/*' do
@file = params[:splat].first @file = params[:splat].first
@versions = params[:versions] || [] @versions = params[:versions] || []
@@ -397,6 +416,8 @@ module Precious
@content = page.formatted_data @content = page.formatted_data
@version = version @version = version
mustache :page mustache :page
elsif file = wikip.wiki.file("#{file_path}", version, true)
show_file(file)
else else
halt 404 halt 404
end end
@@ -454,10 +475,7 @@ module Precious
@page = page @page = page
@name = name @name = name
@content = page.formatted_data @content = page.formatted_data
@upload_dest = settings.wiki_options[:allow_uploads] ? @upload_dest = find_upload_dest(path)
(settings.wiki_options[:per_page_uploads] ?
"#{path}/#{@name}".sub(/^\/\//, '') : 'uploads'
) : ''
# Extensions and layout data # Extensions and layout data
@editable = true @editable = true
@@ -470,18 +488,24 @@ module Precious
mustache :page mustache :page
elsif file = wiki.file(fullpath, wiki.ref, true) elsif file = wiki.file(fullpath, wiki.ref, true)
if file.on_disk? show_file(file)
send_file file.on_disk_path, :disposition => 'inline'
else
content_type file.mime_type
file.raw_data
end
else else
not_found unless @allow_editing
page_path = [path, name].compact.join('/') page_path = [path, name].compact.join('/')
redirect to("/create/#{clean_url(encodeURIComponent(page_path))}") redirect to("/create/#{clean_url(encodeURIComponent(page_path))}")
end end
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) def update_wiki_page(wiki, page, content, commit, name = nil, format = nil)
return if !page || return if !page ||
((!content || page.raw_data == content) && page.format == format) ((!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.merge! author_parameters unless author_parameters.nil?
commit_message commit_message
end end
def find_upload_dest(path)
settings.wiki_options[:allow_uploads] ?
(settings.wiki_options[:per_page_uploads] ?
"#{path}/#{@name}".sub(/^\/\//, '') : 'uploads'
) : ''
end
end end
end end
+34
View File
@@ -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
+12
View File
@@ -39,5 +39,17 @@ module Precious
url.gsub('%2F', '/').gsub(/^\/+/, '').gsub('//', '/') url.gsub('%2F', '/').gsub(/^\/+/, '').gsub('//', '/')
end 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
end end
+117 -15
View File
@@ -4,8 +4,11 @@
display: block; display: block;
overflow: visible; overflow: visible;
position: absolute; position: absolute;
top: 50%; top: 0;
left: 50%; left: 0;
z-index: 999999;
width: 100%;
height: 100%;
} }
#gollum-dialog-dialog.active { #gollum-dialog-dialog.active {
@@ -13,24 +16,117 @@
} }
#gollum-dialog-dialog-inner { #gollum-dialog-dialog-inner {
margin: 0 0 0 -225px; margin: 0px;
position: relative; top: 0px;
width: 450px; right: 0px;
bottom: 0px;
border: 7px solid #999; left: 0px;
border: 7px solid rgba(0, 0, 0, 0.3); width: 100%;
border-radius: 5px; height: 100%;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
} }
#gollum-dialog-dialog-bg { #gollum-dialog-dialog-bg {
background-color: #fff; background-color: #fff;
overflow: hidden;
padding: 1em; padding: 1em;
background: -webkit-gradient(linear, left top, left bottom, from(#f7f7f7), to(#ffffff)); height: 100%;
background: -moz-linear-gradient(top, #f7f7f7, #ffffff); 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 { #gollum-dialog-dialog-inner h4 {
@@ -52,10 +148,16 @@
display: block; display: block;
border: 0; border: 0;
margin: 0; margin: 0;
overflow: hidden;
padding: 0; padding: 0;
} }
#gollum-dialog-dialog-body fieldset:after {
content: ".";
display: block;
clear: both;
visibility: hidden;
}
#gollum-dialog-dialog-body fieldset .field { #gollum-dialog-dialog-body fieldset .field {
margin: 0 0 1.5em 0; margin: 0 0 1.5em 0;
padding: 0; padding: 0;
+218 -60
View File
@@ -19,15 +19,15 @@ a {
} }
#gollum-editor { #gollum-editor {
border: 1px solid #e4e4e4; margin: 0 0 5em;
background: #f9f9f9; padding: 0em 1em 0.4em;
margin: 1em 0 5em; }
overflow: hidden;
padding: 1em 1em 0.4em;
border-radius: 1em; #gollum-editor:after {
-moz-border-radius: 1em; content: ".";
-webkit-border-radius: 1em; display: block;
visibility: hidden;
clear: both;
} }
.ff #gollum-editor, .ff #gollum-editor,
@@ -35,6 +35,18 @@ a {
padding-bottom: 1em; 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 { #gollum-editor form fieldset {
border: 0; border: 0;
margin: 0; margin: 0;
@@ -45,7 +57,13 @@ a {
#gollum-editor .singleline { #gollum-editor .singleline {
display: block; display: block;
margin: 0 0 0.7em 0; margin: 0 0 0.7em 0;
overflow: hidden; }
#gollum-editor .singleline:after {
content: ".";
display: block;
visibility: hidden;
clear: both;
} }
#gollum-editor .singleline input { #gollum-editor .singleline input {
@@ -94,7 +112,6 @@ a {
/* @control function-bar */ /* @control function-bar */
#gollum-editor #gollum-editor-function-bar { #gollum-editor #gollum-editor-function-bar {
border-bottom: 1px solid #ddd; border-bottom: 1px solid #ddd;
overflow: hidden;
padding: 0; padding: 0;
} }
@@ -109,9 +126,21 @@ a {
#gollum-editor #gollum-editor-function-bar.active #gollum-editor-function-buttons { #gollum-editor #gollum-editor-function-bar.active #gollum-editor-function-buttons {
display: block; display: block;
float: left; margin: 0;
overflow: hidden; padding: 0;
padding: 0 0 1.1em 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 { #gollum-editor #gollum-editor-function-bar a.function-button {
@@ -120,12 +149,12 @@ a {
color: #333; color: #333;
display: block; display: block;
float: left; float: left;
height: 25px; height: 32px;
overflow: hidden; overflow: hidden;
margin: 0.2em 0.5em 0 0; margin: 1px 1px 0 0;
/* text-indent: -5000px; */ /* text-indent: -5000px; */
text-shadow: 0 1px 0 #fff; text-shadow: 0 1px 0 #fff;
width: 25px; width: 32px;
border-radius: 0.3em; border-radius: 0.3em;
-moz-border-radius: 0.3em; -moz-border-radius: 0.3em;
@@ -150,41 +179,84 @@ a {
background-image: url(../images/icon-sprite.png); background-image: url(../images/icon-sprite.png);
background-repeat: no-repeat; background-repeat: no-repeat;
display: block; display: block;
height: 25px; height: 32px;
overflow: hidden; overflow: hidden;
text-indent: -5000px; text-indent: -5000px;
width: 25px; width: 32px;
} }
a#function-bold span { background-position: 0 0; } a#function-bold span { background-position: 3px 3px; }
a#function-italic span { background-position: -27px 0; } a#function-italic span { background-position: -24px 3px; }
a#function-underline span { background-position: -54px 0; } a#function-underline span { background-position: -51px 3px; }
a#function-code span { background-position: -82px 0; } a#function-code span { background-position: -79px 3px; }
a#function-ul span { background-position: -109px 0; } a#function-ul span { background-position: -106px 3px; }
a#function-ol span { background-position: -136px 0; } a#function-ol span { background-position: -133px 3px; }
a#function-blockquote span { background-position: -163px 0; } a#function-blockquote span { background-position: -160px 3px; }
a#function-hr span { background-position: -190px 0; } a#function-hr span { background-position: -187px 3px; }
a#function-h1 span { background-position: -217px 0; } a#function-h1 span { background-position: -214px 3px; }
a#function-h2 span { background-position: -244px 0; } a#function-h2 span { background-position: -241px 3px; }
a#function-h3 span { background-position: -271px 0; } a#function-h3 span { background-position: -268px 3px; }
a#function-link span { background-position: -298px 0; } a#function-link span { background-position: -295px 3px; }
a#function-image span { background-position: -324px 0; } a#function-image span { background-position: -321px 3px; }
a#function-help span { background-position: -405px 0; } a#function-help span { background-position: -402px 3px; }
a#function-bold:hover span { background-position: 0 -28px; } a#function-bold:hover span { background-position: 3px -25px; }
a#function-italic:hover span { background-position: -27px -28px; } a#function-italic:hover span { background-position: -24px -25px; }
a#function-underline:hover span { background-position: -54px -28px; } a#function-underline:hover span { background-position: -51px -25px; }
a#function-code:hover span { background-position: -82px -28px; } a#function-code:hover span { background-position: -79px -25px; }
a#function-ul:hover span { background-position: -109px -28px; } a#function-ul:hover span { background-position: -106px -25px; }
a#function-ol:hover span { background-position: -136px -28px; } a#function-ol:hover span { background-position: -133px -25px; }
a#function-blockquote:hover span { background-position: -163px -28px; } a#function-blockquote:hover span { background-position: -160px -25px; }
a#function-hr:hover span { background-position: -190px -28px; } a#function-hr:hover span { background-position: -187px -25px; }
a#function-h1:hover span { background-position: -217px -28px; } a#function-h1:hover span { background-position: -214px -25px; }
a#function-h2:hover span { background-position: -244px -28px; } a#function-h2:hover span { background-position: -241px -25px; }
a#function-h3:hover span { background-position: -271px -28px; } a#function-h3:hover span { background-position: -268px -25px; }
a#function-link:hover span { background-position: -298px -28px; } a#function-link:hover span { background-position: -295px -25px; }
a#function-image:hover span { background-position: -324px -28px; } a#function-image:hover span { background-position: -321px -25px; }
a#function-help:hover span { background-position: -405px -28px; } 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 { #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 { #gollum-editor #gollum-editor-function-bar span.function-divider {
display: block; display: none;
float: left;
width: 0.5em;
} }
#gollum-editor #gollum-editor-function-bar #gollum-editor-format-selector { #gollum-editor #gollum-editor-function-bar #gollum-editor-format-selector {
overflow: hidden; padding: 0.2em 0 0.5em 0;
padding: .2em 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 #gollum-editor #gollum-editor-function-bar
@@ -208,13 +285,12 @@ a#function-help:hover span { background-position: -405px -28px; }
border: 1px solid #ddd; border: 1px solid #ddd;
color: #333; color: #333;
float: right;
font-size: 1em; font-size: 1em;
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-weight: bold; font-weight: bold;
line-height: 1.6em; line-height: 1.6em;
padding: 0.3em 0.4em; padding: 0.3em 0.4em;
display: inline-block;
border-radius: 0.5em; border-radius: 0.5em;
-moz-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 #gollum-editor-function-bar
#gollum-editor-format-selector label { #gollum-editor-format-selector label {
color: #999; color: #999;
float: right;
font-size: 1em; font-size: 1em;
font-weight: bold; font-weight: bold;
line-height: 1.6em; line-height: 1.6em;
padding: .3em 0.5em 0 0; padding: .3em 0.5em 0 0;
display: inline-block;
} }
#gollum-editor #gollum-editor-function-bar #gollum-editor #gollum-editor-function-bar
@@ -236,6 +312,56 @@ a#function-help:hover span { background-position: -405px -28px; }
content: ':'; 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 */ /* @section form-fields */
@@ -245,12 +371,18 @@ a#function-help:hover span { background-position: -405px -28px; }
font-size: 1em; font-size: 1em;
font-family: Consolas, "Liberation Mono", Courier, monospace; font-family: Consolas, "Liberation Mono", Courier, monospace;
line-height: 1.4em; line-height: 1.4em;
margin: 1em 0 0.4em; margin: 0 0 0.4em;
padding: 0.5em; padding: 0.5em;
width: 98%; width: 98%;
height: 20em; height: 20em;
} }
@media all and (min-width: 940px) {
#gollum-editor textarea {
margin: 1em 0 0.4em;
}
}
#gollum-editor input#gollum-editor-submit { #gollum-editor input#gollum-editor-submit {
background-color: #f7f7f7; background-color: #f7f7f7;
border: 1px solid #d4d4d4; border: 1px solid #d4d4d4;
@@ -445,6 +577,7 @@ a#function-help:hover span { background-position: -405px -28px; }
/* @section help */ /* @section help */
#gollum-editor-help { #gollum-editor-help {
clear: both;
margin: 0; margin: 0;
overflow: hidden; overflow: hidden;
padding: 0; padding: 0;
@@ -455,13 +588,13 @@ a#function-help:hover span { background-position: -405px -28px; }
#gollum-editor-help-parent, #gollum-editor-help-parent,
#gollum-editor-help-list { #gollum-editor-help-list {
display: block; display: block;
float: left;
height: 17em;
list-style-type: none; list-style-type: none;
overflow: auto;
margin: 0; margin: 0;
padding: 1em 0; float: left;
width: 18%; width: 50%;
box-sizing: border-box;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
} }
#gollum-editor-help-parent { #gollum-editor-help-parent {
@@ -491,6 +624,7 @@ a#function-help:hover span { background-position: -405px -28px; }
width: auto; width: auto;
padding: 0.2em 1em; padding: 0.2em 1em;
text-shadow: 0 -1px 0 #fff; text-shadow: 0 -1px 0 #fff;
font-size: 0.8em;
} }
#gollum-editor-help-parent li a:hover, #gollum-editor-help-parent li a:hover,
@@ -518,6 +652,7 @@ a#function-help:hover span { background-position: -405px -28px; }
overflow: auto; overflow: auto;
height: 17em; height: 17em;
padding: 1em; padding: 1em;
clear: both;
} }
#gollum-editor-help-content { #gollum-editor-help-content {
@@ -532,6 +667,29 @@ a#function-help:hover span { background-position: -405px -28px; }
padding: 0; 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 */
.ie #gollum-editor .singleline input { .ie #gollum-editor .singleline input {
padding-top: 0.25em; padding-top: 0.25em;
+139 -22
View File
@@ -21,9 +21,15 @@ body, html {
#wiki-wrapper { #wiki-wrapper {
margin: 0 auto; margin: 0 auto;
overflow: visible; overflow: visible;
width: 920px; width: 100%;
padding-left:20px; }
padding-right:20px;
@media all and (min-width: 940px) {
#wiki-wrapper {
max-width: 920px;
padding-left:20px;
padding-right:20px;
}
} }
a:link { a:link {
@@ -39,22 +45,41 @@ a:hover, a:visited {
/* @section head */ /* @section head */
#head { #head {
border-bottom: 1px solid #ddd; margin: 1em 0 0;
margin: 4em 0 1.5em; padding: 0;
padding-bottom: 0.3em;
overflow: hidden; overflow: hidden;
} }
#head h1 { #head h1 {
font-size: 2.5em; font-size: 1.5em;
float: left; float: left;
line-height: normal; line-height: normal;
margin: 0; margin: 0;
padding: 2px 0 0 0; padding: 0 0 0 0.667em;
} }
#head ul.actions { #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 */ /* @section content */
@@ -89,6 +114,12 @@ a:hover, a:visited {
width: 100%; width: 100%;
} }
#wiki-body table {
display: block;
overflow: auto;
border: 0;
}
.has-sidebar #wiki-body { .has-sidebar #wiki-body {
width: 68%; width: 68%;
} }
@@ -244,6 +275,16 @@ a:hover, a:visited {
font-weight: bold; font-weight: bold;
} }
#footer .actions {
margin-left: 1em;
}
@media all and (min-width: 940px) {
#footer .actions {
margin: 0;
}
}
/* @section history */ /* @section history */
.history h1 { .history h1 {
@@ -257,7 +298,7 @@ a:hover, a:visited {
} }
#wiki-history { #wiki-history {
margin-top: 2em; margin: 2em 1em 0 1em;
} }
#wiki-history fieldset { #wiki-history fieldset {
@@ -283,7 +324,8 @@ a:hover, a:visited {
} }
#wiki-history table tr td { #wiki-history table tr td {
border: 1px solid #c0dce9; border-top: 1px solid #c0dce9;
border-bottom: 1px solid #c0dce9;
font-size: 1em; font-size: 1em;
line-height: 1.6em; line-height: 1.6em;
margin: 0; margin: 0;
@@ -291,8 +333,8 @@ a:hover, a:visited {
} }
#wiki-history table tr td.checkbox { #wiki-history table tr td.checkbox {
width: 4em; width: auto;
padding: 0.3em; padding: 0 0.2em 0 0;
} }
#wiki-history table tr td.checkbox input { #wiki-history table tr td.checkbox input {
@@ -364,6 +406,25 @@ a:hover, a:visited {
margin: 0 0.6em 0 0; 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 */ /* @section edit */
.edit h1 { .edit h1 {
@@ -378,6 +439,7 @@ a:hover, a:visited {
/* @section search */ /* @section search */
.results h1 { .results h1 {
color: #999; color: #999;
font-weight: normal; font-weight: normal;
@@ -390,6 +452,8 @@ a:hover, a:visited {
.results #results { .results #results {
border-bottom: 1px solid #ccc; border-bottom: 1px solid #ccc;
margin-left: 1em;
margin-right: 1em;
margin-bottom: 2em; margin-bottom: 2em;
padding-bottom: 2em; padding-bottom: 2em;
} }
@@ -400,12 +464,33 @@ a:hover, a:visited {
} }
.results #results ul li { .results #results ul li {
font-size: 1.2em; list-style: none;
line-height: 1.6em;
list-style-position: outside;
padding: 0.2em 0; 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 { .results #results ul li span.count {
color: #999; color: #999;
} }
@@ -522,8 +607,8 @@ ul.actions {
ul.actions li { ul.actions li {
float: left; float: left;
font-size: 0.9em; font-size: 0.9em;
margin-left: 0.6em; margin-left: 1px;
margin-bottom: 0.6em; margin-bottom: 1px;
} }
.minibutton a { .minibutton a {
@@ -533,7 +618,7 @@ ul.actions {
display: block; display: block;
font-weight: bold; font-weight: bold;
margin: 0; margin: 0;
padding: 0.4em 1em; padding: 0.6em 1em;
height: 1.4em; height: 1.4em;
text-shadow: 0 1px 0 #fff; text-shadow: 0 1px 0 #fff;
@@ -547,6 +632,18 @@ ul.actions {
-webkit-border-radius: 3px; -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 { #search-submit {
background-color: #f7f7f7; background-color: #f7f7f7;
border: 1px solid #d4d4d4; border: 1px solid #d4d4d4;
@@ -627,7 +724,7 @@ ul.actions {
/* @control searchbar */ /* @control searchbar */
#head #searchbar { #head #searchbar {
float: right; float: right;
padding: 0; padding: 2px 0 0 0;
overflow: hidden; overflow: hidden;
} }
@@ -684,7 +781,7 @@ ul.actions {
height: inherit; height: inherit;
overflow: hidden; overflow: hidden;
text-indent: -5000px; text-indent: -5000px;
width: 28px; width: 32px;
} }
.ff #head #searchbar #searchbar-fauxtext #search-submit span, .ff #head #searchbar #searchbar-fauxtext #search-submit span,
@@ -697,11 +794,31 @@ ul.actions {
padding: 0; 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 */ /* @section pages */
#pages { #pages {
font-size: 1.2em; 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 { #pages ul {
+6
View File
@@ -1,5 +1,11 @@
/* IE7-specific styles */ /* IE7-specific styles */
.ie #wiki-wrapper {
width: 920px;
padding-left:20px;
padding-right:20px;
}
.ie #head #searchbar #searchbar-fauxtext input#search-query { .ie #head #searchbar #searchbar-fauxtext input#search-query {
border: 0; border: 0;
float: left; float: left;
+52 -2
View File
@@ -27,6 +27,51 @@
content: "\f0c1"; 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 & padding reset*/
* { * {
margin: 0; margin: 0;
@@ -52,7 +97,6 @@ body {
font: 13.34px Helvetica, arial, freesans, clean, sans-serif; font: 13.34px Helvetica, arial, freesans, clean, sans-serif;
font-size: small; font-size: small;
line-height: 1.4; line-height: 1.4;
min-width: 980px;
} }
img { img {
@@ -86,13 +130,19 @@ a:active, a:hover {
} }
.markdown-body { .markdown-body {
padding: 30px; padding: 1em;
font-size: 15px; font-size: 15px;
line-height: 1.7; line-height: 1.7;
overflow: hidden; overflow: hidden;
word-wrap: break-word; word-wrap: break-word;
} }
@media all and (min-width: 940px) {
.markdown-body {
padding: 30px;
}
}
.markdown-body > *:first-child { .markdown-body > *:first-child {
margin-top: 0 !important; margin-top: 0 !important;
} }
@@ -98,6 +98,52 @@
$('#gollum-editor-help').removeClass('jaws'); $('#gollum-editor-help').removeClass('jaws');
} }
} // EditorHas.functionBar } // 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 } // EditorHas.baseEditorMarkup
}; };
@@ -444,6 +490,17 @@
*/ */
titleDisplayed: function() { titleDisplayed: function() {
return ( ActiveOptions.NewFile ); 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;
} }
}; };
@@ -1,11 +1,11 @@
/** /**
* ASCIIDoc Language Definition * AsciiDoc Language Definition
* *
*/ */
(function($) { (function($) {
var ASCIIDoc = { var AsciiDoc = {
'function-bold' : { 'function-bold' : {
search: /(^[\n]+)([\n\s]*)/g, search: /(^[\n]+)([\n\s]*)/g,
@@ -19,7 +19,7 @@ var ASCIIDoc = {
'function-code' : { 'function-code' : {
search: /(^[\n]+)([\n\s]*)/g, search: /(^[\n]+)([\n\s]*)/g,
replace: "+$1+$2" replace: "`$1`$2"
}, },
'function-ul' : { 'function-ul' : {
@@ -37,6 +37,21 @@ var ASCIIDoc = {
replace: "----\n$1$2\n----\n" 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' : { 'function-link' : {
exec: function( txt, selText, $field ) { exec: function( txt, selText, $field ) {
var results = null; var results = null;
@@ -102,20 +117,20 @@ var ASCIIDoc = {
}; };
$.GollumEditor.defineLanguage('asciidoc', ASCIIDoc); $.GollumEditor.defineLanguage('asciidoc', AsciiDoc);
var ASCIIDocHelp = [ var AsciiDocHelp = [
{ {
menuName: 'Text Formatting', menuName: 'Text Formatting',
content: [ content: [
{ {
menuName: 'Headers', menuName: 'Headers',
data: '<p>ASCIIDoc headers can be written in two ways: with differing underlines or with different indentation using <code>=</code> (equals sign). ASCIIDoc supports headings 1-4. The editor will automatically use the <code>=</code> notation. To create a level one header, prefix your line with one <code>=</code>. Level two headers are created with <code>==</code> and so on.</p>' data: '<p>AsciiDoc headers can be written in two ways: with differing underlines or with different indentation using <code>=</code> (equals sign). AsciiDoc supports headings 1-4. The editor will automatically use the <code>=</code> notation. To create a level one header, prefix your line with one <code>=</code>. Level two headers are created with <code>==</code> and so on.</p>'
}, },
{ {
menuName: 'Bold / Italic', menuName: 'Bold / Italic',
data: '<p>To display text as <strong>bold</strong>, wrap the text in <code>*</code> (asterisks). To display text as <em>italic</em>, wrap the text in <code>_</code> (underscores). To create <code>monospace</code> text, wrap the text in <code>+</code> (plus signs).' data: '<p>To display text as <strong>bold</strong>, wrap the text in <code>*</code> (asterisks). To display text as <em>italic</em>, wrap the text in <code>_</code> (underscores). To create <code>monospace</code> text, wrap the text in <code>`</code> (backtick).'
}, },
{ {
menuName: 'Scripts', menuName: 'Scripts',
@@ -123,7 +138,7 @@ var ASCIIDocHelp = [
}, },
{ {
menuName: 'Special Characters', menuName: 'Special Characters',
data: '<p>ASCIIDoc will automatically convert textual representations of commonly-used special characters. For example, <code>(R)</code> becomes &reg;, <code>(C)</code> becomes &copy; and <code>(TM)</code> becomes &trade;.</p>' data: '<p>AsciiDoc will automatically convert textual representations of commonly-used special characters. For example, <code>(R)</code> becomes &reg;, <code>(C)</code> becomes &copy; and <code>(TM)</code> becomes &trade;.</p>'
} }
] ]
}, },
@@ -132,7 +147,7 @@ var ASCIIDocHelp = [
content: [ content: [
{ {
menuName: 'Paragraphs', menuName: 'Paragraphs',
data: '<p>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 <code>.</code> (full stop). An example paragraph with optional title is displayed below:<br><br><code>.Optional Title<br><br>This is my paragraph. It is two sentences long.</code></p>' data: '<p>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 <code>.</code> (full stop). An example paragraph with optional title is displayed below:<br><br><code>.Optional Title<br><br>This is my paragraph. It is two sentences long.</code></p>'
}, },
{ {
menuName: 'Source Blocks', menuName: 'Source Blocks',
@@ -157,12 +172,12 @@ var ASCIIDocHelp = [
}, },
{ {
menuName: 'Images', menuName: 'Images',
data: '<p>Images in ASCIIDoc work much like hyperlinks, but image URLs are prefixed with <code>image:</code>. For example, to link to an image at <code>images/icons/home.png</code>, write <code>image:images/icons/home.png</code>. Alt text can be added by appending the text to the URI in <code>[</code> (brackets).</p>' data: '<p>Images in AsciiDoc work much like hyperlinks, but image URLs are prefixed with <code>image:</code>. For example, to link to an image at <code>images/icons/home.png</code>, write <code>image:images/icons/home.png</code>. Alt text can be added by appending the text to the URI in <code>[</code> (brackets).</p>'
} }
] ]
} }
]; ];
$.GollumEditor.defineHelp('asciidoc', ASCIIDocHelp); $.GollumEditor.defineHelp('asciidoc', AsciiDocHelp);
})(jQuery); })(jQuery);
@@ -13,6 +13,12 @@
markupCreated: false, markupCreated: false,
markup: '', markup: '',
currentAspect: function(){
if (window.innerWidth < 480) return "small-mobile";
if ($('#gollum-dialog-dialog').css('position') == 'fixed') return "large-mobile";
return "desktop";
},
attachEvents: function( evtOK ) { attachEvents: function( evtOK ) {
$('#gollum-dialog-action-ok').click(function( e ) { $('#gollum-dialog-action-ok').click(function( e ) {
Dialog.eventOK( e, evtOK ); Dialog.eventOK( e, evtOK );
@@ -185,6 +191,8 @@
} }
}); });
} }
$(window).unbind('resize', Dialog.resize);
} }
}, },
@@ -268,14 +276,28 @@
}); });
} }
} }
$(window).bind('resize', Dialog.resize);
} }
}, },
resize: function(){
Dialog.position();
},
position: function() { position: function() {
var dialogHeight = $('#gollum-dialog-dialog-inner').height(); if (Dialog.currentAspect() == "small-mobile") {
$('#gollum-dialog-dialog-inner') $('#gollum-dialog-dialog-inner').css('height', '100%').css('margin-top', 'auto');
.css('height', dialogHeight + 'px') }
.css('margin-top', -1 * parseInt( dialogHeight / 2 )); else if (Dialog.currentAspect() == "large-mobile") {
$('#gollum-dialog-dialog-inner').css('height', 'auto').css('margin-top', 'auto');
}
else if (Dialog.currentAspect() == "desktop") {
var dialogHeight = $('#gollum-dialog-dialog-inner').height();
$('#gollum-dialog-dialog-inner')
.css('height', dialogHeight + 'px')
.css('margin-top', -1 * parseInt( dialogHeight / 2 ));
}
} }
}; };
+16 -10
View File
@@ -8,8 +8,10 @@
</li> </li>
<li class="minibutton"><a href="{{base_url}}/{{escaped_url_path}}" <li class="minibutton"><a href="{{base_url}}/{{escaped_url_path}}"
class="action-view-page">View Page</a></li> class="action-view-page">View Page</a></li>
<li class="minibutton"><a href="{{base_url}}/edit/{{escaped_url_path}}" {{#allow_editing}}
class="action-edit-page">Edit Page</a></li> <li class="minibutton"><a href="{{base_url}}/edit/{{escaped_url_path}}"
class="action-edit-page">Edit Page</a></li>
{{/allow_editing}}
<li class="minibutton"><a href="{{base_url}}/history/{{escaped_url_path}}" <li class="minibutton"><a href="{{base_url}}/history/{{escaped_url_path}}"
class="action-page-history">Page History</a></li> class="action-page-history">Page History</a></li>
</ul> </ul>
@@ -25,11 +27,13 @@
<ul class="actions"> <ul class="actions">
<li class="minibutton"><a href="{{base_url}}/history/{{escaped_url_path}}" <li class="minibutton"><a href="{{base_url}}/history/{{escaped_url_path}}"
class="action-page-history">Back to Page History</a></li> class="action-page-history">Back to Page History</a></li>
<li class="minibutton"> {{#allow_editing}}
<form name="gollum-revert" action="{{base_url}}/revert/{{escaped_url_path}}/{{before}}/{{after}}" method="post" id="gollum-revert-form"> <li class="minibutton">
<a href="#" class="gollum-revert-button">Revert Changes</a> <form name="gollum-revert" action="{{base_url}}/revert/{{escaped_url_path}}/{{before}}/{{after}}" method="post" id="gollum-revert-form">
</form> <a href="#" class="gollum-revert-button">Revert Changes</a>
</li> </form>
</li>
{{/allow_editing}}
</ul> </ul>
{{/show_revert}} {{/show_revert}}
@@ -52,9 +56,11 @@
<li class="minibutton"><a href="{{base_url}}/history/{{escaped_url_path}}" <li class="minibutton"><a href="{{base_url}}/history/{{escaped_url_path}}"
class="action-page-history">Back to Page History</a></li> class="action-page-history">Back to Page History</a></li>
{{#show_revert}} {{#show_revert}}
<li class="minibutton"> {{#allow_editing}}
<a href="#" class="gollum-revert-button">Revert Changes</a> <li class="minibutton">
</li> <a href="#" class="gollum-revert-button">Revert Changes</a>
</li>
{{/allow_editing}}
{{/show_revert}} {{/show_revert}}
<li class="minibutton"><a href="#">Back to Top</a></li> <li class="minibutton"><a href="#">Back to Top</a></li>
</ul> </ul>
+6 -2
View File
@@ -1,4 +1,4 @@
<div id="gollum-editor" data-escaped-name="{{escaped_name}}" class="{{#is_create_page}}create{{/is_create_page}}{{#is_edit_page}}edit{{/is_edit_page}}"> <div id="gollum-editor" data-escaped-name="{{escaped_name}}" class="{{#is_create_page}}create{{/is_create_page}}{{#is_edit_page}}edit{{/is_edit_page}} {{#allow_uploads}}uploads-allowed{{/allow_uploads}}">
{{#is_create_page}} {{#is_create_page}}
<form name="gollum-editor" action="{{base_url}}/create" method="post"> <form name="gollum-editor" action="{{base_url}}/create" method="post">
{{/is_create_page}} {{/is_create_page}}
@@ -55,6 +55,7 @@
</div> </div>
<div id="gollum-editor-format-selector"> <div id="gollum-editor-format-selector">
<label for="format">Edit Mode</label>
<select id="wiki_format" name="format"> <select id="wiki_format" name="format">
{{#formats}} {{#formats}}
<option {{#selected}}selected="selected" {{/selected}}value="{{id}}"> <option {{#selected}}selected="selected" {{/selected}}value="{{id}}">
@@ -62,7 +63,6 @@
</option> </option>
{{/formats}} {{/formats}}
</select> </select>
<label for="format">Edit Mode</label>
</div> </div>
</div> </div>
<div id="gollum-editor-help" class="jaws"> <div id="gollum-editor-help" class="jaws">
@@ -89,6 +89,10 @@
</div> </div>
<textarea id="gollum-editor-body" <textarea id="gollum-editor-body"
data-markup-lang="{{format}}" name="content" class="mousetrap">{{content}}</textarea> data-markup-lang="{{format}}" name="content" class="mousetrap">{{content}}</textarea>
<div>
<i class="fa fa-spinner fa-spin"></i>
Uploading file ...
</div>
{{#header}} {{#header}}
<div id="gollum-editor-edit-header" class="collapsed"> <div id="gollum-editor-edit-header" class="collapsed">
+4 -2
View File
@@ -7,8 +7,10 @@
</li> </li>
<li class="minibutton"><a href="{{base_url}}/{{escaped_url_path}}" <li class="minibutton"><a href="{{base_url}}/{{escaped_url_path}}"
class="action-view-page">View Page</a></li> class="action-view-page">View Page</a></li>
<li class="minibutton"><a href="{{base_url}}/edit/{{escaped_url_path}}" {{#allow_editing}}
class="action-edit-page">Edit Page</a></li> <li class="minibutton"><a href="{{base_url}}/edit/{{escaped_url_path}}"
class="action-edit-page">Edit Page</a></li>
{{/allow_editing}}
</ul> </ul>
</div> </div>
<div id="wiki-history"> <div id="wiki-history">
@@ -0,0 +1,39 @@
<div id="wiki-wrapper" class="history">
<div id="head">
<h1><strong>{{title}}</strong></h1>
<ul class="actions">
<li class="minibutton"><a href="{{base_url}}/{{escaped_url_path}}"
class="action-view-page">Home</a></li>
</ul>
</div>
<div id="wiki-history">
<fieldset>
<table>
<tbody>
{{#versions}}
<tr>
<td class="author">
{{>author_template}}
</td>
<td class="commit-name">
<span class="time-elapsed" title="{{date_full}}">{{date}}:</span>&nbsp;
{{message}}
[{{id7}}]
{{#files}}
<br>
<a href="{{link}}">{{file}}</a>
{{/files}}
</td>
</tr>
{{/versions}}
</tbody>
</table>
</fieldset>
</div>
<div id="footer">
</div>
</div>
+4 -1
View File
@@ -2,6 +2,9 @@
<html> <html>
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=utf-8"> <meta http-equiv="Content-type" content="text/html;charset=utf-8">
<meta name="MobileOptimized" content="width">
<meta name="HandheldFriendly" content="true">
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" type="text/css" href="{{base_url}}/css/gollum.css" media="all"> <link rel="stylesheet" type="text/css" href="{{base_url}}/css/gollum.css" media="all">
<link rel="stylesheet" type="text/css" href="{{base_url}}/css/editor.css" media="all"> <link rel="stylesheet" type="text/css" href="{{base_url}}/css/editor.css" media="all">
<link rel="stylesheet" type="text/css" href="{{base_url}}/css/dialog.css" media="all"> <link rel="stylesheet" type="text/css" href="{{base_url}}/css/dialog.css" media="all">
@@ -16,9 +19,9 @@
<script> <script>
var baseUrl = '{{base_url}}'; var baseUrl = '{{base_url}}';
var uploadDest = '{{upload_dest}}';
{{#page}} {{#page}}
var pageFullPath = '{{url_path_display}}'; var pageFullPath = '{{url_path_display}}';
var uploadDest = '{{upload_dest}}';
{{/page}} {{/page}}
</script> </script>
<script type="text/javascript" src="{{base_url}}/javascript/jquery-1.7.2.min.js"></script> <script type="text/javascript" src="{{base_url}}/javascript/jquery-1.7.2.min.js"></script>
+30 -15
View File
@@ -18,22 +18,35 @@ Mousetrap.bind(['e'], function( e ) {
class="action-all-pages">All</a></li> class="action-all-pages">All</a></li>
<li class="minibutton"><a href="{{base_url}}/fileview" <li class="minibutton"><a href="{{base_url}}/fileview"
class="action-fileview">Files</a></li> class="action-fileview">Files</a></li>
<li class="minibutton jaws"> {{#allow_editing}}
<a href="#" id="minibutton-new-page">New</a></li> <li class="minibutton jaws">
{{#allow_uploads}} <a href="#" id="minibutton-new-page">New</a></li>
<li class="minibutton jaws"> {{/allow_editing}}
<a href="#" id="minibutton-upload-page">Upload</a></li> {{#allow_editing}}
{{/allow_uploads}} {{#allow_uploads}}
{{#editable}} <li class="minibutton jaws">
<li class="minibutton jaws"> <a href="#" id="minibutton-upload-page">Upload</a></li>
<a href="#" id="minibutton-rename-page">Rename</a></li> {{/allow_uploads}}
<li class="minibutton"><a href="{{base_url}}/edit/{{escaped_url_path}}" {{/allow_editing}}
class="action-edit-page">Edit</a></li> {{#allow_editing}}
{{/editable}} {{#editable}}
<li class="minibutton jaws">
<a href="#" id="minibutton-rename-page">Rename</a></li>
{{/editable}}
{{/allow_editing}}
{{#allow_editing}}
{{#editable}}
<li class="minibutton"><a href="{{base_url}}/edit/{{escaped_url_path}}"
class="action-edit-page">Edit</a></li>
{{/editable}}
{{/allow_editing}}
{{#page_exists}} {{#page_exists}}
<li class="minibutton jaws"> <li class="minibutton jaws">
<li class="minibutton"><a href="{{base_url}}/history/{{escaped_url_path}}" <li class="minibutton"><a href="{{base_url}}/history/{{escaped_url_path}}"
class="action-page-history">History</a></li> class="action-page-history">History</a></li>
<li class="minibutton jaws">
<li class="minibutton"><a href="{{base_url}}/latest_changes"
class="action-page-history">Latest Changes</a></li>
{{/page_exists}} {{/page_exists}}
</ul> </ul>
</div> </div>
@@ -75,9 +88,11 @@ Mousetrap.bind(['e'], function( e ) {
</div> </div>
<div id="footer"> <div id="footer">
<p id="last-edit">Last edited by <b>{{author}}</b>, {{date}}</p> <p id="last-edit">Last edited by <b>{{author}}</b>, {{date}}</p>
<p> {{#allow_editing}}
<a id="delete-link" href="{{base_url}}/{{escaped_url_path}}" data-confirm="Are you sure you want to delete this page?"><span>Delete this Page</span></a> <p>
</p> <a id="delete-link" href="{{base_url}}/{{escaped_url_path}}" data-confirm="Are you sure you want to delete this page?"><span>Delete this Page</span></a>
</p>
{{/allow_editing}}
</div> </div>
</div> </div>
+4 -3
View File
@@ -7,9 +7,10 @@
</li> </li>
<li class="minibutton"><a href="{{base_url}}/" <li class="minibutton"><a href="{{base_url}}/"
class="action-home-page">Home</a></li> class="action-home-page">Home</a></li>
<li class="minibutton jaws"> {{#allow_editing}}
<a href="#" id="minibutton-new-page">New</a> <li class="minibutton jaws">
</li> <a href="#" id="minibutton-new-page">New</a></li>
{{/allow_editing}}
</ul> </ul>
</div> </div>
<div id="pages"> <div id="pages">
+1 -1
View File
@@ -3,7 +3,7 @@ module Precious
class Compare < Layout class Compare < Layout
include HasPage include HasPage
attr_reader :page, :diff, :versions, :message attr_reader :page, :diff, :versions, :message, :allow_editing
def title def title
"Comparison of #{@page.title}" "Comparison of #{@page.title}"
+8
View File
@@ -17,6 +17,14 @@ module Precious
false false
end end
def allow_uploads
@allow_uploads
end
def upload_dest
@upload_dest
end
def format def format
@format = (@page.format || false) if @format.nil? && @page @format = (@page.format || false) if @format.nil? && @page
@format.to_s.downcase @format.to_s.downcase
+8
View File
@@ -60,6 +60,14 @@ module Precious
true true
end end
def allow_uploads
@allow_uploads
end
def upload_dest
@upload_dest
end
def format def format
@format = (@page.format || false) if @format.nil? @format = (@page.format || false) if @format.nil?
@format.to_s.downcase @format.to_s.downcase
+1 -1
View File
@@ -3,7 +3,7 @@ module Precious
class History < Layout class History < Layout
include HasPage include HasPage
attr_reader :page, :page_num attr_reader :page, :page_num, :allow_editing
def title def title
@page.title @page.title
+90
View File
@@ -0,0 +1,90 @@
module Precious
module Views
class LatestChanges < Layout
attr_reader :wiki
def title
"Latest Changes (Globally)"
end
def versions
i = @versions.size + 1
@versions.map do |v|
i -= 1
{ :id => v.id,
:id7 => v.id[0..6],
:num => i,
:author => v.author.name.respond_to?(:force_encoding) ? v.author.name.force_encoding('UTF-8') : v.author.name,
:message => v.message.respond_to?(:force_encoding) ? v.message.force_encoding('UTF-8') : v.message,
:date => v.authored_date.strftime("%B %d, %Y"),
:gravatar => Digest::MD5.hexdigest(v.author.email.strip.downcase),
:identicon => self._identicon_code(v.author.email),
:date_full => v.authored_date,
:files => v.stats.files.map { |f,*rest|
page_path = extract_renamed_path_destination(f)
page_path = remove_page_extentions(page_path)
{ :file => f,
:link => "#{page_path}/#{v.id}"
}
}
}
end
end
def remove_page_extentions(page_path)
Gollum::Markup.formats.values.each do |format|
page_path = page_path.gsub(/\.#{format[:regexp]}$/, '')
end
return page_path
end
def extract_renamed_path_destination(file)
return file.gsub(/{.* => (.*)}/, '\1').gsub(/.* => (.*)/, '\1')
end
# http://stackoverflow.com/questions/9445760/bit-shifting-in-ruby
def left_shift(int, shift)
r = ((int & 0xFF) << (shift & 0x1F)) & 0xFFFFFFFF
# 1>>31, 2**32
(r & 2147483648) == 0 ? r : r - 4294967296
end
def string_to_code(string)
# sha bytes
b = [Digest::SHA1.hexdigest(string)[0, 20]].pack('H*').bytes.to_a
# Thanks donpark's IdenticonUtil.java for this.
# Match the following Java code
# ((b[0] & 0xFF) << 24) | ((b[1] & 0xFF) << 16) |
# ((b[2] & 0xFF) << 8) | (b[3] & 0xFF)
return left_shift(b[0], 24) |
left_shift(b[1], 16) |
left_shift(b[2], 8) |
b[3] & 0xFF
end
def _identicon_code(blob)
string_to_code blob + @request.host
end
def use_identicon
@wiki.user_icons == 'identicon'
end
def partial(name)
if name == :author_template
self.class.partial("history_authors/#{@wiki.user_icons}")
else
super
end
end
def previous_link
end
def next_link
end
end
end
end
+29 -11
View File
@@ -14,7 +14,7 @@ module Precious
end end
def page_header def page_header
page_header_from_content(@content) || title title
end end
def content def content
@@ -47,6 +47,10 @@ module Precious
@page_exists @page_exists
end end
def allow_editing
@allow_editing
end
def allow_uploads def allow_uploads
@allow_uploads @allow_uploads
end end
@@ -56,8 +60,12 @@ module Precious
end end
def has_header def has_header
@header = (@page.header || false) if @header.nil? if @header
!!@header @header.formatted_data.strip.empty? ? false : true
else
@header = (@page.header || false)
!!@header
end
end end
def header_content def header_content
@@ -69,8 +77,12 @@ module Precious
end end
def has_footer def has_footer
@footer = (@page.footer || false) if @footer.nil? if @footer
!!@footer @footer.formatted_data.strip.empty? ? false : true
else
@footer = (@page.footer || false)
!!@footer
end
end end
def footer_content def footer_content
@@ -86,8 +98,12 @@ module Precious
end end
def has_sidebar def has_sidebar
@sidebar = (@page.sidebar || false) if @sidebar.nil? if @sidebar
!!@sidebar @sidebar.formatted_data.strip.empty? ? false : true
else
@sidebar = (@page.sidebar || false)
!!@sidebar
end
end end
def sidebar_content def sidebar_content
@@ -142,7 +158,7 @@ module Precious
def find_header_node(doc) def find_header_node(doc)
case @page.format case @page.format
when :asciidoc when :asciidoc
doc.css("div#gollum-root > div#header > h1:first-child") doc.css("div#gollum-root > h1:first-child")
when :org when :org
doc.css("div#gollum-root > p.title:first-child") doc.css("div#gollum-root > p.title:first-child")
when :pod when :pod
@@ -166,9 +182,11 @@ module Precious
# Returns page content without title if it was extracted. # Returns page content without title if it was extracted.
# #
def content_without_page_header(content) def content_without_page_header(content)
doc = build_document(content) doc = build_document(content)
title = find_header_node(doc) if @h1_title
title.remove unless title.empty? title = find_header_node(doc)
title.remove unless title.empty?
end
# .inner_html will cause href escaping on UTF-8 # .inner_html will cause href escaping on UTF-8
doc.css("div#gollum-root").children.to_xml(@@to_xml) doc.css("div#gollum-root").children.to_xml(@@to_xml)
end end
+6 -2
View File
@@ -3,7 +3,7 @@ require "pathname"
module Precious module Precious
module Views module Views
class Pages < Layout class Pages < Layout
attr_reader :results, :ref attr_reader :results, :ref, :allow_editing
def title def title
"All pages in #{@ref}" "All pages in #{@ref}"
@@ -47,7 +47,11 @@ module Precious
folder_link folder_link
end end
elsif page_path != ".gitkeep" elsif page_path != ".gitkeep"
%{<li><a href="#{@base_url}/#{page.escaped_url_path}" class="file">#{page.name}</a></li>} if defined? page.format
%{<li><a href="#{@base_url}/#{page.escaped_url_path}" class="file">#{page.name}</a></li>}
else
%{<li><a href="#{@base_url}/#{page.escaped_url_path}#{page.name}" class="file">#{page.name}</a></li>}
end
end end
}.compact.join("\n") }.compact.join("\n")
else else
+11
View File
@@ -87,3 +87,14 @@ def context(*args, &block)
end end
$contexts = [] $contexts = []
# Commit file to wiki, overwriting previous versions of that file
def commit_test_file(wiki, dir, filename, ext, content)
committer = Gollum::Committer.new(wiki, :message => "Added testfile", :parent => wiki.repo.head.commit)
committer.add_to_index(dir, filename, ext, content, true)
committer.after_commit do |committer, sha|
wiki.clear_cache
committer.update_working_dir(dir, filename, ext)
end
committer.commit
end
+80
View File
@@ -0,0 +1,80 @@
# ~*~ encoding: utf-8 ~*~
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
context "Precious::Views::Editing" do
include Rack::Test::Methods
setup do
examples = testpath "examples"
@path = File.join(examples, "test.git")
Precious::App.set(:gollum_path, @path)
FileUtils.cp_r File.join(examples, "revert.git"), @path, :remove_destination => true
@wiki = Gollum::Wiki.new(@path)
end
teardown do
FileUtils.rm_r(File.join(File.dirname(__FILE__), *%w[examples test.git]))
end
test "creating page is blocked" do
Precious::App.set(:wiki_options, { allow_editing: false})
post "/create", :content => 'abc', :page => "D",
:format => 'markdown', :message => 'def'
assert !last_response.ok?
page = @wiki.page('D')
assert page.nil?
end
test "frontend links for editing are not blocked" do
Precious::App.set(:wiki_options, { allow_editing: true, allow_uploads: true })
get '/A'
assert_match /Delete this Page/, last_response.body, "'Delete this Page' link is blocked in page template"
assert_match /New/, last_response.body, "'New' button is blocked in page template"
assert_match /Upload/, last_response.body, "'Upload' link is blocked in page template"
assert_match /Rename/, last_response.body, "'Rename' link is blocked in page template"
assert_match /Edit/, last_response.body, "'Edit' link is blocked in page template"
get '/pages'
assert_match /New/, last_response.body, "'New' link is blocked in pages template"
get '/history/A'
assert_match /Edit/, last_response.body, "'Edit' link is blocked in history template"
get '/compare/A/fc66539528eb96f21b2bbdbf557788fe8a1196ac..b26b791cb7917c4f37dd9cb4d1e0efb24ac4d26f'
assert_match /Edit Page/, last_response.body, "'Edit Page' link is blocked in compare template"
assert_match /Revert Changes/, last_response.body, "'Revert Changes' link is blocked in compare template"
end
test "frontend links for editing blocked" do
Precious::App.set(:wiki_options, { allow_editing: false })
get '/A'
assert_no_match /Delete this Page/, last_response.body, "'Delete this Page' link not blocked in page template"
assert_no_match /New/, last_response.body, "'New' button not blocked in page template"
assert_no_match /Upload/, last_response.body, "'Upload' link not blocked in page template"
assert_no_match /Rename/, last_response.body, "'Rename' link not blocked in page template"
assert_no_match /Edit/, last_response.body, "'Edit' link not blocked in page template"
get '/pages'
assert_no_match /New/, last_response.body, "'New' link not blocked in pages template"
get '/history/A'
assert_no_match /Edit/, last_response.body, "'Edit' link not blocked in history template"
get '/compare/A/fc66539528eb96f21b2bbdbf557788fe8a1196ac..b26b791cb7917c4f37dd9cb4d1e0efb24ac4d26f'
assert_no_match /Edit Page/, last_response.body, "'Edit Page' link not blocked in compare template"
assert_no_match /Revert Changes/, last_response.body, "'Revert Changes' link not blocked in compare template"
end
def app
Precious::App
end
end
+22 -2
View File
@@ -8,7 +8,7 @@ context "Frontend" do
@path = cloned_testpath("examples/revert.git") @path = cloned_testpath("examples/revert.git")
@wiki = Gollum::Wiki.new(@path) @wiki = Gollum::Wiki.new(@path)
Precious::App.set(:gollum_path, @path) Precious::App.set(:gollum_path, @path)
Precious::App.set(:wiki_options, {}) Precious::App.set(:wiki_options, {allow_editing: true})
end end
teardown do teardown do
@@ -78,12 +78,19 @@ context "Frontend" do
get page get page
expected = "<h2><a class=\"anchor\" id=\"#{text}\" href=\"##{text}\"><i class=\"fa fa-link\"></i></a>#{text}</h2>" expected = "<h2><a class=\"anchor\" id=\"_#{text}\" href=\"#_#{text}\"><i class=\"fa fa-link\"></i></a>#{text}</h2>"
actual = nfd(last_response.body) actual = nfd(last_response.body)
assert_match /#{expected}/, actual assert_match /#{expected}/, actual
end end
test "show sidebar, header, footer when present" do
divs = [@wiki.page("_Header").formatted_data, @wiki.page("_Footer").formatted_data, @wiki.page("_Sidebar").formatted_data]
@wiki.write_page("HeaderTest", :markdown, "Test", commit_details)
get "/HeaderTest"
divs.each {|div| assert_match div, last_response.body}
end
test "retain edit information" do test "retain edit information" do
page1 = 'page1' page1 = 'page1'
user1 = 'user1' user1 = 'user1'
@@ -542,6 +549,19 @@ context "Frontend" do
assert_match /meta name="robots" content="noindex, nofollow"/, last_response.body assert_match /meta name="robots" content="noindex, nofollow"/, last_response.body
end end
test "show revision of specific file" do
shas = {}
["First revision of testfile", "Second revision of testfile"].each do |content|
new_commit = commit_test_file(@wiki, "revisions", "testfile", "log", content)
shas[new_commit] = content
end
shas.each do |sha, content|
get "revisions/testfile.log/#{sha}"
assert last_response.ok?
assert_match /#{content}/, last_response.body
end
end
def app def app
Precious::App Precious::App
end end
+45
View File
@@ -0,0 +1,45 @@
# ~*~ encoding: utf-8 ~*~
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
require File.expand_path '../../lib/gollum/views/latest_changes', __FILE__
context "Precious::Views::LatestChanges" do
include Rack::Test::Methods
def app
Precious::App
end
setup do
@path = cloned_testpath("examples/lotr.git")
@wiki = Gollum::Wiki.new(@path)
Precious::App.set(:gollum_path, @path)
Precious::App.set(:wiki_options, {:latest_changes_count => 10})
end
test "displays_latest_changes" do
get('/latest_changes')
body = last_response.body
assert body.include?('<span class="username">Charles Pence</span>'), "/latest_changes should include the Author Charles Pence"
assert body.include?('60f12f4'), "/latest_changes should include the :latest_changes_count commit"
assert !body.include?('0ed8cbe'), "/latest_changes should not include more than latest_changes_count commits"
assert body.include?('<a href="Data-Two.csv/874f597a5659b4c3b153674ea04e406ff393975e">Data-Two.csv</a>'), "/latest_changes include links to modified files in #{body}"
assert body.include?('<a href="Hobbit/874f597a5659b4c3b153674ea04e406ff393975e">Hobbit.md</a>'), "/latest_changes should include links to modified pages in #{body}"
end
test "extract destination file name in case of path renaming" do
view = Precious::Views::LatestChanges.new
assert_equal "newname.md", view.extract_renamed_path_destination("oldname.md => newname.md")
assert_equal "newDirectoryName/fileName.md", view.extract_renamed_path_destination("{oldDirectoryName => newDirectoryName}/fileName.md")
end
test "remove page extentions" do
view = Precious::Views::LatestChanges.new
assert_equal "page", view.remove_page_extentions("page.wiki")
assert_equal "page-wiki", view.remove_page_extentions("page-wiki.md")
assert_equal "file.any_extention", view.remove_page_extentions("file.any_extention")
end
teardown do
FileUtils.rm_rf(@path)
end
end
+18 -6
View File
@@ -2,14 +2,26 @@
require File.expand_path(File.join(File.dirname(__FILE__), 'helper')) require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
require File.expand_path '../../lib/gollum/views/pages', __FILE__ require File.expand_path '../../lib/gollum/views/pages', __FILE__
FakeResult = Struct.new(:path) do FakePageResult = Struct.new(:path) do
def name def name
File.basename(path, File.extname(path)).gsub("-", " ") File.basename(path, File.extname(path)).gsub("-", " ")
end end
def escaped_url_path def escaped_url_path
CGI.escape(path).gsub(/\..+$/, "").gsub("%2F", "/") CGI.escape(path).gsub(/\..+$/, "").gsub("%2F", "/")
end end
def format
true
end
end
FakeFileResult = Struct.new(:path) do
def name
File.basename(path).gsub("-", " ")
end
def escaped_url_path
result = path.sub(/\/[^\/]+$/, '/')
CGI.escape(result).gsub("%2F", "/")
end
end end
context "Precious::Views::Pages" do context "Precious::Views::Pages" do
@@ -30,17 +42,17 @@ context "Precious::Views::Pages" do
test "files_folders" do test "files_folders" do
@page.instance_variable_set("@path", "Mordor") @page.instance_variable_set("@path", "Mordor")
@page.instance_variable_set("@base_url", "") @page.instance_variable_set("@base_url", "")
results = [FakeResult.new("Mordor/Eye-Of-Sauron.md"), FakeResult.new("Mordor/Orc/Saruman.md"), FakeResult.new("Mordor/.gitkeep")] results = [FakePageResult.new("Mordor/Eye-Of-Sauron.md"), FakeFileResult.new("Mordor/Aragorn.pdf"), FakePageResult.new("Mordor/Orc/Saruman.md"), FakeFileResult.new("Mordor/.gitkeep")]
@page.instance_variable_set("@results", results) @page.instance_variable_set("@results", results)
assert_equal %{<li><a href="/Mordor/Eye-Of-Sauron" class="file">Eye Of Sauron</a></li>\n<li><a href="/pages/Mordor/Orc/" class="folder">Orc</a></li>}, @page.files_folders assert_equal %{<li><a href="/Mordor/Eye-Of-Sauron" class="file">Eye Of Sauron</a></li>\n<li><a href="/Mordor/Aragorn.pdf" class="file">Aragorn.pdf</a></li>\n<li><a href="/pages/Mordor/Orc/" class="folder">Orc</a></li>}, @page.files_folders
end end
test "base url" do test "base url" do
# based on test "files_folders" # based on test "files_folders"
@page.instance_variable_set("@path", "Mordor") @page.instance_variable_set("@path", "Mordor")
@page.instance_variable_set("@base_url", "/wiki") @page.instance_variable_set("@base_url", "/wiki")
results = [FakeResult.new("Mordor/Eye-Of-Sauron.md"), FakeResult.new("Mordor/Orc/Saruman.md"), FakeResult.new("Mordor/.gitkeep")] results = [FakePageResult.new("Mordor/Eye-Of-Sauron.md"), FakeFileResult.new("Mordor/Aragorn.pdf"), FakePageResult.new("Mordor/Orc/Saruman.md"), FakePageResult.new("Mordor/.gitkeep")]
@page.instance_variable_set("@results", results) @page.instance_variable_set("@results", results)
assert_equal %{<li><a href="/wiki/Mordor/Eye-Of-Sauron" class="file">Eye Of Sauron</a></li>\n<li><a href="/wiki/pages/Mordor/Orc/" class="folder">Orc</a></li>}, @page.files_folders assert_equal %{<li><a href="/wiki/Mordor/Eye-Of-Sauron" class="file">Eye Of Sauron</a></li>\n<li><a href=\"/wiki/Mordor/Aragorn.pdf\" class=\"file\">Aragorn.pdf</a></li>\n<li><a href="/wiki/pages/Mordor/Orc/" class="folder">Orc</a></li>}, @page.files_folders
end end
end end