gollum-lib 4.0.3 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,167 @@
1
+ # ~*~ encoding: utf-8 ~*~
2
+ require 'net/http'
3
+ require 'uri'
4
+ require 'open-uri'
5
+ require 'zlib'
6
+
7
+ # PlantUML Diagrams
8
+ #
9
+ # This filter replaces PlantUML blocks with HTML img tags. These img tags
10
+ # point to a PlantUML web service that converts the UML text blocks into nice
11
+ # diagrams.
12
+ #
13
+ # For this to work you must have your own PlantUML server running somewhere.
14
+ # Just follow the instructions on the github page to run your own server:
15
+ #
16
+ # https://github.com/plantuml/plantuml-server
17
+ #
18
+ # Once you start you own plantuml server you need to configure this filter to
19
+ # point to it:
20
+ #
21
+ # Gollum::Filter::PlantUML.configure do |config|
22
+ # config.url = "http://localhost:8080/plantuml/png"
23
+ # end
24
+ #
25
+ # Then in your wiki pages simply add PlantUML blocks anywhere you want a
26
+ # diagram:
27
+ #
28
+ # @startuml
29
+ # Alice -> Bob: Authentication Request
30
+ # Bob --> Alice: Authentication Response
31
+ # Alice -> Bob: Another authentication Request
32
+ # Alice <-- Bob: another authentication Response
33
+ # @enduml
34
+ #
35
+ # To learn more about how to create cool PlantUML diagrams check the examples
36
+ # at: http://plantuml.sourceforge.net/
37
+ #
38
+ class Gollum::Filter::PlantUML < Gollum::Filter
39
+
40
+ DEFAULT_URL = "http://localhost:8080/plantuml/png"
41
+
42
+ # Configuration class used to change the behaviour of the PlatnUML filter.
43
+ #
44
+ # url: PlantUML server URL (e.g. http://localhost:8080)
45
+ # test: Set to true when running tests to skip the server check.
46
+ #
47
+ class Configuration
48
+ attr_accessor :url, :test
49
+
50
+ def initialize
51
+ @url = DEFAULT_URL
52
+ @test = false
53
+ end
54
+ end
55
+
56
+ class << self
57
+ attr_writer :configuration
58
+ end
59
+
60
+ def self.configuration
61
+ @configuration ||= Configuration.new
62
+ end
63
+
64
+ def self.configure
65
+ yield(configuration)
66
+ end
67
+
68
+ # Extract all sequence diagram blocks into the map and replace with
69
+ # placeholders.
70
+ def extract(data)
71
+ return data if @markup.format == :txt
72
+ data.gsub(/(@startuml\r?\n.+?\r?\n@enduml\r?$)/m) do
73
+ id = Digest::SHA1.hexdigest($1)
74
+ @map[id] = { :code => $1 }
75
+ id
76
+ end
77
+ end
78
+
79
+ # Process all diagrams from the map and replace the placeholders with
80
+ # the final HTML.
81
+ def process(data)
82
+ @map.each do |id, spec|
83
+ data.gsub!(id) do
84
+ render_plantuml(id, spec[:code])
85
+ end
86
+ end
87
+ data
88
+ end
89
+
90
+ private
91
+
92
+ def server_url
93
+ PlantUML::configuration.url
94
+ end
95
+
96
+ def test?
97
+ PlantUML::configuration.test
98
+ end
99
+
100
+ def render_plantuml(id, code)
101
+ if check_server
102
+ plantuml_url = gen_url(code)
103
+ "<img src=\"#{gen_url(code)}\" />"
104
+ else
105
+ html_error("Sorry, unable to render PlantUML diagram at this time")
106
+ end
107
+ end
108
+
109
+ # Compression code used to generate PlantUML URLs. Taken directly from the
110
+ # Transcoder class in the PlantUML java code.
111
+ def gen_url(text)
112
+ result = ""
113
+ compressedData = Zlib::Deflate.deflate(text)
114
+ compressedData.chars.each_slice(3) do |bytes|
115
+ #print bytes[0], ' ' , bytes[1] , ' ' , bytes[2]
116
+ b1 = bytes[0].nil? ? 0 : (bytes[0].ord & 0xFF)
117
+ b2 = bytes[1].nil? ? 0 : (bytes[1].ord & 0xFF)
118
+ b3 = bytes[2].nil? ? 0 : (bytes[2].ord & 0xFF)
119
+ result += append3bytes(b1, b2, b3)
120
+ end
121
+ "#{server_url}/#{result}"
122
+ end
123
+
124
+ def encode6bit(b)
125
+ if b < 10
126
+ return ('0'.ord + b).chr
127
+ end
128
+ b = b - 10
129
+ if b < 26
130
+ return ('A'.ord + b).chr
131
+ end
132
+ b = b - 26
133
+ if b < 26
134
+ return ('a'.ord + b).chr
135
+ end
136
+ b = b - 26
137
+ if b == 0
138
+ return '-'
139
+ end
140
+ if b == 1
141
+ return '_'
142
+ end
143
+ return '?'
144
+ end
145
+
146
+ def append3bytes(b1, b2, b3)
147
+ c1 = b1 >> 2
148
+ c2 = ((b1 & 0x3) << 4) | (b2 >> 4)
149
+ c3 = ((b2 & 0xF) << 2) | (b3 >> 6)
150
+ c4 = b3 & 0x3F
151
+ return encode6bit(c1 & 0x3F).chr +
152
+ encode6bit(c2 & 0x3F).chr +
153
+ encode6bit(c3 & 0x3F).chr +
154
+ encode6bit(c4 & 0x3F).chr
155
+ end
156
+
157
+ # Make a call to the PlantUML server with the simplest diagram possible to
158
+ # check if the server is available or not.
159
+ def check_server
160
+ return true if test?
161
+ check_url = "#{server_url}/SyfFKj2rKt3CoKnELR1Io4ZDoSa70000"
162
+ response = Net::HTTP.get_response(URI(check_url))
163
+ return response.is_a?(Net::HTTPSuccess)
164
+ rescue
165
+ return false
166
+ end
167
+ end
@@ -14,14 +14,14 @@ require 'open-uri'
14
14
  class Gollum::Filter::RemoteCode < Gollum::Filter
