Module: VivlioStarter::CLI::PreProcessCommands::QrTransformer
- Defined in:
- lib/vivlio_starter/cli/pre_process/qr_transformer.rb
Overview
@qr:URL を QR コード SVG の へ変換するモジュール。
Constant Summary collapse
- REL_BASE =
生成物の出力先(images/ 配下)。
'qr'- QR_PATTERN =
@qr:に続く URL。空白か)の手前まで(§1.4)。 %r{@qr:(https?://[^\s)]+)}- MODULE_SIZE =
QR の 1 モジュール(黒白の 1 マス)の辺長 px。印刷 18mm 角でも読み取れる解像度。
4- MASK =
インラインコード退避用の番兵(本文に現れない NUL 文字)。
0.chr
Class Method Summary collapse
-
.available? ⇒ Boolean
rqrcode が使えるか(gem 未導入の環境でもビルドは止めない)。.
-
.build_svg(url) ⇒ Object
rqrcode で SVG 本体を組み立て、intrinsic size と viewBox の両方を備えさせる。.
-
.ensure_viewbox(svg) ⇒ Object
width/height しか持たない SVG に同値の viewBox を補う(既にあればそのまま)。.
-
.render_one(url, out_dir) ⇒ Object
URL 1 件を SVG 化して
タグ文字列を返す。生成できなければ nil。.
-
.replace_in_prose(content) ⇒ Object
コード(フェンス・インラインコード)を避けて各プローズ行を書き換える。 Masking.each_prose_line はフェンスだけを判定するため、インラインコード内の 例示(
@qr:https://…)はここで退避してから戻す。. -
.transform(content, source_filename:) ⇒ String
本文中の @qr:URL をすべて
へ置換する。.
-
.warn_gem_missing(content, source_filename) ⇒ Object
--- 警告(出現位置つき・修正案つき) ---.
- .warn_render_failed(source_filename, lineno, url) ⇒ Object
Class Method Details
.available? ⇒ Boolean
rqrcode が使えるか(gem 未導入の環境でもビルドは止めない)。
130 131 132 133 134 135 136 137 138 139 |
# File 'lib/vivlio_starter/cli/pre_process/qr_transformer.rb', line 130 def available? return @available unless @available.nil? @available = begin require 'rqrcode' true rescue LoadError false end end |
.build_svg(url) ⇒ Object
rqrcode で SVG 本体を組み立て、intrinsic size と viewBox の両方を備えさせる。
110 111 112 113 114 115 116 |
# File 'lib/vivlio_starter/cli/pre_process/qr_transformer.rb', line 110 def build_svg(url) svg = RQRCode::QRCode.new(url).as_svg(use_path: true, module_size: MODULE_SIZE, viewbox: false) ensure_viewbox(svg) rescue StandardError => e Common.log_debug("[qr] SVG 生成に失敗: #{url} - #{e.}") nil end |
.ensure_viewbox(svg) ⇒ Object
width/height しか持たない SVG に同値の viewBox を補う(既にあればそのまま)。
119 120 121 122 123 124 125 126 127 |
# File 'lib/vivlio_starter/cli/pre_process/qr_transformer.rb', line 119 def ensure_viewbox(svg) return svg if svg.nil? || svg.include?('viewBox=') width = svg[/<svg[^>]*\bwidth="([\d.]+)"/, 1] height = svg[/<svg[^>]*\bheight="([\d.]+)"/, 1] return svg unless width && height svg.sub(/<svg\b/, %(<svg viewBox="0 0 #{width} #{height}")) end |
.render_one(url, out_dir) ⇒ Object
URL 1 件を SVG 化して タグ文字列を返す。生成できなければ nil。
94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/vivlio_starter/cli/pre_process/qr_transformer.rb', line 94 def render_one(url, out_dir) name = "#{Digest::SHA1.hexdigest(url)[0, 12]}.svg" path = File.join(out_dir, name) unless File.exist?(path) svg = build_svg(url) return nil unless svg FileUtils.mkdir_p(out_dir) File.write(path, svg, encoding: 'utf-8') end %(<img class="vs-qr" src="images/#{REL_BASE}/#{name}" alt="#{CGI.escapeHTML(url)}">) end |
.replace_in_prose(content) ⇒ Object
コード(フェンス・インラインコード)を避けて各プローズ行を書き換える。
Masking.each_prose_line はフェンスだけを判定するため、インラインコード内の
例示(@qr:https://…)はここで退避してから戻す。
79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/vivlio_starter/cli/pre_process/qr_transformer.rb', line 79 def replace_in_prose(content) lines = content.lines Masking.each_prose_line(content) do |line, lineno| spans = [] masked = line.gsub(/`[^`\n]+`/) do spans << Regexp.last_match(0) "#{MASK}QR#{spans.size - 1}#{MASK}" end replaced = yield(masked, lineno) lines[lineno - 1] = replaced.gsub(/#{MASK}QR(\d+)#{MASK}/) { spans[Regexp.last_match(1).to_i] } end lines.join end |
.transform(content, source_filename:) ⇒ String
本文中の @qr:URL をすべて へ置換する。
63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/vivlio_starter/cli/pre_process/qr_transformer.rb', line 63 def transform(content, source_filename:) return content unless content.include?('@qr:') return warn_gem_missing(content, source_filename) unless available? out_dir = File.join(Common::BUILD_HTML_DIR, 'images', REL_BASE) replace_in_prose(content) do |line, lineno| line.gsub(QR_PATTERN) do url = Regexp.last_match(1) render_one(url, out_dir) || warn_render_failed(source_filename, lineno, url) end end end |
.warn_gem_missing(content, source_filename) ⇒ Object
--- 警告(出現位置つき・修正案つき) ---
143 144 145 146 147 148 149 |
# File 'lib/vivlio_starter/cli/pre_process/qr_transformer.rb', line 143 def warn_gem_missing(content, source_filename) Common.log_warn( "[qr] #{source_filename}: rqrcode が無いため @qr:URL を QR コードにできません(記法のまま出力します)", detail: '→ `bundle install`(または `gem install rqrcode`)で導入できます。' ) content end |
.warn_render_failed(source_filename, lineno, url) ⇒ Object
151 152 153 154 155 156 157 |
# File 'lib/vivlio_starter/cli/pre_process/qr_transformer.rb', line 151 def warn_render_failed(source_filename, lineno, url) Common.log_warn( "[qr] #{source_filename}:#{lineno} - QR コードを生成できませんでした(記法のまま残します)", detail: "URL: #{url}\n→ URL が長すぎないか・不正な文字を含まないか確認してください。" ) "@qr:#{url}" end |