giblish 0.5.2 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d917c8b6c513f7759aecbbdb5a93a7cb13cb5774d66ccf0d602a615248723f76
4
- data.tar.gz: b94be771b19dd5890e238ffc0ee0ee5af361919c0e526d63ac4f380b4f6698a0
3
+ metadata.gz: 70c09507979ec9eacf59cfcb8405c929b35b7c24882db0099d4493c18439b754
4
+ data.tar.gz: e707817cee1413bbc9fd28a04ac54a1f5147176ef01070e189096a387620a0e9
5
5
  SHA512:
6
- metadata.gz: 4c9f6b75a6266c65baf0e7876016139703b7b46677fea2dcee54b9ad95b23c04756c8b9383398cdd8055c91e78ea3d275c7968eeabf1154478a44b76faf6c27c
7
- data.tar.gz: c7cb03e7fe95cdf3a13a74c36f0d5efbb06e49828ff04db05b5d231f098bb411ab34584067e03b7a3b93c025224d3d93ccd13366e951fe93826cfdafeaae1bd9
6
+ metadata.gz: 54fbe435b49ec492065b3ba9f9c6bab31d08e56f5843937b36a4bd8c0bd4253ec6bacecc5f2cc530a1ebb188e8289c498fd68d8a7a6951b7b3831d2e7956bffe
7
+ data.tar.gz: 83eb9c41b4437f29e4e779ca7782bc464d42daffd97e0d36ef8482f7155c2ce9364097b97745d700773368c419354d086d2b767e08d1758f9c7ddb11dfdb6aca
@@ -174,3 +174,82 @@ cgi-script must be located at http://your_web_site.com/cgi-bin/giblish-search.cg
174
174
  and this gem provides a default implementation that you can copy from the .../lib
175
175
  folder to the correct destination.
176
176
  ====
177
+
178
+ == Text search implementation
179
+
180
+ The text search enables a user to search for a text string and receive matching
181
+ sections in the documentation tree.
182
+
183
+ To make this work, three things are needed
184
+
185
+ . the source text of all adoc files together with a JSON file that maps sections to
186
+ their line numbers. This 'search data' is collected by giblish when it generates the
187
+ html files to the destination directory. The JSON file and all adoc source files
188
+ are copied to a well-known place in the destination tree (see below).
189
+ . an html form somewhere in the rendered pages that receives the user input (text string
190
+ and other parameters) to start a search.
191
+ ** giblish injects such an html form in the generated index page when the user
192
+ specifies the '-m' switch.
193
+ . a server side script that
194
+ ** receive a text string to search for
195
+ ** parses the search data for matches to the text string
196
+ ** presents the result to the user
197
+
198
+ This gem contains an example implementation of a server side script. It is implemented
199
+ in ruby and uses 'grep' to parse the search data. It then generates a result page where
200
+ each matching section is shown and when clicked, will navigate the user to that section
201
+ in the corresponding document.
202
+
203
+ === Search data and html form parameters
204
+
205
+ giblish will copy all search data to a 'search_assets' dir just under the destination
206
+ root. This is illustrated below.
207
+
208
+ .When rendering documents from a git branch
209
+ dst_root_dir
210
+ |- branch_1_top_dir
211
+ | |- index.html
212
+ | |- file_1.html
213
+ | |- dir_1
214
+ | | |- file2.html
215
+ |- branch_2_top_dir
216
+ |- branch_x_...
217
+ |- web_assets
218
+ |- search_assets
219
+ | |- branch_1_top_dir
220
+ | |- heading_index.json
221
+ | |- file1.adoc
222
+ | |- dir_1
223
+ | | |- file2.adoc
224
+ | |- ...
225
+ | |- branch_2_top_dir
226
+ | | ...
227
+
228
+ assume that the file tree looks like this when not
229
+ rendering a git branch:
230
+
231
+ .When rendering documents not in a git branch
232
+ dst_root_dir
233
+ |- index.html
234
+ |- file_1.html
235
+ |- dir_1
236
+ | |- file2.html
237
+ |...
238
+ |- web_assets (only if a custom stylesheet is used...)
239
+ |- search_assets
240
+ | |- heading_index.json
241
+ | |- file1.adoc
242
+ | |- dir_1
243
+ | | |- file2.adoc
244
+ | |- ...
245
+
246
+ The parameters that is sent to the cgi script via the html form generated
247
+ by giblish are:
248
+
249
+ * searchphrase -> the text string to search for
250
+ * ignorecase -> wether to ignore case or not
251
+ * useregexp -> wether the searchphrase above is treated as a regexp or
252
+ ordinary text
253
+ * css -> the css file name to use when styling the search result page
254
+ * topdir -> the absolute path to the root of the generated document tree
255
+ * reltop -> <clarify this>
data/Rakefile CHANGED
@@ -13,6 +13,24 @@ Rake::TestTask.new(:current) do |t|
13
13
  t.test_files = FileList["test/**/index_heading_test.rb"]
14
14
  end
15
15
 
16
+ Rake::TestTask.new(:paths) do |t|
17
+ t.libs << "test"
18
+ t.libs << "lib"
19
+ t.test_files = FileList["test/**/pathmanager_test.rb"]
20
+ end
21
+
22
+ Rake::TestTask.new(:graph) do |t|
23
+ t.libs << "test"
24
+ t.libs << "lib"
25
+ t.test_files = FileList["test/**/depgraph_test.rb"]
26
+ end
27
+
28
+ Rake::TestTask.new(:css) do |t|
29
+ t.libs << "test"
30
+ t.libs << "lib"
31
+ t.test_files = FileList["test/**/linkcss_test.rb"]
32
+ end
33
+
16
34
  Rake::TestTask.new(:sandbox) do |t|
17
35
  t.libs << "test"
18
36
  t.libs << "lib"
