relaton-render 3.0.0.pre.alpha.43 → 3.0.0.pre.alpha.44

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fc9353e7957ae86c466052968a77f3175a2ed765e6433f7e7d255ef8036614e2
4
- data.tar.gz: a35cb0ee37e731243be02beadc676de056d3b6e91e9f0dc6e9856c151373dbea
3
+ metadata.gz: aedee88b2cbb112fe10bea8cb0a653126eaa9b9fb4cca2acecea9ab0c658836c
4
+ data.tar.gz: 97d83f937135ae571bbd36aa4a35f1d17421a79b61aafee1690d69181bbd05ee
5
5
  SHA512:
6
- metadata.gz: a21521192e248bc508c0256d07c52d59d7cfbc911b82c43073dc99276a62031d4d4f7381eb7e435373850ab665ceee7f93b7c04ad9ee1572e37d9e996a0bc85e
7
- data.tar.gz: 3edca91d8e0c43c547e3e7d8b8007d47df15278e9d0f4a1baee6e4e7e02be52fdbcb86d9400570d7b41d45a5d99af3c6fccc86d722455d975c3673d46b1e19d1
6
+ metadata.gz: 8ed88ac9dbb5d27550fe956c9db969a052609d725e5f6eaa02e158ca65ee1937c083146dbaf5ed8223f830b5b619c36c81afbe04a8da8587755c394690787468
7
+ data.tar.gz: 92aa233a10f6e3479f971a373a7d1786215d5552368f19bd982d1dfde7d63c23d0b5b11aeee183652d48f86e00d13b9a163556c4bcf83453b315e07041b53390
@@ -0,0 +1,129 @@
1
+ require "json"
2
+
3
+ module Relaton
4
+ module Render
5
+ module Iso690
6
+ # Imports a CSL style's common properties into a CitationStyle instance
7
+ # (styles as data, the downgrade direction: CSL's element-list engine
8
+ # is strictly richer, so the import covers what the instance format can
9
+ # express and lists everything it dropped in `requires`).
10
+ #
11
+ # Mapped: the info title, the citation/reference variable runs (text
12
+ # elements over the CSL variables, via the crosswalk below), the
13
+ # name-form scalars (initialize-with, name-as-sort-order, et-al
14
+ # lengths), the year-suffix disambiguation, and the delimiters.
15
+ module CslImport
16
+ # CSL variable -> the ISO 690 slot the engine resolves.
17
+ VARIABLE_SLOTS = {
18
+ "author" => "creator", "editor" => "creator",
19
+ "title" => "title", "container-title" => "series",
20
+ "edition" => "edition", "publisher" => "production",
21
+ "publisher-place" => "location", "issued" => "date",
22
+ "DOI" => "identifier", "URL" => "identifier", "PMID" => "identifier",
23
+ "number" => "numeration", "volume" => "numeration",
24
+ "page" => "numeration", "medium" => "medium",
25
+ "accessed" => "access", "version" => "edition",
26
+ }.freeze
27
+
28
+ # CSL features the import drops, reported in `requires` so a resolver
29
+ # fails loudly instead of silently mis-rendering.
30
+ DROPPED_FEATURES = [
31
+ "csl macros (macro elements are not data-expressible)",
32
+ "csl groups with conditional rendering (match= attributes)",
33
+ "csl per-locator templates",
34
+ ].freeze
35
+
36
+ class << self
37
+ # Build a CitationStyle instance from a parsed CSL style JSON.
38
+ #
39
+ # @param csl [Hash] parsed CSL style
40
+ # @return [Style]
41
+ def style(csl)
42
+ Style.new(
43
+ name: style_name(csl),
44
+ family: "iso690",
45
+ requires: dropped_features(csl),
46
+ scheme: scheme(csl),
47
+ templates: templates(csl),
48
+ )
49
+ end
50
+
51
+ # Parse a CSL style JSON string and build the instance.
52
+ #
53
+ # @param [String] json
54
+ # @return [Style]
55
+ def from_json(json)
56
+ style(JSON.parse(json))
57
+ end
58
+
59
+ private
60
+
61
+ def style_name(csl)
62
+ title = csl.dig("info", "title").to_s
63
+ title.empty? ? "Imported CSL style" : "#{title} (CSL import)"
64
+ end
65
+
66
+ def dropped_features(csl)
67
+ feats = DROPPED_FEATURES.dup
68
+ feats << "csl bibliography section" if csl["bibliography"]
69
+ feats << "csl locales" if csl["locales"]
70
+ feats
71
+ end
72
+
73
+ def scheme(csl)
74
+ Style::Scheme.new(
75
+ system: "name-date",
76
+ name_form: name_form(csl),
77
+ locale: Style::Locale.new(no_date: "n.d."),
78
+ )
79
+ end
80
+
81
+ def name_form(csl)
82
+ citation = csl["citation"] || {}
83
+ initialize_with = citation["initialize-with"]
84
+ Style::NameForm.new(
85
+ initials: !initialize_with.nil?,
86
+ initials_separator: initialize_with.is_a?(String) ? initialize_with : " ",
87
+ initials_period: initialize_with.to_s.include?("."),
88
+ inverted_all: citation["name-as-sort-order"].to_s == "all",
89
+ )
90
+ end
91
+
92
+ def templates(csl)
93
+ citation_elements = csl.dig("citation", "elements") || []
94
+ reference_elements = csl.dig("bibliography", "elements") || []
95
+ Style::TemplateMap.new(
96
+ citation: element_template(
97
+ citation_elements, csl.dig("citation", "delimiter") || ", ",
98
+ "{{creator}}, {{date}}{{disambiguator}}",
99
+ ),
100
+ reference: element_template(
101
+ reference_elements, csl.dig("bibliography", "delimiter") || ". ",
102
+ "{{creator}}. {{title}}. {{edition}}. {{series}}. {{production}}, {{date}}. {{identifier}}. {{location}}.",
103
+ ),
104
+ name: "{{surname}}, {{givenNames}}",
105
+ )
106
+ end
107
+
108
+ # Flatten CSL text/variable elements into a slot template. Non-text
109
+ # elements (macros, groups, conditions) contribute nothing: the
110
+ # import covers flat variable runs only.
111
+ def element_template(elements, delimiter, fallback)
112
+ slots = elements.filter_map do |el|
113
+ next unless el.is_a?(Hash)
114
+
115
+ # A CSL text element nests its variable: {"text": {"variable": ...}}
116
+ variable = el.dig("text", "variable") || el["variable"]
117
+ slot = variable && VARIABLE_SLOTS[variable]
118
+ "{{#{slot}}}" if slot
119
+ end
120
+ slots = slots.uniq
121
+ return fallback if slots.empty?
122
+
123
+ slots.join(delimiter)
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
@@ -95,7 +95,7 @@ module Relaton
95
95
  return in_text_etal if in_text_etal?
