caramelize 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +19 -24
  3. data/bin/caramelize +48 -2
  4. data/caramelize.gemspec +2 -1
  5. data/lib/caramelize.rb +12 -0
  6. data/lib/caramelize/caramel.rb +33 -29
  7. data/lib/caramelize/content_transferer.rb +78 -111
  8. data/lib/caramelize/filter_processor.rb +31 -0
  9. data/lib/caramelize/input_wiki/redmine_wiki.rb +97 -0
  10. data/lib/caramelize/{wiki → input_wiki}/trac_converter.rb +0 -0
  11. data/lib/caramelize/input_wiki/wiki.rb +61 -0
  12. data/lib/caramelize/input_wiki/wikkawiki.rb +57 -0
  13. data/lib/caramelize/output_wiki/gollum.rb +73 -0
  14. data/lib/caramelize/page.rb +10 -4
  15. data/lib/caramelize/services/page_builder.rb +20 -0
  16. data/lib/caramelize/version.rb +1 -1
  17. data/spec/lib/caramelize/content_transferer_spec.rb +9 -0
  18. data/spec/lib/caramelize/filter_processor_spec.rb +32 -0
  19. data/spec/lib/caramelize/filters/wikka_to_markdown_spec.rb +25 -13
  20. data/spec/lib/caramelize/{wiki → input_wiki}/wiki_spec.rb +30 -4
  21. data/spec/lib/caramelize/output_wiki/gollum_spec.rb +113 -0
  22. data/spec/lib/caramelize/page_spec.rb +49 -0
  23. data/spec/lib/caramelize/services/page_builder.rb +29 -0
  24. data/spec/spec_helper.rb +1 -1
  25. metadata +38 -17
  26. data/lib/caramelize/cli.rb +0 -89
  27. data/lib/caramelize/cli/create_command.rb +0 -36
  28. data/lib/caramelize/cli/run_command.rb +0 -33
  29. data/lib/caramelize/gollum_output.rb +0 -79
  30. data/lib/caramelize/wiki/redmine_wiki.rb +0 -88
  31. data/lib/caramelize/wiki/wiki.rb +0 -63
  32. data/lib/caramelize/wiki/wikkawiki.rb +0 -48
  33. data/spec/lib/caramelize/gollum_output_spec.rb +0 -64