@@ -0,0 +1,18 @@
1
+ pipeline {
2
+ agent any
3
+ stages {
4
+ stage('Render html documentation') {
5
+ steps {
6
+ echo "workspace path: ${env.WORKSPACE}"
7
+ // render html versions of all docs found under the 'docs' subdir
8
+ // in the repo
9
+ sh "giblish -n -f html -w ${env.WORKSPACE} -s giblish -r docgen/resources docs gendocs"
10
+ }
11
+ }
12
+ // stage('Render pdf documentation') {
13
+ // steps {
14
+ // sh "giblish -n -f pdf -s vironova-theme -r scripts/adocgen/resources Documents/MiniTEM/third_party_software/ MiniTEM/Deployment/doc"
15
+ // }
16
+ // }
17
+ }
18
+ }
@@ -0,0 +1,24 @@
1
+ #!/bin/sh
2
+ #
3
+ # This hook script kicks-in after git has completed
4
+ # a push, it will thus never be able to abort a push.
5
+ #
6
+ # This hook will:
7
+ # - ping Jenkins to trigger any builds related to the
8
+ # git push
9
+
10
+ # let the user perfoming a git push know that we actually do something
11
+ echo "Start post-update"
12
+
13
+ # Hit Jenkins to initiate a Jenkins poll for which jobs that shall be started as
14
+ # consequence of a push to a specific git repo. The generic format for this is:
15
+ # curl <jenkins_url>/git/notifyCommit?url=<git repo url>
16
+ #
17
+ # If jenkins is accessible on http://jenkins.example.com:8080 and
18
+ # you want to initiate a poll for jobs associated with the giblish repository on
19
+ # github located at https://github.com/rillbert/giblish.git
20
+ # you would use the following:
21
+ curl http://jenkins.example.com:8080/git/notifyCommit?url=https://github.com/rillbert/giblish.git
22
+
23
+ # Tell user we're done
24
+ echo "Finished post-update"
@@ -0,0 +1,67 @@
1
+ = Setup web site powered by giblish
2
+ :imagesdir: setup_server_assets
3
+ :numbered:
4
+
5
+ == Purpose
6
+
7
+ To describe how to setup a web site with documents automatically generated from a git repo.
8
+
9
+ == Toolchain
10
+
11
+ * git
12
+ * giblish
13
+ * git server side hooks to kick-off the document rendering after a git push.
14
+ * a tool that can execute scripts after a git push. *Jenkins* is used in this instruction. Some advantages over calling giblish directly from a git hook:
15
+ ** the document rendering is asynchronous to the git push from the client.
16
+ ** the script executed by Jenkins (the 'pipeline' in Jenkis lingo) can be stored and versioned in the same git repo as the documents to be rendered.
17
+ * a web server to publish the rendered html documents.
18
+
19
+ === Sequence for rendering documents
20
+
21
+ The following image shows how the sequence from user commit to rendered documents.
22
+
23
+ image::Render Documents.png[]
24
+
25
+ === Sequence for viewing documents
26
+
27
+ This is just the standard way of accessing a web site. The html page served by the web server will be the latest generated html page.
28
+
29
+ image::View Documents.png[]
30
+
31
+ == Server requirements
32
+
33
+ The server that will render the documents need the following tools installed:
34
+
35
+ * git
36
+ * giblish
37
+
38
+ The server that runs Jenkins will (of course) need Jenkins installed.
39
+
40
+ === Setup server for both Jenkins and doc rendering on Ubuntu 16.04
41
+
42
+ The easiest setup is to use the same server to run Jenkins and to render the documents. For an Ubuntu 16.04 installation, you can install the needed tools as follows:
43
+
44
+ * install git `sudo apt install git`
45
+ * install Jenkins See https://www.digitalocean.com/community/tutorials/how-to-install-jenkins-on-ubuntu-16-04[this doc].
46
+ * install giblish `sudo gem install giblish`
47
+
48
+
49
+ == server side git hooks
50
+
51
+ git supports hooks in several parts of the sequence of getting changes ommitted and pushed to a remote repo. For details on git hooks see https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks[this doc]. See <<post-update-hook>> An example of a `post-update` hook that triggers Jenkins
52
+
53
+
54
+ [appendix]
55
+ [[post-update-hook]]
56
+ == post-update hook
57
+
58
+ Below is an example of a `post-update` hook that triggers Jenkins jobs after a push to a git repo. This hook should be installed on the server side git repository to trigger Jenkins builds
59
+
60
+ .Example of a git hook triggering Jenkins builds
61
+ ----
62
+ include::../docgen/scripts/githook_examples/post-update.example[]
63
+ ----
64
+
65
+ == Jenkins pipeline script
66
+
67
+ Below is a very basic example of a Jenkins pipeline that triggers giblish to render html and pdf documents located in a specific directory in a git repository.
@@ -38,11 +38,8 @@ Gem::Specification.new do |spec|
38
38
  # Usage: spec.add_runtime_dependency "[gem name]", [[version]]
39
39
  spec.add_runtime_dependency "asciidoctor", "~>2.0", ">= 2.0.10"
40
40
  spec.add_runtime_dependency "asciidoctor-diagram", ["~> 1.5"]
41
- spec.add_runtime_dependency "asciidoctor-pdf", [">= 1.5.0.alpha.18"]
41
+ spec.add_runtime_dependency "asciidoctor-pdf", [">= 1.5.0.beta.6"]
42
42
  spec.add_runtime_dependency "git", "~> 1.3"
43
43
  spec.add_runtime_dependency "rouge", "~> 3.3"
44
- # needed by asciidoctor-pdf, see instructions at
45
- # https://github.com/asciidoctor/asciidoctor-pdf/releases
46
- # spec.add_runtime_dependency "prawn-svg", "~> 0.27.1"
47
- spec.add_runtime_dependency "prawn-svg", "~> 0.29.1"
44
+ spec.add_runtime_dependency "prawn-svg", "~> 0.29.1"
48
45
  end
@@ -215,10 +215,7 @@ class SearchDocTree
215
215
  private
216
216
 
217
217
  def get_uri_top
218
- if @input_data[:gitbranch]
219
- return @input_data[:referer][0,@input_data[:referer].rindex('/')]
220
- end
221
- return @input_data[:referer].chomp('/')
218
+ return @input_data[:referer][0,@input_data[:referer].rindex('/')]
222
219
  end
223
220
 
224
221
  def wash_line line
