class BibSonomy::CSL

Attributes

altmetric_badge_type[RW]

@return [String] the badge type for embedded Altmetric badges. If set to `nil`, no badge is included. (default: `nil`)

css_class[RW]

@return [String] the CSS class used to render the surrounding `<ul>` list (default: 'publications')

group[RW]

@return [String] which posts shall be included, based on the groups they are viewable for

opt_sep[RW]

@return [String] the separator between options. (default: ' | ')

pdf_dir[RW]

@return [String] the output directory for downloaded PDF files. If set to `nil`, no documents are downloaded. (default: `nil`)

public_doc_postfix[RW]

@return [String] When a post has several documents and the

filename of one of them ends with `public_doc_postfix`, only
this document is downloaded and linked, all other are
ignored. (default: '_oa.pdf')
style[RW]

@return [String] the {citationstyles.org/ CSL} style used for rendering. (default: `apa.csl`)

year_headings[RW]

@return [Boolean] whether year headings shall be rendered. (default: `true`)

Public Class Methods

new(user_name, api_key) click to toggle source

Create a new BibSonomy instance.

@param user_name [String] the BibSonomy user name @param api_key [String] the API key of the user (get at www.bibsonomy.org/settings?selTab=1)

Calls superclass method
# File lib/bibsonomy/csl.rb, line 95
def initialize(user_name, api_key)
  super()
  @bibsonomy = BibSonomy::API.new(user_name, api_key, 'csl')
  # setting some defaults
  @style = 'apa.csl'
  @pdf_dir = nil
  @css_class = 'publications'
  @year_headings = true
  @public_doc_postfix = '_oa.pdf'
  @group = 'public'
  @altmetric_badge_type = nil

  # optional parts to be rendered (or not)
  @doi_link = true
  @url_link = true
  @bibtex_link = true
  @bibsonomy_link = true
  @opt_sep = ' | '
end

Public Instance Methods

render(grouping, name, tags, count) click to toggle source

Download `count` posts for the given `user` and `tag(s)` and render them with {citationstyles.org/ CSL}.

@param grouping [String] the type of the name (either “user” or “group”) @param name [String] the name of the group or user @param tags [Array<String>] the tags that all posts must contain (can be empty) @param count [Integer] number of posts to download @return [String] the rendered posts as HTML

# File lib/bibsonomy/csl.rb, line 123
def render(grouping, name, tags, count)
  # get posts from BibSonomy
  posts = JSON.parse(@bibsonomy.get_posts(grouping, name, 'publication', tags, 0, count))

  # render them with citeproc
  cp = CiteProc::Processor.new style: @style, format: 'html'
  cp.import posts

  # to check for duplicate file names
  file_names = []

  # filter posts by group
  # 2017-05-30, rja, disabled until group information is returned by the API
  # posts.delete_if do |v|
  #   if v["group"] == @group
  #     true
  #   else
  #     print("WARN: " + v["group"])
  #     false
  #   end
  # end

  # sort posts by year
  sorted_keys = posts.keys.sort { |a,b| get_sort_posts(posts[b], posts[a]) }

  result = ""

  # print first heading
  last_year = 0

  if @year_headings and sorted_keys.length > 0
    last_year = get_year(posts[sorted_keys[0]])
    result += "<h3>" + last_year + "</h3>"
  end

  result += "<ul class='#{@css_class}'>\n"
  for post_id in sorted_keys
    post = posts[post_id]

    # print heading
    if @year_headings
      year = get_year(post)
      if year != last_year
        last_year = year
        result += "</ul>\n<h3>" + last_year + "</h3>\n<ul class='#{@css_class}'>\n"
      end
    end

    # render metadata
    csl = cp.render(:bibliography, id: post_id)
    result += "<li class='" + post["type"] + "'>#{csl[0]}"

    # extract the post's id
    intra_hash, user_name = get_intra_hash(post_id)

    # optional parts
    options = []
    # attach documents
    if @pdf_dir
      for doc in get_public_docs(post["documents"])
        # fileHash, fileName, md5hash, userName
        file_path = get_document(@bibsonomy, intra_hash, user_name, doc, @pdf_dir, file_names)
        options << "<a href='#{file_path}'>PDF</a>"
      end
    end
    # attach DOI
    doi = post["DOI"]
    if @doi_link and doi != ""
      doi, doi_url = get_doi(doi)
      options << "DOI:<a href='#{doi_url}'>#{doi}</a>"
    end
    # attach URL
    url = post["URL"]
    if @url_link and url != ""
      options << "<a href='#{url}'>URL</a>"
    end
    # attach BibTeX
    if @bibtex_link
      options << "<a href='https://www.bibsonomy.org/bib/publication/#{intra_hash}/#{user_name}'>BibTeX</a>"
    end
    # attach link to BibSonomy
    if @bibsonomy_link
      options << "<a href='https://www.bibsonomy.org/publication/#{intra_hash}/#{user_name}'>BibSonomy</a>"
    end

    # attach options
    if options.length > 0
      result += " <span class='opt'>[" + options.join(@opt_sep) + "]</span>"
    end

    # attach Altmetric badge
    if @altmetric_badge_type and doi != ""
      doi, doi_url = get_doi(doi)
      result += "<div class='altmetric-embed' data-badge-type='#{@altmetric_badge_type}' data-doi='#{doi}'></div>"
    end

    result += "</li>\n"
  end
  result += "</ul>\n"

  return result
