bridgetown-core 0.20.0 → 0.21.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/bridgetown-core.gemspec +0 -1
  3. data/lib/bridgetown-core.rb +11 -22
  4. data/lib/bridgetown-core/cleaner.rb +2 -2
  5. data/lib/bridgetown-core/collection.rb +14 -11
  6. data/lib/bridgetown-core/commands/build.rb +0 -11
  7. data/lib/bridgetown-core/commands/concerns/git_helpers.rb +20 -0
  8. data/lib/bridgetown-core/commands/configure.rb +4 -3
  9. data/lib/bridgetown-core/commands/doctor.rb +1 -19
  10. data/lib/bridgetown-core/commands/new.rb +6 -6
  11. data/lib/bridgetown-core/commands/plugins.rb +14 -13
  12. data/lib/bridgetown-core/commands/serve.rb +0 -14
  13. data/lib/bridgetown-core/commands/webpack.rb +75 -0
  14. data/lib/bridgetown-core/commands/webpack/enable-postcss.rb +12 -0
  15. data/lib/bridgetown-core/commands/webpack/setup.rb +4 -0
  16. data/lib/bridgetown-core/commands/webpack/update.rb +3 -0
  17. data/lib/bridgetown-core/commands/webpack/webpack.config.js +18 -0
  18. data/lib/{site_template/webpack.config.js.erb → bridgetown-core/commands/webpack/webpack.defaults.js.erb} +25 -11
  19. data/lib/bridgetown-core/component.rb +183 -0
  20. data/lib/bridgetown-core/concerns/front_matter_importer.rb +52 -0
  21. data/lib/bridgetown-core/concerns/layout_placeable.rb +1 -1
  22. data/lib/bridgetown-core/concerns/site/configurable.rb +3 -7
  23. data/lib/bridgetown-core/concerns/site/content.rb +2 -3
  24. data/lib/bridgetown-core/concerns/site/localizable.rb +3 -5
  25. data/lib/bridgetown-core/concerns/site/processable.rb +5 -4
  26. data/lib/bridgetown-core/concerns/site/writable.rb +1 -1
  27. data/lib/bridgetown-core/concerns/validatable.rb +1 -5
  28. data/lib/bridgetown-core/configuration.rb +22 -14
  29. data/lib/bridgetown-core/configurations/bt-postcss.rb +6 -6
  30. data/lib/bridgetown-core/configurations/netlify.rb +1 -0
  31. data/lib/bridgetown-core/configurations/tailwindcss.rb +6 -6
  32. data/lib/bridgetown-core/converter.rb +9 -0
  33. data/lib/bridgetown-core/converters/erb_templates.rb +51 -35
  34. data/lib/bridgetown-core/converters/liquid_templates.rb +1 -1
  35. data/lib/bridgetown-core/converters/markdown.rb +1 -1
  36. data/lib/bridgetown-core/converters/markdown/kramdown_parser.rb +2 -38
  37. data/lib/bridgetown-core/converters/ruby_templates.rb +17 -0
  38. data/lib/bridgetown-core/converters/smartypants.rb +3 -1
  39. data/lib/bridgetown-core/core_ext/psych.rb +19 -0
  40. data/lib/bridgetown-core/document.rb +3 -2
  41. data/lib/bridgetown-core/drops/relations_drop.rb +23 -0
  42. data/lib/bridgetown-core/drops/resource_drop.rb +3 -1
  43. data/lib/bridgetown-core/drops/unified_payload_drop.rb +1 -0
  44. data/lib/bridgetown-core/entry_filter.rb +7 -5
  45. data/lib/bridgetown-core/filters.rb +1 -25
  46. data/lib/bridgetown-core/filters/from_liquid.rb +23 -0
  47. data/lib/bridgetown-core/filters/url_filters.rb +12 -0
  48. data/lib/bridgetown-core/frontmatter_defaults.rb +1 -1
  49. data/lib/bridgetown-core/generators/prototype_generator.rb +25 -4
  50. data/lib/bridgetown-core/helpers.rb +48 -9
  51. data/lib/bridgetown-core/layout.rb +52 -20
  52. data/lib/bridgetown-core/model/origin.rb +1 -1
  53. data/lib/bridgetown-core/model/{file_origin.rb → repo_origin.rb} +33 -26
  54. data/lib/bridgetown-core/page.rb +2 -1
  55. data/lib/bridgetown-core/plugin_manager.rb +1 -1
  56. data/lib/bridgetown-core/publisher.rb +2 -2
  57. data/lib/bridgetown-core/reader.rb +13 -11
  58. data/lib/bridgetown-core/readers/data_reader.rb +2 -1
  59. data/lib/bridgetown-core/readers/defaults_reader.rb +1 -1
  60. data/lib/bridgetown-core/readers/layout_reader.rb +1 -1
  61. data/lib/bridgetown-core/readers/page_reader.rb +1 -0
  62. data/lib/bridgetown-core/readers/post_reader.rb +5 -4
  63. data/lib/bridgetown-core/regenerator.rb +1 -1
  64. data/lib/bridgetown-core/related_posts.rb +8 -5
  65. data/lib/bridgetown-core/renderer.rb +1 -1
  66. data/lib/bridgetown-core/resource/base.rb +80 -26
  67. data/lib/bridgetown-core/resource/permalink_processor.rb +1 -1
  68. data/lib/bridgetown-core/resource/relations.rb +132 -0
  69. data/lib/bridgetown-core/resource/taxonomy_term.rb +10 -1
  70. data/lib/bridgetown-core/resource/taxonomy_type.rb +9 -0
  71. data/lib/bridgetown-core/resource/transformer.rb +18 -14
  72. data/lib/bridgetown-core/ruby_template_view.rb +7 -11
  73. data/lib/bridgetown-core/site.rb +4 -5
  74. data/lib/bridgetown-core/tags/highlight.rb +2 -15
  75. data/lib/bridgetown-core/tags/include.rb +1 -1
  76. data/lib/bridgetown-core/tags/post_url.rb +2 -2
  77. data/lib/bridgetown-core/utils.rb +9 -3
  78. data/lib/bridgetown-core/utils/require_gems.rb +60 -0
  79. data/lib/bridgetown-core/utils/ruby_exec.rb +6 -9
  80. data/lib/bridgetown-core/utils/ruby_front_matter.rb +39 -0
  81. data/lib/bridgetown-core/version.rb +2 -2
  82. data/lib/bridgetown-core/watcher.rb +2 -1
  83. data/lib/bridgetown-core/yaml_parser.rb +22 -0
  84. data/lib/site_template/config/.keep +0 -0
  85. data/lib/site_template/package.json.erb +4 -4
  86. data/lib/site_template/plugins/site_builder.rb +1 -1
  87. data/lib/site_template/src/_posts/0000-00-00-welcome-to-bridgetown.md.erb +1 -1
  88. metadata +21 -23
  89. data/lib/bridgetown-core/external.rb +0 -58
  90. data/lib/bridgetown-core/path_manager.rb +0 -31
  91. data/lib/bridgetown-core/readers/static_file_reader.rb +0 -25
  92. data/lib/bridgetown-core/utils/platforms.rb +0 -81
  93. data/lib/bridgetown-core/utils/thread_event.rb +0 -31
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bridgetown
4
+ module Commands
5
+ class Webpack < Thor::Group
6
+ include Thor::Actions
7
+ extend Summarizable
8
+
9
+ Registrations.register do
10
+ register(Webpack, "webpack", "webpack ACTION", Webpack.summary)
11
+ end
12
+
13
+ def self.banner
14
+ "bridgetown webpack ACTION"
15
+ end
16
+ summary "Perform actions on the bridgetown webpack configuration"
17
+
18
+ def self.exit_on_failure?
19
+ true
20
+ end
21
+
22
+ def webpack
23
+ @logger = Bridgetown.logger
24
+ return show_actions if args.empty?
25
+
26
+ action = args.first
27
+ if supported_actions.include?(action)
28
+ perform action
29
+ else
30
+ @logger.error "Error:".red, "🚨 Please enter a valid action."
31
+ say "\n"
32
+ show_actions
33
+ end
34
+ end
35
+
36
+ def self.source_root
37
+ File.expand_path("./webpack", __dir__)
38
+ end
39
+
40
+ def self.destination_root
41
+ config.root_dir
42
+ end
43
+
44
+ def config
45
+ @config ||= Bridgetown.configuration({ root_dir: Dir.pwd })
46
+ end
47
+
48
+ protected
49
+
50
+ def perform(action)
51
+ automation = find_in_source_paths("#{action}.rb")
52
+ inside(New.created_site_dir || Dir.pwd) do
53
+ apply automation, verbose: false
54
+ end
55
+ end
56
+
57
+ def show_actions
58
+ say "Available actions:\n".bold
59
+
60
+ longest_action = supported_actions.keys.max_by(&:size).size
61
+ supported_actions.each do |action, description|
62
+ say action.ljust(longest_action).to_s.bold.blue + "\t" + "# #{description}"
63
+ end
64
+ end
65
+
66
+ def supported_actions
67
+ {
68
+ setup: "Sets up a webpack integration with Bridgetown in your project",
69
+ update: "Updates the Bridgetown webpack defaults to the latest available version",
70
+ "enable-postcss": "Configures PostCSS in your project",
71
+ }.with_indifferent_access
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ default_postcss_config = File.expand_path("../../../site_template/postcss.config.js.erb", __dir__)
4
+
5
+ template default_postcss_config, "postcss.config.js"
6
+ template "webpack.defaults.js.erb", "config/webpack.defaults.js", force: true
7
+
8
+ unless Bridgetown.environment.test?
9
+ packages = %w(postcss@8.3.0 postcss-loader@4.3.0 postcss-flexbugs-fixes postcss-preset-env)
10
+ run "yarn add -D #{packages.join(" ")}"
11
+ run "yarn remove sass sass-loader"
12
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ template "webpack.defaults.js.erb", "config/webpack.defaults.js"
4
+ copy_file "webpack.config.js", force: true
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ template "webpack.defaults.js.erb", "config/webpack.defaults.js", force: true
@@ -0,0 +1,18 @@
1
+ const config = require("./config/webpack.defaults.js")
2
+
3
+ // Add any overrides to the default webpack config here:
4
+
5
+ // Eg:
6
+ //
7
+ // ```
8
+ // const path = require("path")
9
+ // config.resolve.modules.push(path.resolve(__dirname, 'frontend', 'components'))
10
+ // config.resolve.alias.frontendComponents = path.resolve(__dirname, 'frontend', 'components')
11
+ // ```
12
+
13
+
14
+
15
+
16
+ ////////////////////////////////////////////////////////
17
+
18
+ module.exports = config
@@ -1,10 +1,21 @@
1
+ // This file is created and managed by Bridgetown.
2
+ // Instead of editing this file, add your overrides to `webpack.config.js`
3
+ //
4
+ // To update this file to the latest version provided by Bridgetown,
5
+ // run `bridgetown webpack update`. Any changes to this file will be overwritten
6
+ // when an update is applied hence we strongly recommend adding overrides to
7
+ // `webpack.config.js` instead of editing this file.
8
+ //
9
+ // Shipped with Bridgetown v<%= Bridgetown::VERSION %>
10
+
1
11
  const path = require("path");
