lib/md2site/setup.rb in md2site-0.1.2 vs lib/md2site/setup.rb in md2site-0.1.4

- old
+ new

@@ -18,32 +18,34 @@ require "md2site/statusfile" require "md2site/listfile" # # 初期化 - # @param env [Env] Envクラスのメソッド + # + # @param env [Env] 環境クラスのメソッド # @param mes [Messagex] Messagexクラスのインスタンス def initialize(env, mes) @env = env @mes = mes - @category = @env.category - @category_x = @env.category_x + @category_target = @env.category_target absolute_path_status_file = env.conf_hs["ABSOLUTE_PATH_STATUS_FILE"] @url = @env.conf_hs["URL"] @res = {} @mes.add_exitcode("EXIT_CODE_BY_EXCEPTION") @mes.add_exitcode("EXIT_CODE_EXECUTE_SETUP_BEFORE_UPDATE_HTMLFILES") @mes.add_exitcode("EXIT_CODE_CANNOT_FIND_DEST_DIR") @mes.add_exitcode("EXIT_CODE_CANNOT_CONVERT_FROM_HTML_TO_MD") @mes.add_exitcode("EXIT_CODE_PANDOC_EXIT_ABNORMALLY") - @status_file = StatusFile.new(absolute_path_status_file, @url, @mes) + @status_file = StatusFile.new(absolute_path_status_file, @env.absolutepath_root, @url, @mes) end # # サブコマンド実行 + # # @param option [String] サブコマンドのオプション + # @return [void] def execute_subcommand(option) case option.name when "contentUpdate" update_htmlfiles when "zcontents" @@ -65,10 +67,11 @@ private # # リモートサイトのファイル取得 + # # @param url [String] 取得先URL # @return [Array] 第0要素:Datetime 第1要素:UNIXタイム 第2要素:HTTPボディ def get_remote_file(url) connection = Faraday.new(url) do |conn| conn.use(FaradayMiddleware::FollowRedirects) @@ -80,10 +83,11 @@ [datetime_str, datetime_unix_time, res.body] end # # HTTPヘッダの指定フィールドの値を文字列とUNITタイムで取得する + # # @param headers [Hash] HTTPヘッダを表すハッシュ # @param key [String] HTTPヘッダのフィールドを指定するキー # @return [Array] 第0要素: 指定フィールドの値(String) 第1要素: 指定フィールドの値(UNIXタイム) def get_header_value_of_datetime(headers, key) @res[key] ||= Regexp.compile(Regexp.escape(key)) @@ -111,26 +115,29 @@ [s, unixtime] end # # HTTPヘッダのlast-modifiedフィールドの値を文字列とUNITタイムで取得 + # # @param headers [Hash] HTTPヘッダを表すハッシュ # @return [Array] 第0要素: 指定フィールドの値(String) 第1要素: 指定フィールドの値(UNIXタイム) def get_modified_in_datetime_from_header(headers) get_header_value_of_datetime(headers, "last-modified") end # # HTTPヘッダのdateフィールドの値を文字列とUNITタイムで取得 + # # @param headers [Hash] HTTPヘッダを表すハッシュ # @return [Array] 第0要素: 指定フィールドの値(String) 第1要素: 指定フィールドの値(UNIXタイム) def get_date_in_datetime_from_header(headers) get_header_value_of_datetime(headers, "date") end # # HTTPヘッダから時刻を表すlast-modifiedフィールドまたはdateフィールのの値を文字列とUNIXタイムで取得 + # # @param headers [Hash] HTTPヘッダを表すハッシュ # @return [Array] 第0要素: 指定フィールドの値(String) 第1要素: 指定フィールドの値(UNIXタイム) def get_modified_in_datetime_or_date_in_datetime_from_header(headers) ary = get_modified_in_datetime_from_header(headers) unless ary.all? @@ -139,10 +146,11 @@ ary end # # 指定URLのHTTPヘッダから時刻を表すlast-modifiedフィールドまたはdateフィールのの値を文字列とUNIXタイムで取得 + # # @param url [String] HTTPヘッダを取得したいURL # @return [Array] 第0要素: 指定フィールドの値(String) 第1要素: 指定フィールドの値(UNIXタイム) def get_modified_in_datetime_or_date_in_datetime(url) connection = Faraday.new(url) do |conn| conn.use(FaradayMiddleware::FollowRedirects) @@ -153,27 +161,30 @@ get_modified_in_datetime_or_date_in_datetime_from_header(res.headers) end # # 時刻を"年月日-時分秒"の形式の文字列にする + # # @param datetime [Datetime] Datetimeクラスのインスタンス # @return [String] "年月日-時分秒"の形式の文字列 def get_datestring(datetime) datetime.strftime("%Y%m%d-%H%M%S") end # # 現在時刻をDatetimeクラスのインスタンスと文字列にする + # # @return [Array] 第0要素: Datetimeクラスのインスタンス 第1要素: "年月日-時分秒"の形式の文字列 def current_time datetime = DateTime.now datetimestr = get_datestring(datetime) [datetime, datetimestr] end # # 指定サイトでダウンロード指定された全URLのHTTPヘッダの時刻を取得して一覧をファイルに保存 + # # @param dir [String] HTTPヘッダ時刻一覧ファイルの保存先ディレクトリ # @return [Array] 第0要素: Datetimeクラスのインスタンス 第1要素: "年月日-時分秒"の形式の文字列 # @note 一覧を保存するファイルのファイル名はsite-年月日-時分秒.tsvである def get_remote_file_headers(dir) _, datetimestr = current_time @@ -181,27 +192,26 @@ fname = %Q(site-#{datetimestr}.tsv) fpath = File.join(dir, fname) @mes.exc_file_write(fpath) do File.open(fpath, "w") do |ofile| - @category_x[:category].each do |_k, v| - v.each do |_k2, v2| - filename = v2[@env.htmlfile_index] - next if v2[@env.alias_htmlfile_index] + @category_target.each do |_k, v| + v[:subTargets].each do |_k2, subtarget| + filename = subtarget.htmlfile + next unless subtarget.aliashtmlfile && !subtarget.aliashtmlfile&.empty? if %r{/$}.match?(@url) file_url = URI.join(@url, filename) else file_url = URI.join(@url, "/", filename) end ary = get_modified_in_datetime_or_date_in_datetime(file_url) unless ary.all? @mes.output_error("Can't find last-modified header from #{@url}") end - v2.concat(ary) - ofile.puts(v2.join("\t")) + ofile.puts([file_url].join("\t")) end end end end @status_file.fname = fname @@ -210,74 +220,121 @@ @status_file.update end # # 引数で指定したファイルが書込み可能であるように書込み先ディレクトリを作成 + # # @param dir [String] ディレクトリ # @param filename [String] ファイルへのパス(ファイル名のみも可) - def prepare_new_write_path(dir, filename) + def prepare_new_write_path(dir, filename, postfix=nil) + if postfix + extname = File.extname(filename) + basename = File.basename(filename, extname) + new_fname = %Q(#{basename}#{postfix}#{extname}) + else + basename = File.basename(filename) + new_fname = basename + end + dirname = File.dirname(filename) if dirname != "." dirpath = File.join(dir, dirname) @mes.exc_make_directory(dirpath) { FileUtils.mkdir_p(dirpath) } - basename = File.basename(filename) - fpath = File.join(dirpath, basename) + fpath = File.join(dirpath, new_fname) else - fpath = File.join(dir, filename) + fpath = File.join(dir, new_fname) end + fpath end - def get_remote_contents_sub(target_hash, listfile, last_contents_path) - target_hash.each do |_, target_def| - filename = target_def[@env.htmlfile_index] - next if target_def[@env.alias_htmlfile_index] + # + # 指定サイトでダウンロード指定された全URLのをファイルとして、保存先ディレクトリにダウンロードし、 + # ダウンロードステータスファイルを更新 + # + # @param subtarget_hash [Hash] サブターゲット名をキーとしてサブターゲットストラクトを値とするハッシュ + # @param listfile [Listfile] ダウンロードファイル一覧ファイル + # @param last_contents_path [String] ダウンロード保存先ディレクトリ + # @return [void] + def get_remote_contents_subtargets(subtarget_hash, listfile, last_contents_path) + subtarget_hash.each do |_, subtarget_struct| + # filename = target_def[@env.htmlfile_index] + unless subtarget_struct.htmldir&.empty? + filename = File.join(subtarget_struct.htmldir, subtarget_struct.htmlfile) + else + filename = subtarget_struct.htmlfile + end + next unless subtarget_struct.aliashtmlfile&.empty? + # file_urlが'//'とならないようにする if %r{/$}.match?(@url) file_url = URI.join(@url, filename) else file_url = URI.join(@url, "/", filename) end + # file_urlをダウンロードする remote_datetime_str, remote_datetime_unixtime, content = get_remote_file(file_url) + # ダウンロードできなかった場合はエラーメッセージを表示して、次のサブターゲットのダウンロードに移る unless [remote_datetime_str, remote_datetime_unixtime].all? @mes.output_error("Can't get content from #{file_url}") listfile.add([filename, remote_datetime_str, remote_datetime_unixtime, nil]) sleep(ACCESS_WAIT_SEC) next end - fpath = prepare_new_write_path(last_contents_path, filename) + # ダウンロードした内容をファイルに書き込む + fpath = prepare_new_write_path(last_contents_path, filename) @mes.exc_file_write(fpath) do File.open(fpath, "w") do |ofile| if content ofile.puts(content) end end end + # ダウンロードファイル一覧に追加 listfile.add([filename, remote_datetime_str, remote_datetime_unixtime, Digest::MD5.hexdigest(content)]) end end + # + # 指定サイトでダウンロード指定された全URLのをファイルとして、指定ディレクトリ下にダウンロードし、 + # ダウンロードファイル一覧ファイルを作成し、ダウンロードステータスファイルを更新 + # + # @param dir [String] ダウンロードファイルの保存先ディレクトリ + # @return [void] def get_remote_contents(dir) _, datetimestr = current_time @mes.output_info("dir=#{dir}") @mes.output_info("datetimestr=#{datetimestr}") last_contents_path = File.absolute_path(File.join(dir, datetimestr)) @mes.exc_make_directory(last_contents_path) { FileUtils.mkdir_p(last_contents_path) } + # 保存先ディレクトリ内にダウンロードファイル一覧ファイルを作成 lf = ListFile.new(last_contents_path, @mes) - @category_x[:category].each do |_, target_hash| - get_remote_contents_sub(target_hash, lf, last_contents_path) + @category_target.each do |_, target_struct| + # 各ターゲット毎にファイルをダウンロード + get_remote_contents_subtargets(target_struct[:subTargets], lf, last_contents_path) end lf.close + + # ダウンロードステータスファイルを更新 @status_file.last_contents_path = last_contents_path @status_file.update end + # + # ダウンロード保存先ディレクトリから指定サブターゲットのHTMLファイルをサブターゲットで + # 指定されてディレクトリにコピーし、3分割し、中間部分をMarkdown形式に変換する + # + # @param subtarget [String] サブターゲットストラクト + # @param src_fpath [String] コピー元ファイルパス + # @return [void] + # @note HTMLファイルからMarkdown形式ファイルへの変換にはpandocを利用するため、pandoc + # がインストールされていることが前提 def update_htmlfiles_subtarget(subtarget, src_fpath) dest_fpath = prepare_new_write_path(@env.absolutepath_root, subtarget.filedir.html_input) unless dest_fpath dir = File.dirname(subtarget.filedir.html_input) path = File.join(@env.absolutepath_root, dir) @@ -302,27 +359,38 @@ in_html = File.join(dir, %Q(1.html)) unless File.exist?(in_html) @mes.output_fatal("Can't find file(=#{in_html}") exit(@mes.ec("EXIT_CODE_CANNOT_FIND_FILE")) end - out_md = prepare_new_write_path(@env.absolutepath_root, subtarget.filedir.input_md) - simple_html2md(in_html, out_md) - - path = File.join(@env.absolutepath_root, subtarget.workDir) - @mes.exc_make_directory(subtarget.workDir) { FileUtils.mkdir_p(path) } + out_orig_md = prepare_new_write_path(@env.absolutepath_root, subtarget.filedir.input_md, "_orig") + simple_html2md(in_html, out_orig_md) + out_md = File.join(@env.absolutepath_root, subtarget.filedir.input_md) + @mes.exc_file_copy(out_orig_md, out_md) { FileUtils.cp(out_orig_md, out_md) } unless File.exist?(out_md) end + # + # ダウンロードステータスファイルを更新ダウンロード保存先ディレクトリから指定サブターゲットのHTMLファイルをサブターゲットで + # 指定されてディレクトリにコピーし、3分割し、中間部分をMarkdown形式に変換する + # + # @return [void] def update_htmlfiles + # 有効なダウンロードステータスファイルが存在しなければexitする if @status_file.nil? || @status_file.last_contents_path.nil? || @status_file.last_contents_path.empty? @mes.output_info("@status_file=#{@status_file}") unless @status_file.nil? @mes.output_info("@status_file.last_contents_path=#{@status_file.last_contents_path}") end exit(@mes.ec("EXIT_CODE_EXECUTE_SETUP_BEFORE_UPDATE_HTMLFILES")) else - @category.each do |_name, category_struct| + # 全ターゲットの全サブターゲットのうち、エイリアスHTMLファイルが指定されておらず、かつ未ダウンロード + # のもののみをダウンロードする + @category_target.each do |_name, category_struct| category_struct.subTargets.each do |_k, v| + # エイリアスHTMLファイルが指定されていても、ワークディレクトリは必要なため、ここで作成する + path = File.join(@env.absolutepath_root, v.workDir) + @mes.exc_make_directory(path) { FileUtils.mkdir_p(path) } + next unless v.aliashtmlfile.empty? filename = v.htmlfile next if filename.empty? src_fpath = File.join(@status_file.last_contents_path, filename) @@ -334,10 +402,18 @@ end end end end + # + # HTMLファイルをMarkdown形式に変換する + # + # @param input_htmlfname [String] 変換元HTMLファイル名 + # @param outputmd [String] 変換したMakrdown形式ファイル名 + # @return [void] + # @note HTMLファイルからMarkdown形式ファイルへの変換にはpandocを利用するため、pandoc + # がインストールされていることが前提 def simple_html2md(input_htmlfname, outputmd) ret = false _, _, s = Open3.capture3(%Q(pandoc -o #{outputmd} -t markdown #{input_htmlfname})) if s.exited? @@ -353,6 +429,6 @@ end ret end end -end +end