@@ -239,6 +236,8 @@ class SearchDocTree
239
236
  # ...
240
237
  def format_search_adoc index,uri_top
241
238
  str = ""
239
+ # debug print referer...
240
+ # str << "uri_top: #{uri_top}\n"
242
241
  index.each do |file_info|
243
242
  filename = Pathname.new(file_info["filepath"]).basename
244
243
  str << "== #{file_info["title"]}\n\n"
@@ -313,7 +312,7 @@ def cgi_main cgi
313
312
  ignorecase: cgi.has_key?("ignorecase"),
314
313
  useregexp: cgi.has_key?("useregexp"),
315
314
  doc_root_abs: Pathname.new(cgi["topdir"]),
316
- referer_rel_top: Pathname.new("/#{cgi["reltop"]}"),
315
+ referer_rel_top: Pathname.new("#{cgi["reltop"]}"),
317
316
  referer: cgi.referer,
318
317
  uri_path: URI(cgi.referer).path,
319
318
  client_css: cgi["css"],
@@ -328,17 +327,16 @@ def cgi_main cgi
328
327
  #
329
328
  # if the source was rendered from a git branch, the paths
330
329
  # search_assets = <index_dir>/../search_assets/<branch_name>/
331
- # styles_dir = ../web_assets/css
330
+ # styles_top = ../web_assets/css
332
331
  #
333
332
  # and if not, the path is
334
333
  # search_assets = <index_dir>/search_assets
335
- # styles_dir = ./web_assets/css
334
+ # styles_top = /web_assets/css
335
+ # <link rel="stylesheet" href="/web_assets/css/virodoc.css">
336
336
  #
337
- # The styles dir shall be a relative path
338
337
  if input_data[:doc_root_abs].join("./search_assets").exist?
339
338
  # this is not from a git branch
340
339
  input_data[:search_top] = input_data[:doc_root_abs].join("./search_assets")
341
- # input_data[:styles_top] = Pathname.new(input_data[:uri_path]).join("./web_assets/css")
342
340
  input_data[:styles_top] = Pathname.new(input_data[:referer_rel_top]).join("web_assets/css")
343
341
  input_data[:gitbranch] = false
344
342
  elsif input_data[:doc_root_abs].join("../search_assets").exist?
@@ -350,21 +348,53 @@ def cgi_main cgi
350
348
  raise ScriptError, "Could not find search_assets dir!"
351
349
  end
352
350
 
353
- # use a relative stylesheet (same as the index page was rendered with)
354
- adoc_options = {
351
+ # Set some reasonable default attributes and options
352
+ adoc_attributes = {
355
353
  "data-uri" => 1,
356
- "linkcss" => 1,
357
- "stylesdir" => input_data[:styles_top].to_s,
358
- "stylesheet" => input_data[:client_css],
359
- "copycss!" => 1
360
354
  }
361
355
 
356
+ converter_options = {
357
+ backend: "html5",
358
+ # need this to let asciidoctor include the default css if user
359
+ # has not specified any css
360
+ safe: Asciidoctor::SafeMode::SAFE,
361
+ header_footer: true,
362
+ attributes: adoc_attributes
363
+ }
364
+
365
+ # use a relative stylesheet (same as the index page was rendered with)
366
+ # if the script has received input in the client_css form field
367
+ if !input_data[:client_css].nil? && !input_data[:client_css].empty?
368
+ css_path = if input_data[:styles_top].to_s[0] != '/'
369
+ "/" + input_data[:styles_top].to_s
370
+ else
371
+ input_data[:styles_top].to_s
372
+ end
373
+ adoc_attributes.merge!({
374
+ "linkcss" => 1,
375
+ "stylesdir" => css_path,
376
+ "stylesheet" => input_data[:client_css],
377
+ "copycss!" => 1
378
+ })
379
+ end
380
+
362
381
  # search the docs and render html
363
382
  sdt = SearchDocTree.new(input_data)
364
383
  docstr = sdt.search
365
384
 
385
+ # used for debug purposes
386
+ # docstr = <<~EOF
387
+ #
388
+ # #{input_data[:referer_rel_top]} is branch: #{input_data[:gitbranch]}
389
+ #
390
+ # #{adoc_attributes.to_s}
391
+ #
392
+ #
393
+ # #{sdt.search}
394
+ # EOF
395
+
366
396
  # send the result back to the client
367
- print Asciidoctor.convert docstr, header_footer: true, attributes: adoc_options
397
+ print Asciidoctor.convert(docstr, converter_options)
368
398
  end
369
399
 
370
400
  # assume that the file tree looks like this when running
@@ -410,10 +440,14 @@ end
410
440
 
411
441
  # Usage:
412
442
  # to start a local web server for development work
413
- # giblish-giblish-search.rb <web_root>
443
+ # giblish-search.rb <web_root>
444
+ #
445
+ # to run as a cgi script via a previously setup web server
446
+ # giblish-search.rb
414
447
  #
415
- # to run as a cgi script via a previously setup web server:
416
- # giblish-giblish-search.rb
448
+ # (note that you might need to rename the script to eg
449
+ # giblish-search.cgi or similar depending on your web server
450
+ # setup)
417
451
  #
418
452
  if __FILE__ == $PROGRAM_NAME
419
453
 
@@ -425,7 +459,6 @@ if __FILE__ == $PROGRAM_NAME
425
459
  cgi = CGI.new
426
460
  print cgi.header
427
461
  begin
428
- # hello_world
429
462
  cgi_main cgi
430
463
  rescue Exception => e
431
464
  print e.message
@@ -26,17 +26,20 @@ module Giblish
26
26
  @next_id = 0
27
27
  @processed_docs = processed_docs
28
28
  @paths = paths
29
- @options = options.dup
30
- @extension = options.key?(:extension) ? options[:extension] : "html"
29
+ @converter_options = options.dup
30
+ # @options = options.dup
31
+ @extension = @converter_options.key?(:extension) ? options[:extension] : "html"
31
32
  @docid_cache = DocidCollector.docid_cache
32
33
  @docid_deps = DocidCollector.docid_deps
33
34
  @dep_graph = build_dep_graph
34
35
  end
35
36
 
36
37
  # get the asciidoc source for the document.
37
- def source
38
+ def source(make_searchable = false)
38
39
  <<~DOC_STR
39
40
  #{generate_header}
41
+ #{add_search_box if make_searchable}
42
+ #{generate_graph_header}
40
43
  #{generate_labels}
41
44
  #{generate_deps}
42
45
  #{generate_footer}
@@ -58,15 +61,9 @@ module Giblish
58
61
  result
59
62
  end
60
63
 
61
- def generate_header
64
+ def generate_graph_header
62
65
  t = Time.now
63
66
  <<~DOC_STR
64
- = Document-id reference graph
65
- from #{@paths.src_root_abs}
66
-
67
- Generated by Giblish at::
68
- #{t.strftime('%Y-%m-%d %H:%M')}
69
-
70
67
  Below is a graph that visualizes what documents (by doc-id) a specific
71
68
  document references.
72
69
 
@@ -84,6 +81,18 @@ module Giblish
84
81
  DOC_STR
85
82
  end
86
83
 
84
+ def generate_header
85
+ t = Time.now
86
+ <<~DOC_STR
87
+ = Document-id reference graph
88
+ from #{@paths.src_root_abs}
89
+
90
+ Generated by Giblish at::
91
+ #{t.strftime('%Y-%m-%d %H:%M')}
92
+
93
+ DOC_STR
94
+ end
95
+
87
96
  def generate_footer
88
97
  <<~DOC_STR
89
98
  }
