Module: Vivlio::Starter::CLI::PrismLinesCommands

Defined in:
lib/vivlio/starter/cli/prism_lines.rb

Overview

Module: PrismLinesCommands


Prism.js のコードブロック(<pre><code>)に行番号を付与するコマンド群。入力HTMLを解析し、必要なクラスと line-numbers-rows を自動追加して保存する。

提供コマンド:

- prism:lines INPUT_FILE [OUTPUT_FILE]
  入力HTML内の Prism.js コードブロックに行番号を追加する。

備考:

- -v/--verbose で詳細ログを表示(ENV には反映しません)。
- OUTPUT_FILE を省略した場合、INPUT_FILE を上書きします。

Constant Summary collapse

PRISM_LINES_DESC =
{
  short: 'HTMLファイル内のPrism.jsコードブロックに行番号を追加します',
  long: <<~DESC
    指定したHTMLファイル内のPrism.jsコードブロックに行番号を追加します。

    引数:
      INPUT_FILE     入力HTMLファイル(必須)
      OUTPUT_FILE    出力HTMLファイル(省略可、省略時は入力ファイルを上書き)

    オプション:
      -v, --verbose  詳細な処理情報を表示

    使用例:
      vs prism:lines prime.html
      vs prism:lines prime.html prime_with_lines.html
  DESC
}.freeze

Class Method Summary collapse

Class Method Details

.add_prism_line_numbers(input_file, output_file = nil) ⇒ Object

Prism.jsの行番号を追加する処理



64
65
66
67
68
69
70
71
72
# File 'lib/vivlio/starter/cli/prism_lines.rb', line 64

def add_prism_line_numbers(input_file, output_file = nil)
  document = parse_html(input_file)
  document.css('pre').each { |pre| decorate_pre_tag(pre, document) }
  remove_legacy_meta(document)

  target = output_file || input_file
  PostProcessCommands::HtmlParser.save_html_document(target, document)
  log_result(input_file, target)
end

.build_line_numbers_span(document, lines) ⇒ Object

行数分の <span> line-numbers-rows 構造を生成



91
92
93
94
95
96
97
98
99
100
101
# File 'lib/vivlio/starter/cli/prism_lines.rb', line 91

def build_line_numbers_span(document, lines)
  span = Nokogiri::XML::Node.new('span', document)
  span['aria-hidden'] = 'true'
  span['class'] = 'line-numbers-rows'

  lines.times do
    span.add_child(Nokogiri::XML::Node.new('span', document))
  end

  span
end

.combine_class(original, addition) ⇒ Object

既存クラス文字列に安全にクラスを追加



109
110
111
112
# File 'lib/vivlio/starter/cli/prism_lines.rb', line 109

def combine_class(original, addition)
  classes = [original, addition].compact.reject(&:empty?)
  classes.join(' ')
end

.decorate_pre_tag(pre, document) ⇒ Object

<pre> 要素と内包する <code> に行番号用クラスと要素を付与



81
82
83
84
85
86
87
88
# File 'lib/vivlio/starter/cli/prism_lines.rb', line 81

def decorate_pre_tag(pre, document)
  pre[:class] = combine_class(pre[:class], 'line-numbers')
  code = pre.at_css('code')
  return unless code

  code[:class] = combine_class(code[:class], 'line-numbers')
  code.add_child(build_line_numbers_span(document, line_count(pre)))
end

.execute_prism_lines(input_file, output_file = nil) ⇒ Object

Samovar/直接呼び出し用エントリポイント



47
48
49
50
51
52
53
54
55
56
# File 'lib/vivlio/starter/cli/prism_lines.rb', line 47

def execute_prism_lines(input_file, output_file = nil)
  output_file ||= input_file

  unless File.exist?(input_file)
    Common.log_error("エラー: 入力ファイル '#{input_file}' が存在しません")
    return
  end

  add_prism_line_numbers(input_file, output_file)
end

.included(base) ⇒ Object



44
# File 'lib/vivlio/starter/cli/prism_lines.rb', line 44

def included(base); end

.line_count(pre) ⇒ Object

コードの行数を返す



59
60
61
# File 'lib/vivlio/starter/cli/prism_lines.rb', line 59

def line_count(pre)
  pre.text.count("\n") + 1
end

.log_result(input_file, output_file) ⇒ Object

処理完了メッセージを出力



115
116
117
118
# File 'lib/vivlio/starter/cli/prism_lines.rb', line 115

def log_result(input_file, output_file)
  suffix = input_file == output_file ? '' : " -> #{output_file}"
  Common.log_success("行番号付与完了: #{input_file}#{suffix}")
end

.parse_html(path) ⇒ Object

HTMLファイルを Nokogiri ドキュメントに変換(HtmlParser に委譲)



75
76
77
78
# File 'lib/vivlio/starter/cli/prism_lines.rb', line 75

def parse_html(path)
  html = File.read(path, encoding: 'UTF-8')
  PostProcessCommands::HtmlParser.parse_html_document(html)
end

.remove_legacy_meta(document) ⇒ Object

不要な Content-Type メタタグを除去



104
105
106
# File 'lib/vivlio/starter/cli/prism_lines.rb', line 104

def remove_legacy_meta(document)
  document.css('meta[http-equiv="Content-Type"]').each(&:remove)
end