caramelize 1.2.1 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,22 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Caramelize
4
- module Filter
5
- class AddNewlineToPageEnd
6
- def initialize(body)
7
- @body = body
8
- end
4
+ class AddNewlineToPageEnd
5
+ def initialize(body)
6
+ @body = body
7
+ end
9
8
 
10
- # take an input stream and convert all wikka syntax to markdown syntax
11
- def run
12
- return @body if @body[@body.length - 1] == "\n"
9
+ # take an input stream and convert all wikka syntax to markdown syntax
10
+ def run
11
+ return @body if @body[@body.length - 1] == "\n"
13
12
 
14
- migrated_body = @body.dup
13
+ migrated_body = @body.dup
15
14
 
16
- migrated_body << "\n"
15
+ migrated_body << "\n"
17
16
 
18
- migrated_body
19
- end
17
+ migrated_body
20
18
  end
21
19
  end
22
20
  end
@@ -18,8 +18,8 @@ module Caramelize
18
18
  private
19
19
 
20
20
  def format_link(link)
21
- link.gsub!(' ', '_')
22
- link.gsub!('.', '')
21
+ link.tr!(' ', '_')
22
+ link.delete!('.')
23
23
  "[[#{link}]]"
24
24
  end
25
25
  end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'paru/pandoc'
4
+
5
+ module Caramelize
6
+ class MediawikiToMarkdown
7
+ attr_reader :source_body
8
+
9
+ def initialize(source_body)
10
+ @source_body = source_body
11
+ end
12
+
13
+ def run
14
+ Paru::Pandoc.new do
15
+ from 'mediawiki'
16
+ to 'markdown'
17
+ markdown_headings 'atx'
18
+ end << source_body.dup
19
+ end
20
+ end
21
+ end
@@ -20,8 +20,8 @@ module Caramelize
20
20
 
21
21
  def format_link(label, link)
22
22
  link.downcase!
23
- link.gsub!(' ', '_')
24
- link.gsub!('.', '')
23
+ link.tr!(' ', '_')
24
+ link.delete!('.')
25
25
  "[[#{label}|#{link}]]"
26
26
  end
27
27
  end
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Caramelize
4
- class Wikka2Markdown
4
+ # WikkaWiki formatting rules: http://docs.wikkawiki.org/FormattingRules
5
+ class WikkaToMarkdown
5
6
  attr_reader :source_body
6
7
 
7
8
  def initialize(source_body)
@@ -9,9 +10,6 @@ module Caramelize
9
10
  end
10
11
 
11
12
  def run
12
- # TODO: images: ({{image)(url\=?)?(.*)(}})
13
- # markdown: ![Tux, the Linux mascot](/assets/images/tux.png)
14
-
15
13
  replace_headlines
16
14
  replace_formatting
17
15
  replace_lists
@@ -19,6 +17,7 @@ module Caramelize
19
17
  replace_links
20
18
  replace_inline_code
21
19
  replace_code_block
20
+ replace_images
22
21
 
23
22
  target_body
24
23
  end
@@ -43,8 +42,7 @@ module Caramelize
43
42
  target_body.gsub!(/(~-\s?)(.*)/, '- \2') # unordered list
44
43
  target_body.gsub!(/( -\s?)(.*)/, '- \2') # unordered list
45
44
 
46
- target_body.gsub!(/(~1\)\s?)(.*)/, '1. \2') # unordered list
47
- # TODO ordered lists
45
+ target_body.gsub!(/(~1\)\s?)(.*)/, '1. \2') # ordered list
48
46
  end
49
47
 
50
48
  def replace_wiki_links
@@ -66,6 +64,17 @@ module Caramelize
66
64
  target_body.gsub!(/^%%\s(.*?)%%\s?/m) { "```\n#{::Regexp.last_match(1)}```\n" }
67
65
  end
68
66
 