@@ -0,0 +1,31 @@
1
+ require 'gollum-lib'
2
+ require 'grit'
3
+ require 'ruby-progressbar'
4
+
5
+ module Caramelize
6
+ class FilterProcessor
7
+ attr_reader :filters, :input_wiki
8
+
9
+ def initialize(input_wiki)
10
+ @filters = []
11
+ @input_wiki = input_wiki
12
+
13
+ initialize_wiki_filters
14
+ end
15
+
16
+ def run(body)
17
+ body_new = body
18
+ filters.each do |filter|
19
+ body_new = filter.run(body_new)
20
+ end
21
+ body_new
22
+ end
23
+
24
+ private
25
+
26
+ def initialize_wiki_filters
27
+ filters << input_wiki.filters
28
+ filters.flatten!
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,97 @@
1
+ require 'caramelize/input_wiki/wiki'
2
+ require 'caramelize/filters/swap_wiki_links'
3
+ require 'caramelize/filters/remove_table_tab_line_endings'
4
+
5
+ module Caramelize
6
+ module InputWiki
7
+ class RedmineWiki < Wiki
8
+ include DatabaseConnector
9
+
10
+ def initialize options={}
11
+ super(options)
12
+ @options[:markup] = :textile
13
+ @options[:filters] << Caramelize::SwapWikiLinks.new
14
+ @options[:filters] << Caramelize::RemoveTableTabLineEndings.new
15
+ @options[:create_namespace_overview] = true
16
+ end
17
+
18
+ # after calling this action, I expect the titles and revisions to be filled
19
+ def read_pages
20
+ # get all projects
21
+ results_projects = database.query("SELECT id, identifier, name FROM projects;")
22
+ results_projects.each do |row_project|
23
+ #collect all namespaces
24
+ namespaces << OpenStruct.new(identifier: row_project["identifier"], name: row_project["name"])
25
+ end
26
+
27
+ # get all wikis
28
+ results_wikis = database.query("SELECT id, project_id FROM wikis;")
29
+
30
+ # get all lemmas
31
+ results_pages = database.query("SELECT id, title, wiki_id FROM wiki_pages;")
32
+ results_pages.each do |row_page|
33
+ results_contents = database.query("SELECT * FROM wiki_content_versions WHERE page_id='#{row_page["id"]}' ORDER BY updated_on;")
34
+
35
+ # get wiki for page
36
+ wiki_row = nil
37
+ project_row = nil
38
+ results_wikis.each do |wiki|
39
+ wiki_row = wiki if wiki["id"] == row_page["wiki_id"]
40
+ end
41
+
42
+ if wiki_row
43
+ # get project from wiki-id
44
+ results_projects.each do |project|
45
+ project_row = project if project["id"] == wiki_row["project_id"]
46
+ end
47
+ end
48
+
49
+ project_identifier = project_row ? project_row["identifier"] + '/' : ""
50
+
51
+ title = project_identifier + row_page["title"]
52
+ titles << title
53
+
54
+ @latest_revisions = {}
55
+ results_contents.each do |row_content|
56
+ page = Page.new(build_properties(title, row_content))
57
+ revisions << page
58
+ @latest_revisions[title] = page
59
+ end
60
+ end
61
+ titles.uniq!
62
+ @latest_revisions.each { |rev| rev[1].set_latest }
63
+ revisions.sort! { |a,b| a.time <=> b.time }
64
+
65
+ # TODO find latest revision for each limit
66
+
67
+ revisions
68
+ end
69
+
70
+ def read_authors
71
+ results = database.query("SELECT id, login, mail FROM users;")
72
+ results.each do |row|
73
+ authors[row["id"]] = OpenStruct.new(id: row["id"],
74
+ name: row["login"],
75
+ email: row["mail"])
76
+ end
77
+ authors
78
+ end
79
+
80
+ private
81
+
82
+ def build_properties(title, row_content)
83
+ author = authors[row_content["author_id"]] ? authors[row_content["author_id"]] : nil
84
+ { id: row_content["id"],
85
+ title: title,
86
+ body: row_content["data"],
87
+ markup: :textile,
88
+ latest: false,
89
+ time: row_content["updated_on"],
90
+ message: row_content["comments"],
91
+ author: author,
92
+ author_name: author.name
93
+ }
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,61 @@
1
+ module Caramelize
2
+ module InputWiki
3
+ class Wiki
4
+ include DatabaseConnector
5
+
6
+ attr_accessor :revisions, :wiki_title, :titles, :description, :namespaces, :options
7
+
8
+ def initialize(options={})
9
+ @options = options
10
+ @options[:filters] = []
11
+ @namespaces = []
12
+ end
13
+
14
+ def revisions_by_title(title)
15
+ # new array only containing pages by this name sorted by time asc
16
+ # this does not support renamed pages
17
+ return revisions
18
+ .select { |revision| revision.title == title }
19
+ .sort { |x,y| x.time <=> y.time }
20
+ end
21
+
22
+ # return an empty array in case this action was not overridden
23
+ def read_authors
24
+ []
25
+ end
26
+
27
+ def namespaces
28
+ @namespaces ||= {}
29
+ end
30
+
31
+ def authors
32
+ @authors ||= {}
33
+ end
34
+
35
+ def revisions
36
+ @revisions ||= []
37
+ end
38
+
39
+ def titles
40
+ @titles ||= []
41
+ end
42
+
43
+ def convert_markup?(to_markup)
44
+ markup != to_markup
45
+ end
46
+
47
+ def filters
48
+ @options[:filters]
49
+ end
50
+
51
+ def latest_revisions
52
+ titles.map { |title| revisions_by_title(title).last }.compact
53
+ end
54
+
55
+ def markup
56
+ @options[:markup]
57
+ end
58
+
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,57 @@
1
+ require 'caramelize/input_wiki/wiki'
2
+ require 'caramelize/database_connector'
3
+ require 'caramelize/filters/wikka_to_markdown'
4
+
5
+ module Caramelize
6
+ module InputWiki
7
+ class WikkaWiki < Wiki
8
+ include DatabaseConnector
9
+
10
+ def initialize options={}
11
+ super(options)
12
+ @options[:markup] = :wikka
13
+ @options[:filters] << Caramelize::Wikka2Markdown.new
14
+ end
15
+
16
+ # after calling this action, titles and @revisions are expected to be filled
17
+ def read_pages
18
+ sql = "SELECT id, tag, body, time, latest, user, note FROM wikka_pages ORDER BY time;"
19
+ results = database.query(sql)
20
+ results.each do |row|
21
+ titles << row["tag"]
22
+ page = Page.new(build_properties(row))
23
+ revisions << page
24
+ end
25
+ titles.uniq!
26
+ #revisions.sort! { |a,b| a.time <=> b.time }
27
+
28
+ revisions
29
+ end
30
+
31
+ def read_authors
32
+ sql = "SELECT name, email FROM wikka_users;"
33
+ results = database.query(sql)
34
+ results.each do |row|
35
+ authors[row["name"]] = OpenStruct.new(name: row["name"],
36
+ email: row["email"] )
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ def build_properties(row)
43
+ author = authors[row["user"]]
44
+ { id: row["id"],
45
+ title: row["tag"],
46
+ body: row["body"],
47
+ markup: :wikka,
48
+ latest: row["latest"] == "Y",
49
+ time: row["time"],
50
+ message: row["note"],
51
+ author: author,
52
+ author_name: row["user"]
53
+ }
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,73 @@
1
+ require 'caramelize/ext'
2
+ module Caramelize
3
+ module OutputWiki
4
+ class Gollum
5
+
6
+ attr_reader :wiki_path
7
+
8
+ SUPPORTED_TARGET_MARKUP =
9
+ %i[markdown textile rdoc creole media_wiki org pod re_structured_text ascii_doc].freeze
10
+
11
+ # Initialize a new gollum-wiki-repository at the given path.
12
+ def initialize(new_wiki_path)
13
+ # TODO use sanitized name as wiki-repository-title
14
+ @wiki_path = new_wiki_path
15
+ initialize_repository
16
+ end
17
+
18
+ # Commit the given page into the gollum-wiki-repository.
19
+ # Make sure the target markup is correct before calling this method.
20
+ def commit_revision(page, markup)
21
+ gollum_page = gollum.page(page.title)
22
+
23
+ if gollum_page
24
+ gollum.update_page(gollum_page, gollum_page.name, gollum_page.format, page.body, build_commit(page))
25
+ else
26
+ gollum.write_page(page.title, markup, page.body, build_commit(page))
27
+ end
28
+ end
29
+
30
+ # Commit all revisions of the given history into this gollum-wiki-repository.
31
+ def commit_history(revisions, options = {}, &block)
32
+ revisions.each_with_index do |page, index|
33
+ # call debug output from outside
34
+ block.call(page, index) if block_given?
35
+ commit_revision(page, options.fetch(:markup, :markdown))
36
+ end
37
+ end
38
+
39
+ def commit_namespace_overview(namespaces)
40
+ commit_revision(build_namespace_overview(namespaces), :markdown)
41
+ end
42
+
43
+ def supported_markup
44
+ SUPPORTED_TARGET_MARKUP
45
+ end
46
+
47
+ def build_commit(page)
48
+ {
49
+ message: page.commit_message,
50
+ name: page.author_name,
51
+ email: page.author_email,
52
+ authored_date: page.time,
53
+ committed_date: page.time
54
+ }
55
+ end
56
+
57
+ private
58
+
59
+ def build_namespace_overview(namespaces)
60
+ ::Caramelize::Services::PageBuilder.build_namespace_overview(namespaces)
61
+ end
62
+
63
+ def gollum
64
+ @gollum ||= ::Gollum::Wiki.new(wiki_path)
65
+ end
66
+
67
+ def initialize_repository
68
+ return if File.exists?(wiki_path)
69
+ Grit::Repo.init(wiki_path)
70
+ end
71
+ end
72
+ end
73
+ end
@@ -1,9 +1,10 @@
1
1
  module Caramelize
