bridgetown-core 0.15.0.beta2 → 0.16.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +14 -0
  3. data/bridgetown-core.gemspec +3 -0
  4. data/lib/bridgetown-core.rb +6 -1
  5. data/lib/bridgetown-core/commands/concerns/actions.rb +41 -19
  6. data/lib/bridgetown-core/commands/console.rb +12 -2
  7. data/lib/bridgetown-core/commands/serve.rb +5 -0
  8. data/lib/bridgetown-core/concerns/data_accessible.rb +19 -0
  9. data/lib/bridgetown-core/concerns/layout_placeable.rb +17 -0
  10. data/lib/bridgetown-core/concerns/liquid_renderable.rb +20 -0
  11. data/lib/bridgetown-core/concerns/publishable.rb +10 -0
  12. data/lib/bridgetown-core/concerns/site/configurable.rb +62 -31
  13. data/lib/bridgetown-core/concerns/site/content.rb +88 -29
  14. data/lib/bridgetown-core/concerns/site/extensible.rb +15 -12
  15. data/lib/bridgetown-core/concerns/site/processable.rb +12 -10
  16. data/lib/bridgetown-core/concerns/site/renderable.rb +23 -4
  17. data/lib/bridgetown-core/concerns/site/writable.rb +16 -2
  18. data/lib/bridgetown-core/concerns/validatable.rb +59 -0
  19. data/lib/bridgetown-core/configuration.rb +1 -0
  20. data/lib/bridgetown-core/converter.rb +34 -0
  21. data/lib/bridgetown-core/converters/erb_templates.rb +78 -0
  22. data/lib/bridgetown-core/converters/markdown.rb +6 -23
  23. data/lib/bridgetown-core/converters/smartypants.rb +0 -10
  24. data/lib/bridgetown-core/document.rb +8 -52
  25. data/lib/bridgetown-core/drops/document_drop.rb +9 -1
  26. data/lib/bridgetown-core/errors.rb +2 -0
  27. data/lib/bridgetown-core/excerpt.rb +5 -7
  28. data/lib/bridgetown-core/filters.rb +2 -0
  29. data/lib/bridgetown-core/layout.rb +24 -1
  30. data/lib/bridgetown-core/liquid_renderer/file.rb +1 -4
  31. data/lib/bridgetown-core/liquid_renderer/file_system.rb +1 -1
  32. data/lib/bridgetown-core/page.rb +34 -25
  33. data/lib/bridgetown-core/plugin_manager.rb +36 -14
  34. data/lib/bridgetown-core/regenerator.rb +1 -1
  35. data/lib/bridgetown-core/renderer.rb +41 -15
  36. data/lib/bridgetown-core/ruby_template_view.rb +98 -0
  37. data/lib/bridgetown-core/tags/class_map.rb +90 -0
  38. data/lib/bridgetown-core/tags/include.rb +2 -0
  39. data/lib/bridgetown-core/tags/render_content.rb +14 -2
  40. data/lib/bridgetown-core/tags/webpack_path.rb +19 -22
  41. data/lib/bridgetown-core/utils.rb +97 -0
  42. data/lib/bridgetown-core/version.rb +2 -2
  43. data/lib/site_template/bridgetown.config.yml +5 -3
  44. data/lib/site_template/src/_components/{footer.html → footer.liquid} +0 -0
  45. data/lib/site_template/src/_components/{head.html → head.liquid} +0 -0
  46. data/lib/site_template/src/_components/{navbar.html → navbar.liquid} +0 -0
  47. data/lib/site_template/src/_layouts/{default.html → default.liquid} +1 -1
  48. data/lib/site_template/src/_layouts/{home.html → home.liquid} +0 -0
  49. data/lib/site_template/src/_layouts/{page.html → page.liquid} +0 -0
  50. data/lib/site_template/src/_layouts/{post.html → post.liquid} +0 -0
  51. metadata +59 -10
  52. data/lib/bridgetown-core/concerns/convertible.rb +0 -238
@@ -30,16 +30,6 @@ module Bridgetown
30
30
  @config[:input] = :SmartyPants
31
31
  end
