giblish 0.6.1 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,58 @@
1
+ #!/bin/bash
2
+ # generates the asciidoctor.org docs to a web server
3
+ # see usage function for usage
4
+
5
+ ### configuration variables
6
+
7
+ # the deployment paths needed by giblish when generating the docs
8
+ uri_path="/adocorg/with_search"
9
+ deployment_dir="/var/www/rillbert_se/adoc/examples/adocorg"
10
+
11
+ # the cgi bin paths on the deployment server
12
+ cgi_dir="/var/www/cgi-bin"
13
+
14
+ ### end of config section
15
+
16
+ function usage() {
17
+ echo ""
18
+ echo "Generates the asciidoctor.org docs to html using giblish and"
19
+ echo "deploys it to the server given by <ssh_host>."
20
+ echo ""
21
+ echo "NOTE: that you most likely need to tweak the deployment paths within this script"
22
+ echo "to your specific situation. See the doc within the script."
23
+ echo ""
24
+ echo "Usage: "
25
+ echo " gen_adoc_org <ssh_host>"
26
+ echo ""
27
+ echo " ssh_host the ssh host including user name (eg user1@my.webserver.com)"
28
+ echo ""
29
+ }
30
+
31
+ # check input variables
32
+ if [ $# -ne 1 ]; then
33
+ echo ""
34
+ echo "ERROR: Wrong number of input arguments !!!"
35
+ usage
36
+ exit 1
37
+ fi
38
+
39
+ # ssh_host="${ssh_user}@${web_server}:"
40
+ ssh_host="$1:"
41
+ html_doc_target="${ssh_host}${deployment_dir}"
42
+ cgi_bin_target="${ssh_host}${cgi_dir}"
43
+
44
+
45
+ # clone the asciidoctor repo
46
+ git clone https://github.com/asciidoctor/asciidoctor.org.git
47
+
48
+ # generate the html docs
49
+ giblish -j '^.*_include.*' -m -mp "${deployment_dir}" -w ${uri_path} -g master --index-basename "myindex" asciidoctor.org/docs ./generated_docs
50
+
51
+ # copy the docs to the web server
52
+ scp -r ./generated_docs/* "${html_doc_target}"
53
+
54
+ # get the path to the search script
55
+ search_script="$(dirname $(gem which giblish))/giblish-search.rb"
56
+
57
+ # copy the script to the cgi-bin on the web server
58
+ scp "${search_script}" "${cgi_bin_target}/giblish-search.cgi"
@@ -12,7 +12,10 @@ Gem::Specification.new do |spec|
12
12
  spec.email = ["anders.rillbert@kutso.se"]
13
13
 
14
14
  spec.summary = "A tool for publishing asciidoc docs stored in git repos"
15
- spec.description = "A tool for publishing asciidoc docs stored in git repos"
15
+ spec.description = <<~EOF
16
+ giblish generates indexed and searchable documents from a tree of
17
+ asciidoc files.
18
+ EOF
16
19
  spec.homepage = "https://github.com/rillbert/giblish"
17
20
  spec.license = "MIT"
18
21
  spec.required_ruby_version = ">= 2.3"
@@ -38,8 +41,8 @@ Gem::Specification.new do |spec|
38
41
  # Usage: spec.add_runtime_dependency "[gem name]", [[version]]
39
42
  spec.add_runtime_dependency "asciidoctor", "~>2.0", ">= 2.0.10"
40
43
  spec.add_runtime_dependency "asciidoctor-diagram", ["~> 1.5"]
41
- spec.add_runtime_dependency "asciidoctor-pdf", [">= 1.5.0.beta.6"]
44
+ spec.add_runtime_dependency "asciidoctor-pdf", [">= 1.5.0.rc.1"]
42
45
  spec.add_runtime_dependency "git", "~> 1.3"
43
46
  spec.add_runtime_dependency "rouge", "~> 3.3"
44
- spec.add_runtime_dependency "prawn-svg", "~> 0.29.1"
47
+ spec.add_runtime_dependency "prawn-svg", "~> 0.30.0"
45
48
  end
@@ -9,7 +9,7 @@ require "uri/generic"
9
9
 
10
10
  class GrepDocTree
11
11
  Line_info = Struct.new(:line, :line_no) {
12
- def initialize(line,line_no)
12
+ def initialize(line, line_no)
13
13
  self.line = line
14
14
  self.line_no = Integer(line_no)
15
15
  end
@@ -22,10 +22,10 @@ class GrepDocTree
22
22
  # :useregexp
23
23
  def initialize(grep_opts)
24
24
  @grep_opts = "-nHr --include '*.adoc' "
25
- @grep_opts += "-i " if grep_opts.has_key? :ignorecase
26
- @grep_opts += "-F " unless grep_opts.has_key? :useregexp
25
+ @grep_opts += "-i " if grep_opts[:ignorecase]
26
+ @grep_opts += "-F " unless grep_opts[:useregexp]
27
27
 
28
- @search_root = grep_opts[:search_top]
28
+ @search_root = grep_opts[:searchassetstop]
29
29
  @input = grep_opts[:search_phrase]
30
30
 
31
31
  @output = ""
@@ -36,7 +36,7 @@ class GrepDocTree
36
36
 
37
37
  def grep
38
38
  # This console code sequence will only show the matching word in bold ms=01:mc=:sl=:cx=:fn=:ln=:bn=:se=
39
- grep_env="GREP_COLORS=\"ms=01:mc=:sl=:cx=:fn=:ln=:bn=:se=\""
39
+ grep_env = "GREP_COLORS=\"ms=01:mc=:sl=:cx=:fn=:ln=:bn=:se=\""
40
40
  @grep_opts += " --color=always"
41
41
 
42
42
 
@@ -44,8 +44,8 @@ class GrepDocTree
44
44
 
45
45
  begin
46
46
  @output.force_encoding(Encoding::UTF_8)
47
- @output.gsub!(/\x1b\[01m\x1b\[K/,"##")
48
- @output.gsub!(/\x1b\[m\x1b\[K/,"##")
47
+ @output.gsub!(/\x1b\[01m\x1b\[K/, "##")
48
+ @output.gsub!(/\x1b\[m\x1b\[K/, "##")
49
49
  rescue StandardError => e
50
50
  print e.message
51
51
  print e.backtrace.inspect
@@ -87,7 +87,7 @@ class GrepDocTree
87
87
  matches = []
88
88
 
89
89
  # for each file with at least one match
90
- @match_index.each do |file_path,match_infos|
90
+ @match_index.each do |file_path, match_infos|
91
91
  # assume that max one file with the specified path
92
92
  # exists
93
93
  files = heading_db["file_infos"].select do |fi|
@@ -97,7 +97,7 @@ class GrepDocTree
97
97
 
98
98
  file_anchors = construct_user_info files.first, match_infos
99
99
  matches << file_anchors
100
- end
100
+ end
101
101
  matches
102
102
  end
103
103
 
@@ -155,7 +155,7 @@ class GrepDocTree
155
155
  def formatted_output
156
156
  # assume we have an updated index
157
157
  adoc_str = ""
158
- @match_index.each do |k,v|
158
+ @match_index.each do |k, v|
159
159
  adoc_str += "#{k}::\n"
160
160
  v.each { |line_info|
161
161
  adoc_str += "#{line_info.line_no} : #{line_info.line}\n"
@@ -177,10 +177,10 @@ class GrepDocTree
177
177
  def grep2hash(base_dir)
178
178
  @match_index = {}
179
179
  @output.split("\n").each do |line|
180
- tokens = line.split(":",3)
180
+ tokens = line.split(":", 3)
181
181
 
182
182
  # remove all lines starting with :<attrib>:
183
- tokens[2].gsub!(/^:[[:graph:]]+:.*$/,"")
183
+ tokens[2].gsub!(/^:[[:graph:]]+:.*$/, "")
184
184
  next if tokens[2].empty?
185
185
 
186
186
  # remove everything above the repo root from the filepath
@@ -198,8 +198,7 @@ class SearchDocTree
198
198
 
199
199
  def search
200
200
  # read the heading_db from file
201
- jsonpath = @input_data[:search_top].join("heading_index.json")
202
- src_index = {}
201
+ jsonpath = @input_data[:searchassetstop].join("heading_index.json")
203
202
  json = File.read(jsonpath.to_s)
204
203
  src_index = JSON.parse(json)
205
204
 
@@ -215,14 +214,14 @@ class SearchDocTree
215
214
  private
216
215
 
217
216
  def get_uri_top
218
- return @input_data[:referer][0,@input_data[:referer].rindex('/')]
217
+ return @input_data[:referer][0, @input_data[:referer].rindex('/')]
219
218
  end
220
219
 
221
220
  def wash_line line
222
221
  # remove any '::'
223
- result = line.gsub(/::*/,"")
222
+ result = line.gsub(/::*/, "")
224
223
  # remove =,| at the start of a line
