Compare commits

...

17 Commits

Author SHA1 Message Date
benjamin wil bc490c64e5 Create locale helper for global translations
There are some translation strings we should use across multiple views.
Instead of duplicating the translations, we can use a different locale
helper method, `#tt`, to get a hash of all available translations.

Then, in a partial view like `pagination.mustache`, we can render
translations regardless of what the current view class is.

This commit adds the necessary helper, tests, and uses the new method to
render translations on the `pagination.mustache` template, which is used
by many other view classes (latest changes, history, and search).
2022-05-07 20:18:44 -07:00
benjamin wil 33ed562d1c Reset I18n load path after I18n helper tests 2022-05-07 19:38:00 -07:00
benjamin wil 3f4162e2cc Internationalize Views::Search templates 2022-05-07 19:16:19 -07:00
benjamin wil 489f6d7c0f Internationalize Views::Overview templates 2022-05-07 19:16:19 -07:00
benjamin wil 1548034a06 Internationalize Views::Layout templates 2022-05-07 19:16:19 -07:00
benjamin wil f90e7a81b8 Internationalize Views::LatestChanges templates 2022-05-07 19:16:19 -07:00
benjamin wil b9fef4175c Internationalize Views::History templates 2022-05-07 19:16:19 -07:00
benjamin wil dd722e9b06 Internationalize Views::Error templates 2022-05-07 19:16:19 -07:00
benjamin wil e60d4e397c Internationalize Views::Compare templates 2022-05-07 19:16:19 -07:00
benjamin wil 0d2ab11604 Include rdoc as a dependency (#1823)
We've had some reports (#1342, #1809) of `rdoc` not being installed
in some environments, causing Gollum to error in unpleasant ways.

This isn't an issue that's unique to Gollum, and I don't think `rdoc`
should actually be a hard dependency of this project.  But since we can
side-step the issue by requiring `rdoc`, something that most users who
install Gollum via RubyGems would already have installed, I don't think
this is a horrible solution.
2022-05-04 18:25:48 -07:00
Andreas Wachter ddc7dba0a2 Remove arm/v6 and v7 from the Docker builds (#1822)
* added platforms to actions, install libc6-compat for pi

* fix build problem for now. https://github.com/gollum/gollum/runs/6248371141
2022-05-03 08:15:09 -07:00
Andreas Wachter bc3503f374 added platforms to actions, install libc6-compat for pi (#1806) 2022-04-30 23:04:45 -07:00
benjamin wil 2dfe103687 Ensure example git repos are valid (#1821)
* Ensure example git repos are valid

It was reported in #1817 that the `lotr_migration.git` repository we use
in `test/test_migrate.rb` is not a valid git repository on when clone,
causing the test suite to fail when run locally.

The reason is because there is no `.git/refs` directory, meaning it's
not really a valid git repository at all. I noticed that the `empty.git`
example repository has the same problem.

This commit simply ensures that the directory structure of these example
repositories are persisted in git.

* Run `test_migrate` tests on CI

Now that we've resolved the issue with the invalid git repository in the
parent commit, we can run all of the tests in our CI environment.
2022-04-30 23:03:56 -07:00
benjamin wil 95d35d38da Switch from TestUnit to Minitest (#1805)
* Use `Minitest::Test`

`Test::Unit` is deprecated, and we can switch to `Minitest::Test` with
almost no side effects.

This commit does all of the work required to make Minitest tests run
with Gollum's existing test helpers.

* Change Minitest output format

- The `DefaultReporter` seems to have cleaner output than what we had
  before.
- `color: true` ensures things are colorized. It's pretty nice.

* Tweak test formatting; fix order-dependent failure

The order-dependent failure has been been commented in code.

After manually bisecting the test suite, I was able to determine that
the template cascade tests were leaving the `@@template_priority_path`
set to an overridden value in tests run afterward.

* Tweak setting initialization

I could not see a meaningful reason behind calling `forbid` so early in
the settings initialization block. But moving the `forbid` call until
later resolved this issue.

In the real world, I don't see how this would cause issues. But I found
that calling `forbid` when `wiki_options[:allow_editing]` was set to
false caused order-dependent test errors where Sprockets would end up
being badly configured and left without an initialized
`Sprockets::Environment` object, which is required by the
`sprockets-helpers` gem to resolve asset paths.

The test that would cause errors is also in this commit diff. I've
updated it to be a bit more readable.

I also took this opportunity to review and clean up the `@allow_editing`
assignment, which seemed a bit obfuscated.

* Update migration script to test run warnings

When running the entire test suite, many warnings would be output:

/Users/bw/Projects/gollum/test/test_migrate.rb:37: warning: already initialized constant HYPHENATE
/Users/bw/Projects/gollum/test/test_migrate.rb:37: warning: previous definition of HYPHENATE was here
/Users/bw/Projects/gollum/test/test_migrate.rb:37: warning: already initialized constant PAGE_FILE_DIR
/Users/bw/Projects/gollum/test/test_migrate.rb:37: warning: previous definition of PAGE_FILE_DIR was here
/Users/bw/Projects/gollum/bin/gollum-migrate-tags:91: warning: already initialized constant REPO
/Users/bw/Projects/gollum/bin/gollum-migrate-tags:91: warning: previous definition of REPO was here
/Users/bw/Projects/gollum/bin/gollum-migrate-tags:236: warning: already initialized constant TREE
/Users/bw/Projects/gollum/bin/gollum-migrate-tags:236: warning: previous definition of TREE was here
/Users/bw/Projects/gollum/test/test_migrate.rb:37: warning: already initialized constant PAGE_FILE_DIR
/Users/bw/Projects/gollum/test/test_migrate.rb:37: warning: previous definition of PAGE_FILE_DIR was here
/Users/bw/Projects/gollum/bin/gollum-migrate-tags:91: warning: already initialized constant REPO
/Users/bw/Projects/gollum/bin/gollum-migrate-tags:91: warning: previous definition of REPO was here
/Users/bw/Projects/gollum/bin/gollum-migrate-tags:236: warning: already initialized constant TREE
/Users/bw/Projects/gollum/bin/gollum-migrate-tags:236: warning: previous definition of TREE was here

While it's unlikely that end users would ever see these warnings, as
they'd only be running the migration script once, they will always be
shown in our local test runs and CI run output.

So instead of using constants in our migration script, I change the
script to use class variables instead. This should not effect the
functionality of the migration script whatsoever.

* Use `File.exist?` instead of `File.exists?`

In Ruby 3.x, `File.exists?` is deprecated and outputs a warning.

* Improve "allow editing" tests

While making changes to the test suite, I ran into some issues with
these tests failing on occasion.

I added some setup and teardown to help with this.

But one thing I did notice is that the word "Upload" appears in the
response body whether uploading is enabled or not, so I made these
assertions more specific to the HTML rather than other places the word
"Upload" might appear (which is related to Critic Markup).

* Do not attempt to modify frozen strings

Using `#gsub!` here now results in an error. I am not entirely sure why
this hasn't happened before, but the error is straightforward:

     FrozenError: can't modify frozen String: "Author %{author} is from %{location}"
        /home/runner/work/gollum/gollum/lib/gollum/views/helpers/locale_helpers.rb:45:in `gsub!'
        /home/runner/work/gollum/gollum/lib/gollum/views/helpers/locale_helpers.rb:45:in `fill_argument_content'
        /home/runner/work/gollum/gollum/lib/gollum/views/helpers/locale_helpers.rb:37:in `block in autofill'
        /home/runner/work/gollum/gollum/lib/gollum/views/helpers/locale_helpers.rb:33:in `each'
        /home/runner/work/gollum/gollum/lib/gollum/views/helpers/locale_helpers.rb:33:in `map'
        /home/runner/work/gollum/gollum/lib/gollum/views/helpers/locale_helpers.rb:33:in `autofill'
        /home/runner/work/gollum/gollum/lib/gollum/views/helpers/locale_helpers.rb:35:in `block in autofill'
        /home/runner/work/gollum/gollum/lib/gollum/views/helpers/locale_helpers.rb:33:in `each'
        /home/runner/work/gollum/gollum/lib/gollum/views/helpers/locale_helpers.rb:33:in `map'
        /home/runner/work/gollum/gollum/lib/gollum/views/helpers/locale_helpers.rb:33:in `autofill'
        /home/runner/work/gollum/gollum/lib/gollum/views/helpers/locale_helpers.rb:21:in `t'
        /home/runner/work/gollum/gollum/test/gollum/views/test_locale_helper.rb:95:in `block (4 levels) in <top (required)>'

`#gsub!` attempts to modify a string in-place, which does not work when
a string is frozen. It seems that in some Ruby environments, strings
from YAML files are frozen.

* Fix another order-dependent test failure

Very occasionally, this test fails due to `Precious::App` settings set
in previous tests. You can reproduce this failure using this seed:

    bundle exec rake TESTOPTS="--seed=42898"
2022-04-27 08:25:54 -07:00
Tevin 81c90e55a7 Add page context to template filter, resolves #1603 (#1818)
* Add a test for template filter
* Add a test for template filter with page parameter
* Passing page as a parameter to template filter
2022-04-25 09:44:19 +02:00
mishina 3f0b61081b Add Ruby 3.1 to the CI matrix (#1812)
* Enclose all the version numbers in quotes
2022-03-23 15:30:49 +01:00
mishina ecc317886a Remove fields from gemspec that should not be set (#1811) 2022-03-23 13:27:54 +01:00
32 changed files with 657 additions and 339 deletions
+1
View File
@@ -45,5 +45,6 @@ jobs:
tags: ${{ env.DEPLOY_NAME }}
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache
platforms: linux/amd64, linux/arm64
- name: Image digest
run: echo ${{ steps.docker_build.outputs.digest }}
+1 -1
View File
@@ -30,7 +30,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
ruby: [2.6, 2.7, 3.0]
ruby: ['2.6', '2.7', '3.0', '3.1']
steps:
- name: Check out repository code
uses: actions/checkout@v2
+2 -1
View File
@@ -32,7 +32,8 @@ COPY --from=builder /usr/local/bundle/ /usr/local/bundle/
RUN apk add \
bash \
git
git \
libc6-compat
VOLUME /wiki
WORKDIR /wiki
+1 -13
View File
@@ -1,6 +1,5 @@
require 'rubygems'
require 'rake'
require 'date'
#############################################################################
#
@@ -38,14 +37,6 @@ def bump_version
new_version
end
def date
Date.today.to_s
end
def rubyforge_project
name
end
def gemspec_file
"#{name}.gemspec"
end
@@ -143,12 +134,9 @@ task :gemspec => :validate do
spec = File.read(gemspec_file)
head, manifest, tail = spec.split(" # = MANIFEST =\n")
# replace name version and date
# replace name and version
replace_header(head, :name)
replace_header(head, :version)
replace_header(head, :date)
#comment this out if your rubyforge_project has a different name
replace_header(head, :rubyforge_project)
# determine file list from git ls-files
files = `git ls-files`.
+40 -28
View File
@@ -11,8 +11,11 @@ migrate_options = {
:hyphenate => true
}
def setting(const)
Object.const_defined?(const.upcase) && Object.const_get(const.upcase)
def setting(variable_name)
class_variable_name = :"@@#{variable_name.to_s}"
Object.class_variable_defined?(class_variable_name) &&
Object.class_variable_get(class_variable_name)
end
opts = OptionParser.new do |opts|
@@ -25,7 +28,7 @@ It finds and repairs Gollum link tags that no longer work under 5.x for three re
* 5.x wiki internal links are no longer 'global'.
* NB: you can use the --lenient-tag-lookup option in gollum >= 5.x to enable 4.x-backwards compatible tags.
See https://github.com/gollum/gollum/wiki/5.0-release-notes#filename-handling for more information.
Usage of this script comes without any warranty.
@@ -38,7 +41,7 @@ You can use the --page-file-dir and --config options as you would normally with
Requires a non-bare repository. Recommended usage:
1. Clone your wiki's repository to create a backup.
2. Run this script on your cloned repo.
2. Run this script on your cloned repo.
3. If all looks sane, run the script with the --write option. This will overwrite files in your working directory, but not commit the changes, so you have time to review them.
4. Do a 'git diff' to inspect the changes.
5. Commit the changes if all looks sane, and push/pull them back into your original repo.
@@ -52,23 +55,23 @@ EOF
opts.on('--page-file-dir [PATH]', 'Specify the subdirectory for all pages. Default: repository root.') do |path|
wiki_options[:page_file_dir] = path
end
opts.on('--prefer-relative-links', 'When specified, will try to replace broken links with relative links (\'[[Foo/Bar]]\' instead of \'[[/Subdir/Foo/Bar]]\') where possible.') do
migrate_options[:prefer_relative] = true
end
opts.on('--hyphenate', 'Default. Repair links that use spaces instead of hyphens: [[Bilbo Baggins]] -> [[Bilbo-Baggins]]') do
migrate_options[:hyphenate] = true
end
opts.on('--no-hyphenate', 'Turn off the --hyphenate option.') do
migrate_options[:hyphenate] = false
end
opts.on('--run-silent', 'Don\'t output anything.') do
migrate_options[:run_silent] = true
end
opts.on('--write', 'No dry run: actually perform the substitutions.') do
migrate_options[:no_dry_run] = true
end
@@ -78,8 +81,11 @@ end
begin
opts.parse!
migrate_options.each do |setting, value|
const = setting.to_s.upcase
Object.const_set(const, value) unless Object.const_defined?(const)
variable_name = :"@@#{setting.to_s}"
unless Object.class_variable_defined?(variable_name)
Object.class_variable_set(variable_name, value)
end
end
wiki_options[:page_file_dir] = setting(:page_file_dir) ? setting(:page_file_dir) : wiki_options[:page_file_dir] # Allow settings :page_file_dir through PAGE_FILE_DIR constant.
rescue OptionParser::InvalidOption
@@ -88,7 +94,7 @@ rescue OptionParser::InvalidOption
exit
end
REPO = ARGV[0] || Dir.pwd
wiki_directory = ARGV[0] || Dir.pwd
require 'gollum-lib'
@@ -98,7 +104,7 @@ if cfg = options[:config]
cfg = File.join(Dir.getwd, cfg) unless cfg.slice(0) == File::SEPARATOR
require cfg
end
class Gollum::Filter::CodeMigrator < Gollum::Filter::Code
def extract(data)
case @markup.format
@@ -126,7 +132,7 @@ class Gollum::Filter::CodeMigrator < Gollum::Filter::Code
next '' if m_end.length < m_start.length
lang = m_lang ? m_lang.strip.split.first : nil
cache_codeblock($~.to_s)
end
end
end
data.gsub!(/^([ ]{0,3})``` ?([^\r\n]+)?\r?\n(.+?)\r?\n[ ]{0,3}```[ \t]*\r?$/m) do
@@ -134,7 +140,7 @@ class Gollum::Filter::CodeMigrator < Gollum::Filter::Code
end
data
end
def process(data)
return data if data.nil? || data.size.zero? || @map.size.zero?
@map.each do |id, block| ## Just put the code blocks back in verbatim
@@ -142,23 +148,23 @@ class Gollum::Filter::CodeMigrator < Gollum::Filter::Code
end
data
end
def cache_codeblock(block)
id = "#{open_pattern}#{Digest::SHA1.hexdigest(block)}#{close_pattern}"
@map[id] = block
id
end
end
class ::Gollum::Filter::TagMigrator < Gollum::Filter::Tags
def process_tag(tag)
link_part, extra = parse_tag_parts(tag)
orig_tag = %{[[#{tag}]]}
return orig_tag if link_part.nil?
img_args = extra ? [extra, link_part] : [link_part]
mime = MIME::Types.type_for(::File.extname(img_args.first.to_s)).first
# For any kind of tag other than an internal link: just return the tag.
if tag =~ /^_TOC_/ || link_part =~ /^_$/ || link_part =~ /^#{INCLUDE_TAG}/ || (mime && mime.content_type =~ /^image/) || process_external_link_tag(link_part, extra) || process_file_link_tag(link_part, extra)
return orig_tag
@@ -168,7 +174,7 @@ class ::Gollum::Filter::TagMigrator < Gollum::Filter::Tags
link = link_part
page = find_page_or_file_from_path(link)
anchor = nil
if page.nil? # No match yet, now try finding the page with anchor removed
if pos = link.rindex('#')
anchor = link[pos..-1]
@@ -203,12 +209,12 @@ class ::Gollum::Filter::TagMigrator < Gollum::Filter::Tags
pick = possibles.first
return tag_for_pick(pick, orig_tag, extra, anchor, @markup.page.path)
end
end
end
private
def tag_for_pick(pick, orig_tag, extra, anchor, linking_page_path)
pick = if setting(:prefer_relative)
overlapping_path = Pathname.new(linking_page_path).dirname.to_s
@@ -220,7 +226,7 @@ class ::Gollum::Filter::TagMigrator < Gollum::Filter::Tags
end
new_tag = extra.nil? ? %{[[#{pick}#{anchor}]]} : %{[[#{extra}|#{pick}#{anchor}]]}
log(:info, "#{@markup.page.path}: Changing #{orig_tag} -> #{new_tag}")
new_tag
new_tag
end
end
@@ -232,8 +238,12 @@ end
filter_chain = [:PlainTextMigrator, :CodeMigrator, :TagMigrator]
wiki = ::Gollum::Wiki.new(REPO, wiki_options.merge({:filter_chain => filter_chain}))
TREE = wiki.tree_list(wiki.ref, true, true).map {|file| ::File.join('/', file.path)}
wiki = ::Gollum::Wiki.new(wiki_directory, wiki_options.merge({:filter_chain => filter_chain}))
Object.class_variable_set(
:"@@wiki_tree",
wiki.tree_list(wiki.ref, true, true).map {|file| ::File.join('/', file.path)}
)
def find_linked(link)
link.gsub!(' ', '-') if setting(:hyphenate) # Match paths containing dashes instead of spaces
@@ -243,7 +253,9 @@ def find_linked(link)
test_path = ::File.extname(link).empty? ? /#{link}\..+/ : link
# Select pages from the wiki whose path =~ 'Foo/Bar/Samwi.*'
# Match case-insenstively to mimic 4.x behavior!
TREE.select {|path| path =~ /^\/(.*\/)?#{test_path}/i}
Object.class_variable_get(:"@@wiki_tree").select { |path|
path =~ /^\/(.*\/)?#{test_path}/i
}
end
def log(kind, msg = nil)
@@ -268,4 +280,4 @@ wiki.pages.each do |page|
f.close
end
log(:none, '====')
end
end
+1 -3
View File
@@ -1,12 +1,9 @@
Gem::Specification.new do |s|
s.specification_version = 2 if s.respond_to? :specification_version=
s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to? :required_rubygems_version=
s.rubygems_version = '1.3.5'
s.required_ruby_version = '>= 2.6'
s.name = 'gollum'
s.version = '5.2.3'
s.date = '2021-04-18'
s.license = 'MIT'
s.summary = 'A simple, Git-powered wiki.'
@@ -23,6 +20,7 @@ Gem::Specification.new do |s|
s.rdoc_options = ['--charset=UTF-8']
s.extra_rdoc_files = %w[README.md LICENSE]
s.add_dependency 'rdoc', '~> 6'
s.add_dependency 'gollum-lib', '~> 5.1'
s.add_dependency 'kramdown', '~> 2.3'
s.add_dependency 'kramdown-parser-gfm', '~> 1.1.0'
+3 -2
View File
@@ -29,9 +29,10 @@ module Gollum
@@filters[pattern] = replacement
end
def self.apply_filters(data)
def self.apply_filters(wiki_page, data)
@@filters.each do |pattern, replacement|
data.gsub!(pattern, replacement.call)
params = replacement.parameters.length == 0 ? nil : wiki_page
data.gsub!(pattern, replacement.call(*params))
end
data
end
+6 -7
View File
@@ -103,8 +103,7 @@ module Precious
end
before do
settings.wiki_options[:allow_editing] = settings.wiki_options.fetch(:allow_editing, true)
@allow_editing = settings.wiki_options[:allow_editing]
@allow_editing = settings.wiki_options.fetch(:allow_editing, true)
@critic_markup = settings.wiki_options[:critic_markup]
@redirects_enabled = settings.wiki_options.fetch(:redirects_enabled, true)
@per_page_uploads = settings.wiki_options[:per_page_uploads]
@@ -112,8 +111,6 @@ module Precious
@wiki_title = settings.wiki_options.fetch(:title, 'Gollum Wiki')
forbid unless @allow_editing || request.request_method == 'GET'
if settings.wiki_options[:template_dir]
Precious::Views::Layout.extend Precious::Views::TemplateCascade
Precious::Views::Layout.template_priority_path = settings.wiki_options[:template_dir]
@@ -143,6 +140,8 @@ module Precious
config.manifest = Sprockets::Manifest.new(settings.sprockets, @static_assets_path)
end
end
forbid unless @allow_editing || request.request_method == 'GET'
end
get '/' do
@@ -369,7 +368,7 @@ module Precious
@name = wikip.name
@ext = wikip.ext
@path = wikip.path
@template_page = load_template(@path) if settings.wiki_options[:template_page]
@template_page = load_template(wikip, @path) if settings.wiki_options[:template_page]
@allow_uploads = wikip.wiki.allow_uploads
@upload_dest = find_upload_dest(wikip.fullpath)
@@ -661,9 +660,9 @@ module Precious
end
end
def load_template(path)
def load_template(wiki_page, path)
template_page = wiki_page(::File.join(path, '_Template')).page || wiki_page('/_Template').page
template_page ? Gollum::TemplateFilter.apply_filters(template_page.text_data) : nil
template_page ? Gollum::TemplateFilter.apply_filters(wiki_page, template_page.text_data) : nil
end
def update_wiki_page(wiki, page, content, commit, name = nil, format = nil)
+38
View File
@@ -0,0 +1,38 @@
en:
pagination:
aria:
label: Pagination
next_page: Next page
previous_page: Previous page
next: Next
previous: Previous
precious/views/compare:
back_to_page_history: Back to Page History
back_to_top: Back to Top
comparison_of: Comparison of
comparing_versions_of: Comparing versions of
comparing_from: "Comparing %{before} to %{after}"
revert: Revert Changes
precious/views/error:
error: Error
precious/views/history:
browse_in_history_description: Browse the page at this point in the history
compare_revisions: Compare Revisions
history_for: History for
precious/views/latest_changes:
title: Latest Changes (Globally)
precious/views/layout:
title: Home
precious/views/overview:
back_to_top: Back to Top
delete_confirmation: "Are you sure you want to delete %{name}?"
no_pages_in: There are no pages in
on: "on"
title: "Overview of %{ref}"
precious/views/search:
aria:
show_all: "Show all %{count} hits in this page"
back_to_top: Back to Top
no_results: There are no results for your search
search_results_for: Search results for
title: "Search results for %{query}"
+69 -40
View File
@@ -4,55 +4,84 @@
<h1 class="header-title text-center text-md-left py-4">
<span class="f1-light text-gray-light">
Comparing versions of
{{t.comparing_versions_of}}
</span>
{{name}}
</h1>
</div>
{{#message}}
<p>{{message}}</p>
<p>{{message}}</p>
{{/message}}
<div id="compare-content">
<div id="compare-content">
<div class="py-4" id="actions">
{{#show_revert}}
{{#allow_editing}}
<form name="gollum-revert" action="{{revert_path}}/{{escaped_url_path}}/{{before}}/{{after}}" method="post" id="gollum-revert-form"></form>
<span class="pb-4">
<button class="btn btn-sm" type="submit" onclick="$('#gollum-revert-form').submit()">Revert Changes</button>
</span>
{{/allow_editing}}
{{/show_revert}}
<a href="{{history_path}}/{{escaped_url_path}}" class="btn btn-sm action-page-history">Back to Page History</a>
</div>
<div class="py-4" id="actions">
{{#show_revert}}
{{#allow_editing}}
<form name="gollum-revert" action="{{revert_path}}/{{escaped_url_path}}/{{before}}/{{after}}" method="post" id="gollum-revert-form"></form>
<span class="pb-4">
<button
class="btn btn-sm"
onclick="$('#gollum-revert-form').submit()"
type="submit"
>
{{t.revert}}
</button>
</span>
{{/allow_editing}}
{{/show_revert}}
<div class="Box data highlight">
<div class="Box-header Box--condensed Box-header--gray">{{path}} <span class="px-2 float-right">Comparing {{before}} to {{after}}</span></div>
<table >
{{#lines}}
<tr>
<td class="line_numbers">{{ldln}}</td>
<td class="line_numbers">{{rdln}}</td>
<td>
<div class="{{class}} pl-2">{{line}}</div>
</td>
</tr>
{{/lines}}
</table>
</div>
</div>
<a
class="btn btn-sm action-page-history"
href="{{history_path}}/{{escaped_url_path}}"
>
{{t.back_to_page_history}}
</a>
</div>
<div class="pt-4" id="footer">
{{#show_revert}}
{{#allow_editing}}
<span class="pt-4"><button class="btn btn-sm gollum-revert-button" type="submit" onclick="$('#gollum-revert-form').submit()">Revert Changes</button></span>
{{/allow_editing}}
{{/show_revert}}
<div class="pt-4">
<a href="#">Back to Top</a>
</div>
</div>
<div class="Box data highlight">
<div class="Box-header Box--condensed Box-header--gray">
{{path}}
<span class="px-2 float-right">
{{t.comparing_from}}
</span>
</div>
<table>
{{#lines}}
<tr>
<td class="line_numbers">{{ldln}}</td>
<td class="line_numbers">{{rdln}}</td>
<td>
<div class="{{class}} pl-2">{{line}}</div>
</td>
</tr>
{{/lines}}
</table>
</div>
</div>
<div class="pt-4" id="footer">
{{#show_revert}}
{{#allow_editing}}
<span class="pt-4">
<button
class="btn btn-sm gollum-revert-button"
onclick="$('#gollum-revert-form').submit()"
type="submit"
>
{{t.revert}}
</button>
</span>
{{/allow_editing}}
{{/show_revert}}
<div class="pt-4">
<a href="#">
{{t.back_to_top}}
</a>
</div>
</div>
</div>
+2 -2
View File
@@ -1,8 +1,8 @@
<div id="wiki-wrapper" class="error">
<div id="error">
<h1>Error</h1>
<h1>{{t.error}}</h1>
<p>
{{message}}
</p>
</div>
</div>
</div>
+36 -27
View File
@@ -4,7 +4,7 @@
<h1 class="header-title text-center text-md-left py-4">
<span class="f1-light text-gray-light">
History for
{{t.history_for}}
</span>
{{name}}
</h1>
@@ -14,32 +14,41 @@
{{>pagination}}
<form name="selection-form" id="selection-form" method="get" action="{{compare_path}}/{{escaped_url_path}}"></form>
<form name="selection-form" id="selection-form" method="get" action="{{compare_path}}/{{escaped_url_path}}"></form>
<div id="page-history-list" class="Box Box--condensed flex-auto">
<form id="version-form">
<ul>
{{#versions}}
<li class="Box-row border-top Box-row--hover-gray d-flex flex-items-center">
<span class="pr-2"><input class="checkbox" type="checkbox" name="versions[]" value="{{id}}"></span>
<span class="float-left col-2" id="user-icons">{{>author_template}}</span>
<time class="flex-auto col-1 text-gray-light" datetime="{{datetime}}" data-format="{{date_format}}">{{date}}</time>
<span class="flex-auto col-5">{{message}}</span>
<span class="pl-4 float-right">
<a href="{{href}}" class="btn btn-outline text-mono">{{id7}}</a>
<a href="{{href_page}}" title="Browse the page at this point in the history" class="btn btn-outline">{{#octicon}}code{{/octicon}}</a>
</span>
</li>
{{/versions}}
</ul>
</form>
</div>
<div id="page-history-list" class="Box Box--condensed flex-auto">
<form id="version-form">
<ul>
{{#versions}}
<li class="Box-row border-top Box-row--hover-gray d-flex flex-items-center">
<span class="pr-2"><input class="checkbox" type="checkbox" name="versions[]" value="{{id}}"></span>
<span class="float-left col-2" id="user-icons">{{>author_template}}</span>
<time class="flex-auto col-1 text-gray-light" datetime="{{datetime}}" data-format="{{date_format}}">{{date}}</time>
<span class="flex-auto col-5">{{message}}</span>
<span class="pl-4 float-right">
<a href="{{href}}" class="btn btn-outline text-mono">{{id7}}</a>
<a
class="btn btn-outline"
href="{{href_page}}"
title="{{t.browse_in_history_description}}"
>
{{#octicon}}code{{/octicon}}
</a>
</span>
</li>
{{/versions}}
</ul>
</form>
</div>
<div id="footer">
<div class="pt-4">
<button class="btn btn-sm action-compare-revision" type="submit">Compare Revisions</button>
</div>
</div>
<div id="footer">
<div class="pt-4">
<button
class="btn btn-sm action-compare-revision"
type="submit"
>
{{t.compare_revisions}}
</button>
</div>
</div>
</div>
+19 -6
View File
@@ -21,25 +21,38 @@
<span class="pr-2">{{{icon}}}</span>
<span><a href="{{url}}">{{name}}</a></span>
{{#allow_editing}}
{{#is_file}}<button class="btn btn-sm float-right delete-file" data-file-path="{{file_path}}" data-confirm="Are you sure you want to delete {{name}}?">{{#octicon}}trash{{/octicon}}</button>{{/is_file}}
{{/allow_editing}}
{{#is_file}}
<button
class="btn btn-sm float-right delete-file"
data-confirm="{{t.delete_confirmation}}"
data-file-path="{{file_path}}"
>
{{#octicon}}trash{{/octicon}}
</button>
{{/is_file}}
{{/allow_editing}}
</li>
{{/files_folders}}
</ul>
</div>
{{/has_results}}
{{#no_results}}
<p id="no-results">
There are no pages in <strong>{{current_path}}</strong> on <strong>{{ref}}</strong>.
{{t.no_pages_in}}
<strong>{{current_path}}</strong>
{{t.on}}
<strong>{{ref}}</strong>.
</p>
{{/no_results}}
</div>
<div class="pt-4" id="footer">
<a href="#">Back to Top</a>
<a href="#">
{{t.back_to_top}}
</a>
</div>
</div>
+21 -4
View File
@@ -1,6 +1,23 @@
<nav class="paginate-container" aria-label="Pagination">
<nav class="paginate-container" aria-label="{{tt.pagination.aria.label}}">
<div class="pagination" id="pagination">
<a id="prev" href="?page_num={{previous_page}}{{query_string}}" class="previous_page {{^previous_page}}disabled{{/previous_page}}">Previous</span>
<a id="next" href="?page_num={{next_page}}{{query_string}}" class="next_page {{^next_page}}disabled{{/next_page}}" rel="next" aria-label="Next Page">Next</a>
<a
aria-label="{{td.pagination.aria.previous_page}}"
class="previous_page {{^previous_page}}disabled{{/previous_page}}"
href="?page_num={{previous_page}}{{query_string}}"
id="prev"
rel="prev"
>
{{tt.pagination.previous}}
</a>
<a
aria-label="{{td.pagination.aria.next_page}}"
class="next_page {{^next_page}}disabled{{/next_page}}"
href="?page_num={{next_page}}{{query_string}}"
id="next"
rel="next"
>
{{tt.pagination.next}}
</a>
</div>
</nav>
</nav>
+9 -5
View File
@@ -4,7 +4,7 @@
<h1 class="header-title text-center text-md-left py-4">
<span class="f1-light text-gray-light">
Search results for
{{t.search_results_for}}
</span>
{{name}}
</h1>
@@ -21,7 +21,12 @@
<li class="Box-row Box-row--gray">
<span class="Counter Counter--gray tooltipped tooltipped-w" aria-label="{{filename_count}} hits in filename - {{count}} hits in content">{{filename_count}} - {{count}}</span>&nbsp;
<span class="text-bold"><a href="{{href}}">{{name}}</a></span>
<button class="btn-link tooltipped tooltipped-w float-right toggle-context" aria-label="Show all {{count}} hits in this page">{{#octicon}}search{{/octicon}}</button>
<button
class="btn-link tooltipped tooltipped-w float-right toggle-context"
aria-label="{{t.aria.show_all}}"
>
{{#octicon}}search{{/octicon}}
</button>
</li>
<div class="search-context">
@@ -29,7 +34,6 @@
<li class="Box-row border-0"><span class="text-italic">{{.}}</span></li>
{{/context}}
</div>
{{/results}}
</ul>
</div>
@@ -37,12 +41,12 @@
{{#no_results}}
<p id="no-results">
There are no results for your search <strong>{{query}}</strong>.
{{t.no_results}} <strong>{{query}}</strong>.
</p>
{{/no_results}}
<div id="footer" class="mt-4">
<a class="btn" href="#">Back to Top</a>
<a class="btn" href="#">{{t.back_to_top}}</a>
</div>
</div>
+1 -1
View File
@@ -6,7 +6,7 @@ module Precious
attr_reader :page, :diff, :versions, :message, :allow_editing
def title
"Comparison of #{@page.title}"
[t[:comparison_of], @page.title].join(" ")
end
def before
+8 -1
View File
@@ -21,6 +21,13 @@ module Precious
autofill I18n.t(locale_klass_name)
end
# Returns all I18n translation strings from the root of an I18n YAML file.
# Otherwise, it works exactly like the `#t` method that's also defined in
# this file.
def tt
autofill I18n.t('.')
end
private
# Recursively looks up I18n translation values and autofills any YAML
@@ -42,7 +49,7 @@ module Precious
end
def fill_argument_content(i18n_key, i18n_value)
i18n_value.gsub!(YAML_VARIABLE_REGEXP) do |argument|
i18n_value = i18n_value.gsub(YAML_VARIABLE_REGEXP) do |argument|
method_name = argument.gsub(/[^\w]/, '')
next if method_name.nil?
+1 -1
View File
@@ -9,7 +9,7 @@ module Precious
attr_reader :wiki
def title
"Latest Changes (Globally)"
t[:title]
end
def versions
+7 -7
View File
@@ -20,7 +20,7 @@ module Precious
end
def title
"Home"
t[:title]
end
def has_path
@@ -58,11 +58,11 @@ module Precious
def js # custom js
@js
end
def critic_markup
@critic_markup
end
def per_page_uploads
@per_page_uploads
end
@@ -75,19 +75,19 @@ module Precious
def search
false
end
def history
false
end
def overview
false
end
def latest_changes
false
end
end
end
end
+10 -10
View File
@@ -3,11 +3,11 @@ require 'pathname'
module Precious
module Views
class Overview < Layout
attr_reader :results, :ref, :allow_editing, :newable
attr_reader :name, :results, :ref, :allow_editing, :newable
HIDDEN_PATHS = ['.gitkeep']
def title
"Overview of #{@ref}"
t[:title]
end
# def editable
@@ -38,21 +38,21 @@ module Precious
end
end
def files_folders
if has_results
files_and_folders = []
@results.each do |result|
result_path = result.url_path
result_path = result_path.sub(/^#{Regexp.escape(@path)}\//, '') unless @path.nil?
result_path = result_path.sub(/^#{Regexp.escape(@path)}\//, '') unless @path.nil?
if result_path.include?('/')
# result contains a folder
folder_name = result_path.split('/').first
folder_path = @path ? "#{@path}/#{folder_name}" : folder_name
folder_url = "#{overview_path}/#{folder_path}/"
files_and_folders << {name: folder_name, icon: rocticon('file-directory'), type: 'dir', url: folder_url, is_file: false}
elsif !HIDDEN_PATHS.include?(result_path)
elsif !HIDDEN_PATHS.include?(result_path)
file_url = page_route(result.escaped_url_path)
files_and_folders << {name: result.filename, icon: rocticon('file'), type: 'file', url: file_url, file_path: result.escaped_url_path, is_file: true}
end
@@ -61,7 +61,7 @@ module Precious
files_and_folders.uniq{|f| f[:name]}.sort_by!{|f| [f[:type], f[:name]]}
end
end
def has_results
!@results.empty?
@@ -70,12 +70,12 @@ module Precious
def no_results
@results.empty?
end
def latest_changes
true
end
end
end
end
+1 -1
View File
@@ -10,4 +10,4 @@ module Precious
@page_num == 1 ? nil : (@page_num - 1).to_s
end
end
end
end
+1 -1
View File
@@ -23,7 +23,7 @@ module Precious
end
def title
"Search results for " + @query
t[:title]
end
def search
+6 -2
View File
@@ -11,9 +11,13 @@ module Precious
end
def first_path_available(name)
priority = File.join(template_priority_path, "#{name}.#{template_extension}")
default = File.join(template_path, "#{name}.#{template_extension}")
File.exists?(priority) ? priority : default
priority =
if template_priority_path
File.join(template_priority_path, "#{name}.#{template_extension}")
end
priority && File.exist?(priority) ? priority : default
end
# Method should track lib/mustache/settings.rb from Mustache project.
+98 -2
View File
@@ -15,12 +15,13 @@ describe Precious::Views::LocaleHelpers do
end
def setup
::I18n.available_locales = [:en, :de]
::I18n.load_path = Dir[File.expand_path("test/support/locales" + "/*.yml")]
I18n.available_locales = [:en, :de]
I18n.load_path = Dir[File.expand_path("test/support/locales" + "/*.yml")]
end
def teardown
I18n.locale = :en
I18n.load_path = Dir[::File.expand_path("lib/gollum/locales") + "/*.yml"]
end
let(:dummy_instance) { TestClass.new }
@@ -131,4 +132,99 @@ describe Precious::Views::LocaleHelpers do
end
end
end
describe "#tt" do
describe "mustache usage" do
let(:subject) { dummy_instance.render(mustache_template) }
let(:mustache_template) { "{{ tt.test_class.hello_world }}" }
describe "in the default locale" do
it "returns the translation string" do
_(subject).must_equal "Hello world"
end
end
describe "in the configured locale" do
it "returns the translation string" do
I18n.locale = :de
_(subject).must_equal "Hallo Welt"
end
end
describe "translations with YAML arguments" do
let(:mustache_template) { "{{ tt.test_class.author_info.full }}" }
describe "in the default locale" do
it "autofills YAML arguments" do
_(subject).must_equal "Author J.R.R. is from Bloemfontein"
end
end
describe "in the configured locale" do
it "autofills YAML arguments" do
I18n.locale = :de
_(subject).must_equal "Autor J.R.R. ist vom Bloemfontein"
end
end
end
describe "translations with invalid arguments" do
let(:mustache_template) { "{{ tt.test_class.has_invalid_argument }}" }
it "fails gracefully with embedded error message" do
expected_string = "Welcome to " \
"[#{TestClass::NO_METHOD_MESSAGE}: no_matching_method]"
_(subject).must_equal expected_string
end
end
describe "missing translations" do
let(:mustache_template) {
"{{ tt.test_class.nested.nonexistent_key }}"
}
it "outputs an empty string" do
_(subject).must_be_empty
end
end
end
describe "usage" do
let(:subject) { dummy_instance.tt }
it "returns a hash" do
_(subject).must_be_kind_of Hash
end
it "returns all present translation keys" do
i18n_keys = I18n.t(".").keys
_(subject.keys).must_equal i18n_keys
end
it "returns nested keys" do
nested_keys = subject[:test_class][:author_info].keys
_(nested_keys).must_equal [:full]
end
describe "auto-filled YAML arguments" do
let(:subject) { dummy_instance.tt[:test_class][:author_info][:full] }
it "auto-fills in the default locale" do
_(subject).must_equal "Author J.R.R. is from Bloemfontein"
end
it "auto-fills in a configured locale" do
I18n.locale = :de
_(subject).must_equal "Autor J.R.R. ist vom Bloemfontein"
end
end
end
end
end
+33 -13
View File
@@ -1,18 +1,20 @@
require 'rubygems'
require 'rack/test'
require 'test/unit'
require 'shoulda'
require 'mocha/setup'
require 'fileutils'
require 'minitest/autorun'
require 'minitest/reporters'
require 'minitest/spec'
require 'mocha/setup'
require 'fileutils'
require 'tmpdir'
# Silence locale validation warning
require 'i18n'
I18n.enforce_available_locales = false
MiniTest::Reporters.use!
Minitest::Reporters.use! [
Minitest::Reporters::DefaultReporter.new({color: true})
]
dir = File.dirname(File.expand_path(__FILE__))
$LOAD_PATH.unshift(File.join(dir, '..', 'lib'))
@@ -62,14 +64,29 @@ def normal(text)
text
end
# test/spec/mini 3
# http://gist.github.com/25455
# chris@ozmm.org
# file:lib/test/spec/mini.rb
# The following configuration originates from this gist:
# http://gist.github.com/25455
#
# But it has been modified since it was first committed. It allows you to
# write tests with an RSpec-like DSL:
#
# context "my test context" do
# setup do
# # My test setup
# end
#
# teardown do
# # My test teardown
# end
#
# test "some functionality" do
# assert true
# end
# end
def context(*args, &block)
return super unless (name = args.first) && block
require 'test/unit'
klass = Class.new(defined?(ActiveSupport::TestCase) ? ActiveSupport::TestCase : Test::Unit::TestCase) do
klass = Class.new(Minitest::Test) do
def self.test(name, &block)
define_method("test_#{name.gsub(/\W/, '_')}", &block) if block
end
@@ -85,10 +102,13 @@ def context(*args, &block)
define_method(:teardown, &block)
end
end
(
class << klass;
self
end).send(:define_method, :name) { name.gsub(/\W/, '_') }
class << klass;
self
end
).send(:define_method, :name) { name.gsub(/\W/, '_') }
$contexts << klass
klass.class_eval &block
end
+54 -34
View File
@@ -3,87 +3,107 @@ require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
context "Precious::Views::Editing" do
include Rack::Test::Methods
setup do
@path = cloned_testpath('examples/revert.git')
@path = cloned_testpath('examples/revert.git')
Precious::App.set(:gollum_path, @path)
Precious::App.set(:wiki_options, {allow_editing: true, allow_uploads: true})
@wiki = Gollum::Wiki.new(@path)
end
teardown do
Precious::App.set(:wiki_options, {allow_editing: true, allow_uploads: true})
FileUtils.rm_rf(@path)
end
test "creating page is blocked" do
Precious::App.set(:wiki_options, { allow_editing: false})
post "/gollum/create", :content => 'abc', :page => "D",
:format => 'markdown', :message => 'def'
assert !last_response.ok?
test 'creating pages is not blocked' do
post '/gollum/create',
content: 'abc',
format: 'markdown',
message: 'def',
page: 'D'
page = @wiki.page('D')
assert page.nil?
assert_equal last_response.status, 302
refute_nil @wiki.page('D')
end
test 'creating pages is blocked' do
Precious::App.set(:wiki_options, {allow_editing: false, allow_uploads: false})
post '/gollum/create',
content: 'abc',
format: 'markdown',
message: 'def',
page: 'D'
assert last_response.body.include? 'Forbidden. This wiki is set to no-edit mode.'
refute last_response.ok?
assert_nil @wiki.page('D')
end
test ".redirects.gollum file should not be accessible" do
Precious::App.set(:wiki_options, { allow_editing: true, allow_uploads: true })
get '/.redirects.gollum'
assert_match /Accessing this resource is not allowed/, last_response.body
end
test ".redirects.gollum file should not be editable" do
Precious::App.set(:wiki_options, { allow_editing: true, allow_uploads: true })
get '/gollum/edit/.redirects.gollum'
assert_match /Changing this resource is not allowed/, last_response.body
end
test "frontend links for editing are not blocked" do
Precious::App.set(:wiki_options, { allow_editing: true, allow_uploads: true })
get '/A'
assert_match /Delete this Page/, last_response.body, "'Delete this Page' link is blocked in page template"
assert_match /New/, last_response.body, "'New' button is blocked in page template"
assert_match /Upload\b/, last_response.body, "'Upload' link is blocked in page template"
assert_match /Rename/, last_response.body, "'Rename' link is blocked in page template"
assert_match /Edit/, last_response.body, "'Edit' link is blocked in page template"
assert last_response.body.include? "Delete this Page"
assert last_response.body.include? "New"
assert last_response.body.include? "<span>Upload</span>"
assert last_response.body.include? "Rename"
assert last_response.body.include? "Edit"
get '/gollum/overview'
assert_match /New/, last_response.body, "'New' link is blocked in pages template"
assert last_response.body.include? "New"
get '/gollum/history/A'
assert_no_match /Edit/, last_response.body, "'Edit' link is not blocked in history template"
refute last_response.body.include? "Edit"
get '/gollum/compare/A/fc66539528eb96f21b2bbdbf557788fe8a1196ac..b26b791cb7917c4f37dd9cb4d1e0efb24ac4d26f'
get '/gollum/compare/A/fc665395..b26b791c'
assert_no_match /Edit Page/, last_response.body, "'Edit Page' link is not blocked in compare template"
assert_match /Revert Changes/, last_response.body, "'Revert Changes' link is blocked in compare template"
refute last_response.body.include? "Edit Page"
assert last_response.body.include? "Revert Changes"
end
test "frontend links for editing blocked" do
Precious::App.set(:wiki_options, { allow_editing: false })
Precious::App.set(:wiki_options, {allow_editing: false, allow_uploads: false})
get '/A'
assert_no_match /Delete this Page/, last_response.body, "'Delete this Page' link not blocked in page template"
assert_no_match /New/, last_response.body, "'New' button not blocked in page template"
assert_no_match /Upload\b/, last_response.body, "'Upload' link not blocked in page template"
assert_no_match /Rename/, last_response.body, "'Rename' link not blocked in page template"
assert_no_match /Edit/, last_response.body, "'Edit' link not blocked in page template"
refute last_response.body.include? "Delete this Page"
refute last_response.body.include? "<span>Upload</span>"
refute last_response.body.include? "Rename"
refute last_response.body.include? "Edit"
refute last_response.body.include? "New"
get '/gollum/overview'
assert_no_match /New/, last_response.body, "'New' link not blocked in pages template"
refute last_response.body.include? "New"
get '/gollum/history/A'
assert_no_match /Edit/, last_response.body, "'Edit' link not blocked in history template"
refute last_response.body.include? "Edit"
get '/gollum/compare/A/fc66539528eb96f21b2bbdbf557788fe8a1196ac..b26b791cb7917c4f37dd9cb4d1e0efb24ac4d26f'
get '/gollum/compare/A/fc665395..b26b791c'
assert_no_match /Edit Page/, last_response.body, "'Edit Page' link not blocked in compare template"
assert_no_match /Revert Changes/, last_response.body, "'Revert Changes' link not blocked in compare template"
refute last_response.body.include? "Edit Page"
refute last_response.body.include? "Revert Changes"
end
def app
Precious::App
end
end
end
+97 -50
View File
@@ -14,7 +14,7 @@ context "Frontend" do
teardown do
FileUtils.rm_rf(@path)
end
test "utf-8 kcode" do
assert_equal 'μ†ℱ'.scan(/./), ["μ", "", ""]
end
@@ -104,21 +104,21 @@ EOF
page_2 = @wiki.page(page_1.name)
assert_equal 'abc', page_2.raw_data
assert_equal 'def', page_2.version.message
assert_not_equal page_1.version.sha, page_2.version.sha
refute_equal page_1.version.sha, page_2.version.sha
end
test "edit page fails when page is outdated (edit collision)" do
page = @wiki.page('A')
old_sha = page.sha
post "/gollum/edit/A", :content => 'abc', :page => 'A',
:format => page.format, :message => 'def', :etag => old_sha
assert last_response.ok?
@wiki.clear_cache
page = @wiki.page('A')
new_sha = page.sha
assert_not_equal old_sha, new_sha
refute_equal old_sha, new_sha
post "/gollum/edit/A", :content => 'def', :page => 'A',
:format => page.format, :message => 'def', :etag => old_sha
assert_equal last_response.status, 412
@@ -134,7 +134,7 @@ EOF
page_2 = @wiki.page(page_1.name)
assert_equal 'abc', page_2.raw_data
assert_equal '[no message]', page_2.version.message
assert_not_equal page_1.version.sha, page_2.version.sha
refute_equal page_1.version.sha, page_2.version.sha
end
test "edit page with slash" do
@@ -165,12 +165,12 @@ EOF
assert_equal 'header', header_2.raw_data
assert_equal 'footer', foot_2.raw_data
assert_equal 'def', foot_2.version.message
assert_not_equal foot_1.version.sha, foot_2.version.sha
assert_not_equal header_1.version.sha, header_2.version.sha
refute_equal foot_1.version.sha, foot_2.version.sha
refute_equal header_1.version.sha, header_2.version.sha
assert_equal 'sidebar', side_2.raw_data
assert_equal 'def', side_2.version.message
assert_not_equal side_1.version.sha, side_2.version.sha
refute_equal side_1.version.sha, side_2.version.sha
assert_equal commits, @wiki.repo.commits('master').size
end
@@ -187,7 +187,7 @@ EOF
page_2 = @wiki.page('C')
assert_equal "INITIAL\n\nSPAM2\n", page_2.raw_data
assert_equal 'def', page_2.last_version.message
assert_not_equal page_1.version.sha, page_2.version.sha
refute_equal page_1.version.sha, page_2.version.sha
end
test "rename preserves format" do
@@ -222,7 +222,7 @@ EOF
test "renames page in subdirectory" do
page_1 = @wiki.page("G/H")
assert_not_equal page_1, nil
refute_equal page_1, nil
post "/gollum/rename/G/H", :rename => "/I/C", :message => 'def'
follow_redirect!
@@ -234,12 +234,12 @@ EOF
page_2 = @wiki.page('I/C')
assert_equal "INITIAL\n\nSPAM2\n", page_2.raw_data
assert_equal 'def', page_2.last_version.message
assert_not_equal page_1.version.sha, page_2.version.sha
refute_equal page_1.version.sha, page_2.version.sha
end
test "renames page relative in subdirectory" do
page_1 = @wiki.page("G/H")
assert_not_equal page_1, nil
refute_equal page_1, nil
post "/gollum/rename/G/H", :rename => "K/C", :message => 'def'
follow_redirect!
@@ -251,7 +251,7 @@ EOF
page_2 = @wiki.page('G/K/C')
assert_equal "INITIAL\n\nSPAM2\n", page_2.raw_data
assert_equal 'def', page_2.last_version.message
assert_not_equal page_1.version.sha, page_2.version.sha
refute_equal page_1.version.sha, page_2.version.sha
end
test "creates page" do
@@ -320,7 +320,7 @@ EOF
name = "#{dir}/bar"
get "/gollum/create/#{name}"
assert_match(/\/#{dir}/, last_response.body)
assert_no_match(/[^\/]#{dir}/, last_response.body)
refute_match(/[^\/]#{dir}/, last_response.body)
end
test "create with template succeed if template exists" do
@@ -344,6 +344,45 @@ EOF
Precious::App.set(:wiki_options, { :template_page => false })
end
test "create with template filter without parameter" do
Precious::App.set(:wiki_options, { :template_page => true })
# arrange
now = Time.parse('2022-04-16')
Gollum::TemplateFilter.add_filter("{{today}}", & -> () { now.strftime("%Y-%m-%d") })
template_content = "# Daily Log, {{today}}"
@wiki.write_page("daily-logs/_Template",
:markdown,
template_content)
# act
get "/gollum/create/daily-logs/test"
# assert
assert last_response.ok?
assert_match("# Daily Log, 2022-04-16", last_response.body)
Precious::App.set(:wiki_options, { :template_page => false })
end
test "create with template filter with parameter" do
Precious::App.set(:wiki_options, { :template_page => true })
# arrange
Gollum::TemplateFilter.add_filter("{{page_name}}", & -> (page) { page.name })
template_content = "# Daily Log, {{page_name}}"
@wiki.write_page("daily-logs/_Template",
:markdown,
template_content)
# act
get "/gollum/create/daily-logs/2022-04-16"
# assert
assert last_response.ok?
assert_match("# Daily Log, 2022-04-16", last_response.body)
Precious::App.set(:wiki_options, { :template_page => false })
end
test "edit returns nil for non-existant page" do
# post '/edit' fails. post '/edit/' works.
page = 'not-real-page'
@@ -351,7 +390,7 @@ EOF
post '/gollum/edit/', :content => 'edit_msg',
:page => page, :path => path, :message => ''
page_e = @wiki.page(::File.join(path,page))
assert_equal nil, page_e
assert_nil page_e
end
test "edit allows changing format" do
@@ -407,23 +446,31 @@ EOF
@wiki.clear_cache
page = @wiki.page(name)
assert_not_equal 'abc', page.raw_data
refute_equal 'abc', page.raw_data
end
test "uploading is not allowed unless explicitly enabled" do
temp_upload_file = Tempfile.new(['upload', '.file']) << 'abc'
temp_upload_file.close
post "/gollum/upload_file", :file => Rack::Test::UploadedFile.new(::File.open(temp_upload_file))
Precious::App.set(
:wiki_options,
{allow_uploads: false, per_page_uploads: false}
)
post '/gollum/upload_file',
file: Rack::Test::UploadedFile.new(File.open(temp_upload_file))
assert_equal 405, last_response.status
end
test "upload a file with mode dir" do
temp_upload_file = Tempfile.new(['upload', '.file']) << 'abc'
temp_upload_file.close
Precious::App.set(:wiki_options, {allow_uploads: true})
post "/gollum/upload_file", :file => Rack::Test::UploadedFile.new(::File.open(temp_upload_file))
assert_equal 302, last_response.status # redirect is expected
@wiki.clear_cache
file = @wiki.file("uploads/#{::File.basename(temp_upload_file.path)}")
@@ -436,7 +483,7 @@ EOF
temp_upload_file.close
Precious::App.set(:wiki_options, {allow_uploads: true, per_page_uploads: true})
post "/gollum/upload_file", {:file => Rack::Test::UploadedFile.new(::File.open(temp_upload_file))}, {'HTTP_REFERER' => 'http://localhost:4567/Home.md', 'HTTP_HOST' => 'localhost:4567'}
assert_equal 302, last_response.status # redirect is expected
@wiki.clear_cache
# Find the file in a page-specific subdir (here: Home), based on referer
@@ -444,13 +491,13 @@ EOF
assert_equal 'abc', file.raw_data
Precious::App.set(:wiki_options, {allow_uploads: false, per_page_uploads: false})
end
test "upload a file with https referer" do
temp_upload_file = Tempfile.new(['https_upload', '.file']) << 'abc'
temp_upload_file.close
Precious::App.set(:wiki_options, {allow_uploads: true, per_page_uploads: true})
post "/gollum/upload_file", {:file => Rack::Test::UploadedFile.new(::File.open(temp_upload_file))}, {'HTTP_REFERER' => 'https://localhost:4567/Home.md', 'HTTP_HOST' => 'localhost:4567'}
assert_equal 302, last_response.status # redirect is expected
@wiki.clear_cache
# Find the file in a page-specific subdir (here: Home), based on referer
@@ -458,8 +505,8 @@ EOF
assert_equal 'abc', file.raw_data
Precious::App.set(:wiki_options, {allow_uploads: false, per_page_uploads: false})
end
test "guard against uploading an existing file" do
temp_upload_file = Tempfile.new(['upload', '.file']) << 'abc'
temp_upload_file.close
@@ -471,7 +518,7 @@ EOF
assert_equal 409, last_response.status
Precious::App.set(:wiki_options, {allow_uploads: false})
end
test "delete a page" do
name = "deleteme"
post "/gollum/create", :content => 'abc', :page => name,
@@ -483,7 +530,7 @@ EOF
@wiki.clear_cache
page = @wiki.page(name)
assert_equal nil, page
assert_nil page
end
test "previews content" do
@@ -507,7 +554,7 @@ EOF
@wiki.clear_cache
page2 = @wiki.page('B')
assert_not_equal page1.version.sha, page2.version.sha
refute_equal page1.version.sha, page2.version.sha
assert_equal "INITIAL", page2.raw_data.strip
assert_equal "Revert commit 7c45b5f", page2.version.message
end
@@ -521,7 +568,7 @@ EOF
@wiki.clear_cache
page2 = @wiki.page('A')
assert_not_equal page1.version.sha, page2.version.sha
refute_equal page1.version.sha, page2.version.sha
assert_equal "INITIAL", page2.raw_data.strip
end
@@ -535,7 +582,7 @@ EOF
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
@@ -583,7 +630,7 @@ EOF
{ :name => 'user1', :email => 'user1' });
get page
assert_no_match /custom.js/, last_response.body
refute_match /custom.js/, last_response.body
end
test "add custom.js if setting" do
@@ -601,7 +648,7 @@ EOF
test "don't allow changing custom js or css" do
Precious::App.set(:wiki_options, { :js => true, :css => true })
['create', 'edit'].each do |route|
['.css', '.js'].each do |ext|
get "/gollum/#{route}/custom#{ext}"
@@ -634,7 +681,7 @@ EOF
:page => 'Multibyte', :format => :markdown, :message => 'mesg'
page = @wiki.page('Multibyte')
post "/gollum/edit/Multibyte",
:content => 'りんご', :header => 'みかん', :footer => 'バナナ', :sidebar => 'スイカ',
:page => 'Multibyte', :format => :markdown, :message => 'mesg', :etag => page.sha
@@ -652,7 +699,7 @@ EOF
get "A"
assert last_response.ok?
assert_no_match /meta name="robots" content="noindex, nofollow"/, last_response.body
refute_match /meta name="robots" content="noindex, nofollow"/, last_response.body
get "A/fc66539528eb96f21b2bbdbf557788fe8a1196ac"
@@ -831,10 +878,10 @@ context "Frontend with lotr" do
test "show revision of specific file" do
old_sha = "df26e61e707116f81ebc6b935ec6d1676b7e96c4"
update_sha = "f803c64d11407b23797325e3843f3f378b78f611"
get "Data.csv/#{old_sha}"
assert last_response.ok?
assert_no_match /Samwise,Gamgee/, last_response.body
refute_match /Samwise,Gamgee/, last_response.body
get "Data.csv/#{update_sha}"
assert last_response.ok?
@@ -879,7 +926,7 @@ context "Frontend with page-file-dir" do
name = "#{dir}/baz"
get "/gollum/create/#{name}"
assert_match(/\/#{dir}/, last_response.body)
assert_no_match(/[^\/]#{dir}/, last_response.body)
refute_match(/[^\/]#{dir}/, last_response.body)
end
test "use custom.css from page-file-dir path if page-file-dir is set" do
@@ -920,7 +967,7 @@ end
context "Frontend with empty repo" do
include Rack::Test::Methods
setup do
@path = cloned_testpath("examples/empty.git")
@wiki = Gollum::Wiki.new(@path)
@@ -931,11 +978,11 @@ context "Frontend with empty repo" do
teardown do
FileUtils.rm_rf(@path)
end
def app
Precious::App
end
test 'previews content on the first page of an empty wiki' do
post '/gollum/preview', :content => 'abc', :format => 'markdown'
assert last_response.ok?
@@ -947,12 +994,12 @@ context "Frontend with empty repo" do
assert_equal '/gollum/create/Home', last_request.fullpath
assert last_response.ok?
end
end
context 'Frontend with base path' do
include Rack::Test::Methods
setup do
@path = cloned_testpath("examples/lotr.git")
@wiki = Gollum::Wiki.new(@path)
@@ -964,24 +1011,24 @@ context 'Frontend with base path' do
teardown do
FileUtils.rm_rf(@path)
end
test 'page with base path' do
get '/wiki/Home'
assert last_response.ok?
end
test 'base path mathjax assets' do
get '/wiki/Home'
assert last_response.ok?
assert last_response.body.include?('<script defer src="/wiki/gollum/assets/mathjax/MathJax.js?config=')
end
test 'compare view' do
get '/wiki/gollum/compare/Bilbo-Baggins.md?versions[]=f25eccd98e9b667f9e22946f3e2f945378b8a72d&versions[]=5bc1aaec6149e854078f1d0f8b71933bbc6c2e43'
follow_redirect!
assert last_response.ok?
assert_equal '/wiki/gollum/compare/Bilbo-Baggins.md/5bc1aaec6149e854078f1d0f8b71933bbc6c2e43...f25eccd98e9b667f9e22946f3e2f945378b8a72d', last_request.fullpath
get '/wiki/gollum/compare/Bilbo-Baggins.md?versions[]=f25eccd98e9b667f9e22946f3e2f945378b8a72d'
follow_redirect!
assert last_response.ok?
@@ -992,7 +1039,7 @@ context 'Frontend with base path' do
assert last_response.ok?
assert_equal '/wiki/gollum/history/Bilbo-Baggins.md', last_request.fullpath
end
def app
Precious::MapGollum.new(@base_path)
end
+64 -66
View File
@@ -1,28 +1,6 @@
# ~*~ encoding: utf-8 ~*~
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
# Original contents of Subdir/Foo.md:
# waa
# [[Samwi]]
# [[samwise gamgee.mediaWiki]]
# [[Samwise Gamgee.mediawiki]]
# [[Samwise Gamgee]]
# [[Test|Samwise Gamgee#Anchor]]
# [[Waaa|Test]]
# [[Zaa]]
# Contents of Subdir/Foo.md after successful tag migration
result = <<EOF
waa
[[Samwi]]
[[/Samwise Gamgee.mediawiki]]
[[/Samwise Gamgee.mediawiki]]
[[/Samwise Gamgee.md]]
[[Test|/Samwise Gamgee.md#Anchor]]
[[Waaa|/Bar/Test.md]]
[[Subsub/Zaa.md]]
EOF
def load_script(**args)
settings = {
:run_silent => true,
@@ -31,56 +9,76 @@ def load_script(**args)
:hyphenate => false,
:page_file_dir => nil,
}.merge(args)
settings.each do |const, val|
const_name = const.to_s.upcase
Object.const_set(const_name, val) unless Object.const_defined?(const_name) && Object.const_get(const_name) == val
settings.each do |setting, val|
variable_name = :"@@#{setting.to_s}"
unless Object.class_variable_defined?(variable_name) && Object.class_variable_get(variable_name) == val
Object.class_variable_set(variable_name, val)
end
end
script_path = File.expand_path(File.join(File.dirname(__FILE__), '../', 'bin', 'gollum-migrate-tags'))
Dir.chdir(@path) do
load script_path
end
end
end
unless ENV['CI']
context '4.x -> 5.x tag migrator' do
include Rack::Test::Methods
context '4.x -> 5.x tag migrator' do
include Rack::Test::Methods
setup do
@path = cloned_testpath("examples/lotr_migration.git")
end
test 'repair broken links' do
load_script
f = ::File.new(::File.join(@path, 'Subdir/Foo.md'), 'r')
assert_equal result, f.read
end
test 'change spaced filenames to hyphenated filenames' do
load_script(hyphenate: true)
f = ::File.new(::File.join(@path, 'Home.textile'), 'r')
output = f.read
assert_equal true, output.include?('[[Bilbo-Baggins.md]]')
assert_equal true, output.include?('[[evil|Mordor/Eye-Of-Sauron.md]]')
end
test 'migration with page file dir' do
load_script(page_file_dir: 'Subdir')
f = ::File.new(::File.join(@path, 'Subdir/Foo.md'), 'r')
output = f.read
assert_equal true, output.include?('[[Subsub/Zaa.md]]')
assert_equal true, output.include?('[[Samwi]]')
end
teardown do
FileUtils.rm_rf(@path)
end
setup do
@path = cloned_testpath("examples/lotr_migration.git")
end
end
test 'repair broken links' do
# The original contents of Subdir/Foo.md:
#
# waa
# [[Samwi]]
# [[samwise gamgee.mediaWiki]]
# [[Samwise Gamgee.mediawiki]]
# [[Samwise Gamgee]]
# [[Test|Samwise Gamgee#Anchor]]
# [[Waaa|Test]]
# [[Zaa]]
#
# The contents will be updated after running the migration script.
load_script
file = ::File.new(::File.join(@path, 'Subdir/Foo.md'), 'r')
assert_equal <<~FILE_CONTENTS, file.read
waa
[[Samwi]]
[[/Samwise Gamgee.mediawiki]]
[[/Samwise Gamgee.mediawiki]]
[[/Samwise Gamgee.md]]
[[Test|/Samwise Gamgee.md#Anchor]]
[[Waaa|/Bar/Test.md]]
[[Subsub/Zaa.md]]
FILE_CONTENTS
end
test 'change spaced filenames to hyphenated filenames' do
load_script(hyphenate: true)
f = ::File.new(::File.join(@path, 'Home.textile'), 'r')
output = f.read
assert_equal true, output.include?('[[Bilbo-Baggins.md]]')
assert_equal true, output.include?('[[evil|Mordor/Eye-Of-Sauron.md]]')
end
test 'migration with page file dir' do
load_script(page_file_dir: 'Subdir')
f = ::File.new(::File.join(@path, 'Subdir/Foo.md'), 'r')
output = f.read
assert_equal true, output.include?('[[Subsub/Zaa.md]]')
assert_equal true, output.include?('[[Samwi]]')
end
teardown do
FileUtils.rm_rf(@path)
end
end
+1 -1
View File
@@ -35,7 +35,7 @@ context "Precious::Views::Page" do
@view.instance_variable_set :@content, page.formatted_data
@view.instance_variable_set :@h1_title, false
assert_include @view.breadcrumb, "数学 📘"
assert_includes @view.breadcrumb, "数学 📘"
end
test 'page <title> is the page header from content, if present' do
+26 -10
View File
@@ -1,43 +1,59 @@
# ~*~ encoding: utf-8 ~*~
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
class TestTemplateCascade < Minitest::Unit::TestCase
context "Precious::Views::TemplateCascade" do
include Rack::Test::Methods
def setup
setup do
@path = cloned_testpath('examples/lotr.git')
Precious::App.set(:gollum_path, @path)
Precious::App.set(:wiki_options, {template_dir: testpath('examples/template_cascade')})
Precious::App.set(
:wiki_options,
{template_dir: testpath('examples/template_cascade')}
)
@wiki = Gollum::Wiki.new(@path)
end
def teardown
teardown do
FileUtils.rm_rf(@path)
Precious::App.set(:wiki_options, {template_dir: nil})
# The following line has been added to avoid order-dependent test failures.
# We saw issues where the class variable `@@template_priority_path` was not
# being reset between test cases.
Precious::Views::TemplateCascade.class_variable_set(
:@@template_priority_path,
nil
)
end
def app
Precious::App
Precious::App.new
end
def test_overridden_page_template_is_used
test "overridden_page_template_is_used" do
get '/Home'
assert last_response.body.include?('PAGE_OVERRIDE')
end
def test_overridden_navbar_partial_is_used
test "test_overridden_navbar_partial_is_used" do
get '/Home'
assert last_response.body.include?('NAVBAR_OVERRIDE')
end
def test_overridden_templates_are_ignore_without_template_dir_set
test "test_overridden_templates_are_ignore_without_template_dir_set" do
Precious::App.set(:wiki_options, {template_dir: nil})
get '/Home'
assert_equal '/Home', last_request.fullpath
assert last_response.ok?
assert_no_match /PAGE_OVERRIDE/, last_response.body
assert_no_match /NAVBAR_OVERRIDE/, last_response.body
refute_match /PAGE_OVERRIDE/, last_response.body
refute_match /NAVBAR_OVERRIDE/, last_response.body
end
end