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 +7 -0
- data/.gitignore +15 -0
- data/.rspec +2 -0
- data/.travis.yml +3 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +31 -0
- data/Rakefile +7 -0
- data/lib/rmwiki.rb +134 -0
- data/rmwiki.gemspec +27 -0
- data/spec/rmwiki_spec.rb +108 -0
- data/spec/spec_helper.rb +3 -0
- metadata +141 -0
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
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
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
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
|
data/spec/rmwiki_spec.rb
ADDED
@@ -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
|
data/spec/spec_helper.rb
ADDED
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
|