@@ -91,6 +100,15 @@ module Giblish
91
100
  DOC_STR
92
101
  end
93
102
 
103
+ def add_search_box
104
+ # TODO: Fix the hard-coded path
105
+ Giblish::generate_search_box_html(
106
+ @converter_options[:attributes]["stylesheet"],
107
+ "/cgi-bin/giblish-search.cgi",
108
+ @paths
109
+ )
110
+ end
111
+
94
112
  def make_dot_entry(doc_dict, info)
95
113
  # split title into multiple rows if it is too long
96
114
  line_length = 15
@@ -58,33 +58,13 @@ module Giblish
58
58
 
59
59
  def add_search_box
60
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
61
+ Giblish::generate_search_box_html(
62
+ @converter.converter_options[:attributes]["stylesheet"],
63
+ "/cgi-bin/giblish-search.cgi",
64
+ @paths
65
+ )
87
66
  end
67
+
88
68
  def get_docid_statistics
89
69
  largest = ""
90
70
  clash = []
@@ -69,38 +69,53 @@ module Giblish
69
69
  # build index and other fancy stuff if not suppressed
70
70
  unless @options[:suppressBuildRef]
71
71
  # build a dependency graph (only if we resolve docids...)
72
- dep_graph_exist = if @options[:resolveDocid]
73
- if Giblish::GraphBuilderGraphviz.supported
74
- gb = Giblish::GraphBuilderGraphviz.new @processed_docs, @paths, {extension: @converter.converter_options[:fileext]}
75
- @converter.convert_str(gb.source, @paths.dst_root_abs, "graph")
76
- else
77
- Giblog.logger.warn { "Lacking access to needed tools for generating a visual dependency graph." }
78
- Giblog.logger.warn { "The dependency graph will not be generated !!" }
79
- false
80
- end
81
- else
82
- false
83
- end
72
+ dep_graph_exist = @options[:resolveDocid] && build_graph_page
84
73
 
85
74
  # build a reference index
86
- adoc_logger = Giblish::AsciidoctorLogger.new Logger::Severity::WARN
87
- ib = index_factory
88
- @converter.convert_str(
89
- ib.source(
90
- dep_graph_exist,@options[:make_searchable]
91
- ),
92
- @paths.dst_root_abs, "index",
93
- logger: adoc_logger)
94
-
95
- # clean up cached files and adoc resources
96
- remove_diagram_temps if dep_graph_exist
97
- GC.start
75
+ build_index_page(dep_graph_exist)
98
76
  end
99
77
  conv_error
100
78
  end
101
79
 
102
80
  protected
103
81
 
82
+ def build_graph_page
83
+ if Giblish::GraphBuilderGraphviz.supported
84
+ # gb = Giblish::GraphBuilderGraphviz.new @processed_docs, @paths, {extension: @converter.converter_options[:fileext]}
85
+ gb = Giblish::GraphBuilderGraphviz.new @processed_docs, @paths, @converter.converter_options
86
+ errors = @converter.convert_str(
87
+ gb.source(
88
+ @options[:make_searchable]
89
+ ),
90
+ @paths.dst_root_abs,
91
+ "graph"
92
+ )
93
+ remove_diagram_temps unless errors
94
+ !errors
95
+ else
96
+ Giblog.logger.warn { "Lacking access to needed tools for generating a visual dependency graph." }
97
+ Giblog.logger.warn { "The dependency graph will not be generated !!" }
98
+ false
99
+ end
100
+ end
101
+
102
+ def build_index_page(dep_graph_exist)
103
+ # build a reference index
104
+ adoc_logger = Giblish::AsciidoctorLogger.new Logger::Severity::WARN
105
+ ib = index_factory
106
+ @converter.convert_str(
107
+ ib.source(
108
+ dep_graph_exist,@options[:make_searchable]
109
+ ),
110
+ @paths.dst_root_abs,
111
+ "index",
112
+ logger: adoc_logger
113
+ )
114
+
115
+ # clean up cached files and adoc resources
116
+ GC.start
117
+ end
118
+
104
119
  # get the correct index builder type depending on supplied
105
120
  # user options
106
121
  def index_factory
@@ -39,8 +39,11 @@ module Giblish
39
39
  # the user if applicable
40
40
  @converter_options[:attributes] = DEFAULT_ATTRIBUTES.dup
41
41
  @converter_options[:attributes].merge!(options[:attributes]) unless options[:attributes].nil?
42
-
43
42
  @converter_options[:backend] = options[:backend]
43
+
44
+ # give derived classes the opportunity to add options and attributes
45
+ add_backend_options(@converter_options)
46
+ add_backend_attributes(@converter_options[:attributes])
44
47
  end
