bridgetown-core 0.16.0.beta1 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.yardopts +1 -0
- data/bridgetown-core.gemspec +3 -1
- data/lib/bridgetown-core.rb +45 -29
- data/lib/bridgetown-core/collection.rb +5 -1
- data/lib/bridgetown-core/commands/apply.rb +2 -2
- data/lib/bridgetown-core/commands/concerns/actions.rb +2 -1
- data/lib/bridgetown-core/commands/console.rb +4 -4
- data/lib/bridgetown-core/commands/new.rb +1 -1
- data/lib/bridgetown-core/concerns/layout_placeable.rb +1 -1
- data/lib/bridgetown-core/concerns/liquid_renderable.rb +10 -0
- data/lib/bridgetown-core/concerns/site/configurable.rb +24 -22
- data/lib/bridgetown-core/concerns/site/content.rb +46 -33
- data/lib/bridgetown-core/concerns/site/extensible.rb +14 -13
- data/lib/bridgetown-core/concerns/site/localizable.rb +24 -0
- data/lib/bridgetown-core/concerns/site/processable.rb +12 -11
- data/lib/bridgetown-core/concerns/site/renderable.rb +35 -28
- data/lib/bridgetown-core/concerns/site/writable.rb +7 -15
- data/lib/bridgetown-core/concerns/validatable.rb +2 -2
- data/lib/bridgetown-core/configuration.rb +14 -6
- data/lib/bridgetown-core/converter.rb +0 -42
- data/lib/bridgetown-core/converters/erb_templates.rb +93 -17
- data/lib/bridgetown-core/converters/liquid_templates.rb +96 -0
- data/lib/bridgetown-core/converters/markdown.rb +0 -3
- data/lib/bridgetown-core/document.rb +34 -21
- data/lib/bridgetown-core/drops/site_drop.rb +5 -1
- data/lib/bridgetown-core/drops/unified_payload_drop.rb +0 -1
- data/lib/bridgetown-core/drops/url_drop.rb +19 -3
- data/lib/bridgetown-core/excerpt.rb +1 -1
- data/lib/bridgetown-core/filters.rb +37 -55
- data/lib/bridgetown-core/filters/condition_helpers.rb +56 -0
- data/lib/bridgetown-core/frontmatter_defaults.rb +17 -0
- data/lib/bridgetown-core/generators/prototype_generator.rb +42 -25
- data/lib/bridgetown-core/helpers.rb +84 -0
- data/lib/bridgetown-core/liquid_renderer.rb +1 -1
- data/lib/bridgetown-core/log_writer.rb +2 -2
- data/lib/bridgetown-core/page.rb +8 -2
- data/lib/bridgetown-core/plugin_manager.rb +44 -3
- data/lib/bridgetown-core/reader.rb +2 -4
- data/lib/bridgetown-core/readers/collection_reader.rb +1 -0
- data/lib/bridgetown-core/readers/data_reader.rb +4 -3
- data/lib/bridgetown-core/readers/defaults_reader.rb +27 -0
- data/lib/bridgetown-core/readers/layout_reader.rb +1 -0
- data/lib/bridgetown-core/readers/page_reader.rb +1 -0
- data/lib/bridgetown-core/readers/post_reader.rb +29 -15
- data/lib/bridgetown-core/readers/static_file_reader.rb +1 -0
- data/lib/bridgetown-core/renderer.rb +42 -160
- data/lib/bridgetown-core/ruby_template_view.rb +26 -8
- data/lib/bridgetown-core/site.rb +14 -2
- data/lib/bridgetown-core/tags/find.rb +86 -0
- data/lib/bridgetown-core/tags/t.rb +14 -0
- data/lib/bridgetown-core/tags/webpack_path.rb +6 -41
- data/lib/bridgetown-core/utils.rb +69 -2
- data/lib/bridgetown-core/utils/ruby_exec.rb +1 -1
- data/lib/bridgetown-core/version.rb +2 -2
- data/lib/bridgetown-core/watcher.rb +1 -0
- data/lib/site_template/src/_layouts/{default.html → default.liquid} +0 -0
- data/lib/site_template/src/_layouts/{home.html → home.liquid} +0 -0
- data/lib/site_template/src/_layouts/{page.html → page.liquid} +0 -0
- data/lib/site_template/src/_layouts/{post.html → post.liquid} +0 -0
- data/lib/site_template/src/images/.keep +1 -0
- metadata +47 -10
@@ -54,6 +54,10 @@ module Bridgetown
|
|
54
54
|
#
|
55
55
|
# Returns the default value or nil if none was found
|
56
56
|
def find(path, type, setting)
|
57
|
+
merged_data = {}
|
58
|
+
merge_data_cascade_for_path(path, merged_data)
|
59
|
+
return merged_data[setting] if merged_data.key?(setting)
|
60
|
+
|
57
61
|
value = nil
|
58
62
|
old_scope = nil
|
59
63
|
|
@@ -74,6 +78,9 @@ module Bridgetown
|
|
74
78
|
# Returns a hash with all default values (an empty hash if there are none)
|
75
79
|
def all(path, type)
|
76
80
|
defaults = {}
|
81
|
+
|
82
|
+
merge_data_cascade_for_path(path, defaults)
|
83
|
+
|
77
84
|
old_scope = nil
|
78
85
|
matching_sets(path, type).each do |set|
|
79
86
|
if has_precedence?(old_scope, set["scope"])
|
@@ -88,6 +95,16 @@ module Bridgetown
|
|
88
95
|
|
89
96
|
private
|
90
97
|
|
98
|
+
def merge_data_cascade_for_path(path, merged_data)
|
99
|
+
absolute_path = @site.in_source_dir(path)
|
100
|
+
@site.defaults_reader.path_defaults
|
101
|
+
.select { |k, _v| absolute_path.include? k }
|
102
|
+
.sort_by { |k, _v| k.length }
|
103
|
+
.each do |defaults|
|
104
|
+
merged_data.merge!(defaults[1])
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
91
108
|
# Checks if a given default setting scope matches the given path and type
|
92
109
|
#
|
93
110
|
# scope - the hash indicating the scope, as defined in bridgetown.config.yml
|
@@ -10,6 +10,9 @@ module Bridgetown
|
|
10
10
|
class PrototypeGenerator < Generator
|
11
11
|
priority :low
|
12
12
|
|
13
|
+
# @return [Bridgetown::Site]
|
14
|
+
attr_reader :site
|
15
|
+
|
13
16
|
@matching_templates = []
|
14
17
|
|
15
18
|
def self.add_matching_template(template)
|
@@ -17,6 +20,7 @@ module Bridgetown
|
|
17
20
|
end
|
18
21
|
|
19
22
|
class << self
|
23
|
+
# @return [Array<Page>]
|
20
24
|
attr_reader :matching_templates
|
21
25
|
end
|
22
26
|
|
@@ -44,7 +48,13 @@ module Bridgetown
|
|
44
48
|
end
|
45
49
|
end
|
46
50
|
|
51
|
+
# Check incoming prototype configuration and normalize options.
|
52
|
+
#
|
53
|
+
# @param prototype_page [PrototypePage]
|
54
|
+
#
|
55
|
+
# @return [String, nil]
|
47
56
|
def validate_search_term(prototype_page)
|
57
|
+
# @type [String]
|
48
58
|
search_term = prototype_page.data["prototype"]["term"]
|
49
59
|
return nil unless search_term.is_a?(String)
|
50
60
|
|
@@ -52,6 +62,8 @@ module Bridgetown
|
|
52
62
|
@configured_collection = prototype_page.data["prototype"]["collection"]
|
53
63
|
end
|
54
64
|
|
65
|
+
return nil unless site.collections[@configured_collection]
|
66
|
+
|
55
67
|
# Categories and Tags are unique in that singular and plural front matter
|
56
68
|
# can be present for each
|
57
69
|
search_term.sub(%r!^category$!, "categories").sub(%r!^tag$!, "tags")
|
@@ -59,71 +71,75 @@ module Bridgetown
|
|
59
71
|
|
60
72
|
def generate_new_page_from_prototype(prototype_page, search_term, term)
|
61
73
|
new_page = PrototypePage.new(prototype_page, @configured_collection, search_term, term)
|
62
|
-
|
74
|
+
site.pages << new_page
|
63
75
|
new_page
|
64
76
|
end
|
65
77
|
|
66
|
-
#
|
67
|
-
#
|
78
|
+
# Provide a list of all relevent indexed values for the given term.
|
79
|
+
#
|
80
|
+
# @param search_term [String]
|
81
|
+
#
|
82
|
+
# @return [Array<String>]
|
68
83
|
def terms_matching_pages(search_term)
|
69
|
-
selected_docs = @site.documents.select do |document|
|
70
|
-
document.respond_to?(:collection) && document.collection.label == @configured_collection
|
71
|
-
end
|
72
|
-
|
73
84
|
Bridgetown::Paginate::PaginationIndexer.index_documents_by(
|
74
|
-
|
85
|
+
site.collections[@configured_collection].docs, search_term
|
75
86
|
).keys
|
76
87
|
end
|
77
88
|
end
|
78
89
|
|
79
90
|
class PrototypePage < Page
|
80
|
-
|
81
|
-
|
91
|
+
# @return [Page]
|
92
|
+
attr_reader :prototyped_page
|
93
|
+
|
94
|
+
def initialize(prototyped_page, collection, search_term, term)
|
95
|
+
@prototyped_page = prototyped_page
|
96
|
+
@site = prototyped_page.site
|
82
97
|
@url = ""
|
83
98
|
@name = "index.html"
|
84
|
-
@path =
|
99
|
+
@path = prototyped_page.path
|
85
100
|
|
86
101
|
process(@name)
|
87
102
|
|
88
|
-
self.data = Bridgetown::Utils.deep_merge_hashes
|
89
|
-
self.content =
|
103
|
+
self.data = Bridgetown::Utils.deep_merge_hashes prototyped_page.data, {}
|
104
|
+
self.content = prototyped_page.content
|
90
105
|
|
91
106
|
# Perform some validation that is also performed in Bridgetown::Page
|
92
|
-
validate_data!
|
93
|
-
validate_permalink!
|
107
|
+
validate_data! prototyped_page.path
|
108
|
+
validate_permalink! prototyped_page.path
|
94
109
|
|
95
|
-
@dir = Pathname.new(
|
110
|
+
@dir = Pathname.new(prototyped_page.relative_path).dirname.to_s
|
96
111
|
@path = site.in_source_dir(@dir, @name)
|
97
112
|
|
98
|
-
process_prototype_page_data(
|
113
|
+
process_prototype_page_data(collection, search_term, term)
|
99
114
|
|
100
115
|
Bridgetown::Hooks.trigger :pages, :post_init, self
|
101
116
|
end
|
102
117
|
|
103
|
-
def process_prototype_page_data(
|
118
|
+
def process_prototype_page_data(collection, search_term, term)
|
104
119
|
# Fill in pagination details to be handled later by Bridgetown::Paginate
|
105
120
|
data["pagination"] = Bridgetown::Utils.deep_merge_hashes(
|
106
|
-
|
121
|
+
prototyped_page.data["pagination"].to_h, {
|
107
122
|
"enabled" => true,
|
108
123
|
"collection" => collection,
|
109
124
|
"where_query" => [search_term, term],
|
110
125
|
}
|
111
126
|
)
|
112
127
|
# Use the original prototype page term so we get "tag" back, not "tags":
|
113
|
-
data[
|
128
|
+
data[prototyped_page.data["prototype"]["term"]] = term
|
114
129
|
# Process title and slugs/URLs:
|
115
|
-
process_title_data_placeholder(
|
130
|
+
process_title_data_placeholder(search_term, term)
|
116
131
|
process_title_simple_placeholders(term)
|
117
132
|
slugify_term(term)
|
118
133
|
end
|
119
134
|
|
120
|
-
|
121
|
-
|
135
|
+
# rubocop:disable Metrics/AbcSize
|
136
|
+
def process_title_data_placeholder(search_term, term)
|
137
|
+
if prototyped_page.data["prototype"]["data"]
|
122
138
|
if data["title"]&.include?(":prototype-data-label")
|
123
|
-
related_data =
|
139
|
+
related_data = site.data[prototyped_page.data["prototype"]["data"]].dig(term)
|
124
140
|
if related_data
|
125
141
|
data["#{search_term}_data"] = related_data
|
126
|
-
data_label = related_data[
|
142
|
+
data_label = related_data[prototyped_page.data["prototype"]["data_label"]]
|
127
143
|
data["title"] = data["title"].gsub(
|
128
144
|
":prototype-data-label", data_label
|
129
145
|
)
|
@@ -131,6 +147,7 @@ module Bridgetown
|
|
131
147
|
end
|
132
148
|
end
|
133
149
|
end
|
150
|
+
# rubocop:enable Metrics/AbcSize
|
134
151
|
|
135
152
|
def process_title_simple_placeholders(term)
|
136
153
|
if data["title"]&.include?(":prototype-term-titleize")
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bridgetown
|
4
|
+
class RubyTemplateView
|
5
|
+
class Helpers
|
6
|
+
include Bridgetown::Filters
|
7
|
+
|
8
|
+
attr_reader :view, :site
|
9
|
+
|
10
|
+
Context = Struct.new(:registers)
|
11
|
+
|
12
|
+
def initialize(view, site)
|
13
|
+
@view = view
|
14
|
+
@site = site
|
15
|
+
|
16
|
+
# duck typing for Liquid context
|
17
|
+
@context = Context.new({ site: site })
|
18
|
+
end
|
19
|
+
|
20
|
+
def webpack_path(asset_type)
|
21
|
+
Bridgetown::Utils.parse_webpack_manifest_file(site, asset_type.to_s)
|
22
|
+
end
|
23
|
+
|
24
|
+
# @param pairs [Hash] A hash of key/value pairs.
|
25
|
+
#
|
26
|
+
# @return [String] Space-separated keys where the values are truthy.
|
27
|
+
def class_map(pairs = {})
|
28
|
+
pairs.select { |_key, truthy| truthy }.keys.join(" ")
|
29
|
+
end
|
30
|
+
|
31
|
+
# This helper will generate the correct permalink URL for the file path.
|
32
|
+
#
|
33
|
+
# @param relative_path [String, Object] source file path, e.g.
|
34
|
+
# "_posts/2020-10-20-my-post.md", or object that responds to `url`
|
35
|
+
# @return [String] the permalink URL for the file
|
36
|
+
# @raise [ArgumentError] if the file cannot be found
|
37
|
+
def url_for(relative_path)
|
38
|
+
path_string = !relative_path.is_a?(String) ? relative_path.url : relative_path
|
39
|
+
|
40
|
+
return path_string if path_string.start_with?("/", "http")
|
41
|
+
|
42
|
+
site.each_site_file do |item|
|
43
|
+
if item.relative_path == path_string || item.relative_path == "/#{path_string}"
|
44
|
+
return relative_url(item)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
raise ArgumentError, <<~MSG
|
49
|
+
Could not find document '#{relative_path}' in 'url_for' helper.
|
50
|
+
|
51
|
+
Make sure the document exists and the path is correct.
|
52
|
+
MSG
|
53
|
+
end
|
54
|
+
alias_method :link, :url_for
|
55
|
+
|
56
|
+
# This helper will generate the correct permalink URL for the file path.
|
57
|
+
#
|
58
|
+
# @param text [String] the content inside the anchor tag
|
59
|
+
# @param relative_path [String, Object] source file path, e.g.
|
60
|
+
# "_posts/2020-10-20-my-post.md", or object that responds to `url`
|
61
|
+
# @param options [Hash] key-value pairs of HTML attributes to add to the tag
|
62
|
+
# @return [String] the anchor tag HTML
|
63
|
+
# @raise [ArgumentError] if the file cannot be found
|
64
|
+
def link_to(text, relative_path, options = {})
|
65
|
+
segments = []
|
66
|
+
segments << "a"
|
67
|
+
segments << "href=\"#{url_for(relative_path)}\""
|
68
|
+
options.each do |attr, option|
|
69
|
+
attr = attr.to_s.tr("_", "-")
|
70
|
+
segments << "#{attr}=\"#{Utils.xml_escape(option)}\""
|
71
|
+
end
|
72
|
+
"<#{segments.join(" ")}>#{text}</a>"
|
73
|
+
end
|
74
|
+
|
75
|
+
# Forward all arguments to I18n.t method
|
76
|
+
#
|
77
|
+
# @return [String] the translated string
|
78
|
+
# @see I18n
|
79
|
+
def t(*args)
|
80
|
+
I18n.send :t, *args
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -33,12 +33,12 @@ module Bridgetown
|
|
33
33
|
true
|
34
34
|
end
|
35
35
|
|
36
|
-
# Log a
|
36
|
+
# Log a `WARN` message
|
37
37
|
def warn(progname = nil, &block)
|
38
38
|
add(WARN, nil, progname.yellow, &block)
|
39
39
|
end
|
40
40
|
|
41
|
-
# Log an
|
41
|
+
# Log an `ERROR` message
|
42
42
|
def error(progname = nil, &block)
|
43
43
|
add(ERROR, nil, progname.red, &block)
|
44
44
|
end
|
data/lib/bridgetown-core/page.rb
CHANGED
@@ -9,7 +9,7 @@ module Bridgetown
|
|
9
9
|
include Validatable
|
10
10
|
|
11
11
|
attr_writer :dir
|
12
|
-
attr_accessor :site, :pager
|
12
|
+
attr_accessor :site, :paginator, :pager
|
13
13
|
attr_accessor :name, :ext, :basename
|
14
14
|
attr_accessor :data, :content, :output
|
15
15
|
|
@@ -121,12 +121,18 @@ module Bridgetown
|
|
121
121
|
# desired placeholder replacements. For details see "url.rb"
|
122
122
|
def url_placeholders
|
123
123
|
{
|
124
|
-
path:
|
124
|
+
path: qualified_pages_path_for_url,
|
125
125
|
basename: basename,
|
126
126
|
output_ext: output_ext,
|
127
127
|
}
|
128
128
|
end
|
129
129
|
|
130
|
+
# Strips _pages prefix off if needed for the url/destination generation
|
131
|
+
# @return [String]
|
132
|
+
def qualified_pages_path_for_url
|
133
|
+
@dir.sub(%r!^/_pages!, "")
|
134
|
+
end
|
135
|
+
|
130
136
|
# Extract information from the page filename.
|
131
137
|
#
|
132
138
|
# name - The String filename of the page file.
|
@@ -1,11 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "zeitwerk"
|
4
|
+
|
3
5
|
module Bridgetown
|
4
6
|
class PluginManager
|
5
7
|
PLUGINS_GROUP = :bridgetown_plugins
|
6
8
|
YARN_DEPENDENCY_REGEXP = %r!(.+)@([^@]*)$!.freeze
|
7
9
|
|
8
|
-
attr_reader :site
|
10
|
+
attr_reader :site, :component_loaders
|
9
11
|
|
10
12
|
@source_manifests = Set.new
|
11
13
|
@registered_plugins = Set.new
|
@@ -37,6 +39,7 @@ module Bridgetown
|
|
37
39
|
# Returns nothing
|
38
40
|
def initialize(site)
|
39
41
|
@site = site
|
42
|
+
@component_loaders = {}
|
40
43
|
end
|
41
44
|
|
42
45
|
def self.require_from_bundler
|
@@ -68,12 +71,20 @@ module Bridgetown
|
|
68
71
|
# If that exact package hasn't been installed, execute yarn add
|
69
72
|
#
|
70
73
|
# Returns nothing.
|
71
|
-
def self.install_yarn_dependencies(required_gems)
|
74
|
+
def self.install_yarn_dependencies(required_gems, single_gemname = nil)
|
72
75
|
return unless File.exist?("package.json")
|
73
76
|
|
74
77
|
package_json = JSON.parse(File.read("package.json"))
|
75
78
|
|
76
|
-
|
79
|
+
gems_to_search = if single_gemname
|
80
|
+
required_gems.select do |loaded_gem|
|
81
|
+
loaded_gem.to_spec&.name == single_gemname.to_s
|
82
|
+
end
|
83
|
+
else
|
84
|
+
required_gems
|
85
|
+
end
|
86
|
+
|
87
|
+
gems_to_search.each do |loaded_gem|
|
77
88
|
yarn_dependency = find_yarn_dependency(loaded_gem)
|
78
89
|
next unless add_yarn_dependency?(yarn_dependency, package_json)
|
79
90
|
|
@@ -150,5 +161,35 @@ module Bridgetown
|
|
150
161
|
Array(site.config["plugins_dir"]).map { |d| File.expand_path(d) }
|
151
162
|
end
|
152
163
|
end
|
164
|
+
|
165
|
+
# rubocop:disable Metrics/AbcSize
|
166
|
+
def setup_component_loaders
|
167
|
+
unless @component_loaders.keys.empty?
|
168
|
+
@component_loaders.each do |_path, loader|
|
169
|
+
loader.unload
|
170
|
+
end
|
171
|
+
@component_loaders = {}
|
172
|
+
end
|
173
|
+
|
174
|
+
# Because "first constant wins" in Zeitwerk, we need to load the local
|
175
|
+
# source components _before_ we load any from plugins
|
176
|
+
site.components_load_paths.reverse_each do |load_path|
|
177
|
+
next unless Dir.exist? load_path
|
178
|
+
next if Zeitwerk::Registry.loaders.find { |loader| loader.manages?(load_path) }
|
179
|
+
|
180
|
+
@component_loaders[load_path] = Zeitwerk::Loader.new
|
181
|
+
@component_loaders[load_path].push_dir(load_path)
|
182
|
+
@component_loaders[load_path].enable_reloading if load_path.start_with?(site.root_dir)
|
183
|
+
@component_loaders[load_path].ignore(File.join(load_path, "**", "*.js.rb"))
|
184
|
+
@component_loaders[load_path].setup
|
185
|
+
end
|
186
|
+
end
|
187
|
+
# rubocop:enable Metrics/AbcSize
|
188
|
+
|
189
|
+
def reload_component_loaders
|
190
|
+
@component_loaders.each do |path, loader|
|
191
|
+
loader.reload if path.start_with?(site.root_dir)
|
192
|
+
end
|
193
|
+
end
|
153
194
|
end
|
154
195
|
end
|
@@ -13,6 +13,7 @@ module Bridgetown
|
|
13
13
|
# Returns nothing.
|
14
14
|
# rubocop:disable Metrics/AbcSize
|
15
15
|
def read
|
16
|
+
@site.defaults_reader.read
|
16
17
|
@site.layouts = LayoutReader.new(site).read
|
17
18
|
read_directories
|
18
19
|
read_included_excludes
|
@@ -75,10 +76,7 @@ module Bridgetown
|
|
75
76
|
def retrieve_posts(dir)
|
76
77
|
return if outside_configured_directory?(dir)
|
77
78
|
|
78
|
-
post_reader.read_posts(dir)
|
79
|
-
site.posts.docs.concat(entries.select { |entry| entry.is_a?(Document) })
|
80
|
-
site.posts.files.concat(entries.select { |entry| entry.is_a?(StaticFile) })
|
81
|
-
end
|
79
|
+
post_reader.read_posts(dir)
|
82
80
|
end
|
83
81
|
|
84
82
|
# Recursively traverse directories with the read_directories function.
|
@@ -3,9 +3,10 @@
|
|
3
3
|
module Bridgetown
|
4
4
|
class DataReader
|
5
5
|
attr_reader :site, :content
|
6
|
+
|
6
7
|
def initialize(site)
|
7
8
|
@site = site
|
8
|
-
@content =
|
9
|
+
@content = {}
|
9
10
|
@entry_filter = EntryFilter.new(site)
|
10
11
|
end
|
11
12
|
|
@@ -19,7 +20,7 @@ module Bridgetown
|
|
19
20
|
base = site.in_source_dir(dir)
|
20
21
|
read_data_to(base, @content)
|
21
22
|
merge_environment_specific_metadata!
|
22
|
-
@content
|
23
|
+
@content = @content.with_dot_access
|
23
24
|
end
|
24
25
|
|
25
26
|
# Read and parse all .yaml, .yml, .json, .csv and .tsv
|
@@ -43,7 +44,7 @@ module Bridgetown
|
|
43
44
|
if File.directory?(path)
|
44
45
|
read_data_to(
|
45
46
|
path,
|
46
|
-
data[sanitize_filename(entry)] =
|
47
|
+
data[sanitize_filename(entry)] = {}
|
47
48
|
)
|
48
49
|
else
|
49
50
|
key = sanitize_filename(File.basename(entry, ".*"))
|