2
2
  class Page
3
3
 
4
- attr_accessor :title, :body, :id, :markup, :latest, :time, :message, :author, :author_name
4
+ attr_accessor :title, :body, :id, :markup, :latest, :time, :message,
5
+ :author, :author_name
5
6
 
6
- def initialize page={}
7
+ def initialize(page={})
7
8
  @id = page[:id]
8
9
  @title = page[:title] || ""
9
10
  @body = page[:body] || ""
@@ -12,7 +13,7 @@ module Caramelize
12
13
  @time = page[:time] || Time.now
13
14
  @message = page[:message] || ""
14
15
  @author = page[:author]
15
- @author_name = page[:author_name]
16
+ @author_name = page[:author_name]
16
17
  end
17
18
 
18
19
  def author_email
@@ -39,5 +40,10 @@ module Caramelize
39
40
  def to_s
40
41
  @title
41
42
  end
43
+
44
+ def commit_message
45
+ return "Edit in page #{title}" if message.empty?
46
+ message
47
+ end
42
48
  end
43
- end
49
+ end
@@ -0,0 +1,20 @@
1
+ module Caramelize
2
+ module Services
3
+ class PageBuilder
4
+ def self.build_namespace_overview(namespaces)
5
+ body = "## Overview of namespaces\n\n"
6
+
7
+ namespaces.each do |namespace|
8
+ # TODO change wiki as configurable default home
9
+ # TODO support other markup syntaxes
10
+ body << "* [[#{namespace[:name]}|#{namespace[:identifier]}/Wiki]] \n"
11
+ end
12
+
13
+ Page.new(title: "Home",
14
+ body: body,
15
+ message: 'Create Namespace Overview',
16
+ latest: true)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -1,3 +1,3 @@
1
1
  module Caramelize
2
- VERSION = "0.3.0"
2
+ VERSION = '0.4.0'
3
3
  end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ describe Caramelize::ContentTransferer do