45
48
 
46
49
  # Public: Convert one single adoc file using the specific conversion
@@ -56,23 +59,18 @@ module Giblish
56
59
 
57
60
  Giblog.logger.info {"Processing: #{filepath}"}
58
61
 
59
- # create an asciidoc doc object and convert to requested
60
- # output using current conversion options
61
- @converter_options[:to_dir] = @paths.adoc_output_dir(filepath).to_s
62
- @converter_options[:base_dir] =
63
- Giblish::PathManager.closest_dir(filepath).to_s
64
- @converter_options[:to_file] =
65
- Giblish::PathManager.get_new_basename(filepath,
66
- @converter_options[:fileext])
62
+ # update the relevant options for each specific document
63
+ set_common_doc_specific_options(filepath,logger)
67
64
 
68
- # set a specific logger instance to-be-used by asciidoctor
69
- @converter_options[:logger] = logger unless logger.nil?
65
+ # give derived classes the opportunity to set doc specific attributes
66
+ add_doc_specific_attributes(filepath,true, @converter_options[:attributes])
70
67
 
71
68
  Giblog.logger.debug {"converter_options: #{@converter_options}"}
72
69
 
73
70
  # do the actual conversion
74
71
  doc = Asciidoctor.convert_file filepath, @converter_options
75
72
 
73
+ # bail out if asciidoctor failed to convert the doc
76
74
  if logger && logger.max_severity && logger.max_severity > Logger::Severity::WARN
77
75
  raise RuntimeError, "Failed to convert the file #{filepath}"
78
76
  end
@@ -88,6 +86,7 @@ module Giblish
88
86
  # Returns: whether any errors occured during conversion (true) or
89
87
  # not (false).
90
88
  def convert_str(src_str, dst_dir, basename,logger: nil)
89
+
91
90
  index_opts = @converter_options.dup
92
91
 
93
92
  # use the same options as when converting all docs
@@ -98,6 +97,10 @@ module Giblish
98
97
  index_opts[:base_dir] = dst_dir.to_s
99
98
  index_opts.delete_if {|k, _v| %i[to_file].include? k}
100
99
 
100
+ # give derived classes the opportunity to set doc specific attributes
101
+ index_filepath = dst_dir + "#{basename}.#{index_opts[:fileext]}"
102
+ add_doc_specific_attributes(index_filepath,false, index_opts[:attributes])
103
+
101
104
  # load and convert the document using the converter options
102
105
  doc = nil, output = nil
103
106
 
@@ -108,105 +111,176 @@ module Giblish
108
111
  doc = Asciidoctor.load src_str, index_opts
109
112
  output = doc.convert index_opts
110
113
 
111
- index_filepath = dst_dir + "#{basename}.#{index_opts[:fileext]}"
112
-
113
114
  if logger && logger.max_severity && logger.max_severity > Logger::Severity::WARN
114
115
  raise RuntimeError, "Failed to convert string to asciidoc!! Will _not_ generate #{index_filepath.to_s}"
115
116
  end
117
+
118
+ # write the converted document to an index file located at the
119
+ # destination root
120
+ doc.write output, index_filepath.to_s
116
121
  rescue Exception => e
117
122
  Giblog.logger.error(e)
118
123
  conv_error = true
119
124
  end
120
125
 
121
-
122
- # write the converted document to an index file located at the
123
- # destination root
124
- doc.write output, index_filepath.to_s
125
126
  conv_error
126
127
  end
127
128
 
128
129
  protected
129
130
 
130
- # Protected: Adds the supplied backend specific options and
131
- # attributes to the base ones.
132
- # The following options must be provided by the derived class:
133
- # :fileext - a string with the filename extention to use for the
134
- # generated file
131
+ # Hook for specific converters to inject their own options.
132
+ # The following options must be provided by the derived class:
133
+ # :fileext - a string with the filename extention to use for the
134
+ # generated file
135
135
  #
136
- # backend_opts - the options specific to the asciidoctor backend
137
- # that the derived class supports
138
- # backend_attribs - the attributes specific to the asciidoctor backend
139
- # that the derived class supports
140
- def add_backend_options(backend_opts, backend_attribs)
141
- @converter_options = @converter_options.merge(backend_opts)
142
- @converter_options[:attributes] =
143
- @converter_options[:attributes].merge(backend_attribs)
136
+ # backend_options - the option dict from the backend implementation
137
+ def add_backend_options(backend_options)
138
+ @converter_options.merge!(backend_options)
139
+ end
140
+
141
+ # Hook for specific converters to inject their own attributes
142
+ # valid for all conversions.
143
+ # backend_attributes - the attribute dict from the backend implementation
144
+ def add_backend_attributes(backend_attributes)
145
+ @converter_options[:attributes].merge!(backend_attributes)
146
+ end
147
+
148
+ # Hook for specific converters to inject attributes on a per-doc
149
+ # basis
150
+ def add_doc_specific_attributes(filepath, is_src, attributes)
151
+
152
+ end
153
+
154
+ private
155
+
156
+ def set_common_doc_specific_options(src_filepath,logger)
157
+ # create an asciidoc doc object and convert to requested
158
+ # output using current conversion options
159
+ @converter_options[:to_dir] = @paths.adoc_output_dir(src_filepath).to_s
160
+ @converter_options[:base_dir] =
161
+ Giblish::PathManager.closest_dir(src_filepath).to_s
162
+ @converter_options[:to_file] =
163
+ Giblish::PathManager.get_new_basename(src_filepath,
164
+ @converter_options[:fileext])
165
+ @converter_options[:logger] = logger unless logger.nil?
144
166
  end
145
167
  end
146
168
 
147
- # Converts asciidoc files to html5 output.
169
+ # Converts asciidoc files to html5 output.
148
170
  class HtmlConverter < DocConverter
149
171
  def initialize(paths, options)
150
172
  super paths, options
151
173
 
152
- # handle needed assets for the styling (css et al)
153
- html_attrib = setup_web_assets options[:webRoot]
174
+ # validate that things are ok on the resource front
175
+ # and copy if needed
176
+ @dst_asset_dir = @paths.dst_root_abs.join("web_assets")
177
+ validate_and_copy_resources @dst_asset_dir
154
178
 