225
- result.gsub!(/^[=|]+/,"")
224
+ result.gsub!(/^[=|]+/, "")
226
225
  result
227
226
  end
228
227
 
@@ -234,19 +233,19 @@ class SearchDocTree
234
233
  # line_1
235
234
  # line_2
236
235
  # ...
237
- def format_search_adoc index,uri_top
236
+ def format_search_adoc index, uri_top
238
237
  str = ""
239
238
  # debug print referer...
240
239
  # str << "uri_top: #{uri_top}\n"
241
240
  index.each do |file_info|
242
241
  filename = Pathname.new(file_info["filepath"]).basename
243
242
  str << "== #{file_info["title"]}\n\n"
244
- file_info["matches"].each do |section_id, info |
243
+ file_info["matches"].each do |section_id, info|
245
244
  str << "#{uri_top}/#{info["location"]}[#{info["section_title"]}]::\n\n"
246
245
  # str << "<<#{info["location"]},#{info["section_title"]}>>::\n\n"
247
246
  str << "[subs=\"quotes\"]\n"
248
247
  str << "----\n"
249
- info["lines"].each do | line |
248
+ info["lines"].each do |line|
250
249
  str << "-- #{wash_line(line)}\n"
251
250
  end.join("\n\n")
252
251
  str << "----\n"
