giblish 0.3.1 → 0.4.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.
@@ -53,7 +53,7 @@ module Giblish
53
53
  doc.src_file.to_s.eql? src_file
54
54
  end
55
55
  raise "Inconsistent docs when building graph!! found no match for #{src_file}" if d.nil?
56
- result[d] = id_array
56
+ result[d] = id_array if d.converted
57
57
  end
58
58
  result
59
59
  end
@@ -10,17 +10,20 @@ module Giblish
10
10
  # Base class with common functionality for all index builders
11
11
  class BasicIndexBuilder
12
12
  # set up the basic index building info
13
- def initialize(processed_docs, path_manager, handle_docid = false)
13
+ def initialize(processed_docs, converter, path_manager, handle_docid = false)
14
14
  @paths = path_manager
15
15
  @nof_missing_titles = 0
16
16
  @processed_docs = processed_docs
17
+ @converter = converter
17
18
  @src_str = ""
18
19
  @manage_docid = handle_docid
19
20
  end
20
21
 
21
- def source(dep_graph_exists = false)
22
+ def source(dep_graph_exists = false, make_searchable = false)
22
23
  <<~DOC_STR
23
- #{generate_header}
24
+ #{generate_title_and_header}
25
+ #{generate_date_info}
26
+ #{add_search_box if make_searchable}
24
27
  #{generate_tree(dep_graph_exists)}
25
28
  #{generate_details}
26
29
  #{generate_footer}
@@ -28,28 +31,60 @@ module Giblish
28
31
  end
29
32
 
30
33
  protected
34
+ def generate_title_and_header
35
+ <<~DOC_HEADER
36
+ = Document index
37
+ from #{@paths.src_root_abs}
38
+ :icons: font
39
+
40
+ DOC_HEADER
41
+ end
42
+
31
43
  # return the adoc string for displaying the source file
32
44
  def display_source_file(doc_info)
33
45
  <<~SRC_FILE_TXT
34
46
  Source file::
35
- #{doc_info.srcFile_utf8}
47
+ #{doc_info.src_file}
36
48
 
37
49
  SRC_FILE_TXT
38
50
  end
39
51
 
40
- def generate_header
52
+ def generate_date_info
41
53
  t = Time.now
42
54
  <<~DOC_HEADER
43
- = Document index
44
- from #{@paths.src_root_abs}
45
-
46
- Generated by Giblish at::
47
-
48
- #{t.strftime('%Y-%m-%d %H:%M')}
49
-
55
+ *Generated by Giblish at:* #{t.strftime('%Y-%m-%d %H:%M')}
50
56
  DOC_HEADER
51
57
  end
52
58
 
59
+ def add_search_box
60
+ # TODO: Fix the hard-coded path
61
+ cgi_path = "/cgi-bin/giblish-search.cgi"
62
+ css = @converter.converter_options[:attributes]["stylesheet"]
63
+
64
+ # button with magnifying glass icon (not working when deployed)
65
+ # <button id="search" type="submit"><i class="fa fa-search"></i></button>
66
+ <<~SEARCH_INFO
67
+ ++++
68
+ <form class="example" action="#{cgi_path}" style="margin:20px 0px 20px 0px;max-width:380px">
69
+ Search all documents:
70
+ <input id="searchphrase" type="text" placeholder="Search.." name="searchphrase"/>
71
+ <button id="search" type="submit">Search</button>
72
+ <br>
73
+
74
+ <input id="ignorecase" type="checkbox" value="true" name="ignorecase" checked/>
75
+ <label for="ignorecase">Ignore Case</label>
76
+ &nbsp;&nbsp;
77
+ <input id="useregexp" type="checkbox" value="true" name="regexp"/>
78
+ <label for="useregexp">Use Regexp</label>
79
+
80
+ <input type="hidden" name="topdir" value="#{@paths.dst_root_abs.to_s}"</input>
81
+ <input type="hidden" name="reltop" value="#{@paths.reldir_from_web_root(@paths.dst_root_abs)}"</input>
82
+ <input type="hidden" name="css" value="#{css}"</input>
83
+ </form>
84
+ ++++
85
+
86
+ SEARCH_INFO
87
+ end
53
88
  def get_docid_statistics
54
89
  largest = ""
55
90
  clash = []
@@ -91,8 +126,7 @@ module Giblish
91
126
 
92
127
  if @manage_docid
93
128
  <<~DOC_ID_INFO
