Class: AsciidoctorBibliography::Citation
- Inherits:
-
Object
- Object
- AsciidoctorBibliography::Citation
- Defined in:
- lib/asciidoctor-bibliography/citation.rb
Constant Summary collapse
- TEX_MACROS =
%w[citet citet* citealt citealt* citep citep* citealp citealp* citeauthor citeauthor* citeyear citeyearpar].freeze
- MACRO_NAME_REGEXP =
TEX_MACROS.dup.concat(%w[cite fullcite nocite]). map { |s| Regexp.escape s }.join("|").freeze
- REGEXP =
/ \\? (#{MACRO_NAME_REGEXP}) # macro name ( (?: : (?:\S*?) \[(?:|.*?[^\\])\] ) # first target with attributes list (?: \+ (?:\S*?) \[(?:|.*?[^\\])\] )* # other targets with wttributes lists ) /x
- MACRO_PARAMETERS_REGEXP =
/ \G # restart metching from here (?: [:+] # separator (\S*?) # optional target \[(|.*?[^\\])\] # attributes list ) /x
- REF_ATTRIBUTES =
%i[chapter page section clause].freeze
- MISSING_ID_MARK =
"*??*".freeze
Instance Attribute Summary collapse
-
#citation_items ⇒ Object
readonly
Returns the value of attribute citation_items.
-
#macro ⇒ Object
readonly
Returns the value of attribute macro.
Instance Method Summary collapse
- #any_missing_id?(bibliographer) ⇒ Boolean
-
#initialize(macro, *target_and_attributes_list_pairs) ⇒ Citation
constructor
A new instance of Citation.
- #interpolate_formatted_citation!(formatted_citation) ⇒ Object
- #missing_ids(bibliographer) ⇒ Object
- #prepare_fullcite_item(bibliographer, formatter) ⇒ Object
- #prepare_item(options, item, affix: true) ⇒ Object
- #prepare_items(bibliographer, formatter, tex: false) ⇒ Object
- #prepare_metadata(bibliographer, cite, affix: false) ⇒ Object
- #render(bibliographer) ⇒ Object
- #render_citation_with_csl(bibliographer, style: bibliographer.options.style, tex: false) ⇒ Object
- #render_fullcite_with_csl(bibliographer) ⇒ Object
- #render_texmacro_with_csl(bibliographer) ⇒ Object
- #render_with_csl(bibliographer) ⇒ Object
- #uuid ⇒ Object
- #wrap_item(item, prefix, suffix) ⇒ Object
- #wrap_up_citation(citation:, bibliographer:) ⇒ Object
- #xref_id(*fragments) ⇒ Object
Constructor Details
#initialize(macro, *target_and_attributes_list_pairs) ⇒ Citation
Returns a new instance of Citation.
38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/asciidoctor-bibliography/citation.rb', line 38 def initialize(macro, *target_and_attributes_list_pairs) @uuid = SecureRandom.uuid @macro = macro @citation_items = [] target_and_attributes_list_pairs.each do |target, attribute_list| @citation_items << CitationItem.new do |cite| cite.target = target.to_s.empty? ? "default" : target cite.parse_attribute_list attribute_list end end # rubocop:enable Performance/HashEachMethods end |
Instance Attribute Details
#citation_items ⇒ Object (readonly)
Returns the value of attribute citation_items.
36 37 38 |
# File 'lib/asciidoctor-bibliography/citation.rb', line 36 def citation_items @citation_items end |
#macro ⇒ Object (readonly)
Returns the value of attribute macro.
36 37 38 |
# File 'lib/asciidoctor-bibliography/citation.rb', line 36 def macro @macro end |
Instance Method Details
#any_missing_id?(bibliographer) ⇒ Boolean
56 57 58 59 |
# File 'lib/asciidoctor-bibliography/citation.rb', line 56 def any_missing_id?(bibliographer) # NOTE: do not use :any? since it ignores nil not missing_ids(bibliographer).empty? end |
#interpolate_formatted_citation!(formatted_citation) ⇒ Object
120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/asciidoctor-bibliography/citation.rb', line 120 def interpolate_formatted_citation!(formatted_citation) citation_items.each do |citation_item| key = Regexp.escape citation_item.key formatted_citation.gsub!(/___#{key}___(?<citation>.*?)___\/#{key}___/) do # NOTE: this handles custom citation text (slight overkill but easy to extend) # NOTE: escaping ] is necessary to safely nest macros (e.g. citing in a footnote) (citation_item.text || "{cite}"). sub("{cite}", Regexp.last_match[:citation].gsub("]", "]")) end end end |
#missing_ids(bibliographer) ⇒ Object
51 52 53 54 |
# File 'lib/asciidoctor-bibliography/citation.rb', line 51 def missing_ids(bibliographer) m_ids = (@citation_items.map(&:key) - bibliographer.database.map { |entry| entry["id"] }) m_ids.map! { |id| id.nil? ? "" : id } end |
#prepare_fullcite_item(bibliographer, formatter) ⇒ Object
108 109 110 |
# File 'lib/asciidoctor-bibliography/citation.rb', line 108 def prepare_fullcite_item(bibliographer, formatter) formatter.import([bibliographer.database.find_entry_by_id(citation_items.first.key)]) end |
#prepare_item(options, item, affix: true) ⇒ Object
151 152 153 154 155 156 157 158 159 |
# File 'lib/asciidoctor-bibliography/citation.rb', line 151 def prepare_item(, item, affix: true) # TODO: hyperlink, suppress_author and only_author options ci = citation_items.detect { |c| c.key == item.id } wrap_item item, ci.prefix, ci.suffix if affix id = xref_id "bibliography", ci.target, item.id wrap_item item, "___#{item.id}___", "___/#{item.id}___" wrap_item item, "<<#{id},", ">>" if .hyperlinks? item.label, item.locator = ci.locator end |
#prepare_items(bibliographer, formatter, tex: false) ⇒ Object
132 133 134 135 136 137 138 139 |
# File 'lib/asciidoctor-bibliography/citation.rb', line 132 def prepare_items(bibliographer, formatter, tex: false) # NOTE: when we're using our custom TeX CSL styles prefix/suffix are used as # variables for metadata instead of as parameters for citations. cites_with_local_attributes = citation_items.map { |cite| bibliographer, cite, affix: tex } formatter.import cites_with_local_attributes formatter.force_sort!(mode: :citation) formatter.data.map(&:cite).each { |item| prepare_item bibliographer., item, affix: !tex } end |
#prepare_metadata(bibliographer, cite, affix: false) ⇒ Object
141 142 143 144 145 146 147 148 149 |
# File 'lib/asciidoctor-bibliography/citation.rb', line 141 def (bibliographer, cite, affix: false) bibliographer.database.find_entry_by_id(cite.key). merge 'citation-number': bibliographer.appearance_index_of(cite.target, cite.key), 'citation-label': cite.key, # TODO: smart label generators 'locator': cite.locator.nil? ? nil : " ", 'prefix': affix ? cite.prefix : nil, 'suffix': affix ? cite.suffix : nil # TODO: why is a non blank 'locator' necessary to display locators set at a later stage? end |
#render(bibliographer) ⇒ Object
61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/asciidoctor-bibliography/citation.rb', line 61 def render(bibliographer) # NOTE: If there is any blank key we must render the entire (possibly composite) # NOTE: citation as missing, as we don't have that kind of control over CSL styles. if any_missing_id?(bibliographer) warn "Warning: I didn't find a database entry for #{missing_ids(bibliographer)}." # TODO: It would be cool to have the title attribute show the missing keys # TODO: as a popup above *??* but it does not work on inline quoted text. return MISSING_ID_MARK end formatted_citation = render_with_csl(bibliographer) wrap_up_citation citation: formatted_citation, bibliographer: bibliographer end |
#render_citation_with_csl(bibliographer, style: bibliographer.options.style, tex: false) ⇒ Object
112 113 114 115 116 117 118 |
# File 'lib/asciidoctor-bibliography/citation.rb', line 112 def render_citation_with_csl(bibliographer, style: bibliographer..style, tex: false) formatter = Formatter.new(style, locale: bibliographer..locale) items = prepare_items bibliographer, formatter, tex: tex formatted_citation = formatter.engine.renderer.render(items, formatter.engine.style.citation) interpolate_formatted_citation! formatted_citation formatted_citation end |
#render_fullcite_with_csl(bibliographer) ⇒ Object
102 103 104 105 106 |
# File 'lib/asciidoctor-bibliography/citation.rb', line 102 def render_fullcite_with_csl(bibliographer) formatter = Formatter.new(bibliographer..style, locale: bibliographer..locale) prepare_fullcite_item bibliographer, formatter formatter.render(:bibliography, id: citation_items.first.key).join end |
#render_texmacro_with_csl(bibliographer) ⇒ Object
96 97 98 99 100 |
# File 'lib/asciidoctor-bibliography/citation.rb', line 96 def render_texmacro_with_csl(bibliographer) filename = ["tex", macro.tr("*", "s"), bibliographer..tex_style].join("-") filepath = File.join AsciidoctorBibliography.root, "lib/csl/styles", filename render_citation_with_csl(bibliographer, style: filepath, tex: true) end |
#render_with_csl(bibliographer) ⇒ Object
75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/asciidoctor-bibliography/citation.rb', line 75 def render_with_csl(bibliographer) case macro when "cite" render_citation_with_csl(bibliographer) when "fullcite" render_fullcite_with_csl(bibliographer) when "nocite" "" when *TEX_MACROS render_texmacro_with_csl(bibliographer) end end |
#uuid ⇒ Object
166 167 168 |
# File 'lib/asciidoctor-bibliography/citation.rb', line 166 def uuid ":#{@uuid}:" end |
#wrap_item(item, prefix, suffix) ⇒ Object
161 162 163 164 |
# File 'lib/asciidoctor-bibliography/citation.rb', line 161 def wrap_item(item, prefix, suffix) item.prefix = prefix.to_s + item.prefix.to_s item.suffix = item.suffix.to_s + suffix.to_s end |
#wrap_up_citation(citation:, bibliographer:) ⇒ Object
88 89 90 91 92 93 94 |
# File 'lib/asciidoctor-bibliography/citation.rb', line 88 def wrap_up_citation(citation:, bibliographer:) text = citation.dup # TODO: handle hyperlinks here, maybe? text = ["+++", text, "+++"].join if bibliographer..passthrough?(:citation) text.prepend "{empty}" if bibliographer..prepend_empty?(:citation) text end |
#xref_id(*fragments) ⇒ Object
170 171 172 |
# File 'lib/asciidoctor-bibliography/citation.rb', line 170 def xref_id(*fragments) fragments.compact.join("-") end |