bibsonomy 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|