Skip to content

Instantly share code, notes, and snippets.

@ethnt
Created May 9, 2014 20:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ethnt/dd49101c5479e6561313 to your computer and use it in GitHub Desktop.
Save ethnt/dd49101c5479e6561313 to your computer and use it in GitHub Desktop.
A Ruby script to get the fields needed to build a form for a citation using Citation Styles.
# a script to get the fields necessary to build forms for a citation
# using citation styles
# to-do: name-parts, date-parts, punctuation (delimiters), comments
require 'citeproc'
require 'csl/styles'
TYPES = [
'article',
'article-magazine',
'article-newspaper',
'article-journal',
'bill',
'book',
'broadcast',
'chapter',
'dataset',
'entry',
'entry-dictionary',
'entry-encyclopedia',
'figure',
'graphic',
'interview',
'legislation',
'legal_case',
'manuscript',
'map',
'motion_picture',
'musical_score',
'pamphlet',
'paper-conference',
'patent',
'post',
'post-weblog',
'personal_communication',
'report',
'review',
'review-book',
'song',
'speech',
'thesis',
'treaty',
'webpage'
]
File.open('output.txt', 'w') do |log|
LOG = log
CSL::Style.ls.each do |shortname|
@csl = CSL::Style.load(shortname)
TYPES.each do |type|
LOG.puts "#{shortname}: #{type}"
def run(options)
fields = []
if @csl.methods.include?(:has_bibliography?) && @csl.has_bibliography?
@csl.bibliography.layout.each_child do |c|
fields << renderable_node(c, options)
end
else
LOG.puts "skipping, no bibliography"
end
fields
end
def renderable_node(node, options = {})
# If it's a renderable element and it has a macro, return it.
if renderable?(node)
if node.methods.include?(:has_macro?) && node.has_macro?
variable = node['variable'] || '(no variable)'
LOG.puts "#{variable} renderable field and has a macro (#{node.macro['name']}) \n"
return node['variable']
else
variable = node['variable'] || '(no variable)'
LOG.puts "#{variable} renderable field \n"
return node['variable']
end
elsif node.class == CSL::Style::Choose
conditionals = node.find_children('if')
conditionals.concat(node.find_children('else-if'))
need_else = true
conditionals.each do |condition|
if matches_conditional_block?(condition, options)
need_else = false
condition.each_child do |c|
renderable_node(c, options)
end
end
end
if need_else
else_block = node.find_child('else')
unless else_block.nil?
else_block.each_child do |c|
renderable_node(c, options)
end
end
end
elsif node.class == CSL::Style::Group
unless node.nil?
node.each_child do |child|
renderable_node(child, options)
end
end
end
end
def matches_conditional_block?(block, options = {})
unless block.methods.include?(:conditions)
return false
end
if block.conditions.blank?
return false
end
conditions = block.conditions.first
var = conditions[0]
matcher = conditions[1]
matches = conditions[2]
# The var needs to be in the options
if !options.keys.include?(var)
return false
end
case matcher
when :any?
# If it's any, it needs to match one of the matches
return matches.include?(options[var])
when :all?
# If it's all, it needs to match all of the matches
return matches == [options[var]]
when :none?
# If it's none, it needs to not match the matches
return !matches.include?(options[var])
else
return false
end
end
def renderable?(node)
renderable = [
CSL::Style::Text,
CSL::Style::Names,
CSL::Style::Date
]
renderable.include?(node.class)
end
# LOG.puts run({type: 'book'})
run({type: type})
LOG.puts "\n----------------------------------------------------------------------\n\n\n"
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment