happy-titles 1.1.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/happy-titles.rb CHANGED
@@ -1,79 +1,19 @@
1
- require File.join(File.dirname(__FILE__), *%w[happy-titles railtie]) if defined?(::Rails::Railtie)
1
+ # frozen_string_literal: true
2
+ require "happy-titles/railtie" if defined?(::Rails::Railtie)
3
+
4
+ require "happy-titles/config"
5
+ require "happy-titles/helpers"
6
+ require "happy-titles/template"
7
+ require "happy-titles/template_set"
2
8
 
3
9
  module HappyTitles
4
-
5
- attr_accessor :page_title
6
-
7
- @@happy_title_settings = {
8
- :site => 'My Site',
9
- :tagline => 'My short, descriptive and witty tagline',
10
- :templates => {
11
- :default => [':site | :title', ':title | :site']
12
- }
13
- }
14
-
15
- def happy_title(template_key = :default)
16
- content_tag(:title, render_title_template(template_key))
17
- end
18
-
19
- def title(page_title = nil, settings = {})
10
+ class TemplateNotFound < StandardError; end
20
11
 
21
- if page_title && page_title.is_a?(Hash)
22
- settings = page_title
23
- page_title = settings[:title] ? settings[:title] : nil
24
- end
25
-
26
- @happy_title_settings = settings
27
- if page_title
28
- @page_title = h(page_title.gsub(/<\/?[^>]*>/, '')) if page_title
29
- else
30
- @page_title || ''
31
- end
32
-
12
+ def self.config
13
+ @config ||= Config.new
33
14
  end
34
-
35
- def self.included(base)
36
- base.class_eval do
37
-
38
- cattr_accessor :happy_title_settings
39
-
40
- def self.happy_title_template(template_key, format, additional_format = nil)
41
- template = [format]
42
- template << additional_format if additional_format
43
- @@happy_title_settings[:templates][template_key] = template
44
- end
45
15
 
46
- def self.happy_title_setting(key, value)
47
- @@happy_title_settings[key] = value
48
- end
49
-
50
- end
16
+ def self.configure
17
+ yield config
51
18
  end
52
-
53
- private
54
-
55
- def render_title_template(template_key)
56
- key = (@page_title && @@happy_title_settings[:templates][template_key][1]) ? 1 : 0
57
- template = read_happy_title_setting(:template) ? read_happy_title_setting(:template) : @@happy_title_settings[:templates][template_key][key]
58
- substitute_placeholders(template)
59
- end
60
-
61
- def substitute_placeholders(template)
62
- title = template
63
- title = title.gsub(':title', title_text)
64
- title = title.gsub(':site', read_happy_title_setting(:site))
65
- title = title.gsub(':tagline', read_happy_title_setting(:tagline))
66
- end
67
-
68
- def read_happy_title_setting(key)
69
- setting = @@happy_title_settings[key]
70
- setting = @happy_title_settings[key] if @happy_title_settings && !@happy_title_settings[key].blank?
71
- setting = setting.call if setting.is_a?(Proc)
72
- setting
73
- end
74
-
75
- def title_text
76
- (@page_title) ? @page_title : read_happy_title_setting(:tagline)
77
- end
78
-
79
- end
19
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+ module HappyTitles
3
+ class Config
4
+ attr_accessor :site, :tagline
5
+
6
+ def initialize
7
+ @site = DEFAULT_SITE
8
+ @tagline = DEFAULT_TAGLINE
9
+ @template_set = HappyTitles::TemplateSet.new(default_template)
10
+ end
11
+
12
+ def template(key = :default)
13
+ template_set.get(key)
14
+ end
15
+
16
+ def templates(&block)
17
+ template_set.instance_eval(&block)
18
+ end
19
+
20
+ private
21
+
22
+ DEFAULT_SITE = "My site"
23
+ DEFAULT_TAGLINE = "My short, descriptive and witty tagline"
24
+
25
+ DEFAULT_TEMPLATE_OPTIONS = {
26
+ name: :default,
27
+ with_title: ":title | :site",
28
+ without_title: ":site | :tagline"
29
+ }.freeze
30
+
31
+ attr_reader :template_set
32
+
33
+ def default_template
34
+ HappyTitles::Template.new(**DEFAULT_TEMPLATE_OPTIONS)
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+ module HappyTitles
3
+ module Helpers
4
+ def title(title = nil)
5
+ if title
6
+ @happy_titles_page_title = title
7
+ else
8
+ @happy_titles_page_title
9
+ end
10
+ end
11
+
12
+ def page_title(key = nil)
13
+ content_tag(:title, render_happy_titles_template(key))
14
+ end
15
+
16
+ private
17
+
18
+ def render_happy_titles_template(key)
19
+ templete = key ? HappyTitles.config.template(key) : HappyTitles.config.template
20
+
21
+ templete.render(
22
+ title: @happy_titles_page_title,
23
+ site: HappyTitles.config.site,
24
+ tagline: HappyTitles.config.tagline
25
+ )
26
+ end
27
+ end
28
+ end
@@ -1,10 +1,11 @@
1
- require 'happy-titles'
2
- require 'rails'
1
+ # frozen_string_literal: true
2
+ require "happy-titles"
3
+ require "rails"
3
4
 
