seiten 1.2.0 → 1.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '09cdd9e8323ed21cafe0eb5f92544ee05a8e78bc86b421a0fb2bfc6c865ecd8b'
4
- data.tar.gz: f9860ca8c46a06a36136a992e078be502c81fba45373c5feae6682a5fb431e8e
3
+ metadata.gz: 6289826464b8f2c34c78a4d469fe26e0e772c79f67adf29f38dc3465c9d35ed6
4
+ data.tar.gz: fb131648fd8558fadf4e3b17f27aa1c24e4b4d4b59a13fcf0d173632c561c2a3
5
5
  SHA512:
6
- metadata.gz: 4ab559c9fb74b3373ddb9b31485dd4d78b56bcab9dbd1c1e863bafcf0a60c1a4cfb502728ea763db6e7b81ca9b1ff9d3c17d529fcf5b7b8c0bf226cca5316e6d
7
- data.tar.gz: 4525be586db9bba6d0c8b1589d7297680b411523874c4fae5ed73dbb3ebff0445a65c7a27c22c65612c29c2dd525a30de5c845482c2cafef044824c8e7acc426
6
+ metadata.gz: b69aa165a103bd083dba0cb57c6c34078b139d56dba5a0e83679e4d654bd863e1e245d7dc247e429f6f3bf393818faa450f6c59fe9ad2255498e773427eb865c
7
+ data.tar.gz: '0643406590aa1ae9a182222163f903764807699d460cfa9652f3a56e235685bbb4c50e440701cae5a519f1f0a2afb5c5ba680ea41d74bf9098257737bd39242b'
@@ -32,6 +32,16 @@ module Seiten
32
32
  page_collection
33
33
  end
34
34
 
35
+ # The navigation's own title and slug, from I18n like its pages' (<i18n_scope>.<name>.title and
36
+ # .slug; the slug defaults to the parameterized title). Its localized routes start with the slug.
37
+ def title
38
+ I18n.t('title', scope: [Seiten.config[:i18n_scope], name], locale: locale, default: nil)
39
+ end
40
+
41
+ def slug
42
+ I18n.t('slug', scope: [Seiten.config[:i18n_scope], name], locale: locale, default: nil) || title&.parameterize
43
+ end
44
+
35
45
  def pages=(pages_array)
36
46
  page_collection.pages = pages_array.map { |page| page.navigation_id = id; page }
37
47
  # return page_collection
@@ -1,15 +1,48 @@
1
1
  class ActionDispatch::Routing::Mapper
2
+ # Routes a navigation's pages. Draw it after your other routes, which it would swallow.
3
+ #
4
+ # A navigation built in every locale from one file (config/navigations/help.yml) gets a route per
5
+ # locale, under the locale and the navigation's slug (its I18n title or slug, see
6
+ # Navigation#slug), to Help::PagesController#show, named help_page_<locale>:
7
+ #
8
+ # seiten :help # /en/help(/*slug), /de/hilfe(/*slug)
9
+ #
10
+ # Every page gets a link helper named after the navigation and its key, and the navigation one that
11
+ # takes a key; both link to the page in I18n.locale or the `locale:` option:
12
+ #
13
+ # help_account_manage_path # => "/en/help/your-account/manage-your-account"
14
+ # help_account_manage_url(locale: :de) # => "http://…/de/hilfe/dein-account/account-verwalten"
15
+ # help_page_path(page.key) # the same, for a key in a variable; unknown keys raise
16
+ # help_page_path # => "/en/help", the navigation's root
17
+ #
18
+ # `to:`, `as:` (of the navigation's helper) and `path:` (the same in every locale) replace the
19
+ # defaults, `prefix: false` names the page helpers without the navigation (account_manage_path), and
20
+ # `localized: false` draws one catch-all route instead.
21
+ #
22
+ # Other navigations get one catch-all route to seiten/pages#show (or `to:`) that sets
23
+ # params[:navigation_id] (except for the application navigation); `localized: true` routes them per
24
+ # locale too.
25
+ #
26
+ # seiten # /*slug, the application navigation
27
+ # scope(:help) { seiten :help }
2
28
  def seiten(*resources)
3
29
  options = resources.extract_options!
4
- options[:to] ||= 'seiten/pages#show'
30
+ localized, path, prefix = options.extract!(:localized, :path, :prefix).values_at(:localized, :path, :prefix)
5
31
 
6
32
  resources.each do |resource|
7
- resource_options = options.dup
33
+ name = resource.to_s
34
+
35
+ if localized.nil? ? Seiten.i18n_navigation?(name) : localized
36
+ seiten_localized_routes(name, options.dup, path: path, prefix: prefix.nil? ? name : prefix)
37
+ next
38
+ end
8
39
 
