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 }} tags: ${{ env.DEPLOY_NAME }}
cache-from: type=local,src=/tmp/.buildx-cache cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache cache-to: type=local,dest=/tmp/.buildx-cache
platforms: linux/amd64, linux/arm64
- name: Image digest - name: Image digest
run: echo ${{ steps.docker_build.outputs.digest }} run: echo ${{ steps.docker_build.outputs.digest }}
+1 -1
View File
@@ -30,7 +30,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
ruby: [2.6, 2.7, 3.0] ruby: ['2.6', '2.7', '3.0', '3.1']
steps: steps:
- name: Check out repository code - name: Check out repository code
uses: actions/checkout@v2 uses: actions/checkout@v2
+2 -1
View File
@@ -32,7 +32,8 @@ COPY --from=builder /usr/local/bundle/ /usr/local/bundle/
RUN apk add \ RUN apk add \
bash \ bash \
git git \
libc6-compat
VOLUME /wiki VOLUME /wiki
WORKDIR /wiki WORKDIR /wiki
+1 -13
View File
@@ -1,6 +1,5 @@
require 'rubygems' require 'rubygems'
require 'rake' require 'rake'
require 'date'
############################################################################# #############################################################################
# #
@@ -38,14 +37,6 @@ def bump_version
new_version new_version
end end
def date
Date.today.to_s
end
def rubyforge_project
name
end
def gemspec_file def gemspec_file
"#{name}.gemspec" "#{name}.gemspec"
end end
@@ -143,12 +134,9 @@ task :gemspec => :validate do
spec = File.read(gemspec_file) spec = File.read(gemspec_file)
head, manifest, tail = spec.split(" # = MANIFEST =\n") head, manifest, tail = spec.split(" # = MANIFEST =\n")
# replace name version and date # replace name and version
replace_header(head, :name) replace_header(head, :name)
replace_header(head, :version) 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 # determine file list from git ls-files
files = `git ls-files`. files = `git ls-files`.
+20 -8
View File
@@ -11,8 +11,11 @@ migrate_options = {
:hyphenate => true :hyphenate => true
} }
def setting(const) def setting(variable_name)
Object.const_defined?(const.upcase) && Object.const_get(const.upcase) class_variable_name = :"@@#{variable_name.to_s}"
Object.class_variable_defined?(class_variable_name) &&
Object.class_variable_get(class_variable_name)
end end
opts = OptionParser.new do |opts| opts = OptionParser.new do |opts|
@@ -78,8 +81,11 @@ end
begin begin
opts.parse! opts.parse!
migrate_options.each do |setting, value| migrate_options.each do |setting, value|
const = setting.to_s.upcase variable_name = :"@@#{setting.to_s}"
Object.const_set(const, value) unless Object.const_defined?(const)
unless Object.class_variable_defined?(variable_name)
Object.class_variable_set(variable_name, value)
end
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. 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 rescue OptionParser::InvalidOption
@@ -88,7 +94,7 @@ rescue OptionParser::InvalidOption
exit exit
end end
REPO = ARGV[0] || Dir.pwd wiki_directory = ARGV[0] || Dir.pwd
require 'gollum-lib' require 'gollum-lib'
@@ -232,8 +238,12 @@ end
filter_chain = [:PlainTextMigrator, :CodeMigrator, :TagMigrator] filter_chain = [:PlainTextMigrator, :CodeMigrator, :TagMigrator]
wiki = ::Gollum::Wiki.new(REPO, wiki_options.merge({:filter_chain => filter_chain})) wiki = ::Gollum::Wiki.new(wiki_directory, wiki_options.merge({:filter_chain => filter_chain}))
TREE = wiki.tree_list(wiki.ref, true, true).map {|file| ::File.join('/', file.path)}
Object.class_variable_set(
:"@@wiki_tree",
wiki.tree_list(wiki.ref, true, true).map {|file| ::File.join('/', file.path)}
)
def find_linked(link) def find_linked(link)
link.gsub!(' ', '-') if setting(:hyphenate) # Match paths containing dashes instead of spaces 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 test_path = ::File.extname(link).empty? ? /#{link}\..+/ : link
# Select pages from the wiki whose path =~ 'Foo/Bar/Samwi.*' # Select pages from the wiki whose path =~ 'Foo/Bar/Samwi.*'
# Match case-insenstively to mimic 4.x behavior! # 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 end
def log(kind, msg = nil) def log(kind, msg = nil)
+1 -3
View File
@@ -1,12 +1,9 @@
Gem::Specification.new do |s| 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.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.required_ruby_version = '>= 2.6'
s.name = 'gollum' s.name = 'gollum'
s.version = '5.2.3' s.version = '5.2.3'
s.date = '2021-04-18'
s.license = 'MIT' s.license = 'MIT'
s.summary = 'A simple, Git-powered wiki.' s.summary = 'A simple, Git-powered wiki.'
@@ -23,6 +20,7 @@ Gem::Specification.new do |s|
s.rdoc_options = ['--charset=UTF-8'] s.rdoc_options = ['--charset=UTF-8']
s.extra_rdoc_files = %w[README.md LICENSE] s.extra_rdoc_files = %w[README.md LICENSE]
s.add_dependency 'rdoc', '~> 6'
s.add_dependency 'gollum-lib', '~> 5.1' s.add_dependency 'gollum-lib', '~> 5.1'
s.add_dependency 'kramdown', '~> 2.3' s.add_dependency 'kramdown', '~> 2.3'
s.add_dependency 'kramdown-parser-gfm', '~> 1.1.0' s.add_dependency 'kramdown-parser-gfm', '~> 1.1.0'
+3 -2
View File
@@ -29,9 +29,10 @@ module Gollum
@@filters[pattern] = replacement @@filters[pattern] = replacement
end end
def self.apply_filters(data) def self.apply_filters(wiki_page, data)
@@filters.each do |pattern, replacement| @@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 end
data data
end end
+6 -7
View File
@@ -103,8 +103,7 @@ module Precious
end end
before do before do
settings.wiki_options[:allow_editing] = settings.wiki_options.fetch(:allow_editing, true) @allow_editing = settings.wiki_options.fetch(:allow_editing, true)
@allow_editing = settings.wiki_options[:allow_editing]
@critic_markup = settings.wiki_options[:critic_markup] @critic_markup = settings.wiki_options[:critic_markup]
@redirects_enabled = settings.wiki_options.fetch(:redirects_enabled, true) @redirects_enabled = settings.wiki_options.fetch(:redirects_enabled, true)
@per_page_uploads = settings.wiki_options[:per_page_uploads] @per_page_uploads = settings.wiki_options[:per_page_uploads]
@@ -112,8 +111,6 @@ module Precious
@wiki_title = settings.wiki_options.fetch(:title, 'Gollum Wiki') @wiki_title = settings.wiki_options.fetch(:title, 'Gollum Wiki')
forbid unless @allow_editing || request.request_method == 'GET'
if settings.wiki_options[:template_dir] if settings.wiki_options[:template_dir]
Precious::Views::Layout.extend Precious::Views::TemplateCascade Precious::Views::Layout.extend Precious::Views::TemplateCascade
Precious::Views::Layout.template_priority_path = settings.wiki_options[:template_dir] 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) config.manifest = Sprockets::Manifest.new(settings.sprockets, @static_assets_path)
end end
end end
forbid unless @allow_editing || request.request_method == 'GET'
end end
get '/' do get '/' do
@@ -369,7 +368,7 @@ module Precious
@name = wikip.name @name = wikip.name
@ext = wikip.ext @ext = wikip.ext
@path = wikip.path @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 @allow_uploads = wikip.wiki.allow_uploads
@upload_dest = find_upload_dest(wikip.fullpath) @upload_dest = find_upload_dest(wikip.fullpath)
@@ -661,9 +660,9 @@ module Precious
end end
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 = 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 end
def update_wiki_page(wiki, page, content, commit, name = nil, format = nil) 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}"
+39 -10
View File
@@ -4,7 +4,7 @@
<h1 class="header-title text-center text-md-left py-4"> <h1 class="header-title text-center text-md-left py-4">
<span class="f1-light text-gray-light"> <span class="f1-light text-gray-light">
Comparing versions of {{t.comparing_versions_of}}
</span> </span>
{{name}} {{name}}
</h1> </h1>
@@ -21,15 +21,34 @@
{{#allow_editing}} {{#allow_editing}}
<form name="gollum-revert" action="{{revert_path}}/{{escaped_url_path}}/{{before}}/{{after}}" method="post" id="gollum-revert-form"></form> <form name="gollum-revert" action="{{revert_path}}/{{escaped_url_path}}/{{before}}/{{after}}" method="post" id="gollum-revert-form"></form>
<span class="pb-4"> <span class="pb-4">
<button class="btn btn-sm" type="submit" onclick="$('#gollum-revert-form').submit()">Revert Changes</button> <button
class="btn btn-sm"
onclick="$('#gollum-revert-form').submit()"
type="submit"
>
{{t.revert}}
</button>
</span> </span>
{{/allow_editing}} {{/allow_editing}}
{{/show_revert}} {{/show_revert}}
<a href="{{history_path}}/{{escaped_url_path}}" class="btn btn-sm action-page-history">Back to Page History</a>
<a
class="btn btn-sm action-page-history"
href="{{history_path}}/{{escaped_url_path}}"
>
{{t.back_to_page_history}}
</a>
</div> </div>
<div class="Box data highlight"> <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> <div class="Box-header Box--condensed Box-header--gray">
{{path}}
<span class="px-2 float-right">
{{t.comparing_from}}
</span>
</div>
<table> <table>
{{#lines}} {{#lines}}
<tr> <tr>
@@ -47,12 +66,22 @@
<div class="pt-4" id="footer"> <div class="pt-4" id="footer">
{{#show_revert}} {{#show_revert}}
{{#allow_editing}} {{#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> <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}} {{/allow_editing}}
{{/show_revert}} {{/show_revert}}
<div class="pt-4">
<a href="#">Back to Top</a>
</div>
</div>
</div>
<div class="pt-4">
<a href="#">
{{t.back_to_top}}
</a>
</div>
</div>
</div>
+1 -1
View File
@@ -1,6 +1,6 @@
<div id="wiki-wrapper" class="error"> <div id="wiki-wrapper" class="error">
<div id="error"> <div id="error">
<h1>Error</h1> <h1>{{t.error}}</h1>
<p> <p>
{{message}} {{message}}
</p> </p>
+14 -5
View File
@@ -4,7 +4,7 @@
<h1 class="header-title text-center text-md-left py-4"> <h1 class="header-title text-center text-md-left py-4">
<span class="f1-light text-gray-light"> <span class="f1-light text-gray-light">
History for {{t.history_for}}
</span> </span>
{{name}} {{name}}
</h1> </h1>
@@ -27,7 +27,13 @@
<span class="flex-auto col-5">{{message}}</span> <span class="flex-auto col-5">{{message}}</span>
<span class="pl-4 float-right"> <span class="pl-4 float-right">
<a href="{{href}}" class="btn btn-outline text-mono">{{id7}}</a> <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> <a
class="btn btn-outline"
href="{{href_page}}"
title="{{t.browse_in_history_description}}"
>
{{#octicon}}code{{/octicon}}
</a>
</span> </span>
</li> </li>
{{/versions}} {{/versions}}
@@ -35,11 +41,14 @@
</form> </form>
</div> </div>
<div id="footer"> <div id="footer">
<div class="pt-4"> <div class="pt-4">
<button class="btn btn-sm action-compare-revision" type="submit">Compare Revisions</button> <button
class="btn btn-sm action-compare-revision"
type="submit"
>
{{t.compare_revisions}}
</button>
</div> </div>
</div> </div>
</div> </div>
+16 -3
View File
@@ -21,7 +21,15 @@
<span class="pr-2">{{{icon}}}</span> <span class="pr-2">{{{icon}}}</span>
<span><a href="{{url}}">{{name}}</a></span> <span><a href="{{url}}">{{name}}</a></span>
{{#allow_editing}} {{#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}} {{#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}} {{/allow_editing}}
</li> </li>
{{/files_folders}} {{/files_folders}}
@@ -33,13 +41,18 @@
{{#no_results}} {{#no_results}}
<p id="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> </p>
{{/no_results}} {{/no_results}}
</div> </div>
<div class="pt-4" id="footer"> <div class="pt-4" id="footer">
<a href="#">Back to Top</a> <a href="#">
{{t.back_to_top}}
</a>
</div> </div>
</div> </div>
+20 -3
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"> <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
<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> 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> </div>
</nav> </nav>
+9 -5
View File
@@ -4,7 +4,7 @@
<h1 class="header-title text-center text-md-left py-4"> <h1 class="header-title text-center text-md-left py-4">
<span class="f1-light text-gray-light"> <span class="f1-light text-gray-light">
Search results for {{t.search_results_for}}
</span> </span>
{{name}} {{name}}
</h1> </h1>
@@ -21,7 +21,12 @@
<li class="Box-row Box-row--gray"> <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="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> <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> </li>
<div class="search-context"> <div class="search-context">
@@ -29,7 +34,6 @@
<li class="Box-row border-0"><span class="text-italic">{{.}}</span></li> <li class="Box-row border-0"><span class="text-italic">{{.}}</span></li>
{{/context}} {{/context}}
</div> </div>
{{/results}} {{/results}}
</ul> </ul>
</div> </div>
@@ -37,12 +41,12 @@
{{#no_results}} {{#no_results}}
<p id="no-results"> <p id="no-results">
There are no results for your search <strong>{{query}}</strong>. {{t.no_results}} <strong>{{query}}</strong>.
</p> </p>
{{/no_results}} {{/no_results}}
<div id="footer" class="mt-4"> <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>
</div> </div>
+1 -1
View File
@@ -6,7 +6,7 @@ module Precious
attr_reader :page, :diff, :versions, :message, :allow_editing attr_reader :page, :diff, :versions, :message, :allow_editing
def title def title
"Comparison of #{@page.title}" [t[:comparison_of], @page.title].join(" ")
end end
def before def before
+8 -1
View File
@@ -21,6 +21,13 @@ module Precious
autofill I18n.t(locale_klass_name) autofill I18n.t(locale_klass_name)
end 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 private
# Recursively looks up I18n translation values and autofills any YAML # Recursively looks up I18n translation values and autofills any YAML
@@ -42,7 +49,7 @@ module Precious
end end
def fill_argument_content(i18n_key, i18n_value) 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]/, '') method_name = argument.gsub(/[^\w]/, '')
next if method_name.nil? next if method_name.nil?
+1 -1
View File
@@ -9,7 +9,7 @@ module Precious
attr_reader :wiki attr_reader :wiki
def title def title
"Latest Changes (Globally)" t[:title]
end end
def versions def versions
+1 -1
View File
@@ -20,7 +20,7 @@ module Precious
end end
def title def title
"Home" t[:title]
end end
def has_path def has_path
+2 -2
View File
@@ -3,11 +3,11 @@ require 'pathname'
module Precious module Precious
module Views module Views
class Overview < Layout class Overview < Layout
attr_reader :results, :ref, :allow_editing, :newable attr_reader :name, :results, :ref, :allow_editing, :newable
HIDDEN_PATHS = ['.gitkeep'] HIDDEN_PATHS = ['.gitkeep']
def title def title
"Overview of #{@ref}" t[:title]
end end
# def editable # def editable
+1 -1
View File
@@ -23,7 +23,7 @@ module Precious
end end
def title def title
"Search results for " + @query t[:title]
end end
def search def search
+6 -2
View File
@@ -11,9 +11,13 @@ module Precious
end end
def first_path_available(name) def first_path_available(name)
priority = File.join(template_priority_path, "#{name}.#{template_extension}")
default = File.join(template_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 end
# Method should track lib/mustache/settings.rb from Mustache project. # Method should track lib/mustache/settings.rb from Mustache project.
+98 -2
View File
@@ -15,12 +15,13 @@ describe Precious::Views::LocaleHelpers do
end end
def setup def setup
::I18n.available_locales = [:en, :de] I18n.available_locales = [:en, :de]
::I18n.load_path = Dir[File.expand_path("test/support/locales" + "/*.yml")] I18n.load_path = Dir[File.expand_path("test/support/locales" + "/*.yml")]
end end
def teardown def teardown
I18n.locale = :en I18n.locale = :en
I18n.load_path = Dir[::File.expand_path("lib/gollum/locales") + "/*.yml"]
end end
let(:dummy_instance) { TestClass.new } let(:dummy_instance) { TestClass.new }
@@ -131,4 +132,99 @@ describe Precious::Views::LocaleHelpers do
end end
end 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 end
+30 -10
View File
@@ -1,18 +1,20 @@
require 'rubygems' require 'rubygems'
require 'rack/test' require 'rack/test'
require 'test/unit'
require 'shoulda' require 'shoulda'
require 'mocha/setup' require 'minitest/autorun'
require 'fileutils'
require 'minitest/reporters' require 'minitest/reporters'
require 'minitest/spec' require 'minitest/spec'
require 'mocha/setup'
require 'fileutils'
require 'tmpdir' require 'tmpdir'
# Silence locale validation warning # Silence locale validation warning
require 'i18n' require 'i18n'
I18n.enforce_available_locales = false I18n.enforce_available_locales = false
MiniTest::Reporters.use! Minitest::Reporters.use! [
Minitest::Reporters::DefaultReporter.new({color: true})
]
dir = File.dirname(File.expand_path(__FILE__)) dir = File.dirname(File.expand_path(__FILE__))
$LOAD_PATH.unshift(File.join(dir, '..', 'lib')) $LOAD_PATH.unshift(File.join(dir, '..', 'lib'))
@@ -62,14 +64,29 @@ def normal(text)
text text
end end
# test/spec/mini 3 # The following configuration originates from this gist:
# http://gist.github.com/25455 # http://gist.github.com/25455
# chris@ozmm.org #
# file:lib/test/spec/mini.rb # 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) def context(*args, &block)
return super unless (name = args.first) && block return super unless (name = args.first) && block
require 'test/unit' klass = Class.new(Minitest::Test) do
klass = Class.new(defined?(ActiveSupport::TestCase) ? ActiveSupport::TestCase : Test::Unit::TestCase) do
def self.test(name, &block) def self.test(name, &block)
define_method("test_#{name.gsub(/\W/, '_')}", &block) if block define_method("test_#{name.gsub(/\W/, '_')}", &block) if block
end end
@@ -85,10 +102,13 @@ def context(*args, &block)
define_method(:teardown, &block) define_method(:teardown, &block)
end end
end end
( (
class << klass; class << klass;
self self
end).send(:define_method, :name) { name.gsub(/\W/, '_') } end
).send(:define_method, :name) { name.gsub(/\W/, '_') }
$contexts << klass $contexts << klass
klass.class_eval &block klass.class_eval &block
end end
+51 -31
View File
@@ -3,84 +3,104 @@ require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
context "Precious::Views::Editing" do context "Precious::Views::Editing" do
include Rack::Test::Methods include Rack::Test::Methods
setup do setup do
@path = cloned_testpath('examples/revert.git') @path = cloned_testpath('examples/revert.git')
Precious::App.set(:gollum_path, @path) Precious::App.set(:gollum_path, @path)
Precious::App.set(:wiki_options, {allow_editing: true, allow_uploads: true})
@wiki = Gollum::Wiki.new(@path) @wiki = Gollum::Wiki.new(@path)
end end
teardown do teardown do
Precious::App.set(:wiki_options, {allow_editing: true, allow_uploads: true})
FileUtils.rm_rf(@path) FileUtils.rm_rf(@path)
end end
test "creating page is blocked" do test 'creating pages is not blocked' do
Precious::App.set(:wiki_options, { allow_editing: false}) post '/gollum/create',
post "/gollum/create", :content => 'abc', :page => "D", content: 'abc',
:format => 'markdown', :message => 'def' format: 'markdown',
assert !last_response.ok? message: 'def',
page: 'D'
page = @wiki.page('D') assert_equal last_response.status, 302
assert page.nil?
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 end
test ".redirects.gollum file should not be accessible" do test ".redirects.gollum file should not be accessible" do
Precious::App.set(:wiki_options, { allow_editing: true, allow_uploads: true })
get '/.redirects.gollum' get '/.redirects.gollum'
assert_match /Accessing this resource is not allowed/, last_response.body assert_match /Accessing this resource is not allowed/, last_response.body
end end
test ".redirects.gollum file should not be editable" do 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' get '/gollum/edit/.redirects.gollum'
assert_match /Changing this resource is not allowed/, last_response.body assert_match /Changing this resource is not allowed/, last_response.body
end end
test "frontend links for editing are not blocked" do test "frontend links for editing are not blocked" do
Precious::App.set(:wiki_options, { allow_editing: true, allow_uploads: true })
get '/A' get '/A'
assert_match /Delete this Page/, last_response.body, "'Delete this Page' link is blocked in page template" assert last_response.body.include? "Delete this Page"
assert_match /New/, last_response.body, "'New' button is blocked in page template" assert last_response.body.include? "New"
assert_match /Upload\b/, last_response.body, "'Upload' link is blocked in page template" assert last_response.body.include? "<span>Upload</span>"
assert_match /Rename/, last_response.body, "'Rename' link is blocked in page template" assert last_response.body.include? "Rename"
assert_match /Edit/, last_response.body, "'Edit' link is blocked in page template" assert last_response.body.include? "Edit"
get '/gollum/overview' 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' 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" refute last_response.body.include? "Edit Page"
assert_match /Revert Changes/, last_response.body, "'Revert Changes' link is blocked in compare template"
assert last_response.body.include? "Revert Changes"
end end
test "frontend links for editing blocked" do 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' get '/A'
assert_no_match /Delete this Page/, last_response.body, "'Delete this Page' link not blocked in page template" refute last_response.body.include? "Delete this Page"
assert_no_match /New/, last_response.body, "'New' button not blocked in page template" refute last_response.body.include? "<span>Upload</span>"
assert_no_match /Upload\b/, last_response.body, "'Upload' link not blocked in page template" refute last_response.body.include? "Rename"
assert_no_match /Rename/, last_response.body, "'Rename' link not blocked in page template" refute last_response.body.include? "Edit"
assert_no_match /Edit/, last_response.body, "'Edit' link not blocked in page template" refute last_response.body.include? "New"
get '/gollum/overview' 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' 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" refute last_response.body.include? "Edit Page"
assert_no_match /Revert Changes/, last_response.body, "'Revert Changes' link not blocked in compare template" refute last_response.body.include? "Revert Changes"
end end
def app def app
+69 -22
View File
@@ -104,7 +104,7 @@ EOF
page_2 = @wiki.page(page_1.name) page_2 = @wiki.page(page_1.name)
assert_equal 'abc', page_2.raw_data assert_equal 'abc', page_2.raw_data
assert_equal 'def', page_2.version.message 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 end
test "edit page fails when page is outdated (edit collision)" do test "edit page fails when page is outdated (edit collision)" do
@@ -117,7 +117,7 @@ EOF
@wiki.clear_cache @wiki.clear_cache
page = @wiki.page('A') page = @wiki.page('A')
new_sha = page.sha 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', post "/gollum/edit/A", :content => 'def', :page => 'A',
:format => page.format, :message => 'def', :etag => old_sha :format => page.format, :message => 'def', :etag => old_sha
@@ -134,7 +134,7 @@ EOF
page_2 = @wiki.page(page_1.name) page_2 = @wiki.page(page_1.name)
assert_equal 'abc', page_2.raw_data assert_equal 'abc', page_2.raw_data
assert_equal '[no message]', page_2.version.message 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 end
test "edit page with slash" do test "edit page with slash" do
@@ -165,12 +165,12 @@ EOF
assert_equal 'header', header_2.raw_data assert_equal 'header', header_2.raw_data
assert_equal 'footer', foot_2.raw_data assert_equal 'footer', foot_2.raw_data
assert_equal 'def', foot_2.version.message assert_equal 'def', foot_2.version.message
assert_not_equal foot_1.version.sha, foot_2.version.sha refute_equal foot_1.version.sha, foot_2.version.sha
assert_not_equal header_1.version.sha, header_2.version.sha refute_equal header_1.version.sha, header_2.version.sha
assert_equal 'sidebar', side_2.raw_data assert_equal 'sidebar', side_2.raw_data
assert_equal 'def', side_2.version.message 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 assert_equal commits, @wiki.repo.commits('master').size
end end
@@ -187,7 +187,7 @@ EOF
page_2 = @wiki.page('C') page_2 = @wiki.page('C')
assert_equal "INITIAL\n\nSPAM2\n", page_2.raw_data assert_equal "INITIAL\n\nSPAM2\n", page_2.raw_data
assert_equal 'def', page_2.last_version.message 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 end
test "rename preserves format" do test "rename preserves format" do
@@ -222,7 +222,7 @@ EOF
test "renames page in subdirectory" do test "renames page in subdirectory" do
page_1 = @wiki.page("G/H") 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' post "/gollum/rename/G/H", :rename => "/I/C", :message => 'def'
follow_redirect! follow_redirect!
@@ -234,12 +234,12 @@ EOF
page_2 = @wiki.page('I/C') page_2 = @wiki.page('I/C')
assert_equal "INITIAL\n\nSPAM2\n", page_2.raw_data assert_equal "INITIAL\n\nSPAM2\n", page_2.raw_data
assert_equal 'def', page_2.last_version.message 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 end
test "renames page relative in subdirectory" do test "renames page relative in subdirectory" do
page_1 = @wiki.page("G/H") 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' post "/gollum/rename/G/H", :rename => "K/C", :message => 'def'
follow_redirect! follow_redirect!
@@ -251,7 +251,7 @@ EOF
page_2 = @wiki.page('G/K/C') page_2 = @wiki.page('G/K/C')
assert_equal "INITIAL\n\nSPAM2\n", page_2.raw_data assert_equal "INITIAL\n\nSPAM2\n", page_2.raw_data
assert_equal 'def', page_2.last_version.message 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 end
test "creates page" do test "creates page" do
@@ -320,7 +320,7 @@ EOF
name = "#{dir}/bar" name = "#{dir}/bar"
get "/gollum/create/#{name}" get "/gollum/create/#{name}"
assert_match(/\/#{dir}/, last_response.body) assert_match(/\/#{dir}/, last_response.body)
assert_no_match(/[^\/]#{dir}/, last_response.body) refute_match(/[^\/]#{dir}/, last_response.body)
end end
test "create with template succeed if template exists" do test "create with template succeed if template exists" do
@@ -344,6 +344,45 @@ EOF
Precious::App.set(:wiki_options, { :template_page => false }) Precious::App.set(:wiki_options, { :template_page => false })
end 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 test "edit returns nil for non-existant page" do
# post '/edit' fails. post '/edit/' works. # post '/edit' fails. post '/edit/' works.
page = 'not-real-page' page = 'not-real-page'
@@ -351,7 +390,7 @@ EOF
post '/gollum/edit/', :content => 'edit_msg', post '/gollum/edit/', :content => 'edit_msg',
:page => page, :path => path, :message => '' :page => page, :path => path, :message => ''
page_e = @wiki.page(::File.join(path,page)) page_e = @wiki.page(::File.join(path,page))
assert_equal nil, page_e assert_nil page_e
end end
test "edit allows changing format" do test "edit allows changing format" do
@@ -407,13 +446,21 @@ EOF
@wiki.clear_cache @wiki.clear_cache
page = @wiki.page(name) page = @wiki.page(name)
assert_not_equal 'abc', page.raw_data refute_equal 'abc', page.raw_data
end end
test "uploading is not allowed unless explicitly enabled" do test "uploading is not allowed unless explicitly enabled" do
temp_upload_file = Tempfile.new(['upload', '.file']) << 'abc' temp_upload_file = Tempfile.new(['upload', '.file']) << 'abc'
temp_upload_file.close 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 assert_equal 405, last_response.status
end end
@@ -483,7 +530,7 @@ EOF
@wiki.clear_cache @wiki.clear_cache
page = @wiki.page(name) page = @wiki.page(name)
assert_equal nil, page assert_nil page
end end
test "previews content" do test "previews content" do
@@ -507,7 +554,7 @@ EOF
@wiki.clear_cache @wiki.clear_cache
page2 = @wiki.page('B') 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 "INITIAL", page2.raw_data.strip
assert_equal "Revert commit 7c45b5f", page2.version.message assert_equal "Revert commit 7c45b5f", page2.version.message
end end
@@ -521,7 +568,7 @@ EOF
@wiki.clear_cache @wiki.clear_cache
page2 = @wiki.page('A') 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 assert_equal "INITIAL", page2.raw_data.strip
end end
@@ -583,7 +630,7 @@ EOF
{ :name => 'user1', :email => 'user1' }); { :name => 'user1', :email => 'user1' });
get page get page
assert_no_match /custom.js/, last_response.body refute_match /custom.js/, last_response.body
end end
test "add custom.js if setting" do test "add custom.js if setting" do
@@ -652,7 +699,7 @@ EOF
get "A" get "A"
assert last_response.ok? 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" get "A/fc66539528eb96f21b2bbdbf557788fe8a1196ac"
@@ -834,7 +881,7 @@ context "Frontend with lotr" do
get "Data.csv/#{old_sha}" get "Data.csv/#{old_sha}"
assert last_response.ok? assert last_response.ok?
assert_no_match /Samwise,Gamgee/, last_response.body refute_match /Samwise,Gamgee/, last_response.body
get "Data.csv/#{update_sha}" get "Data.csv/#{update_sha}"
assert last_response.ok? assert last_response.ok?
@@ -879,7 +926,7 @@ context "Frontend with page-file-dir" do
name = "#{dir}/baz" name = "#{dir}/baz"
get "/gollum/create/#{name}" get "/gollum/create/#{name}"
assert_match(/\/#{dir}/, last_response.body) assert_match(/\/#{dir}/, last_response.body)
assert_no_match(/[^\/]#{dir}/, last_response.body) refute_match(/[^\/]#{dir}/, last_response.body)
end end
test "use custom.css from page-file-dir path if page-file-dir is set" do test "use custom.css from page-file-dir path if page-file-dir is set" do
+29 -31
View File
@@ -1,28 +1,6 @@
# ~*~ encoding: utf-8 ~*~ # ~*~ encoding: utf-8 ~*~
require File.expand_path(File.join(File.dirname(__FILE__), 'helper')) 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) def load_script(**args)
settings = { settings = {
:run_silent => true, :run_silent => true,
@@ -32,9 +10,12 @@ def load_script(**args)
:page_file_dir => nil, :page_file_dir => nil,
}.merge(args) }.merge(args)
settings.each do |const, val| settings.each do |setting, val|
const_name = const.to_s.upcase variable_name = :"@@#{setting.to_s}"
Object.const_set(const_name, val) unless Object.const_defined?(const_name) && Object.const_get(const_name) == val
unless Object.class_variable_defined?(variable_name) && Object.class_variable_get(variable_name) == val
Object.class_variable_set(variable_name, val)
end
end end
script_path = File.expand_path(File.join(File.dirname(__FILE__), '../', 'bin', 'gollum-migrate-tags')) script_path = File.expand_path(File.join(File.dirname(__FILE__), '../', 'bin', 'gollum-migrate-tags'))
@@ -44,8 +25,6 @@ def load_script(**args)
end end
end end
unless ENV['CI']
context '4.x -> 5.x tag migrator' do context '4.x -> 5.x tag migrator' do
include Rack::Test::Methods include Rack::Test::Methods
@@ -54,10 +33,31 @@ unless ENV['CI']
end end
test 'repair broken links' do 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 load_script
f = ::File.new(::File.join(@path, 'Subdir/Foo.md'), 'r') file = ::File.new(::File.join(@path, 'Subdir/Foo.md'), 'r')
assert_equal result, f.read 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 end
test 'change spaced filenames to hyphenated filenames' do test 'change spaced filenames to hyphenated filenames' do
@@ -82,5 +82,3 @@ unless ENV['CI']
FileUtils.rm_rf(@path) FileUtils.rm_rf(@path)
end end
end 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 :@content, page.formatted_data
@view.instance_variable_set :@h1_title, false @view.instance_variable_set :@h1_title, false
assert_include @view.breadcrumb, "数学 📘" assert_includes @view.breadcrumb, "数学 📘"
end end
test 'page <title> is the page header from content, if present' do test 'page <title> is the page header from content, if present' do
+26 -10
View File
@@ -1,43 +1,59 @@
# ~*~ encoding: utf-8 ~*~ # ~*~ encoding: utf-8 ~*~
require File.expand_path(File.join(File.dirname(__FILE__), 'helper')) require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
class TestTemplateCascade < Minitest::Unit::TestCase context "Precious::Views::TemplateCascade" do
include Rack::Test::Methods include Rack::Test::Methods
def setup setup do
@path = cloned_testpath('examples/lotr.git') @path = cloned_testpath('examples/lotr.git')
Precious::App.set(:gollum_path, @path) 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) @wiki = Gollum::Wiki.new(@path)
end end
def teardown teardown do
FileUtils.rm_rf(@path) 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 end
def app def app
Precious::App Precious::App.new
end end
def test_overridden_page_template_is_used test "overridden_page_template_is_used" do
get '/Home' get '/Home'
assert last_response.body.include?('PAGE_OVERRIDE') assert last_response.body.include?('PAGE_OVERRIDE')
end end
def test_overridden_navbar_partial_is_used test "test_overridden_navbar_partial_is_used" do
get '/Home' get '/Home'
assert last_response.body.include?('NAVBAR_OVERRIDE') assert last_response.body.include?('NAVBAR_OVERRIDE')
end 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}) Precious::App.set(:wiki_options, {template_dir: nil})
get '/Home' get '/Home'
assert_equal '/Home', last_request.fullpath assert_equal '/Home', last_request.fullpath
assert last_response.ok? 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
end end