Module: Postnhost::ApplicationHelper

Included in:
SeoHelper
Defined in:
app/helpers/postnhost/application_helper.rb

Constant Summary collapse

AUTHOR_SOCIAL_FIELDS =
[
  { field: :website_url, label: "Website", icon: "external-link" },
  { field: :x_url, label: "X", icon: "x" },
  { field: :linkedin_url, label: "LinkedIn", icon: "linkedin" },
  { field: :facebook_url, label: "Facebook", icon: "facebook" },
  { field: :youtube_url, label: "YouTube", icon: "youtube" },
  { field: :instagram_url, label: "Instagram", icon: "instagram" },
  { field: :threads_url, label: "Threads", icon: "threads" },
  { field: :tiktok_url, label: "TikTok", icon: "tiktok" },
  { field: :mastodon_url, label: "Mastodon", icon: "mastodon" },
  { field: :bluesky_url, label: "Bluesky", icon: "bluesky" }
].freeze

Instance Method Summary collapse

Instance Method Details

#admin_datetime(value, format: "%B %d, %Y at %l:%M %p %Z") ⇒ Object



39
40
41
42
43
# File 'app/helpers/postnhost/application_helper.rb', line 39

def admin_datetime(value, format: "%B %d, %Y at %l:%M %p %Z")
  return if value.blank?

  l(value, format:)
end

#admin_datetime_local_value(value) ⇒ Object



45
46
47
48
49
# File 'app/helpers/postnhost/application_helper.rb', line 45

def admin_datetime_local_value(value)
  return if value.blank?

  l(value, format: "%Y-%m-%dT%H:%M")
end

#article_author_label(author) ⇒ Object



108
109
110
# File 'app/helpers/postnhost/application_helper.rb', line 108

def (author)
  author&.position.presence || t("postnhost.public.blog.author_label")
end

#article_author_records(article) ⇒ Object



203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# File 'app/helpers/postnhost/application_helper.rb', line 203

def (article)
  association_name = article.is_a?(Postnhost::Snapshot::Article) ? :article_snapshot_authors : :article_authors
  return [] unless article.respond_to?(association_name)

  @article_author_records_cache ||= {}
  cache_key = [article.class.name, article.id || article.object_id]
  return @article_author_records_cache[cache_key] if @article_author_records_cache.key?(cache_key)

  records = if article.association(association_name).loaded?
              article.public_send(association_name).to_a
            else
              article.public_send(association_name).order(:position).to_a
            end

  ActiveRecord::Associations::Preloader.new(records:, associations: :user).call if records.any?

  @article_author_records_cache[cache_key] = records
end

#article_authors(article) ⇒ Object



81
82
83
84
85
86
87
# File 'app/helpers/postnhost/application_helper.rb', line 81

def (article)
  article = article_record_for_author_data(article)
  return [] unless article

  authors = (article).map(&:user)
  authors.select { |author| author_name(author).present? }
end

#article_authors_cache_key(article) ⇒ Object



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'app/helpers/postnhost/application_helper.rb', line 89

def (article)
  article = article_record_for_author_data(article)
  return [] unless article.respond_to?(:article_authors) || article.respond_to?(:article_snapshot_authors)

  [
    "author_pages_enabled",
    author_pages_enabled?,
    *(article).map do ||
      author = .user
      [
        .user_id,
        .position,
        .updated_at&.to_i,
        author&.updated_at&.to_i
      ]
    end
  ]
end

#article_record_for_author_data(record) ⇒ Object



190
191
192
193
194
195
196
197
198
199
200
201
# File 'app/helpers/postnhost/application_helper.rb', line 190

def article_record_for_author_data(record)
  return unless record

  case record
  when Postnhost::Snapshot::ArticleVariant
    record.article_snapshot
  when Postnhost::ArticleVariant
    record.article
  else
    record
  end
end

#author_avatar(user = nil) ⇒ Object



59
60
61
62
63
64
# File 'app/helpers/postnhost/application_helper.rb', line 59

def author_avatar(user = nil)
  user ||= current_user if respond_to?(:current_user)
  return unless user.respond_to?(:avatar_file) && user.avatar_file?

  user.avatar_file.url
end

#author_initials(user = nil) ⇒ Object



66
67
68
69
70
71
# File 'app/helpers/postnhost/application_helper.rb', line 66

def author_initials(user = nil)
  name = author_name(user)
  return if name.blank?

  name.split.map(&:first).join.upcase[0, 2]
end

#author_name(user = nil) ⇒ Object

Author helpers rely on the CMS user profile only.



52
53
54
55
56
57
# File 'app/helpers/postnhost/application_helper.rb', line 52

def author_name(user = nil)
  user ||= current_user if respond_to?(:current_user)
  return unless user.respond_to?(:name)

  user.name.presence
end

#author_pages_enabled?Boolean

Returns:

  • (Boolean)


73
74
75
76
77
# File 'app/helpers/postnhost/application_helper.rb', line 73