12
+ const rootDir = path.resolve(__dirname, "..")
2
13
  const MiniCssExtractPlugin = require("mini-css-extract-plugin");
3
14
  const ManifestPlugin = require("webpack-manifest-plugin");
4
15
 
5
16
  module.exports = {
6
17
  entry: {
7
- main: "./frontend/javascript/index.js"
18
+ main: path.resolve(rootDir, "frontend", "javascript", "index.js")
8
19
  },
9
20
  devtool: "source-map",
10
21
  // Set some or all of these to true if you want more verbose logging:
@@ -15,18 +26,18 @@ module.exports = {
15
26
  children: false,
16
27
  },
17
28
  output: {
18
- path: path.resolve(__dirname, "output", "_bridgetown", "static", "js"),
29
+ path: path.resolve(rootDir, "output", "_bridgetown", "static", "js"),
19
30
  filename: "[name].[contenthash].js",
20
31
  },
21
32
  resolve: {
22
33
  extensions: [".js", ".jsx"],
23
34
  modules: [
24
- path.resolve(__dirname, 'frontend', 'javascript'),
25
- path.resolve(__dirname, 'frontend', 'styles'),
26
- path.resolve('./node_modules')
35
+ path.resolve(rootDir, 'frontend', 'javascript'),
36
+ path.resolve(rootDir, 'frontend', 'styles'),
37
+ path.resolve(rootDir, 'node_modules')
27
38
  ],
28
39
  alias: {
29
- bridgetownComponents: path.resolve(__dirname, "src", "_components")
40
+ bridgetownComponents: path.resolve(rootDir, "src", "_components")
30
41
  }
31
42
  },
32
43
  plugins: [
@@ -34,7 +45,7 @@ module.exports = {
34
45
  filename: "../css/[name].[contenthash].css",
35
46
  }),
36
47
  new ManifestPlugin({
37
- fileName: path.resolve(__dirname, ".bridgetown-webpack", "manifest.json"),
48
+ fileName: path.resolve(rootDir, ".bridgetown-webpack", "manifest.json"),
38
49
  }),
39
50
  ],