155
- # Setting 'data-uri' makes asciidoctor embed images in the resulting
156
- # html file
157
- html_attrib["data-uri"] = 1
179
+ # convenience path to css dir
180
+ @dst_css_dir = @dst_asset_dir.join("css")
158
181
 
159
- # tell asciidoctor to use the html5 backend
160
- backend_options = {backend: "html5", fileext: "html"}
161
- add_backend_options backend_options, html_attrib
182
+ # identify ourselves as an html converter
183
+ add_backend_options({backend: "html5", fileext: "html"})
184
+ # setup the attributes specific for this converter
185
+ add_backend_attributes(get_common_attributes)
162
186
  end
163
187
 
164
- private
165
-
166
- def setup_stylesheet_attributes(css_dir)
167
- return {} if @paths.resource_dir_abs.nil?
188
+ protected
168
189
 
169
- # use the supplied stylesheet if there is one
170
- attrib = {"linkcss" => 1,
171
- "stylesdir" => css_dir,
172
- "stylesheet" => "giblish.css",
173
- "copycss!" => 1}
190
+ def add_doc_specific_attributes(filepath, is_src_file, attributes)
191
+ doc_attributes = {}
192
+ if @paths.resource_dir_abs and not @web_root
193
+ # user wants to use own styling without use of a
194
+ # web root. the correct css link is the relative path
195
+ # from the specific doc to the common css directory
196
+ css_rel_dir = if is_src_file
197
+ # the filepath is a src path
198
+ @paths.relpath_to_dir_after_generate(
199
+ filepath,
200
+ @dst_css_dir
201
+ )
202
+ else
203
+ # the given file path is the destination path of
204
+ # the generated file, find the relative path to the
205
+ # css dir
206
+ dst_dir = PathManager.closest_dir(filepath)
207
+ @dst_css_dir.relative_path_from(dst_dir)
208
+ end
209
+ doc_attributes["stylesdir"] = css_rel_dir.to_s
210
+ end
174
211
 
175
- # Make sure that a user supplied stylesheet ends with .css or .CSS
176
- @user_style &&
177
- attrib["stylesheet"] =
178
- /\.(css|CSS)$/ =~ @user_style ? @user_style : "#{@user_style}.css"
179
- Giblog.logger.debug {"stylesheet attributes: #{attrib}"}
180
- attrib
212
+ attributes.merge!(doc_attributes)
181
213
  end
182
214
 
183
- # make sure that linked assets are available at dst_root
184
- def setup_web_assets(html_dir_root = nil)
185
- # only set this up if user has specified a resource dir
186
- return {} unless @paths.resource_dir_abs
215
+ private
216
+
217
+ def get_common_attributes
218
+ # Setting 'data-uri' makes asciidoctor embed images in the resulting
219
+ # html file
220
+ html_attrib = {
221
+ "data-uri" => 1,
222
+ }
187
223
 
188
- # create dir for web assets directly under dst_root
189
- assets_dir = "#{@paths.dst_root_abs}/web_assets"
190
- Dir.exist?(assets_dir) || FileUtils.mkdir_p(assets_dir)
224
+ if @paths.resource_dir_abs
225
+ # user wants to use own styling, set common attributes
226
+ html_attrib.merge!(
227
+ {
228
+ "linkcss" => 1,
229
+ "stylesheet" => @user_style ||= "giblish.css",
230
+ "copycss!" => 1
231
+ }
232
+ )
233
+
234
+ # check if user wants to use a web root path
235
+ @web_root = @paths.web_root_abs
236
+
237
+ if @web_root
238
+ # if user requested a web root to be used, the correct
239
+ # css link is the relative path from the web root to the
240
+ # css file. This is true for all documents
241
+ wr_rel = @dst_css_dir.relative_path_from @web_root
242
+ Giblog.logger.info {"Relative web root: #{wr_rel}"}
243
+ html_attrib["stylesdir"] = "/" << wr_rel.to_s
244
+ end
245
+ end
246
+ html_attrib
247
+ end
191
248
 
192
- # copy needed assets
249
+ def copy_resource_dir(dst_dir)
250
+ # create assets_dir and copy everything in the resource dir
251
+ # to the destination
252
+ Dir.exist?(dst_dir) || FileUtils.mkdir_p(dst_dir)
253
+
254
+ # copy all subdirs that exist in the source tree to the
255
+ # dst tree
193
256
  %i[css fonts images].each do |dir|
194
257
  src = "#{@paths.resource_dir_abs}/#{dir}"
195
- Dir.exist?(src) && FileUtils.copy_entry(src, "#{assets_dir}/#{dir}")
258
+ Dir.exist?(src) && FileUtils.copy_entry(src, "#{dst_dir}/#{dir}")
196
259
  end
260
+ end
197
261
 
198
- # find the path to the assets dir that is correct when called from a url,
199
- # taking the DirectoryRoot for the web site into consideration.
200
- if html_dir_root
201
- wr = Pathname.new(
202
- assets_dir
203
- ).relative_path_from Pathname.new(html_dir_root)
204
- Giblog.logger.info {"Relative web root: #{wr}"}
205
- assets_dir = "/" << wr.to_s
262
+ # make as sure as we can that the user has given a
263
+ # directory with valid resources
264
+ def validate_and_copy_resources(dst_dir)
265
+ # we don't have a resource path, which is fine, use
266
+ # defaults
267
+ return nil unless @paths.resource_dir_abs
268
+
269
+ # If user has requested the use of a specific css, use that,
270
+ # otherwise use asciidoctor default css
271
+ if @user_style
272
+ # Make sure that a user supplied stylesheet ends with .css or .CSS
273
+ @user_style && @user_style =
274
+ /\.(css|CSS)$/ =~ @user_style ? @user_style : "#{@user_style}.css"
275
+
276
+ # bail out if we can not find the given css file
277
+ src_css_path = @paths.resource_dir_abs.
278
+ join("css").join(Pathname.new(@user_style))
279
+ raise RuntimeError, "Could not find the specified " +
280
+ "css file at: #{src_css_path}" unless src_css_path.exist?
206
281
  end