32
32
 
33
- # Does the given extension match this converter's list of acceptable extensions?
34
- # Takes one argument: the file's extension (including the dot).
35
- #
36
- # ext - The String extension to check.
37
- #
38
- # Returns true if it matches, false otherwise.
39
- def matches(_ext)
40
- false
41
- end
42
-
43
33
  # Public: The extension to be given to the output file (including the dot).
44
34
  #
45
35
  # ext - The String extension or original file.
@@ -2,8 +2,12 @@
2
2
 
3
3
  module Bridgetown
4
4
  class Document
5
- include Comparable
6
5
  extend Forwardable
6
+ include DataAccessible
7
+ include Comparable
8
+ include LayoutPlaceable
9
+ include LiquidRenderable
10
+ include Publishable
7
11
 
8
12
  attr_reader :path, :site, :extname, :collection, :type
9
13
  attr_accessor :content, :output
@@ -95,6 +99,9 @@ module Bridgetown
95
99
  @relative_path ||= path.sub("#{site.collections_path}/", "")
96
100
  end
97
101
 
102
+ # FIXME: spinning up a new Renderer object just to get an extension
103
+ # seems excessive
104
+ #
98
105
  # The output extension of the document.
99
106
  #
100
107
  # Returns the output extension
@@ -143,38 +150,6 @@ module Bridgetown
143
150
  YAML_FILE_EXTS.include?(extname)
144
151
  end
145
152
 
146
- # TODO: Depricated
147
- # Used to determine CoffeeScript and Sass/SCSS files.
148
- def asset_file?
149
- false
150
- end
151
-
152
- # Determine whether the file should be rendered with Liquid.
153
- #
154
- # Returns false if the document is either an asset file or a yaml file,
155
- # or if the document doesn't contain any Liquid Tags or Variables,
156
- # true otherwise.
157
- def render_with_liquid?
158
- return false if data["render_with_liquid"] == false
159
-
160
- !(yaml_file? || !Utils.has_liquid_construct?(content))
161
- end
162
-
163
- # Determine whether the file should be rendered with a layout.
164
- #
165
- # Returns true if the Front Matter specifies that `layout` is set to `none`.
166
- def no_layout?
167
- data["layout"] == "none"
168
- end
169
-
170
- # Determine whether the file should be placed into layouts.
171
- #
172
- # Returns false if the document is set to `layouts: none`, or is either an
173
- # asset file or a yaml file. Returns true otherwise.
174
- def place_in_layout?
175
- !(asset_file? || yaml_file? || no_layout?)
176
- end
177
-
178
153
  # The URL template where the document would be accessible.
179
154
  #
180
155
  # Returns the URL template for the document.
@@ -209,10 +184,6 @@ module Bridgetown
209
184
  ).to_s
210
185
  end
211
186
 
212
- def [](key)
213
- data[key]
214
- end
215
-
216
187
  # The full path to the output file.
217
188
  #
218
189
  # base_directory - the base path of the output directory
@@ -243,14 +214,6 @@ module Bridgetown
243
214
  trigger_hooks(:post_write)
244
215
  end
245
216
 
246
- # Whether the file is published or not, as indicated in YAML front-matter
247
- #
248
- # Returns 'false' if the 'published' key is specified in the
249
- # YAML front-matter and is 'false'. Otherwise returns 'true'.
250
- def published?
251
- !(data.key?("published") && data["published"] == false)
252
- end
253
-
254
217
  # Read in the file and assign the content and data based on the file contents.
255
218
  # Merge the frontmatter of the file with the frontmatter default
256
219
  # values
@@ -287,13 +250,6 @@ module Bridgetown
287
250
  "#<#{self.class} #{relative_path} collection=#{collection.label}>"
288
251
  end
289
252
 
290
- # The string representation for this document.
291
- #
292
- # Returns the content of the document
293
- def to_s
294
- output || content || "NO CONTENT"
295
- end
296
-
297
253
  # Compare this document against another document.
298
254
  # Comparison is a comparison between the 2 paths of the documents.
299
255
  #
@@ -12,7 +12,15 @@ module Bridgetown
12
12
  mutable false
