giblish 0.8.2 → 1.0.0.rc2

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.
Files changed (113) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/unit_tests.yml +30 -0
  3. data/.gitignore +7 -3
  4. data/.ruby-version +1 -1
  5. data/Changelog.adoc +61 -0
  6. data/README.adoc +267 -0
  7. data/docs/concepts/text_search.adoc +213 -0
  8. data/docs/concepts/text_search_im/cgi-search_request.puml +35 -0
  9. data/docs/concepts/text_search_im/cgi-search_request.svg +397 -0
  10. data/docs/concepts/text_search_im/search_request.puml +40 -0
  11. data/docs/concepts/text_search_im/search_request.svg +408 -0
  12. data/docs/howtos/trigger_generation.adoc +180 -0
  13. data/docs/{setup_server_assets → howtos/trigger_generation_im}/Render Documents.png +0 -0
  14. data/docs/{setup_server_assets → howtos/trigger_generation_im}/View Documents.png +0 -0
  15. data/docs/{setup_server_assets → howtos/trigger_generation_im}/deploy_with_hooks.graphml +0 -0
  16. data/docs/{setup_server_assets → howtos/trigger_generation_im}/deploy_with_hooks.svg +0 -0
  17. data/docs/{setup_server_assets → howtos/trigger_generation_im}/deploy_with_jenkins.graphml +0 -0
  18. data/docs/{setup_server_assets → howtos/trigger_generation_im}/deploy_with_jenkins.svg +0 -0
  19. data/docs/howtos/trigger_generation_im/docgen_github.puml +51 -0
  20. data/docs/{setup_server_assets → howtos/trigger_generation_im}/giblish_deployment.graphml +0 -0
  21. data/docs/howtos/trigger_generation_im/post-receive-example.sh +50 -0
  22. data/docs/reference/box_flow_spec.adoc +22 -0
  23. data/docs/reference/search_spec.adoc +185 -0
  24. data/giblish.gemspec +47 -29
  25. data/lib/giblish/adocsrc_providers.rb +23 -0
  26. data/lib/giblish/application.rb +214 -41
  27. data/lib/giblish/cmdline.rb +273 -259
  28. data/lib/giblish/config_utils.rb +41 -0
  29. data/lib/giblish/configurator.rb +163 -0
  30. data/lib/giblish/conversion_info.rb +120 -0
  31. data/lib/giblish/docattr_providers.rb +125 -0
  32. data/lib/giblish/docid/docid.rb +181 -0
  33. data/lib/giblish/github_trigger/webhook_manager.rb +64 -0
  34. data/lib/giblish/gitrepos/checkoutmanager.rb +124 -0
  35. data/lib/giblish/{gititf.rb → gitrepos/gititf.rb} +30 -4
  36. data/lib/giblish/gitrepos/gitsummary.erb +61 -0
  37. data/lib/giblish/gitrepos/gitsummaryprovider.rb +78 -0
  38. data/lib/giblish/gitrepos/history_pb.rb +41 -0
  39. data/lib/giblish/indexbuilders/d3treegraph.rb +88 -0
  40. data/lib/giblish/indexbuilders/depgraphbuilder.rb +109 -0
  41. data/lib/giblish/indexbuilders/dotdigraphadoc.rb +174 -0
  42. data/lib/giblish/indexbuilders/standard_index.erb +10 -0
  43. data/lib/giblish/indexbuilders/subtree_indices.rb +132 -0
  44. data/lib/giblish/indexbuilders/templates/circles.html.erb +111 -0
  45. data/lib/giblish/indexbuilders/templates/flame.html.erb +61 -0
  46. data/lib/giblish/indexbuilders/templates/tree.html.erb +366 -0
  47. data/lib/giblish/indexbuilders/templates/treemap.html.erb +127 -0
  48. data/lib/giblish/indexbuilders/verbatimtree.rb +94 -0
  49. data/lib/giblish/pathtree.rb +473 -74
  50. data/lib/giblish/resourcepaths.rb +150 -0
  51. data/lib/giblish/search/expand_adoc.rb +55 -0
  52. data/lib/giblish/search/headingindexer.rb +312 -0
  53. data/lib/giblish/search/request_manager.rb +110 -0
  54. data/lib/giblish/search/searchquery.rb +68 -0
  55. data/lib/giblish/search/textsearcher.rb +349 -0
  56. data/lib/giblish/subtreeinfobuilder.rb +77 -0
  57. data/lib/giblish/treeconverter.rb +272 -0
  58. data/lib/giblish/utils.rb +142 -294
  59. data/lib/giblish/version.rb +1 -1
  60. data/lib/giblish.rb +10 -7
  61. data/scripts/hooks/post-receive.example +66 -0
  62. data/{docgen/scripts/githook_examples → scripts/hooks}/post-update.example +0 -0
  63. data/{docgen → scripts}/resources/css/adoc-colony.css +0 -0
  64. data/scripts/resources/css/giblish-serif.css +419 -0
  65. data/scripts/resources/css/giblish.css +1979 -419
  66. data/{docgen → scripts}/resources/fonts/Ubuntu-B.ttf +0 -0
  67. data/{docgen → scripts}/resources/fonts/Ubuntu-BI.ttf +0 -0
  68. data/{docgen → scripts}/resources/fonts/Ubuntu-R.ttf +0 -0
  69. data/{docgen → scripts}/resources/fonts/Ubuntu-RI.ttf +0 -0
  70. data/{docgen → scripts}/resources/fonts/mplus1p-regular-fallback.ttf +0 -0
  71. data/{docgen → scripts}/resources/images/giblish_logo.png +0 -0
  72. data/{docgen → scripts}/resources/images/giblish_logo.svg +0 -0
  73. data/{docgen → scripts}/resources/themes/giblish.yml +0 -0
  74. data/scripts/wserv_development.rb +32 -0
  75. data/web_apps/cgi_search/gibsearch.rb +43 -0
  76. data/web_apps/gh_webhook_trigger/config.ru +2 -0
  77. data/web_apps/gh_webhook_trigger/gh_webhook_trigger.rb +73 -0
  78. data/web_apps/gh_webhook_trigger/public/dummy.txt +3 -0
  79. data/web_apps/sinatra_search/config.ru +2 -0
  80. data/web_apps/sinatra_search/public/dummy.txt +3 -0
  81. data/web_apps/sinatra_search/sinatra_search.rb +34 -0
  82. data/web_apps/sinatra_search/tmp/restart.txt +0 -0
  83. metadata +168 -73
  84. data/.rubocop.yml +0 -7
  85. data/.travis.yml +0 -3
  86. data/Changelog +0 -16
  87. data/Gemfile +0 -4
  88. data/README.adoc +0 -1
  89. data/Rakefile +0 -41
  90. data/bin/console +0 -14
  91. data/bin/setup +0 -8
  92. data/data/testdocs/malformed/no_header.adoc +0 -5
  93. data/data/testdocs/toplevel.adoc +0 -19
  94. data/data/testdocs/wellformed/adorned_purpose.adoc +0 -17
  95. data/data/testdocs/wellformed/docidtest/docid_1.adoc +0 -24
  96. data/data/testdocs/wellformed/docidtest/docid_2.adoc +0 -8
  97. data/data/testdocs/wellformed/simple.adoc +0 -14
  98. data/data/testdocs/wellformed/source_highlighting/highlight_source.adoc +0 -38
  99. data/docgen/resources/css/giblish.css +0 -1979
  100. data/docgen/scripts/Jenkinsfile +0 -18
  101. data/docgen/scripts/gen_adoc_org.sh +0 -58
  102. data/docs/README.adoc +0 -387
  103. data/docs/setup_server.adoc +0 -202
  104. data/lib/giblish/buildgraph.rb +0 -216
  105. data/lib/giblish/buildindex.rb +0 -459
  106. data/lib/giblish/core.rb +0 -451
  107. data/lib/giblish/docconverter.rb +0 -308
  108. data/lib/giblish/docid.rb +0 -180
  109. data/lib/giblish/docinfo.rb +0 -75
  110. data/lib/giblish/indexheadings.rb +0 -251
  111. data/lib/giblish-search.cgi +0 -459
  112. data/scripts/hooks/post-receive +0 -57
  113. data/scripts/publish_html.sh +0 -99
