html2index 1.2.1 → 1.32
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/bin/html2index +4 -10
- data/doc/html/html2index.html +430 -582
- data/doc/man/html2index.1.gz +0 -0
- data/doc/pdf/html2index.pdf +0 -0
- data/doc/rst/html2index.rst +30 -14
- data/html2index.gemspec +11 -7
- data/lib/argparser.rb +9 -19
- data/lib/basic_logging.rb +202 -0
- data/lib/config +27 -0
- data/lib/configuration.rb +48 -45
- data/lib/constants.rb +8 -14
- data/lib/definition.rb +5 -10
- data/lib/dictionary.rb +12 -10
- data/lib/html2index.rb +125 -91
- data/lib/template.rb +20 -29
- data/lib/translating.rb +31 -28
- data/lib/user_input.rb +4 -12
- data/lib/version.rb +16 -12
- metadata +21 -23
- data/lib/file_checking.rb +0 -103
- data/lib/log.conf +0 -56
- data/lib/logging.rb +0 -206
data/doc/man/html2index.1.gz
CHANGED
|
Binary file
|
data/doc/pdf/html2index.pdf
CHANGED
|
Binary file
|
data/doc/rst/html2index.rst
CHANGED
|
@@ -7,11 +7,11 @@ HTML2Index
|
|
|
7
7
|
|
|
8
8
|
SYNOPSIS
|
|
9
9
|
=========
|
|
10
|
-
|
|
10
|
+
**html2index -s input.html [-o output.html] [-t template.html] [-c config] [-d]**
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
**html2index -v**
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
**html2index -h**
|
|
15
15
|
|
|
16
16
|
DESCRIPTION
|
|
17
17
|
============
|
|
@@ -86,7 +86,7 @@ the French language :
|
|
|
86
86
|
déglingué ou allégé) il a de fortes chances de fonctionner encore
|
|
87
87
|
correctement.
|
|
88
88
|
La version la plus répandue est vim.
|
|
89
|
-
|
|
89
|
+
|
|
90
90
|
2. [nom de domaine]. Nom de domaine de premier niveau des îles Vierges étasuniennes.
|
|
91
91
|
------------------------------------------------------------
|
|
92
92
|
xinput
|
|
@@ -163,7 +163,8 @@ However, an explanation of each one of the available variables follows:
|
|
|
163
163
|
Each dictionary-definition must start with a dash, followed by a white-space, then the
|
|
164
164
|
first variable. Each variable-name must be enclosed by colons (see comments in the config-file).
|
|
165
165
|
|
|
166
|
-
:name: The name of the dictionary, how it will be referred
|
|
166
|
+
:name: The name of the dictionary, how it will be referred
|
|
167
|
+
to in the Glossary. An example could be 'Merriam-Webster'
|
|
167
168
|
|
|
168
169
|
:url: Note here the part from the url to a search-result in
|
|
169
170
|
the chosen dictionary, which precedes the searched
|
|
@@ -175,6 +176,9 @@ However, an explanation of each one of the available variables follows:
|
|
|
175
176
|
item in the url. Remove only the searched expression
|
|
176
177
|
and note the remainder as the value to the variable
|
|
177
178
|
*url*.
|
|
179
|
+
For Merriam-Webster, this url fragment would be (in
|
|
180
|
+
January 2026):
|
|
181
|
+
"https://www.merriam-webster.com/dictionary/"
|
|
178
182
|
|
|
179
183
|
:xpath: This is the xpath which identifies the HTML-element
|
|
180
184
|
in a search-result which contains the explanation of
|
|
@@ -224,8 +228,8 @@ However, an explanation of each one of the available variables follows:
|
|
|
224
228
|
|
|
225
229
|
EXAMPLE-Template
|
|
226
230
|
============================
|
|
227
|
-
|
|
228
|
-
|
|
231
|
+
Assuming that the defaults are used, the following could be a working
|
|
232
|
+
HTML-template to use with HTML2Index:
|
|
229
233
|
|
|
230
234
|
::
|
|
231
235
|
|
|
@@ -245,15 +249,15 @@ EXAMPLE-Template
|
|
|
245
249
|
ERRORS and WARNINGS
|
|
246
250
|
============================
|
|
247
251
|
|
|
248
|
-
|
|
249
|
-
|
|
252
|
+
html2index warns you if the output-file exists and asks you if you want to
|
|
253
|
+
replace it with a new version.
|
|
250
254
|
|
|
251
|
-
|
|
252
|
-
|
|
255
|
+
The program also tries to determine the file-type of the input (HTML) file and
|
|
256
|
+
gives out a warning if the file is considered unsuitable.
|
|
253
257
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
258
|
+
Each time, that an expression cannot be found in one of the targeted
|
|
259
|
+
dictionaries, a warning is given. All these problematic expressions will be
|
|
260
|
+
listed in a temporary file, which is named after html2index has terminated.
|
|
257
261
|
|
|
258
262
|
SOURCE CODE and DEVELOPMENT
|
|
259
263
|
============================
|
|
@@ -263,3 +267,15 @@ accessible. You can also decompress the gem-file to take a look at the code.
|
|
|
263
267
|
|
|
264
268
|
:AUTHOR: Michael Uplawski <michael[dot]uplawski[at]uplawski[dot]eu>
|
|
265
269
|
|
|
270
|
+
This document
|
|
271
|
+
=============
|
|
272
|
+
.. _CC By-ND 4.0: https://creativecommons.org/licenses/by-nd/4.0/
|
|
273
|
+
.. |date| date::
|
|
274
|
+
|
|
275
|
+
©Michael Uplawski <michael.uplawski@uplawski.eu>
|
|
276
|
+
|
|
277
|
+
License: `CC BY-ND 4.0`_
|
|
278
|
+
|
|
279
|
+
Date: |date|
|
|
280
|
+
|
|
281
|
+
**Ω**
|
data/html2index.gemspec
CHANGED
|
@@ -6,16 +6,20 @@ Gem::Specification.new do |s|
|
|
|
6
6
|
s.version = VERSION
|
|
7
7
|
s.name = File.basename(__FILE__, '.gemspec')
|
|
8
8
|
s.date = Date.today.strftime('%F')
|
|
9
|
-
s.summary =
|
|
9
|
+
s.summary = SUMMARY
|
|
10
10
|
s.description = "creates a glossary from HTML"
|
|
11
11
|
s.authors = ["Michael Uplawski"]
|
|
12
12
|
s.email = 'michael.uplawski@uplawski.eu'
|
|
13
|
-
s.files = %w~html2index~.collect{|f| 'bin/' << f} + %w~version.rb argparser.rb configuration.rb constants.rb dictionary.rb html2index.rb
|
|
14
|
-
s.homepage = 'http://www.souris-libre.fr'
|
|
13
|
+
s.files = %w~html2index~.collect{|f| 'bin/' << f} + %w~version.rb argparser.rb config configuration.rb constants.rb dictionary.rb html2index.rb basic_logging.rb translating.rb user_input.rb definition.rb template.rb translations~.collect{|f| 'lib/' << f} + %w~html2index.gemspec~.collect{|f|f} + %w~html/html2index.html man/html2index.1.gz pdf/html2index.pdf rst/html2index.rst~.collect{|f| 'doc/' << f}
|
|
15
14
|
s.requirements = 'nokogiri, ruby-filemagic'
|
|
16
|
-
s.add_runtime_dependency 'nokogiri', '~> 1.
|
|
17
|
-
s.add_runtime_dependency '
|
|
15
|
+
s.add_runtime_dependency 'nokogiri', '~> 1.18', '>= 1.18.10'
|
|
16
|
+
s.add_runtime_dependency 'marcel', '~> 1.2', '>= 1.2.1'
|
|
18
17
|
s.executables = 'html2index'
|
|
19
|
-
s.
|
|
20
|
-
|
|
18
|
+
s.metadata = {
|
|
19
|
+
"homepage_uri" => 'https://www.uplawski.eu/software/',
|
|
20
|
+
"documentation_uri" => 'https://www.uplawski.eu/software/html2index/html2index.html',
|
|
21
|
+
"license_uri" => 'https://www.wtfpl.net/about/'
|
|
22
|
+
}
|
|
23
|
+
s.license = 'Nonstandard'
|
|
24
|
+
s.required_ruby_version = '>= 3.0'
|
|
21
25
|
end
|
data/lib/argparser.rb
CHANGED
|
@@ -1,39 +1,30 @@
|
|
|
1
1
|
#encoding: UTF-8
|
|
2
2
|
=begin
|
|
3
3
|
/***************************************************************************
|
|
4
|
-
* ©
|
|
4
|
+
* ©2011-2026, Michael Uplawski <michael.uplawski@uplawski.eu> *
|
|
5
5
|
* *
|
|
6
6
|
* This program is free software; you can redistribute it and/or modify *
|
|
7
|
-
* it under the terms of the
|
|
8
|
-
*
|
|
9
|
-
* (at your option) any later version. *
|
|
7
|
+
* it under the terms of the WTFPL, version 2 or later, as published on *
|
|
8
|
+
* https://www.wtfpl.net/about/. *
|
|
10
9
|
* *
|
|
11
10
|
* This program is distributed in the hope that it will be useful, *
|
|
12
11
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
13
|
-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
14
|
-
* GNU General Public License for more details. *
|
|
12
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
|
15
13
|
* *
|
|
16
|
-
* You should have received a copy of the GNU General Public License *
|
|
17
|
-
* along with this program; if not, write to the *
|
|
18
|
-
* Free Software Foundation, Inc., *
|
|
19
|
-
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
|
20
14
|
***************************************************************************/
|
|
21
15
|
=end
|
|
22
16
|
|
|
23
|
-
|
|
24
17
|
require 'optparse'
|
|
25
18
|
require 'optparse/time'
|
|
26
19
|
require 'ostruct'
|
|
27
|
-
require_relative '
|
|
20
|
+
require_relative 'basic_logging'
|
|
28
21
|
require_relative 'version'
|
|
29
22
|
# require_relative 'translating'
|
|
30
23
|
require_relative 'constants'
|
|
31
24
|
|
|
32
25
|
class ArgParser
|
|
33
|
-
|
|
34
|
-
self.extend(Logging)
|
|
26
|
+
extend BasicLogging
|
|
35
27
|
# self.extend(Translating)
|
|
36
|
-
@@log = init_logger()
|
|
37
28
|
|
|
38
29
|
# Returns a structure describing the options.
|
|
39
30
|
#
|
|
@@ -54,8 +45,8 @@ class ArgParser
|
|
|
54
45
|
opts.banner = usage
|
|
55
46
|
|
|
56
47
|
opts.on("-d", "--debug", 'Be verbose') do
|
|
57
|
-
$log_level =
|
|
58
|
-
|
|
48
|
+
$log_level = BasicLogging::DEBUG
|
|
49
|
+
set_level BasicLogging::DEBUG
|
|
59
50
|
end
|
|
60
51
|
|
|
61
52
|
opts.on("-sOURCE", "--source=SOURCE", 'Source document (html)') do |so|
|
|
@@ -92,7 +83,6 @@ class ArgParser
|
|
|
92
83
|
puts "Start this program with parameter -h or --help to see the usage-message."
|
|
93
84
|
exit false
|
|
94
85
|
end
|
|
95
|
-
@@log.debug('options are ' << options.to_s)
|
|
96
86
|
|
|
97
87
|
options
|
|
98
88
|
end # parse()
|
|
@@ -101,7 +91,7 @@ class ArgParser
|
|
|
101
91
|
Shows the usage-message
|
|
102
92
|
=end
|
|
103
93
|
def self::usage
|
|
104
|
-
msg = "\n\tUsage: html2index -s input.html [-o output.html] [-c config-file] [-t template.html] [-d]"
|
|
94
|
+
msg = "\n\tUsage: html2index -s input.html \n\t\t[-o output.html] \n\t\t[-c config-file] \n\t\t[-t template.html] \n\t\t[-d]"
|
|
105
95
|
msg << "\n\n\t* Will print to stdout, if the output-file is not provided."
|
|
106
96
|
msg << "\n\t* Adapt ~/.config/HTML2Index/config to your needs.\n\n"
|
|
107
97
|
end
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
#!/bin/env ruby
|
|
2
|
+
#encoding: UTF-8
|
|
3
|
+
=begin
|
|
4
|
+
/***************************************************************************
|
|
5
|
+
* ©2023-2026, Michael Uplawski <michael.uplawski@uplawski.eu> *
|
|
6
|
+
* *
|
|
7
|
+
* This program is free software; you can redistribute it and/or modify *
|
|
8
|
+
* it under the terms of the WTFPL, version 2 or later, as published on *
|
|
9
|
+
* https://www.wtfpl.net/about/. *
|
|
10
|
+
* *
|
|
11
|
+
* This program is distributed in the hope that it will be useful, *
|
|
12
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
13
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
|
14
|
+
* *
|
|
15
|
+
***************************************************************************/
|
|
16
|
+
=end
|
|
17
|
+
|
|
18
|
+
#
|
|
19
|
+
# Simplified logging.
|
|
20
|
+
# See example code at the bottom of this file.
|
|
21
|
+
# Execute this file to see the output.
|
|
22
|
+
module BasicLogging
|
|
23
|
+
|
|
24
|
+
DEBUG ||= 0
|
|
25
|
+
INFO ||= 1
|
|
26
|
+
WARN ||= 2
|
|
27
|
+
ERROR ||= 3
|
|
28
|
+
FATAL ||= 4
|
|
29
|
+
UNKNOWN ||= nil
|
|
30
|
+
|
|
31
|
+
# this is mainly for the translation of method calls into log levels
|
|
32
|
+
Levels ||= {:debug => DEBUG, :info => INFO, :warn => WARN, :error => ERROR,
|
|
33
|
+
:fatal => FATAL, :unknown => UNKNOWN}
|
|
34
|
+
|
|
35
|
+
@@log_level = UNKNOWN
|
|
36
|
+
@@target = STDOUT
|
|
37
|
+
@@muted = []
|
|
38
|
+
|
|
39
|
+
# do not log, if caller is obj (class or instance)
|
|
40
|
+
def self.mute(obj)
|
|
41
|
+
name = obj.class == Class ? obj.name.dup : obj.class.name
|
|
42
|
+
@@muted << name
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def self.is_muted?(obj)
|
|
46
|
+
name = obj.class == Class ? obj.name.dup : obj.class.name
|
|
47
|
+
@@muted.include?(name)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# set the log level
|
|
51
|
+
def set_level(lv)
|
|
52
|
+
if lv.respond_to?(:to_str) && Levels.keys.include?(lv.strip.to_sym)
|
|
53
|
+
lv = Levels[lv.to_sym]
|
|
54
|
+
elsif lv.respond_to?(:to_sym) && Levels.keys.include?(lv)
|
|
55
|
+
lv = Levels[lv]
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
if(!lv || (lv.respond_to?(:to_int) && lv >= DEBUG && lv <= FATAL) )
|
|
59
|
+
@@log_level = lv
|
|
60
|
+
else
|
|
61
|
+
msg = __FILE__.dup << ": ERROR : invalid log level \"" << lv.to_s << "\""
|
|
62
|
+
msg << "\n" << "Keepinng old log level " << Levels.keys.detect {| k| Levels[k] == @@log_level}.to_s
|
|
63
|
+
STDERR.puts msg
|
|
64
|
+
puts msg
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# set the log target
|
|
69
|
+
def set_target(tg)
|
|
70
|
+
if tg.respond_to?(:to_io)
|
|
71
|
+
@@target = tg
|
|
72
|
+
elsif(!File::exist?(tg) || ( File.file?(tg) && File.writable?(tg) ) )
|
|
73
|
+
@@target = File.open(tg, 'w+')
|
|
74
|
+
elsif !tg || tg.respond_to?(:to_str) && tg.strip.empty?
|
|
75
|
+
@@target = nil
|
|
76
|
+
else
|
|
77
|
+
STDERR.puts __FILE__.dup << ': ERROR : target ' << tg << ' cannot be set'
|
|
78
|
+
STDERR.puts "Keeping old target " << @@target.inspect
|
|
79
|
+
return
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Output of log messages, depending on the log level set for the calling class
|
|
84
|
+
# and the name of the alias method which is actually called.
|
|
85
|
+
def log(message)
|
|
86
|
+
if !BasicLogging.is_muted?(self)
|
|
87
|
+
# how has this method been called?
|
|
88
|
+
mlevel = __callee__
|
|
89
|
+
if Levels.has_key?(mlevel) && Levels[mlevel] <= FATAL
|
|
90
|
+
# output only for levels equal or above the value that corresponds to
|
|
91
|
+
# the calling alias.
|
|
92
|
+
format_log( message, mlevel) if @@log_level && Levels[mlevel] >= @@log_level
|
|
93
|
+
else
|
|
94
|
+
STDERR.puts __FILE__.dup << ": ERROR : invalid log level \"" << mlevel.to_s << "\""
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def target
|
|
100
|
+
@@target.path if @@target
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def level
|
|
104
|
+
@@level.to_s if @@level
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Clear the log (-file)
|
|
108
|
+
def clear_log
|
|
109
|
+
if @@target && @@target.respond_to?(:truncate)
|
|
110
|
+
lock_target{ @@target.truncate(0) }
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
alias :debug :log
|
|
115
|
+
alias :info :log
|
|
116
|
+
alias :warn :log
|
|
117
|
+
alias :error :log
|
|
118
|
+
alias :fatal :log
|
|
119
|
+
|
|
120
|
+
private
|
|
121
|
+
|
|
122
|
+
def lock_target(&block)
|
|
123
|
+
begin
|
|
124
|
+
if @@target.respond_to?(:flock)
|
|
125
|
+
@@target.flock(File::LOCK_EX)
|
|
126
|
+
block.call
|
|
127
|
+
@@target.flock(File::LOCK_UN)
|
|
128
|
+
elsif @@target.respond_to?(:to_io)
|
|
129
|
+
block.call
|
|
130
|
+
end
|
|
131
|
+
rescue => ex
|
|
132
|
+
STDERR.puts __FILE__.dup << ": ERROR : cannot lock target (" << ex.message << ")"
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# 1 format_log for all loggers.
|
|
137
|
+
def format_log(message, mlevel)
|
|
138
|
+
if @@target
|
|
139
|
+
# indicate if a registered class or the registered object of a class is calling.
|
|
140
|
+
name = self.class == Class ? self.name.dup << ' [class]' : self.class.name
|
|
141
|
+
lock_target{@@target.puts '' << name << ' ' << mlevel.to_s << ' ' << Time.now.strftime("%H:%M:%S:%6N") << ': ' << message.gsub("\n", "\n |")}
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
#---------test: execute file----------
|
|
146
|
+
if $0 == __FILE__
|
|
147
|
+
Array.extend(BasicLogging)
|
|
148
|
+
Array.set_level(BasicLogging::INFO)
|
|
149
|
+
Array.info('TEST')
|
|
150
|
+
ar = Array.new
|
|
151
|
+
ar.extend(BasicLogging)
|
|
152
|
+
# --- no output :
|
|
153
|
+
l = __LINE__
|
|
154
|
+
ar.debug(l.next.to_s << ': debug-test 0')
|
|
155
|
+
# output
|
|
156
|
+
ar.set_level(BasicLogging::DEBUG)
|
|
157
|
+
l = __LINE__
|
|
158
|
+
ar.debug(l.next.to_s << ': debug-test 1')
|
|
159
|
+
|
|
160
|
+
obj = Object.new
|
|
161
|
+
obj.extend(BasicLogging)
|
|
162
|
+
obj.set_level(BasicLogging::DEBUG)
|
|
163
|
+
puts "--------debug-----------"
|
|
164
|
+
obj.debug('debug')
|
|
165
|
+
obj.info('info')
|
|
166
|
+
obj.warn('warn')
|
|
167
|
+
obj.error('error')
|
|
168
|
+
obj.fatal('fatal')
|
|
169
|
+
puts "--------info-----------"
|
|
170
|
+
obj.set_level("info")
|
|
171
|
+
obj.debug('debug')
|
|
172
|
+
obj.info('info')
|
|
173
|
+
obj.warn('warn')
|
|
174
|
+
obj.error('error')
|
|
175
|
+
obj.fatal('fatal')
|
|
176
|
+
puts "--------fatal-----------"
|
|
177
|
+
obj.set_level("fatal")
|
|
178
|
+
obj.debug('debug')
|
|
179
|
+
obj.info('info')
|
|
180
|
+
obj.warn('warn')
|
|
181
|
+
obj.error('error')
|
|
182
|
+
obj.fatal('fatal')
|
|
183
|
+
puts "--------UNKNOWN-----------"
|
|
184
|
+
obj.set_level(nil)
|
|
185
|
+
obj.debug('debug')
|
|
186
|
+
obj.info('info')
|
|
187
|
+
obj.warn('warn')
|
|
188
|
+
obj.error('error')
|
|
189
|
+
obj.fatal('fatal')
|
|
190
|
+
puts " ------ Output into file ----"
|
|
191
|
+
obj.set_target "/tmp/test_log.log"
|
|
192
|
+
puts " ------ INFO -----------"
|
|
193
|
+
obj.set_level BasicLogging::INFO
|
|
194
|
+
obj.info('info output')
|
|
195
|
+
|
|
196
|
+
obj.info('info output 2')
|
|
197
|
+
puts "---------- invalid -------"
|
|
198
|
+
obj.set_target "/dev/sr0"
|
|
199
|
+
obj.set_level "power"
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
# EOF
|
data/lib/config
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
|
|
3
|
+
template: "~/template.html "
|
|
4
|
+
|
|
5
|
+
placeholders:
|
|
6
|
+
dict_list : "index"
|
|
7
|
+
glossary : "glossary"
|
|
8
|
+
|
|
9
|
+
fdelim: '%='
|
|
10
|
+
|
|
11
|
+
html_tag: 'span'
|
|
12
|
+
html_attribute: 'class'
|
|
13
|
+
attr_value: 'glossar'
|
|
14
|
+
|
|
15
|
+
dictionaries:
|
|
16
|
+
- dict1:
|
|
17
|
+
name: Merriam-Webster
|
|
18
|
+
url: https://www.merriam-webster.com/thesaurus/
|
|
19
|
+
xpath: ".//span[@class='dt ']"
|
|
20
|
+
color: #a0a000
|
|
21
|
+
|
|
22
|
+
# - dict2
|
|
23
|
+
# name:
|
|
24
|
+
# url:
|
|
25
|
+
# xpath:
|
|
26
|
+
# color:
|
|
27
|
+
|
data/lib/configuration.rb
CHANGED
|
@@ -1,46 +1,38 @@
|
|
|
1
1
|
#encoding: UTF-8
|
|
2
2
|
=begin
|
|
3
3
|
/***************************************************************************
|
|
4
|
-
* ©
|
|
4
|
+
* ©2023-2026, Michael Uplawski <michael.uplawski@uplawski.eu> *
|
|
5
5
|
* *
|
|
6
6
|
* This program is free software; you can redistribute it and/or modify *
|
|
7
|
-
* it under the terms of the
|
|
8
|
-
*
|
|
9
|
-
* (at your option) any later version. *
|
|
7
|
+
* it under the terms of the WTFPL, version 2 or later, as published on *
|
|
8
|
+
* https://www.wtfpl.net/about/. *
|
|
10
9
|
* *
|
|
11
10
|
* This program is distributed in the hope that it will be useful, *
|
|
12
11
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
13
|
-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
14
|
-
* GNU General Public License for more details. *
|
|
12
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
|
15
13
|
* *
|
|
16
|
-
* You should have received a copy of the GNU General Public License *
|
|
17
|
-
* along with this program; if not, write to the *
|
|
18
|
-
* Free Software Foundation, Inc., *
|
|
19
|
-
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
|
20
14
|
***************************************************************************/
|
|
21
15
|
=end
|
|
22
16
|
require 'yaml'
|
|
23
17
|
require 'singleton'
|
|
24
18
|
require 'ostruct'
|
|
25
19
|
require_relative 'constants'
|
|
26
|
-
require_relative '
|
|
27
|
-
require_relative 'logging'
|
|
20
|
+
require_relative 'basic_logging'
|
|
28
21
|
require_relative 'translating'
|
|
29
22
|
|
|
23
|
+
# TODO: write default configuration to file !
|
|
30
24
|
class Configuration
|
|
31
|
-
include File_Checking
|
|
32
25
|
include Translating
|
|
33
|
-
include
|
|
26
|
+
include BasicLogging
|
|
34
27
|
|
|
35
28
|
# default configuration file
|
|
36
29
|
@@config_file = File::dirname(__FILE__) << File::Separator << 'config'
|
|
37
30
|
|
|
38
31
|
# do initializations
|
|
39
32
|
def initialize(options)
|
|
40
|
-
|
|
41
|
-
@log.level = $log_level
|
|
33
|
+
set_level $log_level
|
|
42
34
|
set(options)
|
|
43
|
-
|
|
35
|
+
debug('config-file is ' << @@config_file)
|
|
44
36
|
end
|
|
45
37
|
|
|
46
38
|
def user_conf
|
|
@@ -51,10 +43,19 @@ class Configuration
|
|
|
51
43
|
config = confdir << File::Separator << 'config'
|
|
52
44
|
if(!File.exist?(config ) )
|
|
53
45
|
begin
|
|
54
|
-
|
|
55
|
-
|
|
46
|
+
debug 'user cofiguration shall be ' << config
|
|
47
|
+
debug 'reading defaults from ' << @@config_file
|
|
48
|
+
if(File.exist?(@@config_file) )
|
|
49
|
+
File.open(config, 'w+') {|co| co.write(File.read(@@config_file))}
|
|
50
|
+
info("Created user-version of the configuration-file in\n\t" << config)
|
|
51
|
+
else
|
|
52
|
+
warn(@@config_file.dup << ' does not exist!')
|
|
53
|
+
#----------- write default configuration to file --------
|
|
54
|
+
|
|
55
|
+
give_up
|
|
56
|
+
end
|
|
56
57
|
rescue Exception => ex
|
|
57
|
-
|
|
58
|
+
error('Cannot create the configuration: ' << ex.message)
|
|
58
59
|
give_up
|
|
59
60
|
end
|
|
60
61
|
end
|
|
@@ -79,24 +80,26 @@ class Configuration
|
|
|
79
80
|
|
|
80
81
|
# Configure with the command-line arguments.
|
|
81
82
|
def set(options)
|
|
82
|
-
|
|
83
|
+
debug('merging options ' << options.to_s)
|
|
83
84
|
# User-provided configuration-file?
|
|
84
85
|
if(options['config'])
|
|
85
86
|
cf = options['config']
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
87
|
+
debug('config should be ' << cf.to_s)
|
|
88
|
+
[:file?, :readable?].each do |cond|
|
|
89
|
+
if ! File.send(cond, cf)
|
|
90
|
+
msg = cf.dup.to_s << ": Not " << cond.to_s.split('?')[0] << '!'
|
|
91
|
+
error(("ERROR! Unsuitable file") << ' ' << msg)
|
|
92
|
+
# exit
|
|
93
|
+
give_up
|
|
94
|
+
end
|
|
94
95
|
end
|
|
96
|
+
|
|
97
|
+
@@config_file = cf
|
|
95
98
|
else
|
|
96
99
|
@@config_file = user_conf
|
|
97
100
|
end
|
|
98
101
|
|
|
99
|
-
|
|
102
|
+
debug('config-file is ' << @@config_file)
|
|
100
103
|
|
|
101
104
|
# read defaults from configuration-file
|
|
102
105
|
co = OpenStruct.new(YAML::load_file(@@config_file))
|
|
@@ -105,8 +108,8 @@ class Configuration
|
|
|
105
108
|
@config = co.to_h.update(options.to_h)
|
|
106
109
|
if(! @config[:source] )
|
|
107
110
|
msg = ('missing argument %s') %'source'
|
|
108
|
-
|
|
109
|
-
|
|
111
|
+
error msg
|
|
112
|
+
error(("Start this program with parameter -h or --help to see the usage-message.") )
|
|
110
113
|
give_up
|
|
111
114
|
end
|
|
112
115
|
|
|
@@ -116,21 +119,21 @@ class Configuration
|
|
|
116
119
|
if @config[:template]
|
|
117
120
|
@template = @config[:template]
|
|
118
121
|
else
|
|
119
|
-
|
|
122
|
+
warn 'Using default-template!'
|
|
120
123
|
warn ||= true
|
|
121
124
|
end
|
|
122
125
|
# fields in the template file
|
|
123
126
|
if @config[:placeholders] && @config[:template]
|
|
124
127
|
@placeholders = @config[:placeholders]
|
|
125
|
-
|
|
128
|
+
debug('placeholders from config: ' << @placeholders.to_s)
|
|
126
129
|
else
|
|
127
130
|
@placeholders = Template.default(:placeholders)
|
|
128
131
|
if @config[:placeholders]
|
|
129
|
-
|
|
132
|
+
warn 'Placeholders are defined, but no template-file is given.'
|
|
130
133
|
else
|
|
131
|
-
|
|
134
|
+
warn 'Template is given, but placeholders are not defined.'
|
|
132
135
|
end
|
|
133
|
-
|
|
136
|
+
warn 'Using default placeholders ' << @placeholders.to_a.collect{|p|p.join(': ')}.join(', ')
|
|
134
137
|
warn = true
|
|
135
138
|
end
|
|
136
139
|
@fields = [@placeholders[:dict_list], @placeholders[:glossary]]
|
|
@@ -140,11 +143,11 @@ class Configuration
|
|
|
140
143
|
else
|
|
141
144
|
@fdelim = Template.default(:fdelim)
|
|
142
145
|
if @config[:template]
|
|
143
|
-
|
|
146
|
+
warn 'Template is given, but field delimiters are not defined.'
|
|
144
147
|
else
|
|
145
|
-
|
|
148
|
+
warn 'Field delimiters are defined but no template is given.'
|
|
146
149
|
end
|
|
147
|
-
|
|
150
|
+
warn 'Using default delimiters ' << @fdelim << ', ' << @fdelim.reverse
|
|
148
151
|
warn ||= true
|
|
149
152
|
end
|
|
150
153
|
|
|
@@ -155,22 +158,22 @@ class Configuration
|
|
|
155
158
|
dictionaries.each do |d|
|
|
156
159
|
@dicts << Dictionary.new(d[:name], d[:url], d[:xpath], d[:color])
|
|
157
160
|
end
|
|
158
|
-
|
|
161
|
+
debug('dicts are from config' << @dicts.to_s)
|
|
159
162
|
else
|
|
160
|
-
|
|
163
|
+
warn( %~NO DICTIONARIES have been set in the configuration!
|
|
161
164
|
Will use the defaults, which is probably NOT what you want!
|
|
162
165
|
Defaults are: %s~ %[URL_DICT1.dup << ', ' << URL_DICT2.dup])
|
|
163
166
|
warn ||= true
|
|
164
167
|
@dicts << Dictionary.new(NAME_DICT1, URL_DICT1,XPATH_DICT1, DICT_COLORS[0])
|
|
165
168
|
@dicts << Dictionary.new(NAME_DICT2, URL_DICT2, XPATH_DICT2, DICT_COLORS[1])
|
|
166
|
-
|
|
169
|
+
debug('dicts are from constants' << @dicts.to_s)
|
|
167
170
|
end
|
|
168
|
-
|
|
171
|
+
warn "HINT: Adapt #{@@config_file} to avoid warnings in the future."
|
|
169
172
|
end
|
|
170
173
|
|
|
171
174
|
# exit on error
|
|
172
175
|
def give_up
|
|
173
|
-
|
|
176
|
+
error("\t" << ("Aborting. Bye!"))
|
|
174
177
|
exit false
|
|
175
178
|
end
|
|
176
179
|
end
|
data/lib/constants.rb
CHANGED
|
@@ -1,29 +1,23 @@
|
|
|
1
1
|
#encoding: UTF-8
|
|
2
2
|
=begin
|
|
3
3
|
/***************************************************************************
|
|
4
|
-
* ©2015-
|
|
4
|
+
* ©2015-2026, Michael Uplawski <michael.uplawski@uplawski.eu> *
|
|
5
5
|
* *
|
|
6
6
|
* This program is free software; you can redistribute it and/or modify *
|
|
7
|
-
* it under the terms of the
|
|
8
|
-
*
|
|
9
|
-
* (at your option) any later version. *
|
|
7
|
+
* it under the terms of the WTFPL, version 2 or later, as published on *
|
|
8
|
+
* https://www.wtfpl.net/about/. *
|
|
10
9
|
* *
|
|
11
10
|
* This program is distributed in the hope that it will be useful, *
|
|
12
11
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
13
|
-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
14
|
-
* GNU General Public License for more details. *
|
|
12
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
|
15
13
|
* *
|
|
16
|
-
* You should have received a copy of the GNU General Public License *
|
|
17
|
-
* along with this program; if not, write to the *
|
|
18
|
-
* Free Software Foundation, Inc., *
|
|
19
|
-
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
|
20
14
|
***************************************************************************/
|
|
21
15
|
=end
|
|
22
16
|
require_relative 'dictionary'
|
|
23
|
-
|
|
17
|
+
require_relative 'basic_logging'
|
|
24
18
|
require 'date'
|
|
25
19
|
|
|
26
|
-
APPNAME
|
|
20
|
+
APPNAME ||= 'HTML2Index'
|
|
27
21
|
|
|
28
22
|
# URL and xpath for the definitions.
|
|
29
23
|
#
|
|
@@ -49,7 +43,7 @@ DICT_COLORS ||= ['a000a0', '00a000']
|
|
|
49
43
|
|
|
50
44
|
# definitions which cause problems are logged.
|
|
51
45
|
PROBLEM_LOG ||= 'html2index_problems.txt'
|
|
52
|
-
$log_level
|
|
46
|
+
$log_level ||= BasicLogging::INFO
|
|
53
47
|
|
|
54
48
|
# meta-tag for the html-output
|
|
55
|
-
GeneratorMeta
|
|
49
|
+
GeneratorMeta ||= "<meta name=\"generator\" content=\"HTML2Index ©2015-#{Date.today.strftime('%Y')} michael.uplawski@uplawski.eu\" />"
|