@@ -255,9 +254,9 @@ class SearchDocTree
255
254
  end
256
255
 
257
256
  <<~ADOC
258
- = Search Result
257
+ = Search Result
259
258
 
260
- #{str}
259
+ #{str}
261
260
  ADOC
262
261
  end
263
262
  end
@@ -271,12 +270,14 @@ def init_web_server web_root
271
270
  server = WEBrick::HTTPServer.new(
272
271
  :Port => 8000,
273
272
  :DocumentRoot => root,
274
- :Logger => WEBrick::Log.new("webrick.log",WEBrick::Log::DEBUG)
273
+ :Logger => WEBrick::Log.new("webrick.log", WEBrick::Log::DEBUG)
275
274
  )
276
275
 
277
276
  puts "WEBrick instance now listening to localhost:8000"
278
277
 
279
- trap 'INT' do server.shutdown end
278
+ trap 'INT' do
279
+ server.shutdown
280
+ end
280
281
 
281
282
  server.start
282
283
  end
@@ -305,110 +306,20 @@ def hello_world
305
306
  print "<br>"
306
307
  end
307
308
 
308
- def cgi_main cgi
309
- # retrieve the form data supplied by user
310
- input_data = {
311
- search_phrase: cgi["searchphrase"],
312
- ignorecase: cgi.has_key?("ignorecase"),
313
- useregexp: cgi.has_key?("useregexp"),
314
- doc_root_abs: Pathname.new(cgi["topdir"]),
315
- referer_rel_top: Pathname.new("#{cgi["reltop"]}"),
316
- referer: cgi.referer,
317
- uri_path: URI(cgi.referer).path,
318
- client_css: cgi["css"],
319
- search_top: nil,
320
- styles_top: nil
321
- }
322
-
323
- # fixup paths depending on git branch or not
324
- #
325
- # search_assets is an absolute path
326
- # styles_top is a relative path
327
- #
328
- # if the source was rendered from a git branch, the paths
329
- # search_assets = <index_dir>/../search_assets/<branch_name>/
330
- # styles_top = ../web_assets/css
331
- #
332
- # and if not, the path is
333
- # search_assets = <index_dir>/search_assets
334
- # styles_top = /web_assets/css
335
- # <link rel="stylesheet" href="/web_assets/css/virodoc.css">
336
- #
337
- if input_data[:doc_root_abs].join("./search_assets").exist?
338
- # this is not from a git branch
339
- input_data[:search_top] = input_data[:doc_root_abs].join("./search_assets")
340
- input_data[:styles_top] = Pathname.new(input_data[:referer_rel_top]).join("web_assets/css")
341
- input_data[:gitbranch] = false
342
- elsif input_data[:doc_root_abs].join("../search_assets").exist?
343
- # this is from a git branch
344
- input_data[:search_top] = input_data[:doc_root_abs].join("../search_assets").join(input_data[:doc_root_abs].basename)
345
- input_data[:styles_top] = Pathname.new(input_data[:referer_rel_top]).join("../web_assets/css")
346
- input_data[:gitbranch] = true
347
- else
348
- raise ScriptError, "Could not find search_assets dir!"
349
- end
350
-
351
- # Set some reasonable default attributes and options
352
- adoc_attributes = {
353
- "data-uri" => 1,
354
- }
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
309
 
381
- # search the docs and render html
382
- sdt = SearchDocTree.new(input_data)
383
- docstr = sdt.search
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}
310
+ # assume that the file tree looks like this when rendering
311
+ # a git branch:
391
312
  #
