From 921b0c9dc2c2af83b193cdab86dda37ae3d3d4b4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Gaya?= <sebastien.gaya@gmail.com>
Date: Fri, 7 Jul 2023 16:44:56 +0200
Subject: [PATCH] citations on research journal paper

---
 Gemfile                               |  4 +++-
 Gemfile.lock                          | 14 ++++++++++++++
 app/models/concerns/with_citations.rb | 28 +++++++++++++++++++++++++++
 app/models/research/journal/paper.rb  | 18 +++++++++++++++++
 4 files changed, 63 insertions(+), 1 deletion(-)
 create mode 100644 app/models/concerns/with_citations.rb

diff --git a/Gemfile b/Gemfile
index f912dfc61..1a97a4ebd 100644
--- a/Gemfile
+++ b/Gemfile
@@ -15,8 +15,11 @@ gem "breadcrumbs_on_rails"
 gem "bugsnag"
 gem "cancancan", "3.3.0"
 gem "caxlsx_rails", "~> 0.6.3"
+gem "citeproc", "~> 1.0"
+gem "citeproc-ruby", "~> 2.0"
 gem "cocoon", "~> 1.2"
 gem "country_select"
+gem "csl-styles", "~> 2.0"
 gem "curation"#, path: "../../arnaudlevy/curation"
 gem "delayed_job_active_record"
 gem "delayed_job_web"
@@ -91,4 +94,3 @@ group :test do
 end
 
 gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw, :jruby]
-
diff --git a/Gemfile.lock b/Gemfile.lock
index 83b5f9329..b69910983 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -152,6 +152,11 @@ GEM
     caxlsx_rails (0.6.3)
       actionpack (>= 3.1)
       caxlsx (>= 3.0)
+    citeproc (1.0.10)
+      namae (~> 1.0)
+    citeproc-ruby (2.0.0)
+      citeproc (~> 1.0, >= 1.0.9)
+      csl (~> 2.0)
     cocoon (1.2.15)
     concurrent-ruby (1.2.2)
     countries (5.5.0)
@@ -161,6 +166,11 @@ GEM
     crack (0.4.5)
       rexml
     crass (1.0.6)
+    csl (2.0.0)
+      namae (~> 1.0)
+      rexml
+    csl-styles (2.0.1)
+      csl (~> 2.0)
     curation (1.10)
       htmlentities
       metainspector (~> 5.12)
@@ -330,6 +340,7 @@ GEM
     multipart-post (2.3.0)
     mustermann (3.0.0)
       ruby2_keywords (~> 0.0.1)
+    namae (1.1.1)
     nesty (1.0.2)
     net-http (0.3.2)
       uri
@@ -575,8 +586,11 @@ DEPENDENCIES
   cancancan (= 3.3.0)
   capybara (>= 3.26)
   caxlsx_rails (~> 0.6.3)
+  citeproc (~> 1.0)
+  citeproc-ruby (~> 2.0)
   cocoon (~> 1.2)
   country_select
+  csl-styles (~> 2.0)
   curation
   delayed_job_active_record
   delayed_job_web
diff --git a/app/models/concerns/with_citations.rb b/app/models/concerns/with_citations.rb
new file mode 100644
index 000000000..2b7214615
--- /dev/null
+++ b/app/models/concerns/with_citations.rb
@@ -0,0 +1,28 @@
+module WithCitations
+  extend ActiveSupport::Concern
+
+  def citation_apa(website)
+    citation_for(website, "apa")
+  end
+
+  def citation_iso690(website)
+    citation_for(website, "iso690-author-date-fr-no-abstract")
+  end
+
+  def citation_mla(website)
+    citation_for(website, "modern-language-association")
+  end
+
+  protected
+
+  def citeproc_for_website(website)
+    raise NotImplementedError
+  end
+
+  def citation_for(website, style)
+    citeproc = citeproc_for_website(website)
+    processor = CiteProc::Processor.new style: style, format: 'text'
+    processor.import([citeproc])
+    processor.render(:bibliography, id: citeproc["id"]).first
+  end
+end
\ No newline at end of file
diff --git a/app/models/research/journal/paper.rb b/app/models/research/journal/paper.rb
index d616d31e5..793b684ea 100644
--- a/app/models/research/journal/paper.rb
+++ b/app/models/research/journal/paper.rb
@@ -47,6 +47,7 @@ class Research::Journal::Paper < ApplicationRecord
   include Sanitizable
   include WithBlobs
   include WithBlocks
+  include WithCitations
   include WithGitFiles
   include WithPermalink
   include WithPosition
@@ -105,6 +106,23 @@ class Research::Journal::Paper < ApplicationRecord
 
   protected
 
+  def citeproc_for_website(website)
+    {
+      "title" => title,
+      "author" => people.map { |person|
+        { "family" => person.last_name, "given" => person.first_name }
+      },
+      "URL" => website.url + Communication::Website::Permalink.for_object(self, website).computed_path,
+      "container-title" => journal.title,
+      "publisher" => university.name,
+      "keywords" => keywords,
+      "pdf" => pdf.attached? ? pdf.url : nil,
+      "month-numeric" => published_at.present? ? published_at.month.to_s : nil,
+      "issued" => published_at.present? ? { "date-parts" => [[published_at.year, published_at.month]] } : nil,
+      "id" => id
+    }
+  end
+
   def other_papers_in_the_volume
     return [] if volume.nil?
     volume.papers.where.not(id: self)
-- 
GitLab