207
282
 
208
- Giblog.logger.info {"stylesheet dir: #{assets_dir}"}
209
- setup_stylesheet_attributes "#{assets_dir}/css"
283
+ copy_resource_dir dst_dir
210
284
  end
211
285
  end
212
286
 
@@ -214,10 +288,10 @@ module Giblish
214
288
  def initialize(paths, options)
215
289
  super paths, options
216
290
 
217
- pdf_attrib = setup_pdf_attribs
218
-
219
- backend_options = {backend: "pdf", fileext: "pdf"}
220
- add_backend_options backend_options, pdf_attrib
291
+ # identify ourselves as a pdf converter
292
+ add_backend_options({backend: "pdf", fileext: "pdf"})
293
+ # setup the attributes specific for this converter
294
+ add_backend_attributes(setup_pdf_attribs)
221
295
  end
222
296
 
223
297
  private
@@ -25,7 +25,7 @@ module Giblish
25
25
  # parent
26
26
  # message
27
27
  def file_log(filename)
28
- o, e, s = exec_cmd("log", %w[--follow --date=iso --], filename)
28
+ o, e, s = exec_cmd("log", %w[--follow --date=iso --], "'#{filename}'")
29
29
  raise "Failed to get git log for #{filename}!!\n#{e}" if s.exitstatus != 0
30
30
 
31
31
  process_log_output(o)
@@ -86,6 +86,7 @@ module Giblish
86
86
  attr_reader :src_root_abs
87
87
  attr_reader :dst_root_abs
88
88
  attr_reader :resource_dir_abs
89
+ attr_reader :web_root_abs
89
90
 
90
91
  # Public:
91
92
  #
@@ -95,7 +96,7 @@ module Giblish
95
96
  # tree
96
97
  # resource_dir - a string or pathname with the directory containing
97
98
  # resources
98
- def initialize(src_root, dst_root, resource_dir = nil, web_root = false)
99
+ def initialize(src_root, dst_root, resource_dir = nil, web_root = nil)
99
100
  # Make sure that the source root exists in the file system
100
101
  @src_root_abs = Pathname.new(src_root).realpath
101
102
  self.dst_root_abs = dst_root
@@ -104,7 +105,11 @@ module Giblish
104
105
  resource_dir && (@resource_dir_abs = Pathname.new(resource_dir).realpath)
105
106
 
106
107
  # Set web root if given by user
107
- @web_root_abs = web_root ? Pathname.new(web_root) : nil
108
+ @web_root_abs = nil
109
+ if web_root
110
+ web_root = "/" + web_root unless web_root[0] == '/'
111
+ @web_root_abs = web_root ? Pathname.new(web_root) : nil
112
+ end
108
113
  end
109
114
 
110
115
  def dst_root_abs=(dst_root)
@@ -115,26 +120,72 @@ module Giblish
115
120
  end
116
121
 
117
122
  # Public: Get the relative path from the source root dir to the
118
- # source file dir.
123
+ # directory where the supplied path points.
119
124
  #
120
- # in_path - an absolute or relative path
125
+ # in_path - an absolute or relative path to a file or dir
121
126
  def reldir_from_src_root(in_path)
122
- p = in_path.is_a?(Pathname) ? in_path : Pathname.new(in_path)
127
+ p = self.class.closest_dir in_path
128
+ p.relative_path_from(@src_root_abs)
129
+ end
123
130
 
124
- # Get absolute source dir path
125
- src_abs = p.directory? ? p.realpath : p.dirname.realpath
131
+ # Public: Get the relative path from the
132
+ # directory where the supplied path points to
133
+ # the src root dir
134
+ #
135
+ # path - an absolute or relative path to a file or dir
136
+ def reldir_to_src_root(path)
137
+ src = self.class.closest_dir path
138
+ @src_root_abs.relative_path_from(src)
139
+ end
126
140
 
127
- # Get relative path from source root dir
128
- src_abs.relative_path_from(@src_root_abs)
141
+ # Public: Get the relative path from the dst root dir to the
142
+ # directory where the supplied path points.
143
+ #
144
+ # path - an absolute or relative path to a file or dir
145
+ def reldir_from_dst_root(path)
146
+ dst = self.class.closest_dir path
147
+ dst.relative_path_from(@dst_root_abs)
129
148
  end
130
149
 
131
- def reldir_from_web_root(in_path)
132
- p = in_path.is_a?(Pathname) ? in_path : Pathname.new(in_path)
133
- return p if @web_root_abs.nil?
150
+ # Public: Get the relative path from the
151
+ # directory where the supplied path points to
152
+ # the dst root dir
153
+ #
154
+ # path - an absolute or relative path to a file or dir
155
+ def reldir_to_dst_root(path)
156
+ dst = self.class.closest_dir path
157
+ @dst_root_abs.relative_path_from(dst)
158
+ end
159
+
160
+ # return the destination dir corresponding to the given src path
161
+ # the src path must exist in the file system
162
+ def dst_abs_from_src_abs(src_path)
163
+ src_abs = (self.class.to_pathname src_path).realpath
164
+ src_rel = reldir_from_src_root src_abs
165
+ @dst_root_abs.join(src_rel)
166
+ end
134
167
 
168
+ # return the relative path from a generated document to
169
+ # the supplied folder given the corresponding absolute source
170
+ # file path
171
+ def relpath_to_dir_after_generate(src_filepath,dir_path)
172
+ dst_abs = dst_abs_from_src_abs(src_filepath)
173
+ dir = self.class.to_pathname(dir_path)
174
+ dir.relative_path_from(dst_abs)
175
+ end
176
+
177
+ def reldir_from_web_root(path)
178
+ p = self.class.closest_dir path
179
+ return p if @web_root_abs.nil?
135
180
  p.relative_path_from(@web_root_abs)
136
181
  end
137
182
 
183
+ def reldir_to_web_root(path)
184
+ p = self.class.closest_dir path
185
+ return p if @web_root_abs.nil?
186
+ @web_root_abs.relative_path_from(p)
187
+ end
188
+
138
189
  def adoc_output_file(infile_path, extension)
