Compare commits

..

29 Commits

Author SHA1 Message Date
Dawa Ometto 9bc3baa1dc Force utf8 encoding for diffs 2021-07-31 10:29:13 +02:00
yy0931 046353cf7e Fix an IME rendering issue (#1735)
* Fix an IME rendering issue

* Execute rake precompile
2021-07-09 07:52:38 -07:00
benjamin wil 51f2f032d7 Add I18n interface for use in Mustache templates (#1679)
* Add `i18n` dependency

We will use `i18n` to provide localization for Gollum's frontend. I
chose this because it's a well-supported, pretty normal Ruby library.

* Configure I18n

- Locale files will be kept in `lib/gollum/locales/[lang].yml`
- The available locales, to start, will be English (`en`).

* Add I18n interface for mustache templates

This commit adds an interface that allows mustache templates to get I18n
translation strings, transform any arguments that may be present in
them, and then render them on the frontend.

This is our first real step to getting internationalizing the Gollum
frontend.
2021-06-27 09:26:45 -07:00
Dawa Ometto 70360edb96 Update test.yaml (#1734) 2021-06-26 22:06:34 +02:00
benjamin wil 2b12ab9206 Explicitly set encoding for Precious::App (#1731)
An issue was reported (see #1721) where, in docker containers where the
`LANG` was not being set, `Precious::App` would serve Mustache templates
in an ASCII encoding. This caused templates to error out.

In the past, this would have happened in environments where `LANG` was
not set and the Gollum applciation configuration had enabled MathJax.
Now, it happens even if MathJax is disabled because of a UTF-8 character
I added to the mobile navigation menu.

Basically, we should enforce a UTF-8 encoding from now on to avoid
runtime errors related to ASCII encoding.
2021-06-14 21:28:12 +02:00
Darless 87a01e04ce fixes #1723: Github Actions Supported (#1729)
* fixes #1723: Github Actions Supported

- This is to switch from Travis CI which is shutting down the org version,
  and the .com version, a free account is limited.
- Switch test environment variable from TRAVIS to CI to be more generic.

* Adding jruby-9.2.18.0 to matrix for github actions
2021-06-14 21:21:40 +02:00
Sam 5f04200bd0 README.md: Clarify that Gollum should run against an already-initialized Git repository. (#1722) 2021-06-13 14:34:28 -07:00
benjamin wil aa823b5a2d Use recent JRuby release for Travis CI (#1730)
Our JRuby CI runs have been errorring due to what I think is an issue
with an older `jruby-openssl` version.
2021-06-13 14:17:18 -07:00
Dawa Ometto 9012dee888 Release 5.2.3 2021-04-18 13:43:00 +02:00
benjamin wil 81d5f1a8bb Ensure <title> is rendered for pages (#1710)
I made a mistake when I made `#title` a private method. I did not see
that it was being called from `layout.mustache` to generate the
`<title></title>` tag in the `<head></head>` of each page.

This fixes my error, and adds tests so the behaviour is more explicit.
2021-04-05 09:26:50 -07:00
Dawa Ometto d2b0a22a8f Release 5.2.2 2021-03-27 19:43:38 +01:00
Dawa Ometto 355e6b1f18 Fix query ? in mathjax script path (#1706) 2021-03-27 19:40:35 +01:00
Nikita Ivanov 7a2c9107c3 Delete dublicate error (#1700) 2021-03-27 14:05:03 +01:00
benjamin wil 127473fff8 Fix tab navigation styles (#1696)
* Fix tabnav styles on #create and #edit views

The Primer CSS-provided `tabnav` styles were not being used on the Edit
and Preview tabs on the create and edit pages.

After following Primer's documentation [1], it looks like we were using
the `aria-current` attribute incorrectly. Dynamically adding/removing
this attribute on the selected tab fixes the issue.

[1]: https://primer-css-git-next-inputs.primer.now.sh/css/components/navigation#tabnav

* Recompile static assets
2021-03-23 09:13:23 -07:00
benjamin wil 9a79b0a800 Merge pull request #1701 from ViChyavIn/fix-focused-button
Fix focused button border shown wrong in dialogs
2021-03-23 07:49:52 -07:00
ViChyavIn ca13298d00 Update static assets 2021-03-23 13:43:26 +05:00
ViChyavIn eaf82e6367 Overflow is set to visible by default so declaration is removed 2021-03-23 13:39:44 +05:00
benjamin wil cae290ded7 Merge pull request #1697 from gollum/benjaminwil/fix-nav-outline
Fix nav outline styles
2021-03-22 10:21:29 -07:00
Benjamin Willems a22208a0be Use <button> instead of <a> without href
It is more semantic to use a `<button>` tag in the place of an `<a>`
when there is no other page being linked to. In this circumstance, we're
using JavaScript to present a modal to the user on click.

This change makes the "Upload" and "Rename" buttons appear in the
browser's tab index.
2021-03-21 14:21:07 -07:00
Benjamin Willems bc877dc9dc Fix indentation due to DOM simplification
We removed one of the parent elements of the `<nav>`, so we must
re-indent the entire file.
2021-03-21 14:19:32 -07:00
Benjamin Willems 40b1775d42 Make the main <nav> element a TableObject
There was a display issue, where navbar items's outline styles were
being cut off due to the parent `<nav>` element's margin and padding.

Fortunately, we can do away with the navbar wrapper div entirely. It was
not doing anything important except defining its children as
`TableObject` items. But we can just do this on the `<nav>` itself.
2021-03-21 14:18:45 -07:00
ViChyavIn c2dc605adb Fix focused button border shown wrong 2021-03-20 21:43:53 +05:00
benjamin wil a1e1af07a4 Merge pull request #1676 from gollum/benjaminwil/button-labels
Move "Page History" into button group
2021-03-15 08:24:04 -07:00
benjamin wil 76948130f6 Display button groups using Primer flex utilities
This small improvement just uses Primer `d-flex` utilities to `display:
flex;` instead of using style tags. It's preferable.
2021-03-06 16:19:01 -08:00
Benjamin Willems f71ba31bfe Move "Page History" into button group
If the user has edit permissions, the "History" button is shown in a
button group with "Edit" and "Rename". If the user does not have edit
permissions, it's shown by itself.

This commit also renames the label from "Page History" to "History".
2021-03-06 16:19:01 -08:00
Dawa Ometto b7caa228e6 Add webrick dependency (#1695)
* Remove webrick as dev dependency
2021-03-06 15:39:21 +01:00
Dawa Ometto 0101dd2f65 Update .travis.yml (#1690) 2021-03-06 10:06:11 +01:00
Dawa Ometto c8baa61fe3 Update image icon in editor (#1687) 2021-02-26 15:30:02 +01:00
Dawa Ometto 104335706a Faster tests (#1686) 2021-02-26 11:34:41 +01:00
36 changed files with 466 additions and 167 deletions
+29
View File
@@ -0,0 +1,29 @@
name: Ruby Build
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
ruby: [2.4.0, 2.6.0, 3.0.0, jruby-9.2.18.0]
steps:
- run: echo "The job was automatically triggered by a ${{ github.event_name }} event."
- run: echo "This job is now running on a ${{ runner.os }} server hosted by GitHub!"
- run: echo "The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}."
- name: Check out repository code
uses: actions/checkout@v2
- run: echo "The ${{ github.repository }} repository has been cloned to the runner."
- run: echo "The workflow is now ready to test your code on the runner."
- name: List files in the repository
run: |
ls ${{ github.workspace }}
- uses: actions/setup-java@v2
with:
distribution: 'adopt'
java-version: '9'
- uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: true
- name: exec rake
run: bundle exec rake
+1
View File
@@ -8,3 +8,4 @@ Gemfile.lock
.*
!.sprockets*
!lib/gollum/public/gollum/stylesheets/_styles.css
!.github*
+2 -1
View File
@@ -1,7 +1,8 @@
rvm:
- 2.4.0
- 2.6.0
- jruby-9.2.9.0
- 3.0.0
- jruby-9.2.18.0
jdk:
- oraclejdk9
before_install:
+2
View File
@@ -62,6 +62,8 @@ Pull Requests fixing bugs, implementing new features, or updating documentation
```
bundle exec rake test
```
To profile slow tests, you can use `bundle exec rake test TESTOPTS="--verbose"`.
### Working with test repositories
+1 -2
View File
@@ -6,5 +6,4 @@ end
gemspec
gem "rake", '~> 13.0'
gem 'rake', '~> 13.0'
+4
View File
@@ -1,3 +1,7 @@
# 5.2.3 2021-04-18
* Fix bug preventing page titles from being displayed
# 5.2.1 2021-02-25
* Fix include call to a missing asset (@benjaminwil). This caused slow first page loads on JRuby.
+3 -2
View File
@@ -2,10 +2,11 @@ gollum -- A git-based Wiki
====================================
[![Gem Version](https://badge.fury.io/rb/gollum.svg)](http://badge.fury.io/rb/gollum)
[![Build Status](https://travis-ci.org/gollum/gollum.svg?branch=master)](https://travis-ci.org/gollum/gollum)
![Build Status](https://github.com/gollum/gollum/actions/workflows/test.yaml/badge.svg)
[![Open Source Helpers](https://www.codetriage.com/gollum/gollum/badges/users.svg)](https://www.codetriage.com/gollum/gollum)
[![Cutting Edge Dependency Status](https://dometto-cuttingedge.herokuapp.com/github/gollum/gollum/svg 'Cutting Edge Dependency Status')](https://dometto-cuttingedge.herokuapp.com/github/gollum/gollum/info)
**Gollum version 5.0 is out!** See [here](https://github.com/gollum/gollum/wiki/5.0-release-notes) for a list of changes and new features compared to Gollum version 4.x, and see some [Screenshots](https://github.com/gollum/gollum/wiki/Screenshots) of Gollum's features.
## DESCRIPTION
@@ -45,7 +46,7 @@ Installation examples for individual systems can be seen [here](https://github.c
To run, simply:
1. Run: `gollum /path/to/wiki`.
1. Run: `gollum /path/to/wiki` where `/path/to/wiki` is an initialized Git repository.
2. Open `http://localhost:4567` in your browser.
See [below](#running-from-source) for information on running Gollum from source, as a Rack app, and more.
+9 -8
View File
@@ -5,8 +5,8 @@ Gem::Specification.new do |s|
s.required_ruby_version = '>= 1.9'
s.name = 'gollum'
s.version = '5.2.1'
s.date = '2021-02-25'
s.version = '5.2.3'
s.date = '2021-04-18'
s.license = 'MIT'
s.summary = 'A simple, Git-powered wiki.'
@@ -38,6 +38,8 @@ Gem::Specification.new do |s|
s.add_dependency 'sprockets-helpers', '~> 1.2'
s.add_dependency 'rss', '~> 0.2.9'
s.add_dependency 'therubyrhino', '~> 2.1.0'
s.add_dependency 'webrick', '~> 1.7'
s.add_dependency 'i18n', '~> 1.8'
s.add_development_dependency 'rack-test', '~> 0.6.3'
s.add_development_dependency 'shoulda', '~> 3.6.0'
@@ -45,7 +47,6 @@ Gem::Specification.new do |s|
s.add_development_dependency 'twitter_cldr', '~> 3.2.0'
s.add_development_dependency 'mocha', '~> 1.8.0'
s.add_development_dependency 'test-unit', '~> 3.3.0'
s.add_development_dependency 'webrick', '~> 1.4.2'
# = MANIFEST =
s.files = %w[
@@ -69,11 +70,11 @@ Gem::Specification.new do |s|
lib/gollum/app.rb
lib/gollum/assets.rb
lib/gollum/helpers.rb
lib/gollum/public/assets/.sprockets-manifest-15b663a27211dc9de9a452b4b74462d7.json
lib/gollum/public/assets/app-7a0bbff2e8bad3033e7c17e0e0f886f336a9d23d3b912dcd2ae389c48b4b63e6.css
lib/gollum/public/assets/app-7a0bbff2e8bad3033e7c17e0e0f886f336a9d23d3b912dcd2ae389c48b4b63e6.css.gz
lib/gollum/public/assets/app-7a4bd115f4bc7ece39bc8073ca0ffad7c5e55cc5837b1464a12dead4905cefb2.js
lib/gollum/public/assets/app-7a4bd115f4bc7ece39bc8073ca0ffad7c5e55cc5837b1464a12dead4905cefb2.js.gz
lib/gollum/public/assets/.sprockets-manifest-de7bb79aec424e55af1acdcc4237b301.json
lib/gollum/public/assets/app-0fd228e26bfbe6fe31a2da268eb0e98e780c1191c1a918adf383377946e9c838.js
lib/gollum/public/assets/app-0fd228e26bfbe6fe31a2da268eb0e98e780c1191c1a918adf383377946e9c838.js.gz
lib/gollum/public/assets/app-ad43ca64b295d8444b10f22ee868f18429268af498f1bc515434878b690e37a2.css
lib/gollum/public/assets/app-ad43ca64b295d8444b10f22ee868f18429268af498f1bc515434878b690e37a2.css.gz
lib/gollum/public/assets/criticmarkup-31ae5d3282bbb8e7b7c3c9917e9fb68e3315a6b4a75da6cec48d21b8846905c4.css
lib/gollum/public/assets/criticmarkup-31ae5d3282bbb8e7b7c3c9917e9fb68e3315a6b4a75da6cec48d21b8846905c4.css.gz
lib/gollum/public/assets/editor-db10c8351306e92f1926ba225d0cd9c8e886482b3b9820a85825ec3abab5f1cf.js
+6 -19
View File
@@ -5,35 +5,23 @@ require 'digest/sha1'
require 'ostruct'
# external
require 'i18n'
require 'github/markup'
require 'rhino' if RUBY_PLATFORM == 'java'
# internal
require File.expand_path('../gollum/uri_encode_component', __FILE__)
require ::File.expand_path('../gollum/uri_encode_component', __FILE__)
module Gollum
VERSION = '5.2.1'
VERSION = '5.2.3'
::I18n.available_locales = [:en]
::I18n.load_path = Dir[::File.expand_path("lib/gollum/locales") + "/*.yml"]
def self.assets_path
::File.expand_path('gollum/public', ::File.dirname(__FILE__))
end
class Error < StandardError;
end
class DuplicatePageError < Error
attr_accessor :dir
attr_accessor :existing_path
attr_accessor :attempted_path
def initialize(dir, existing, attempted, message = nil)
@dir = dir
@existing_path = existing
@attempted_path = attempted
super(message || "Cannot write #{@dir}/#{@attempted_path}, found #{@dir}/#{@existing_path}.")
end
end
class TemplateFilter
@@filters = {}
@@ -48,5 +36,4 @@ module Gollum
data
end
end
end
+21 -17
View File
@@ -1,4 +1,5 @@
# ~*~ encoding: utf-8 ~*~
# encoding: UTF-8
require 'cgi'
require 'sinatra'
require 'sinatra/namespace'
@@ -14,6 +15,7 @@ require 'pathname'
require 'gollum'
require 'gollum/assets'
require 'gollum/views/helpers'
require 'gollum/views/helpers/locale_helpers'
require 'gollum/views/layout'
require 'gollum/views/editable'
require 'gollum/views/has_page'
@@ -40,7 +42,7 @@ Gollum::set_git_max_filesize(190 * 10**6)
# See the wiki.rb file for more details on wiki options
module Precious
# For use with the --base-path option.
class MapGollum
def initialize(base_path)
@@ -63,12 +65,14 @@ module Precious
@mg.call(env)
end
end
class App < Sinatra::Base
register Mustache::Sinatra
register Sinatra::Namespace
include Precious::Helpers
Encoding.default_external = "UTF-8"
dir = File.dirname(File.expand_path(__FILE__))
set :sprockets, ::Precious::Assets.sprockets(dir)
@@ -102,7 +106,7 @@ module Precious
@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]
@wiki_title = settings.wiki_options.fetch(:title, 'Gollum Wiki')
forbid unless @allow_editing || request.request_method == 'GET'
@@ -117,10 +121,10 @@ module Precious
@js = settings.wiki_options[:js]
@mathjax_config = settings.wiki_options[:mathjax_config]
@use_static_assets = settings.wiki_options.fetch(:static, settings.environment == :production || settings.environment == :staging)
@use_static_assets = settings.wiki_options.fetch(:static, settings.environment != :development)
@static_assets_path = settings.wiki_options.fetch(:static_assets_path, ::File.join(File.dirname(__FILE__), 'public/assets'))
@mathjax_path = ::File.join(File.dirname(__FILE__), 'public/gollum/javascript/MathJax')
Sprockets::Helpers.configure do |config|
config.environment = settings.sprockets
config.environment.context_class.class_variable_set(:@@base_url, @base_url)
@@ -219,7 +223,7 @@ module Precious
# AJAX calls only
post '/upload_file' do
wiki = wiki_new
halt 405 unless wiki.allow_uploads
@@ -235,7 +239,7 @@ module Precious
dir.sub!(/^#{wiki.base_path}/, '') if wiki.base_path
# remove base_url and gollum/* subpath if necessary
dir.sub!(/^\/gollum\/[-\w]+\//, '')
# remove file extension
# remove file extension
dir.sub!(/#{::File.extname(dir)}$/, '')
# revert escaped whitespaces
dir.gsub!(/%20/, ' ')
@@ -317,7 +321,7 @@ module Precious
end
post '/edit/*' do
etag = params[:etag]
etag = params[:etag]
path = "/#{clean_url(sanitize_empty_params(params[:path]))}"
wiki = wiki_new
page = wiki.page(::File.join(path, params[:page]))
@@ -327,7 +331,7 @@ module Precious
# Signal edit collision and return the page's most recent version
halt 412, {etag: page.sha, text_data: page.text_data}.to_json
end
committer = Gollum::Committer.new(wiki, commit_message)
commit = { :committer => committer }
@@ -348,7 +352,7 @@ module Precious
commit[:message] = "Deleted #{filepath}"
wiki.delete_file(filepath, commit)
end
end
end
get '/create/*' do
forbid unless @allow_editing
@@ -406,7 +410,7 @@ module Precious
else
sha2, sha1 = sha1, "#{sha1}^" if !sha2
@versions = [sha1, sha2]
@diff = wiki.repo.diff(@versions.first, @versions.last, @page.path)
@diff = wiki.repo.diff(@versions.first, @versions.last, @page.path).force_encoding('utf-8')
@message = 'The patch does not apply.'
mustache :compare
end
@@ -471,7 +475,7 @@ module Precious
@versions = [start_version, end_version]
wiki = wikip.wiki
@page = wikip.page
@diff = wiki.repo.diff(@versions.first, @versions.last, @page.path)
@diff = wiki.repo.diff(@versions.first, @versions.last, @page.path).force_encoding('utf-8')
if @diff.empty?
@message = 'Could not compare these two revisions, no differences were found.'
mustache :error
@@ -515,7 +519,7 @@ module Precious
@commit = wiki.repo.commit(version)
parent = @commit.parent
parent_id = parent.nil? ? nil : parent.id
@diff = wiki.repo.diff(parent_id, version)
@diff = wiki.repo.diff(parent_id, version).force_encoding('utf-8')
mustache :commit
rescue Gollum::Git::NoSuchShaFound
@message = "Invalid commit: #{@version}"
@@ -625,7 +629,7 @@ module Precious
end
end
end
def show_file(file)
return unless file
if file.on_disk?
@@ -683,4 +687,4 @@ module Precious
end
end
end
end
@@ -1 +0,0 @@
{"files":{"app-7a4bd115f4bc7ece39bc8073ca0ffad7c5e55cc5837b1464a12dead4905cefb2.js":{"logical_path":"app.js","mtime":"2021-02-24T23:16:14-08:00","size":135925,"digest":"7a4bd115f4bc7ece39bc8073ca0ffad7c5e55cc5837b1464a12dead4905cefb2","integrity":"sha256-ekvRFfS8fs45vIBzyg/618XlXMWDexRkoS3q1JBc77I="},"editor-db10c8351306e92f1926ba225d0cd9c8e886482b3b9820a85825ec3abab5f1cf.js":{"logical_path":"editor.js","mtime":"2021-02-24T23:16:14-08:00","size":744866,"digest":"db10c8351306e92f1926ba225d0cd9c8e886482b3b9820a85825ec3abab5f1cf","integrity":"sha256-2xDINRMG6S8ZJroiXQzZyOiGSCs7mCCoWCXsOrq18c8="},"app-7a0bbff2e8bad3033e7c17e0e0f886f336a9d23d3b912dcd2ae389c48b4b63e6.css":{"logical_path":"app.css","mtime":"2021-02-24T23:16:14-08:00","size":396661,"digest":"7a0bbff2e8bad3033e7c17e0e0f886f336a9d23d3b912dcd2ae389c48b4b63e6","integrity":"sha256-egu/8ui60wM+fBfg4PiG8zap0j07kS3NKuOJxItLY+Y="},"criticmarkup-31ae5d3282bbb8e7b7c3c9917e9fb68e3315a6b4a75da6cec48d21b8846905c4.css":{"logical_path":"criticmarkup.css","mtime":"2021-02-24T23:16:14-08:00","size":646,"digest":"31ae5d3282bbb8e7b7c3c9917e9fb68e3315a6b4a75da6cec48d21b8846905c4","integrity":"sha256-Ma5dMoK7uOe3w8mRfp+2jjMVprSnXabOxI0huIRpBcQ="},"print-512498c368be0d3fb1ba105dfa84289ae48380ec9fcbef948bd4e23b0b095bfb.css":{"logical_path":"print.css","mtime":"2021-02-24T23:16:14-08:00","size":75,"digest":"512498c368be0d3fb1ba105dfa84289ae48380ec9fcbef948bd4e23b0b095bfb","integrity":"sha256-USSYw2i+DT+xuhBd+oQomuSDgOyfy++Ui9TiOwsJW/s="}},"assets":{"app.js":"app-7a4bd115f4bc7ece39bc8073ca0ffad7c5e55cc5837b1464a12dead4905cefb2.js","editor.js":"editor-db10c8351306e92f1926ba225d0cd9c8e886482b3b9820a85825ec3abab5f1cf.js","app.css":"app-7a0bbff2e8bad3033e7c17e0e0f886f336a9d23d3b912dcd2ae389c48b4b63e6.css","criticmarkup.css":"criticmarkup-31ae5d3282bbb8e7b7c3c9917e9fb68e3315a6b4a75da6cec48d21b8846905c4.css","print.css":"print-512498c368be0d3fb1ba105dfa84289ae48380ec9fcbef948bd4e23b0b095bfb.css"}}
@@ -0,0 +1 @@
{"files":{"app-0fd228e26bfbe6fe31a2da268eb0e98e780c1191c1a918adf383377946e9c838.js":{"logical_path":"app.js","mtime":"2021-07-08T06:42:59+09:00","size":136020,"digest":"0fd228e26bfbe6fe31a2da268eb0e98e780c1191c1a918adf383377946e9c838","integrity":"sha256-D9Io4mv75v4xotomjrDpjngMEZHBqRit84M3eUbpyDg="},"editor-db10c8351306e92f1926ba225d0cd9c8e886482b3b9820a85825ec3abab5f1cf.js":{"logical_path":"editor.js","mtime":"2021-07-08T05:19:03+09:00","size":744866,"digest":"db10c8351306e92f1926ba225d0cd9c8e886482b3b9820a85825ec3abab5f1cf","integrity":"sha256-2xDINRMG6S8ZJroiXQzZyOiGSCs7mCCoWCXsOrq18c8="},"app-cb122b4c17500faa5e013cb43334fafcf2dd7d72f694b06d9616f8b33fefb694.css":{"logical_path":"app.css","mtime":"2021-07-08T06:42:59+09:00","size":396625,"digest":"cb122b4c17500faa5e013cb43334fafcf2dd7d72f694b06d9616f8b33fefb694","integrity":"sha256-yxIrTBdQD6peATy0MzT6/PLdfXL2lLBtlhb4sz/vtpQ="},"criticmarkup-31ae5d3282bbb8e7b7c3c9917e9fb68e3315a6b4a75da6cec48d21b8846905c4.css":{"logical_path":"criticmarkup.css","mtime":"2021-07-08T05:19:03+09:00","size":646,"digest":"31ae5d3282bbb8e7b7c3c9917e9fb68e3315a6b4a75da6cec48d21b8846905c4","integrity":"sha256-Ma5dMoK7uOe3w8mRfp+2jjMVprSnXabOxI0huIRpBcQ="},"print-512498c368be0d3fb1ba105dfa84289ae48380ec9fcbef948bd4e23b0b095bfb.css":{"logical_path":"print.css","mtime":"2021-07-08T05:19:03+09:00","size":75,"digest":"512498c368be0d3fb1ba105dfa84289ae48380ec9fcbef948bd4e23b0b095bfb","integrity":"sha256-USSYw2i+DT+xuhBd+oQomuSDgOyfy++Ui9TiOwsJW/s="}},"assets":{"app.js":"app-0fd228e26bfbe6fe31a2da268eb0e98e780c1191c1a918adf383377946e9c838.js","editor.js":"editor-db10c8351306e92f1926ba225d0cd9c8e886482b3b9820a85825ec3abab5f1cf.js","app.css":"app-cb122b4c17500faa5e013cb43334fafcf2dd7d72f694b06d9616f8b33fefb694.css","criticmarkup.css":"criticmarkup-31ae5d3282bbb8e7b7c3c9917e9fb68e3315a6b4a75da6cec48d21b8846905c4.css","print.css":"print-512498c368be0d3fb1ba105dfa84289ae48380ec9fcbef948bd4e23b0b095bfb.css"}}
@@ -380,8 +380,12 @@ $(document).ready(function() {
active_tab = '#edit.tabnav-tab';
}
$('.tabnav-tab.selected').removeAttr('aria-current');
$('.tabnav-tab.selected').removeClass('selected');
$(active_tab).attr('aria-current', 'page');
$(active_tab).addClass('selected');
$('.tabnav-div').hide();
$(active_div).show();
}
@@ -147,7 +147,3 @@
}
}
}
#gollum-dialog-dialog-buttons {
overflow: hidden;
}
@@ -29,6 +29,7 @@ a.tabnav-tab:focus {
overflow: hidden;
font-family: Consolas, "Liberation Mono", Courier, monospace;
font-size: 1em;
padding: 0;
}
#gollum-editor {
+9 -7
View File
@@ -4,13 +4,15 @@
<h1 class="py-4">Create New Page</h1>
</div>
<div id="wiki-content" class="create edit">
<div class="tabnav">
<nav class="tabnav-tabs" aria-label="Foo bar">
<a href="#" id="edit" class="tabnav-tab selected" aria-current="edit">Edit</a>
<a href="#" id="preview" class="tabnav-tab" aria-current="preview">Preview</a>
</nav>
</div>
<div class="tabnav">
<nav class="tabnav-tabs" aria-label="Toggle edit or preview mode">
<a href="#" id="edit" class="tabnav-tab selected" aria-current="page">
Edit
</a>
<a href="#" id="preview" class="tabnav-tab">Preview</a>
</nav>
</div>
<div class="has-sidebar tabnav-div" id="edit-content">
{{>editor}}
</div>
+4 -2
View File
@@ -5,8 +5,10 @@
</div>
<div class="tabnav">
<nav class="tabnav-tabs">
<a href="#" id="edit" class="tabnav-tab selected" aria-current="edit">Edit</a>
<a href="#" id="preview" class="tabnav-tab" aria-current="preview">Preview</a>
<a href="#" id="edit" class="tabnav-tab selected" aria-current="page">
Edit
</a>
<a href="#" id="preview" class="tabnav-tab">Preview</a>
</nav>
</div>
<div class="tabnav-div" id="edit-content">{{>editor}}</div>
+1 -1
View File
@@ -37,7 +37,7 @@
<button class="btn btn-sm function-button" id="function-h3" title="Heading 3">h3</button>
<span class="pr-2"></span>
<button class="btn btn-sm function-button" id="function-link" title="Link">{{#octicon}}link{{/octicon}}</button>
<button class="btn btn-sm function-button" id="function-image" title="Image">{{#octicon}}file-media{{/octicon}}</button>
<button class="btn btn-sm function-button" id="function-image" title="Image">{{#octicon}}image{{/octicon}}</button>
<span class="pr-2"></span>
{{#critic_markup}}
<button class="btn btn-sm function-button" id="function-critic-accept" title="Accept Selected CriticMarkup">{{#octicon}}plus{{/octicon}}</button>
+87 -89
View File
@@ -1,105 +1,103 @@
<nav class="actions pt-4 px-2 px-lg-0 overflow-x-scroll">
<div class="TableObject">
<div class="TableObject-item hide-lg hide-xl">
{{>mobilenav}}
</div>
<nav class="TableObject actions pt-4 px-2 px-lg-0 overflow-x-scroll">
<div class="TableObject-item hide-lg hide-xl">
{{>mobilenav}}
</div>
<div class="TableObject-item hide-sm hide-md">
<a class="btn btn-sm" id="minibutton-home" href="{{page_route}}">
Home
</a>
</div>
<div class="TableObject-item hide-sm hide-md">
<a class="btn btn-sm" id="minibutton-home" href="{{page_route}}">
Home
</a>
</div>
<div
class="TableObject-item TableObject-item--primary px-2"
{{^search}}style="visibility:hidden"{{/search}}
>
{{>searchbar}}
</div>
<div
class="TableObject-item TableObject-item--primary px-2"
{{^search}}style="visibility:hidden"{{/search}}
>
{{>searchbar}}
</div>
<div class="TableObject-item hide-sm hide-md">
<div class="BtnGroup" style="display: flex;">
{{#overview}}
<a
class="btn BtnGroup-item btn-sm"
href="{{overview_path}}"
id="minibutton-overview"
>
Overview
</a>
{{/overview}}
{{#latest_changes}}
<a
class="btn BtnGroup-item btn-sm"
href="{{latest_changes_path}}"
id="minibutton-latest-changes"
>
Latest Changes
</a>
{{/latest_changes}}
</div>
</div>
{{#history}}
<div class="TableObject-item pl-2 hide-sm hide-md">
<div class="TableObject-item hide-sm hide-md">
<div class="BtnGroup d-flex">
{{#overview}}
<a
class="btn btn-sm"
class="btn BtnGroup-item btn-sm"
href="{{overview_path}}"
id="minibutton-overview"
>
Overview
</a>
{{/overview}}
{{#latest_changes}}
<a
class="btn BtnGroup-item btn-sm"
href="{{latest_changes_path}}"
id="minibutton-latest-changes"
>
Latest Changes
</a>
{{/latest_changes}}
</div>
</div>
<div class="TableObject-item px-2">
<div class="BtnGroup d-flex">
{{#history}}
<a
class="btn BtnGroup-item btn-sm hide-sm hide-md"
href="{{history_path}}/{{escaped_url_path}}"
id="minibutton-history"
>
Page History
History
</a>
{{/history}}
{{#allow_editing}}
{{#allow_uploads}}
<button
class="btn BtnGroup-item btn-sm hide-sm hide-md
minibutton-upload-page"
>
Upload
</button>
{{/allow_uploads}}
{{#editable}}
<button
class="btn BtnGroup-item btn-sm hide-sm hide-md
minibutton-rename-page"
>
Rename
</button>
<a
class="btn BtnGroup-item btn-sm hide-sm hide-md"
href="{{edit_path}}/{{escaped_url_path}}"
id="minibutton-edit-page"
>
Edit
</a>
{{/editable}}
{{/allow_editing}}
</div>
</div>
{{#allow_editing}}
{{#editable}}
<div class="TableObject-item">
<a class="btn btn-primary btn-sm minibutton-new-page" href="#">
New
</a>
</div>
{{/history}}
{{/editable}}
{{#allow_editing}}
<div class="TableObject-item px-2">
<div class="BtnGroup" style="display: flex;">
{{#allow_uploads}}
<a
class="btn BtnGroup-item btn-sm hide-sm hide-md
minibutton-upload-page"
>
Upload
</a>
{{/allow_uploads}}
{{#editable}}
<a
class="btn BtnGroup-item btn-sm hide-sm hide-md
minibutton-rename-page"
>
Rename
</a>
<a
class="btn BtnGroup-item btn-sm hide-sm hide-md"
href="{{edit_path}}/{{escaped_url_path}}"
id="minibutton-edit-page"
>
Edit
</a>
{{/editable}}
</div>
</div>
{{#editable}}
{{^editable}}
{{#newable}}
<div class="TableObject-item">
<a class="btn btn-primary btn-sm minibutton-new-page" href="#">
New
</a>
</div>
{{/editable}}
{{^editable}}
{{#newable}}
<div class="TableObject-item">
<a class="btn btn-primary btn-sm minibutton-new-page" href="#">
New
</a>
</div>
{{/newable}}
{{/editable}}
{{/allow_editing}}
</div>
{{/newable}}
{{/editable}}
{{/allow_editing}}
</nav>
@@ -0,0 +1,82 @@
module Precious
module Views
module LocaleHelpers
NO_METHOD_MESSAGE = 'Argument must be a view method'
YAML_VARIABLE_REGEXP = /\%\{[\w]+\}/
# Returns all I18n translation strings for the current view class.
# This method support YAML arguments. For example:
#
# last_edited: This content was last edited at %{date}.
#
# Where the `date` argument must be a method available on the current
# class.
#
# Use this interface within Mustache templates to render any user
# interface strings in the current locale. For example:
#
# {{ t.last_edited }}
#
def t
autofill I18n.t(locale_klass_name)
end
private
# Recursively looks up I18n translation values and autofills any YAML
# arguments with the return value of the current class's matching method.
#
# When a translation value with an argument has no matching method, we
# then return that value transformed to include the `no_method_message`
#
def autofill(yaml)
yaml.map { |i18n_key, i18n_value|
if i18n_value.is_a? Hash
[i18n_key, autofill(i18n_value)]
elsif has_arguments?(i18n_value)
fill_argument_content(i18n_key, i18n_value)
else
[i18n_key, i18n_value]
end
}.to_h
end
def fill_argument_content(i18n_key, i18n_value)
i18n_value.gsub!(YAML_VARIABLE_REGEXP) do |argument|
method_name = argument.gsub(/[^\w]/, '')
next if method_name.nil?
begin
self.public_send(method_name)
rescue NoMethodError => error
no_method_message(method_name)
end
end
[i18n_key, i18n_value]
end
def has_arguments?(i18n_value)
i18n_value.match?(YAML_VARIABLE_REGEXP)
end
# Returns the current class name in a format that is acceptable in YAML.
# To summarize its function:
#
# NameOfConstant => name_of_constant
#
def locale_klass_name
@locale_klass_name ||= self.class.name.gsub(/::/, '/').
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
gsub(/([a-z\d])([A-Z])/,'\1_\2').
tr('-', '_').
downcase
end
def no_method_message(method_name, message = NO_METHOD_MESSAGE)
"[#{message}: #{method_name}]"
end
end
end
end
+3 -2
View File
@@ -6,10 +6,11 @@ module Precious
include Rack::Utils
include Sprockets::Helpers
include Precious::Views::AppHelpers
include Precious::Views::LocaleHelpers
include Precious::Views::SprocketsHelpers
include Precious::Views::RouteHelpers
include Precious::Views::OcticonHelpers
alias_method :h, :escape_html
attr_reader :name, :path
@@ -47,7 +48,7 @@ module Precious
end
def mathjax_js
page_route("gollum/assets/mathjax/MathJax.js?config=TeX-AMS-MML_HTMLorMML")
"#{page_route('gollum/assets/mathjax/MathJax.js')}?config=TeX-AMS-MML_HTMLorMML"
end
def css # custom css
+5 -5
View File
@@ -16,6 +16,11 @@ module Precious
DEFAULT_AUTHOR = 'you'
@@to_xml = { :save_with => Nokogiri::XML::Node::SaveOptions::DEFAULT_XHTML ^ 1, :indent => 0, :encoding => 'UTF-8' }
def title
h1 = @h1_title ? page_header_from_content(@content) : false
h1 || @page.url_path_title # url_path_title is the metadata title if present, otherwise the filename-based title
end
def page_header
title
end
@@ -263,11 +268,6 @@ module Precious
end
result << "</tr>\n</table>\n"
end
def title
h1 = @h1_title ? page_header_from_content(@content) : false
h1 || @page.url_path_title # url_path_title is the metadata title if present, otherwise the filename-based title
end
end
end
end
+134
View File
@@ -0,0 +1,134 @@
require_relative "../../helper"
require_relative "../../../lib/gollum/views/helpers"
describe Precious::Views::LocaleHelpers do
class TestClass < Mustache
include Precious::Views::LocaleHelpers
def author
"J.R.R."
end
def location
"Bloemfontein"
end
end
def setup
::I18n.available_locales = [:en, :de]
::I18n.load_path = Dir[File.expand_path("test/support/locales" + "/*.yml")]
end
def teardown
I18n.locale = :en
end
let(:dummy_instance) { TestClass.new }
describe "#t" do
describe "mustache usage" do
let(:subject) { dummy_instance.render(mustache_template) }
let(:mustache_template) { "{{ t.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) { "{{ t.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) { "{{ t.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 "out of scope translations" do
let(:mustache_template) { "{{ t.never_called }}" }
it "does not include translation keys from other classes" do
_(subject).must_be_empty
end
end
describe "missing translations" do
let(:mustache_template) { "{{ t.nested.nonexistent_key }}" }
it "outputs an empty string" do
_(subject).must_be_empty
end
end
end
describe "usage" do
let(:subject) { dummy_instance.t }
it "returns a hash" do
_(subject).must_be_kind_of Hash
end
it "returns translation keys under 'test_class'" do
i18n_keys = I18n.t("test_class").keys
_(subject.keys).must_equal i18n_keys
end
it "does not return translation keys under other classes" do
other_i18n_keys = I18n.t("nonexistant_test_class").keys
_(subject.keys).wont_include other_i18n_keys
end
it "returns nested keys" do
nested_keys = subject[:author_info].keys
_(nested_keys).must_equal [:full]
end
describe "auto-filled YAML arguments" do
let(:subject) { dummy_instance.t[: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
+2 -1
View File
@@ -5,6 +5,7 @@ require 'shoulda'
require 'mocha/setup'
require 'fileutils'
require 'minitest/reporters'
require 'minitest/spec'
require 'twitter_cldr'
require 'tmpdir'
@@ -93,4 +94,4 @@ def context(*args, &block)
klass.class_eval &block
end
$contexts = []
$contexts = []
+8
View File
@@ -0,0 +1,8 @@
de:
test_class:
author_info:
full: Autor %{author} ist vom %{location}
has_invalid_argument: Willkommen in %{no_matching_method}
hello_world: Hallo Welt
nonexistant_test_class:
never_called: Nie angerufen
+8
View File
@@ -0,0 +1,8 @@
en:
test_class:
author_info:
full: Author %{author} is from %{location}
has_invalid_argument: Welcome to %{no_matching_method}
hello_world: Hello world
nonexistant_test_class:
never_called: Never called
+10 -1
View File
@@ -47,6 +47,15 @@ context "Frontend" do
get '/gollum/assets/mathjax/MathJax.js'
assert last_response.ok?
end
test 'compare with utf8' do
commit = { :name => 'user1', :email => 'user1' }
@wiki.write_page('Utf8', :markdown, '\n中文', commit)
page = @wiki.page('Utf8')
@wiki.update_page(page, nil, nil, "No utf-8", commit)
get "/gollum/compare/Utf8.md/#{page.versions.first.id}..#{page.versions.last.id}"
assert last_response.body.include?('<div class="gi pl-2">+\n中文</div>')
end
test "UTF-8 headers href preserved" do
page = 'utfh1'
@@ -953,7 +962,7 @@ context 'Frontend with base path' do
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')
assert last_response.body.include?('<script defer src="/wiki/gollum/assets/mathjax/MathJax.js?config=')
end
test 'compare view' do
+1 -1
View File
@@ -44,7 +44,7 @@ def load_script(**args)
end
end
unless ENV['TRAVIS']
unless ENV['CI']
context '4.x -> 5.x tag migrator' do
include Rack::Test::Methods
+25 -1
View File
@@ -38,7 +38,31 @@ context "Precious::Views::Page" do
assert_include @view.breadcrumb, "数学 📘"
end
test "page header retains unicde and ASCII characters" do
test 'page <title> is the page header from content, if present' do
page_title = 'Page header from content'
@wiki.write_page(page_title, :markdown, 'Contents', commit_details)
@view = Precious::Views::Page.new.tap do |view|
view.instance_variable_set :@page, @wiki.page(page_title)
view.instance_variable_set :@h1_title, true
end
assert_equal @view.title, 'Page header from content'
end
test 'page <title> is URL path title if no h1 present' do
@wiki.write_page('dir/My path title', :markdown, 'Contents', commit_details)
page = @wiki.page('dir/My path title')
@view = Precious::Views::Page.new.tap do |view|
view.instance_variable_set :@page, page
view.instance_variable_set :@h1_title, false
end
assert_equal @view.title, 'My path title'
end
test "page header retains unicode and ASCII characters" do
title = "数学 📘"
@wiki.write_page(title, :markdown, "How old is Bilbo?")
page = @wiki.page(title)