40
51
  module: {
@@ -54,11 +65,12 @@ module.exports = {
54
65
  helpers: false,
55
66
  },
56
67
  ],
68
+ ["@babel/plugin-proposal-private-methods", { "loose": true }],
57
69
  ],
58
70
  },
59
71
  },
60
72
  },
61
- <% if options["use-postcss"] %>
73
+ <% if self.config.uses_postcss? %>
62
74
  {
63
75
  test: /\.(s[ac]|c)ss$/,
64
76
  use: [
@@ -72,7 +84,7 @@ module.exports = {
72
84
  },
73
85
  "postcss-loader"
74
86
  ],
75
- },
87
+ },
76
88
  <% else %>
77
89
  {
78
90
  test: /\.(s[ac]|c)ss$/,
@@ -87,9 +99,11 @@ module.exports = {
87
99
  {
88
100
  loader: "sass-loader",
89
101
  options: {
102
+ implementation: require("sass"),
90
103
  sassOptions: {
104
+ fiber: false,
91
105
  includePaths: [
92
- path.resolve(__dirname, "src/_components")
106
+ path.resolve(rootDir, "src/_components")
93
107
  ],
94
108
  },
95
109
  },
@@ -117,4 +131,4 @@ module.exports = {
117
131
  },
118
132
  ],
119
133
  },
120
- };
134
+ };
@@ -0,0 +1,183 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bridgetown
4
+ class Component
5
+ extend Forwardable
6
+
7
+ def_delegators :@view_context, :helpers, :liquid_render, :partial
8
+
9
+ # @return [Bridgetown::Site]
10
+ attr_reader :site # will be nil unless you explicitly set a `@site` ivar
11
+
12
+ # @return [Bridgetown::RubyTemplateView, Bridgetown::Component]
13
+ attr_reader :view_context
14
+
15
+ class << self
16
+ attr_accessor :source_location
17
+
18
+ def inherited(child)
19
+ # Code cribbed from ViewComponent by GitHub:
20
+ # Derive the source location of the component Ruby file from the call stack
21
+ child.source_location = caller_locations(1, 10).reject do |l|
22
+ l.label == "inherited"
23
+ end[0].absolute_path
24
+
25
+ super
26
+ end
27
+
28
+ # Return the appropriate template renderer for a given extension.
29
+ # TODO: make this extensible
30
+ #
31
+ # @param ext [String] erb, slim, etc.
32
+ def renderer_for_ext(ext, &block)
33
+ @_tmpl ||= case ext
34
+ when "erb"
35
+ include ERBCapture
36
+ Tilt::ErubiTemplate.new(component_template_path,
37
+ outvar: "@_erbout",
38
+ bufval: "Bridgetown::OutputBuffer.new",
39
+ engine_class: Bridgetown::ERBEngine,
40
+ &block)
41
+ when "serb" # requires serbea
42
+ include Serbea::Helpers
43
+ Tilt::SerbeaTemplate.new(component_template_path, &block)
44
+ when "slim" # requires bridgetown-slim
45
+ Slim::Template.new(component_template_path, &block)
46
+ when "haml" # requires bridgetown-haml
47
+ Tilt::HamlTemplate.new(component_template_path, &block)
48
+ else
49
+ raise NameError
50
+ end
51
+ rescue NameError, LoadError
52
+ raise "No component rendering engine could be found for .#{ext} templates"
53
+ end
54
+
55
+ # Find the first matching template path based on source location and extension.
56
+ #
57
+ # @return [String]
58
+ def component_template_path
59
+ @_tmpl_path ||= begin
60
+ stripped_path = File.join(
61
+ File.dirname(source_location),
62
+ File.basename(source_location, ".*")
63
+ )
64
+ supported_template_extensions.each do |ext|
65
+ test_path = "#{stripped_path}.#{ext}"
66
+ break test_path if File.exist?(test_path)
67
+
68
+ test_path = "#{stripped_path}.html.#{ext}"
69
+ break test_path if File.exist?(test_path)
70
+ end
71
+ end
72
+
73
+ unless @_tmpl_path.is_a?(String)
74
+ raise "#{name}: no matching template could be found in #{File.dirname(source_location)}"
75
+ end
76
+
77
+ @_tmpl_path
78
+ end
79
+
80
+ # Read the template file.
81
+ #
82
+ # @return [String]
83
+ def component_template_content
84
+ @_tmpl_content ||= File.read(component_template_path)
85
+ end
86
+
87
+ # A list of extensions supported by the renderer
88
+ # TODO: make this extensible
89
+ #
90
+ # @return [Array<String>]
91
+ def supported_template_extensions
92
+ %w(erb serb slim haml)
93
+ end
94
+ end
95
+
96
+ # If a content block was originally passed into via `render`, capture its output.
97
+ #
98
+ # @return [String] or nil
99
+ def content
100
+ @_content ||= begin
101
+ view_context.capture(self, &@_content_block) if @_content_block
102
+ end
103
+ end
104
+
105
+ # Provide a render helper for evaluation within the component context.
106
+ #
107
+ # @param item [Object] a component supporting `render_in` or a partial name
108
+ # @param options [Hash] passed to the `partial` helper if needed
109
+ # @return [String]
110
+ def render(item, options = {}, &block)
111
+ if item.respond_to?(:render_in)
112
+ result = ""
113
+ capture do # this ensures no leaky interactions between BT<=>VC blocks
114
+ result = item.render_in(self, &block)
115
+ end
116
+ result&.html_safe
117
+ else
118
+ partial(item, options, &block)&.html_safe
119
+ end
120
+ end
121
+
122
+ # This is where the magic happens. Render the component within a view context.
123
+ #
124
+ # @param view_context [Bridgetown::RubyTemplateView]
125
+ def render_in(view_context, &block)
126
+ @view_context = view_context
127
+ @_content_block = block
128
+
129
+ if render?
130
+ before_render
131
+ template
132
+ else
133
+ ""
134
+ end
135
+ rescue StandardError => e
136
+ Bridgetown.logger.error "Component error:",
137
+ "#{self.class} encountered an error while "\
138
+ "rendering `#{self.class.component_template_path}'"
139
+ raise e
140
+ end
141
+
142
+ # Subclasses can override this method to return a string from their own
143
+ # template handling.
144
+ def template
145
+ call || _renderer.render(self)
146
+ end
147
+
148
+ # Typically not used but here as a compatibility nod toward ViewComponent.
149
+ def call
150
+ nil
151
+ end
152
+
153
+ # Subclasses can override this method to perform tasks before a render.
154
+ def before_render; end
155
+
156
+ # Subclasses can override this method to determine if the component should
157
+ # be rendered based on initialized data or other logic.
158
+ def render?
159
+ true
160
+ end
161
+
162
+ def _renderer
163
+ @_renderer ||= begin
164
+ ext = File.extname(self.class.component_template_path).delete_prefix(".")
165
+ self.class.renderer_for_ext(ext) { self.class.component_template_content }
166
+ end
167
+ end
168
+
169
+ # rubocop:disable Style/MissingRespondToMissing
170
+ ruby2_keywords def method_missing(method, *args, &block)
171
+ if helpers.respond_to?(method.to_sym)
172
+ helpers.send method.to_sym, *args, &block
173
+ else
174
+ super
175
+ end
176
+ end
177
+
178
+ def respond_to_missing?(method, include_private = false)
179
+ helpers.respond_to?(method.to_sym, include_private) || super
180
+ end
181
+ # rubocop:enable Style/MissingRespondToMissing
182
+ end
183
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bridgetown
4
+ module FrontMatterImporter
5
+ # Requires klass#content and klass#front_matter_line_count accessors
6
+ def self.included(klass)
7
+ klass.include Bridgetown::Utils::RubyFrontMatterDSL
8
+ end
9
+
10
+ YAML_HEADER = %r!\A---\s*\n!.freeze
11
+ YAML_BLOCK = %r!\A(---\s*\n.*?\n?)^((---|\.\.\.)\s*$\n?)!m.freeze
12
+ RUBY_HEADER = %r!\A[~`#\-]{3,}(?:ruby|<%|{%)\s*\n!.freeze
13
+ RUBY_BLOCK =
14
+ %r!#{RUBY_HEADER.source}(.*?\n?)^((?:%>|%})?[~`#\-]{3,}\s*$\n?)!m.freeze
15
+
16
+ def read_front_matter(file_path) # rubocop:todo Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength
17
+ file_contents = File.read(
18
+ file_path, **Bridgetown::Utils.merged_file_read_opts(Bridgetown::Current.site, {})
19
+ )
20
+ yaml_content = file_contents.match(YAML_BLOCK)
21
+ if !yaml_content && Bridgetown::Current.site.config.should_execute_inline_ruby?
22
+ ruby_content = file_contents.match(RUBY_BLOCK)
23
+ end
24
+
25
+ if yaml_content
26
+ self.content = yaml_content.post_match
27
+ self.front_matter_line_count = yaml_content[1].lines.size - 1
28
+ YAMLParser.load(yaml_content[1])
29
+ elsif ruby_content
30
+ # rbfm header + content underneath
31
+ self.content = ruby_content.post_match
32
+ self.front_matter_line_count = ruby_content[1].lines.size
33
+ process_ruby_data(ruby_content[1], file_path, 2)
34
+ elsif Bridgetown::Utils.has_rbfm_header?(file_path)
35
+ process_ruby_data(File.read(file_path).lines[1..-1].join("\n"), file_path, 2)
36
+ elsif is_a?(Layout)
37
+ self.content = file_contents
38
+ {}
39
+ else
40
+ yaml_data = YAMLParser.load_file(file_path)
41
+ yaml_data.is_a?(Array) ? { rows: yaml_data } : yaml_data
42
+ end
43
+ end
44
+
45
+ def process_ruby_data(rubycode, file_path, starting_line)
46
+ ruby_data = instance_eval(rubycode, file_path.to_s, starting_line)
47
+ ruby_data.is_a?(Array) ? { rows: ruby_data } : ruby_data.to_h
48
+ rescue StandardError => e
49
+ raise "Ruby code isn't returning an array, or object which responds to `to_h' (#{e.message})"
50
+ end
51
+ end
52
+ end