asciidoctor-dita-map 0.9.3 → 0.9.5

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: 7868b5b984e99b8e02f45f267b4d493943d4232c1dc69e52169e39076f42bc01
4
- data.tar.gz: 664073302552d392ba455a64fa4f28affd2b3fa890dfb333620b077094291835
3
+ metadata.gz: cc9694104672b3a22efb305a08f2954941f8d91acf81d9fa9f0d5cb64380337b
4
+ data.tar.gz: 914fd13e2487bbde82996710386e54e877f7b95af72c48ab18a46542c8878c6f
5
5
  SHA512:
6
- metadata.gz: c707f1e3aedc8aaec0b8be683eb9b01df94c1ce7812a994d5d6d09e727de1bd4e3c2e66a4cd84fbb06cfcb0e7fdbc0528e3b6d992c4787d1e6537450aa2f2130
7
- data.tar.gz: f7cfb07b8374bd7f5d20fcde17b2b9221a019bb236592860a09a73b87b9483f47eb65ee2e113a979a0268756f6d384fe4d463aa7a4048dd843261b8f5aebb8e9
6
+ metadata.gz: 5745079517ec9a0e9671cec8e89ddc617904de1bc407f2341383a213e31f6f185ee22c8c7a9cee30c07cc201e6928a073870f19d26b2843c5938c40883b4e5b0
7
+ data.tar.gz: b532bef1754789cb635e4731b1d8ecb292ce75e37261901dde755395f0d66616de7f12efe17f5ff661efeaaf8561153e3cb7b72273ce28fe072689ac7d527eb8
data/bin/dita-map CHANGED
@@ -26,11 +26,11 @@
26
26
  require (cli = File.absolute_path '../lib/dita-map/cli.rb', __dir__) ? cli : 'dita-map/cli'
27
27
 
28
28
  begin
29
- name = File.basename($0)
30
- converter = AsciidoctorDitaMap::Cli.new name, ARGV
29
+ converter = AsciidoctorDitaMap::Cli.new ARGV
31
30
  converter.run
32
- rescue OptionParser::InvalidArgument, OptionParser::InvalidOption, OptionParser::MissingArgument => error
33
- abort "#{name}: #{error.message}"
31
+ rescue OptionParser::InvalidArgument, OptionParser::InvalidOption,
32
+ OptionParser::AmbiguousOption, OptionParser::MissingArgument => error
33
+ abort "#{AsciidoctorDitaMap::NAME}: #{error.message}"
34
34
  rescue Interrupt
35
35
  exit 130
36
36
  end
@@ -29,16 +29,18 @@ class CatalogIncludeDirectives < Asciidoctor::Extensions::IncludeProcessor
29
29
  end
30
30
 
31
31
  def process doc, reader, target, attributes
32
- offset = attributes['leveloffset'].to_i
33
- chunk = attributes['chunk'] or nil
34
- toc = attributes['toc'] or nil
32
+ offset = attributes['leveloffset'].to_i
33
+ navtitle = attributes['navtitle'] or nil
34
+ chunk = attributes['chunk'] or nil
35
+ toc = attributes['toc'] or nil
35
36
 
36
37
  doc.catalog[:include_files] = [] unless doc.catalog[:include_files]
37
38
  doc.catalog[:include_files].append({
38
- :target => target,
39
- :offset => offset,
40
- :chunk => chunk,
41
- :toc => toc
39
+ :target => target,
40
+ :offset => offset,
41
+ :navtitle => navtitle,
42
+ :chunk => chunk,
43
+ :toc => toc
42
44
  })
43
45
 
44
46
  reader
data/lib/dita-map/cli.rb CHANGED
@@ -23,43 +23,28 @@
23
23
 
24
24
  require 'optparse'
25
25
  require 'pathname'
26
- require 'asciidoctor'
27
- require 'rexml/document'
28
- require_relative 'catalog'
26
+ require_relative 'convert'
29
27
  require_relative 'version'
