relaton 3.0.7 → 3.1.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/bin/relaton +20 -0
- data/lib/relaton/3gpp/processor.rb +1 -1
- data/lib/relaton/3gpp.rb +3 -3
- data/lib/relaton/adobe/processor.rb +1 -1
- data/lib/relaton/adobe.rb +3 -3
- data/lib/relaton/bib/item_data.rb +2 -2
- data/lib/relaton/bib/model/docidentifier.rb +17 -2
- data/lib/relaton/bib.rb +2 -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/bipm/processor.rb +1 -1
- data/lib/relaton/bipm.rb +3 -3
- data/lib/relaton/bsi/processor.rb +1 -1
- data/lib/relaton/bsi.rb +1 -1
- data/lib/relaton/calconnect/data_fetcher.rb +2 -2
- data/lib/relaton/calconnect/model/item.rb +1 -1
- data/lib/relaton/calconnect/processor.rb +1 -1
- data/lib/relaton/calconnect.rb +2 -2
- data/lib/relaton/ccsds/data/fetcher.rb +1 -1
- data/lib/relaton/ccsds/model/item.rb +1 -1
- data/lib/relaton/ccsds/processor.rb +1 -1
- data/lib/relaton/ccsds/util.rb +1 -1
- data/lib/relaton/ccsds.rb +1 -1
- data/lib/relaton/cen/processor.rb +1 -1
- data/lib/relaton/cen.rb +2 -2
- data/lib/relaton/cie/data_fetcher.rb +3 -3
- data/lib/relaton/cie/processor.rb +1 -1
- data/lib/relaton/cie.rb +2 -2
- data/lib/relaton/cli/base_convertor.rb +134 -0
- data/lib/relaton/cli/command.rb +396 -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 +1043 -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/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 +103 -0
- data/lib/relaton/core/processor.rb +1 -1
- data/lib/relaton/core.rb +1 -1
- data/lib/relaton/db/registry.rb +1 -1
- data/lib/relaton/db.rb +1 -1
- data/lib/relaton/doi/CLAUDE.md +1 -1
- data/lib/relaton/doi/parser.rb +2 -1
- data/lib/relaton/doi/processor.rb +1 -1
- data/lib/relaton/doi.rb +4 -4
- data/lib/relaton/easc/processor.rb +1 -1
- data/lib/relaton/easc.rb +3 -3
- data/lib/relaton/ecma/data_fetcher.rb +1 -1
- data/lib/relaton/ecma/processor.rb +1 -1
- data/lib/relaton/ecma.rb +2 -2
- data/lib/relaton/element_finder.rb +29 -0
- data/lib/relaton/etsi/data_fetcher.rb +2 -2
- data/lib/relaton/etsi/item.rb +1 -1
- data/lib/relaton/etsi/processor.rb +2 -2
- data/lib/relaton/etsi.rb +1 -1
- data/lib/relaton/evs/processor.rb +1 -1
- data/lib/relaton/evs.rb +2 -2
- data/lib/relaton/gb/CLAUDE.md +1 -1
- data/lib/relaton/gb/bibliography.rb +1 -1
- data/lib/relaton/gb/processor.rb +1 -1
- data/lib/relaton/gb.rb +2 -2
- data/lib/relaton/gost/processor.rb +1 -1
- data/lib/relaton/gost.rb +3 -3
- data/lib/relaton/iala/processor.rb +1 -1
- data/lib/relaton/iala.rb +3 -3
- data/lib/relaton/iana/data_fetcher.rb +1 -1
- data/lib/relaton/iana/processor.rb +1 -1
- data/lib/relaton/iana.rb +2 -2
- data/lib/relaton/iec/data_fetcher.rb +1 -1
- data/lib/relaton/iec/processor.rb +1 -1
- data/lib/relaton/iec.rb +2 -2
- data/lib/relaton/ieee/processor.rb +1 -1
- data/lib/relaton/ieee.rb +2 -2
- data/lib/relaton/ietf/CLAUDE.md +1 -1
- data/lib/relaton/ietf/data_fetcher.rb +1 -1
- data/lib/relaton/ietf/processor.rb +1 -1
- data/lib/relaton/ietf.rb +2 -2
- data/lib/relaton/iho/CLAUDE.md +3 -3
- data/lib/relaton/iho/bibliography.rb +41 -27
- data/lib/relaton/iho/hash_parser_v1.rb +1 -1
- data/lib/relaton/iho/processor.rb +4 -3
- data/lib/relaton/iho.rb +2 -2
- data/lib/relaton/index.rb +1 -1
- data/lib/relaton/isbn/processor.rb +1 -1
- data/lib/relaton/isbn.rb +1 -1
- data/lib/relaton/iso/hash_parser_v1.rb +1 -1
- data/lib/relaton/iso/processor.rb +1 -1
- data/lib/relaton/iso.rb +3 -3
- data/lib/relaton/itu/processor.rb +1 -1
- data/lib/relaton/itu.rb +3 -3
- data/lib/relaton/jcgm/processor.rb +1 -1
- data/lib/relaton/jcgm.rb +2 -2
- data/lib/relaton/jis/processor.rb +1 -1
- data/lib/relaton/jis.rb +2 -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/processor.rb +1 -1
- data/lib/relaton/nist/pubs_export.rb +69 -11
- data/lib/relaton/nist.rb +2 -2
- data/lib/relaton/oasis/processor.rb +1 -1
- data/lib/relaton/oasis.rb +2 -2
- data/lib/relaton/ogc/CLAUDE.md +1 -1
- data/lib/relaton/ogc/processor.rb +1 -1
- data/lib/relaton/ogc.rb +2 -2
- data/lib/relaton/oiml/processor.rb +1 -1
- data/lib/relaton/oiml.rb +2 -2
- data/lib/relaton/omg/CLAUDE.md +1 -1
- data/lib/relaton/omg/processor.rb +1 -1
- data/lib/relaton/omg.rb +1 -1
- data/lib/relaton/plateau/CLAUDE.md +1 -1
- data/lib/relaton/plateau/data_fetcher.rb +1 -1
- data/lib/relaton/plateau/processor.rb +1 -1
- data/lib/relaton/plateau.rb +2 -2
- 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/sae/CLAUDE.md +89 -0
- data/lib/relaton/sae/bibdata.rb +8 -0
- data/lib/relaton/sae/bibitem.rb +8 -0
- data/lib/relaton/sae/bibliography.rb +128 -0
- data/lib/relaton/sae/data_fetcher.rb +219 -0
- data/lib/relaton/sae/doi_code.rb +83 -0
- data/lib/relaton/sae/item.rb +10 -0
- data/lib/relaton/sae/item_data.rb +6 -0
- data/lib/relaton/sae/processor.rb +62 -0
- data/lib/relaton/sae/util.rb +9 -0
- data/lib/relaton/sae.rb +37 -0
- data/lib/relaton/un/CLAUDE.md +1 -1
- data/lib/relaton/un/processor.rb +1 -1
- data/lib/relaton/un.rb +1 -1
- data/lib/relaton/version.rb +1 -1
- data/lib/relaton/w3c/bibliography.rb +1 -1
- data/lib/relaton/w3c/data_fetcher.rb +1 -1
- data/lib/relaton/w3c/processor.rb +1 -1
- data/lib/relaton/w3c.rb +2 -2
- data/lib/relaton/xsf/data_fetcher.rb +1 -1
- data/lib/relaton/xsf/processor.rb +1 -1
- data/lib/relaton/xsf.rb +2 -2
- data/lib/relaton-cli.rb +17 -0
- data/lib/relaton-render.rb +12 -0
- data/lib/relaton.rb +3 -2
- metadata +203 -23
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
require "nokogiri"
|
|
2
|
+
require_relative "base_convertor"
|
|
3
|
+
|
|
4
|
+
module Relaton
|
|
5
|
+
module Cli
|
|
6
|
+
class XMLConvertor < Relaton::Cli::BaseConvertor
|
|
7
|
+
def to_yaml
|
|
8
|
+
convert_and_write(file_content, :to_yaml)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Convert to YAML
|
|
12
|
+
#
|
|
13
|
+
# This interface allow us to convert any XML file to YAML.
|
|
14
|
+
# It only require us to provide a valid XML file and it can
|
|
15
|
+
# do converstion using default attributes, but it also allow
|
|
16
|
+
# us to provide custom options to customize this converstion
|
|
17
|
+
# process.
|
|
18
|
+
#
|
|
19
|
+
# @param file [File] The complete path to a XML file
|
|
20
|
+
# @param options [Hash] Options as hash key, value pairs.
|
|
21
|
+
#
|
|
22
|
+
def self.to_yaml(file, options = {})
|
|
23
|
+
new(file, options).to_yaml
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def default_ext
|
|
29
|
+
"yaml"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# @param content [Nokogiri::XML::Document]
|
|
33
|
+
# @return [Hash]
|
|
34
|
+
def convert_content(content)
|
|
35
|
+
if %w[bibitem bibdata].include? content.root.name
|
|
36
|
+
Bibdata.from_xml(content)
|
|
37
|
+
else
|
|
38
|
+
Bibcollection.from_xml(content)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def file_content
|
|
43
|
+
Nokogiri::XML(File.read(file, encoding: "utf-8"))
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
require "nokogiri"
|
|
2
|
+
require "liquid"
|
|
3
|
+
|
|
4
|
+
module Relaton::Cli
|
|
5
|
+
class XmlToHtmlRenderer
|
|
6
|
+
def initialize(liquid_dir: nil, stylesheet: nil)
|
|
7
|
+
@liquid_dir = liquid_dir
|
|
8
|
+
@stylesheet = read_file(stylesheet)
|
|
9
|
+
init_liquid_template_and_filesystem
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# @param index_xml [String] Relaton XML
|
|
13
|
+
# @return [String] HTML
|
|
14
|
+
def render(index_xml)
|
|
15
|
+
Liquid::Template
|
|
16
|
+
.parse(template)
|
|
17
|
+
.render(build_liquid_document(index_xml))
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def uri_for_extension(uri, extension)
|
|
21
|
+
uri&.sub(/\.[^.]+$/, ".#{extension}")
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Render HTML
|
|
25
|
+
#
|
|
26
|
+
# This interface allow us to convert a Relaton XML to HTML
|
|
27
|
+
# using the specified liquid template and stylesheets. It
|
|
28
|
+
# also do some minor clean during this conversion.
|
|
29
|
+
#
|
|
30
|
+
# @param file [String] Relaton XML
|
|
31
|
+
# @param options [Hash]
|
|
32
|
+
# @return [String] HTML
|
|
33
|
+
def self.render(file, options)
|
|
34
|
+
new(**options).render(file)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
attr_reader :stylesheet, :liquid_dir, :template
|
|
40
|
+
|
|
41
|
+
def read_file(file)
|
|
42
|
+
File.read(file, encoding: "utf-8")
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# rubocop:disable Metrics/MethodLength
|
|
46
|
+
# @param source [String] Relaton XML
|
|
47
|
+
def build_liquid_document(source)
|
|
48
|
+
bibcollection = build_bibcollection(source)
|
|
49
|
+
hash_to_liquid(
|
|
50
|
+
depth: 2,
|
|
51
|
+
css: stylesheet,
|
|
52
|
+
title: bibcollection.title,
|
|
53
|
+
date: DateTime.now.to_s,
|
|
54
|
+
author: bibcollection.author,
|
|
55
|
+
documents: document_items(bibcollection)
|
|
56
|
+
)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def init_liquid_template_and_filesystem
|
|
60
|
+
file_system = Liquid::LocalFileSystem.new(liquid_dir)
|
|
61
|
+
@template = read_file(file_system.full_path("index"))
|
|
62
|
+
|
|
63
|
+
Liquid::Template.file_system = file_system
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
67
|
+
|
|
68
|
+
# TODO: This should be recursive, but it's not
|
|
69
|
+
# @param hash [Hash]
|
|
70
|
+
# @option hash [Integer] :dept
|
|
71
|
+
# @option hash [String] :css path to stylesheet file
|
|
72
|
+
# @option hash [String] :title
|
|
73
|
+
# @option hash [String] :author
|
|
74
|
+
# @option hash [Array<Hash>] :documents
|
|
75
|
+
#
|
|
76
|
+
# @return [Hash]
|
|
77
|
+
def hash_to_liquid(hash)
|
|
78
|
+
hash.map do |key, value|
|
|
79
|
+
case key
|
|
80
|
+
when "title"
|
|
81
|
+
if value.is_a?(Array)
|
|
82
|
+
title = value.detect { |t| t["type"] == "main" } || value.first
|
|
83
|
+
v = title ? title["content"] : nil
|
|
84
|
+
elsif value.is_a?(Hash) then v = value["content"]
|
|
85
|
+
else v = value
|
|
86
|
+
end
|
|
87
|
+
when "docidentifier"
|
|
88
|
+
did = if value.is_a?(Array)
|
|
89
|
+
value.detect { |d| (d["id"] || d["content"]).to_s !~ /^(http|https):\/\// } ||
|
|
90
|
+
value.first
|
|
91
|
+
else value
|
|
92
|
+
end
|
|
93
|
+
v = did
|
|
94
|
+
else v = value
|
|
95
|
+
end
|
|
96
|
+
[key.to_s, empty2nil(v)]
|
|
97
|
+
end.to_h
|
|
98
|
+
end
|
|
99
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
|
100
|
+
|
|
101
|
+
def empty2nil(value)
|
|
102
|
+
value unless value.is_a?(String) && value.empty? && !value.nil?
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# @param source [String] Relaton XML
|
|
106
|
+
# @return [Relaton::Bibcollection]
|
|
107
|
+
def build_bibcollection(source)
|
|
108
|
+
Relaton::Bibcollection.from_xml(Nokogiri::XML(source))
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# @param bibcollection [Relaton::Bibcollection]
|
|
112
|
+
# @return [Array<Hash>]
|
|
113
|
+
def document_items(bibcollection)
|
|
114
|
+
bibcollection.to_h["root"]["items"].map { |item| hash_to_liquid(item) }
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
require "yaml"
|
|
2
|
+
require_relative "base_convertor"
|
|
3
|
+
require_relative "../bib"
|
|
4
|
+
|
|
5
|
+
module Relaton
|
|
6
|
+
module Cli
|
|
7
|
+
class YAMLConvertor < Relaton::Cli::BaseConvertor
|
|
8
|
+
def to_xml
|
|
9
|
+
if writable
|
|
10
|
+
convert_and_write(file_content, :to_xml)
|
|
11
|
+
else
|
|
12
|
+
convert_content(file_content).to_xml date_format: :full, bibdata: true
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
class << self
|
|
17
|
+
# Convert to XML
|
|
18
|
+
#
|
|
19
|
+
# This interface allow us to convert any YAML file to XML.
|
|
20
|
+
# It only require us to provide a valid YAML file and it can
|
|
21
|
+
# do converstion using default attributes, but it also allow
|
|
22
|
+
# us to provide custom options to customize this converstion
|
|
23
|
+
# process.
|
|
24
|
+
#
|
|
25
|
+
# @param file [File] The complete path to a YAML file
|
|
26
|
+
# @param options [Hash] Options as hash key, value pairs.
|
|
27
|
+
#
|
|
28
|
+
def to_xml(file, options = {})
|
|
29
|
+
new(file, options).to_xml
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# @param content [Hash] document in YAML format
|
|
33
|
+
# @return [RelatonBib::BibliographicItem,
|
|
34
|
+
# RelatonIso::IsoBiblioraphicItem]
|
|
35
|
+
def convert_single_file(content)
|
|
36
|
+
flavor = content.dig("ext", "flavor") || doctype(content["docidentifier"])
|
|
37
|
+
if (processor = Relaton::Db::Registry.instance.by_type(flavor))
|
|
38
|
+
begin
|
|
39
|
+
processor.from_yaml content.to_yaml
|
|
40
|
+
rescue RuntimeError
|
|
41
|
+
Relaton::Bib::Item.from_yaml(content.to_yaml)
|
|
42
|
+
end
|
|
43
|
+
else
|
|
44
|
+
Relaton::Bib::Item.from_yaml(content.to_yaml)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
private
|
|
49
|
+
|
|
50
|
+
# @param content [Hash]
|
|
51
|
+
# @return [String]
|
|
52
|
+
def doctype(docid)
|
|
53
|
+
did = docid.is_a?(Array) ? docid.fetch(0) : docid
|
|
54
|
+
return unless did
|
|
55
|
+
|
|
56
|
+
did["type"] || did.fetch("content")&.match(/^\w+/)&.to_s
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
private
|
|
61
|
+
|
|
62
|
+
def default_ext
|
|
63
|
+
"rxl"
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def file_content
|
|
67
|
+
date_to_string(YAML.load_file(file))
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def date_to_string(obj)
|
|
71
|
+
if obj.is_a? Hash
|
|
72
|
+
obj.reduce({}) do |memo, (k, v)|
|
|
73
|
+
memo[k] = date_to_string(v)
|
|
74
|
+
memo
|
|
75
|
+
end
|
|
76
|
+
elsif obj.is_a? Array
|
|
77
|
+
obj.reduce([]) { |memo, v| memo << date_to_string(v) }
|
|
78
|
+
else
|
|
79
|
+
obj.is_a?(Date) ? obj.to_s : obj
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def convert_collection(content)
|
|
84
|
+
if content.has_key?("root")
|
|
85
|
+
content["root"]["items"] = content["root"]["items"].map do |i|
|
|
86
|
+
# RelatonBib::HashConverter::hash_to_bib(i)
|
|
87
|
+
self.class.convert_single_file(i)
|
|
88
|
+
end
|
|
89
|
+
Relaton::Bibcollection.new(content["root"])
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def xml_content(_raw_file)
|
|
94
|
+
convert_content(file_content).to_xml(date_format: :full, bibdata: true)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def convert_content(content)
|
|
98
|
+
convert_collection(content) || self.class.convert_single_file(content)
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
data/lib/relaton/cli.rb
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
require "fileutils"
|
|
2
|
+
require "thor"
|
|
3
|
+
require "thor/hollaback"
|
|
4
|
+
require_relative "cli/util"
|
|
5
|
+
require_relative "cli/command"
|
|
6
|
+
|
|
7
|
+
module Relaton
|
|
8
|
+
def self.db(dir = nil)
|
|
9
|
+
Cli.relaton dir
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
module Cli
|
|
13
|
+
class RelatonDb
|
|
14
|
+
include Singleton
|
|
15
|
+
|
|
16
|
+
DBCONF = "#{Dir.home}/.relaton/dbpath".freeze
|
|
17
|
+
|
|
18
|
+
# @param dir [String, nil]
|
|
19
|
+
# @return [Relaton::Db]
|
|
20
|
+
def db(dir)
|
|
21
|
+
if dir
|
|
22
|
+
FileUtils.mkdir_p File.dirname(DBCONF)
|
|
23
|
+
File.write DBCONF, dir, encoding: "UTF-8"
|
|
24
|
+
@db = Relaton::Db.new dir, nil
|
|
25
|
+
else
|
|
26
|
+
@db ||= Relaton::Db.new dbpath, nil
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
# @return [String] path to DB
|
|
33
|
+
def dbpath
|
|
34
|
+
if File.exist?(DBCONF)
|
|
35
|
+
File.read(DBCONF, encoding: "UTF-8")
|
|
36
|
+
else "#{Dir.home}/.relaton/cache"
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
class << self
|
|
42
|
+
def version
|
|
43
|
+
# One gem, one version.
|
|
44
|
+
puts "relaton => #{Relaton::VERSION}"
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def start(arguments)
|
|
48
|
+
Relaton::Cli::Command.start(arguments)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Relaton
|
|
52
|
+
#
|
|
53
|
+
# Based on current setup, we need to initiate a Db instance to
|
|
54
|
+
# register all of it's supported processor backends. To make it
|
|
55
|
+
# easier we have added it as a class method so we can use this
|
|
56
|
+
# whenever necessary.
|
|
57
|
+
#
|
|
58
|
+
# @param dir [String, nil]
|
|
59
|
+
# @return [Relaton::Db]
|
|
60
|
+
def relaton(dir)
|
|
61
|
+
RelatonDb.instance.db dir
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# @param content [Nokogiri::XML::Document]
|
|
65
|
+
# @return [RelatonBib::BibliographicItem,
|
|
66
|
+
# RelatonIsoBib::IsoBibliongraphicItem]
|
|
67
|
+
def parse_xml(doc)
|
|
68
|
+
doc.remove_namespaces! if doc.respond_to?(:remove_namespaces!)
|
|
69
|
+
if (proc = Cli.processor(doc))
|
|
70
|
+
proc.from_xml(doc.to_s)
|
|
71
|
+
else
|
|
72
|
+
Relaton::Bib::Item.from_xml(doc.to_s) rescue nil
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# @param doc [Nokogiri::XML::Element]
|
|
77
|
+
# @return [RelatonIso::Processor, RelatonIec::Processor,
|
|
78
|
+
# RelatonNist::Processor, RelatonIetf::Processot,
|
|
79
|
+
# RelatonItu::Processor, RelatonGb::Processor,
|
|
80
|
+
# RelatonOgc::Processor, RelatonCalconnect::Processor]
|
|
81
|
+
def processor(doc)
|
|
82
|
+
docid = doc.at "docidentifier"
|
|
83
|
+
proc = get_proc docid
|
|
84
|
+
return proc if proc
|
|
85
|
+
|
|
86
|
+
Relaton::Db::Registry.instance.by_type(docid&.text&.match(/^\w+/)&.to_s)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
private
|
|
90
|
+
|
|
91
|
+
# @param doc [Nokogiri::XML::Element]
|
|
92
|
+
# @return [RelatonIso::Processor, RelatonIec::Processor,
|
|
93
|
+
# RelatonNist::Processor, RelatonIetf::Processot,
|
|
94
|
+
# RelatonItu::Processor, RelatonGb::Processor,
|
|
95
|
+
# RelatonOgc::Processor, RelatonCalconnect::Processor]
|
|
96
|
+
def get_proc(docid)
|
|
97
|
+
return unless docid && docid[:type]
|
|
98
|
+
|
|
99
|
+
Relaton::Db::Registry.instance.by_type(docid[:type])
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
@@ -69,7 +69,7 @@ module Relaton
|
|
|
69
69
|
pubid_class&.parse(ref)
|
|
70
70
|
rescue ArgumentError, ::Pubid::Errors::Error
|
|
71
71
|
# relaton-bib carries the log facade; core specs load without it.
|
|
72
|
-
|
|
72
|
+
require_relative "../bib"
|
|
73
73
|
Relaton::Bib::Util.info "does not parse as this flavor's pubid; " \
|
|
74
74
|
"passing the reference to the flavor as " \
|
|
75
75
|
"written", "relaton-db", key: ref
|
data/lib/relaton/core.rb
CHANGED
data/lib/relaton/db/registry.rb
CHANGED
|
@@ -13,7 +13,7 @@ module Relaton
|
|
|
13
13
|
relaton/oasis relaton/doi relaton/jis relaton/xsf
|
|
14
14
|
relaton/ccsds relaton/etsi relaton/isbn relaton/plateau
|
|
15
15
|
relaton/oiml relaton/jcgm relaton/easc relaton/gost relaton/adobe
|
|
16
|
-
relaton/iala relaton/evs
|
|
16
|
+
relaton/iala relaton/evs relaton/sae
|
|
17
17
|
].freeze
|
|
18
18
|
|
|
19
19
|
include Singleton
|
data/lib/relaton/db.rb
CHANGED
data/lib/relaton/doi/CLAUDE.md
CHANGED
|
@@ -38,7 +38,7 @@ Key classes in `lib/relaton/doi/`:
|
|
|
38
38
|
- **RSpec** with `expect` syntax only (monkey patching disabled)
|
|
39
39
|
- **VCR** cassettes in `spec/vcr_cassettes/` record Crossref HTTP responses and are never auto-rerecorded (see root `CLAUDE.md`). Because Crossref rate-limits, **re-record this suite alone** — under parallel `rake spec` it answers 429 and the empty body gets recorded as if it were data.
|
|
40
40
|
- **XML fixtures** in `spec/fixtures/` — expected output XML files. The `read_fixture` helper auto-substitutes today's date into `<fetched>` tags.
|
|
41
|
-
- **
|
|
41
|
+
- **canon** gem for XML comparison in integration tests
|
|
42
42
|
- Integration tests in `spec/relaton/doi_spec.rb` cover 40+ document types via VCR cassettes
|
|
43
43
|
- Unit tests in `spec/relaton/doi/parser_spec.rb` test Parser methods directly with hash inputs
|
|
44
44
|
|
data/lib/relaton/doi/parser.rb
CHANGED
|
@@ -731,7 +731,8 @@ module Relaton
|
|
|
731
731
|
#
|
|
732
732
|
def parse_relation # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
733
733
|
rels = included_in_relation
|
|
734
|
-
|
|
734
|
+
# Crossref leaves the key out of some records (SAE standards).
|
|
735
|
+
(@src["relation"] || {}).each_with_object(rels) do |(k, v), a|
|
|
735
736
|
type, desc = relation_type k
|
|
736
737
|
Array(v).each do |r|
|
|
737
738
|
rel_item = Crossref.get_by_id r["id"]
|
data/lib/relaton/doi.rb
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
require_relative "bipm"
|
|
4
|
+
require_relative "ietf"
|
|
5
|
+
require_relative "ieee"
|
|
6
|
+
require_relative "nist"
|
|
7
7
|
require_relative "version"
|
|
8
8
|
require_relative "doi/util"
|
|
9
9
|
require_relative "doi/parser"
|
data/lib/relaton/easc.rb
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
require_relative "bib"
|
|
4
|
+
require_relative "index"
|
|
5
|
+
require_relative "version"
|
|
6
6
|
require "pubid"
|
|
7
7
|
|
|
8
8
|
# Relaton::Easc is the EASC (Евразийский экономический совет /
|
data/lib/relaton/ecma.rb
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
# (The IANA/IHO/IALA/OGC form; spec/relaton/lazy_loading_spec.rb guards that
|
|
4
4
|
# this file is not itself loaded when a Db is built.)
|
|
5
5
|
require "pubid"
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
require_relative "index"
|
|
7
|
+
require_relative "bib"
|
|
8
8
|
require_relative "version"
|
|
9
9
|
require_relative "ecma/util"
|
|
10
10
|
require_relative "ecma/item_data"
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module Relaton
|
|
2
|
+
module ElementFinder
|
|
3
|
+
attr_reader :document
|
|
4
|
+
|
|
5
|
+
def find_text(xpath, element = nil)
|
|
6
|
+
find(xpath, element)&.text
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def find_html(xpath, element = nil)
|
|
10
|
+
find(xpath, element)&.inner_html
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def find(xpath, element = nil)
|
|
14
|
+
(element || document).at(apply_namespace(xpath))
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def find_xpath(xpath, element = nil)
|
|
18
|
+
element&.xpath(apply_namespace(xpath))
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def apply_namespace(xpath)
|
|
22
|
+
xpath
|
|
23
|
+
.gsub(%r{/([a-zA-Z])}, "/xmlns:\\1")
|
|
24
|
+
.gsub(%r{::([a-zA-Z])}, "::xmlns:\\1")
|
|
25
|
+
.gsub(%r{\[([a-zA-Z][a-z0-9A-Z@/]* ?=)}, "[xmlns:\\1")
|
|
26
|
+
.gsub(%r{\[([a-zA-Z][a-z0-9A-Z@/]*\])}, "[xmlns:\\1")
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
data/lib/relaton/etsi/item.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
require_relative "../core/processor"
|
|
2
2
|
|
|
3
3
|
module Relaton
|
|
4
4
|
module Etsi
|
|
@@ -54,7 +54,7 @@ module Relaton
|
|
|
54
54
|
# @return [String]
|
|
55
55
|
def grammar_hash
|
|
56
56
|
require "digest/md5" # not loaded by etsi.rb; needed on the cold path
|
|
57
|
-
|
|
57
|
+
require_relative "../version"
|
|
58
58
|
Digest::MD5.hexdigest Relaton::VERSION
|
|
59
59
|
end
|
|
60
60
|
|
data/lib/relaton/etsi.rb
CHANGED
data/lib/relaton/evs.rb
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
require "digest/md5"
|
|
4
4
|
require "mechanize"
|
|
5
|
-
|
|
5
|
+
require_relative "core"
|
|
6
6
|
require "isoics"
|
|
7
7
|
require "pubid"
|
|
8
|
-
|
|
8
|
+
require_relative "bib"
|
|
9
9
|
require_relative "version"
|
|
10
10
|
require_relative "evs/util"
|
|
11
11
|
require_relative "evs/model/item"
|
data/lib/relaton/gb/CLAUDE.md
CHANGED
|
@@ -44,4 +44,4 @@ GB parses identifiers with `Pubid::Gb::Identifier`. It publishes no index, so it
|
|
|
44
44
|
|
|
45
45
|
## Testing
|
|
46
46
|
|
|
47
|
-
RSpec with WebMock + VCR (cassettes in `spec/vcr_cassettes/`). Network is blocked via WebMock. SimpleCov and
|
|
47
|
+
RSpec with WebMock + VCR (cassettes in `spec/vcr_cassettes/`). Network is blocked via WebMock. SimpleCov and canon are loaded via `spec/support/`. No index fixture — GB is scraped, not indexed; `spec/fixtures/` holds XML/YAML round-trip data.
|
data/lib/relaton/gb/processor.rb
CHANGED
data/lib/relaton/gb.rb
CHANGED
data/lib/relaton/gost.rb
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
require_relative "bib"
|
|
4
|
+
require_relative "index"
|
|
5
5
|
require "pubid"
|
|
6
|
-
|
|
6
|
+
require_relative "version"
|
|
7
7
|
|
|
8
8
|
# Relaton::Gost is the GOST (Russian federal standards — Гостстандарт)
|
|
9
9
|
# flavor of the unified relaton gem. Adds typed Ext fields (urn,
|