end

Private Instance Methods

get_document(bib, intra_hash, user_name, doc, dir, file_names) click to toggle source

downloads the documents for the posts (if necessary)

# File lib/bibsonomy/csl.rb, line 297
def get_document(bib, intra_hash, user_name, doc, dir, file_names)
  # fileHash, fileName, md5hash, userName
  file_name = doc["fileName"]
  # strip doc prefix for public documents
  if file_name.end_with? @public_doc_postfix
    file_name = file_name[0, file_name.length - @public_doc_postfix.length] + ".pdf"
  end
  # check for possible duplicate file names
  if file_names.include? file_name
    warn "duplicate file name " + file_name + " for post " + intra_hash
  end
  # remember file name
  file_names << file_name
  # produce file path
  file_path = dir + "/" + file_name
  # download PDF if it not already exists
  if not File.exists? file_path
    pdf, mime = bib.get_document(user_name, intra_hash, doc["fileName"])
    if pdf == nil
      warn "could not download file " + intra_hash + "/" + user_name + "/" + file_name
    else
      File.binwrite(file_path, pdf)
    end
  end
  return file_path
end
get_doi(doi) click to toggle source

given a DOI (or a URL with a DOI) return DOI and resolvable URL

# File lib/bibsonomy/csl.rb, line 233
def get_doi(doi)
  # simplistic check whether DOI is a URL
  if doi.start_with?("http")
    # extract DOI, regex from https://www.crossref.org/blog/dois-and-matching-regular-expressions/
    if doi =~ /(10.\d{4,9}\/[-._;()\/:A-Z0-9]+)/i
      return $1, doi
    else
      return doi, doi
    end
  else
    return doi, "https://doi.org/#{doi}"
  end
end
get_intra_hash(post_id) click to toggle source

format of the post ID for CSL: [0-9a-f]{32}USERNAME

# File lib/bibsonomy/csl.rb, line 325
def get_intra_hash(post_id)
  return [post_id[0, 32], post_id[32, post_id.length]]
end
get_public_docs(documents) click to toggle source

only show PDF files

# File lib/bibsonomy/csl.rb, line 277
def get_public_docs(documents)
  result = []
  for doc in documents
    file_name = doc["fileName"]
    if file_name.end_with? ".pdf"
      if documents.length < 2 or file_name.end_with? @public_doc_postfix
        result << doc
      end
    end
  end
  return result
end
get_sort_posts(a, b) click to toggle source
# File lib/bibsonomy/csl.rb, line 260
def get_sort_posts(a, b)
  person_a = a["author"]
  if person_a.length == 0
    person_a = a["editor"]
  end
  person_b = b["author"]
  if person_b.length == 0
    person_b = b["editor"]
  end
  # we switch the order of person_b and person_a, to sort
  # descending by year but ascending by person name
  return [get_year(a), a["type"], person_b[0]["family"]] <=> [get_year(b), b["type"], person_a[0]["family"]]
end
get_year(post) click to toggle source
# File lib/bibsonomy/csl.rb, line 247
def get_year(post)
  issued = post["issued"]
  # if the post contains only a "year" field, it is contained in
  # the field "literal"
  if issued["literal"]
    return issued["literal"]
  else
    # otherwise, the date can be contained in the "raw" field
    # TODO: extract the year ([12][0-9]{3}) from that field
    return issued["raw"]
  end
end
warn(m) click to toggle source
# File lib/bibsonomy/csl.rb, line 290
def warn(m)
  print("WARN: " + m + "\n")
end