40
+ resource_options = options.dup
41
+ resource_options[:to] ||= 'seiten/pages#show'
9
42
  resource_options[:as] ||= resource == :application ? :seiten_page : "seiten_#{resource}_page"
10
43
 
11
- resource_options[:defaults] ||= {}
12
- resource_options[:defaults][:navigation_id] = resource.to_s unless resource == :application
44
+ resource_options[:defaults] = resource_options[:defaults].to_h.dup
45
+ resource_options[:defaults][:navigation_id] = name unless resource == :application
13
46
  resource_options[:defaults][:slug] = ''
14
47
 
15
48
  # NOTE: See https://github.com/rails/rails/issues/31228
@@ -18,4 +51,46 @@ class ActionDispatch::Routing::Mapper
18
51
  get '(*slug)', **resource_options
19
52
  end
20
53
  end
54
+
55
+ private
56
+
57
+ def seiten_localized_routes(name, options, path:, prefix:)
58
+ navigations = Seiten::Navigation.where(name: name)
59
+ raise ArgumentError, "No #{name} navigation in #{Seiten.config[:config_dir]}" if navigations.empty?
60
+
61
+ route = (options.delete(:as) || "#{name}_page").to_s
62
+ options = { to: "#{name}/pages#show", format: false, **options }
63
+ defaults = { **options.delete(:defaults).to_h, navigation_id: name, slug: '' }
64
+
65
+ navigations.each do |navigation|
66
+ locale_path = [navigation.locale, path || navigation.slug].compact_blank.join('/')
67
+ get "#{locale_path}(/*slug)", **options, as: "#{route}_#{navigation.locale}", defaults: defaults.merge(locale: navigation.locale)
68
+ end
69
+
70
+ keys = navigations.first.pages.all.filter_map(&:key)
71
+ helpers = keys.map { |key| [prefix.presence, *key.split('.')].compact.join('_') }
72
+ duplicate = [route, *helpers].tally.find { |_, count| count > 1 }&.first
73
+ raise ArgumentError, "The #{name} navigation would define #{duplicate}_path twice" if duplicate
74
+
75
+ seiten_link_helper(route, name, route)
76
+ keys.zip(helpers).each { |key, helper| seiten_link_helper(helper, name, route, key) }
77
+ end
78
+
79
+ # <helper>_path and <helper>_url: the page with `page_key` (else the key given first, else the
80
+ # navigation's root) in the navigation of I18n.locale or the `locale:` option.
81
+ def seiten_link_helper(helper, navigation_name, route, page_key = nil)
82
+ @set.add_url_helper(helper, {}) do |*args|
83
+ options = args.extract_options!
84
+ key = page_key || args.first
85
+ locale = (options[:locale] || I18n.locale).to_s
86
+
87
+ navigation = Seiten::Navigation.find_by(name: navigation_name, locale: locale)
88
+ raise ArgumentError, "No #{navigation_name} navigation in #{locale}" unless navigation
89
+
90
+ page = navigation.pages.find_by(key: key.to_s) if key
91
+ raise ArgumentError, "No page #{key} in the #{navigation_name} navigation" if key && !page
92
+
93
+ { use_route: "#{route}_#{locale}", slug: page&.slug.to_s, **options.except(:locale) }
94
+ end
95
+ end
21
96
  end
@@ -1,3 +1,3 @@
1
1
  module Seiten
2
- VERSION = "1.2.0"
2
+ VERSION = "1.3.0"
3
3
  end
data/lib/seiten.rb CHANGED
@@ -80,6 +80,11 @@ module Seiten
80
80
  end
81
81
  end
82
82
 
83
+ # Whether the navigation is built in every locale from one file (config/navigations/<name>.yml).
84
+ def i18n_navigation?(name)
85
+ @i18n_files.key?(name.to_s)
86
+ end
87
+
83
88
  # Drops the navigations built from I18n, so they're built again with the current translations
84
89
  # (on every code or translation reload in development).
85
90
  def reset_i18n_navigations!
@@ -0,0 +1,5 @@
1
+ class Guide::PagesController < ApplicationController
2
+ def show
3
+ render plain: "#{current_navigation.id} #{current_page&.key}"
4
+ end
5
+ end
@@ -1,6 +1,7 @@
1
1
  de:
2
2
  navigations:
3
3
  guide:
4
+ title: Anleitung
4
5
  start:
5
6
  title: Start
6
7
  account:
@@ -1,6 +1,7 @@
1
1
  en:
2
2
  navigations:
3
3
  guide:
4
+ title: Guide
4
5
  start:
5
6
  title: Start
6
7
  account:
@@ -3,6 +3,8 @@ Dummy::Application.routes.draw do
3
3
 
4
4
  get "/blog", to: "posts#index"
5
5
 
6
+ seiten :guide
7
+
6
8
  scope :help do
7
9
  seiten :help
8
10
  end
File without changes