4
5
  module HappyTitles
5
6
  class Railtie < Rails::Railtie
6
- initializer 'happy-titles.initialize', :after => :after_initialize do
7
- ActionView::Base.send :include, HappyTitles
7
+ initializer "happy-titles.initialize" do
8
+ ActionView::Base.send :include, HappyTitles::Helpers
8
9
  end
9
10
  end
10
- end
11
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+ module HappyTitles
3
+ class Template
4
+ attr_reader :name
5
+
6
+ def initialize(name:, without_title:, with_title:)
7
+ @name = name.to_sym
8
+ @with_title = with_title
9
+ @without_title = without_title
10
+ end
11
+
12
+ def render(title:, tagline:, site:)
13
+ template = (title && with_title) ? with_title : without_title
14
+ substitute_placeholders(
15
+ template,
16
+ title: title || tagline,
17
+ tagline: tagline,
18
+ site: site
19
+ )
20
+ end
21
+
22
+ private
23
+
24
+ attr_reader :with_title, :without_title
25
+
26
+ def substitute_placeholders(template, options)
27
+ options.each do |key, value|
28
+ template = template.gsub(":#{key}", value.to_s)
29
+ end
30
+ template
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+ module HappyTitles
3
+ class TemplateSet
4
+ def initialize(*templates)
5
+ @templates = templates
6
+ end
7
+
8
+ def get(key)
9
+ find_template(key) || raise_template_not_found(key)
10
+ end
11
+
12
+ private
13
+
14
+ attr_accessor :templates
15
+
16
+ def method_missing(*args)
17
+ delete_template(args[0])
18
+ templates << HappyTitles::Template.new(
19
+ name: args[0],
20
+ without_title: args[1],
21
+ with_title: args[2]
22
+ )
23
+ end
24
+
25
+ def find_template(key)
26
+ templates.find do |template|
27
+ template.name == key.to_sym
28
+ end
29
+ end
30
+
31
+ def delete_template(key)
32
+ templates.reject! do |template|
33
+ template.name == key.to_sym
34
+ end
35
+ end
36
+
37
+ def raise_template_not_found(key)
38
+ raise(
39
+ HappyTitles::TemplateNotFound,
40
+ "A template called \"#{key}\" could not be found. Templates that exist are: #{template_names}"
41
+ )
42
+ end
43
+
44
+ def template_names
45
+ @templates.collect(&:name).join(", ")
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+ module HappyTitles
3
+ VERSION = "2.0.0"
4
+ end
data/spec/fake_app.rb ADDED
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+ module FakeApp
3
+ class Application < Rails::Application
4
+ config.secret_key_base = "test"
5
+ config.eager_load = false
6
+ end
7
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+ describe HappyTitles::Config do
3
+ subject { described_class.new }
4
+
5
+ describe "#site" do
6
+ it "returns the default" do
7
+ expect(subject.site).to eq("My site")
8
+ end
9
+
10
+ context "When the default has been changed" do
11
+ before { subject.site = "Custom site" }
12
+
13
+ it "returns the new value" do
14
+ expect(subject.site).to eq("Custom site")
15
+ end
16
+ end
17
+ end
18
+
19
+ describe "#tagline" do
20
+ it "returns the default" do
21
+ expect(subject.tagline).to eq("My short, descriptive and witty tagline")
22
+ end
23
+
24
+ context "When the default has been changed" do
25
+ before { subject.tagline = "Custom tagline" }
26
+
27
+ it "returns the new value" do
28
+ expect(subject.tagline).to eq("Custom tagline")
29
+ end
30
+ end
31
+ end
32
+
33
+ describe "#template" do
34
+ it "returns the default template" do
35
+ expect(subject.template.name).to eq(:default)
36
+ end
37
+
38
+ it "returns a template based on the key" do
39
+ expect(subject.template(:default).name).to eq(:default)
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+ describe HappyTitles do
3
+ subject { described_class }
4
+
5
+ describe ".config" do
6
+ it "returns a config object" do
7
+ expect(subject.config).to be_a(subject::Config)
8
+ end
9
+
10
+ it "always returns the same config object" do
11
+ expect(subject.config).to equal(subject.config)
12
+ end
13
+ end
14
+
15
+ describe ".configure" do
16
+ it "yields the config object" do
17
+ expect { |b| subject.configure(&b) }.to yield_with_args(subject.config)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+ describe "HappyTitle Helpers" do
3
+ let(:view) { ActionView::Base.new }
4
+ let(:page_title) { view.page_title }
5
+
6
+ before do
7
+ HappyTitles.configure do |config|
8
+ config.site = "Custom site"
9
+ config.tagline = "Custom tagline"
10
+ end
11
+ end
12
+
13
+ it "renders the page title" do
14
+ expect(page_title).to eq("<title>Custom site | Custom tagline</title>")
15
+ end
16
+
17
+ context "when the title is set" do
18
+ before do
19
+ view.title "Custom title"
20
+ end
21
+
22
+ it "returns the title" do
23
+ expect(view.title).to eq("Custom title")
24
+ end
25
+
26
+ it "renders the page title" do
27
+ expect(page_title).to eq("<title>Custom title | Custom site</title>")
28
+ end
29
+
30
+ context "setting the title again" do
31
+ before do
32
+ view.title "Another title"
33
+ end
34
+
35
+ it "should overwrite the previously set title" do
36
+ expect(view.title).to eq("Another title")
37
+ end
38
+ end
39
+ end
40
+
41
+ context "when the title contains special entities" do
42
+ before do
43
+ view.title "This & That"
44
+ end
45
+
46
+ it "should escape special entities" do
47
+ expect(page_title).to eq("<title>This &amp; That | Custom site</title>")
48
+ end
49
+ end
50
+
51
+ context "when there is a custom template" do
52
+ let(:page_title) { view.page_title(:custom) }
53
+
54
+ before do
55
+ HappyTitles.configure do |config|
56
+ config.templates do
57
+ custom "++ :site ++", "++ :site ++ :title ++"
58
+ end
59
+ end
60
+ end
61
+
62
+ it "renders the page title" do
63
+ expect(page_title).to eq("<title>++ Custom site ++</title>")
64
+ end
65
+
66
+ context "when the title is set" do
67
+ before do
68
+ view.title "Custom title"
69
+ end
70
+
71
+ it "renders the page title" do
72
+ expect(page_title).to eq("<title>++ Custom site ++ Custom title ++</title>")
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+ describe HappyTitles::TemplateSet do
3
+ subject do
4
+ described_class.new(template)
5
+ end
6
+
7
+ let(:template) { instance_double(HappyTitles::Template, name: :custom) }
8
+
9
+ describe "#get" do
10
+ it "gets the template" do
11
+ expect(subject.get(:custom)).to eq(template)
12
+ end
13
+
14
+ it "converts string arguments to a symbol" do
15
+ expect(subject.get("custom")).to eq(template)
16
+ end
17
+
18
+ it "raises an error if a template cannot be found" do
19
+ expect { subject.get(:unknown) }.to raise_error(
20
+ HappyTitles::TemplateNotFound,
21
+ 'A template called "unknown" could not be found. Templates that exist are: custom'
22
+ )
23
+ end
24
+ end
25
+
26
+ describe "Adding a new template" do
27
+ let(:new_template) { subject.get(:additional) }
28
+
29
+ before do
30
+ subject.additional("without_title", "with_title")
31
+ end
32
+
33
+ it "adds a template" do
34
+ expect(new_template).to be_a(HappyTitles::Template)
35
+ end
36
+
37
+ it "sets the template name" do
38
+ expect(new_template.name).to eq(:additional)
39
+ end
40
+ end
41
+
42
+ describe "Adding a template with only one format" do
43
+ let(:new_template) { subject.get(:single_format) }
44
+
45
+ before do
46
+ subject.single_format("without_title")
47
+ end
48
+
49
+ it "adds a template" do
50
+ expect(new_template).to be_a(HappyTitles::Template)
51
+ end
52
+ end
53
+
54
+ describe "Overwriting an existing template" do
55
+ before do
56
+ subject.custom("without_title", "with_title")
57
+ end
58
+
59
+ it "overwrites the old template" do
60
+ expect(subject.get(:custom)).not_to eq(template)
61
+ end
62
+ end
63
+ end