94
- Document id numbers::
95
- The generation of this repository uses document id numbers. #{docid_info_str} #{dep_graph_str}
129
+ *Document id numbers:* #{docid_info_str} #{dep_graph_str}
96
130
 
97
131
  #{docid_warn_str}
98
132
 
@@ -105,12 +139,6 @@ module Giblish
105
139
  def generate_tree(dep_graph_exists)
106
140
  # output tree intro
107
141
  tree_string = <<~DOC_HEADER
108
- == Document Overview
109
-
110
- _Click on the title to open the document or on `details` to see more
111
- info about the document. A `(warn)` label indicates that there were
112
- warnings while converting the document from its asciidoc format._
113
-
114
142
  #{generate_doc_id_info dep_graph_exists}
115
143
 
116
144
  [subs=\"normal\"]
@@ -172,8 +200,8 @@ module Giblish
172
200
  doc_info.title
173
201
  end
174
202
 
175
- [title, "<<#{doc_info.rel_path}#,#{title}>>".encode("utf-8"),
176
- "<<#{Giblish.to_valid_id(doc_info.title)},details>>\n".encode("utf-8")]
203
+ [title, "<<#{doc_info.rel_path}#,#{title}>>",
204
+ "<<#{Giblish.to_valid_id(doc_info.title)},details>>\n"]
177
205
  end
178
206
 
179
207
  # Generate an adoc string that will display as
@@ -206,7 +234,7 @@ module Giblish
206
234
  tree_entry_converted prefix_str, d
207
235
  else
208
236
  # no converted file exists, show what we know
209
- "#{prefix_str} FAIL: #{d.srcFile_utf8} <<#{d.srcFile_utf8},details>>\n"
237
+ "#{prefix_str} FAIL: #{d.src_file} <<#{d.src_file},details>>\n"
210
238
  end
211
239
  end
212
240
 
@@ -217,7 +245,7 @@ module Giblish
217
245
 
218
246
  def generate_detail_fail(d)
219
247
  <<~FAIL_INFO
220
- === #{d.srcFile_utf8}
248
+ === #{d.src_file}
221
249
 
222
250
  #{display_source_file(d)}
223
251
 
@@ -288,16 +316,16 @@ module Giblish
288
316
 
289
317
  # A simple index generator that shows a table with the generated documents
290
318
  class SimpleIndexBuilder < BasicIndexBuilder
291
- def initialize(processed_docs, path_manager, manage_docid = false)
292
- super processed_docs, path_manager, manage_docid
319
+ def initialize(processed_docs, converter, path_manager, manage_docid = false)
320
+ super processed_docs, converter, path_manager, manage_docid
293
321
  end
294
322
  end
295
323
 
296
324
  # Builds an index of the generated documents and includes some git metadata
297
325
  # from the repository
298
326
  class GitRepoIndexBuilder < BasicIndexBuilder
299
- def initialize(processed_docs, path_manager, manage_docid, git_repo_root)
300
- super processed_docs, path_manager, manage_docid
327
+ def initialize(processed_docs, converter, path_manager, manage_docid, git_repo_root)
328
+ super processed_docs, converter, path_manager, manage_docid
301
329
 
302
330
  # no repo root given...
303
331
  return unless git_repo_root
@@ -328,14 +356,13 @@ module Giblish
328
356
  end
329
357
 
330
358
 
331
- def generate_header
359
+ def generate_title_and_header
332
360
  t = Time.now
333
361
  <<~DOC_HEADER
334
362
  = Document index
335
363
  #{@git_repo.current_branch}
336
364
 
337
- Generated by Giblish at::
338
- #{t.strftime('%Y-%m-%d %H:%M')}
365
+ :icons:
339
366
 
340
367
  DOC_HEADER
341
368
  end
@@ -69,6 +69,28 @@ class CmdLineParser
69
69
  generate the documents and use the collected
70
70
  doc ids to resolve relative paths between the
71
71
  generated documents
72
+ -m --make-searchable (only supported for html generation)
73
+ take steps to make it possible to
74
+ search the published content via a cgi-script. This
75
+ flag will do the following:
76
+ 1. index all headings in all source files and store
77
+ the result in a JSON file
78
+ 2. copy the JSON file and all source (adoc) files to
79
+ a 'search_assets' folder in the top-level dir of
80
+ the destination.
81
+ 3. add html code that displays a search field in the
82
+ index page that will try to call the cgi-script
83
+ 'giblish-search' when the user inputs some text.
84
+ To actually provide search functionality for a user, you
85
+ need to provide the cgi-script and configure your web-server
86
+ to invoke it when needed. NOTE: The generated search box cgi
87
+ is currently hard-coded to look for the cgi script at the URL:
88
+ http://<your-web-domain>/cgi-bin/giblish-search.cgi
89
+ E.g.
90
+ http://example.com/cgi-bin/giblish-search.cgi
91
+ An implementation of the giblish-search cgi-script is found
92
+ within the lib folder of this gem, you can copy that to your
93
+ cgi-bin dir in your webserver and rename it from .rb to .cgi
72
94
  --log-level set the log level explicitly. Must be one of
73
95
  debug, info (default), warn, error or fatal.
74
96
  ENDHELP
@@ -139,6 +161,7 @@ ENDHELP
139
161
  suppressBuildRef: false,
140
162
  localRepoOnly: false,
141
163
  resolveDocid: false,
164
+ make_searchable: false,
142
165
  webRoot: false
143
166
  }
