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
* 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
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).
+13 -4
View File
@@ -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
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.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 =
+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'
module Gollum
VERSION = '3.0.0'
VERSION = '3.1.0'
def self.assets_path
::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 '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
+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('//', '/')
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
+117 -15
View File
@@ -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;
+218 -60
View File
@@ -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;
+139 -22
View File
@@ -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 {
+6
View File
@@ -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;
+52 -2
View File
@@ -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;
}
@@ -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;
}
};
@@ -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: '<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',
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',
@@ -123,7 +138,7 @@ var ASCIIDocHelp = [
},
{
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: [
{
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',
@@ -157,12 +172,12 @@ var ASCIIDocHelp = [
},
{
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);
@@ -13,6 +13,12 @@
markupCreated: false,
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 ) {
$('#gollum-dialog-action-ok').click(function( e ) {
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() {
var dialogHeight = $('#gollum-dialog-dialog-inner').height();
$('#gollum-dialog-dialog-inner')
.css('height', dialogHeight + 'px')
.css('margin-top', -1 * parseInt( dialogHeight / 2 ));
if (Dialog.currentAspect() == "small-mobile") {
$('#gollum-dialog-dialog-inner').css('height', '100%').css('margin-top', 'auto');
}
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 class="minibutton"><a href="{{base_url}}/{{escaped_url_path}}"
class="action-view-page">View 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}}/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}}"
class="action-page-history">Page History</a></li>
</ul>
@@ -25,11 +27,13 @@
<ul class="actions">
<li class="minibutton"><a href="{{base_url}}/history/{{escaped_url_path}}"
class="action-page-history">Back to Page History</a></li>
<li class="minibutton">
<form name="gollum-revert" action="{{base_url}}/revert/{{escaped_url_path}}/{{before}}/{{after}}" method="post" id="gollum-revert-form">
<a href="#" class="gollum-revert-button">Revert Changes</a>
</form>
</li>
{{#allow_editing}}
<li class="minibutton">
<form name="gollum-revert" action="{{base_url}}/revert/{{escaped_url_path}}/{{before}}/{{after}}" method="post" id="gollum-revert-form">
<a href="#" class="gollum-revert-button">Revert Changes</a>
</form>
</li>
{{/allow_editing}}
</ul>
{{/show_revert}}
@@ -52,9 +56,11 @@
<li class="minibutton"><a href="{{base_url}}/history/{{escaped_url_path}}"
class="action-page-history">Back to Page History</a></li>
{{#show_revert}}
<li class="minibutton">
<a href="#" class="gollum-revert-button">Revert Changes</a>
</li>
{{#allow_editing}}
<li class="minibutton">
<a href="#" class="gollum-revert-button">Revert Changes</a>
</li>
{{/allow_editing}}
{{/show_revert}}
<li class="minibutton"><a href="#">Back to Top</a></li>
</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}}
<form name="gollum-editor" action="{{base_url}}/create" method="post">
{{/is_create_page}}
@@ -55,6 +55,7 @@
</div>
<div id="gollum-editor-format-selector">
<label for="format">Edit Mode</label>
<select id="wiki_format" name="format">
{{#formats}}
<option {{#selected}}selected="selected" {{/selected}}value="{{id}}">
@@ -62,7 +63,6 @@
</option>
{{/formats}}
</select>
<label for="format">Edit Mode</label>
</div>
</div>
<div id="gollum-editor-help" class="jaws">
@@ -89,6 +89,10 @@
</div>
<textarea id="gollum-editor-body"
data-markup-lang="{{format}}" name="content" class="mousetrap">{{content}}</textarea>
<div>
<i class="fa fa-spinner fa-spin"></i>
Uploading file ...
</div>
{{#header}}
<div id="gollum-editor-edit-header" class="collapsed">
+4 -2
View File
@@ -7,8 +7,10 @@
</li>
<li class="minibutton"><a href="{{base_url}}/{{escaped_url_path}}"
class="action-view-page">View 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}}/edit/{{escaped_url_path}}"
class="action-edit-page">Edit Page</a></li>
{{/allow_editing}}
</ul>
</div>
<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>
<head>
<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/editor.css" media="all">
<link rel="stylesheet" type="text/css" href="{{base_url}}/css/dialog.css" media="all">
@@ -16,9 +19,9 @@
<script>
var baseUrl = '{{base_url}}';
var uploadDest = '{{upload_dest}}';
{{#page}}
var pageFullPath = '{{url_path_display}}';
var uploadDest = '{{upload_dest}}';
{{/page}}
</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>
<li class="minibutton"><a href="{{base_url}}/fileview"
class="action-fileview">Files</a></li>
<li class="minibutton jaws">
<a href="#" id="minibutton-new-page">New</a></li>
{{#allow_uploads}}
<li class="minibutton jaws">
<a href="#" id="minibutton-upload-page">Upload</a></li>
{{/allow_uploads}}
{{#editable}}
<li class="minibutton jaws">
<a href="#" id="minibutton-rename-page">Rename</a></li>
<li class="minibutton"><a href="{{base_url}}/edit/{{escaped_url_path}}"
class="action-edit-page">Edit</a></li>
{{/editable}}
{{#allow_editing}}
<li class="minibutton jaws">
<a href="#" id="minibutton-new-page">New</a></li>
{{/allow_editing}}
{{#allow_editing}}
{{#allow_uploads}}
<li class="minibutton jaws">
<a href="#" id="minibutton-upload-page">Upload</a></li>
{{/allow_uploads}}
{{/allow_editing}}
{{#allow_editing}}
{{#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}}
<li class="minibutton jaws">
<li class="minibutton"><a href="{{base_url}}/history/{{escaped_url_path}}"
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}}
</ul>
</div>
@@ -75,9 +88,11 @@ Mousetrap.bind(['e'], function( e ) {
</div>
<div id="footer">
<p id="last-edit">Last edited by <b>{{author}}</b>, {{date}}</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}}
<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>
+4 -3
View File
@@ -7,9 +7,10 @@
</li>
<li class="minibutton"><a href="{{base_url}}/"
class="action-home-page">Home</a></li>
<li class="minibutton jaws">
<a href="#" id="minibutton-new-page">New</a>
</li>
{{#allow_editing}}
<li class="minibutton jaws">
<a href="#" id="minibutton-new-page">New</a></li>
{{/allow_editing}}
</ul>
</div>
<div id="pages">
+1 -1
View File
@@ -3,7 +3,7 @@ module Precious
class Compare < Layout
include HasPage
attr_reader :page, :diff, :versions, :message
attr_reader :page, :diff, :versions, :message, :allow_editing
def title
"Comparison of #{@page.title}"
+8
View File
@@ -17,6 +17,14 @@ module Precious
false
end
def allow_uploads
@allow_uploads
end
def upload_dest
@upload_dest
end
def format
@format = (@page.format || false) if @format.nil? && @page
@format.to_s.downcase
+8
View File
@@ -60,6 +60,14 @@ module Precious
true
end
def allow_uploads
@allow_uploads
end
def upload_dest
@upload_dest
end
def format
@format = (@page.format || false) if @format.nil?
@format.to_s.downcase
+1 -1
View File
@@ -3,7 +3,7 @@ module Precious
class History < Layout
include HasPage
attr_reader :page, :page_num
attr_reader :page, :page_num, :allow_editing
def 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
def page_header
page_header_from_content(@content) || title
title
end
def content
@@ -47,6 +47,10 @@ module Precious
@page_exists
end
def allow_editing
@allow_editing
end
def allow_uploads
@allow_uploads
end
@@ -56,8 +60,12 @@ module Precious
end
def has_header
@header = (@page.header || false) if @header.nil?
!!@header
if @header
@header.formatted_data.strip.empty? ? false : true
else
@header = (@page.header || false)
!!@header
end
end
def header_content
@@ -69,8 +77,12 @@ module Precious
end
def has_footer
@footer = (@page.footer || false) if @footer.nil?
!!@footer
if @footer
@footer.formatted_data.strip.empty? ? false : true
else
@footer = (@page.footer || false)
!!@footer
end
end
def footer_content
@@ -86,8 +98,12 @@ module Precious
end
def has_sidebar
@sidebar = (@page.sidebar || false) if @sidebar.nil?
!!@sidebar
if @sidebar
@sidebar.formatted_data.strip.empty? ? false : true
else
@sidebar = (@page.sidebar || false)
!!@sidebar
end
end
def sidebar_content
@@ -142,7 +158,7 @@ module Precious
def find_header_node(doc)
case @page.format
when :asciidoc
doc.css("div#gollum-root > div#header > h1:first-child")
doc.css("div#gollum-root > h1:first-child")
when :org
doc.css("div#gollum-root > p.title:first-child")
when :pod
@@ -166,9 +182,11 @@ module Precious
# Returns page content without title if it was extracted.
#
def content_without_page_header(content)
doc = build_document(content)
title = find_header_node(doc)
title.remove unless title.empty?
doc = build_document(content)
if @h1_title
title = find_header_node(doc)
title.remove unless title.empty?
end
# .inner_html will cause href escaping on UTF-8
doc.css("div#gollum-root").children.to_xml(@@to_xml)
end
+6 -2
View File
@@ -3,7 +3,7 @@ require "pathname"
module Precious
module Views
class Pages < Layout
attr_reader :results, :ref
attr_reader :results, :ref, :allow_editing
def title
"All pages in #{@ref}"
@@ -47,7 +47,11 @@ module Precious
folder_link
end
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
}.compact.join("\n")
else
+11
View File
@@ -87,3 +87,14 @@ def context(*args, &block)
end
$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")
@wiki = Gollum::Wiki.new(@path)
Precious::App.set(:gollum_path, @path)
Precious::App.set(:wiki_options, {})
Precious::App.set(:wiki_options, {allow_editing: true})
end
teardown do
@@ -78,12 +78,19 @@ context "Frontend" do
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)
assert_match /#{expected}/, actual
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
page1 = 'page1'
user1 = 'user1'
@@ -542,6 +549,19 @@ context "Frontend" do
assert_match /meta name="robots" content="noindex, nofollow"/, last_response.body
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
Precious::App
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 '../../lib/gollum/views/pages', __FILE__
FakeResult = Struct.new(:path) do
FakePageResult = Struct.new(:path) do
def name
File.basename(path, File.extname(path)).gsub("-", " ")
end
def escaped_url_path
CGI.escape(path).gsub(/\..+$/, "").gsub("%2F", "/")
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
context "Precious::Views::Pages" do
@@ -30,17 +42,17 @@ context "Precious::Views::Pages" do
test "files_folders" do
@page.instance_variable_set("@path", "Mordor")
@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)
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
test "base url" do
# based on test "files_folders"
@page.instance_variable_set("@path", "Mordor")
@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)
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