markdown_helper 2.1.0 → 2.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cee806406f109c72b11a7a4f78c8ad7efc59706f278a0a5b654267e3ae38ddf6
4
- data.tar.gz: 4e49e14011eb429bd5d523a314572aff3693876b07fa50b52d9cfecf693fcd3d
3
+ metadata.gz: '09204d578d4034b5940afc983b9d3989adff2d1b05763b0e6e867e3183b338c8'
4
+ data.tar.gz: a90232dc47c8d901f1fa1a5bed7964e0deee6fb3b3bd9d2713f46ea105b162b2
5
5
  SHA512:
6
- metadata.gz: 5d4c4a25171b3ac8df8cfd84766843ae7c8d599c896d70b1d70854353dc7f0cb06741d1832640f5f24fdc500285bf16684f09d7d08450a48c73680d0033cab9f
7
- data.tar.gz: 5f81f39ad84273fa2367a03e7bc18773190c97398ff7ac3c8834eac464a2a9dbe8bbedbf566fee79489124d2458fc32bfec96534b85f2edd4a7cadbb1e5dd63c
6
+ metadata.gz: ad9d3e8cbf0a1fa17eba25579c02165571e5408ea979747600aa6db74b52122fd2157d61d6f2a65e7302eac52a443e40343d10d0c291eae7912d64ccd099ed6f
7
+ data.tar.gz: 4ee21575e5d049259b9c365ab9842d904127ebe8df9f023304bcb35c34242f3eb81edf37a055aee6cdce61283c635fb4d38bb4ffbfa7cdc54f6b7f8584fb8672
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- markdown_helper (2.1.0)
4
+ markdown_helper (2.2.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2018 Burdette Lamar
3
+ Copyright (c) 2018-2019 Burdette Lamar
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,16 +1,11 @@
1
- <!-- >>>>>> BEGIN GENERATED FILE (include): SOURCE README.template.md -->
1
+ <!-- >>>>>> BEGIN GENERATED FILE (include): SOURCE markdown/readme/README.template.md -->
2
2
  # Markdown Helper
3
3
 
4
4
  [![Gem](https://img.shields.io/gem/v/markdown_helper.svg?style=flat)](http://rubygems.org/gems/markdown_helper "View this project in Rubygems")
5
5
 
6
6
  ## What's New?
7
7
 
8
- Page TOC (table of contents) is improved:
9
-
10
- - **Old**: You would first run the markdown helper to generate a page TOC, then run the helper a second time to include the page TOC where you want it.
11
- - **New**: You specify the site for the page TOC in the page itself, and the page TOC is automatically generated and inserted there. See the [use case](markdown/use_cases/include_files/include_page_toc/use_case.md#include-page-toc)
12
-
13
- The old way is now deprecated.
8
+ Command line creation of page TOC (table of contents), previously deprecated, is removed.
14
9
 
15
10
  ## Contents
16
11
  - [What's a Markdown Helper?](#whats-a-markdown-helper)
@@ -172,7 +167,7 @@ where:
172
167
 
173
168
  <!-- >>>>>> BEGIN INCLUDED FILE (code_block): SOURCE markdown/readme/include.md -->
174
169
  ```include.md```:
175
- ```code_block
170
+ ```
176
171
  @[ruby](my_ruby.rb)
177
172
 
178
173
  @[:code_block](my_language.xyzzy)
@@ -213,4 +208,4 @@ I have opened some enhancement Issues in the GitHub [markdown_helper](https://gi
213
208
  * [Pagination](https://github.com/BurdetteLamar/markdown_helper/issues/40): series of markdown pages connected by prev/next navigation links.
214
209
 
215
210
  Feel free to comment on any of these, or to add more Issues (enhancement or otherwise).
216
- <!-- <<<<<< END GENERATED FILE (include): SOURCE README.template.md -->
211
+ <!-- <<<<<< END GENERATED FILE (include): SOURCE markdown/readme/README.template.md -->
data/Rakefile CHANGED
@@ -26,7 +26,6 @@ namespace :build do
26
26
  desc 'Build usage for executables'
27
27
  task :usages do
28
28
  %w/
29
- create_page_toc
30
29
  include
31
30
  /.each do |executable_name|
32
31
  usage_text = `ruby bin/_#{executable_name} --help`
@@ -1,19 +1,20 @@
1
1
  require 'pathname'
2
+
2
3
  require 'markdown_helper/version'
3
4
 
4
5
  class MarkdownHelper
5
6
 
6
7
  class MarkdownHelperError < RuntimeError; end
7
- class CircularIncludeError < MarkdownHelperError; end
8
- class UnreadableInputError < MarkdownHelperError; end
9
- class TocHeadingsError < MarkdownHelperError; end
10
8
  class OptionError < MarkdownHelperError; end
11
- class EnvironmentError < MarkdownHelperError; end
12
- class InvalidTocTitleError < MarkdownHelperError; end
13
- class MisplacedPageTocError < MarkdownHelperError; end
14
9
  class MultiplePageTocError < MarkdownHelperError; end
10
+ class InvalidTocTitleError < MarkdownHelperError; end
11
+ class UnreadableTemplateError < MarkdownHelperError; end
12
+ class UnwritableMarkdownError < MarkdownHelperError; end
13
+ class CircularIncludeError < MarkdownHelperError; end
14
+ class UnreadableIncludeeError < MarkdownHelperError; end
15
15
 
16
16
  INCLUDE_REGEXP = /^@\[([^\[]+)\]\(([^)]+)\)$/
17
+ INCLUDE_MARKDOWN_REGEXP = /^@\[:markdown\]\(([^)]+)\)$/
17
18
 
18
19
  attr_accessor :pristine
19
20
 
@@ -35,187 +36,192 @@ class MarkdownHelper
35
36
  send(setter_method, value)
36
37
  merged_options.delete(method)
37
38
  end
39
+ @inclusions = []
38
40
  end
39
41
 
40
42
  def include(template_file_path, markdown_file_path)
41
- send(:generate_file, template_file_path, markdown_file_path, __method__) do |input_lines, output_lines|
42
- send(:include_files, template_file_path, input_lines, output_lines, Inclusions.new)
43
- end
44
- end
45
-
46
- def create_page_toc(markdown_file_path, toc_file_path)
47
- message = <<EOT
48
- Method create_page_toc is deprecated.
49
- Please use method include with embedded :page_toc treatment.
50
- See https://github.com/BurdetteLamar/markdown_helper/blob/master/markdown/use_cases/include_files/include_page_toc/use_case.md#include-page-toc.
51
- EOT
52
- warn(message)
53
- send(:generate_file, markdown_file_path, toc_file_path, __method__) do |input_lines, output_lines|
54
- send(:_create_page_toc, input_lines, output_lines)
43
+ send(:generate_file, template_file_path, markdown_file_path) do |output_lines|
44
+ Dir.chdir(File.dirname(template_file_path)) do
45
+ markdown_lines = include_markdown(template_file_path)
46
+ markdown_lines = include_page_toc(markdown_lines)
47
+ include_all(template_file_path, markdown_lines, output_lines)
48
+ end
55
49
  end
56
50
  end
57
51
 
58
52
  private
59
53
 
60
- class Heading
61
-
62
- attr_accessor :level, :title
63
-
64
- def initialize(level, title)
65
- self.level = level
66
- self.title = title
67
- end
68
-
69
- def self.parse(line)
70
- # Four leading spaces not allowed (but three are allowed).
71
- return nil if line.start_with?(' ' * 4)
72
- stripped_line = line.sub(/^ */, '')
73
- # Now must begin with hash marks and space.
74
- return nil unless stripped_line.match(/^#+ /)
75
- hash_marks, title = stripped_line.split(' ', 2)
76
- level = hash_marks.size
77
- # Seventh level heading not allowed.
78
- return nil if level > 6
79
- self.new(level, title)
80
- end
81
-
82
-
83
- def link
84
- remove_regexp = /[\#\(\)\[\]\{\}\.\?\+\*\`\"\']+/
85
- to_hyphen_regexp = /\W+/
86
- anchor = title.
87
- gsub(remove_regexp, '').
88
- gsub(to_hyphen_regexp, '-').
89
- downcase
90
- "[#{title}](##{anchor})"
54
+ def generate_file(template_file_path, markdown_file_path)
55
+ template_path_in_project = MarkdownHelper.path_in_project(template_file_path)
56
+ output_lines = []
57
+ yield output_lines
58
+ unless pristine
59
+ output_lines.unshift(MarkdownHelper.comment(" >>>>>> BEGIN GENERATED FILE (include): SOURCE #{template_path_in_project} "))
60
+ output_lines.push(MarkdownHelper.comment(" <<<<<< END GENERATED FILE (include): SOURCE #{template_path_in_project} "))
91
61
  end
92
-
62
+ output_lines.push('')
63
+ output = output_lines.join("\n")
64
+ File.write(markdown_file_path, output)
93
65
  end
94
66
 
95
- def self.comment(text)
96
- "<!--#{text}-->\n"
97
- end
98
-
99
- def generate_file(template_file_path, markdown_file_path, method)
100
- unless File.readable?(template_file_path)
101
- message = [
102
- Inclusions::UNREADABLE_INPUT_EXCEPTION_LABEL,
103
- template_file_path.inspect,
104
- ].join("\n")
105
- raise UnreadableInputError.new(message)
106
- end
107
- output_lines = []
108
- File.open(template_file_path, 'r') do |template_file|
109
- template_path_in_project = MarkdownHelper.path_in_project(template_file_path)
110
- output_lines.push(MarkdownHelper.comment(" >>>>>> BEGIN GENERATED FILE (#{method.to_s}): SOURCE #{template_path_in_project} ")) unless pristine
111
- input_lines = template_file.readlines
112
- yield input_lines, output_lines
113
- output_lines.push(MarkdownHelper.comment(" <<<<<< END GENERATED FILE (#{method.to_s}): SOURCE #{template_path_in_project} ")) unless pristine
114
- end
115
- File.open(markdown_file_path, 'w') do |file|
116
- output_lines.each do |line|
117
- file.write(line)
67
+ def include_markdown(template_file_path)
68
+ Dir.chdir(File.dirname(template_file_path)) do
69
+ markdown_lines = []
70
+ unless File.readable?(template_file_path)
71
+ message = [
72
+ 'Could not read template file:',
73
+ MarkdownHelper.backtrace_inclusions(@inclusions),
74
+ ].join("\n")
75
+ e = UnreadableTemplateError.new(message)
76
+ e.set_backtrace([])
77
+ raise e
78
+ end
79
+ template_lines = File.readlines(template_file_path)
80
+ template_lines.each_with_index do |template_line, i|
81
+ template_line.chomp!
82
+ treatment, includee_file_path = *parse_include(template_line)
83
+ if treatment.nil?
84
+ markdown_lines.push(template_line)
85
+ next
86
+ end
87
+ if treatment == ':page_toc'
88
+ markdown_lines.push(template_line)
89
+ next
90
+ end
91
+ inclusion = Inclusion.new(
92
+ template_file_path,
93
+ template_line,
94
+ i,
95
+ treatment,
96
+ includee_file_path,
97
+ @inclusions
98
+ )
99
+ treatment.sub!(/^:/, '')
100
+ case treatment
101
+ when 'markdown'
102
+ check_includee(inclusion)
103
+ check_circularity(inclusion)
104
+ @inclusions.push(inclusion)
105
+ includee_lines = include_markdown(File.absolute_path(includee_file_path))
106
+ markdown_lines.concat(includee_lines)
107
+ when 'comment'
108
+ text = File.read(includee_file_path)
109
+ markdown_lines.push(MarkdownHelper.comment(text))
110
+ @inclusions.push(inclusion)
111
+ when 'pre'
112
+ text = File.read(includee_file_path)
113
+ markdown_lines.push(MarkdownHelper.pre(text))
114
+ @inclusions.push(inclusion)
115
+ else
116
+ markdown_lines.push(template_line)
117
+ next
118
+ end
119
+ @inclusions.pop
120
+ add_inclusion_comments(treatment, includee_file_path, markdown_lines)
118
121
  end
122
+ markdown_lines
119
123
  end
120
124
  end
121
125
 
122
- def _create_page_toc(input_lines, output_lines)
126
+ def include_page_toc(template_lines)
127
+ toc_line_index = nil
128
+ toc_title = nil
129
+ template_lines.each_with_index do |template_line, i|
130
+ match_data = template_line.match(INCLUDE_REGEXP)
131
+ next unless match_data
132
+ treatment = match_data[1]
133
+ next unless treatment == ':page_toc'
134
+ unless toc_line_index.nil?
135
+ message = 'Multiple page TOC not allowed'
136
+ raise MultiplePageTocError.new(message)
137
+ end
138
+ toc_line_index = i
139
+ toc_title = match_data[2]
140
+ title_regexp = /^\#{1,6}\s/
141
+ unless toc_title.match(title_regexp)
142
+ message = "TOC title must be a valid markdown header, not #{toc_title}"
143
+ raise InvalidTocTitleError.new(message)
144
+ end
145
+ end
146
+ return template_lines unless toc_line_index
147
+ toc_lines = [toc_title]
123
148
  first_heading_level = nil
124
- input_lines.each do |input_line|
149
+ template_lines.each_with_index do |input_line, i|
150
+ next if i < toc_line_index
125
151
  line = input_line.chomp
126
152
  heading = Heading.parse(line)
127
153
  next unless heading
128
154
  first_heading_level ||= heading.level
129
155
  indentation = ' ' * (heading.level - first_heading_level)
130
- output_line = "#{indentation}- #{heading.link}"
131
- output_lines.push("#{output_line}\n")
156
+ toc_line = "#{indentation}- #{heading.link}"
157
+ toc_lines.push(toc_line)
132
158
  end
159
+ template_lines.delete_at(toc_line_index)
160
+ template_lines.insert(toc_line_index, *toc_lines)
161
+ template_lines
133
162
  end
134
163
 
135
- def include_files(includer_file_path, input_lines, output_lines, inclusions)
136
- markdown_lines = []
137
- page_toc_inclusion = nil
138
- input_lines.each_with_index do |input_line, line_index|
139
- match_data = input_line.match(INCLUDE_REGEXP)
140
- unless match_data
141
- markdown_lines.push(input_line)
164
+ def include_all(template_file_path, template_lines, output_lines)
165
+ template_lines.each_with_index do |template_line, i|
166
+ treatment, includee_file_path = *parse_include(template_line)
167
+ if treatment.nil?
168
+ output_lines.push(template_line)
142
169
  next
143
170
  end
144
- treatment = match_data[1]
145
- cited_includee_file_path = match_data[2]
146
- new_inclusion = Inclusion.new(
147
- input_line.chomp,
148
- includer_file_path,
149
- line_index + 1,
150
- cited_includee_file_path,
151
- treatment
171
+ inclusion = Inclusion.new(
172
+ template_file_path,
173
+ template_line,
174
+ i,
175
+ treatment,
176
+ includee_file_path,
177
+ @inclusions
152
178
  )
153
- case treatment
154
- when ':markdown'
155
- inclusions.include(
156
- new_inclusion,
157
- markdown_lines,
158
- self
159
- )
160
- when ':page_toc'
161
- unless inclusions.inclusions.size == 0
162
- message = 'Page TOC must be in outermost markdown file.'
163
- raise MisplacedPageTocError.new(message)
164
- end
165
- unless page_toc_inclusion.nil?
166
- message = 'Only one page TOC allowed.'
167
- raise MultiplePageTocError.new(message)
168
- end
169
- page_toc_inclusion = new_inclusion
170
- toc_title = match_data[2]
171
- title_regexp = /^\#{1,6}\s/
172
- unless toc_title.match(title_regexp)
173
- message = "TOC title must be a valid markdown header, not #{toc_title}"
174
- raise InvalidTocTitleError.new(message)
175
- end
176
- page_toc_inclusion.page_toc_title = toc_title
177
- page_toc_inclusion.page_toc_line = input_line
178
- markdown_lines.push(input_line)
179
- else
180
- markdown_lines.push(input_line)
181
- end
182
- end
183
- # If needed, create page TOC and insert into markdown_lines.
184
- unless page_toc_inclusion.nil?
185
- toc_lines = [
186
- page_toc_inclusion.page_toc_title + "\n",
187
- '',
188
- ]
189
- page_toc_index = markdown_lines.index(page_toc_inclusion.page_toc_line)
190
- lines_to_scan = markdown_lines[page_toc_index + 1..-1]
191
- _create_page_toc(lines_to_scan, toc_lines)
192
- markdown_lines.delete_at(page_toc_index)
193
- markdown_lines.insert(page_toc_index, *toc_lines)
179
+ check_includee(inclusion)
180
+ @inclusions.push(inclusion)
181
+ file_marker = format('```%s```:', File.basename(includee_file_path))
182
+ begin_backticks = '```'
183
+ end_backticks = '```'
184
+ begin_backticks += treatment unless treatment.start_with?(':')
185
+ includee_lines = File.read(includee_file_path).split("\n")
186
+ includee_lines.unshift(begin_backticks)
187
+ includee_lines.unshift(file_marker)
188
+ includee_lines.push(end_backticks)
189
+ add_inclusion_comments(treatment.sub(':', ''), includee_file_path, includee_lines)
190
+ output_lines.concat(includee_lines)
194
191
  end
195
- # Now review the markdown and include everything.
196
- markdown_lines.each_with_index do |markdown_line, line_index|
197
- match_data = markdown_line.match(INCLUDE_REGEXP)
198
- unless match_data
199
- output_lines.push(markdown_line)
200
- next
201
- end
202
- treatment = match_data[1]
203
- cited_includee_file_path = match_data[2]
204
- new_inclusion = Inclusion.new(
205
- markdown_line.chomp,
206
- includer_file_path,
207
- line_index + 1,
208
- cited_includee_file_path,
209
- treatment
210
- )
211
- inclusions.include(
212
- new_inclusion,
213
- output_lines,
214
- self
215
- )
192
+ end
193
+
194
+ def add_inclusion_comments(treatment, includee_file_path, lines)
195
+ path_in_project = MarkdownHelper.path_in_project(includee_file_path)
196
+ unless pristine
197
+ comment = format(' >>>>>> BEGIN INCLUDED FILE (%s): SOURCE %s ', treatment, path_in_project)
198
+ lines.unshift(MarkdownHelper.comment(comment))
199
+ comment = format(' <<<<<< END INCLUDED FILE (%s): SOURCE %s ', treatment, path_in_project)
200
+ lines.push(MarkdownHelper.comment(comment))
216
201
  end
217
202
  end
218
203
 
204
+ def parse_include(line)
205
+ match_data = line.match(INCLUDE_REGEXP)
206
+ return [nil, nil] unless match_data
207
+ treatment = match_data[1]
208
+ includee_file_path = match_data[2]
209
+ [treatment, includee_file_path]
210
+ end
211
+
212
+ def self.path_in_project(file_path)
213
+ abs_path = File.absolute_path(file_path)
214
+ abs_path.sub(self.git_clone_dir_path + '/', '')
215
+ end
216
+
217
+ def self.comment(text)
218
+ "<!--#{text}-->"
219
+ end
220
+
221
+ def self.pre(text)
222
+ "<pre>\n#{text}</pre>"
223
+ end
224
+
219
225
  def self.git_clone_dir_path
220
226
  git_dir = `git rev-parse --show-toplevel`.chomp
221
227
  unless $?.success?
@@ -229,157 +235,122 @@ EOT
229
235
  git_dir
230
236
  end
231
237
 
232
- def self.path_in_project(path)
233
- path.sub(MarkdownHelper.git_clone_dir_path + '/', '')
234
- end
238
+ class Heading
235
239
 
236
- class Inclusions
240
+ attr_accessor :level, :title
237
241
 
238
- attr_accessor :inclusions
242
+ def initialize(level, title)
243
+ self.level = level
244
+ self.title = title
245
+ end
239
246
 
240
- def initialize
241
- self.inclusions = []
247
+ def self.parse(line)
248
+ # Four leading spaces not allowed (but three are allowed).
249
+ return nil if line.start_with?(' ' * 4)
250
+ stripped_line = line.sub(/^ */, '')
251
+ # Now must begin with hash marks and space.
252
+ return nil unless stripped_line.match(/^#+ /)
253
+ hash_marks, title = stripped_line.split(' ', 2)
254
+ level = hash_marks.size
255
+ # Seventh level heading not allowed.
256
+ return nil if level > 6
257
+ self.new(level, title)
242
258
  end
243
259
 
244
- def include(
245
- new_inclusion,
246
- output_lines,
247
- markdown_helper
248
- )
249
- treatment = case new_inclusion.treatment
250
- when ':code_block'
251
- :code_block
252
- when ':markdown'
253
- :markdown
254
- when ':verbatim'
255
- message = "Treatment ':verbatim' is deprecated; please use treatment ':markdown'."
256
- warn(message)
257
- :markdown
258
- when ':comment'
259
- :comment
260
- when ':pre'
261
- :pre
262
- else
263
- new_inclusion.treatment
264
- end
265
- if treatment == :markdown
266
- check_circularity(new_inclusion)
267
- end
268
- includee_path_in_project = MarkdownHelper.path_in_project(new_inclusion.absolute_includee_file_path)
269
- output_lines.push(MarkdownHelper.comment(" >>>>>> BEGIN INCLUDED FILE (#{treatment}): SOURCE #{includee_path_in_project} ")) unless markdown_helper.pristine
270
- begin
271
- include_lines = File.readlines(new_inclusion.absolute_includee_file_path)
272
- rescue => e
273
- inclusions.push(new_inclusion)
274
- message = [
275
- MISSING_INCLUDEE_EXCEPTION_LABEL,
276
- backtrace_inclusions,
277
- ].join("\n")
278
- e = UnreadableInputError.new(message)
279
- e.set_backtrace([])
280
- raise e
281
- end
282
- last_line = include_lines.last
283
- unless last_line && last_line.match("\n")
284
- message = "Warning: Included file has no trailing newline: #{new_inclusion.cited_includee_file_path}"
285
- warn(message)
286
- end
287
- case treatment
288
- when :markdown
289
- # Pass through unadorned, but honor any nested includes.
290
- inclusions.push(new_inclusion)
291
- markdown_helper.send(:include_files, new_inclusion.absolute_includee_file_path, include_lines, output_lines, self)
292
- inclusions.pop
293
- when :comment
294
- output_lines.push(MarkdownHelper.comment(include_lines.join('')))
295
- when :pre
296
- output_lines.push("<pre>\n")
297
- output_lines.push(include_lines.join(''))
298
- output_lines.push("</pre>\n")
299
- else
300
- # Use the file name as a label.
301
- file_name_line = format("```%s```:\n", File.basename(new_inclusion.cited_includee_file_path))
302
- output_lines.push(file_name_line)
303
- # Put into code block.
304
- language = treatment == :code_block ? '' : treatment
305
- output_lines.push("```#{language}\n")
306
- output_lines.push(*include_lines)
307
- output_lines.push("```\n")
308
- end
309
- output_lines.push(MarkdownHelper.comment(" <<<<<< END INCLUDED FILE (#{treatment}): SOURCE #{includee_path_in_project} ")) unless markdown_helper.pristine
260
+
261
+ def link
262
+ remove_regexp = /[\#\(\)\[\]\{\}\.\?\+\*\`\"\']+/
263
+ to_hyphen_regexp = /\W+/
264
+ anchor = title.
265
+ gsub(remove_regexp, '').
266
+ gsub(to_hyphen_regexp, '-').
267
+ downcase
268
+ "[#{title}](##{anchor})"
310
269
  end
311
270
 
312
- CIRCULAR_EXCEPTION_LABEL = 'Includes are circular:'
313
- UNREADABLE_INPUT_EXCEPTION_LABEL = 'Could not read input file.'
314
- UNWRITABLE_OUTPUT_EXCEPTION_LABEL = 'Could not write output file.'
315
- MISSING_INCLUDEE_EXCEPTION_LABEL = 'Could not read include file,'
316
- LEVEL_LABEL = ' Level'
317
- BACKTRACE_LABEL = ' Backtrace (innermost include first):'
318
-
319
- def check_circularity(new_inclusion)
320
- previous_inclusions = inclusions.collect {|x| x.real_includee_file_path}
321
- previously_included = previous_inclusions.include?(new_inclusion.real_includee_file_path)
322
- if previously_included
323
- inclusions.push(new_inclusion)
324
- message = [
325
- CIRCULAR_EXCEPTION_LABEL,
326
- backtrace_inclusions,
327
- ].join("\n")
328
- e = MarkdownHelper::CircularIncludeError.new(message)
329
- e.set_backtrace([])
330
- raise e
331
- end
271
+ end
272
+
273
+ def check_circularity(inclusion)
274
+ included_file_paths = @inclusions.collect { |x| x.includee_real_file_path}
275
+ previously_included = included_file_paths.include?(inclusion.includee_real_file_path)
276
+ if previously_included
277
+ @inclusions.push(inclusion)
278
+ message = [
279
+ 'Includes are circular:',
280
+ MarkdownHelper.backtrace_inclusions(@inclusions),
281
+ ].join("\n")
282
+ e = MarkdownHelper::CircularIncludeError.new(message)
283
+ e.set_backtrace([])
284
+ raise e
332
285
  end
286
+ end
333
287
 
334
- def backtrace_inclusions
335
- lines = [BACKTRACE_LABEL]
336
- inclusions.reverse.each_with_index do |inclusion, i|
337
- lines.push("#{LEVEL_LABEL} #{i}:")
338
- level_lines = inclusion.to_lines(indentation_level = 3)
339
- lines.push(*level_lines)
340
- end
341
- lines.join("\n")
288
+ def check_includee(inclusion)
289
+ unless File.readable?(inclusion.includee_absolute_file_path)
290
+ @inclusions.push(inclusion)
291
+ message = [
292
+ 'Could not read includee file:',
293
+ MarkdownHelper.backtrace_inclusions(@inclusions),
294
+ ].join("\n")
295
+ e = MarkdownHelper::UnreadableIncludeeError.new(message)
296
+ e.set_backtrace([])
297
+ raise e
342
298
  end
343
299
 
344
300
  end
345
301
 
346
- class Inclusion
302
+ def self.backtrace_inclusions(inclusions)
303
+ lines = [' Backtrace (innermost include first):']
304
+ inclusions.reverse.each_with_index do |inclusion, i|
305
+ lines.push("#{' Level'} #{i}:")
306
+ level_lines = inclusion.to_lines(indentation_level = 3)
307
+ lines.push(*level_lines)
308
+ end
309
+ lines.join("\n")
310
+ end
347
311
 
348
- LINE_COUNT = 5
312
+ class Inclusion
349
313
 
350
314
  attr_accessor \
351
315
  :includer_file_path,
316
+ :includer_absolute_file_path,
317
+ :include_pragma,
318
+ :treatment,
352
319
  :includer_line_number,
353
- :include_description,
354
- :absolute_includee_file_path,
355
320
  :cited_includee_file_path,
356
- :treatment,
357
- :page_toc_title,
358
- :page_toc_line
321
+ :includee_absolute_file_path
359
322
 
360
323
  def initialize(
361
- include_description,
362
324
  includer_file_path,
325
+ include_pragma,
363
326
  includer_line_number,
327
+ treatment,
364
328
  cited_includee_file_path,
365
- treatment
366
- )
367
- self.include_description = include_description
329
+ inclusions
330
+ )
368
331
  self.includer_file_path = includer_file_path
332
+ self.include_pragma = include_pragma
369
333
  self.includer_line_number = includer_line_number
370
- self.cited_includee_file_path = cited_includee_file_path
371
- self.absolute_includee_file_path = absolute_includee_file_path
372
334
  self.treatment = treatment
373
- self.absolute_includee_file_path = File.absolute_path(File.join(
335
+ self.cited_includee_file_path = cited_includee_file_path
336
+
337
+ self.includer_absolute_file_path = File.absolute_path(includer_file_path)
338
+ unless File.exist?(self.includer_absolute_file_path)
339
+ fail self.includer_absolute_file_path
340
+ end
341
+
342
+ self.includee_absolute_file_path = File.absolute_path(File.join(
374
343
  File.dirname(includer_file_path),
375
344
  cited_includee_file_path,
376
- ))
345
+ ))
346
+ end
347
+
348
+ def includer_real_file_path
349
+ Pathname.new(includer_absolute_file_path).realpath.to_s
377
350
  end
378
351
 
379
- def real_includee_file_path
380
- # Would raise exception unless exists.
381
- return nil unless File.exist?(absolute_includee_file_path)
382
- Pathname.new(absolute_includee_file_path).realpath.to_s
352
+ def includee_real_file_path
353
+ Pathname.new(includee_absolute_file_path).realpath.to_s
383
354
  end
384
355
 
385
356
  def indentation(level)
@@ -388,11 +359,11 @@ EOT
388
359
 
389
360
  def to_lines(indentation_level)
390
361
  relative_inluder_file_path = MarkdownHelper.path_in_project(includer_file_path)
391
- relative_inludee_file_path = MarkdownHelper.path_in_project(absolute_includee_file_path)
362
+ relative_inludee_file_path = MarkdownHelper.path_in_project(includee_absolute_file_path)
392
363
  text = <<EOT
393
364
  #{indentation(indentation_level)}Includer:
394
365
  #{indentation(indentation_level+1)}Location: #{relative_inluder_file_path}:#{includer_line_number}
395
- #{indentation(indentation_level+1)}Include description: #{include_description}
366
+ #{indentation(indentation_level+1)}Include pragma: #{include_pragma}
396
367
  #{indentation(indentation_level)}Includee:
397
368
  #{indentation(indentation_level+1)}File path: #{relative_inludee_file_path}
398
369
  EOT
@@ -402,4 +373,3 @@ EOT
402
373
  end
403
374
 
404
375
  end
405
-