theoj 1.11.0 → 1.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/lib/theoj/author.rb +93 -14
- data/lib/theoj/paper.rb +7 -7
- data/lib/theoj/submission.rb +1 -1
- data/lib/theoj/version.rb +1 -1
- metadata +16 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6862eb2fc9d140c509d46202caf2bbd5edd8aa8273ab5a97ed9cfabaa1bdef04
|
|
4
|
+
data.tar.gz: 674e699e2e66dbb855e2423a1b04f0ccb7efd10e8455c95caa01504186c1f324
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9ae854285d72cb34bedc7bacb4bf6f04c966d13c1cd3d133c73ffaa786fef0c7fdfe9c22924d988fe625f79da653748a53ad7026804ffff5542550cdc17edbc3
|
|
7
|
+
data.tar.gz: cf43d49f026b8e9498c26287c8a8afc1bfd8ae29dabfe58d5652b5783e0c9a4e6b12f8389e2c327ba09d92a782e521f7178441185842430ab93c1ba5d6d70adf
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.12.0 (2026-01-20)
|
|
4
|
+
|
|
5
|
+
- Update name parsing to match JOSS' Pandoc pipeline
|
|
6
|
+
|
|
7
|
+
## 1.11.1 (2025-07-16)
|
|
8
|
+
|
|
9
|
+
- Remove code tags & html comments from title in submission metadata
|
|
10
|
+
|
|
3
11
|
## 1.11.0 (2025-06-21)
|
|
4
12
|
|
|
5
13
|
- Remove support for Ruby 3.1
|
data/lib/theoj/author.rb
CHANGED
|
@@ -17,19 +17,51 @@ module Theoj
|
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
def given_name
|
|
20
|
-
@
|
|
20
|
+
return nil if @given_names.to_s.strip.empty?
|
|
21
|
+
|
|
22
|
+
@given_names.to_s.split(/\s+/).first
|
|
21
23
|
end
|
|
22
24
|
|
|
23
25
|
def middle_name
|
|
24
|
-
@
|
|
26
|
+
return nil if @middle_names.to_s.strip.empty?
|
|
27
|
+
|
|
28
|
+
@middle_names
|
|
25
29
|
end
|
|
26
30
|
|
|
27
31
|
def last_name
|
|
28
|
-
@
|
|
32
|
+
particle = @non_dropping_particle.to_s.strip.empty? ? @dropping_particle : @non_dropping_particle
|
|
33
|
+
name_parts = [particle, @surname, @suffix].map do |part|
|
|
34
|
+
part.to_s.strip
|
|
35
|
+
end.reject(&:empty?)
|
|
36
|
+
|
|
37
|
+
fallback = @surname || @literal_name
|
|
38
|
+
|
|
39
|
+
name_parts.empty? ? fallback : name_parts.join(" ")
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def citation_last_name
|
|
43
|
+
return @literal_name unless @literal_name.to_s.strip.empty?
|
|
44
|
+
|
|
45
|
+
name_parts = [@non_dropping_particle, @surname, @suffix].map do |part|
|
|
46
|
+
part.to_s.strip
|
|
47
|
+
end.reject(&:empty?)
|
|
48
|
+
|
|
49
|
+
return @surname if name_parts.empty?
|
|
50
|
+
|
|
51
|
+
name_parts.join(" ")
|
|
29
52
|
end
|
|
30
53
|
|
|
31
54
|
def initials
|
|
32
|
-
|
|
55
|
+
initials_parts = []
|
|
56
|
+
first_name = given_name.to_s
|
|
57
|
+
initials_parts << "#{first_name[0]}." unless first_name.empty?
|
|
58
|
+
|
|
59
|
+
middle_for_initials = @middle_names.to_s.strip.empty? ? @dropping_particle : @middle_names
|
|
60
|
+
unless middle_for_initials.to_s.strip.empty?
|
|
61
|
+
initials_parts.concat(middle_for_initials.split(/\s+/).map { |v| "#{v[0]}." })
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
initials_parts.compact.join(" ")
|
|
33
65
|
end
|
|
34
66
|
|
|
35
67
|
def to_h
|
|
@@ -46,24 +78,71 @@ module Theoj
|
|
|
46
78
|
|
|
47
79
|
def parse_name(author_name)
|
|
48
80
|
if author_name.is_a? Hash
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
@
|
|
81
|
+
name_parts = normalize_name_parts(author_name)
|
|
82
|
+
given_names = strip_footnotes(name_parts[:given_names])
|
|
83
|
+
dropping_particle = strip_footnotes(name_parts[:dropping_particle])
|
|
84
|
+
@dropping_particle = dropping_particle
|
|
85
|
+
@non_dropping_particle = strip_footnotes(name_parts[:non_dropping_particle])
|
|
86
|
+
display_particle = @non_dropping_particle || dropping_particle
|
|
87
|
+
@surname = strip_footnotes(name_parts[:surname])
|
|
88
|
+
@suffix = strip_footnotes(name_parts[:suffix])
|
|
89
|
+
literal_name = strip_footnotes(name_parts[:literal])
|
|
90
|
+
@literal_name = literal_name unless literal_name.to_s.strip.empty?
|
|
91
|
+
@middle_names = nil
|
|
92
|
+
@given_names = given_names
|
|
93
|
+
|
|
94
|
+
surname_with_particle = [@non_dropping_particle || @dropping_particle, @surname].compact.reject(&:empty?).join(" ")
|
|
95
|
+
name_hash = {
|
|
96
|
+
first: given_names,
|
|
97
|
+
middle: dropping_particle,
|
|
98
|
+
last: surname_with_particle,
|
|
99
|
+
suffix: @suffix
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
@parsed_name = Nameable::Latin.new(name_hash)
|
|
103
|
+
@name = @literal_name || build_display_name(given_names, display_particle, nil, @surname, @suffix)
|
|
57
104
|
else
|
|
58
|
-
|
|
105
|
+
parsed_name = Nameable::Latin.new.parse(strip_footnotes(author_name))
|
|
106
|
+
@parsed_name = parsed_name
|
|
107
|
+
@given_names = parsed_name.first
|
|
108
|
+
@middle_names = parsed_name.middle
|
|
109
|
+
@surname = parsed_name.last
|
|
110
|
+
@suffix = parsed_name.suffix
|
|
111
|
+
@dropping_particle = nil
|
|
112
|
+
@non_dropping_particle = nil
|
|
113
|
+
@literal_name = nil
|
|
114
|
+
@name = build_display_name(@given_names, nil, nil, @surname, @suffix)
|
|
59
115
|
end
|
|
116
|
+
end
|
|
60
117
|
|
|
61
|
-
|
|
118
|
+
def normalize_name_parts(author_hash)
|
|
119
|
+
{
|
|
120
|
+
literal: fetch_name_field(author_hash, %w[literal]),
|
|
121
|
+
given_names: fetch_name_field(author_hash, ["given-names", "given", "first", "firstname"]),
|
|
122
|
+
dropping_particle: fetch_name_field(author_hash, ["dropping-particle"]),
|
|
123
|
+
non_dropping_particle: fetch_name_field(author_hash, ["non-dropping-particle"]),
|
|
124
|
+
surname: fetch_name_field(author_hash, ["surname", "family"]),
|
|
125
|
+
suffix: fetch_name_field(author_hash, ["suffix"])
|
|
126
|
+
}
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def fetch_name_field(name_hash, keys)
|
|
130
|
+
keys.map do |key|
|
|
131
|
+
name_hash[key] || name_hash[key.to_sym]
|
|
132
|
+
end.compact.first
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def build_display_name(given_names, dropping_particle, non_dropping_particle, surname, suffix)
|
|
136
|
+
[given_names, dropping_particle, non_dropping_particle, surname, suffix].map do |part|
|
|
137
|
+
part.to_s.strip
|
|
138
|
+
end.reject(&:empty?).join(" ")
|
|
62
139
|
end
|
|
63
140
|
|
|
64
141
|
# Input: Arfon Smith^[Corresponding author: arfon@example.com]
|
|
65
142
|
# Output: Arfon Smith
|
|
66
143
|
def strip_footnotes(author_name)
|
|
144
|
+
return nil if author_name.nil?
|
|
145
|
+
|
|
67
146
|
author_name.to_s[AUTHOR_FOOTNOTE_REGEX]
|
|
68
147
|
end
|
|
69
148
|
|
data/lib/theoj/paper.rb
CHANGED
|
@@ -26,14 +26,14 @@ module Theoj
|
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
def citation_author
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
first_author = authors.first
|
|
30
|
+
surname = first_author.citation_last_name.to_s
|
|
31
|
+
initials = first_author.initials
|
|
31
32
|
|
|
32
|
-
if authors.size > 1
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
end
|
|
33
|
+
return "#{surname} et al." if authors.size > 1
|
|
34
|
+
return surname if initials.to_s.strip.empty?
|
|
35
|
+
|
|
36
|
+
"#{surname}, #{initials}"
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
def title
|
data/lib/theoj/submission.rb
CHANGED
|
@@ -187,7 +187,7 @@ module Theoj
|
|
|
187
187
|
|
|
188
188
|
def plaintext(t)
|
|
189
189
|
parsed_title = Commonmarker.to_html(t.strip, options:{ render: { hardbreaks: false } })
|
|
190
|
-
parsed_title.gsub("\n", "").gsub(" ", " ").gsub(/\A<p>/, "").gsub(/<\/p>\z/, "").gsub("<span data-escaped-char>", "").gsub("<span>", "").gsub(/<\/span>/, "")
|
|
190
|
+
parsed_title.gsub("\n", "").gsub(" ", " ").gsub(/\A<p>/, "").gsub(/<\/p>\z/, "").gsub("<span data-escaped-char>", "").gsub("<span>", "").gsub(/<\/span>/, "").gsub("<code>", "").gsub(/<\/code>/, "").gsub("<!-- raw HTML omitted -->","")
|
|
191
191
|
end
|
|
192
192
|
|
|
193
193
|
def format_date(date_string)
|
data/lib/theoj/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: theoj
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.12.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Juanjo Bazán
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date:
|
|
10
|
+
date: 2026-01-20 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: octokit
|
|
@@ -121,6 +121,20 @@ dependencies:
|
|
|
121
121
|
- - ">="
|
|
122
122
|
- !ruby/object:Gem::Version
|
|
123
123
|
version: '0'
|
|
124
|
+
- !ruby/object:Gem::Dependency
|
|
125
|
+
name: ostruct
|
|
126
|
+
requirement: !ruby/object:Gem::Requirement
|
|
127
|
+
requirements:
|
|
128
|
+
- - ">="
|
|
129
|
+
- !ruby/object:Gem::Version
|
|
130
|
+
version: '0'
|
|
131
|
+
type: :runtime
|
|
132
|
+
prerelease: false
|
|
133
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
134
|
+
requirements:
|
|
135
|
+
- - ">="
|
|
136
|
+
- !ruby/object:Gem::Version
|
|
137
|
+
version: '0'
|
|
124
138
|
- !ruby/object:Gem::Dependency
|
|
125
139
|
name: rake
|
|
126
140
|
requirement: !ruby/object:Gem::Requirement
|