Compare commits
229 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| df75d2d60c | |||
| 2713aabeaf | |||
| 796d1b44c2 | |||
| 470a7b8f52 | |||
| f699b82a9f | |||
| 44edb8c7da | |||
| bc4fc0edd9 | |||
| 6545fa691b | |||
| 4954553927 | |||
| 9c50ba9eeb | |||
| 9a67da145a | |||
| ca7d82278c | |||
| f6245c53dd | |||
| 6888420cc6 | |||
| c5631f5b7d | |||
| 34e0b49d72 | |||
| bd072264ef | |||
| cfb2d24c71 | |||
| fe0eb72fa3 | |||
| 2783257f06 | |||
| cc11cb866c | |||
| 6a02643bda | |||
| 7f269c8da3 | |||
| ef7f7cebd1 | |||
| 05c24fd5e3 | |||
| b08b97bd28 | |||
| dbb6ce2f71 | |||
| f66f14b593 | |||
| 8a52315dee | |||
| 7c4052906c | |||
| 3a56f39f6a | |||
| 6585ca5dd0 | |||
| 792abae07e | |||
| 74ce648c59 | |||
| 2686e96046 | |||
| 213e2bb432 | |||
| 79bb5c10ab | |||
| 7ea012d786 | |||
| 43591f75de | |||
| 05d82c0569 | |||
| 76c8d3206c | |||
| 00751d05b4 | |||
| b5be5df11a | |||
| 7d159273fc | |||
| 70127922ab | |||
| b95df93775 | |||
| dc06edcf5b | |||
| fdc437dcd5 | |||
| f6873c9612 | |||
| 93754ab32d | |||
| 5759334635 | |||
| f2f543b72d | |||
| 598b052be3 | |||
| a746062422 | |||
| c8868d369f | |||
| 52c6e7474c | |||
| be81f09b0e | |||
| 6fa4504e31 | |||
| 992ba01a12 | |||
| 72c5a74cf1 | |||
| 919f41a0f1 | |||
| 785921cb0f | |||
| 8c8cda5e7d | |||
| 64ef74e7e9 | |||
| 776df4e6ee | |||
| 68465a8651 | |||
| fa16c8960c | |||
| 2c57915781 | |||
| d0527f1aeb | |||
| 75083c5b56 | |||
| 82526594db | |||
| 941d39800c | |||
| a1ae2e8bc0 | |||
| 4af6f366ca | |||
| c7a9534ed9 | |||
| 00bcbbf72b | |||
| ed2254ff9f | |||
| b6633f0ecb | |||
| e08d2d3052 | |||
| fbc0548b43 | |||
| a9807bd1e1 | |||
| 554b80b39d | |||
| 99e74bf00b | |||
| f48e923f28 | |||
| 5400b4bfdd | |||
| f68bebe0f6 | |||
| 4c6019b439 | |||
| 66e08a6b17 | |||
| 7898db70ed | |||
| 7c357116ff | |||
| 69ce0eb0d0 | |||
| 4db31a297b | |||
| e1fca457e4 | |||
| 7f8485ce80 | |||
| 290061fd11 | |||
| a507836936 | |||
| 6524d20a96 | |||
| f1c523aa30 | |||
| 87c08f5613 | |||
| 82913cea20 | |||
| 2ad743e4bd | |||
| fa97b57a96 | |||
| 1b952b6d56 | |||
| 90cc512bd1 | |||
| b82556c9c0 | |||
| fbe3b4bb3b | |||
| 5ffd98ad31 | |||
| cb9dd4d228 | |||
| cd823bf10c | |||
| 5560ec52c2 | |||
| 065151a77f | |||
| 23454f556c | |||
| a2b3ddf931 | |||
| 44b0d2fcfc | |||
| aed4cc590a | |||
| 72ee08b5ab | |||
| 45547624e4 | |||
| f928cfa8be | |||
| 988984846a | |||
| 1149618653 | |||
| 168a033903 | |||
| 6a765c9791 | |||
| e16ae7b511 | |||
| 174334ea44 | |||
| dbdf06930d | |||
| c93e65ddc3 | |||
| 56101ed264 | |||
| 8269c8e574 | |||
| 2246419d1e | |||
| 118a0c318b | |||
| 5401cf2910 | |||
| 432f9b8d2f | |||
| 66fc8a2d31 | |||
| 2f3dd3d227 | |||
| c43fd9fa6c | |||
| 868518e0f5 | |||
| 039b5cce98 | |||
| 4a421842d5 | |||
| cfbb124f81 | |||
| dcb147cde2 | |||
| 8d06b5e67e | |||
| 4776d0b422 | |||
| 58bb340c33 | |||
| ee790a9b7c | |||
| ac432aad78 | |||
| 30207e0a39 | |||
| d98547a33c | |||
| b7cdeabbf6 | |||
| be9907a0cc | |||
| 30f42c50a9 | |||
| 7cba65b138 | |||
| f34a78b336 | |||
| e1942dda03 | |||
| 7142e284fa | |||
| 3c1c588953 | |||
| 52cc6bae34 | |||
| 955c608115 | |||
| 2e00cf312c | |||
| 09bbc144d1 | |||
| d02b63a434 | |||
| 9b63c67d8c | |||
| 05c4bf3374 | |||
| 424b4d3f4e | |||
| f9a6187fab | |||
| d406472882 | |||
| 749b5a5ff8 | |||
| 091d5fe750 | |||
| c8894fb465 | |||
| 2dd41cbfac | |||
| 1f2165e68b | |||
| e9b6bdbdd7 | |||
| c0c77c5ba7 | |||
| 12403172ac | |||
| 3b41ab8d75 | |||
| 7bcf35f5b1 | |||
| 9a7e1c94c7 | |||
| 30c2e675da | |||
| ac405803e8 | |||
| 7dee787a92 | |||
| ae4b1cdeca | |||
| 572982cbf9 | |||
| 74290874f9 | |||
| 847f08d952 | |||
| 0bcd616668 | |||
| 9dd701ccc4 | |||
| 56a5a7d92b | |||
| 0cf0fad50e | |||
| 5f9e91656e | |||
| a7a2479f85 | |||
| a8b230a490 | |||
| 041b01f171 | |||
| 1c475f3215 | |||
| ab699d94b0 | |||
| 942d32c9b6 | |||
| 97f15f0b18 | |||
| ed49358c50 | |||
| 85eeecd140 | |||
| 30fd40fbe5 | |||
| 2ed262cacd | |||
| 29a1ef8f8a | |||
| 772d18ee62 | |||
| dd604d9942 | |||
| 85abc83427 | |||
| 6d8220629c | |||
| 6ff7ada096 | |||
| 8575049de5 | |||
| bb6fb0c253 | |||
| eb2ad9f840 | |||
| d0dd23fc11 | |||
| 7ae4acbdb0 | |||
| 881590ab37 | |||
| 5e479dc5d9 | |||
| 7db9c2e762 | |||
| ce6b0ac095 | |||
| 420bb06988 | |||
| 20566f8acf | |||
| 1d5f69704a | |||
| 0da664299e | |||
| 6e8fb2b457 | |||
| d1c72a4ff3 | |||
| 0bf05392e4 | |||
| 7ecef0c045 | |||
| 33ca329253 | |||
| 01fa4770cb | |||
| b76257c49c | |||
| e2fbf22f38 | |||
| 134432d029 | |||
| 8d4d6e80b8 | |||
| 3767a11d21 |
@@ -0,0 +1,25 @@
|
||||
# https://help.github.com/articles/dealing-with-line-endings
|
||||
# Set default behaviour, in case users don't have core.autocrlf set.
|
||||
* text=auto
|
||||
|
||||
# Explicitly declare text files we want to always be normalized and converted
|
||||
# to native line endings on checkout.
|
||||
*.txt text
|
||||
*.md text
|
||||
*.rb text
|
||||
*.js text
|
||||
*.html text
|
||||
*.yml text
|
||||
*.mustache text
|
||||
*.css text
|
||||
Rakefile text
|
||||
Gemfile text
|
||||
LICENSE text
|
||||
COPYRIGHT text
|
||||
gollum text
|
||||
.gitattributes text
|
||||
.gitignore text
|
||||
|
||||
# Denote all files that are truly binary and should not be modified.
|
||||
*.png binary
|
||||
*.jpg binary
|
||||
@@ -4,3 +4,4 @@ pkg
|
||||
.bundle
|
||||
Gemfile.lock
|
||||
*.gem
|
||||
*.swp
|
||||
|
||||
+2
-2
@@ -4,5 +4,5 @@ rvm:
|
||||
notifications:
|
||||
disabled: true
|
||||
before_install:
|
||||
- gem uninstall ffi -a
|
||||
- sudo apt-get install -y asciidoc
|
||||
- sudo apt-get update
|
||||
- sudo apt-get install -y --force-yes asciidoc
|
||||
@@ -1,4 +1,4 @@
|
||||
source "http://rubygems.org"
|
||||
source 'http://rubygems.org'
|
||||
|
||||
gemspec
|
||||
gem "rake", "~> 0.9.2"
|
||||
gem 'rake', '~> 0.9'
|
||||
@@ -2,6 +2,7 @@ gollum -- A wiki built on top of Git
|
||||
====================================
|
||||
|
||||
[](http://travis-ci.org/github/gollum)
|
||||
[](https://gemnasium.com/github/gollum)
|
||||
|
||||
## DESCRIPTION
|
||||
|
||||
@@ -18,6 +19,11 @@ number of ways depending on your needs. You can edit your wiki locally:
|
||||
Gollum follows the rules of [Semantic Versioning](http://semver.org/) and uses
|
||||
[TomDoc](http://tomdoc.org/) for inline documentation.
|
||||
|
||||
## SYSTEM REQUIREMENTS
|
||||
- Python 2.5+ (2.7.3 recommended)
|
||||
- Ruby 1.8.7+ (1.9.3 recommended)
|
||||
- Unix like operating system (OS X, Ubuntu, Debian, and more)
|
||||
- Will not work on Windows (because of [grit](https://github.com/github/grit))
|
||||
|
||||
## INSTALLATION
|
||||
|
||||
@@ -130,7 +136,13 @@ or JavaScript. These tags will be stripped from the converted HTML. See
|
||||
`docs/sanitization.md` for more details on what tags and attributes are
|
||||
allowed.
|
||||
|
||||
## TITLES
|
||||
|
||||
The first defined `h1` will override the default header on a page. There are two ways to set a page title. The metadata syntax:
|
||||
|
||||
`<!-- --- title: New Title -->`
|
||||
|
||||
The first `h1` tag can be set to always override the page title, without needing to use the metadata syntax. Start gollum with the `--h1-title` flag.
|
||||
## BRACKET TAGS
|
||||
|
||||
A variety of Gollum tags use a double bracket syntax. For example:
|
||||
@@ -295,7 +307,7 @@ This is useful for writing about the link syntax in your wiki pages.
|
||||
|
||||
Gollum has a special tag to insert a table of contents (new in v2.1)
|
||||
|
||||
'[[_TOC_]]
|
||||
[[_TOC_]]
|
||||
|
||||
This tag is case sensitive, use all upper case. The TOC tag can be inserted
|
||||
into the `_Header`, `_Footer` or `_Sidebar` files too.
|
||||
@@ -334,27 +346,40 @@ then that whitespace will be ignored (this makes the blocks easier to read in pl
|
||||
The block must end with three backticks indented at the same level than the opening
|
||||
backticks.
|
||||
|
||||
### GITHUB SYNTAX HIGHLIGHTING
|
||||
|
||||
As an extra feature, you can syntax highlight a file from your repository, allowing
|
||||
you keep some of your sample code in the main repository. The code-snippet is
|
||||
updated when the wiki is rebuilt. You include github code like this:
|
||||
|
||||
```html:github/gollum/master/test/file_view/1_file.txt```
|
||||
|
||||
This will make the builder look at the **github user**, in the **gollum project**,
|
||||
in the **master branch**, at path **test/file_view/1_file.txt**. It will be
|
||||
rewritten to:
|
||||
|
||||
```html
|
||||
<ol class="tree">
|
||||
<li class="file"><a href="0">0</a></li>
|
||||
</ol>
|
||||
```
|
||||
|
||||
Which will be parsed as HTML code during the Pygments run, and thereby coloured
|
||||
appropriately.
|
||||
|
||||
## MATHEMATICAL EQUATIONS
|
||||
|
||||
Start gollum with the `--mathjax` flag. Read more about [MathJax](http://docs.mathjax.org/en/latest/index.html) on the web. Gollum uses the `TeX-AMS-MML_HTMLorMML` config with the `autoload-all` extension.
|
||||
|
||||
Page files may contain mathematic equations in TeX syntax that will be nicely
|
||||
typeset into the expected output. A block-style equation is delimited by `\[`
|
||||
and `\]`. For example:
|
||||
Inline math:
|
||||
|
||||
\[ P(E) = {n \choose k} p^k (1-p)^{ n-k} \]
|
||||
- $2^2$
|
||||
- `\\(2^2\\)`
|
||||
|
||||
Inline equations are delimited by `\(` and `\)`. These equations will appear
|
||||
inline with regular text. For example:
|
||||
Display math:
|
||||
|
||||
The Pythagorean theorem is \( a^2 + b^2 = c^2 \).
|
||||
|
||||
### INSTALLATION REQUIREMENTS
|
||||
|
||||
In order to get the mathematical equations rendering to work, you need the following binaries:
|
||||
|
||||
* LaTex, TeTex or MacTex/BasicTeX (pdflatex)
|
||||
* Netpbm (pnmcrop, pnmpad, pnmscale, ppmtopgm, pnmgamma, pnmtopng)
|
||||
* Ghostscript (gs)
|
||||
- $$2^2$$
|
||||
- [2^2]
|
||||
|
||||
## SEQUENCE DIAGRAMS
|
||||
|
||||
@@ -362,10 +387,10 @@ You may imbed sequence diagrams into your wiki page (rendered by
|
||||
[WebSequenceDiagrams](http://www.websequencediagrams.com) by using the
|
||||
following syntax:
|
||||
|
||||
{{{ blue-modern
|
||||
{{{{{{ blue-modern
|
||||
alice->bob: Test
|
||||
bob->alice: Test response
|
||||
}}}
|
||||
}}}}}}
|
||||
|
||||
You can replace the string "blue-modern" with any supported style.
|
||||
|
||||
@@ -392,6 +417,17 @@ By default, internal wiki links are all absolute from the root. To specify a dif
|
||||
|
||||
wiki = Gollum::Wiki.new("my-gollum-repo.git", :base_path => "/wiki")
|
||||
|
||||
Note that base_path just modifies the links. To map gollum to a non-root location:
|
||||
|
||||
- Use the gollum binary: `gollum path/to/wiki --base-path mywiki`
|
||||
- Define config.ru with `map`. See [#532](https://github.com/github/gollum/issues/532) for an example.
|
||||
|
||||
> :base_path - String base path for all Wiki links.
|
||||
>
|
||||
> The String base path to prefix to internal links. For example, when set
|
||||
> to "/wiki", the page "Hobbit" will be linked as "/wiki/Hobbit". Defaults
|
||||
> to "/".
|
||||
|
||||
Get the latest version of the given human or canonical page name:
|
||||
|
||||
page = wiki.page('page-name')
|
||||
@@ -497,9 +533,23 @@ like Rack::Auth, OmniAuth, etc.
|
||||
Precious::App.set(:wiki_options, {:universal_toc => false})
|
||||
run Precious::App
|
||||
|
||||
## Windows Filename Validation
|
||||
Your Rack middleware can pass author details to Gollum in a Hash in the session under the 'gollum.author' key.
|
||||
|
||||
## WINDOWS FILENAME VALIDATION
|
||||
Note that filenames on windows must not contain any of the following characters `\ / : * ? " < > |`. See [this support article](http://support.microsoft.com/kb/177506) for details.
|
||||
|
||||
## CONFIG FILE
|
||||
|
||||
Gollum optionally takes a `--config file`. See [config.rb](https://github.com/github/gollum/blob/master/config.rb) for an example.
|
||||
|
||||
## CUSTOM CSS
|
||||
|
||||
The `--css` flag will inject `custom.css` from the root of your git repository into each page. `custom.css` must be commited to git or you will get a 302 redirect to the create page. Here's an example of floating the sidebar to the left.
|
||||
|
||||
```css
|
||||
#wiki-rightbar { float: left !important; }
|
||||
```
|
||||
|
||||
## CONTRIBUTE
|
||||
|
||||
If you'd like to hack on Gollum, start by forking my repo on GitHub:
|
||||
@@ -520,16 +570,20 @@ your changes merged back into core is as follows:
|
||||
1. Send a pull request to the github/gollum project.
|
||||
|
||||
## RELEASING
|
||||
x.y.z
|
||||
|
||||
For z releases:
|
||||
$ rake bump
|
||||
$ rake release
|
||||
|
||||
For x.y releases:
|
||||
Update VERSION in lib/gollum.rb
|
||||
$ rake gemspec
|
||||
$ git tag vX.Y.Z
|
||||
$ git push origin vX.Y.Z
|
||||
$ gem build gollum.gemspec
|
||||
$ gem push gollum-X.Y.Z.gem
|
||||
$ rake release
|
||||
|
||||
## BUILDING THE GEM FROM MASTER
|
||||
$ gem uninstall -aix gollum
|
||||
$ gem uninstall -aIx gollum
|
||||
$ git clone https://github.com/github/gollum.git
|
||||
$ cd gollum
|
||||
gollum$ rake build
|
||||
gollum$ gem install pkg/gollum*.gem
|
||||
gollum$ gem install --no-ri --no-rdoc pkg/gollum*.gem
|
||||
|
||||
@@ -17,6 +17,27 @@ def version
|
||||
line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1]
|
||||
end
|
||||
|
||||
# assumes x.y.z all digit version
|
||||
def next_version
|
||||
# x.y.z
|
||||
v = version.split '.'
|
||||
# bump z
|
||||
v[-1] = v[-1].to_i + 1
|
||||
v.join '.'
|
||||
end
|
||||
|
||||
def bump_version
|
||||
old_file = File.read("lib/#{name}.rb")
|
||||
old_version_line = old_file[/^\s*VERSION\s*=\s*.*/]
|
||||
new_version = next_version
|
||||
# replace first match of old vesion with new version
|
||||
old_file.sub!(old_version_line, " VERSION = '#{new_version}'")
|
||||
|
||||
File.write("lib/#{name}.rb", old_file)
|
||||
|
||||
new_version
|
||||
end
|
||||
|
||||
def date
|
||||
Date.today.to_s
|
||||
end
|
||||
@@ -71,7 +92,14 @@ end
|
||||
#
|
||||
#############################################################################
|
||||
|
||||
|
||||
desc "Update version number and gemspec"
|
||||
task :bump do
|
||||
puts "Updated version to #{bump_version}"
|
||||
# Execute does not invoke dependencies.
|
||||
# Manually invoke gemspec then validate.
|
||||
Rake::Task[:gemspec].execute
|
||||
Rake::Task[:validate].execute
|
||||
end
|
||||
|
||||
#############################################################################
|
||||
#
|
||||
@@ -86,6 +114,7 @@ task :release => :build do
|
||||
exit!
|
||||
end
|
||||
sh "git commit --allow-empty -a -m 'Release #{version}'"
|
||||
sh "git pull"
|
||||
sh "git tag v#{version}"
|
||||
sh "git push origin master"
|
||||
sh "git push origin v#{version}"
|
||||
@@ -117,7 +146,7 @@ task :gemspec => :validate do
|
||||
split("\n").
|
||||
sort.
|
||||
reject { |file| file =~ /^\./ }.
|
||||
reject { |file| file =~ /^(rdoc|pkg)/ }.
|
||||
reject { |file| file =~ /^(rdoc|pkg|test|Home\.md|\.gitattributes)/ }.
|
||||
map { |file| " #{file}" }.
|
||||
join("\n")
|
||||
|
||||
@@ -139,4 +168,4 @@ task :validate do
|
||||
puts "A `VERSION` file at root level violates Gem best practices."
|
||||
exit!
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
+43
-2
@@ -45,6 +45,10 @@ opts = OptionParser.new do |opts|
|
||||
options['irb'] = true
|
||||
end
|
||||
|
||||
opts.on("--css", "Inject custom css. Uses custom.css from root repository") do
|
||||
wiki_options[:css] = true
|
||||
end
|
||||
|
||||
opts.on("--page-file-dir [PATH]", "Specify the sub directory for all page files (default: repository root).") do |path|
|
||||
wiki_options[:page_file_dir] = path
|
||||
end
|
||||
@@ -66,7 +70,18 @@ opts = OptionParser.new do |opts|
|
||||
end
|
||||
|
||||
opts.on("--mathjax", "Enables mathjax.") do
|
||||
options['mathjax'] = true
|
||||
wiki_options[:mathjax] = true
|
||||
end
|
||||
|
||||
opts.on("--show-all", "Shows all files in file view. By default only valid pages are shown.") do
|
||||
wiki_options[:show_all] = true
|
||||
end
|
||||
|
||||
opts.on("--collapse-tree", "Collapse file view tree. By default, expanded tree is shown.") do
|
||||
wiki_options[:collapse_tree] = true
|
||||
end
|
||||
opts.on("--h1-title", "Sets page title to value of first h1") do
|
||||
wiki_options[:h1_title] = true
|
||||
end
|
||||
end
|
||||
|
||||
@@ -141,5 +156,31 @@ else
|
||||
require cfg
|
||||
end
|
||||
|
||||
Precious::App.run!(options)
|
||||
base_path = wiki_options[:base_path]
|
||||
|
||||
if wiki_options[:base_path].nil?
|
||||
Precious::App.run!(options)
|
||||
else
|
||||
require 'rack'
|
||||
|
||||
class MapGollum
|
||||
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
|
||||
end
|
||||
end
|
||||
|
||||
def call(env)
|
||||
@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']).start
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
# 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" }
|
||||
=end
|
||||
+27
-170
@@ -5,8 +5,8 @@ Gem::Specification.new do |s|
|
||||
s.required_ruby_version = ">= 1.8.7"
|
||||
|
||||
s.name = 'gollum'
|
||||
s.version = '2.1.5'
|
||||
s.date = '2012-08-22'
|
||||
s.version = '2.4.0'
|
||||
s.date = '2012-11-11'
|
||||
s.rubyforge_project = 'gollum'
|
||||
|
||||
s.summary = "A simple, Git-powered wiki."
|
||||
@@ -23,35 +23,37 @@ Gem::Specification.new do |s|
|
||||
s.rdoc_options = ["--charset=UTF-8"]
|
||||
s.extra_rdoc_files = %w[README.md LICENSE]
|
||||
|
||||
s.add_dependency('grit', "~> 2.5.0")
|
||||
s.add_dependency('github-markup', [">= 0.7.0", "< 1.0.0"])
|
||||
s.add_dependency('github-markdown')
|
||||
s.add_dependency('pygments.rb', "~> 0.2.0")
|
||||
s.add_dependency('posix-spawn', "~> 0.3.0")
|
||||
s.add_dependency('sinatra', "~> 1.0")
|
||||
s.add_dependency('mustache', [">= 0.11.2", "< 1.0.0"])
|
||||
s.add_dependency('sanitize', "~> 2.0.0")
|
||||
s.add_dependency('nokogiri', "~> 1.4")
|
||||
s.add_dependency('useragent', "~> 0.4.9")
|
||||
s.add_dependency('stringex', "~> 1.4.0")
|
||||
s.add_dependency('grit', '~> 2.5.0')
|
||||
s.add_dependency('github-markup', ['>= 0.7.4', '< 1.0.0'])
|
||||
s.add_dependency('github-markdown', '~> 0.5.1')
|
||||
s.add_dependency('pygments.rb', '~> 0.3.2')
|
||||
s.add_dependency('sinatra', '~> 1.3.3')
|
||||
s.add_dependency('mustache', ['>= 0.99.4', '< 1.0.0'])
|
||||
s.add_dependency('sanitize', '~> 2.0.3')
|
||||
s.add_dependency('nokogiri', '~> 1.5.5')
|
||||
s.add_dependency('useragent', '~> 0.4.12')
|
||||
s.add_dependency('stringex', '~> 1.4.0')
|
||||
|
||||
s.add_development_dependency('RedCloth')
|
||||
s.add_development_dependency('mocha')
|
||||
s.add_development_dependency('org-ruby', '~> 0.7.0')
|
||||
s.add_development_dependency('shoulda')
|
||||
s.add_development_dependency('rack-test')
|
||||
s.add_development_dependency('wikicloth', '~>0.8.0')
|
||||
s.add_development_dependency('rake', '~> 0.9.2')
|
||||
s.add_development_dependency('RedCloth', '~> 4.2.9')
|
||||
s.add_development_dependency('mocha', '~> 0.12.7')
|
||||
s.add_development_dependency('org-ruby', '~> 0.7.2')
|
||||
s.add_development_dependency('shoulda', '~> 3.3.1')
|
||||
s.add_development_dependency('rack-test', '~> 0.6.2')
|
||||
s.add_development_dependency('wikicloth', '~> 0.8.0')
|
||||
s.add_development_dependency('rake', '~> 0.9')
|
||||
s.add_development_dependency('pry', '~> 0.9.10')
|
||||
# required by pry
|
||||
s.add_development_dependency('rb-readline', '~> 0.4.2')
|
||||
|
||||
# = MANIFEST =
|
||||
s.files = %w[
|
||||
Gemfile
|
||||
HISTORY.md
|
||||
Home.md
|
||||
LICENSE
|
||||
README.md
|
||||
Rakefile
|
||||
bin/gollum
|
||||
config.rb
|
||||
docs/sanitization.md
|
||||
gollum.gemspec
|
||||
lib/gollum.rb
|
||||
@@ -94,6 +96,7 @@ Gem::Specification.new do |s|
|
||||
lib/gollum/frontend/public/gollum/javascript/mousetrap.min.js
|
||||
lib/gollum/frontend/public/gollum/livepreview/css/custom.css
|
||||
lib/gollum/frontend/public/gollum/livepreview/images/cancel_24.png
|
||||
lib/gollum/frontend/public/gollum/livepreview/images/globe_24.png
|
||||
lib/gollum/frontend/public/gollum/livepreview/images/lr_24.png
|
||||
lib/gollum/frontend/public/gollum/livepreview/images/save_24.png
|
||||
lib/gollum/frontend/public/gollum/livepreview/images/savecomment_24.png
|
||||
@@ -426,6 +429,7 @@ Gem::Specification.new do |s|
|
||||
lib/gollum/frontend/public/gollum/livepreview/licenses/retina_display_icon_set/by_sa_3.0_unported_legalcode.txt
|
||||
lib/gollum/frontend/public/gollum/livepreview/licenses/sizzle/LICENSE.txt
|
||||
lib/gollum/frontend/public/gollum/livepreview/licenses/sundown/sundown.txt
|
||||
lib/gollum/frontend/public/gollum/livepreview/licenses/templarian_windowsicons/license.txt
|
||||
lib/gollum/frontend/public/gollum/livepreview/readme.md
|
||||
lib/gollum/frontend/templates/compare.mustache
|
||||
lib/gollum/frontend/templates/create.mustache
|
||||
@@ -453,165 +457,18 @@ Gem::Specification.new do |s|
|
||||
lib/gollum/frontend/views/pages.rb
|
||||
lib/gollum/frontend/views/search.rb
|
||||
lib/gollum/git_access.rb
|
||||
lib/gollum/gitcode.rb
|
||||
lib/gollum/markup.rb
|
||||
lib/gollum/page.rb
|
||||
lib/gollum/pagination.rb
|
||||
lib/gollum/sanitization.rb
|
||||
lib/gollum/tex.rb
|
||||
lib/gollum/web_sequence_diagram.rb
|
||||
lib/gollum/wiki.rb
|
||||
licenses/css_tree_menu_thecssninja/license.txt
|
||||
licenses/licenses.txt
|
||||
licenses/unity_asset_pool/COPYRIGHT
|
||||
templates/formatting.html
|
||||
test/examples/empty.git/HEAD
|
||||
test/examples/empty.git/config
|
||||
test/examples/empty.git/description
|
||||
test/examples/empty.git/hooks/applypatch-msg.sample
|
||||
test/examples/empty.git/hooks/commit-msg.sample
|
||||
test/examples/empty.git/hooks/post-commit.sample
|
||||
test/examples/empty.git/hooks/post-receive.sample
|
||||
test/examples/empty.git/hooks/post-update.sample
|
||||
test/examples/empty.git/hooks/pre-applypatch.sample
|
||||
test/examples/empty.git/hooks/pre-commit.sample
|
||||
test/examples/empty.git/hooks/pre-rebase.sample
|
||||
test/examples/empty.git/hooks/prepare-commit-msg.sample
|
||||
test/examples/empty.git/hooks/update.sample
|
||||
test/examples/empty.git/info/exclude
|
||||
test/examples/empty.git/objects/info/.gitkeep
|
||||
test/examples/empty.git/objects/pack/.gitkeep
|
||||
test/examples/empty.git/refs/heads/.gitkeep
|
||||
test/examples/lotr.git/COMMIT_EDITMSG
|
||||
test/examples/lotr.git/HEAD
|
||||
test/examples/lotr.git/ORIG_HEAD
|
||||
test/examples/lotr.git/config
|
||||
test/examples/lotr.git/description
|
||||
test/examples/lotr.git/index
|
||||
test/examples/lotr.git/info/exclude
|
||||
test/examples/lotr.git/logs/HEAD
|
||||
test/examples/lotr.git/logs/refs/heads/master
|
||||
test/examples/lotr.git/objects/06/131480411710c92a82fe2d1e76932c70feb2e5
|
||||
test/examples/lotr.git/objects/0a/de1e2916346d4c1f2fb63b863fd3c16808fe44
|
||||
test/examples/lotr.git/objects/0d/c9016ca928c78d5421a99a53b379b53929221e
|
||||
test/examples/lotr.git/objects/0e/d8cbe0a25235bd867e65193c7d837c66b328ef
|
||||
test/examples/lotr.git/objects/12/629d666c5e3178f82f533f543d61b53dc78c0b
|
||||
test/examples/lotr.git/objects/1c/79ddc69707f7b164bc2ea58beb5d8965ff6bd0
|
||||
test/examples/lotr.git/objects/1d/b89ebba7e2c14d93b94ff98cfa3708a4f0d4e3
|
||||
test/examples/lotr.git/objects/24/49c2681badfd3c189e8ed658dacffe8ba48fe5
|
||||
test/examples/lotr.git/objects/25/4bdc1ba27d8b8a794538a8522d9a2b56ec2dd9
|
||||
test/examples/lotr.git/objects/27/680b0fce1abfbc528e7aa53d92645852d52eb6
|
||||
test/examples/lotr.git/objects/2c/b9156ad383914561a8502fc70f5a1d887e48ad
|
||||
test/examples/lotr.git/objects/45/3b250f979c7bd6dfb62640c944c982ae6721ee
|
||||
test/examples/lotr.git/objects/45/f319ee12f2b551b901b22e72602963c366fff1
|
||||
test/examples/lotr.git/objects/46/a697caf435815bb07bbce947fc2d58be15f087
|
||||
test/examples/lotr.git/objects/4c/45c2b4e297a726c3d3f66886f35373e48fe1c5
|
||||
test/examples/lotr.git/objects/4e/023f460ce466e154ca09d8774c79ad5a53fc15
|
||||
test/examples/lotr.git/objects/5d/cac289a8603188d2c5caf481dcba2985126aaa
|
||||
test/examples/lotr.git/objects/60/f12f4254f58801b9ee7db7bca5fa8aeefaa56b
|
||||
test/examples/lotr.git/objects/62/9aa678272b017a4d136d35e77ac94d80b08dc2
|
||||
test/examples/lotr.git/objects/6e/48abfc56565574859e081ee58eae655d48cf71
|
||||
test/examples/lotr.git/objects/71/4323c104239440a5c66ab12a67ed07a83c404f
|
||||
test/examples/lotr.git/objects/7b/60c5a20a501a70f2317fa0ef763e1e2ce22d6b
|
||||
test/examples/lotr.git/objects/7d/981cd984ad589e3cf00d8122170c6f7d685979
|
||||
test/examples/lotr.git/objects/84/0ec5b1ba1320e8ec443f28f99566f615d5af10
|
||||
test/examples/lotr.git/objects/93/6b83ee0dd8837adb82511e40d5e4ebe59bb675
|
||||
test/examples/lotr.git/objects/94/523d7ae48aeba575099dd12926420d8fd0425d
|
||||
test/examples/lotr.git/objects/94/9a9cc3119b9c98817f375e976d2bb5e2a42809
|
||||
test/examples/lotr.git/objects/96/97dc65e095658bbd1b8e8678e08881e86d32f1
|
||||
test/examples/lotr.git/objects/9b/e95b960ac388d4e7db55f610f828e9c31344e6
|
||||
test/examples/lotr.git/objects/a3/1ca2a7c352c92531a8b99815d15843b259e814
|
||||
test/examples/lotr.git/objects/a6/59b3763b822dd97544621fd0beef162ea37b14
|
||||
test/examples/lotr.git/objects/a8/ad3c09dd842a3517085bfadd37718856dee813
|
||||
test/examples/lotr.git/objects/aa/b61fe89d56f8614c0a8151da34f939dcedfa68
|
||||
test/examples/lotr.git/objects/b0/de6e794dfdc7ef3400e894225bfe23308aae5c
|
||||
test/examples/lotr.git/objects/b1/6b3d9fad9d78e5a669e7f33d94c96da374eccd
|
||||
test/examples/lotr.git/objects/bc/4b5fc0ce2c2ba3acef6647e4f67256ee45ab60
|
||||
test/examples/lotr.git/objects/c3/b43e9f08966b088e7a0192e436b7a884542e05
|
||||
test/examples/lotr.git/objects/c9/6a7645db5d4c76389e77cd103ef3ed77d81e4c
|
||||
test/examples/lotr.git/objects/ca/7355dc497e9729fbaf0c0e3f424b86afef5614
|
||||
test/examples/lotr.git/objects/cf/ea406f5f77afc7fb673a43e97721234385b1bd
|
||||
test/examples/lotr.git/objects/d5/29304506d37f544675244c335d85cab5d29966
|
||||
test/examples/lotr.git/objects/dc/596d6b2dd89ab05c66f4abd7d5eb706bc17f19
|
||||
test/examples/lotr.git/objects/ec/da3205bee14520aab5a7bb307392064b938e83
|
||||
test/examples/lotr.git/objects/f4/84ebb1f40f8eb20d1bcd8d1d71934d2b8ae961
|
||||
test/examples/lotr.git/objects/fa/e7ef5344202bba4129abdc13060d9297d99465
|
||||
test/examples/lotr.git/objects/fb/c5dd7d807707b4a0a97c1182fecfef1eced5df
|
||||
test/examples/lotr.git/objects/fc/3eee516ff72dc9099ba00d4611eb02e5c9e634
|
||||
test/examples/lotr.git/objects/ff/6f7de62644369380ba73b4e4297c1a2d6f0b66
|
||||
test/examples/lotr.git/objects/info/packs
|
||||
test/examples/lotr.git/objects/pack/pack-dcbeaf3f6ff6c5eb08ea2b0a2d83626e8763546b.idx
|
||||
test/examples/lotr.git/objects/pack/pack-dcbeaf3f6ff6c5eb08ea2b0a2d83626e8763546b.pack
|
||||
test/examples/lotr.git/packed-refs
|
||||
test/examples/lotr.git/refs/heads/master
|
||||
test/examples/lotr.git/refs/remotes/origin/HEAD
|
||||
test/examples/page_file_dir.git/COMMIT_EDITMSG
|
||||
test/examples/page_file_dir.git/HEAD
|
||||
test/examples/page_file_dir.git/config
|
||||
test/examples/page_file_dir.git/description
|
||||
test/examples/page_file_dir.git/index
|
||||
test/examples/page_file_dir.git/info/exclude
|
||||
test/examples/page_file_dir.git/logs/HEAD
|
||||
test/examples/page_file_dir.git/logs/refs/heads/master
|
||||
test/examples/page_file_dir.git/objects/0c/7d27db1f575263efdcab3dc650f4502a2dbcbf
|
||||
test/examples/page_file_dir.git/objects/22/b404803c966dd92865614d86ff22ca12e50c1e
|
||||
test/examples/page_file_dir.git/objects/25/7cc5642cb1a054f08cc83f2d943e56fd3ebe99
|
||||
test/examples/page_file_dir.git/objects/57/16ca5987cbf97d6bb54920bea6adde242d87e6
|
||||
test/examples/page_file_dir.git/objects/5b/43e14e0a15fb6f08feab1773d1c0991e9f71e2
|
||||
test/examples/page_file_dir.git/refs/heads/master
|
||||
test/examples/revert.git/COMMIT_EDITMSG
|
||||
test/examples/revert.git/HEAD
|
||||
test/examples/revert.git/config
|
||||
test/examples/revert.git/description
|
||||
test/examples/revert.git/index
|
||||
test/examples/revert.git/info/exclude
|
||||
test/examples/revert.git/logs/HEAD
|
||||
test/examples/revert.git/logs/refs/heads/master
|
||||
test/examples/revert.git/objects/10/2685c42018f802557f05db171f44443e8dacab
|
||||
test/examples/revert.git/objects/20/2ced67cea93c7b6bd2928aa1daef8d1d55a20d
|
||||
test/examples/revert.git/objects/41/76394bfa11222363c66ce7e84b5f154095b6d9
|
||||
test/examples/revert.git/objects/6a/69f92020f5df77af6e8813ff1232493383b708
|
||||
test/examples/revert.git/objects/8e/83f898e5e16ae400db59dda1017acad540f3aa
|
||||
test/examples/revert.git/objects/b4/785957bc986dc39c629de9fac9df46972c00fc
|
||||
test/examples/revert.git/objects/ed/6c9f63b98acf73c25b5ffbb38da557d3682023
|
||||
test/examples/revert.git/objects/f4/03b791119f8232b7cb0ba455c624ac6435f433
|
||||
test/examples/revert.git/objects/info/packs
|
||||
test/examples/revert.git/objects/pack/pack-a561f8437234f74d0bacb9e0eebe52d207f5770d.idx
|
||||
test/examples/revert.git/objects/pack/pack-a561f8437234f74d0bacb9e0eebe52d207f5770d.pack
|
||||
test/examples/revert.git/packed-refs
|
||||
test/examples/revert.git/refs/heads/master
|
||||
test/examples/revert.git/refs/remotes/origin/HEAD
|
||||
test/examples/yubiwa.git/HEAD
|
||||
test/examples/yubiwa.git/config
|
||||
test/examples/yubiwa.git/description
|
||||
test/examples/yubiwa.git/info/exclude
|
||||
test/examples/yubiwa.git/objects/10/fa2ddc4e3b4009d8a453aace10bd6148c1ad00
|
||||
test/examples/yubiwa.git/objects/52/4b82874327ea7cbf730389964ba7cb3de966de
|
||||
test/examples/yubiwa.git/objects/58/3fc201cb457fb3f1480f3e1e5999b119633835
|
||||
test/examples/yubiwa.git/objects/87/bc1dd46ab3d3874d4e898d45dd512cc20a7cc8
|
||||
test/examples/yubiwa.git/objects/89/64ed1b4e21aa90e831763bbce9034bfda81b70
|
||||
test/examples/yubiwa.git/objects/9f/f6dd0660da5fba2d3374adb2b84fa653bb538b
|
||||
test/examples/yubiwa.git/objects/ac/e97abf2b177815a1972d7db22f229f58c83309
|
||||
test/examples/yubiwa.git/objects/b1/f443863a4816628807fbf86141ebef055dda34
|
||||
test/examples/yubiwa.git/refs/heads/master
|
||||
test/file_view/1_file.txt
|
||||
test/file_view/1_file_1_folder.txt
|
||||
test/file_view/1_folder.txt
|
||||
test/file_view/2_files_2_folders.txt
|
||||
test/file_view/2_files_2_folders_1_root.txt
|
||||
test/file_view/nested_folders.txt
|
||||
test/helper.rb
|
||||
test/test_app.rb
|
||||
test/test_app_helpers.rb
|
||||
test/test_committer.rb
|
||||
test/test_file.rb
|
||||
test/test_file_view.rb
|
||||
test/test_git_access.rb
|
||||
test/test_markup.rb
|
||||
test/test_page.rb
|
||||
test/test_page_revert.rb
|
||||
test/test_pages_view.rb
|
||||
test/test_unicode.rb
|
||||
test/test_wiki.rb
|
||||
templates/helper_wiki.rb
|
||||
]
|
||||
# = MANIFEST =
|
||||
|
||||
|
||||
+3
-2
@@ -1,3 +1,4 @@
|
||||
# ~*~ encoding: utf-8 ~*~
|
||||
# stdlib
|
||||
require 'digest/md5'
|
||||
require 'ostruct'
|
||||
@@ -18,11 +19,11 @@ require File.expand_path('../gollum/file', __FILE__)
|
||||
require File.expand_path('../gollum/file_view', __FILE__)
|
||||
require File.expand_path('../gollum/markup', __FILE__)
|
||||
require File.expand_path('../gollum/sanitization', __FILE__)
|
||||
require File.expand_path('../gollum/tex', __FILE__)
|
||||
require File.expand_path('../gollum/web_sequence_diagram', __FILE__)
|
||||
require File.expand_path('../gollum/frontend/uri_encode_component', __FILE__)
|
||||
|
||||
module Gollum
|
||||
VERSION = '2.1.5'
|
||||
VERSION = '2.4.0'
|
||||
|
||||
def self.assets_path
|
||||
::File.expand_path('gollum/frontend/public', ::File.dirname(__FILE__))
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# ~*~ encoding: utf-8 ~*~
|
||||
module Gollum
|
||||
class BlobEntry
|
||||
# Gets the String SHA for this blob.
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# ~*~ encoding: utf-8 ~*~
|
||||
module Gollum
|
||||
# Responsible for handling the commit process for a Wiki. It sets up the
|
||||
# Git index, provides methods for modifying the tree, and stores callbacks
|
||||
@@ -100,9 +101,13 @@ module Gollum
|
||||
|
||||
tree.blobs.each do |blob|
|
||||
next if page_path_scheduled_for_deletion?(index.tree, fullpath)
|
||||
file = blob.name.downcase.sub(/\.\w+$/, '')
|
||||
file_ext = ::File.extname(blob.name).sub(/^\./, '')
|
||||
if downpath == file && !(allow_same_ext && file_ext == ext)
|
||||
|
||||
existing_file = blob.name.downcase.sub(/\.\w+$/, '')
|
||||
existing_file_ext = ::File.extname(blob.name).sub(/^\./, '')
|
||||
|
||||
new_file_ext = ::File.extname(path).sub(/^\./, '')
|
||||
|
||||
if downpath == existing_file && !(allow_same_ext && new_file_ext == existing_file_ext)
|
||||
raise DuplicatePageError.new(dir, blob.name, path)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# ~*~ encoding: utf-8 ~*~
|
||||
module Gollum
|
||||
class File
|
||||
Wiki.file_class = self
|
||||
@@ -13,6 +14,22 @@ module Gollum
|
||||
@path = nil
|
||||
end
|
||||
|
||||
# Public: The url path required to reach this page within the repo.
|
||||
#
|
||||
# Returns the String url_path
|
||||
def url_path
|
||||
path = self.path
|
||||
path = path.sub(/\/[^\/]+$/, '/') if path.include?('/')
|
||||
path
|
||||
end
|
||||
|
||||
# Public: The url_path, but CGI escaped.
|
||||
#
|
||||
# Returns the String url_path
|
||||
def escaped_url_path
|
||||
CGI.escape(self.url_path).gsub('%2F','/')
|
||||
end
|
||||
|
||||
# Public: The on-disk filename of the file.
|
||||
#
|
||||
# Returns the String name.
|
||||
|
||||
+22
-12
@@ -1,3 +1,4 @@
|
||||
# ~*~ encoding: utf-8 ~*~
|
||||
module Gollum
|
||||
=begin
|
||||
FileView requires that:
|
||||
@@ -5,8 +6,13 @@ module Gollum
|
||||
- Then all the folders are sorted and processed
|
||||
=end
|
||||
class FileView
|
||||
def initialize pages
|
||||
# common use cases:
|
||||
# set pages to wiki.pages and show_all to false
|
||||
# set pages to wiki.pages + wiki.files and show_all to true
|
||||
def initialize pages, options = {}
|
||||
@pages = pages
|
||||
@show_all = options[:show_all] || false
|
||||
@checked = options[:collapse_tree] ? '' : "checked"
|
||||
end
|
||||
|
||||
def enclose_tree string
|
||||
@@ -16,7 +22,7 @@ module Gollum
|
||||
def new_page page
|
||||
name = page.name
|
||||
url = url_for_page page
|
||||
%Q( <li class="file"><a href="#{url}">#{name}</a></li>\n)
|
||||
%Q( <li class="file"><a href="#{url}"><span class="icon"></span>#{name}</a></li>)
|
||||
end
|
||||
|
||||
def new_folder folder_path
|
||||
@@ -26,20 +32,26 @@ module Gollum
|
||||
def new_sub_folder path
|
||||
<<-HTML
|
||||
<li>
|
||||
<label>#{path}</label> <input type="checkbox" checked />
|
||||
<label>#{path}</label> <input type="checkbox" #{@checked} />
|
||||
<ol>
|
||||
HTML
|
||||
end
|
||||
|
||||
def end_folder
|
||||
<<-HTML
|
||||
</ol>
|
||||
</li>
|
||||
HTML
|
||||
"</ol></li>\n"
|
||||
end
|
||||
|
||||
def url_for_page page
|
||||
url = ::File.join(::File.dirname(page.path), page.filename_stripped)
|
||||
url = ''
|
||||
if @show_all
|
||||
# Remove ext for valid pages.
|
||||
filename = page.filename
|
||||
filename = Page::valid_page_name?(filename) ? filename.chomp(::File.extname(filename)) : filename
|
||||
|
||||
url = ::File.join(::File.dirname(page.path), filename)
|
||||
else
|
||||
url = ::File.join(::File.dirname(page.path), page.filename_stripped)
|
||||
end
|
||||
url = url[2..-1] if url[0,2] == './'
|
||||
url
|
||||
end
|
||||
@@ -70,13 +82,11 @@ module Gollum
|
||||
# Handle special case of only one folder.
|
||||
if (count - folder_start == 1)
|
||||
page = @pages[ folder_start ]
|
||||
name = page.name
|
||||
url = url_for_page page
|
||||
html += <<-HTML
|
||||
<li>
|
||||
<label>#{::File.dirname(page.path)}</label> <input type="checkbox" checked />
|
||||
<label>#{::File.dirname(page.path)}</label> <input type="checkbox" #{@checked} />
|
||||
<ol>
|
||||
<li class="file"><a href="#{url}">#{name}</a></li>
|
||||
#{new_page page}
|
||||
</ol>
|
||||
</li>
|
||||
HTML
|
||||
|
||||
+56
-29
@@ -1,3 +1,4 @@
|
||||
# ~*~ encoding: utf-8 ~*~
|
||||
require 'cgi'
|
||||
require 'sinatra'
|
||||
require 'gollum'
|
||||
@@ -9,7 +10,6 @@ require 'gollum/frontend/views/layout'
|
||||
require 'gollum/frontend/views/editable'
|
||||
require 'gollum/frontend/views/has_page'
|
||||
|
||||
require File.expand_path '../uri_encode_component', __FILE__
|
||||
require File.expand_path '../helpers', __FILE__
|
||||
|
||||
# Fix to_url
|
||||
@@ -83,11 +83,12 @@ module Precious
|
||||
|
||||
before do
|
||||
@base_url = url('/', false).chomp('/')
|
||||
settings.wiki_options.merge!({ :base_path => @base_url }) unless settings.wiki_options.has_key? :base_path
|
||||
# above will detect base_path when it's used with map in a config.ru
|
||||
settings.wiki_options.merge!({ :base_path => @base_url })
|
||||
end
|
||||
|
||||
get '/' do
|
||||
redirect File.join(settings.wiki_options[:base_path].to_s, 'Home')
|
||||
redirect ::File.join(@base_url, 'Home')
|
||||
end
|
||||
|
||||
# path is set to name if path is nil.
|
||||
@@ -95,14 +96,15 @@ module Precious
|
||||
# path must have a trailing slash 'a/b/' or
|
||||
# extract_path will trim path to 'a'
|
||||
# name, path, version
|
||||
def wiki_page( name, path = nil, version = nil)
|
||||
def wiki_page(name, path = nil, version = nil, exact = true)
|
||||
path = name if path.nil?
|
||||
name = extract_name(name)
|
||||
path = extract_path(path)
|
||||
path = '/' if exact && path.nil?
|
||||
|
||||
wiki = wiki_new
|
||||
|
||||
OpenStruct.new(:wiki => wiki, :page => wiki.paged(name, path, version),
|
||||
OpenStruct.new(:wiki => wiki, :page => wiki.paged(name, path, exact, version),
|
||||
:name => name, :path => path)
|
||||
end
|
||||
|
||||
@@ -141,14 +143,15 @@ module Precious
|
||||
end
|
||||
|
||||
post '/edit/*' do
|
||||
wikip = wiki_page(CGI.unescape(params[:page]), sanitize_empty_params(params[:path]))
|
||||
path = wikip.path
|
||||
wiki = wikip.wiki
|
||||
page = wikip.page
|
||||
rename = params[:rename].to_url if params[:rename]
|
||||
name = rename || page.name
|
||||
committer = Gollum::Committer.new(wiki, commit_message)
|
||||
commit = {:committer => committer}
|
||||
path = '/' + clean_url(sanitize_empty_params(params[:path])).to_s
|
||||
page_name = CGI.unescape(params[:page])
|
||||
wiki = wiki_new
|
||||
page = wiki.paged(page_name, path, exact = true)
|
||||
return if page.nil?
|
||||
rename = params[:rename].to_url if params[:rename]
|
||||
name = rename || page.name
|
||||
committer = Gollum::Committer.new(wiki, commit_message)
|
||||
commit = {:committer => committer}
|
||||
|
||||
update_wiki_page(wiki, page, params[:content], commit, name, params[:format])
|
||||
update_wiki_page(wiki, page.header, params[:header], commit) if params[:header]
|
||||
@@ -186,17 +189,20 @@ module Precious
|
||||
|
||||
post '/create' do
|
||||
name = params[:page].to_url
|
||||
path = sanitize_empty_params(params[:path])
|
||||
path = sanitize_empty_params(params[:path]) || ''
|
||||
format = params[:format].intern
|
||||
|
||||
# ensure pages are created in page_file_dir
|
||||
page_dir = settings.wiki_options[:page_file_dir].to_s
|
||||
path = clean_url(::File.join(page_dir, path)) unless path.start_with?(page_dir)
|
||||
|
||||
# write_page is not directory aware so use wiki_options to emulate dir support.
|
||||
wiki_options = settings.wiki_options.merge({ :page_file_dir => path })
|
||||
wiki = Gollum::Wiki.new(settings.gollum_path, wiki_options)
|
||||
|
||||
begin
|
||||
wiki.write_page(name, format, params[:content], commit_message)
|
||||
page = wiki.page(name)
|
||||
redirect to("/#{page.escaped_url_path}") unless page.nil?
|
||||
redirect to("/#{clean_url(::File.join(path,name))}")
|
||||
rescue Gollum::DuplicatePageError => e
|
||||
@message = "Duplicate page: #{e.message}"
|
||||
mustache :error
|
||||
@@ -232,6 +238,8 @@ module Precious
|
||||
@content = @page.formatted_data
|
||||
@toc_content = wiki.universal_toc ? @page.toc_data : nil
|
||||
@mathjax = wiki.mathjax
|
||||
@css = wiki.css
|
||||
@h1_title = wiki.h1_title
|
||||
@editable = false
|
||||
mustache :page
|
||||
end
|
||||
@@ -276,12 +284,6 @@ module Precious
|
||||
mustache :compare
|
||||
end
|
||||
|
||||
get '/_tex.png' do
|
||||
content_type 'image/png'
|
||||
formula = Base64.decode64(params[:data])
|
||||
Gollum::Tex.render_formula(formula)
|
||||
end
|
||||
|
||||
get %r{^/(javascript|css|images)} do
|
||||
halt 404
|
||||
end
|
||||
@@ -306,7 +308,8 @@ module Precious
|
||||
get '/search' do
|
||||
@query = params[:q]
|
||||
wiki = wiki_new
|
||||
@results = wiki.search @query
|
||||
# Sort wiki search results by count (desc) and then by name (asc)
|
||||
@results = wiki.search(@query).sort{ |a, b| (a[:count] <=> b[:count]).nonzero? || b[:name] <=> a[:name] }.reverse
|
||||
@name = @query
|
||||
mustache :search
|
||||
end
|
||||
@@ -321,13 +324,21 @@ module Precious
|
||||
wiki_options = settings.wiki_options.merge({ :page_file_dir => @path })
|
||||
wiki = Gollum::Wiki.new(settings.gollum_path, wiki_options)
|
||||
@results = wiki.pages
|
||||
@results += wiki.files if settings.wiki_options[:show_all]
|
||||
@ref = wiki.ref
|
||||
mustache :pages
|
||||
end
|
||||
|
||||
get '/fileview' do
|
||||
wiki = Gollum::Wiki.new(settings.gollum_path, settings.wiki_options)
|
||||
@results = Gollum::FileView.new(wiki.pages).render_files
|
||||
wiki = wiki_new
|
||||
options = settings.wiki_options
|
||||
content = wiki.pages
|
||||
# if showing all files include wiki.files
|
||||
content += wiki.files if options[:show_all]
|
||||
|
||||
# must pass wiki_options to FileView
|
||||
# --show-all and --collapse-tree can be set.
|
||||
@results = Gollum::FileView.new(content, options).render_files
|
||||
@ref = wiki.ref
|
||||
mustache :file_view, { :layout => false }
|
||||
end
|
||||
@@ -338,23 +349,28 @@ module Precious
|
||||
|
||||
def show_page_or_file(fullpath)
|
||||
name = extract_name(fullpath)
|
||||
path = extract_path(fullpath)
|
||||
path = extract_path(fullpath) || '/'
|
||||
wiki = wiki_new
|
||||
|
||||
if page = wiki.paged(name, path)
|
||||
page_dir = settings.wiki_options[:page_file_dir].to_s
|
||||
path = ::File.join(page_dir, path) unless path.start_with?(page_dir)
|
||||
|
||||
if page = wiki.paged(name, path, exact = true)
|
||||
@page = page
|
||||
@name = name
|
||||
@editable = true
|
||||
@content = page.formatted_data
|
||||
@toc_content = wiki.universal_toc ? @page.toc_data : nil
|
||||
@mathjax = wiki.mathjax
|
||||
@css = wiki.css
|
||||
@h1_title = wiki.h1_title
|
||||
mustache :page
|
||||
elsif file = wiki.file(fullpath)
|
||||
content_type file.mime_type
|
||||
file.raw_data
|
||||
else
|
||||
page_path = [path, name].compact.join('/')
|
||||
redirect to("/create/#{encodeURIComponent(page_path).gsub('%2F','/')}")
|
||||
redirect to("/create/#{clean_url(encodeURIComponent(page_path))}")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -367,8 +383,19 @@ module Precious
|
||||
wiki.update_page(page, name, format, content.to_s, commit)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Options parameter to Gollum::Committer#initialize
|
||||
# :message - The String commit message.
|
||||
# :name - The String author full name.
|
||||
# :email - The String email address.
|
||||
# message is sourced from the incoming request parameters
|
||||
# author details are sourced from the session, to be populated by rack middleware ahead of us
|
||||
def commit_message
|
||||
{ :message => params[:message] }
|
||||
commit_message = { :message => params[:message] }
|
||||
author_parameters = session['gollum.author']
|
||||
commit_message.merge! author_parameters unless author_parameters.nil?
|
||||
commit_message
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# ~*~ encoding: utf-8 ~*~
|
||||
module Precious
|
||||
module Helpers
|
||||
# Extract the path string that Gollum::Wiki expects
|
||||
@@ -17,5 +18,19 @@ module Precious
|
||||
def sanitize_empty_params(param)
|
||||
[nil,''].include?(param) ? nil : CGI.unescape(param)
|
||||
end
|
||||
|
||||
# Remove all slashes from the start of string.
|
||||
# Remove all double slashes
|
||||
def clean_url url
|
||||
return url if url.nil?
|
||||
url.gsub('%2F','/').gsub(/^\/+/,'').gsub('//','/')
|
||||
end
|
||||
|
||||
def trim_leading_slash url
|
||||
return url if url.nil?
|
||||
url.gsub!('%2F','/')
|
||||
return '/' + url.gsub(/^\/+/,'') if url[0,1] == '/'
|
||||
url
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,121 +1,128 @@
|
||||
*, html {
|
||||
font-family: Verdana, Arial, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
#results a:hover {
|
||||
background-color: #4c4c4c;
|
||||
}
|
||||
|
||||
#home_button {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 50%;
|
||||
}
|
||||
|
||||
#home_button .minibutton {
|
||||
font-size: 1em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#results {
|
||||
position: absolute;
|
||||
top: 60px;
|
||||
left: 10px;
|
||||
}
|
||||
|
||||
body, form, ul, li, p, h1, h2, h3, h4, h5 {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: #606061;
|
||||
color: #ffffff;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
img {
|
||||
border: none;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 1em;
|
||||
margin: 0 0 1em 0;
|
||||
}
|
||||
|
||||
html { font-size: 100%; /* IE hack */ }
|
||||
body { font-size: 1em; /* Sets base font size to 16px */ }
|
||||
table { font-size: 100%; /* IE hack */ }
|
||||
input, select, textarea, th, td { font-size: 1em; }
|
||||
|
||||
/* Prevent wrapping on large file names. */
|
||||
li.file {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* CSS Tree menu styles */
|
||||
ol.tree
|
||||
{
|
||||
padding: 0 0 0 30px;
|
||||
width: 300px;
|
||||
}
|
||||
li
|
||||
{
|
||||
position: relative;
|
||||
margin-left: -15px;
|
||||
list-style: none;
|
||||
}
|
||||
li.file
|
||||
{
|
||||
margin-left: -1px !important;
|
||||
height: 1.5em;
|
||||
}
|
||||
li.file a
|
||||
{
|
||||
background: url(../images/fileview/document.png) 0 0 no-repeat;
|
||||
color: #fff;
|
||||
padding-left: 21px;
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
}
|
||||
li.file a[href *= '.pdf'] { background: url(../images/fileview/document.png) 0 0 no-repeat; }
|
||||
li.file a[href *= '.html'] { background: url(../images/fileview/document.png) 0 0 no-repeat; }
|
||||
li.file a[href $= '.css'] { background: url(../images/fileview/document.png) 0 0 no-repeat; }
|
||||
li.file a[href $= '.js'] { background: url(../images/fileview/document.png) 0 0 no-repeat; }
|
||||
li input
|
||||
{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
margin-left: 0;
|
||||
opacity: 0;
|
||||
z-index: 2;
|
||||
cursor: pointer;
|
||||
height: 1em;
|
||||
width: 1em;
|
||||
top: 0;
|
||||
}
|
||||
li input + ol
|
||||
{
|
||||
background: url(../images/fileview/toggle-small-expand.png) 40px 0 no-repeat;
|
||||
margin: -1.188em 0 0 -44px; /* 15px */
|
||||
height: 1.5em;
|
||||
}
|
||||
li input + ol > li { display: none; margin-left: -14px !important; padding-left: 1px; }
|
||||
li label
|
||||
{
|
||||
background: url(../images/fileview/folder-horizontal.png) 15px 1px no-repeat;
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
padding-left: 37px;
|
||||
}
|
||||
|
||||
li input:checked + ol
|
||||
{
|
||||
background: url(../images/fileview/toggle-small.png) 40px 5px no-repeat;
|
||||
margin: -1.5em 0 0 -44px; /* 20px */
|
||||
padding: 1.563em 0 0 80px;
|
||||
height: auto;
|
||||
}
|
||||
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 */ }
|
||||
|
||||
*, html {
|
||||
font-family: Verdana, Arial, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
#results a:hover {
|
||||
background-color: #4c4c4c;
|
||||
}
|
||||
|
||||
#home_button {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 50%;
|
||||
}
|
||||
|
||||
#home_button .minibutton {
|
||||
font-size: 1em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#results {
|
||||
position: absolute;
|
||||
top: 60px;
|
||||
left: 10px;
|
||||
}
|
||||
|
||||
body, form, ul, li, p, h1, h2, h3, h4, h5 {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: #606061;
|
||||
color: #ffffff;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
img {
|
||||
border: none;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 1em;
|
||||
margin: 0 0 1em 0;
|
||||
}
|
||||
|
||||
html { font-size: 100%; /* IE hack */ }
|
||||
body { font-size: 1em; /* Sets base font size to 16px */ }
|
||||
table { font-size: 100%; /* IE hack */ }
|
||||
input, select, textarea, th, td { font-size: 1em; }
|
||||
|
||||
/* Prevent wrapping on large file names. */
|
||||
li.file {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* CSS Tree menu styles */
|
||||
ol.tree
|
||||
{
|
||||
padding: 0 0 0 30px;
|
||||
width: 300px;
|
||||
}
|
||||
li
|
||||
{
|
||||
position: relative;
|
||||
margin-left: -15px;
|
||||
list-style: none;
|
||||
}
|
||||
li.file
|
||||
{
|
||||
margin-left: -1px !important;
|
||||
height: 1.5em;
|
||||
}
|
||||
li.file a
|
||||
{
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
}
|
||||
li.file a span.icon
|
||||
{
|
||||
width: 14px;
|
||||
height: 18px;
|
||||
background: url(../images/fileview/document.png) 0 0 no-repeat;
|
||||
display: inline-block;
|
||||
margin-right: 7px;
|
||||
vertical-align: text-top;
|
||||
}
|
||||
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; }
|
||||
li.file a[href $= '.js'] span.icon { background: url(../images/fileview/document.png) 0 0 no-repeat; }
|
||||
li input
|
||||
{
|
||||
position: absolute;
|
||||
left: 0;
|
||||
margin-left: 0;
|
||||
opacity: 0;
|
||||
z-index: 2;
|
||||
cursor: pointer;
|
||||
height: 1em;
|
||||
width: 1em;
|
||||
top: 0;
|
||||
}
|
||||
li input + ol
|
||||
{
|
||||
background: url(../images/fileview/toggle-small-expand.png) 40px 0 no-repeat;
|
||||
margin: -1.188em 0 0 -44px; /* 15px */
|
||||
height: 1.5em;
|
||||
}
|
||||
li input + ol > li { display: none; margin-left: -14px !important; padding-left: 1px; }
|
||||
li label
|
||||
{
|
||||
background: url(../images/fileview/folder-horizontal.png) 15px 1px no-repeat;
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
padding-left: 37px;
|
||||
}
|
||||
|
||||
li input:checked + ol
|
||||
{
|
||||
background: url(../images/fileview/toggle-small.png) 40px 5px no-repeat;
|
||||
margin: -1.5em 0 0 -44px; /* 20px */
|
||||
padding: 1.563em 0 0 80px;
|
||||
height: auto;
|
||||
}
|
||||
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 */ }
|
||||
|
||||
|
||||
@@ -196,7 +196,9 @@
|
||||
LanguageDefinition.getHookFunctionFor("activate")();
|
||||
}
|
||||
|
||||
function hotkey( cmd ) {
|
||||
function hotkey( e, cmd ) {
|
||||
e.preventDefault();
|
||||
|
||||
var def = LanguageDefinition.getDefinitionFor( cmd );
|
||||
if ( typeof def == 'object' ) {
|
||||
FunctionBar.executeAction( def );
|
||||
@@ -205,8 +207,17 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
Mousetrap.bind(['command+b', 'ctrl+b'], function(){ hotkey('function-bold'); });
|
||||
Mousetrap.bind(['command+i', 'ctrl+i'], function(){ hotkey('function-italic'); });
|
||||
Mousetrap.bind(['command+1', 'ctrl+1'], function( e ){ hotkey( e, 'function-h1' ); });
|
||||
Mousetrap.bind(['command+2', 'ctrl+2'], function( e ){ hotkey( e, 'function-h2' ); });
|
||||
Mousetrap.bind(['command+3', 'ctrl+3'], function( e ){ hotkey( e, 'function-h3' ); });
|
||||
Mousetrap.bind(['command+b', 'ctrl+b'], function( e ){ hotkey( e, 'function-bold' ); });
|
||||
Mousetrap.bind(['command+i', 'ctrl+i'], function( e ){ hotkey( e, 'function-italic' ); });
|
||||
Mousetrap.bind(['command+s', 'ctrl+s'], function( e ){
|
||||
e.preventDefault();
|
||||
$("#gollum-editor-submit").trigger("click");
|
||||
return false;
|
||||
});
|
||||
|
||||
} );
|
||||
} else {
|
||||
LanguageDefinition._ACTIVE_LANG = name;
|
||||
|
||||
@@ -212,4 +212,20 @@ $(document).ready(function() {
|
||||
$('#gollum-revert-form').submit();
|
||||
});
|
||||
}
|
||||
|
||||
if( $('#wiki-wrapper.edit').length ){
|
||||
$("#gollum-editor-submit").click( function() { window.onbeforeunload = null; } );
|
||||
$("#gollum-editor-body").one('change', function(){
|
||||
window.onbeforeunload = function(){ return "Leaving will discard all edits!" };
|
||||
});
|
||||
$.GollumEditor();
|
||||
}
|
||||
|
||||
if( $('#wiki-wrapper.create').length ){
|
||||
$("#gollum-editor-submit").click( function() { window.onbeforeunload = null; } );
|
||||
$("#gollum-editor-body").one('change', function(){
|
||||
window.onbeforeunload = function(){ return "Leaving will not create a new page!" };
|
||||
});
|
||||
$.GollumEditor({ NewFile: true, MarkupType: default_markup });
|
||||
}
|
||||
});
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 630 B |
Binary file not shown.
|
Before Width: | Height: | Size: 757 B After Width: | Height: | Size: 919 B |
@@ -11,12 +11,13 @@
|
||||
<div id='previewframe'><div id='contentframe' class='markdown-body'></div></div>
|
||||
<!-- tool panel from notepage.es. save & savecomment icons from Retina Display Icon Set. -->
|
||||
<div id='toolpanel' class='toolpanel edit' style='width: 500px; right: 0px; visibility: hidden;'>
|
||||
<a id='preview' class='edit'><img src='images/globe_24.png' alt='Preview' title='Preview'></a>
|
||||
<a id='save' class='edit'><img src='images/save_24.png' alt='Save' title='Save'></a>
|
||||
<a id='savecomment' class='edit'><img src='images/savecomment_24.png' alt='Save with comment' title='Save with comment'></a>
|
||||
<a id='toggle' class='edit' href='javascript:void(0)' onclick='jsm.toggleLeftRight();'><img src='images/lr_24.png' alt='Toggle left to right' title='Toggle left to right'></a>
|
||||
</div>
|
||||
|
||||
<div class='editor_bg'></div>
|
||||
<div id='editor_bg' class='editor_bg'></div>
|
||||
<div class='toolpanel_bg'></div>
|
||||
|
||||
<div id='commenttoolpanel' class='toolpanel edit' style='width: 500px; right: 0px; '>
|
||||
@@ -39,11 +40,5 @@ var require = {
|
||||
<script src='js/sundown.js'></script>
|
||||
<script src='js/md_sundown.js'></script>
|
||||
<script src='js/livepreview.js'></script>
|
||||
<!--<script>(function(d,j){
|
||||
j = d.createElement('script');
|
||||
j.src = 'https://c328740.ssl.cf1.rackcdn.com/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML';
|
||||
(d.head || d.getElementsByTagName('head')[0]).appendChild(j);
|
||||
}(document));
|
||||
</script>-->
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -62,9 +62,10 @@ initAce( commentEditor, commentEditorSession );
|
||||
var baseUrl = location.pathname.split('/').slice(0,-2).join('/');
|
||||
|
||||
// RegExp from http://stackoverflow.com/questions/901115/get-query-string-values-in-javascript
|
||||
// Returns value on success and undefined on failure.
|
||||
$.key = function( key ) {
|
||||
var value = new RegExp( '[\\?&]' + key + '=([^&#]*)' ).exec( location.href );
|
||||
return ( !value ) ? 0 : value[ 1 ] || 0;
|
||||
return ( !value ) ? undefined : value[ 1 ] || undefined;
|
||||
}
|
||||
|
||||
// True if &create=true
|
||||
@@ -73,10 +74,6 @@ var create = $.key( 'create' );
|
||||
var pageName = $.key( 'page' );
|
||||
var pathName = $.key( 'path' );
|
||||
|
||||
if ( pathName === 0 ) {
|
||||
pathName = undefined;
|
||||
}
|
||||
|
||||
defaultCommitMessage = function() {
|
||||
var msg = pageName + ' (markdown)';
|
||||
|
||||
@@ -90,6 +87,18 @@ defaultCommitMessage = function() {
|
||||
// Set comment using the default commit message.
|
||||
commentEditorSession.setValue( defaultCommitMessage() );
|
||||
|
||||
$.preview = function( previewWindow ) {
|
||||
jQuery.ajax( {
|
||||
type: 'POST',
|
||||
url: baseUrl + '/preview',
|
||||
data: { page: 'Preview: ' + pageName, format: 'markdown', content: editorSession.getValue() },
|
||||
success: function( html ) {
|
||||
previewWindow.document.write( html );
|
||||
previewWindow.focus();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$.save = function( commitMessage ) {
|
||||
win.onbeforeunload = null;
|
||||
|
||||
@@ -99,13 +108,22 @@ $.save = function( commitMessage ) {
|
||||
var msg = defaultCommitMessage();
|
||||
var newLocation = baseUrl;
|
||||
|
||||
// Remove all duplicate slashes
|
||||
function clean( str ) {
|
||||
return str.replace(/\/+/g, '/');
|
||||
}
|
||||
|
||||
// 'a%2Fb' => a/b
|
||||
if (pathName) {
|
||||
newLocation += '/' + unescape(pathName);
|
||||
if ( pathName ) {
|
||||
pathName = unescape( pathName );
|
||||
newLocation += '/' + pathName;
|
||||
pathName = pathName + '/'; // pathName must end with /
|
||||
|
||||
pathName = clean( pathName );
|
||||
}
|
||||
|
||||
newLocation += '/' + pageName;
|
||||
newLocation = clean( newLocation );
|
||||
|
||||
// if &create=true then handle create instead of edit.
|
||||
if ( create ) {
|
||||
@@ -189,13 +207,14 @@ var previewSet = function( text ) {
|
||||
}
|
||||
};
|
||||
|
||||
// 'c', 'c++', 'cpp' are github specific and transformed to c_cpp for Ace.
|
||||
var languages = [ 'c', 'c++', 'cpp', 'clojure', 'coffee', 'coldfusion',
|
||||
'csharp', 'css', 'diff', 'golang', 'groovy', 'haxe', 'html',
|
||||
'java', 'javascript', 'json', 'latex', 'less', 'liquid',
|
||||
'lua', 'markdown', 'ocaml', 'perl', 'pgsql', 'php', 'powershell',
|
||||
'python', 'ruby', 'scad', 'scala', 'scss', 'sh', 'sql', 'svg',
|
||||
'textile', 'text', 'xml', 'xquery', 'yaml' ];
|
||||
// See pygmentsLanguageToAceMode for pygment to ace mode translations.
|
||||
// TODO: Update languages and translation once Ace is upgraded to v1.0.
|
||||
var languages = [ 'c', 'c++', 'cpp', 'clojure', 'coffee',
|
||||
'coffeescript', 'coldfusion', 'csharp', 'css', 'diff', 'golang',
|
||||
'groovy', 'haxe', 'html', 'java', 'javascript', 'json', 'latex',
|
||||
'less', 'liquid', 'lua', 'markdown', 'ocaml', 'perl', 'pgsql', 'php',
|
||||
'powershell', 'python', 'ruby', 'scad', 'scala', 'scss', 'sh', 'sql',
|
||||
'svg', 'textile', 'text', 'xml', 'xquery', 'yaml' ];
|
||||
|
||||
var staticHighlight = require( 'ace/ext/static_highlight' );
|
||||
var githubTheme = require( 'ace/theme/github' );
|
||||
@@ -238,6 +257,31 @@ function highlight( element, language ) {
|
||||
element.parentNode.parentNode.replaceChild( newDiv, element.parentNode );
|
||||
}
|
||||
|
||||
// Pygments and Ace have different names for languages.
|
||||
function pygmentsLanguageToAceMode( declaredLanguage ) {
|
||||
declaredLanguage = declaredLanguage.toLowerCase();
|
||||
|
||||
switch ( declaredLanguage ) {
|
||||
case 'bash':
|
||||
return 'sh';
|
||||
case 'c':
|
||||
case 'c++':
|
||||
case 'cpp':
|
||||
case 'objective-c':
|
||||
return 'c_cpp';
|
||||
case 'c#':
|
||||
return 'csharp';
|
||||
case 'coffeescript':
|
||||
return 'coffee';
|
||||
case 'html+erb':
|
||||
return 'html'
|
||||
}
|
||||
|
||||
// Assume language name is the same
|
||||
// if it's not handled above.
|
||||
return declaredLanguage;
|
||||
}
|
||||
|
||||
var makePreviewHtml = function () {
|
||||
var text = editorSession.getValue();
|
||||
|
||||
@@ -264,8 +308,6 @@ var makePreviewHtml = function () {
|
||||
// Update the text using feature detection to support IE.
|
||||
// preview.innerHTML = text; // this doesn't work on IE.
|
||||
previewSet( text );
|
||||
// MathJax is loaded asynchronously.
|
||||
if (typeof MathJax != 'undefined') { MathJax.Hub.Typeset( content ); }
|
||||
|
||||
// highlight code blocks.
|
||||
var codeElements = preview.getElementsByTagName( 'pre' );
|
||||
@@ -290,15 +332,7 @@ var makePreviewHtml = function () {
|
||||
// the syntax for code highlighting means all code, even one line, contains newlines.
|
||||
if ( txt.length > 1 && codeHTML.match( /\n/ ) ) {
|
||||
var declaredLanguage = element.className.toLowerCase();
|
||||
var aceMode = declaredLanguage;
|
||||
|
||||
// GitHub supports 'c', 'c++', 'cpp'
|
||||
// which must trigger the 'c_cpp' mode in Ace.
|
||||
if ( declaredLanguage === 'c' ||
|
||||
declaredLanguage === 'c++' ||
|
||||
declaredLanguage === 'cpp' ) {
|
||||
aceMode = 'c_cpp';
|
||||
}
|
||||
var aceMode = pygmentsLanguageToAceMode( declaredLanguage );
|
||||
|
||||
if ( $.inArray( declaredLanguage, languages ) === -1 ) {
|
||||
// Unsupported language.
|
||||
@@ -333,18 +367,39 @@ var applyTimeout = function () {
|
||||
/* Load markdown from /data/page into the ace editor.
|
||||
~-1 == false; !~-1 == true;
|
||||
*/
|
||||
if ( !~location.host.indexOf('github.com') ) {
|
||||
if ( !~ location.host.indexOf( 'github.com' ) ) {
|
||||
|
||||
// returns unescaped key with leading slashes removed
|
||||
function key_no_leading_slash( key ) {
|
||||
return unescape( $.key( key ) || '' ).replace( /^\/+/, '' );
|
||||
}
|
||||
|
||||
// ensure leading / is removed from path and that it ends with /
|
||||
var path = key_no_leading_slash( 'path' );
|
||||
// don't append '/' if path is empty from removing leading slash
|
||||
if ( path !== '' && path.charAt( path.length - 1 ) !== '/' ) {
|
||||
path += '/';
|
||||
}
|
||||
|
||||
jQuery.ajax( {
|
||||
type: 'GET',
|
||||
url: baseUrl + '/data/' + $.key( 'page' ),
|
||||
url: baseUrl + '/data/' + path + key_no_leading_slash( 'page' ),
|
||||
success: function( data ) {
|
||||
editorSession.setValue( data );
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$( '#preview' ).click( function() {
|
||||
$(this).target = "_blank";
|
||||
// pass window into preview
|
||||
$.preview( window.open() );
|
||||
return false;
|
||||
});
|
||||
|
||||
$( '#save' ).click( function() {
|
||||
$.save();
|
||||
return false;
|
||||
});
|
||||
|
||||
// Hide dimmer, comment tool panel, and comment.
|
||||
@@ -447,6 +502,11 @@ var applyTimeout = function () {
|
||||
|
||||
win.jsm.resize = resize;
|
||||
|
||||
// remove editor_bg after loading because
|
||||
// it'll cause problems if toggle left right is used
|
||||
var ebg = doc.getElementById('editor_bg');
|
||||
ebg.parentNode.removeChild(ebg);
|
||||
|
||||
/*
|
||||
Resize can be called an absurd amount of times
|
||||
and will crash the page without debouncing.
|
||||
|
||||
@@ -15,7 +15,10 @@ CC BY-SA 3.0 Unported
|
||||
http://blog.twg.ca/2010/11/retina-display-icon-set/
|
||||
http://creativecommons.org/licenses/by-sa/3.0/legalcode.txt
|
||||
|
||||
lib/gollum/frontend/public/images/savecomment_24.png
|
||||
lib/gollum/frontend/public/images/cancel_24.png
|
||||
lib/gollum/frontend/public/images/save_24.png
|
||||
lib/gollum/frontend/public/images/globe_24.png
|
||||
|
||||
---
|
||||
|
||||
@@ -57,3 +60,10 @@ http://www.thecssninja.com/css/css-tree-menu
|
||||
http://www.thecssninja.com/demo/license.txt
|
||||
|
||||
lib/gollum/frontend/public/css/_styles.css
|
||||
|
||||
---
|
||||
|
||||
`lr_24.png` is a modified version of http://templarian.com/files/wp_icons/icons/light/appbar.arrow.right.left.png
|
||||
|
||||
https://github.com/Templarian/WindowsIcons/blob/21189bffeb17237d444419ef43ed1b49e9f4e9f8/WindowsPhone/license.txt
|
||||
|
||||
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
Read the license:
|
||||
http://creativecommons.org/licenses/by/3.0/ **
|
||||
|
||||
Basicaly, use it anyway you want but include this license file in the source if your project is open source. Nothing is needed in the front facing project. Commercial use is not only allowed but encouraged. This pack was made to promote consistency in applications.
|
||||
|
||||
Creator
|
||||
- Austin Andrews (@templarian)
|
||||
|
||||
Contributor*
|
||||
- Oren Nachman
|
||||
- appbar.chevron.down
|
||||
- appbar.chevron.up
|
||||
- appbar.chevron.left
|
||||
- appbar.chevron.right
|
||||
- Kris Vandermotten (@kvandermotten)
|
||||
- appbar.medical.pulse
|
||||
- Constantin Kichinsky (@kichinsky)
|
||||
- appbar.currency.rubles
|
||||
- appbar.currency.grivna
|
||||
- Massimo Savazzi (@msavazzi)
|
||||
- List of missing exported icons
|
||||
- Proletkult Graphik, from The Noun Project
|
||||
- appbar.draw.pen (inspired)
|
||||
- Olivier Guin, from The Noun Project
|
||||
- appbar.draw.marker
|
||||
- Gibran Bisio, from The Noun Project
|
||||
- appbar.draw.bucket
|
||||
|
||||
* Developers and designers that emailed Templarian the source .design icons to be added into the package. PNGs also accepted, but may take longer to be added.
|
||||
|
||||
|
||||
Contact
|
||||
- http://templarian.com/
|
||||
- admin[@]templarian[.]com
|
||||
|
||||
** Does not apply to copyrighted logos
|
||||
- Skype
|
||||
- Facebook
|
||||
- Twitter
|
||||
- etc...
|
||||
@@ -1,4 +1,4 @@
|
||||
<div id="wiki-wrapper">
|
||||
<div id="wiki-wrapper" class="create">
|
||||
<div id="head">
|
||||
<h1>Create New Page</h1>
|
||||
</div>
|
||||
@@ -9,12 +9,6 @@
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
window.onbeforeunload = function(){ return "Leaving will not create a new page!" };
|
||||
$("#gollum-editor-submit").click( function() { window.onbeforeunload = null; } );
|
||||
|
||||
jQuery(document).ready(function() {
|
||||
$.GollumEditor({ NewFile: true, MarkupType: '{{default_markup}}' });
|
||||
});
|
||||
var default_markup = '{{default_markup}}';
|
||||
</script>
|
||||
|
||||
{{something}}
|
||||
|
||||
@@ -10,11 +10,3 @@
|
||||
</div>
|
||||
<div id="wiki-content">{{>editor}}</div>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
window.onbeforeunload = function(){ return "Leaving will discard all edits!" };
|
||||
$("#gollum-editor-submit").click( function() { window.onbeforeunload = null; } );
|
||||
|
||||
jQuery(document).ready(function() {
|
||||
$.GollumEditor();
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<link rel="stylesheet" type="text/css" href="{{base_url}}/css/editor.css" media="all">
|
||||
<link rel="stylesheet" type="text/css" href="{{base_url}}/css/dialog.css" media="all">
|
||||
<link rel="stylesheet" type="text/css" href="{{base_url}}/css/template.css" media="all">
|
||||
{{#css}}<link rel="stylesheet" type="text/css" href="{{base_url}}/custom.css" media="all">{{/css}}
|
||||
|
||||
<!--[if IE 7]>
|
||||
<link rel="stylesheet" type="text/css" href="{{base_url}}/css/ie7.css" media="all">
|
||||
@@ -18,7 +19,17 @@
|
||||
<script type="text/javascript" src="{{base_url}}/javascript/gollum.dialog.js"></script>
|
||||
<script type="text/javascript" src="{{base_url}}/javascript/gollum.placeholder.js"></script>
|
||||
<script type="text/javascript" src="{{base_url}}/javascript/editor/gollum.editor.js"></script>
|
||||
{{#mathjax}}<script>(function(d,j){
|
||||
{{#mathjax}}
|
||||
<script type="text/x-mathjax-config">
|
||||
MathJax.Hub.Config({
|
||||
tex2jax: {
|
||||
inlineMath: [ ['$','$'], ['\\(','\\)']],
|
||||
displayMath: [ ['$$','$$'], ['\[','\]'] ],
|
||||
processEscapes: true
|
||||
},
|
||||
TeX: { extensions: ["autoload-all.js"] }});
|
||||
</script>
|
||||
<script>(function(d,j){
|
||||
j = d.createElement('script');
|
||||
j.src = 'https://c328740.ssl.cf1.rackcdn.com/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML';
|
||||
(d.head || d.getElementsByTagName('head')[0]).appendChild(j);
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
<script>
|
||||
Mousetrap.bind(['e'], function( e ) {
|
||||
e.preventDefault();
|
||||
window.location = "/edit" + window.location.pathname;
|
||||
return false;
|
||||
});
|
||||
</script>
|
||||
<div id="wiki-wrapper" class="page">
|
||||
<div id="head">
|
||||
<h1>{{title}}</h1>
|
||||
<h1>{{page_header}}</h1>
|
||||
<ul class="actions">
|
||||
<li class="minibutton">
|
||||
{{>searchbar}}
|
||||
|
||||
@@ -6,6 +6,11 @@ module Precious
|
||||
|
||||
attr_reader :page, :content
|
||||
|
||||
# return path set in app.rb not @page.path
|
||||
def path
|
||||
@path
|
||||
end
|
||||
|
||||
def title
|
||||
"#{@page.title}"
|
||||
end
|
||||
|
||||
@@ -8,7 +8,16 @@ module Precious
|
||||
DEFAULT_AUTHOR = 'you'
|
||||
|
||||
def title
|
||||
@page.url_path.gsub("-", " ")
|
||||
h1 = @h1_title ? page_header_from_content(@content) : false
|
||||
h1 || @page.url_path_title
|
||||
end
|
||||
|
||||
def page_header
|
||||
page_header_from_content(@content) || title
|
||||
end
|
||||
|
||||
def content
|
||||
content_without_page_header(@content)
|
||||
end
|
||||
|
||||
def author
|
||||
@@ -80,6 +89,10 @@ module Precious
|
||||
@mathjax
|
||||
end
|
||||
|
||||
def css # custom css
|
||||
@css
|
||||
end
|
||||
|
||||
# Access to embedded metadata.
|
||||
#
|
||||
# Examples
|
||||
@@ -90,6 +103,48 @@ module Precious
|
||||
def metadata
|
||||
@page.metadata
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Wraps page formatted data to Nokogiri::HTML document.
|
||||
#
|
||||
def build_document(content)
|
||||
Nokogiri::HTML(%{<div id="gollum-root">} + content + %{</div>})
|
||||
end
|
||||
|
||||
# Finds header node inside Nokogiri::HTML document.
|
||||
#
|
||||
def find_header_node(doc)
|
||||
case self.format
|
||||
when :asciidoc
|
||||
doc.css("div#gollum-root > div#header > h1:first-child")
|
||||
when :org
|
||||
doc.css("div#gollum-root > p.title:first-child")
|
||||
when :pod
|
||||
doc.css("div#gollum-root > a.dummyTopAnchor:first-child + h1")
|
||||
when :rest
|
||||
doc.css("div#gollum-root > div > div > h1:first-child")
|
||||
else
|
||||
doc.css("div#gollum-root > h1:first-child")
|
||||
end
|
||||
end
|
||||
|
||||
# Extracts title from page if present.
|
||||
#
|
||||
def page_header_from_content(content)
|
||||
doc = build_document(content)
|
||||
title = find_header_node(doc)
|
||||
Sanitize.clean(title.to_html).strip unless title.empty?
|
||||
end
|
||||
|
||||
# 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.css("div#gollum-root").inner_html
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# ~*~ encoding: utf-8 ~*~
|
||||
module Gollum
|
||||
# Controls all access to the Git objects from Gollum. Extend this class to
|
||||
# add custom caching for special cases.
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
# ~*~ encoding: utf-8 ~*~
|
||||
require 'net/http'
|
||||
require 'net/https' # ruby 1.8.7 fix, remove at upgrade
|
||||
require 'uri'
|
||||
require 'open-uri'
|
||||
|
||||
module Gollum
|
||||
class Gitcode
|
||||
def initialize path
|
||||
raise(ArgumentError, 'path is nil or empty') if path.nil? or path.empty?
|
||||
|
||||
@uri = URI::HTTP.build({
|
||||
:path => self.unchomp(path),
|
||||
:host => 'raw.github.com',
|
||||
:scheme => 'https',
|
||||
:port => 443 })
|
||||
end
|
||||
|
||||
def contents
|
||||
@contents ||= self.req @uri
|
||||
end
|
||||
|
||||
def unchomp p
|
||||
return p if p.nil?
|
||||
p[0] == '/' ? p : ('/' + p)
|
||||
end
|
||||
|
||||
def req uri, cut = 1
|
||||
return "Too many redirects or retries" if cut >= 10
|
||||
http = Net::HTTP.new uri.host, uri.port
|
||||
http.use_ssl = true
|
||||
resp = http.get uri.path, {
|
||||
'Accept' => 'text/plain',
|
||||
'Cache-Control' => 'no-cache',
|
||||
'Connection' => 'keep-alive',
|
||||
'Host' => uri.host,
|
||||
'User-Agent' => 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:15.0) Gecko/20100101 Firefox/15.0'
|
||||
}
|
||||
code = resp.code.to_i
|
||||
return resp.body if code == 200
|
||||
return "Not Found" if code == 404
|
||||
return "Unhandled Response Code #{code}" unless code == 304 or not resp.header['location'].nil?
|
||||
loc = URI.parse resp.header['location']
|
||||
uri2 = loc.relative?() ? (uri + loc) : loc # overloads (+)
|
||||
return req uri2, (cut + 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
+129
-80
@@ -1,14 +1,20 @@
|
||||
# ~*~ encoding: utf-8 ~*~
|
||||
require 'digest/sha1'
|
||||
require 'cgi'
|
||||
require 'pygments'
|
||||
require 'base64'
|
||||
|
||||
require File.expand_path '../frontend/helpers', __FILE__
|
||||
require File.expand_path '../gitcode', __FILE__
|
||||
|
||||
# initialize Pygments
|
||||
Pygments.start
|
||||
|
||||
module Gollum
|
||||
|
||||
class Markup
|
||||
include Precious::Helpers
|
||||
|
||||
attr_accessor :toc
|
||||
attr_reader :metadata
|
||||
|
||||
@@ -28,11 +34,11 @@ module Gollum
|
||||
@dir = ::File.dirname(page.path)
|
||||
@tagmap = {}
|
||||
@codemap = {}
|
||||
@texmap = {}
|
||||
@wsdmap = {}
|
||||
@premap = {}
|
||||
@toc = nil
|
||||
@metadata = nil
|
||||
@to_xml = { :save_with => Nokogiri::XML::Node::SaveOptions::DEFAULT_XHTML ^ 1, :indent => 0, :encoding => 'UTF-8' }
|
||||
end
|
||||
|
||||
# Render the content with Gollum wiki syntax on top of the file's own
|
||||
@@ -50,8 +56,8 @@ module Gollum
|
||||
|
||||
data = @data.dup
|
||||
data = extract_metadata(data)
|
||||
data = extract_gitcode(data)
|
||||
data = extract_code(data)
|
||||
data = extract_tex(data)
|
||||
data = extract_wsd(data)
|
||||
data = extract_tags(data)
|
||||
begin
|
||||
@@ -70,12 +76,18 @@ module Gollum
|
||||
doc,toc = process_headers(doc)
|
||||
@toc = @sub_page ? ( @parent_page ? @parent_page.toc_data : "[[_TOC_]]" ) : toc
|
||||
yield doc if block_given?
|
||||
data = doc.to_html
|
||||
# nokogiri's save options are ored together. FORMAT has a value of 1 so ^ 1 removes it.
|
||||
# formatting will create extra spaces in pre tags.
|
||||
# https://github.com/sparklemotion/nokogiri/issues/782
|
||||
# DEFAULT_HTML encodes unicode so XHTML is used for proper unicode support in href.
|
||||
data = doc.to_xml( @to_xml )
|
||||
|
||||
data = process_toc_tags(data)
|
||||
data = process_tex(data)
|
||||
data = process_wsd(data)
|
||||
data.gsub!(/<p><\/p>/, '')
|
||||
data.gsub!(/<p><\/p>/) do
|
||||
''
|
||||
end
|
||||
|
||||
data
|
||||
end
|
||||
|
||||
@@ -87,15 +99,13 @@ module Gollum
|
||||
def process_headers(doc)
|
||||
toc = nil
|
||||
doc.css('h1,h2,h3,h4,h5,h6').each do |h|
|
||||
id = encodeURIComponent(h.content.gsub(' ','-'))
|
||||
# must escape "
|
||||
h_name = h.content.gsub(' ','-').gsub('"','%22')
|
||||
|
||||
level = h.name.gsub(/[hH]/,'').to_i
|
||||
|
||||
# Add anchors
|
||||
anchor = Nokogiri::XML::Node.new('a', doc)
|
||||
anchor['class'] = 'anchor'
|
||||
anchor['id'] = id
|
||||
anchor['href'] = '#' + id.gsub('%', '%25')
|
||||
h.add_child(anchor)
|
||||
h.add_child(%Q{<a class="anchor" id="#{h_name}" href="##{h_name}"></a>})
|
||||
|
||||
# Build TOC
|
||||
toc ||= Nokogiri::XML::DocumentFragment.parse('<div class="toc"><div class="toc-title">Table of Contents</div></div>')
|
||||
@@ -112,68 +122,14 @@ module Gollum
|
||||
tail_level -= 1
|
||||
end
|
||||
node = Nokogiri::XML::Node.new('li', doc)
|
||||
node.add_child("<a href='##{id}'>#{h.content}</a>")
|
||||
# % -> %25 so anchors work on Firefox. See issue #475
|
||||
node.add_child(%Q{<a href="##{h_name}">#{h.content}</a>})
|
||||
tail.add_child(node)
|
||||
end
|
||||
toc = toc.to_xhtml if toc != nil
|
||||
toc = toc.to_xml(@to_xml) if toc != nil
|
||||
[doc, toc]
|
||||
end
|
||||
|
||||
#########################################################################
|
||||
#
|
||||
# TeX
|
||||
#
|
||||
#########################################################################
|
||||
|
||||
# Extract all TeX into the texmap and replace with placeholders.
|
||||
#
|
||||
# data - The raw String data.
|
||||
#
|
||||
# Returns the placeholder'd String data.
|
||||
def extract_tex(data)
|
||||
data.gsub(/\\\[\s*(.*?)\s*\\\]/m) do
|
||||
tag = CGI.escapeHTML($1)
|
||||
id = Digest::SHA1.hexdigest(tag)
|
||||
@texmap[id] = [:block, tag]
|
||||
id
|
||||
end.gsub(/\\\(\s*(.*?)\s*\\\)/m) do
|
||||
tag = CGI.escapeHTML($1)
|
||||
id = Digest::SHA1.hexdigest(tag)
|
||||
@texmap[id] = [:inline, tag]
|
||||
id
|
||||
end
|
||||
end
|
||||
|
||||
# Process all TeX from the texmap and replace the placeholders with the
|
||||
# final markup.
|
||||
#
|
||||
# data - The String data (with placeholders).
|
||||
#
|
||||
# Returns the marked up String data.
|
||||
def process_tex(data)
|
||||
@texmap.each do |id, spec|
|
||||
type, tex = *spec
|
||||
|
||||
# Obtain the formula with parameters
|
||||
out = nil
|
||||
begin
|
||||
width, height, align, base64 = Gollum::Tex.render_formula(tex, true)
|
||||
|
||||
# TODO: Should we load the binary inside the html?
|
||||
#out = %{<img width="#{width}" height="#{height}" style="vertical-align: #{align}px;" src="data:image/png;base64,\n#{base64}" alt="#{CGI.escapeHTML(tex)}" />}
|
||||
|
||||
# Use the alignment values from the formula rendering but still use the call to '_tex.png'. Although it will call render_formula()
|
||||
# again, it will use the already cached formula and it might have some advantages from the point of view of browser caching (really not sure here).
|
||||
out = %{<img width="#{width}" height="#{height}" style="vertical-align: #{align}px;" src="#{::File.join(@wiki.base_path, '_tex.png')}?type=#{type}&data=#{Base64.encode64(tex).chomp}" alt="#{CGI.escapeHTML(tex)}" />}
|
||||
rescue # In case of error
|
||||
out = CGI.escapeHTML(tex)
|
||||
end
|
||||
|
||||
data.gsub!(id, out)
|
||||
end
|
||||
data
|
||||
end
|
||||
|
||||
#########################################################################
|
||||
#
|
||||
# Tags
|
||||
@@ -224,9 +180,13 @@ module Gollum
|
||||
@tagmap.each do |id, tag|
|
||||
# If it's preformatted, just put the tag back
|
||||
if is_preformatted?(data, id)
|
||||
data.gsub!(id, "[[#{tag}]]")
|
||||
data.gsub!(id) do
|
||||
"[[#{tag}]]"
|
||||
end
|
||||
else
|
||||
data.gsub!(id, process_tag(tag))
|
||||
data.gsub!(id) do
|
||||
process_tag(tag).gsub('%2F', '/')
|
||||
end
|
||||
end
|
||||
end
|
||||
data
|
||||
@@ -407,6 +367,12 @@ module Gollum
|
||||
presence = "present"
|
||||
end
|
||||
link = ::File.join(@wiki.base_path, page ? page.escaped_url_path : CGI.escape(link_name))
|
||||
|
||||
# //page is invalid
|
||||
# strip all duplicate forward slashes using helpers.rb trim_leading_slash
|
||||
# //page => /page
|
||||
link = trim_leading_slash link
|
||||
|
||||
%{<a class="internal #{presence}" href="#{link}#{extra}">#{name}</a>}
|
||||
end
|
||||
end
|
||||
@@ -418,7 +384,9 @@ module Gollum
|
||||
#
|
||||
# Returns the marked up String data.
|
||||
def process_toc_tags(data)
|
||||
data.gsub!("[[_TOC_]]", @toc.nil? ? '' : @toc)
|
||||
data.gsub!("[[_TOC_]]") do
|
||||
@toc.nil? ? '' : @toc
|
||||
end
|
||||
data
|
||||
end
|
||||
|
||||
@@ -439,13 +407,23 @@ module Gollum
|
||||
# Find a page from a given cname. If the page has an anchor (#) and has
|
||||
# no match, strip the anchor and try again.
|
||||
#
|
||||
# cname - The String canonical page name.
|
||||
# cname - The String canonical page name including path.
|
||||
#
|
||||
# Returns a Gollum::Page instance if a page is found, or an Array of
|
||||
# [Gollum::Page, String extra] if a page without the extra anchor data
|
||||
# is found.
|
||||
def find_page_from_name(cname)
|
||||
if page = @wiki.page(cname)
|
||||
slash = cname.rindex('/')
|
||||
|
||||
unless slash.nil?
|
||||
name = cname[slash+1..-1]
|
||||
path = cname[0..slash]
|
||||
page = @wiki.paged(name, path)
|
||||
else
|
||||
page = @wiki.paged(cname, '/')
|
||||
end
|
||||
|
||||
if page
|
||||
return page
|
||||
end
|
||||
if pos = cname.index('#')
|
||||
@@ -453,6 +431,34 @@ module Gollum
|
||||
end
|
||||
end
|
||||
|
||||
#########################################################################
|
||||
#
|
||||
# Gitcode - fetch code from github search path and replace the contents
|
||||
# to a code-block that gets run the next parse.
|
||||
#
|
||||
#########################################################################
|
||||
|
||||
def extract_gitcode data
|
||||
data.gsub /^[ \t]*``` ?([^:\n\r]+):([^`\n\r]+)```/ do
|
||||
contents = ''
|
||||
# Use empty string if $2 is nil.
|
||||
uri = $2 || ''
|
||||
# Detect local file.
|
||||
if uri[0..6] != 'github/'
|
||||
if uri[0..0] != '/' # relative file
|
||||
contents = @wiki.page(uri).formatted_data
|
||||
else # use full path
|
||||
contents = @wiki.paged( extract_name( clean_url( uri ) ),
|
||||
'/' + clean_url( extract_path( uri ) ) ).formatted_data
|
||||
end
|
||||
else
|
||||
contents = Gollum::Gitcode.new(uri).contents
|
||||
end
|
||||
|
||||
"```#{$1}\n#{contents}\n```\n"
|
||||
end
|
||||
end
|
||||
|
||||
#########################################################################
|
||||
#
|
||||
# Code
|
||||
@@ -465,6 +471,35 @@ module Gollum
|
||||
#
|
||||
# Returns the placeholder'd String data.
|
||||
def extract_code(data)
|
||||
data.gsub!(/^([ \t]*)(~~~+) ?([^\r\n]+)?\r?\n(.+?)\r?\n\1(~~~+)\r?$/m) do
|
||||
m_indent = $1
|
||||
m_start = $2 # ~~~
|
||||
m_lang = $3
|
||||
m_code = $4
|
||||
m_end = $5 # ~~~
|
||||
|
||||
# start and finish tilde fence must be the same length
|
||||
return '' if m_start.length != m_end.length
|
||||
|
||||
lang = m_lang ? m_lang.strip : nil
|
||||
id = Digest::SHA1.hexdigest("#{lang}.#{m_code}")
|
||||
cached = check_cache(:code, id)
|
||||
|
||||
# extract lang from { .ruby } or { #stuff .ruby .indent }
|
||||
# see http://johnmacfarlane.net/pandoc/README.html#delimited-code-blocks
|
||||
|
||||
if lang
|
||||
lang = lang.match(/\.([^}\s]+)/)
|
||||
lang = lang[1] unless lang.nil?
|
||||
end
|
||||
|
||||
@codemap[id] = cached ?
|
||||
{ :output => cached } :
|
||||
{ :lang => lang, :code => m_code, :indent => m_indent }
|
||||
|
||||
"#{m_indent}#{id}" # print the SHA1 ID with the proper indentation
|
||||
end
|
||||
|
||||
data.gsub!(/^([ \t]*)``` ?([^\r\n]+)?\r?\n(.+?)\r?\n\1```\r?$/m) do
|
||||
lang = $2 ? $2.strip : nil
|
||||
id = Digest::SHA1.hexdigest("#{lang}.#{$3}")
|
||||
@@ -485,7 +520,9 @@ module Gollum
|
||||
# regex - A regex to match whitespace
|
||||
def remove_leading_space(code, regex)
|
||||
if code.lines.all? { |line| line =~ /\A\r?\n\Z/ || line =~ regex }
|
||||
code.gsub!(regex, '')
|
||||
code.gsub!(regex) do
|
||||
''
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -515,13 +552,15 @@ module Gollum
|
||||
blocks.each do |lang, code|
|
||||
encoding ||= 'utf-8'
|
||||
begin
|
||||
hl_code = Pygments.highlight(code, :lexer => lang, :options => {:encoding => encoding.to_s})
|
||||
rescue ::RubyPython::PythonError
|
||||
# must set startinline to true for php to be highlighted without <?
|
||||
# http://pygments.org/docs/lexers/
|
||||
hl_code = Pygments.highlight(code, :lexer => lang, :options => {:encoding => encoding.to_s, :startinline => true})
|
||||
rescue
|
||||
hl_code = code
|
||||
end
|
||||
highlighted << hl_code
|
||||
end
|
||||
|
||||
|
||||
@codemap.each do |id, spec|
|
||||
body = spec[:output] || begin
|
||||
if (body = highlighted.shift.to_s).size > 0
|
||||
@@ -531,7 +570,9 @@ module Gollum
|
||||
"<pre><code>#{CGI.escapeHTML(spec[:code])}</code></pre>"
|
||||
end
|
||||
end
|
||||
data.gsub!(id, body)
|
||||
data.gsub!(id) do
|
||||
body
|
||||
end
|
||||
end
|
||||
|
||||
data
|
||||
@@ -567,7 +608,9 @@ module Gollum
|
||||
@wsdmap.each do |id, spec|
|
||||
style = spec[:style]
|
||||
code = spec[:code]
|
||||
data.gsub!(id, Gollum::WebSequenceDiagram.new(code, style).to_tag)
|
||||
data.gsub!(id) do
|
||||
Gollum::WebSequenceDiagram.new(code, style).to_tag
|
||||
end
|
||||
end
|
||||
data
|
||||
end
|
||||
@@ -579,12 +622,18 @@ module Gollum
|
||||
#########################################################################
|
||||
|
||||
# Extract metadata for data and build metadata table. Metadata
|
||||
# is content found between `<!-- ---` and `-->` markers, and must
|
||||
# is content found between markers, and must
|
||||
# be a valid YAML mapping.
|
||||
#
|
||||
# Because ri and ruby 1.8.7 are awesome, the markers can't
|
||||
# be included in this documentation without triggering
|
||||
# `Unhandled special: Special: type=17`
|
||||
# Please read the source code for the exact markers
|
||||
#
|
||||
# Returns the String of formatted data with metadata removed.
|
||||
def extract_metadata(data)
|
||||
@metadata ||= {}
|
||||
# The markers are `<!-- ---` and `-->`
|
||||
data.gsub(/\<\!--+\s+---(.*?)--+\>/m) do
|
||||
yaml = @wiki.sanitizer.clean($1)
|
||||
hash = YAML.load(yaml)
|
||||
|
||||
+29
-5
@@ -1,3 +1,4 @@
|
||||
# ~*~ encoding: utf-8 ~*~
|
||||
module Gollum
|
||||
class Page
|
||||
include Pagination
|
||||
@@ -167,6 +168,27 @@ module Gollum
|
||||
path
|
||||
end
|
||||
|
||||
# Public: Defines title for page.rb
|
||||
#
|
||||
# Returns the String title
|
||||
def url_path_title
|
||||
metadata_title || url_path.gsub("-", " ")
|
||||
end
|
||||
|
||||
# Public: Metadata title
|
||||
#
|
||||
# Set with <!-- --- title: New Title --> in page content
|
||||
#
|
||||
# Returns the String title or nil if not defined
|
||||
def metadata_title
|
||||
if metadata
|
||||
title = metadata['title']
|
||||
return title unless title.nil?
|
||||
end
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
# Public: The url_path, but CGI escaped.
|
||||
#
|
||||
# Returns the String url_path
|
||||
@@ -220,7 +242,7 @@ module Gollum
|
||||
# Public: Embedded metadata.
|
||||
#
|
||||
# Returns Hash of metadata.
|
||||
def meta_data()
|
||||
def metadata()
|
||||
formatted_data if markup_class.metadata == nil
|
||||
markup_class.metadata
|
||||
end
|
||||
@@ -327,7 +349,7 @@ module Gollum
|
||||
# Returns the String canonical name.
|
||||
def self.cname(name, char_white_sub = '-', char_other_sub = '-')
|
||||
name.respond_to?(:gsub) ?
|
||||
name.gsub(%r{\s},char_white_sub).gsub(%r{[/<>+]}, char_other_sub) :
|
||||
name.gsub(%r{\s},char_white_sub).gsub(%r{[<>+]}, char_other_sub) :
|
||||
''
|
||||
end
|
||||
|
||||
@@ -372,9 +394,9 @@ module Gollum
|
||||
# version - The String version ID to find.
|
||||
#
|
||||
# Returns a Gollum::Page or nil if the page could not be found.
|
||||
def find(name, version, dir = nil)
|
||||
def find(name, version, dir = nil, exact = false)
|
||||
map = @wiki.tree_map_for(version.to_s)
|
||||
if page = find_page_in_tree(map, name, dir)
|
||||
if page = find_page_in_tree(map, name, dir, exact)
|
||||
page.version = version.is_a?(Grit::Commit) ?
|
||||
version : @wiki.commit_for(version)
|
||||
page.historical = page.version.to_s == version.to_s
|
||||
@@ -391,12 +413,14 @@ module Gollum
|
||||
# to be in. The string should
|
||||
#
|
||||
# Returns a Gollum::Page or nil if the page could not be found.
|
||||
def find_page_in_tree(map, name, checked_dir = nil)
|
||||
def find_page_in_tree(map, name, checked_dir = nil, exact = false)
|
||||
return nil if !map || name.to_s.empty?
|
||||
if checked_dir = BlobEntry.normalize_dir(checked_dir)
|
||||
checked_dir.downcase!
|
||||
end
|
||||
|
||||
checked_dir = '' if exact && checked_dir.nil?
|
||||
|
||||
map.each do |entry|
|
||||
next if entry.name.to_s.empty?
|
||||
next unless checked_dir.nil? || entry.dir.downcase == checked_dir
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# ~*~ encoding: utf-8 ~*~
|
||||
module Gollum
|
||||
module Pagination
|
||||
def self.included(klass)
|
||||
@@ -58,4 +59,4 @@ module Gollum
|
||||
self.class.log_pagination_options(options)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# ~*~ encoding: utf-8 ~*~
|
||||
module Gollum
|
||||
# Encapsulate sanitization options.
|
||||
#
|
||||
|
||||
@@ -1,366 +0,0 @@
|
||||
require 'fileutils'
|
||||
require 'shellwords'
|
||||
require 'tmpdir'
|
||||
require 'posix/spawn'
|
||||
require 'base64'
|
||||
|
||||
module Gollum
|
||||
module Tex
|
||||
class Error < StandardError; end
|
||||
|
||||
extend POSIX::Spawn
|
||||
|
||||
Template = <<-EOS
|
||||
\\documentclass[11pt]{article}
|
||||
\\pagestyle{empty}
|
||||
\\setlength{\\topskip}{0pt}
|
||||
\\setlength{\\parindent}{0pt}
|
||||
\\setlength{\\abovedisplayskip}{0pt}
|
||||
\\setlength{\\belowdisplayskip}{0pt}
|
||||
|
||||
\\usepackage{geometry}
|
||||
|
||||
\\usepackage{amsfonts}
|
||||
\\usepackage{amsmath}
|
||||
|
||||
\\newsavebox{\\snippetbox}
|
||||
\\newlength{\\snippetwidth}
|
||||
\\newlength{\\snippetheight}
|
||||
\\newlength{\\snippetdepth}
|
||||
\\newlength{\\pagewidth}
|
||||
\\newlength{\\pageheight}
|
||||
\\newlength{\\pagemargin}
|
||||
|
||||
\\begin{lrbox}{\\snippetbox}%
|
||||
\$%s\$
|
||||
\\end{lrbox}
|
||||
|
||||
\\settowidth{\\snippetwidth}{\\usebox{\\snippetbox}}
|
||||
\\settoheight{\\snippetheight}{\\usebox{\\snippetbox}}
|
||||
\\settodepth{\\snippetdepth}{\\usebox{\\snippetbox}}
|
||||
|
||||
\\setlength\\pagemargin{4pt}
|
||||
|
||||
\\setlength\\pagewidth\\snippetwidth
|
||||
\\addtolength\\pagewidth\\pagemargin
|
||||
\\addtolength\\pagewidth\\pagemargin
|
||||
|
||||
\\setlength\\pageheight\\snippetheight
|
||||
\\addtolength{\\pageheight}{\\snippetdepth}
|
||||
\\addtolength\\pageheight\\pagemargin
|
||||
\\addtolength\\pageheight\\pagemargin
|
||||
|
||||
\\newwrite\\foo
|
||||
\\immediate\\openout\\foo=\\jobname.dimensions
|
||||
\\immediate\\write\\foo{snippetdepth = \\the\\snippetdepth}
|
||||
\\immediate\\write\\foo{snippetheight = \\the\\snippetheight}
|
||||
\\immediate\\write\\foo{snippetwidth = \\the\\snippetwidth}
|
||||
\\immediate\\write\\foo{pagewidth = \\the\\pagewidth}
|
||||
\\immediate\\write\\foo{pageheight = \\the\\pageheight}
|
||||
\\immediate\\write\\foo{pagemargin = \\the\\pagemargin}
|
||||
\\closeout\\foo
|
||||
|
||||
\\geometry{paperwidth=\\pagewidth,paperheight=\\pageheight,margin=\\pagemargin}
|
||||
|
||||
\\begin{document}%
|
||||
\\usebox{\\snippetbox}%
|
||||
\\end{document}
|
||||
EOS
|
||||
|
||||
class << self
|
||||
attr_accessor :latex_path
|
||||
end
|
||||
|
||||
self.latex_path = 'pdflatex'
|
||||
|
||||
def self.check_dependencies!
|
||||
return if @dependencies_available
|
||||
|
||||
if `which pdflatex` == ""
|
||||
raise Error, "`pdflatex` command not found"
|
||||
end
|
||||
|
||||
if `which gs` == ""
|
||||
raise Error, "`gs` command not found"
|
||||
end
|
||||
|
||||
if `which pnmcrop` == ""
|
||||
raise Error, "`pnmcrop` command not found"
|
||||
end
|
||||
|
||||
if `which pnmpad` == ""
|
||||
raise Error, "`pnmpad` command not found"
|
||||
end
|
||||
|
||||
if `which pnmscale` == ""
|
||||
raise Error, "`pnmscale` command not found"
|
||||
end
|
||||
|
||||
if `which ppmtopgm` == ""
|
||||
raise Error, "`ppmtopgm` command not found"
|
||||
end
|
||||
|
||||
if `which pnmgamma` == ""
|
||||
raise Error, "`pnmgamma` command not found"
|
||||
end
|
||||
|
||||
if `which pnmtopng` == ""
|
||||
raise Error, "`pnmtopng` command not found"
|
||||
end
|
||||
|
||||
@dependencies_available = true
|
||||
end
|
||||
|
||||
# Render the formula and calculate the correct alignment
|
||||
# for the image in the html.
|
||||
#
|
||||
# This is a ruby implementation of the Perl version described
|
||||
# at http://tex.stackexchange.com/questions/44486/pixel-perfect-vertical-alignment-of-image-rendered-tex-snippets
|
||||
#
|
||||
# The main caveat is that rendering takes quite a bit of processing power,
|
||||
# which can make the page load slowly if it has to render each time.
|
||||
# For this reason, the method caches the rendered formula in `/tmp` for reduced
|
||||
# loading time in subsequent loads.
|
||||
#
|
||||
# @param formula the tex formula to render
|
||||
# @param with_properties, if true it returns an array with a base64
|
||||
# string with the image, and the alignment values for the image.
|
||||
# Otherwise it returns the binary image.
|
||||
def self.render_formula(formula, with_properties=false)
|
||||
check_dependencies!
|
||||
|
||||
render_antialias_bits = 4
|
||||
render_oversample = 4
|
||||
display_oversample = 4
|
||||
gamma = 0.3
|
||||
if !with_properties
|
||||
display_oversample = 1
|
||||
gamma = 0.5
|
||||
end
|
||||
|
||||
oversample = render_oversample * display_oversample
|
||||
render_dpi = 96*1.2 * 72.27/72 * oversample # This is 1850.112 dpi.
|
||||
|
||||
|
||||
# Cache rendered formula and returned cached version if it exists
|
||||
|
||||
# First look for the .cache directory in the home folder
|
||||
cache_dir = ::File.expand_path("~/.cache")
|
||||
if not ::File.exists?(cache_dir) or not ::File.directory?(cache_dir)
|
||||
::Dir.mkdir(cache_dir)
|
||||
end
|
||||
|
||||
# Check that the gollum directory exists inside the cache dir
|
||||
cache_dir = ::File.join(cache_dir, "gollum")
|
||||
if not ::File.exists?(cache_dir) or not ::File.directory?(cache_dir)
|
||||
::Dir.mkdir(cache_dir)
|
||||
end
|
||||
|
||||
# Check for the formula in the cache dir
|
||||
hash = Digest::SHA1.hexdigest(formula)
|
||||
cache_file = ::File.join(cache_dir, "tex-#{hash}")
|
||||
|
||||
if ::File.exists?(cache_file)
|
||||
width, height, align, base64 = ::File.open(cache_file, 'rb') { |io| io.read }.split(",")
|
||||
|
||||
if with_properties
|
||||
return width, height, align, base64
|
||||
else
|
||||
return Base64.decode64(base64)
|
||||
end
|
||||
end
|
||||
|
||||
Dir.mktmpdir('tex') do |path|
|
||||
file = ::File.join(path, "formula")
|
||||
|
||||
# --- Write TeX source and compile to PDF.Write snippet into template
|
||||
::File.open(file + ".tex", 'w') { |f| f.write(Template % formula) }
|
||||
|
||||
result = sh_chdir path, "pdflatex",
|
||||
"-halt-on-error",
|
||||
"-output-directory=#{path}",
|
||||
"-output-format=pdf",
|
||||
"#{file}.tex",
|
||||
">#{file}.err 2>&1"
|
||||
|
||||
|
||||
|
||||
# --- Convert PDF to PNM using Ghostscript.
|
||||
sh "gs",
|
||||
"-q -dNOPAUSE -dBATCH",
|
||||
"-dTextAlphaBits=#{render_antialias_bits}",
|
||||
"-dGraphicsAlphaBits=#{render_antialias_bits}",
|
||||
"-r#{render_dpi}",
|
||||
"-sDEVICE=pnmraw",
|
||||
"-sOutputFile=#{file}.pnm",
|
||||
"#{file}.pdf"
|
||||
|
||||
|
||||
img_width, img_height = pnm_width_height(file + ".pnm")
|
||||
|
||||
|
||||
# --- Read dimensions file written by TeX during processing.
|
||||
#
|
||||
# Example of file contents:
|
||||
# snippetdepth = 6.50009pt
|
||||
# snippetheight = 13.53899pt
|
||||
# snippetwidth = 145.4777pt
|
||||
# pagewidth = 153.4777pt
|
||||
# pageheight = 28.03908pt
|
||||
# pagemargin = 4.0pt
|
||||
dimensions = {}
|
||||
::File.open(file + ".dimensions").readlines.each_with_index do |line, i|
|
||||
if line =~ /^(\S+)\s+=\s+(-?[0-9\.]+)pt$/
|
||||
dimensions[$1] = Float($2) / 72.27 * render_dpi
|
||||
else
|
||||
raise Error, "#{file}.dimensions: invalid line: #{i}"
|
||||
end
|
||||
end
|
||||
|
||||
# --- Crop bottom, then measure how much was cropped.
|
||||
sh "pnmcrop -white -bottom #{file}.pnm >#{file}.bottomcrop.pnm"
|
||||
#raise Error, "`pnmcrop` command failed: #{result}" unless ::File.exist?(file + ".bottomcrop.pnm")
|
||||
|
||||
img_width_bottomcrop, img_height_bottomcrop = pnm_width_height("#{file}.bottomcrop.pnm")
|
||||
bottomcrop = img_height - img_height_bottomcrop
|
||||
|
||||
# --- Crop top and sides, then measure how much was cropped from the top.
|
||||
sh "pnmcrop -white #{file}.bottomcrop.pnm > #{file}.crop.pnm"
|
||||
#raise Error, "`pnmcrop` command failed: #{result}" unless ::File.exist?(file + ".crop.pnm")
|
||||
|
||||
cropped_img_width, cropped_img_height = pnm_width_height("#{file}.crop.pnm")
|
||||
topcrop = img_height_bottomcrop - cropped_img_height
|
||||
|
||||
# --- Pad image with specific values on all four sides, in preparation for
|
||||
# downsampling.
|
||||
|
||||
# Calculate bottom padding.
|
||||
snippet_depth = Integer(dimensions["snippetdepth"] + dimensions["pagemargin"] + 0.5) - bottomcrop
|
||||
padded_snippet_depth = round_up(snippet_depth, oversample)
|
||||
increase_snippet_depth = padded_snippet_depth - snippet_depth
|
||||
bottom_padding = increase_snippet_depth
|
||||
|
||||
# --- Next calculate top padding, which depends on bottom padding.
|
||||
|
||||
padded_img_height = round_up(cropped_img_height + bottom_padding,
|
||||
oversample)
|
||||
top_padding = padded_img_height - (cropped_img_height + bottom_padding)
|
||||
|
||||
|
||||
# --- Calculate left and right side padding. Distribute padding evenly.
|
||||
|
||||
padded_img_width = round_up(cropped_img_width, oversample)
|
||||
left_padding = Integer((padded_img_width - cropped_img_width) / 2.0)
|
||||
right_padding = (padded_img_width - cropped_img_width) - left_padding
|
||||
|
||||
|
||||
# --- Pad the final image.
|
||||
result = sh "pnmpad",
|
||||
"-white",
|
||||
"-bottom=#{bottom_padding}",
|
||||
"-top=#{top_padding}",
|
||||
"-left=#{left_padding}",
|
||||
"-right=#{right_padding}",
|
||||
"#{file}.crop.pnm",
|
||||
">#{file}.pad.pnm"
|
||||
|
||||
# --- Sanity check of final size.
|
||||
final_pnm_width, final_pnm_height = pnm_width_height(file + ".pad.pnm")
|
||||
raise Error, "#{final_pnm_width} is not a multiple of #{oversample}" unless final_pnm_width % oversample == 0
|
||||
|
||||
raise "#{final_pnm_height} is not a multiple of #{oversample}" unless final_pnm_height % oversample == 0
|
||||
|
||||
# --- Convert PNM to PNG.
|
||||
|
||||
final_png_width = final_pnm_width / render_oversample
|
||||
final_png_height = final_pnm_height / render_oversample
|
||||
|
||||
result = sh "cat #{file}.pad.pnm",
|
||||
"| ppmtopgm",
|
||||
"| pnmscale -reduce #{render_oversample}",
|
||||
"| pnmgamma #{gamma}",
|
||||
"| pnmtopng -compression 9",
|
||||
"> #{file}.png"
|
||||
|
||||
raise Error, "Conversion to png failed: #{result}" unless ::File.exist?(file + ".png")
|
||||
|
||||
# Calculate html properties
|
||||
html_img_width = final_png_width / display_oversample
|
||||
html_img_height = final_png_height / display_oversample
|
||||
html_img_vertical_align = sprintf("%.0f", -padded_snippet_depth / oversample)
|
||||
png_data_base64 = Base64.encode64(::File.open("#{file}.png") { |io| io.read }).chomp
|
||||
|
||||
::File.open(cache_file, 'w') { |f| f.write(%{#{html_img_width},#{html_img_height},#{html_img_vertical_align},#{png_data_base64}}) }
|
||||
if with_properties
|
||||
return html_img_width, html_img_height, html_img_vertical_align, png_data_base64
|
||||
else
|
||||
::File.read(file + ".png")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def self.sh_chdir(path, *args)
|
||||
origcommand = args * " "
|
||||
return if origcommand == ""
|
||||
|
||||
command = origcommand
|
||||
command.gsub! /(["\\])/, "\\$1"
|
||||
command = %{/bin/sh -c "(#{command}) 2>&1"}
|
||||
|
||||
pid = spawn command, :chdir => path
|
||||
|
||||
result = Process::waitpid(pid)
|
||||
exit_value = Integer($? >> 8), signal_num = Integer($? & 127), dumped_core = Integer($? & 128)
|
||||
raise Error, "Failed #{result}: #{origcommand}. Exit value = #{exit_value}. Signal Num = #{signal_num}. Dumped core = #{dumped_core}" unless $?.success?
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
def self.sh(*args)
|
||||
origcommand = args * " "
|
||||
return if origcommand == ""
|
||||
|
||||
command = origcommand
|
||||
command.gsub! /(["\\])/, "\\$1"
|
||||
command = %{/bin/sh -c "(#{command}) 2>&1"}
|
||||
|
||||
pid = spawn command
|
||||
#pid = spawn *args
|
||||
result = Process::waitpid(pid)
|
||||
exit_value = $? >> 8, signal_num = $? & 127, dumped_core = $? & 128
|
||||
raise Error, "Failed #{result}: #{origcommand}. Exit value = #{exit_value}. Signal Num = #{signal_num}. Dumped core = #{dumped_core}" unless $?.success?
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
def self.round_up(num, mod)
|
||||
num + (num % mod == 0 ? 0 : (mod - (num % mod)))
|
||||
end
|
||||
|
||||
def self.pnm_width_height(filename)
|
||||
raise Error, "#{filename} is not a .pnm file" if filename !~ /\.pnm$/
|
||||
|
||||
width = nil, height = nil
|
||||
::File.open(filename) do |file|
|
||||
# Read first line
|
||||
line = file.gets
|
||||
begin
|
||||
line = file.gets # Read next line, skipping comments
|
||||
end while line && line =~ /^#/
|
||||
|
||||
if line =~ /^(\d+)\s+(\d+)$/
|
||||
width = Integer($1)
|
||||
height = Integer($2)
|
||||
else
|
||||
raise Error, "#{filename}: couldn't read image size"
|
||||
end
|
||||
end
|
||||
|
||||
raise Error, "#{filename}: couldn't read image size" unless width && height
|
||||
|
||||
return width, height
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
@@ -1,3 +1,4 @@
|
||||
# ~*~ encoding: utf-8 ~*~
|
||||
require 'net/http'
|
||||
require 'uri'
|
||||
require 'open-uri'
|
||||
|
||||
+57
-24
@@ -1,3 +1,4 @@
|
||||
# ~*~ encoding: utf-8 ~*~
|
||||
module Gollum
|
||||
class Wiki
|
||||
include Pagination
|
||||
@@ -136,6 +137,14 @@ module Gollum
|
||||
# Gets the boolean live preview value.
|
||||
attr_reader :live_preview
|
||||
|
||||
# Injects custom css from custom.css in root repo.
|
||||
# Defaults to false
|
||||
attr_reader :css
|
||||
|
||||
# Sets page title to value of first h1
|
||||
# Defaults to false
|
||||
attr_reader :h1_title
|
||||
|
||||
# Public: Initialize a new Gollum Repo.
|
||||
#
|
||||
# path - The String path to the Git repository that holds the Gollum
|
||||
@@ -154,6 +163,9 @@ module Gollum
|
||||
# :ref - String the repository ref to retrieve pages from
|
||||
# :ws_subs - Array of chars to sub for ws in filenames.
|
||||
# :mathjax - Set to false to disable mathjax.
|
||||
# :show_all - Show all files in file view, not just valid pages.
|
||||
# Default: false
|
||||
# :collapse_tree - Start with collapsed file view. Default: false
|
||||
#
|
||||
# Returns a fresh Gollum::Repo.
|
||||
def initialize(path, options = {})
|
||||
@@ -162,24 +174,33 @@ module Gollum
|
||||
options[:access] = path
|
||||
path = path.path
|
||||
end
|
||||
@path = path
|
||||
@repo_is_bare = options[:repo_is_bare]
|
||||
@page_file_dir = options[:page_file_dir]
|
||||
@access = options[:access] || GitAccess.new(path, @page_file_dir, @repo_is_bare)
|
||||
@base_path = options[:base_path] || "/"
|
||||
@page_class = options[:page_class] || self.class.page_class
|
||||
@file_class = options[:file_class] || self.class.file_class
|
||||
@markup_classes = options[:markup_classes] || self.class.markup_classes
|
||||
@repo = @access.repo
|
||||
@ref = options[:ref] || self.class.default_ref
|
||||
@sanitization = options[:sanitization] || self.class.sanitization
|
||||
@ws_subs = options[:ws_subs] ||
|
||||
self.class.default_ws_subs
|
||||
@history_sanitization = options[:history_sanitization] ||
|
||||
self.class.history_sanitization
|
||||
@live_preview = options.fetch(:live_preview, true)
|
||||
@universal_toc = options.fetch(:universal_toc, false)
|
||||
@mathjax = options[:mathjax] || false
|
||||
|
||||
# Use .fetch instead of ||
|
||||
#
|
||||
# o = { :a => false }
|
||||
# o[:a] || true # => true
|
||||
# o.fetch :a, true # => false
|
||||
|
||||
@path = path
|
||||
@repo_is_bare = options.fetch :repo_is_bare, nil
|
||||
@page_file_dir = options.fetch :page_file_dir, nil
|
||||
@access = options.fetch :access, GitAccess.new(path, @page_file_dir, @repo_is_bare)
|
||||
@base_path = options.fetch :base_path, "/"
|
||||
@page_class = options.fetch :page_class, self.class.page_class
|
||||
@file_class = options.fetch :file_class, self.class.file_class
|
||||
@markup_classes = options.fetch :markup_classes, self.class.markup_classes
|
||||
@repo = @access.repo
|
||||
@ref = options.fetch :ref, self.class.default_ref
|
||||
@sanitization = options.fetch :sanitization, self.class.sanitization
|
||||
@ws_subs = options.fetch :ws_subs, self.class.default_ws_subs
|
||||
@history_sanitization = options.fetch :history_sanitization, self.class.history_sanitization
|
||||
@live_preview = options.fetch :live_preview, true
|
||||
@universal_toc = options.fetch :universal_toc, false
|
||||
@mathjax = options.fetch :mathjax, false
|
||||
@show_all = options.fetch :show_all, false
|
||||
@collapse_tree = options.fetch :collapse_tree, false
|
||||
@css = options.fetch :css, false
|
||||
@h1_title = options.fetch :h1_title, false
|
||||
end
|
||||
|
||||
# Public: check whether the wiki's git repo exists on the filesystem.
|
||||
@@ -196,9 +217,9 @@ module Gollum
|
||||
# dir - The directory String relative to the repo.
|
||||
#
|
||||
# Returns a Gollum::Page or nil if no matching page was found.
|
||||
def page(name, version = @ref, dir = nil)
|
||||
def page(name, version = @ref, dir = nil, exact = false)
|
||||
version = @ref if version.nil?
|
||||
@page_class.new(self).find(name, version, dir)
|
||||
@page_class.new(self).find(name, version, dir, exact)
|
||||
end
|
||||
|
||||
# Public: Convenience method instead of calling page(name, nil, dir).
|
||||
@@ -208,8 +229,8 @@ module Gollum
|
||||
# dir - The directory String relative to the repo.
|
||||
#
|
||||
# Returns a Gollum::Page or nil if no matching page was found.
|
||||
def paged(name, dir = nil, version = @ref)
|
||||
page(name, version, dir)
|
||||
def paged(name, dir = nil, exact = false, version = @ref)
|
||||
page(name, version, dir, exact)
|
||||
end
|
||||
|
||||
# Public: Get the static file for a given name.
|
||||
@@ -495,14 +516,19 @@ module Gollum
|
||||
@repo.git.grep(*args).split("\n").each do |line|
|
||||
result = line.split(':')
|
||||
result_1 = result[1]
|
||||
file_name = result_1.chomp(::File.extname(result_1))
|
||||
# Remove ext only from known extensions.
|
||||
# test.pdf => test.pdf, test.md => test
|
||||
file_name = Page::valid_page_name?(result_1) ? result_1.chomp(::File.extname(result_1)) :
|
||||
result_1
|
||||
results[file_name] = result[2].to_i
|
||||
end
|
||||
|
||||
# Use git ls-files '*query*' to search for file names. Grep only searches file content.
|
||||
# Spaces are converted to dashes when saving pages to disk.
|
||||
@repo.git.ls_files({}, "*#{ query.gsub(' ', '-') }*").split("\n").each do |line|
|
||||
file_name = line.chomp(::File.extname(line))
|
||||
# Remove ext only from known extensions.
|
||||
file_name = Page::valid_page_name?(line) ? line.chomp(::File.extname(line)) :
|
||||
line
|
||||
# If there's not already a result for file_name then
|
||||
# the value is nil and nil.to_i is 0.
|
||||
results[file_name] = results[file_name].to_i + 1;
|
||||
@@ -583,6 +609,13 @@ module Gollum
|
||||
# Toggles mathjax.
|
||||
attr_reader :mathjax
|
||||
|
||||
# Toggles showing all files in files view. Default is false.
|
||||
# When false, only valid pages in the git repo are displayed.
|
||||
attr_reader :show_all
|
||||
|
||||
# Start with collapsed file view. Default: false
|
||||
attr_reader :collapse_tree
|
||||
|
||||
# Normalize the data.
|
||||
#
|
||||
# data - The String data to be normalized.
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
For gollum code, everything should fall under the existing MIT License.
|
||||
Alternative permissive licenses (such as BSD) for 3rd party dependencies are
|
||||
acceptable. For image assets in Gollum, CC BY or CC BY-SA is fine. Anything
|
||||
released under a copyleft license (for example GPL, AGPL, LGPL, MPL, EPL,
|
||||
etc.) is not permitted in gollum. Public domain, CC BY or CC BY-SA for code in
|
||||
gollum is not permitted.
|
||||
|
||||
---
|
||||
|
||||
The following PNGs are based on Ubuntu 11.10 SVG files located in /usr/share/icons/unity-icon-theme/places/svg/
|
||||
- group-folders.svg
|
||||
- group-files.svg
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
class WikiFactory
|
||||
def self.create p
|
||||
path = testpath "examples/test.git"
|
||||
Grit::Repo.init_bare(@path)
|
||||
Gollum::Wiki.default_options = {:universal_toc => false}
|
||||
cleanup = Proc.new { FileUtils.rm_r File.join(File.dirname(__FILE__), *%w[examples test.git]) }
|
||||
Gollum::Wiki.new(@path), @path, cleanup
|
||||
end
|
||||
end
|
||||
@@ -5,3 +5,4 @@ a8ad3c09dd842a3517085bfadd37718856dee813 1db89ebba7e2c14d93b94ff98cfa3708a4f0d4e
|
||||
b16b3d9fad9d78e5a669e7f33d94c96da374eccd b0de6e794dfdc7ef3400e894225bfe23308aae5c kristi <kristi.dev@gmail.com> 1336984025 -0700 push
|
||||
b0de6e794dfdc7ef3400e894225bfe23308aae5c cfea406f5f77afc7fb673a43e97721234385b1bd Darren Oakley <daz.oakley@gmail.com> 1341830099 +0100 push
|
||||
cfea406f5f77afc7fb673a43e97721234385b1bd 629aa678272b017a4d136d35e77ac94d80b08dc2 Darren Oakley <daz.oakley@gmail.com> 1341830833 +0100 push
|
||||
629aa678272b017a4d136d35e77ac94d80b08dc2 7d6aeab8b84c895f21f6c66b84a457b0fced9693 Daniel Kimsey <dekimsey@ufl.edu> 1352501984 -0500 push
|
||||
|
||||
@@ -5,3 +5,4 @@ a8ad3c09dd842a3517085bfadd37718856dee813 1db89ebba7e2c14d93b94ff98cfa3708a4f0d4e
|
||||
b16b3d9fad9d78e5a669e7f33d94c96da374eccd b0de6e794dfdc7ef3400e894225bfe23308aae5c kristi <kristi.dev@gmail.com> 1336984025 -0700 push
|
||||
b0de6e794dfdc7ef3400e894225bfe23308aae5c cfea406f5f77afc7fb673a43e97721234385b1bd Darren Oakley <daz.oakley@gmail.com> 1341830099 +0100 push
|
||||
cfea406f5f77afc7fb673a43e97721234385b1bd 629aa678272b017a4d136d35e77ac94d80b08dc2 Darren Oakley <daz.oakley@gmail.com> 1341830833 +0100 push
|
||||
629aa678272b017a4d136d35e77ac94d80b08dc2 7d6aeab8b84c895f21f6c66b84a457b0fced9693 Daniel Kimsey <dekimsey@ufl.edu> 1352501984 -0500 push
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,2 @@
|
||||
xE�OK1Å=÷S<ëEaºz’EYð ]¼g·™™`¦•´3ê··ã<åù½—4ps}{¶=!gtä;°ö.„{w��ZNѹSÄ<g‹È=^eáYµCN¼vêȘdëlV¶²6³Æ6
|
||||
ã‰$q„$÷"1*&«c«!µ`?J?¼Á“$š�)øwšµ®°·JV|¿&!æ‰}ç²Áï´)�<Ò—«þ¦cýƒHÐ s:²Õf£C»dŸõC8ah.Jß³qªˆl²P•ܤ›·ÿÁ§¶ï”«�s¿³6gú
|
||||
Binary file not shown.
@@ -0,0 +1 @@
|
||||
x�Î=j1@áÔ:Åt®ô?cC\ù³šY¼Ú
ZmáÛ|„t¯ùà•µy€õþct>èDh*q0Á°ËÅŠµbLbı+è²%õG]ÖÑf¢ˆÉ¢�´Aòl\d‘Jöœô¤«è¿[‡ZgYà>·]žðÍòx×å¨Ë—ðqã‚
ÚdÌð©ƒÖª¼‡üǪ+³0Ü–¾|Ú¡S šb¤^í/M1
|
||||
@@ -1 +1 @@
|
||||
629aa678272b017a4d136d35e77ac94d80b08dc2
|
||||
7d6aeab8b84c895f21f6c66b84a457b0fced9693
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
<ol class="tree">
|
||||
<li class="file"><a href="0">0</a></li>
|
||||
</ol>
|
||||
<li class="file">
|
||||
<a href="0"><span class="icon"></span>0</a>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
<ol class="tree">
|
||||
<li>
|
||||
<label>folder0</label> <input type="checkbox" checked />
|
||||
<ol>
|
||||
<li class="file"><a href="folder0/0">0</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
</ol>
|
||||
<li>
|
||||
<label>folder0</label>
|
||||
<input type="checkbox" />
|
||||
<ol>
|
||||
<li class="file">
|
||||
<a href="folder0/0"><span class="icon"></span>0</a>
|
||||
</li>
|
||||
</ol>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
<ol class="tree">
|
||||
<li>
|
||||
<label>.</label> <input type="checkbox" checked />
|
||||
<ol>
|
||||
<li class="file"><a href="folder0">folder0</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
</ol>
|
||||
<li>
|
||||
<label>.</label>
|
||||
<input type="checkbox" />
|
||||
<ol>
|
||||
<li class="file">
|
||||
<a href="folder0"><span class="icon"></span>folder0</a>
|
||||
</li>
|
||||
</ol>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
@@ -1,12 +1,20 @@
|
||||
<ol class="tree">
|
||||
<li>
|
||||
<label>folder0</label> <input type="checkbox" checked />
|
||||
<ol>
|
||||
<li class="file"><a href="folder0/0">0</a></li>
|
||||
</ol>
|
||||
<li>
|
||||
<label>folder0</label>
|
||||
<input type="checkbox" />
|
||||
<ol>
|
||||
<li class="file">
|
||||
<a href="folder0/0"><span class="icon"></span>0</a>
|
||||
</li>
|
||||
<li>
|
||||
<label>folder1</label> <input type="checkbox" checked />
|
||||
<ol>
|
||||
<li class="file"><a href="folder1/1">1</a></li>
|
||||
</ol>
|
||||
</ol>
|
||||
</li>
|
||||
<li>
|
||||
<label>folder1</label>
|
||||
<input type="checkbox" />
|
||||
<ol>
|
||||
<li class="file">
|
||||
<a href="folder1/1"><span class="icon"></span>1</a>
|
||||
</li>
|
||||
</ol>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
@@ -1,13 +1,23 @@
|
||||
<ol class="tree">
|
||||
<li class="file"><a href="root">root</a></li>
|
||||
<li>
|
||||
<label>folder0</label> <input type="checkbox" checked />
|
||||
<ol>
|
||||
<li class="file"><a href="folder0/0">0</a></li>
|
||||
</ol>
|
||||
<li class="file">
|
||||
<a href="root"><span class="icon"></span>root</a>
|
||||
</li>
|
||||
<li>
|
||||
<label>folder0</label>
|
||||
<input type="checkbox" />
|
||||
<ol>
|
||||
<li class="file">
|
||||
<a href="folder0/0"><span class="icon"></span>0</a>
|
||||
</li>
|
||||
<li>
|
||||
<label>folder1</label> <input type="checkbox" checked />
|
||||
<ol>
|
||||
<li class="file"><a href="folder1/1">1</a></li>
|
||||
</ol>
|
||||
</ol>
|
||||
</li>
|
||||
<li>
|
||||
<label>folder1</label>
|
||||
<input type="checkbox" />
|
||||
<ol>
|
||||
<li class="file">
|
||||
<a href="folder1/1"><span class="icon"></span>1</a>
|
||||
</li>
|
||||
</ol>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
@@ -1,28 +1,41 @@
|
||||
<ol class="tree">
|
||||
<li>
|
||||
<label>folder0</label>
|
||||
<input type="checkbox" />
|
||||
<ol>
|
||||
<li>
|
||||
<label>folder0</label> <input type="checkbox" checked />
|
||||
<label>folder1</label>
|
||||
<input type="checkbox" />
|
||||
<ol>
|
||||
<li>
|
||||
<label>folder1</label> <input type="checkbox" checked />
|
||||
<ol>
|
||||
<li>
|
||||
<label>folder2</label> <input type="checkbox" checked />
|
||||
<ol>
|
||||
<li class="file"><a href="folder0/folder1/folder2/0">0</a></li>
|
||||
<li>
|
||||
<label>folder2</label>
|
||||
<input type="checkbox" />
|
||||
<ol>
|
||||
<li class="file">
|
||||
<a href="folder0/folder1/folder2/0"><span class="icon"></span>0</a>
|
||||
</li>
|
||||
</ol>
|
||||
</li>
|
||||
<li>
|
||||
<label>folder3</label>
|
||||
<input type="checkbox" />
|
||||
<ol>
|
||||
<li class="file">
|
||||
<a href="folder0/folder1/folder3/1"><span class="icon"></span>1</a>
|
||||
</li>
|
||||
</ol>
|
||||
</li>
|
||||
</ol>
|
||||
</li>
|
||||
<li>
|
||||
<label>folder3</label> <input type="checkbox" checked />
|
||||
<ol>
|
||||
<li class="file"><a href="folder0/folder1/folder3/1">1</a></li>
|
||||
</ol>
|
||||
</ol>
|
||||
</li>
|
||||
<li>
|
||||
<label>folder4</label>
|
||||
<input type="checkbox" />
|
||||
<ol>
|
||||
<li class="file">
|
||||
<a href="folder4/2"><span class="icon"></span>2</a>
|
||||
</li>
|
||||
</ol>
|
||||
</li>
|
||||
</ol>
|
||||
</li>
|
||||
<li>
|
||||
<label>folder4</label> <input type="checkbox" checked />
|
||||
<ol>
|
||||
<li class="file"><a href="folder4/2">2</a></li>
|
||||
</ol>
|
||||
</ol>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
@@ -50,6 +50,14 @@ context "Frontend" do
|
||||
assert_not_equal page_1.version.sha, page_2.version.sha
|
||||
end
|
||||
|
||||
test "edit page with slash" do
|
||||
page_1 = @wiki.page('A')
|
||||
post "/edit/A", :content => 'abc', :page => 'A', :path => '/////',
|
||||
:format => page_1.format, :message => 'def'
|
||||
follow_redirect!
|
||||
assert last_response.ok?
|
||||
end
|
||||
|
||||
test "edits page header footer and sidebar" do
|
||||
commits = @wiki.repo.commits('master').size
|
||||
page_1 = @wiki.page('A')
|
||||
@@ -176,6 +184,9 @@ context "Frontend" do
|
||||
name = "A"
|
||||
post "/create", :content => 'abc', :page => name,
|
||||
:format => 'markdown', :message => 'def'
|
||||
|
||||
follow_redirect!
|
||||
|
||||
assert last_response.ok?
|
||||
|
||||
@wiki.clear_cache
|
||||
@@ -251,6 +262,9 @@ context "Frontend" do
|
||||
page2 = @wiki.page('A')
|
||||
assert_equal page1.version.sha, page2.version.sha
|
||||
end
|
||||
=begin
|
||||
# redirects are now handled by class MapGollum in bin/gollum
|
||||
# they should be set in config.ru
|
||||
|
||||
test "redirects from 'base_path' or 'base_path/' to 'base_path/Home'" do
|
||||
Precious::App.set(:wiki_options, {})
|
||||
@@ -264,6 +278,28 @@ context "Frontend" do
|
||||
Precious::App.set(:wiki_options, { :base_path => '/wiki/' })
|
||||
get "/"
|
||||
assert_match "http://example.org/wiki/Home", last_response.headers['Location']
|
||||
|
||||
# Reset base path
|
||||
Precious::App.set(:wiki_options, { :base_path => nil })
|
||||
end
|
||||
=end
|
||||
|
||||
test "author details in session are used" do
|
||||
page1 = @wiki.page('A')
|
||||
|
||||
gollum_author = { :name => 'ghi', :email => 'jkl' }
|
||||
session = { 'gollum.author' => gollum_author }
|
||||
|
||||
post "/edit/A", { :content => 'abc', :page => 'A', :format => page1.format, :message => 'def' }, { 'rack.session' => session }
|
||||
follow_redirect!
|
||||
assert last_response.ok?
|
||||
|
||||
@wiki.clear_cache
|
||||
page2 = @wiki.page(page1.name)
|
||||
|
||||
author = page2.version.author
|
||||
assert_equal 'ghi', author.name
|
||||
assert_equal 'jkl', author.email
|
||||
end
|
||||
|
||||
def app
|
||||
@@ -333,6 +369,36 @@ context "Frontend with lotr" do
|
||||
assert body.include?("Eye Of Sauron"), "/pages/Mordor/ should include the page 'Eye Of Sauron'"
|
||||
end
|
||||
|
||||
# base path requires 'map' in a config.ru to work correctly.
|
||||
test "create pages within sub-directories using base path" do
|
||||
Precious::App.set(:wiki_options, { :base_path => 'wiki' })
|
||||
page = 'path'
|
||||
post "/create", :content => '123', :page => page,
|
||||
:path => 'Mordor', :format => 'markdown', :message => 'oooh, scary'
|
||||
# should be wiki/Mordor/path
|
||||
assert_equal 'http://example.org/Mordor/' + page, last_response.headers['Location']
|
||||
get '/Mordor/' + page
|
||||
assert_match /123/, last_response.body
|
||||
|
||||
# Reset base path
|
||||
Precious::App.set(:wiki_options, { :base_path => nil })
|
||||
end
|
||||
|
||||
test "create pages within sub-directories using page file dir" do
|
||||
Precious::App.set(:wiki_options, { :page_file_dir => 'wiki' })
|
||||
|
||||
post "/create", :content => 'one two', :page => 'base',
|
||||
:path => 'Mordor', :format => 'markdown', :message => 'oooh, scary'
|
||||
assert_equal 'http://example.org/wiki/Mordor/base', last_response.headers['Location']
|
||||
get "/wiki/Mordor/base"
|
||||
|
||||
# Reset page_file_dir after request but before matching.
|
||||
Precious::App.set(:wiki_options, { :page_file_dir => nil })
|
||||
|
||||
assert_match /one two/, last_response.body
|
||||
end
|
||||
|
||||
|
||||
test "create pages within sub-directories" do
|
||||
post "/create", :content => 'big smelly creatures', :page => 'Orc',
|
||||
:path => 'Mordor', :format => 'markdown', :message => 'oooh, scary'
|
||||
@@ -350,6 +416,7 @@ context "Frontend with lotr" do
|
||||
test "edit pages within sub-directories" do
|
||||
post "/create", :content => 'big smelly creatures', :page => 'Orc',
|
||||
:path => 'Mordor', :format => 'markdown', :message => 'oooh, scary'
|
||||
|
||||
assert_equal 'http://example.org/Mordor/orc', last_response.headers['Location']
|
||||
|
||||
post "/edit/Mordor/Orc", :content => 'not so big smelly creatures',
|
||||
|
||||
@@ -50,7 +50,7 @@ context "Wiki" do
|
||||
end
|
||||
|
||||
test "parents with default master ref" do
|
||||
ref = '629aa678272b017a4d136d35e77ac94d80b08dc2'
|
||||
ref = '7d6aeab8b84c895f21f6c66b84a457b0fced9693'
|
||||
committer = Gollum::Committer.new(@wiki)
|
||||
assert_equal ref, committer.parents.first.sha
|
||||
end
|
||||
|
||||
+19
-1
@@ -12,6 +12,10 @@ class FakePage
|
||||
::File.basename(@filepath, ::File.extname(@filepath))
|
||||
end
|
||||
|
||||
def filename
|
||||
::File.basename(@filepath)
|
||||
end
|
||||
|
||||
def path
|
||||
return @filepath
|
||||
end
|
||||
@@ -64,10 +68,24 @@ def write file, content
|
||||
end
|
||||
end
|
||||
|
||||
def to_html html
|
||||
# Remove blank nodes for proper formatting
|
||||
doc = Nokogiri.XML(html) do |cfg|
|
||||
cfg.default_xml.noblanks
|
||||
end
|
||||
|
||||
# Save as XHTML
|
||||
doc.to_xml( { :save_with => Nokogiri::XML::Node::SaveOptions::DEFAULT_XHTML, :indent => 2, :encoding => 'UTF-8' } )
|
||||
end
|
||||
|
||||
def check name, pages_array
|
||||
pages = FakePages.new pages_array
|
||||
expected = read name
|
||||
actual = view pages
|
||||
actual = to_html view pages
|
||||
|
||||
# Uncomment when updating tests
|
||||
# write name, actual
|
||||
|
||||
assert_equal expected, actual
|
||||
end
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ context "GitAccess" do
|
||||
assert @access.ref_map.empty?
|
||||
assert @access.tree_map.empty?
|
||||
@access.tree 'master'
|
||||
assert_equal({"master"=>"629aa678272b017a4d136d35e77ac94d80b08dc2"}, @access.ref_map)
|
||||
assert_equal({"master"=>"7d6aeab8b84c895f21f6c66b84a457b0fced9693"}, @access.ref_map)
|
||||
|
||||
@access.tree '1db89ebba7e2c14d93b94ff98cfa3708a4f0d4e3'
|
||||
map = @access.tree_map['1db89ebba7e2c14d93b94ff98cfa3708a4f0d4e3']
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
# ~*~ encoding: utf-8 ~*~
|
||||
require File.expand_path( '../helper', __FILE__ )
|
||||
require File.expand_path( '../wiki_factory', __FILE__ )
|
||||
|
||||
context "gitcode" do
|
||||
|
||||
def page_with_content c
|
||||
index = @wiki.repo.index
|
||||
index.add 'Sample-Html.md', c
|
||||
index.commit 'adding file html sample'
|
||||
|
||||
page = @wiki.page 'Sample Html'
|
||||
page
|
||||
end
|
||||
|
||||
setup do
|
||||
# context
|
||||
@wiki, @path, @cleanup = WikiFactory.create 'examples/test.git'
|
||||
|
||||
# given
|
||||
p = page_with_content "a\n\n```html:github/gollum/master/test/file_view/1_file.txt```\n\nb"
|
||||
|
||||
# when rendering the page
|
||||
@rendered = Gollum::Markup.new(p).render
|
||||
end
|
||||
|
||||
test 'that the rendered output is correctly fetched and rendered as html code' do
|
||||
assert_equal %Q{<p>a</p>\n\n<div class=\"highlight\"><pre><span class=\"nt\"><ol</span> <span class=\"na\">class=</span><span class=\"s\">\"tree\"</span><span class=\"nt\">></span>\n <span class=\"nt\"><li</span> <span class=\"na\">class=</span><span class=\"s\">\"file\"</span><span class=\"nt\">></span>\n <span class=\"nt\"><a</span> <span class=\"na\">href=</span><span class=\"s\">\"0\"</span><span class=\"nt\">><span</span> <span class=\"na\">class=</span><span class=\"s\">\"icon\"</span><span class=\"nt\">></span></span>0<span class=\"nt\"></a></span>\n <span class=\"nt\"></li></span>\n<span class=\"nt\"></ol></span>\n</pre></div>\n\n<p>b</p>}, @rendered
|
||||
end
|
||||
|
||||
test 'contents' do
|
||||
g = Gollum::Gitcode.new 'github/gollum/master/test/file_view/1_file.txt'
|
||||
|
||||
assert_equal g.contents, %{<ol class=\"tree\">\n <li class=\"file\">\n <a href=\"0\"><span class=\"icon\"></span>0</a>\n </li>\n</ol>\n}
|
||||
end
|
||||
|
||||
teardown do
|
||||
@cleanup.call
|
||||
end
|
||||
end
|
||||
+158
-55
@@ -1,17 +1,14 @@
|
||||
# ~*~ encoding: utf-8 ~*~
|
||||
require File.expand_path(File.join(File.dirname(__FILE__), "helper"))
|
||||
require File.expand_path( "../helper", __FILE__ )
|
||||
require File.expand_path( "../wiki_factory", __FILE__ )
|
||||
|
||||
context "Markup" do
|
||||
setup do
|
||||
@path = testpath("examples/test.git")
|
||||
FileUtils.rm_rf(@path)
|
||||
Grit::Repo.init_bare(@path)
|
||||
Gollum::Wiki.default_options = {:universal_toc => false}
|
||||
@wiki = Gollum::Wiki.new(@path)
|
||||
@wiki, @path, @teardown = WikiFactory.create 'examples/test.git'
|
||||
end
|
||||
|
||||
teardown do
|
||||
FileUtils.rm_r(File.join(File.dirname(__FILE__), *%w[examples test.git]))
|
||||
@teardown.call
|
||||
end
|
||||
|
||||
test "formats page from Wiki#pages" do
|
||||
@@ -58,6 +55,21 @@ context "Markup" do
|
||||
#
|
||||
#########################################################################
|
||||
|
||||
test "absolute link to non-existent page" do
|
||||
@wiki.write_page("linktest", :markdown, "[[/Page]]", commit_details)
|
||||
|
||||
page = @wiki.page("linktest")
|
||||
doc = Nokogiri::HTML page.formatted_data
|
||||
paras = doc / :p
|
||||
para = paras.first
|
||||
anchors = para / :a
|
||||
assert_equal 1, paras.size
|
||||
assert_equal 1, anchors.size
|
||||
assert_equal 'internal absent', anchors[0]['class']
|
||||
assert_equal '/Page', anchors[0]['href']
|
||||
assert_equal '/Page', anchors[0].text
|
||||
end
|
||||
|
||||
test "double page links no space" do
|
||||
@wiki.write_page("Bilbo Baggins", :markdown, "a [[Foo]][[Bar]] b", commit_details)
|
||||
|
||||
@@ -184,6 +196,84 @@ context "Markup" do
|
||||
assert_equal "<p><code>sed -i '' 's/[[:space:]]*$//'</code></p>", page.formatted_data
|
||||
end
|
||||
|
||||
test "regexp gsub! backref (#383)" do
|
||||
# bug only triggers on "```" syntax
|
||||
# not `code`
|
||||
page = 'test_rgx'
|
||||
@wiki.write_page(page, :markdown,
|
||||
(<<-'DATA'
|
||||
```
|
||||
rot13='tr '\''A-Za-z'\'' '\''N-ZA-Mn-za-m'\'
|
||||
```
|
||||
DATA
|
||||
), commit_details)
|
||||
output = @wiki.page(page).formatted_data
|
||||
expected = %Q{<pre><code> <div class=\"highlight\"><pre><span class=\"n\">rot13</span><span class=\"p\">=</span><span class=\"s\">'tr '</span><span class=\"o\">\\</span><span class=\"s\">''</span><span class=\"n\">A</span><span class=\"o\">-</span><span class=\"n\">Za</span><span class=\"o\">-</span><span class=\"n\">z</span><span class=\"o\">'\\</span><span class=\"s\">''</span> <span class=\"s\">'\\''N-ZA-Mn-za-m'</span><span class=\"o\">\\</span><span class=\"s\">'</span>\n</pre></div>\n</code></pre>}
|
||||
assert_equal expected, output
|
||||
end
|
||||
|
||||
# Issue #568
|
||||
test "tilde code blocks without a language" do
|
||||
page = 'test_rgx'
|
||||
@wiki.write_page(page, :markdown,
|
||||
%Q(~~~
|
||||
'hi'
|
||||
~~~
|
||||
), commit_details)
|
||||
output = @wiki.page(page).formatted_data
|
||||
expected = %Q{<div class=\"highlight\"><pre><span class=\"s\">'hi'</span>\n</pre></div>}
|
||||
assert_equal expected, output
|
||||
end
|
||||
|
||||
test "tilde code blocks #537" do
|
||||
page = 'test_rgx'
|
||||
@wiki.write_page(page, :markdown,
|
||||
%Q(~~~ {.ruby}
|
||||
'hi'
|
||||
~~~
|
||||
), commit_details)
|
||||
output = @wiki.page(page).formatted_data
|
||||
expected = %Q{<div class=\"highlight\"><pre><span class=\"s1\">'hi'</span>\n</pre></div>}
|
||||
assert_equal expected, output
|
||||
end
|
||||
|
||||
# Issue #537
|
||||
test "tilde code blocks with more than one class" do
|
||||
page = 'test_rgx'
|
||||
@wiki.write_page(page, :markdown,
|
||||
%Q(~~~ {#hi .ruby .sauce}
|
||||
'hi'
|
||||
~~~
|
||||
), commit_details)
|
||||
output = @wiki.page(page).formatted_data
|
||||
expected = %Q{<div class=\"highlight\"><pre><span class=\"s1\">'hi'</span>\n</pre></div>}
|
||||
assert_equal expected, output
|
||||
end
|
||||
|
||||
# Issue #537
|
||||
test "tilde code blocks with lots of tildes" do
|
||||
page = 'test_rgx'
|
||||
@wiki.write_page(page, :markdown,
|
||||
%Q(~~~~~~ {#hi .ruby .sauce}
|
||||
~~
|
||||
'hi'~
|
||||
~~~~~~
|
||||
), commit_details)
|
||||
output = @wiki.page(page).formatted_data
|
||||
expected = %Q{<div class=\"highlight\"><pre><span class=\"o\">~~</span>\n<span class=\"s1\">'hi'</span><span class=\"o\">~</span>\n</pre></div>}
|
||||
assert_equal expected, output
|
||||
end
|
||||
|
||||
test "four space indented code block" do
|
||||
page = 'test_four'
|
||||
@wiki.write_page(page, :markdown,
|
||||
%( test
|
||||
test), commit_details)
|
||||
output = @wiki.page(page).formatted_data
|
||||
expected = %(<pre><code>test\ntest\n</code></pre>)
|
||||
assert_equal expected, output
|
||||
end
|
||||
|
||||
test "wiki link within code block" do
|
||||
@wiki.write_page("Potato", :markdown, " sed -i '' 's/[[:space:]]*$//'", commit_details)
|
||||
page = @wiki.page("Potato")
|
||||
@@ -209,7 +299,7 @@ context "Markup" do
|
||||
|
||||
page = @wiki.page(name)
|
||||
output = page.formatted_data
|
||||
assert_equal %{<p>a <img src="#{scheme}://example.com/bilbo.jpg"> b</p>}, output
|
||||
assert_equal %{<p>a <img src=\"#{scheme}://example.com/bilbo.jpg\" /> b</p>}, output
|
||||
end
|
||||
end
|
||||
|
||||
@@ -220,7 +310,7 @@ context "Markup" do
|
||||
|
||||
page = @wiki.page(name)
|
||||
output = page.formatted_data
|
||||
assert_equal %{<p>a <img src="#{scheme}://example.com/bilbo.JPG"> b</p>}, output
|
||||
assert_equal %{<p>a <img src=\"#{scheme}://example.com/bilbo.JPG\" /> b</p>}, output
|
||||
end
|
||||
end
|
||||
|
||||
@@ -232,7 +322,7 @@ context "Markup" do
|
||||
@wiki.write_page("Bilbo Baggins", :markdown, "a [[/alpha.jpg]] [[a | /alpha.jpg]] b", commit_details)
|
||||
|
||||
page = @wiki.page("Bilbo Baggins")
|
||||
assert_equal %{<p>a <img src="/wiki/alpha.jpg"><a href="/wiki/alpha.jpg">a</a> b</p>}, page.formatted_data
|
||||
assert_equal %{<p>a <img src=\"/wiki/alpha.jpg\" /><a href=\"/wiki/alpha.jpg\">a</a> b</p>}, page.formatted_data
|
||||
end
|
||||
|
||||
test "image with relative path on root" do
|
||||
@@ -243,7 +333,7 @@ context "Markup" do
|
||||
index.commit("Add alpha.jpg")
|
||||
|
||||
page = @wiki.page("Bilbo Baggins")
|
||||
assert_equal %{<p>a <img src="/wiki/alpha.jpg"><a href="/wiki/alpha.jpg">a</a> b</p>}, page.formatted_data
|
||||
assert_equal %Q{<p>a <img src=\"/wiki/alpha.jpg\" /><a href=\"/wiki/alpha.jpg\">a</a> b</p>}, page.formatted_data
|
||||
end
|
||||
|
||||
test "image with relative path" do
|
||||
@@ -255,7 +345,7 @@ context "Markup" do
|
||||
|
||||
page = @wiki.page("Bilbo Baggins")
|
||||
output = page.formatted_data
|
||||
assert_equal %{<p>a <img src="/wiki/greek/alpha.jpg"><a href="/wiki/greek/alpha.jpg">a</a> b</p>}, output
|
||||
assert_equal %{<p>a <img src=\"/wiki/greek/alpha.jpg\" /><a href=\"/wiki/greek/alpha.jpg\">a</a> b</p>}, output
|
||||
end
|
||||
|
||||
test "image with absolute path on a preview" do
|
||||
@@ -265,7 +355,7 @@ context "Markup" do
|
||||
index.commit("Add alpha.jpg")
|
||||
|
||||
page = @wiki.preview_page("Test", "a [[/alpha.jpg]] b", :markdown)
|
||||
assert_equal %{<p>a <img src="/wiki/alpha.jpg"> b</p>}, page.formatted_data
|
||||
assert_equal %{<p>a <img src=\"/wiki/alpha.jpg\" /> b</p>}, page.formatted_data
|
||||
end
|
||||
|
||||
test "image with relative path on a preview" do
|
||||
@@ -276,12 +366,12 @@ context "Markup" do
|
||||
index.commit("Add alpha.jpg")
|
||||
|
||||
page = @wiki.preview_page("Test", "a [[alpha.jpg]] [[greek/alpha.jpg]] b", :markdown)
|
||||
assert_equal %{<p>a <img src="/wiki/alpha.jpg"><img src="/wiki/greek/alpha.jpg"> b</p>}, page.formatted_data
|
||||
assert_equal %{<p>a <img src=\"/wiki/alpha.jpg\" /><img src=\"/wiki/greek/alpha.jpg\" /> b</p>}, page.formatted_data
|
||||
end
|
||||
|
||||
test "image with alt" do
|
||||
content = "a [[alpha.jpg|alt=Alpha Dog]] b"
|
||||
output = %{<p>a <img src="/greek/alpha.jpg" alt="Alpha Dog"> b</p>}
|
||||
output = %{<p>a<imgsrc=\"/greek/alpha.jpg\"alt=\"AlphaDog\"/>b</p>}
|
||||
relative_image(content, output)
|
||||
end
|
||||
|
||||
@@ -289,7 +379,7 @@ context "Markup" do
|
||||
%w{em px}.each do |unit|
|
||||
%w{width height}.each do |dim|
|
||||
content = "a [[alpha.jpg|#{dim}=100#{unit}]] b"
|
||||
output = "<p>a <img src=\"/greek/alpha.jpg\" #{dim}=\"100#{unit}\"> b</p>"
|
||||
output = "<p>a<imgsrc=\"/greek/alpha.jpg\"#{dim}=\"100#{unit}\"/>b</p>"
|
||||
relative_image(content, output)
|
||||
end
|
||||
end
|
||||
@@ -298,7 +388,7 @@ context "Markup" do
|
||||
test "image with bogus dimension" do
|
||||
%w{width height}.each do |dim|
|
||||
content = "a [[alpha.jpg|#{dim}=100]] b"
|
||||
output = "<p>a <img src=\"/greek/alpha.jpg\"> b</p>"
|
||||
output = "<p>a<imgsrc=\"/greek/alpha.jpg\"/>b</p>"
|
||||
relative_image(content, output)
|
||||
end
|
||||
end
|
||||
@@ -306,7 +396,7 @@ context "Markup" do
|
||||
test "image with vertical align" do
|
||||
%w{top texttop middle absmiddle bottom absbottom baseline}.each do |align|
|
||||
content = "a [[alpha.jpg|align=#{align}]] b"
|
||||
output = "<p>a <img src=\"/greek/alpha.jpg\" align=\"#{align}\"> b</p>"
|
||||
output = %Q{<p>a<imgsrc=\"/greek/alpha.jpg\"align=\"#{align}\"/>b</p>}
|
||||
relative_image(content, output)
|
||||
end
|
||||
end
|
||||
@@ -314,40 +404,40 @@ context "Markup" do
|
||||
test "image with horizontal align" do
|
||||
%w{left center right}.each do |align|
|
||||
content = "a [[alpha.jpg|align=#{align}]] b"
|
||||
output = "<p>a <span class=\"align-#{align}\"><span><img src=\"/greek/alpha.jpg\"></span></span> b</p>"
|
||||
output = "<p>a<spanclass=\"align-#{align}\"><span><imgsrc=\"/greek/alpha.jpg\"/></span></span>b</p>"
|
||||
relative_image(content, output)
|
||||
end
|
||||
end
|
||||
|
||||
test "image with float" do
|
||||
content = "a\n\n[[alpha.jpg|float]]\n\nb"
|
||||
output = "<p>a</p>\n\n<p><span class=\"float-left\"><span><img src=\"/greek/alpha.jpg\"></span></span></p>\n\n<p>b</p>"
|
||||
output = "<p>a</p><p><spanclass=\"float-left\"><span><imgsrc=\"/greek/alpha.jpg\"/></span></span></p><p>b</p>"
|
||||
relative_image(content, output)
|
||||
end
|
||||
|
||||
test "image with float and align" do
|
||||
%w{left right}.each do |align|
|
||||
content = "a\n\n[[alpha.jpg|float|align=#{align}]]\n\nb"
|
||||
output = "<p>a</p>\n\n<p><span class=\"float-#{align}\"><span><img src=\"/greek/alpha.jpg\"></span></span></p>\n\n<p>b</p>"
|
||||
output = "<p>a</p><p><spanclass=\"float-#{align}\"><span><imgsrc=\"/greek/alpha.jpg\"/></span></span></p><p>b</p>"
|
||||
relative_image(content, output)
|
||||
end
|
||||
end
|
||||
|
||||
test "image with frame" do
|
||||
content = "a\n\n[[alpha.jpg|frame]]\n\nb"
|
||||
output = "<p>a</p>\n\n<p><span class=\"frame\"><span><img src=\"/greek/alpha.jpg\"></span></span></p>\n\n<p>b</p>"
|
||||
output = "<p>a</p><p><spanclass=\"frame\"><span><imgsrc=\"/greek/alpha.jpg\"/></span></span></p><p>b</p>"
|
||||
relative_image(content, output)
|
||||
end
|
||||
|
||||
test "absolute image with frame" do
|
||||
content = "a\n\n[[http://example.com/bilbo.jpg|frame]]\n\nb"
|
||||
output = "<p>a</p>\n\n<p><span class=\"frame\"><span><img src=\"http://example.com/bilbo.jpg\"></span></span></p>\n\n<p>b</p>"
|
||||
output = "<p>a</p><p><spanclass=\"frame\"><span><imgsrc=\"http://example.com/bilbo.jpg\"/></span></span></p><p>b</p>"
|
||||
relative_image(content, output)
|
||||
end
|
||||
|
||||
test "image with frame and alt" do
|
||||
content = "a\n\n[[alpha.jpg|frame|alt=Alpha]]\n\nb"
|
||||
output = "<p>a</p>\n\n<p><span class=\"frame\"><span><img src=\"/greek/alpha.jpg\" alt=\"Alpha\"><span>Alpha</span></span></span></p>\n\n<p>b</p>"
|
||||
output = "<p>a</p><p><spanclass=\"frame\"><span><imgsrc=\"/greek/alpha.jpg\"alt=\"Alpha\"/><span>Alpha</span></span></span></p><p>b</p>"
|
||||
relative_image(content, output)
|
||||
end
|
||||
|
||||
@@ -394,11 +484,9 @@ context "Markup" do
|
||||
#
|
||||
#########################################################################
|
||||
|
||||
test "code blocks" do
|
||||
test "regular code blocks" do
|
||||
content = "a\n\n```ruby\nx = 1\n```\n\nb"
|
||||
output = "<p>a</p>\n\n<div class=\"highlight\">\n<pre>" +
|
||||
"<span class=\"n\">x</span> <span class=\"o\">=</span> " +
|
||||
"<span class=\"mi\">1</span>\n</pre>\n</div>\n\n\n<p>b</p>"
|
||||
output = %Q{<p>a</p>\n\n<div class=\"highlight\"><pre><span class=\"n\">x</span> <span class=\"o\">=</span> <span class=\"mi\">1</span>\n</pre></div>\n\n<p>b</p>}
|
||||
|
||||
index = @wiki.repo.index
|
||||
index.add("Bilbo-Baggins.md", content)
|
||||
@@ -411,9 +499,7 @@ context "Markup" do
|
||||
|
||||
test "code blocks with carriage returns" do
|
||||
content = "a\r\n\r\n```ruby\r\nx = 1\r\n```\r\n\r\nb"
|
||||
output = "<p>a</p>\n\n<div class=\"highlight\">\n<pre>" +
|
||||
"<span class=\"n\">x</span> <span class=\"o\">=</span> " +
|
||||
"<span class=\"mi\">1</span>\n</pre>\n</div>\n\n\n<p>b</p>"
|
||||
output = %Q{<p>a</p>\n\n<div class=\"highlight\"><pre><span class=\"n\">x</span> <span class=\"o\">=</span> <span class=\"mi\">1</span>\n</pre></div>\n\n<p>b</p>}
|
||||
|
||||
index = @wiki.repo.index
|
||||
index.add("Bilbo-Baggins.md", content)
|
||||
@@ -444,9 +530,7 @@ context "Markup" do
|
||||
|
||||
test "code blocks with multibyte caracters indent" do
|
||||
content = "a\n\n```ruby\ns = 'やくしまるえつこ'\n```\n\nb"
|
||||
output = "<p>a</p>\n\n<div class=\"highlight\">\n<pre><span class=\"n\">" +
|
||||
"s</span> <span class=\"o\">=</span> <span class=\"s1\">'やくしまるえつこ'" +
|
||||
"</span>\n</pre>\n</div>\n\n\n<p>b</p>"
|
||||
output = %Q{<p>a</p>\n\n<div class=\"highlight\"><pre><span class=\"n\">s</span> <span class=\"o\">=</span> <span class=\"s1\">'やくしまるえつこ'</span>\n</pre></div>\n\n<p>b</p>}
|
||||
index = @wiki.repo.index
|
||||
index.add("Bilbo-Baggins.md", content)
|
||||
index.commit("Add alpha.jpg")
|
||||
@@ -498,6 +582,43 @@ np.array([[2,2],[1,3]],np.float)
|
||||
assert_match /\(\[\[/, rendered, "#{markup_class} parses out wiki links\n#{rendered}"
|
||||
end
|
||||
|
||||
test "embed code is escaped" do
|
||||
@wiki.write_page("script", :markdown, "a <script></script> b", commit_details)
|
||||
@wiki.write_page("page", :markdown, "```html:script```", commit_details)
|
||||
|
||||
output_script = @wiki.page("script").formatted_data
|
||||
output_page = @wiki.page("page").formatted_data
|
||||
|
||||
assert_equal %Q{<p>a b</p>}, output_script
|
||||
assert_equal %Q{<div class=\"highlight\"><pre><span class=\"nt\"><p></span>a b<span class=\"nt\"></p></span>\n</pre></div>}, output_page
|
||||
end
|
||||
|
||||
test "embed code page absolute link" do
|
||||
@wiki.write_page("base", :markdown, "a\n!base\b", commit_details)
|
||||
@wiki.write_page("a", :markdown, "a\n```html:/base```\b", commit_details)
|
||||
|
||||
page = @wiki.page("a")
|
||||
output = page.formatted_data
|
||||
assert_equal %Q{<p>a\n</p><div class=\"highlight\"><pre><span class=\"nt\"><p></span>a\n!base<span class=\"nt\"></p></span>\n</pre></div>\n}, output
|
||||
end
|
||||
|
||||
test "embed code page relative link" do
|
||||
@wiki.write_page("base", :markdown, "a\n!rel\b", commit_details)
|
||||
@wiki.write_page("a", :markdown, "a\n```html:base```\b", commit_details)
|
||||
|
||||
page = @wiki.page("a")
|
||||
output = page.formatted_data
|
||||
assert_equal %Q{<p>a\n</p><div class=\"highlight\"><pre><span class=\"nt\"><p></span>a\n!rel<span class=\"nt\"></p></span>\n</pre></div>\n}, output
|
||||
end
|
||||
|
||||
test "code block in unsupported language" do
|
||||
@wiki.write_page("a", :markdown, "a\n```nonexistent\ncode\n```\nb", commit_details)
|
||||
|
||||
page = @wiki.page("a")
|
||||
output = page.formatted_data
|
||||
assert_equal %Q{<p>a\ncode\nb</p>}, output
|
||||
end
|
||||
|
||||
#########################################################################
|
||||
#
|
||||
# Web Sequence Diagrams
|
||||
@@ -535,7 +656,7 @@ np.array([[2,2],[1,3]],np.float)
|
||||
page = @wiki.page("Bilbo Baggins")
|
||||
rendered = Gollum::Markup.new(page).render
|
||||
assert_equal output, rendered
|
||||
assert_equal result, page.meta_data
|
||||
assert_equal result, page.metadata
|
||||
end
|
||||
|
||||
test "metadata blocks with newline" do
|
||||
@@ -550,7 +671,7 @@ np.array([[2,2],[1,3]],np.float)
|
||||
page = @wiki.page("Bilbo Baggins")
|
||||
rendered = Gollum::Markup.new(page).render
|
||||
assert_equal output, rendered
|
||||
assert_equal result, page.meta_data
|
||||
assert_equal result, page.metadata
|
||||
end
|
||||
|
||||
test "metadata sanitation" do
|
||||
@@ -565,7 +686,7 @@ np.array([[2,2],[1,3]],np.float)
|
||||
page = @wiki.page("Bilbo Baggins")
|
||||
rendered = Gollum::Markup.new(page).render
|
||||
assert_equal output, rendered
|
||||
assert_equal result, page.meta_data
|
||||
assert_equal result, page.metadata
|
||||
end
|
||||
|
||||
#########################################################################
|
||||
@@ -662,24 +783,6 @@ end
|
||||
]
|
||||
end
|
||||
|
||||
#########################################################################
|
||||
#
|
||||
# TeX
|
||||
#
|
||||
#########################################################################
|
||||
|
||||
test "TeX block syntax" do
|
||||
content = 'a \[ a^2 \] b'
|
||||
output = "<p>a<imgwidth=\"15\"height=\"16\"style=\"vertical-align:-1px;\"src=\"/_tex.png?type=block&data=YV4y\"alt=\"a^2\"/>b</p>"
|
||||
compare(content, output, 'md')
|
||||
end
|
||||
|
||||
test "TeX inline syntax" do
|
||||
content = 'a \( a^2 \) b'
|
||||
output = "<p>a<imgwidth=\"15\"height=\"16\"style=\"vertical-align:-1px;\"src=\"/_tex.png?type=inline&data=YV4y\"alt=\"a^2\"/>b</p>"
|
||||
compare(content, output, 'md')
|
||||
end
|
||||
|
||||
#########################################################################
|
||||
# Asciidoc
|
||||
#########################################################################
|
||||
|
||||
+10
-2
@@ -16,7 +16,7 @@ context "Page" do
|
||||
page = @wiki.page('Bilbo Baggins')
|
||||
assert_equal Gollum::Page, page.class
|
||||
assert page.raw_data =~ /^# Bilbo Baggins\n\nBilbo Baggins/
|
||||
assert page.formatted_data =~ %r{<h1>Bilbo Baggins<a class="anchor" id="Bilbo-Baggins" href="#Bilbo-Baggins"></a>\n</h1>\n\n<p>Bilbo Baggins}
|
||||
assert page.formatted_data =~ %r{<h1>Bilbo Baggins<a class="anchor" id="Bilbo-Baggins" href="#Bilbo-Baggins"></a></h1>\n\n<p>Bilbo Baggins}
|
||||
assert_equal 'Bilbo-Baggins.md', page.path
|
||||
assert_equal :markdown, page.format
|
||||
assert_equal @wiki.repo.commits.first.id, page.version.id
|
||||
@@ -99,7 +99,8 @@ context "Page" do
|
||||
test "cname" do
|
||||
assert_equal "Foo", Gollum::Page.cname("Foo")
|
||||
assert_equal "Foo-Bar", Gollum::Page.cname("Foo Bar")
|
||||
assert_equal "Foo---Bar", Gollum::Page.cname("Foo / Bar")
|
||||
# / is now a directory delimiter so it must be preserved
|
||||
assert_equal "Foo-/-Bar", Gollum::Page.cname("Foo / Bar")
|
||||
assert_equal "José", Gollum::Page.cname("José")
|
||||
assert_equal "モルドール", Gollum::Page.cname("モルドール")
|
||||
end
|
||||
@@ -226,5 +227,12 @@ context "within a sub-directory" do
|
||||
assert page.header.raw_data =~ /^Hobbits/
|
||||
assert page.footer.raw_data =~ /^Lord of the Rings/
|
||||
end
|
||||
|
||||
test "get metadata on page" do
|
||||
page = @wiki.page('Elrond')
|
||||
assert_equal Gollum::Page, page.class
|
||||
assert_equal 'elf', page.metadata['race']
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -39,7 +39,6 @@ context "Page Reverting" do
|
||||
assert_equal "INITIAL", body=page2.raw_data.strip
|
||||
assert_equal body, File.read(File.join(@path, "B.md")).strip
|
||||
end
|
||||
=end
|
||||
|
||||
test "reverts multiple commits for a page" do
|
||||
page1 = @wiki.page('A')
|
||||
@@ -49,6 +48,7 @@ context "Page Reverting" do
|
||||
assert_equal "INITIAL", body=page2.raw_data.strip
|
||||
assert_equal body, File.read(File.join(@path, "A.md")).strip
|
||||
end
|
||||
=end
|
||||
|
||||
test "cannot revert conflicting commit" do
|
||||
page1 = @wiki.page('A')
|
||||
|
||||
+24
-7
@@ -29,19 +29,36 @@ context "Unicode Support" do
|
||||
assert_equal "# 한글", utf8(page.raw_data)
|
||||
|
||||
# markup.rb
|
||||
# #简介
|
||||
# href.gsub('%', '%25') so the anchor works in Firefox.
|
||||
# <a href="#%25ED%2595%259C%25EA%25B8%2580" id="%ED%95%9C%EA%B8%80" class="anchor"></a>
|
||||
doc = Nokogiri::HTML page.formatted_data
|
||||
h1s = doc / :h1
|
||||
h1 = h1s.first
|
||||
anchors = h1 / :a
|
||||
assert_equal 1, h1s.size
|
||||
assert_equal 1, anchors.size
|
||||
assert_equal '#%25ED%2595%259C%25EA%25B8%2580', anchors[0]['href']
|
||||
assert_equal '%ED%95%9C%EA%B8%80', anchors[0]['id']
|
||||
assert_equal 'anchor', anchors[0]['class']
|
||||
assert_equal '', anchors[0].text
|
||||
assert_equal '#한글', anchors[0]['href']
|
||||
assert_equal '한글', anchors[0]['id']
|
||||
assert_equal 'anchor', anchors[0]['class']
|
||||
assert_equal '', anchors[0].text
|
||||
end
|
||||
|
||||
test "create and read non-latin page with anchor 2" do
|
||||
@wiki.write_page("test", :markdown, "# \"La\" faune d'Édiacara")
|
||||
|
||||
page = @wiki.page("test")
|
||||
assert_equal Gollum::Page, page.class
|
||||
assert_equal "# \"La\" faune d'Édiacara", utf8(page.raw_data)
|
||||
|
||||
# markup.rb test: ', ", É
|
||||
doc = Nokogiri::HTML page.formatted_data
|
||||
h1s = doc / :h1
|
||||
h1 = h1s.first
|
||||
anchors = h1 / :a
|
||||
assert_equal 1, h1s.size
|
||||
assert_equal 1, anchors.size
|
||||
assert_equal %q(#%22La%22-faune-d'Édiacara), anchors[0]['href']
|
||||
assert_equal %q(%22La%22-faune-d'Édiacara), anchors[0]['id']
|
||||
assert_equal 'anchor', anchors[0]['class']
|
||||
assert_equal '', anchors[0].text
|
||||
end
|
||||
|
||||
test "unicode with existing format rules" do
|
||||
|
||||
+19
-1
@@ -123,7 +123,7 @@ context "Wiki page previewing" do
|
||||
test "preview_page" do
|
||||
page = @wiki.preview_page("Test", "# Bilbo", :markdown)
|
||||
assert_equal "# Bilbo", page.raw_data
|
||||
assert_equal %Q{<h1>Bilbo<a class="anchor" id="Bilbo" href="#Bilbo"></a>\n</h1>}, page.formatted_data
|
||||
assert_equal %Q{<h1>Bilbo<a class=\"anchor\" id=\"Bilbo\" href=\"#Bilbo\"></a></h1>}, page.formatted_data
|
||||
assert_equal "Test.md", page.filename
|
||||
assert_equal "Test", page.name
|
||||
end
|
||||
@@ -142,6 +142,16 @@ context "Wiki TOC" do
|
||||
assert_equal '<h1>Bilbo<a class="anchor" id="Bilbo" href="#Bilbo"></a></h1>', page.formatted_data.gsub(/\n/,"")
|
||||
assert_equal %{<div class="toc"><div class="toc-title">Table of Contents</div><ul><li><a href="#Bilbo">Bilbo</a></li></ul></div>}, page.toc_data.gsub(/\n */,"")
|
||||
end
|
||||
|
||||
# Ensure ' creates valid links in TOC
|
||||
# Incorrect: <a href=\"#a\" b=\"\">
|
||||
# Correct: <a href=\"#a'b\">
|
||||
test "' in link" do
|
||||
page = @wiki.preview_page("Test", "# a'b", :markdown)
|
||||
assert_equal "# a'b", page.raw_data
|
||||
assert_equal %q{<h1>a'b<a class="anchor" id="a'b" href="#a'b"></a></h1>}, page.formatted_data.gsub(/\n/,"")
|
||||
assert_equal %{<div class=\"toc\"><div class=\"toc-title\">Table of Contents</div><ul><li><a href=\"#a'b\">a'b</a></li></ul></div>}, page.toc_data.gsub(/\n */,"")
|
||||
end
|
||||
end
|
||||
|
||||
context "Wiki page writing" do
|
||||
@@ -188,6 +198,14 @@ context "Wiki page writing" do
|
||||
assert_equal cd[:email], @wiki.repo.commits.first.author.email
|
||||
end
|
||||
|
||||
test "page title override with metadata" do
|
||||
@wiki.write_page("Gollum", :markdown, "<!-- --- title: Over -->", commit_details)
|
||||
|
||||
page = @wiki.page("Gollum")
|
||||
|
||||
assert_equal 'Over', page.url_path_title
|
||||
end
|
||||
|
||||
test "update page with format change" do
|
||||
@wiki.write_page("Gollum", :markdown, "# Gollum", commit_details)
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
class WikiFactory
|
||||
def self.create p
|
||||
path = testpath "examples/test.git"
|
||||
Grit::Repo.init_bare(path)
|
||||
Gollum::Wiki.default_options = {:universal_toc => false}
|
||||
cleanup = Proc.new { FileUtils.rm_r File.join(File.dirname(__FILE__), *%w[examples test.git]) }
|
||||
wiki = Gollum::Wiki.new(path)
|
||||
return wiki, path, cleanup
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user