gollum-lib 5.0.a.3-java → 5.0.a.4-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/HISTORY.md +7 -0
- data/gemspec.rb +10 -4
- data/lib/gollum-lib.rb +3 -6
- data/lib/gollum-lib/file.rb +7 -0
- data/lib/gollum-lib/filter.rb +2 -2
- data/lib/gollum-lib/filter/bibtex.rb +55 -0
- data/lib/gollum-lib/filter/code.rb +0 -2
- data/lib/gollum-lib/filter/emoji.rb +10 -3
- data/lib/gollum-lib/filter/pandoc_bib.rb +52 -0
- data/lib/gollum-lib/filter/plain_text.rb +4 -0
- data/lib/gollum-lib/filter/plantuml.rb +3 -4
- data/lib/gollum-lib/filter/remote_code.rb +0 -1
- data/lib/gollum-lib/filter/sanitize.rb +1 -1
- data/lib/gollum-lib/filter/tags.rb +196 -173
- data/lib/gollum-lib/macro/video.rb +9 -0
- data/lib/gollum-lib/markup.rb +25 -41
- data/lib/gollum-lib/markups.rb +36 -3
- data/lib/gollum-lib/sanitization.rb +215 -14
- data/lib/gollum-lib/version.rb +1 -1
- data/lib/gollum-lib/wiki.rb +8 -1
- metadata +53 -15
- data/lib/gollum-lib/filter/wsd.rb +0 -54
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f3579bcfc342afcfe2b398241c190fbba84cfe2c5c922576aaaecb512bab5cd8
|
4
|
+
data.tar.gz: 9387c63c0f369902cf50439b750864fc2c4f86834da46576da7e1c8dc51464c6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4a9bfdbb8a78a024d9c66c4cfa3d185b4156c3bd86068006ea26977db3dcb456691863a19359917cd3e5d70bf5c92f261bd4b47b977d21727608c783b6f0ce58
|
7
|
+
data.tar.gz: 29ac662c80e6b90fad991b7bb421486cf2b1a5b5a3838f342bbdfb0d26f23a6680a98cd6372077a5ed3e8e07578a9470600a4c9a427346fcc36700e735f8f9c5
|
data/HISTORY.md
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
# v5.0
|
2
|
+
|
3
|
+
For a detailed overview of changes in 5.0 and a guide to migrating your wiki, see https://github.com/gollum/gollum/wiki/5.0-release-notes
|
4
|
+
|
5
|
+
* Removed support for Web Sequence Diagroms, PlantUML now default.
|
6
|
+
** PlantUML users in 4.x please note: in this release PlantUML uses the server at https://plantuml.com by default, not `localhost`. Use the config option to keep using your own server.
|
7
|
+
|
1
8
|
# v4.2.1
|
2
9
|
|
3
10
|
* Performances improvements
|
data/gemspec.rb
CHANGED
@@ -8,6 +8,7 @@ def specification(version, default_adapter, platform = nil)
|
|
8
8
|
s.name = 'gollum-lib'
|
9
9
|
s.version = version
|
10
10
|
s.platform = platform if platform
|
11
|
+
s.date = '2018-09-17'
|
11
12
|
s.date = '2017-04-13'
|
12
13
|
s.rubyforge_project = 'gollum-lib'
|
13
14
|
s.license = 'MIT'
|
@@ -25,19 +26,22 @@ def specification(version, default_adapter, platform = nil)
|
|
25
26
|
s.extra_rdoc_files = %w(README.md LICENSE)
|
26
27
|
|
27
28
|
s.add_dependency *default_adapter
|
28
|
-
s.add_dependency 'rouge', '~>
|
29
|
-
s.add_dependency 'nokogiri', '~> 1.
|
29
|
+
s.add_dependency 'rouge', '~> 3.1'
|
30
|
+
s.add_dependency 'nokogiri', '~> 1.8'
|
30
31
|
s.add_dependency 'stringex', '~> 2.6'
|
31
32
|
s.add_dependency 'sanitize', '~> 2.1'
|
32
33
|
s.add_dependency 'github-markup', '~> 1.6'
|
33
34
|
s.add_dependency 'gemojione', '~> 3.2'
|
35
|
+
s.add_dependency 'twitter-text', '1.14.7'
|
34
36
|
|
35
37
|
s.add_development_dependency 'org-ruby', '~> 0.9.9'
|
36
38
|
s.add_development_dependency 'kramdown', '~> 1.13'
|
37
39
|
s.add_development_dependency 'RedCloth', '~> 4.2.9'
|
38
|
-
s.add_development_dependency 'mocha', '~> 1.
|
40
|
+
s.add_development_dependency 'mocha', '~> 1.2.0'
|
39
41
|
s.add_development_dependency 'shoulda', '~> 3.5.0'
|
40
42
|
s.add_development_dependency 'wikicloth', '~> 0.8.3'
|
43
|
+
s.add_development_dependency 'bibtex-ruby', '~> 4.3'
|
44
|
+
s.add_development_dependency 'citeproc-ruby', '~> 1.1'
|
41
45
|
s.add_development_dependency 'rake', '~> 10.4.0'
|
42
46
|
s.add_development_dependency 'pry', '~> 0.10.1'
|
43
47
|
# required by pry
|
@@ -71,9 +75,11 @@ def specification(version, default_adapter, platform = nil)
|
|
71
75
|
lib/gollum-lib/file.rb
|
72
76
|
lib/gollum-lib/file_view.rb
|
73
77
|
lib/gollum-lib/filter.rb
|
78
|
+
lib/gollum-lib/filter/bibtex.rb
|
74
79
|
lib/gollum-lib/filter/code.rb
|
75
80
|
lib/gollum-lib/filter/emoji.rb
|
76
81
|
lib/gollum-lib/filter/macro.rb
|
82
|
+
lib/gollum-lib/filter/pandoc_bib.rb
|
77
83
|
lib/gollum-lib/filter/plain_text.rb
|
78
84
|
lib/gollum-lib/filter/plantuml.rb
|
79
85
|
lib/gollum-lib/filter/remote_code.rb
|
@@ -81,7 +87,6 @@ def specification(version, default_adapter, platform = nil)
|
|
81
87
|
lib/gollum-lib/filter/sanitize.rb
|
82
88
|
lib/gollum-lib/filter/tags.rb
|
83
89
|
lib/gollum-lib/filter/toc.rb
|
84
|
-
lib/gollum-lib/filter/wsd.rb
|
85
90
|
lib/gollum-lib/filter/yaml.rb
|
86
91
|
lib/gollum-lib/git_access.rb
|
87
92
|
lib/gollum-lib/helpers.rb
|
@@ -91,6 +96,7 @@ def specification(version, default_adapter, platform = nil)
|
|
91
96
|
lib/gollum-lib/macro/global_toc.rb
|
92
97
|
lib/gollum-lib/macro/navigation.rb
|
93
98
|
lib/gollum-lib/macro/series.rb
|
99
|
+
lib/gollum-lib/macro/video.rb
|
94
100
|
lib/gollum-lib/markup.rb
|
95
101
|
lib/gollum-lib/markups.rb
|
96
102
|
lib/gollum-lib/page.rb
|
data/lib/gollum-lib.rb
CHANGED
@@ -5,13 +5,10 @@ require 'digest/sha1'
|
|
5
5
|
require 'ostruct'
|
6
6
|
require 'pathname'
|
7
7
|
|
8
|
-
DEFAULT_ADAPTER = RUBY_PLATFORM == 'java' ? '
|
8
|
+
DEFAULT_ADAPTER = RUBY_PLATFORM == 'java' ? 'rjgit' : 'grit'
|
9
9
|
|
10
|
-
if defined?(Gollum::GIT_ADAPTER)
|
11
|
-
|
12
|
-
else
|
13
|
-
require DEFAULT_ADAPTER
|
14
|
-
end
|
10
|
+
Gollum::GIT_ADAPTER = DEFAULT_ADAPTER if !defined?(Gollum::GIT_ADAPTER)
|
11
|
+
require "#{Gollum::GIT_ADAPTER.downcase}_adapter"
|
15
12
|
|
16
13
|
# external
|
17
14
|
require 'github/markup'
|
data/lib/gollum-lib/file.rb
CHANGED
data/lib/gollum-lib/filter.rb
CHANGED
@@ -55,12 +55,12 @@ module Gollum
|
|
55
55
|
@map = {}
|
56
56
|
end
|
57
57
|
|
58
|
-
def extract(
|
58
|
+
def extract(data)
|
59
59
|
raise RuntimeError,
|
60
60
|
"#{self.class} has not implemented ##extract!"
|
61
61
|
end
|
62
62
|
|
63
|
-
def process(
|
63
|
+
def process(data)
|
64
64
|
raise RuntimeError,
|
65
65
|
"#{self.class} has not implemented ##process!"
|
66
66
|
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
begin
|
2
|
+
require 'bibtex'
|
3
|
+
require 'citeproc'
|
4
|
+
require 'csl'
|
5
|
+
require 'csl/styles'
|
6
|
+
rescue LoadError => error
|
7
|
+
end
|
8
|
+
|
9
|
+
# Render BibTeX files.
|
10
|
+
class Gollum::Filter::BibTeX < Gollum::Filter
|
11
|
+
|
12
|
+
def extract(data)
|
13
|
+
return data unless supported_format? && gems_available? && bib = ::BibTeX.parse(data).convert(:latex)
|
14
|
+
style = find_csl_data('csl') || ::CSL::Style.default
|
15
|
+
locale = find_csl_data('locale') || ::CSL::Locale.default
|
16
|
+
|
17
|
+
begin
|
18
|
+
style = ::CSL::Style.load(style)
|
19
|
+
::CSL::Locale.load(locale)
|
20
|
+
rescue ::CSL::ParseError => error
|
21
|
+
log_failure(error.to_s)
|
22
|
+
return CGI.escapeHTML(data)
|
23
|
+
end
|
24
|
+
|
25
|
+
citeproc = ::CiteProc::Processor.new(style: style, locale: locale, format: 'html')
|
26
|
+
citeproc.import(bib.to_citeproc)
|
27
|
+
citeproc.bibliography.references.join('<br/>')
|
28
|
+
end
|
29
|
+
|
30
|
+
def process(data)
|
31
|
+
data
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def log_failure(msg)
|
37
|
+
@markup.metadata = {} unless @markup.metadata
|
38
|
+
@markup.metadata['errors'] = [] unless @markup.metadata['errors']
|
39
|
+
@markup.metadata['errors'] << "Could not render the bibliography because no valid CSL or locale file was found in the wiki or in the CSL directory. Please commited a valid file, or install the csl-styles gem. The message from the parser was: #{msg.to_s}."
|
40
|
+
end
|
41
|
+
|
42
|
+
def supported_format?
|
43
|
+
@markup.format == :bib
|
44
|
+
end
|
45
|
+
|
46
|
+
def gems_available?
|
47
|
+
::Gollum::Markup.formats[:bib][:enabled]
|
48
|
+
end
|
49
|
+
|
50
|
+
def find_csl_data(key)
|
51
|
+
path = @markup.metadata ? @markup.metadata[key] : nil
|
52
|
+
file = path ? @markup.wiki.file(path) : nil
|
53
|
+
file.nil? ? path : file.raw_data
|
54
|
+
end
|
55
|
+
end
|
@@ -2,12 +2,15 @@
|
|
2
2
|
|
3
3
|
# Emoji
|
4
4
|
#
|
5
|
-
# Render emoji such as :smile:
|
5
|
+
# Render an emoji tag such as ":smile:". In some rare situations, you have
|
6
|
+
# to escape emoji tags e.g. when your content contains something like
|
7
|
+
# "hh:mm:ss" or "rake app:shell:install". Prefix the leading colon with a
|
8
|
+
# backslash to disable this emoji tag e.g. "hh\:mm:ss".
|
6
9
|
class Gollum::Filter::Emoji < Gollum::Filter
|
7
10
|
|
8
11
|
EXTRACT_PATTERN = %r{
|
9
12
|
(?<!\[{2})
|
10
|
-
|
13
|
+
(?<escape>\\)?:(?<name>[\w-]+):
|
11
14
|
(?!\]{^2})
|
12
15
|
}ix
|
13
16
|
|
@@ -19,7 +22,11 @@ class Gollum::Filter::Emoji < Gollum::Filter
|
|
19
22
|
|
20
23
|
def extract(data)
|
21
24
|
data.gsub! EXTRACT_PATTERN do
|
22
|
-
|
25
|
+
case
|
26
|
+
when $~[:escape] then $&[1..-1]
|
27
|
+
when emoji_exists?($~[:name]) then "=EEMMOOJJII=#{$~[:name]}=IIJJOOMMEE="
|
28
|
+
else $&
|
29
|
+
end
|
23
30
|
end
|
24
31
|
data
|
25
32
|
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'pathname'
|
3
|
+
|
4
|
+
# When using pandoc, put relevant bibliography metadata extracted in the YAML filter back in the document so it gets passed on to pandoc.
|
5
|
+
class Gollum::Filter::PandocBib < Gollum::Filter
|
6
|
+
|
7
|
+
BIB_PATH_KEYS = ['bibliography', 'csl']
|
8
|
+
BIB_KEYS = ['link-citations', 'nocite']
|
9
|
+
ALL_BIB_KEYS = BIB_PATH_KEYS + BIB_KEYS
|
10
|
+
|
11
|
+
def process(data)
|
12
|
+
data
|
13
|
+
end
|
14
|
+
|
15
|
+
def extract(data)
|
16
|
+
return data unless supported_format? && bibliography_metadata_present?
|
17
|
+
bib_metadata = {}
|
18
|
+
bib_metadata.merge!(@markup.metadata.select {|key, _value| BIB_KEYS.include?(key)})
|
19
|
+
|
20
|
+
BIB_PATH_KEYS.each do |bibliography_key|
|
21
|
+
if path = @markup.metadata[bibliography_key]
|
22
|
+
next unless file = @markup.wiki.file(path)
|
23
|
+
bib_metadata[bibliography_key] = path_for_bibfile(file)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
bib_metadata.empty? ? data : "#{bib_metadata.to_yaml}---\n#{data}"
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def path_for_bibfile(file)
|
32
|
+
if @markup.wiki.repo_is_bare
|
33
|
+
path = Pathname.new("#{::File.join(::Dir.tmpdir, file.sha)}#{::File.extname(file.path)}")
|
34
|
+
unless path.exist?
|
35
|
+
path.open('w') do |copy_file|
|
36
|
+
copy_file.write(file.raw_data)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
path.to_s
|
40
|
+
else
|
41
|
+
::File.expand_path(::File.join(@markup.wiki.path, file.path))
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def supported_format?
|
46
|
+
@markup.format == :markdown
|
47
|
+
end
|
48
|
+
|
49
|
+
def bibliography_metadata_present?
|
50
|
+
@markup.metadata && @markup.metadata.keys.any? {|key| ALL_BIB_KEYS.include?(key)}
|
51
|
+
end
|
52
|
+
end
|
@@ -37,7 +37,7 @@ require 'zlib'
|
|
37
37
|
#
|
38
38
|
class Gollum::Filter::PlantUML < Gollum::Filter
|
39
39
|
|
40
|
-
DEFAULT_URL = "http://
|
40
|
+
DEFAULT_URL = "http://www.plantuml.com/plantuml/png"
|
41
41
|
|
42
42
|
# Configuration class used to change the behaviour of the PlatnUML filter.
|
43
43
|
#
|
@@ -69,7 +69,6 @@ class Gollum::Filter::PlantUML < Gollum::Filter
|
|
69
69
|
# Extract all sequence diagram blocks into the map and replace with
|
70
70
|
# placeholders.
|
71
71
|
def extract(data)
|
72
|
-
return data if @markup.format == :txt
|
73
72
|
data.gsub(/(@startuml\r?\n.+?\r?\n@enduml\r?$)/m) do
|
74
73
|
id = Digest::SHA1.hexdigest($1)
|
75
74
|
@map[id] = { :code => $1 }
|
@@ -115,9 +114,9 @@ class Gollum::Filter::PlantUML < Gollum::Filter
|
|
115
114
|
# Transcoder class in the PlantUML java code.
|
116
115
|
def gen_url(text)
|
117
116
|
result = ""
|
118
|
-
compressedData = Zlib::Deflate.deflate(text)
|
117
|
+
compressedData = Zlib::Deflate.new(nil, -Zlib::MAX_WBITS).deflate(text, Zlib::FINISH)
|
118
|
+
|
119
119
|
compressedData.chars.each_slice(3) do |bytes|
|
120
|
-
#print bytes[0], ' ' , bytes[1] , ' ' , bytes[2]
|
121
120
|
b1 = bytes[0].nil? ? 0 : (bytes[0].ord & 0xFF)
|
122
121
|
b2 = bytes[1].nil? ? 0 : (bytes[1].ord & 0xFF)
|
123
122
|
b3 = bytes[2].nil? ? 0 : (bytes[2].ord & 0xFF)
|
@@ -13,7 +13,6 @@ require 'open-uri'
|
|
13
13
|
#
|
14
14
|
class Gollum::Filter::RemoteCode < Gollum::Filter
|
15
15
|
def extract(data)
|
16
|
-
return data if @markup.format == :txt
|
17
16
|
data.gsub(/^[ \t]*``` ?([^:\n\r]+):((http)?[^`\n\r]+)```/) do
|
18
17
|
language = Regexp.last_match[1]
|
19
18
|
uri = Regexp.last_match[2]
|
@@ -10,7 +10,7 @@ class Gollum::Filter::Sanitize < Gollum::Filter
|
|
10
10
|
doc = Nokogiri::HTML::DocumentFragment.parse(data)
|
11
11
|
doc = @markup.sanitize.clean_node!(doc)
|
12
12
|
|
13
|
-
doc.to_xml(@markup.to_xml_opts)
|
13
|
+
doc.to_xml(@markup.to_xml_opts).gsub(/<p><\/p>/, '')
|
14
14
|
else
|
15
15
|
data
|
16
16
|
end
|
@@ -4,7 +4,6 @@
|
|
4
4
|
class Gollum::Filter::Tags < Gollum::Filter
|
5
5
|
# Extract all tags into the tagmap and replace with placeholders.
|
6
6
|
def extract(data)
|
7
|
-
return data if @markup.format == :txt || @markup.format == :asciidoc
|
8
7
|
data.gsub!(/(.?)\[\[(.+?)\]\]([^\[]?)/) do
|
9
8
|
if Regexp.last_match[1] == "'" && Regexp.last_match[3] != "'"
|
10
9
|
"[[#{Regexp.last_match[2]}]]#{Regexp.last_match[3]}"
|
@@ -28,12 +27,6 @@ class Gollum::Filter::Tags < Gollum::Filter
|
|
28
27
|
data
|
29
28
|
end
|
30
29
|
|
31
|
-
def register_tag(tag)
|
32
|
-
id = "TAG#{Digest::SHA1.hexdigest(tag)}TAG"
|
33
|
-
@map[id] = tag
|
34
|
-
id
|
35
|
-
end
|
36
|
-
|
37
30
|
# Process all text nodes from the doc and replace the placeholders with the
|
38
31
|
# final markup.
|
39
32
|
def process(rendered_data)
|
@@ -60,6 +53,13 @@ class Gollum::Filter::Tags < Gollum::Filter
|
|
60
53
|
private
|
61
54
|
|
62
55
|
PREFORMATTED_TAGS = %w(code tt)
|
56
|
+
INCLUDE_TAG = 'include:'
|
57
|
+
|
58
|
+
def register_tag(tag)
|
59
|
+
id = "TAG#{Digest::SHA1.hexdigest(tag)}TAG"
|
60
|
+
@map[id] = tag
|
61
|
+
id
|
62
|
+
end
|
63
63
|
|
64
64
|
def is_preformatted?(node)
|
65
65
|
node && (PREFORMATTED_TAGS.include?(node.name) ||
|
@@ -73,20 +73,43 @@ class Gollum::Filter::Tags < Gollum::Filter
|
|
73
73
|
#
|
74
74
|
# Returns the String HTML version of the tag.
|
75
75
|
def process_tag(tag)
|
76
|
-
|
76
|
+
link_part, extra = parse_tag_parts(tag)
|
77
|
+
return generate_link('', nil, nil, :page_absent) if link_part.nil?
|
78
|
+
img_args = extra ? [extra, link_part] : [link_part]
|
79
|
+
mime = MIME::Types.type_for(::File.extname(img_args.first.to_s)).first
|
80
|
+
|
81
|
+
result = if tag =~ /^_TOC_/
|
77
82
|
%{[[#{tag}]]}
|
78
|
-
elsif
|
83
|
+
elsif link_part =~ /^_$/
|
79
84
|
%{<div class="clearfloats"></div>}
|
80
|
-
elsif
|
81
|
-
|
82
|
-
elsif
|
83
|
-
|
84
|
-
elsif
|
85
|
-
|
86
|
-
|
87
|
-
|
85
|
+
elsif link_part =~ /^#{INCLUDE_TAG}/
|
86
|
+
process_include_tag(link_part)
|
87
|
+
elsif mime && mime.content_type =~ /^image/
|
88
|
+
process_image_tag(*img_args)
|
89
|
+
elsif external = process_external_link_tag(link_part, extra)
|
90
|
+
external
|
91
|
+
end
|
92
|
+
result ? result : process_link_tag(link_part, extra)
|
93
|
+
end
|
94
|
+
|
95
|
+
# Process the tag parts as an internal link to a File or Page.
|
96
|
+
def process_link_tag(link_part, pretty_name)
|
97
|
+
process_file_link_tag(link_part, pretty_name) || process_page_link_tag(link_part, pretty_name)
|
98
|
+
end
|
99
|
+
|
100
|
+
# Parse the tag (stuff between the double brackets) into a link part and additional information (a pretty name, description, or image options).
|
101
|
+
#
|
102
|
+
# tag - The String tag contents (the stuff inside the double
|
103
|
+
# brackets).
|
104
|
+
#
|
105
|
+
# Returns an Array of the form [link_part, extra], where both elements are Strings and the second element may be nil.
|
106
|
+
def parse_tag_parts(tag)
|
107
|
+
parts = tag.split('|').map(&:strip)[0..1]
|
108
|
+
parts.reverse! if @markup.reverse_links?
|
109
|
+
if parts[1]
|
110
|
+
return parts[1], parts[0]
|
88
111
|
else
|
89
|
-
|
112
|
+
return parts[0], nil
|
90
113
|
end
|
91
114
|
end
|
92
115
|
|
@@ -94,16 +117,14 @@ class Gollum::Filter::Tags < Gollum::Filter
|
|
94
117
|
#
|
95
118
|
# tag - The String tag contents (the stuff inside the double brackets).
|
96
119
|
#
|
97
|
-
# Returns the String HTML if the tag
|
98
|
-
# if it is not.
|
99
|
-
#
|
120
|
+
# Returns the String HTML if the tag includes a valid page or an error message if the page could not be found.
|
100
121
|
def process_include_tag(tag)
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
122
|
+
len = INCLUDE_TAG.length
|
123
|
+
return html_error('Cannot process include directive: no page name given') if tag.length <= len
|
124
|
+
page_name = tag[len..-1]
|
125
|
+
resolved_page_name = ::File.expand_path(page_name, "#{::File::SEPARATOR}#{@markup.dir}")
|
105
126
|
if @markup.include_levels > 0
|
106
|
-
page =
|
127
|
+
page = find_page_from_path(resolved_page_name)
|
107
128
|
if page
|
108
129
|
page.formatted_data(@markup.encoding, @markup.include_levels-1)
|
109
130
|
else
|
@@ -116,110 +137,42 @@ class Gollum::Filter::Tags < Gollum::Filter
|
|
116
137
|
|
117
138
|
# Attempt to process the tag as an image tag.
|
118
139
|
#
|
119
|
-
#
|
140
|
+
# path - The String path to the image.
|
141
|
+
# options - The String of options for the image (the stuff after the '|'). Optional.
|
120
142
|
#
|
121
143
|
# Returns the String HTML if the tag is a valid image tag or nil
|
122
144
|
# if it is not.
|
123
|
-
def process_image_tag(
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
path = name
|
132
|
-
elsif name =~ /.+(jpg|png|gif|svg|bmp)$/i
|
133
|
-
# If is image, file not found and no link, then populate with empty String
|
134
|
-
# We can than add an image not found alt attribute for this later
|
135
|
-
path = ""
|
136
|
-
end
|
137
|
-
|
138
|
-
if path
|
139
|
-
opts = parse_image_tag_options(tag)
|
140
|
-
|
141
|
-
containered = false
|
142
|
-
|
143
|
-
classes = [] # applied to whatever the outermost container is
|
144
|
-
attrs = [] # applied to the image
|
145
|
-
|
146
|
-
align = opts['align']
|
147
|
-
if opts['float']
|
148
|
-
containered = true
|
149
|
-
align ||= 'left'
|
150
|
-
if %w{left right}.include?(align)
|
151
|
-
classes << "float-#{align}"
|
152
|
-
end
|
153
|
-
elsif %w{top texttop middle absmiddle bottom absbottom baseline}.include?(align)
|
154
|
-
attrs << %{align="#{align}"}
|
155
|
-
elsif align
|
156
|
-
if %w{left center right}.include?(align)
|
157
|
-
containered = true
|
158
|
-
classes << "align-#{align}"
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
if (width = opts['width'])
|
163
|
-
if width =~ /^\d+(\.\d+)?(em|px)$/
|
164
|
-
attrs << %{width="#{width}"}
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
if (height = opts['height'])
|
169
|
-
if height =~ /^\d+(\.\d+)?(em|px)$/
|
170
|
-
attrs << %{height="#{height}"}
|
171
|
-
end
|
172
|
-
end
|
173
|
-
|
174
|
-
if path != "" && (alt = opts['alt'])
|
175
|
-
attrs << %{alt="#{alt}"}
|
176
|
-
elsif path == ""
|
177
|
-
attrs << %{alt="Image not found"}
|
178
|
-
end
|
179
|
-
|
180
|
-
attr_string = attrs.size > 0 ? attrs.join(' ') + ' ' : ''
|
181
|
-
|
182
|
-
if opts['frame'] || containered
|
183
|
-
classes << 'frame' if opts['frame']
|
184
|
-
%{<span class="#{classes.join(' ')}">} +
|
185
|
-
%{<span>} +
|
186
|
-
%{<img src="#{path}" #{attr_string}/>} +
|
187
|
-
(alt ? %{<span>#{alt}</span>} : '') +
|
188
|
-
%{</span>} +
|
189
|
-
%{</span>}
|
190
|
-
else
|
191
|
-
%{<img src="#{path}" #{attr_string}/>}
|
192
|
-
end
|
145
|
+
def process_image_tag(path, options = nil)
|
146
|
+
opts = parse_image_tag_options(options)
|
147
|
+
if path =~ /^https?:\/\/.+$/i
|
148
|
+
generate_image(path, opts)
|
149
|
+
elsif file = @markup.find_file(path)
|
150
|
+
generate_image(generate_href_for_path(file.path), opts)
|
151
|
+
else
|
152
|
+
generate_image('', opts)
|
193
153
|
end
|
194
154
|
end
|
195
155
|
|
196
|
-
# Parse any options present on the image tag and extract them into a
|
156
|
+
# Parse any options present on the image tag (comma separated) and extract them into a
|
197
157
|
# Hash of option names and values.
|
198
158
|
#
|
199
|
-
#
|
159
|
+
# options - The String image options (the stuff in the after '|').
|
200
160
|
#
|
201
161
|
# Returns the options Hash:
|
202
162
|
# key - The String option name.
|
203
163
|
# val - The String option value or true if it is a binary option.
|
204
|
-
def parse_image_tag_options(
|
205
|
-
|
206
|
-
|
207
|
-
|
164
|
+
def parse_image_tag_options(options)
|
165
|
+
return {} if options.nil?
|
166
|
+
options.split(',').inject({}) do |memo, attr|
|
167
|
+
parts = attr.split('=').map { |x| x.strip }
|
168
|
+
memo[parts[0].to_sym] = (parts.size == 1 ? true : parts[1])
|
208
169
|
memo
|
209
170
|
end
|
210
171
|
end
|
211
172
|
|
212
173
|
# Return the String HTML if the tag is a valid external link tag or
|
213
174
|
# nil if it is not.
|
214
|
-
def process_external_link_tag(
|
215
|
-
parts = tag.split('|')
|
216
|
-
parts.reverse! if @markup.reverse_links?
|
217
|
-
return if parts.size.zero?
|
218
|
-
if parts.size == 1
|
219
|
-
url = parts[0].strip
|
220
|
-
else
|
221
|
-
name, url = *parts.compact.map(&:strip)
|
222
|
-
end
|
175
|
+
def process_external_link_tag(url, pretty_name = nil)
|
223
176
|
accepted_protocols = @markup.wiki.sanitization.protocols['a']['href'].dup
|
224
177
|
if accepted_protocols.include?(:relative)
|
225
178
|
accepted_protocols.select!{|protocol| protocol != :relative}
|
@@ -228,40 +181,22 @@ class Gollum::Filter::Tags < Gollum::Filter
|
|
228
181
|
regexp = %r{^((#{accepted_protocols.join("|")}):)}
|
229
182
|
end
|
230
183
|
if url =~ regexp
|
231
|
-
|
232
|
-
%{<a href="#{url}">#{url}</a>}
|
233
|
-
else
|
234
|
-
%{<a href="#{url}">#{name}</a>}
|
235
|
-
end
|
184
|
+
generate_link(url, pretty_name, nil, :external)
|
236
185
|
else
|
237
186
|
nil
|
238
187
|
end
|
239
|
-
|
240
188
|
end
|
241
189
|
|
242
190
|
# Attempt to process the tag as a file link tag.
|
243
191
|
#
|
244
|
-
#
|
245
|
-
#
|
192
|
+
# link_part - The String part of the tag containing the link
|
193
|
+
# pretty_name - The String name for the link (optional)
|
246
194
|
#
|
247
195
|
# Returns the String HTML if the tag is a valid file link tag or nil
|
248
196
|
# if it is not.
|
249
|
-
def process_file_link_tag(
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
name = parts[0].strip
|
254
|
-
path = parts[1] && parts[1].strip
|
255
|
-
if path && file = @markup.find_file(path)
|
256
|
-
path = ::File.join @markup.wiki.base_path, file.path
|
257
|
-
else
|
258
|
-
path = nil
|
259
|
-
end
|
260
|
-
|
261
|
-
if name && path && file
|
262
|
-
%{<a href="#{::File.join @markup.wiki.base_path, file.path}">#{name}</a>}
|
263
|
-
elsif name && path
|
264
|
-
%{<a href="#{path}">#{name}</a>}
|
197
|
+
def process_file_link_tag(link_part, pretty_name)
|
198
|
+
if file = @markup.find_file(link_part)
|
199
|
+
generate_link(file.path, pretty_name, nil, :file)
|
265
200
|
else
|
266
201
|
nil
|
267
202
|
end
|
@@ -269,59 +204,147 @@ class Gollum::Filter::Tags < Gollum::Filter
|
|
269
204
|
|
270
205
|
# Attempt to process the tag as a page link tag.
|
271
206
|
#
|
272
|
-
#
|
273
|
-
#
|
207
|
+
# link_part - The String part of the tag containing the link
|
208
|
+
# pretty_name - The String name for the link (optional)
|
274
209
|
#
|
275
210
|
# Returns the String HTML if the tag is a valid page link tag or nil
|
276
211
|
# if it is not.
|
277
|
-
def process_page_link_tag(
|
278
|
-
|
279
|
-
|
212
|
+
def process_page_link_tag(link_part, pretty_name = nil)
|
213
|
+
presence = :page_absent
|
214
|
+
link = link_part
|
215
|
+
page = find_page_from_path(link)
|
216
|
+
|
217
|
+
# If no match yet, try finding page with anchor removed
|
218
|
+
if (page.nil? && pos = link.rindex('#'))
|
219
|
+
extra = link[pos..-1]
|
220
|
+
link = link[0...pos]
|
221
|
+
page = find_page_from_path(link)
|
222
|
+
end
|
223
|
+
presence = :page_present if page
|
224
|
+
|
225
|
+
name = pretty_name ? pretty_name : link
|
226
|
+
link = page ? page.escaped_url_path : CGI.escape(link)
|
227
|
+
generate_link(link, name, extra, presence)
|
228
|
+
end
|
280
229
|
|
281
|
-
|
282
|
-
|
230
|
+
# Find a page from a given path
|
231
|
+
#
|
232
|
+
# path - The String path to search for.
|
233
|
+
#
|
234
|
+
# Returns a Gollum::Page instance if a page is found, or nil otherwise
|
235
|
+
def find_page_from_path(path)
|
236
|
+
slash = path.rindex('/')
|
283
237
|
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
238
|
+
unless slash.nil?
|
239
|
+
name = path[slash+1..-1]
|
240
|
+
path = path[0..slash]
|
241
|
+
@markup.wiki.paged(name, path)
|
242
|
+
else
|
243
|
+
@markup.wiki.page(path)
|
290
244
|
end
|
291
|
-
|
292
|
-
|
293
|
-
# //page is invalid
|
294
|
-
# strip all duplicate forward slashes using helpers.rb trim_leading_slash
|
295
|
-
# //page => /page
|
296
|
-
link = trim_leading_slash link
|
245
|
+
end
|
297
246
|
|
298
|
-
|
247
|
+
# Generate an HTML link tag.
|
248
|
+
#
|
249
|
+
# path - The String path (href) to construct a link to.
|
250
|
+
# name - The String name of the link (text inside the link tag). Optional.
|
251
|
+
# extra - The String anchor to add the link. Optional.
|
252
|
+
# kind - A Symbol indicating whether this is a Page, File, or External link.
|
253
|
+
#
|
254
|
+
# Returns a String HTML link tag.
|
255
|
+
def generate_link(path, name = nil, extra = nil, kind = nil)
|
256
|
+
url = kind == :external ? path : generate_href_for_path(path, extra)
|
257
|
+
%{<a #{css_options_for_link(kind)} href="#{url}">#{name || path}</a>}
|
299
258
|
end
|
300
259
|
|
301
|
-
#
|
302
|
-
# no match, strip the anchor and try again.
|
260
|
+
# Generate a normalized href for a path, taking into consideration the wiki's path settings.
|
303
261
|
#
|
304
|
-
#
|
262
|
+
# path - The String path to generate an href for.
|
263
|
+
# extra - The String anchor to add to the href. Optional.
|
305
264
|
#
|
306
|
-
# Returns a
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
slash = cname.rindex('/')
|
265
|
+
# Returns a String href.
|
266
|
+
def generate_href_for_path(path, extra = nil)
|
267
|
+
"#{trim_leading_slash(::File.join(@markup.wiki.base_path, path))}#{extra}"
|
268
|
+
end
|
311
269
|
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
270
|
+
# Construct a CSS class and attribute string for different kinds of links: internal Pages (absent or present) and Files, and External links.
|
271
|
+
#
|
272
|
+
# kind - The Symbol indicating the kind of link. Can be one of: :page_absent, :page_present, :file, :external.
|
273
|
+
#
|
274
|
+
# Returns the String CSS class and attributes.
|
275
|
+
def css_options_for_link(kind)
|
276
|
+
case kind
|
277
|
+
when :page_absent
|
278
|
+
'class="internal absent"'
|
279
|
+
when :page_present
|
280
|
+
'class="internal present"'
|
281
|
+
when :file
|
282
|
+
nil
|
283
|
+
when :external
|
284
|
+
nil
|
285
|
+
else
|
286
|
+
nil
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
# Generate an HTML image tag.
|
291
|
+
#
|
292
|
+
# path - The String path (href) of the image.
|
293
|
+
# options - The Hash of parsed image options.
|
294
|
+
#
|
295
|
+
# Returns a String HTML img tag.
|
296
|
+
def generate_image(path, options = nil)
|
297
|
+
classes, attrs, containered = generate_image_attributes(options)
|
298
|
+
attrs[:alt] = 'Image not found' if path.empty?
|
299
|
+
attr_string = attrs.map {|key, value| "#{key}=\"#{value}\""}.join(' ')
|
300
|
+
|
301
|
+
if containered
|
302
|
+
%{<span class="#{classes.join(' ')}">} +
|
303
|
+
%{<span>} +
|
304
|
+
%{<img src="#{path}" #{attr_string}/>} +
|
305
|
+
(attrs[:alt] ? %{<span>#{attrs[:alt]}</span>} : '') +
|
306
|
+
%{</span>} +
|
307
|
+
%{</span>}
|
316
308
|
else
|
317
|
-
|
309
|
+
%{<img src="#{path}" #{attr_string}/>}
|
318
310
|
end
|
311
|
+
end
|
319
312
|
|
320
|
-
|
321
|
-
|
313
|
+
# Helper method to generate the styling attributes and elements for an image tag.
|
314
|
+
#
|
315
|
+
# options - The Hash of parsed image options.
|
316
|
+
#
|
317
|
+
# Returns an Array of CSS classes, a Hash of CSS attributes, and a Boolean indicating whether or not the image is containered.
|
318
|
+
def generate_image_attributes(options)
|
319
|
+
containered = false
|
320
|
+
classes = [] # applied to whatever the outermost container is
|
321
|
+
attrs = {} # applied to the image
|
322
|
+
|
323
|
+
align = options[:align]
|
324
|
+
if options[:float]
|
325
|
+
containered = true
|
326
|
+
align ||= 'left'
|
327
|
+
if %w{left right}.include?(align)
|
328
|
+
classes << "float-#{align}"
|
329
|
+
end
|
330
|
+
elsif %w{top texttop middle absmiddle bottom absbottom baseline}.include?(align)
|
331
|
+
attrs[:align] = align
|
332
|
+
elsif align
|
333
|
+
if %w{left center right}.include?(align)
|
334
|
+
containered = true
|
335
|
+
classes << "align-#{align}"
|
336
|
+
end
|
322
337
|
end
|
323
|
-
|
324
|
-
|
338
|
+
|
339
|
+
if options[:frame]
|
340
|
+
containered = true
|
341
|
+
classes << 'frame'
|
325
342
|
end
|
343
|
+
|
344
|
+
attrs[:alt] = options[:alt] if options[:alt]
|
345
|
+
attrs[:width] = options[:width] if options[:width] =~ /^\d+(\.\d+)?(em|px)$/
|
346
|
+
attrs[:height] = options[:height] if options[:height] =~ /^\d+(\.\d+)?(em|px)$/
|
347
|
+
|
348
|
+
return classes, attrs, containered
|
326
349
|
end
|
327
350
|
end
|