rmwiki 0.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f0729913a338313c2d4290cc8db08930c5c13c2e
4
+ data.tar.gz: fa73337b194bb00d5640e42aadf8e01edbae7e17
5
+ SHA512:
6
+ metadata.gz: 1b78cbed07fca24eae191903486aaf4b7ad8d2143aa8c617fb11869ebc5ea150d0f3a04a86ea9664c5fe17be8b6b9600b0d39e509f7120c7224cd1ceab45ed93
7
+ data.tar.gz: 8b1fd543f8ad24dbeabcb4de1960cdf713959590c129e394f10f8f117c5bc1452a7ba036cfd7679c870bfc2378974ec55f6c9a91d17fe23e48693f0476663351
data/.gitignore ADDED
@@ -0,0 +1,15 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+ /vendor
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rmwiki.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 bigwheel
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ 'Software'), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,31 @@
1
+ # Rmwiki
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'rmwiki'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install rmwiki
20
+
21
+ ## Usage
22
+
23
+ TODO: Write usage instructions here
24
+
25
+ ## Contributing
26
+
27
+ 1. Fork it ( https://github.com/[my-github-username]/rmwiki/fork )
28
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
29
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
30
+ 4. Push to the branch (`git push origin my-new-feature`)
31
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
7
+
data/lib/rmwiki.rb ADDED
@@ -0,0 +1,134 @@
1
+ require 'httpclient'
2
+ require 'nokogiri'
3
+ require 'json'
4
+ require 'uri'
5
+ require 'time'
6
+
7
+ class Rmwiki
8
+ # ここで使われたユーザーはRedMineの方の操作ログに名前が残るよ
9
+ def initialize(wiki_root, username, password)
10
+ @wiki_root = wiki_root
11
+ @http_client = HTTPClient.new
12
+ login username, password
13
+ end
14
+
15
+ class SimpleWikiPage
16
+ attr_reader :title, :parent_title, :version, :created_on, :updated_on
17
+
18
+ def initialize(raw_obj)
19
+ @title = raw_obj['title']
20
+ @parent_title = raw_obj['parent'] && raw_obj['parent']['title']
21
+ # Option型ってないんよね
22
+ @version = raw_obj['version']
23
+ @created_on = DateTime::iso8601(raw_obj['created_on'])
24
+ @updated_on = DateTime::iso8601(raw_obj['updated_on'])
25
+ end
26
+ end
27
+
28
+ class ExtendedWikiPage < SimpleWikiPage
29
+ attr_reader :text, :author_id, :author_name, :comments
30
+ def initialize(raw_obj)
31
+ super(raw_obj)
32
+ @text = raw_obj['text']
33
+ @author_id = raw_obj['author']['id']
34
+ @author_name = raw_obj['author']['name']
35
+ @comments = raw_obj['comments']
36
+ end
37
+ end
38
+
39
+ def all_pages
40
+ response = @http_client.get(File.join(@wiki_root, 'index.json'))
41
+ check_status_code response
42
+ JSON.parse(response.content)['wiki_pages'].map { |raw_obj|
43
+ SimpleWikiPage.new(raw_obj)
44
+ }
45
+ end
46
+
47
+ def page page_title
48
+ response = @http_client.get(File.join(@wiki_root, URI::escape(page_title) + '.json'))
49
+
50
+ if response.header.status_code == 200
51
+ ExtendedWikiPage.new(JSON.parse(response.content)['wiki_page'])
52
+ else
53
+ nil
54
+ end
55
+ end
56
+
57
+ def exist? page_title
58
+ self.page(page_title) != nil
59
+ end
60
+
61
+ # スペースの入ったページ名などダメなページ名があるので
62
+ # 返り値として移動後のページ名を返す
63
+ def rename before_title, after_title, parent_title = :default
64
+ def get_page_title_id_map nokogiri_doc
65
+ page_id_and_anme = nokogiri_doc.css('#wiki_page_parent_id option').
66
+ map { |i| i.text =~ /(?:.*» )?(.+)/; [$1, i.attributes['value'].value.to_i] }.
67
+ select { |page_title, id| page_title }
68
+ Hash[page_id_and_anme]
69
+ end
70
+
71
+ def get_default_parent_id nokogiri_doc
72
+ elem = nokogiri_doc.css('#wiki_page_parent_id option[selected="selected"]').first
73
+ if elem
74
+ elem.attributes['value'].value.to_i
75
+ else
76
+ ''
77
+ end
78
+ end
79
+
80
+ rename_form_url = File.join(@wiki_root, before_title, '/rename')
81
+ doc = Nokogiri::HTML(@http_client.get_content(rename_form_url))
82
+ authenticity_token = get_authenticity_token(doc)
83
+ parent_id = if parent_title == :default
84
+ get_default_parent_id(doc)
85
+ elsif parent_title == nil
86
+ ''
87
+ else
88
+ page_title_to_id = get_page_title_id_map(doc)
89
+ unless page_title_to_id.has_key? parent_title
90
+ raise '指定された親ページが存在しません'
91
+ end
92
+ page_title_to_id[parent_title]
93
+ end
94
+
95
+ res = @http_client.post(rename_form_url, {
96
+ 'authenticity_token' => authenticity_token,
97
+ 'wiki_page[title]' => after_title,
98
+ 'wiki_page[redirect_existing_links]' => 0,
99
+ 'wiki_page[parent_id]' => parent_id
100
+ })
101
+ check_status_code res, 302
102
+ File.basename(res.header['Location'].first)
103
+ end
104
+
105
+ private
106
+ def login username, password
107
+ def fetch_login_url_from_wiki_root
108
+ url = URI.parse(@wiki_root)
109
+ doc = Nokogiri::HTML(@http_client.get_content(@wiki_root))
110
+ url.path = doc.css('.login').first.attributes['href'].value
111
+ url.to_s
112
+ end
113
+
114
+ login_url = fetch_login_url_from_wiki_root
115
+ login_page_doc = Nokogiri::HTML(@http_client.get_content(login_url))
116
+ authenticity_token = get_authenticity_token(login_page_doc)
117
+ # redmineは認証失敗したら200,成功したら302が帰る。ks
118
+ check_status_code(@http_client.post(login_url, {
119
+ authenticity_token: authenticity_token,
120
+ username: username,
121
+ password: password
122
+ }), 302)
123
+ end
124
+
125
+ def check_status_code response, status_code = 200
126
+ unless response.header.status_code == status_code
127
+ raise '失敗したっぽい' + response.to_s
128
+ end
129
+ end
130
+
131
+ def get_authenticity_token nokogiri_doc
132
+ nokogiri_doc.css('input[name="authenticity_token"]').first.attributes['value'].value
133
+ end
134
+ end
data/rmwiki.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'rmwiki'
7
+ spec.version = '0.0.1'
8
+ spec.authors = ['bigwheel']
9
+ spec.email = ['k.bigwheel+eng@gmail.com']
10
+ spec.summary = %q{redmine wiki manupilator}
11
+ spec.description = spec.summary
12
+ spec.homepage = ''
13
+ spec.license = 'MIT'
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ['lib']
19
+
20
+ spec.add_runtime_dependency 'httpclient'
21
+ spec.add_runtime_dependency 'nokogiri'
22
+
23
+ spec.add_development_dependency 'bundler', '~> 1.7'
24
+ spec.add_development_dependency 'rake', '~> 10.0'
25
+ spec.add_development_dependency 'rspec'
26
+ spec.add_development_dependency 'pry'
27
+ end
@@ -0,0 +1,108 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rmwiki do
4
+ # sample site
5
+ wiki_root = 'https://www.hostedredmine.com/projects/redminefs-test-project/wiki/'
6
+ username = 'bigwheel'
7
+ password = '4CrY39Ellb07'
8
+ it '正しいアカウントならインスタンスが作れる' do
9
+ expect { Rmwiki.new(wiki_root, username, password) }.not_to raise_error
10
+ end
11
+
12
+ it '正しくないアカウントでは例外が出る' do
13
+ expect { Rmwiki.new(wiki_root, username, 'invalid_pass') }.to raise_error
14
+ end
15
+
16
+ describe '細かい挙動' do
17
+ before(:context) do
18
+ @subject = Rmwiki.new(wiki_root, username, password)
19
+ end
20
+
21
+ it 'とりあえずall_pagesが呼べる' do
22
+ expect { @subject.all_pages }.not_to raise_error
23
+ end
24
+
25
+ it 'とりあえずページ詳細が取れる' do
26
+ page = @subject.page('C')
27
+
28
+ expect(page.title).to eq('C')
29
+ expect(page.parent_title).to eq('Parent')
30
+ expect(page.text).not_to be_empty
31
+ expect(page.author_name).to eq('bigwheel k')
32
+ expect(page.author_id).to eq(33563)
33
+ expect(page.created_on).to eq(DateTime.parse('2014-09-24T18:13:16Z'))
34
+ end
35
+
36
+ it 'ページの存在を確認できる' do
37
+ expect(@subject.exist?('C')).to be_truthy
38
+ end
39
+
40
+ it 'ページの不在を確認できる' do
41
+ expect(@subject.exist?('not_exists')).to be_falsey
42
+ end
43
+
44
+ it '存在しないページの詳細を取ろうとするとnilが帰る' do
45
+ expect(@subject.page('not_exists')).to be_nil
46
+ end
47
+
48
+ it '親がないページのrenameテスト' do
49
+ expect(@subject.exist?('A')).to be_truthy
50
+ expect(@subject.exist?('B')).to be_falsey
51
+
52
+ @subject.rename 'A', 'B'
53
+
54
+ expect(@subject.exist?('A')).to be_falsey
55
+ expect(@subject.exist?('B')).to be_truthy
56
+
57
+ @subject.rename 'B', 'A' # 面倒なので元に戻しておく
58
+ end
59
+
60
+ it '親があるページのrenameテスト' do
61
+ expect(@subject.exist?('Child')).to be_truthy
62
+ expect(@subject.exist?('NextChild')).to be_falsey
63
+
64
+ @subject.rename 'Child', 'NextChild'
65
+
66
+ expect(@subject.exist?('Child')).to be_falsey
67
+ expect(@subject.exist?('NextChild')).to be_truthy
68
+
69
+ @subject.rename 'NextChild', 'Child' # 面倒なので元に戻しておく
70
+ end
71
+
72
+ it 'スペースを含む名前へ変更しようとしてもアンダースコアで置換される' do
73
+ renamed_name = @subject.rename 'A', 'Space Ga Aru'
74
+ @subject.rename renamed_name, 'A' # 元に戻しておく
75
+ expect(renamed_name).to eq('Space_Ga_Aru')
76
+ end
77
+
78
+ it '親のあるページを別の親へ移動できる' do
79
+ @subject.rename 'Child', 'Child', 'Wiki'
80
+
81
+ page = @subject.page('Child')
82
+ expect(page.parent_title).to eq('Wiki')
83
+
84
+ @subject.rename 'Child', 'Child', 'Parent' # 元に戻しておく
85
+ end
86
+
87
+ it '親のないページを別の親へ移動できる' do
88
+ @subject.rename 'Parentless', 'Parentless', 'Wiki'
89
+
90
+ page = @subject.page('Parentless')
91
+ expect(page.parent_title).to eq('Wiki')
92
+ end
93
+
94
+ # 上のテストの副作用はこっちで戻す
95
+ it '親のあるページを親なしへ移動できる' do
96
+ @subject.rename 'Parentless', 'Parentless', nil
97
+
98
+ page = @subject.page('Parentless')
99
+ expect(page.parent_title).to be_nil
100
+ end
101
+
102
+ it '存在しない親ページを指定すると例外が出る' do
103
+ expect {
104
+ @subject.rename('Parentless', 'Parentless', 'not_exist_page')
105
+ }.to raise_error
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,3 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'rmwiki'
3
+ require 'pry'
metadata ADDED
@@ -0,0 +1,141 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rmwiki
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - bigwheel
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-10-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: httpclient
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: nokogiri
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '1.7'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '1.7'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: pry
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: redmine wiki manupilator
98
+ email:
99
+ - k.bigwheel+eng@gmail.com
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - .gitignore
105
+ - .rspec
106
+ - .travis.yml
107
+ - Gemfile
108
+ - LICENSE.txt
109
+ - README.md
110
+ - Rakefile
111
+ - lib/rmwiki.rb
112
+ - rmwiki.gemspec
113
+ - spec/rmwiki_spec.rb
114
+ - spec/spec_helper.rb
115
+ homepage: ''
116
+ licenses:
117
+ - MIT
118
+ metadata: {}
119
+ post_install_message:
120
+ rdoc_options: []
121
+ require_paths:
122
+ - lib
123
+ required_ruby_version: !ruby/object:Gem::Requirement
124
+ requirements:
125
+ - - '>='
126
+ - !ruby/object:Gem::Version
127
+ version: '0'
128
+ required_rubygems_version: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - '>='
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ requirements: []
134
+ rubyforge_project:
135
+ rubygems_version: 2.0.14
136
+ signing_key:
137
+ specification_version: 4
138
+ summary: redmine wiki manupilator
139
+ test_files:
140
+ - spec/rmwiki_spec.rb
141
+ - spec/spec_helper.rb