Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fda5bcf3f6 | |||
| 01005fdccf | |||
| 95d35d38da | |||
| 81c90e55a7 | |||
| 3f0b61081b | |||
| ecc317886a | |||
| 4b2dc8e5c0 | |||
| 6f870501a0 | |||
| f30058f4ee | |||
| 82ce013cab | |||
| 0c36cdf5ba | |||
| 6159fcd4a2 | |||
| 8f7793f461 | |||
| 589b4bce39 | |||
| 9c574fd760 | |||
| 46c22a8b87 | |||
| 7e379cfab1 | |||
| 93d3d10453 | |||
| 98a0006c86 | |||
| d97721f38b | |||
| 8d3ec8605e | |||
| 7517389072 | |||
| b7011139cf | |||
| 6e8a68dd0d | |||
| 4e8309d3e4 | |||
| 371ab21d16 | |||
| cbcbc4bc3f | |||
| dc9b2e1766 | |||
| 334df62651 |
@@ -0,0 +1,49 @@
|
|||||||
|
name: Deploy docker
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
release:
|
||||||
|
types: [published]
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Set deploy name to master
|
||||||
|
if: github.ref == 'refs/heads/master'
|
||||||
|
run: |
|
||||||
|
echo "DEPLOY_NAME=gollumwiki/gollum:master" >> $GITHUB_ENV
|
||||||
|
- name: Set deploy name to release version
|
||||||
|
if: startsWith(github.ref, 'refs/tags/')
|
||||||
|
run: |
|
||||||
|
echo "DEPLOY_NAME=gollumwiki/gollum:${{ github.ref_name }}" >> $GITHUB_ENV
|
||||||
|
- name: Check Out Repo
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: Login
|
||||||
|
uses: docker/login-action@v1
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
id: buildx
|
||||||
|
uses: docker/setup-buildx-action@v1
|
||||||
|
- name: Cache docker layers
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: /tmp/.buildx-cache
|
||||||
|
key: ${{ runner.os }}-buildx-${{ github.sha }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-buildx-
|
||||||
|
- name: Build and push
|
||||||
|
id: docker_build
|
||||||
|
uses: docker/build-push-action@v2
|
||||||
|
with:
|
||||||
|
context: ./
|
||||||
|
file: ./Dockerfile
|
||||||
|
builder: ${{ steps.buildx.outputs.name }}
|
||||||
|
push: true
|
||||||
|
tags: ${{ env.DEPLOY_NAME }}
|
||||||
|
cache-from: type=local,src=/tmp/.buildx-cache
|
||||||
|
cache-to: type=local,dest=/tmp/.buildx-cache
|
||||||
|
- name: Image digest
|
||||||
|
run: echo ${{ steps.docker_build.outputs.digest }}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
name: Build and Test Docker
|
||||||
|
on: [push, pull_request]
|
||||||
|
env:
|
||||||
|
CI_IMAGE: gollum-ci-img
|
||||||
|
jobs:
|
||||||
|
build-and-test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Check Out Repo
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
id: buildx
|
||||||
|
uses: docker/setup-buildx-action@v1
|
||||||
|
- name: Cache docker layers
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: /tmp/.buildx-cache
|
||||||
|
key: ${{ runner.os }}-buildx-${{ github.sha }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-buildx-
|
||||||
|
- name: Build
|
||||||
|
id: docker_build
|
||||||
|
uses: docker/build-push-action@v2
|
||||||
|
with:
|
||||||
|
context: ./
|
||||||
|
file: ./Dockerfile
|
||||||
|
builder: ${{ steps.buildx.outputs.name }}
|
||||||
|
push: false
|
||||||
|
tags: ${{ env.CI_IMAGE }}
|
||||||
|
outputs: type=docker
|
||||||
|
cache-from: type=local,src=/tmp/.buildx-cache
|
||||||
|
cache-to: type=local,dest=/tmp/.buildx-cache
|
||||||
|
- name: Image digest
|
||||||
|
run: echo ${{ steps.docker_build.outputs.digest }}
|
||||||
|
- name: docker state
|
||||||
|
run: docker image ls
|
||||||
|
- name: Run gollum as test
|
||||||
|
run: docker run -e CI=true ${{ env.CI_IMAGE }} --irb
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
on:
|
||||||
|
push:
|
||||||
|
# Sequence of patterns matched against refs/tags
|
||||||
|
tags:
|
||||||
|
- 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
|
||||||
|
|
||||||
|
name: Create Release
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Create Release
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: Create Release
|
||||||
|
id: create_release
|
||||||
|
uses: actions/create-release@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
|
||||||
|
with:
|
||||||
|
tag_name: ${{ github.ref }}
|
||||||
|
release_name: Release ${{ github.ref }}
|
||||||
|
draft: false
|
||||||
|
prerelease: false
|
||||||
+28
-11
@@ -1,29 +1,46 @@
|
|||||||
name: Ruby Build
|
name: Ruby Build
|
||||||
on: [push, pull_request]
|
on: [push, pull_request]
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
jruby_build:
|
||||||
|
name: JRuby (${{ matrix.ruby }})
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
ruby: [2.4.0, 2.6.0, 3.0.0, jruby-9.2.18.0]
|
ruby: [jruby-9.3.2.0]
|
||||||
steps:
|
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
|
- name: Check out repository code
|
||||||
uses: actions/checkout@v2
|
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
|
- name: List files in the repository
|
||||||
run: |
|
run: |
|
||||||
ls ${{ github.workspace }}
|
ls ${{ github.workspace }}
|
||||||
- uses: actions/setup-java@v2
|
- name: Set up Java
|
||||||
|
uses: actions/setup-java@v2
|
||||||
with:
|
with:
|
||||||
distribution: 'adopt'
|
distribution: 'adopt'
|
||||||
java-version: '9'
|
java-version: '11'
|
||||||
- uses: ruby/setup-ruby@v1
|
- name: Set up Ruby
|
||||||
|
uses: ruby/setup-ruby@v1
|
||||||
with:
|
with:
|
||||||
ruby-version: ${{ matrix.ruby }}
|
ruby-version: ${{ matrix.ruby }}
|
||||||
bundler-cache: true
|
bundler-cache: true
|
||||||
- name: exec rake
|
- name: Run tests
|
||||||
|
run: bundle exec rake
|
||||||
|
mri_build:
|
||||||
|
name: Ruby (${{ matrix.ruby }})
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
ruby: ['2.6', '2.7', '3.0', '3.1']
|
||||||
|
steps:
|
||||||
|
- name: Check out repository code
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: List files in the repository
|
||||||
|
run: |
|
||||||
|
ls ${{ github.workspace }}
|
||||||
|
- name: Set up Ruby
|
||||||
|
uses: ruby/setup-ruby@v1
|
||||||
|
with:
|
||||||
|
ruby-version: ${{ matrix.ruby }}
|
||||||
|
bundler-cache: true
|
||||||
|
- name: Run tests
|
||||||
run: bundle exec rake
|
run: bundle exec rake
|
||||||
|
|||||||
-10
@@ -1,10 +0,0 @@
|
|||||||
rvm:
|
|
||||||
- 2.4.0
|
|
||||||
- 2.6.0
|
|
||||||
- 3.0.0
|
|
||||||
- jruby-9.2.18.0
|
|
||||||
jdk:
|
|
||||||
- oraclejdk9
|
|
||||||
before_install:
|
|
||||||
- sudo apt-get update
|
|
||||||
- sudo apt-get install libicu-dev
|
|
||||||
+40
@@ -0,0 +1,40 @@
|
|||||||
|
FROM ruby:2.7-alpine AS builder
|
||||||
|
|
||||||
|
RUN apk add \
|
||||||
|
build-base \
|
||||||
|
cmake \
|
||||||
|
git \
|
||||||
|
icu-dev \
|
||||||
|
openssl-dev
|
||||||
|
|
||||||
|
COPY Gemfile* /tmp/
|
||||||
|
COPY gollum.gemspec* /tmp/
|
||||||
|
WORKDIR /tmp
|
||||||
|
RUN bundle install
|
||||||
|
|
||||||
|
RUN gem install \
|
||||||
|
asciidoctor \
|
||||||
|
creole \
|
||||||
|
wikicloth \
|
||||||
|
org-ruby \
|
||||||
|
RedCloth \
|
||||||
|
bibtex-ruby \
|
||||||
|
&& echo "gem-extra complete"
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
COPY . /app
|
||||||
|
RUN bundle exec rake install
|
||||||
|
|
||||||
|
|
||||||
|
FROM ruby:2.7-alpine
|
||||||
|
|
||||||
|
COPY --from=builder /usr/local/bundle/ /usr/local/bundle/
|
||||||
|
|
||||||
|
RUN apk add \
|
||||||
|
bash \
|
||||||
|
git
|
||||||
|
|
||||||
|
VOLUME /wiki
|
||||||
|
WORKDIR /wiki
|
||||||
|
COPY docker-run.sh /docker-run.sh
|
||||||
|
ENTRYPOINT ["/docker-run.sh"]
|
||||||
@@ -1,9 +1,23 @@
|
|||||||
source 'https://rubygems.org'
|
source 'https://rubygems.org'
|
||||||
|
|
||||||
if RUBY_PLATFORM == 'java'
|
gem 'warbler', platforms: :jruby
|
||||||
gem 'warbler'
|
|
||||||
end
|
# FIXME:
|
||||||
|
#
|
||||||
|
# There's an issue in 1.12.5 that causes XHTML elements to be generated badly,
|
||||||
|
# causing Gollum's test suite to fail.[1] The issue has been fixed upstream,
|
||||||
|
# but we're still waiting for a new Nokogiri point release.
|
||||||
|
#
|
||||||
|
# However, 1.12.5 is a security patch, so we don't want end users to use an
|
||||||
|
# older version of Nokogiri. But this is safe to do in our CI environment.
|
||||||
|
#
|
||||||
|
# Once there's a new Nokogiri release, we can remove this dependency and JRuby
|
||||||
|
# CI should pass normally again.
|
||||||
|
#
|
||||||
|
# Note that Nokogiri 1.11+ does not support Ruby v2.4.x anymore. So to make our
|
||||||
|
# current CI workflows pass, we should only try to install this version of
|
||||||
|
# Nokogiri for newer Ruby versions.
|
||||||
|
|
||||||
gemspec
|
gemspec
|
||||||
|
|
||||||
gem 'rake', '~> 13.0'
|
gem 'rake', '~> 13.0'
|
||||||
|
|||||||
@@ -37,11 +37,11 @@ Gollum runs on Unix-like systems using its [adapter](https://github.com/gollum/r
|
|||||||
## INSTALLATION
|
## INSTALLATION
|
||||||
|
|
||||||
1. Ruby is best installed either via [RVM](https://rvm.io/) or a package manager of choice.
|
1. Ruby is best installed either via [RVM](https://rvm.io/) or a package manager of choice.
|
||||||
2. Gollum is best installed via RubyGems:
|
2. Gollum is best installed via RubyGems:
|
||||||
```
|
```
|
||||||
[sudo] gem install gollum
|
[sudo] gem install gollum
|
||||||
```
|
```
|
||||||
|
|
||||||
Installation examples for individual systems can be seen [here](https://github.com/gollum/gollum/wiki/Installation).
|
Installation examples for individual systems can be seen [here](https://github.com/gollum/gollum/wiki/Installation).
|
||||||
|
|
||||||
To run, simply:
|
To run, simply:
|
||||||
@@ -84,19 +84,19 @@ See [here](https://github.com/gollum/gollum/wiki/Custom-rendering-gems) for inst
|
|||||||
|
|
||||||
### Rack
|
### Rack
|
||||||
|
|
||||||
Gollum can also be ran with any [rack-compatible web server](https://github.com/rack/rack#supported-web-servers). More on that [over here](https://github.com/gollum/gollum/wiki/Gollum-via-Rack).
|
Gollum can also be run with any [rack-compatible web server](https://github.com/rack/rack#supported-web-servers). More on that [over here](https://github.com/gollum/gollum/wiki/Gollum-via-Rack).
|
||||||
|
|
||||||
### Rack, with an authentication server
|
### Rack, with an authentication server
|
||||||
|
|
||||||
Gollum can also be ran alongside a CAS (Central Authentication Service) SSO (single sign-on) server. With a bit of tweaking, this adds basic user-support to Gollum. To see an example and an explanation, navigate [over here](https://github.com/gollum/gollum/wiki/Gollum-via-Rack-and-CAS-SSO).
|
Gollum can also be run alongside a CAS (Central Authentication Service) SSO (single sign-on) server. With a bit of tweaking, this adds basic user-support to Gollum. To see an example and an explanation, navigate [over here](https://github.com/gollum/gollum/wiki/Gollum-via-Rack-and-CAS-SSO).
|
||||||
|
|
||||||
### Docker
|
### Docker
|
||||||
|
|
||||||
Gollum can also be ran via [Docker](https://www.docker.com/). More on that [over here](https://github.com/gollum/gollum/wiki/Gollum-via-Docker).
|
Gollum can also be run via [Docker](https://www.docker.com/). More on that [over here](https://github.com/gollum/gollum/wiki/Gollum-via-Docker).
|
||||||
|
|
||||||
### Service
|
### Service
|
||||||
|
|
||||||
Gollum can also be ran as a service. More on that [over here](https://github.com/gollum/gollum/wiki/Gollum-as-a-service).
|
Gollum can also be run as a service. More on that [over here](https://github.com/gollum/gollum/wiki/Gollum-as-a-service).
|
||||||
|
|
||||||
## CONFIGURATION
|
## CONFIGURATION
|
||||||
|
|
||||||
@@ -117,6 +117,7 @@ Gollum comes with the following command line options:
|
|||||||
| --css | none | Tell Gollum to inject custom CSS into each page. Uses `custom.css` from wiki root.<sup>3</sup> |
|
| --css | none | Tell Gollum to inject custom CSS into each page. Uses `custom.css` from wiki root.<sup>3</sup> |
|
||||||
| --js | none | Tell Gollum to inject custom JS into each page. Uses `custom.js` from wiki root.<sup>3</sup> |
|
| --js | none | Tell Gollum to inject custom JS into each page. Uses `custom.js` from wiki root.<sup>3</sup> |
|
||||||
| --no-edit | none | Disable the feature of editing pages. |
|
| --no-edit | none | Disable the feature of editing pages. |
|
||||||
|
| --local-time | none | Use the browser's local timezone instead of the server's for displaying dates. Default: false.
|
||||||
| --follow-renames, --no-follow-renames | none | Follow pages across renames in the History view. Default: true.
|
| --follow-renames, --no-follow-renames | none | Follow pages across renames in the History view. Default: true.
|
||||||
| --allow-uploads | [MODE] | Enable file uploads. If set to `dir`, Gollum will store all uploads in the `/uploads/` directory in repository root. If set to `page`, Gollum will store each upload at the currently edited page.<sup>4</sup> |
|
| --allow-uploads | [MODE] | Enable file uploads. If set to `dir`, Gollum will store all uploads in the `/uploads/` directory in repository root. If set to `page`, Gollum will store each upload at the currently edited page.<sup>4</sup> |
|
||||||
| --mathjax | none | Enables MathJax (renders mathematical equations). By default, uses the `TeX-AMS-MML_HTMLorMML` config with the `autoload-all` extension.<sup>5</sup> |
|
| --mathjax | none | Enables MathJax (renders mathematical equations). By default, uses the `TeX-AMS-MML_HTMLorMML` config with the `autoload-all` extension.<sup>5</sup> |
|
||||||
@@ -126,7 +127,7 @@ Gollum comes with the following command line options:
|
|||||||
| --no-display-metadata | none | Do not render metadata tables in pages. |
|
| --no-display-metadata | none | Do not render metadata tables in pages. |
|
||||||
| --user-icons | [MODE] | Tell Gollum to use specific user icons for history view. Can be set to `gravatar`, `identicon` or `none`. Default: `none`. |
|
| --user-icons | [MODE] | Tell Gollum to use specific user icons for history view. Can be set to `gravatar`, `identicon` or `none`. Default: `none`. |
|
||||||
| --mathjax-config | [FILE] | Specify path to a custom MathJax configuration. If not specified, uses the `mathjax.config.js` file from repository root. |
|
| --mathjax-config | [FILE] | Specify path to a custom MathJax configuration. If not specified, uses the `mathjax.config.js` file from repository root. |
|
||||||
| --template-dir | [PATH] | Specify custom mustache template directory. |
|
| --template-dir | [PATH] | Specify custom mustache template directory. Only overrides templates that exist in this directory. |
|
||||||
| --template-page | none | Use _Template in root as a template for new pages. Must be committed. |
|
| --template-page | none | Use _Template in root as a template for new pages. Must be committed. |
|
||||||
| --emoji | none | Parse and interpret emoji tags (e.g. `:heart:`) except when the leading colon is backslashed (e.g. `\:heart:`). |
|
| --emoji | none | Parse and interpret emoji tags (e.g. `:heart:`) except when the leading colon is backslashed (e.g. `\:heart:`). |
|
||||||
| --lenient-tag-lookup | none | Internal links resolve case-insensitively, will treat spaces as hyphens, and will match the first page found with a certain filename, anywhere in the repository. Provides compatibility with Gollum 4.x. |
|
| --lenient-tag-lookup | none | Internal links resolve case-insensitively, will treat spaces as hyphens, and will match the first page found with a certain filename, anywhere in the repository. Provides compatibility with Gollum 4.x. |
|
||||||
@@ -150,3 +151,7 @@ When `--config` option is used, certain inner parts of Gollum can be customized.
|
|||||||
## CONTRIBUTING
|
## CONTRIBUTING
|
||||||
|
|
||||||
Please consider helping out! See [CONTRIBUTING](CONTRIBUTING.md) for information on how to submit issues, and how to start hacking on gollum.
|
Please consider helping out! See [CONTRIBUTING](CONTRIBUTING.md) for information on how to submit issues, and how to start hacking on gollum.
|
||||||
|
|
||||||
|
## THANKS TO
|
||||||
|
|
||||||
|
[](https://saucelabs.com)
|
||||||
|
|||||||
@@ -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`.
|
||||||
|
|||||||
+6
-4
@@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env ruby
|
#!/usr/bin/env -S ruby -Eutf-8
|
||||||
|
|
||||||
$:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
|
$:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
|
||||||
|
|
||||||
@@ -112,6 +112,9 @@ MSG
|
|||||||
opts.on('--no-edit', 'Disable the feature of editing pages.') do
|
opts.on('--no-edit', 'Disable the feature of editing pages.') do
|
||||||
wiki_options[:allow_editing] = false
|
wiki_options[:allow_editing] = false
|
||||||
end
|
end
|
||||||
|
opts.on('--local-time', "Use the browser's local timezone instead of the server's for displaying dates.") do
|
||||||
|
wiki_options[:show_local_time] = true
|
||||||
|
end
|
||||||
opts.on('--follow-renames', 'Follow pages across renames in the History view. Default: true.') do
|
opts.on('--follow-renames', 'Follow pages across renames in the History view. Default: true.') do
|
||||||
wiki_options[:follow_renames] = true
|
wiki_options[:follow_renames] = true
|
||||||
end
|
end
|
||||||
@@ -149,7 +152,7 @@ MSG
|
|||||||
'Can be set to \'gravatar\' or \'identicon\'. Default: standard avatar.') do |mode|
|
'Can be set to \'gravatar\' or \'identicon\'. Default: standard avatar.') do |mode|
|
||||||
wiki_options[:user_icons] = mode.to_s
|
wiki_options[:user_icons] = mode.to_s
|
||||||
end
|
end
|
||||||
opts.on('--template-dir [PATH]', 'Specify custom mustache template directory.') do |path|
|
opts.on('--template-dir [PATH]', 'Specify custom mustache template directory. Only overrides templates that exist in this directory.') do |path|
|
||||||
wiki_options[:template_dir] = path
|
wiki_options[:template_dir] = path
|
||||||
end
|
end
|
||||||
opts.on('--template-page', 'Use _Template.{ext} as a template for new pages.') do
|
opts.on('--template-page', 'Use _Template.{ext} as a template for new pages.') do
|
||||||
@@ -206,7 +209,7 @@ begin
|
|||||||
rescue OptionParser::InvalidOption => e
|
rescue OptionParser::InvalidOption => e
|
||||||
puts "gollum: #{e.message}"
|
puts "gollum: #{e.message}"
|
||||||
puts 'gollum: try \'gollum --help\' for more information'
|
puts 'gollum: try \'gollum --help\' for more information'
|
||||||
exit
|
exit 1
|
||||||
end
|
end
|
||||||
|
|
||||||
# --gollum-path wins over ARGV[0]
|
# --gollum-path wins over ARGV[0]
|
||||||
@@ -271,7 +274,6 @@ else
|
|||||||
Precious::App.set(:environment, ENV.fetch('RACK_ENV', :production).to_sym)
|
Precious::App.set(:environment, ENV.fetch('RACK_ENV', :production).to_sym)
|
||||||
Precious::App.set(:gollum_path, gollum_path)
|
Precious::App.set(:gollum_path, gollum_path)
|
||||||
Precious::App.set(:wiki_options, wiki_options)
|
Precious::App.set(:wiki_options, wiki_options)
|
||||||
Precious::App.settings.mustache[:templates] = wiki_options[:template_dir] if wiki_options[:template_dir]
|
|
||||||
|
|
||||||
if cfg = options[:config]
|
if cfg = options[:config]
|
||||||
# If the path begins with a '/' it will be considered an absolute path,
|
# If the path begins with a '/' it will be considered an absolute path,
|
||||||
|
|||||||
+40
-28
@@ -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|
|
||||||
@@ -25,7 +28,7 @@ It finds and repairs Gollum link tags that no longer work under 5.x for three re
|
|||||||
* 5.x wiki internal links are no longer 'global'.
|
* 5.x wiki internal links are no longer 'global'.
|
||||||
|
|
||||||
* NB: you can use the --lenient-tag-lookup option in gollum >= 5.x to enable 4.x-backwards compatible tags.
|
* NB: you can use the --lenient-tag-lookup option in gollum >= 5.x to enable 4.x-backwards compatible tags.
|
||||||
|
|
||||||
See https://github.com/gollum/gollum/wiki/5.0-release-notes#filename-handling for more information.
|
See https://github.com/gollum/gollum/wiki/5.0-release-notes#filename-handling for more information.
|
||||||
Usage of this script comes without any warranty.
|
Usage of this script comes without any warranty.
|
||||||
|
|
||||||
@@ -38,7 +41,7 @@ You can use the --page-file-dir and --config options as you would normally with
|
|||||||
Requires a non-bare repository. Recommended usage:
|
Requires a non-bare repository. Recommended usage:
|
||||||
|
|
||||||
1. Clone your wiki's repository to create a backup.
|
1. Clone your wiki's repository to create a backup.
|
||||||
2. Run this script on your cloned repo.
|
2. Run this script on your cloned repo.
|
||||||
3. If all looks sane, run the script with the --write option. This will overwrite files in your working directory, but not commit the changes, so you have time to review them.
|
3. If all looks sane, run the script with the --write option. This will overwrite files in your working directory, but not commit the changes, so you have time to review them.
|
||||||
4. Do a 'git diff' to inspect the changes.
|
4. Do a 'git diff' to inspect the changes.
|
||||||
5. Commit the changes if all looks sane, and push/pull them back into your original repo.
|
5. Commit the changes if all looks sane, and push/pull them back into your original repo.
|
||||||
@@ -52,23 +55,23 @@ EOF
|
|||||||
opts.on('--page-file-dir [PATH]', 'Specify the subdirectory for all pages. Default: repository root.') do |path|
|
opts.on('--page-file-dir [PATH]', 'Specify the subdirectory for all pages. Default: repository root.') do |path|
|
||||||
wiki_options[:page_file_dir] = path
|
wiki_options[:page_file_dir] = path
|
||||||
end
|
end
|
||||||
|
|
||||||
opts.on('--prefer-relative-links', 'When specified, will try to replace broken links with relative links (\'[[Foo/Bar]]\' instead of \'[[/Subdir/Foo/Bar]]\') where possible.') do
|
opts.on('--prefer-relative-links', 'When specified, will try to replace broken links with relative links (\'[[Foo/Bar]]\' instead of \'[[/Subdir/Foo/Bar]]\') where possible.') do
|
||||||
migrate_options[:prefer_relative] = true
|
migrate_options[:prefer_relative] = true
|
||||||
end
|
end
|
||||||
|
|
||||||
opts.on('--hyphenate', 'Default. Repair links that use spaces instead of hyphens: [[Bilbo Baggins]] -> [[Bilbo-Baggins]]') do
|
opts.on('--hyphenate', 'Default. Repair links that use spaces instead of hyphens: [[Bilbo Baggins]] -> [[Bilbo-Baggins]]') do
|
||||||
migrate_options[:hyphenate] = true
|
migrate_options[:hyphenate] = true
|
||||||
end
|
end
|
||||||
|
|
||||||
opts.on('--no-hyphenate', 'Turn off the --hyphenate option.') do
|
opts.on('--no-hyphenate', 'Turn off the --hyphenate option.') do
|
||||||
migrate_options[:hyphenate] = false
|
migrate_options[:hyphenate] = false
|
||||||
end
|
end
|
||||||
|
|
||||||
opts.on('--run-silent', 'Don\'t output anything.') do
|
opts.on('--run-silent', 'Don\'t output anything.') do
|
||||||
migrate_options[:run_silent] = true
|
migrate_options[:run_silent] = true
|
||||||
end
|
end
|
||||||
|
|
||||||
opts.on('--write', 'No dry run: actually perform the substitutions.') do
|
opts.on('--write', 'No dry run: actually perform the substitutions.') do
|
||||||
migrate_options[:no_dry_run] = true
|
migrate_options[:no_dry_run] = true
|
||||||
end
|
end
|
||||||
@@ -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'
|
||||||
|
|
||||||
@@ -98,7 +104,7 @@ if cfg = options[:config]
|
|||||||
cfg = File.join(Dir.getwd, cfg) unless cfg.slice(0) == File::SEPARATOR
|
cfg = File.join(Dir.getwd, cfg) unless cfg.slice(0) == File::SEPARATOR
|
||||||
require cfg
|
require cfg
|
||||||
end
|
end
|
||||||
|
|
||||||
class Gollum::Filter::CodeMigrator < Gollum::Filter::Code
|
class Gollum::Filter::CodeMigrator < Gollum::Filter::Code
|
||||||
def extract(data)
|
def extract(data)
|
||||||
case @markup.format
|
case @markup.format
|
||||||
@@ -126,7 +132,7 @@ class Gollum::Filter::CodeMigrator < Gollum::Filter::Code
|
|||||||
next '' if m_end.length < m_start.length
|
next '' if m_end.length < m_start.length
|
||||||
lang = m_lang ? m_lang.strip.split.first : nil
|
lang = m_lang ? m_lang.strip.split.first : nil
|
||||||
cache_codeblock($~.to_s)
|
cache_codeblock($~.to_s)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
data.gsub!(/^([ ]{0,3})``` ?([^\r\n]+)?\r?\n(.+?)\r?\n[ ]{0,3}```[ \t]*\r?$/m) do
|
data.gsub!(/^([ ]{0,3})``` ?([^\r\n]+)?\r?\n(.+?)\r?\n[ ]{0,3}```[ \t]*\r?$/m) do
|
||||||
@@ -134,7 +140,7 @@ class Gollum::Filter::CodeMigrator < Gollum::Filter::Code
|
|||||||
end
|
end
|
||||||
data
|
data
|
||||||
end
|
end
|
||||||
|
|
||||||
def process(data)
|
def process(data)
|
||||||
return data if data.nil? || data.size.zero? || @map.size.zero?
|
return data if data.nil? || data.size.zero? || @map.size.zero?
|
||||||
@map.each do |id, block| ## Just put the code blocks back in verbatim
|
@map.each do |id, block| ## Just put the code blocks back in verbatim
|
||||||
@@ -142,23 +148,23 @@ class Gollum::Filter::CodeMigrator < Gollum::Filter::Code
|
|||||||
end
|
end
|
||||||
data
|
data
|
||||||
end
|
end
|
||||||
|
|
||||||
def cache_codeblock(block)
|
def cache_codeblock(block)
|
||||||
id = "#{open_pattern}#{Digest::SHA1.hexdigest(block)}#{close_pattern}"
|
id = "#{open_pattern}#{Digest::SHA1.hexdigest(block)}#{close_pattern}"
|
||||||
@map[id] = block
|
@map[id] = block
|
||||||
id
|
id
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class ::Gollum::Filter::TagMigrator < Gollum::Filter::Tags
|
class ::Gollum::Filter::TagMigrator < Gollum::Filter::Tags
|
||||||
def process_tag(tag)
|
def process_tag(tag)
|
||||||
link_part, extra = parse_tag_parts(tag)
|
link_part, extra = parse_tag_parts(tag)
|
||||||
orig_tag = %{[[#{tag}]]}
|
orig_tag = %{[[#{tag}]]}
|
||||||
return orig_tag if link_part.nil?
|
return orig_tag if link_part.nil?
|
||||||
|
|
||||||
img_args = extra ? [extra, link_part] : [link_part]
|
img_args = extra ? [extra, link_part] : [link_part]
|
||||||
mime = MIME::Types.type_for(::File.extname(img_args.first.to_s)).first
|
mime = MIME::Types.type_for(::File.extname(img_args.first.to_s)).first
|
||||||
|
|
||||||
# For any kind of tag other than an internal link: just return the tag.
|
# For any kind of tag other than an internal link: just return the tag.
|
||||||
if tag =~ /^_TOC_/ || link_part =~ /^_$/ || link_part =~ /^#{INCLUDE_TAG}/ || (mime && mime.content_type =~ /^image/) || process_external_link_tag(link_part, extra) || process_file_link_tag(link_part, extra)
|
if tag =~ /^_TOC_/ || link_part =~ /^_$/ || link_part =~ /^#{INCLUDE_TAG}/ || (mime && mime.content_type =~ /^image/) || process_external_link_tag(link_part, extra) || process_file_link_tag(link_part, extra)
|
||||||
return orig_tag
|
return orig_tag
|
||||||
@@ -168,7 +174,7 @@ class ::Gollum::Filter::TagMigrator < Gollum::Filter::Tags
|
|||||||
link = link_part
|
link = link_part
|
||||||
page = find_page_or_file_from_path(link)
|
page = find_page_or_file_from_path(link)
|
||||||
anchor = nil
|
anchor = nil
|
||||||
|
|
||||||
if page.nil? # No match yet, now try finding the page with anchor removed
|
if page.nil? # No match yet, now try finding the page with anchor removed
|
||||||
if pos = link.rindex('#')
|
if pos = link.rindex('#')
|
||||||
anchor = link[pos..-1]
|
anchor = link[pos..-1]
|
||||||
@@ -203,12 +209,12 @@ class ::Gollum::Filter::TagMigrator < Gollum::Filter::Tags
|
|||||||
pick = possibles.first
|
pick = possibles.first
|
||||||
return tag_for_pick(pick, orig_tag, extra, anchor, @markup.page.path)
|
return tag_for_pick(pick, orig_tag, extra, anchor, @markup.page.path)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def tag_for_pick(pick, orig_tag, extra, anchor, linking_page_path)
|
def tag_for_pick(pick, orig_tag, extra, anchor, linking_page_path)
|
||||||
pick = if setting(:prefer_relative)
|
pick = if setting(:prefer_relative)
|
||||||
overlapping_path = Pathname.new(linking_page_path).dirname.to_s
|
overlapping_path = Pathname.new(linking_page_path).dirname.to_s
|
||||||
@@ -220,7 +226,7 @@ class ::Gollum::Filter::TagMigrator < Gollum::Filter::Tags
|
|||||||
end
|
end
|
||||||
new_tag = extra.nil? ? %{[[#{pick}#{anchor}]]} : %{[[#{extra}|#{pick}#{anchor}]]}
|
new_tag = extra.nil? ? %{[[#{pick}#{anchor}]]} : %{[[#{extra}|#{pick}#{anchor}]]}
|
||||||
log(:info, "#{@markup.page.path}: Changing #{orig_tag} -> #{new_tag}")
|
log(:info, "#{@markup.page.path}: Changing #{orig_tag} -> #{new_tag}")
|
||||||
new_tag
|
new_tag
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -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)
|
||||||
@@ -268,4 +280,4 @@ wiki.pages.each do |page|
|
|||||||
f.close
|
f.close
|
||||||
end
|
end
|
||||||
log(:none, '====')
|
log(:none, '====')
|
||||||
end
|
end
|
||||||
|
|||||||
Executable
+18
@@ -0,0 +1,18 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Initialize the wiki
|
||||||
|
if [ ! -d .git ]; then
|
||||||
|
git init
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Set git user.name and user.email
|
||||||
|
if [ ${GOLLUM_AUTHOR_USERNAME:+1} ]; then
|
||||||
|
git config user.name "${GOLLUM_AUTHOR_USERNAME}"
|
||||||
|
fi
|
||||||
|
if [ ${GOLLUM_AUTHOR_EMAIL:+1} ]; then
|
||||||
|
git config user.email "${GOLLUM_AUTHOR_EMAIL}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Start gollum service
|
||||||
|
[[ "$@" != *--mathjax* ]] && echo "WARNING: Mathjax will soon be disabled by default. To explicitly enable it, use --mathjax" >&2
|
||||||
|
exec gollum $@ --mathjax
|
||||||
+3
-6
@@ -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 = '>= 1.9'
|
|
||||||
|
|
||||||
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.'
|
||||||
@@ -28,7 +25,7 @@ Gem::Specification.new do |s|
|
|||||||
s.add_dependency 'kramdown-parser-gfm', '~> 1.1.0'
|
s.add_dependency 'kramdown-parser-gfm', '~> 1.1.0'
|
||||||
s.add_dependency 'sinatra', '~> 2.0'
|
s.add_dependency 'sinatra', '~> 2.0'
|
||||||
s.add_dependency 'sinatra-contrib', '~> 2.0'
|
s.add_dependency 'sinatra-contrib', '~> 2.0'
|
||||||
s.add_dependency 'mustache-sinatra', '~> 1.0'
|
s.add_dependency 'mustache-sinatra', '>= 1.0.1', '< 2'
|
||||||
s.add_dependency 'useragent', '~> 0.16.2'
|
s.add_dependency 'useragent', '~> 0.16.2'
|
||||||
s.add_dependency 'gemojione', '~> 4.1'
|
s.add_dependency 'gemojione', '~> 4.1'
|
||||||
s.add_dependency 'octicons', '~> 12.0'
|
s.add_dependency 'octicons', '~> 12.0'
|
||||||
@@ -44,7 +41,6 @@ Gem::Specification.new do |s|
|
|||||||
s.add_development_dependency 'rack-test', '~> 0.6.3'
|
s.add_development_dependency 'rack-test', '~> 0.6.3'
|
||||||
s.add_development_dependency 'shoulda', '~> 3.6.0'
|
s.add_development_dependency 'shoulda', '~> 3.6.0'
|
||||||
s.add_development_dependency 'minitest-reporters', '~> 1.3.6'
|
s.add_development_dependency 'minitest-reporters', '~> 1.3.6'
|
||||||
s.add_development_dependency 'twitter_cldr', '~> 3.2.0'
|
|
||||||
s.add_development_dependency 'mocha', '~> 1.8.0'
|
s.add_development_dependency 'mocha', '~> 1.8.0'
|
||||||
s.add_development_dependency 'test-unit', '~> 3.3.0'
|
s.add_development_dependency 'test-unit', '~> 3.3.0'
|
||||||
|
|
||||||
@@ -1153,6 +1149,7 @@ Gem::Specification.new do |s|
|
|||||||
lib/gollum/public/gollum/javascript/ace/worker-xquery.js
|
lib/gollum/public/gollum/javascript/ace/worker-xquery.js
|
||||||
lib/gollum/public/gollum/javascript/app.js
|
lib/gollum/public/gollum/javascript/app.js
|
||||||
lib/gollum/public/gollum/javascript/clipboard.min.js
|
lib/gollum/public/gollum/javascript/clipboard.min.js
|
||||||
|
lib/gollum/public/gollum/javascript/date.min.js
|
||||||
lib/gollum/public/gollum/javascript/editor.js
|
lib/gollum/public/gollum/javascript/editor.js
|
||||||
lib/gollum/public/gollum/javascript/editor/gollum.editor.js
|
lib/gollum/public/gollum/javascript/editor/gollum.editor.js
|
||||||
lib/gollum/public/gollum/javascript/editor/langs/asciidoc.js
|
lib/gollum/public/gollum/javascript/editor/langs/asciidoc.js
|
||||||
|
|||||||
+3
-2
@@ -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
|
||||||
|
|||||||
+50
-30
@@ -20,8 +20,10 @@ require 'gollum/views/layout'
|
|||||||
require 'gollum/views/editable'
|
require 'gollum/views/editable'
|
||||||
require 'gollum/views/has_page'
|
require 'gollum/views/has_page'
|
||||||
require 'gollum/views/has_user_icons'
|
require 'gollum/views/has_user_icons'
|
||||||
|
require 'gollum/views/has_math'
|
||||||
require 'gollum/views/pagination'
|
require 'gollum/views/pagination'
|
||||||
require 'gollum/views/rss.rb'
|
require 'gollum/views/rss.rb'
|
||||||
|
require 'gollum/views/template_cascade'
|
||||||
|
|
||||||
require File.expand_path '../helpers', __FILE__
|
require File.expand_path '../helpers', __FILE__
|
||||||
|
|
||||||
@@ -101,16 +103,18 @@ 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]
|
||||||
|
@show_local_time = settings.wiki_options.fetch(:show_local_time, false)
|
||||||
|
|
||||||
@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]
|
||||||
Precious::App.set(:mustache, {:templates => settings.wiki_options[:template_dir]}) if settings.wiki_options[:template_dir]
|
Precious::Views::Layout.extend Precious::Views::TemplateCascade
|
||||||
|
Precious::Views::Layout.template_priority_path = settings.wiki_options[:template_dir]
|
||||||
|
end
|
||||||
|
|
||||||
@base_url = url('/', false).chomp('/').force_encoding('utf-8')
|
@base_url = url('/', false).chomp('/').force_encoding('utf-8')
|
||||||
@page_dir = settings.wiki_options[:page_file_dir].to_s
|
@page_dir = settings.wiki_options[:page_file_dir].to_s
|
||||||
@@ -120,6 +124,7 @@ module Precious
|
|||||||
@css = settings.wiki_options[:css]
|
@css = settings.wiki_options[:css]
|
||||||
@js = settings.wiki_options[:js]
|
@js = settings.wiki_options[:js]
|
||||||
@mathjax_config = settings.wiki_options[:mathjax_config]
|
@mathjax_config = settings.wiki_options[:mathjax_config]
|
||||||
|
@mathjax = settings.wiki_options[:mathjax]
|
||||||
|
|
||||||
@use_static_assets = settings.wiki_options.fetch(:static, settings.environment != :development)
|
@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'))
|
@static_assets_path = settings.wiki_options.fetch(:static_assets_path, ::File.join(File.dirname(__FILE__), 'public/assets'))
|
||||||
@@ -135,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
|
||||||
@@ -171,7 +178,9 @@ module Precious
|
|||||||
content_type :json
|
content_type :json
|
||||||
if page = wiki_page(params[:path]).page
|
if page = wiki_page(params[:path]).page
|
||||||
version = page.last_version
|
version = page.last_version
|
||||||
{:author => version.author.name, :date => version.authored_date}.to_json
|
authored_date = version.authored_date
|
||||||
|
authored_date = authored_date.utc.iso8601 if @show_local_time
|
||||||
|
{:author => version.author.name, :date => authored_date}.to_json
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -212,7 +221,6 @@ module Precious
|
|||||||
if page = wikip.page
|
if page = wikip.page
|
||||||
@page = page
|
@page = page
|
||||||
@content = page.text_data
|
@content = page.text_data
|
||||||
@mathjax = wiki.mathjax
|
|
||||||
@etag = page.sha
|
@etag = page.sha
|
||||||
mustache :edit
|
mustache :edit
|
||||||
else
|
else
|
||||||
@@ -234,7 +242,7 @@ module Precious
|
|||||||
halt 500 unless tempfile.is_a? Tempfile
|
halt 500 unless tempfile.is_a? Tempfile
|
||||||
|
|
||||||
if wiki.per_page_uploads
|
if wiki.per_page_uploads
|
||||||
dir = request.referer.sub(request.base_url, '')
|
dir = request.referer.match(/^https?:\/\/#{request.host_with_port}\/(.*)/)[1]
|
||||||
# remove base path if it is set
|
# remove base path if it is set
|
||||||
dir.sub!(/^#{wiki.base_path}/, '') if wiki.base_path
|
dir.sub!(/^#{wiki.base_path}/, '') if wiki.base_path
|
||||||
# remove base_url and gollum/* subpath if necessary
|
# remove base_url and gollum/* subpath if necessary
|
||||||
@@ -360,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)
|
||||||
|
|
||||||
@@ -434,23 +442,18 @@ module Precious
|
|||||||
mustache :page
|
mustache :page
|
||||||
end
|
end
|
||||||
|
|
||||||
|
get %r{
|
||||||
|
/history/ # match any URL beginning with /history/
|
||||||
|
(.+?) # extract the full path (including any directories)
|
||||||
|
/
|
||||||
|
([0-9a-f]{40}) # match SHA
|
||||||
|
}x do |path, version|
|
||||||
|
wiki = wiki_new
|
||||||
|
show_history wiki_page(path, wiki.commit_for(version), wiki)
|
||||||
|
end
|
||||||
|
|
||||||
get '/history/*' do
|
get '/history/*' do
|
||||||
wikip = wiki_page(params[:splat].first)
|
show_history wiki_page(params[:splat].first)
|
||||||
@name = wikip.fullname
|
|
||||||
@page = wikip.page
|
|
||||||
@page_num = [params[:page_num].to_i, 1].max
|
|
||||||
@max_count = settings.wiki_options.fetch(:pagination_count, 10)
|
|
||||||
unless @page.nil?
|
|
||||||
@wiki = @page.wiki
|
|
||||||
@versions = @page.versions(
|
|
||||||
per_page: @max_count,
|
|
||||||
page_num: @page_num,
|
|
||||||
follow: settings.wiki_options.fetch(:follow_renames, true)
|
|
||||||
)
|
|
||||||
mustache :history
|
|
||||||
else
|
|
||||||
redirect to("/")
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
get '/latest_changes' do
|
get '/latest_changes' do
|
||||||
@@ -597,6 +600,24 @@ module Precious
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def show_history(wikip)
|
||||||
|
@name = wikip.fullname
|
||||||
|
@page = wikip.page
|
||||||
|
@page_num = [params[:page_num].to_i, 1].max
|
||||||
|
@max_count = settings.wiki_options.fetch(:pagination_count, 10)
|
||||||
|
unless @page.nil?
|
||||||
|
@wiki = @page.wiki
|
||||||
|
@versions = @page.versions(
|
||||||
|
per_page: @max_count,
|
||||||
|
page_num: @page_num,
|
||||||
|
follow: settings.wiki_options.fetch(:follow_renames, true)
|
||||||
|
)
|
||||||
|
mustache :history
|
||||||
|
else
|
||||||
|
redirect to("/")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def show_page_or_file(fullpath)
|
def show_page_or_file(fullpath)
|
||||||
wiki = wiki_new
|
wiki = wiki_new
|
||||||
if page = wiki.page(fullpath)
|
if page = wiki.page(fullpath)
|
||||||
@@ -608,7 +629,6 @@ module Precious
|
|||||||
# Extensions and layout data
|
# Extensions and layout data
|
||||||
@editable = true
|
@editable = true
|
||||||
@toc_content = wiki.universal_toc ? @page.toc_data : nil
|
@toc_content = wiki.universal_toc ? @page.toc_data : nil
|
||||||
@mathjax = wiki.mathjax
|
|
||||||
@h1_title = wiki.h1_title
|
@h1_title = wiki.h1_title
|
||||||
@bar_side = wiki.bar_side
|
@bar_side = wiki.bar_side
|
||||||
@allow_uploads = wiki.allow_uploads
|
@allow_uploads = wiki.allow_uploads
|
||||||
@@ -640,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.raw_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)
|
||||||
@@ -654,9 +674,9 @@ module Precious
|
|||||||
wiki.update_page(page, name, format, content.to_s, commit)
|
wiki.update_page(page, name, format, content.to_s, commit)
|
||||||
end
|
end
|
||||||
|
|
||||||
def wiki_page(path, version = nil)
|
def wiki_page(path, version = nil, wiki = nil)
|
||||||
pathname = (Pathname.new('/') + path).cleanpath
|
pathname = (Pathname.new('/') + path).cleanpath
|
||||||
wiki = wiki_new
|
wiki = wiki_new if wiki.nil?
|
||||||
OpenStruct.new(:wiki => wiki, :page => wiki.page(pathname.to_s, version = version),
|
OpenStruct.new(:wiki => wiki, :page => wiki.page(pathname.to_s, version = version),
|
||||||
:name => pathname.basename.sub_ext('').to_s, :path => pathname.dirname.to_s, :ext => pathname.extname, :fullname => pathname.basename.to_s, :fullpath => pathname.to_s)
|
:name => pathname.basename.sub_ext('').to_s, :path => pathname.dirname.to_s, :ext => pathname.extname, :fullname => pathname.basename.to_s, :fullpath => pathname.to_s)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
{"files":{"app-f05401ee374f0c7f48fc2bc08e30b4f4db705861fd5895ed70998683b383bfb5.js":{"logical_path":"app.js","mtime":"2021-11-15T20:08:30-08:00","size":136040,"digest":"f05401ee374f0c7f48fc2bc08e30b4f4db705861fd5895ed70998683b383bfb5","integrity":"sha256-8FQB7jdPDH9I/CvAjjC09NtwWGH9WJXtcJmGg7ODv7U="},"editor-9881d0c7ae663293f0e3a7e72729eec7e940fa613185c076709b76d292f5703a.js":{"logical_path":"editor.js","mtime":"2021-11-15T20:08:30-08:00","size":744886,"digest":"9881d0c7ae663293f0e3a7e72729eec7e940fa613185c076709b76d292f5703a","integrity":"sha256-mIHQx65mMpPw46fnJynux+lA+mExhcB2cJt20pL1cDo="},"app-309be032396e783b13a47df58f389b7c8e11c2b2d42640560b874f677c25f6e5.css":{"logical_path":"app.css","mtime":"2021-11-15T20:08:30-08:00","size":396731,"digest":"309be032396e783b13a47df58f389b7c8e11c2b2d42640560b874f677c25f6e5","integrity":"sha256-MJvgMjlueDsTpH31jzibfI4RwrLUJkBWC4dPZ3wl9uU="},"criticmarkup-31ae5d3282bbb8e7b7c3c9917e9fb68e3315a6b4a75da6cec48d21b8846905c4.css":{"logical_path":"criticmarkup.css","mtime":"2021-08-22T15:24:51-07:00","size":646,"digest":"31ae5d3282bbb8e7b7c3c9917e9fb68e3315a6b4a75da6cec48d21b8846905c4","integrity":"sha256-Ma5dMoK7uOe3w8mRfp+2jjMVprSnXabOxI0huIRpBcQ="},"print-512498c368be0d3fb1ba105dfa84289ae48380ec9fcbef948bd4e23b0b095bfb.css":{"logical_path":"print.css","mtime":"2021-08-22T15:24:51-07:00","size":75,"digest":"512498c368be0d3fb1ba105dfa84289ae48380ec9fcbef948bd4e23b0b095bfb","integrity":"sha256-USSYw2i+DT+xuhBd+oQomuSDgOyfy++Ui9TiOwsJW/s="}},"assets":{"app.js":"app-f05401ee374f0c7f48fc2bc08e30b4f4db705861fd5895ed70998683b383bfb5.js","editor.js":"editor-9881d0c7ae663293f0e3a7e72729eec7e940fa613185c076709b76d292f5703a.js","app.css":"app-309be032396e783b13a47df58f389b7c8e11c2b2d42640560b874f677c25f6e5.css","criticmarkup.css":"criticmarkup-31ae5d3282bbb8e7b7c3c9917e9fb68e3315a6b4a75da6cec48d21b8846905c4.css","print.css":"print-512498c368be0d3fb1ba105dfa84289ae48380ec9fcbef948bd4e23b0b095bfb.css"}}
|
||||||
@@ -1 +0,0 @@
|
|||||||
{"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"}}
|
|
||||||
+1
-1
File diff suppressed because one or more lines are too long
BIN
Binary file not shown.
+2
-2
File diff suppressed because one or more lines are too long
BIN
Binary file not shown.
BIN
Binary file not shown.
+2
-2
File diff suppressed because one or more lines are too long
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -1,5 +1,6 @@
|
|||||||
//= require jquery-1.7.2.min
|
//= require jquery-1.7.2.min
|
||||||
//= require identicon
|
//= require identicon
|
||||||
|
//= require date.min
|
||||||
//= require mousetrap.min
|
//= require mousetrap.min
|
||||||
//= require clipboard.min
|
//= require clipboard.min
|
||||||
//= require gollum
|
//= require gollum
|
||||||
|
|||||||
+123
@@ -0,0 +1,123 @@
|
|||||||
|
/**
|
||||||
|
* @overview datejs
|
||||||
|
* @version 1.0.0-rc3
|
||||||
|
* @author Gregory Wild-Smith <gregory@wild-smith.com>
|
||||||
|
* @copyright 2015 Gregory Wild-Smith
|
||||||
|
* @license MIT
|
||||||
|
* @homepage https://github.com/abritinthebay/datejs
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
2015 Gregory Wild-Smith
|
||||||
|
@license MIT
|
||||||
|
@homepage https://github.com/abritinthebay/datejs
|
||||||
|
*/
|
||||||
|
(function(){var h=Date,f=Date.CultureStrings?Date.CultureStrings.lang:null,d={},c={getFromKey:function(a,b){var e;e=Date.CultureStrings&&Date.CultureStrings[b]&&Date.CultureStrings[b][a]?Date.CultureStrings[b][a]:c.buildFromDefault(a);"/"===a.charAt(0)&&(e=c.buildFromRegex(a,b));return e},getFromObjectValues:function(a,b){var e,g={};for(e in a)a.hasOwnProperty(e)&&(g[e]=c.getFromKey(a[e],b));return g},getFromObjectKeys:function(a,b){var e,g={};for(e in a)a.hasOwnProperty(e)&&(g[c.getFromKey(e,b)]=
|
||||||
|
a[e]);return g},getFromArray:function(a,b){for(var e=[],g=0;g<a.length;g++)g in a&&(e[g]=c.getFromKey(a[g],b));return e},buildFromDefault:function(a){var b,e,g;switch(a){case "name":b="en-US";break;case "englishName":b="English (United States)";break;case "nativeName":b="English (United States)";break;case "twoDigitYearMax":b=2049;break;case "firstDayOfWeek":b=0;break;default:if(b=a,g=a.split("_"),e=g.length,1<e&&"/"!==a.charAt(0)&&(a=g[e-1].toLowerCase(),"initial"===a||"abbr"===a))b=g[0]}return b},
|
||||||
|
buildFromRegex:function(a,b){return Date.CultureStrings&&Date.CultureStrings[b]&&Date.CultureStrings[b][a]?new RegExp(Date.CultureStrings[b][a],"i"):new RegExp(a.replace(RegExp("/","g"),""),"i")}},a=function(a,b){var e=b?b:f;d[a]=a;return"object"===typeof a?a instanceof Array?c.getFromArray(a,e):c.getFromObjectKeys(a,e):c.getFromKey(a,e)},b=function(a){a=Date.Config.i18n+a+".js";var b=document.getElementsByTagName("head")[0]||document.documentElement,e=document.createElement("script");e.src=a;var g=
|
||||||
|
{done:function(){}};e.onload=e.onreadystatechange=function(){this.readyState&&"loaded"!==this.readyState&&"complete"!==this.readyState||(g.done(),b.removeChild(e))};setTimeout(function(){b.insertBefore(e,b.firstChild)},0);return{done:function(a){g.done=function(){a&&setTimeout(a,0)}}}},e={buildFromMethodHash:function(a){for(var b in a)a.hasOwnProperty(b)&&(a[b]=e[a[b]]());return a},timeZoneDST:function(){return a({CHADT:"+1345",NZDT:"+1300",AEDT:"+1100",ACDT:"+1030",AZST:"+0500",IRDT:"+0430",EEST:"+0300",
|
||||||
|
CEST:"+0200",BST:"+0100",PMDT:"-0200",ADT:"-0300",NDT:"-0230",EDT:"-0400",CDT:"-0500",MDT:"-0600",PDT:"-0700",AKDT:"-0800",HADT:"-0900"})},timeZoneStandard:function(){return a({LINT:"+1400",TOT:"+1300",CHAST:"+1245",NZST:"+1200",NFT:"+1130",SBT:"+1100",AEST:"+1000",ACST:"+0930",JST:"+0900",CWST:"+0845",CT:"+0800",ICT:"+0700",MMT:"+0630",BST:"+0600",NPT:"+0545",IST:"+0530",PKT:"+0500",AFT:"+0430",MSK:"+0400",IRST:"+0330",FET:"+0300",EET:"+0200",CET:"+0100",GMT:"+0000",UTC:"+0000",CVT:"-0100",GST:"-0200",
|
||||||
|
BRT:"-0300",NST:"-0330",AST:"-0400",EST:"-0500",CST:"-0600",MST:"-0700",PST:"-0800",AKST:"-0900",MIT:"-0930",HST:"-1000",SST:"-1100",BIT:"-1200"})},timeZones:function(a){var b;a.timezones=[];for(b in a.abbreviatedTimeZoneStandard)a.abbreviatedTimeZoneStandard.hasOwnProperty(b)&&a.timezones.push({name:b,offset:a.abbreviatedTimeZoneStandard[b]});for(b in a.abbreviatedTimeZoneDST)a.abbreviatedTimeZoneDST.hasOwnProperty(b)&&a.timezones.push({name:b,offset:a.abbreviatedTimeZoneDST[b],dst:!0});return a.timezones},
|
||||||
|
days:function(){return a("Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "))},dayAbbr:function(){return a("Sun Mon Tue Wed Thu Fri Sat".split(" "))},dayShortNames:function(){return a("Su Mo Tu We Th Fr Sa".split(" "))},dayFirstLetters:function(){return a("S_Sun_Initial M_Mon_Initial T_Tues_Initial W_Wed_Initial T_Thu_Initial F_Fri_Initial S_Sat_Initial".split(" "))},months:function(){return a("January February March April May June July August September October November December".split(" "))},
|
||||||
|
monthAbbr:function(){return a("Jan_Abbr Feb_Abbr Mar_Abbr Apr_Abbr May_Abbr Jun_Abbr Jul_Abbr Aug_Abbr Sep_Abbr Oct_Abbr Nov_Abbr Dec_Abbr".split(" "))},formatPatterns:function(){return c.getFromObjectValues({shortDate:"M/d/yyyy",longDate:"dddd, MMMM dd, yyyy",shortTime:"h:mm tt",longTime:"h:mm:ss tt",fullDateTime:"dddd, MMMM dd, yyyy h:mm:ss tt",sortableDateTime:"yyyy-MM-ddTHH:mm:ss",universalSortableDateTime:"yyyy-MM-dd HH:mm:ssZ",rfc1123:"ddd, dd MMM yyyy HH:mm:ss",monthDay:"MMMM dd",yearMonth:"MMMM, yyyy"},
|
||||||
|
Date.i18n.currentLanguage())},regex:function(){return c.getFromObjectValues({inTheMorning:"/( in the )(morn(ing)?)\\b/",thisMorning:"/(this )(morn(ing)?)\\b/",amThisMorning:"/(\b\\d(am)? )(this )(morn(ing)?)/",inTheEvening:"/( in the )(even(ing)?)\\b/",thisEvening:"/(this )(even(ing)?)\\b/",pmThisEvening:"/(\b\\d(pm)? )(this )(even(ing)?)/",jan:"/jan(uary)?/",feb:"/feb(ruary)?/",mar:"/mar(ch)?/",apr:"/apr(il)?/",may:"/may/",jun:"/jun(e)?/",jul:"/jul(y)?/",aug:"/aug(ust)?/",sep:"/sep(t(ember)?)?/",
|
||||||
|
oct:"/oct(ober)?/",nov:"/nov(ember)?/",dec:"/dec(ember)?/",sun:"/^su(n(day)?)?/",mon:"/^mo(n(day)?)?/",tue:"/^tu(e(s(day)?)?)?/",wed:"/^we(d(nesday)?)?/",thu:"/^th(u(r(s(day)?)?)?)?/",fri:"/fr(i(day)?)?/",sat:"/^sa(t(urday)?)?/",future:"/^next/",past:"/^last|past|prev(ious)?/",add:"/^(\\+|aft(er)?|from|hence)/",subtract:"/^(\\-|bef(ore)?|ago)/",yesterday:"/^yes(terday)?/",today:"/^t(od(ay)?)?/",tomorrow:"/^tom(orrow)?/",now:"/^n(ow)?/",millisecond:"/^ms|milli(second)?s?/",second:"/^sec(ond)?s?/",
|
||||||
|
minute:"/^mn|min(ute)?s?/",hour:"/^h(our)?s?/",week:"/^w(eek)?s?/",month:"/^m(onth)?s?/",day:"/^d(ay)?s?/",year:"/^y(ear)?s?/",shortMeridian:"/^(a|p)/",longMeridian:"/^(a\\.?m?\\.?|p\\.?m?\\.?)/",timezone:"/^((e(s|d)t|c(s|d)t|m(s|d)t|p(s|d)t)|((gmt)?\\s*(\\+|\\-)\\s*\\d\\d\\d\\d?)|gmt|utc)/",ordinalSuffix:"/^\\s*(st|nd|rd|th)/",timeContext:"/^\\s*(\\:|a(?!u|p)|p)/"},Date.i18n.currentLanguage())}},g=function(){var a=c.getFromObjectValues({name:"name",englishName:"englishName",nativeName:"nativeName",
|
||||||
|
amDesignator:"AM",pmDesignator:"PM",firstDayOfWeek:"firstDayOfWeek",twoDigitYearMax:"twoDigitYearMax",dateElementOrder:"mdy"},Date.i18n.currentLanguage()),b=e.buildFromMethodHash({dayNames:"days",abbreviatedDayNames:"dayAbbr",shortestDayNames:"dayShortNames",firstLetterDayNames:"dayFirstLetters",monthNames:"months",abbreviatedMonthNames:"monthAbbr",formatPatterns:"formatPatterns",regexPatterns:"regex",abbreviatedTimeZoneDST:"timeZoneDST",abbreviatedTimeZoneStandard:"timeZoneStandard"}),g;for(g in b)b.hasOwnProperty(g)&&
|
||||||
|
(a[g]=b[g]);e.timeZones(a);return a};h.i18n={__:function(m,b){return a(m,b)},currentLanguage:function(){return f||"en-US"},setLanguage:function(a,e,c){var d=!1;if(e||"en-US"===a||Date.CultureStrings&&Date.CultureStrings[a])f=a,Date.CultureStrings=Date.CultureStrings||{},Date.CultureStrings.lang=a,Date.CultureInfo=new g;else if(!Date.CultureStrings||!Date.CultureStrings[a])if("undefined"!==typeof exports&&this.exports!==exports)try{require("../i18n/"+a+".js"),f=a,Date.CultureStrings.lang=a,Date.CultureInfo=
|
||||||
|
new g}catch(p){throw Error("The DateJS IETF language tag '"+a+"' could not be loaded by Node. It likely does not exist.");}else if(Date.Config&&Date.Config.i18n)d=!0,b(a).done(function(){f=a;Date.CultureStrings=Date.CultureStrings||{};Date.CultureStrings.lang=a;Date.CultureInfo=new g;h.Parsing.Normalizer.buildReplaceData();h.Grammar&&h.Grammar.buildGrammarFormats();c&&setTimeout(c,0)});else return Date.console.error("The DateJS IETF language tag '"+a+"' is not available and has not been loaded."),
|
||||||
|
!1;h.Parsing.Normalizer.buildReplaceData();h.Grammar&&h.Grammar.buildGrammarFormats();!d&&c&&setTimeout(c,0)},getLoggedKeys:function(){return d},updateCultureInfo:function(){Date.CultureInfo=new g}};h.i18n.updateCultureInfo()})();
|
||||||
|
(function(){var h=Date,f=h.prototype,d=function(a,b){b||(b=2);return("000"+a).slice(-1*b)};h.console="undefined"!==typeof window&&"undefined"!==typeof window.console&&"undefined"!==typeof window.console.log?console:{log:function(){},error:function(){}};h.Config=h.Config||{};h.initOverloads=function(){h.now?h._now||(h._now=h.now):h._now=function(){return(new Date).getTime()};h.now=function(a){return a?h.present():h._now()};f.toISOString||(f.toISOString=function(){return this.getUTCFullYear()+"-"+d(this.getUTCMonth()+
|
||||||
|
1)+"-"+d(this.getUTCDate())+"T"+d(this.getUTCHours())+":"+d(this.getUTCMinutes())+":"+d(this.getUTCSeconds())+"."+String((this.getUTCMilliseconds()/1E3).toFixed(3)).slice(2,5)+"Z"});void 0===f._toString&&(f._toString=f.toString)};h.initOverloads();h.today=function(){return(new Date).clearTime()};h.present=function(){return new Date};h.compare=function(a,b){if(isNaN(a)||isNaN(b))throw Error(a+" - "+b);if(a instanceof Date&&b instanceof Date)return a<b?-1:a>b?1:0;throw new TypeError(a+" - "+b);};h.equals=
|
||||||
|
function(a,b){return 0===a.compareTo(b)};h.getDayName=function(a){return Date.CultureInfo.dayNames[a]};h.getDayNumberFromName=function(a){var b=Date.CultureInfo.dayNames,e=Date.CultureInfo.abbreviatedDayNames,g=Date.CultureInfo.shortestDayNames;a=a.toLowerCase();for(var m=0;m<b.length;m++)if(b[m].toLowerCase()===a||e[m].toLowerCase()===a||g[m].toLowerCase()===a)return m;return-1};h.getMonthNumberFromName=function(a){var b=Date.CultureInfo.monthNames,e=Date.CultureInfo.abbreviatedMonthNames;a=a.toLowerCase();
|
||||||
|
for(var g=0;g<b.length;g++)if(b[g].toLowerCase()===a||e[g].toLowerCase()===a)return g;return-1};h.getMonthName=function(a){return Date.CultureInfo.monthNames[a]};h.isLeapYear=function(a){return 0===a%4&&0!==a%100||0===a%400};h.getDaysInMonth=function(a,b){!b&&h.validateMonth(a)&&(b=a,a=Date.today().getFullYear());return[31,h.isLeapYear(a)?29:28,31,30,31,30,31,31,30,31,30,31][b]};f.getDaysInMonth=function(){return h.getDaysInMonth(this.getFullYear(),this.getMonth())};h.getTimezoneAbbreviation=function(a,
|
||||||
|
b){var e,g=b?Date.CultureInfo.abbreviatedTimeZoneDST:Date.CultureInfo.abbreviatedTimeZoneStandard;for(e in g)if(g.hasOwnProperty(e)&&g[e]===a)return e;return null};h.getTimezoneOffset=function(a,b){var e,g=[],m=Date.CultureInfo.timezones;a||(a=(new Date).getTimezone());for(e=0;e<m.length;e++)m[e].name===a.toUpperCase()&&g.push(e);if(!m[g[0]])return null;if(1!==g.length&&b)for(e=0;e<g.length;e++){if(m[g[e]].dst)return m[g[e]].offset}else return m[g[0]].offset};h.getQuarter=function(a){a=a||new Date;
|
||||||
|
return[1,2,3,4][Math.floor(a.getMonth()/3)]};h.getDaysLeftInQuarter=function(a){a=a||new Date;var b=new Date(a);b.setMonth(b.getMonth()+3-b.getMonth()%3,0);return Math.floor((b-a)/864E5)};var c=function(a,b,e,g){if("undefined"===typeof a)return!1;if("number"!==typeof a)throw new TypeError(a+" is not a Number.");return a<b||a>e?!1:!0};h.validateMillisecond=function(a){return c(a,0,999,"millisecond")};h.validateSecond=function(a){return c(a,0,59,"second")};h.validateMinute=function(a){return c(a,0,
|
||||||
|
59,"minute")};h.validateHour=function(a){return c(a,0,23,"hour")};h.validateDay=function(a,b,e){return void 0===b||null===b||void 0===e||null===e?!1:c(a,1,h.getDaysInMonth(b,e),"day")};h.validateWeek=function(a){return c(a,0,53,"week")};h.validateMonth=function(a){return c(a,0,11,"month")};h.validateYear=function(a){return c(a,-271822,275760,"year")};h.validateTimezone=function(a){return 1==={ACDT:1,ACST:1,ACT:1,ADT:1,AEDT:1,AEST:1,AFT:1,AKDT:1,AKST:1,AMST:1,AMT:1,ART:1,AST:1,AWDT:1,AWST:1,AZOST:1,
|
||||||
|
AZT:1,BDT:1,BIOT:1,BIT:1,BOT:1,BRT:1,BST:1,BTT:1,CAT:1,CCT:1,CDT:1,CEDT:1,CEST:1,CET:1,CHADT:1,CHAST:1,CHOT:1,ChST:1,CHUT:1,CIST:1,CIT:1,CKT:1,CLST:1,CLT:1,COST:1,COT:1,CST:1,CT:1,CVT:1,CWST:1,CXT:1,DAVT:1,DDUT:1,DFT:1,EASST:1,EAST:1,EAT:1,ECT:1,EDT:1,EEDT:1,EEST:1,EET:1,EGST:1,EGT:1,EIT:1,EST:1,FET:1,FJT:1,FKST:1,FKT:1,FNT:1,GALT:1,GAMT:1,GET:1,GFT:1,GILT:1,GIT:1,GMT:1,GST:1,GYT:1,HADT:1,HAEC:1,HAST:1,HKT:1,HMT:1,HOVT:1,HST:1,ICT:1,IDT:1,IOT:1,IRDT:1,IRKT:1,IRST:1,IST:1,JST:1,KGT:1,KOST:1,KRAT:1,
|
||||||
|
KST:1,LHST:1,LINT:1,MAGT:1,MART:1,MAWT:1,MDT:1,MET:1,MEST:1,MHT:1,MIST:1,MIT:1,MMT:1,MSK:1,MST:1,MUT:1,MVT:1,MYT:1,NCT:1,NDT:1,NFT:1,NPT:1,NST:1,NT:1,NUT:1,NZDT:1,NZST:1,OMST:1,ORAT:1,PDT:1,PET:1,PETT:1,PGT:1,PHOT:1,PHT:1,PKT:1,PMDT:1,PMST:1,PONT:1,PST:1,PYST:1,PYT:1,RET:1,ROTT:1,SAKT:1,SAMT:1,SAST:1,SBT:1,SCT:1,SGT:1,SLST:1,SRT:1,SST:1,SYOT:1,TAHT:1,THA:1,TFT:1,TJT:1,TKT:1,TLT:1,TMT:1,TOT:1,TVT:1,UCT:1,ULAT:1,UTC:1,UYST:1,UYT:1,UZT:1,VET:1,VLAT:1,VOLT:1,VOST:1,VUT:1,WAKT:1,WAST:1,WAT:1,WEDT:1,WEST:1,
|
||||||
|
WET:1,WST:1,YAKT:1,YEKT:1,Z:1}[a]};h.validateTimezoneOffset=function(a){return-841<a&&721>a}})();
|
||||||
|
(function(){var h=Date,f=h.prototype,d=function(a,b){b||(b=2);return("000"+a).slice(-1*b)},c=function(a){var b={},e=this,g,c;c=function(b,g,c){if("day"===b){b=void 0!==a.month?a.month:e.getMonth();var d=void 0!==a.year?a.year:e.getFullYear();return h[g](c,d,b)}return h[g](c)};for(g in a)if(Object.prototype.hasOwnProperty.call(a,g)){var d="validate"+g.charAt(0).toUpperCase()+g.slice(1);h[d]&&null!==a[g]&&c(g,d,a[g])&&(b[g]=a[g])}return b};f.clearTime=function(){this.setHours(0);this.setMinutes(0);
|
||||||
|
this.setSeconds(0);this.setMilliseconds(0);return this};f.setTimeToNow=function(){var a=new Date;this.setHours(a.getHours());this.setMinutes(a.getMinutes());this.setSeconds(a.getSeconds());this.setMilliseconds(a.getMilliseconds());return this};f.clone=function(){return new Date(this.getTime())};f.compareTo=function(a){return Date.compare(this,a)};f.equals=function(a){return Date.equals(this,void 0!==a?a:new Date)};f.between=function(a,b){return this.getTime()>=a.getTime()&&this.getTime()<=b.getTime()};
|
||||||
|
f.isAfter=function(a){return 1===this.compareTo(a||new Date)};f.isBefore=function(a){return-1===this.compareTo(a||new Date)};f.isToday=f.isSameDay=function(a){return this.clone().clearTime().equals((a||new Date).clone().clearTime())};f.addMilliseconds=function(a){if(!a)return this;this.setTime(this.getTime()+1*a);return this};f.addSeconds=function(a){return a?this.addMilliseconds(1E3*a):this};f.addMinutes=function(a){return a?this.addMilliseconds(6E4*a):this};f.addHours=function(a){return a?this.addMilliseconds(36E5*
|
||||||
|
a):this};f.addDays=function(a){if(!a)return this;this.setDate(this.getDate()+1*a);return this};f.addWeekdays=function(a){if(!a)return this;var b=this.getDay(),e=Math.ceil(Math.abs(a)/7);(0===b||6===b)&&0<a&&(this.next().monday(),this.addDays(-1),b=this.getDay());if(0>a){for(;0>a;)this.addDays(-1),b=this.getDay(),0!==b&&6!==b&&a++;return this}if(5<a||6-b<=a)a+=2*e;return this.addDays(a)};f.addWeeks=function(a){return a?this.addDays(7*a):this};f.addMonths=function(a){if(!a)return this;var b=this.getDate();
|
||||||
|
this.setDate(1);this.setMonth(this.getMonth()+1*a);this.setDate(Math.min(b,h.getDaysInMonth(this.getFullYear(),this.getMonth())));return this};f.addQuarters=function(a){return a?this.addMonths(3*a):this};f.addYears=function(a){return a?this.addMonths(12*a):this};f.add=function(a){if("number"===typeof a)return this._orient=a,this;a.day&&0!==a.day-this.getDate()&&this.setDate(a.day);a.milliseconds&&this.addMilliseconds(a.milliseconds);a.seconds&&this.addSeconds(a.seconds);a.minutes&&this.addMinutes(a.minutes);
|
||||||
|
a.hours&&this.addHours(a.hours);a.weeks&&this.addWeeks(a.weeks);a.months&&this.addMonths(a.months);a.years&&this.addYears(a.years);a.days&&this.addDays(a.days);return this};f.getWeek=function(a){var b=new Date(this.valueOf());a?(b.addMinutes(b.getTimezoneOffset()),a=b.clone()):a=this;a=(a.getDay()+6)%7;b.setDate(b.getDate()-a+3);a=b.valueOf();b.setMonth(0,1);4!==b.getDay()&&b.setMonth(0,1+(4-b.getDay()+7)%7);return 1+Math.ceil((a-b)/6048E5)};f.getISOWeek=function(){return d(this.getWeek(!0))};f.setWeek=
|
||||||
|
function(a){return 0===a-this.getWeek()?1!==this.getDay()?this.moveToDayOfWeek(1,1<this.getDay()?-1:1):this:this.moveToDayOfWeek(1,1<this.getDay()?-1:1).addWeeks(a-this.getWeek())};f.setQuarter=function(a){a=Math.abs(3*(a-1)+1);return this.setMonth(a,1)};f.getQuarter=function(){return Date.getQuarter(this)};f.getDaysLeftInQuarter=function(){return Date.getDaysLeftInQuarter(this)};f.moveToNthOccurrence=function(a,b){if("Weekday"===a){if(0<b)this.moveToFirstDayOfMonth(),this.is().weekday()&&--b;else if(0>
|
||||||
|
b)this.moveToLastDayOfMonth(),this.is().weekday()&&(b+=1);else return this;return this.addWeekdays(b)}var e=0;if(0<b)e=b-1;else if(-1===b)return this.moveToLastDayOfMonth(),this.getDay()!==a&&this.moveToDayOfWeek(a,-1),this;return this.moveToFirstDayOfMonth().addDays(-1).moveToDayOfWeek(a,1).addWeeks(e)};var a=function(a,b,e){return function(g,c){var d=(g-this[a]()+e*(c||1))%e;return this[b](0===d?d+e*(c||1):d)}};f.moveToDayOfWeek=a("getDay","addDays",7);f.moveToMonth=a("getMonth","addMonths",12);
|
||||||
|
f.getOrdinate=function(){var a=this.getDate();return b(a)};f.getOrdinalNumber=function(){return Math.ceil((this.clone().clearTime()-new Date(this.getFullYear(),0,1))/864E5)+1};f.getTimezone=function(){return h.getTimezoneAbbreviation(this.getUTCOffset(),this.isDaylightSavingTime())};f.setTimezoneOffset=function(a){var b=this.getTimezoneOffset();return(a=-6*Number(a)/10)||0===a?this.addMinutes(a-b):this};f.setTimezone=function(a){return this.setTimezoneOffset(h.getTimezoneOffset(a))};f.hasDaylightSavingTime=
|
||||||
|
function(){return Date.today().set({month:0,day:1}).getTimezoneOffset()!==Date.today().set({month:6,day:1}).getTimezoneOffset()};f.isDaylightSavingTime=function(){return Date.today().set({month:0,day:1}).getTimezoneOffset()!==this.getTimezoneOffset()};f.getUTCOffset=function(a){a=-10*(a||this.getTimezoneOffset())/6;if(0>a)return a=(a-1E4).toString(),a.charAt(0)+a.substr(2);a=(a+1E4).toString();return"+"+a.substr(1)};f.getElapsed=function(a){return(a||new Date)-this};f.set=function(a){a=c.call(this,
|
||||||
|
a);for(var b in a)if(Object.prototype.hasOwnProperty.call(a,b)){var e=b.charAt(0).toUpperCase()+b.slice(1),g,d;"week"!==b&&"month"!==b&&"timezone"!==b&&"timezoneOffset"!==b&&(e+="s");g="add"+e;d="get"+e;"month"===b?g+="s":"year"===b&&(d="getFullYear");if("day"!==b&&"timezone"!==b&&"timezoneOffset"!==b&&"week"!==b&&"hour"!==b)this[g](a[b]-this[d]());else if("timezone"===b||"timezoneOffset"===b||"week"===b||"hour"===b)this["set"+e](a[b])}a.day&&this.addDays(a.day-this.getDate());return this};f.moveToFirstDayOfMonth=
|
||||||
|
function(){return this.set({day:1})};f.moveToLastDayOfMonth=function(){return this.set({day:h.getDaysInMonth(this.getFullYear(),this.getMonth())})};var b=function(a){switch(1*a){case 1:case 21:case 31:return"st";case 2:case 22:return"nd";case 3:case 23:return"rd";default:return"th"}},e=function(a){var b=Date.CultureInfo.formatPatterns;switch(a){case "d":return this.toString(b.shortDate);case "D":return this.toString(b.longDate);case "F":return this.toString(b.fullDateTime);case "m":return this.toString(b.monthDay);
|
||||||
|
case "r":case "R":return a=this.clone().addMinutes(this.getTimezoneOffset()),a.toString(b.rfc1123)+" GMT";case "s":return this.toString(b.sortableDateTime);case "t":return this.toString(b.shortTime);case "T":return this.toString(b.longTime);case "u":return a=this.clone().addMinutes(this.getTimezoneOffset()),a.toString(b.universalSortableDateTime);case "y":return this.toString(b.yearMonth);default:return!1}},g=function(a){return function(e){if("\\"===e.charAt(0))return e.replace("\\","");switch(e){case "hh":return d(13>
|
||||||
|
a.getHours()?0===a.getHours()?12:a.getHours():a.getHours()-12);case "h":return 13>a.getHours()?0===a.getHours()?12:a.getHours():a.getHours()-12;case "HH":return d(a.getHours());case "H":return a.getHours();case "mm":return d(a.getMinutes());case "m":return a.getMinutes();case "ss":return d(a.getSeconds());case "s":return a.getSeconds();case "yyyy":return d(a.getFullYear(),4);case "yy":return d(a.getFullYear());case "y":return a.getFullYear();case "E":case "dddd":return Date.CultureInfo.dayNames[a.getDay()];
|
||||||
|
case "ddd":return Date.CultureInfo.abbreviatedDayNames[a.getDay()];case "dd":return d(a.getDate());case "d":return a.getDate();case "MMMM":return Date.CultureInfo.monthNames[a.getMonth()];case "MMM":return Date.CultureInfo.abbreviatedMonthNames[a.getMonth()];case "MM":return d(a.getMonth()+1);case "M":return a.getMonth()+1;case "t":return 12>a.getHours()?Date.CultureInfo.amDesignator.substring(0,1):Date.CultureInfo.pmDesignator.substring(0,1);case "tt":return 12>a.getHours()?Date.CultureInfo.amDesignator:
|
||||||
|
Date.CultureInfo.pmDesignator;case "S":return b(a.getDate());case "W":return a.getWeek();case "WW":return a.getISOWeek();case "Q":return"Q"+a.getQuarter();case "q":return String(a.getQuarter());case "z":return a.getTimezone();case "Z":case "X":return Date.getTimezoneOffset(a.getTimezone());case "ZZ":return-60*a.getTimezoneOffset();case "u":return a.getDay();case "L":return h.isLeapYear(a.getFullYear())?1:0;case "B":return"@"+(a.getUTCSeconds()+60*a.getUTCMinutes()+3600*(a.getUTCHours()+1))/86.4;default:return e}}};
|
||||||
|
f.toString=function(a,b){if(!b&&a&&1===a.length&&(output=e.call(this,a)))return output;var c=g(this);return a?a.replace(/((\\)?(dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|S|q|Q|WW?W?W?)(?![^\[]*\]))/g,c).replace(/\[|\]/g,""):this._toString()}})();
|
||||||
|
(function(){var h=Date,f=h.prototype,d=Number.prototype;f._orient=1;f._nth=null;f._is=!1;f._same=!1;f._isSecond=!1;d._dateElement="days";f.next=function(){this._move=!0;this._orient=1;return this};h.next=function(){return h.today().next()};f.last=f.prev=f.previous=function(){this._move=!0;this._orient=-1;return this};h.last=h.prev=h.previous=function(){return h.today().last()};f.is=function(){this._is=!0;return this};f.same=function(){this._same=!0;this._isSecond=!1;return this};f.today=function(){return this.same().day()};
|
||||||
|
f.weekday=function(){return this._nth?m("Weekday").call(this):this._move?this.addWeekdays(this._orient):this._is?(this._is=!1,!this.is().sat()&&!this.is().sun()):!1};f.weekend=function(){return this._is?(this._is=!1,this.is().sat()||this.is().sun()):!1};f.at=function(a){return"string"===typeof a?h.parse(this.toString("d")+" "+a):this.set(a)};d.fromNow=d.after=function(a){var b={};b[this._dateElement]=this;return(a?a.clone():new Date).add(b)};d.ago=d.before=function(a){var b={};b["s"!==this._dateElement[this._dateElement.length-
|
||||||
|
1]?this._dateElement+"s":this._dateElement]=-1*this;return(a?a.clone():new Date).add(b)};var c="sunday monday tuesday wednesday thursday friday saturday".split(/\s/),a="january february march april may june july august september october november december".split(/\s/),b="Millisecond Second Minute Hour Day Week Month Year Quarter Weekday".split(/\s/),e="Milliseconds Seconds Minutes Hours Date Week Month FullYear Quarter".split(/\s/),g="final first second third fourth fifth".split(/\s/);f.toObject=function(){for(var a=
|
||||||
|
{},g=0;g<b.length;g++)this["get"+e[g]]&&(a[b[g].toLowerCase()]=this["get"+e[g]]());return a};h.fromObject=function(a){a.week=null;return Date.today().set(a)};var m=function(a){return function(){if(this._is)return this._is=!1,this.getDay()===a;this._move&&(this._move=null);if(null!==this._nth){this._isSecond&&this.addSeconds(-1*this._orient);this._isSecond=!1;var b=this._nth;this._nth=null;var e=this.clone().moveToLastDayOfMonth();this.moveToNthOccurrence(a,b);if(this>e)throw new RangeError(h.getDayName(a)+
|
||||||
|
" does not occur "+b+" times in the month of "+h.getMonthName(e.getMonth())+" "+e.getFullYear()+".");return this}return this.moveToDayOfWeek(a,this._orient)}},k=function(a,b,e){for(var g=0;g<a.length;g++)h[a[g].toUpperCase()]=h[a[g].toUpperCase().substring(0,3)]=g,h[a[g]]=h[a[g].substring(0,3)]=b(g),f[a[g]]=f[a[g].substring(0,3)]=e(g)};k(c,function(a){return function(){var b=h.today(),e=a-b.getDay();0===a&&1===Date.CultureInfo.firstDayOfWeek&&0!==b.getDay()&&(e+=7);return b.addDays(e)}},m);k(a,function(a){return function(){return h.today().set({month:a,
|
||||||
|
day:1})}},function(a){return function(){return this._is?(this._is=!1,this.getMonth()===a):this.moveToMonth(a,this._orient)}});for(var a=function(a){return function(e){if(this._isSecond)return this._isSecond=!1,this;if(this._same){this._same=this._is=!1;var g=this.toObject();e=(e||new Date).toObject();for(var c="",d=a.toLowerCase(),d="s"===d[d.length-1]?d.substring(0,d.length-1):d,f=b.length-1;-1<f;f--){c=b[f].toLowerCase();if(g[c]!==e[c])return!1;if(d===c)break}return!0}"s"!==a.substring(a.length-
|
||||||
|
1)&&(a+="s");this._move&&(this._move=null);return this["add"+a](this._orient)}},k=function(a){return function(){this._dateElement=a;return this}},n=0;n<b.length;n++)c=b[n].toLowerCase(),"weekday"!==c&&(f[c]=f[c+"s"]=a(b[n]),d[c]=d[c+"s"]=k(c+"s"));f._ss=a("Second");d=function(a){return function(b){if(this._same)return this._ss(b);if(b||0===b)return this.moveToNthOccurrence(b,a);this._nth=a;return 2!==a||void 0!==b&&null!==b?this:(this._isSecond=!0,this.addSeconds(this._orient))}};for(c=0;c<g.length;c++)f[g[c]]=
|
||||||
|
0===c?d(-1):d(c)})();
|
||||||
|
(function(){Date.Parsing={Exception:function(a){this.message="Parse error at '"+a.substring(0,10)+" ...'"}};var h=Date.Parsing,f=[0,31,59,90,120,151,181,212,243,273,304,334],d=[0,31,60,91,121,152,182,213,244,274,305,335];h.isLeapYear=function(a){return 0===a%4&&0!==a%100||0===a%400};var c={multiReplace:function(a,b){for(var e in b)if(Object.prototype.hasOwnProperty.call(b,e)){var g;"function"!==typeof b[e]&&(g=b[e]instanceof RegExp?b[e]:new RegExp(b[e],"g"));a=a.replace(g,e)}return a},getDayOfYearFromWeek:function(a){var b;
|
||||||
|
a.weekDay=a.weekDay||0===a.weekDay?a.weekDay:1;b=new Date(a.year,0,4);b=(0===b.getDay()?7:b.getDay())+3;a.dayOfYear=7*a.week+(0===a.weekDay?7:a.weekDay)-b;return a},getDayOfYear:function(a,b){a.dayOfYear||(a=c.getDayOfYearFromWeek(a));for(var e=0;e<=b.length;e++)if(a.dayOfYear<b[e]||e===b.length){a.day=a.day?a.day:a.dayOfYear-b[e-1];break}else a.month=e;return a},adjustForTimeZone:function(a,b){var e;"Z"===a.zone.toUpperCase()||0===a.zone_hours&&0===a.zone_minutes?e=-b.getTimezoneOffset():(e=60*a.zone_hours+
|
||||||
|
(a.zone_minutes||0),"+"===a.zone_sign&&(e*=-1),e-=b.getTimezoneOffset());b.setMinutes(b.getMinutes()+e);return b},setDefaults:function(a){a.year=a.year||Date.today().getFullYear();a.hours=a.hours||0;a.minutes=a.minutes||0;a.seconds=a.seconds||0;a.milliseconds=a.milliseconds||0;if(a.month||!a.week&&!a.dayOfYear)a.month=a.month||0,a.day=a.day||1;return a},dataNum:function(a,b,e,g){var c=1*a;return b?g?a?1*b(a):a:a?b(c):a:e?a&&"undefined"!==typeof a?c:a:a?c:a},timeDataProcess:function(a){var b={},e;
|
||||||
|
for(e in a.data)a.data.hasOwnProperty(e)&&(b[e]=a.ignore[e]?a.data[e]:c.dataNum(a.data[e],a.mods[e],a.explict[e],a.postProcess[e]));a.data.secmins&&(a.data.secmins=60*a.data.secmins.replace(",","."),b.minutes?b.seconds||(b.seconds=a.data.secmins):b.minutes=a.data.secmins,delete a.secmins);return b},buildTimeObjectFromData:function(a){return c.timeDataProcess({data:{year:a[1],month:a[5],day:a[7],week:a[8],dayOfYear:a[10],hours:a[15],zone_hours:a[23],zone_minutes:a[24],zone:a[21],zone_sign:a[22],weekDay:a[9],
|
||||||
|
minutes:a[16],seconds:a[19],milliseconds:a[20],secmins:a[18]},mods:{month:function(a){return a-1},weekDay:function(a){a=Math.abs(a);return 7===a?0:a},minutes:function(a){return a.replace(":","")},seconds:function(a){return Math.floor(1*a.replace(":","").replace(",","."))},milliseconds:function(a){return 1E3*a.replace(",",".")}},postProcess:{minutes:!0,seconds:!0,milliseconds:!0},explict:{zone_hours:!0,zone_minutes:!0},ignore:{zone:!0,zone_sign:!0,secmins:!0}})},addToHash:function(a,b,e){for(var g=
|
||||||
|
b.length,c=0;c<g;c++)a[b[c]]=e[c];return a},combineRegex:function(a,b){return new RegExp("(("+a.source+")\\s("+b.source+"))")},getDateNthString:function(a,b,e){if(a)return Date.today().addDays(e).toString("d");if(b)return Date.today().last()[e]().toString("d")},buildRegexData:function(a){for(var b=[],e=a.length,g=0;g<e;g++)"[object Array]"===Object.prototype.toString.call(a[g])?b.push(this.combineRegex(a[g][0],a[g][1])):b.push(a[g]);return b}};h.processTimeObject=function(a){var b;c.setDefaults(a);
|
||||||
|
b=h.isLeapYear(a.year)?d:f;a.month||!a.week&&!a.dayOfYear?a.dayOfYear=b[a.month]+a.day:c.getDayOfYear(a,b);b=new Date(a.year,a.month,a.day,a.hours,a.minutes,a.seconds,a.milliseconds);a.zone&&c.adjustForTimeZone(a,b);return b};h.ISO={regex:/^([\+-]?\d{4}(?!\d{2}\b))((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?|W([0-4]\d|5[0-3])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[1-6])))([T\s]((([01]\d|2[0-4])((:?)[0-5]\d)?|24\:?00)([\.,]\d+(?!:))?)?(\17[0-5]\d([\.,]\d+)?)?\s?([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$/,
|
||||||
|
parse:function(a){a=a.match(this.regex);if(!a||!a.length)return null;a=c.buildTimeObjectFromData(a);return a.year&&(a.year||a.month||a.day||a.week||a.dayOfYear)?h.processTimeObject(a):null}};h.Numeric={isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},regex:/\b([0-1]?[0-9])([0-3]?[0-9])([0-2]?[0-9]?[0-9][0-9])\b/i,parse:function(a){var b,e={},g=Date.CultureInfo.dateElementOrder.split("");if(!this.isNumeric(a)||"+"===a[0]&&"-"===a[0])return null;if(5>a.length&&0>a.indexOf(".")&&0>a.indexOf("/"))return e.year=
|
||||||
|
a,h.processTimeObject(e);a=a.match(this.regex);if(!a||!a.length)return null;for(b=0;b<g.length;b++)switch(g[b]){case "d":e.day=a[b+1];break;case "m":e.month=a[b+1]-1;break;case "y":e.year=a[b+1]}return h.processTimeObject(e)}};h.Normalizer={regexData:function(){var a=Date.CultureInfo.regexPatterns;return c.buildRegexData([a.tomorrow,a.yesterday,[a.past,a.mon],[a.past,a.tue],[a.past,a.wed],[a.past,a.thu],[a.past,a.fri],[a.past,a.sat],[a.past,a.sun]])},basicReplaceHash:function(){var a=Date.CultureInfo.regexPatterns;
|
||||||
|
return{January:a.jan.source,February:a.feb,March:a.mar,April:a.apr,May:a.may,June:a.jun,July:a.jul,August:a.aug,September:a.sep,October:a.oct,November:a.nov,December:a.dec,"":/\bat\b/gi," ":/\s{2,}/,am:a.inTheMorning,"9am":a.thisMorning,pm:a.inTheEvening,"7pm":a.thisEvening}},keys:function(){return[c.getDateNthString(!0,!1,1),c.getDateNthString(!0,!1,-1),c.getDateNthString(!1,!0,"monday"),c.getDateNthString(!1,!0,"tuesday"),c.getDateNthString(!1,!0,"wednesday"),c.getDateNthString(!1,!0,"thursday"),
|
||||||
|
c.getDateNthString(!1,!0,"friday"),c.getDateNthString(!1,!0,"saturday"),c.getDateNthString(!1,!0,"sunday")]},buildRegexFunctions:function(){var a=Date.CultureInfo.regexPatterns,b=Date.i18n.__,b=new RegExp("(\\b\\d\\d?("+b("AM")+"|"+b("PM")+")? )("+a.tomorrow.source.slice(1)+")","i");this.replaceFuncs=[[new RegExp(a.today.source+"(?!\\s*([+-]))\\b"),function(a){return 1<a.length?Date.today().toString("d"):a}],[b,function(a,b){return Date.today().addDays(1).toString("d")+" "+b}],[a.amThisMorning,function(a,
|
||||||
|
b){return b}],[a.pmThisEvening,function(a,b){return b}]]},buildReplaceData:function(){this.buildRegexFunctions();this.replaceHash=c.addToHash(this.basicReplaceHash(),this.keys(),this.regexData())},stringReplaceFuncs:function(a){for(var b=0;b<this.replaceFuncs.length;b++)a=a.replace(this.replaceFuncs[b][0],this.replaceFuncs[b][1]);return a},parse:function(a){a=this.stringReplaceFuncs(a);a=c.multiReplace(a,this.replaceHash);try{var b=a.split(/([\s\-\.\,\/\x27]+)/);3===b.length&&h.Numeric.isNumeric(b[0])&&
|
||||||
|
h.Numeric.isNumeric(b[2])&&4<=b[2].length&&"d"===Date.CultureInfo.dateElementOrder[0]&&(a="1/"+b[0]+"/"+b[2])}catch(e){}return a}};h.Normalizer.buildReplaceData()})();
|
||||||
|
(function(){for(var h=Date.Parsing,f=h.Operators={rtoken:function(a){return function(e){var g=e.match(a);if(g)return[g[0],e.substring(g[0].length)];throw new h.Exception(e);}},token:function(){return function(a){return f.rtoken(new RegExp("^\\s*"+a+"\\s*"))(a)}},stoken:function(a){return f.rtoken(new RegExp("^"+a))},until:function(a){return function(e){for(var g=[],c=null;e.length;){try{c=a.call(this,e)}catch(d){g.push(c[0]);e=c[1];continue}break}return[g,e]}},many:function(a){return function(e){for(var g=
|
||||||
|
[],c=null;e.length;){try{c=a.call(this,e)}catch(d){break}g.push(c[0]);e=c[1]}return[g,e]}},optional:function(a){return function(e){var g=null;try{g=a.call(this,e)}catch(c){return[null,e]}return[g[0],g[1]]}},not:function(a){return function(e){try{a.call(this,e)}catch(g){return[null,e]}throw new h.Exception(e);}},ignore:function(a){return a?function(e){var g=null,g=a.call(this,e);return[null,g[1]]}:null},product:function(){for(var a=arguments[0],e=Array.prototype.slice.call(arguments,1),g=[],c=0;c<
|
||||||
|
a.length;c++)g.push(f.each(a[c],e));return g},cache:function(a){var e={},g=0,c=[],d=Date.Config.CACHE_MAX||1E5,f=null;return function(l){if(g===d)for(var p=0;10>p;p++){var q=c.shift();q&&(delete e[q],g--)}try{f=e[l]=e[l]||a.call(this,l)}catch(s){f=e[l]=s}g++;c.push(l);if(f instanceof h.Exception)throw f;return f}},any:function(){var a=arguments;return function(e){for(var g=null,c=0;c<a.length;c++)if(null!=a[c]){try{g=a[c].call(this,e)}catch(d){g=null}if(g)return g}throw new h.Exception(e);}},each:function(){var a=
|
||||||
|
arguments;return function(e){for(var c=[],d=null,f=0;f<a.length;f++)if(null!=a[f]){try{d=a[f].call(this,e)}catch(n){throw new h.Exception(e);}c.push(d[0]);e=d[1]}return[c,e]}},all:function(){var a=a;return a.each(a.optional(arguments))},sequence:function(a,e,c){e=e||f.rtoken(/^\s*/);c=c||null;return 1===a.length?a[0]:function(d){for(var f=null,n=null,l=[],p=0;p<a.length;p++){try{f=a[p].call(this,d)}catch(q){break}l.push(f[0]);try{n=e.call(this,f[1])}catch(s){n=null;break}d=n[1]}if(!f)throw new h.Exception(d);
|
||||||
|
if(n)throw new h.Exception(n[1]);if(c)try{f=c.call(this,f[1])}catch(u){throw new h.Exception(f[1]);}return[l,f?f[1]:d]}},between:function(a,e,c){c=c||a;var d=f.each(f.ignore(a),e,f.ignore(c));return function(a){a=d.call(this,a);return[[a[0][0],r[0][2]],a[1]]}},list:function(a,e,c){e=e||f.rtoken(/^\s*/);c=c||null;return a instanceof Array?f.each(f.product(a.slice(0,-1),f.ignore(e)),a.slice(-1),f.ignore(c)):f.each(f.many(f.each(a,f.ignore(e))),px,f.ignore(c))},set:function(a,e,c){e=e||f.rtoken(/^\s*/);
|
||||||
|
c=c||null;return function(d){for(var k=null,n=k=null,l=null,p=[[],d],q=!1,s=0;s<a.length;s++){k=n=null;q=1===a.length;try{k=a[s].call(this,d)}catch(u){continue}l=[[k[0]],k[1]];if(0<k[1].length&&!q)try{n=e.call(this,k[1])}catch(v){q=!0}else q=!0;q||0!==n[1].length||(q=!0);if(!q){k=[];for(q=0;q<a.length;q++)s!==q&&k.push(a[q]);k=f.set(k,e).call(this,n[1]);0<k[0].length&&(l[0]=l[0].concat(k[0]),l[1]=k[1])}l[1].length<p[1].length&&(p=l);if(0===p[1].length)break}if(0===p[0].length)return p;if(c){try{n=
|
||||||
|
c.call(this,p[1])}catch(w){throw new h.Exception(p[1]);}p[1]=n[1]}return p}},forward:function(a,e){return function(c){return a[e].call(this,c)}},replace:function(a,e){return function(c){c=a.call(this,c);return[e,c[1]]}},process:function(a,e){return function(c){c=a.call(this,c);return[e.call(this,c[0]),c[1]]}},min:function(a,e){return function(c){var d=e.call(this,c);if(d[0].length<a)throw new h.Exception(c);return d}}},d=function(a){return function(){var e=null,c=[],d;1<arguments.length?e=Array.prototype.slice.call(arguments):
|
||||||
|
arguments[0]instanceof Array&&(e=arguments[0]);if(e){if(d=e.shift(),0<d.length)return e.unshift(d[void 0]),c.push(a.apply(null,e)),e.shift(),c}else return a.apply(null,arguments)}},c="optional not ignore cache".split(/\s/),a=0;a<c.length;a++)f[c[a]]=d(f[c[a]]);d=function(a){return function(){return arguments[0]instanceof Array?a.apply(null,arguments[0]):a.apply(null,arguments)}};c="each any all".split(/\s/);for(a=0;a<c.length;a++)f[c[a]]=d(f[c[a]])})();
|
||||||
|
(function(){var h=Date,f=function(c){for(var a=[],b=0;b<c.length;b++)c[b]instanceof Array?a=a.concat(f(c[b])):c[b]&&a.push(c[b]);return a},d=function(){if(this.meridian&&(this.hour||0===this.hour)){if("a"===this.meridian&&11<this.hour&&Date.Config.strict24hr)throw"Invalid hour and meridian combination";if("p"===this.meridian&&12>this.hour&&Date.Config.strict24hr)throw"Invalid hour and meridian combination";"p"===this.meridian&&12>this.hour?this.hour+=12:"a"===this.meridian&&12===this.hour&&(this.hour=
|
||||||
|
0)}};h.Translator={hour:function(c){return function(){this.hour=Number(c)}},minute:function(c){return function(){this.minute=Number(c)}},second:function(c){return function(){this.second=Number(c)}},secondAndMillisecond:function(c){return function(){var a=c.match(/^([0-5][0-9])\.([0-9]{1,3})/);this.second=Number(a[1]);this.millisecond=Number(a[2])}},meridian:function(c){return function(){this.meridian=c.slice(0,1).toLowerCase()}},timezone:function(c){return function(){var a=c.replace(/[^\d\+\-]/g,
|
||||||
|
"");a.length?this.timezoneOffset=Number(a):this.timezone=c.toLowerCase()}},day:function(c){var a=c[0];return function(){this.day=Number(a.match(/\d+/)[0]);if(1>this.day)throw"invalid day";}},month:function(c){return function(){this.month=3===c.length?"jan feb mar apr may jun jul aug sep oct nov dec".indexOf(c)/4:Number(c)-1;if(0>this.month)throw"invalid month";}},year:function(c){return function(){var a=Number(c);this.year=2<c.length?a:a+(a+2E3<Date.CultureInfo.twoDigitYearMax?2E3:1900)}},rday:function(c){return function(){switch(c){case "yesterday":this.days=
|
||||||
|
-1;break;case "tomorrow":this.days=1;break;case "today":this.days=0;break;case "now":this.days=0,this.now=!0}}},finishExact:function(c){c=c instanceof Array?c:[c];for(var a=0;a<c.length;a++)c[a]&&c[a].call(this);c=new Date;!this.hour&&!this.minute||this.month||this.year||this.day||(this.day=c.getDate());this.year||(this.year=c.getFullYear());this.month||0===this.month||(this.month=c.getMonth());this.day||(this.day=1);this.hour||(this.hour=0);this.minute||(this.minute=0);this.second||(this.second=
|
||||||
|
0);this.millisecond||(this.millisecond=0);d.call(this);if(this.day>h.getDaysInMonth(this.year,this.month))throw new RangeError(this.day+" is not a valid value for days.");c=new Date(this.year,this.month,this.day,this.hour,this.minute,this.second,this.millisecond);100>this.year&&c.setFullYear(this.year);this.timezone?c.set({timezone:this.timezone}):this.timezoneOffset&&c.set({timezoneOffset:this.timezoneOffset});return c},finish:function(c){var a,b,e;c=c instanceof Array?f(c):[c];if(0===c.length)return null;
|
||||||
|
for(a=0;a<c.length;a++)"function"===typeof c[a]&&c[a].call(this);if(!this.now||this.unit||this.operator)c=this.now||-1!=="hour minute second".indexOf(this.unit)?new Date:h.today();else return new Date;a=!!(this.days&&null!==this.days||this.orient||this.operator);b="past"===this.orient||"subtract"===this.operator?-1:1;this.month&&"week"===this.unit&&(this.value=this.month+1,delete this.month,delete this.day);!this.month&&0!==this.month||-1==="year day hour minute second".indexOf(this.unit)||(this.value||
|
||||||
|
(this.value=this.month+1),this.month=null,a=!0);a||!this.weekday||this.day||this.days||(e=Date[this.weekday](),this.day=e.getDate(),this.month||(this.month=e.getMonth()),this.year=e.getFullYear());if(a&&this.weekday&&"month"!==this.unit&&"week"!==this.unit){var g=c;e=b||1;this.unit="day";this.days=(g=h.getDayNumberFromName(this.weekday)-g.getDay())?(g+7*e)%7:7*e}!this.weekday||"week"===this.unit||this.day||this.days||(e=Date[this.weekday](),this.day=e.getDate(),e.getMonth()!==c.getMonth()&&(this.month=
|
||||||
|
e.getMonth()));this.month&&"day"===this.unit&&this.operator&&(this.value||(this.value=this.month+1),this.month=null);null!=this.value&&null!=this.month&&null!=this.year&&(this.day=1*this.value);this.month&&!this.day&&this.value&&(c.set({day:1*this.value}),a||(this.day=1*this.value));this.month||!this.value||"month"!==this.unit||this.now||(this.month=this.value,a=!0);a&&(this.month||0===this.month)&&"year"!==this.unit&&(e=b||1,this.unit="month",this.months=(g=this.month-c.getMonth())?(g+12*e)%12:12*
|
||||||
|
e,this.month=null);this.unit||(this.unit="day");if(!this.value&&this.operator&&null!==this.operator&&this[this.unit+"s"]&&null!==this[this.unit+"s"])this[this.unit+"s"]=this[this.unit+"s"]+("add"===this.operator?1:-1)+(this.value||0)*b;else if(null==this[this.unit+"s"]||null!=this.operator)this.value||(this.value=1),this[this.unit+"s"]=this.value*b;d.call(this);!this.month&&0!==this.month||this.day||(this.day=1);if(!this.orient&&!this.operator&&"week"===this.unit&&this.value&&!this.day&&!this.month)return Date.today().setWeek(this.value);
|
||||||
|
if("week"===this.unit&&this.weeks&&!this.day&&!this.month)return c=Date[void 0!==this.weekday?this.weekday:"today"]().addWeeks(this.weeks),this.now&&c.setTimeToNow(),c;a&&this.timezone&&this.day&&this.days&&(this.day=this.days);a?c.add(this):c.set(this);this.timezone&&(this.timezone=this.timezone.toUpperCase(),a=h.getTimezoneOffset(this.timezone),c.hasDaylightSavingTime()&&(b=h.getTimezoneAbbreviation(a,c.isDaylightSavingTime()),b!==this.timezone&&(c.isDaylightSavingTime()?c.addHours(-1):c.addHours(1))),
|
||||||
|
c.setTimezoneOffset(a));return c}}})();
|
||||||
|
(function(){var h=Date;h.Grammar={};var f=h.Parsing.Operators,d=h.Grammar,c=h.Translator,a;a=function(){return f.each(f.any.apply(null,arguments),f.not(d.ctoken2("timeContext")))};d.datePartDelimiter=f.rtoken(/^([\s\-\.\,\/\x27]+)/);d.timePartDelimiter=f.stoken(":");d.whiteSpace=f.rtoken(/^\s*/);d.generalDelimiter=f.rtoken(/^(([\s\,]|at|@|on)+)/);var b={};d.ctoken=function(a){var c=b[a];if(!c){for(var c=Date.CultureInfo.regexPatterns,e=a.split(/\s+/),d=[],g=0;g<e.length;g++)d.push(f.replace(f.rtoken(c[e[g]]),
|
||||||
|
e[g]));c=b[a]=f.any.apply(null,d)}return c};d.ctoken2=function(a){return f.rtoken(Date.CultureInfo.regexPatterns[a])};var e=function(a,b,c,e){d[a]=e?f.cache(f.process(f.each(f.rtoken(b),f.optional(d.ctoken2(e))),c)):f.cache(f.process(f.rtoken(b),c))},g=function(a,b){return f.cache(f.process(d.ctoken2(a),b))},m={},k=function(a){m[a]=m[a]||d.format(a)[0];return m[a]};d.allformats=function(a){var b=[];if(a instanceof Array)for(var c=0;c<a.length;c++)b.push(k(a[c]));else b.push(k(a));return b};d.formats=
|
||||||
|
function(a){if(a instanceof Array){for(var b=[],c=0;c<a.length;c++)b.push(k(a[c]));return f.any.apply(null,b)}return k(a)};var n={timeFormats:function(){var a,b="h hh H HH m mm s ss ss.s z zz".split(" "),h=[/^(0[0-9]|1[0-2]|[1-9])/,/^(0[0-9]|1[0-2])/,/^([0-1][0-9]|2[0-3]|[0-9])/,/^([0-1][0-9]|2[0-3])/,/^([0-5][0-9]|[0-9])/,/^[0-5][0-9]/,/^([0-5][0-9]|[0-9])/,/^[0-5][0-9]/,/^[0-5][0-9]\.[0-9]{1,3}/,/^((\+|\-)\s*\d\d\d\d)|((\+|\-)\d\d\:?\d\d)/,/^((\+|\-)\s*\d\d\d\d)|((\+|\-)\d\d\:?\d\d)/],m=[c.hour,
|
||||||
|
c.hour,c.hour,c.hour,c.minute,c.minute,c.second,c.second,c.secondAndMillisecond,c.timezone,c.timezone];for(a=0;a<b.length;a++)e(b[a],h[a],m[a]);d.hms=f.cache(f.sequence([d.H,d.m,d.s],d.timePartDelimiter));d.t=g("shortMeridian",c.meridian);d.tt=g("longMeridian",c.meridian);d.zzz=g("timezone",c.timezone);d.timeSuffix=f.each(f.ignore(d.whiteSpace),f.set([d.tt,d.zzz]));d.time=f.each(f.optional(f.ignore(f.stoken("T"))),d.hms,d.timeSuffix)},dateFormats:function(){var b=function(){return f.set(arguments,
|
||||||
|
d.datePartDelimiter)},g,h="d dd M MM y yy yyy yyyy".split(" "),m=[/^([0-2]\d|3[0-1]|\d)/,/^([0-2]\d|3[0-1])/,/^(1[0-2]|0\d|\d)/,/^(1[0-2]|0\d)/,/^(\d+)/,/^(\d\d)/,/^(\d\d?\d?\d?)/,/^(\d\d\d\d)/],n=[c.day,c.day,c.month,c.month,c.year,c.year,c.year,c.year],k=["ordinalSuffix","ordinalSuffix"];for(g=0;g<h.length;g++)e(h[g],m[g],n[g],k[g]);d.MMM=d.MMMM=f.cache(f.process(d.ctoken("jan feb mar apr may jun jul aug sep oct nov dec"),c.month));d.ddd=d.dddd=f.cache(f.process(d.ctoken("sun mon tue wed thu fri sat"),
|
||||||
|
function(a){return function(){this.weekday=a}}));d.day=a(d.d,d.dd);d.month=a(d.M,d.MMM);d.year=a(d.yyyy,d.yy);d.mdy=b(d.ddd,d.month,d.day,d.year);d.ymd=b(d.ddd,d.year,d.month,d.day);d.dmy=b(d.ddd,d.day,d.month,d.year);d.date=function(a){return(d[Date.CultureInfo.dateElementOrder]||d.mdy).call(this,a)}},relative:function(){d.orientation=f.process(d.ctoken("past future"),function(a){return function(){this.orient=a}});d.operator=f.process(d.ctoken("add subtract"),function(a){return function(){this.operator=
|
||||||
|
a}});d.rday=f.process(d.ctoken("yesterday tomorrow today now"),c.rday);d.unit=f.process(d.ctoken("second minute hour day week month year"),function(a){return function(){this.unit=a}})}};d.buildGrammarFormats=function(){b={};n.timeFormats();n.dateFormats();n.relative();d.value=f.process(f.rtoken(/^([-+]?\d+)?(st|nd|rd|th)?/),function(a){return function(){this.value=a.replace(/\D/g,"")}});d.expression=f.set([d.rday,d.operator,d.value,d.unit,d.orientation,d.ddd,d.MMM]);d.format=f.process(f.many(f.any(f.process(f.rtoken(/^(dd?d?d?(?!e)|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?)/),
|
||||||
|
function(a){if(d[a])return d[a];throw h.Parsing.Exception(a);}),f.process(f.rtoken(/^[^dMyhHmstz]+/),function(a){return f.ignore(f.stoken(a))}))),function(a){return f.process(f.each.apply(null,a),c.finishExact)});d._start=f.process(f.set([d.date,d.time,d.expression],d.generalDelimiter,d.whiteSpace),c.finish)};d.buildGrammarFormats();d._formats=d.formats('"yyyy-MM-ddTHH:mm:ssZ";yyyy-MM-ddTHH:mm:ss.sz;yyyy-MM-ddTHH:mm:ssZ;yyyy-MM-ddTHH:mm:ssz;yyyy-MM-ddTHH:mm:ss;yyyy-MM-ddTHH:mmZ;yyyy-MM-ddTHH:mmz;yyyy-MM-ddTHH:mm;ddd, MMM dd, yyyy H:mm:ss tt;ddd MMM d yyyy HH:mm:ss zzz;MMddyyyy;ddMMyyyy;Mddyyyy;ddMyyyy;Mdyyyy;dMyyyy;yyyy;Mdyy;dMyy;d'.split(";"));
|
||||||
|
d.start=function(a){try{var b=d._formats.call({},a);if(0===b[1].length)return b}catch(c){}return d._start.call({},a)}})();
|
||||||
|
(function(){var h=Date,f={removeOrds:function(d){return d=(ords=d.match(/\b(\d+)(?:st|nd|rd|th)\b/))&&2===ords.length?d.replace(ords[0],ords[1]):d},grammarParser:function(d){var c=null;try{c=h.Grammar.start.call({},d.replace(/^\s*(\S*(\s+\S+)*)\s*$/,"$1"))}catch(a){return null}return 0===c[1].length?c[0]:null},nativeFallback:function(d){var c;try{return(c=Date._parse(d))||0===c?new Date(c):null}catch(a){return null}}};h._parse||(h._parse=h.parse);h.parse=function(d){var c;if(!d)return null;if(d instanceof
|
||||||
|
Date)return d.clone();4<=d.length&&"0"!==d.charAt(0)&&"+"!==d.charAt(0)&&"-"!==d.charAt(0)&&(c=h.Parsing.ISO.parse(d)||h.Parsing.Numeric.parse(d));if(c instanceof Date&&!isNaN(c.getTime()))return c;d=h.Parsing.Normalizer.parse(f.removeOrds(d));c=f.grammarParser(d);return null!==c?c:f.nativeFallback(d)};Date.getParseFunction=function(d){var c=Date.Grammar.allformats(d);return function(a){for(var b=null,e=0;e<c.length;e++){try{b=c[e].call({},a)}catch(d){continue}if(0===b[1].length)return b[0]}return null}};
|
||||||
|
h.parseExact=function(d,c){return h.getParseFunction(c)(d)}})();
|
||||||
|
(function(){var h=Date,f=h.prototype,d=function(a,b){b||(b=2);return("000"+a).slice(-1*b)},c={d:"dd","%d":"dd",D:"ddd","%a":"ddd",j:"dddd",l:"dddd","%A":"dddd",S:"S",F:"MMMM","%B":"MMMM",m:"MM","%m":"MM",M:"MMM","%b":"MMM","%h":"MMM",n:"M",Y:"yyyy","%Y":"yyyy",y:"yy","%y":"yy",g:"h","%I":"h",G:"H",h:"hh",H:"HH","%H":"HH",i:"mm","%M":"mm",s:"ss","%S":"ss","%r":"hh:mm tt","%R":"H:mm","%T":"H:mm:ss","%X":"t","%x":"d","%e":"d","%D":"MM/dd/yy","%n":"\\n","%t":"\\t",e:"z",T:"z","%z":"z","%Z":"z",Z:"ZZ",
|
||||||
|
N:"u",w:"u","%w":"u",W:"W","%V":"W"},a={substitutes:function(a){return c[a]},interpreted:function(a,b){var c;switch(a){case "%u":return b.getDay()+1;case "z":return b.getOrdinalNumber();case "%j":return d(b.getOrdinalNumber(),3);case "%U":c=b.clone().set({month:0,day:1}).addDays(-1).moveToDayOfWeek(0);var f=b.clone().addDays(1).moveToDayOfWeek(0,-1);return f<c?"00":d((f.getOrdinalNumber()-c.getOrdinalNumber())/7+1);case "%W":return d(b.getWeek());case "t":return h.getDaysInMonth(b.getFullYear(),b.getMonth());
|
||||||
|
case "o":case "%G":return b.setWeek(b.getISOWeek()).toString("yyyy");case "%g":return b._format("%G").slice(-2);case "a":case "%p":return t("tt").toLowerCase();case "A":return t("tt").toUpperCase();case "u":return d(b.getMilliseconds(),3);case "I":return b.isDaylightSavingTime()?1:0;case "O":return b.getUTCOffset();case "P":return c=b.getUTCOffset(),c.substring(0,c.length-2)+":"+c.substring(c.length-2);case "B":return c=new Date,Math.floor((3600*c.getHours()+60*c.getMinutes()+c.getSeconds()+60*(c.getTimezoneOffset()+
|
||||||
|
60))/86.4);case "c":return b.toISOString().replace(/\"/g,"");case "U":return h.strtotime("now");case "%c":return t("d")+" "+t("t");case "%C":return Math.floor(b.getFullYear()/100+1)}},shouldOverrideDefaults:function(a){switch(a){case "%e":return!0;default:return!1}},parse:function(b,c){var d,f=c||new Date;return(d=a.substitutes(b))?d:(d=a.interpreted(b,f))?d:b}};h.normalizeFormat=function(b,c){return b.replace(/(%|\\)?.|%%/g,function(b){return a.parse(b,c)})};h.strftime=function(a,b){return Date.parse(b)._format(a)};
|
||||||
|
h.strtotime=function(a){a=h.parse(a);return Math.round(h.UTC(a.getUTCFullYear(),a.getUTCMonth(),a.getUTCDate(),a.getUTCHours(),a.getUTCMinutes(),a.getUTCSeconds(),a.getUTCMilliseconds())/1E3)};var b=function(b){return function(c){var d=!1;if("\\"===c.charAt(0)||"%%"===c.substring(0,2))return c.replace("\\","").replace("%%","%");d=a.shouldOverrideDefaults(c);if(c=h.normalizeFormat(c,b))return b.toString(c,d)}};f._format=function(a){var c=b(this);return a?a.replace(/(%|\\)?.|%%/g,c):this._toString()};
|
||||||
|
f.format||(f.format=f._format)})();
|
||||||
|
(function(){var h=function(c){return function(){return this[c]}},f=function(c){return function(a){this[c]=a;return this}},d=function(c,a,b,e,f){if(1===arguments.length&&"number"===typeof c){var h=0>c?-1:1,k=Math.abs(c);this.setDays(Math.floor(k/864E5)*h);k%=864E5;this.setHours(Math.floor(k/36E5)*h);k%=36E5;this.setMinutes(Math.floor(k/6E4)*h);k%=6E4;this.setSeconds(Math.floor(k/1E3)*h);this.setMilliseconds(k%1E3*h)}else this.set(c,a,b,e,f);this.getTotalMilliseconds=function(){return 864E5*this.getDays()+
|
||||||
|
36E5*this.getHours()+6E4*this.getMinutes()+1E3*this.getSeconds()};this.compareTo=function(a){var b=new Date(1970,1,1,this.getHours(),this.getMinutes(),this.getSeconds());a=null===a?new Date(1970,1,1,0,0,0):new Date(1970,1,1,a.getHours(),a.getMinutes(),a.getSeconds());return b<a?-1:b>a?1:0};this.equals=function(a){return 0===this.compareTo(a)};this.add=function(a){return null===a?this:this.addSeconds(a.getTotalMilliseconds()/1E3)};this.subtract=function(a){return null===a?this:this.addSeconds(-a.getTotalMilliseconds()/
|
||||||
|
1E3)};this.addDays=function(a){return new d(this.getTotalMilliseconds()+864E5*a)};this.addHours=function(a){return new d(this.getTotalMilliseconds()+36E5*a)};this.addMinutes=function(a){return new d(this.getTotalMilliseconds()+6E4*a)};this.addSeconds=function(a){return new d(this.getTotalMilliseconds()+1E3*a)};this.addMilliseconds=function(a){return new d(this.getTotalMilliseconds()+a)};this.get12HourHour=function(){return 12<this.getHours()?this.getHours()-12:0===this.getHours()?12:this.getHours()};
|
||||||
|
this.getDesignator=function(){return 12>this.getHours()?Date.CultureInfo.amDesignator:Date.CultureInfo.pmDesignator};this.toString=function(a){this._toString=function(){return null!==this.getDays()&&0<this.getDays()?this.getDays()+"."+this.getHours()+":"+this.p(this.getMinutes())+":"+this.p(this.getSeconds()):this.getHours()+":"+this.p(this.getMinutes())+":"+this.p(this.getSeconds())};this.p=function(a){return 2>a.toString().length?"0"+a:a};var b=this;return a?a.replace(/dd?|HH?|hh?|mm?|ss?|tt?/g,
|
||||||
|
function(a){switch(a){case "d":return b.getDays();case "dd":return b.p(b.getDays());case "H":return b.getHours();case "HH":return b.p(b.getHours());case "h":return b.get12HourHour();case "hh":return b.p(b.get12HourHour());case "m":return b.getMinutes();case "mm":return b.p(b.getMinutes());case "s":return b.getSeconds();case "ss":return b.p(b.getSeconds());case "t":return(12>b.getHours()?Date.CultureInfo.amDesignator:Date.CultureInfo.pmDesignator).substring(0,1);case "tt":return 12>b.getHours()?Date.CultureInfo.amDesignator:
|
||||||
|
Date.CultureInfo.pmDesignator}}):this._toString()};return this};(function(c,a){for(var b=0;b<a.length;b++){var e=a[b],d=e.slice(0,1).toUpperCase()+e.slice(1);c.prototype[e]=0;c.prototype["get"+d]=h(e);c.prototype["set"+d]=f(e)}})(d,"years months days hours minutes seconds milliseconds".split(" ").slice(2));d.prototype.set=function(c,a,b,e,d){this.setDays(c||this.getDays());this.setHours(a||this.getHours());this.setMinutes(b||this.getMinutes());this.setSeconds(e||this.getSeconds());this.setMilliseconds(d||
|
||||||
|
this.getMilliseconds())};Date.prototype.getTimeOfDay=function(){return new d(0,this.getHours(),this.getMinutes(),this.getSeconds(),this.getMilliseconds())};Date.TimeSpan=d;"undefined"!==typeof window&&(window.TimeSpan=d)})();
|
||||||
|
(function(){var h=function(a){return function(){return this[a]}},f=function(a){return function(b){this[a]=b;return this}},d=function(a,b,c,d){function f(){b.addMonths(-a);d.months++;12===d.months&&(d.years++,d.months=0)}if(1===a)for(;b>c;)f();else for(;b<c;)f();d.months--;d.months*=a;d.years*=a},c=function(a,b,c,f,h,k,n){if(7===arguments.length)this.set(a,b,c,f,h,k,n);else if(2===arguments.length&&arguments[0]instanceof Date&&arguments[1]instanceof Date){var l=arguments[0].clone(),p=arguments[1].clone(),
|
||||||
|
q=l>p?1:-1;this.dates={start:arguments[0].clone(),end:arguments[1].clone()};d(q,l,p,this);var s=!1===(l.isDaylightSavingTime()===p.isDaylightSavingTime());s&&1===q?l.addHours(-1):s&&l.addHours(1);l=p-l;0!==l&&(l=new TimeSpan(l),this.set(this.years,this.months,l.getDays(),l.getHours(),l.getMinutes(),l.getSeconds(),l.getMilliseconds()))}return this};(function(a,b){for(var c=0;c<b.length;c++){var d=b[c],m=d.slice(0,1).toUpperCase()+d.slice(1);a.prototype[d]=0;a.prototype["get"+m]=h(d);a.prototype["set"+
|
||||||
|
m]=f(d)}})(c,"years months days hours minutes seconds milliseconds".split(" "));c.prototype.set=function(a,b,c,d,f,h,n){this.setYears(a||this.getYears());this.setMonths(b||this.getMonths());this.setDays(c||this.getDays());this.setHours(d||this.getHours());this.setMinutes(f||this.getMinutes());this.setSeconds(h||this.getSeconds());this.setMilliseconds(n||this.getMilliseconds())};Date.TimePeriod=c;"undefined"!==typeof window&&(window.TimePeriod=c)})();
|
||||||
@@ -218,7 +218,7 @@
|
|||||||
$form.attr('action', this.href || routePath('preview'));
|
$form.attr('action', this.href || routePath('preview'));
|
||||||
$form.attr('target', '_blank');
|
$form.attr('target', '_blank');
|
||||||
var paths = window.location.pathname.split('/');
|
var paths = window.location.pathname.split('/');
|
||||||
$form.attr('page', paths[ paths.length - 1 ] || '')
|
$form.attr('page', decodeURIComponent(paths[ paths.length - 1 ]) || '')
|
||||||
$form.submit();
|
$form.submit();
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -96,6 +96,13 @@ function preparePage () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getLocalTime(datetime_string, format) {
|
||||||
|
if (format === undefined) { format = 'Y-m-d %H:%M:%S O'; }
|
||||||
|
|
||||||
|
var date = new Date(datetime_string);
|
||||||
|
return date.format(format);
|
||||||
|
}
|
||||||
|
|
||||||
function flashNotice(type, notice, button_label, button_function, button_type) {
|
function flashNotice(type, notice, button_label, button_function, button_type) {
|
||||||
// accepted types: info, success, warn, error
|
// accepted types: info, success, warn, error
|
||||||
nested_button_html = '';
|
nested_button_html = '';
|
||||||
@@ -155,6 +162,16 @@ $(document).ready(function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set time in local time
|
||||||
|
if (showLocalTime) {
|
||||||
|
$(function() {
|
||||||
|
$('time').each(function() {
|
||||||
|
var datetime = $(this).attr('datetime');
|
||||||
|
var format = $(this).data('format');
|
||||||
|
$(this).html(getLocalTime(datetime, format));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if ($('.minibutton-upload-page').length) {
|
if ($('.minibutton-upload-page').length) {
|
||||||
new ClipboardJS('#ClipboardJSlink');
|
new ClipboardJS('#ClipboardJSlink');
|
||||||
@@ -345,7 +362,7 @@ $(document).ready(function() {
|
|||||||
var formData = new FormData($('#gollum-editor-form').get(0));
|
var formData = new FormData($('#gollum-editor-form').get(0));
|
||||||
var paths = window.location.pathname.split('/');
|
var paths = window.location.pathname.split('/');
|
||||||
var sectionAnchor = window.location.hash.substr(1);
|
var sectionAnchor = window.location.hash.substr(1);
|
||||||
formData.append('page', paths[ paths.length - 1 ] || '')
|
formData.append('page', decodeURIComponent(paths[ paths.length - 1 ]) || '')
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: routePath('preview'),
|
url: routePath('preview'),
|
||||||
data: formData,
|
data: formData,
|
||||||
@@ -574,8 +591,9 @@ $(document).ready(function() {
|
|||||||
url: routePath('last_commit_info'),
|
url: routePath('last_commit_info'),
|
||||||
data: {path: $("#page-info-toggle").data('pagepath')},
|
data: {path: $("#page-info-toggle").data('pagepath')},
|
||||||
success: function ( data ) {
|
success: function ( data ) {
|
||||||
|
var date = showLocalTime ? getLocalTime(data.date) : data.date;
|
||||||
$("#last-edit").next(".dotted-spinner").toggleClass('hidden');
|
$("#last-edit").next(".dotted-spinner").toggleClass('hidden');
|
||||||
$("#last-edit-in-progress").html('Last edited by <b>' + data.author + '</b>, ' + data.date);
|
$("#last-edit-in-progress").html('Last edited by <b>' + data.author + '</b>, ' + date);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
$("#last-edit").next(".dotted-spinner").toggleClass('hidden')
|
$("#last-edit").next(".dotted-spinner").toggleClass('hidden')
|
||||||
|
|||||||
@@ -510,6 +510,14 @@ a {
|
|||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#head .header-title {
|
||||||
|
font-size: 1.5em;
|
||||||
|
|
||||||
|
@include largemobile-breakpoint {
|
||||||
|
font-size: 32px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Highlights */
|
/* Highlights */
|
||||||
|
|
||||||
.highlight {
|
.highlight {
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
<div id="wiki-wrapper" class="compare">
|
<div id="wiki-wrapper" class="compare">
|
||||||
<div id="head">
|
<div id="head">
|
||||||
<h1 class="py-4">{{message}}</h1>
|
<h1 class="header-title text-center text-md-left py-4">
|
||||||
{{author}} commited {{authored_date}}
|
{{message}}
|
||||||
|
</h1>
|
||||||
|
{{author}} commited <time datetime="{{datetime}}">{{authored_date}}</time>
|
||||||
<span class="px-2 float-right">commit <code>{{version}}</code></span>
|
<span class="px-2 float-right">commit <code>{{version}}</code></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,14 @@
|
|||||||
<div id="wiki-wrapper" class="compare">
|
<div id="wiki-wrapper" class="compare">
|
||||||
<div id="head">
|
<div id="head">
|
||||||
{{>navbar}}
|
{{>navbar}}
|
||||||
<h1 class="py-4"><span class="f1-light text-gray-light">Comparing versions of</span> {{name}}</h1>
|
|
||||||
</div>
|
<h1 class="header-title text-center text-md-left py-4">
|
||||||
|
<span class="f1-light text-gray-light">
|
||||||
|
Comparing versions of
|
||||||
|
</span>
|
||||||
|
{{name}}
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
{{#message}}
|
{{#message}}
|
||||||
<p>{{message}}</p>
|
<p>{{message}}</p>
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
<div id="wiki-wrapper" class="create">
|
<div id="wiki-wrapper" class="create">
|
||||||
<div id="head">
|
<div id="head">
|
||||||
{{>navbar}}
|
{{>navbar}}
|
||||||
<h1 class="py-4">Create New Page</h1>
|
|
||||||
</div>
|
<h1 class="header-title text-center text-md-left py-4">
|
||||||
|
Create New Page
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
<div id="wiki-content" class="create edit">
|
<div id="wiki-content" class="create edit">
|
||||||
<div class="tabnav">
|
<div class="tabnav">
|
||||||
<nav class="tabnav-tabs" aria-label="Toggle edit or preview mode">
|
<nav class="tabnav-tabs" aria-label="Toggle edit or preview mode">
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
<div id="wiki-wrapper" class="edit">
|
<div id="wiki-wrapper" class="edit">
|
||||||
<div id="head">
|
<div id="head">
|
||||||
{{>navbar}}
|
{{>navbar}}
|
||||||
<h1 class="py-4">Editing <strong>{{title}}</strong></h1>
|
|
||||||
</div>
|
<h1 class="header-title text-center text-md-left py-4">
|
||||||
|
Editing <strong>{{title}}</strong>
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
<div class="tabnav">
|
<div class="tabnav">
|
||||||
<nav class="tabnav-tabs">
|
<nav class="tabnav-tabs">
|
||||||
<a href="#" id="edit" class="tabnav-tab selected" aria-current="page">
|
<a href="#" id="edit" class="tabnav-tab selected" aria-current="page">
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
<div id="wiki-wrapper" class="history">
|
<div id="wiki-wrapper" class="history">
|
||||||
<div id="head">
|
<div id="head">
|
||||||
{{>navbar}}
|
{{>navbar}}
|
||||||
<h1 class="py-4"><span class="f1-light text-gray-light">History for</span> {{name}}</h1>
|
|
||||||
|
<h1 class="header-title text-center text-md-left py-4">
|
||||||
|
<span class="f1-light text-gray-light">
|
||||||
|
History for
|
||||||
|
</span>
|
||||||
|
{{name}}
|
||||||
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="page-history">
|
<div id="page-history">
|
||||||
|
|
||||||
{{>pagination}}
|
{{>pagination}}
|
||||||
@@ -16,7 +23,7 @@
|
|||||||
<li class="Box-row border-top Box-row--hover-gray d-flex flex-items-center">
|
<li class="Box-row border-top Box-row--hover-gray d-flex flex-items-center">
|
||||||
<span class="pr-2"><input class="checkbox" type="checkbox" name="versions[]" value="{{id}}"></span>
|
<span class="pr-2"><input class="checkbox" type="checkbox" name="versions[]" value="{{id}}"></span>
|
||||||
<span class="float-left col-2" id="user-icons">{{>author_template}}</span>
|
<span class="float-left col-2" id="user-icons">{{>author_template}}</span>
|
||||||
<span class="flex-auto col-1 text-gray-light">{{date}}</span>
|
<time class="flex-auto col-1 text-gray-light" datetime="{{datetime}}" data-format="{{date_format}}">{{date}}</time>
|
||||||
<span class="flex-auto col-5">{{message}}</span>
|
<span class="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>
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
<div id="wiki-wrapper" class="history">
|
<div id="wiki-wrapper" class="history">
|
||||||
<div id="head">
|
<div id="head">
|
||||||
{{>navbar}}
|
{{>navbar}}
|
||||||
<h1 class="py-4">{{title}}</h1>
|
|
||||||
</div>
|
<h1 class="header-title text-center text-md-left py-4">
|
||||||
|
{{title}}
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
{{>pagination}}
|
{{>pagination}}
|
||||||
|
|
||||||
@@ -12,7 +15,7 @@
|
|||||||
{{#versions}}
|
{{#versions}}
|
||||||
<li class="Box-row Box-row--hover-gray border-top d-flex flex-items-center">
|
<li class="Box-row Box-row--hover-gray border-top d-flex flex-items-center">
|
||||||
<span class="float-left col-2" id="user-icons">{{>author_template}}</span>
|
<span class="float-left col-2" id="user-icons">{{>author_template}}</span>
|
||||||
<span class="flex-auto col-1 text-gray-light">{{date}}</span>
|
<time class="flex-auto col-1 text-gray-light" datetime="{{datetime}}" data-format="{{date_format}}">{{date}}</time>
|
||||||
<span class="flex-auto col-5">{{message}}<br/>
|
<span class="flex-auto col-5">{{message}}<br/>
|
||||||
{{#files}}
|
{{#files}}
|
||||||
<span class="flex-auto col-2">{{#renamed}}{{renamed}} -> {{/renamed}}<a href="{{link}}">{{file}}</a></span><br/>
|
<span class="flex-auto col-2">{{#renamed}}{{renamed}} -> {{/renamed}}<a href="{{link}}">{{file}}</a></span><br/>
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
<script>
|
<script>
|
||||||
var criticMarkup = '{{critic_markup}}';
|
var criticMarkup = '{{critic_markup}}';
|
||||||
var baseUrl = '{{base_url}}';
|
var baseUrl = '{{base_url}}';
|
||||||
|
var showLocalTime = {{{show_local_time}}};
|
||||||
var uploadDest = 'uploads';
|
var uploadDest = 'uploads';
|
||||||
var perPageUploads = '{{per_page_uploads}}';
|
var perPageUploads = '{{per_page_uploads}}';
|
||||||
if (perPageUploads == 'true') {
|
if (perPageUploads == 'true') {
|
||||||
|
|||||||
@@ -1,4 +1,11 @@
|
|||||||
<nav class="TableObject actions pt-4 px-2 px-lg-0 overflow-x-scroll">
|
<nav class="TableObject
|
||||||
|
actions
|
||||||
|
border-bottom
|
||||||
|
border-md-0
|
||||||
|
p-2
|
||||||
|
pt-lg-4
|
||||||
|
px-lg-0
|
||||||
|
overflow-x-scroll">
|
||||||
<div class="TableObject-item hide-lg hide-xl">
|
<div class="TableObject-item hide-lg hide-xl">
|
||||||
{{>mobilenav}}
|
{{>mobilenav}}
|
||||||
</div>
|
</div>
|
||||||
@@ -45,7 +52,7 @@
|
|||||||
{{#history}}
|
{{#history}}
|
||||||
<a
|
<a
|
||||||
class="btn BtnGroup-item btn-sm hide-sm hide-md"
|
class="btn BtnGroup-item btn-sm hide-sm hide-md"
|
||||||
href="{{history_path}}/{{escaped_url_path}}"
|
href="{{history_path}}/{{escaped_url_path}}/{{version}}"
|
||||||
id="minibutton-history"
|
id="minibutton-history"
|
||||||
>
|
>
|
||||||
History
|
History
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
<div id="wiki-wrapper" class="results">
|
<div id="wiki-wrapper" class="results">
|
||||||
<div id="head" class="overview">
|
<div id="head" class="overview">
|
||||||
{{>navbar}}
|
{{>navbar}}
|
||||||
<h1 class="py-4">{{title}}</h1>
|
|
||||||
</div>
|
<h1 class="header-title text-center text-md-left py-4">
|
||||||
|
{{title}}
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
<div id="overview">
|
<div id="overview">
|
||||||
|
|
||||||
{{#has_results}}
|
{{#has_results}}
|
||||||
|
|||||||
@@ -1,7 +1,13 @@
|
|||||||
<div id="wiki-wrapper" class="results">
|
<div id="wiki-wrapper" class="results">
|
||||||
<div id="head">
|
<div id="head">
|
||||||
{{>navbar}}
|
{{>navbar}}
|
||||||
<h1 class="py-4"><span class="f1-light text-gray-light">Search results for</span> {{name}}</h1>
|
|
||||||
|
<h1 class="header-title text-center text-md-left py-4">
|
||||||
|
<span class="f1-light text-gray-light">
|
||||||
|
Search results for
|
||||||
|
</span>
|
||||||
|
{{name}}
|
||||||
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{#has_results}}
|
{{#has_results}}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
<div id="wiki-content" class="px-2 px-lg-0">
|
<div id="wiki-content" class="px-2 px-lg-0">
|
||||||
<h1 class="pt-4">{{page_header}}</h1>
|
<h1 class="header-title text-center text-md-left pt-4">
|
||||||
|
{{page_header}}
|
||||||
|
</h1>
|
||||||
<div class="breadcrumb">{{{breadcrumb}}}</div>
|
<div class="breadcrumb">{{{breadcrumb}}}</div>
|
||||||
|
|
||||||
<div class="{{#has_header}}has-header{{/has_header}}{{#has_footer}} has-footer{{/has_footer}}{{#has_sidebar}} has-sidebar has-{{bar_side}}bar{{/has_sidebar}}{{#has_toc}} has-toc{{/has_toc}}">
|
<div class="{{#has_header}}has-header{{/has_header}}{{#has_footer}} has-footer{{/has_footer}}{{#has_sidebar}} has-sidebar has-{{bar_side}}bar{{/has_sidebar}}{{#has_toc}} has-toc{{/has_toc}}">
|
||||||
@@ -54,7 +56,7 @@
|
|||||||
{{/preview}}
|
{{/preview}}
|
||||||
{{/historical}}
|
{{/historical}}
|
||||||
{{#historical}}
|
{{#historical}}
|
||||||
<p>This version of the page was edited by <b>{{author}}</b> at {{date}}. <a href="{{full_url_path}}">View the most recent version.</a></p>
|
<p>This version of the page was edited by <b>{{author}}</b> at <time datetime="{{datetime}}" data-format="{{date_format}}">{{date}}</time>. <a href="{{full_url_path}}">View the most recent version.</a></p>
|
||||||
{{/historical}}
|
{{/historical}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,10 @@ module Precious
|
|||||||
def authored_date
|
def authored_date
|
||||||
@commit.authored_date
|
@commit.authored_date
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def datetime
|
||||||
|
authored_date.utc.iso8601
|
||||||
|
end
|
||||||
|
|
||||||
def message
|
def message
|
||||||
@commit.message
|
@commit.message
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ module Precious
|
|||||||
module Views
|
module Views
|
||||||
class Create < Layout
|
class Create < Layout
|
||||||
include Editable
|
include Editable
|
||||||
|
include HasMath
|
||||||
|
|
||||||
attr_reader :page, :name
|
attr_reader :page, :name
|
||||||
|
|
||||||
@@ -41,9 +42,9 @@ module Precious
|
|||||||
def content
|
def content
|
||||||
@template_page
|
@template_page
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def find_format
|
def find_format
|
||||||
@found_format ||= (Gollum::Page.format_for("#{@name}#{@ext}") || default_markup)
|
@found_format ||= (Gollum::Page.format_for("#{@name}#{@ext}") || default_markup)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ module Precious
|
|||||||
class Edit < Layout
|
class Edit < Layout
|
||||||
include Editable
|
include Editable
|
||||||
include HasPage
|
include HasPage
|
||||||
|
include HasMath
|
||||||
|
|
||||||
attr_reader :page, :content
|
attr_reader :page, :content
|
||||||
|
|
||||||
@@ -18,10 +19,6 @@ module Precious
|
|||||||
def page_name
|
def page_name
|
||||||
@name
|
@name
|
||||||
end
|
end
|
||||||
|
|
||||||
def mathjax
|
|
||||||
@mathjax
|
|
||||||
end
|
|
||||||
|
|
||||||
def header
|
def header
|
||||||
if @header.nil?
|
if @header.nil?
|
||||||
@@ -67,7 +64,7 @@ module Precious
|
|||||||
def etag
|
def etag
|
||||||
@etag
|
@etag
|
||||||
end
|
end
|
||||||
|
|
||||||
def allow_uploads
|
def allow_uploads
|
||||||
@allow_uploads
|
@allow_uploads
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
module Precious
|
||||||
|
module HasMath
|
||||||
|
def mathjax
|
||||||
|
@mathjax
|
||||||
|
end
|
||||||
|
|
||||||
|
def mathjax_config
|
||||||
|
@mathjax_config
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -42,7 +42,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?
|
||||||
|
|||||||
+17
-12
@@ -1,6 +1,8 @@
|
|||||||
module Precious
|
module Precious
|
||||||
module Views
|
module Views
|
||||||
class History < Layout
|
class History < Layout
|
||||||
|
DATE_FORMAT = '%B %d, %Y'
|
||||||
|
|
||||||
include HasPage
|
include HasPage
|
||||||
include Pagination
|
include Pagination
|
||||||
include HasUserIcons
|
include HasUserIcons
|
||||||
@@ -18,18 +20,21 @@ module Precious
|
|||||||
@versions.map do |v|
|
@versions.map do |v|
|
||||||
i -= 1
|
i -= 1
|
||||||
filename = path_for_version(v.tracked_pathname)
|
filename = path_for_version(v.tracked_pathname)
|
||||||
{ :id => v.id,
|
authored_date = v.authored_date
|
||||||
:id7 => v.id[0..6],
|
{ :id => v.id,
|
||||||
:href => page_route("gollum/commit/#{v.id}"),
|
:id7 => v.id[0..6],
|
||||||
:href_page => page_route("#{filename}/#{v.id}"),
|
:href => page_route("gollum/commit/#{v.id}"),
|
||||||
:num => i,
|
:href_page => page_route("#{filename}/#{v.id}"),
|
||||||
:selected => @page.version.id == v.id,
|
:num => i,
|
||||||
:author => v.author.name.respond_to?(:force_encoding) ? v.author.name.force_encoding('UTF-8') : v.author.name,
|
:selected => @page.version.id == v.id,
|
||||||
:message => v.message.respond_to?(:force_encoding) ? v.message.force_encoding('UTF-8') : v.message,
|
:author => v.author.name.respond_to?(:force_encoding) ? v.author.name.force_encoding('UTF-8') : v.author.name,
|
||||||
:date => v.authored_date.strftime("%B %d, %Y"),
|
:message => v.message.respond_to?(:force_encoding) ? v.message.force_encoding('UTF-8') : v.message,
|
||||||
:user_icon => self.user_icon_code(v.author.email),
|
:date_full => authored_date,
|
||||||
:filename => filename,
|
:date => authored_date.strftime(DATE_FORMAT),
|
||||||
:date_full => v.authored_date,
|
:datetime => authored_date.utc.iso8601,
|
||||||
|
:date_format => DATE_FORMAT,
|
||||||
|
:user_icon => self.user_icon_code(v.author.email),
|
||||||
|
:filename => filename
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
module Precious
|
module Precious
|
||||||
module Views
|
module Views
|
||||||
class LatestChanges < Layout
|
class LatestChanges < Layout
|
||||||
|
DATE_FORMAT = '%B %d, %Y'
|
||||||
|
|
||||||
include Pagination
|
include Pagination
|
||||||
include HasUserIcons
|
include HasUserIcons
|
||||||
|
|
||||||
@@ -14,16 +16,19 @@ module Precious
|
|||||||
i = @versions.size + 1
|
i = @versions.size + 1
|
||||||
@versions.map do |v|
|
@versions.map do |v|
|
||||||
i -= 1
|
i -= 1
|
||||||
{ :id => v.id,
|
authored_date = v.authored_date
|
||||||
:id7 => v.id[0..6],
|
{ :id => v.id,
|
||||||
:href => page_route("gollum/commit/#{v.id}"),
|
:id7 => v.id[0..6],
|
||||||
:num => i,
|
:href => page_route("gollum/commit/#{v.id}"),
|
||||||
:author => v.author.name.respond_to?(:force_encoding) ? v.author.name.force_encoding('UTF-8') : v.author.name,
|
:num => i,
|
||||||
:message => v.message.respond_to?(:force_encoding) ? v.message.force_encoding('UTF-8') : v.message,
|
:author => v.author.name.respond_to?(:force_encoding) ? v.author.name.force_encoding('UTF-8') : v.author.name,
|
||||||
:date => v.authored_date.strftime("%B %d, %Y"),
|
:message => v.message.respond_to?(:force_encoding) ? v.message.force_encoding('UTF-8') : v.message,
|
||||||
:user_icon => self.user_icon_code(v.author.email),
|
:date_full => authored_date,
|
||||||
:date_full => v.authored_date,
|
:date => authored_date.strftime(DATE_FORMAT),
|
||||||
:files => v.stats.files.map { |f|
|
:datetime => authored_date.utc.iso8601,
|
||||||
|
:date_format => DATE_FORMAT,
|
||||||
|
:user_icon => self.user_icon_code(v.author.email),
|
||||||
|
:files => v.stats.files.map { |f|
|
||||||
new_path = extract_page_dir(f[:new_file])
|
new_path = extract_page_dir(f[:new_file])
|
||||||
{ :file => new_path,
|
{ :file => new_path,
|
||||||
:link => "#{page_route(new_path)}/#{v.id}",
|
:link => "#{page_route(new_path)}/#{v.id}",
|
||||||
|
|||||||
@@ -67,6 +67,10 @@ module Precious
|
|||||||
@per_page_uploads
|
@per_page_uploads
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def show_local_time
|
||||||
|
@show_local_time ? 'true' : 'false'
|
||||||
|
end
|
||||||
|
|
||||||
# Navigation bar
|
# Navigation bar
|
||||||
def search
|
def search
|
||||||
false
|
false
|
||||||
|
|||||||
+23
-18
@@ -2,8 +2,9 @@ module Precious
|
|||||||
module Views
|
module Views
|
||||||
class Page < Layout
|
class Page < Layout
|
||||||
include HasPage
|
include HasPage
|
||||||
|
include HasMath
|
||||||
|
|
||||||
attr_reader :content, :page, :header, :footer, :preview, :historical
|
attr_reader :content, :page, :header, :footer, :preview, :historical, :version
|
||||||
|
|
||||||
VALID_COUNTER_STYLES = ['decimal', 'decimal-leading-zero', 'arabic-indic', 'armenian', 'upper-armenian',
|
VALID_COUNTER_STYLES = ['decimal', 'decimal-leading-zero', 'arabic-indic', 'armenian', 'upper-armenian',
|
||||||
'lower-armenian', 'bengali', 'cambodian', 'khmer', 'cjk-decimal', 'devanagari', 'georgian', 'gujarati', 'gurmukhi',
|
'lower-armenian', 'bengali', 'cambodian', 'khmer', 'cjk-decimal', 'devanagari', 'georgian', 'gujarati', 'gurmukhi',
|
||||||
@@ -47,11 +48,23 @@ module Precious
|
|||||||
return DEFAULT_AUTHOR unless first
|
return DEFAULT_AUTHOR unless first
|
||||||
first.author.name.respond_to?(:force_encoding) ? first.author.name.force_encoding('UTF-8') : first.author.name
|
first.author.name.respond_to?(:force_encoding) ? first.author.name.force_encoding('UTF-8') : first.author.name
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def date_full
|
||||||
|
first = @version ? page.version : page.last_version
|
||||||
|
return Time.now unless first
|
||||||
|
first.authored_date
|
||||||
|
end
|
||||||
|
|
||||||
def date
|
def date
|
||||||
first = @version ? page.version : page.last_version
|
date_full.strftime(DATE_FORMAT)
|
||||||
return Time.now.strftime(DATE_FORMAT) unless first
|
end
|
||||||
first.authored_date.strftime(DATE_FORMAT)
|
|
||||||
|
def datetime
|
||||||
|
date_full.utc.iso8601
|
||||||
|
end
|
||||||
|
|
||||||
|
def date_format
|
||||||
|
DATE_FORMAT
|
||||||
end
|
end
|
||||||
|
|
||||||
def noindex
|
def noindex
|
||||||
@@ -61,11 +74,11 @@ module Precious
|
|||||||
def editable
|
def editable
|
||||||
@editable
|
@editable
|
||||||
end
|
end
|
||||||
|
|
||||||
def search
|
def search
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
def history
|
def history
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
@@ -73,11 +86,11 @@ module Precious
|
|||||||
def latest_changes
|
def latest_changes
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
def overview
|
def overview
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
def allow_editing
|
def allow_editing
|
||||||
@allow_editing
|
@allow_editing
|
||||||
end
|
end
|
||||||
@@ -157,14 +170,6 @@ module Precious
|
|||||||
@toc_content
|
@toc_content
|
||||||
end
|
end
|
||||||
|
|
||||||
def mathjax
|
|
||||||
@mathjax
|
|
||||||
end
|
|
||||||
|
|
||||||
def mathjax_config
|
|
||||||
@mathjax_config
|
|
||||||
end
|
|
||||||
|
|
||||||
def use_identicon
|
def use_identicon
|
||||||
@page.wiki.user_icons == 'identicon'
|
@page.wiki.user_icons == 'identicon'
|
||||||
end
|
end
|
||||||
@@ -182,7 +187,7 @@ module Precious
|
|||||||
# Returns Hash.
|
# Returns Hash.
|
||||||
def metadata
|
def metadata
|
||||||
@page.metadata
|
@page.metadata
|
||||||
end
|
end
|
||||||
|
|
||||||
# Access to embedded metadata.
|
# Access to embedded metadata.
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
module Precious
|
||||||
|
module Views
|
||||||
|
module TemplateCascade
|
||||||
|
def template_priority_path
|
||||||
|
@@template_priority_path
|
||||||
|
end
|
||||||
|
|
||||||
|
def template_priority_path=(path)
|
||||||
|
@@template_priority_path = File.expand_path(path)
|
||||||
|
@template = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def first_path_available(name)
|
||||||
|
default = File.join(template_path, "#{name}.#{template_extension}")
|
||||||
|
priority =
|
||||||
|
if template_priority_path
|
||||||
|
File.join(template_priority_path, "#{name}.#{template_extension}")
|
||||||
|
end
|
||||||
|
|
||||||
|
priority && File.exist?(priority) ? priority : default
|
||||||
|
end
|
||||||
|
|
||||||
|
# Method should track lib/mustache/settings.rb from Mustache project.
|
||||||
|
def template_file
|
||||||
|
@template_file || first_path_available(template_name)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Method should track lib/mustache.rb from Mustache project.
|
||||||
|
def partial(name)
|
||||||
|
path = first_path_available(name)
|
||||||
|
begin
|
||||||
|
File.read(path)
|
||||||
|
rescue
|
||||||
|
raise if raise_on_context_miss?
|
||||||
|
""
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
Binary file not shown.
@@ -3,3 +3,5 @@
|
|||||||
f403b791119f8232b7cb0ba455c624ac6435f433 ed6c9f63b98acf73c25b5ffbb38da557d3682023 bootstraponline <cafe@bootstraponline.com> 1336421777 -0600 commit: Add header.
|
f403b791119f8232b7cb0ba455c624ac6435f433 ed6c9f63b98acf73c25b5ffbb38da557d3682023 bootstraponline <cafe@bootstraponline.com> 1336421777 -0600 commit: Add header.
|
||||||
ed6c9f63b98acf73c25b5ffbb38da557d3682023 084a558a1fb3cded23129e2dfad3a17d07d73fd3 Daniel Kimsey <dekimsey@ufl.edu> 1354899095 -0500 push
|
ed6c9f63b98acf73c25b5ffbb38da557d3682023 084a558a1fb3cded23129e2dfad3a17d07d73fd3 Daniel Kimsey <dekimsey@ufl.edu> 1354899095 -0500 push
|
||||||
084a558a1fb3cded23129e2dfad3a17d07d73fd3 02796b1450691f90db5d6dc6a816a4980ce80d07 Dawa Ometto <dawa.ometto@phil.uu.nl> 1538516954 +0200 push
|
084a558a1fb3cded23129e2dfad3a17d07d73fd3 02796b1450691f90db5d6dc6a816a4980ce80d07 Dawa Ometto <dawa.ometto@phil.uu.nl> 1538516954 +0200 push
|
||||||
|
02796b1450691f90db5d6dc6a816a4980ce80d07 db8b297cf5a31b46ac24500edfdbd0d3d8eed4eb Nikita Ivanov <nikita.vyach.ivanov@gmail.com> 1640368693 +0500 commit: Created C (markdown)
|
||||||
|
db8b297cf5a31b46ac24500edfdbd0d3d8eed4eb c736e410f98df7a1173a540364dbb8a18274273e Nikita Ivanov <nikita.vyach.ivanov@gmail.com> 1640368721 +0500 commit: Deleted C.md
|
||||||
|
|||||||
@@ -3,3 +3,5 @@
|
|||||||
f403b791119f8232b7cb0ba455c624ac6435f433 ed6c9f63b98acf73c25b5ffbb38da557d3682023 bootstraponline <cafe@bootstraponline.com> 1336421777 -0600 commit: Add header.
|
f403b791119f8232b7cb0ba455c624ac6435f433 ed6c9f63b98acf73c25b5ffbb38da557d3682023 bootstraponline <cafe@bootstraponline.com> 1336421777 -0600 commit: Add header.
|
||||||
ed6c9f63b98acf73c25b5ffbb38da557d3682023 084a558a1fb3cded23129e2dfad3a17d07d73fd3 Daniel Kimsey <dekimsey@ufl.edu> 1354899095 -0500 push
|
ed6c9f63b98acf73c25b5ffbb38da557d3682023 084a558a1fb3cded23129e2dfad3a17d07d73fd3 Daniel Kimsey <dekimsey@ufl.edu> 1354899095 -0500 push
|
||||||
084a558a1fb3cded23129e2dfad3a17d07d73fd3 02796b1450691f90db5d6dc6a816a4980ce80d07 Dawa Ometto <dawa.ometto@phil.uu.nl> 1538516954 +0200 push
|
084a558a1fb3cded23129e2dfad3a17d07d73fd3 02796b1450691f90db5d6dc6a816a4980ce80d07 Dawa Ometto <dawa.ometto@phil.uu.nl> 1538516954 +0200 push
|
||||||
|
02796b1450691f90db5d6dc6a816a4980ce80d07 db8b297cf5a31b46ac24500edfdbd0d3d8eed4eb Nikita Ivanov <nikita.vyach.ivanov@gmail.com> 1640368693 +0500 commit: Created C (markdown)
|
||||||
|
db8b297cf5a31b46ac24500edfdbd0d3d8eed4eb c736e410f98df7a1173a540364dbb8a18274273e Nikita Ivanov <nikita.vyach.ivanov@gmail.com> 1640368721 +0500 commit: Deleted C.md
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,6 @@
|
|||||||
|
x¥ŽK
|
||||||
|
Â0@]÷³Ê¤ù4A7n¼Ã$3±AÓJ‰ooñ
|
||||||
|
.ß[<^œKÉ:‹»ºˆ€Öɸ€bY¥Á¡öI'Rh¢Ø8hSô¨4Só¢E¦
|
||||||
|
|è†>&KZã(vÆ"
|
||||||
|
'Œ¬Ù‹°‘ÐлŽó·üÈ•àºÒ4¯p˜~Ø®Šc›òt/”ŸmœË”3¨�ï;{ܲÍf·Ý*‡š‹<¥
|
||||||
|
ù-üš…Q×
|
||||||
Binary file not shown.
@@ -1 +1 @@
|
|||||||
02796b1450691f90db5d6dc6a816a4980ce80d07
|
c736e410f98df7a1173a540364dbb8a18274273e
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<nav>
|
||||||
|
<div style="background-color: red;">NAVBAR_OVERRIDE</div>
|
||||||
|
|
||||||
|
<p>Still include an original partial to ensure the fallback works even when nested from an overriden partial:</p>
|
||||||
|
<div>
|
||||||
|
{{>mobilenav}}
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
<div id="wiki-wrapper" class="page">
|
||||||
|
|
||||||
|
<p>Include an overridden partial:</p>
|
||||||
|
<div id="head">
|
||||||
|
{{#navbar?}}{{>navbar}}{{/navbar?}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="background-color: red;">PAGE_OVERRIDE</div>
|
||||||
|
|
||||||
|
{{>wiki_content}}
|
||||||
|
|
||||||
|
</div>
|
||||||
+33
-14
@@ -1,19 +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 'twitter_cldr'
|
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'))
|
||||||
@@ -63,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
|
|
||||||
# chris@ozmm.org
|
# http://gist.github.com/25455
|
||||||
# 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
|
||||||
@@ -86,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
|
||||||
|
|||||||
+54
-34
@@ -3,87 +3,107 @@ 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
|
||||||
Precious::App
|
Precious::App
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
+139
-72
@@ -14,7 +14,7 @@ context "Frontend" do
|
|||||||
teardown do
|
teardown do
|
||||||
FileUtils.rm_rf(@path)
|
FileUtils.rm_rf(@path)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "utf-8 kcode" do
|
test "utf-8 kcode" do
|
||||||
assert_equal 'μ†ℱ'.scan(/./), ["μ", "†", "ℱ"]
|
assert_equal 'μ†ℱ'.scan(/./), ["μ", "†", "ℱ"]
|
||||||
end
|
end
|
||||||
@@ -39,31 +39,29 @@ context "Frontend" do
|
|||||||
assert_match /<pre><code>one\ntwo\nthree\nfour\n<\/code><\/pre>\n/m, last_response.body
|
assert_match /<pre><code>one\ntwo\nthree\nfour\n<\/code><\/pre>\n/m, last_response.body
|
||||||
end
|
end
|
||||||
|
|
||||||
def nfd utf8
|
|
||||||
TwitterCldr::Normalization.normalize(utf8, using: :nfd)
|
|
||||||
end
|
|
||||||
|
|
||||||
test 'mathjax assets are served' do
|
test 'mathjax assets are served' do
|
||||||
get '/gollum/assets/mathjax/MathJax.js'
|
get '/gollum/assets/mathjax/MathJax.js'
|
||||||
assert last_response.ok?
|
assert last_response.ok?
|
||||||
end
|
end
|
||||||
|
|
||||||
test "UTF-8 headers href preserved" do
|
test "UTF-8 headers href preserved" do
|
||||||
page = 'utfh1'
|
page_content = <<~TEXT
|
||||||
text = nfd('한글')
|
## 한글
|
||||||
|
|
||||||
# don't use h1 or it will be promoted to replace file name
|
Test page "utfh1" content.
|
||||||
# which doesn't generate a normal header link
|
TEXT
|
||||||
@wiki.write_page(page, :markdown, '## ' + text,
|
|
||||||
{ :name => 'user1', :email => 'user1' });
|
|
||||||
|
|
||||||
get page
|
@wiki.write_page('utfh1',
|
||||||
expected = "<h2 class=\"editable\"><a class=\"anchor\" (href|id)=\"(#)?#{text}\" (href|id)=\"(#)?#{text}\"></a>#{text}</h2>"
|
:markdown,
|
||||||
actual = nfd(last_response.body)
|
page_content,
|
||||||
|
{name: 'user1', email: 'user1'})
|
||||||
|
|
||||||
assert_match /#{expected}/, actual
|
get 'utfh1'
|
||||||
|
expected = "<h2 class=\"editable\"><a class=\"anchor\" (href|id)=\"(#)?한글\" (href|id)=\"(#)?한글\"></a>한글</h2>"
|
||||||
|
|
||||||
|
assert_match /#{expected}/, last_response.body
|
||||||
end
|
end
|
||||||
|
|
||||||
test 'rss feed' do
|
test 'rss feed' do
|
||||||
channel_title = <<EOF
|
channel_title = <<EOF
|
||||||
<title>Gollum Wiki Latest Changes</title>
|
<title>Gollum Wiki Latest Changes</title>
|
||||||
@@ -106,24 +104,24 @@ 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
|
||||||
page = @wiki.page('A')
|
page = @wiki.page('A')
|
||||||
old_sha = page.sha
|
old_sha = page.sha
|
||||||
post "/gollum/edit/A", :content => 'abc', :page => 'A',
|
post "/gollum/edit/A", :content => 'abc', :page => 'A',
|
||||||
:format => page.format, :message => 'def', :etag => old_sha
|
:format => page.format, :message => 'def', :etag => old_sha
|
||||||
assert last_response.ok?
|
assert last_response.ok?
|
||||||
|
|
||||||
@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
|
||||||
assert_equal last_response.status, 412
|
assert_equal last_response.status, 412
|
||||||
end
|
end
|
||||||
|
|
||||||
test "edit page with empty message" do
|
test "edit page with empty message" do
|
||||||
@@ -136,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
|
||||||
@@ -167,13 +165,13 @@ 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+1, @wiki.repo.commits('master').size
|
assert_equal commits, @wiki.repo.commits('master').size
|
||||||
end
|
end
|
||||||
|
|
||||||
test "renames page" do
|
test "renames page" do
|
||||||
@@ -189,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
|
||||||
@@ -224,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!
|
||||||
@@ -236,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!
|
||||||
@@ -253,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
|
||||||
@@ -322,17 +320,17 @@ 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
|
||||||
Precious::App.set(:wiki_options, { :template_page => true })
|
Precious::App.set(:wiki_options, { :template_page => true })
|
||||||
page='_Template'
|
page='_Template'
|
||||||
post '/gollum/create', :content => 'fake template', :page => page,
|
post '/gollum/create', :content => 'fake template with some Utf-8: Ü', :page => page,
|
||||||
:path => '/', :format => 'markdown', :message => ''
|
:path => '/', :format => 'markdown', :message => ''
|
||||||
follow_redirect!
|
follow_redirect!
|
||||||
assert last_response.ok?
|
assert last_response.ok?
|
||||||
@wiki.clear_cache
|
@wiki.clear_cache
|
||||||
get "/gollum/create/TT"
|
get "/gollum/create/TT"
|
||||||
assert last_response.ok?
|
assert last_response.ok?
|
||||||
post '/gollum/delete/_Template'
|
post '/gollum/delete/_Template'
|
||||||
@@ -340,12 +338,51 @@ EOF
|
|||||||
end
|
end
|
||||||
|
|
||||||
test "create with template succeed if template doesn't exist" do
|
test "create with template succeed if template doesn't exist" do
|
||||||
Precious::App.set(:wiki_options, { :template_page => true })
|
Precious::App.set(:wiki_options, { :template_page => true })
|
||||||
get "/gollum/create/TT"
|
get "/gollum/create/TT"
|
||||||
assert last_response.ok?
|
assert last_response.ok?
|
||||||
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'
|
||||||
@@ -353,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
|
||||||
@@ -409,23 +446,31 @@ 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
|
||||||
|
|
||||||
test "upload a file with mode dir" do
|
test "upload a file with mode dir" 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
|
||||||
Precious::App.set(:wiki_options, {allow_uploads: true})
|
Precious::App.set(:wiki_options, {allow_uploads: true})
|
||||||
|
|
||||||
post "/gollum/upload_file", :file => Rack::Test::UploadedFile.new(::File.open(temp_upload_file))
|
post "/gollum/upload_file", :file => Rack::Test::UploadedFile.new(::File.open(temp_upload_file))
|
||||||
|
|
||||||
assert_equal 302, last_response.status # redirect is expected
|
assert_equal 302, last_response.status # redirect is expected
|
||||||
@wiki.clear_cache
|
@wiki.clear_cache
|
||||||
file = @wiki.file("uploads/#{::File.basename(temp_upload_file.path)}")
|
file = @wiki.file("uploads/#{::File.basename(temp_upload_file.path)}")
|
||||||
@@ -438,7 +483,7 @@ EOF
|
|||||||
temp_upload_file.close
|
temp_upload_file.close
|
||||||
Precious::App.set(:wiki_options, {allow_uploads: true, per_page_uploads: true})
|
Precious::App.set(:wiki_options, {allow_uploads: true, per_page_uploads: true})
|
||||||
post "/gollum/upload_file", {:file => Rack::Test::UploadedFile.new(::File.open(temp_upload_file))}, {'HTTP_REFERER' => 'http://localhost:4567/Home.md', 'HTTP_HOST' => 'localhost:4567'}
|
post "/gollum/upload_file", {:file => Rack::Test::UploadedFile.new(::File.open(temp_upload_file))}, {'HTTP_REFERER' => 'http://localhost:4567/Home.md', 'HTTP_HOST' => 'localhost:4567'}
|
||||||
|
|
||||||
assert_equal 302, last_response.status # redirect is expected
|
assert_equal 302, last_response.status # redirect is expected
|
||||||
@wiki.clear_cache
|
@wiki.clear_cache
|
||||||
# Find the file in a page-specific subdir (here: Home), based on referer
|
# Find the file in a page-specific subdir (here: Home), based on referer
|
||||||
@@ -446,7 +491,22 @@ EOF
|
|||||||
assert_equal 'abc', file.raw_data
|
assert_equal 'abc', file.raw_data
|
||||||
Precious::App.set(:wiki_options, {allow_uploads: false, per_page_uploads: false})
|
Precious::App.set(:wiki_options, {allow_uploads: false, per_page_uploads: false})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "upload a file with https referer" do
|
||||||
|
temp_upload_file = Tempfile.new(['https_upload', '.file']) << 'abc'
|
||||||
|
temp_upload_file.close
|
||||||
|
Precious::App.set(:wiki_options, {allow_uploads: true, per_page_uploads: true})
|
||||||
|
post "/gollum/upload_file", {:file => Rack::Test::UploadedFile.new(::File.open(temp_upload_file))}, {'HTTP_REFERER' => 'https://localhost:4567/Home.md', 'HTTP_HOST' => 'localhost:4567'}
|
||||||
|
|
||||||
|
assert_equal 302, last_response.status # redirect is expected
|
||||||
|
@wiki.clear_cache
|
||||||
|
# Find the file in a page-specific subdir (here: Home), based on referer
|
||||||
|
file = @wiki.file("uploads/Home/#{::File.basename(temp_upload_file.path)}")
|
||||||
|
assert_equal 'abc', file.raw_data
|
||||||
|
Precious::App.set(:wiki_options, {allow_uploads: false, per_page_uploads: false})
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
test "guard against uploading an existing file" do
|
test "guard against uploading an existing file" 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
|
||||||
@@ -458,7 +518,7 @@ EOF
|
|||||||
assert_equal 409, last_response.status
|
assert_equal 409, last_response.status
|
||||||
Precious::App.set(:wiki_options, {allow_uploads: false})
|
Precious::App.set(:wiki_options, {allow_uploads: false})
|
||||||
end
|
end
|
||||||
|
|
||||||
test "delete a page" do
|
test "delete a page" do
|
||||||
name = "deleteme"
|
name = "deleteme"
|
||||||
post "/gollum/create", :content => 'abc', :page => name,
|
post "/gollum/create", :content => 'abc', :page => name,
|
||||||
@@ -470,15 +530,15 @@ 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
|
||||||
post "/gollum/preview", :content => 'abc', :format => 'markdown', :page => 'Samewise Gamgee.mediawiki'
|
post "/gollum/preview", :content => 'abc', :format => 'markdown', :page => 'Samewise Gamgee.mediawiki'
|
||||||
assert last_response.ok?
|
assert last_response.ok?
|
||||||
assert last_response.body.include?('Samewise Gamgee</h1>')
|
assert last_response.body.include?('Samewise Gamgee')
|
||||||
end
|
end
|
||||||
|
|
||||||
test 'throws an error when comparing two identical revisions for a page' do
|
test 'throws an error when comparing two identical revisions for a page' do
|
||||||
get '/gollum/compare/A.md/fc66539528eb96f21b2bbdbf557788fe8a1196ac...fc66539528eb96f21b2bbdbf557788fe8a1196ac'
|
get '/gollum/compare/A.md/fc66539528eb96f21b2bbdbf557788fe8a1196ac...fc66539528eb96f21b2bbdbf557788fe8a1196ac'
|
||||||
assert last_response.ok?
|
assert last_response.ok?
|
||||||
@@ -494,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
|
||||||
@@ -508,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
|
||||||
|
|
||||||
@@ -522,7 +582,7 @@ EOF
|
|||||||
page2 = @wiki.page('A')
|
page2 = @wiki.page('A')
|
||||||
assert_equal page1.version.sha, page2.version.sha
|
assert_equal page1.version.sha, page2.version.sha
|
||||||
end
|
end
|
||||||
|
|
||||||
=begin
|
=begin
|
||||||
# redirects are now handled by class MapGollum in bin/gollum
|
# redirects are now handled by class MapGollum in bin/gollum
|
||||||
# they should be set in config.ru
|
# they should be set in config.ru
|
||||||
@@ -570,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
|
||||||
@@ -588,7 +648,7 @@ EOF
|
|||||||
|
|
||||||
test "don't allow changing custom js or css" do
|
test "don't allow changing custom js or css" do
|
||||||
Precious::App.set(:wiki_options, { :js => true, :css => true })
|
Precious::App.set(:wiki_options, { :js => true, :css => true })
|
||||||
|
|
||||||
['create', 'edit'].each do |route|
|
['create', 'edit'].each do |route|
|
||||||
['.css', '.js'].each do |ext|
|
['.css', '.js'].each do |ext|
|
||||||
get "/gollum/#{route}/custom#{ext}"
|
get "/gollum/#{route}/custom#{ext}"
|
||||||
@@ -621,7 +681,7 @@ EOF
|
|||||||
:page => 'Multibyte', :format => :markdown, :message => 'mesg'
|
:page => 'Multibyte', :format => :markdown, :message => 'mesg'
|
||||||
|
|
||||||
page = @wiki.page('Multibyte')
|
page = @wiki.page('Multibyte')
|
||||||
|
|
||||||
post "/gollum/edit/Multibyte",
|
post "/gollum/edit/Multibyte",
|
||||||
:content => 'りんご', :header => 'みかん', :footer => 'バナナ', :sidebar => 'スイカ',
|
:content => 'りんご', :header => 'みかん', :footer => 'バナナ', :sidebar => 'スイカ',
|
||||||
:page => 'Multibyte', :format => :markdown, :message => 'mesg', :etag => page.sha
|
:page => 'Multibyte', :format => :markdown, :message => 'mesg', :etag => page.sha
|
||||||
@@ -639,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"
|
||||||
|
|
||||||
@@ -655,6 +715,13 @@ EOF
|
|||||||
assert_equal last_response.status, 302
|
assert_equal last_response.status, 302
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "view deleted page in history" do
|
||||||
|
get 'C/db8b297cf5a31b46ac24500edfdbd0d3d8eed4eb'
|
||||||
|
|
||||||
|
assert last_response.ok?
|
||||||
|
assert_match /This page will be deleted in the next commit :\(/, last_response.body
|
||||||
|
end
|
||||||
|
|
||||||
def app
|
def app
|
||||||
Precious::App
|
Precious::App
|
||||||
end
|
end
|
||||||
@@ -804,17 +871,17 @@ context "Frontend with lotr" do
|
|||||||
assert last_response.ok?
|
assert last_response.ok?
|
||||||
assert_equal last_response.body.include?('delete-link'), false
|
assert_equal last_response.body.include?('delete-link'), false
|
||||||
assert_equal last_response.body.include?('page-info-toggle'), false
|
assert_equal last_response.body.include?('page-info-toggle'), false
|
||||||
assert last_response.body.include?('This version of the page was edited by <b>Tom Preston-Werner</b> at 2010-04-07')
|
assert_match %r{This version of the page was edited by <b>Tom Preston-Werner</b> at <time datetime="2010-04-07T19:49:43Z" data-format="%Y-%m-%d %H:%M:%S">\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}</time>.}, last_response.body
|
||||||
assert last_response.body.include?("<a href=\"/Bilbo-Baggins.md\">View the most recent version.</a></p>")
|
assert last_response.body.include?("<a href=\"/Bilbo-Baggins.md\">View the most recent version.</a></p>")
|
||||||
end
|
end
|
||||||
|
|
||||||
test "show revision of specific file" do
|
test "show revision of specific file" do
|
||||||
old_sha = "df26e61e707116f81ebc6b935ec6d1676b7e96c4"
|
old_sha = "df26e61e707116f81ebc6b935ec6d1676b7e96c4"
|
||||||
update_sha = "f803c64d11407b23797325e3843f3f378b78f611"
|
update_sha = "f803c64d11407b23797325e3843f3f378b78f611"
|
||||||
|
|
||||||
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?
|
||||||
@@ -859,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
|
||||||
@@ -900,7 +967,7 @@ end
|
|||||||
|
|
||||||
context "Frontend with empty repo" do
|
context "Frontend with empty repo" do
|
||||||
include Rack::Test::Methods
|
include Rack::Test::Methods
|
||||||
|
|
||||||
setup do
|
setup do
|
||||||
@path = cloned_testpath("examples/empty.git")
|
@path = cloned_testpath("examples/empty.git")
|
||||||
@wiki = Gollum::Wiki.new(@path)
|
@wiki = Gollum::Wiki.new(@path)
|
||||||
@@ -911,11 +978,11 @@ context "Frontend with empty repo" do
|
|||||||
teardown do
|
teardown do
|
||||||
FileUtils.rm_rf(@path)
|
FileUtils.rm_rf(@path)
|
||||||
end
|
end
|
||||||
|
|
||||||
def app
|
def app
|
||||||
Precious::App
|
Precious::App
|
||||||
end
|
end
|
||||||
|
|
||||||
test 'previews content on the first page of an empty wiki' do
|
test 'previews content on the first page of an empty wiki' do
|
||||||
post '/gollum/preview', :content => 'abc', :format => 'markdown'
|
post '/gollum/preview', :content => 'abc', :format => 'markdown'
|
||||||
assert last_response.ok?
|
assert last_response.ok?
|
||||||
@@ -927,12 +994,12 @@ context "Frontend with empty repo" do
|
|||||||
assert_equal '/gollum/create/Home', last_request.fullpath
|
assert_equal '/gollum/create/Home', last_request.fullpath
|
||||||
assert last_response.ok?
|
assert last_response.ok?
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'Frontend with base path' do
|
context 'Frontend with base path' do
|
||||||
include Rack::Test::Methods
|
include Rack::Test::Methods
|
||||||
|
|
||||||
setup do
|
setup do
|
||||||
@path = cloned_testpath("examples/lotr.git")
|
@path = cloned_testpath("examples/lotr.git")
|
||||||
@wiki = Gollum::Wiki.new(@path)
|
@wiki = Gollum::Wiki.new(@path)
|
||||||
@@ -944,24 +1011,24 @@ context 'Frontend with base path' do
|
|||||||
teardown do
|
teardown do
|
||||||
FileUtils.rm_rf(@path)
|
FileUtils.rm_rf(@path)
|
||||||
end
|
end
|
||||||
|
|
||||||
test 'page with base path' do
|
test 'page with base path' do
|
||||||
get '/wiki/Home'
|
get '/wiki/Home'
|
||||||
assert last_response.ok?
|
assert last_response.ok?
|
||||||
end
|
end
|
||||||
|
|
||||||
test 'base path mathjax assets' do
|
test 'base path mathjax assets' do
|
||||||
get '/wiki/Home'
|
get '/wiki/Home'
|
||||||
assert last_response.ok?
|
assert last_response.ok?
|
||||||
assert last_response.body.include?('<script defer src="/wiki/gollum/assets/mathjax/MathJax.js?config=')
|
assert last_response.body.include?('<script defer src="/wiki/gollum/assets/mathjax/MathJax.js?config=')
|
||||||
end
|
end
|
||||||
|
|
||||||
test 'compare view' do
|
test 'compare view' do
|
||||||
get '/wiki/gollum/compare/Bilbo-Baggins.md?versions[]=f25eccd98e9b667f9e22946f3e2f945378b8a72d&versions[]=5bc1aaec6149e854078f1d0f8b71933bbc6c2e43'
|
get '/wiki/gollum/compare/Bilbo-Baggins.md?versions[]=f25eccd98e9b667f9e22946f3e2f945378b8a72d&versions[]=5bc1aaec6149e854078f1d0f8b71933bbc6c2e43'
|
||||||
follow_redirect!
|
follow_redirect!
|
||||||
assert last_response.ok?
|
assert last_response.ok?
|
||||||
assert_equal '/wiki/gollum/compare/Bilbo-Baggins.md/5bc1aaec6149e854078f1d0f8b71933bbc6c2e43...f25eccd98e9b667f9e22946f3e2f945378b8a72d', last_request.fullpath
|
assert_equal '/wiki/gollum/compare/Bilbo-Baggins.md/5bc1aaec6149e854078f1d0f8b71933bbc6c2e43...f25eccd98e9b667f9e22946f3e2f945378b8a72d', last_request.fullpath
|
||||||
|
|
||||||
get '/wiki/gollum/compare/Bilbo-Baggins.md?versions[]=f25eccd98e9b667f9e22946f3e2f945378b8a72d'
|
get '/wiki/gollum/compare/Bilbo-Baggins.md?versions[]=f25eccd98e9b667f9e22946f3e2f945378b8a72d'
|
||||||
follow_redirect!
|
follow_redirect!
|
||||||
assert last_response.ok?
|
assert last_response.ok?
|
||||||
@@ -972,8 +1039,8 @@ context 'Frontend with base path' do
|
|||||||
assert last_response.ok?
|
assert last_response.ok?
|
||||||
assert_equal '/wiki/gollum/history/Bilbo-Baggins.md', last_request.fullpath
|
assert_equal '/wiki/gollum/history/Bilbo-Baggins.md', last_request.fullpath
|
||||||
end
|
end
|
||||||
|
|
||||||
def app
|
def app
|
||||||
Precious::MapGollum.new(@base_path)
|
Precious::MapGollum.new(@base_path)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
# ~*~ encoding: utf-8 ~*~
|
||||||
|
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
|
||||||
|
require 'nokogiri'
|
||||||
|
require 'json'
|
||||||
|
require 'time'
|
||||||
|
|
||||||
|
def local_time
|
||||||
|
Precious::App.set(:wiki_options, { show_local_time: true})
|
||||||
|
end
|
||||||
|
|
||||||
|
def no_local_time
|
||||||
|
Precious::App.set(:wiki_options, { show_local_time: false})
|
||||||
|
end
|
||||||
|
|
||||||
|
def assert_time_tags(body)
|
||||||
|
tags = Nokogiri::HTML(body).css('time')
|
||||||
|
assert_equal tags.empty?, false
|
||||||
|
tags.each do |tag|
|
||||||
|
assert Time.parse(tag[:datetime]).utc?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context ":show_local_time option" do
|
||||||
|
include Rack::Test::Methods
|
||||||
|
|
||||||
|
setup do
|
||||||
|
@path = cloned_testpath('examples/lotr.git')
|
||||||
|
@wiki = Gollum::Wiki.new(@path)
|
||||||
|
Precious::App.set(:gollum_path, @path)
|
||||||
|
local_time()
|
||||||
|
end
|
||||||
|
|
||||||
|
teardown do
|
||||||
|
FileUtils.rm_rf(@path)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "last_commit_info no local time" do
|
||||||
|
no_local_time()
|
||||||
|
get '/gollum/last_commit_info', {path: 'Home.textile'}
|
||||||
|
assert_equal Time.parse(JSON.parse(last_response.body)['date']).utc?, false
|
||||||
|
end
|
||||||
|
|
||||||
|
test "last_commit_info local time" do
|
||||||
|
local_time()
|
||||||
|
get '/gollum/last_commit_info', {path: 'Home.textile'}
|
||||||
|
assert Time.parse(JSON.parse(last_response.body)['date']).utc?
|
||||||
|
end
|
||||||
|
|
||||||
|
test "datetime attributes in utc" do
|
||||||
|
get '/Home/b0d108328459e44fff4a76cd19b10ddc34adce4b'
|
||||||
|
assert_time_tags last_response.body
|
||||||
|
|
||||||
|
get '/gollum/latest_changes'
|
||||||
|
assert_time_tags last_response.body
|
||||||
|
|
||||||
|
get '/gollum/history/Home'
|
||||||
|
assert_time_tags last_response.body
|
||||||
|
|
||||||
|
get '/gollum/commit/b0d108328459e44fff4a76cd19b10ddc34adce4b'
|
||||||
|
assert_time_tags last_response.body
|
||||||
|
end
|
||||||
|
|
||||||
|
def app
|
||||||
|
Precious::App
|
||||||
|
end
|
||||||
|
end
|
||||||
+64
-66
@@ -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,
|
||||||
@@ -31,56 +9,76 @@ def load_script(**args)
|
|||||||
:hyphenate => false,
|
:hyphenate => false,
|
||||||
: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'))
|
||||||
|
|
||||||
Dir.chdir(@path) do
|
Dir.chdir(@path) do
|
||||||
load script_path
|
load script_path
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
unless ENV['CI']
|
context '4.x -> 5.x tag migrator' do
|
||||||
|
include Rack::Test::Methods
|
||||||
|
|
||||||
context '4.x -> 5.x tag migrator' do
|
setup do
|
||||||
include Rack::Test::Methods
|
@path = cloned_testpath("examples/lotr_migration.git")
|
||||||
|
|
||||||
setup do
|
|
||||||
@path = cloned_testpath("examples/lotr_migration.git")
|
|
||||||
end
|
|
||||||
|
|
||||||
test 'repair broken links' do
|
|
||||||
load_script
|
|
||||||
|
|
||||||
f = ::File.new(::File.join(@path, 'Subdir/Foo.md'), 'r')
|
|
||||||
assert_equal result, f.read
|
|
||||||
end
|
|
||||||
|
|
||||||
test 'change spaced filenames to hyphenated filenames' do
|
|
||||||
load_script(hyphenate: true)
|
|
||||||
|
|
||||||
f = ::File.new(::File.join(@path, 'Home.textile'), 'r')
|
|
||||||
output = f.read
|
|
||||||
assert_equal true, output.include?('[[Bilbo-Baggins.md]]')
|
|
||||||
assert_equal true, output.include?('[[evil|Mordor/Eye-Of-Sauron.md]]')
|
|
||||||
end
|
|
||||||
|
|
||||||
test 'migration with page file dir' do
|
|
||||||
load_script(page_file_dir: 'Subdir')
|
|
||||||
|
|
||||||
f = ::File.new(::File.join(@path, 'Subdir/Foo.md'), 'r')
|
|
||||||
output = f.read
|
|
||||||
assert_equal true, output.include?('[[Subsub/Zaa.md]]')
|
|
||||||
assert_equal true, output.include?('[[Samwi]]')
|
|
||||||
end
|
|
||||||
|
|
||||||
teardown do
|
|
||||||
FileUtils.rm_rf(@path)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
test 'repair broken links' do
|
||||||
|
# The original contents of Subdir/Foo.md:
|
||||||
|
#
|
||||||
|
# waa
|
||||||
|
# [[Samwi]]
|
||||||
|
# [[samwise gamgee.mediaWiki]]
|
||||||
|
# [[Samwise Gamgee.mediawiki]]
|
||||||
|
# [[Samwise Gamgee]]
|
||||||
|
# [[Test|Samwise Gamgee#Anchor]]
|
||||||
|
# [[Waaa|Test]]
|
||||||
|
# [[Zaa]]
|
||||||
|
#
|
||||||
|
# The contents will be updated after running the migration script.
|
||||||
|
load_script
|
||||||
|
|
||||||
|
file = ::File.new(::File.join(@path, 'Subdir/Foo.md'), 'r')
|
||||||
|
assert_equal <<~FILE_CONTENTS, file.read
|
||||||
|
waa
|
||||||
|
[[Samwi]]
|
||||||
|
[[/Samwise Gamgee.mediawiki]]
|
||||||
|
[[/Samwise Gamgee.mediawiki]]
|
||||||
|
[[/Samwise Gamgee.md]]
|
||||||
|
[[Test|/Samwise Gamgee.md#Anchor]]
|
||||||
|
[[Waaa|/Bar/Test.md]]
|
||||||
|
[[Subsub/Zaa.md]]
|
||||||
|
FILE_CONTENTS
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'change spaced filenames to hyphenated filenames' do
|
||||||
|
load_script(hyphenate: true)
|
||||||
|
|
||||||
|
f = ::File.new(::File.join(@path, 'Home.textile'), 'r')
|
||||||
|
output = f.read
|
||||||
|
assert_equal true, output.include?('[[Bilbo-Baggins.md]]')
|
||||||
|
assert_equal true, output.include?('[[evil|Mordor/Eye-Of-Sauron.md]]')
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'migration with page file dir' do
|
||||||
|
load_script(page_file_dir: 'Subdir')
|
||||||
|
|
||||||
|
f = ::File.new(::File.join(@path, 'Subdir/Foo.md'), 'r')
|
||||||
|
output = f.read
|
||||||
|
assert_equal true, output.include?('[[Subsub/Zaa.md]]')
|
||||||
|
assert_equal true, output.include?('[[Samwi]]')
|
||||||
|
end
|
||||||
|
|
||||||
|
teardown do
|
||||||
|
FileUtils.rm_rf(@path)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
# ~*~ encoding: utf-8 ~*~
|
||||||
|
require File.expand_path(File.join(File.dirname(__FILE__), 'helper'))
|
||||||
|
|
||||||
|
context "Precious::Views::TemplateCascade" do
|
||||||
|
include Rack::Test::Methods
|
||||||
|
|
||||||
|
setup do
|
||||||
|
@path = cloned_testpath('examples/lotr.git')
|
||||||
|
Precious::App.set(:gollum_path, @path)
|
||||||
|
Precious::App.set(
|
||||||
|
:wiki_options,
|
||||||
|
{template_dir: testpath('examples/template_cascade')}
|
||||||
|
)
|
||||||
|
@wiki = Gollum::Wiki.new(@path)
|
||||||
|
end
|
||||||
|
|
||||||
|
teardown do
|
||||||
|
FileUtils.rm_rf(@path)
|
||||||
|
|
||||||
|
Precious::App.set(:wiki_options, {template_dir: nil})
|
||||||
|
|
||||||
|
# The following line has been added to avoid order-dependent test failures.
|
||||||
|
# We saw issues where the class variable `@@template_priority_path` was not
|
||||||
|
# being reset between test cases.
|
||||||
|
Precious::Views::TemplateCascade.class_variable_set(
|
||||||
|
:@@template_priority_path,
|
||||||
|
nil
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def app
|
||||||
|
Precious::App.new
|
||||||
|
end
|
||||||
|
|
||||||
|
test "overridden_page_template_is_used" do
|
||||||
|
get '/Home'
|
||||||
|
|
||||||
|
assert last_response.body.include?('PAGE_OVERRIDE')
|
||||||
|
end
|
||||||
|
|
||||||
|
test "test_overridden_navbar_partial_is_used" do
|
||||||
|
get '/Home'
|
||||||
|
|
||||||
|
assert last_response.body.include?('NAVBAR_OVERRIDE')
|
||||||
|
end
|
||||||
|
|
||||||
|
test "test_overridden_templates_are_ignore_without_template_dir_set" do
|
||||||
|
Precious::App.set(:wiki_options, {template_dir: nil})
|
||||||
|
|
||||||
|
get '/Home'
|
||||||
|
|
||||||
|
assert_equal '/Home', last_request.fullpath
|
||||||
|
|
||||||
|
assert last_response.ok?
|
||||||
|
|
||||||
|
refute_match /PAGE_OVERRIDE/, last_response.body
|
||||||
|
refute_match /NAVBAR_OVERRIDE/, last_response.body
|
||||||
|
end
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user