13
13
 
14
14
  def_delegator :@obj, :relative_path, :path
15
- def_delegators :@obj, :id, :output, :content, :to_s, :relative_path, :url, :date
15
+ def_delegators :@obj,
16
+ :id,
17
+ :output,
18
+ :content,
19
+ :to_s,
20
+ :relative_path,
21
+ :url,
22
+ :date,
23
+ :related_posts
16
24
 
17
25
  private def_delegator :@obj, :data, :fallback_data
18
26
 
@@ -16,5 +16,7 @@ module Bridgetown
16
16
  PostURLError = Class.new(FatalException)
17
17
  InvalidURLError = Class.new(FatalException)
18
18
  InvalidConfigurationError = Class.new(FatalException)
19
+
20
+ WebpackAssetError = Class.new(FatalException)
19
21
  end
20
22
  end
@@ -3,6 +3,7 @@
3
3
  module Bridgetown
4
4
  class Excerpt
5
5
  extend Forwardable
6
+ include LiquidRenderable
6
7
 
7
8
  attr_accessor :doc
8
9
  attr_accessor :content, :ext
@@ -81,19 +82,16 @@ module Bridgetown
81
82
  end
82
83
 
83
84
  def output
84
- @output ||= Renderer.new(doc.site, self, site.site_payload).run
85
+ @output || (
86
+ Renderer.new(doc.site, self, site.site_payload).run
87
+ @output
88
+ )
85
89
  end
86
90
 
87
91
  def place_in_layout?
88
92
  false
89
93
  end
90
94
 
91
- def render_with_liquid?
92
- return false if data["render_with_liquid"] == false
93
-
94
- !(yaml_file? || !Utils.has_liquid_construct?(content))
95
- end
96
-
97
95
  protected
98
96
 
99
97
  # Internal: Extract excerpt from the content
@@ -30,6 +30,7 @@ module Bridgetown
30
30
  ).convert(input.to_s)
31
31
  end
32
32
 
33
+ # TODO: This should be removed, there is no Sass converter
33
34
  # Convert a Sass string into CSS output.
34
35
  #
35
36
  # input - The Sass String to convert.
@@ -41,6 +42,7 @@ module Bridgetown
41
42
  ).convert(input)
42
43
  end
43
44
 
45
+ # TODO: This should be removed, there is no Scss converter
44
46
  # Convert a Scss string into CSS output.
45
47
  #
46
48
  # input - The Scss String to convert.
@@ -2,7 +2,9 @@
2
2
 
3
3
  module Bridgetown
4
4
  class Layout
5
- include Convertible
5
+ include DataAccessible
6
+ include LiquidRenderable
7
+ include Validatable
6
8
 
7
9
  # Gets the Site object.
8
10
  attr_reader :site
@@ -25,6 +27,12 @@ module Bridgetown
25
27
  # Gets/Sets the content of this layout.
26
28
  attr_accessor :content
27
29
 
30
+ # Gets/Sets the current document (for layout-compatible converters)
31
+ attr_accessor :current_document
32
+
33
+ # Gets/Sets the document output (for layout-compatible converters)
34
+ attr_accessor :current_document_output
35
+
28
36
  # Initialize a new Layout.
29
37
  #
30
38
  # site - The Site.
@@ -51,6 +59,14 @@ module Bridgetown
51
59
  read_yaml(base, name)
52
60
  end
53
61
 
62
+ # The inspect string for this document.
63
+ # Includes the relative path and the collection label.
64
+ #
65
+ # Returns the inspect string for this document.
66
+ def inspect
67
+ "#<#{self.class} #{@path}>"
68
+ end
69
+
54
70
  # Extract information from the layout filename.
55
71
  #
56
72
  # name - The String filename of the layout file.
@@ -59,5 +75,12 @@ module Bridgetown
59
75
  def process(name)
60
76
  self.ext = File.extname(name)
61
77
  end
78
+
79
+ # Provide this Layout's data to a Hash suitable for use by Liquid.
80
+ #
81
+ # Returns the Hash representation of this Layout.
82
+ def to_liquid
83
+ data
84
+ end
62
85
  end
