Merge branch 'rc'
This commit is contained in:
+14
@@ -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`
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 ®, <code>(C)</code> becomes © and <code>(TM)</code> becomes ™.</p>'
|
||||
data: '<p>AsciiDoc will automatically convert textual representations of commonly-used special characters. For example, <code>(R)</code> becomes ®, <code>(C)</code> becomes © and <code>(TM)</code> becomes ™.</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 ));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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>
|
||||
{{message}}
|
||||
[{{id7}}]
|
||||
{{#files}}
|
||||
<br>
|
||||
<a href="{{link}}">{{file}}</a>
|
||||
{{/files}}
|
||||
</td>
|
||||
</tr>
|
||||
{{/versions}}
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</fieldset>
|
||||
</div>
|
||||
<div id="footer">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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}"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user