def author_pages_enabled?
  return @author_pages_enabled if defined?(@author_pages_enabled)

  @author_pages_enabled = current_setting.author_pages_enabled?
end


112
113
114
115
116
117
118
119
120
121
# File 'app/helpers/postnhost/application_helper.rb', line 112

def author_social_links(author)
  return [] unless author

  AUTHOR_SOCIAL_FIELDS.filter_map do |social|
    url = normalize_external_url(author.public_send(social[:field]))
    next unless url

    social.merge(url:)
  end
end

#current_path_without_localeObject

Language switcher helpers



124
125
126
127
128
129
130
131
132
# File 'app/helpers/postnhost/application_helper.rb', line 124

def current_path_without_locale
  base_path = request.path_info.to_s
  base_path = "/" if base_path.blank?

  locale = params[:locale].presence
  stripped_path = locale.present? ? base_path.sub(%r{\A/#{Regexp.escape(locale)}(?=/|$)}, "") : base_path

  stripped_path.presence || "/"
end

#flash_class(level) ⇒ Object



28
29
30
31
32
33
34
35
36
37
# File 'app/helpers/postnhost/application_helper.rb', line 28

def flash_class(level)
  case level.to_sym
  when :notice then "bg-blue-50 border border-blue-200 text-blue-800  rounded-2xl"
  when :success then "bg-green-50 border border-green-200 text-green-800  rounded-2xl"
  when :error then "bg-red-50 border border-red-200 text-red-800  rounded-2xl"
  when :alert then "bg-yellow-50 border border-yellow-200 text-yellow-800  rounded-2xl"
  when :payment_required then "hidden"
  else "bg-gray-50 border border-gray-200 text-gray-800  rounded-2xl"
  end
end

#language_author_path(author_slug, language) ⇒ Object



168
169
170
171
172
173
174
175
176
177
# File 'app/helpers/postnhost/application_helper.rb', line 168

def language_author_path(author_slug, language)
  return unless author_pages_enabled?
  return public_author_path(author_slug) unless language

  if language.default
    public_author_path(author_slug)
  else
    localized_public_author_path(language.html_lang, author_slug)
  end
end

#language_author_url(author_slug, language) ⇒ Object



179
180
181
182
183
184
185
186
187
188
# File 'app/helpers/postnhost/application_helper.rb', line 179

def language_author_url(author_slug, language)
  return unless author_pages_enabled?
  return public_author_url(author_slug) unless language

  if language.default
    public_author_url(author_slug)
  else
    localized_public_author_url(language.html_lang, author_slug)
  end
end

#language_category_path(category_slug, language) ⇒ Object



158
159
160
161
162
163
164
165
166
# File 'app/helpers/postnhost/application_helper.rb', line 158

def language_category_path(category_slug, language)
  return public_category_path(category_slug) unless language

  if language.default
    public_category_path(category_slug)
  else
    localized_public_category_path(language.html_lang, category_slug)
  end
end

#language_root_path(language) ⇒ Object

Language-aware navigation helpers for public pages



148
149
150
151
152
153
154
155
156
# File 'app/helpers/postnhost/application_helper.rb', line 148

def language_root_path(language)
  return root_path unless language

  if language.default
    root_path
  else
    localized_root_path(locale: language.html_lang)
  end
end

#localized_path(language) ⇒ Object



134
135
136
137
138
139
140
141
142
143
144
145
# File 'app/helpers/postnhost/application_helper.rb', line 134

def localized_path(language)
  base_path = current_path_without_locale
  base_path = "/" if base_path.empty?

  locale_path = if language.default
                  base_path
                else
                  base_path == "/" ? "/#{language.html_lang}" : "/#{language.html_lang}#{base_path}"
                end

  "#{request.script_name}#{locale_path}"
end

#normalize_external_url(value) ⇒ Object



222
223
224
225
226
227
228
229
230
231
232
233
234
# File 'app/helpers/postnhost/application_helper.rb', line 222

def normalize_external_url(value)
  raw_url = value.to_s.strip
  return if raw_url.blank?

  normalized_url = raw_url.match?(%r{\Ahttps?://}i) ? raw_url : "https://#{raw_url}"
  uri = URI.parse(normalized_url)
  return if uri.host.blank?
  return if uri.userinfo.present?

  normalized_url
rescue URI::InvalidURIError
  nil
end

#postnhost_openai_api_key_configured?Boolean

Returns:

  • (Boolean)


16
17
18
# File 'app/helpers/postnhost/application_helper.rb', line 16

def postnhost_openai_api_key_configured?
  Postnhost.config.openai_api_key.present?
end

#postnhost_public_locale_file_present_for?(html_lang) ⇒ Boolean

Returns:

  • (Boolean)


20
21
22
23
24
25
26
# File 'app/helpers/postnhost/application_helper.rb', line 20

def postnhost_public_locale_file_present_for?(html_lang)
  locale = html_lang.to_s.strip
  return true if locale.blank?

  Postnhost::Engine.root.join("config/locales/#{locale}.yml").exist? ||
    Rails.root.join("config/locales/#{locale}.yml").exist?
end