@@ -1,251 +0,0 @@
1
- require "json"
2
- require "pathname"
3
- require "asciidoctor"
4
- require "asciidoctor/extensions"
5
- require_relative "./utils"
6
-
7
- # put the indexing in the giblish namespace
8
- module Giblish
9
- # This hook is called by Asciidoctor once for each document _before_
10
- # Asciidoctor processes the adoc content.
11
- #
12
- # It indexes all headings found in all documents in the tree.
13
- # The resulting index can be serialized to a JSON file
14
- # with the following format:
15
- #
16
- # {
17
- # file_infos : [{
18
- # filepath : filepath_1,
19
- # title : Title,
20
- # sections : [{
21
- # id : section_id_1,
22
- # title : section_title_1,
23
- # line_no : line_no
24
- # },
25
- # {
26
- # id : section_id_1,
27
- # title : section_title_1,
28
- # line_no : line_no
29
- # },
30
- # ...
31
- # ]
32
- # },
33
- # {
34
- # filepath : filepath_1,
35
- # ...
36
- # }]
37
- # }
38
- class IndexHeadings < Asciidoctor::Extensions::Preprocessor
39
- # Use a class-global heading_index dict since asciidoctor creates a new instance
40
- # of this class for each processed file
41
- @heading_index = { "file_infos" => [] }
42
-
43
- # prio order:
44
- # 1. values in this hash
45
- # 2. values taken from the document
46
- # 3. default values
47
- @id_elements = {
48
- # prefix: "_",
49
- # separator: "_"
50
- }
51
-
52
- class << self
53
- attr_accessor :id_elements
54
-
55
- attr_reader :heading_index
56
-
57
- def clear_index
58
- @heading_index = { "file_infos" => [] }
59
- end
60
-
61
- # write the index to a file in dst_dir and remove the base_dir
62
- # part of the path for each filename
63
- def serialize(dst_dir, base_dir = "")
64
- dst_dir = Pathname.new(dst_dir) unless dst_dir.respond_to?(:join)
65
- base_dir = Pathname.new(base_dir) unless base_dir.respond_to?(:join)
66
-
67
- if base_dir.to_s.empty?
68
- heading_index
69
- else
70
- # remove the base_dir part of the file path
71
- heading_index["file_infos"].each do |file_info|
72
- file_info["filepath"] = Pathname.new(file_info["filepath"])
73
- .relative_path_from(base_dir)
74
- end
75
- end
76
-
77
- Giblog.logger.info { "writing json to #{dst_dir.join('heading_index.json')}" }
78
- File.open(dst_dir.join("heading_index.json").to_s, "w") do |f|
79
- f.write(heading_index.to_json)
80
- end
81
- end
82
- end
83
-
84
- def process(document, reader)
85
- # Add doc as a source dependency for doc ids
86
- src_path = document.attributes["docfile"]
87
-
88
- # Note: the nil check is there to prevent us adding generated
89
- # asciidoc docs that does not exist in the file system (e.g. the
90
- # generated index pages). This is a bit hackish and should maybe be
91
- # done differently
92
- return if src_path.nil?
93
-
94
- # get the title from thw raw text (asciidoctor has not yet
95
- # processed the text)
96
- title = find_title reader.lines
97
-
98
- # make sure we use the correct id elements when indexing
99
- # sections
100
- opts = find_id_attributes(reader.lines)
101
-
102
- # Index all headings in the doc
103
- Giblog.logger.debug { "indexing headings in #{src_path}" }
104
- sections = []
105
- file_info_hash = {
106
- "filepath" => src_path,
107
- "title" => title,
108
- "sections" => sections
109
- }
110
-
111
- index_sections(reader, file_info_hash, opts)
112
-
113
- heading_index["file_infos"] << file_info_hash
114
- reader
115
- end
116
-
117
- private
118
-
119
- # build the 'sections' array
120
- def index_sections(reader, file_info_hash, opts)
121
- sections = file_info_hash["sections"]
122
-
123
- heading_regex = Regexp.new(/^=+\s+(.*)$/)
124
- anchor_regex = Regexp.new(/^\[\[(\w+)\]\]\s*$/)
125
-
126
- line_no = 0
127
- m = nil
128
- match_str = ""
129
- state = :text
130
- reader.lines.each do |line|
131
- line_no += 1
132
- # implement a state machine that supports both custom
133
- # anchors for a heading and the default heading ids generated
134
- # by asciidoctor
135
- case state
136
- when :text
137
- m = heading_regex.match(line)
138
- if m
139
- state = :heading
140
- match_str = m[1]
141
- else
142
- m = anchor_regex.match(line)
143
- if m
144
- state = :expecting_heading
145
- match_str = m[1]
146
- end
147
- end
148
- when :expecting_heading
149
- m = heading_regex.match(line)
150
- if m
151
- # we have an anchor and got a heading as expected, index it
152
- section = { "id" => match_str }
153
- section["title"] = m[1].strip
154
- section["line_no"] = line_no
155
- sections << section
156
- else
157
- Giblog.logger.debug do
158
- "Did not index the anchor: #{match_str} at "\
159
- "line #{line_no}, probably not associated "\
160
- "with a heading."
161
- end
162
- end
163
- state = :text
164
- when :heading
165
- # we got a heading without an accompanying anchor, index it
166
- section = { "id" => get_unique_id(file_info_hash, match_str, opts) }
167
- section["title"] = m[1].strip
168
- section["line_no"] = line_no
169
- sections << section
170
- state = :text
171
- end
172
- end
173
- end
174
-
175
- def find_title(lines)
176
- title = "No title Found!"
177
- Giblish.process_header_lines(lines) do |line|
178
- m = /^=+(.*)$/.match(line)
179
- if m
180
- # We found a decent title
181
- title = m[1].strip
182
- end
183
- end
184
- title
185
- end
186
-
187
- # id elements prio:
188
- # 1. values in class variable
189
- # 2. values taken from doc
190
- # 3. default values
191
- def find_id_attributes(lines)
192
- result = {}
193
- # prio 1
194
- result[:id_prefix] = IndexHeadings.id_elements.fetch(:id_prefix, nil)
195
- result[:id_separator] = IndexHeadings.id_elements.fetch(:id_separator, nil)
196
- return result if result[:id_prefix] && result[:id_separator]
197
-
198
- # prio 2
199
- # check if the doc specifies id attributes
200
- Giblish.process_header_lines(lines) do |line|
201
- m = /^:idprefix:(.*)$/.match(line)
202
- n = /^:idseparator:(.*)$/.match(line)
203
- if m && !result[:id_prefix]
204
- # We found a id prefix
205
- result[:id_prefix] = m[1].strip
206
- end
207
- if n && !result[:id_separator]
208
- # We found a id separator
209
- result[:id_separator] = n[1].strip
210
- end
211
- end
212
-
213
- # prio 3
214
- # default values
215
- result[:id_prefix] = "_" unless result[:id_prefix]
216
- result[:id_separator] = "_" unless result[:id_separator]
217
- result
218
- end
219
-
220
- def get_unique_id(doc_heading_dict, heading_str, opts)
221
- id_base = Giblish.to_valid_id(heading_str, opts[:id_prefix], opts[:id_separator])
222
- return id_base unless doc_heading_dict.key? id_base
223
-
224
- # handle the case with several sections with the same name
225
- idx = 1
226
- heading_id = ""
227
- loop do
228
- idx += 1
229
- heading_id = "#{id_base}_#{idx}"
230
- # some code here
231
- break unless doc_heading_dict.key? heading_id
232
- end
233
- heading_id
234
- end
235
-
236
- # Helper method to shorten calls to the heading_index from instance methods
237
- def heading_index
238
- self.class.heading_index
239
- end
240
- end
241
-
242
- # Helper method to register the docid preprocessor extension with
243
- # the asciidoctor engine.
244
- def register_index_heading_extension
245
- Asciidoctor::Extensions.register do
246
- preprocessor IndexHeadings
247
- end
248
- end
249
-
250
- module_function :register_index_heading_extension
251
- end
@@ -1,459 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require "pathname"
4
- require "json"
5
- require "asciidoctor"
6
- require "open3"
7
- require "cgi"
8
- require "uri"
9
-
10
- class GrepDocTree
11
- Line_info = Struct.new(:line, :line_no) {
12
- def initialize(line, line_no)
13
- self.line = line
14
- self.line_no = Integer(line_no)
15
- end
16
- }
17
-
18
- # grep_opts:
19
- # :search_top
20
- # :search_phrase
21
- # :ignorecase
22
- # :useregexp
23
- def initialize(grep_opts)
24
- @grep_opts = "-nHr --include '*.adoc' "
25
- @grep_opts += "-i " if grep_opts[:ignorecase]
26
- @grep_opts += "-F " unless grep_opts[:useregexp]
27
-
28
- @search_root = grep_opts[:searchassetstop]
29
- @input = grep_opts[:search_phrase]
30
-
31
- @output = ""
32
- @error = ""
33
- @status = 0
34
- @match_index = {}
35
- end
36
-
37
- def grep
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=\""
40
- @grep_opts += " --color=always"
41
-
42
-
43
- @output, @error, @status = Open3.capture3("#{grep_env} grep #{@grep_opts} \"#{@input}\" #{@search_root}")
44
-
45
- begin
46
- @output.force_encoding(Encoding::UTF_8)
47
- @output.gsub!(/\x1b\[01m\x1b\[K/, "##")
48
- @output.gsub!(/\x1b\[m\x1b\[K/, "##")
49
- rescue StandardError => e
50
- print e.message
51
- print e.backtrace.inspect
52
- exit 0
53
- end
54
-
55
- grep2hash @search_root
56
- end
57
-
58
- # returns an indexed output where each match from the search is associated with the
59
- # corresponding src file's closest heading.
60
- # the format of the output:
61
- # {html_filename#heading : [line_1, line_2, ...], ...}
62
- #
63
- # The heading_db has the following JSON format
64
- # {
65
- # file_infos : [{
66
- # filepath : filepath_1,
67
- # title : Title,
68
- # sections : [{
69
- # id : section_id_1,
70
- # title : section_title_1,
71
- # line_no : line_no
72
- # },
73
- # {
74
- # id : section_id_1,
75
- # title : section_title_1,
76
- # line_no : line_no
77
- # },
78
- # ...
79
- # ]
80
- # },
81
- # {
82
- # filepath : filepath_1,
83
- # ...
84
- # }]
85
- # }
86
- def match_with_headings heading_db
87
- matches = []
88
-
89
- # for each file with at least one match
90
- @match_index.each do |file_path, match_infos|
91
- # assume that max one file with the specified path
92
- # exists
93
- files = heading_db["file_infos"].select do |fi|
94
- fi["filepath"] == file_path.to_s
95
- end
96
- next if files.empty?
97
-
98
- file_anchors = construct_user_info files.first, match_infos
99
- matches << file_anchors
100
- end
101
- matches
102
- end
103
-
104
- # Produce a hash with all info needed for the user to navigate to the
105
- # matching html section for all matches to the file in the supplied file
106
- # info hash.
107
- #
108
- # format of the resulting hash:
109
- # {
110
- # filepath : Filepath,
111
- # title : Title,
112
- # matches : {
113
- # section_id :
114
- # {
115
- # section_title : Section Title,
116
- # location : Location,
117
- # lines : [line_1, line_2, ...]
118
- # }
119
- # }
120
- # ]
121
- # }
122
- #
123
- def construct_user_info file_info, match_infos
124
- matches = {}
125
- file_anchors = {
126
- "filepath" => file_info["filepath"],
127
- "title" => file_info["title"],
128
- "matches" => matches
129
- }
130
-
131
- match_infos.each do |match_info|
132
- match_line_nr = match_info.line_no
133
-
134
- # find section with closest lower line_no to line_info
135
- best_so_far = 0
136
- chosen_section_info = {}
137
- file_info["sections"].each do |section_info|
138
- l = Integer(section_info["line_no"])
139
- if l <= match_line_nr && l > best_so_far
140
- chosen_section_info = section_info
141
- end
142
- end
143
-
144
- matches[chosen_section_info["id"]] =
145
- {
146
- "section_title" => chosen_section_info["title"],
147
- "location" => "#{Pathname.new(file_info["filepath"]).sub_ext(".html").to_s}##{chosen_section_info["id"]}",
148
- "lines" => []
149
- } unless matches.key?(chosen_section_info["id"])
150
- matches[chosen_section_info["id"]]["lines"] << match_info.line
151
- end
152
- file_anchors
153
- end
154
-
155
- def formatted_output
156
- # assume we have an updated index
157
- adoc_str = ""
158
- @match_index.each do |k, v|
159
- adoc_str += "#{k}::\n"
160
- v.each { |line_info|
161
- adoc_str += "#{line_info.line_no} : #{line_info.line}\n"
162
- }
163
- end
164
- adoc_str
165
- end
166
-
167
- private
168
-
169
- # converts the 'raw' matches from grep into a hash.
170
- # i.e. from:
171
- # <filename>:<line_no>:<line>
172
- # <filename>:<line_no>:<line>
173
- # ...
174
- #
175
- # to
176
- # {file_path : [line_info1, line_info2, ...], ...}
177
- def grep2hash(base_dir)
178
- @match_index = {}
179
- @output.split("\n").each do |line|
180
- tokens = line.split(":", 3)
181
-
182
- # remove all lines starting with :<attrib>:
183
- tokens[2].gsub!(/^:[[:graph:]]+:.*$/, "")
184
- next if tokens[2].empty?
185
-
186
- # remove everything above the repo root from the filepath
187
- file_path = Pathname.new(tokens[0]).relative_path_from Pathname.new(base_dir)
188
- @match_index[file_path] = [] unless @match_index.key? file_path
189
- @match_index[file_path] << Line_info.new(tokens[2], tokens[1])
190
- end
191
- end
192
- end
193
-
194
- class SearchDocTree
195
- def initialize(input_data)
196
- @input_data = input_data
197
- end
198
-
199
- def search
200
- # read the heading_db from file
201
- jsonpath = @input_data[:searchassetstop].join("heading_index.json")
202
- json = File.read(jsonpath.to_s)
203
- src_index = JSON.parse(json)
204
-
205
- # search the doc tree for regex
206
- gt = GrepDocTree.new @input_data
207
- gt.grep
208
-
209
- matches = gt.match_with_headings src_index
210
-
211
- format_search_adoc matches, get_uri_top
212
- end
213
-
214
- private
215
-
216
- def get_uri_top
217
- return @input_data[:referer][0, @input_data[:referer].rindex('/')]
218
- end
219
-
220
- def wash_line line
221
- # remove any '::'
222
- result = line.gsub(/::*/, "")
223
- # remove =,| at the start of a line
224
- result.gsub!(/^[=|]+/, "")
225
- result
226
- end
227
-
228
- # index is an array of file_info, see construct_user_info
229
- # for format per file
230
- # == Title (filename)
231
- #
232
- # <<location,section_title>>::
233
- # line_1
234
- # line_2
235
- # ...
236
- def format_search_adoc index, uri_top
237
- str = ""
238
- # debug print referer...
239
- # str << "uri_top: #{uri_top}\n"
240
- index.each do |file_info|
241
- filename = Pathname.new(file_info["filepath"]).basename
242
- str << "== #{file_info["title"]}\n\n"
243
- file_info["matches"].each do |section_id, info|
244
- str << "#{uri_top}/#{info["location"]}[#{info["section_title"]}]::\n\n"
245
- # str << "<<#{info["location"]},#{info["section_title"]}>>::\n\n"
246
- str << "[subs=\"quotes\"]\n"
247
- str << "----\n"
248
- info["lines"].each do |line|
249
- str << "-- #{wash_line(line)}\n"
250
- end.join("\n\n")
251
- str << "----\n"
252
- end
253
- str << "\n"
254
- end
255
-
256
- <<~ADOC
257
- = Search Result
258
-
259
- #{str}
260
- ADOC
261
- end
262
- end
263
-
264
- def init_web_server web_root
265
- require 'webrick'
266
-
267
- root = File.expand_path web_root
268
- puts "Trying to start a WEBrick instance at port 8000 serving files from #{web_root}..."
269
-
270
- server = WEBrick::HTTPServer.new(
271
- :Port => 8000,
272
- :DocumentRoot => root,
273
- :Logger => WEBrick::Log.new("webrick.log", WEBrick::Log::DEBUG)
274
- )
275
-
276
- puts "WEBrick instance now listening to localhost:8000"
277
-
278
- trap 'INT' do
279
- server.shutdown
280
- end
281
-
282
- server.start
283
- end
284
-
285
- def hello_world
286
- require "pp"
287
-
288
- # init a new cgi 'connection'
289
- cgi = CGI.new
290
- print cgi.header
291
- print "<br>"
292
- print "Useful cgi parameters and variables."
293
- print "<br>"
294
- print cgi.public_methods(false).sort
295
- print "<br>"
296
- print "<br>"
297
- print "referer: #{cgi.referer}<br>"
298
- print "path: #{URI(cgi.referer).path}<br>"
299
- print "host: #{cgi.host}<br>"
300
- print "client_sent_topdir: #{cgi["topdir"]}<br>"
301
- print "<br>"
302
- print "client_sent_reldir: #{cgi["reltop"]}<br>"
303
- print "<br>"
304
- print "ENV: "
305
- pp ENV
306
- print "<br>"
307
- end
308
-
309
-
310
- # assume that the file tree looks like this when rendering
311
- # a git branch:
312
- #
313
- # root_dir
314
- # |- index.html (the generated index of rendered git branches and tags)
315
- # |- branch_1_top_dir
316
- # | |- index.html (the generated index of this branch)
317
- # | |- file_1.html
318
- # | |- dir_1
319
- # | | |- file2.html
320
- # |- branch_2_top_dir
321
- # |- branch_x_...
322
- # |- web_assets (only if a custom stylesheet is used...)
323
- # |- search_assets
324
- # | |- branch_1_top_dir
325
- # | |- heading_index.json
326
- # | |- file1.adoc
327
- # | |- dir_1
328
- # | | |- file2.html
329
- # | |- ...
330
- # | |- branch_2_top_dir
331
- # | | ...
332
-
333
- # assume that the file tree looks like this when not
334
- # rendering a git branch:
335
- #
336
- # root_dir
337
- # |- index.html (the generated index of all rendered files)
338
- # |- file_1.html
339
- # |- dir_1
340
- # | |- file2.html
341
- # |...
342
- # |- web_assets (only if a custom stylesheet is used...)
343
- # |- search_assets
344
- # | |- heading_index.json
345
- # | |- file1.adoc
346
- # | |- dir_1
347
- # | | |- file2.html
348
- # | |- ...
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
419
-
420
-
421
- # Usage:
422
- # to start a local web server for development work
423
- # ruby giblish-search.cgi <web_root>
424
- #
425
- # to run as a cgi script via a previously setup web server
426
- # giblish-search.cgi
427
- #
428
- # (note that you might need to rename the script to eg
429
- # giblish-search.cgi or similar depending on your web server
430
- # setup)
431
- #
432
- if __FILE__ == $PROGRAM_NAME
433
-
434
- STDOUT.sync = true
435
- if ARGV.length == 0
436
- # 'Normal' cgi usage, as called from a web server
437
-
438
- # init a new cgi 'connection' and print headers
439
- cgi = CGI.new
440
- print cgi.header
441
- begin
442
- cgi_main(cgi, false)
443
- rescue Exception => e
444
- print e.message
445
- print ""
446
- print e.backtrace
447
- exit 1
448
- end
449
- exit 0
450
- end
451
-
452
- if ARGV.length == 1
453
- # Run a simple web server to test this locally..
454
- # and then create the html docs using:
455
- # giblish -c -m -w <web_root> -r <resource_dir> -s <style_name> -g <git_branch> <src_root> <web_root>
456
- init_web_server ARGV[0]
457
- exit 0
458
- end
459
- end