Module: Vivlio::Starter::CLI::EntriesCommands

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

Overview

Module: entries.js 生成ロジック

提供機能:

- HTML から entries.js(ESM)を生成

Constant Summary collapse

ENTRIES_DESC =
{
  short: 'entries.jsを生成します',
  long: <<~DESC
    指定した HTML ファイルから entries.js を生成します。指定が無い場合はカレントディレクトリの全 .html を対象にします。

    処理内容:
    - HTMLファイルからタイトルを取得(titleタグ優先)
    - entries.js をES Module形式で生成
    - 各エントリにパスとタイトル情報を含む

    例:
      vs entries 11-install.html
      vs entries 11-install 12-tutorial
  DESC
}.freeze

Class Method Summary collapse

Class Method Details

.build_entry(html_file) ⇒ Object



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/vivlio/starter/cli/entries.rb', line 83

def build_entry(html_file)
  base_name = File.basename(html_file, '.html')
  title = base_name
  html_title = extract_html_title(html_file)

  if html_title && !html_title.empty?
    title = html_title
  elsif html_title.to_s.empty? && (base_name =~ /^\d+-(.+)$/)
    title = ::Regexp.last_match(1)
  end

  # パスを相対パス形式に正規化(./を接頭辞として付与)
  normalized_path = html_file.start_with?('./') ? html_file : "./#{html_file}"
  { path: normalized_path, title: title }
end

.enable_verbose(context) ⇒ Object



131
132
133
# File 'lib/vivlio/starter/cli/entries.rb', line 131

def enable_verbose(context)
  ENV['VERBOSE'] = '1' if options_of(context)[:verbose]
end

.execute_entries(command_or_context, tokens_or_entries) ⇒ Object



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/vivlio/starter/cli/entries.rb', line 35

def execute_entries(command_or_context, tokens_or_entries)
  ctx = normalized_context(command_or_context)
  enable_verbose(ctx)

  Common.log_action('entries.jsを生成しています...')

  base_dir = '.'
  html_files = resolve_html_files_for_entries(base_dir, tokens_or_entries)
  Common.log_info("目次作成対象ファイル: #{html_files.join(', ')}")

  entries = html_files.map { |html_file| build_entry(html_file) }

  write_entries(base_dir, entries)

  Common.log_success("entries.js生成完了: #{entries.length}件のエントリを登録")
end

.extract_html_title(path) ⇒ Object



100
101
102
103
104
105
106
107
# File 'lib/vivlio/starter/cli/entries.rb', line 100

def extract_html_title(path)
  return unless File.exist?(path)

  content = File.read(path)
  ::Regexp.last_match(1).strip if content =~ %r{<title>(.+?)</title>}
rescue StandardError
  nil
end

.included(base) ⇒ Object



33
# File 'lib/vivlio/starter/cli/entries.rb', line 33

def included(base); end

.normalized_context(command_or_ctx) ⇒ Object



124
125
126
127
128
# File 'lib/vivlio/starter/cli/entries.rb', line 124

def normalized_context(command_or_ctx)
  return command_or_ctx if command_or_ctx.is_a?(Hash)

  { options: options_of(command_or_ctx) }
end

.options_of(command_or_ctx) ⇒ Object



136
137
138
139
140
141
142
143
144
# File 'lib/vivlio/starter/cli/entries.rb', line 136

def options_of(command_or_ctx)
  if command_or_ctx.is_a?(Hash)
    command_or_ctx[:options] || {}
  elsif command_or_ctx.respond_to?(:options)
    command_or_ctx.options || {}
  else
    {}
  end
end

.resolve_html_files_for_entries(base_dir, entries_or_basenames) ⇒ Array<String>

Entry 配列または basename 配列から HTML ファイルパス配列を解決する

Parameters:

  • base_dir (String)

    ベースディレクトリ(プロジェクトルート)

  • entries_or_basenames (Array<TokenResolver::Entry>, Array<String>)

Returns:

  • (Array<String>)

    HTML ファイルパスの配列



57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/vivlio/starter/cli/entries.rb', line 57

def resolve_html_files_for_entries(base_dir, entries_or_basenames)
  raw = Array(entries_or_basenames).compact
  return Dir.glob(File.join(base_dir, '*.html')) if raw.empty?

  # Entry オブジェクトかどうかを判定
  if raw.first.respond_to?(:basename)
    raw.map { |entry| File.join(base_dir, "#{entry.basename}.html") }.uniq
  else
    # basename 配列: パスに変換
    raw.flat_map { |bn| resolve_token(base_dir, bn.to_s) }.uniq
  end
end

.resolve_token(base_dir, token) ⇒ Object



71
72
73
74
75
76
77
78
79
80
# File 'lib/vivlio/starter/cli/entries.rb', line 71

def resolve_token(base_dir, token)
  if File.extname(token) == '.html'
    path = File.dirname(token) == '.' ? File.join(base_dir, token) : token
    File.exist?(path) ? [path] : []
  else
    pattern1 = File.join(base_dir, "#{token}.html")
    pattern2 = File.join(base_dir, "#{token}-*.html")
    Dir.glob([pattern1, pattern2])
  end
end

.write_entries(base_dir, entries) ⇒ Object



110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/vivlio/starter/cli/entries.rb', line 110

def write_entries(base_dir, entries)
  File.open(File.join(base_dir, 'entries.js'), 'w') do |f|
    f.puts 'export default ['
    entries.each_with_index do |entry, i|
      f.puts '  {'
      f.puts %(    "path": "#{entry[:path]}",)
      f.puts %(    "title": "#{entry[:title]}")
      f.puts "  }#{',' if i < entries.length - 1}"
    end
    f.puts ']'
  end
end