giblish 0.8.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/unit_tests.yml +30 -0
- data/.gitignore +7 -3
- data/.ruby-version +1 -1
- data/Changelog.adoc +59 -0
- data/README.adoc +261 -0
- data/docs/concepts/text_search.adoc +213 -0
- data/docs/concepts/text_search_im/cgi-search_request.puml +35 -0
- data/docs/concepts/text_search_im/cgi-search_request.svg +397 -0
- data/docs/concepts/text_search_im/search_request.puml +40 -0
- data/docs/concepts/text_search_im/search_request.svg +408 -0
- data/docs/howtos/trigger_generation.adoc +180 -0
- data/docs/{setup_server_assets → howtos/trigger_generation_im}/Render Documents.png +0 -0
- data/docs/{setup_server_assets → howtos/trigger_generation_im}/View Documents.png +0 -0
- data/docs/{setup_server_assets → howtos/trigger_generation_im}/deploy_with_hooks.graphml +0 -0
- data/docs/{setup_server_assets → howtos/trigger_generation_im}/deploy_with_hooks.svg +0 -0
- data/docs/{setup_server_assets → howtos/trigger_generation_im}/deploy_with_jenkins.graphml +0 -0
- data/docs/{setup_server_assets → howtos/trigger_generation_im}/deploy_with_jenkins.svg +0 -0
- data/docs/howtos/trigger_generation_im/docgen_github.puml +51 -0
- data/docs/{setup_server_assets → howtos/trigger_generation_im}/giblish_deployment.graphml +0 -0
- data/docs/howtos/trigger_generation_im/post-receive-example.sh +50 -0
- data/docs/reference/box_flow_spec.adoc +22 -0
- data/docs/reference/search_spec.adoc +185 -0
- data/giblish.gemspec +50 -29
- data/lib/giblish/adocsrc_providers.rb +23 -0
- data/lib/giblish/application.rb +214 -41
- data/lib/giblish/cmdline.rb +273 -259
- data/lib/giblish/config_utils.rb +41 -0
- data/lib/giblish/configurator.rb +163 -0
- data/lib/giblish/conversion_info.rb +120 -0
- data/lib/giblish/docattr_providers.rb +125 -0
- data/lib/giblish/docid/docid.rb +181 -0
- data/lib/giblish/github_trigger/webhook_manager.rb +64 -0
- data/lib/giblish/gitrepos/checkoutmanager.rb +124 -0
- data/lib/giblish/{gititf.rb → gitrepos/gititf.rb} +30 -4
- data/lib/giblish/gitrepos/gitsummary.erb +61 -0
- data/lib/giblish/gitrepos/gitsummaryprovider.rb +78 -0
- data/lib/giblish/gitrepos/history_pb.rb +41 -0
- data/lib/giblish/indexbuilders/d3treegraph.rb +88 -0
- data/lib/giblish/indexbuilders/depgraphbuilder.rb +109 -0
- data/lib/giblish/indexbuilders/dotdigraphadoc.rb +174 -0
- data/lib/giblish/indexbuilders/standard_index.erb +10 -0
- data/lib/giblish/indexbuilders/subtree_indices.rb +132 -0
- data/lib/giblish/indexbuilders/templates/circles.html.erb +111 -0
- data/lib/giblish/indexbuilders/templates/flame.html.erb +61 -0
- data/lib/giblish/indexbuilders/templates/tree.html.erb +366 -0
- data/lib/giblish/indexbuilders/templates/treemap.html.erb +127 -0
- data/lib/giblish/indexbuilders/verbatimtree.rb +94 -0
- data/lib/giblish/pathtree.rb +473 -74
- data/lib/giblish/resourcepaths.rb +150 -0
- data/lib/giblish/search/expand_adoc.rb +55 -0
- data/lib/giblish/search/headingindexer.rb +312 -0
- data/lib/giblish/search/request_manager.rb +110 -0
- data/lib/giblish/search/searchquery.rb +68 -0
- data/lib/giblish/search/textsearcher.rb +349 -0
- data/lib/giblish/subtreeinfobuilder.rb +77 -0
- data/lib/giblish/treeconverter.rb +272 -0
- data/lib/giblish/utils.rb +142 -294
- data/lib/giblish/version.rb +1 -1
- data/lib/giblish.rb +10 -7
- data/scripts/hooks/post-receive.example +66 -0
- data/{docgen/scripts/githook_examples → scripts/hooks}/post-update.example +0 -0
- data/{docgen → scripts}/resources/css/adoc-colony.css +0 -0
- data/scripts/resources/css/giblish-serif.css +419 -0
- data/scripts/resources/css/giblish.css +1979 -419
- data/{docgen → scripts}/resources/fonts/Ubuntu-B.ttf +0 -0
- data/{docgen → scripts}/resources/fonts/Ubuntu-BI.ttf +0 -0
- data/{docgen → scripts}/resources/fonts/Ubuntu-R.ttf +0 -0
- data/{docgen → scripts}/resources/fonts/Ubuntu-RI.ttf +0 -0
- data/{docgen → scripts}/resources/fonts/mplus1p-regular-fallback.ttf +0 -0
- data/{docgen → scripts}/resources/images/giblish_logo.png +0 -0
- data/{docgen → scripts}/resources/images/giblish_logo.svg +0 -0
- data/{docgen → scripts}/resources/themes/giblish.yml +0 -0
- data/scripts/wserv_development.rb +32 -0
- data/web_apps/cgi_search/gibsearch.rb +43 -0
- data/web_apps/gh_webhook_trigger/config.ru +2 -0
- data/web_apps/gh_webhook_trigger/gh_webhook_trigger.rb +73 -0
- data/web_apps/gh_webhook_trigger/public/dummy.txt +3 -0
- data/web_apps/sinatra_search/config.ru +2 -0
- data/web_apps/sinatra_search/public/dummy.txt +3 -0
- data/web_apps/sinatra_search/sinatra_search.rb +34 -0
- data/web_apps/sinatra_search/tmp/restart.txt +0 -0
- metadata +180 -71
- data/.rubocop.yml +0 -7
- data/.travis.yml +0 -3
- data/Changelog +0 -16
- data/Gemfile +0 -4
- data/README.adoc +0 -1
- data/Rakefile +0 -41
- data/bin/console +0 -14
- data/bin/setup +0 -8
- data/data/testdocs/malformed/no_header.adoc +0 -5
- data/data/testdocs/toplevel.adoc +0 -19
- data/data/testdocs/wellformed/adorned_purpose.adoc +0 -17
- data/data/testdocs/wellformed/docidtest/docid_1.adoc +0 -24
- data/data/testdocs/wellformed/docidtest/docid_2.adoc +0 -8
- data/data/testdocs/wellformed/simple.adoc +0 -14
- data/data/testdocs/wellformed/source_highlighting/highlight_source.adoc +0 -38
- data/docgen/resources/css/giblish.css +0 -1979
- data/docgen/scripts/Jenkinsfile +0 -18
- data/docgen/scripts/gen_adoc_org.sh +0 -58
- data/docs/README.adoc +0 -387
- data/docs/setup_server.adoc +0 -202
- data/lib/giblish/buildgraph.rb +0 -216
- data/lib/giblish/buildindex.rb +0 -459
- data/lib/giblish/core.rb +0 -451
- data/lib/giblish/docconverter.rb +0 -308
- data/lib/giblish/docid.rb +0 -180
- data/lib/giblish/docinfo.rb +0 -75
- data/lib/giblish/indexheadings.rb +0 -251
- data/lib/giblish-search.cgi +0 -459
- data/scripts/hooks/post-receive +0 -57
- data/scripts/publish_html.sh +0 -99
data/lib/giblish/utils.rb
CHANGED
@@ -1,18 +1,20 @@
|
|
1
1
|
require "logger"
|
2
2
|
require "pathname"
|
3
3
|
require "fileutils"
|
4
|
+
require "find"
|
4
5
|
|
5
6
|
# The logger used from within giblish
|
6
7
|
class Giblog
|
7
8
|
# Defines the format for log messages from giblish.
|
8
9
|
class GiblogFormatter
|
9
10
|
def call(severity, datetime, _progname, msg)
|
10
|
-
"#{datetime.strftime(
|
11
|
+
"#{datetime.strftime("%H:%M:%S")} #{severity} - #{msg}\n"
|
11
12
|
end
|
12
13
|
end
|
13
14
|
|
14
15
|
# bootstrap the application-wide logger object
|
15
|
-
def self.setup
|
16
|
+
def self.setup(logger = nil)
|
17
|
+
@logger = logger unless logger.nil?
|
16
18
|
return if defined? @logger
|
17
19
|
|
18
20
|
@logger = Logger.new($stdout)
|
@@ -32,13 +34,24 @@ end
|
|
32
34
|
|
33
35
|
# Public: Contains a number of generic utility methods.
|
34
36
|
module Giblish
|
35
|
-
#
|
36
|
-
#
|
37
|
+
# This logger is customized to receive log messages via the Asciidoctor API.
|
38
|
+
# It parses the messages and 'source_location' objects from the Asciidoctor API
|
39
|
+
# into messages using an opinionated format.
|
40
|
+
#
|
41
|
+
# The output is written to both $stdout and an in-memory StringIO instance. The log level
|
42
|
+
# can be set separately for each of these output channels.
|
37
43
|
class AsciidoctorLogger < ::Logger
|
44
|
+
attr_reader :max_severity, :in_mem_storage
|
45
|
+
|
38
46
|
# log formatter specialized for formatting messages from
|
39
|
-
# asciidoctor's stdout
|
47
|
+
# asciidoctor's stdout, handles the different log record types that Asciidoctor
|
48
|
+
# emits
|
40
49
|
class UserInfoFormatter
|
41
|
-
SEVERITY_LABELS = {
|
50
|
+
SEVERITY_LABELS = {"WARN" => "WARNING", "FATAL" => "FAILED"}.freeze
|
51
|
+
|
52
|
+
def call(severity, datetime, progname, msg)
|
53
|
+
%(#{datetime.strftime("%H:%M:%S")} #{progname}: #{SEVERITY_LABELS[severity] || severity}: #{UserInfoFormatter.adoc_to_message(msg)}\n)
|
54
|
+
end
|
42
55
|
|
43
56
|
# The hash that can be emitted as the msg from asciidoctor have the
|
44
57
|
# following format:
|
@@ -49,260 +62,58 @@ module Giblish
|
|
49
62
|
# @path="<only file name>",
|
50
63
|
# @lineno=<src line no>
|
51
64
|
# }
|
52
|
-
def
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
attr_reader :max_severity, :user_info_str
|
73
|
-
|
74
|
-
def initialize(user_info_log_level)
|
75
|
-
super($stdout, progname: "(from asciidoctor)", formatter: UserInfoFormatter.new)
|
76
|
-
@user_info_str = StringIO.new
|
77
|
-
@user_info_logger = ::Logger.new(@user_info_str, formatter: UserInfoFormatter.new, level: user_info_log_level)
|
78
|
-
end
|
79
|
-
|
80
|
-
def add(severity, message = nil, progname = nil)
|
81
|
-
if (severity ||= UNKNOWN) > (@max_severity ||= severity)
|
82
|
-
@max_severity = severity
|
83
|
-
end
|
84
|
-
@user_info_logger.add(severity, message, progname)
|
85
|
-
super
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
# returns the paths to the search assets and web assets
|
90
|
-
# in the deployment machine's file system.
|
91
|
-
class DeploymentPaths
|
92
|
-
attr_reader :web_path
|
93
|
-
|
94
|
-
def initialize(web_path, search_asset_path)
|
95
|
-
@search_assets_path = if search_asset_path.nil?
|
96
|
-
nil
|
97
|
-
else
|
98
|
-
Pathname.new("/#{search_asset_path}").cleanpath
|
99
|
-
end
|
100
|
-
@web_path = if web_path.nil?
|
101
|
-
nil
|
102
|
-
else
|
103
|
-
Pathname.new("/#{web_path}/web_assets").cleanpath
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
def search_assets_path(branch_dir = nil)
|
108
|
-
if branch_dir.nil?
|
109
|
-
@search_assets_path
|
110
|
-
else
|
111
|
-
@search_assets_path.join(branch_dir)
|
65
|
+
def self.adoc_to_message(msg)
|
66
|
+
case msg
|
67
|
+
when ::String
|
68
|
+
msg
|
69
|
+
when ::Hash
|
70
|
+
# asciidoctor seem to emit a hash with the following structure on errors:
|
71
|
+
# :text => String
|
72
|
+
# :source_location => Reader::Cursor with the following props:
|
73
|
+
# dir, file, lineno, path
|
74
|
+
# Only the lineno prop can be trusted when Asciidoctor is used via Giblish
|
75
|
+
#
|
76
|
+
src_loc = msg.fetch(:source_location, nil)
|
77
|
+
err_txt = msg.fetch(:text, "")
|
78
|
+
str = ""
|
79
|
+
str << "Line #{src_loc.lineno} - " if src_loc.lineno
|
80
|
+
str << err_txt
|
81
|
+
str
|
82
|
+
else
|
83
|
+
msg.inspect
|
84
|
+
end
|
112
85
|
end
|
113
86
|
end
|
114
87
|
|
115
|
-
|
116
|
-
end
|
117
|
-
|
118
|
-
# Helper class to ease construction of different paths for input and output
|
119
|
-
# files and directories
|
120
|
-
class PathManager
|
121
|
-
attr_reader :src_root_abs, :dst_root_abs, :resource_dir_abs, :search_assets_abs
|
122
|
-
|
123
|
-
# Public:
|
88
|
+
# The level is one of the standard ::Logger levels
|
124
89
|
#
|
125
|
-
#
|
126
|
-
#
|
127
|
-
#
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
# Make sure that the resource dir exists if user gives a path to it
|
141
|
-
resource_dir && (@resource_dir_abs = Pathname.new(resource_dir).realpath)
|
142
|
-
end
|
143
|
-
|
144
|
-
def search_assets_abs=(path)
|
145
|
-
if path.nil?
|
146
|
-
@search_assets_abs = nil
|
147
|
-
return
|
148
|
-
end
|
149
|
-
# Make sure that the destination root exists and expand it to an
|
150
|
-
# absolute path
|
151
|
-
dir = Pathname.new(path)
|
152
|
-
dir.mkpath
|
153
|
-
@search_assets_abs = dir.realpath
|
90
|
+
# stdout_level:: the log level to use for gating the messages to stdout
|
91
|
+
# string_level:: the log level to use for gating the messages to the in-memory string.
|
92
|
+
# defaults to 'stdout_level' if not set.
|
93
|
+
def initialize(user_logger, string_level = nil)
|
94
|
+
# def initialize(stdout_level, string_level = nil)
|
95
|
+
string_level = stdout_level if string_level.nil?
|
96
|
+
@user_logger = user_logger
|
97
|
+
|
98
|
+
@max_severity = UNKNOWN
|
99
|
+
|
100
|
+
# create a new, internal logger that echos messages to an in-memory string
|
101
|
+
@in_mem_storage = StringIO.new
|
102
|
+
# @in_mem_logger = ::Logger.new(@in_mem_storage, formatter: UserInfoFormatter.new, level: string_level)
|
103
|
+
super(@in_mem_storage, progname: "(asciidoctor)", formatter: UserInfoFormatter.new, level: string_level)
|
154
104
|
end
|
155
105
|
|
156
|
-
def
|
157
|
-
#
|
158
|
-
|
159
|
-
Pathname.new(dst_root).mkpath
|
160
|
-
@dst_root_abs = Pathname.new(dst_root).realpath
|
161
|
-
end
|
106
|
+
def add(severity, message = nil, progname = nil, &block)
|
107
|
+
# add message to adoc log
|
108
|
+
super(severity, message.dup, progname)
|
162
109
|
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
def reldir_from_src_root(in_path)
|
168
|
-
p = self.class.closest_dir in_path
|
169
|
-
p.relative_path_from(@src_root_abs)
|
170
|
-
end
|
171
|
-
|
172
|
-
# Public: Get the relative path from the
|
173
|
-
# directory where the supplied path points to
|
174
|
-
# the src root dir
|
175
|
-
#
|
176
|
-
# path - an absolute or relative path to a file or dir
|
177
|
-
def reldir_to_src_root(path)
|
178
|
-
src = self.class.closest_dir path
|
179
|
-
@src_root_abs.relative_path_from(src)
|
180
|
-
end
|
181
|
-
|
182
|
-
# Public: Get the relative path from the dst root dir to the
|
183
|
-
# directory where the supplied path points.
|
184
|
-
#
|
185
|
-
# path - an absolute or relative path to a file or dir
|
186
|
-
def reldir_from_dst_root(path)
|
187
|
-
dst = self.class.closest_dir path
|
188
|
-
dst.relative_path_from(@dst_root_abs)
|
189
|
-
end
|
190
|
-
|
191
|
-
# Public: Get the relative path from the
|
192
|
-
# directory where the supplied path points to
|
193
|
-
# the dst root dir
|
194
|
-
#
|
195
|
-
# path - an absolute or relative path to a file or dir
|
196
|
-
def reldir_to_dst_root(path)
|
197
|
-
dst = self.class.closest_dir path
|
198
|
-
@dst_root_abs.relative_path_from(dst)
|
199
|
-
end
|
110
|
+
# add message to user log (wierd interface... see Logger::add(...))
|
111
|
+
message = yield if block
|
112
|
+
message ||= progname
|
113
|
+
@user_logger&.add(severity, "(asciidoctor) #{UserInfoFormatter.adoc_to_message(message)}")
|
200
114
|
|
201
|
-
|
202
|
-
|
203
|
-
def dst_abs_from_src_abs(src_path)
|
204
|
-
src_abs = (self.class.to_pathname src_path).realpath
|
205
|
-
src_rel = reldir_from_src_root src_abs
|
206
|
-
@dst_root_abs.join(src_rel)
|
207
|
-
end
|
208
|
-
|
209
|
-
# return the relative path from a generated document to
|
210
|
-
# the supplied folder given the corresponding absolute source
|
211
|
-
# file path
|
212
|
-
def relpath_to_dir_after_generate(src_filepath, dir_path)
|
213
|
-
dst_abs = dst_abs_from_src_abs(src_filepath)
|
214
|
-
dir = self.class.to_pathname(dir_path)
|
215
|
-
dir.relative_path_from(dst_abs)
|
216
|
-
end
|
217
|
-
|
218
|
-
def adoc_output_file(infile_path, extension)
|
219
|
-
# Get absolute source dir path
|
220
|
-
src_dir_abs = self.class.closest_dir infile_path
|
221
|
-
|
222
|
-
# Get relative path from source root dir
|
223
|
-
src_dir_rel = src_dir_abs.relative_path_from(@src_root_abs)
|
224
|
-
|
225
|
-
# Get the destination path relative the absolute source
|
226
|
-
# root
|
227
|
-
dst_dir_abs = @dst_root_abs.realpath.join(src_dir_rel)
|
228
|
-
|
229
|
-
# return full file path with correct extension
|
230
|
-
dst_dir_abs + get_new_basename(infile_path, extension)
|
231
|
-
end
|
232
|
-
|
233
|
-
# Public: Get the path to the directory where to generate the given
|
234
|
-
# file. The path is given as the relative path from the source adoc
|
235
|
-
# file to the desired output directory (required by the Asciidoctor
|
236
|
-
# API).
|
237
|
-
#
|
238
|
-
# infile_path - a string or Pathname containing the absolute path of the
|
239
|
-
# source adoc file
|
240
|
-
#
|
241
|
-
# Returns: a Pathname with the relative path from the source file to the
|
242
|
-
# output directory
|
243
|
-
def adoc_output_dir(infile_path)
|
244
|
-
# Get absolute source dir path
|
245
|
-
src_abs = self.class.closest_dir infile_path
|
246
|
-
|
247
|
-
# Get relative path from source root dir
|
248
|
-
src_rel = src_abs.relative_path_from(@src_root_abs)
|
249
|
-
|
250
|
-
# Get the destination path relative the absolute source
|
251
|
-
# root
|
252
|
-
dst_abs = @dst_root_abs.realpath.join(src_rel)
|
253
|
-
dst_abs.relative_path_from(src_abs)
|
254
|
-
end
|
255
|
-
|
256
|
-
# return a pathname, regardless if the given path is a Pathname or
|
257
|
-
# a string
|
258
|
-
def self.to_pathname(path)
|
259
|
-
path.is_a?(Pathname) ? path : Pathname.new(path)
|
260
|
-
end
|
261
|
-
|
262
|
-
# Public: Get the basename for a file by replacing the file
|
263
|
-
# extention of the source file with the supplied one.
|
264
|
-
#
|
265
|
-
# src_filepath - the full path of the source file
|
266
|
-
# file_ext - the file extention of the resulting file name
|
267
|
-
#
|
268
|
-
# Example
|
269
|
-
#
|
270
|
-
# Giblish::PathManager.get_new_basename(
|
271
|
-
# "/my/old/file.txt","pdf") => "file.pdf"
|
272
|
-
#
|
273
|
-
# Returns: the basename of a file that uses the supplied file extention.
|
274
|
-
def self.get_new_basename(src_filepath, file_ext)
|
275
|
-
p = Pathname.new src_filepath
|
276
|
-
newname = p.basename.to_s.reverse.sub(p.extname.reverse, ".").reverse
|
277
|
-
newname << file_ext
|
278
|
-
end
|
279
|
-
|
280
|
-
# Public: Return the absolute path to the closest directory (defined as
|
281
|
-
# - the parent dir when called with an existing file
|
282
|
-
# - the directory itself when called with an existing directory
|
283
|
-
# - the parent dir when called with a non-existing file/directory
|
284
|
-
def self.closest_dir(in_path)
|
285
|
-
sr = to_pathname(in_path)
|
286
|
-
if sr.exist?
|
287
|
-
sr.directory? ? sr.realpath : sr.dirname.realpath
|
288
|
-
else
|
289
|
-
sr.parent.expand_path
|
290
|
-
end
|
291
|
-
end
|
292
|
-
|
293
|
-
# Public: Find the root directory of the git repo in which the
|
294
|
-
# given dirpath resides.
|
295
|
-
#
|
296
|
-
# dirpath - a relative or absolute path to a directory that resides
|
297
|
-
# within a git repo.
|
298
|
-
#
|
299
|
-
# Returns: the root direcotry of the git repo or nil if the input path
|
300
|
-
# does not reside within a git repo.
|
301
|
-
def self.find_gitrepo_root(dirpath)
|
302
|
-
Pathname.new(dirpath).realpath.ascend do |p|
|
303
|
-
git_dir = p.join(".git")
|
304
|
-
return p if git_dir.directory?
|
305
|
-
end
|
115
|
+
# update the maximum severity received by this logger
|
116
|
+
@max_severity = severity if severity != UNKNOWN && severity > @max_severity
|
306
117
|
end
|
307
118
|
end
|
308
119
|
|
@@ -313,13 +124,15 @@ module Giblish
|
|
313
124
|
# ex:
|
314
125
|
# process_header_lines(file_path) do |line|
|
315
126
|
# if line == "Quack!"
|
316
|
-
#
|
127
|
+
# myvar = "Donald!"
|
317
128
|
# 1
|
318
129
|
# else
|
319
130
|
# nil
|
320
131
|
# end
|
321
132
|
# end
|
322
|
-
def process_header_lines(lines)
|
133
|
+
def process_header_lines(lines, &block)
|
134
|
+
return unless block
|
135
|
+
|
323
136
|
state = "before_header"
|
324
137
|
lines.each do |line|
|
325
138
|
case state
|
@@ -338,15 +151,17 @@ module Giblish
|
|
338
151
|
# ex:
|
339
152
|
# process_header_lines_from_file(file_path) do |line|
|
340
153
|
# if line == "Quack!"
|
341
|
-
#
|
154
|
+
# myvar = "Donald!"
|
342
155
|
# 1
|
343
156
|
# else
|
344
157
|
# nil
|
345
158
|
# end
|
346
159
|
# end
|
347
|
-
def process_header_lines_from_file(path)
|
160
|
+
def process_header_lines_from_file(path, &block)
|
161
|
+
return unless block
|
162
|
+
|
348
163
|
lines = File.readlines(path)
|
349
|
-
process_header_lines(lines, &
|
164
|
+
process_header_lines(lines, &block)
|
350
165
|
end
|
351
166
|
module_function :process_header_lines_from_file
|
352
167
|
|
@@ -363,9 +178,15 @@ module Giblish
|
|
363
178
|
module_function :with_captured_stderr
|
364
179
|
|
365
180
|
# transforms strings to valid asciidoctor id strings
|
366
|
-
|
181
|
+
# in some cases you want to add a semi-unique checksum. If you do, you are no longer
|
182
|
+
# compatible with asciidoctor's generated ids
|
183
|
+
def to_valid_id(input_str, id_prefix = "_", id_separator = "_", use_checksum = false)
|
184
|
+
# use a basic checksum to reduce the risk for duplicate ids
|
185
|
+
check_sum = use_checksum ? input_str.chars.reduce(0) { |sum, c| sum + c.ord } : ""
|
186
|
+
|
367
187
|
id_str = input_str.strip.downcase.gsub(/[^a-z0-9]+/, id_separator)
|
368
|
-
id_str = "#{id_prefix}#{id_str}"
|
188
|
+
id_str = "#{id_prefix}#{check_sum}#{id_prefix}#{id_str}"
|
189
|
+
id_str.gsub!(/#{Regexp.quote(id_separator)}+/, id_separator)
|
369
190
|
id_str.chomp(id_separator)
|
370
191
|
end
|
371
192
|
module_function :to_valid_id
|
@@ -387,44 +208,71 @@ module Giblish
|
|
387
208
|
end
|
388
209
|
module_function :which
|
389
210
|
|
390
|
-
#
|
391
|
-
#
|
211
|
+
# Convert a string into a string where all characters forbidden as part of
|
212
|
+
# filenames are replaced by an underscore '_'.
|
392
213
|
#
|
393
|
-
#
|
394
|
-
#
|
395
|
-
#
|
396
|
-
#
|
397
|
-
#
|
398
|
-
#
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
#
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
<button id="search" type="submit"><i class="fa fa-search"></i></button>
|
413
|
-
<br>
|
214
|
+
# returns:: a String most likely a valid filename in windows & linux
|
215
|
+
#
|
216
|
+
# A comprehensive list of forbidden chars in different file systems can be
|
217
|
+
# found here: https://stackoverflow.com/a/31976060
|
218
|
+
# In short, chars forbidden in any of Windows and Linux are:
|
219
|
+
# / < > : " \\ | ? *
|
220
|
+
def to_fs_str(str)
|
221
|
+
# printable chars -> '_'
|
222
|
+
tmp = str.gsub(/[\/<>:"\\|?*]/, "_")
|
223
|
+
# non-printable chars -> '_'
|
224
|
+
tmp.gsub!(/[\x00-\x1F]/, "_")
|
225
|
+
# remove heading/trailing spaces
|
226
|
+
tmp.strip!
|
227
|
+
# Windows disallows files ending in '.'
|
228
|
+
tmp += "_" if tmp.end_with?(".")
|
229
|
+
|
230
|
+
tmp
|
231
|
+
end
|
232
|
+
module_function :to_fs_str
|
414
233
|
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
234
|
+
# Break a line into rows of max_length, using '-' semi-intelligently
|
235
|
+
# to split words if needed
|
236
|
+
#
|
237
|
+
# return:: an Array with the resulting rows
|
238
|
+
def break_line(line, max_length)
|
239
|
+
too_short = 3
|
240
|
+
return [line] if line.length <= too_short
|
241
|
+
raise ArgumentError, "max_length must be larger than #{too_short - 1}" if max_length < too_short
|
242
|
+
|
243
|
+
rows = []
|
244
|
+
row = ""
|
245
|
+
|
246
|
+
until line.empty?
|
247
|
+
word, _sep, _remaining = line.strip.partition(" ")
|
248
|
+
row_space = max_length - row.length
|
249
|
+
|
250
|
+
# start word with a space if row is not empty
|
251
|
+
sep = row.empty? ? "" : " "
|
252
|
+
|
253
|
+
# if word fits in row, just insert it and take next word
|
254
|
+
if row_space - (word.length + sep.length) >= 0
|
255
|
+
row = "#{row}#{sep}#{word}"
|
256
|
+
line = line.sub(word, "").strip
|
257
|
+
next
|
258
|
+
end
|
420
259
|
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
260
|
+
# shall we split word or just move it to next row?
|
261
|
+
if (row_space == max_length && word.length > row_space) ||
|
262
|
+
(word.length > too_short && (row_space > too_short) && (word.length - row_space).abs > too_short)
|
263
|
+
# we will split the word, using a '-'
|
264
|
+
first_part = word[0..row_space - (1 + sep.length)]
|
265
|
+
row = "#{row}#{sep}#{first_part}-"
|
266
|
+
line = line.sub(first_part, "").strip
|
267
|
+
end
|
426
268
|
|
427
|
-
|
269
|
+
# start a new row
|
270
|
+
rows << row
|
271
|
+
row = ""
|
272
|
+
end
|
273
|
+
# need to add unfinished row if any
|
274
|
+
rows << row unless row.empty?
|
275
|
+
rows
|
428
276
|
end
|
429
|
-
module_function :
|
277
|
+
module_function :break_line
|
430
278
|
end
|
data/lib/giblish/version.rb
CHANGED
data/lib/giblish.rb
CHANGED
@@ -1,18 +1,21 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
if /^2/.match?(RUBY_VERSION)
|
3
|
+
# suppress warnings for 'experimental' pattern matching
|
4
|
+
# for ruby versions < 3.x
|
5
|
+
require "warning"
|
6
|
+
Warning.ignore(/Pattern matching/)
|
7
|
+
end
|
2
8
|
|
3
9
|
require_relative "giblish/version"
|
4
|
-
require_relative "giblish/utils"
|
5
|
-
require_relative "giblish/core"
|
6
|
-
require_relative "giblish/buildindex"
|
7
|
-
require_relative "giblish/cmdline"
|
8
|
-
require_relative "giblish/pathtree"
|
9
10
|
require_relative "giblish/application"
|
11
|
+
require_relative "giblish/search/request_manager"
|
12
|
+
require_relative "giblish/github_trigger/webhook_manager"
|
10
13
|
|
11
14
|
module Giblish
|
15
|
+
# The main entry point to the giblish application
|
12
16
|
class << self
|
13
|
-
|
14
17
|
def application
|
15
|
-
@application ||= Giblish::
|
18
|
+
@application ||= Giblish::EntryPoint
|
16
19
|
end
|
17
20
|
end
|
18
21
|
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
#
|
3
|
+
# this hook runs giblish on a document tree according to the
|
4
|
+
# users settings.
|
5
|
+
# Typically used to publish html documents when a push to a matching
|
6
|
+
# branch is detected.
|
7
|
+
|
8
|
+
# the git refs that should trigger a doc generation at update
|
9
|
+
TRIGGERING_REFS_REGEX=$'main'
|
10
|
+
|
11
|
+
# the relative path to a subfolder in the repo where the docs are
|
12
|
+
REPO_DOC_SUBFOLDER="docs"
|
13
|
+
|
14
|
+
# the staging repo root (where the working tree exists)
|
15
|
+
STAGING_REPO="/usr/local/git_staging/rillbert_se_staging"
|
16
|
+
|
17
|
+
# The web-server top dir for the published documents
|
18
|
+
DST_DIR="/var/www/rillbert_se/html/public/docs"
|
19
|
+
|
20
|
+
# path to a top dir of the styling css and other resources
|
21
|
+
RESOURCE_DIR="scripts/resources"
|
22
|
+
|
23
|
+
# the name of the css file to use for styling, without the 'css' extension
|
24
|
+
LAYOUT_STYLE="giblish"
|
25
|
+
|
26
|
+
# "true" runs an 'rm -rf' of the destination dir before generating new htmls
|
27
|
+
CLEAR_DST="true"
|
28
|
+
|
29
|
+
echo "post-receive hook running..."
|
30
|
+
|
31
|
+
# read the input that git sends to this hook
|
32
|
+
read oldrev newrev ref
|
33
|
+
|
34
|
+
# remove the 'refs/heads/' prefix from the git ref
|
35
|
+
ref="${ref/refs\/heads\//}"
|
36
|
+
|
37
|
+
# filter out refs that are irrelevant for doc generation
|
38
|
+
if [[ ! "${ref}" =~ "${TRIGGERING_REFS_REGEX}" ]]; then
|
39
|
+
echo "Ref '${ref}' received. Doing nothing: only refs matching the regex: /${TRIGGERING_REFS_REGEX}/ will trigger a doc generation."
|
40
|
+
exit 0
|
41
|
+
fi
|
42
|
+
|
43
|
+
echo "Document generation triggered by an update to ${ref}."
|
44
|
+
echo ""
|
45
|
+
|
46
|
+
# use a subshell with the correct working dir for the actual doc generation
|
47
|
+
(
|
48
|
+
cd "${STAGING_REPO}"
|
49
|
+
|
50
|
+
# need to unset the GIT_DIR env set by the invoking hook for giblish to work correctly
|
51
|
+
unset GIT_DIR
|
52
|
+
|
53
|
+
if [[ "${CLEAR_DST}" -eq "true" ]]; then
|
54
|
+
echo "Remove everything under ${DST_DIR}/"
|
55
|
+
rm -rf ${DST_DIR}/*
|
56
|
+
fi
|
57
|
+
|
58
|
+
# Generate html docs
|
59
|
+
echo "running giblish..."
|
60
|
+
giblish -a xrefstyle=basic \
|
61
|
+
--copy-asset-folders "_assets$" \
|
62
|
+
-g "${TRIGGERING_REFS_REGEX}" \
|
63
|
+
-r "${RESOURCE_DIR}" \
|
64
|
+
-s "${LAYOUT_STYLE}" \
|
65
|
+
"${REPO_DOC_SUBFOLDER}" "${DST_DIR}"
|
66
|
+
)
|
File without changes
|
File without changes
|