gollum-lib 5.0.a.4-java → 5.0.5-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 +4 -4
- data/Gemfile +2 -1
- data/HISTORY.md +4 -0
- data/README.md +12 -7
- data/Rakefile +8 -7
- data/gemspec.rb +17 -10
- data/gollum-lib.gemspec +8 -6
- data/gollum-lib_java.gemspec +2 -2
- data/lib/gollum-lib.rb +9 -9
- data/lib/gollum-lib/blob_entry.rb +2 -8
- data/lib/gollum-lib/committer.rb +23 -61
- data/lib/gollum-lib/file.rb +105 -82
- data/lib/gollum-lib/file_view.rb +8 -4
- data/lib/gollum-lib/filter.rb +12 -0
- data/lib/gollum-lib/filter/code.rb +9 -13
- data/lib/gollum-lib/filter/critic_markup.rb +97 -0
- data/lib/gollum-lib/filter/emoji.rb +11 -8
- data/lib/gollum-lib/filter/macro.rb +5 -2
- data/lib/gollum-lib/filter/plantuml.rb +1 -1
- data/lib/gollum-lib/filter/remote_code.rb +3 -2
- data/lib/gollum-lib/filter/render.rb +25 -2
- data/lib/gollum-lib/filter/sanitize.rb +1 -8
- data/lib/gollum-lib/filter/tags.rb +57 -46
- data/lib/gollum-lib/filter/toc.rb +17 -21
- data/lib/gollum-lib/filter/yaml.rb +1 -1
- data/lib/gollum-lib/git_access.rb +0 -25
- data/lib/gollum-lib/helpers.rb +13 -3
- data/lib/gollum-lib/macro.rb +4 -0
- data/lib/gollum-lib/macro/audio.rb +9 -0
- data/lib/gollum-lib/macro/global_toc.rb +2 -1
- data/lib/gollum-lib/macro/navigation.rb +8 -6
- data/lib/gollum-lib/macro/note.rb +19 -0
- data/lib/gollum-lib/macro/octicon.rb +12 -0
- data/lib/gollum-lib/macro/series.rb +2 -2
- data/lib/gollum-lib/macro/warn.rb +11 -0
- data/lib/gollum-lib/markup.rb +17 -32
- data/lib/gollum-lib/markups.rb +13 -8
- data/lib/gollum-lib/page.rb +80 -166
- data/lib/gollum-lib/pagination.rb +7 -6
- data/lib/gollum-lib/redirects.rb +42 -0
- data/lib/gollum-lib/sanitization.rb +32 -357
- data/lib/gollum-lib/version.rb +1 -1
- data/lib/gollum-lib/wiki.rb +216 -404
- metadata +65 -27
- data/ROADMAP +0 -6
data/lib/gollum-lib/file.rb
CHANGED
@@ -2,55 +2,125 @@
|
|
2
2
|
|
3
3
|
module Gollum
|
4
4
|
class File
|
5
|
-
|
5
|
+
|
6
|
+
# Does the filesystem support reading symlinks?
|
7
|
+
FS_SUPPORT_SYMLINKS = !Gem.win_platform?
|
8
|
+
|
9
|
+
class << self
|
10
|
+
|
11
|
+
# For use with self.find: returns true if the given query corresponds to the in-repo path of the BlobEntry.
|
12
|
+
#
|
13
|
+
# query - The String path to match.
|
14
|
+
# entry - The BlobEntry to check against.
|
15
|
+
# global_match - (Not implemented for File, see Page.path_match)
|
16
|
+
# hyphened_tags - If true, replace spaces in match_path with hyphens.
|
17
|
+
# case_insensitive - If true, compare query and match_path case-insensitively
|
18
|
+
def path_match(query, entry, global_match = false, hyphened_tags = false, case_insensitive = false)
|
19
|
+
path_compare(query, ::File.join('/', entry.path), hyphened_tags, case_insensitive)
|
20
|
+
end
|
21
|
+
|
22
|
+
# For use with self.path_match: returns true if 'query' and 'match_path' match, strictly or taking account of the following parameters:
|
23
|
+
# hyphened_tags - If true, replace spaces in match_path with hyphens.
|
24
|
+
# case_insensitive - If true, compare query and match_path case-insensitively
|
25
|
+
def path_compare(query, match_path, hyphened_tags, case_insensitive)
|
26
|
+
if hyphened_tags
|
27
|
+
final_query = query.gsub(' ', '-')
|
28
|
+
final_match = match_path.gsub(' ', '-')
|
29
|
+
else
|
30
|
+
final_query = query
|
31
|
+
final_match = match_path
|
32
|
+
end
|
33
|
+
final_match.send(case_insensitive ? :casecmp? : :==, final_query)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Find a file in the given Gollum wiki.
|
38
|
+
#
|
39
|
+
# wiki - The wiki.
|
40
|
+
# path - The full String path.
|
41
|
+
# version - The String version ID to find.
|
42
|
+
# try_on_disk - If true, try to return just a reference to a file
|
43
|
+
# that exists on the disk.
|
44
|
+
# global_match - If true, find a File matching path's filename, but not it's directory (so anywhere in the repo)
|
45
|
+
#
|
46
|
+
# Returns a Gollum::File or nil if the file could not be found. Note
|
47
|
+
# that if you specify try_on_disk=true, you may or may not get a file
|
48
|
+
# for which on_disk? is actually true.
|
49
|
+
def self.find(wiki, path, version, try_on_disk = false, global_match = false)
|
50
|
+
map = wiki.tree_map_for(version.to_s)
|
51
|
+
|
52
|
+
query_path = Pathname.new(::File.join(['/', wiki.page_file_dir, path].compact)).cleanpath.to_s
|
53
|
+
query_path.sub!(/^\/\//, '/') if Gem.win_platform? # On Windows, Pathname#cleanpath will leave double slashes at the start of a path intact, so sub them out.
|
54
|
+
|
55
|
+
begin
|
56
|
+
entry = map.detect do |entry|
|
57
|
+
path_match(query_path, entry, global_match, wiki.hyphened_tag_lookup, wiki.case_insensitive_tag_lookup)
|
58
|
+
end
|
59
|
+
entry ? self.new(wiki, entry.blob(wiki.repo), entry.dir, version, try_on_disk) : nil
|
60
|
+
rescue Gollum::Git::NoSuchShaFound
|
61
|
+
nil
|
62
|
+
end
|
63
|
+
end
|
6
64
|
|
7
65
|
# Public: Initialize a file.
|
8
66
|
#
|
9
|
-
# wiki - The Gollum::Wiki
|
67
|
+
# wiki - The Gollum::Wiki
|
68
|
+
# blob - The Gollum::Git::Blob
|
69
|
+
# path - The String path
|
70
|
+
# version - The String SHA or Gollum::Git::Commit version
|
71
|
+
# try_on_disk - If true, try to get an on disk reference for this file.
|
10
72
|
#
|
11
73
|
# Returns a newly initialized Gollum::File.
|
12
|
-
def initialize(wiki)
|
74
|
+
def initialize(wiki, blob, path, version, try_on_disk = false)
|
13
75
|
@wiki = wiki
|
14
|
-
@blob =
|
15
|
-
@path =
|
16
|
-
@
|
17
|
-
|
76
|
+
@blob = blob
|
77
|
+
@path = "#{path}/#{blob.name}"[1..-1]
|
78
|
+
@version = version.is_a?(Gollum::Git::Commit) ? version : @wiki.commit_for(version)
|
79
|
+
get_disk_reference if try_on_disk
|
18
80
|
end
|
19
81
|
|
20
|
-
# Public: The
|
82
|
+
# Public: The path of the page within the repo.
|
21
83
|
#
|
22
|
-
# Returns the String
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
end
|
84
|
+
# Returns the String path.
|
85
|
+
attr_reader :path
|
86
|
+
|
87
|
+
# Public: The Gollum::Git::Commit version of the file.
|
88
|
+
attr_accessor :version
|
28
89
|
|
29
|
-
# Public:
|
90
|
+
# Public: Whether the file can be read from disk.
|
91
|
+
attr_accessor :on_disk
|
92
|
+
|
93
|
+
# Public: The SHA hash identifying this page
|
30
94
|
#
|
31
95
|
# Returns the String SHA.
|
32
96
|
def sha
|
33
97
|
@blob && @blob.id
|
34
98
|
end
|
35
99
|
|
36
|
-
# Public: The
|
100
|
+
# Public: The on-disk filename of the page including extension.
|
37
101
|
#
|
38
|
-
# Returns the String
|
39
|
-
def
|
40
|
-
|
102
|
+
# Returns the String name.
|
103
|
+
def filename
|
104
|
+
@blob && @blob.name
|
41
105
|
end
|
106
|
+
alias :name :filename
|
42
107
|
|
43
|
-
# Public: The
|
108
|
+
# Public: The url path required to reach this file within the repo.
|
44
109
|
#
|
45
|
-
# Returns the String
|
46
|
-
def
|
47
|
-
|
48
|
-
@
|
110
|
+
# Returns the String url_path
|
111
|
+
def url_path
|
112
|
+
# Chop off the page_file_dir and first slash if necessary
|
113
|
+
@wiki.page_file_dir ? self.path[@wiki.page_file_dir.length+1..-1] : self.path
|
49
114
|
end
|
50
115
|
|
51
|
-
|
116
|
+
# Public: The url_path, but URL encoded.
|
117
|
+
#
|
118
|
+
# Returns the String url_path
|
119
|
+
def escaped_url_path
|
120
|
+
ERB::Util.url_encode(self.url_path).gsub('%2F', '/').force_encoding('utf-8')
|
121
|
+
end
|
52
122
|
|
53
|
-
# Public: The raw contents of the
|
123
|
+
# Public: The raw contents of the file.
|
54
124
|
#
|
55
125
|
# Returns the String data.
|
56
126
|
def raw_data
|
@@ -69,7 +139,7 @@ module Gollum
|
|
69
139
|
#
|
70
140
|
# Returns true if this is a pointer to an on-disk file
|
71
141
|
def on_disk?
|
72
|
-
|
142
|
+
!!@on_disk
|
73
143
|
end
|
74
144
|
|
75
145
|
# Public: The path to this file on disk
|
@@ -79,48 +149,29 @@ module Gollum
|
|
79
149
|
@on_disk_path
|
80
150
|
end
|
81
151
|
|
82
|
-
# Public: The Gollum::Git::Commit version of the file.
|
83
|
-
attr_accessor :version
|
84
|
-
|
85
|
-
# Public: The String path of the file.
|
86
|
-
attr_reader :path
|
87
|
-
|
88
152
|
# Public: The String mime type of the file.
|
89
153
|
def mime_type
|
90
154
|
@blob && @blob.mime_type
|
91
155
|
end
|
92
156
|
|
93
|
-
|
94
|
-
|
95
|
-
# blob - The Gollum::Git::Blob that contains the info.
|
96
|
-
# path - The String directory path of the file.
|
97
|
-
#
|
98
|
-
# Returns the populated Gollum::File.
|
99
|
-
def populate(blob, path = nil)
|
100
|
-
@blob = blob
|
101
|
-
@path = "#{path}/#{blob.name}"[1..-1]
|
102
|
-
@on_disk = false
|
103
|
-
@on_disk_path = nil
|
104
|
-
self
|
157
|
+
def self.protected_files
|
158
|
+
['custom.css', 'custom.js', '.redirects.gollum']
|
105
159
|
end
|
106
160
|
|
107
|
-
|
108
|
-
#
|
109
|
-
# Internal Methods
|
110
|
-
#
|
111
|
-
#########################################################################
|
161
|
+
private
|
112
162
|
|
113
163
|
# Return the file path to this file on disk, if available.
|
114
164
|
#
|
115
165
|
# Returns nil if the file isn't available on disk. This can occur if the
|
116
166
|
# repo is bare, if the commit isn't the HEAD, or if there are problems
|
117
167
|
# resolving symbolic links.
|
118
|
-
def get_disk_reference
|
168
|
+
def get_disk_reference
|
119
169
|
return false if @wiki.repo.bare
|
120
|
-
return false if
|
170
|
+
return false if @version.sha != @wiki.repo.head.commit.sha
|
171
|
+
return false if @blob.is_symlink && !FS_SUPPORT_SYMLINKS
|
121
172
|
|
122
173
|
# This will try to resolve symbolic links, as well
|
123
|
-
pathname = Pathname.new(::File.expand_path(::File.join(@wiki.repo.path, '..',
|
174
|
+
pathname = Pathname.new(::File.expand_path(::File.join(@wiki.repo.path, '..', @path)))
|
124
175
|
if pathname.symlink?
|
125
176
|
source = ::File.readlink(pathname.to_path)
|
126
177
|
realpath = ::File.join(::File.dirname(pathname.to_path), source)
|
@@ -129,36 +180,8 @@ module Gollum
|
|
129
180
|
else
|
130
181
|
@on_disk_path = pathname.to_path
|
131
182
|
end
|
132
|
-
true
|
183
|
+
@on_disk = true
|
133
184
|
end
|
134
185
|
|
135
|
-
# Find a file in the given Gollum repo.
|
136
|
-
#
|
137
|
-
# name - The full String path.
|
138
|
-
# version - The String version ID to find.
|
139
|
-
# try_on_disk - If true, try to return just a reference to a file
|
140
|
-
# that exists on the disk.
|
141
|
-
#
|
142
|
-
# Returns a Gollum::File or nil if the file could not be found. Note
|
143
|
-
# that if you specify try_on_disk=true, you may or may not get a file
|
144
|
-
# for which on_disk? is actually true.
|
145
|
-
def find(name, version, try_on_disk = false)
|
146
|
-
checked = name.downcase
|
147
|
-
map = @wiki.tree_map_for(version)
|
148
|
-
commit = version.is_a?(Gollum::Git::Commit) ? version : @wiki.commit_for(version)
|
149
|
-
|
150
|
-
if (result = map.detect { |entry| entry.path.downcase == checked })
|
151
|
-
@path = name
|
152
|
-
@version = commit
|
153
|
-
|
154
|
-
if try_on_disk && get_disk_reference(name, commit)
|
155
|
-
@on_disk = true
|
156
|
-
else
|
157
|
-
@blob = result.blob(@wiki.repo)
|
158
|
-
end
|
159
|
-
|
160
|
-
self
|
161
|
-
end
|
162
|
-
end
|
163
186
|
end
|
164
187
|
end
|
data/lib/gollum-lib/file_view.rb
CHANGED
@@ -10,12 +10,13 @@ module Gollum
|
|
10
10
|
# set pages to wiki.pages + wiki.files and show_all to true
|
11
11
|
def initialize(pages, options = {})
|
12
12
|
@pages = pages
|
13
|
+
@wiki = @pages.first ? @pages.first.wiki : nil
|
13
14
|
@show_all = options[:show_all] || false
|
14
15
|
@checked = options[:collapse_tree] ? '' : "checked"
|
15
16
|
end
|
16
17
|
|
17
18
|
def enclose_tree(string)
|
18
|
-
%Q(<ol class="tree">\n) + string + %Q(</ol>)
|
19
|
+
sanitize_html(%Q(<ol class="tree">\n) + string + %Q(</ol>))
|
19
20
|
end
|
20
21
|
|
21
22
|
def new_page(page)
|
@@ -96,7 +97,7 @@ module Gollum
|
|
96
97
|
</li>
|
97
98
|
HTML
|
98
99
|
|
99
|
-
return enclose_tree
|
100
|
+
return enclose_tree(html)
|
100
101
|
end
|
101
102
|
|
102
103
|
sorted_folders = []
|
@@ -153,8 +154,11 @@ module Gollum
|
|
153
154
|
changed = false
|
154
155
|
end
|
155
156
|
|
156
|
-
|
157
|
-
enclose_tree html
|
157
|
+
enclose_tree(html)
|
158
158
|
end # end render_files
|
159
|
+
|
160
|
+
def sanitize_html(data)
|
161
|
+
@wiki ? @wiki.sanitizer.clean(data) : data
|
162
|
+
end
|
159
163
|
end # end FileView class
|
160
164
|
end # end Gollum module
|
data/lib/gollum-lib/filter.rb
CHANGED
@@ -47,14 +47,21 @@ module Gollum
|
|
47
47
|
class Filter
|
48
48
|
include Gollum::Helpers
|
49
49
|
|
50
|
+
PLACEHOLDER_PATTERN = /%(\S+)%.+=\1=/
|
51
|
+
|
50
52
|
# Setup the object. Sets `@markup` to be the instance of Gollum::Markup that
|
51
53
|
# is running this filter chain, and sets `@map` to be an empty hash (for use
|
52
54
|
# in your extract/process operations).
|
55
|
+
|
53
56
|
def initialize(markup)
|
54
57
|
@markup = markup
|
55
58
|
@map = {}
|
59
|
+
@open_pattern = "%#{self.class.to_s.split('::').last}%"
|
60
|
+
@close_pattern = "=#{self.class.to_s.split('::').last}="
|
56
61
|
end
|
57
62
|
|
63
|
+
attr_reader :open_pattern, :close_pattern
|
64
|
+
|
58
65
|
def extract(data)
|
59
66
|
raise RuntimeError,
|
60
67
|
"#{self.class} has not implemented ##extract!"
|
@@ -66,6 +73,11 @@ module Gollum
|
|
66
73
|
end
|
67
74
|
|
68
75
|
protected
|
76
|
+
|
77
|
+
def sanitize(data)
|
78
|
+
@markup.wiki.sanitizer.clean(data, @markup.historical)
|
79
|
+
end
|
80
|
+
|
69
81
|
# Render a (presumably) non-fatal error as HTML
|
70
82
|
#
|
71
83
|
def html_error(message)
|
@@ -14,31 +14,27 @@ class Gollum::Filter::Code < Gollum::Filter
|
|
14
14
|
org_headers = %r{([ \t]*#\+HEADER[S]?:[^\r\n]*\n)*}
|
15
15
|
org_name = %r{([ \t]*#\+NAME:[^\r\n]*\n)?}
|
16
16
|
org_lang = %r{[ ]*([^\n \r]*)[ ]*[^\r\n]*}
|
17
|
-
org_begin = %r{[ \t]
|
18
|
-
org_end = %r{\n[ \t]*#\+END_SRC[ \t]*}
|
17
|
+
org_begin = %r{([ \t]*)#\+BEGIN_SRC#{org_lang}\r?\n}
|
18
|
+
org_end = %r{\r?\n[ \t]*#\+END_SRC[ \t\r]*}
|
19
19
|
data.gsub!(/^#{org_headers}#{org_name}#{org_begin}(.+?)#{org_end}$/mi) do
|
20
|
-
cache_codeblock(Regexp.last_match[
|
20
|
+
"#{Regexp.last_match[3]}#{cache_codeblock(Regexp.last_match[4], Regexp.last_match[5])}"
|
21
21
|
end
|
22
22
|
when :markdown
|
23
|
-
data.gsub!(/^([
|
23
|
+
data.gsub!(/^([ ]{0,3})(~~~+) ?([^\r\n]+)?\r?\n(.+?)\r?\n[ ]{0,3}(~~~+)[ \t\r]*$/m) do
|
24
24
|
m_indent = Regexp.last_match[1]
|
25
25
|
m_start = Regexp.last_match[2] # ~~~
|
26
26
|
m_lang = Regexp.last_match[3]
|
27
27
|
m_code = Regexp.last_match[4]
|
28
28
|
m_end = Regexp.last_match[5] # ~~~
|
29
|
-
#
|
30
|
-
next '' if
|
31
|
-
lang = m_lang ? m_lang.strip : nil
|
32
|
-
if lang
|
33
|
-
lang = lang.match(/\.([^}\s]+)/)
|
34
|
-
lang = lang[1] unless lang.nil?
|
35
|
-
end
|
29
|
+
# The closing code fence must be at least as long as the opening fence
|
30
|
+
next '' if m_end.length < m_start.length
|
31
|
+
lang = m_lang ? m_lang.strip.split.first : nil
|
36
32
|
"#{m_indent}#{cache_codeblock(lang, m_code, m_indent)}"
|
37
33
|
end
|
38
34
|
end
|
39
35
|
|
40
36
|
|
41
|
-
data.gsub!(/^([
|
37
|
+
data.gsub!(/^([ ]{0,3})``` ?([^\r\n]+)?\r?\n(.+?)\r?\n[ ]{0,3}```[ \t]*\r?$/m) do
|
42
38
|
"#{Regexp.last_match[1]}#{cache_codeblock(Regexp.last_match[2].to_s.strip, Regexp.last_match[3], Regexp.last_match[1])}" # print the SHA1 ID with the proper indentation
|
43
39
|
end
|
44
40
|
data
|
@@ -133,7 +129,7 @@ class Gollum::Filter::Code < Gollum::Filter
|
|
133
129
|
|
134
130
|
def cache_codeblock(language, code, indent = "")
|
135
131
|
language = language.to_s.empty? ? nil : language
|
136
|
-
id = Digest::SHA1.hexdigest("#{language}.#{code}")
|
132
|
+
id = "#{open_pattern}#{Digest::SHA1.hexdigest("#{language}.#{code}")}#{close_pattern}"
|
137
133
|
cached = @markup.check_cache(:code, id)
|
138
134
|
@map[id] = cached ?
|
139
135
|
{ :output => cached } :
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# ~*~ encoding: utf-8 ~*~
|
2
|
+
|
3
|
+
# CriticMarkup
|
4
|
+
#
|
5
|
+
# Render CriticMarkup
|
6
|
+
|
7
|
+
class Gollum::Filter::CriticMarkup < Gollum::Filter
|
8
|
+
|
9
|
+
# Patterns inspired by https://github.com/DivineDominion/criticmarkup.tmbundle/blob/master/Syntaxes/criticmarkup.tmLanguage
|
10
|
+
# All patterns use multiline matching (m flag)
|
11
|
+
# Logic inspired by https://github.com/CriticMarkup/CriticMarkup-toolkit/blob/master/CLI/criticParser_CLI.py
|
12
|
+
|
13
|
+
ADDITION_PATTERN = %r|{\+\+(?<content>.*?)\+\+[ \t]*(\[(.*?)\])?[ \t]*\}|m
|
14
|
+
DELETION_PATTERN = %r|{--(?<content>.*?)--[ \t]*(\[(.*?)\])?[ \t]*\}|m
|
15
|
+
SUBSTITUTION_PATTERN = %r|{~~(?<oldcontent>.*?)~>(?<newcontent>.*?)~~}|m
|
16
|
+
HIGHLIGHT_PATTERN = %r|{\=\=(?<content>.*?)[ \t]*(\[(.*?)\])?[ \t]*\=\=\}{>>(?<comment>.*?)<<}|m
|
17
|
+
COMMENT_PATTERN = %r|{>>(?<content>.*?)<<}|m
|
18
|
+
|
19
|
+
def extract(data)
|
20
|
+
data.gsub! ADDITION_PATTERN do
|
21
|
+
content = $~[:content]
|
22
|
+
placeholder = generate_placeholder("#{content}#{@map.size}")
|
23
|
+
# Is there a new paragraph followed by new text
|
24
|
+
if content.start_with?("\n\n") && content != "\n\n"
|
25
|
+
html = "\n\n<ins class='critic break'> </ins>\n\n<ins>#{content.gsub('\n', ' ')}</ins>"
|
26
|
+
# Is the addition just a single new paragraph
|
27
|
+
elsif content == "\n\n"
|
28
|
+
html = "\n\n<ins class='critic break'> </ins>\n\n"
|
29
|
+
# Is it added text followed by a new paragraph?
|
30
|
+
elsif content.end_with?("\n\n") && content != "\n\n"
|
31
|
+
html = "<ins>#{content.gsub('\n', ' ')}</ins>\n\n<ins class='critic break'> </ins>\n\n"
|
32
|
+
else
|
33
|
+
html = "<ins>#{content.gsub('\n', ' ')}</ins>"
|
34
|
+
end
|
35
|
+
@map[placeholder] = html
|
36
|
+
placeholder
|
37
|
+
end
|
38
|
+
|
39
|
+
data.gsub! DELETION_PATTERN do
|
40
|
+
content = $~[:content]
|
41
|
+
placeholder = generate_placeholder("#{content}#{@map.size}")
|
42
|
+
if content == "\n\n"
|
43
|
+
html = "<del> </del>"
|
44
|
+
else
|
45
|
+
html = "<del>#{content.gsub('\n\n', ' ')}</del>"
|
46
|
+
end
|
47
|
+
@map[placeholder] = html
|
48
|
+
placeholder
|
49
|
+
end
|
50
|
+
|
51
|
+
data.gsub! SUBSTITUTION_PATTERN do
|
52
|
+
oldcontent = $~[:oldcontent]
|
53
|
+
newcontent = $~[:newcontent]
|
54
|
+
placeholder = generate_placeholder("#{oldcontent}#{newcontent}#{@map.size}")
|
55
|
+
html = "<del>#{oldcontent}</del><ins>#{newcontent}</ins>"
|
56
|
+
@map[placeholder] = html
|
57
|
+
placeholder
|
58
|
+
end
|
59
|
+
|
60
|
+
data.gsub! HIGHLIGHT_PATTERN do
|
61
|
+
content = $~[:content]
|
62
|
+
comment = $~[:comment]
|
63
|
+
placeholder = generate_placeholder("#{content}#{@map.size}")
|
64
|
+
html = "<mark>#{content}</mark><span class='critic comment'>#{comment}</span>"
|
65
|
+
@map[placeholder] = html
|
66
|
+
placeholder
|
67
|
+
end
|
68
|
+
|
69
|
+
data.gsub! COMMENT_PATTERN do
|
70
|
+
content = $~[:content]
|
71
|
+
placeholder = generate_placeholder("#{content}#{@map.size}")
|
72
|
+
html = "<span class='critic comment'>#{content}</span>"
|
73
|
+
@map[placeholder] = html
|
74
|
+
placeholder
|
75
|
+
end
|
76
|
+
|
77
|
+
data
|
78
|
+
end
|
79
|
+
|
80
|
+
def process(data)
|
81
|
+
data.gsub! process_pattern do
|
82
|
+
@map[$~[:placeholder]]
|
83
|
+
end
|
84
|
+
data
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def process_pattern
|
90
|
+
/(?<placeholder>#{open_pattern}\h{40}#{close_pattern})/
|
91
|
+
end
|
92
|
+
|
93
|
+
def generate_placeholder(content)
|
94
|
+
"#{open_pattern}#{Digest::SHA1.hexdigest(content)}#{close_pattern}"
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|