139
190
  # Get absolute source dir path
140
191
  src_dir_abs = self.class.closest_dir infile_path
@@ -173,6 +224,12 @@ module Giblish
173
224
  dst_abs.relative_path_from(src_abs)
174
225
  end
175
226
 
227
+ # return a pathname, regardless if the given path is a Pathname or
228
+ # a string
229
+ def self.to_pathname(path)
230
+ path.is_a?(Pathname) ? path : Pathname.new(path)
231
+ end
232
+
176
233
  # Public: Get the basename for a file by replacing the file
177
234
  # extention of the source file with the supplied one.
178
235
  #
@@ -196,7 +253,7 @@ module Giblish
196
253
  # - the directory itself when called with an existing directory
197
254
  # - the parent dir when called with a non-existing file/directory
198
255
  def self.closest_dir(in_path)
199
- sr = in_path.is_a?(Pathname) ? in_path : Pathname.new(in_path)
256
+ sr = self.to_pathname(in_path)
200
257
  if sr.exist?
201
258
  sr.directory? ? sr.realpath : sr.dirname.realpath
202
259
  else
@@ -302,4 +359,40 @@ module Giblish
302
359
  module_function :which
303
360
 
304
361
 
362
+ # returns raw html that displays a search box to let the user
363
+ # acces the text search functionality.
364
+ #
365
+ # css - the name of the css file to use for the search box layout
366
+ # cgi_path - the path to a cgi script that implements the server side
367
+ # functionality of searching the text
368
+ # path_manager - an instance of the path manager class to keep track of all
369
+ # destinations.
370
+ def generate_search_box_html(css, cgi_path, paths)
371
+
372
+ # button with magnifying glass icon (not working when deployed)
373
+ # <button id="search" type="submit"><i class="fa fa-search"></i></button>
374
+ <<~SEARCH_INFO
375
+ ++++
376
+ <form class="example" action="#{cgi_path}" style="margin:20px 0px 20px 0px;max-width:380px">
377
+ Search all documents:
378
+ <input id="searchphrase" type="text" placeholder="Search.." name="searchphrase"/>
379
+ <button id="search" type="submit">Search</button>
380
+ <br>
381
+
382
+ <input id="ignorecase" type="checkbox" value="true" name="ignorecase" checked/>
383
+ <label for="ignorecase">Ignore Case</label>
384
+ &nbsp;&nbsp;
385
+ <input id="useregexp" type="checkbox" value="true" name="regexp"/>
386
+ <label for="useregexp">Use Regexp</label>
387
+
388
+ <input type="hidden" name="topdir" value="#{paths.dst_root_abs}"</input>
389
+ <input type="hidden" name="reltop" value="#{paths.reldir_from_web_root(paths.dst_root_abs)}"</input>
390
+ <input type="hidden" name="css" value="#{css}"</input>
391
+ </form>
392
+ ++++
393
+
394
+ SEARCH_INFO
395
+ end
396
+ module_function :generate_search_box_html
397
+
305
398
  end
@@ -1,3 +1,3 @@
1
1
  module Giblish
2
- VERSION = "0.5.2".freeze
2
+ VERSION = "0.6.0".freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: giblish
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.2
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anders Rillbert
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-06-22 00:00:00.000000000 Z
11
+ date: 2019-10-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -106,14 +106,14 @@ dependencies:
106
106
  requirements:
107
107
  - - ">="
108
108
  - !ruby/object:Gem::Version
109
- version: 1.5.0.alpha.18
109
+ version: 1.5.0.beta.6
110
110
  type: :runtime
111
111
  prerelease: false
112
112
  version_requirements: !ruby/object:Gem::Requirement
113
113
  requirements:
114
114
  - - ">="
115
115
  - !ruby/object:Gem::Version
116
- version: 1.5.0.alpha.18
116
+ version: 1.5.0.beta.6
117
117
  - !ruby/object:Gem::Dependency
118
118
  name: git
119
119
  requirement: !ruby/object:Gem::Requirement
@@ -181,6 +181,20 @@ files:
181
181
  - data/testdocs/wellformed/docidtest/docid_2.adoc
182
182
  - data/testdocs/wellformed/simple.adoc
183
183
  - data/testdocs/wellformed/source_highlighting/highlight_source.adoc
184
+ - docgen/resources/css/giblish.css
185
+ - docgen/resources/fonts/Ubuntu-B.ttf
186
+ - docgen/resources/fonts/Ubuntu-BI.ttf
187
+ - docgen/resources/fonts/Ubuntu-R.ttf
188
+ - docgen/resources/fonts/Ubuntu-RI.ttf
189
+ - docgen/resources/fonts/mplus1p-regular-fallback.ttf
190
+ - docgen/resources/images/giblish_logo.png
191
+ - docgen/resources/images/giblish_logo.svg
192
+ - docgen/resources/themes/giblish.yml
193
+ - docgen/scripts/Jenkinsfile
194
+ - docgen/scripts/githook_examples/post-update.example
195
+ - docs/setup_server.adoc
196
+ - docs/setup_server_assets/Render Documents.png
197
+ - docs/setup_server_assets/View Documents.png
184
198
  - exe/giblish
185
199
  - giblish.gemspec
186
200
  - lib/giblish-search.rb
@@ -198,15 +212,6 @@ files:
198
212
  - lib/giblish/pathtree.rb
199
213
  - lib/giblish/utils.rb
200
214
  - lib/giblish/version.rb
201
- - resources/css/giblish.css
202
- - resources/fonts/Ubuntu-B.ttf
203
- - resources/fonts/Ubuntu-BI.ttf
204
- - resources/fonts/Ubuntu-R.ttf
205
- - resources/fonts/Ubuntu-RI.ttf
206
- - resources/fonts/mplus1p-regular-fallback.ttf
207
- - resources/images/giblish_logo.png
208
- - resources/images/giblish_logo.svg
209
- - resources/themes/giblish.yml
210
215
  homepage: https://github.com/rillbert/giblish
211
216
  licenses:
212
217
  - MIT