giblish 0.7.6 → 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.
- checksums.yaml +4 -4
- data/.github/workflows/unit_tests.yml +30 -0
- data/.gitignore +7 -3
- data/.ruby-version +1 -1
- data/Changelog.adoc +61 -0
- data/README.adoc +267 -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 +51 -32
- data/lib/giblish/adocsrc_providers.rb +23 -0
- data/lib/giblish/application.rb +213 -37
- 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} +33 -9
- 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 +472 -76
- 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 +167 -321
- 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 +190 -81
- data/.rubocop.yml +0 -8
- 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 -218
- data/lib/giblish/buildindex.rb +0 -464
- data/lib/giblish/core.rb +0 -442
- data/lib/giblish/docconverter.rb +0 -310
- data/lib/giblish/docid.rb +0 -188
- data/lib/giblish/docinfo.rb +0 -100
- data/lib/giblish/indexheadings.rb +0 -255
- 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,23 +1,27 @@
|
|
1
1
|
require "logger"
|
2
2
|
require "pathname"
|
3
3
|
require "fileutils"
|
4
|
+
require "find"
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
|
6
|
+
# The logger used from within giblish
|
7
|
+
class Giblog
|
8
|
+
# Defines the format for log messages from giblish.
|
9
|
+
class GiblogFormatter
|
10
|
+
def call(severity, datetime, _progname, msg)
|
11
|
+
"#{datetime.strftime("%H:%M:%S")} #{severity} - #{msg}\n"
|
12
|
+
end
|
8
13
|
end
|
9
|
-
end
|
10
14
|
|
11
|
-
|
12
|
-
def self.setup
|
15
|
+
# bootstrap the application-wide logger object
|
16
|
+
def self.setup(logger = nil)
|
17
|
+
@logger = logger unless logger.nil?
|
13
18
|
return if defined? @logger
|
14
|
-
|
19
|
+
|
20
|
+
@logger = Logger.new($stdout)
|
15
21
|
@logger.formatter = GiblogFormatter.new
|
16
|
-
# @logger.formatter = proc do |severity, datetime, _progname, msg|
|
17
|
-
# "#{datetime.strftime('%H:%M:%S')} #{severity} - #{msg}\n"
|
18
|
-
# end
|
19
22
|
end
|
20
23
|
|
24
|
+
# returns the application-wide logger instance.
|
21
25
|
def self.logger
|
22
26
|
unless defined? @logger
|
23
27
|
puts "!!!! Error: Trying to access logger before setup !!!!"
|
@@ -28,282 +32,90 @@ class Giblog
|
|
28
32
|
end
|
29
33
|
end
|
30
34
|
|
31
|
-
|
32
|
-
|
33
35
|
# Public: Contains a number of generic utility methods.
|
34
36
|
module Giblish
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
# @file="<full adoc filename>",
|
42
|
-
# @dir="<full src dir>",
|
43
|
-
# @path="<only file name>",
|
44
|
-
# @lineno=<src line no>
|
45
|
-
# }
|
46
|
-
def call severity, datetime, progname, msg
|
47
|
-
message = case msg
|
48
|
-
when ::String
|
49
|
-
msg
|
50
|
-
when ::Hash
|
51
|
-
# asciidoctor seem to emit a hash with error text and source location info
|
52
|
-
# for warnings and errors
|
53
|
-
str = ""
|
54
|
-
str << "Line #{msg[:source_location].lineno.to_s} - " if msg[:source_location]
|
55
|
-
str << "#{msg[:text].to_s}" if msg[:text]
|
56
|
-
str
|
57
|
-
else
|
58
|
-
msg.inspect
|
59
|
-
end
|
60
|
-
%(#{datetime.strftime('%H:%M:%S')} #{progname}: #{SEVERITY_LABELS[severity] || severity}: #{message}\n)
|
61
|
-
end
|
62
|
-
end
|
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.
|
63
43
|
class AsciidoctorLogger < ::Logger
|
44
|
+
attr_reader :max_severity, :in_mem_storage
|
64
45
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
@user_info_str = StringIO.new
|
71
|
-
@user_info_logger = ::Logger.new(@user_info_str, formatter: UserInfoFormatter.new, level: user_info_log_level)
|
72
|
-
end
|
73
|
-
|
74
|
-
def add severity, message = nil, progname = nil
|
75
|
-
if (severity ||= UNKNOWN) > (@max_severity ||= severity)
|
76
|
-
@max_severity = severity
|
77
|
-
end
|
78
|
-
@user_info_logger.add(severity,message,progname)
|
79
|
-
super
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
class DeploymentPaths
|
84
|
-
|
85
|
-
attr_reader :web_path
|
86
|
-
|
87
|
-
def initialize(web_path, search_asset_path)
|
88
|
-
@search_assets_path = if search_asset_path.nil?
|
89
|
-
nil
|
90
|
-
else
|
91
|
-
Pathname.new("/#{search_asset_path.to_s}").cleanpath
|
92
|
-
end
|
93
|
-
@web_path = if web_path.nil?
|
94
|
-
nil
|
95
|
-
else
|
96
|
-
Pathname.new("/#{web_path.to_s}/web_assets").cleanpath
|
97
|
-
end
|
98
|
-
end
|
46
|
+
# log formatter specialized for formatting messages from
|
47
|
+
# asciidoctor's stdout, handles the different log record types that Asciidoctor
|
48
|
+
# emits
|
49
|
+
class UserInfoFormatter
|
50
|
+
SEVERITY_LABELS = {"WARN" => "WARNING", "FATAL" => "FAILED"}.freeze
|
99
51
|
|
100
|
-
|
101
|
-
|
102
|
-
@search_assets_path
|
103
|
-
else
|
104
|
-
@search_assets_path.join(branch_dir)
|
52
|
+
def call(severity, datetime, progname, msg)
|
53
|
+
%(#{datetime.strftime("%H:%M:%S")} #{progname}: #{SEVERITY_LABELS[severity] || severity}: #{UserInfoFormatter.adoc_to_message(msg)}\n)
|
105
54
|
end
|
106
|
-
end
|
107
|
-
|
108
|
-
def search_assets_path=(path)
|
109
|
-
@search_assets_path = path
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
# Helper class to ease construction of different paths for input and output
|
114
|
-
# files and directories
|
115
|
-
class PathManager
|
116
|
-
attr_reader :src_root_abs
|
117
|
-
attr_reader :dst_root_abs
|
118
|
-
attr_reader :resource_dir_abs
|
119
|
-
attr_reader :search_assets_abs
|
120
|
-
|
121
|
-
# Public:
|
122
|
-
#
|
123
|
-
# src_root - a string or pathname with the top directory of the input file
|
124
|
-
# tree
|
125
|
-
# dst_root - a string or pathname with the top directory of the output file
|
126
|
-
# tree
|
127
|
-
# resource_dir - a string or pathname with the directory containing
|
128
|
-
# resources
|
129
|
-
# create_search_asset_dir - true if this instance shall create a dir for storing
|
130
|
-
# search artefacts, false otherwise
|
131
|
-
def initialize(src_root, dst_root, resource_dir = nil,create_search_asset_dir=false)
|
132
|
-
# Make sure that the source root exists in the file system
|
133
|
-
@src_root_abs = Pathname.new(src_root).realpath
|
134
|
-
self.dst_root_abs = dst_root
|
135
|
-
|
136
|
-
self.search_assets_abs = create_search_asset_dir ?
|
137
|
-
@dst_root_abs.join("search_assets") : nil
|
138
|
-
|
139
|
-
# Make sure that the resource dir exists if user gives a path to it
|
140
|
-
resource_dir && (@resource_dir_abs = Pathname.new(resource_dir).realpath)
|
141
|
-
end
|
142
55
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
56
|
+
# The hash that can be emitted as the msg from asciidoctor have the
|
57
|
+
# following format:
|
58
|
+
# {:text=>"...",
|
59
|
+
# :source_location=>#<Asciidoctor::Reader::Cursor:0x000055e65a8729e0
|
60
|
+
# @file="<full adoc filename>",
|
61
|
+
# @dir="<full src dir>",
|
62
|
+
# @path="<only file name>",
|
63
|
+
# @lineno=<src line no>
|
64
|
+
# }
|
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
|
147
85
|
end
|
148
|
-
# Make sure that the destination root exists and expand it to an
|
149
|
-
# absolute path
|
150
|
-
dir = Pathname.new(path)
|
151
|
-
dir.mkpath
|
152
|
-
@search_assets_abs = dir.realpath
|
153
86
|
end
|
154
87
|
|
155
|
-
|
156
|
-
# Make sure that the destination root exists and expand it to an
|
157
|
-
# absolute path
|
158
|
-
Pathname.new(dst_root).mkpath
|
159
|
-
@dst_root_abs = Pathname.new(dst_root).realpath
|
160
|
-
end
|
161
|
-
|
162
|
-
# Public: Get the relative path from the source root dir to the
|
163
|
-
# directory where the supplied path points.
|
164
|
-
#
|
165
|
-
# in_path - an absolute or relative path to a file or dir
|
166
|
-
def reldir_from_src_root(in_path)
|
167
|
-
p = self.class.closest_dir in_path
|
168
|
-
p.relative_path_from(@src_root_abs)
|
169
|
-
end
|
170
|
-
|
171
|
-
# Public: Get the relative path from the
|
172
|
-
# directory where the supplied path points to
|
173
|
-
# the src root dir
|
88
|
+
# The level is one of the standard ::Logger levels
|
174
89
|
#
|
175
|
-
#
|
176
|
-
|
177
|
-
|
178
|
-
|
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)
|
179
104
|
end
|
180
105
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
# path - an absolute or relative path to a file or dir
|
185
|
-
def reldir_from_dst_root(path)
|
186
|
-
dst = self.class.closest_dir path
|
187
|
-
dst.relative_path_from(@dst_root_abs)
|
188
|
-
end
|
106
|
+
def add(severity, message = nil, progname = nil, &block)
|
107
|
+
# add message to adoc log
|
108
|
+
super(severity, message.dup, progname)
|
189
109
|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
# path - an absolute or relative path to a file or dir
|
195
|
-
def reldir_to_dst_root(path)
|
196
|
-
dst = self.class.closest_dir path
|
197
|
-
@dst_root_abs.relative_path_from(dst)
|
198
|
-
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)}")
|
199
114
|
|
200
|
-
|
201
|
-
|
202
|
-
def dst_abs_from_src_abs(src_path)
|
203
|
-
src_abs = (self.class.to_pathname src_path).realpath
|
204
|
-
src_rel = reldir_from_src_root src_abs
|
205
|
-
@dst_root_abs.join(src_rel)
|
115
|
+
# update the maximum severity received by this logger
|
116
|
+
@max_severity = severity if severity != UNKNOWN && severity > @max_severity
|
206
117
|
end
|
207
|
-
|
208
|
-
# return the relative path from a generated document to
|
209
|
-
# the supplied folder given the corresponding absolute source
|
210
|
-
# file path
|
211
|
-
def relpath_to_dir_after_generate(src_filepath,dir_path)
|
212
|
-
dst_abs = dst_abs_from_src_abs(src_filepath)
|
213
|
-
dir = self.class.to_pathname(dir_path)
|
214
|
-
dir.relative_path_from(dst_abs)
|
215
|
-
end
|
216
|
-
|
217
|
-
def adoc_output_file(infile_path, extension)
|
218
|
-
# Get absolute source dir path
|
219
|
-
src_dir_abs = self.class.closest_dir infile_path
|
220
|
-
|
221
|
-
# Get relative path from source root dir
|
222
|
-
src_dir_rel = src_dir_abs.relative_path_from(@src_root_abs)
|
223
|
-
|
224
|
-
# Get the destination path relative the absolute source
|
225
|
-
# root
|
226
|
-
dst_dir_abs = @dst_root_abs.realpath.join(src_dir_rel)
|
227
|
-
|
228
|
-
# return full file path with correct extension
|
229
|
-
dst_dir_abs + get_new_basename(infile_path, extension)
|
230
|
-
end
|
231
|
-
|
232
|
-
# Public: Get the path to the directory where to generate the given
|
233
|
-
# file. The path is given as the relative path from the source adoc
|
234
|
-
# file to the desired output directory (required by the Asciidoctor
|
235
|
-
# API).
|
236
|
-
#
|
237
|
-
# infile_path - a string or Pathname containing the absolute path of the
|
238
|
-
# source adoc file
|
239
|
-
#
|
240
|
-
# Returns: a Pathname with the relative path from the source file to the
|
241
|
-
# output directory
|
242
|
-
def adoc_output_dir(infile_path)
|
243
|
-
# Get absolute source dir path
|
244
|
-
src_abs = self.class.closest_dir infile_path
|
245
|
-
|
246
|
-
# Get relative path from source root dir
|
247
|
-
src_rel = src_abs.relative_path_from(@src_root_abs)
|
248
|
-
|
249
|
-
# Get the destination path relative the absolute source
|
250
|
-
# root
|
251
|
-
dst_abs = @dst_root_abs.realpath.join(src_rel)
|
252
|
-
dst_abs.relative_path_from(src_abs)
|
253
|
-
end
|
254
|
-
|
255
|
-
# return a pathname, regardless if the given path is a Pathname or
|
256
|
-
# a string
|
257
|
-
def self.to_pathname(path)
|
258
|
-
path.is_a?(Pathname) ? path : Pathname.new(path)
|
259
|
-
end
|
260
|
-
|
261
|
-
# Public: Get the basename for a file by replacing the file
|
262
|
-
# extention of the source file with the supplied one.
|
263
|
-
#
|
264
|
-
# src_filepath - the full path of the source file
|
265
|
-
# file_ext - the file extention of the resulting file name
|
266
|
-
#
|
267
|
-
# Example
|
268
|
-
#
|
269
|
-
# Giblish::PathManager.get_new_basename(
|
270
|
-
# "/my/old/file.txt","pdf") => "file.pdf"
|
271
|
-
#
|
272
|
-
# Returns: the basename of a file that uses the supplied file extention.
|
273
|
-
def self.get_new_basename(src_filepath, file_ext)
|
274
|
-
p = Pathname.new src_filepath
|
275
|
-
newname = p.basename.to_s.reverse.sub(p.extname.reverse, ".").reverse
|
276
|
-
newname << file_ext
|
277
|
-
end
|
278
|
-
|
279
|
-
# Public: Return the absolute path to the closest directory (defined as
|
280
|
-
# - the parent dir when called with an existing file
|
281
|
-
# - the directory itself when called with an existing directory
|
282
|
-
# - the parent dir when called with a non-existing file/directory
|
283
|
-
def self.closest_dir(in_path)
|
284
|
-
sr = self.to_pathname(in_path)
|
285
|
-
if sr.exist?
|
286
|
-
sr.directory? ? sr.realpath : sr.dirname.realpath
|
287
|
-
else
|
288
|
-
sr.parent.expand_path
|
289
|
-
end
|
290
|
-
end
|
291
|
-
|
292
|
-
# Public: Find the root directory of the git repo in which the
|
293
|
-
# given dirpath resides.
|
294
|
-
#
|
295
|
-
# dirpath - a relative or absolute path to a directory that resides
|
296
|
-
# within a git repo.
|
297
|
-
#
|
298
|
-
# Returns: the root direcotry of the git repo or nil if the input path
|
299
|
-
# does not reside within a git repo.
|
300
|
-
def self.find_gitrepo_root(dirpath)
|
301
|
-
Pathname.new(dirpath).realpath.ascend do |p|
|
302
|
-
git_dir = p.join(".git")
|
303
|
-
return p if git_dir.directory?
|
304
|
-
end
|
305
|
-
end
|
306
|
-
end # end of PathManager
|
118
|
+
end
|
307
119
|
|
308
120
|
# Helper method that provides the user with a way of processing only the
|
309
121
|
# lines within the asciidoc header block.
|
@@ -312,13 +124,15 @@ module Giblish
|
|
312
124
|
# ex:
|
313
125
|
# process_header_lines(file_path) do |line|
|
314
126
|
# if line == "Quack!"
|
315
|
-
#
|
127
|
+
# myvar = "Donald!"
|
316
128
|
# 1
|
317
129
|
# else
|
318
130
|
# nil
|
319
131
|
# end
|
320
132
|
# end
|
321
|
-
def process_header_lines(lines)
|
133
|
+
def process_header_lines(lines, &block)
|
134
|
+
return unless block
|
135
|
+
|
322
136
|
state = "before_header"
|
323
137
|
lines.each do |line|
|
324
138
|
case state
|
@@ -337,15 +151,17 @@ module Giblish
|
|
337
151
|
# ex:
|
338
152
|
# process_header_lines_from_file(file_path) do |line|
|
339
153
|
# if line == "Quack!"
|
340
|
-
#
|
154
|
+
# myvar = "Donald!"
|
341
155
|
# 1
|
342
156
|
# else
|
343
157
|
# nil
|
344
158
|
# end
|
345
159
|
# end
|
346
|
-
def process_header_lines_from_file(path)
|
160
|
+
def process_header_lines_from_file(path, &block)
|
161
|
+
return unless block
|
162
|
+
|
347
163
|
lines = File.readlines(path)
|
348
|
-
process_header_lines(lines
|
164
|
+
process_header_lines(lines, &block)
|
349
165
|
end
|
350
166
|
module_function :process_header_lines_from_file
|
351
167
|
|
@@ -362,9 +178,15 @@ module Giblish
|
|
362
178
|
module_function :with_captured_stderr
|
363
179
|
|
364
180
|
# transforms strings to valid asciidoctor id strings
|
365
|
-
|
366
|
-
|
367
|
-
|
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
|
+
|
187
|
+
id_str = input_str.strip.downcase.gsub(/[^a-z0-9]+/, id_separator)
|
188
|
+
id_str = "#{id_prefix}#{check_sum}#{id_prefix}#{id_str}"
|
189
|
+
id_str.gsub!(/#{Regexp.quote(id_separator)}+/, id_separator)
|
368
190
|
id_str.chomp(id_separator)
|
369
191
|
end
|
370
192
|
module_function :to_valid_id
|
@@ -375,58 +197,82 @@ module Giblish
|
|
375
197
|
# Ex
|
376
198
|
# which('ruby') #=> /usr/bin/ruby
|
377
199
|
def which(cmd)
|
378
|
-
exts = ENV[
|
379
|
-
ENV[
|
380
|
-
exts.each
|
200
|
+
exts = ENV["PATHEXT"] ? ENV["PATHEXT"].split(";") : [""]
|
201
|
+
ENV["PATH"].split(File::PATH_SEPARATOR).each do |path|
|
202
|
+
exts.each do |ext|
|
381
203
|
exe = File.join(path, "#{cmd}#{ext}")
|
382
204
|
return exe if File.executable?(exe) && !File.directory?(exe)
|
383
|
-
|
205
|
+
end
|
384
206
|
end
|
385
|
-
|
207
|
+
nil
|
386
208
|
end
|
387
209
|
module_function :which
|
388
210
|
|
389
|
-
|
390
|
-
#
|
391
|
-
# acces the text search functionality.
|
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
|
-
<input id="searchphrase" type="text" placeholder="Search.." name="searchphrase"/>
|
413
|
-
<button id="search" type="submit"><i class="fa fa-search"></i></button>
|
414
|
-
<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
|
415
233
|
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
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
|
421
259
|
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
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
|
427
268
|
|
428
|
-
|
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
|
429
276
|
end
|
430
|
-
module_function :
|
431
|
-
|
277
|
+
module_function :break_line
|
432
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
|