144
167
 
@@ -163,6 +186,7 @@ ENDHELP
163
186
  when "-t", "--git-tags" then next_arg = :gitTagRegexp
164
187
  when "-c", "--local-only" then @args[:localRepoOnly] = true
165
188
  when "-d", "--resolve-docid" then @args[:resolveDocid] = true
189
+ when "-m", "--make-searchable" then @args[:make_searchable] = true
166
190
  when "-s", "--style" then next_arg = :userStyle
167
191
  when "-w", "--web-root" then next_arg = :webRoot
168
192
  when "--log-level" then next_arg = :logLevel
@@ -181,6 +205,9 @@ ENDHELP
181
205
  if !@args[:resourceDir] && @args[:userStyle]
182
206
  puts "Error: The given style would not be used since no resource dir "\
183
207
  "was specified (-s specified without -r)"
208
+ elsif @args[:make_searchable] && @args[:format] != "html"
209
+ puts "Error: The --make-searchable option is only supported for "\
210
+ "html rendering"
184
211
  else
185
212
  return
186
213
  end
@@ -6,6 +6,7 @@ require "pathname"
6
6
  require_relative "buildindex"
7
7
  require_relative "docconverter"
8
8
  require_relative "docid"
9
+ require_relative "indexheadings"
9
10
  require_relative "docinfo"
10
11
  require_relative "buildgraph"
11
12
 
@@ -27,10 +28,12 @@ module Giblish
27
28
  @paths = Giblish::PathManager.new(
28
29
  @options[:srcDirRoot],
29
30
  @options[:dstDirRoot],
30
- @options[:resourceDir]
31
+ @options[:resourceDir],
32
+ @options[:webRoot]
31
33
  )
32
34
  @processed_docs = []
33
35
  @converter = converter_factory
36
+ @search_assets_path = @paths.dst_root_abs.realpath.join("search_assets")
34
37
  end
35
38
 
36
39
  def convert
@@ -38,6 +41,9 @@ module Giblish
38
41
  # valid references to adoc files
39
42
  manage_doc_ids if @options[:resolveDocid]
40
43
 
44
+ # register add-on for handling searchability
45
+ manage_searchability if @options[:make_searchable]
46
+
41
47
  # traverse the src file tree and convert all files deemed as
42
48
  # adoc files
43
49
  Find.find(@paths.src_root_abs) do |path|
@@ -45,6 +51,9 @@ module Giblish
45
51
  to_asciidoc(p) if adocfile? p
46
52
  end if @paths.src_root_abs.directory?
47
53
 
54
+ # create necessary search assets if needed
55
+ create_search_assets if @options[:make_searchable]
56
+
48
57
  # check if we shall build index or not
49
58
  return if @options[:suppressBuildRef]
50
59
 
@@ -64,7 +73,7 @@ module Giblish
64
73
 
65
74
  # build a reference index
66
75
  ib = index_factory
67
- @converter.convert_str ib.source(dep_graph_exist), @paths.dst_root_abs, "index"
76
+ @converter.convert_str ib.source(dep_graph_exist,@options[:make_searchable]), @paths.dst_root_abs, "index"
68
77
 
69
78
  # clean up cached files and adoc resources
70
79
  remove_diagram_temps if dep_graph_exist
@@ -77,7 +86,7 @@ module Giblish
77
86
  # user options
78
87
  def index_factory
79
88
  raise "Internal logic error!" if @options[:suppressBuildRef]