67
+ def replace_images
68
+ # {{image class="center" alt="DVD logo" title="An image link" url="images/dvdvideo.gif" link="RecentChanges"}}
69
+ target_body.gsub!(/{{image\s(.*)}}/) do |image_match|
70
+ url = image_match.match(/url="([^"]*)"/)[1]
71
+ link = image_match.match(/link="([^"]*)"/) && image_match.match(/link="([^"]*)"/)[1]
72
+ alt = image_match.match(/alt="([^"]*)"/) && image_match.match(/alt="([^"]*)"/)[1]
73
+
74
+ link.nil? ? "![#{alt}](#{url})" : "[[<img src=\"#{url}\" alt=\"#{alt}\">|#{link}]]"
75
+ end
76
+ end
77
+
69
78
  def target_body
70
79
  @target_body ||= source_body.dup
71
80
  end
@@ -18,7 +18,7 @@ module Caramelize
18
18
 
19
19
  private
20
20
 
21
- def check_page(page) # rubocop:todo Metrics/MethodLength
21
+ def check_page(page)
22
22
  0.tap do |available_count|
23
23
  page.intra_wiki_links.each do |intra_wiki_path|
24
24
  if page_paths.include?(intra_wiki_path)
@@ -0,0 +1,114 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'caramelize/filters/add_newline_to_page_end'
4
+ require 'caramelize/filters/mediawiki_to_markdown'
5
+
6
+ module Caramelize
7
+ module InputWiki
8
+ class MediaWiki < Wiki
9
+ include DatabaseConnector
10
+
11
+ # for Mediawiki v1.41
12
+ SQL_PAGES = %{
13
+ SELECT *
14
+ FROM revision as r
15
+ JOIN page as p on r.rev_page = p.page_id
16
+ JOIN comment as c ON c.comment_id = r.rev_comment_id
17
+ JOIN actor as a ON a.actor_id = r.rev_actor
18
+ JOIN slots as s ON s.slot_revision_id = r.rev_id
19
+ JOIN content as cn ON cn.`content_id` = s.slot_content_id
20
+ JOIN text as t ON cn.content_address = CONCAT('tt:', t.old_id)
21
+ ORDER BY r.rev_timestamp ASC;
22
+ }
23
+ SQL_AUTHORS = 'SELECT user_id, user_name, user_real_name, user_email FROM user;'
24
+ NAMESPACE_MAPPING = {
25
+ 0 => :NS_MAIN,
26
+ 1 => :NS_TALK,
27
+ 2 => :NS_USER,
28
+ 3 => :NS_USER_TALK,
29
+ 4 => :NS_PROJECT,
30
+ 5 => :NS_PROJECT_TALK,
31
+ 6 => :NS_FILE,
32
+ 7 => :NS_FILE_TALK,
33
+ 8 => :NS_MEDIAWIKI,
34
+ 9 => :NS_MEDIAWIKI_TALK,
35
+ 10 => :NS_TEMPLATE,
36
+ 11 => :NS_TEMPLATE_TALK,
37
+ 12 => :NS_HELP,
38
+ 13 => :NS_HELP_TALK,
39
+ 14 => :NS_CATEGORY,
40
+ 15 => :NS_CATEGORY_TALK
41
+ }.freeze
42
+
43
+ def initialize(options = {})
44
+ super(options)
45
+ @options[:markup] = :media_wiki
46
+ @options[:filters] << Caramelize::AddNewlineToPageEnd
47
+ @options[:filters] << ::Caramelize::MediawikiToMarkdown
48
+ end
49
+
50
+ # after calling this action, titles and @revisions are expected to be filled
51
+ def read_pages
52
+ pages.each do |row|
53
+ titles << row['page_title']
54
+ revisions << Page.new(build_properties(row))
55
+ end
56
+ titles.uniq!
57
+ revisions
58
+ end
59
+
60
+ def read_authors
61
+ database.query(authors_query).each do |row|
62
+ name = row['user_real_name'].empty? ? row['user_name'] : 'Anonymous'
63
+ email = row['user_email'].empty? ? nil : row['user_email']
64
+ authors[row['user_id']] = { name:, email: }
65
+ end
66
+
67
+ authors
68
+ end
69
+
70
+ def excluded_pages
71
+ []
72
+ end
73
+
74
+ private
75
+
76
+ def pages_query
77
+ SQL_PAGES
78
+ end
79
+
80
+ def authors_query
81
+ SQL_AUTHORS
82
+ end
83
+
84
+ def pages
85
+ @pages ||= database.query(pages_query)
86
+ end
87
+
88
+ def build_properties(row)
89
+ author = authors[row['actor_user']] || { name: 'Anonymous', email: 'anonymous@example.com' }
90
+ {
91
+ id: row['rev_id'],
92
+ title: title_by_namespace(row),
93
+ body: row['old_text'],
94
+ markup: :media_wiki,
95
+ latest: row['page_latest'] == row['rev_id'],
96
+ time: Time.strptime(row['rev_timestamp'], '%Y%m%d%H%M%S'),
97
+ message: row['comment_text'],
98
+ author:
99
+ }
100
+ end
101
+
102
+ def title_by_namespace(row)
103
+ return row['page_title'] if namespace_matches?(row['page_namespace'], :NS_MAIN)
104
+ return "#{row['page_title']}_Discussion" if namespace_matches?(row['page_namespace'], :NS_TALK)
105
+
106
+ row['page_title']
107
+ end
108
+
109
+ def namespace_matches?(namespace_id, expected_namespace)
110
+ NAMESPACE_MAPPING[namespace_id] == expected_namespace
111
+ end
112
+ end
113
+ end
114
+ end
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'caramelize/input_wiki/wiki'
4
3
  require 'caramelize/filters/swap_wiki_links'
5
4
  require 'caramelize/filters/remove_table_tab_line_endings'
6
5
 
@@ -12,8 +11,8 @@ module Caramelize
12
11
  def initialize(options = {})
13
12
  super(options)
14
13
  @options[:markup] = :textile
15
- @options[:filters] << Caramelize::SwapWikiLinks
16
- @options[:filters] << Caramelize::RemoveTableTabLineEndings
14
+ @options[:filters] << ::Caramelize::SwapWikiLinks
15
+ @options[:filters] << ::Caramelize::RemoveTableTabLineEndings
17
16
  @options[:create_namespace_overview] = true
18
17
  end
19
18
 
@@ -25,14 +24,13 @@ module Caramelize
25
24
  build_page(row_page)
26
25
  end
27
26
  titles.uniq!
28
- revisions.sort! { |a, b| a.time <=> b.time }
27
+ revisions.sort_by!(&:time)
29
28
 
30
29
  revisions
31
30
  end
32
31
 
33
32
  def read_authors
34
- results = database.query(authors_query)
35
- results.each do |row|
33
+ database.query(authors_query).each do |row|
36
34
  authors[row['id']] = { id: row['id'],
37
35
  name: row['login'],
38
36
  email: row['mail'] }
@@ -42,16 +40,15 @@ module Caramelize
42
40
 
43
41
  private
44
42
 
45
- # rubocop:todo Metrics/MethodLength
46
- def build_page(row_page) # rubocop:todo Metrics/AbcSize, Metrics/MethodLength
43
+ def build_page(row_page)
47
44
  results_contents = database.query(single_page_query(row_page['id']))
48
45
 
49
- wiki = wikis.select { |row| row['id'] == row_page['wiki_id'] }.first
46
+ wiki = wikis.find { |row| row['id'] == row_page['wiki_id'] }
50
47
 
51
48
  project_identifier = ''
52
49
 
53
50
  if wiki
54
- project = projects.select { |row| row['id'] == wiki['project_id'] }.first
51
+ project = projects.find { |row| row['id'] == wiki['project_id'] }
55
52
  project_identifier = "#{project['identifier']}/"
56
53
  end
57
54
 
@@ -63,7 +60,6 @@ module Caramelize
63
60
  revisions << page
64
61
  end
65
62
  end
66
- # rubocop:enable Metrics/MethodLength
67
63
 
68
64
  def add_projects_as_namespaces
69
65
  projects.each do |row_project|
@@ -105,7 +101,7 @@ module Caramelize
105
101
  @wikis ||= database.query(wikis_query)
106
102
  end
107
103
 
108
- def build_properties(title, row_content) # rubocop:todo Metrics/MethodLength
104
+ def build_properties(title, row_content)
109
105
  author = authors.fetch(row_content['author_id'], nil)
110
106
  {
111
107
  id: row_content['id'],
@@ -17,7 +17,7 @@ module Caramelize
17
17
  # new array only containing pages by this name sorted by time asc
18
18
  # this does not support renamed pages
19
19
  revisions.select { |revision| revision.title == title }
20
- .sort { |x, y| x.time <=> y.time }
20
+ .sort_by(&:time)
21
21
  end
22
22
 
23
23
  # return an empty array in case this action was not overridden
@@ -54,7 +54,7 @@ module Caramelize
54
54
  end
55
55
 
56
56
  def latest_revisions
57
- @latest_revisions ||= titles.map { |title| revisions_by_title(title).last }.compact
57
+ @latest_revisions ||= titles.filter_map { |title| revisions_by_title(title).last }
58
58
  end
59
59
 
60
60
  def markup
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'caramelize/database_connector'
4
3
  require 'caramelize/filters/add_newline_to_page_end'
5
4
  require 'caramelize/filters/camel_case_to_wiki_links'
6
5
  require 'caramelize/filters/wikka_to_markdown'
@@ -17,21 +16,18 @@ module Caramelize
17
16
  def initialize(options = {})
18
17
  super(options)
19
18
  @options[:markup] = :wikka
20
- @options[:filters] << Caramelize::AddNewlineOnPageEnd
21
- @options[:filters] << Caramelize::Wikka2Markdown
22
- @options[:filters] << Caramelize::CamelCaseToWikiLinks
19
+ @options[:filters] << ::Caramelize::AddNewlineToPageEnd
20
+ @options[:filters] << ::Caramelize::WikkaToMarkdown
21
+ @options[:filters] << ::Caramelize::CamelCaseToWikiLinks
23
22
  end
24
23
 
25
24
  # after calling this action, titles and @revisions are expected to be filled
26
25
  def read_pages
27
26
  pages.each do |row|
28
27
  titles << row['tag']
29
- page = Page.new(build_properties(row))
30
- revisions << page
28
+ revisions << Page.new(build_properties(row))
31
29
  end
32
30
  titles.uniq!
33
- # revisions.sort! { |a,b| a.time <=> b.time }
34
-
35
31
  revisions
36
32
  end
37
33
 
@@ -60,7 +56,7 @@ module Caramelize
60
56
  @pages ||= database.query(pages_query)
61
57
  end
62
58
 
63
- def build_properties(row) # rubocop:todo Metrics/MethodLength
59
+ def build_properties(row)
64
60
  author = authors[row['user']]
65
61
  {
66
62
  id: row['id'],
@@ -38,7 +38,7 @@ module Caramelize
38
38
  def commit_history(revisions, options = {}, &block)
39
39
  revisions.each_with_index do |page, index|
40
40
  # call debug output from outside
41
- block.call(page, index) if block_given?
41
+ yield(page, index) if block
42
42
  commit_revision(page, options.fetch(:markup, :markdown))
43
43
  end
44
44
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Caramelize
4
- VERSION = '1.2.1'
4
+ VERSION = '1.3.1'
5
5
  end
data/lib/caramelize.rb CHANGED
@@ -2,18 +2,20 @@
2
2
 
3
3
  require 'caramelize/version'
4
4
  require 'caramelize/page'
5
- require 'caramelize/content_transferer'
6
- require 'caramelize/filter_processor'
7
5
  require 'caramelize/database_connector'
6
+ require 'caramelize/filters/add_newline_to_page_end'
7
+ require 'caramelize/filter_processor'
8
+ require 'caramelize/input_wiki/wiki'
9
+ require 'caramelize/input_wiki/media_wiki'
10
+ require 'caramelize/input_wiki/redmine_wiki'
11
+ require 'caramelize/input_wiki/wikka_wiki'
12
+ require 'caramelize/content_transferer'
8
13
  require 'caramelize/health_check'
9
14
  require 'caramelize/health_checks/home_page_check'
10
15
  require 'caramelize/health_checks/orphaned_pages_check'
11
16
  require 'caramelize/health_checks/page'
12
17
  require 'caramelize/output_wiki/gollum'
13
18
  require 'caramelize/services/page_builder'
14
- require 'caramelize/input_wiki/wiki'
15
- require 'caramelize/input_wiki/redmine_wiki'
16
- require 'caramelize/input_wiki/wikkawiki'
17
19
 
18
20
  Encoding.default_external = Encoding::UTF_8
19
21
  Encoding.default_internal = Encoding::UTF_8
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Connecting to the MediaWiki Docker setup at https://hub.docker.com/_/mediawiki/
4
+
5
+ def input_wiki
6
+ options = {
7
+ host: '0.0.0.0',
8
+ username: 'wikiuser',
9
+ password: 'example',
10
+ database: 'my_wiki',
11
+ port: 63_645
12
+ }
13
+ Caramelize::InputWiki::MediaWiki.new(options)
14
+ end
@@ -2,9 +2,7 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- # rubocop:todo RSpec/SpecFilePathFormat
6
- describe Caramelize::Filter::AddNewlineToPageEnd do # rubocop:todo RSpec/FilePath, RSpec/SpecFilePathFormat
7
- # rubocop:enable RSpec/SpecFilePathFormat
5
+ describe Caramelize::AddNewlineToPageEnd do
8
6
  describe '#run' do
9
7
  subject(:run) { filter.run }
10
8
 
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Caramelize::MediawikiToMarkdown do
6
+ let(:filter) { described_class.new(body) }
7
+
8
+ describe '#run' do
9
+ subject { filter.run }
10
+
11
+ # the conversions are performed through pandoc-ruby.
12
+ # This is a smoke test to see if it's called at all,
13
+ # but not testing every single option.
14
+
15
+ context 'when headline h1' do
16
+ let(:body) { "= Headline =\n" }
17
+
18
+ it { is_expected.to eq "# Headline\n" }
19
+ end
20
+
21
+ context 'when headline h2' do
22
+ let(:body) { "== Headline ==\n" }
23
+
24
+ it { is_expected.to eq "## Headline\n" }
25
+ end
26
+ end
27
+ end
@@ -3,7 +3,7 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  # rubocop:todo RSpec/SpecFilePathFormat
6
- describe Caramelize::Wikka2Markdown do # rubocop:todo RSpec/FilePath, RSpec/SpecFilePathFormat
6
+ describe Caramelize::WikkaToMarkdown do # rubocop:todo RSpec/FilePath, RSpec/SpecFilePathFormat
7
7
  # rubocop:enable RSpec/SpecFilePathFormat
8
8
  let(:filter) { described_class.new(body) }
9
9
 
@@ -71,37 +71,19 @@ describe Caramelize::Wikka2Markdown do # rubocop:todo RSpec/FilePath, RSpec/Spec
71
71
  end
72
72
 
73
73
  context 'when unordered list entry' do
74
- context 'with tab based' do
74
+ context 'with tabs' do
75
75
  let(:body) { "\t-unordered list entry" }
76
76
 
77
77
  it { is_expected.to eq '- unordered list entry' }
78
78
  end
79
79
 
80
- context 'with tabs' do
80
+ context 'with tilde' do
81
81
  let(:body) { '~-unordered list entry' }
82
82
 
83
83
  it { is_expected.to eq '- unordered list entry' }
84
84
  end
85
85
 
86
86
  context 'with spaces' do
87
- let(:body) { ' -unordered list entry' }
88
-
89
- it { is_expected.to eq '- unordered list entry' }
90
- end
91
-
92
- context 'with tab based with space' do
93
- let(:body) { "\t- unordered list entry" }
94
-
95
- it { is_expected.to eq '- unordered list entry' }
96
- end
97
-
98
- context 'with another tab based with space' do
99
- let(:body) { '~- unordered list entry' }
100
-
101
- it { is_expected.to eq '- unordered list entry' }
102
- end
103
-
104
- context 'with space based with space' do
105
87
  let(:body) { ' - unordered list entry' }
106
88
 
107
89
  it { is_expected.to eq '- unordered list entry' }
@@ -129,7 +111,7 @@ describe Caramelize::Wikka2Markdown do # rubocop:todo RSpec/FilePath, RSpec/Spec
129
111
  it { is_expected.to eq '[[LemmaLemma]]' }
130
112
  end
131
113
 
132
- context 'with only url sklfs' do
114
+ context 'with only wikilink' do
133
115
  let(:body) { "\n [[ComunitySiteIdeas]] \n" }
134
116
 
135
117
  it { is_expected.to eq "\n [[ComunitySiteIdeas]] \n" }
@@ -261,5 +243,31 @@ describe Caramelize::Wikka2Markdown do # rubocop:todo RSpec/FilePath, RSpec/Spec
261
243
 
262
244
  it { is_expected.to eq expected_result }
263
245
  end
246
+
247
+ context 'when image' do
248
+ context 'with link' do
249
+ let(:body) { '{{image class="center" alt="DVD logo" title="An image link" url="images/dvdvideo.gif" link="RecentChanges"}}' }
250
+
251
+ it { is_expected.to eq '[[<img src="images/dvdvideo.gif" alt="DVD logo">|RecentChanges]]' }
252
+ end
253
+
254
+ context 'with alt and with title' do
255
+ let(:body) { '{{image class="center" alt="DVD logo" title="An image link" url="images/dvdvideo.gif"}}' }
256
+
257
+ it { is_expected.to eq '![DVD logo](images/dvdvideo.gif)' }
258
+ end
259
+
260
+ context 'without alt and with title' do
261
+ let(:body) { '{{image class="center" title="An image link" url="images/dvdvideo.gif"}}' }
262
+
263
+ it { is_expected.to eq '![](images/dvdvideo.gif)' }
264
+ end
265
+
266
+ context 'without alt and without title' do
267
+ let(:body) { '{{image class="center" url="images/dvdvideo.gif"}}' }
268
+
269
+ it { is_expected.to eq '![](images/dvdvideo.gif)' }
270
+ end
271
+ end
264
272
  end
265
273
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Caramelize::InputWiki::MediaWiki do
6
+ subject(:wiki) { described_class.new }
7
+
8
+ describe '#filters' do
9
+ it 'has 2 filters' do
10
+ expect(wiki.filters.count).to be(2)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Caramelize::InputWiki::WikkaWiki do
6
+ subject(:wiki) { described_class.new }
7
+
8
+ describe '#filters' do
9
+ it 'has 3 filters' do
10
+ expect(wiki.filters.count).to be(3)
11
+ end
12
+ end
13
+ end