bridgetown-core 1.0.0 → 1.1.0.beta3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +6 -1
  3. data/bridgetown-core.gemspec +0 -1
  4. data/lib/bridgetown-core/collection.rb +39 -22
  5. data/lib/bridgetown-core/commands/apply.rb +3 -3
  6. data/lib/bridgetown-core/commands/build.rb +6 -6
  7. data/lib/bridgetown-core/commands/concerns/actions.rb +3 -2
  8. data/lib/bridgetown-core/commands/concerns/build_options.rb +2 -2
  9. data/lib/bridgetown-core/commands/configure.rb +1 -1
  10. data/lib/bridgetown-core/commands/console.rb +5 -5
  11. data/lib/bridgetown-core/commands/doctor.rb +7 -7
  12. data/lib/bridgetown-core/commands/esbuild/esbuild.defaults.js.erb +95 -12
  13. data/lib/bridgetown-core/commands/esbuild/migrate-from-webpack.rb +1 -6
  14. data/lib/bridgetown-core/commands/new.rb +20 -19
  15. data/lib/bridgetown-core/commands/plugins.rb +47 -9
  16. data/lib/bridgetown-core/commands/registrations.rb +2 -3
  17. data/lib/bridgetown-core/commands/serve.rb +2 -2
  18. data/lib/bridgetown-core/commands/start.rb +3 -0
  19. data/lib/bridgetown-core/commands/webpack/update.rb +3 -3
  20. data/lib/bridgetown-core/commands/webpack/webpack.defaults.js.erb +19 -14
  21. data/lib/bridgetown-core/component.rb +14 -8
  22. data/lib/bridgetown-core/concerns/localizable.rb +20 -0
  23. data/lib/bridgetown-core/concerns/prioritizable.rb +44 -0
  24. data/lib/bridgetown-core/concerns/publishable.rb +11 -1
  25. data/lib/bridgetown-core/concerns/site/configurable.rb +2 -10
  26. data/lib/bridgetown-core/concerns/site/localizable.rb +5 -1
  27. data/lib/bridgetown-core/concerns/site/ssr.rb +3 -3
  28. data/lib/bridgetown-core/concerns/site/writable.rb +28 -0
  29. data/lib/bridgetown-core/concerns/transformable.rb +2 -2
  30. data/lib/bridgetown-core/configuration.rb +4 -2
  31. data/lib/bridgetown-core/configurations/bt-postcss/postcss.config.js +5 -3
  32. data/lib/bridgetown-core/configurations/bt-postcss.rb +1 -1
  33. data/lib/bridgetown-core/configurations/lit/esbuild-plugins.js +21 -0
  34. data/lib/bridgetown-core/configurations/lit/happy-days.lit.js +26 -0
  35. data/lib/bridgetown-core/configurations/lit/lit-components-entry.js +1 -0
  36. data/lib/bridgetown-core/configurations/lit/lit-ssr.config.js +6 -0
  37. data/lib/bridgetown-core/configurations/lit.rb +95 -0
  38. data/lib/bridgetown-core/configurations/open-props/variables.css.erb +11 -0
  39. data/lib/bridgetown-core/configurations/open-props.rb +21 -0
  40. data/lib/bridgetown-core/configurations/ruby2js/hello_world.js.rb +9 -0
  41. data/lib/bridgetown-core/configurations/ruby2js.rb +67 -0
  42. data/lib/bridgetown-core/configurations/shoelace.rb +50 -0
  43. data/lib/bridgetown-core/configurations/tailwindcss.rb +16 -2
  44. data/lib/bridgetown-core/configurations/turbo/turbo_transitions.js +1 -1
  45. data/lib/bridgetown-core/converters/erb_templates.rb +7 -2
  46. data/lib/bridgetown-core/converters/markdown/kramdown_parser.rb +1 -1
  47. data/lib/bridgetown-core/converters/serbea_templates.rb +1 -4
  48. data/lib/bridgetown-core/drops/generated_page_drop.rb +2 -1
  49. data/lib/bridgetown-core/drops/resource_drop.rb +2 -1
  50. data/lib/bridgetown-core/errors.rb +5 -5
  51. data/lib/bridgetown-core/filters/translation_filters.rb +11 -0
  52. data/lib/bridgetown-core/filters/url_filters.rb +37 -10
  53. data/lib/bridgetown-core/filters.rb +3 -0
  54. data/lib/bridgetown-core/frontmatter_defaults.rb +14 -8
  55. data/lib/bridgetown-core/generated_page.rb +1 -0
  56. data/lib/bridgetown-core/kramdown/parser/gfm.rb +36 -0
  57. data/lib/bridgetown-core/model/base.rb +3 -4
  58. data/lib/bridgetown-core/plugin.rb +6 -37
  59. data/lib/bridgetown-core/plugin_manager.rb +3 -2
  60. data/lib/bridgetown-core/rack/boot.rb +7 -2
  61. data/lib/bridgetown-core/rack/logger.rb +14 -4
  62. data/lib/bridgetown-core/rack/roda.rb +106 -9
  63. data/lib/bridgetown-core/rack/routes.rb +67 -2
  64. data/lib/bridgetown-core/resource/base.rb +9 -6
  65. data/lib/bridgetown-core/resource/destination.rb +18 -0
  66. data/lib/bridgetown-core/resource/permalink_processor.rb +6 -4
  67. data/lib/bridgetown-core/resource/relations.rb +1 -1
  68. data/lib/bridgetown-core/ruby_template_view.rb +3 -3
  69. data/lib/bridgetown-core/static_file.rb +1 -1
  70. data/lib/bridgetown-core/tags/highlight.rb +1 -1
  71. data/lib/bridgetown-core/tags/post_url.rb +1 -1
  72. data/lib/bridgetown-core/url.rb +1 -1
  73. data/lib/bridgetown-core/utils/aux.rb +2 -1
  74. data/lib/bridgetown-core/utils/require_gems.rb +3 -6
  75. data/lib/bridgetown-core/utils.rb +24 -11
  76. data/lib/bridgetown-core/version.rb +2 -2
  77. data/lib/bridgetown-core/watcher.rb +21 -8
  78. data/lib/bridgetown-core.rb +8 -2
  79. data/lib/site_template/Gemfile.erb +4 -0
  80. data/lib/site_template/README.md +2 -2
  81. data/lib/site_template/bridgetown.config.yml +3 -0
  82. data/lib/site_template/frontend/javascript/index.js.erb +1 -0
  83. data/lib/site_template/frontend/styles/syntax-highlighting.css +77 -0
  84. data/lib/site_template/package.json.erb +18 -18
  85. data/lib/site_template/server/roda_app.rb +3 -6
  86. data/lib/site_template/src/404.html +2 -1
  87. data/lib/site_template/src/500.html +10 -0
  88. metadata +20 -19
  89. data/lib/bridgetown-core/publisher.rb +0 -29
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ unless Bridgetown::Utils.frontend_bundler_type == :esbuild
4
+ error_message = "#{"esbuild.config.js".bold} not found. (This configuration doesn't currently " \
5
+ "support Webpack.)"
6
+
7
+ @logger.error "\nError:".red, "🚨 #{error_message}"
8
+
9
+ return
10
+ end
11
+
12
+ say_status :lit, "Installing Lit + SSR Plugin..."
13
+
14
+ add_bridgetown_plugin "bridgetown-lit-renderer", version: "2.0.0.beta3"
15
+
16
+ run "yarn add lit esbuild-plugin-lit-css bridgetown-lit-renderer@2.0.0-beta3"
17
+
18
+ copy_file in_templates_dir("lit-ssr.config.js"), "config/lit-ssr.config.js"
19
+ copy_file in_templates_dir("lit-components-entry.js"), "config/lit-components-entry.js"
20
+ copy_file in_templates_dir("esbuild-plugins.js"), "config/esbuild-plugins.js"
21
+
22
+ insert_into_file "esbuild.config.js",
23
+ after: 'const build = require("./config/esbuild.defaults.js")' do
24
+ <<~JS
25
+
26
+ const { plugins } = require("./config/esbuild-plugins.js")
27
+ JS
28
+ end
29
+
30
+ found_match = false
31
+ gsub_file "esbuild.config.js", %r{const esbuildOptions = {}\n} do |_match|
32
+ found_match = true
33
+
34
+ <<~JS
35
+ const esbuildOptions = {
36
+ plugins: [...plugins],
37
+ // Uncomment the following to opt into `.global.css` & `.lit.css` nomenclature.
38
+ // Read https://edge.bridgetownrb.com/docs/components/lit#sidecar-css-files for documentation.
39
+ /*
40
+ postCssPluginConfig: {
41
+ filter: /(?:index|\.global)\.css$/,
42
+ },
43
+ */
44
+ }
45
+ JS
46
+ end
47
+
48
+ unless found_match
49
+ insert_into_file "esbuild.config.js",
50
+ after: 'const { plugins } = require("./config/esbuild-plugins.js")' do
51
+ <<~JS
52
+
53
+ // TODO: You will manually need to move any plugins below you wish to share with
54
+ // Lit SSR into the `config/esbuild-plugins.js` file.
55
+ // Then add `...plugins` as an item in your plugins array.
56
+ //
57
+ // You might also want to include the following in your esbuild config to opt into
58
+ // `.global.css` & `.lit.css` nomenclature.
59
+ // Read https://edge.bridgetownrb.com/docs/components/lit#sidecar-css-files for documentation.
60
+ /*
61
+ postCssPluginConfig: {
62
+ filter: /(?:index|\.global)\.css$/,
63
+ },
64
+ */
65
+ JS
66
+ end
67
+ end
68
+
69
+ copy_file in_templates_dir("happy-days.lit.js"), "src/_components/happy-days.lit.js"
70
+
71
+ javascript_import do
72
+ <<~JS
73
+ import "bridgetown-lit-renderer"
74
+ JS
75
+ end
76
+
77
+ insert_into_file "frontend/javascript/index.js",
78
+ before: 'import components from "bridgetownComponents/**/*.{js,jsx,js.rb,css}"' do
79
+ <<~JS
80
+ // To opt into `.global.css` & `.lit.css` nomenclature, change the `css` extension below to `global.css`.
81
+ // Read https://edge.bridgetownrb.com/docs/components/lit#sidecar-css-files for documentation.
82
+ JS
83
+ end
84
+
85
+ if found_match
86
+ say_status :lit, "Lit is now configured!"
87
+ say_status :lit,
88
+ "The `config/esbuild-plugins.js` file will let you add full-stack plugins in future."
89
+ else
90
+ say_status :lit, "Lit is just about configured!"
91
+ say_status :lit, "You will need to edit `esbuild.config.js` to finish setting up the plugin."
92
+ end
93
+
94
+ say "Check out the example `happy-days.lit.js` file in `src/_components`", :blue
95
+ say 'For further reading, check out "https://edge.bridgetownrb.com/docs/components/lit"', :blue
@@ -0,0 +1,11 @@
1
+ @import "open-props/<% if Bridgetown::Utils.frontend_bundler_type == :esbuild %>open-props.min.css<% else %>style<% end %>";
2
+
3
+ /* Uncomment this if you want addiitonal "default" styles applied: */
4
+ /* @import "open-props/normalize<% if Bridgetown::Utils.frontend_bundler_type == :esbuild %>.min.css<% end %>"; */
5
+
6
+ :root {
7
+ /* Define additional variables here. */
8
+
9
+ /* You can use variables from Open Props in your own custom properties. */
10
+ --color-medium-gray: var(--gray-7);
11
+ }
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ run "yarn add open-props"
4
+
5
+ variables_import = <<~CSS
6
+ @import "variables.css";
7
+
8
+ CSS
9
+
10
+ if File.exist?("frontend/styles/index.css")
11
+ prepend_to_file "frontend/styles/index.css", variables_import
12
+ elsif File.exist?("frontend/styles/index.scss")
13
+ prepend_to_file "frontend/styles/index.scss", variables_import
14
+ else
15
+ say "\nPlease add the following lines to your CSS index file:"
16
+ say variables_import
17
+ end
18
+
19
+ template in_templates_dir("variables.css.erb"), "frontend/styles/variables.css"
20
+
21
+ say_status :open_props, "Open Props is now configured."
@@ -0,0 +1,9 @@
1
+ class HelloWorld < HTMLElement
2
+ def connected_callback()
3
+ self.inner_html = "<p><strong>Hello World!</strong></p>"
4
+ end
5
+ end
6
+
7
+ # Try adding `<hello-world></hello-world>` somewhere on your site to see this
8
+ # example web component in action!
9
+ custom_elements.define "hello-world", HelloWorld
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ unless Bridgetown::Utils.frontend_bundler_type == :esbuild
4
+ error_message = "#{"esbuild.config.js".bold} not found. (This configuration doesn't currently " \
5
+ "support Webpack.)"
6
+
7
+ @logger.error "\nError:".red, "🚨 #{error_message}"
8
+
9
+ return
10
+ end
11
+
12
+ say_status :ruby2js, "Installing Ruby2JS..."
13
+
14
+ run "yarn add -D @ruby2js/esbuild-plugin"
15
+
16
+ found_match = false
17
+ gsub_file "esbuild.config.js", %r{const esbuildOptions = {}\n} do |_match|
18
+ found_match = true
19
+
20
+ <<~JS
21
+ const ruby2js = require("@ruby2js/esbuild-plugin")
22
+
23
+ const esbuildOptions = {
24
+ plugins: [
25
+ // See docs on Ruby2JS options here: https://www.ruby2js.com/docs/options
26
+ ruby2js({
27
+ eslevel: 2022,
28
+ autoexports: "default",
29
+ filters: ["camelCase", "functions", "lit", "esm", "return"]
30
+ })
31
+ ]
32
+ }
33
+ JS
34
+ end
35
+
36
+ unless found_match
37
+ insert_into_file "esbuild.config.js",
38
+ after: 'const build = require("./config/esbuild.defaults.js")' do
39
+ <<~JS
40
+
41
+ const ruby2js = require("@ruby2js/esbuild-plugin")
42
+
43
+ // TODO: Uncomment and move the following into your plugins array:
44
+ //
45
+ // ruby2js({
46
+ // eslevel: 2022,
47
+ // autoexports: "default",
48
+ // filters: ["camelCase", "functions", "lit", "esm", "return"]
49
+ // })
50
+ //
51
+ // See docs on Ruby2JS options here: https://www.ruby2js.com/docs/options
52
+
53
+ JS
54
+ end
55
+ end
56
+
57
+ copy_file in_templates_dir("hello_world.js.rb"), "src/_components/hello_world.js.rb"
58
+
59
+ if found_match
60
+ say_status :ruby2js, "Ruby2JS is now configured!"
61
+ else
62
+ say_status :ruby2js, "Ruby2JS is just about configured!"
63
+ say_status :ruby2js, "You will need to edit `esbuild.config.js` to finish setting up the plugin."
64
+ end
65
+
66
+ say "Check out the example `hello_world.js.rb` file in `src/_components`", :blue
67
+ say 'For further reading, check out "https://www.ruby2js.com"', :blue
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ say_status :shoelace, "Installing Shoelace..."
4
+
5
+ run "yarn add @shoelace-style/shoelace"
6
+
7
+ say 'Adding Shoelace to "frontend/javascript/index.js"...', :magenta
8
+
9
+ javascript_import do
10
+ <<~JS
11
+ // Import the base Shoelace stylesheet:
12
+ import "@shoelace-style/shoelace/dist/themes/light.css"
13
+
14
+ // Example components, mix 'n' match however you like!
15
+ import "@shoelace-style/shoelace/dist/components/button/button.js"
16
+ import "@shoelace-style/shoelace/dist/components/icon/icon.js"
17
+ import "@shoelace-style/shoelace/dist/components/spinner/spinner.js"
18
+
19
+ // Use the public icons folder:
20
+ import { setBasePath } from "@shoelace-style/shoelace/dist/utilities/base-path.js"
21
+ setBasePath("/shoelace-assets")
22
+ JS
23
+ end
24
+
25
+ say "Updating frontend build commands...", :magenta
26
+
27
+ if Bridgetown::Utils.frontend_bundler_type == :esbuild
28
+ insert_into_file "package.json", before: ' "esbuild": "node' do
29
+ <<-JS
30
+ "shoelace:copy-assets": "mkdir -p src/shoelace-assets && cp -r node_modules/@shoelace-style/shoelace/dist/assets src/shoelace-assets",
31
+ JS
32
+ end
33
+ gsub_file "package.json", %r{"esbuild": "node}, '"esbuild": "yarn shoelace:copy-assets && node'
34
+ gsub_file "package.json", %r{"esbuild-dev": "node},
35
+ '"esbuild-dev": "yarn shoelace:copy-assets && node'
36
+ else
37
+ insert_into_file "package.json", before: ' "webpack-build": "webpack' do
38
+ <<-JS
39
+ "shoelace:copy-assets": "mkdir -p src/shoelace-assets && cp -r node_modules/@shoelace-style/shoelace/dist/assets src/shoelace-assets",
40
+ JS
41
+ end
42
+ gsub_file "package.json", %r{"webpack-build": "webpack},
43
+ '"webpack-build": "yarn shoelace:copy-assets && webpack'
44
+ gsub_file "package.json", %r{"webpack-dev": "webpack},
45
+ '"webpack-dev": "yarn shoelace:copy-assets && webpack'
46
+ end
47
+
48
+ say_status :shoelace, "Shoelace is now configured!"
49
+
50
+ say 'For further reading, check out "https://shoelace.style"', :blue
@@ -21,7 +21,7 @@ run "npx tailwindcss init"
21
21
 
22
22
  gsub_file "tailwind.config.js", "content: [],", <<~JS.strip
23
23
  content: [
24
- './src/**/*.{html,md,liquid,erb,serb}',
24
+ './src/**/*.{html,md,liquid,erb,serb,rb}',
25
25
  './frontend/javascript/**/*.js',
26
26
  ],
27
27
  JS
@@ -38,6 +38,20 @@ end
38
38
 
39
39
  create_file "frontend/styles/jit-refresh.css", "/* #{Time.now.to_i} */"
40
40
 
41
+ insert_into_file "Rakefile",
42
+ after: %r{ task :(build|dev) do\n} do
43
+ <<-JS
44
+ sh "touch frontend/styles/jit-refresh.css"
45
+ JS
46
+ end
47
+
48
+ append_to_file ".gitignore" do
49
+ <<~FILES
50
+
51
+ frontend/styles/jit-refresh.css
52
+ FILES
53
+ end
54
+
41
55
  create_builder "tailwind_jit.rb" do
42
56
  <<~RUBY
43
57
  class Builders::TailwindJit < SiteBuilder
@@ -45,7 +59,7 @@ create_builder "tailwind_jit.rb" do
45
59
  hook :site, :pre_reload do |_, paths|
46
60
  # Don't trigger refresh if it's a frontend-only change
47
61
  next if paths.length == 1 && paths.first.ends_with?("manifest.json")
48
-
62
+
49
63
  # Save out a comment file to trigger Tailwind's JIT
50
64
  refresh_file = site.in_root_dir("frontend", "styles", "jit-refresh.css")
51
65
  File.write refresh_file, "/* \#{Time.now.to_i} */"
@@ -16,7 +16,7 @@ document.addEventListener("turbo:visit", () => {
16
16
  { opacity: 1, transform: "translateY(0px) scale(1)" },
17
17
  { opacity: 0, transform: `translateY(${movement}) scale(${scale})` }
18
18
  ],
19
- { duration: 300, easing: "cubic-bezier(0.45, 0, 0.55, 1)" }
19
+ { duration: 300, easing: "cubic-bezier(0.45, 0, 0.55, 1)", fill: "forwards" }
20
20
  );
21
21
 
22
22
  Promise.all(main.getAnimations().map(animation => animation.finished)).then(() => {
@@ -79,10 +79,15 @@ module Bridgetown
79
79
  Erubi.h(input)
80
80
  end
81
81
 
82
- def partial(partial_name, options = {})
82
+ def partial(partial_name = nil, **options, &block)
83
+ partial_name = options[:template] if partial_name.nil? && options[:template]
83
84
  options.merge!(options[:locals]) if options[:locals]
84
- options[:content] = yield if block_given?
85
+ options[:content] = capture(&block) if block
85
86
 
87
+ _render_partial partial_name, options
88
+ end
89
+
90
+ def _render_partial(partial_name, options)
86
91
  partial_path = _partial_path(partial_name, "erb")
87
92
  tmpl = site.tmp_cache["partial-tmpl:#{partial_path}"] ||= Tilt::ErubiTemplate.new(
88
93
  partial_path,
@@ -76,7 +76,7 @@ module Bridgetown
76
76
  @config["syntax_highlighter"] ||= config["highlighter"] || "rouge"
77
77
  @config["syntax_highlighter_opts"] ||= {}
78
78
  @config["syntax_highlighter_opts"]["guess_lang"] = @config["guess_lang"]
79
- require "kramdown-parser-gfm" if @config["input"] == "GFM"
79
+ require_relative "../../kramdown/parser/gfm" if @config["input"] == "GFM"
80
80
  end
81
81
 
82
82
  def convert(content)
@@ -7,10 +7,7 @@ module Bridgetown
7
7
  class SerbeaView < ERBView
8
8
  include Serbea::Helpers
9
9
 
10
- def partial(partial_name, options = {}, &block)
11
- options.merge!(options[:locals]) if options[:locals]
12
- options[:content] = capture(&block) if block
13
-
10
+ def _render_partial(partial_name, options)
14
11
  partial_path = _partial_path(partial_name, "serb")
15
12
  tmpl = site.tmp_cache["partial-tmpl:#{partial_path}"] ||=
16
13
  Tilt::SerbeaTemplate.new(partial_path)
@@ -15,7 +15,8 @@ module Bridgetown
15
15
  :path,
16
16
  :url,
17
17
  :relative_url,
18
- :relative_path
18
+ :relative_path,
19
+ :all_locales
19
20
 
20
21
  private def_delegator :@obj, :data, :fallback_data
21
22
  end
@@ -24,7 +24,8 @@ module Bridgetown
24
24
  :relative_url,
25
25
  :date,
26
26
  :taxonomies,
27
- :relations
27
+ :relations,
28
+ :all_locales
28
29
 
29
30
  private def_delegator :@obj, :data, :fallback_data
30
31
 
@@ -15,9 +15,9 @@ module Bridgetown
15
15
  InvalidURLError = Class.new(FatalException)
16
16
  InvalidConfigurationError = Class.new(FatalException)
17
17
 
18
- def self.print_build_error(exc, trace: false)
19
- Bridgetown.logger.error "Exception raised:", exc.class.to_s.bold
20
- Bridgetown.logger.error exc.message.reset_ansi
18
+ def self.print_build_error(exc, trace: false, logger: Bridgetown.logger)
19
+ logger.error "Exception raised:", exc.class.to_s.bold
20
+ logger.error exc.message.reset_ansi
21
21
 
22
22
  trace_args = ["-t", "--trace"]
23
23
  print_trace_msg = true
@@ -28,12 +28,12 @@ module Bridgetown
28
28
  exc.backtrace[0..4]
29
29
  end
30
30
  traces.each_with_index do |backtrace_line, index|
31
- Bridgetown.logger.error "#{index + 1}:", backtrace_line.reset_ansi
31
+ logger.error "#{index + 1}:", backtrace_line.reset_ansi
32
32
  end
33
33
 
34
34
  return unless print_trace_msg
35
35
 
36
- Bridgetown.logger.warn "Backtrace:", "Use the --trace option for complete information."
36
+ logger.warn "Backtrace:", "Use the --trace option for complete information."
37
37
  end
38
38
  end
39
39
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bridgetown
4
+ module Filters
5
+ module TranslationFilters
6
+ def t(input)
7
+ I18n.t(input.to_s)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -7,9 +7,8 @@ module Bridgetown
7
7
 
8
8
  # Produces an absolute URL based on site.url and site.base_path.
9
9
  #
10
- # input - the URL to make absolute.
11
- #
12
- # Returns the absolute URL as a String.
10
+ # @param input [String] the URL to make absolute.
11
+ # @return [String] the absolute URL as a String.
13
12
  def absolute_url(input)
14
13
  cache = (@context.registers[:cached_absolute_urls] ||= {})
15
14
  cache[input] ||= compute_absolute_url(input)
@@ -18,19 +17,47 @@ module Bridgetown
18
17
  # Produces a URL relative to the domain root based on site.base_path
19
18
  # unless it is already an absolute url with an authority (host).
20
19
  #
21
- # input - the URL to make relative to the domain root
22
- #
23
- # Returns a URL relative to the domain root as a String.
20
+ # @param input [String] the URL to make relative to the domain root
21
+ # @return [String] a URL relative to the domain root as a String.
24
22
  def relative_url(input)
25
23
  cache = (@context.registers[:cached_relative_urls] ||= {})
26
24
  cache[input] ||= compute_relative_url(input)
27
25
  end
28
26
 
29
- # Strips trailing `/index.html` from URLs to create pretty permalinks
27
+ # For string input, adds a prefix of the current site locale to a relative
28
+ # URL, unless it's a default locale and prefix_current_locale config is
29
+ # false. For a resources array input, return a filtered resources array
30
+ # based on the locale.
30
31
  #
31
- # input - the URL with a possible `/index.html`
32
+ # @param input [String, Array] the relative URL, or an array of resources
33
+ # @param use_locale [String] another locale to use beside the current one
34
+ # (must be in site's `available_locales` config)
35
+ # @return [String, Array] the prefixed relative URL, or filtered resources
36
+ def in_locale(input, use_locale = nil)
37
+ site = @context.registers[:site]
38
+ use_locale ||= site.locale
39
+
40
+ # If we're given a collection, filter down and return
41
+ if input.is_a?(Array)
42
+ return input.select do |res|
43
+ res.data[:locale].to_sym == use_locale.to_sym
44
+ end
45
+ end
46
+
47
+ if !site.config.prefix_default_locale &&
48
+ use_locale.to_sym == site.config.default_locale
49
+ return input
50
+ end
51
+
52
+ return input unless site.config.available_locales.include?(use_locale.to_sym)
53
+
54
+ "#{use_locale}/#{input.to_s.delete_prefix("/")}"
55
+ end
56
+
57
+ # Strips trailing `/index.html` from URLs to create pretty permalinks
32
58
  #
33
- # Returns a URL with the trailing `/index.html` removed
59
+ # @param input [String] the URL with a possible `/index.html`
60
+ # @return [String] a URL with the trailing `/index.html` removed
34
61
  def strip_index(input)
35
62
  return if input.nil? || input.to_s.empty?
36
63
 
@@ -42,7 +69,7 @@ module Bridgetown
42
69
  # @param input [Object] value which responds to `to_s`
43
70
  # @return [String]
44
71
  def strip_extname(input)
45
- Pathname.new(input.to_s).yield_self do |path|
72
+ Pathname.new(input.to_s).then do |path|
46
73
  path.dirname + path.basename(".*")
47
74
  end.to_s
48
75
  end
@@ -435,3 +435,6 @@ end
435
435
  Liquid::Template.register_filter(
436
436
  Bridgetown::Filters
437
437
  )
438
+ Liquid::Template.register_filter(
439
+ Bridgetown::Filters::TranslationFilters
440
+ )
@@ -9,10 +9,12 @@ module Bridgetown
9
9
 
10
10
  def initialize(site)
11
11
  @site = site
12
+ @defaults_cache = {}
12
13
  end
13
14
 
14
15
  def reset
15
16
  @glob_cache = {}
17
+ @defaults_cache = {}
16
18
  end
17
19
 
18
20
  def ensure_time!(set)
@@ -29,16 +31,19 @@ module Bridgetown
29
31
  # Collects a hash with all default values for a resource
30
32
  #
31
33
  # @param path [String] the relative path of the resource
32
- # @param collection [Symbol] :posts, :pages, etc.
34
+ # @param collection_name [Symbol] :posts, :pages, etc.
33
35
  #
34
- # @returns [Hash] all default values (an empty hash if there are none)
35
- def all(path, collection)
36
- defaults = {}
36
+ # @return [Hash] all default values (an empty hash if there are none)
37
+ def all(path, collection_name)
38
+ if @defaults_cache.key?([path, collection_name])
39
+ return @defaults_cache[[path, collection_name]]
40
+ end
37
41
 
42
+ defaults = {}
38
43
  merge_data_cascade_for_path(path, defaults)
39
44
 
40
45
  old_scope = nil
41
- matching_sets(path, collection).each do |set|
46
+ matching_sets(path, collection_name).each do |set|
42
47
  if has_precedence?(old_scope, set["scope"])
43
48
  defaults = Utils.deep_merge_hashes(defaults, set["values"])
44
49
  old_scope = set["scope"]
@@ -46,7 +51,8 @@ module Bridgetown
46
51
  defaults = Utils.deep_merge_hashes(set["values"], defaults)
47
52
  end
48
53
  end
49
- defaults
54
+
55
+ @defaults_cache[[path, collection_name]] = defaults
50
56
  end
51
57
 
52
58
  private
@@ -123,7 +129,7 @@ module Bridgetown
123
129
  # @param scope [Hash] the defaults set being asked about
124
130
  # @param collection [Symbol] the collection of the resource being processed
125
131
  #
126
- # @returns [Boolean] whether either of the above conditions are satisfied
132
+ # @return [Boolean] whether either of the above conditions are satisfied
127
133
  def applies_collection?(scope, collection)
128
134
  !scope.key?("collection") || scope["collection"].eql?(collection.to_s)
129
135
  end
@@ -132,7 +138,7 @@ module Bridgetown
132
138
  #
133
139
  # @param set [Hash] the default value hash as defined in bridgetown.config.yml
134
140
  #
135
- # @returns [Boolean] if the set is valid and can be used
141
+ # @return [Boolean] if the set is valid and can be used
136
142
  def valid?(set)
137
143
  set.is_a?(Hash) && set["values"].is_a?(Hash)
138
144
  end
@@ -4,6 +4,7 @@ module Bridgetown
4
4
  class GeneratedPage
5
5
  include LayoutPlaceable
6
6
  include LiquidRenderable
7
+ include Localizable
7
8
  include Publishable
8
9
  include Transformable
9
10
 
@@ -0,0 +1,36 @@
1
+ # Frozen-string-literal: true
2
+
3
+ require "kramdown-parser-gfm"
4
+
5
+ module Kramdown
6
+ module Parser
7
+ class GFM
8
+ MARK_DELIMITER = %r{(==|::)+}.freeze
9
+ MARK_MATCH = %r{#{MARK_DELIMITER}(?!\s|=|:).*?[^\s=:]#{MARK_DELIMITER}}m.freeze
10
+
11
+ # Monkey-patch GFM initializer to add our new mark parser
12
+ alias_method :_old_initialize, :initialize
13
+ def initialize(source, options)
14
+ _old_initialize(source, options)
15
+ @span_parsers << :mark if @options[:mark_highlighting]
16
+ end
17
+
18
+ def parse_mark
19
+ line_number = @src.current_line_number
20
+
21
+ @src.pos += @src.matched_size
22
+ el = Element.new(:html_element, "mark", {}, category: :span, line: line_number)
23
+ @tree.children << el
24
+
25
+ env = save_env
26
+ reset_env(src: Kramdown::Utils::StringScanner.new(@src.matched[2..-3], line_number),
27
+ text_type: :text)
28
+ parse_spans(el)
29
+ restore_env(env)
30
+
31
+ el
32
+ end
33
+ define_parser(:mark, MARK_MATCH)
34
+ end
35
+ end
36
+ end
@@ -95,8 +95,7 @@ module Bridgetown
95
95
 
96
96
  # @return [Bridgetown::Resource::Base]
97
97
  def as_resource_in_collection
98
- collection.resources << to_resource.read!
99
- collection.resources.last
98
+ collection.add_resource_from_model(self)
100
99
  end
101
100
 
102
101
  # @return [Bridgetown::Resource::Base]
@@ -153,8 +152,8 @@ module Bridgetown
153
152
  return attributes[key]
154
153
  end
155
154
 
156
- Bridgetown.logger.warn "key `#{method_name}' not found in attributes for" \
157
- " #{attributes[:id].presence || "new #{self.class}"}"
155
+ Bridgetown.logger.warn "key `#{method_name}' not found in attributes for " \
156
+ "#{attributes[:id].presence || "new #{self.class}"}"
158
157
  nil
159
158
  end
160
159