Class: SiteSetting

Inherits:
Object
  • Object
show all
Defined in:
lib/sitesetting.rb

Constant Summary collapse

NOVEL_SITE_SETTING_DIR =
"webnovel/"
EXCLUDE_KEYS =
%w(name version)

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path) ⇒ SiteSetting

Returns a new instance of SiteSetting.



74
75
76
77
78
# File 'lib/sitesetting.rb', line 74

def initialize(path)
  @match_values = {}
  @yaml = YAML.unsafe_load_file(path)
  @path = path
end

Instance Attribute Details

#pathObject (readonly)

Returns the value of attribute path.



14
15
16
# File 'lib/sitesetting.rb', line 14

def path
  @path
end

#yamlObject (readonly)

Returns the value of attribute yaml.



14
15
16
# File 'lib/sitesetting.rb', line 14

def yaml
  @yaml
end

Class Method Details

.find(toc_url) ⇒ Object



57
58
59
60
61
62
63
64
65
66
67
# File 'lib/sitesetting.rb', line 57

def find(toc_url)
  result = nil
  settings.each_value do |s|
    setting = s.clone
    if setting.multi_match(toc_url, "url")
      result = setting
      break
    end
  end
  result
end

.load_file(path) ⇒ Object



69
70
71
# File 'lib/sitesetting.rb', line 69

def load_file(path)
  new(path)
end

.load_settingsObject

小説サイトの定義ファイルを全部読み込む

スクリプト同梱の設定ファイルを読み込んだあと、ユーザの小説の管理ディレクトリ内にある webnovel ディレクトリからも定義ファイルを読み込む



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/sitesetting.rb', line 23

def load_settings
  result = {}
  load_paths = [
    Narou.script_dir.join(NOVEL_SITE_SETTING_DIR, "*.yaml"),
    Narou.root_dir.join(NOVEL_SITE_SETTING_DIR, "*.yaml")
  ].uniq
  Dir.glob(load_paths) do |path|
    setting = SiteSetting.load_file(path)
    name = setting["name"]
    @narou ||= setting if name == "小説家になろう"
    origin = result[name]
    origin&.merge(setting)
    result[name] ||= setting
  end
  if result.empty?
    error "小説サイトの定義ファイルがひとつもありません"
    exit Narou::EXIT_ERROR_CODE
  end
  unless @narou
    error "小説家になろうの定義ファイルが見つかりませんでした"
    exit Narou::EXIT_ERROR_CODE
  end
  result
end

.narouObject



52
53
54
55
# File 'lib/sitesetting.rb', line 52

def narou
  settings unless @narou
  @narou.clone
end

.settingsObject



48
49
50
# File 'lib/sitesetting.rb', line 48

def settings
  @settings ||= load_settings
end

Instance Method Details

#[](key) ⇒ Object



80
81
82
# File 'lib/sitesetting.rb', line 80

def [](key)
  replace_group_values(key)
end

#[]=(key, value) ⇒ Object



84
85
86
# File 'lib/sitesetting.rb', line 84

def []=(key, value)
  @match_values[key] = value
end

#clearObject



88
89
90
# File 'lib/sitesetting.rb', line 88

def clear
  @match_values.clear
end

#do_replace(dest, option_values) ⇒ Object



149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/sitesetting.rb', line 149

def do_replace(dest, option_values)
  return dest unless dest.respond_to?(:gsub)
  values = yaml.merge(@match_values).merge(option_values)
  dest.gsub(/\\\\k<(.+?)>/) do |match|
    value = values[$1]
    if value
      value.gsub(/\\\\k<(.+?)>/) do
        replace_group_values($1, option_values)
      end
    else
      match
    end
  end
end

#initialize_copy(_obj) ⇒ Object



92
93
94
# File 'lib/sitesetting.rb', line 92

def initialize_copy(_obj)
  @match_values = {}
end

#is_container?(value) ⇒ Boolean

Returns:

  • (Boolean)


133
134
135
# File 'lib/sitesetting.rb', line 133

def is_container?(value)
  value.is_a?(Hash) || value.is_a?(Narou::API)
end

#matched?(key) ⇒ Boolean

Returns:

  • (Boolean)


96
97
98
# File 'lib/sitesetting.rb', line 96

def matched?(key)
  @match_values[key]
end

#merge(setting) ⇒ Object



166
167
168
169
170
171
# File 'lib/sitesetting.rb', line 166

def merge(setting)
  validate_version(setting) or return
  (setting.yaml.keys - EXCLUDE_KEYS).each do |key|
    yaml[key] = setting.yaml[key]
  end
end

#multi_match(source, *keys) ⇒ Object



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/sitesetting.rb', line 100

def multi_match(source, *keys)
  match_data = nil
  keys.each do |key|
    setting_value = self[key] or next
    [*setting_value].each do |value|
      handle = SiteSettingHandler.handler(self, value)
      match_data = handle&.match(source) # ハンドルオブジェクトを得て、それにより処理する
      next unless match_data
      value = handle.value if handle.respond_to?(:value)
                                       # rubocop:disable Layout/CommentIndentation
                                       # 通常はこれまで通りだが、valueを変更することも可能にする
      @match_values[key] = value       # yamlのキーでもmatch_valuesに設定しておくが、
      update_match_values(match_data)  # ←ここで同名のグループ名が定義されていたら上書きされるので注意
                                       # 例えば、title: <title>(?<title>.+?)</title> と定義されていた場合、
                                       # @match_values["title"] には (?<title>.+?) 部分の要素が反映される
                                       # rubocop:enable Layout/CommentIndentation
      break
    end
  end
  match_data
end

#multi_match_once(source, *keys) ⇒ Object



122
123
124
125
# File 'lib/sitesetting.rb', line 122

def multi_match_once(source, *keys)
  clear
  multi_match(source, *keys)
end

#replace_group_values(key, option_values = {}) ⇒ Object



137
138
139
140
141
142
143
144
145
146
147
# File 'lib/sitesetting.rb', line 137

def replace_group_values(key, option_values = {})
  buf = option_values[key] || @match_values[key] || yaml[key]
  return buf if is_container?(buf)
  if buf.is_a?(Array)
    buf.map do |dest|
      do_replace(dest, option_values)
    end
  else
    do_replace(buf, option_values)
  end
end

#update_match_values(match_data) ⇒ Object



127
128
129
130
131
# File 'lib/sitesetting.rb', line 127

def update_match_values(match_data)
  match_data.names.each do |name|
    @match_values[name] = match_data[name] || ""
  end
end

#validate_version(setting) ⇒ Object



173
174
175
176
177
178
179
180
# File 'lib/sitesetting.rb', line 173

def validate_version(setting)
  version = setting.yaml["version"]
  return true unless version # version が指定されていない場合は常に上書きを許可する
  return true if version >= yaml["version"]

  error "#{setting.path} の内容が古いため読み込みをスキップしました"
  false
end