relaton 3.0.6 → 3.0.8
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/bin/relaton +20 -0
- data/lib/relaton/bib/model/docidentifier.rb +17 -2
- data/lib/relaton/bibcollection.rb +146 -0
- data/lib/relaton/bibdata.rb +92 -0
- data/lib/relaton/bipm/data_outcomes_parser.rb +6 -1
- data/lib/relaton/cli/base_convertor.rb +134 -0
- data/lib/relaton/cli/command.rb +390 -0
- data/lib/relaton/cli/data_fetcher.rb +20 -0
- data/lib/relaton/cli/frontend/dist/404.html +18 -0
- data/lib/relaton/cli/frontend/dist/app.iife.js +1 -0
- data/lib/relaton/cli/frontend/dist/style.css +3 -0
- data/lib/relaton/cli/frontend/index.html +14 -0
- data/lib/relaton/cli/frontend/package-lock.json +2945 -0
- data/lib/relaton/cli/frontend/package.json +29 -0
- data/lib/relaton/cli/frontend/public/404.html +18 -0
- data/lib/relaton/cli/frontend/src/App.test.ts +501 -0
- data/lib/relaton/cli/frontend/src/App.vue +506 -0
- data/lib/relaton/cli/frontend/src/app.ts +90 -0
- data/lib/relaton/cli/frontend/src/components/DocumentDetail.test.ts +142 -0
- data/lib/relaton/cli/frontend/src/components/DocumentDetail.vue +228 -0
- data/lib/relaton/cli/frontend/src/components/DocumentRow.vue +88 -0
- data/lib/relaton/cli/frontend/src/components/Icon.test.ts +44 -0
- data/lib/relaton/cli/frontend/src/components/Icon.vue +55 -0
- data/lib/relaton/cli/frontend/src/components/Pagination.vue +26 -0
- data/lib/relaton/cli/frontend/src/dev/main.ts +100 -0
- data/lib/relaton/cli/frontend/src/dev/sample-data.json +71 -0
- data/lib/relaton/cli/frontend/src/lib/filter.test.ts +88 -0
- data/lib/relaton/cli/frontend/src/lib/filter.ts +95 -0
- data/lib/relaton/cli/frontend/src/lib/hydrate.test.ts +102 -0
- data/lib/relaton/cli/frontend/src/lib/hydrate.ts +55 -0
- data/lib/relaton/cli/frontend/src/lib/shards.test.ts +319 -0
- data/lib/relaton/cli/frontend/src/lib/shards.ts +183 -0
- data/lib/relaton/cli/frontend/src/lib/types.ts +148 -0
- data/lib/relaton/cli/frontend/src/lib/url.test.ts +151 -0
- data/lib/relaton/cli/frontend/src/lib/url.ts +111 -0
- data/lib/relaton/cli/frontend/src/shims-vue.d.ts +5 -0
- data/lib/relaton/cli/frontend/src/styles/index.css +27 -0
- data/lib/relaton/cli/frontend/src/test/fetch.ts +58 -0
- data/lib/relaton/cli/frontend/tsconfig.json +20 -0
- data/lib/relaton/cli/frontend/vite.config.ts +42 -0
- data/lib/relaton/cli/frontend/vitest.config.ts +11 -0
- data/lib/relaton/cli/frontend_assets.rb +58 -0
- data/lib/relaton/cli/full_text_search.rb +98 -0
- data/lib/relaton/cli/i18n.yaml +1 -0
- data/lib/relaton/cli/index_item_normalizer.rb +380 -0
- data/lib/relaton/cli/index_site_generator.rb +1015 -0
- data/lib/relaton/cli/relaton_file.rb +290 -0
- data/lib/relaton/cli/subcommand_collection.rb +263 -0
- data/lib/relaton/cli/subcommand_db.rb +81 -0
- data/lib/relaton/cli/templates/_document.liquid +111 -0
- data/lib/relaton/cli/templates/_index.liquid +61 -0
- data/lib/relaton/cli/templates/index/page.liquid +20 -0
- data/lib/relaton/cli/templates/index-style.css +1017 -0
- data/lib/relaton/cli/util.rb +8 -0
- data/lib/relaton/cli/version.rb +11 -0
- data/lib/relaton/cli/xml_convertor.rb +47 -0
- data/lib/relaton/cli/xml_to_html_renderer.rb +117 -0
- data/lib/relaton/cli/yaml_convertor.rb +102 -0
- data/lib/relaton/cli.rb +113 -0
- data/lib/relaton/doi/CLAUDE.md +1 -1
- data/lib/relaton/element_finder.rb +29 -0
- data/lib/relaton/gb/CLAUDE.md +1 -1
- data/lib/relaton/ietf/CLAUDE.md +1 -1
- data/lib/relaton/iho/CLAUDE.md +3 -3
- data/lib/relaton/iho/bibliography.rb +41 -27
- data/lib/relaton/iho/processor.rb +3 -2
- data/lib/relaton/nist/CLAUDE.md +11 -1
- data/lib/relaton/nist/README.adoc +7 -1
- data/lib/relaton/nist/hit_collection.rb +25 -1
- data/lib/relaton/nist/mods_parser.rb +32 -8
- data/lib/relaton/nist/pubs_export.rb +69 -11
- data/lib/relaton/ogc/CLAUDE.md +1 -1
- data/lib/relaton/omg/CLAUDE.md +1 -1
- data/lib/relaton/plateau/CLAUDE.md +1 -1
- data/lib/relaton/render/general.rb +319 -0
- data/lib/relaton/render/iso690/csl_import.rb +129 -0
- data/lib/relaton/render/iso690/element.rb +153 -0
- data/lib/relaton/render/iso690/elements/access.rb +44 -0
- data/lib/relaton/render/iso690/elements/authorizer.rb +45 -0
- data/lib/relaton/render/iso690/elements/citeid.rb +39 -0
- data/lib/relaton/render/iso690/elements/component_part.rb +97 -0
- data/lib/relaton/render/iso690/elements/creator.rb +267 -0
- data/lib/relaton/render/iso690/elements/edition.rb +97 -0
- data/lib/relaton/render/iso690/elements/extent.rb +71 -0
- data/lib/relaton/render/iso690/elements/identifier.rb +46 -0
- data/lib/relaton/render/iso690/elements/location.rb +73 -0
- data/lib/relaton/render/iso690/elements/medium.rb +32 -0
- data/lib/relaton/render/iso690/elements/numeration.rb +26 -0
- data/lib/relaton/render/iso690/elements/production.rb +111 -0
- data/lib/relaton/render/iso690/elements/pub_date.rb +63 -0
- data/lib/relaton/render/iso690/elements/series.rb +66 -0
- data/lib/relaton/render/iso690/elements/size.rb +45 -0
- data/lib/relaton/render/iso690/elements/status.rb +30 -0
- data/lib/relaton/render/iso690/elements/stddoc.rb +40 -0
- data/lib/relaton/render/iso690/elements/title.rb +56 -0
- data/lib/relaton/render/iso690/elements/updated.rb +38 -0
- data/lib/relaton/render/iso690/elements.rb +67 -0
- data/lib/relaton/render/iso690/fields.rb +142 -0
- data/lib/relaton/render/iso690/i18n/en.yml +48 -0
- data/lib/relaton/render/iso690/i18n/fr.yml +14 -0
- data/lib/relaton/render/iso690/i18n/ja.yml +38 -0
- data/lib/relaton/render/iso690/i18n.rb +83 -0
- data/lib/relaton/render/iso690/identifier_kinds.rb +29 -0
- data/lib/relaton/render/iso690/index_renderer.rb +57 -0
- data/lib/relaton/render/iso690/kinds.rb +53 -0
- data/lib/relaton/render/iso690/renderer.rb +150 -0
- data/lib/relaton/render/iso690/rules/bipm.rb +186 -0
- data/lib/relaton/render/iso690/rules/jis.rb +103 -0
- data/lib/relaton/render/iso690/rules/nist.rb +384 -0
- data/lib/relaton/render/iso690/rules.rb +227 -0
- data/lib/relaton/render/iso690/style/locale.rb +59 -0
- data/lib/relaton/render/iso690/style/name_form.rb +87 -0
- data/lib/relaton/render/iso690/style/scheme.rb +33 -0
- data/lib/relaton/render/iso690/style/sort_rule.rb +25 -0
- data/lib/relaton/render/iso690/style/template_map.rb +40 -0
- data/lib/relaton/render/iso690/style/type_template.rb +45 -0
- data/lib/relaton/render/iso690/style.rb +227 -0
- data/lib/relaton/render/iso690/styles/apa.yml +45 -0
- data/lib/relaton/render/iso690/styles/author-date.yml +31 -0
- data/lib/relaton/render/iso690/styles/chicago.yml +49 -0
- data/lib/relaton/render/iso690/styles/ieee-sa.yml +45 -0
- data/lib/relaton/render/iso690/styles/jis-en.yml +68 -0
- data/lib/relaton/render/iso690/styles/jis-ja.yml +67 -0
- data/lib/relaton/render/iso690/styles/lncs.yml +54 -0
- data/lib/relaton/render/iso690/styles/mla.yml +56 -0
- data/lib/relaton/render/iso690/template.rb +248 -0
- data/lib/relaton/render/iso690.rb +28 -0
- data/lib/relaton/render/version.rb +5 -0
- data/lib/relaton/un/CLAUDE.md +1 -1
- data/lib/relaton/version.rb +1 -1
- data/lib/relaton-cli.rb +17 -0
- data/lib/relaton-render.rb +13 -0
- metadata +192 -21
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c2d44cf8ad434afddc1e4b0b2b4ce979970271e7ce871c48a2bb436e42eccfee
|
|
4
|
+
data.tar.gz: '07891a8f6deafa0d294519798a4576e7de997d0faead9d02077d9ab840c5d2ab'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5ca0eb885107187f7881e2fd42e665cebc70b6e9154f3b52cfeb8597037f5543dd9d921cb698a17e86723c86b592cef6bc19979051cc2bff7b4898c981c45840
|
|
7
|
+
data.tar.gz: ed359c58cb0ef93f972c0a30e8d89aed165841a9b392664241fa15f08d638fbf72a9e50c29994acc4bb5de3a7c0b0394c8bf9d801cf99c217c06b282e75089a3
|
data/bin/relaton
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# encoding: UTF-8
|
|
3
|
+
|
|
4
|
+
# resolve bin path, ignoring symlinks
|
|
5
|
+
require "pathname"
|
|
6
|
+
bin_file = Pathname.new(__FILE__).realpath
|
|
7
|
+
|
|
8
|
+
# add self to libpath
|
|
9
|
+
$:.unshift File.expand_path("../../lib", bin_file)
|
|
10
|
+
|
|
11
|
+
# Fixes https://github.com/rubygems/rubygems/issues/1420
|
|
12
|
+
require "rubygems/specification"
|
|
13
|
+
|
|
14
|
+
class Gem::Specification
|
|
15
|
+
def this; self; end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
require "relaton-cli"
|
|
19
|
+
|
|
20
|
+
Relaton::Cli.start(ARGV)
|
|
@@ -66,7 +66,7 @@ module Relaton
|
|
|
66
66
|
"BSI" => :Bsi,
|
|
67
67
|
}.freeze
|
|
68
68
|
|
|
69
|
-
FORMS = %i[external internal].freeze
|
|
69
|
+
FORMS = %i[external internal slug].freeze
|
|
70
70
|
|
|
71
71
|
# The parsed identifier. A pubid-backed flavor subclass overrides it.
|
|
72
72
|
def pubid; end
|
|
@@ -94,7 +94,22 @@ module Relaton
|
|
|
94
94
|
def form_content(form)
|
|
95
95
|
flavor = FORM_PUBID[type]
|
|
96
96
|
id = flavor && (pubid || parse_form_pubid(flavor))
|
|
97
|
-
|
|
97
|
+
return content unless id
|
|
98
|
+
|
|
99
|
+
return slug_form(id) if form == :slug
|
|
100
|
+
|
|
101
|
+
id.to_s(with_publisher: form == :external)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# The pubid-scheme slug (relaton#441): the URN in HTTP-path
|
|
105
|
+
# clothes, bijective with Pubid.from_slug. A flavor whose
|
|
106
|
+
# pubid-scheme schema has not landed yet degrades to the stored
|
|
107
|
+
# content, like a form pubid cannot parse.
|
|
108
|
+
def slug_form(id)
|
|
109
|
+
require "pubid"
|
|
110
|
+
::Pubid.to_slug(id)
|
|
111
|
+
rescue ::Pubid::Errors::InvalidInputError, NameError
|
|
112
|
+
content
|
|
98
113
|
end
|
|
99
114
|
|
|
100
115
|
def parse_form_pubid(flavor)
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
require "relaton/element_finder"
|
|
2
|
+
|
|
3
|
+
module Relaton
|
|
4
|
+
class Bibcollection
|
|
5
|
+
extend Relaton::ElementFinder
|
|
6
|
+
|
|
7
|
+
ATTRIBS = %i[title items doctype author].freeze
|
|
8
|
+
|
|
9
|
+
attr_accessor(*ATTRIBS)
|
|
10
|
+
|
|
11
|
+
# @param options [Hash]
|
|
12
|
+
def initialize(options)
|
|
13
|
+
ATTRIBS.each do |k|
|
|
14
|
+
value = options[k] || options[k.to_s]
|
|
15
|
+
send("#{k}=", value)
|
|
16
|
+
end
|
|
17
|
+
reduce_items
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# arbitrary number, must sort after all bib items
|
|
21
|
+
def doc_number
|
|
22
|
+
9999999
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Add a dcoument to the collection
|
|
26
|
+
# @param item [RelatonBib::BibliographicItem]
|
|
27
|
+
def <<(item)
|
|
28
|
+
items << new_bib_item_class(item)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# rubocop:disable Metrics/MethodLength
|
|
32
|
+
|
|
33
|
+
# @param source [Nokogiri::XML::Element]
|
|
34
|
+
def self.from_xml(source)
|
|
35
|
+
title = find_html("./relaton-collection/title", source)
|
|
36
|
+
author = find_html(
|
|
37
|
+
"./relaton-collection/contributor[role/@type='author']/organization/"\
|
|
38
|
+
"name", source
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
items = find_xpath("./relaton-collection/relation", source)&.map do |item|
|
|
42
|
+
bibdata = find("./bibdata|./bibitem", item)
|
|
43
|
+
klass = bibdata ? Bibdata : Bibcollection
|
|
44
|
+
klass.from_xml(bibdata || item)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
new(title: title, author: author, items: items)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# rubocop:disable Metrics/AbcSize
|
|
51
|
+
|
|
52
|
+
# @param opts [Hash]
|
|
53
|
+
# @return [String] XML
|
|
54
|
+
def to_xml(opts = {})
|
|
55
|
+
items.sort_by! &:doc_number
|
|
56
|
+
|
|
57
|
+
collection_type = if doctype
|
|
58
|
+
"type=\"#{doctype}\""
|
|
59
|
+
else
|
|
60
|
+
'xmlns="https://open.ribose.com/relaton-xml"'
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
ret = "<relaton-collection #{collection_type}>"
|
|
64
|
+
ret += "<title>#{xml_escape(title)}</title>" if title
|
|
65
|
+
if author
|
|
66
|
+
ret += "<contributor><role type='author'/><organization><name>"\
|
|
67
|
+
"#{xml_escape(author)}</name></organization></contributor>"
|
|
68
|
+
end
|
|
69
|
+
unless items.empty?
|
|
70
|
+
items.each do |item|
|
|
71
|
+
ret += "<relation type='partOf'>"
|
|
72
|
+
ret += item.to_xml(opts)
|
|
73
|
+
ret += "</relation>\n"
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
ret += "</relaton-collection>\n"
|
|
77
|
+
end
|
|
78
|
+
# rubocop:enable Metrics/AbcSize
|
|
79
|
+
|
|
80
|
+
# @param item [Hash, RelatonBib::BibliographicItem, Relatin::Bibdata,
|
|
81
|
+
# Relaton::Bibcollection]
|
|
82
|
+
# @return [Relaton::Bibdata, Relaton::Bibcollection]
|
|
83
|
+
def new_bib_item_class(item)
|
|
84
|
+
if item.is_a?(Hash)
|
|
85
|
+
if item["items"]
|
|
86
|
+
::Relaton::Bibcollection.new(item)
|
|
87
|
+
else
|
|
88
|
+
bibitem = ::Relaton::Cli::YAMLConvertor.convert_single_file item
|
|
89
|
+
::Relaton::Bibdata.new bibitem
|
|
90
|
+
end
|
|
91
|
+
elsif item.is_a?(Relaton::Bibdata) || item.is_a?(Relaton::Bibcollection)
|
|
92
|
+
item
|
|
93
|
+
else ::Relaton::Bibdata.new(item)
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
# rubocop:enable Metrics/MethodLength
|
|
97
|
+
|
|
98
|
+
def items_flattened
|
|
99
|
+
items.sort_by! &:doc_number
|
|
100
|
+
|
|
101
|
+
items.reduce([]) do |acc, item|
|
|
102
|
+
acc << if item.is_a? ::Relaton::Bibcollection
|
|
103
|
+
item.items_flattened
|
|
104
|
+
else
|
|
105
|
+
item
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def to_yaml
|
|
111
|
+
to_h.to_yaml
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def to_h
|
|
115
|
+
items.sort_by! &:doc_number
|
|
116
|
+
|
|
117
|
+
a = ATTRIBS.reduce({}) do |acc, k|
|
|
118
|
+
acc[k.to_s] = send(k)
|
|
119
|
+
acc
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
a["items"] = a["items"].map(&:to_h)
|
|
123
|
+
|
|
124
|
+
{ "root" => a }
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
private
|
|
128
|
+
|
|
129
|
+
def reduce_items
|
|
130
|
+
self.items = (items || []).reduce([]) do |acc, item|
|
|
131
|
+
acc << if item.is_a?(Bibcollection) || item.is_a?(Bibdata)
|
|
132
|
+
item
|
|
133
|
+
else new_bib_item_class(item)
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# Escape bare & in content for XML serialization, leaving already-encoded
|
|
139
|
+
# entity references (&, {, ) and inline markup (<em> etc.)
|
|
140
|
+
# untouched. This prevents invalid XML when plain-text values (e.g. from
|
|
141
|
+
# YAML) contain literal ampersands.
|
|
142
|
+
def xml_escape(str)
|
|
143
|
+
str.gsub(/&(?![a-zA-Z][a-zA-Z0-9]*;|#[0-9]+;|#x[0-9a-fA-F]+;)/, "&")
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
require "date"
|
|
2
|
+
|
|
3
|
+
module Relaton
|
|
4
|
+
class Bibdata
|
|
5
|
+
URL_TYPES = %i[uri xml pdf doc html rxl txt].freeze
|
|
6
|
+
|
|
7
|
+
# @return [RelatonBib::BibliographicItem]
|
|
8
|
+
attr_reader :bibitem
|
|
9
|
+
|
|
10
|
+
# @param bibitem [RelatonBib::BibliographicItem]
|
|
11
|
+
def initialize(bibitem)
|
|
12
|
+
@bibitem = bibitem
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def docidentifier
|
|
16
|
+
@bibitem.docidentifier.first&.content&.to_s
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# def doctype
|
|
20
|
+
# @bibitem.type
|
|
21
|
+
# end
|
|
22
|
+
|
|
23
|
+
# From http://gavinmiller.io/2016/creating-a-secure-sanitization-function/
|
|
24
|
+
FILENAME_BAD_CHARS = ["/", '\\', "?", "%", "*", ":", "|", '"', "<", ">",
|
|
25
|
+
".", " "].freeze
|
|
26
|
+
|
|
27
|
+
def docidentifier_code
|
|
28
|
+
return "" if docidentifier.nil?
|
|
29
|
+
|
|
30
|
+
FILENAME_BAD_CHARS.reduce(docidentifier.downcase) do |result, bad_char|
|
|
31
|
+
result.gsub(bad_char, "-")
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
DOC_NUMBER_REGEX = /([\w\/]+)\s+(\d+):?(\d*)/.freeze
|
|
36
|
+
def doc_number
|
|
37
|
+
docidentifier&.match(DOC_NUMBER_REGEX) ? $2.to_i : 999999
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def self.from_xml(source)
|
|
41
|
+
bi = Relaton::Cli.parse_xml(source)
|
|
42
|
+
new(bi) if bi
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def to_xml(opts = {})
|
|
46
|
+
options = { bibdata: true, date_format: :full }.merge(
|
|
47
|
+
opts.select { |k, _v| k.is_a? Symbol },
|
|
48
|
+
)
|
|
49
|
+
@bibitem.to_xml(**options)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def to_h
|
|
53
|
+
URL_TYPES.each_with_object(YAML.safe_load(@bibitem.to_yaml)) do |t, h|
|
|
54
|
+
value = send t
|
|
55
|
+
h[t.to_s] = value if value
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def to_yaml
|
|
60
|
+
to_h.to_yaml
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/AbcSize
|
|
64
|
+
# rubocop:disable Metrics/MethodLength, Metrics/PerceivedComplexity, Style/MissingRespondToMissing
|
|
65
|
+
|
|
66
|
+
def method_missing(meth, *args)
|
|
67
|
+
if @bibitem.respond_to?(meth)
|
|
68
|
+
@bibitem.send meth, *args
|
|
69
|
+
elsif URL_TYPES.include? meth
|
|
70
|
+
source = (@bibitem.source || []).detect do |l|
|
|
71
|
+
l.type == meth.to_s || (meth == :uri && l.type.nil?)
|
|
72
|
+
end
|
|
73
|
+
source&.content&.to_s
|
|
74
|
+
elsif URL_TYPES.include? meth.match(/^\w+(?==)/).to_s.to_sym
|
|
75
|
+
/^(?<type>\w+)/ =~ meth
|
|
76
|
+
@bibitem.source ||= []
|
|
77
|
+
source = @bibitem.source.detect do |l|
|
|
78
|
+
l.type == type || (type == "uri" && l.type.nil?)
|
|
79
|
+
end
|
|
80
|
+
if source
|
|
81
|
+
source.content = args[0]
|
|
82
|
+
else
|
|
83
|
+
@bibitem.source << Relaton::Bib::Uri.new(type: type, content: args[0])
|
|
84
|
+
end
|
|
85
|
+
else
|
|
86
|
+
super
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/AbcSize
|
|
90
|
+
# rubocop:enable Metrics/MethodLength, Metrics/PerceivedComplexity, Style/MissingRespondToMissing
|
|
91
|
+
end
|
|
92
|
+
end
|
|
@@ -94,9 +94,14 @@ module Relaton::Bipm
|
|
|
94
94
|
@data_fetcher.write_file path, has_part_item, warn_duplicate: false
|
|
95
95
|
path = File.join dir, "#{num}-#{part}.#{@data_fetcher.ext}"
|
|
96
96
|
elsif part
|
|
97
|
-
|
|
97
|
+
# The part item keeps the full titles ("… (Session I)"); the base
|
|
98
|
+
# item's titles drop the parenthetical. Assign the stripped form -
|
|
99
|
+
# `Title#content` exposes the source metadata string, and a
|
|
100
|
+
# mutating `sub!` would strip the part item's title too (the two
|
|
101
|
+
# share the string object).
|
|
98
102
|
h = meeting_bibitem body: body, type: type, en: en_md, fr: fr_md, num: num, src: src, pdf: en["pdf"]
|
|
99
103
|
add_part h, body, type, num, part
|
|
104
|
+
hash[:title].each { |t| t.content = t.content.sub(/\s\(.+\)$/, "") }
|
|
100
105
|
part_item = ItemData.new(**h)
|
|
101
106
|
part_item_path = File.join dir, "#{num}-#{part}.#{@data_fetcher.ext}"
|
|
102
107
|
@data_fetcher.write_file part_item_path, part_item
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
require "fileutils"
|
|
2
|
+
require "relaton/bibdata"
|
|
3
|
+
require "relaton/bibcollection"
|
|
4
|
+
require "relaton/cli/xml_to_html_renderer"
|
|
5
|
+
|
|
6
|
+
module Relaton
|
|
7
|
+
module Cli
|
|
8
|
+
class BaseConvertor
|
|
9
|
+
def initialize(file, options = {})
|
|
10
|
+
@file = file
|
|
11
|
+
@options = options
|
|
12
|
+
@outdir = options.fetch(:outdir, nil)
|
|
13
|
+
@writable = options.fetch(:write, true)
|
|
14
|
+
@overwrite = options.fetch(:overwrite, true)
|
|
15
|
+
@default_filelabel = 0
|
|
16
|
+
|
|
17
|
+
install_dependencies(options[:require] || [])
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# @return [String] HTML
|
|
21
|
+
def to_html
|
|
22
|
+
content = convert_to_html
|
|
23
|
+
write_to_a_file(content)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Convert to HTML
|
|
27
|
+
#
|
|
28
|
+
# This interface expect us to provide Relaton collection XML
|
|
29
|
+
# as XML/RXL, and necessary styels / templates then it will be
|
|
30
|
+
# used convert that collection to HTML.
|
|
31
|
+
#
|
|
32
|
+
# @param file [String] Relaton collection file path
|
|
33
|
+
# @param style [String] Stylesheet file path for styles
|
|
34
|
+
# @param template [String] The liquid tempalte directory
|
|
35
|
+
#
|
|
36
|
+
# @return [String] HTML
|
|
37
|
+
def self.to_html(file, style = nil, template = nil)
|
|
38
|
+
new(
|
|
39
|
+
file,
|
|
40
|
+
style: style || File.join(File.dirname(__FILE__), "templates/index-style.css"),
|
|
41
|
+
template: template || File.join(File.dirname(__FILE__), "templates/"),
|
|
42
|
+
extension: "html"
|
|
43
|
+
).to_html
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
private
|
|
47
|
+
|
|
48
|
+
attr_reader :file, :outdir, :options, :writable, :overwrite
|
|
49
|
+
|
|
50
|
+
# @return [String] HTML
|
|
51
|
+
def convert_to_html
|
|
52
|
+
Relaton::Cli::XmlToHtmlRenderer.render(
|
|
53
|
+
xml_content(file),
|
|
54
|
+
stylesheet: options[:style],
|
|
55
|
+
liquid_dir: options[:template]
|
|
56
|
+
)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# @param file [String] path to a file
|
|
60
|
+
# @return [String] the file's content
|
|
61
|
+
# @return [String] HTML
|
|
62
|
+
def xml_content(file)
|
|
63
|
+
File.read(file, encoding: "utf-8")
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def install_dependencies(dependencies)
|
|
67
|
+
dependencies.each { |dependency| require(dependency) }
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def item_output(content, format)
|
|
71
|
+
case format.to_sym
|
|
72
|
+
when :to_yaml then content.to_yaml
|
|
73
|
+
when :to_xml then content.to_xml(date_format: :full, bibdata: true)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def convert_and_write(content, format)
|
|
78
|
+
content = convert_content(content)
|
|
79
|
+
write_to_a_file(item_output(content, format))
|
|
80
|
+
write_to_file_collection(content, format.to_sym)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def write_to_a_file(content, outfile = nil)
|
|
84
|
+
outfile ||= Pathname.new(file).sub_ext(extension).to_s
|
|
85
|
+
|
|
86
|
+
if !File.exist?(outfile) || overwrite
|
|
87
|
+
File.open(outfile, "w:utf-8") do |file|
|
|
88
|
+
file.write(content)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def write_to_file_collection(content, format)
|
|
94
|
+
if outdir && content.is_a?(Relaton::Bibcollection)
|
|
95
|
+
FileUtils.mkdir_p(outdir)
|
|
96
|
+
content.items_flattened.each do |item|
|
|
97
|
+
collection = collection_filename(extract_docid(item))
|
|
98
|
+
write_to_a_file(item_output(item, format), collection)
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def extract_docid(item)
|
|
104
|
+
@default_filelabel += 1
|
|
105
|
+
item.docidentifier.nil? && (return @default_filelabel.to_s)
|
|
106
|
+
# item.docidentifier.is_a?(Array) or return @default_filelabel.to_s
|
|
107
|
+
item.docidentifier.empty? && (return @default_filelabel.to_s)
|
|
108
|
+
docidentifier_code(item.docidentifier)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# From http://gavinmiller.io/2016/creating-a-secure-sanitization-function/
|
|
112
|
+
FILENAME_BAD_CHARS = ["/", '\\', "?", '%", "*", ":', "|", '"', "<", ">",
|
|
113
|
+
".", " "].freeze
|
|
114
|
+
|
|
115
|
+
def docidentifier_code(docidentifier)
|
|
116
|
+
return "" if docidentifier.nil?
|
|
117
|
+
|
|
118
|
+
FILENAME_BAD_CHARS.reduce(docidentifier.downcase) do |result, bad_char|
|
|
119
|
+
result.gsub(bad_char, "-")
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def extension
|
|
124
|
+
@extension ||= [".", options.fetch(:extension, default_ext)].join
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def collection_filename(identifier)
|
|
128
|
+
File.join(
|
|
129
|
+
outdir, [@options[:prefix], identifier, extension].compact.join("")
|
|
130
|
+
)
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|