4
+ describe '#execute' do
5
+ context 'with original_wiki' do
6
+ pending
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe Caramelize::FilterProcessor do
4
+ let(:filters) { [] }
5
+ let(:input_wiki) { double(filters: filters) }
6
+ let(:body) { 'body' }
7
+ subject(:processor) { described_class.new(input_wiki) }
8
+
9
+ class ReverseFilter
10
+ def run(body)
11
+ body.reverse
12
+ end
13
+ end
14
+
15
+ describe '#run' do
16
+ context 'without any filters' do
17
+ it 'returns same revision body' do
18
+ expect(processor.run(body)).to eql body
19
+ end
20
+ end
21
+
22
+ context 'with reverse filter' do
23
+ let(:filters) do
24
+ [ReverseFilter.new]
25
+ end
26
+
27
+ it 'returns reversed body' do
28
+ expect(processor.run(body)).to eql body.reverse
29
+ end
30
+ end
31
+ end
32
+ end
@@ -5,81 +5,93 @@ describe Caramelize::Wikka2Markdown do
5
5
  describe :run do
6
6
  let(:filter) { Caramelize::Wikka2Markdown.new }
7
7
  context 'headline h1' do
8
- it 'should convert to markdown' do
8
+ it 'converts to markdown' do
9
9
  body = '======Headline======'
10
10
  expect(filter.run(body)).to eq '# Headline'
11
11
  end
12
12
  end
13
+
13
14
  context 'headline h2' do
14
- it 'should convert to markdown' do
15
+ it 'converts to markdown' do
15
16
  body = '=====Headline====='
16
17
  expect(filter.run(body)).to eq '## Headline'
17
18
  end
18
19
  end
20
+
19
21
  context 'headline h3' do
20
- it 'should convert to markdown' do
22
+ it 'converts to markdown' do
21
23
  body = '====Headline===='
22
24
  expect(filter.run(body)).to eq '### Headline'
23
25
  end
24
26
  end
27
+
25
28
  context 'headline h4' do
26
- it 'should convert to markdown' do
29
+ it 'converts to markdown' do
27
30
  body = '===Headline==='
28
31
  expect(filter.run(body)).to eq '#### Headline'
29
32
  end
30
33
  end
34
+
31
35
  context 'headline h1' do
32
- it 'should convert to markdown' do
36
+ it 'converts to markdown' do
33
37
  body = '======Headline======'
34
38
  expect(filter.run(body)).to eq '# Headline'
35
39
  end
36
40
  end
41
+
37
42
  context 'bold' do
38
- it 'should convert to markdown' do
43
+ it 'converts to markdown' do
39
44
  body = '**Text is bold**'
40
45
  expect(filter.run(body)).to eq '**Text is bold**'
41
46
  end
42
47
  end
48
+
43
49
  context 'italic' do
44
- it 'should convert to markdown' do
50
+ it 'converts to markdown' do
45
51
  body = '//Text is italic//'
46
52
  expect(filter.run(body)).to eq '_Text is italic_'
47
53
  end
48
54
  end
55
+
49
56
  context 'underline' do
50
- it 'should convert to markdown' do
57
+ it 'converts to markdown' do
51
58
  body = '__Text is underlined__'
52
59
  expect(filter.run(body)).to eq '<u>Text is underlined</u>'
53
60
  end
54
61
  end
62
+
55
63
  context 'line break' do
56
- it 'should convert to markdown' do
64
+ it 'converts to markdown' do
57
65
  body = 'Text is---\nbroken to two lines.'
58
66
  expect(filter.run(body)).to eq 'Text is \nbroken to two lines.'
59
67
  end
60
68
  end
69
+
61
70
  context 'unordered list entry' do
62
71
  context 'tab based' do
63
- it 'should convert to markdown' do
72
+ it 'converts to markdown' do
64
73
  body = "\t-unordered list entry"
65
74
  expect(filter.run(body)).to eq '*unordered list entry'
66
75
  end
67
76
  end
77
+
68
78
  context 'also tab based' do
69
- it 'should convert to markdown' do
79
+ it 'converts to markdown' do
70
80
  body = "~-unordered list entry"
71
81
  expect(filter.run(body)).to eq '*unordered list entry'
72
82
  end
73
83
  end
84
+
74
85
  context 'space based' do
75
- it 'should convert to markdown' do
86
+ it 'converts to markdown' do
76
87
  body = " -unordered list entry"
77
88
  expect(filter.run(body)).to eq '*unordered list entry'
78
89
  end
79
90
  end
80
91
  end
92
+
81
93
  context 'hyperlink' do
82
- it 'should convert to markdown' do
94
+ it 'converts to markdown' do
83
95
  body = '[[Title http://target]]'
84
96
  expect(filter.run(body)).to eq '[[http://target|Title]]'
85
97
  end