96
96
 
97
97
  name = creators.first ? in_text_name(creators.first) : ""
98
- etal? ? "#{name} <em>et al.</em>" : name
98
+ etal? ? "#{name}#{etal_suffix}" : name
99
99
  end
100
100
 
101
101
  # The in-text cite truncates at its own threshold: at
@@ -104,7 +104,16 @@ module Relaton
104
104
  def in_text_etal
105
105
  names = creators.first(name_form.in_text_etal_display)
106
106
  .map { |c| in_text_name(c) }
107
- "#{join(names)} <em>et al.</em>"
107
+ "#{join(names)}#{etal_suffix}"
108
+ end
109
+
110
+ # The et-al suffix is the locale's label (roman by default; a
111
+ # pack's `others` label may carry its own presentation), joined
112
+ # per the style's list style — the serial comma before it is the
113
+ # MLA form ("Fielding, Roy, et al.")
114
+ def etal_suffix
115
+ sep = name_form.list_style == "serial" ? "," : ""
116
+ "#{sep} #{@i18n.label('others')}"
108
117
  end
109
118
 
110
119
  # The in-text cite names by surname alone (the 1.x
@@ -190,7 +199,7 @@ module Relaton
190
199
  creators.first(display).each_with_index
191
200
  .map do |contributor, index|