80
- SimpleIndexBuilder.new(@processed_docs, @paths,
89
+ SimpleIndexBuilder.new(@processed_docs, @converter, @paths,
81
90
  @options[:resolveDocid])
82
91
  end
83
92
 
@@ -112,7 +121,7 @@ module Giblish
112
121
 
113
122
  # the only info we have is the source file name
114
123
  info.converted = false
115
- info.src_file = filepath
124
+ info.src_file = filepath.to_s
116
125
  info.error_msg = exception.message
117
126
 
118
127
  @processed_docs << info
@@ -121,6 +130,11 @@ module Giblish
121
130
 
122
131
  private
123
132
 
133
+ def create_search_asset_dir
134
+ Dir.exist?(@search_assets_path) || FileUtils.mkdir_p(@search_assets_path.to_s)
135
+ @search_assets_path
136
+ end
137
+
124
138
  # remove cache dir and svg image created by asciidoctor-diagram
125
139
  # when creating the document dependency graph
126
140
  def remove_diagram_temps
@@ -165,12 +179,57 @@ module Giblish
165
179
  return !ir.match(fs).nil?
166
180
  end
167
181
 
182
+ def manage_searchability
183
+ # register the extension
184
+ Giblish.register_index_heading_extension
185
+
186
+ # make sure we start from a clean slate
187
+ IndexHeadings.clear_index
188
+ end
189
+
190
+ # top_dir
191
+ # |- web_assets
192
+ # |- branch_1_top_dir
193
+ # | |- index.html
194
+ # | |- file1.html
195
+ # | |- dir_1
196
+ # | | |- file2.html
197
+ # |- search_assets
198
+ # | |- branch_1
199
+ # | |- heading_index.json
200
+ # | |- file1.adoc
201
+ # | |- dir_1
202
+ # | | |- file2.html
203
+ # | |- ...
204
+ # | |- branch_2
205
+ # | | ...
206
+ # |- branch_2_top_dir
207
+ # | ...
208
+ def create_search_assets
209
+ # get the proper dir for the search assets
210
+ assets_dir = create_search_asset_dir
211
+
212
+ # store the JSON file
213
+ IndexHeadings.serialize assets_dir, @paths.src_root_abs
214
+
215
+ # traverse the src file tree and copy all published adoc files
216
+ # to the search_assets dir
217
+ Find.find(@paths.src_root_abs) do |path|
218
+ p = Pathname.new(path)
219
+ next unless adocfile? p
220
+
221
+ dst_dir = assets_dir.join(@paths.reldir_from_src_root(p))
222
+ FileUtils.mkdir_p(dst_dir)
223
+ FileUtils.cp(p.to_s, dst_dir)
224
+ end if @paths.src_root_abs.directory?
225
+ end
226
+
168
227
  # Register the asciidoctor extension that handles doc ids and traverse
169
228
  # the source tree to collect all :docid: attributes found in document
170
229
  # headers.
171
230
  def manage_doc_ids
172
231
  # Register the docid preprocessor hook
173
- Giblish.register_extensions
232
+ Giblish.register_docid_extension
174
233
 
175
234
  # Make sure that no prior docid's are hangning around
176
235
  DocidCollector.clear_cache
@@ -218,7 +277,7 @@ module Giblish
218
277
  protected
219
278
 
220
279
  def index_factory
221
- GitRepoIndexBuilder.new(@processed_docs, @paths,
280
+ GitRepoIndexBuilder.new(@processed_docs, @converter, @paths,
222
281
  @options[:resolveDocid], @options[:gitRepoRoot])
223
282
  end
224
283
 
@@ -305,7 +364,7 @@ module Giblish
305
364
  # Update needed base class members before converting a new checkout
306
365
  @processed_docs = []
307
366
  @paths.dst_root_abs = @master_paths.dst_root_abs.realpath.join(dir_name)
308
- # @converter.paths = @paths
367
+ @search_assets_path = @master_paths.dst_root_abs.realpath.join("search_assets").join(dir_name)
309
368
 
310
369
  # Parse and convert docs using given args
311
370
  Giblog.logger.info {"Convert docs into dir #{@paths.dst_root_abs}"}
@@ -52,7 +52,7 @@ module Giblish
52
52
  # - does not contain any blank line
53
53
  def parse_file(path)
54
54
  Giblog.logger.debug { "parsing file #{path} for docid..." }
55
- process_header_lines(path) do |line|
55
+ Giblish.process_header_lines_from_file(path) do |line|
56
56
  m = /^:docid: +(.*)$/.match(line)
57
57
  if m
58
58
  # There is a docid defined, cache the path and doc id
@@ -111,30 +111,6 @@ module Giblish
111
111
 
112
112
  private
113
113
 
114
- # Helper method that provides the user with a way of processing only the
115
- # lines within the asciidoc header block.
116
- # The user must return nil to get the next line.
117
- #
118
- # ex:
119
- # process_header_lines(file_path) do |line|
120
- # if line == "Quack!"
121
- # puts "Donald!"
122
- # 1
123
- # else
124
- # nil
125
- # end
126
- # end
127
- def process_header_lines(path)
128
- state = "before_header"
129
- File.foreach(path) do |line|
130
- case state
131
- when "before_header" then (state = "in_header" if line =~ /^=+.*$/)
132
- when "in_header" then (state = "done" if line =~ /^\s*$/ || yield(line))
133
- when "done" then break
134
- end
135
- end
136
- end
137
-
138
114
  # Helper method to shorten calls to docid_cache from instance methods
139
115
  def docid_cache
140
116
  self.class.docid_cache
@@ -203,10 +179,10 @@ module Giblish
203
179
 
204
180
  # Helper method to register the docid preprocessor extension with
205
181
  # the asciidoctor engine.
206
- def register_extensions
182
+ def register_docid_extension
207
183
  Asciidoctor::Extensions.register do
208
184
  preprocessor DocidCollector
209
185
  end
210
186
  end
211
- module_function :register_extensions
187
+ module_function :register_docid_extension
212
188
  end
@@ -12,29 +12,44 @@ module Giblish
12
12
  end
13
13
 
14
14
  attr_accessor :converted
15
- attr_accessor :title
16
15
  attr_accessor :doc_id
17
16
  attr_accessor :purpose_str
18
17
  attr_accessor :status
19
18
  attr_accessor :history
20
19
  attr_accessor :error_msg
21
20
  attr_accessor :stderr
22
- # these two members can have encoding issues when
23
- # running in a mixed Windows/Linux setting.
24
- # that is why the explicit utf-8 read methods are
25
- # provided.
26
- attr_accessor :rel_path
27
- attr_accessor :src_file
28
21
 
29
- def relPath_utf8
30
- return nil if @rel_path.nil?
31
- @rel_path.to_s.encode("utf-8")
22
+ # these members can have encoding issues when
23
+ # running in a mixed Windows/Linux setting.
24
+ # that is why we explicitly encodes them when
25
+ # writing to them
26
+ def title
27
+ @title
32
28
  end
33
-
34
- def srcFile_utf8
35
- return nil if @src_file.nil?
36
- @src_file.to_s.encode("utf-8")
29
+ def title=(rhs)
30
+ @title = rhs.nil? ? nil : rhs.encode("utf-8")
31
+ end
32
+ def rel_path
33
+ @rel_path
37
34
  end
35
+ # attr_accessor :rel_path
36
+ def src_file
37
+ @src_file
38
+ end
39
+ def src_file=(rhs)
40
+ @src_file = rhs.nil? ? nil : rhs.encode("utf-8")
41
+ end
42
+ # attr_accessor :src_file
43
+
44
+ # def relPath_utf8
45
+ # return nil if @rel_path.nil?
46
+ # @rel_path.to_s.encode("utf-8")
47
+ # end
48
+ #
49
+ # def srcFile_utf8
50
+ # return nil if @src_file.nil?
51
+ # @src_file.to_s.encode("utf-8")
52
+ # end
38
53
 
39
54
  def initialize(adoc: nil, dst_root_abs: nil, adoc_stderr: "")
40
55
  @src_file = nil
@@ -48,14 +63,14 @@ module Giblish
48
63
 
49
64
  # fill in doc meta data
50
65
  d_attr = adoc.attributes
66
+ self.src_file=(d_attr["docfile"])
67
+ self.title=(adoc.doctitle)
51
68
  @doc_id = d_attr["docid"]
52
- @src_file = d_attr["docfile"]
53
- @title = adoc.doctitle
54
69
  return if dst_root_abs.nil?
55
70
 
56
71
  # Get the relative path beneath the root dir to the doc
57
72
  @rel_path = Pathname.new(
58
- "#{d_attr['outdir']}/#{d_attr['docname']}#{d_attr['docfilesuffix']}"
73
+ "#{d_attr['outdir']}/#{d_attr['docname']}#{d_attr['docfilesuffix']}".encode("utf-8")
59
74
  ).relative_path_from(dst_root_abs)
60
75
  end
61
76