# -*- coding: utf-8 -*- # # Copyright 2013 whiteleaf. All rights reserved. # require "open-uri" # # 挿絵管理 # class Illustration ILLUST_DIR = "挿絵/" NAROU_ILLUST_URL = "http://%s.mitemin.net/userpageimage/viewimage/icode/%s/" NAROU_ILLUST_TAG_PATTERN = /[  \t]*?<(i[0-9]+)\|([0-9]+)>\n?/m MIME = { "image/jpeg" => "jpg", "image/png" => "png", "image/gif" => "gif", "image/bmp" => "bmp" } class UnknownMIMEType < StandardError; end def initialize(setting, inspector) @setting = setting @inspector = inspector end def scanner(source, &block) source.gsub!(/[#挿絵((.+?))入る]/) do |match| url = $1 if url =~ URI.regexp path = download_image(url) path ? block.call(make_illust_chuki(path)) : "" else # URLでなければ、ローカルのパスが指定されたと判断してそのままの注記を使う block.call(match) end end source.gsub!(NAROU_ILLUST_TAG_PATTERN) do id1, id2 = $1, $2 basename = "#{id1},#{id2}.*" url = NAROU_ILLUST_URL % [id2, id1] path = download_image(url, basename) path ? block.call(make_illust_chuki(path)) : "" end source end # # 画像のURLからデータを保存して、保存したファイルの絶対パスを返す # def download_image(url, basename = nil) basename = File.basename(basename ? basename : url, ".*") if path = search_image(basename) return path end open(url, make_open_uri_options(allow_redirections: :safe)) do |fp| content_type = fp.meta["content-type"] ext = MIME[content_type] or raise UnknownMIMEType, content_type illust_abs_path = create_illust_path(basename) + "." + ext open(illust_abs_path, "wb") do |write_fp| write_fp.write(fp.read) end @inspector.info("挿絵「#{File.basename(illust_abs_path)}」を保存しました。") return illust_abs_path end rescue UnknownMIMEType => e @inspector.error("Illustration#download_image: #{url} は未対応の画像フォーマットです" + "(content-type: #{e.message})") nil rescue StandardError => e @inspector.error("Illustration#download_image: #{url} を処理中に例外が発生しました(#{e})") nil end def search_image(basename) path = create_illust_path(basename) + ".*" Dir.glob(path)[0] end def create_illust_path(basename) illust_abs_dir = File.join(@setting.archive_path, ILLUST_DIR) Dir.mkdir(illust_abs_dir) unless File.exist?(illust_abs_dir) File.join(illust_abs_dir, basename) end def make_illust_chuki(illust_path) rel_illust_path = to_rel(@setting.archive_path, illust_path) "[#挿絵(#{rel_illust_path})入る]" end # # 絶対パスから相対パスを作成 # http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-list/36985 # def to_rel(base, target) sep = /#{File::SEPARATOR}+/o base = base.split(sep) base.pop target = target.split(sep) while base.shift == target.shift end File.join([".."]*base.size+target) end end