192
201
  format(contributor, first: index.zero?)
193
- end.join(", ") + " <em>et al.</em>"
202
+ end.join(", ") + etal_suffix
194
203
  end
195
204
 
196
205
  def format(contributor, first:)
@@ -54,10 +54,13 @@ module Relaton
54
54
  private
55
55
 
56
56
  # Worded editions are document editions; online resources
57
- # carry numbered builds rendered as versions
57
+ # carry numbered builds rendered as versions. A standard is a
58
+ # document edition too (its report kind carries the clause 8.11
59
+ # fallback templates, but its numbered editions read as
60
+ # "Nth edition" — the TS contract renders them so).
58
61
  def word_edition?
59
62
  number.positive? &&
60
- %w[monograph component_part serial_part]
63
+ %w[monograph component_part serial_part report]
61
64
  .include?(item_kind)
62
65
  end
63
66
 
@@ -41,6 +41,7 @@ labels:
41
41
  in: "In:"
42
42
  and: "and"
43
43
  oxford_comma: ","
44
+ others: "et al."
44
45
  ed: "ed."
45
46
  eds: "eds."
46
47
  date_range: "–"
@@ -15,13 +15,13 @@ scheme:
15
15
  givenNameFirst: false
16
16
  editorsMarked: false
17
17
  surnameUpcase: false
18
+ orgUpcase: false
18
19
  subsequentSurnameUpcase: false
19
20
  locale:
20
21
  "in": "In"
21
22
  labels:
22
23
  "and": "&"
23
24
  oxford_comma: ","
24
- oxford_comma: ","
25
25
  templates:
26
26
  titleOpen: ""
27
27
  titleClose: ""
@@ -34,7 +34,7 @@ perType:
34
34
  home: true
35
35
  template: "{{title}}"
36
36
  - type: report
37
- template: "{{identifier}}. {{title}}. {{production}}."
37
+ template: "{{identifier}}. ({{date}}). {{title}}. {{production}}."
38
38
  - type: monograph
39
39
  title: "<em>{{title}}</em>"
40
40
  template: "{{creator}} ({{date}}). {{title}}. {{production}}."
@@ -18,7 +18,8 @@ scheme:
18
18
  editorsMarked: true
19
19
  loneEditorMarked: true
20
20
  surnameUpcase: false
21
- subsequentSurnameUpcase: false
21
+ subsequentSurnameUpcase: true
22
+ orgUpcase: false
22
23
  locale:
23
24
  "in": "in"
24
25
  labels:
@@ -0,0 +1,56 @@
1
+ # MLA Handbook (9th ed.), Works Cited forms: every author after the
2
+ # first renders in natural order ("Dorris, Michael, and Louise
3
+ # Erdrich"), three or more collapse to "et al."; self-contained titles
4
+ # are italic and container/part titles take quotation marks; the date
5
+ # closes the entry before the extent. The in-text citation carries the
6
+ # author alone - MLA has no date in the parenthesis.
7
+ name: "MLA (9th edition) Works Cited"
8
+ family: mla
9
+ requires:
10
+ - extent_units
11
+ scheme:
12
+ system: name-date
13
+ nameForm:
14
+ initials: false
15
+ initialsSeparator: " "
16
+ initialsPeriod: true
17
+ invertedAll: false
18
+ givenNameFirst: false
19
+ editorsMarked: true
20
+ surnameUpcase: false
21
+ subsequentSurnameUpcase: false
22
+ orgUpcase: false
23
+ listStyle: serial
24
+ etalCount: 3
25
+ etalDisplay: 1
26
+ locale:
27
+ "in": "in"
28
+ labels:
29
+ "and": "and"
30
+ oxford_comma: ","
31
+ others: "et al."
32
+ templates:
33
+ titleOpen: "\""
34
+ titleClose: "\""
35
+ citation: "{{surname}}"
36
+ reference: "{{creator}}. {{title}}. {{edition}}. {{series}}. {{production}}, {{date}}. {{extent}}."
37
+ name: "{{surname}}, {{givenNames}}"
38
+ identifierMode: all
39
+ perType:
40
+ - type: report
41
+ title: "<em>{{title}}</em>"
42
+ template: "{{creator}}. {{title}}. {{edition}}. {{production}}, {{date}}."
43
+ - type: monograph
44
+ title: "<em>{{title}}</em>"
45
+ template: "{{creator}}. {{title}}. {{edition}}. {{production}}, {{date}}. {{extent}}."
46
+ - type: component_part
47
+ title: "\"{{title}}\""
48
+ componentpart: "<em>{{componentpart}}</em>"
49
+ template: "{{creator}}. {{title}}. {{componentpart}}, {{production}}, {{date}}. {{extent}}."
50
+ - type: continuing
51
+ title: "\"{{title}}\""
52
+ series: "<em>{{seriestitle}}</em>"
53
+ template: "{{creator}}. {{title}}. {{series}}, {{date}}. {{extent}}."
54
+ sortKey:
55
+ - attribute: creator
56
+ - attribute: date
@@ -21,6 +21,7 @@ module Relaton
21
21
  autoload :Renderer, "relaton/render/iso690/renderer"