15
15
  def extract(data)
16
16
  return data if @markup.format == :txt
17
- data.gsub /^[ \t]*``` ?([^:\n\r]+):((http)?[^`\n\r]+)```/ do
18
- language = $1
19
- uri = $2
20
- protocol = $3
17
+ data.gsub(/^[ \t]*``` ?([^:\n\r]+):((http)?[^`\n\r]+)```/) do
18
+ language = Regexp.last_match[1]
19
+ uri = Regexp.last_match[2]
20
+ protocol = Regexp.last_match[3]
21
21
 
22
22
  # Detect local file
23
23
  if protocol.nil?
24
- if file = @markup.find_file(uri, @markup.wiki.ref)
24
+ if (file = @markup.find_file(uri, @markup.wiki.ref))
25
25
  contents = file.raw_data
26
26
  else
27
27
  # How do we communicate a render error?
@@ -35,13 +35,13 @@ class Gollum::Filter::RemoteCode < Gollum::Filter
35
35
  end
36
36
  end
37
37
 
38
- def process(d)
39
- d
38
+ def process(data)
39
+ data
40
40
  end
41
41
 
42
42
  private
43
43
 
44
- def req uri, cut = 1
44
+ def req(uri, cut = 1)
45
45
  uri = URI(uri)
46
46
  return "Too many redirects or retries" if cut >= 10
47
47
  http = Net::HTTP.new uri.host, uri.port
@@ -14,7 +14,7 @@ class Gollum::Filter::Render < Gollum::Filter
14
14
  data
15
15
  end
16
16
 
17
- def process(d)
18
- d
17
+ def process(data)
18
+ data
19
19
  end
20
20
  end
@@ -1,8 +1,8 @@
1
1
  # ~*~ encoding: utf-8 ~*~
2
2
 
3
3
  class Gollum::Filter::Sanitize < Gollum::Filter
4
- def extract(d)
5
- d
4
+ def extract(data)
5
+ data
6
6
  end
7
7
 
8
8
  def process(data)
@@ -6,23 +6,23 @@ class Gollum::Filter::Tags < Gollum::Filter
6
6
  def extract(data)
7
7
  return data if @markup.format == :txt || @markup.format == :asciidoc
8
8
  data.gsub!(/(.?)\[\[(.+?)\]\]([^\[]?)/m) do
9
- if $1 == "'" && $3 != "'"
10
- "[[#{$2}]]#{$3}"
11
- elsif $2.include?('][')
12
- if $2[0..4] == 'file:'
13
- pre = $1
14
- post = $3
15
- parts = $2.split('][')
9
+ if Regexp.last_match[1] == "'" && Regexp.last_match[3] != "'"
10
+ "[[#{Regexp.last_match[2]}]]#{Regexp.last_match[3]}"
11
+ elsif Regexp.last_match[2].include?('][')
12
+ if Regexp.last_match[2][0..4] == 'file:'
13
+ pre = Regexp.last_match[1]
14
+ post = Regexp.last_match[3]
15
+ parts = Regexp.last_match[2].split('][')
16
16
  parts[0][0..4] = ""
17
17
  link = "#{parts[1]}|#{parts[0].sub(/\.org/, '')}"
18
18
  id = register_tag(link)
19
19
  "#{pre}#{id}#{post}"
20
20
  else
21
- $&
21
+ Regexp.last_match[0]
22
22
  end
23
23
  else
24
- id = register_tag($2)
25
- "#{$1}#{id}#{$3}"
24
+ id = register_tag(Regexp.last_match[2])
25
+ "#{Regexp.last_match[1]}#{id}#{Regexp.last_match[3]}"
26
26
  end
27
27
  end
28
28
  data
@@ -42,7 +42,7 @@ class Gollum::Filter::Tags < Gollum::Filter
42
42
  if node.text? then
43
43
  content = node.content
44
44
  content.gsub!(/TAG[a-f0-9]+TAG/) do |id|
45
- if tag = @map[id] then
45
+ if (tag = @map[id]) then
46
46
  if is_preformatted?(node) then
47
47
  "[[#{tag}]]"
48
48
  else
@@ -77,13 +77,13 @@ class Gollum::Filter::Tags < Gollum::Filter
77
77
  %{[[#{tag}]]}
78
78
  elsif tag =~ /^_$/
79
79
  %{<div class="clearfloats"></div>}
80
- elsif html = process_include_tag(tag)
80
+ elsif (html = process_include_tag(tag))
81
81
  html
82
- elsif html = process_image_tag(tag)
82
+ elsif (html = process_image_tag(tag))
83
83
  html
84
- elsif html = process_external_link_tag(tag)
84
+ elsif (html = process_external_link_tag(tag))
85
85
  html
86
- elsif html = process_file_link_tag(tag)
86
+ elsif (html = process_file_link_tag(tag))
87
87
  html
88
88
  else
89
89
  process_page_link_tag(tag)
@@ -125,11 +125,11 @@ class Gollum::Filter::Tags < Gollum::Filter
125
125
  return if parts.size.zero?
126
126
 
127
127
  name = parts[0].strip
128
- path = if file = @markup.find_file(name)
129
- ::File.join @markup.wiki.base_path, file.path
130
- elsif name =~ /^https?:\/\/.+(jpg|png|gif|svg|bmp)$/i
131
- name
132
- end
128
+ if (file = @markup.find_file(name))
129
+ path = ::File.join @markup.wiki.base_path, file.path
130
+ elsif name =~ /^https?:\/\/.+(jpg|png|gif|svg|bmp)$/i
131
+ path = name
132
+ end
133
133
 
134
134
  if path
135
135
  opts = parse_image_tag_options(tag)
@@ -155,19 +155,19 @@ class Gollum::Filter::Tags < Gollum::Filter
155
155
  end
156
156
  end
157
157
 
158
- if width = opts['width']
158
+ if (width = opts['width'])
159
159
  if width =~ /^\d+(\.\d+)?(em|px)$/
160
160
  attrs << %{width="#{width}"}
161
161
  end
162
162
  end
163
163
 
164
- if height = opts['height']
164
+ if (height = opts['height'])
165
165
  if height =~ /^\d+(\.\d+)?(em|px)$/
166
166
  attrs << %{height="#{height}"}
167
167
  end
168
168
  end
169
169
 
170
- if alt = opts['alt']
170
+ if (alt = opts['alt'])
171
171
  attrs << %{alt="#{alt}"}
172
172
  end
173
173
 
@@ -207,6 +207,7 @@ class Gollum::Filter::Tags < Gollum::Filter
207
207
  # nil if it is not.
208
208
  def process_external_link_tag(tag)
209
209
  parts = tag.split('|')
210
+ parts.reverse! if @markup.reverse_links?
210
211
  return if parts.size.zero?
211
212
  if parts.size == 1
212
213
  url = parts[0].strip
@@ -245,11 +246,11 @@ class Gollum::Filter::Tags < Gollum::Filter
245
246
 
246
247
  name = parts[0].strip
247
248
  path = parts[1] && parts[1].strip
248
- path = if path && file = @markup.find_file(path)
249
- ::File.join @markup.wiki.base_path, file.path
250
- else
251
- nil
252
- end
249
+ if path && file = @markup.find_file(path)
250
+ path = ::File.join @markup.wiki.base_path, file.path
251
+ else
252
+ path = nil
253
+ end
253
254
 
254
255
  if name && path && file
255
256
  %{<a href="#{::File.join @markup.wiki.base_path, file.path}">#{name}</a>}
@@ -269,7 +270,7 @@ class Gollum::Filter::Tags < Gollum::Filter
269
270
  # if it is not.
270
271
  def process_page_link_tag(tag)
271
272
  parts = tag.split('|')
272
- parts.reverse! if @markup.format == :mediawiki
273
+ parts.reverse! if @markup.reverse_links?
273
274
 
274
275
  name, page_name = *parts.compact.map(&:strip)
275
276
  cname = @markup.wiki.page_class.cname(page_name || name)
@@ -313,7 +314,7 @@ class Gollum::Filter::Tags < Gollum::Filter
313
314
  if page
314
315
  return page
315
316
  end
316
- if pos = cname.index('#')
317
+ if (pos = cname.index('#'))
317
318
  [@markup.wiki.page(cname[0...pos]), cname[pos..-1]]
318
319
  end
319
320
  end
@@ -78,22 +78,22 @@ class Gollum::Filter::TOC < Gollum::Filter
78
78
  # Adds an entry to the TOC for the given header. The generated entry
79
79
  # is a link to the given anchor name
80
80
  def add_entry_to_toc(header, name)
81
- @toc ||= Nokogiri::XML::DocumentFragment.parse('<div class="toc"><div class="toc-title">Table of Contents</div></div>')
82
- tail ||= @toc.child
83
- tail_level ||= 0
81
+ @toc ||= Nokogiri::XML::DocumentFragment.parse('<div class="toc"><div class="toc-title">Table of Contents</div></div>')
82
+ tail ||= @toc.child
83
+ tail_level ||= 0
84
84
 
85
85
  level = header.name.gsub(/[hH]/, '').to_i
86
86
 
87
87
  while tail_level < level
88
- node = Nokogiri::XML::Node.new('ul', @doc)
89
- tail = tail.add_child(node)
88
+ node = Nokogiri::XML::Node.new('ul', @doc)
89
+ tail = tail.add_child(node)
90
90
  tail_level += 1
91
91
  end
92
92
 
93
93
  while tail_level > level
94
- tail = tail.parent
94
+ tail = tail.parent
95
95
  tail_level -= 1
96
- end
96
+ end
97
97
  node = Nokogiri::XML::Node.new('li', @doc)
98
98
  # % -> %25 so anchors work on Firefox. See issue #475
99
99
  node.add_child(%Q{<a href="##{name}">#{header.content}</a>})
@@ -16,8 +16,8 @@ class Gollum::Filter::WSD < Gollum::Filter
16
16
  def extract(data)
17
17
  return data if @markup.format == :txt
18
18
  data.gsub(/^\{\{\{\{\{\{ ?(.+?)\r?\n(.+?)\r?\n\}\}\}\}\}\}\r?$/m) do
19
- id = Digest::SHA1.hexdigest($2)
20
- @map[id] = { :style => $1, :code => $2 }
19
+ id = Digest::SHA1.hexdigest(Regexp.last_match[2])
20
+ @map[id] = { :style => Regexp.last_match[1], :code => Regexp.last_match[2] }
21
21
  id
22
22
  end
23
23
  end
@@ -44,7 +44,7 @@ class Gollum::Filter::WSD < Gollum::Filter
44
44
  def render_wsd(code, style)
45
45
  response = Net::HTTP.post_form(URI.parse(WSD_URL), 'style' => style, 'message' => code)
46
46
  if response.body =~ /img: "(.+)"/
47
- url = "//www.websequencediagrams.com/#{$1}"
47
+ url = "//www.websequencediagrams.com/#{Regexp.last_match[1]}"
48
48
  "<img src=\"#{url}\" />"
49
49
  else
50
50
  puts response.body
@@ -49,7 +49,7 @@ module Gollum
49
49
  #
50
50
  # Returns an Array of BlobEntry instances.
51
51
  def tree(ref)
52
- if sha = ref_to_sha(ref)
52
+ if (sha = ref_to_sha(ref))
53
53
  get_cache(:tree, sha) { tree!(sha) }
54
54
  else
55
55
  []
@@ -74,10 +74,10 @@ module Gollum
74
74
  if sha?(ref)
75
75
  get_cache(:commit, ref) { commit!(ref) }
76
76
  else
77
- if sha = get_cache(:ref, ref)
77
+ if (sha = get_cache(:ref, ref))
78
78
  commit(sha)
79
79
  else
80
- if cm = commit!(ref)
80
+ if (cm = commit!(ref))
81
81
  set_cache(:ref, ref, cm.id)
82
82
  set_cache(:commit, cm.id, cm)
83
83
  end
@@ -164,7 +164,7 @@ module Gollum
164
164
  items << BlobEntry.new(entry[:sha], entry[:path], entry[:size], entry[:mode].to_i(8))
165
165
  end
166
166
  end
167
- if dir = @page_file_dir
167
+ if (dir = @page_file_dir)
168
168
  regex = /^#{dir}\//
169
169
  items.select { |i| i.path =~ regex }
170
170
  else
@@ -226,7 +226,7 @@ module Gollum
226
226
  #
227
227
  # Returns an Array of BlobEntry instances.
228
228
  def parse_tree_line(line)
229
- mode, type, sha, size, *name = line.split(/\s+/)
229
+ mode, _type, sha, size, *name = line.split(/\s+/)
230
230
  BlobEntry.new(sha, name.join(' '), size.to_i, mode.to_i(8))
231
231
  end
232
232
 
@@ -240,7 +240,7 @@ module Gollum
240
240
  path = path[1...-1]
241
241
  path.gsub!(/\\\d{3}/) { |m| m[1..-1].to_i(8).chr }
242
242
  end
243
- path.gsub!(/\\[rn"\\]/) { |m| eval(%("#{m.to_s}")) }
243
+ path.gsub!(/\\[rn"\\]/) { |m| eval(%("#{m}")) }
244
244
  path
245
245
  end
246
246
  end