bibsonomy 0.4.0
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 +34 -0
- data/Gemfile +4 -0
- data/LICENSE +505 -0
- data/README.md +121 -0
- data/Rakefile +2 -0
- data/bibsonomy.gemspec +33 -0
- data/lib/bibsonomy.rb +7 -0
- data/lib/bibsonomy/api.rb +150 -0
- data/lib/bibsonomy/csl.rb +395 -0
- data/lib/bibsonomy/post.rb +21 -0
- data/lib/bibsonomy/version.rb +3 -0
- data/test/post_test.rb +39 -0
- data/test/test_helper.rb +9 -0
- metadata +199 -0
data/README.md
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
# BibSonomy
|
2
|
+
|
3
|
+
BibSonomy client for Ruby
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'bibsonomy'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install bibsonomy
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
Getting posts from BibSonomy:
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
require 'bibsonomy'
|
27
|
+
api = BibSonomy::API.new('yourusername', 'yourapikey', 'ruby')
|
28
|
+
posts = api.get_posts_for_user('jaeschke', 'publication', ['myown'], 0, 20)
|
29
|
+
```
|
30
|
+
|
31
|
+
Rendering posts with [CSL](http://citationstyles.org/):
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
require 'bibsonomy/csl'
|
35
|
+
csl = BibSonomy::CSL.new('yourusername', 'yourapikey')
|
36
|
+
html = csl.render('jaeschke', ['myown'], 100)
|
37
|
+
print html
|
38
|
+
```
|
39
|
+
|
40
|
+
A command line wrapper to the CSL renderer:
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
#!/usr/bin/ruby
|
44
|
+
require 'bibsonomy/csl'
|
45
|
+
print BibSonomy::main(ARGV)
|
46
|
+
```
|
47
|
+
|
48
|
+
## Jekyll
|
49
|
+
|
50
|
+
A [Jekyll](http://jekyllrb.com/) plugin:
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
# coding: utf-8
|
54
|
+
require 'time'
|
55
|
+
require 'bibsonomy/csl'
|
56
|
+
|
57
|
+
module Jekyll
|
58
|
+
|
59
|
+
class BibSonomyPostList < Liquid::Tag
|
60
|
+
def initialize(tag_name, text, tokens)
|
61
|
+
super
|
62
|
+
parts = text.split(/\s+/)
|
63
|
+
@user = parts[0]
|
64
|
+
@tag = parts[1]
|
65
|
+
@count = Integer(parts[2])
|
66
|
+
end
|
67
|
+
|
68
|
+
def render(context)
|
69
|
+
site = context.registers[:site]
|
70
|
+
|
71
|
+
# user name and API key for BibSonomy
|
72
|
+
user_name = site.config['bibsonomy_user']
|
73
|
+
api_key = site.config['bibsonomy_apikey']
|
74
|
+
csl = BibSonomy::CSL.new(user_name, api_key)
|
75
|
+
|
76
|
+
# target directory for PDF documents
|
77
|
+
pdf_dir = site.config['bibsonomy_document_directory']
|
78
|
+
csl.pdf_dir = pdf_dir
|
79
|
+
|
80
|
+
# CSL style for rendering
|
81
|
+
style = site.config['bibsonomy_style']
|
82
|
+
csl.style = style
|
83
|
+
|
84
|
+
html = csl.render(@user, [@tag], @count)
|
85
|
+
|
86
|
+
# set date to now
|
87
|
+
context.registers[:page]["date"] = Time.new
|
88
|
+
|
89
|
+
return html
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
Liquid::Template.register_tag('bibsonomy', Jekyll::BibSonomyPostList)
|
96
|
+
```
|
97
|
+
|
98
|
+
The plugin can be used inside Markdown files as follows:
|
99
|
+
|
100
|
+
```
|
101
|
+
{% bibsonomy jaeschke myown 100 %}
|
102
|
+
```
|
103
|
+
|
104
|
+
Add the following options to your `_config.yml`:
|
105
|
+
|
106
|
+
```
|
107
|
+
bibsonomy_user: yourusername
|
108
|
+
bibsonomy_apikey: yourapikey
|
109
|
+
bibsonomy_document_directory: pdf
|
110
|
+
# other: apa, acm-siggraph
|
111
|
+
bibsonomy_style: springer-lecture-notes-in-computer-science
|
112
|
+
```
|
113
|
+
|
114
|
+
|
115
|
+
## Contributing
|
116
|
+
|
117
|
+
1. Fork it ( https://github.com/rjoberon/bibsonomy-ruby/fork )
|
118
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
119
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
120
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
121
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/bibsonomy.gemspec
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'bibsonomy/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "bibsonomy"
|
8
|
+
spec.version = BibSonomy::VERSION
|
9
|
+
spec.authors = ["Robert Jäschke"]
|
10
|
+
spec.email = ["jaeschke@l3s.de"]
|
11
|
+
spec.summary = %q{Wraps the BibSonomy REST API.}
|
12
|
+
spec.description = %q{Enables calls to the BibSonomy REST API with Ruby.}
|
13
|
+
spec.homepage = "https://github.com/rjoberon/bibsonomy-ruby"
|
14
|
+
spec.license = "LGPL 2.1"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
22
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
23
|
+
spec.add_development_dependency "minitest", "~> 5.4"
|
24
|
+
spec.add_development_dependency "vcr", "~> 2.9"
|
25
|
+
spec.add_development_dependency "webmock", "~> 1.19"
|
26
|
+
|
27
|
+
spec.add_dependency "faraday", "~> 0.9"
|
28
|
+
spec.add_dependency "json", "~> 1.8"
|
29
|
+
spec.add_dependency "citeproc", "~> 1.0"
|
30
|
+
spec.add_dependency "csl-styles", "~> 1.0"
|
31
|
+
spec.add_dependency "bibtex-ruby", "~> 4.0"
|
32
|
+
|
33
|
+
end
|
data/lib/bibsonomy.rb
ADDED
@@ -0,0 +1,150 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require 'faraday'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
#
|
6
|
+
# TODO:
|
7
|
+
# - error handling
|
8
|
+
# - getting more than 1000 posts
|
9
|
+
#
|
10
|
+
|
11
|
+
# configuration options
|
12
|
+
$API_URL = "https://www.bibsonomy.org/"
|
13
|
+
$MAX_POSTS_PER_REQUEST = 20
|
14
|
+
|
15
|
+
#
|
16
|
+
# allowed shortcuts for resource types
|
17
|
+
#
|
18
|
+
$resource_types_bookmark = ['bookmark', 'bookmarks', 'book', 'link', 'links', 'url']
|
19
|
+
$resource_types_bibtex = ['bibtex', 'pub', 'publication', 'publications', 'publ']
|
20
|
+
|
21
|
+
#
|
22
|
+
# The BibSonomy REST client for Ruby.
|
23
|
+
#
|
24
|
+
module BibSonomy
|
25
|
+
class API
|
26
|
+
|
27
|
+
# Initializes the client with the given credentials.
|
28
|
+
#
|
29
|
+
# @param user_name [String] The name of the user account used for
|
30
|
+
# accessing the API
|
31
|
+
#
|
32
|
+
# @param api_key [String] The API key corresponding to the user
|
33
|
+
# account - can be obtained from
|
34
|
+
# http://www.bibsonomy.org/settings?selTab=1
|
35
|
+
#
|
36
|
+
# @param format [String] The requested return format. One of:
|
37
|
+
# 'xml', 'json', 'ruby', 'csl', 'bibtex'. The default is 'ruby'
|
38
|
+
# which returns Ruby objects defined by this library. Currently,
|
39
|
+
# 'csl' and 'bibtex' are only available for publications.
|
40
|
+
#
|
41
|
+
def initialize(user_name, api_key, format = 'ruby')
|
42
|
+
|
43
|
+
# configure output format
|
44
|
+
if format == 'ruby'
|
45
|
+
@format = 'json'
|
46
|
+
@parse = true
|
47
|
+
else
|
48
|
+
@format = format
|
49
|
+
@parse = false
|
50
|
+
end
|
51
|
+
|
52
|
+
@conn = Faraday.new(:url => $API_URL) do |faraday|
|
53
|
+
faraday.request :url_encoded # form-encode POST params
|
54
|
+
#faraday.response :logger
|
55
|
+
faraday.adapter Faraday.default_adapter # make requests with
|
56
|
+
# Net::HTTP
|
57
|
+
end
|
58
|
+
|
59
|
+
@conn.basic_auth(user_name, api_key)
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
#
|
65
|
+
# Get a single post
|
66
|
+
#
|
67
|
+
# @param user_name [String] The name of the post's owner.
|
68
|
+
# @param intra_hash [String] The intrag hash of the post.
|
69
|
+
# @return [BibSonomy::Post] the requested post
|
70
|
+
#
|
71
|
+
def get_post(user_name, intra_hash)
|
72
|
+
response = @conn.get "/api/users/" + CGI.escape(user_name) + "/posts/" + CGI.escape(intra_hash), { :format => @format }
|
73
|
+
|
74
|
+
if @parse
|
75
|
+
attributes = JSON.parse(response.body)
|
76
|
+
return Post.new(attributes["post"])
|
77
|
+
end
|
78
|
+
return response.body
|
79
|
+
end
|
80
|
+
|
81
|
+
#
|
82
|
+
# Get posts owned by a user, optionally filtered by tags.
|
83
|
+
#
|
84
|
+
# @param user_name [String] The name of the posts' owner.
|
85
|
+
# @resource_type [String] The type of the post. Currently
|
86
|
+
# supported are 'bookmark' and 'publication'.
|
87
|
+
#
|
88
|
+
def get_posts_for_user(user_name, resource_type, tags = nil, start = 0, endc = $MAX_POSTS_PER_REQUEST)
|
89
|
+
params = {
|
90
|
+
:format => @format,
|
91
|
+
:resourcetype => self.get_resource_type(resource_type),
|
92
|
+
:start => start,
|
93
|
+
:end => endc
|
94
|
+
}
|
95
|
+
# add tags, if requested
|
96
|
+
if tags != nil
|
97
|
+
params[:tags] = tags.join(" ")
|
98
|
+
end
|
99
|
+
response = @conn.get "/api/users/" + CGI.escape(user_name) + "/posts", params
|
100
|
+
|
101
|
+
if @parse
|
102
|
+
posts = JSON.parse(response.body)["posts"]["post"]
|
103
|
+
return posts.map { |attributes| Post.new(attributes) }
|
104
|
+
end
|
105
|
+
return response.body
|
106
|
+
end
|
107
|
+
|
108
|
+
def get_document_href(user_name, intra_hash, file_name)
|
109
|
+
return "/api/users/" + CGI.escape(user_name) + "/posts/" + CGI.escape(intra_hash) + "/documents/" + CGI.escape(file_name)
|
110
|
+
end
|
111
|
+
|
112
|
+
#
|
113
|
+
# get a document belonging to a post
|
114
|
+
#
|
115
|
+
def get_document(user_name, intra_hash, file_name)
|
116
|
+
response = @conn.get get_document_href(user_name, intra_hash, file_name)
|
117
|
+
if response.status == 200
|
118
|
+
return [response.body, response.headers['content-type']]
|
119
|
+
end
|
120
|
+
return nil, nil
|
121
|
+
end
|
122
|
+
|
123
|
+
def get_document_preview(user_name, intra_hash, file_name, size)
|
124
|
+
response = get_document_href(user_name, intra_hash, file_name), { :preview => size }
|
125
|
+
if response.status = 200
|
126
|
+
return [response.body, 'image/jpeg']
|
127
|
+
end
|
128
|
+
return nil, nil
|
129
|
+
end
|
130
|
+
|
131
|
+
#
|
132
|
+
# Convenience method to allow sloppy specification of the resource
|
133
|
+
# type.
|
134
|
+
#
|
135
|
+
# @private
|
136
|
+
#
|
137
|
+
def get_resource_type(resource_type)
|
138
|
+
if $resource_types_bookmark.include? resource_type.downcase()
|
139
|
+
return "bookmark"
|
140
|
+
end
|
141
|
+
|
142
|
+
if $resource_types_bibtex.include? resource_type.downcase()
|
143
|
+
return "bibtex"
|
144
|
+
end
|
145
|
+
|
146
|
+
raise ArgumentError.new("Unknown resource type: #{resource_type}. Supported resource types are ")
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
150
|
+
end
|
@@ -0,0 +1,395 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
require 'citeproc'
|
5
|
+
require 'csl/styles'
|
6
|
+
require 'bibtex'
|
7
|
+
require 'json'
|
8
|
+
require 'bibsonomy'
|
9
|
+
|
10
|
+
#
|
11
|
+
# Generates a list of publication posts from BibSonomy
|
12
|
+
#
|
13
|
+
# required parameters:
|
14
|
+
# - user name
|
15
|
+
# - api key
|
16
|
+
# optional parameters:
|
17
|
+
# - user name
|
18
|
+
# - tags
|
19
|
+
# - number of posts
|
20
|
+
# - style
|
21
|
+
# - directory
|
22
|
+
#
|
23
|
+
# Changes:
|
24
|
+
# 2015-02-24
|
25
|
+
# - initial version
|
26
|
+
#
|
27
|
+
# TODO:
|
28
|
+
# - escape data
|
29
|
+
# - make sorting, etc. configurable
|
30
|
+
# - add link to BibSonomy
|
31
|
+
# - automatically rename files (TODO: CSL lacks BibTeX key)
|
32
|
+
# - add intra_hash, user_name, DOI to CSL
|
33
|
+
# - integrate AJAX abstract
|
34
|
+
# - make all options available via command line
|
35
|
+
|
36
|
+
module BibSonomy
|
37
|
+
class CSL
|
38
|
+
|
39
|
+
#
|
40
|
+
# Create a new BibSonomy instance
|
41
|
+
# Params:
|
42
|
+
# +user_name+:: BibSonomy user name
|
43
|
+
# +api_key+:: API key of the given user (get at http://www.bibsonomy.org/settings?selTab=1)
|
44
|
+
def initialize(user_name, api_key)
|
45
|
+
super()
|
46
|
+
@bibsonomy = BibSonomy::API.new(user_name, api_key, 'csl')
|
47
|
+
# setting some defaults
|
48
|
+
@style = 'apa.csl'
|
49
|
+
@pdf_dir = nil
|
50
|
+
@css_class = 'publications'
|
51
|
+
@year_headings = true
|
52
|
+
@public_doc_postfix = '_oa.pdf'
|
53
|
+
|
54
|
+
# optional parts to be rendered (or not)
|
55
|
+
@doi_link = true
|
56
|
+
@url_link = true
|
57
|
+
@bibtex_link = true
|
58
|
+
@bibsonomy_link = true
|
59
|
+
@opt_sep = ' | '
|
60
|
+
end
|
61
|
+
|
62
|
+
#
|
63
|
+
# Download +count+ posts for the given +user+ and +tag(s)+ and render them with CSL.
|
64
|
+
# Params:
|
65
|
+
# +user+:: user name
|
66
|
+
# +tags+:: an array of tags
|
67
|
+
# +count+:: number of posts to download
|
68
|
+
def render(user, tags, count)
|
69
|
+
# get posts from BibSonomy
|
70
|
+
posts = JSON.parse(@bibsonomy.get_posts_for_user(user, 'publication', tags, 0, count))
|
71
|
+
|
72
|
+
# render them with citeproc
|
73
|
+
cp = CiteProc::Processor.new style: @style, format: 'html'
|
74
|
+
cp.import posts
|
75
|
+
|
76
|
+
# to check for duplicate file names
|
77
|
+
file_names = []
|
78
|
+
|
79
|
+
# sort posts by year
|
80
|
+
sorted_keys = posts.keys.sort { |a,b| get_sort_posts(posts[b], posts[a]) }
|
81
|
+
|
82
|
+
result = ""
|
83
|
+
|
84
|
+
# print first heading
|
85
|
+
last_year = 0
|
86
|
+
|
87
|
+
if @year_headings and sorted_keys.length > 0
|
88
|
+
last_year = get_year(posts[sorted_keys[0]])
|
89
|
+
result += "<h3>" + last_year + "</h3>"
|
90
|
+
end
|
91
|
+
|
92
|
+
result += "<ul class='#{@publications}'>\n"
|
93
|
+
for post_id in sorted_keys
|
94
|
+
post = posts[post_id]
|
95
|
+
|
96
|
+
# print heading
|
97
|
+
if @year_headings
|
98
|
+
year = get_year(post)
|
99
|
+
if year != last_year
|
100
|
+
last_year = year
|
101
|
+
result += "</ul>\n<h3>" + last_year + "</h3>\n<ul class='#{@publications}'>\n"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# render metadata
|
106
|
+
csl = cp.render(:bibliography, id: post_id)
|
107
|
+
result += "<li class='" + post["type"] + "'>#{csl[0]}"
|
108
|
+
|
109
|
+
# extract the post's id
|
110
|
+
intra_hash, user_name = get_intra_hash(post_id)
|
111
|
+
|
112
|
+
# optional parts
|
113
|
+
options = []
|
114
|
+
# attach documents
|
115
|
+
if @pdf_dir
|
116
|
+
for doc in get_public_docs(post["documents"])
|
117
|
+
# fileHash, fileName, md5hash, userName
|
118
|
+
file_path = get_document(@bibsonomy, intra_hash, user_name, doc, @pdf_dir, file_names)
|
119
|
+
options << "<a href='#{file_path}'>PDF</a>"
|
120
|
+
end
|
121
|
+
end
|
122
|
+
# attach DOI
|
123
|
+
doi = post["DOI"]
|
124
|
+
if @doi_link and doi != ""
|
125
|
+
options << "DOI:<a href='http://dx.doi.org/#{doi}'>#{doi}</a>"
|
126
|
+
end
|
127
|
+
# attach URL
|
128
|
+
url = post["URL"]
|
129
|
+
if @url_link and url != ""
|
130
|
+
options << "<a href='#{url}'>URL</a>"
|
131
|
+
end
|
132
|
+
# attach BibTeX
|
133
|
+
if @bibtex_link
|
134
|
+
options << "<a href='http://www.bibsonomy.org/bib/publication/#{intra_hash}/#{user_name}'>BibTeX</a>"
|
135
|
+
end
|
136
|
+
# attach link to BibSonomy
|
137
|
+
if @bibsonomy_link
|
138
|
+
options << "<a href='http://www.bibsonomy.org/publication/#{intra_hash}/#{user_name}'>BibSonomy</a>"
|
139
|
+
end
|
140
|
+
|
141
|
+
# attach options
|
142
|
+
if options.length > 0
|
143
|
+
result += " <span class='opt'>[" + options.join(@opt_sep) + "]</span>"
|
144
|
+
end
|
145
|
+
|
146
|
+
result += "</li>\n"
|
147
|
+
end
|
148
|
+
result += "</ul>\n"
|
149
|
+
|
150
|
+
return result
|
151
|
+
end
|
152
|
+
|
153
|
+
def get_year(post)
|
154
|
+
return post["issued"]["literal"]
|
155
|
+
end
|
156
|
+
|
157
|
+
def get_sort_posts(a, b)
|
158
|
+
person_a = a["author"]
|
159
|
+
if person_a.length == 0
|
160
|
+
person_a = a["editor"]
|
161
|
+
end
|
162
|
+
person_b = b["author"]
|
163
|
+
if person_b.length == 0
|
164
|
+
person_b = b["editor"]
|
165
|
+
end
|
166
|
+
return [get_year(a), a["type"], person_b[0]["family"]] <=> [get_year(b), b["type"], person_a[0]["family"]]
|
167
|
+
end
|
168
|
+
|
169
|
+
#
|
170
|
+
# only show PDF files and if
|
171
|
+
#
|
172
|
+
def get_public_docs(documents)
|
173
|
+
result = []
|
174
|
+
for doc in documents
|
175
|
+
file_name = doc["fileName"]
|
176
|
+
if file_name.end_with? ".pdf"
|
177
|
+
if documents.length < 2 or file_name.end_with? @public_doc_postfix
|
178
|
+
result << doc
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
return result
|
183
|
+
end
|
184
|
+
|
185
|
+
def warn(m)
|
186
|
+
print("WARN: " + m + "\n")
|
187
|
+
end
|
188
|
+
|
189
|
+
#
|
190
|
+
# downloads the documents for the posts (if necessary)
|
191
|
+
#
|
192
|
+
def get_document(bib, intra_hash, user_name, doc, dir, file_names)
|
193
|
+
# fileHash, fileName, md5hash, userName
|
194
|
+
file_name = doc["fileName"]
|
195
|
+
# strip doc prefix for public documents
|
196
|
+
if file_name.end_with? @public_doc_postfix
|
197
|
+
file_name = file_name[0, file_name.length - @public_doc_postfix.length] + ".pdf"
|
198
|
+
end
|
199
|
+
# check for possible duplicate file names
|
200
|
+
if file_names.include? file_name
|
201
|
+
warn "duplicate file name " + file_name + " for post " + intra_hash
|
202
|
+
end
|
203
|
+
# remember file name
|
204
|
+
file_names << file_name
|
205
|
+
# produce file path
|
206
|
+
file_path = dir + "/" + file_name
|
207
|
+
# download PDF if it not already exists
|
208
|
+
if not File.exists? file_path
|
209
|
+
pdf, mime = bib.get_document(user_name, intra_hash, doc["fileName"])
|
210
|
+
if pdf == nil
|
211
|
+
warn "could not download file " + intra_hash + "/" + user_name + "/" + file_name
|
212
|
+
else
|
213
|
+
File.binwrite(file_path, pdf)
|
214
|
+
end
|
215
|
+
end
|
216
|
+
return file_path
|
217
|
+
end
|
218
|
+
|
219
|
+
# format of the post ID for CSL: [0-9a-f]{32}USERNAME
|
220
|
+
def get_intra_hash(post_id)
|
221
|
+
return [post_id[0, 32], post_id[32, post_id.length]]
|
222
|
+
end
|
223
|
+
|
224
|
+
#
|
225
|
+
# setters
|
226
|
+
#
|
227
|
+
|
228
|
+
#
|
229
|
+
# Set the output directory for downloaded PDF files (default: +nil+)
|
230
|
+
# Params:
|
231
|
+
# +pdf_dir+:: directory for downloaded PDF files. If set to +nil+, no documents are downloaded.
|
232
|
+
def pdf_dir=(pdf_dir)
|
233
|
+
@pdf_dir = pdf_dir
|
234
|
+
end
|
235
|
+
|
236
|
+
#
|
237
|
+
# Set the CSL style used for rendering (default: +apa.csl+)
|
238
|
+
# Params:
|
239
|
+
# +style+:: CSL style used for rendering
|
240
|
+
def style=(style)
|
241
|
+
@style = style
|
242
|
+
end
|
243
|
+
|
244
|
+
#
|
245
|
+
# Enable/disable headings for years (default: enabled)
|
246
|
+
# Params:
|
247
|
+
# +year_headings+:: boolean indicating whether year headings shall be rendered
|
248
|
+
def year_headings=(year_headings)
|
249
|
+
@year_headings = year_headings
|
250
|
+
end
|
251
|
+
|
252
|
+
#
|
253
|
+
# The CSS class used to render the surrounding +<ul>+ list (default: 'publications')
|
254
|
+
# Params:
|
255
|
+
# +css_class+:: string indicating the CSS class for rendering the publication list
|
256
|
+
def css_class=(css_class)
|
257
|
+
@css_class = css_class
|
258
|
+
end
|
259
|
+
|
260
|
+
#
|
261
|
+
# Shall links for DOIs be rendered? (default: true)
|
262
|
+
# Params:
|
263
|
+
# +doi_link+:: render DOI link
|
264
|
+
def doi_link=(doi_link)
|
265
|
+
@doi_link = doi_link
|
266
|
+
end
|
267
|
+
|
268
|
+
#
|
269
|
+
# Shall links for URLs of posts be rendered? (default: true)
|
270
|
+
# Params:
|
271
|
+
# +url_link+:: render URL link
|
272
|
+
def url_link=(url_link)
|
273
|
+
@url_link = url_link
|
274
|
+
end
|
275
|
+
|
276
|
+
#
|
277
|
+
# Shall links to the BibTeX of a post (in BibSonomy) be rendered? (default: true)
|
278
|
+
# Params:
|
279
|
+
# +bibtex_link+:: render BibTeX link
|
280
|
+
def bibtex_link=(bibtex_link)
|
281
|
+
@bibtex_link = bibtex_link
|
282
|
+
end
|
283
|
+
|
284
|
+
#
|
285
|
+
# Shall links to BibSonomy be rendered? (default: true)
|
286
|
+
# Params:
|
287
|
+
# +bibsonomy_link+:: render BibSonomy link
|
288
|
+
def bibsonomy_link=(bibsonomy_link)
|
289
|
+
@bibsonomy_link = bibsonomy_link
|
290
|
+
end
|
291
|
+
|
292
|
+
#
|
293
|
+
# Separator between options (default: ' | ')
|
294
|
+
# Params:
|
295
|
+
# +opt_sep+:: option separator
|
296
|
+
def opt_sep=(opt_sep)
|
297
|
+
@opt_sep = opt_sep
|
298
|
+
end
|
299
|
+
|
300
|
+
#
|
301
|
+
# When a post has several documents and the filename of one of
|
302
|
+
# them ends with +public_doc_postfix+, only this document is
|
303
|
+
# downloaded and linked, all other are ignored. (default:
|
304
|
+
# '_oa.pdf')
|
305
|
+
# Params:
|
306
|
+
# +public_doc_postfix+:: postfix to check at document filenames
|
307
|
+
def public_doc_postfix=(public_doc_postfix)
|
308
|
+
@public_doc_postfix = public_doc_postfix
|
309
|
+
end
|
310
|
+
|
311
|
+
end
|
312
|
+
|
313
|
+
|
314
|
+
# parse command line options
|
315
|
+
def self.main(args)
|
316
|
+
|
317
|
+
# setting default options
|
318
|
+
options = OpenStruct.new
|
319
|
+
options.documents = false
|
320
|
+
options.directory = nil
|
321
|
+
options.tags = []
|
322
|
+
options.style = "apa.csl"
|
323
|
+
options.posts = 1000
|
324
|
+
|
325
|
+
opt_parser = OptionParser.new do |opts|
|
326
|
+
opts.banner = "Usage: csl.rb [options] user_name api_key"
|
327
|
+
|
328
|
+
opts.separator ""
|
329
|
+
opts.separator "Specific options:"
|
330
|
+
|
331
|
+
# mandatory arguments are handled separately
|
332
|
+
|
333
|
+
# optional arguments
|
334
|
+
opts.on('-u', '--user USER', 'return posts for USER instead of user') { |v| options[:user] = v }
|
335
|
+
opts.on('-t', '--tags TAG,TAG,...', Array, 'return posts with the given tags') { |v| options[:tags] = v }
|
336
|
+
opts.on('-s', '--style STYLE', 'use CSL style STYLE for rendering') { |v| options[:style] = v }
|
337
|
+
opts.on('-n', '--number-of-posts [COUNT]', Integer, 'number of posts to download') { |v| options[:posts] = v }
|
338
|
+
opts.on('-d', '--directory DIR', 'target directory', ' (if not given, no documents are downloaed)') { |v| options[:directory] = v }
|
339
|
+
|
340
|
+
opts.separator ""
|
341
|
+
opts.separator "Common options:"
|
342
|
+
|
343
|
+
opts.on('-h', '--help', 'show this help message and exit') do
|
344
|
+
puts opts
|
345
|
+
exit
|
346
|
+
end
|
347
|
+
|
348
|
+
opts.on_tail('-v', "--version", "show version") do
|
349
|
+
puts BibSonomy::VERSION
|
350
|
+
exit
|
351
|
+
end
|
352
|
+
|
353
|
+
end
|
354
|
+
|
355
|
+
opt_parser.parse!(args)
|
356
|
+
|
357
|
+
# handle mandatory arguments
|
358
|
+
begin
|
359
|
+
mandatory = [:user_name, :api_key]
|
360
|
+
missing = []
|
361
|
+
|
362
|
+
options[:api_key] = args.pop
|
363
|
+
missing << :api_key unless options[:api_key]
|
364
|
+
|
365
|
+
options[:user_name] = args.pop
|
366
|
+
missing << :user_name unless options[:user_name]
|
367
|
+
|
368
|
+
if not missing.empty?
|
369
|
+
puts "Missing options: #{missing.join(', ')}"
|
370
|
+
puts opt_parser
|
371
|
+
exit
|
372
|
+
end
|
373
|
+
rescue OptionParser::InvalidOption, OptionParser::MissingArgument
|
374
|
+
puts $!.to_s
|
375
|
+
puts opt_parser
|
376
|
+
exit
|
377
|
+
end
|
378
|
+
|
379
|
+
# set defaults for optional arguments
|
380
|
+
options[:user] = options[:user_name] unless options[:user]
|
381
|
+
|
382
|
+
#
|
383
|
+
# do the actual work
|
384
|
+
#
|
385
|
+
csl = BibSonomy::CSL.new(options[:user_name], options[:api_key])
|
386
|
+
csl.pdf_dir(options[:directory])
|
387
|
+
csl.style(options[:style])
|
388
|
+
|
389
|
+
html = csl.render(options[:user], options[:tags], options[:posts])
|
390
|
+
|
391
|
+
return html
|
392
|
+
|
393
|
+
end
|
394
|
+
|
395
|
+
end
|