63
86
  end
@@ -10,11 +10,8 @@ module Bridgetown
10
10
 
11
11
  def parse(content)
12
12
  measure_time do
13
- # Remove extraneous indentation for rendercontent tags
14
- processed_content = content.gsub(%r!^[ \t]+{%-? rendercontent!, "{% rendercontent")
15
-
16
13
  @renderer.cache[@filename] ||= Liquid::Template.parse(
17
- processed_content, line_numbers: true
14
+ content, line_numbers: true
18
15
  )
19
16
  end
20
17
  @template = @renderer.cache[@filename]
@@ -32,7 +32,7 @@ module Bridgetown
32
32
 
33
33
  # Last path in the list wins
34
34
  LiquidComponent.parse(
35
- ::File.read(found_paths.last, site.file_read_opts)
35
+ ::File.read(found_paths.last, **site.file_read_opts)
36
36
  ).content
37
37
  end
38
38
  end
@@ -2,7 +2,11 @@
2
2
 
3
3
  module Bridgetown
4
4
  class Page
5
- include Convertible
5
+ include DataAccessible
6
+ include LayoutPlaceable
7
+ include LiquidRenderable
8
+ include Publishable
9
+ include Validatable
6
10
 
7
11
  attr_writer :dir
8
12
  attr_accessor :site, :pager
@@ -11,15 +15,6 @@ module Bridgetown
11
15
 
12
16
  alias_method :extname, :ext
13
17
 
14
- # Attributes for Liquid templates
15
- ATTRIBUTES_FOR_LIQUID = %w(
16
- content
17
- dir
18
- name
19
- path
20
- url
21
- ).freeze
22
-
23
18
  # A set of extensions that are considered HTML or HTML-like so we
24
19
  # should not alter them, this includes .xhtml through XHTM5.
25
20
 
@@ -143,19 +138,6 @@ module Bridgetown
143
138
  self.basename = name[0..-ext.length - 1].gsub(%r!\.*\z!, "")
144
139
  end
145
140
 
146
- # Add any necessary layouts to this post
147
- #
148
- # layouts - The Hash of {"name" => "layout"}.
149
- # site_payload - The site payload Hash.
150
- #
151
- # Returns String rendered page.
152
- def render(layouts, site_payload)
153
- site_payload["page"] = to_liquid
154
- site_payload["paginator"] = pager.to_liquid
155
-
156
- do_layout(site_payload, layouts)
157
- end
158
-
159
141
  # The path to the source file
160
142
  #
161
143
  # Returns the path to the source file
@@ -165,7 +147,17 @@ module Bridgetown
165
147
 
166
148
  # The path to the page source file, relative to the site source
167
149
  def relative_path
168
- @relative_path ||= File.join(*[@dir, @name].map(&:to_s).reject(&:empty?)).sub(%r!\A\/!, "")
150
+ @relative_path ||= File.join(*[@dir, @name].map(&:to_s).reject(&:empty?)).delete_prefix("/")
151
+ end
152
+
153
+ # FIXME: spinning up a new Renderer object just to get an extension
154
+ # seems excessive
155
+ #
156
+ # The output extension of the page.
157
+ #
158
+ # Returns the output extension
159
+ def output_ext
160
+ @output_ext ||= Bridgetown::Renderer.new(site, self).output_ext
169
161
  end
170
162
 
171
163
  # Obtain destination path.
@@ -180,9 +172,22 @@ module Bridgetown
180
172
  path
181
173
  end
182
174
 
175
+ # Write the generated page file to the destination directory.
176
+ #
177
+ # dest - The String path to the destination dir.
178
+ #
179
+ # Returns nothing.
180
+ def write(dest)
181
+ path = destination(dest)
182
+ FileUtils.mkdir_p(File.dirname(path))
183
+ Bridgetown.logger.debug "Writing:", path
184
+ File.write(path, output, mode: "wb")
185
+ Bridgetown::Hooks.trigger :pages, :post_write, self
186
+ end
187
+
183
188
  # Returns the object as a debug String.
184
189
  def inspect
185
- "#<#{self.class} @relative_path=#{relative_path.inspect}>"
190
+ "#<#{self.class} #{relative_path}>"
186
191
  end
187
192
 
188
193
  # Returns the Boolean of whether this Page is HTML or not.
@@ -199,6 +204,10 @@ module Bridgetown
199
204
  Bridgetown::Hooks.trigger :pages, hook_name, self, *args
200
205
  end
201
206
 
207
+ def type
208
+ :pages
209
+ end
210
+
202
211
  def write?
203
212
  true
204
213
  end
@@ -3,6 +3,7 @@
3
3
  module Bridgetown
4
4
  class PluginManager
5
5
  PLUGINS_GROUP = :bridgetown_plugins
6
+ YARN_DEPENDENCY_REGEXP = %r!(.+)@([^@]*)$!.freeze
6
7
 
7
8
  attr_reader :site
8
9
 
@@ -67,30 +68,51 @@ module Bridgetown
67
68
  # If that exact package hasn't been installed, execute yarn add
68
69
  #
69
70
  # Returns nothing.
70
- # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
71
- def self.install_yarn_dependencies(required_gems)
71
+ def self.install_yarn_dependencies(required_gems, single_gemname = nil)
72
72
  return unless File.exist?("package.json")
73
73
 
74
74
  package_json = JSON.parse(File.read("package.json"))
75
75
 
76
- required_gems.each do |loaded_gem|
77
- next unless loaded_gem.to_spec&.metadata&.dig("yarn-add")
76
+ gems_to_search = if single_gemname
77
+ required_gems.select do |loaded_gem|
78
+ loaded_gem.to_spec&.name == single_gemname.to_s
79
+ end
80
+ else
81
+ required_gems
82
+ end
78
83
 
79
- yarn_add_dependency = loaded_gem.to_spec.metadata["yarn-add"].split("@")
80
- next unless yarn_add_dependency.length == 2
81
-
82
- # check matching version number is see if it's already installed
83
- if package_json["dependencies"]
84
- current_package = package_json["dependencies"].dig(yarn_add_dependency.first)
85
- next unless current_package.nil? || current_package != yarn_add_dependency.last
86
- end
84
+ gems_to_search.each do |loaded_gem|
85
+ yarn_dependency = find_yarn_dependency(loaded_gem)
86
+ next unless add_yarn_dependency?(yarn_dependency, package_json)
87
87
 
88
88
  # all right, time to install the package
89
- cmd = "yarn add #{yarn_add_dependency.join("@")}"
89
+ cmd = "yarn add #{yarn_dependency.join("@")}"
90
90
  system cmd
91
91
  end
92
92
  end
93
- # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity
93
+
94
+ def self.find_yarn_dependency(loaded_gem)
95
+ yarn_dependency = loaded_gem.to_spec&.metadata&.dig("yarn-add")&.match(YARN_DEPENDENCY_REGEXP)
96
+ return nil if yarn_dependency&.length != 3 || yarn_dependency[2] == ""
97
+
98
+ yarn_dependency[1..2]
99
+ end
100
+
101
+ def self.add_yarn_dependency?(yarn_dependency, package_json)
102
+ return false if yarn_dependency.nil?
103
+
104
+ # check matching version number is see if it's already installed
105
+ if package_json["dependencies"]
106
+ current_version = package_json["dependencies"].dig(yarn_dependency.first)
107
+ package_requires_updating?(current_version, yarn_dependency.last)
108
+ else
109
+ true
110
+ end
111
+ end
112
+
113
+ def self.package_requires_updating?(current_version, dep_version)
114
+ current_version.nil? || current_version != dep_version && !current_version.include?("/")
115
+ end
94
116
 
95
117
  # Require all .rb files
96
118
  #
@@ -163,7 +163,7 @@ module Bridgetown
163
163
  end
164
164
 
165
165
  def regenerate_page?(document)
166
- document.asset_file? || document.data["regenerate"] ||
166
+ document.data["regenerate"] ||
167
167
  source_modified_or_dest_missing?(
168
168
  site.in_source_dir(document.relative_path), document.destination(@site.dest)
169
169
  )