30
28
 
31
29
  module AsciidoctorDitaMap
32
30
  class Cli
33
- def initialize name, argv
34
- @attr = []
35
- @opts = {
36
- :chunk => true,
37
- :id => true,
38
- :navtitle => true,
39
- :output => false,
40
- :title => true,
41
- :toc => true,
42
- :type => true,
43
- :self => false,
44
- :verbose => false,
45
- :zero_offset => false
46
- }
47
- @prep = []
48
- @name = name
49
- @args = self.parse_args argv
31
+ def initialize argv
32
+ @output = nil
33
+ @converter = Convert.new
34
+ @args = self.parse_args argv
50
35
  end
51
36
 
52
37
  def parse_args argv
53
38
  parser = OptionParser.new do |opt|
54
- opt.banner = "Usage: #{@name} [OPTION...] [FILE...]\n"
55
- opt.banner += " #{@name} -h|-v\n\n"
39
+ opt.banner = "Usage: #{NAME} [OPTION...] [FILE...]\n"
40
+ opt.banner += " #{NAME} -h|-v\n\n"
56
41
 
57
42
  opt.on('-o', '--out-file FILE', 'specify the output file; by default, the output file name is based on the input file') do |output|
58
- @opts[:output] = (output.strip == '-') ? $stdout : output
43
+ @output = (output.strip == '-') ? $stdout : output
59
44
  end
60
45
 
61
46
  opt.on('-a', '--attribute ATTRIBUTE', 'set a document attribute in the form of name, name!, or name=value pair; can be supplied multiple times') do |value|
62
- @attr.append value
47
+ @converter.attr.append value
63
48
  end
64
49
 
65
50
  opt.separator ''
@@ -68,47 +53,56 @@ module AsciidoctorDitaMap
68
53
  raise OptionParser::InvalidArgument, "not a file: #{file}" unless File.exist? file and File.file? file
69
54
  raise OptionParser::InvalidArgument, "file not readable: #{file}" unless File.readable? file
70
55
 
71
- @prep.append file
56
+ @converter.prep << File.read(file)
57
+ @converter.prep << "\n"
72
58
  end
73
59
 
74
60
  opt.on('-i', '--include-self', 'make the supplied file the toplevel topicref') do
75
- @opts[:self] = true
61
+ @converter.opts[:self] = true
76
62
  end
77
63
 
78
64
  opt.separator ''
79
65
 
80
66
  opt.on('-I', '--no-id', 'do not generate the map id attribute') do
81
- @opts[:id] = false
67
+ @converter.opts[:id] = false
82
68
  end
83
69
 
84
70
  opt.on('-M', '--no-maptitle', 'do not generate the map title') do
85
- @opts[:title] = false
71
+ @converter.opts[:title] = false
72
+ end
73
+
74
+ opt.on('-A', '--no-assembly', 'do treat assemblies as maps') do
75
+ @converter.opts[:assembly] = false
86
76
  end
87
77
 
88
78
  opt.on('-C', '--no-chunk', 'do not generate the chunk attribute') do
89
- @opts[:chunk] = false
79
+ @converter.opts[:chunk] = false
80
+ end
81
+
82
+ opt.on('-L', '--no-locktitle', 'do not generate the locktitle attribute') do
83
+ @converter.opts[:locktitle] = false
90
84
  end
91
85
 
92
86
  opt.on('-N', '--no-navtitle', 'do not generate the navtitle attribute') do
93
- @opts[:navtitle] = false
87
+ @converter.opts[:navtitle] = false
94
88
  end
95
89
 
96
90
  opt.on('-O', '--no-toc', 'do not generate the toc attribute') do
97
- @opts[:toc] = false
91
+ @converter.opts[:toc] = false
98
92
  end
99
93
 
100
94
  opt.on('-T', '--no-type', 'do not generate the type attribute') do