392
- #
393
- # #{sdt.search}
394
- # EOF
395
-
396
- # send the result back to the client
397
- print Asciidoctor.convert(docstr, converter_options)
398
- end
399
-
400
- # assume that the file tree looks like this when running
401
- # on a git branch:
402
- #
403
- # dst_root_dir
313
+ # root_dir
314
+ # |- index.html (the generated index of rendered git branches and tags)
404
315
  # |- branch_1_top_dir
405
- # | |- index.html
316
+ # | |- index.html (the generated index of this branch)
406
317
  # | |- file_1.html
407
318
  # | |- dir_1
408
319
  # | | |- file2.html
409
320
  # |- branch_2_top_dir
410
321
  # |- branch_x_...
411
- # |- web_assets
322
+ # |- web_assets (only if a custom stylesheet is used...)
412
323
  # |- search_assets
413
324
  # | |- branch_1_top_dir
414
325
  # | |- heading_index.json
@@ -422,8 +333,8 @@ end
422
333
  # assume that the file tree looks like this when not
423
334
  # rendering a git branch:
424
335
  #
425
- # dst_root_dir
426
- # |- index.html
336
+ # root_dir
337
+ # |- index.html (the generated index of all rendered files)
427
338
  # |- file_1.html
428
339
  # |- dir_1
429
340
  # | |- file2.html
@@ -436,14 +347,83 @@ end
436
347
  # | | |- file2.html
437
348
  # | |- ...
438
349
 
350
+ def cgi_main(cgi, debug_mode = false)
351
+ # retrieve the form data supplied by user
352
+ input_data = {
353
+ search_phrase: cgi["searchphrase"],
354
+ ignorecase: cgi.has_key?("ignorecase"),
355
+ useregexp: cgi.has_key?("useregexp"),
356
+ searchassetstop: Pathname.new(
357
+ cgi.has_key?("searchassetstop") ? cgi["searchassetstop"] : ""),
358
+ webassetstop: Pathname.new(
359
+ cgi.has_key?("webassetstop") ? cgi["webassetstop"] : nil),
360
+ client_css:
361
+ cgi.has_key?("css") ? cgi["css"] : nil,
362
+ referer: cgi.referer
363
+ }
364
+
365
+ if input_data[:searchassetstop].nil? || !Dir.exist?(input_data[:searchassetstop])
366
+ raise ScriptError, "Could not find search_assets dir (#{input_data[:searchassetstop]}) !"
367
+ end
368
+
369
+ adoc_attributes = {
370
+ "data-uri" => 1,
371
+ }
372
+
373
+ # Set attributes so that the generated result page uses the same
374
+ # css as the other docs
375
+ if !input_data[:client_css].nil? && !input_data[:webassetstop].nil?
376
+ adoc_attributes.merge!(
377
+ {
378
+ "linkcss" => 1,
379
+ "stylesdir" => "#{input_data[:webassetstop]}/css",
380
+ "stylesheet" => input_data[:client_css],
381
+ "copycss!" => 1
382
+ }
383
+ )
384
+ end
385
+
386
+ converter_options = {
387
+ backend: "html5",
388
+ # need this to let asciidoctor include the default css if user
389
+ # has not specified any css
390
+ safe: Asciidoctor::SafeMode::SAFE,
391
+ header_footer: true,
392
+ attributes: adoc_attributes
393
+ }
394
+
395
+
396
+ # search the docs and render html
397
+ sdt = SearchDocTree.new(input_data)
398
+ docstr = sdt.search
399
+
400
+ if debug_mode
401
+ # print some useful data for debugging
402
+ docstr = <<~EOF
403
+
404
+ == Input data
405
+
406
+ #{input_data.to_s}
407
+
408
+ == Adoc attributes
409
+
410
+ #{adoc_attributes.to_s}
411
+
412
+ #{docstr}
413
+ EOF
414
+ end
415
+
416
+ # send the result back to the client
417
+ print Asciidoctor.convert(docstr, converter_options)
418
+ end
439
419
 
440
420
 
441
421
  # Usage:
442
422
  # to start a local web server for development work
443
- # giblish-search.rb <web_root>
423
+ # ruby giblish-search.cgi <web_root>
444
424
  #
445
425
  # to run as a cgi script via a previously setup web server
446
- # giblish-search.rb
426
+ # giblish-search.cgi
447
427
  #
448
428
  # (note that you might need to rename the script to eg
449
429
  # giblish-search.cgi or similar depending on your web server
@@ -459,9 +439,11 @@ if __FILE__ == $PROGRAM_NAME
459
439
  cgi = CGI.new
460
440
  print cgi.header
461
441
  begin
462
- cgi_main cgi
442
+ cgi_main(cgi, false)
463
443
  rescue Exception => e
464
444
  print e.message
445
+ print ""
446
+ print e.backtrace
465
447
  exit 1
466
448
  end
467
449
  exit 0