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/docconverter.rb
DELETED
@@ -1,308 +0,0 @@
|
|
1
|
-
require "pathname"
|
2
|
-
require "asciidoctor"
|
3
|
-
require "asciidoctor-pdf"
|
4
|
-
|
5
|
-
require_relative "utils"
|
6
|
-
|
7
|
-
module Giblish
|
8
|
-
# Base class for document converters. It contains a hash of
|
9
|
-
# conversion options used by derived classes
|
10
|
-
class DocConverter
|
11
|
-
# a common set of converter options used for all output formats
|
12
|
-
COMMON_CONVERTER_OPTS = {
|
13
|
-
safe: Asciidoctor::SafeMode::UNSAFE,
|
14
|
-
header_footer: true,
|
15
|
-
mkdirs: true
|
16
|
-
}.freeze
|
17
|
-
|
18
|
-
# the giblish attribute defaults used if nothing else
|
19
|
-
# is required by the user
|
20
|
-
DEFAULT_ATTRIBUTES = {
|
21
|
-
"source-highlighter" => "rouge",
|
22
|
-
"xrefstyle" => "short"
|
23
|
-
}.freeze
|
24
|
-
|
25
|
-
# setup common options that are used regardless of the
|
26
|
-
# specific output format used
|
27
|
-
attr_reader :converter_options
|
28
|
-
|
29
|
-
# the path manager used by this converter
|
30
|
-
attr_accessor :paths
|
31
|
-
|
32
|
-
def initialize(paths, deployment_info, options)
|
33
|
-
@paths = paths
|
34
|
-
@deployment_info = deployment_info
|
35
|
-
@user_style = options[:userStyle]
|
36
|
-
@converter_options = COMMON_CONVERTER_OPTS.dup
|
37
|
-
|
38
|
-
# use the default options and override them with options set by
|
39
|
-
# the user if applicable
|
40
|
-
@converter_options[:attributes] = DEFAULT_ATTRIBUTES.dup
|
41
|
-
@converter_options[:attributes].merge!(options[:attributes]) unless options[:attributes].nil?
|
42
|
-
@converter_options[:backend] = options[:backend]
|
43
|
-
|
44
|
-
# give derived classes the opportunity to add options and attributes
|
45
|
-
add_backend_options(@converter_options)
|
46
|
-
add_backend_attributes(@converter_options[:attributes])
|
47
|
-
end
|
48
|
-
|
49
|
-
# Public: Convert one single adoc file using the specific conversion
|
50
|
-
# options.
|
51
|
-
#
|
52
|
-
# filepath - a pathname with the absolute path to the input file to convert
|
53
|
-
#
|
54
|
-
# Returns: The resulting Asciidoctor::Document object
|
55
|
-
def convert(filepath, logger: nil)
|
56
|
-
raise ArgumentError, "Trying to invoke convert with non-pathname!" unless filepath.is_a?(Pathname)
|
57
|
-
|
58
|
-
Giblog.logger.info { "Processing: #{filepath}" }
|
59
|
-
|
60
|
-
# update the relevant options for each specific document
|
61
|
-
set_common_doc_specific_options(filepath, logger)
|
62
|
-
|
63
|
-
# give derived classes the opportunity to set doc specific attributes
|
64
|
-
add_doc_specific_attributes(filepath, true, @converter_options[:attributes])
|
65
|
-
|
66
|
-
Giblog.logger.debug { "converter_options: #{@converter_options}" }
|
67
|
-
|
68
|
-
# do the actual conversion
|
69
|
-
doc = Asciidoctor.convert_file filepath, @converter_options
|
70
|
-
|
71
|
-
# bail out if asciidoctor failed to convert the doc
|
72
|
-
if logger&.max_severity && logger.max_severity > Logger::Severity::WARN
|
73
|
-
raise "Failed to convert the file #{filepath}"
|
74
|
-
end
|
75
|
-
|
76
|
-
doc
|
77
|
-
end
|
78
|
-
|
79
|
-
# converts the supplied string to the file
|
80
|
-
# dst_dir/basename.<backend-ext>
|
81
|
-
#
|
82
|
-
# the supplied string must pass asciidoctor without
|
83
|
-
# any error to stderr, otherwise, nothing will be written
|
84
|
-
# to disk.
|
85
|
-
# Returns: whether any errors occured during conversion (true) or
|
86
|
-
# not (false).
|
87
|
-
def convert_str(src_str, dst_dir, basename, logger: nil)
|
88
|
-
index_opts = @converter_options.dup
|
89
|
-
|
90
|
-
# use the same options as when converting all docs
|
91
|
-
# in the tree but make sure we don't write to file
|
92
|
-
# by trial and error, the following dirs seem to be
|
93
|
-
# necessary to change
|
94
|
-
index_opts[:to_dir] = dst_dir.to_s
|
95
|
-
index_opts[:base_dir] = dst_dir.to_s
|
96
|
-
index_opts.delete_if { |k, _v| %i[to_file].include? k }
|
97
|
-
|
98
|
-
# give derived classes the opportunity to set doc specific attributes
|
99
|
-
index_filepath = dst_dir + "#{basename}.#{index_opts[:fileext]}"
|
100
|
-
add_doc_specific_attributes(index_filepath, false, index_opts[:attributes])
|
101
|
-
|
102
|
-
# load and convert the document using the converter options
|
103
|
-
begin
|
104
|
-
conv_error = false
|
105
|
-
# set a specific logger instance to-be-used by asciidoctor
|
106
|
-
index_opts[:logger] = logger unless logger.nil?
|
107
|
-
doc = Asciidoctor.load src_str, index_opts
|
108
|
-
output = doc.convert index_opts
|
109
|
-
|
110
|
-
if logger&.max_severity && logger.max_severity > Logger::Severity::WARN
|
111
|
-
raise "Failed to convert string to asciidoc!! "\
|
112
|
-
"Will _not_ generate #{index_filepath}"
|
113
|
-
end
|
114
|
-
|
115
|
-
# write the converted document to an index file located at the
|
116
|
-
# destination root
|
117
|
-
doc.write output, index_filepath.to_s
|
118
|
-
rescue StandardError => e
|
119
|
-
puts e.backtrace
|
120
|
-
Giblog.logger.error(e)
|
121
|
-
conv_error = true
|
122
|
-
end
|
123
|
-
|
124
|
-
conv_error
|
125
|
-
end
|
126
|
-
|
127
|
-
protected
|
128
|
-
|
129
|
-
# Hook for specific converters to inject their own options.
|
130
|
-
# The following options must be provided by the derived class:
|
131
|
-
# :fileext - a string with the filename extention to use for the
|
132
|
-
# generated file
|
133
|
-
#
|
134
|
-
# backend_options - the option dict from the backend implementation
|
135
|
-
def add_backend_options(backend_options)
|
136
|
-
@converter_options.merge!(backend_options)
|
137
|
-
end
|
138
|
-
|
139
|
-
# Hook for specific converters to inject their own attributes
|
140
|
-
# valid for all conversions.
|
141
|
-
# backend_attributes - the attribute dict from the backend implementation
|
142
|
-
def add_backend_attributes(backend_attributes)
|
143
|
-
@converter_options[:attributes].merge!(backend_attributes)
|
144
|
-
end
|
145
|
-
|
146
|
-
# Hook for specific converters to inject attributes on a per-doc
|
147
|
-
# basis
|
148
|
-
def add_doc_specific_attributes(filepath, is_src, attributes); end
|
149
|
-
|
150
|
-
private
|
151
|
-
|
152
|
-
def set_common_doc_specific_options(src_filepath, logger)
|
153
|
-
# create an asciidoc doc object and convert to requested
|
154
|
-
# output using current conversion options
|
155
|
-
@converter_options[:to_dir] = @paths.adoc_output_dir(src_filepath).to_s
|
156
|
-
@converter_options[:base_dir] =
|
157
|
-
Giblish::PathManager.closest_dir(src_filepath).to_s
|
158
|
-
@converter_options[:to_file] =
|
159
|
-
Giblish::PathManager.get_new_basename(src_filepath,
|
160
|
-
@converter_options[:fileext])
|
161
|
-
@converter_options[:logger] = logger unless logger.nil?
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
# Converts asciidoc files to html5 output.
|
166
|
-
class HtmlConverter < DocConverter
|
167
|
-
def initialize(paths, deployment_info, options)
|
168
|
-
super paths, deployment_info, options
|
169
|
-
|
170
|
-
# validate that things are ok on the resource front
|
171
|
-
# and copy if needed
|
172
|
-
@dst_asset_dir = @paths.dst_root_abs.join("web_assets")
|
173
|
-
validate_and_copy_resources @dst_asset_dir
|
174
|
-
|
175
|
-
# identify ourselves as an html converter
|
176
|
-
add_backend_options({ backend: "html5", fileext: "html" })
|
177
|
-
# setup the attributes specific for this converter
|
178
|
-
add_backend_attributes(common_attributes)
|
179
|
-
end
|
180
|
-
|
181
|
-
protected
|
182
|
-
|
183
|
-
def add_doc_specific_attributes(filepath, is_src_file, attributes)
|
184
|
-
doc_attrib = {}
|
185
|
-
if @paths.resource_dir_abs
|
186
|
-
# user has given a resource dir, use the css from that dir
|
187
|
-
doc_attrib.merge!(
|
188
|
-
{
|
189
|
-
"linkcss" => 1,
|
190
|
-
"stylesheet" => @user_style ||= "giblish.css",
|
191
|
-
"copycss!" => 1
|
192
|
-
}
|
193
|
-
)
|
194
|
-
if @deployment_info.web_path.nil?
|
195
|
-
# user wants to deploy without web server, the css
|
196
|
-
# link shall thus be the relative path from the
|
197
|
-
# generated doc to the css directory
|
198
|
-
dst_css_dir = @dst_asset_dir.join("css")
|
199
|
-
css_rel_dir = if is_src_file
|
200
|
-
# the filepath is a src path
|
201
|
-
@paths.relpath_to_dir_after_generate(
|
202
|
-
filepath,
|
203
|
-
dst_css_dir
|
204
|
-
)
|
205
|
-
else
|
206
|
-
# the given file path is the destination path of
|
207
|
-
# the generated file, find the relative path to the
|
208
|
-
# css dir
|
209
|
-
dst_dir = PathManager.closest_dir(filepath)
|
210
|
-
dst_css_dir.relative_path_from(dst_dir)
|
211
|
-
end
|
212
|
-
doc_attrib["stylesdir"] = css_rel_dir.to_s
|
213
|
-
else
|
214
|
-
# user has given a web deployment path, the css shall then
|
215
|
-
# be linked using that path
|
216
|
-
doc_attrib["stylesdir"] = @deployment_info.web_path.join("css").cleanpath.to_s
|
217
|
-
end
|
218
|
-
end
|
219
|
-
Giblog.logger.debug { "Rendered docs expect a css at: #{doc_attrib['stylesdir']}" }
|
220
|
-
Giblog.logger.debug { "The expected css is named: #{doc_attrib['stylesheet']}" }
|
221
|
-
|
222
|
-
attributes.merge!(doc_attrib)
|
223
|
-
end
|
224
|
-
|
225
|
-
private
|
226
|
-
|
227
|
-
def common_attributes
|
228
|
-
# Setting 'data-uri' makes asciidoctor embed images in the resulting
|
229
|
-
# html file
|
230
|
-
{
|
231
|
-
"data-uri" => 1
|
232
|
-
}
|
233
|
-
end
|
234
|
-
|
235
|
-
def copy_resource_dir(dst_dir)
|
236
|
-
# create assets_dir and copy everything in the resource dir
|
237
|
-
# to the destination
|
238
|
-
Dir.exist?(dst_dir) || FileUtils.mkdir_p(dst_dir)
|
239
|
-
|
240
|
-
# copy all subdirs that exist in the source tree to the
|
241
|
-
# dst tree
|
242
|
-
%i[css fonts images].each do |dir|
|
243
|
-
src = "#{@paths.resource_dir_abs}/#{dir}"
|
244
|
-
Dir.exist?(src) && FileUtils.copy_entry(src, "#{dst_dir}/#{dir}")
|
245
|
-
end
|
246
|
-
end
|
247
|
-
|
248
|
-
# make as sure as we can that the user has given a
|
249
|
-
# directory with valid resources
|
250
|
-
def validate_and_copy_resources(dst_dir)
|
251
|
-
# we don't have a resource path, which is fine, use
|
252
|
-
# defaults
|
253
|
-
return nil unless @paths.resource_dir_abs
|
254
|
-
|
255
|
-
# If user has requested the use of a specific css, use that,
|
256
|
-
# otherwise use asciidoctor default css
|
257
|
-
if @user_style
|
258
|
-
# Make sure that a user supplied stylesheet ends with .css or .CSS
|
259
|
-
@user_style && @user_style =
|
260
|
-
/\.(css|CSS)$/ =~ @user_style ? @user_style : "#{@user_style}.css"
|
261
|
-
|
262
|
-
# bail out if we can not find the given css file
|
263
|
-
src_css_path = @paths.resource_dir_abs
|
264
|
-
.join("css").join(Pathname.new(@user_style))
|
265
|
-
unless src_css_path.exist?
|
266
|
-
raise "Could not find the specified "\
|
267
|
-
"css file at: #{src_css_path}"
|
268
|
-
end
|
269
|
-
end
|
270
|
-
|
271
|
-
copy_resource_dir dst_dir
|
272
|
-
end
|
273
|
-
end
|
274
|
-
|
275
|
-
# Converts adoc into pdf
|
276
|
-
class PdfConverter < DocConverter
|
277
|
-
def initialize(paths, deployment_info, options)
|
278
|
-
super paths, deployment_info, options
|
279
|
-
require "asciidoctor-mathematical"
|
280
|
-
|
281
|
-
# identify ourselves as a pdf converter
|
282
|
-
add_backend_options({ backend: "pdf", fileext: "pdf" })
|
283
|
-
# setup the attributes specific for this converter
|
284
|
-
add_backend_attributes(setup_pdf_attribs)
|
285
|
-
end
|
286
|
-
|
287
|
-
private
|
288
|
-
|
289
|
-
def setup_pdf_attribs
|
290
|
-
# only set this up if user has specified a resource dir
|
291
|
-
return {} unless @paths.resource_dir_abs
|
292
|
-
|
293
|
-
pdf_attrib = {
|
294
|
-
"pdf-stylesdir" => "#{@paths.resource_dir_abs}/themes",
|
295
|
-
"pdf-style" => "giblish.yml",
|
296
|
-
"pdf-fontsdir" => "#{@paths.resource_dir_abs}/fonts",
|
297
|
-
"icons" => "font"
|
298
|
-
}
|
299
|
-
|
300
|
-
# Make sure that the stylesheet ends with .yml or YML
|
301
|
-
@user_style &&
|
302
|
-
pdf_attrib["pdf-style"] =
|
303
|
-
/\.(yml|YML)$/ =~ @user_style ? @user_style : "#{@user_style}.yml"
|
304
|
-
|
305
|
-
pdf_attrib
|
306
|
-
end
|
307
|
-
end
|
308
|
-
end
|
data/lib/giblish/docid.rb
DELETED
@@ -1,180 +0,0 @@
|
|
1
|
-
require_relative "./utils"
|
2
|
-
require "asciidoctor"
|
3
|
-
require "asciidoctor/extensions"
|
4
|
-
|
5
|
-
# put docid stuff in the giblish namespace
|
6
|
-
module Giblish
|
7
|
-
# Parse all adoc files for :docid: attributes
|
8
|
-
class DocidCollector < Asciidoctor::Extensions::Preprocessor
|
9
|
-
# Use a class-global docid_cache since asciidoctor creates a new instance
|
10
|
-
# for each preprocessor hook
|
11
|
-
# a hash of {doc_id => Pathname(src_path)}
|
12
|
-
@docid_cache = {}
|
13
|
-
|
14
|
-
# A class-global hash of {src_path => [target doc_ids] }
|
15
|
-
@docid_deps = {}
|
16
|
-
|
17
|
-
class << self
|
18
|
-
attr_reader :docid_cache, :docid_deps
|
19
|
-
|
20
|
-
def clear_cache
|
21
|
-
@docid_cache = {}
|
22
|
-
end
|
23
|
-
|
24
|
-
def clear_deps
|
25
|
-
@docid_deps = {}
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
# The minimum number of characters required for a valid doc id
|
30
|
-
ID_MIN_LENGTH = 2
|
31
|
-
|
32
|
-
# The maximum number of characters required for a valid doc id
|
33
|
-
ID_MAX_LENGTH = 10
|
34
|
-
|
35
|
-
# Note: I don't know how to hook into the 'initialize' or if I should
|
36
|
-
# let this be, currently it is disabled...
|
37
|
-
# def initialize(*everything)
|
38
|
-
# super(everything)
|
39
|
-
# end
|
40
|
-
|
41
|
-
# Check if a :docid: <id> entry exists in the header.
|
42
|
-
# According to http://www.methods.co.nz/asciidoc/userguide.html#X95
|
43
|
-
# the header is optional, but if it exists it:
|
44
|
-
# - must start with a titel (=+ <My Title>)
|
45
|
-
# - ends with one or more blank lines
|
46
|
-
# - does not contain any blank line
|
47
|
-
def parse_file(path)
|
48
|
-
Giblog.logger.debug { "parsing file #{path} for docid..." }
|
49
|
-
Giblish.process_header_lines_from_file(path) do |line|
|
50
|
-
m = /^:docid: +(.*)$/.match(line)
|
51
|
-
if m
|
52
|
-
# There is a docid defined, cache the path and doc id
|
53
|
-
validate_and_add m[1], path
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
# add a new source document to the docid_deps
|
59
|
-
def add_source_dep(src_path)
|
60
|
-
return if docid_deps.key? src_path
|
61
|
-
|
62
|
-
docid_deps[src_path] = []
|
63
|
-
end
|
64
|
-
|
65
|
-
# This hook is called by Asciidoctor once for each document _before_
|
66
|
-
# Asciidoctor processes the adoc content.
|
67
|
-
#
|
68
|
-
# It replaces references of the format <<:docid: ID-1234,Hello >> with
|
69
|
-
# references to a resolved relative path.
|
70
|
-
def process(document, reader)
|
71
|
-
# Add doc as a source dependency for doc ids
|
72
|
-
src_path = document.attributes["docfile"]
|
73
|
-
|
74
|
-
# Note: the nil check is there to prevent us adding generated
|
75
|
-
# asciidoc docs that does not exist in the file system (e.g. the
|
76
|
-
# generated index pages). This is a bit hackish and should maybe be
|
77
|
-
# done differently
|
78
|
-
return if src_path.nil?
|
79
|
-
|
80
|
-
add_source_dep src_path
|
81
|
-
|
82
|
-
# Convert all docid refs to valid relative refs
|
83
|
-
reader.lines.each do |line|
|
84
|
-
line.gsub!(/<<\s*:docid:\s*(.*?)>>/) do |_m|
|
85
|
-
# parse the ref
|
86
|
-
target_id, section, display_str =
|
87
|
-
parse_doc_id_ref Regexp.last_match(1)
|
88
|
-
|
89
|
-
# The result is a valid ref in the form
|
90
|
-
# <<target_doc.adoc#[section][,display_str]>>
|
91
|
-
Giblog.logger.debug { "Replace docid ref in doc #{src_path}..." }
|
92
|
-
if docid_cache.key? target_id
|
93
|
-
# add the referenced doc id as a target dependency of this document
|
94
|
-
docid_deps[src_path] << target_id
|
95
|
-
docid_deps[src_path] = docid_deps[src_path].uniq
|
96
|
-
|
97
|
-
# resolve the doc id ref to a valid relative path
|
98
|
-
"<<#{get_rel_path(src_path, target_id)}##{section}#{display_str}>>"
|
99
|
-
else
|
100
|
-
"<<UNKNOWN_DOC, Could not resolve doc id reference !!!>>"
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
104
|
-
reader
|
105
|
-
end
|
106
|
-
|
107
|
-
private
|
108
|
-
|
109
|
-
# Helper method to shorten calls to docid_cache from instance methods
|
110
|
-
def docid_cache
|
111
|
-
self.class.docid_cache
|
112
|
-
end
|
113
|
-
|
114
|
-
def docid_deps
|
115
|
-
self.class.docid_deps
|
116
|
-
end
|
117
|
-
|
118
|
-
# Get the relative path from the src doc to the
|
119
|
-
# doc with the given doc id
|
120
|
-
def get_rel_path(src_path, doc_id)
|
121
|
-
raise ArgumentError("unknown doc id: #{doc_id}") unless docid_cache.key? doc_id
|
122
|
-
|
123
|
-
rel_path = docid_cache[doc_id]
|
124
|
-
.dirname
|
125
|
-
.relative_path_from(Pathname.new(src_path).dirname) +
|
126
|
-
docid_cache[doc_id].basename
|
127
|
-
rel_path.to_s
|
128
|
-
end
|
129
|
-
|
130
|
-
# input_str shall be the expression between
|
131
|
-
# <<:docid:<input_str>>> where the <input_str> is in the form
|
132
|
-
# <id>[#section][,display_str]
|
133
|
-
#
|
134
|
-
# returns an array with [id, section, display_str]
|
135
|
-
def parse_doc_id_ref(input_str)
|
136
|
-
ref, display_str = input_str.split(",").each(&:strip)
|
137
|
-
id, section = ref.split "#"
|
138
|
-
|
139
|
-
display_str = id.dup if display_str.nil?
|
140
|
-
display_str.prepend ","
|
141
|
-
|
142
|
-
section = "" if section.nil?
|
143
|
-
|
144
|
-
[id, section, display_str]
|
145
|
-
end
|
146
|
-
|
147
|
-
# make sure the id is within the designated length and
|
148
|
-
# does not contain a '#' symbol
|
149
|
-
def doc_id_ok?(doc_id)
|
150
|
-
(doc_id.length.between?(ID_MIN_LENGTH, ID_MAX_LENGTH) &&
|
151
|
-
!doc_id.include?("#"))
|
152
|
-
end
|
153
|
-
|
154
|
-
def validate_and_add(doc_id, path)
|
155
|
-
id = doc_id.strip
|
156
|
-
Giblog.logger.debug { "found possible docid: #{id}" }
|
157
|
-
|
158
|
-
unless doc_id_ok? doc_id
|
159
|
-
Giblog.logger.error { "Invalid docid: #{id} in file #{path}, this will be ignored!" }
|
160
|
-
return
|
161
|
-
end
|
162
|
-
|
163
|
-
if docid_cache.key? id
|
164
|
-
Giblog.logger.warn { "Found same doc id twice (#{id})." }
|
165
|
-
Giblog.logger.warn { "Assigning this id to the file #{path}." }
|
166
|
-
Giblog.logger.warn { "Discarding this id from the file #{docid_cache[id]}." }
|
167
|
-
end
|
168
|
-
docid_cache[id] = Pathname(path)
|
169
|
-
end
|
170
|
-
end
|
171
|
-
|
172
|
-
# Helper method to register the docid preprocessor extension with
|
173
|
-
# the asciidoctor engine.
|
174
|
-
def register_docid_extension
|
175
|
-
Asciidoctor::Extensions.register do
|
176
|
-
preprocessor DocidCollector
|
177
|
-
end
|
178
|
-
end
|
179
|
-
module_function :register_docid_extension
|
180
|
-
end
|
data/lib/giblish/docinfo.rb
DELETED
@@ -1,75 +0,0 @@
|
|
1
|
-
require "pathname"
|
2
|
-
|
3
|
-
module Giblish
|
4
|
-
# Container class for bundling together the data we cache for
|
5
|
-
# each asciidoc file we come across
|
6
|
-
class DocInfo
|
7
|
-
# History info from git
|
8
|
-
class DocHistory
|
9
|
-
attr_accessor :date, :author, :message
|
10
|
-
end
|
11
|
-
|
12
|
-
attr_accessor :converted, :doc_id, :purpose_str, :status, :history, :error_msg, :stderr
|
13
|
-
attr_reader :title, :rel_path, :src_file
|
14
|
-
|
15
|
-
# these members can have encoding issues when
|
16
|
-
# running in a mixed Windows/Linux setting.
|
17
|
-
# that is why we explicitly encodes them when
|
18
|
-
# writing to them
|
19
|
-
|
20
|
-
def title=(rhs)
|
21
|
-
@title = rhs.nil? ? nil : rhs.encode("utf-8")
|
22
|
-
end
|
23
|
-
|
24
|
-
def src_file=(rhs)
|
25
|
-
@src_file = rhs.nil? ? nil : rhs.encode("utf-8")
|
26
|
-
end
|
27
|
-
|
28
|
-
def initialize(adoc: nil, dst_root_abs: nil, adoc_stderr: "")
|
29
|
-
@src_file = nil
|
30
|
-
@history = []
|
31
|
-
@converted = true
|
32
|
-
@stderr = adoc_stderr
|
33
|
-
return unless adoc
|
34
|
-
|
35
|
-
# Get the purpose info if it exists
|
36
|
-
@purpose_str = get_purpose_info adoc
|
37
|
-
|
38
|
-
# fill in doc meta data
|
39
|
-
d_attr = adoc.attributes
|
40
|
-
self.src_file = (d_attr["docfile"])
|
41
|
-
self.title = (adoc.doctitle)
|
42
|
-
@doc_id = d_attr["docid"]
|
43
|
-
return if dst_root_abs.nil?
|
44
|
-
|
45
|
-
# Get the relative path beneath the root dir to the doc
|
46
|
-
@rel_path = Pathname.new(
|
47
|
-
"#{d_attr['outdir']}/#{d_attr['docname']}#{d_attr['docfilesuffix']}".encode("utf-8")
|
48
|
-
).relative_path_from(dst_root_abs)
|
49
|
-
end
|
50
|
-
|
51
|
-
def to_s
|
52
|
-
"DocInfo: title: #{@title} src_file: #{@src_file}"
|
53
|
-
end
|
54
|
-
|
55
|
-
private
|
56
|
-
|
57
|
-
def get_purpose_info(adoc)
|
58
|
-
# Get the 'Purpose' section if it exists
|
59
|
-
purpose_str = String.new("")
|
60
|
-
adoc.blocks.each do |section|
|
61
|
-
next unless section.is_a?(Asciidoctor::Section) &&
|
62
|
-
(section.level == 1) &&
|
63
|
-
(section.name =~ /^Purpose$/)
|
64
|
-
|
65
|
-
# filter out 'odd' text, such as lists etc...
|
66
|
-
section.blocks.each do |bb|
|
67
|
-
next unless bb.is_a?(Asciidoctor::Block)
|
68
|
-
|
69
|
-
purpose_str << "#{bb.source}\n+\n"
|
70
|
-
end
|
71
|
-
end
|
72
|
-
purpose_str
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|