)
puts
@@ -192,7 +230,9 @@ if options['irb']
puts %( page.formatted_data)
puts %( # => "My wiki page
")
puts
- puts "Check out the Gollum README for more."
+ puts "Full API documentation at:"
+ puts "https://github.com/gollum/gollum-lib"
+ puts
IRB.start_session(binding)
rescue Gollum::InvalidGitRepositoryError, Gollum::NoSuchPathError
puts "Invalid Gollum wiki at #{File.expand_path(gollum_path).inspect}"
@@ -204,7 +244,7 @@ else
Precious::App.set(:wiki_options, wiki_options)
Precious::App.settings.mustache[:templates] = wiki_options[:template_dir] if wiki_options[:template_dir]
- if cfg = options['config']
+ if cfg = options[:config]
# If the path begins with a '/' it will be considered an absolute path,
# otherwise it will be relative to the CWD
cfg = File.join(Dir.getwd, cfg) unless cfg.slice(0) == File::SEPARATOR
@@ -220,21 +260,25 @@ else
base_path = wiki_options[:base_path]
- if wiki_options[:base_path].nil?
+ if base_path.nil?
Precious::App.run!(options)
else
require 'rack'
class MapGollum
- def initialize base_path
+ def initialize(base_path)
@mg = Rack::Builder.new do
- map '/' do
- run Proc.new { [302, { 'Location' => "/#{base_path}" }, []] }
- end
-
+
map "/#{base_path}" do
run Precious::App
end
+ map '/' do
+ run Proc.new { [302, { 'Location' => "/#{base_path}" }, []] }
+ end
+ map '/*' do
+ run Proc.new { [302, { 'Location' => "/#{base_path}" }, []] }
+ end
+
end
end
@@ -242,7 +286,8 @@ else
@mg.call(env)
end
end
+
# 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
diff --git a/config.rb b/config.rb
index 3f28df94..9c0a2150 100644
--- a/config.rb
+++ b/config.rb
@@ -1,28 +1,11 @@
-# Example gollum config
-# gollum ../wiki --config config.rb
-#
-# or run from source with
-#
-# bundle exec bin/gollum ../wiki/ --config config.rb
-
-# Remove const to avoid
-# warning: already initialized constant FORMAT_NAMES
-#
-# only remove if it's defined.
-# constant Gollum::Page::FORMAT_NAMES not defined (NameError)
-Gollum::Page.send :remove_const, :FORMAT_NAMES if defined? Gollum::Page::FORMAT_NAMES
-# limit to one format
-Gollum::Page::FORMAT_NAMES = { :markdown => "Markdown" }
-
=begin
-Valid formats are:
-{ :markdown => "Markdown",
- :textile => "Textile",
- :rdoc => "RDoc",
- :org => "Org-mode",
- :creole => "Creole",
- :rest => "reStructuredText",
- :asciidoc => "AsciiDoc",
- :mediawiki => "MediaWiki",
- :pod => "Pod" }
+This file can be used to (e.g.):
+- alter certain inner parts of Gollum,
+- extend it with your stuff.
+
+It is especially useful for customizing supported formats/markups. For more information and examples:
+- https://github.com/gollum/gollum#config-file
+
=end
+
+# enter your Ruby code here ...
diff --git a/config.ru b/config.ru
new file mode 100644
index 00000000..48f605a4
--- /dev/null
+++ b/config.ru
@@ -0,0 +1,12 @@
+=begin
+You should use this file, if you wish to:
+- launch Gollum as a Rack app,
+- alter certain startup behaviour of Gollum.
+
+For more information and examples:
+- https://github.com/gollum/gollum/wiki/Gollum-via-Rack
+- https://github.com/gollum/gollum#config-file
+
+=end
+
+# enter your Ruby code here ...
diff --git a/contrib/sysv-debian/init.d/gollum b/contrib/sysv-debian/init.d/gollum
new file mode 100755
index 00000000..b6bac7ba
--- /dev/null
+++ b/contrib/sysv-debian/init.d/gollum
@@ -0,0 +1,79 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides: gollum
+# Required-Start: $local_fs $remote_fs $network $syslog
+# Required-Stop: $local_fs $remote_fs $network $syslog
+# Default-Start: 2 3 4 5
+# Default-Stop: 0 1 6
+# X-Interactive: true
+# Short-Description: Start/stop gollum wiki
+### END INIT INFO
+
+# Distributed under the terms of the MIT License
+
+set -e
+
+# Edit these settings to your liking:
+GOLLUM_USER=gollum
+GOLLUM_BASE=/var/lib/gollum/.git
+GOLLUM_OPTS="--bare"
+
+NAME=gollum
+PID=/var/run/${NAME}.pid
+EXEC=/usr/local/bin/gollum
+LOG=/var/log/gollum.log
+
+. /lib/lsb/init-functions
+
+start ()
+{
+ # Change log file to be owned by GOLLUM_USER
+ touch "${LOG}"
+ chown "${GOLLUM_USER}" "${LOG}"
+
+ log_daemon_msg "Starting Gollum"
+ start-stop-daemon --start \
+ --name "${NAME}" \
+ --user "${GOLLUM_USER}" \
+ --chuid "${GOLLUM_USER}" \
+ --pidfile "${PID}" \
+ --make-pidfile --background \
+ --startas /bin/sh -- -c "exec ${EXEC} $GOLLUM_OPTS \"$GOLLUM_BASE\" > \"${LOG}\" 2>&1"
+ log_end_msg $?
+}
+
+stop ()
+{
+ log_daemon_msg "Stopping Gollum"
+ start-stop-daemon --stop \
+ --user "${GOLLUM_USER}" \
+ --signal INT \
+ --pidfile "${PID}" \
+ --retry 10
+ log_end_msg $?
+}
+
+status ()
+{
+ status_of_proc -p $PID $EXEC $NAME
+}
+
+case $1 in
+ start)
+ start
+ ;;
+ stop)
+ stop
+ ;;
+ restart)
+ stop
+ start
+ ;;
+ status)
+ status
+ ;;
+ *)
+ log_success_msg "Usage: $0 {start|stop|restart|status}"
+ exit 1
+ ;;
+esac
diff --git a/docs/sanitization.md b/docs/sanitization.md
deleted file mode 100644
index e23c5dba..00000000
--- a/docs/sanitization.md
+++ /dev/null
@@ -1,33 +0,0 @@
-Sanitization Rules
-==================
-
-Gollum uses the [Sanitize](http://wonko.com/post/sanitize) gem for HTML
-sanitization. Below you find the default allowed tags, attributes, and protocols, as well as directions to customize these settings.
-
-# Default Settings
-
-## ALLOWED TAGS
-
-a, abbr, acronym, address, area, b, big, blockquote, br, button, caption, center, cite, code, col, colgroup, dd, del, dfn, dir, div, dl, dt, em, fieldset, font, form, h1, h2, h3, h4, h5, h6, hr, i, img, input, ins, kbd, label, legend, li, map, menu, ol, optgroup, option, p, pre, q, s, samp, select, small, span, strike, strong, sub, sup, table, tbody, td, textarea, tfoot, th, thead, tr, tt, u, ul, var
-
-## ALLOWED ATTRIBUTES
-
-a href, abbr, accept, accept-charset, accesskey, action, align, alt, axis, border, cellpadding, cellspacing, char, charoff, class, charset, checked, cite, clear, cols, colspan, color, compact, coords, datetime, dir, disabled, enctype, for, frame, headers, height, hreflang, hspace, id, img src, ismap, label, lang, longdesc, maxlength, media, method, multiple, name, nohref, noshade, nowrap, prompt, readonly, rel, rev, rows, rowspan, rules, scope, selected, shape, size, span, start, summary, tabindex, target, title, type, usemap, valign, value, vspace, width
-
-## ALLOWED PROTOCOLS
-
-* a href: http, https, mailto, ftp, irc, apt, :relative
-* img src: http, https, :relative
-* form action: http, https, :relative
-
-# Customizing
-
-To customize these settings, edit your `config.rb` file along the following lines (be sure to run gollum with the `--config` option):
-
-```ruby
-sanitizer = Gollum::Sanitization.new
-sanitizer.protocols['a']['href'].concat ['ssh', 'vnc'] # Protocols
-sanitizer.elements.concat ['customtag1', 'customtag2'] # Tags
-sanitizer.attributes['a'].push 'target' # Attributes
-Precious::App.set(:wiki_options, {:sanitization => sanitizer})
-```
diff --git a/gollum.gemspec b/gollum.gemspec
index ecfb4818..84be9fe6 100644
--- a/gollum.gemspec
+++ b/gollum.gemspec
@@ -5,8 +5,8 @@ Gem::Specification.new do |s|
s.required_ruby_version = '>= 1.9'
s.name = 'gollum'
- s.version = '4.0.0'
- s.date = '2015-04-11'
+ s.version = '4.0.1'
+ s.date = '2016-05-19'
s.rubyforge_project = 'gollum'
s.license = 'MIT'
@@ -25,17 +25,19 @@ Gem::Specification.new do |s|
s.extra_rdoc_files = %w[README.md LICENSE]
s.add_dependency 'gollum-lib', '~> 4.0', '>= 4.0.1'
- s.add_dependency 'kramdown', '~> 1.8.0'
+ s.add_dependency 'kramdown', '~> 1.9.0'
s.add_dependency 'sinatra', '~> 1.4', '>= 1.4.4'
s.add_dependency 'mustache', ['>= 0.99.5', '< 1.0.0']
- s.add_dependency 'useragent', '~> 0.14.0'
+ s.add_dependency 'useragent', '~> 0.16.2'
+ s.add_dependency 'gemojione', '~> 2'
s.add_development_dependency 'rack-test', '~> 0.6.2'
s.add_development_dependency 'shoulda', '~> 3.5.0'
s.add_development_dependency 'minitest-reporters', '~> 0.14.16'
s.add_development_dependency 'twitter_cldr', '~> 3.2.0'
s.add_development_dependency 'mocha', '~> 1.1.0'
- s.add_development_dependency 'test-unit', '~> 3.1.0' if RUBY_VERSION =~ /^2.2/
+ s.add_development_dependency 'test-unit', '~> 3.1.0'
+ s.add_development_dependency 'webrick', '~> 1.3.1'
# = MANIFEST =
s.files = %w[
@@ -46,10 +48,11 @@ Gem::Specification.new do |s|
Rakefile
bin/gollum
config.rb
+ config.ru
contrib/openrc/conf.d/gollum
contrib/openrc/init.d/gollum
contrib/systemd/gollum@.service
- docs/sanitization.md
+ contrib/sysv-debian/init.d/gollum
gollum.gemspec
lib/gollum.rb
lib/gollum/app.rb
diff --git a/lib/gollum.rb b/lib/gollum.rb
index 55b81ca6..ca342ac9 100644
--- a/lib/gollum.rb
+++ b/lib/gollum.rb
@@ -16,7 +16,7 @@ require File.expand_path('../gollum/uri_encode_component', __FILE__)
$KCODE = 'U' if RUBY_VERSION[0, 3] == '1.8'
module Gollum
- VERSION = '4.0.0'
+ VERSION = '4.0.1'
def self.assets_path
::File.expand_path('gollum/public', ::File.dirname(__FILE__))
diff --git a/lib/gollum/app.rb b/lib/gollum/app.rb
index 12e47541..0896a79f 100644
--- a/lib/gollum/app.rb
+++ b/lib/gollum/app.rb
@@ -49,7 +49,7 @@ module Precious
class App < Sinatra::Base
register Mustache::Sinatra
include Precious::Helpers
-
+
dir = File.dirname(File.expand_path(__FILE__))
# Detect unsupported browsers.
@@ -59,6 +59,7 @@ module Precious
Browser.new('Internet Explorer', '10.0'),
Browser.new('Chrome', '7.0'),
Browser.new('Firefox', '4.0'),
+ Browser.new('Safari', '9.0')
]
def supported_useragent?(user_agent)
@@ -95,7 +96,6 @@ module Precious
before do
settings.wiki_options[:allow_editing] = settings.wiki_options.fetch(:allow_editing, true)
@allow_editing = settings.wiki_options[:allow_editing]
- forbid unless @allow_editing || request.request_method == "GET"
Precious::App.set(:mustache, {:templates => settings.wiki_options[:template_dir]}) if settings.wiki_options[:template_dir]
@base_url = url('/', false).chomp('/')
@page_dir = settings.wiki_options[:page_file_dir].to_s
@@ -130,6 +130,14 @@ module Precious
Gollum::Wiki.new(settings.gollum_path, settings.wiki_options)
end
+ get '/emoji/:name' do
+ begin
+ [200, {'Content-Type' => 'image/png'}, emoji(params['name'])]
+ rescue ArgumentError
+ not_found
+ end
+ end
+
get '/data/*' do
if page = wiki_page(params[:splat].first).page
page.raw_data
@@ -164,6 +172,8 @@ module Precious
end
post '/uploadFile' do
+ forbid unless @allow_editing
+
wiki = wiki_new
unless wiki.allow_uploads
@@ -176,9 +186,10 @@ module Precious
fullname = params[:file][:filename]
tempfile = params[:file][:tempfile]
end
+ halt 500 unless tempfile.is_a? Tempfile
# Remove page file dir prefix from upload path if necessary -- committer handles this itself
- dir = wiki.per_page_uploads ? params[:upload_dest].match(/^(#{wiki.page_file_dir}\/+)?(.*)/)[2] : 'uploads'
+ dir = wiki.per_page_uploads ? params[:upload_dest] : ::File.join([wiki.page_file_dir, 'uploads'].compact)
ext = ::File.extname(fullname)
format = ext.split('.').last || 'txt'
filename = ::File.basename(fullname, ext)
@@ -211,7 +222,22 @@ module Precious
end
end
+ post '/deleteFile/*' do
+ forbid unless @allow_editing
+ wiki = wiki_new
+ filepath = params[:splat].first
+ unless filepath.nil?
+ commit = commit_message
+ commit[:message] = "Deleted #{filepath}"
+ wiki.delete_file(filepath, commit)
+ end
+
+ redirect to('/fileview')
+ end
+
post '/rename/*' do
+ forbid unless @allow_editing
+
wikip = wiki_page(params[:splat].first)
halt 500 if wikip.nil?
wiki = wikip.wiki
@@ -248,6 +274,8 @@ module Precious
end
post '/edit/*' do
+ forbid unless @allow_editing
+
path = '/' + clean_url(sanitize_empty_params(params[:path])).to_s
page_name = CGI.unescape(params[:page])
wiki = wiki_new
@@ -307,6 +335,8 @@ module Precious
end
post '/create' do
+ forbid unless @allow_editing
+
name = params[:page].to_url
path = sanitize_empty_params(params[:path]) || ''
format = params[:format].intern
@@ -326,6 +356,8 @@ module Precious
end
post '/revert/*/:sha1/:sha2' do
+ forbid unless @allow_editing
+
wikip = wiki_page(params[:splat].first)
@path = wikip.path
@name = wikip.name
@@ -349,6 +381,8 @@ module Precious
end
post '/preview' do
+ forbid unless @allow_editing
+
wiki = wiki_new
@name = params[:page] || "Preview"
@page = wiki.preview_page(@name, params[:content], params[:format])
@@ -357,6 +391,7 @@ module Precious
@mathjax = wiki.mathjax
@h1_title = wiki.h1_title
@editable = false
+ @bar_side = wiki.bar_side
@allow_uploads = wiki.allow_uploads
mustache :page
end
@@ -494,7 +529,7 @@ module Precious
# Extensions and layout data
@editable = true
- @page_exists = !page.versions.empty?
+ @page_exists = !page.last_version.nil?
@toc_content = wiki.universal_toc ? @page.toc_data : nil
@mathjax = wiki.mathjax
@h1_title = wiki.h1_title
diff --git a/lib/gollum/helpers.rb b/lib/gollum/helpers.rb
index 3e057f3e..d140b932 100644
--- a/lib/gollum/helpers.rb
+++ b/lib/gollum/helpers.rb
@@ -1,6 +1,11 @@
# ~*~ encoding: utf-8 ~*~
+require 'gemojione'
+
module Precious
module Helpers
+
+ EMOJI_PATHNAME = Pathname.new(Gemojione.index.images_path).freeze
+
# Extract the path string that Gollum::Wiki expects
def extract_path(file_path)
return nil if file_path.nil?
@@ -51,5 +56,13 @@ module Precious
return mustache :error
end
+ def emoji(name)
+ if emoji = Gemojione.index.find_by_name(name)
+ IO.read(EMOJI_PATHNAME.join("#{emoji['unicode']}.png"))
+ else
+ fail ArgumentError, "emoji `#{name}' not found"
+ end
+ end
+
end
end
diff --git a/lib/gollum/public/gollum/css/_styles.css b/lib/gollum/public/gollum/css/_styles.css
index c058fa2b..a9d79f56 100644
--- a/lib/gollum/public/gollum/css/_styles.css
+++ b/lib/gollum/public/gollum/css/_styles.css
@@ -85,6 +85,22 @@ ol.tree
margin-right: 7px;
vertical-align: text-top;
}
+ li.file form
+ {
+ vertical-align:middle;
+ display: inline-block;
+ }
+ li.file form button
+ {
+ vertical-align:middle;
+ height: 20px;
+ padding-left: 36px;
+ padding-right: 10px;
+ border: 0px solid #000000;
+ background: url("../images/fileview/trashcan.png") no-repeat 16px center;
+ cursor: pointer;
+ }
+ }
li.file a[href *= '.pdf'] span.icon { background: url(../images/fileview/document.png) 0 0 no-repeat; }
li.file a[href *= '.html'] span.icon { background: url(../images/fileview/document.png) 0 0 no-repeat; }
li.file a[href $= '.css'] span.icon { background: url(../images/fileview/document.png) 0 0 no-repeat; }
@@ -125,4 +141,3 @@ ol.tree
}
li input:checked + ol > li { display: block; margin: 0 0 0.125em; /* 2px */}
li input:checked + ol > li:last-child { margin: 0 0 0.063em; /* 1px */ }
-
diff --git a/lib/gollum/public/gollum/css/gollum.css b/lib/gollum/public/gollum/css/gollum.css
index cd577b78..de90e47d 100755
--- a/lib/gollum/public/gollum/css/gollum.css
+++ b/lib/gollum/public/gollum/css/gollum.css
@@ -849,3 +849,9 @@ ul.actions {
.clearfloats {
clear: both;
}
+
+.emoji {
+ width: 20px;
+ height: 20px;
+ vertical-align: -18%;
+}
diff --git a/lib/gollum/public/gollum/images/fileview/trashcan.png b/lib/gollum/public/gollum/images/fileview/trashcan.png
new file mode 100644
index 00000000..1749e6e2
Binary files /dev/null and b/lib/gollum/public/gollum/images/fileview/trashcan.png differ
diff --git a/lib/gollum/public/gollum/javascript/editor/langs/markdown.js b/lib/gollum/public/gollum/javascript/editor/langs/markdown.js
index 851b7381..b1f917eb 100644
--- a/lib/gollum/public/gollum/javascript/editor/langs/markdown.js
+++ b/lib/gollum/public/gollum/javascript/editor/langs/markdown.js
@@ -211,6 +211,11 @@ var MarkDownHelp = [
{
menuName: 'Escaping',
data: 'If you want to use a special Markdown character in your document (such as displaying literal asterisks), you can escape the character with the backslash (\\). Markdown will ignore the character directly after a backslash.'
+ },
+
+ {
+ menuName: 'Emoji',
+ data: '
See the EmojiOne demo for all available emoji. To include one, wrap the emoji name in colons and use underscores instead of spaces (e.g. :heart: or :point_up:).'
}
]
}
diff --git a/lib/gollum/views/layout.rb b/lib/gollum/views/layout.rb
index d6de7393..e2d14166 100644
--- a/lib/gollum/views/layout.rb
+++ b/lib/gollum/views/layout.rb
@@ -29,7 +29,7 @@ module Precious
end
def custom_path
- "#{@base_url}#{@page_dir.nil? ? '' : '/'}#{@page_dir}"
+ "#{@base_url}#{@page_dir.empty? ? '' : '/'}#{@page_dir}"
end
def css # custom css
diff --git a/lib/gollum/views/page.rb b/lib/gollum/views/page.rb
index 6f635d17..e903f734 100644
--- a/lib/gollum/views/page.rb
+++ b/lib/gollum/views/page.rb
@@ -22,15 +22,13 @@ module Precious
end
def author
- page_versions = @page.versions
- first = page_versions ? page_versions.first : false
+ first = page.last_version
return DEFAULT_AUTHOR unless first
first.author.name.respond_to?(:force_encoding) ? first.author.name.force_encoding('UTF-8') : first.author.name
end
def date
- page_versions = @page.versions
- first = page_versions ? page_versions.first : false
+ first = page.last_version
return Time.now.strftime(DATE_FORMAT) unless first
first.authored_date.strftime(DATE_FORMAT)
end
diff --git a/test/test_app.rb b/test/test_app.rb
index 454d4de3..32ba29ea 100644
--- a/test/test_app.rb
+++ b/test/test_app.rb
@@ -513,10 +513,23 @@ context "Frontend" do
{ :name => 'user1', :email => 'user1' });
get page
- assert_match /custom.js/, last_response.body
+ assert_match /"\/custom.js"/, last_response.body
Precious::App.set(:wiki_options, { :js => nil })
end
+ test "change custom.css path if page-file-dir is set" do
+ Precious::App.set(:wiki_options, { :css => true, :page_file_dir => 'docs'})
+ page = 'docs/yaycustom'
+ text = 'customized!'
+
+ @wiki.write_page(page, :markdown, text,
+ { :name => 'user1', :email => 'user1' });
+
+ get page
+ assert_match /"\/docs\/custom.css"/, last_response.body
+ Precious::App.set(:wiki_options, { :css => nil, :page_file_dir => nil })
+ end
+
test "show edit page with header and footer and sidebar of multibyte" do
post "/create",
:content => 'りんご',
@@ -694,6 +707,18 @@ context "Frontend with lotr" do
assert_match /not so big smelly creatures/, last_response.body
end
+ test "existing emoji" do
+ get "/emoji/heart"
+ assert_equal 200, last_response.status
+ assert_equal 'image/png', last_response.headers['Content-Type']
+ assert_equal [137, 80, 78, 71, 13, 10, 26, 10], last_response.body.each_byte.to_a[0..7]
+ end
+
+ test "missing emoji" do
+ get "/emoji/oggy_was_here"
+ assert_equal 404, last_response.status
+ end
+
def app
Precious::App
end