From 8032f55cc4cc160db8259e3123f4f25557ac5a78 Mon Sep 17 00:00:00 2001 From: Max Kadel Date: Tue, 8 Oct 2024 19:14:18 +0300 Subject: [PATCH] Add APA and Chicago CiteProc citations - Moves shared CiteProc methods into their own module --- .reek.yml | 2 +- .../concerns/blacklight/document/apa.rb | 21 +++++++ .../concerns/blacklight/document/chicago.rb | 21 +++++++ .../concerns/blacklight/document/cite_proc.rb | 62 +++++++++++++++++++ .../concerns/blacklight/document/mla.rb | 57 ----------------- app/models/solr_document.rb | 10 +++ spec/models/apa_spec.rb | 53 ++++++++++++++++ spec/models/chicago_spec.rb | 53 ++++++++++++++++ 8 files changed, 221 insertions(+), 58 deletions(-) create mode 100644 app/models/concerns/blacklight/document/apa.rb create mode 100644 app/models/concerns/blacklight/document/chicago.rb create mode 100644 app/models/concerns/blacklight/document/cite_proc.rb create mode 100644 spec/models/apa_spec.rb create mode 100644 spec/models/chicago_spec.rb diff --git a/.reek.yml b/.reek.yml index c01be552a..513801373 100644 --- a/.reek.yml +++ b/.reek.yml @@ -753,6 +753,7 @@ detectors: - Requests::RequestMailer#service_error_email - Bookmark#self.destroy_without_solr_documents - Bookmark#self.update_to_alma_ids + - Blacklight::Document::CiteProc#properties - Blacklight::Document::DublinCore#export_as_oai_dc_xml - Blacklight::Document::DublinCore#export_as_rdf_dc - Blacklight::Document::Email#add_holdings_text @@ -762,7 +763,6 @@ detectors: - Blacklight::Document::JsonLd#date - Blacklight::Document::JsonLd#identifier - Blacklight::Document::JsonLd#location - - Blacklight::Document::Mla#properties - Blacklight::Document::Ris#author_roles_1display_to_ris - Blacklight::Document::Ris#export_as_ris - Blacklight::Marc::DocumentExtension#build_ctx diff --git a/app/models/concerns/blacklight/document/apa.rb b/app/models/concerns/blacklight/document/apa.rb new file mode 100644 index 000000000..16657b8a5 --- /dev/null +++ b/app/models/concerns/blacklight/document/apa.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +# Creates an html APA citation for non-Marc records +module Blacklight::Document::Apa + def self.extended(document) + Blacklight::Document::Apa.register_export_formats(document) + end + + def self.register_export_formats(document) + document.will_export_as(:apa, 'text/html') + end + + def export_as_apa + return export_as_apa_citation_txt if alma? + + cp = CiteProc::Processor.new style: 'apa', format: 'html' + item = CiteProc::Item.new(properties) + cp.import(item) + cp.render(:bibliography, id:).first + end +end diff --git a/app/models/concerns/blacklight/document/chicago.rb b/app/models/concerns/blacklight/document/chicago.rb new file mode 100644 index 000000000..4d56f4b42 --- /dev/null +++ b/app/models/concerns/blacklight/document/chicago.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +# Creates an html Chicago citation for non-Marc records +module Blacklight::Document::Chicago + def self.extended(document) + Blacklight::Document::Chicago.register_export_formats(document) + end + + def self.register_export_formats(document) + document.will_export_as(:chicago, 'text/html') + end + + def export_as_chicago + return export_as_chicago_citation_txt if alma? + + cp = CiteProc::Processor.new style: 'chicago-author-date', format: 'html' + item = CiteProc::Item.new(properties) + cp.import(item) + cp.render(:bibliography, id:).first + end +end diff --git a/app/models/concerns/blacklight/document/cite_proc.rb b/app/models/concerns/blacklight/document/cite_proc.rb new file mode 100644 index 000000000..ee4d88954 --- /dev/null +++ b/app/models/concerns/blacklight/document/cite_proc.rb @@ -0,0 +1,62 @@ +# frozen_string_literal: true + +## Adds the methods needed for CiteProc citations, +# Including MLA, APA, and Chicago +module Blacklight::Document::CiteProc + private + + def properties + props = {} + props[:id] = id + props[:edition] = cite_proc_edition if cite_proc_edition + props[:type] = cite_proc_type if cite_proc_type + props[:author] = cite_proc_author if cite_proc_author + props[:title] = cite_proc_title if cite_proc_title + props[:publisher] = cite_proc_publisher if cite_proc_publisher + props[:'publisher-place'] = cite_proc_publisher_place if cite_proc_publisher_place + props[:issued] = cite_proc_issued if cite_proc_issued + props + end + + def cite_proc_type + self[:format]&.first&.downcase + end + + def cite_proc_author + @cite_proc_author ||= begin + family, given = citation_fields_from_solr[:author_citation_display]&.first&.split(', ') + CiteProc::Name.new(family:, given:) if family || given + end + end + + def cite_proc_edition + @cite_proc_edition ||= begin + str = citation_fields_from_solr[:edition_display]&.first + str&.dup&.sub!(/[[:punct:]]?$/, '') + end + end + + def cite_proc_title + @cite_proc_title ||= citation_fields_from_solr[:title_citation_display]&.first + end + + def cite_proc_publisher + @cite_proc_publisher ||= citation_fields_from_solr[:pub_citation_display]&.first&.split(': ').try(:[], 1) + end + + def cite_proc_publisher_place + @cite_proc_publisher_place ||= citation_fields_from_solr[:pub_citation_display]&.first&.split(': ').try(:[], 0) + end + + def cite_proc_issued + @cite_proc_issued ||= citation_fields_from_solr[:pub_date_start_sort] + end + + def citation_fields_from_solr + @citation_fields_from_solr ||= begin + params = { q: "id:#{RSolr.solr_escape(id)}", fl: "author_citation_display, title_citation_display, pub_citation_display, number_of_pages_citation_display, pub_date_start_sort, edition_display" } + solr_response = Blacklight.default_index.connection.get('select', params:) + solr_response["response"]["docs"].first.with_indifferent_access + end + end +end diff --git a/app/models/concerns/blacklight/document/mla.rb b/app/models/concerns/blacklight/document/mla.rb index 94e3a11d4..015e97187 100644 --- a/app/models/concerns/blacklight/document/mla.rb +++ b/app/models/concerns/blacklight/document/mla.rb @@ -18,61 +18,4 @@ def export_as_mla cp.import(item) cp.render(:bibliography, id:).first end - - private - - def properties - props = {} - props[:id] = id - props[:edition] = mla_edition if mla_edition - props[:type] = mla_type if mla_type - props[:author] = mla_author if mla_author - props[:title] = mla_title if mla_title - props[:publisher] = mla_publisher if mla_publisher - props[:'publisher-place'] = mla_publisher_place if mla_publisher_place - props[:issued] = mla_issued if mla_issued - props - end - - def mla_type - self[:format]&.first&.downcase - end - - def mla_author - @mla_author ||= begin - family, given = citation_fields_from_solr[:author_citation_display]&.first&.split(', ') - CiteProc::Name.new(family:, given:) if family || given - end - end - - def mla_edition - @mla_edition ||= begin - str = citation_fields_from_solr[:edition_display]&.first - str&.dup&.sub!(/[[:punct:]]?$/, '') - end - end - - def mla_title - @mla_title ||= citation_fields_from_solr[:title_citation_display]&.first - end - - def mla_publisher - @mla_publisher ||= citation_fields_from_solr[:pub_citation_display]&.first&.split(': ').try(:[], 1) - end - - def mla_publisher_place - @mla_publisher_place ||= citation_fields_from_solr[:pub_citation_display]&.first&.split(': ').try(:[], 0) - end - - def mla_issued - @mla_issued ||= citation_fields_from_solr[:pub_date_start_sort] - end - - def citation_fields_from_solr - @citation_fields_from_solr ||= begin - params = { q: "id:#{RSolr.solr_escape(id)}", fl: "author_citation_display, title_citation_display, pub_citation_display, number_of_pages_citation_display, pub_date_start_sort, edition_display" } - solr_response = Blacklight.default_index.connection.get('select', params:) - solr_response["response"]["docs"].first.with_indifferent_access - end - end end diff --git a/app/models/solr_document.rb b/app/models/solr_document.rb index 87e4240dc..3f95248c3 100644 --- a/app/models/solr_document.rb +++ b/app/models/solr_document.rb @@ -52,9 +52,19 @@ class SolrDocument ## Adds JSON-LD use_extension(Blacklight::Document::JsonLd) + ## Adds the methods needed for CiteProc citations, + # Including MLA, APA, and Chicago + use_extension(Blacklight::Document::CiteProc) + ## Adds MLA html use_extension(Blacklight::Document::Mla) + # Adds APA html + use_extension(Blacklight::Document::Apa) + + # Adds Chicago html + use_extension(Blacklight::Document::Chicago) + def identifier_data values = identifiers.each_with_object({}) do |identifier, hsh| hsh[identifier.data_key.to_sym] ||= [] diff --git a/spec/models/apa_spec.rb b/spec/models/apa_spec.rb new file mode 100644 index 000000000..125519212 --- /dev/null +++ b/spec/models/apa_spec.rb @@ -0,0 +1,53 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe Blacklight::Document::Apa, citation: true do + let(:document) { SolrDocument.new(properties).export_as_apa } + + context 'with a SCSB record' do + context 'with a book' do + let(:properties) do + { + id: "SCSB-2635660", + format: ['Book'], + author_citation_display: ["Saer, Juan José"], + edition_display: ['1a edición.'], + title_citation_display: ['El entenado'], + pub_citation_display: ["Barcelona: Destino"], + pub_date_start_sort: 1988 + } + end + + it 'includes the author' do + expect(document).to include('Saer') + expect(document).to include('Juan José. ') + end + + it 'includes the author with the proper delimiter' do + pending('Fixing the bug with CiteProc') + expect(document).to include('Saer, Juan José. ') + end + + it 'includes the title in italics' do + expect(document).to include('El entenado') + end + + it 'includes the publisher' do + expect(document).to include('Destino') + end + + it 'does not include the place of publication' do + expect(document).not_to include('Barcelona') + end + + it 'includes the publication date' do + expect(document).to include('1988') + end + + it 'includes the edition' do + expect(document).to include('(1a edición)') + end + end + end +end diff --git a/spec/models/chicago_spec.rb b/spec/models/chicago_spec.rb new file mode 100644 index 000000000..5aabdcb50 --- /dev/null +++ b/spec/models/chicago_spec.rb @@ -0,0 +1,53 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe Blacklight::Document::Chicago, citation: true do + let(:document) { SolrDocument.new(properties).export_as_chicago } + + context 'with a SCSB record' do + context 'with a book' do + let(:properties) do + { + id: "SCSB-2635660", + format: ['Book'], + author_citation_display: ["Saer, Juan José"], + edition_display: ['1a edición.'], + title_citation_display: ['El entenado'], + pub_citation_display: ["Barcelona: Destino"], + pub_date_start_sort: 1988 + } + end + + it 'includes the author' do + expect(document).to include('Saer') + expect(document).to include('Juan José. ') + end + + it 'includes the author with the proper delimiter' do + pending('Fixing the bug with CiteProc') + expect(document).to include('Saer, Juan José. ') + end + + it 'includes the title in italics' do + expect(document).to include('El Entenado') + end + + it 'includes the publisher' do + expect(document).to include('Destino') + end + + it 'includes the place of publication' do + expect(document).to include('Barcelona') + end + + it 'includes the publication date' do + expect(document).to include('1988') + end + + it 'includes the edition' do + expect(document).to include('1A edición') + end + end + end +end