relaton-cli 1.0.2 → 1.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +1 -1
- data/lib/relaton-cli.rb +7 -1
- data/lib/relaton/bibcollection.rb +35 -30
- data/lib/relaton/bibdata.rb +23 -27
- data/lib/relaton/cli/base_convertor.rb +15 -7
- data/lib/relaton/cli/command.rb +2 -11
- data/lib/relaton/cli/relaton_file.rb +22 -13
- data/lib/relaton/cli/version.rb +1 -1
- data/lib/relaton/cli/xml_convertor.rb +1 -11
- data/lib/relaton/cli/xml_to_html_renderer.rb +32 -12
- data/relaton-cli.gemspec +1 -1
- data/templates/_document.liquid +10 -5
- metadata +4 -6
- data/lib/relaton/cli/_document.liquid +0 -82
- data/lib/relaton/cli/_index.liquid +0 -53
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 57f7abf09dc691dbeca299fe1960057c040778da128d45b5cff25748c8442f72
|
4
|
+
data.tar.gz: 39520c2293ea0f938ba81acfe13b5def8cd505bf3d6a0bf0e4c8d2ff2ec90beb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8efa168c29a5d1a6f49142e19d86a24f3e2ad26afb97f8126e2104f14eb86276d8e0a778bc58ff328f542d4579776ddd925d130a406c959616ece08a0a997583
|
7
|
+
data.tar.gz: 75aedff7abac327dfe3b7d0abd9948fba5447e326a887dc06f0fe8fbc1b247797303193e788e13c7330f2c6b6ad0febd2f8752701b363e411f69ee34c28e35be
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
data/lib/relaton-cli.rb
CHANGED
@@ -1,4 +1,10 @@
|
|
1
1
|
require_relative "relaton/bibcollection"
|
2
2
|
require_relative "relaton/bibdata"
|
3
3
|
require_relative "relaton/element_finder"
|
4
|
-
require_relative "relaton/xml_document"
|
4
|
+
# require_relative "relaton/xml_document"
|
5
|
+
require_relative "relaton/cli/yaml_convertor"
|
6
|
+
|
7
|
+
module Relaton
|
8
|
+
module Cli
|
9
|
+
end
|
10
|
+
end
|
@@ -4,15 +4,12 @@ module Relaton
|
|
4
4
|
class Bibcollection
|
5
5
|
extend Relaton::ElementFinder
|
6
6
|
|
7
|
-
ATTRIBS = %i[
|
8
|
-
title
|
9
|
-
items
|
10
|
-
doctype
|
11
|
-
author
|
12
|
-
].freeze
|
7
|
+
ATTRIBS = %i[title items doctype author].freeze
|
13
8
|
|
14
9
|
attr_accessor *ATTRIBS
|
15
10
|
|
11
|
+
# rubocop:disable Metrics/MethodLength
|
12
|
+
|
16
13
|
def initialize(options)
|
17
14
|
self.items = []
|
18
15
|
ATTRIBS.each do |k|
|
@@ -20,30 +17,38 @@ module Relaton
|
|
20
17
|
send("#{k}=", value)
|
21
18
|
end
|
22
19
|
self.items = (items || []).reduce([]) do |acc, item|
|
23
|
-
acc << if item.is_a?(
|
20
|
+
acc << if item.is_a?(Bibcollection) || item.is_a?(Bibdata)
|
24
21
|
item
|
25
22
|
else new_bib_item_class(item)
|
26
23
|
end
|
27
24
|
end
|
28
25
|
end
|
26
|
+
# rubocop:enable Metrics/MethodLength
|
29
27
|
|
30
28
|
# arbitrary number, must sort after all bib items
|
31
29
|
def doc_number
|
32
30
|
9999999
|
33
31
|
end
|
34
32
|
|
33
|
+
# rubocop:disable Metrics/MethodLength
|
34
|
+
|
35
|
+
# @param source [Nokogiri::XML::Element]
|
35
36
|
def self.from_xml(source)
|
36
37
|
title = find_text("./relaton-collection/title", source)
|
37
|
-
author = find_text(
|
38
|
+
author = find_text(
|
39
|
+
"./relaton-collection/contributor[role/@type='author']/organization/name",
|
40
|
+
source,
|
41
|
+
)
|
38
42
|
|
39
43
|
items = find_xpath("./relaton-collection/relation", source)&.map do |item|
|
40
|
-
bibdata = find("./bibdata", item)
|
44
|
+
bibdata = find("./bibdata|./bibitem", item)
|
41
45
|
klass = bibdata ? Bibdata : Bibcollection
|
42
46
|
klass.from_xml(bibdata || item)
|
43
47
|
end
|
44
48
|
|
45
49
|
new(title: title, author: author, items: items)
|
46
50
|
end
|
51
|
+
# rubocop:enable Metrics/MethodLength
|
47
52
|
|
48
53
|
def new_bib_item_class(options)
|
49
54
|
if options.is_a?(Hash) && options["items"]
|
@@ -54,34 +59,35 @@ module Relaton
|
|
54
59
|
end
|
55
60
|
|
56
61
|
def items_flattened
|
57
|
-
items.sort_by!
|
58
|
-
b.docnumber
|
59
|
-
end
|
62
|
+
items.sort_by! &:docnumber
|
60
63
|
|
61
|
-
items.
|
62
|
-
if item.is_a? ::Relaton::Bibcollection
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
64
|
+
items.reduce([]) do |acc,item|
|
65
|
+
acc << if item.is_a? ::Relaton::Bibcollection
|
66
|
+
item.items_flattened
|
67
|
+
else
|
68
|
+
item
|
69
|
+
end
|
67
70
|
end
|
68
71
|
end
|
69
72
|
|
73
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
74
|
+
|
75
|
+
# @param opts [Hash]
|
76
|
+
# @return [String] XML
|
70
77
|
def to_xml(opts = {})
|
71
|
-
items.sort_by!
|
72
|
-
b.doc_number
|
73
|
-
end
|
78
|
+
items.sort_by! &:doc_number
|
74
79
|
|
75
80
|
collection_type = if doctype
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
81
|
+
"type=\"#{doctype}\""
|
82
|
+
else
|
83
|
+
'xmlns="https://open.ribose.com/relaton-xml"'
|
84
|
+
end
|
80
85
|
|
81
86
|
ret = "<relaton-collection #{collection_type}>"
|
82
87
|
ret += "<title>#{title}</title>" if title
|
83
88
|
if author
|
84
|
-
ret += "<contributor><role type='author'/><organization><name
|
89
|
+
ret += "<contributor><role type='author'/><organization><name>"\
|
90
|
+
"#{author}</name></organization></contributor>"
|
85
91
|
end
|
86
92
|
unless items.empty?
|
87
93
|
items.each do |item|
|
@@ -92,17 +98,16 @@ module Relaton
|
|
92
98
|
end
|
93
99
|
ret += "</relaton-collection>\n"
|
94
100
|
end
|
101
|
+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
95
102
|
|
96
103
|
def to_yaml
|
97
104
|
to_h.to_yaml
|
98
105
|
end
|
99
106
|
|
100
107
|
def to_h
|
101
|
-
items.sort_by!
|
102
|
-
b.doc_number
|
103
|
-
end
|
108
|
+
items.sort_by! &:doc_number
|
104
109
|
|
105
|
-
a = ATTRIBS.
|
110
|
+
a = ATTRIBS.reduce({}) do |acc, k|
|
106
111
|
acc[k.to_s] = send(k)
|
107
112
|
acc
|
108
113
|
end
|
data/lib/relaton/bibdata.rb
CHANGED
@@ -2,7 +2,7 @@ require "date"
|
|
2
2
|
|
3
3
|
module Relaton
|
4
4
|
class Bibdata
|
5
|
-
URL_TYPES = %i[uri xml pdf doc html rxl txt]
|
5
|
+
URL_TYPES = %i[uri xml pdf doc html rxl txt].freeze
|
6
6
|
|
7
7
|
attr_reader :bibitem
|
8
8
|
|
@@ -10,18 +10,6 @@ module Relaton
|
|
10
10
|
@bibitem = bibitem
|
11
11
|
end
|
12
12
|
|
13
|
-
# def method_missing(method, *args)
|
14
|
-
# %r{(?<m>\w+)=$} =~ method
|
15
|
-
# return unless m && %w[xml pdf doc html rxl txt].include?(m)
|
16
|
-
|
17
|
-
# uri = @bibitem.link.detect { |u| u.type == m }
|
18
|
-
# if uri
|
19
|
-
# uri.content = args[0]
|
20
|
-
# else
|
21
|
-
# @bibitem.link << RelatonBib::TypedUri.new(type: m, content: args[0])
|
22
|
-
# end
|
23
|
-
# end
|
24
|
-
|
25
13
|
def docidentifier
|
26
14
|
@bibitem.docidentifier.first&.id
|
27
15
|
end
|
@@ -31,16 +19,18 @@ module Relaton
|
|
31
19
|
# end
|
32
20
|
|
33
21
|
# From http://gavinmiller.io/2016/creating-a-secure-sanitization-function/
|
34
|
-
FILENAME_BAD_CHARS = [
|
22
|
+
FILENAME_BAD_CHARS = ["/", '\\', "?", "%", "*", ":", "|", '"', "<", ">",
|
23
|
+
".", " "].freeze
|
35
24
|
|
36
25
|
def docidentifier_code
|
37
26
|
return "" if docidentifier.nil?
|
38
|
-
|
39
|
-
|
27
|
+
|
28
|
+
FILENAME_BAD_CHARS.reduce(docidentifier.downcase) do |result, bad_char|
|
29
|
+
result.gsub(bad_char, "-")
|
40
30
|
end
|
41
31
|
end
|
42
32
|
|
43
|
-
DOC_NUMBER_REGEX = /([\w\/]+)\s+(\d+):?(\d*)
|
33
|
+
DOC_NUMBER_REGEX = /([\w\/]+)\s+(\d+):?(\d*)/.freeze
|
44
34
|
def doc_number
|
45
35
|
docidentifier&.match(DOC_NUMBER_REGEX) ? $2.to_i : 999999
|
46
36
|
end
|
@@ -51,18 +41,15 @@ module Relaton
|
|
51
41
|
end
|
52
42
|
|
53
43
|
def to_xml(opts = {})
|
54
|
-
options = { bibdata: true, date_format: :full }.merge
|
44
|
+
options = { bibdata: true, date_format: :full }.merge(
|
45
|
+
opts.select { |k, _v| k.is_a? Symbol },
|
46
|
+
)
|
55
47
|
@bibitem.to_xml nil, **options
|
56
|
-
|
57
|
-
# #datetype = stage&.casecmp("published") == 0 ? "published" : "circulated"
|
58
|
-
|
59
|
-
# ret = ref ? "<bibitem id= '#{ref}' type='#{doctype}'>\n" : "<bibdata type='#{doctype}'>\n"
|
60
|
-
# ret += "<fetched>#{Date.today.to_s}</fetched>\n"
|
61
48
|
end
|
62
49
|
|
63
50
|
def to_h
|
64
|
-
URL_TYPES.reduce(
|
65
|
-
value =
|
51
|
+
URL_TYPES.reduce(@bibitem.to_hash) do |h, t|
|
52
|
+
value = send t
|
66
53
|
h[t.to_s] = value
|
67
54
|
h
|
68
55
|
end
|
@@ -72,15 +59,22 @@ module Relaton
|
|
72
59
|
to_h.to_yaml
|
73
60
|
end
|
74
61
|
|
62
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/AbcSize
|
63
|
+
# rubocop:disable Metrics/MethodLength, Metrics/PerceivedComplexity, Style/MissingRespondToMissing
|
64
|
+
|
75
65
|
def method_missing(meth, *args)
|
76
66
|
if @bibitem.respond_to?(meth)
|
77
67
|
@bibitem.send meth, *args
|
78
68
|
elsif URL_TYPES.include? meth
|
79
|
-
link = @bibitem.link.detect
|
69
|
+
link = @bibitem.link.detect do |l|
|
70
|
+
l.type == meth.to_s || meth == :uri && l.type.nil?
|
71
|
+
end
|
80
72
|
link&.content&.to_s
|
81
73
|
elsif URL_TYPES.include? meth.match(/^\w+(?==)/).to_s.to_sym
|
82
74
|
/^(?<type>\w+)/ =~ meth
|
83
|
-
link = @bibitem.link.detect
|
75
|
+
link = @bibitem.link.detect do |l|
|
76
|
+
l.type == type || type == "uri" && l.type.nil?
|
77
|
+
end
|
84
78
|
if link
|
85
79
|
link.content = args[0]
|
86
80
|
else
|
@@ -90,5 +84,7 @@ module Relaton
|
|
90
84
|
super
|
91
85
|
end
|
92
86
|
end
|
87
|
+
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/AbcSize
|
88
|
+
# rubocop:enable Metrics/MethodLength, Metrics/PerceivedComplexity, Style/MissingRespondToMissing
|
93
89
|
end
|
94
90
|
end
|
@@ -17,6 +17,7 @@ module Relaton
|
|
17
17
|
install_dependencies(options[:require] || [])
|
18
18
|
end
|
19
19
|
|
20
|
+
# @return [String] HTML
|
20
21
|
def to_html
|
21
22
|
content = convert_to_html
|
22
23
|
write_to_a_file(content)
|
@@ -32,12 +33,13 @@ module Relaton
|
|
32
33
|
# @param style [String] Stylesheet file path for styles
|
33
34
|
# @param template [String] The liquid tempalte directory
|
34
35
|
#
|
36
|
+
# @return [String] HTML
|
35
37
|
def self.to_html(file, style = nil, template = nil)
|
36
38
|
new(
|
37
39
|
file,
|
38
40
|
style: style || File.join(File.dirname(__FILE__), "../../../templates/index-style.css"),
|
39
41
|
template: template || File.join(File.dirname(__FILE__), "../../../templates/"),
|
40
|
-
extension: "html"
|
42
|
+
extension: "html",
|
41
43
|
).to_html
|
42
44
|
end
|
43
45
|
|
@@ -45,6 +47,7 @@ module Relaton
|
|
45
47
|
|
46
48
|
attr_reader :file, :outdir, :options, :writable, :overwrite
|
47
49
|
|
50
|
+
# @return [String] HTML
|
48
51
|
def convert_to_html
|
49
52
|
Relaton::Cli::XmlToHtmlRenderer.render(
|
50
53
|
xml_content(file),
|
@@ -53,6 +56,9 @@ module Relaton
|
|
53
56
|
)
|
54
57
|
end
|
55
58
|
|
59
|
+
# @param file [String] path to a file
|
60
|
+
# @return [String] the file's content
|
61
|
+
# @return [String] HTML
|
56
62
|
def xml_content(file)
|
57
63
|
File.read(file, encoding: "utf-8")
|
58
64
|
end
|
@@ -92,7 +98,7 @@ module Relaton
|
|
92
98
|
# write_to_a_file(item_output(item, format), collection)
|
93
99
|
# end
|
94
100
|
# end
|
95
|
-
if outdir &&
|
101
|
+
if outdir && content.is_a?(Relaton::Bibcollection)
|
96
102
|
FileUtils.mkdir_p(outdir)
|
97
103
|
content.items_flattened.each do |item|
|
98
104
|
collection = collection_filename(extract_docid(item))
|
@@ -103,19 +109,21 @@ module Relaton
|
|
103
109
|
|
104
110
|
def extract_docid(item)
|
105
111
|
@default_filelabel += 1
|
106
|
-
item.docidentifier.nil?
|
112
|
+
item.docidentifier.nil? && (return @default_filelabel.to_s)
|
107
113
|
# item.docidentifier.is_a?(Array) or return @default_filelabel.to_s
|
108
|
-
item.docidentifier.empty?
|
114
|
+
item.docidentifier.empty? && (return @default_filelabel.to_s)
|
109
115
|
docidentifier_code(item.docidentifier)
|
110
116
|
end
|
111
117
|
|
112
118
|
# From http://gavinmiller.io/2016/creating-a-secure-sanitization-function/
|
113
|
-
FILENAME_BAD_CHARS = [
|
119
|
+
FILENAME_BAD_CHARS = ["/", '\\', "?", '%", "*", ":', "|", '"', "<", ">",
|
120
|
+
".", " "].freeze
|
114
121
|
|
115
122
|
def docidentifier_code(docidentifier)
|
116
123
|
return "" if docidentifier.nil?
|
117
|
-
|
118
|
-
|
124
|
+
|
125
|
+
FILENAME_BAD_CHARS.reduce(docidentifier.downcase) do |result, bad_char|
|
126
|
+
result.gsub(bad_char, "-")
|
119
127
|
end
|
120
128
|
end
|
121
129
|
|
data/lib/relaton/cli/command.rb
CHANGED
@@ -28,7 +28,7 @@ module Relaton
|
|
28
28
|
option :title, aliases: :t, desc: "Title of resulting Relaton collection"
|
29
29
|
option :organization, aliases: :g, desc: "Organization owner of Relaton collection"
|
30
30
|
option :new, aliases: :n, type: :boolean, desc: "Use the new Relaton YAML format"
|
31
|
-
option :extension, aliases: :x,
|
31
|
+
option :extension, aliases: :x, desc: "File extension of destination Relaton file, defaults to 'rxl'"
|
32
32
|
|
33
33
|
def concatenate(source_dir, outfile)
|
34
34
|
Relaton::Cli::RelatonFile.concatenate(source_dir, outfile, options)
|
@@ -73,16 +73,7 @@ module Relaton
|
|
73
73
|
Relaton::Cli::XMLConvertor.to_html(file, style, template)
|
74
74
|
end
|
75
75
|
|
76
|
-
|
77
|
-
# option :stylesheet, aliases: :s, desc: "Stylesheet file path for rendering HTML index"
|
78
|
-
# option :templatedir, aliases: :t, desc: "Liquid template directory for rendering Relaton items and collection"
|
79
|
-
# option :overwrite, aliases: :f, type: :boolean, default: false, desc: "Overwrite the existing file"
|
80
|
-
|
81
|
-
# def yaml2html(file, style = nil, template = nil)
|
82
|
-
# Relaton::Cli::YAMLConvertor.to_html(file, style, template)
|
83
|
-
# end
|
84
|
-
|
85
|
-
desc "yaml2htmlnew RELATON-INDEX-YAML", "Concatenate Relaton Collection YAML into HTML"
|
76
|
+
desc "yaml2html RELATON-INDEX-YAML", "Concatenate Relaton Collection YAML into HTML"
|
86
77
|
option :stylesheet, aliases: :s, desc: "Stylesheet file path for rendering HTML index"
|
87
78
|
option :templatedir, aliases: :t, desc: "Liquid template directory for rendering Relaton items and collection"
|
88
79
|
option :overwrite, aliases: :f, type: :boolean, default: false, desc: "Overwrite the existing file"
|
@@ -89,6 +89,9 @@ module Relaton
|
|
89
89
|
)
|
90
90
|
end
|
91
91
|
|
92
|
+
# @param document [String] XML
|
93
|
+
# @param file [String, nil] path to file
|
94
|
+
# @return [Nokogiri::XML::Document]
|
92
95
|
def nokogiri_document(document, file = nil)
|
93
96
|
document ||= File.read(file, encoding: "utf-8")
|
94
97
|
Nokogiri.XML(document)
|
@@ -115,7 +118,6 @@ module Relaton
|
|
115
118
|
bib = nokogiri_document(bib.to_xml)
|
116
119
|
elsif (rfc = xml.at("//rfc"))
|
117
120
|
require "relaton_ietf/scrapper"
|
118
|
-
#ietf = RelatonIetf::Scrapper.bib_item rfc, "rfc"
|
119
121
|
ietf = RelatonIetf::Scrapper.fetch_rfc rfc
|
120
122
|
bib = nokogiri_document ietf.to_xml(bibdata: true)
|
121
123
|
else
|
@@ -139,18 +141,16 @@ module Relaton
|
|
139
141
|
|
140
142
|
xml_files.flatten.reduce([]) do |mem, xml|
|
141
143
|
doc = nokogiri_document(xml[:content])
|
142
|
-
if (
|
144
|
+
if (rfc = doc.at("/rfc"))
|
143
145
|
require "relaton_ietf/scrapper"
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
end
|
149
|
-
elsif doc&.root&.name == "bibdata"
|
146
|
+
ietf = RelatonIetf::Scrapper.fetch_rfc rfc
|
147
|
+
d = nokogiri_document ietf.to_xml(bibdata: true)
|
148
|
+
mem << bibdata_instance(d, xml[:file])
|
149
|
+
elsif %w[bibitem bibdata].include? doc&.root&.name
|
150
150
|
mem << bibdata_instance(doc, xml[:file])
|
151
151
|
else mem
|
152
152
|
end
|
153
|
-
end.
|
153
|
+
end.uniq &:id
|
154
154
|
end
|
155
155
|
|
156
156
|
def concatenate_and_write_to_files
|
@@ -167,25 +167,30 @@ module Relaton
|
|
167
167
|
end
|
168
168
|
end
|
169
169
|
|
170
|
-
def find_available_bibrxl_file(name,
|
170
|
+
def find_available_bibrxl_file(name, _ouputdir, content)
|
171
171
|
if options[:extension] == "yaml" || options[:extension] == "yml"
|
172
172
|
bib_rxl = Pathname.new([outdir, name].join("/")).sub_ext(".rxl")
|
173
173
|
content.bib_rxl = bib_rxl.to_s if File.file?(bib_rxl)
|
174
174
|
end
|
175
175
|
end
|
176
176
|
|
177
|
-
def output_type(ext=options[:extension])
|
177
|
+
def output_type(ext = options[:extension])
|
178
|
+
ext ||= File.extname(outfile)[1..-1] if outfile
|
178
179
|
case ext
|
179
180
|
when "rxl", "xml"
|
180
181
|
:to_xml
|
181
182
|
when "yml", "yaml"
|
182
183
|
:to_yaml
|
183
184
|
else
|
184
|
-
puts "[relaton-cli] the given extension of '#{ext}' is
|
185
|
+
puts "[relaton-cli] the given extension of '#{ext}' is "\
|
186
|
+
"not supported. Use 'rxl'."
|
185
187
|
:to_xml
|
186
188
|
end
|
187
189
|
end
|
188
190
|
|
191
|
+
# @param document [Nokogiri::XML::Document]
|
192
|
+
# @param file [String] path to file
|
193
|
+
# @return [Relaton::Bibdata]
|
189
194
|
def bibdata_instance(document, file)
|
190
195
|
document = clean_nokogiri_document(document)
|
191
196
|
bibdata = Relaton::Bibdata.from_xml document.root
|
@@ -194,6 +199,8 @@ module Relaton
|
|
194
199
|
bibdata
|
195
200
|
end
|
196
201
|
|
202
|
+
# @param bibdata [Relaton::Bibdata]
|
203
|
+
# @param file [String] path to file
|
197
204
|
def build_bibdata_relaton(bibdata, file)
|
198
205
|
["xml", "pdf", "doc", "html", "rxl", "txt"].each do |type|
|
199
206
|
file = Pathname.new(file).sub_ext(".#{type}")
|
@@ -206,6 +213,8 @@ module Relaton
|
|
206
213
|
# has an xmlns. We don't want to change the code for bibdata
|
207
214
|
# hence this hack #bibdata_doc.root['xmlns'] = "xmlns"
|
208
215
|
#
|
216
|
+
# @param document [Nokogiri::XML::Document]
|
217
|
+
# @return [Nokogiri::XML::Document]
|
209
218
|
def clean_nokogiri_document(document)
|
210
219
|
document.remove_namespaces!
|
211
220
|
document.root.add_namespace(nil, "xmlns")
|
@@ -260,7 +269,7 @@ module Relaton
|
|
260
269
|
|
261
270
|
def replace_bad_characters(string)
|
262
271
|
bad_chars = ["/", "\\", "?", "%", "*", ":", "|", '"', "<", ">", ".", " "]
|
263
|
-
bad_chars.
|
272
|
+
bad_chars.reduce(string.downcase) { |res, char| res.gsub(char, "-") }
|
264
273
|
end
|
265
274
|
end
|
266
275
|
end
|
data/lib/relaton/cli/version.rb
CHANGED
@@ -32,20 +32,10 @@ module Relaton
|
|
32
32
|
# @param content [Nokogiri::XML::Document]
|
33
33
|
# @return [Hash]
|
34
34
|
def convert_content(content)
|
35
|
-
if content.root.name
|
35
|
+
if %w[bibitem bibdata].include? content.root.name
|
36
36
|
Bibdata.from_xml(content)
|
37
|
-
# Relaton::Cli.parse_xml(content).to_hash
|
38
37
|
else
|
39
38
|
Bibcollection.from_xml(content)
|
40
|
-
# title = content.at("relaton-collection/title").text
|
41
|
-
# author = content.at("relaton-collection/contributor/organization/name").text
|
42
|
-
# collection = { "root" => { "title" => title, "author" => author } }
|
43
|
-
|
44
|
-
# collection["root"]["items"] = content.xpath("//bibdata").map do |bib|
|
45
|
-
# Relaton::Cli.parse_xml(bib).to_hash
|
46
|
-
# end
|
47
|
-
|
48
|
-
# collection
|
49
39
|
end
|
50
40
|
end
|
51
41
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require "nokogiri"
|
2
2
|
require "liquid"
|
3
|
-
require
|
3
|
+
require "pp"
|
4
4
|
|
5
5
|
module Relaton::Cli
|
6
6
|
class XmlToHtmlRenderer
|
@@ -10,16 +10,16 @@ module Relaton::Cli
|
|
10
10
|
init_liquid_template_and_filesystem
|
11
11
|
end
|
12
12
|
|
13
|
+
# @param index_xml [String] Relaton XML
|
14
|
+
# @return [String] HTML
|
13
15
|
def render(index_xml)
|
14
16
|
Liquid::Template.
|
15
17
|
parse(template).
|
16
|
-
render(build_liquid_document(index_xml)
|
18
|
+
render(build_liquid_document(index_xml))
|
17
19
|
end
|
18
20
|
|
19
21
|
def uri_for_extension(uri, extension)
|
20
|
-
|
21
|
-
uri.sub(/\.[^.]+$/, ".#{extension.to_s}")
|
22
|
-
end
|
22
|
+
uri&.sub(/\.[^.]+$/, ".#{extension}")
|
23
23
|
end
|
24
24
|
|
25
25
|
# Render HTML
|
@@ -28,6 +28,9 @@ module Relaton::Cli
|
|
28
28
|
# using the specified liquid template and stylesheets. It
|
29
29
|
# also do some minor clean during this conversion.
|
30
30
|
#
|
31
|
+
# @param file [String] Relaton XML
|
32
|
+
# @param options [Hash]
|
33
|
+
# @return [String] HTML
|
31
34
|
def self.render(file, options)
|
32
35
|
new(options).render(file)
|
33
36
|
end
|
@@ -40,16 +43,17 @@ module Relaton::Cli
|
|
40
43
|
File.read(file, encoding: "utf-8")
|
41
44
|
end
|
42
45
|
|
46
|
+
# @param source [String] Relaton XML
|
43
47
|
def build_liquid_document(source)
|
44
48
|
bibcollection = build_bibcollection(source)
|
45
49
|
|
46
|
-
hash_to_liquid(
|
50
|
+
hash_to_liquid(
|
47
51
|
depth: 2,
|
48
52
|
css: stylesheet,
|
49
53
|
title: bibcollection.title,
|
50
54
|
author: bibcollection.author,
|
51
|
-
documents: document_items(bibcollection)
|
52
|
-
|
55
|
+
documents: document_items(bibcollection),
|
56
|
+
)
|
53
57
|
end
|
54
58
|
|
55
59
|
def init_liquid_template_and_filesystem
|
@@ -59,7 +63,17 @@ module Relaton::Cli
|
|
59
63
|
Liquid::Template.file_system = file_system
|
60
64
|
end
|
61
65
|
|
66
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
67
|
+
|
62
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]
|
63
77
|
def hash_to_liquid(hash)
|
64
78
|
hash.map do |key, value|
|
65
79
|
case key
|
@@ -71,24 +85,30 @@ module Relaton::Cli
|
|
71
85
|
else v = value
|
72
86
|
end
|
73
87
|
when "docid"
|
74
|
-
if value.is_a?(Array)
|
75
|
-
|
76
|
-
|
77
|
-
|
88
|
+
v = if value.is_a?(Array)
|
89
|
+
value.detect { |did| did["id"] !~ /^(http|https):\/\// } ||
|
90
|
+
value.first
|
91
|
+
else value
|
92
|
+
end
|
78
93
|
else v = value
|
79
94
|
end
|
80
95
|
[key.to_s, empty2nil(v)]
|
81
96
|
end.to_h
|
82
97
|
end
|
98
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
83
99
|
|
84
100
|
def empty2nil(value)
|
85
101
|
value unless value.is_a?(String) && value.empty? && !value.nil?
|
86
102
|
end
|
87
103
|
|
104
|
+
# @param source [String] Relaton XML
|
105
|
+
# @return [Relaton::Bibcollection]
|
88
106
|
def build_bibcollection(source)
|
89
107
|
Relaton::Bibcollection.from_xml(Nokogiri::XML(source))
|
90
108
|
end
|
91
109
|
|
110
|
+
# @param bibcollection [Relaton::Bibcollection]
|
111
|
+
# @return [Array<Hash>]
|
92
112
|
def document_items(bibcollection)
|
93
113
|
bibcollection.to_h["root"]["items"].map { |item| hash_to_liquid(item) }
|
94
114
|
end
|
data/relaton-cli.gemspec
CHANGED
@@ -34,7 +34,7 @@ Gem::Specification.new do |spec|
|
|
34
34
|
spec.add_development_dependency "simplecov"
|
35
35
|
|
36
36
|
spec.add_runtime_dependency "liquid"
|
37
|
-
spec.add_runtime_dependency "relaton", "~> 1.
|
37
|
+
spec.add_runtime_dependency "relaton", "~> 1.1.0"
|
38
38
|
spec.add_runtime_dependency "thor"
|
39
39
|
# spec.add_runtime_dependency 'byebug'
|
40
40
|
end
|
data/templates/_document.liquid
CHANGED
@@ -32,12 +32,17 @@
|
|
32
32
|
</h{{ depth | plus: 1 }}>
|
33
33
|
</div>
|
34
34
|
|
35
|
-
<div class="doc-info {{ document.docstatus.stage | downcase }}">
|
36
|
-
<div class="doc-stage {{ document.docstatus.stage | downcase }}">
|
37
|
-
{{ document.docstatus.stage }}
|
35
|
+
<div class="doc-info {{ document.docstatus.stage.value | downcase }}">
|
36
|
+
<div class="doc-stage {{ document.docstatus.stage.value | downcase }}">
|
37
|
+
{{ document.docstatus.stage.abbreviation }}
|
38
|
+
{% if document.docstatus.substage %}
|
39
|
+
{{ document.docstatus.stage.value }}.{{ document.docstatus.substage.value }}
|
40
|
+
{% else %}
|
41
|
+
{{ document.docstatus.stage.value }}
|
42
|
+
{% endif %}
|
38
43
|
</div>
|
39
44
|
<div class="doc-dates">
|
40
|
-
{% unless document.docstatus.stage == "published" %}
|
45
|
+
{% unless document.docstatus.stage.value == "published" %}
|
41
46
|
<div class="doc-updated">
|
42
47
|
{% else %}
|
43
48
|
<div class="doc-published">
|
@@ -49,7 +54,7 @@
|
|
49
54
|
|
50
55
|
<div class="doc-bib">
|
51
56
|
<div class="doc-bib-relaton">
|
52
|
-
<a href="{{ document.
|
57
|
+
<a href="{{ document.rxl }}">Relaton XML</a>
|
53
58
|
</div>
|
54
59
|
</div>
|
55
60
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: relaton-cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ribose Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-06-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: byebug
|
@@ -170,14 +170,14 @@ dependencies:
|
|
170
170
|
requirements:
|
171
171
|
- - "~>"
|
172
172
|
- !ruby/object:Gem::Version
|
173
|
-
version: 1.
|
173
|
+
version: 1.1.0
|
174
174
|
type: :runtime
|
175
175
|
prerelease: false
|
176
176
|
version_requirements: !ruby/object:Gem::Requirement
|
177
177
|
requirements:
|
178
178
|
- - "~>"
|
179
179
|
- !ruby/object:Gem::Version
|
180
|
-
version: 1.
|
180
|
+
version: 1.1.0
|
181
181
|
- !ruby/object:Gem::Dependency
|
182
182
|
name: thor
|
183
183
|
requirement: !ruby/object:Gem::Requirement
|
@@ -223,8 +223,6 @@ files:
|
|
223
223
|
- lib/relaton/bibcollection.rb
|
224
224
|
- lib/relaton/bibdata.rb
|
225
225
|
- lib/relaton/cli.rb
|
226
|
-
- lib/relaton/cli/_document.liquid
|
227
|
-
- lib/relaton/cli/_index.liquid
|
228
226
|
- lib/relaton/cli/base_convertor.rb
|
229
227
|
- lib/relaton/cli/command.rb
|
230
228
|
- lib/relaton/cli/relaton_file.rb
|
@@ -1,82 +0,0 @@
|
|
1
|
-
{%- if document.items.size > 0 -%}
|
2
|
-
<div class="doc-section">
|
3
|
-
{%- else -%}
|
4
|
-
<div class="document">
|
5
|
-
{%- endif -%}
|
6
|
-
|
7
|
-
<div class="doc-line">
|
8
|
-
<div class="doc-identifier">
|
9
|
-
<h{{ depth }}>
|
10
|
-
{% if document.html == "" %}
|
11
|
-
{{ document.docid.id }}
|
12
|
-
{% else %}
|
13
|
-
<a href="{{ document.html }}">{{ document.docid.id }}</a>
|
14
|
-
{% endif %}
|
15
|
-
</h{{ depth }}>
|
16
|
-
</div>
|
17
|
-
|
18
|
-
<div class="doc-type-wrap">
|
19
|
-
<div class="doc-type {{ document.type | downcase | split: " " | join: "-" }}">
|
20
|
-
{{ document.type }}
|
21
|
-
</div>
|
22
|
-
</div>
|
23
|
-
</div>
|
24
|
-
|
25
|
-
<div class="doc-title">
|
26
|
-
<h{{ depth | plus: 1 }}>
|
27
|
-
{% if document.html == blank or document.html == nil %}
|
28
|
-
{{ document.title }}
|
29
|
-
{% else %}
|
30
|
-
<a href="{{ document.html }}">{{ document.title }}</a>
|
31
|
-
{% endif %}
|
32
|
-
</h{{ depth | plus: 1 }}>
|
33
|
-
</div>
|
34
|
-
|
35
|
-
<div class="doc-info {{ document.docstatus.stage | downcase }}">
|
36
|
-
<div class="doc-stage {{ document.docstatus.stage | downcase }}">
|
37
|
-
{{ document.docstatus.stage }}
|
38
|
-
</div>
|
39
|
-
<div class="doc-dates">
|
40
|
-
{% unless document.docstatus.stage == "published" %}
|
41
|
-
<div class="doc-updated">
|
42
|
-
{% else %}
|
43
|
-
<div class="doc-published">
|
44
|
-
{% endunless %}
|
45
|
-
{{ document.revdate }}
|
46
|
-
</div>
|
47
|
-
</div>
|
48
|
-
</div>
|
49
|
-
|
50
|
-
<div class="doc-bib">
|
51
|
-
<div class="doc-bib-relaton">
|
52
|
-
<a href="{{ document.relaton }}">Relaton XML</a>
|
53
|
-
</div>
|
54
|
-
</div>
|
55
|
-
|
56
|
-
<div class="doc-access">
|
57
|
-
{% unless document.html == blank or document.html == nil %}
|
58
|
-
<div class="doc-access-button-html">
|
59
|
-
<a href="{{ document.html }}">HTML</a>
|
60
|
-
</div>
|
61
|
-
{% endunless %}
|
62
|
-
{% unless document.pdf == blank or document.pdf == nil %}
|
63
|
-
<div class="doc-access-button-pdf">
|
64
|
-
<a href="{{ document.pdf }}">PDF</a>
|
65
|
-
</div>
|
66
|
-
{% endunless %}
|
67
|
-
{% unless document.doc == blank or document.doc == nil %}
|
68
|
-
<div class="doc-access-button-doc">
|
69
|
-
<a href="{{ document.doc }}">Word</a>
|
70
|
-
</div>
|
71
|
-
{% endunless %}
|
72
|
-
{% unless document.xml == blank or document.xml == nil %}
|
73
|
-
<div class="doc-access-button-xml">
|
74
|
-
<a href="{{ document.xml }}">XML</a>
|
75
|
-
</div>
|
76
|
-
{% endunless %}
|
77
|
-
</div>
|
78
|
-
</div>
|
79
|
-
|
80
|
-
{%- if document.items.size > 0 -%}
|
81
|
-
{%- include 'document' for document.items -%}
|
82
|
-
{%- endif -%}
|
@@ -1,53 +0,0 @@
|
|
1
|
-
<!DOCTYPE HTML>
|
2
|
-
<html>
|
3
|
-
<head>
|
4
|
-
<title>{{ title }}</title>
|
5
|
-
<style>
|
6
|
-
<!--
|
7
|
-
{{ css }}
|
8
|
-
-->
|
9
|
-
</style>
|
10
|
-
<meta http-equiv="Content-Type" content="text/html" charset="utf-8"/>
|
11
|
-
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js" type="text/javascript"></script>
|
12
|
-
<script src="https://cdn.rawgit.com/jgallen23/toc/0.3.2/dist/toc.min.js" type="text/javascript"></script>
|
13
|
-
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,300i,400,400i,600,600i|Space+Mono:400,700|Overpass:300,300i,600,900|Ek+Mukta:200" rel="stylesheet" type="text/css"/>
|
14
|
-
<link href="https://use.fontawesome.com/releases/v5.0.8/css/solid.css" integrity="sha384-v2Tw72dyUXeU3y4aM2Y0tBJQkGfplr39mxZqlTBDUZAb9BGoC40+rdFCG0m10lXk" crossorigin="anonymous"/>
|
15
|
-
<link href="https://use.fontawesome.com/releases/v5.0.8/css/fontawesome.css" integrity="sha384-q3jl8XQu1OpdLgGFvNRnPdj5VIlCvgsDQTQB6owSOHWlAurxul7f+JpUOVdAiJ5P" crossorigin="anonymous"/>
|
16
|
-
</head>
|
17
|
-
<body>
|
18
|
-
<header>
|
19
|
-
<div id="topbar-inner">
|
20
|
-
<div id="title-bar"><span>{{ author }}</span></div>
|
21
|
-
</div>
|
22
|
-
<div class="title-section">
|
23
|
-
<div class="coverpage">
|
24
|
-
<div class="wrapper-top">
|
25
|
-
<div class="coverpage-doc-identity">
|
26
|
-
<div class="coverpage-title"><span class="title-first">{{ title }}</span></div>
|
27
|
-
</div>
|
28
|
-
</div>
|
29
|
-
</div>
|
30
|
-
</div>
|
31
|
-
</header>
|
32
|
-
<main class="main-section">
|
33
|
-
{% include 'document' for documents %}
|
34
|
-
</main>
|
35
|
-
<footer>
|
36
|
-
<div class="copyright">
|
37
|
-
<p class="year">© {{ author }}</p>
|
38
|
-
<p class="message">All rights reserved. Unless otherwise specified, no part of this publication may be reproduced or utilized otherwise in any form or by any means, electronic or mechanical, including photocopying, or posting on the internet or an intranet, without prior written permission.</p>
|
39
|
-
</div>
|
40
|
-
</footer>
|
41
|
-
<script>
|
42
|
-
$(document).ready(function() {
|
43
|
-
$('[id^=toc]').each(function () {
|
44
|
-
var currentToc = $(this);
|
45
|
-
var url = window.location.href;
|
46
|
-
currentToc.wrap("<a href='" + url + "#" + currentToc.attr("id") + "' <\/a>");
|
47
|
-
});
|
48
|
-
});
|
49
|
-
anchors.options = { placement: 'left' };
|
50
|
-
anchors.add('h1, h2, h3, h4');
|
51
|
-
</script>
|
52
|
-
</body>
|
53
|
-
</html>
|