giblish 0.6.1 → 0.7.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 +4 -4
- data/Changelog +16 -0
- data/README.adoc +303 -170
- data/Rakefile +1 -8
- data/docgen/resources/css/adoc-colony.css +634 -0
- data/docgen/scripts/gen_adoc_org.sh +58 -0
- data/giblish.gemspec +6 -3
- data/lib/giblish-search.rb +107 -125
- data/lib/giblish/buildgraph.rb +24 -3
- data/lib/giblish/buildindex.rb +11 -7
- data/lib/giblish/cmdline.rb +42 -21
- data/lib/giblish/core.rb +76 -51
- data/lib/giblish/docconverter.rb +43 -51
- data/lib/giblish/indexheadings.rb +62 -9
- data/lib/giblish/utils.rb +71 -37
- data/lib/giblish/version.rb +1 -1
- metadata +12 -7
@@ -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"
|
data/giblish.gemspec
CHANGED
@@ -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 =
|
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.
|
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.
|
47
|
+
spec.add_runtime_dependency "prawn-svg", "~> 0.30.0"
|
45
48
|
end
|
data/lib/giblish-search.rb
CHANGED
@@ -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
|
26
|
-
@grep_opts += "-F " unless grep_opts
|
25
|
+
@grep_opts += "-i " if grep_opts[:ignorecase]
|
26
|
+
@grep_opts += "-F " unless grep_opts[:useregexp]
|
27
27
|
|
28
|
-
@search_root = grep_opts[:
|
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
|
-
|
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[:
|
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
|
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 |
|
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
|
-
|
257
|
+
= Search Result
|
259
258
|
|
260
|
-
|
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
|
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
|
-
|
382
|
-
|
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
|
-
#
|
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
|
-
#
|
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.
|
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.
|
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
|
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
|