md2site 0.1.2
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 +7 -0
- data/.gitignore +30 -0
- data/.gitmodules +3 -0
- data/.rspec +3 -0
- data/.rubocop.yml +138 -0
- data/.rubocop_todo.yml +47 -0
- data/.travis.yml +7 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +98 -0
- data/LICENSE +8 -0
- data/LICENSE.txt +8 -0
- data/README.md +39 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/md2site +157 -0
- data/bin/setup +8 -0
- data/data/conf/conf-sample.yml +5 -0
- data/data/conf/conf.sh +32 -0
- data/data/conf/setting.yml +3 -0
- data/data/conf/site.tsv +1 -0
- data/data/template/5col_no_attr.erb +72 -0
- data/data/template/5col_no_attr_b.erb +72 -0
- data/data/template/functions_static.erb +10 -0
- data/data/template/functions_variable.erb +3 -0
- data/data/template2/contest_notification.erb +16 -0
- data/data/template2/contest_notification_2.erb +34 -0
- data/data/template2/contest_winners.erb +69 -0
- data/data/template2/contest_winners_statement.erb +1 -0
- data/data/testdata/conf-blog.yml +6 -0
- data/data/testdata/conf-download.yml +6 -0
- data/data/testdata/conf-link.yml +6 -0
- data/data/testdata/conf-profile.yml +6 -0
- data/data/testdata/conf-top.yml +6 -0
- data/data/testdata/site.tsv +5 -0
- data/data/testdata0/conf-appliction.yml +1 -0
- data/data/testdata0/conf-attempt.yml +69 -0
- data/data/testdata0/conf-autosar.yml +11 -0
- data/data/testdata0/conf-community.yml +3 -0
- data/data/testdata0/conf-document.yml +1 -0
- data/data/testdata0/conf-download.yml +1 -0
- data/data/testdata0/conf-edu.yml +52 -0
- data/data/testdata0/conf-etc.yml +1 -0
- data/data/testdata0/conf-members.yml +2 -0
- data/data/testdata0/conf-product.yml +37 -0
- data/data/testdata0/conf-project.yml +14 -0
- data/data/testdata0/conf-rtk.yml +25 -0
- data/data/testdata0/conf-top.yml +1 -0
- data/data/testdata0/setting.yml +33 -0
- data/data/testdata0/site.tsv +123 -0
- data/lib/md2site/env.rb +649 -0
- data/lib/md2site/htmlutils.rb +142 -0
- data/lib/md2site/htmlutils0.rb +223 -0
- data/lib/md2site/info.rb +17 -0
- data/lib/md2site/init.rb +90 -0
- data/lib/md2site/listfile.rb +22 -0
- data/lib/md2site/make.rb +295 -0
- data/lib/md2site/nkfguess.rb +33 -0
- data/lib/md2site/setup.rb +358 -0
- data/lib/md2site/statusfile.rb +75 -0
- data/lib/md2site/testdata.rb +50 -0
- data/lib/md2site/testx.rb +73 -0
- data/lib/md2site/version.rb +3 -0
- data/lib/md2site.rb +161 -0
- data/md2site.gemspec +59 -0
- metadata +359 -0
data/lib/md2site/make.rb
ADDED
@@ -0,0 +1,295 @@
|
|
1
|
+
module Md2site
|
2
|
+
#
|
3
|
+
# makeサブコマンドクラス
|
4
|
+
#
|
5
|
+
class Make
|
6
|
+
#
|
7
|
+
# 初期化
|
8
|
+
# @param env [Env] Envクラスのインスタンス
|
9
|
+
# @param mes [Messagex] Messagexクラスのインスタンス
|
10
|
+
# @param verbose [Boolean] FileUtilsクラスのメソッドのverbose引数に与える値
|
11
|
+
# @param str_variable [String] 2段階の変数置換が必要なeRubyスクリプト(一度置換をし、さらにもう一度置換が必要なeRubyスクリプト)
|
12
|
+
# @param str_static [String] 1段階の変数置換のみが必要なeRubyスクリプト(一度置換をしたら、その後は置換が必要ないeRubyスクリプト)
|
13
|
+
# @param obj_by_yaml [Hash] 変数置換に用いるハッシュ
|
14
|
+
def initialize(env, mes, verbose, str_variable, str_static, obj_by_yaml)
|
15
|
+
@env = env
|
16
|
+
@mes = mes
|
17
|
+
@verbose = verbose
|
18
|
+
@str_variable = str_variable
|
19
|
+
@str_static = str_static
|
20
|
+
@obj_by_yaml = obj_by_yaml
|
21
|
+
@template_dir = @env.conf_hs["TEMPLELATE_DIR"]
|
22
|
+
@default_table_template = @env.conf_hs["DEFAULT_TABLE_TEMPLATE"] # 5col_no_attr_b.erb
|
23
|
+
end
|
24
|
+
|
25
|
+
#
|
26
|
+
# 引数optionでの指定に従いサブコマンドを実行
|
27
|
+
# @param target_command [String] ターゲットコマンド名
|
28
|
+
# @param subtarget_command [String] サブターゲットコマンド名
|
29
|
+
def execute_subcommand(target_command, subtarget_command)
|
30
|
+
if subtarget_command == SUB_TARGET_COMMAND_OF_ALL
|
31
|
+
do_multiple_commands(target_command)
|
32
|
+
else
|
33
|
+
do_single_command(target_command, subtarget_command)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
#
|
38
|
+
# 指定ターゲットコマンドに属する全サブターゲットコマンドを順次実行する
|
39
|
+
# @param target_command [String] ターゲットコマンド名
|
40
|
+
def do_multiple_commands(target_command)
|
41
|
+
ary = @env.get_subtarget_commands(target_command)
|
42
|
+
if !ary.empty?
|
43
|
+
ary.map do |subtarget_command, _v|
|
44
|
+
@mes.output_info("#{target_command} #{subtarget_command}")
|
45
|
+
do_single_command(target_command, subtarget_command)
|
46
|
+
end
|
47
|
+
else
|
48
|
+
@mes.output_fatal("Illeagel targetcommand(#{target_command}")
|
49
|
+
exit(@mes.ec("EXIT_CODE_ILLEAGAL_TARGETCOMMAND"))
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
#
|
56
|
+
# ターゲットコマンド名、サブターゲットコマンド名の組み合わせを実行する
|
57
|
+
# @param target_command [String] ターゲットコマンド名
|
58
|
+
# @param subtarget_command [String] サブターゲットコマンド名
|
59
|
+
def do_single_command(target_command, subtarget_command)
|
60
|
+
target, subtarget = @env.get_target_and_subtarget(target_command, subtarget_command)
|
61
|
+
@mes.output_info(%Q(target=#{target}))
|
62
|
+
@mes.output_info(%Q(subtarget=#{subtarget}))
|
63
|
+
unless target
|
64
|
+
@mes.output_fatal(%Q(Cannot find target by #{target_command}))
|
65
|
+
exit(@mes.ec("EXIT_CODE_BY_CANNOT_FIND_TARGET"))
|
66
|
+
end
|
67
|
+
|
68
|
+
unless subtarget
|
69
|
+
@mes.output_fatal(%Q(Cannot find subtarget by #{subtarget_command}))
|
70
|
+
exit(@mes.ec("EXIT_CODE_BY_CANNOT_FIND_SUBTARGET"))
|
71
|
+
end
|
72
|
+
|
73
|
+
execute_single_command(target, subtarget)
|
74
|
+
end
|
75
|
+
|
76
|
+
#
|
77
|
+
# 指定パスが有効なファイルであるか調べる
|
78
|
+
# @param fname [String] ファイルのパス
|
79
|
+
# @return [Boolean] true:有効なファイルパスである false:有効なファイルパスでない
|
80
|
+
def check_valid_src_file(fname)
|
81
|
+
valid_src_file = true
|
82
|
+
|
83
|
+
ret = FileTest.size?(fname)
|
84
|
+
if !ret || (ret == 0)
|
85
|
+
valid_src_file = false
|
86
|
+
elsif FileTest.directory?(fname)
|
87
|
+
valid_src_file = false
|
88
|
+
elsif File.read(fname).strip.empty?
|
89
|
+
valid_src_file = false
|
90
|
+
end
|
91
|
+
valid_src_file
|
92
|
+
end
|
93
|
+
|
94
|
+
#
|
95
|
+
# eRubyスクリプトを用いてMarkdown形式ファイルを生成
|
96
|
+
# @param target_struct [Struct] ターゲットストラクト
|
97
|
+
# @param template_struct [Struct] テンプレートストラクト
|
98
|
+
def execute_single_command_for_template(target_struct, template_struct)
|
99
|
+
# 既存のファイルを読み込む
|
100
|
+
if template_struct.kind == :INCLUDE
|
101
|
+
dataop = :FILE_INCLUDE
|
102
|
+
# 読み込み元のファイルが存在しなければ、あらかじめ作成する
|
103
|
+
unless check_valid_src_file(template_struct.datafname)
|
104
|
+
src_subtarget = @env.get_sub_target(target_struct.name, template_struct.src_subtarget_name)
|
105
|
+
execute_single_command(target_struct, src_subtarget)
|
106
|
+
end
|
107
|
+
command_make_md(@env.absolutepath_root, template_struct.datafname, template_struct.outputfname, dataop, nil, { template_struct.macroname => template_struct.datafname })
|
108
|
+
# YAML形式ファイルを、eRubyスクリプトを用いて、Markdown形式ファイルに変換する
|
109
|
+
else
|
110
|
+
dataop = :YAML_TO_MD
|
111
|
+
command_make_md(@env.absolutepath_root, template_struct.datafname, template_struct.outputfname, dataop, template_struct.templatefname, { template_struct.macroname => template_struct.outputfname })
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
#
|
116
|
+
# Markdown形式ファイルをeRubyスクリプトを用いて
|
117
|
+
# @param target_struct [Struct] ターゲットストラクト
|
118
|
+
# @param subtarget_struct [Struct] サブターゲットストラクト
|
119
|
+
def execute_single_command(target_struct, subtarget_struct)
|
120
|
+
# 設定されていれば、全テンプレートストラクトに対して、テンプレートを用いてMarkdown形式ファイルを生成
|
121
|
+
unless subtarget_struct.templates.empty?
|
122
|
+
subtarget_struct.templates.each do |template_struct|
|
123
|
+
execute_single_command_for_template(target_struct, template_struct)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
# eRubyスクリプト内でファイルを表すマクロ名と実際のファイルパスの対応をハッシュで実現
|
127
|
+
ary = subtarget_struct.templates.map {|x| [x.macroname, x.outputfname] }.flatten
|
128
|
+
hash = Hash[*ary]
|
129
|
+
# Markdown形式ファイルから生成するHTMLファイルは、HTMLのbodyタグ内の部分である
|
130
|
+
# HTMLの先頭から<body>の直前までと、</body>から最後までを別途取得して、最終的にそれらを結合してHTMLファイルにする。
|
131
|
+
parta_html = get_part_html(target_struct, subtarget_struct, :partA)
|
132
|
+
partc_html = get_part_html(target_struct, subtarget_struct, :partC)
|
133
|
+
|
134
|
+
datafile = subtarget_struct.filedir.input_md
|
135
|
+
outputfile = subtarget_struct.filedir.output_md
|
136
|
+
dataop = :FILE_INCLUDE
|
137
|
+
templatefile = nil
|
138
|
+
# HTMLファイルに変換する元となるMarkdown形式ファイル生成
|
139
|
+
command_make_md(@env.absolutepath_root, datafile, outputfile, dataop, templatefile, hash)
|
140
|
+
|
141
|
+
outputfile_md = subtarget_struct.filedir.output_md
|
142
|
+
root_output_md = subtarget_struct.filedir.root_output_md
|
143
|
+
out_htmlfname = subtarget_struct.filedir.html_output
|
144
|
+
# Markdown形式ファイルをHTMLに変換、結合して最終的なHTMLファイルを生成
|
145
|
+
command_make_html(@env.absolutepath_root, outputfile_md, root_output_md, parta_html, partc_html, out_htmlfname)
|
146
|
+
end
|
147
|
+
|
148
|
+
#
|
149
|
+
# サブターゲットでエイリアスが指定されていれば、エイリアスを生成するサブターゲットを得る
|
150
|
+
# @param target_struct [Struct] ターゲットストラクト
|
151
|
+
# @param subtarget_struct [Struct] サブターゲットストラクト
|
152
|
+
# @return [Struct] 有効なサブターゲットストラクト
|
153
|
+
def get_effective_subtarget(target_struct, subtarget_struct)
|
154
|
+
if subtarget_struct.aliashtmldir == ""
|
155
|
+
if subtarget_struct.aliashtmlfile == ""
|
156
|
+
htmlfpath = nil
|
157
|
+
else
|
158
|
+
htmlfpath = subtarget_struct.aliashtmlfile
|
159
|
+
end
|
160
|
+
else
|
161
|
+
htmlfpath = File.join(subtarget_struct.aliashtmldir, subtarget_struct.aliashtmlfile)
|
162
|
+
end
|
163
|
+
|
164
|
+
if htmlfpath
|
165
|
+
subtarget_struct_x = @env.get_subtarget_by_htmlfile(target_struct.name, htmlfpath)
|
166
|
+
else
|
167
|
+
subtarget_struct_x = subtarget_struct
|
168
|
+
end
|
169
|
+
|
170
|
+
subtarget_struct_x
|
171
|
+
end
|
172
|
+
|
173
|
+
#
|
174
|
+
# 指定されたパートに対応するHTMLファイルパスを得る
|
175
|
+
# @param target_struct [Struct] ターゲットストラクト
|
176
|
+
# @param subtarget_struct [Struct] サブターゲットストラクト
|
177
|
+
# @param kind [Symbol] :partA パートA :partB パートB
|
178
|
+
def get_part_html(target_struct, subtarget_struct, kind)
|
179
|
+
subtarget_x = get_effective_subtarget(target_struct, subtarget_struct)
|
180
|
+
|
181
|
+
path = ""
|
182
|
+
case kind
|
183
|
+
when :partA
|
184
|
+
path = subtarget_x.filedir.partAhtml
|
185
|
+
when :partC
|
186
|
+
path = subtarget_x.filedir.partChtml
|
187
|
+
end
|
188
|
+
|
189
|
+
path
|
190
|
+
end
|
191
|
+
|
192
|
+
def command_make_md(src_dir, datafile, outputfile, dataop, templatefile, auxhs={})
|
193
|
+
@mes.output_info(%Q!command_make_md(#{datafile}, #{outputfile}, #{dataop}, #{templatefile}, #{auxhs}!)
|
194
|
+
if src_dir
|
195
|
+
datafile = File.join(src_dir, datafile) if datafile
|
196
|
+
outputfile = File.join(src_dir, outputfile) if outputfile
|
197
|
+
end
|
198
|
+
optsx = {}
|
199
|
+
optsx["data"] = datafile
|
200
|
+
optsx["output"] = outputfile
|
201
|
+
optsx["dataop"] = dataop
|
202
|
+
|
203
|
+
mmt = Mdextab::Makemdtab.new(optsx, @str_variable, @str_static, @obj_by_yaml, @mes)
|
204
|
+
if templatefile
|
205
|
+
if src_dir
|
206
|
+
template_fullpath = File.join(src_dir, @template_dir, templatefile)
|
207
|
+
else
|
208
|
+
template_fullpath = File.join(@template_dir, templatefile)
|
209
|
+
end
|
210
|
+
else
|
211
|
+
template_fullpath = @default_table_template
|
212
|
+
end
|
213
|
+
|
214
|
+
mmt.make_md2(src_dir, template_fullpath, auxhs)
|
215
|
+
mmt.post_process
|
216
|
+
end
|
217
|
+
|
218
|
+
def simple_md2html(inputmd, output_htmlfname)
|
219
|
+
@mes.output_info(%Q(pandoc -o #{output_htmlfname} -t html5 #{inputmd}))
|
220
|
+
ret = false
|
221
|
+
_, _, s = Open3.capture3(%Q(pandoc -o #{output_htmlfname} -t html5 #{inputmd}))
|
222
|
+
|
223
|
+
if s.exited?
|
224
|
+
if s.exitstatus == 0
|
225
|
+
ret = true
|
226
|
+
else
|
227
|
+
@mes.output_error("Can't convert from md to html by pandoc(exit_code=#{s.exitstatus})")
|
228
|
+
exit(@mes.ec("EXIT_CODE_CANNOT_CONVERT_FROM_MD_TO_HTML"))
|
229
|
+
end
|
230
|
+
else
|
231
|
+
@mes.output_error("Pandoc exit abnormally")
|
232
|
+
exit(@mes.ec("EXIT_CODE_PANDOC_EXIT_ABNORMALLY"))
|
233
|
+
end
|
234
|
+
|
235
|
+
ret
|
236
|
+
end
|
237
|
+
|
238
|
+
def output_html(out_htmlfname, mode, parta, content, partb)
|
239
|
+
File.open(out_htmlfname, mode) do |f|
|
240
|
+
f.write(parta)
|
241
|
+
f.write(content)
|
242
|
+
f.write(partb)
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
def md2html(root_outputmd, out_htmlfname, parta, partb)
|
247
|
+
tmpdir = File.dirname(out_htmlfname)
|
248
|
+
tmpbasename = File.basename(out_htmlfname)
|
249
|
+
|
250
|
+
content_htmlfname = File.join(tmpdir, tmpbasename + ".tmp")
|
251
|
+
unless root_outputmd
|
252
|
+
@mes.output_fatal("Can't find file(=#{root_outputmd}")
|
253
|
+
exit(@mes.ec("EXIT_CODE_CANNOT_FIND_FILE"))
|
254
|
+
end
|
255
|
+
@mes.output_debug("root_outputmd=#{root_outputmd}")
|
256
|
+
@mes.output_debug("content_htmlfname=#{content_htmlfname}")
|
257
|
+
ret = simple_md2html(root_outputmd, content_htmlfname)
|
258
|
+
return unless ret
|
259
|
+
|
260
|
+
ret = simple_md2html(root_outputmd, "x.html")
|
261
|
+
unless ret
|
262
|
+
tmpf.close(true)
|
263
|
+
return
|
264
|
+
end
|
265
|
+
|
266
|
+
content = ""
|
267
|
+
@mes.exc_file_read(content_htmlfname) { content = File.readlines(content_htmlfname).join }
|
268
|
+
@mes.output_debug("file_read #{content_htmlfname}")
|
269
|
+
# @mes.output_debug("content #{content}")
|
270
|
+
@mes.exc_file_write(out_htmlfname) { output_html(out_htmlfname, "w", parta, content, partb) }
|
271
|
+
@mes.output_debug("file_write #{out_htmlfname}")
|
272
|
+
# File.unlink(content_htmlfname)
|
273
|
+
end
|
274
|
+
|
275
|
+
def command_make_html(src_dir, outputfile_md, root_output_md, parta_html, partc_html, out_htmlfname)
|
276
|
+
@mes.output_info(%Q!command_makehtml(#{outputfile_md}, #{root_output_md}, #{parta_html} #{partc_html} #{out_htmlfname}!)
|
277
|
+
if src_dir
|
278
|
+
outputfile_md = File.join(src_dir, outputfile_md) if outputfile_md
|
279
|
+
root_output_md = File.join(src_dir, root_output_md) if root_output_md
|
280
|
+
parta_html = File.join(src_dir, parta_html) if parta_html
|
281
|
+
partc_html = File.join(src_dir, partc_html) if partc_html
|
282
|
+
out_htmlfname = File.join(src_dir, out_htmlfname) if out_htmlfname
|
283
|
+
end
|
284
|
+
|
285
|
+
optsx = {}
|
286
|
+
m = Mdextab::Mdextab.new(optsx, outputfile_md, root_output_md, @mes)
|
287
|
+
m.parse(@obj_by_yaml)
|
288
|
+
m.post_process
|
289
|
+
|
290
|
+
parta = Filex::Filex.check_and_load_file(parta_html, @mes)
|
291
|
+
partc = Filex::Filex.check_and_load_file(partc_html, @mes)
|
292
|
+
md2html(root_output_md, out_htmlfname, parta, partc)
|
293
|
+
end
|
294
|
+
end
|
295
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Md2site
|
2
|
+
module Nkfguess
|
3
|
+
require "nkf"
|
4
|
+
|
5
|
+
def self.guess_file(fname, mes)
|
6
|
+
str = nil
|
7
|
+
mes.exc_file_read(fname) { File.open(fname) {|f| str = f.gets(nil) } }
|
8
|
+
if str.nil?
|
9
|
+
encoding = nil
|
10
|
+
else
|
11
|
+
case NKF.guess(str)
|
12
|
+
when NKF::JIS
|
13
|
+
encoding = "ISO-2022-JP"
|
14
|
+
when NKF::EUC
|
15
|
+
encoding = "eucJP"
|
16
|
+
when NKF::SJIS
|
17
|
+
encoding = "CP932"
|
18
|
+
when NKF::UTF8
|
19
|
+
encoding = "UTF-8"
|
20
|
+
when NKF::BINARY
|
21
|
+
encoding = "ASCII-8BIT"
|
22
|
+
when NKF::ASCII
|
23
|
+
encoding = "ASCII-8BIT"
|
24
|
+
when NKF::UNKNOWN
|
25
|
+
encoding = "ASCII-8BIT"
|
26
|
+
else
|
27
|
+
encoding = "ASCII-8BIT"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
encoding
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,358 @@
|
|
1
|
+
module Md2site
|
2
|
+
#
|
3
|
+
# setupサブコマンドクラス
|
4
|
+
#
|
5
|
+
class Setup
|
6
|
+
# WEBサイトへのアクセス待ち時間(秒単位)
|
7
|
+
ACCESS_WAIT_SEC = 10
|
8
|
+
# ACCESS_WAIT_SEC=5
|
9
|
+
# ACCESS_WAIT_SEC=1
|
10
|
+
|
11
|
+
require "faraday_middleware"
|
12
|
+
require "faraday"
|
13
|
+
require "date"
|
14
|
+
require "open3"
|
15
|
+
require "uri"
|
16
|
+
require "digest"
|
17
|
+
require "messagex"
|
18
|
+
require "md2site/statusfile"
|
19
|
+
require "md2site/listfile"
|
20
|
+
|
21
|
+
#
|
22
|
+
# 初期化
|
23
|
+
# @param env [Env] Envクラスのメソッド
|
24
|
+
# @param mes [Messagex] Messagexクラスのインスタンス
|
25
|
+
def initialize(env, mes)
|
26
|
+
@env = env
|
27
|
+
@mes = mes
|
28
|
+
@category = @env.category
|
29
|
+
@category_x = @env.category_x
|
30
|
+
absolute_path_status_file = env.conf_hs["ABSOLUTE_PATH_STATUS_FILE"]
|
31
|
+
@url = @env.conf_hs["URL"]
|
32
|
+
@res = {}
|
33
|
+
|
34
|
+
@mes.add_exitcode("EXIT_CODE_BY_EXCEPTION")
|
35
|
+
@mes.add_exitcode("EXIT_CODE_EXECUTE_SETUP_BEFORE_UPDATE_HTMLFILES")
|
36
|
+
@mes.add_exitcode("EXIT_CODE_CANNOT_FIND_DEST_DIR")
|
37
|
+
@mes.add_exitcode("EXIT_CODE_CANNOT_CONVERT_FROM_HTML_TO_MD")
|
38
|
+
@mes.add_exitcode("EXIT_CODE_PANDOC_EXIT_ABNORMALLY")
|
39
|
+
@status_file = StatusFile.new(absolute_path_status_file, @url, @mes)
|
40
|
+
end
|
41
|
+
|
42
|
+
#
|
43
|
+
# サブコマンド実行
|
44
|
+
# @param option [String] サブコマンドのオプション
|
45
|
+
def execute_subcommand(option)
|
46
|
+
case option.name
|
47
|
+
when "contentUpdate"
|
48
|
+
update_htmlfiles
|
49
|
+
when "zcontents"
|
50
|
+
dir = @env.get_filepath(option.value)
|
51
|
+
unless dir
|
52
|
+
@mes.exc_make_directory(option.value) { FileUtils.mkdir_p(option.value) }
|
53
|
+
dir = @env.get_filepath(option.value)
|
54
|
+
end
|
55
|
+
unless dir || FileTest.directory?(dir)
|
56
|
+
@mes.output_fatal("Can't find drectory(=#{dir}")
|
57
|
+
exit(@mes.ec("EXIT_CODE_CANNOT_FIND_DIRECTORY"))
|
58
|
+
end
|
59
|
+
get_remote_contents(dir)
|
60
|
+
when "getfiles"
|
61
|
+
dir = @env.get_filepath(option.value)
|
62
|
+
get_remote_file_headers(dir)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
#
|
69
|
+
# リモートサイトのファイル取得
|
70
|
+
# @param url [String] 取得先URL
|
71
|
+
# @return [Array] 第0要素:Datetime 第1要素:UNIXタイム 第2要素:HTTPボディ
|
72
|
+
def get_remote_file(url)
|
73
|
+
connection = Faraday.new(url) do |conn|
|
74
|
+
conn.use(FaradayMiddleware::FollowRedirects)
|
75
|
+
conn.adapter(:net_http)
|
76
|
+
end
|
77
|
+
@mes.output_debug("url=#{url}")
|
78
|
+
res = connection.get(url)
|
79
|
+
datetime_str, datetime_unix_time = get_modified_in_datetime_or_date_in_datetime_from_header(res.headers)
|
80
|
+
[datetime_str, datetime_unix_time, res.body]
|
81
|
+
end
|
82
|
+
|
83
|
+
#
|
84
|
+
# HTTPヘッダの指定フィールドの値を文字列とUNITタイムで取得する
|
85
|
+
# @param headers [Hash] HTTPヘッダを表すハッシュ
|
86
|
+
# @param key [String] HTTPヘッダのフィールドを指定するキー
|
87
|
+
# @return [Array] 第0要素: 指定フィールドの値(String) 第1要素: 指定フィールドの値(UNIXタイム)
|
88
|
+
def get_header_value_of_datetime(headers, key)
|
89
|
+
@res[key] ||= Regexp.compile(Regexp.escape(key))
|
90
|
+
keys = headers.keys.select {|x| @res[key].match?(x.downcase) }
|
91
|
+
|
92
|
+
if keys.size == 1
|
93
|
+
k = keys.first
|
94
|
+
s = headers[k]
|
95
|
+
begin
|
96
|
+
dt = DateTime.httpdate(s)
|
97
|
+
unixtime = dt.to_time.to_i
|
98
|
+
rescue ArgumentError => e
|
99
|
+
@mes.output_exception(e)
|
100
|
+
@mes.output_fatal("s=#{s}")
|
101
|
+
exit(@mes.ec("EXIT_CODE_BY_EXCEPTION"))
|
102
|
+
rescue Error => e
|
103
|
+
@mes.output_exception(e)
|
104
|
+
@mes.output_fatal("s=#{s}")
|
105
|
+
exit(@mes.ec("EXIT_CODE_BY_EXCEPTION"))
|
106
|
+
end
|
107
|
+
else
|
108
|
+
s = nil
|
109
|
+
unixtime = nil
|
110
|
+
end
|
111
|
+
[s, unixtime]
|
112
|
+
end
|
113
|
+
|
114
|
+
#
|
115
|
+
# HTTPヘッダのlast-modifiedフィールドの値を文字列とUNITタイムで取得
|
116
|
+
# @param headers [Hash] HTTPヘッダを表すハッシュ
|
117
|
+
# @return [Array] 第0要素: 指定フィールドの値(String) 第1要素: 指定フィールドの値(UNIXタイム)
|
118
|
+
def get_modified_in_datetime_from_header(headers)
|
119
|
+
get_header_value_of_datetime(headers, "last-modified")
|
120
|
+
end
|
121
|
+
|
122
|
+
#
|
123
|
+
# HTTPヘッダのdateフィールドの値を文字列とUNITタイムで取得
|
124
|
+
# @param headers [Hash] HTTPヘッダを表すハッシュ
|
125
|
+
# @return [Array] 第0要素: 指定フィールドの値(String) 第1要素: 指定フィールドの値(UNIXタイム)
|
126
|
+
def get_date_in_datetime_from_header(headers)
|
127
|
+
get_header_value_of_datetime(headers, "date")
|
128
|
+
end
|
129
|
+
|
130
|
+
#
|
131
|
+
# HTTPヘッダから時刻を表すlast-modifiedフィールドまたはdateフィールのの値を文字列とUNIXタイムで取得
|
132
|
+
# @param headers [Hash] HTTPヘッダを表すハッシュ
|
133
|
+
# @return [Array] 第0要素: 指定フィールドの値(String) 第1要素: 指定フィールドの値(UNIXタイム)
|
134
|
+
def get_modified_in_datetime_or_date_in_datetime_from_header(headers)
|
135
|
+
ary = get_modified_in_datetime_from_header(headers)
|
136
|
+
unless ary.all?
|
137
|
+
ary = get_date_in_datetime_from_header(headers)
|
138
|
+
end
|
139
|
+
ary
|
140
|
+
end
|
141
|
+
|
142
|
+
#
|
143
|
+
# 指定URLのHTTPヘッダから時刻を表すlast-modifiedフィールドまたはdateフィールのの値を文字列とUNIXタイムで取得
|
144
|
+
# @param url [String] HTTPヘッダを取得したいURL
|
145
|
+
# @return [Array] 第0要素: 指定フィールドの値(String) 第1要素: 指定フィールドの値(UNIXタイム)
|
146
|
+
def get_modified_in_datetime_or_date_in_datetime(url)
|
147
|
+
connection = Faraday.new(url) do |conn|
|
148
|
+
conn.use(FaradayMiddleware::FollowRedirects)
|
149
|
+
conn.adapter(:net_http)
|
150
|
+
end
|
151
|
+
@mes.output_debug("url=#{url}")
|
152
|
+
res = connection.head(url)
|
153
|
+
get_modified_in_datetime_or_date_in_datetime_from_header(res.headers)
|
154
|
+
end
|
155
|
+
|
156
|
+
#
|
157
|
+
# 時刻を"年月日-時分秒"の形式の文字列にする
|
158
|
+
# @param datetime [Datetime] Datetimeクラスのインスタンス
|
159
|
+
# @return [String] "年月日-時分秒"の形式の文字列
|
160
|
+
def get_datestring(datetime)
|
161
|
+
datetime.strftime("%Y%m%d-%H%M%S")
|
162
|
+
end
|
163
|
+
|
164
|
+
#
|
165
|
+
# 現在時刻をDatetimeクラスのインスタンスと文字列にする
|
166
|
+
# @return [Array] 第0要素: Datetimeクラスのインスタンス 第1要素: "年月日-時分秒"の形式の文字列
|
167
|
+
def current_time
|
168
|
+
datetime = DateTime.now
|
169
|
+
datetimestr = get_datestring(datetime)
|
170
|
+
[datetime, datetimestr]
|
171
|
+
end
|
172
|
+
|
173
|
+
#
|
174
|
+
# 指定サイトでダウンロード指定された全URLのHTTPヘッダの時刻を取得して一覧をファイルに保存
|
175
|
+
# @param dir [String] HTTPヘッダ時刻一覧ファイルの保存先ディレクトリ
|
176
|
+
# @return [Array] 第0要素: Datetimeクラスのインスタンス 第1要素: "年月日-時分秒"の形式の文字列
|
177
|
+
# @note 一覧を保存するファイルのファイル名はsite-年月日-時分秒.tsvである
|
178
|
+
def get_remote_file_headers(dir)
|
179
|
+
_, datetimestr = current_time
|
180
|
+
|
181
|
+
fname = %Q(site-#{datetimestr}.tsv)
|
182
|
+
fpath = File.join(dir, fname)
|
183
|
+
|
184
|
+
@mes.exc_file_write(fpath) do
|
185
|
+
File.open(fpath, "w") do |ofile|
|
186
|
+
@category_x[:category].each do |_k, v|
|
187
|
+
v.each do |_k2, v2|
|
188
|
+
filename = v2[@env.htmlfile_index]
|
189
|
+
next if v2[@env.alias_htmlfile_index]
|
190
|
+
|
191
|
+
if %r{/$}.match?(@url)
|
192
|
+
file_url = URI.join(@url, filename)
|
193
|
+
else
|
194
|
+
file_url = URI.join(@url, "/", filename)
|
195
|
+
end
|
196
|
+
ary = get_modified_in_datetime_or_date_in_datetime(file_url)
|
197
|
+
unless ary.all?
|
198
|
+
@mes.output_error("Can't find last-modified header from #{@url}")
|
199
|
+
end
|
200
|
+
v2.concat(ary)
|
201
|
+
|
202
|
+
ofile.puts(v2.join("\t"))
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
@status_file.fname = fname
|
208
|
+
@status_file.fpath = fpath
|
209
|
+
@status_file.last_datetime = datetimestr
|
210
|
+
@status_file.update
|
211
|
+
end
|
212
|
+
|
213
|
+
#
|
214
|
+
# 引数で指定したファイルが書込み可能であるように書込み先ディレクトリを作成
|
215
|
+
# @param dir [String] ディレクトリ
|
216
|
+
# @param filename [String] ファイルへのパス(ファイル名のみも可)
|
217
|
+
def prepare_new_write_path(dir, filename)
|
218
|
+
dirname = File.dirname(filename)
|
219
|
+
if dirname != "."
|
220
|
+
dirpath = File.join(dir, dirname)
|
221
|
+
@mes.exc_make_directory(dirpath) { FileUtils.mkdir_p(dirpath) }
|
222
|
+
basename = File.basename(filename)
|
223
|
+
fpath = File.join(dirpath, basename)
|
224
|
+
else
|
225
|
+
fpath = File.join(dir, filename)
|
226
|
+
end
|
227
|
+
fpath
|
228
|
+
end
|
229
|
+
|
230
|
+
def get_remote_contents_sub(target_hash, listfile, last_contents_path)
|
231
|
+
target_hash.each do |_, target_def|
|
232
|
+
filename = target_def[@env.htmlfile_index]
|
233
|
+
next if target_def[@env.alias_htmlfile_index]
|
234
|
+
|
235
|
+
if %r{/$}.match?(@url)
|
236
|
+
file_url = URI.join(@url, filename)
|
237
|
+
else
|
238
|
+
file_url = URI.join(@url, "/", filename)
|
239
|
+
end
|
240
|
+
remote_datetime_str, remote_datetime_unixtime, content = get_remote_file(file_url)
|
241
|
+
unless [remote_datetime_str, remote_datetime_unixtime].all?
|
242
|
+
@mes.output_error("Can't get content from #{file_url}")
|
243
|
+
listfile.add([filename, remote_datetime_str, remote_datetime_unixtime, nil])
|
244
|
+
|
245
|
+
sleep(ACCESS_WAIT_SEC)
|
246
|
+
next
|
247
|
+
end
|
248
|
+
fpath = prepare_new_write_path(last_contents_path, filename)
|
249
|
+
|
250
|
+
@mes.exc_file_write(fpath) do
|
251
|
+
File.open(fpath, "w") do |ofile|
|
252
|
+
if content
|
253
|
+
ofile.puts(content)
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
257
|
+
listfile.add([filename, remote_datetime_str, remote_datetime_unixtime, Digest::MD5.hexdigest(content)])
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
def get_remote_contents(dir)
|
262
|
+
_, datetimestr = current_time
|
263
|
+
|
264
|
+
@mes.output_info("dir=#{dir}")
|
265
|
+
@mes.output_info("datetimestr=#{datetimestr}")
|
266
|
+
|
267
|
+
last_contents_path = File.absolute_path(File.join(dir, datetimestr))
|
268
|
+
@mes.exc_make_directory(last_contents_path) { FileUtils.mkdir_p(last_contents_path) }
|
269
|
+
|
270
|
+
lf = ListFile.new(last_contents_path, @mes)
|
271
|
+
@category_x[:category].each do |_, target_hash|
|
272
|
+
get_remote_contents_sub(target_hash, lf, last_contents_path)
|
273
|
+
end
|
274
|
+
lf.close
|
275
|
+
@status_file.last_contents_path = last_contents_path
|
276
|
+
@status_file.update
|
277
|
+
end
|
278
|
+
|
279
|
+
def update_htmlfiles_subtarget(subtarget, src_fpath)
|
280
|
+
dest_fpath = prepare_new_write_path(@env.absolutepath_root, subtarget.filedir.html_input)
|
281
|
+
unless dest_fpath
|
282
|
+
dir = File.dirname(subtarget.filedir.html_input)
|
283
|
+
path = File.join(@env.absolutepath_root, dir)
|
284
|
+
@mes.exc_make_directory(path) { FileUtils.mkdir_p(path) }
|
285
|
+
dest_fpath2 = prepare_new_write_path(@env.absolutepath_root, subtarget.filedir.html_input)
|
286
|
+
if dest_fpath2
|
287
|
+
dest_fpath = dest_fpath2
|
288
|
+
else
|
289
|
+
@mes.output_fatal("Can't find dest dir(#{path})")
|
290
|
+
exit(@mes.ec("EXIT_CODE_CANNOT_FIND_DEST_DIR"))
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
@mes.exc_file_copy(src_fpath, dest_fpath) { FileUtils.cp(src_fpath, dest_fpath) }
|
295
|
+
@mes.output_info("HtmlUtils.divideHtml dest_fpath=#{dest_fpath}")
|
296
|
+
ary = HTMLUtils.new(dest_fpath, @mes).divide_html
|
297
|
+
dir = File.dirname(dest_fpath)
|
298
|
+
(0..2).each do |x|
|
299
|
+
ofname = File.join(dir, %Q(#{x}.html))
|
300
|
+
@mes.exc_file_write(ofname) { File.open(ofname, "w") {|f| f.puts(ary[x]) } }
|
301
|
+
end
|
302
|
+
in_html = File.join(dir, %Q(1.html))
|
303
|
+
unless File.exist?(in_html)
|
304
|
+
@mes.output_fatal("Can't find file(=#{in_html}")
|
305
|
+
exit(@mes.ec("EXIT_CODE_CANNOT_FIND_FILE"))
|
306
|
+
end
|
307
|
+
out_md = prepare_new_write_path(@env.absolutepath_root, subtarget.filedir.input_md)
|
308
|
+
simple_html2md(in_html, out_md)
|
309
|
+
|
310
|
+
path = File.join(@env.absolutepath_root, subtarget.workDir)
|
311
|
+
@mes.exc_make_directory(subtarget.workDir) { FileUtils.mkdir_p(path) }
|
312
|
+
end
|
313
|
+
|
314
|
+
def update_htmlfiles
|
315
|
+
if @status_file.nil? || @status_file.last_contents_path.nil? || @status_file.last_contents_path.empty?
|
316
|
+
@mes.output_info("@status_file=#{@status_file}")
|
317
|
+
unless @status_file.nil?
|
318
|
+
@mes.output_info("@status_file.last_contents_path=#{@status_file.last_contents_path}")
|
319
|
+
end
|
320
|
+
exit(@mes.ec("EXIT_CODE_EXECUTE_SETUP_BEFORE_UPDATE_HTMLFILES"))
|
321
|
+
else
|
322
|
+
@category.each do |_name, category_struct|
|
323
|
+
category_struct.subTargets.each do |_k, v|
|
324
|
+
next unless v.aliashtmlfile.empty?
|
325
|
+
filename = v.htmlfile
|
326
|
+
next if filename.empty?
|
327
|
+
|
328
|
+
src_fpath = File.join(@status_file.last_contents_path, filename)
|
329
|
+
unless File.exist?(src_fpath)
|
330
|
+
@mes.output_info("#{src_fpath} doesn't exist")
|
331
|
+
next
|
332
|
+
end
|
333
|
+
update_htmlfiles_subtarget(v, src_fpath)
|
334
|
+
end
|
335
|
+
end
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
def simple_html2md(input_htmlfname, outputmd)
|
340
|
+
ret = false
|
341
|
+
_, _, s = Open3.capture3(%Q(pandoc -o #{outputmd} -t markdown #{input_htmlfname}))
|
342
|
+
|
343
|
+
if s.exited?
|
344
|
+
if s.exitstatus == 0
|
345
|
+
ret = true
|
346
|
+
else
|
347
|
+
@mes.output_error("Can't convert from html to md by pandoc(IN:#{input_htmlfname} OUT:#{outputmd}(exit_code=#{s.exitstatus})")
|
348
|
+
exit(@mes.ec("EXIT_CODE_CANNOT_CONVERT_FROM_HTML_TO_MD"))
|
349
|
+
end
|
350
|
+
else
|
351
|
+
@mes.output_error("Pandoc exit abnormally")
|
352
|
+
exit(@mes.ec("EXIT_CODE_PANDOC_EXIT_ABNORMALLY"))
|
353
|
+
end
|
354
|
+
|
355
|
+
ret
|
356
|
+
end
|
357
|
+
end
|
358
|
+
end
|