22
22
  autoload :Rules, "relaton/render/iso690/rules"
23
23
  autoload :Style, "relaton/render/iso690/style"
24
+ autoload :CslImport, "relaton/render/iso690/csl_import"
24
25
  autoload :Template, "relaton/render/iso690/template"
25
26
  end
26
27
  end
@@ -1,5 +1,5 @@
1
1
  module Relaton
2
2
  module Render
3
- VERSION = "3.0.0.pre.alpha.43".freeze
3
+ VERSION = "3.0.0.pre.alpha.44".freeze
4
4
  end
5
5
  end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ # The gem's require entry: the public rendering surface — General (the
4
+ # localized multi-renderer front) and the ISO 690 engine with its
5
+ # CitationStyle loader. Styles are data (lib/relaton/render/iso690/styles);
6
+ # the engine holds none.
7
+ require_relative "render/version"
8
+ require_relative "render/general"
9
+ require_relative "render/iso690"
@@ -24,7 +24,7 @@ Gem::Specification.new do |spec|
24
24
  spec.add_dependency "htmlentities"
25
25
  spec.add_development_dependency "relaton-bib"
26
26
  spec.add_dependency "liquid", "~> 5"
27
- spec.add_dependency "lutaml-model"
27
+ spec.add_dependency "lutaml-model", "~> 0.8"
28
28
  spec.add_dependency "nokogiri"
29
29
  spec.add_dependency "twitter_cldr"
30
30
  # spec.metadata["rubygems_mfa_required"] = "true"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: relaton-render
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0.pre.alpha.43
4
+ version: 3.0.0.pre.alpha.44
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-10-10 00:00:00.000000000 Z
11
+ date: 2026-10-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: htmlentities
@@ -56,16 +56,16 @@ dependencies:
56
56
  name: lutaml-model
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ">="
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '0'
61
+ version: '0.8'
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ">="
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '0'
68
+ version: '0.8'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: nokogiri
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -115,8 +115,10 @@ files:
115
115
  - bin/setup
116
116
  - docs/citation-style-pack.adoc
117
117
  - lib/relaton-render.rb
118
+ - lib/relaton/render.rb
118
119
  - lib/relaton/render/general.rb
119
120
  - lib/relaton/render/iso690.rb
121
+ - lib/relaton/render/iso690/csl_import.rb
120
122
  - lib/relaton/render/iso690/element.rb
121
123
  - lib/relaton/render/iso690/elements.rb
122
124
  - lib/relaton/render/iso690/elements/access.rb
@@ -165,6 +167,7 @@ files:
165
167
  - lib/relaton/render/iso690/styles/jis-en.yml
166
168
  - lib/relaton/render/iso690/styles/jis-ja.yml
167
169
  - lib/relaton/render/iso690/styles/lncs.yml
170
+ - lib/relaton/render/iso690/styles/mla.yml
168
171
  - lib/relaton/render/iso690/template.rb
169
172
  - lib/relaton/render/version.rb
170
173
  - relaton-render.gemspec