101
- @opts[:type] = false
95
+ @converter.opts[:type] = false
102
96
  end
103
97
 
104
98
  opt.separator ''
105
99
 
106
- opt.on('-z', '--zero-offset', 'allow include directives with zero leveloffset') do
107
- @opts[:zero_offset] = true
100
+ opt.on('-v', '--verbose', 'report additional problems in the supplied files') do
101
+ @converter.opts[:verbose] = true
108
102
  end
109
103
 
110
- opt.on('-v', '--verbose', 'report additional problems in the supplied files') do
111
- @opts[:verbose] = true
104
+ opt.on('-z', '--zero-offset', 'allow include directives with zero leveloffset') do
105
+ @converter.opts[:zero_offset] = true
112
106
  end
113
107
 
114
108
  opt.separator ''
@@ -119,7 +113,7 @@ module AsciidoctorDitaMap
119
113
  end
120
114
 
121
115
  opt.on('-V', '--version', 'display version information and exit') do
122
- puts "#{@name} #{VERSION}"
116
+ puts "#{NAME} #{VERSION}"
123
117
  exit
124
118
  end
125
119
  end
@@ -138,182 +132,22 @@ module AsciidoctorDitaMap
138
132
  return args
139
133
  end
140
134
 
141
- def compose_mapref_attributes file_info, type
142
- target_file = file_info[:target].sub(/\.adoc$/, '.ditamap')
143
- attributes = { 'href' => target_file, 'format' => 'ditamap' }
144
- attributes['type'] = type if @opts[:type]
145
- attributes['chunk'] = file_info[:chunk] if @opts[:chunk] and file_info[:chunk]
146
- attributes['toc'] = file_info[:toc] if @opts[:toc] and file_info[:toc]
147
-
148
- return attributes
149
- end
150
-
151
- def compose_topicref_attributes file_info, title, type
152
- target_file = file_info[:target].sub(/\.adoc$/, '.dita')
153
- attributes = { 'href' => target_file }
154
- attributes['navtitle'] = title if @opts[:navtitle] and title
155
- attributes['type'] = type if @opts[:type] and type and ['concept', 'reference', 'task'].include? type
156
- attributes['chunk'] = file_info[:chunk] if @opts[:chunk] and file_info[:chunk]
157
- attributes['toc'] = file_info[:toc] if @opts[:toc] and file_info[:toc]
158
-
159
- return attributes
160
- end
161
-
162
- def get_content_type attributes
163
- document_type = attributes['_mod-docs-content-type'] ? attributes['_mod-docs-content-type'].downcase : nil
164
- document_type = attributes['_content-type'] ? attributes['_content-type'].downcase : nil unless document_type
165
- document_type = attributes['_module-type'] ? attributes['_module-type'].downcase : nil unless document_type
166
-
167
- if document_type
168
- document_type.sub!(/^assembly$/, 'concept')
169
- document_type.sub!(/^procedure$/, 'task')
170
- end
171
-
172
- unless ['concept', 'reference', 'task', 'map', 'attributes', 'snippet'].include? document_type
173
- return nil
174
- end
175
-
176
- return document_type
177
- end
178
-
179
- def parse_topic input
180
- doc = Asciidoctor.load input, safe: :secure, attributes: @attr
181
-
182
- document_title = doc.title ? doc.title.gsub(/<[^>]*>/, '') : nil
183
- document_type = get_content_type doc.attributes
184
-
185
- return document_title, document_type
186
- end
187
-
188
- def parse_map input, base_dir
189
- Asciidoctor::Extensions.register do
190
- include_processor CatalogIncludeDirectives
191
- end
192
-
193
- doc = Asciidoctor.load input, safe: :safe, catalog_assets: true, attributes: @attr, base_dir: base_dir
194
-
195
- include_files = doc.catalog[:include_files] ? doc.catalog[:include_files] : []
196
- map_id = doc.id ? doc.id.gsub(/["']/, '') : nil
197
- map_title = doc.title ? doc.title.gsub(/<[^>]*>/, '') : nil
198
- map_type = get_content_type doc.attributes
199
-
200
- info = {
201
- :id => map_id,
202
- :title => map_title,
203
- :type => map_type
204
- }
205
-
206
- return include_files, info
207
- end
208
-
209
- def convert_map input, base_dir, prepended = '', file = nil
210
- result = ''
211
-
212
- include_files, map = parse_map prepended + input, base_dir
213
-
214
- xml = REXML::Document.new
215
- xml.context[:attribute_quote] = :quote
216
- xml << REXML::XMLDecl.new('1.0', 'utf-8')
217
- xml << REXML::DocType.new('map', 'PUBLIC "-//OASIS//DTD DITA Map//EN" "map.dtd"')
218
-
219
- if map[:id] and @opts[:id]
220
- xml_root = xml.add_element('map', { 'id' => map[:id] })
221
- else
222
- xml_root = xml.add_element('map')
223
- end
224
-
225
- if map[:title] and @opts[:title]
226
- xml_title = xml_root.add_element('title')
227
- xml_title.text = map[:title]
228
- end
229
-
230
- if @opts[:self] and file
231
- attributes = compose_topicref_attributes({ :target => file }, map[:title], map[:type])
232
- xml_self = xml_root.add_element('topicref', attributes)
233
- stack = [{ :offset => 0, :element => xml_self }]
234
- else
235
- stack = [{ :offset => 0, :element => xml_root }]
236
- end
237
-
238
- include_files.each do |file_info|
239
- target = file_info[:target]
240
- offset = file_info[:offset]
241
- last_offset = stack.last[:offset]
242
- full_path = base_dir + target
243
-
244
- if not File.exist? full_path and @opts[:verbose]
245
- warn "#{@name}: warning: file not found: #{target}"
246
- end
247
-
248
- begin
249
- include_title, include_type = parse_topic prepended + File.read(full_path)
250
- next if ['attributes', 'snippet'].include? include_type
251
- rescue
252
- warn "#{@name}: warning: unable to read included file: #{target}"
253
- include_title, include_type = nil, nil
254
- end
255
-
256
- if offset == 0
257
- if @opts[:zero_offset]
258
- offset = 0
259
- else
260
- warn "#{@name}: warning: invalid leveloffset - expected 1, got 0: #{target}"
261
- offset = 1
262
- end
263
- elsif offset > last_offset and offset - last_offset > 1
264
- expected_offset = last_offset + 1
265
- warn "#{@name}: warning: invalid leveloffset - expected #{expected_offset}, got #{offset}: #{target}"
266
- end
267
-
268
- while stack.length > 1 and stack.last[:offset] >= offset
269
- stack.pop
270
- end
271
-
272
- xml_parent = stack.last[:element]
273
-
274
- if include_type == 'map'
275
- attributes = compose_mapref_attributes file_info, include_type
276
- xml_element = xml_parent.add_element('mapref', attributes)
277
- else
278
- attributes = compose_topicref_attributes file_info, include_title, include_type
279
- xml_element = xml_parent.add_element('topicref', attributes)
280
- end
281
-
282
- stack.push ({ :offset => offset, :element => xml_element })
283
- end
284
-
285
- formatter = REXML::Formatters::Pretty.new(2, true)
286
- formatter.compact = true
287
- formatter.write(xml, result)
288
-
289
- result << "\n"
290
-
291
- return result
292
- end
293
-
294
135
  def run
295
- prepended = ''
296
-
297
- @prep.each do |file|
298
- prepended << File.read(file)
299
- prepended << "\n"
300
- end
301
-
302
136
  @args.each do |file|
303
137
  if file == $stdin
304
138
  base_dir = Pathname.new(Dir.pwd).expand_path
305
139
  input = $stdin.read
306
- output = @opts[:output] ? @opts[:output] : $stdout
140
+ output = @output ? @output : $stdout
307
141
  else
308
142
  base_dir = Pathname.new(file).dirname.expand_path
309
143
  input = File.read(file)
310
- output = @opts[:output] ? @opts[:output] : Pathname.new(file).sub_ext('.ditamap').to_s
144
+ output = @output ? @output : Pathname.new(file).sub_ext('.ditamap').to_s
311
145
  end
312
146
 
313
- if @opts[:self] and file != $stdin
314
- result = convert_map input, base_dir, prepended, file
147
+ if @converter.opts[:self] and file != $stdin
148
+ result = @converter.run input, base_dir, file
315
149
  else
316
- result = convert_map input, base_dir, prepended
150
+ result = @converter.run input, base_dir
317
151
  end
318
152
 
319
153
  if output == $stdout
@@ -0,0 +1,164 @@
1
+ # Copyright (C) 2026 Jaromir Hradilek
2
+
3
+ # MIT License
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining
6
+ # a copy of this software and associated documentation files (the "Soft-
7
+ # ware"), to deal in the Software without restriction, including without
8
+ # limitation the rights to use, copy, modify, merge, publish, distribute,
9
+ # sublicense, and/or sell copies of the Software, and to permit persons to
10
+ # whom the Software is furnished to do so, subject to the following condi-
11
+ # tions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included
14
+ # in all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17
+ # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABI-
18
+ # LITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
19
+ # SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
20
+ # OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21
+ # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ # OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ require 'rexml/document'
25
+ require_relative 'topic'
26
+ require_relative 'map'
27
+
28
+ module AsciidoctorDitaMap
29
+ class Convert
30
+ attr_accessor :attr, :opts, :prep
31
+
32
+ def initialize
33
+ @attr = []
34
+ @opts = {
35
+ :chunk => true,
36
+ :id => true,
37
+ :assembly => true,
38
+ :locktitle => true,
39
+ :navtitle => true,
40
+ :title => true,
41
+ :toc => true,
42
+ :type => true,
43
+ :self => false,
44
+ :verbose => false,
45
+ :zero_offset => false
46
+ }
47
+ @prep = ''
48
+ end
49
+
50
+ def compose_mapref_attributes element, file_info, type
51
+ target_file = file_info[:target].sub(/\.adoc$/, '.ditamap')
52
+
53
+ element.add_attribute 'href', target_file
54
+ element.add_attribute 'format', 'ditamap'
55
+ element.add_attribute 'type', type if @opts[:type]
56
+ element.add_attribute 'chunk', file_info[:chunk] if @opts[:chunk] and file_info[:chunk]
57
+ element.add_attribute 'toc', file_info[:toc] if @opts[:toc] and file_info[:toc]
58
+ end
59
+
60
+ def compose_topicref_attributes element, file_info, title, type
61
+ target_file = file_info[:target].sub(/\.adoc$/, '.dita')
62
+
63
+ element.add_attribute 'href', target_file
64
+
65
+ if file_info[:navtitle]
66
+ element.add_attribute REXML::Attribute.new('navtitle', file_info[:navtitle]) if @opts[:navtitle]
67
+ else
68
+ element.add_attribute REXML::Attribute.new('navtitle', title) if @opts[:navtitle] and title
69
+ end
70
+
71
+ element.add_attribute 'locktitle', 'yes' if @opts[:locktitle] and element['navtitle']
72
+ element.add_attribute 'type', type if @opts[:type] and type and ['concept', 'reference', 'task'].include? type
73
+ element.add_attribute 'chunk', file_info[:chunk] if @opts[:chunk] and file_info[:chunk]
74
+ element.add_attribute 'toc', file_info[:toc] if @opts[:toc] and file_info[:toc]
75
+ end
76
+
77
+ def run input, base_dir, file = nil
78
+ result = ''
79
+
80
+ map = Map.new @prep + input, base_dir, @attr
81
+
82
+ xml = REXML::Document.new
83
+ xml.context[:attribute_quote] = :quote
84
+ xml << REXML::XMLDecl.new('1.0', 'utf-8')
85
+ xml << REXML::DocType.new('map', 'PUBLIC "-//OASIS//DTD DITA Map//EN" "map.dtd"')
86
+
87
+ if map.id and @opts[:id]
88
+ xml_root = xml.add_element('map', { 'id' => map.id })
89
+ else
90
+ xml_root = xml.add_element('map')
91
+ end
92
+
93
+ if map.title and @opts[:title]
94
+ xml_title = xml_root.add_element('title')
95
+ xml_title.add REXML::Text.new(map.title, false, nil, true)
96
+ end
97
+
98
+ if @opts[:self] and file
99
+ xml_self = xml_root.add_element('topicref')
100
+ compose_topicref_attributes(xml_self, { :target => file }, map.title, map.type)
101
+ stack = [{ :offset => 0, :element => xml_self }]
102
+ else
103
+ stack = [{ :offset => 0, :element => xml_root }]
104
+ end
105
+
106
+ map.includes.each do |file_info|
107
+ target = file_info[:target]
108
+ offset = file_info[:offset]
109
+ last_offset = stack.last[:offset]
110
+ full_path = base_dir + target
111
+
112
+ if not File.exist? full_path and @opts[:verbose]
113
+ warn "#{NAME}: warning: file not found: #{target}"
114
+ end
115
+
116
+ begin
117
+ topic = Topic.new @prep + File.read(full_path), @attr
118
+ next if ['attributes', 'snippet'].include? topic.type
119
+ rescue
120
+ warn "#{NAME}: warning: unable to read included file: #{target}"
121
+ topic = Topic.new ''
122
+ end
123
+
124
+ if offset == 0
125
+ if @opts[:zero_offset]
126
+ offset = 0
127
+ else
128
+ warn "#{NAME}: warning: invalid leveloffset - expected 1, got 0: #{target}"
129
+ offset = 1
130
+ end
131
+ elsif offset > last_offset and offset - last_offset > 1
132
+ expected_offset = last_offset + 1
133
+ warn "#{NAME}: warning: invalid leveloffset - expected #{expected_offset}, got #{offset}: #{target}"
134
+ end
135
+
136
+ while stack.length > 1 and stack.last[:offset] >= offset
137
+ stack.pop
138
+ end
139
+
140
+ xml_parent = stack.last[:element]
141
+
142
+ topic.type.sub!(/^assembly$/, 'concept') if not @opts[:assembly]
143
+
144
+ if topic.type == 'map' or topic.type == 'assembly'
145
+ xml_element = xml_parent.add_element('mapref')
146
+ compose_mapref_attributes xml_element, file_info, 'map'
147
+ else
148
+ xml_element = xml_parent.add_element('topicref')
149
+ compose_topicref_attributes xml_element, file_info, topic.title, topic.type
150
+ end
151
+
152
+ stack.push ({ :offset => offset, :element => xml_element })
153
+ end
154
+
155
+ formatter = REXML::Formatters::Pretty.new(2, true)
156
+ formatter.compact = true
157
+ formatter.write(xml, result)
158
+
159
+ result << "\n"
160
+
161
+ return result
162
+ end
163
+ end
164
+ end
@@ -0,0 +1,52 @@
1
+ # Copyright (C) 2026 Jaromir Hradilek
2
+
3
+ # MIT License
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining
6
+ # a copy of this software and associated documentation files (the "Soft-
7
+ # ware"), to deal in the Software without restriction, including without
8
+ # limitation the rights to use, copy, modify, merge, publish, distribute,
9
+ # sublicense, and/or sell copies of the Software, and to permit persons to
10
+ # whom the Software is furnished to do so, subject to the following condi-
11
+ # tions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included
14
+ # in all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17
+ # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABI-
18
+ # LITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
19
+ # SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
20
+ # OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21
+ # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ # OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ require 'asciidoctor'
25
+ require_relative 'catalog'
26
+ require_relative 'topic'
27
+
28
+ module AsciidoctorDitaMap
29
+ class Map < Topic
30
+ attr_accessor :id, :includes
31
+
32
+ def initialize input, base_dir, attributes = []
33
+ if input.empty?
34
+ @id = nil
35
+ @title = nil
36
+ @type = nil
37
+ @includes = []
38
+ else
39
+ Asciidoctor::Extensions.register do
40
+ include_processor CatalogIncludeDirectives
41
+ end
42
+
43
+ doc = Asciidoctor.load input, safe: :safe, catalog_assets: true, attributes: attributes, base_dir: base_dir
44
+
45
+ @includes = doc.catalog[:include_files] ? doc.catalog[:include_files] : []
46
+ @id = doc.id ? doc.id.gsub(/["']/, '') : nil
47
+ @title = doc.title ? doc.title.gsub(/<[^>]*>/, '') : nil
48
+ @type = get_content_type doc.attributes
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,60 @@
1
+ # Copyright (C) 2026 Jaromir Hradilek
2
+
3
+ # MIT License
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining
6
+ # a copy of this software and associated documentation files (the "Soft-
7
+ # ware"), to deal in the Software without restriction, including without
8
+ # limitation the rights to use, copy, modify, merge, publish, distribute,
9
+ # sublicense, and/or sell copies of the Software, and to permit persons to
10
+ # whom the Software is furnished to do so, subject to the following condi-
11
+ # tions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included
14
+ # in all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17
+ # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABI-
18
+ # LITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
19
+ # SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
20
+ # OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21
+ # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ # OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ require 'asciidoctor'
25
+
26
+ module AsciidoctorDitaMap
27
+ class Topic
28
+ attr_accessor :title, :type
29
+
30
+ def initialize input, attributes = []
31
+ if input.empty?
32
+ @title = nil
33
+ @type = nil
34
+ else
35
+ doc = Asciidoctor.load input, safe: :secure, attributes: attributes
36
+
37
+ @title = doc.title ? doc.title.gsub(/<[^>]*>/, '') : nil
38
+ @type = get_content_type doc.attributes
39
+ end
40
+ end
41
+
42
+ private
43
+
44
+ def get_content_type attributes
45
+ type = attributes['_mod-docs-content-type'] ? attributes['_mod-docs-content-type'].downcase : nil
46
+ type = attributes['_content-type'] ? attributes['_content-type'].downcase : nil unless type
47
+ type = attributes['_module-type'] ? attributes['_module-type'].downcase : nil unless type
48
+
49
+ if type
50
+ type.sub!(/^procedure$/, 'task')
51
+ end
52
+
53
+ unless ['assembly', 'concept', 'reference', 'task', 'map', 'attributes', 'snippet'].include? type
54
+ return nil
55
+ end
56
+
57
+ return type
58
+ end
59
+ end
60
+ end
@@ -24,5 +24,6 @@
24
24
  # frozen_string_literal: true
25
25
 
26
26
  module AsciidoctorDitaMap
27
- VERSION = '0.9.3'
27
+ NAME = 'dita-map'
28
+ VERSION = '0.9.5'
28
29
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: asciidoctor-dita-map
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.3
4
+ version: 0.9.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jaromir Hradilek
@@ -117,6 +117,9 @@ files:
117
117
  - bin/dita-map
118
118
  - lib/dita-map/catalog.rb
119
119
  - lib/dita-map/cli.rb
120
+ - lib/dita-map/convert.rb
121
+ - lib/dita-map/map.rb
122
+ - lib/dita-map/topic.rb
120
123
  - lib/dita-map/version.rb
121
124
  homepage: https://github.com/jhradilek/asciidoctor-dita-map
122
125
  licenses: