client_pages 0.0.1.alpha

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: dc3c627266b1e9187280a19b95fd613e73f08acc
4
+ data.tar.gz: 9c72b430526090a8c73866c6fef996b7e9b2e003
5
+ SHA512:
6
+ metadata.gz: e01fbb81395367d36f4217fa7221841e1881f6bedca4d0ebb9c3ebec09e3aa0687ea2f366bf5011ef429669fe72206abdcfdcea281f2101455d3a46fcd107a97
7
+ data.tar.gz: e471af6747143523d2c94fd5de271d981f16f4011dd1faff736b2028e8e6625414a3f43edfabfd88efa754b901cf68b47fb7321ca77238d83c39998b6d47bd47
data/.gitignore ADDED
@@ -0,0 +1,20 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ .rspec
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
19
+ .rvmrc
20
+ .rubocop.yml
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in client_pages.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Marco Schaden
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,150 @@
1
+ # ClientPages
2
+
3
+ ##### Todo:
4
+
5
+ - fallback option? => error handling if no such file?
6
+ - yaml content?
7
+ - builder#wrap needs conditional and multi wrap + nested wrap
8
+ - builder methoden vereinheitlichen
9
+ - builder defaults? (all :p will get class x)
10
+ - > maybe adjust ```render_content``` with additional parameter, like simple_form does
11
+ - > defaults: :table_settings => will be stored somewhere as a block
12
+ - test new configs! (.remote, .remote_content_path, .content_path, .caching, .fallback, .i18n)
13
+ - railtie
14
+ - i18n support content/de/something, content/en/something
15
+ - extract classes
16
+ - oauth dropbox?
17
+ - logger!?
18
+ - back up command/rake task, content:pull
19
+ nimmt alle local content files und überschreibt diese mit denen der remote version (wenn verfügbar)
20
+ - travis
21
+ - codeclimate
22
+
23
+ ---
24
+
25
+ # Ideas/Notes:
26
+
27
+ ---
28
+
29
+ with client_pages you can separate your content from html markup and css styles.
30
+
31
+ use it for small content parts of your app which need to be updated regulary by someone
32
+ or outsource all your content together, it's up to you.
33
+
34
+ **Ever heard "can we change the text on page x?"**
35
+
36
+ the main benefit of doing this: anybody can change the content, without the need for an admin backend and stuff like this.
37
+ just make it possible for them to edit the files.
38
+
39
+ from the beginning client pages was built for supporting remote files.
40
+ an easy example could be a public shared dropbox folder (or anything that can deliver files),
41
+
42
+ a sample configuration could look like this:
43
+ here we set ```bla = true``` to enable ...
44
+
45
+ btw, the core markdown parser is redcarpet and you can customize the behaviour
46
+ of it like you would normaly do by setting renderer and extensions through the config. (~ naaa, formulierung)
47
+
48
+ but the power of client_pages comes from its helper methods for rendering content
49
+
50
+ ### simple example
51
+
52
+ imaginge you have this markdown file:
53
+ **insert markdown here**
54
+
55
+ Let's say you want a class on each list item, and a data attribute on that link.
56
+ And maybe a 'active' class on any link, when it's the current path?
57
+ It would also be nice to wrap each paragraph in a container?
58
+
59
+ we can accomplish all that by just giving the ```render_content(:file)``` method a block
60
+ and tell the content builder to do that for you.
61
+ **insert haml here**
62
+
63
+ this way, you can add a lot of behaivour by leaving your markdown content just as content with raw structure,
64
+ and the main markup and styling stays in your views.
65
+
66
+ ### Installation and setup
67
+
68
+ Add this line to your application's Gemfile:
69
+
70
+ gem 'client_pages'
71
+
72
+ And then execute:
73
+
74
+ $ bundle
75
+
76
+ Or install it yourself as:
77
+
78
+ $ gem install client_pages
79
+
80
+ rails project?
81
+
82
+ add a content directory and your done, per default it's _content_
83
+ maybe you like to configure this to app/content or app/views/content
84
+ totaly up to you.
85
+
86
+ no framework? pure rack? sinatra?
87
+
88
+ for convenience you can add ``` include ClientPages::MarkdownContent ``` to your application controller/view_helper/presenter/... or something which is responsible for building html
89
+ so that you can call ```render_content``` there.
90
+
91
+ or if you're riding the real blank slate, just call ```ClientPages::MarkdownContent.render_content``` directly.
92
+
93
+ ### renderer
94
+ if you call ```render_content``` without a block it just renders the markdown to html
95
+
96
+ ```render_content(:index)```
97
+
98
+ ```render_content('posts/index')```
99
+
100
+ ### builder
101
+ - modify
102
+ - wrap
103
+ - switch?
104
+
105
+ ### matcher
106
+ - implicit attribute match
107
+ - explicit match
108
+ - content match? (hole file?)
109
+
110
+ ### config
111
+ config.ru file or initializer
112
+
113
+ - by default...
114
+ - content_path
115
+ - if you go the full remote path without fallback, you might consider to turn on caching.
116
+
117
+ ### i18n
118
+ per default client_pages looks in your content_path for /locale/...
119
+ - is the locale a config_setting?
120
+ - how to tell client_pages the locale?
121
+
122
+ hm, or where is the problem? ```render_content("#{my_locale}/posts/index")```
123
+
124
+ ### caching
125
+ the current implementation it the easiest way to do this.
126
+ it's really simple and lives as long as the process runs.
127
+ it can not be shared between processes
128
+ and because one of the [hard things in Computer Science](http://martinfowler.com/bliki/TwoHardThings.html) is _cache invalidation_
129
+ you can flush the cache also at runtime either complete or by passing a file_path (which is the cache key):
130
+
131
+ you can accomplish this with some additional code.
132
+
133
+ ```code follows```
134
+
135
+ or run the corresponding command. (not implemented yet)
136
+
137
+ ### commands
138
+ - downloader!!!
139
+ - cache killer?
140
+
141
+ ----
142
+
143
+ ## Contributing
144
+
145
+ + Fork it
146
+ + Change it
147
+ + Test it
148
+ + Commit it
149
+ + Push it
150
+ + Pull Request
data/Rakefile ADDED
@@ -0,0 +1,5 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+ task default: :spec
@@ -0,0 +1,34 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'client_pages/version'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = 'client_pages'
8
+ s.version = ClientPages::VERSION
9
+ s.authors = ['Marco Schaden']
10
+ s.email = ['ms@donschado.de']
11
+ s.summary = %q{With client_pages you can separate your content from html markup and css styles}
12
+ s.description = <<-EOF
13
+ With client_pages you can separate your content from html markup and css styles.
14
+ use it for small content parts of your app which need to be updated regulary by someone
15
+ or outsource all your content together, it's up to you.
16
+ EOF
17
+ s.homepage = ''
18
+ s.license = 'MIT'
19
+
20
+ s.files = `git ls-files`.split($/)
21
+ s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
22
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
23
+ s.require_paths = ['lib']
24
+
25
+ s.add_dependency 'redcarpet', '~> 3.1.1'
26
+
27
+ s.add_development_dependency 'bundler', '~> 1.5.3'
28
+ s.add_development_dependency 'rake', '~> 10.1.1'
29
+ s.add_development_dependency 'rspec', '~> 2.14.1'
30
+ s.add_development_dependency 'webmock', '~> 1.17.3'
31
+ s.add_development_dependency 'pry-plus', '~> 1.0.0'
32
+ s.add_development_dependency 'rubocop', '~> 0.18.1'
33
+ s.add_development_dependency 'simplecov', '~> 0.8.2'
34
+ end
@@ -0,0 +1,3 @@
1
+ module ClientPages
2
+ VERSION = '0.0.1.alpha'
3
+ end
@@ -0,0 +1,208 @@
1
+ # encoding: utf-8
2
+ require 'client_pages/version'
3
+ require 'open-uri'
4
+ require 'redcarpet'
5
+
6
+ module ClientPages
7
+ class << self
8
+ attr_accessor :configuration
9
+
10
+ def config
11
+ self.configuration ||= Configuration.new
12
+ block_given? ? yield(configuration) : configuration
13
+ end
14
+
15
+ def cache
16
+ @cache ||= {}
17
+ end
18
+
19
+ def clear_cache(key=nil)
20
+ if key
21
+ cache.delete(key)
22
+ "cache cleared: #{key}"
23
+ else
24
+ cache.clear
25
+ 'cache cleared'
26
+ end
27
+ end
28
+ end
29
+
30
+ module MarkdownContent
31
+ class Matcher
32
+ attr_accessor :tag, :line
33
+
34
+ def initialize(tag, line)
35
+ @tag, @line = tag, line
36
+ end
37
+
38
+ def exact_match?(attribute, match)
39
+ !!line.match(/<#{tag}[^>]*#{attribute}="#{match}"/i)
40
+ end
41
+
42
+ def attr?(attribute, match)
43
+ !!line.match(/#{attribute}="#{match}"/i)
44
+ end
45
+
46
+ def match?(pattern)
47
+ !!line.match(pattern)
48
+ end
49
+
50
+ def find(type)
51
+ pattern = { opening: /<#{tag}[^>]*>/, closing: /<\/#{tag}[^>]*>/ }[type]
52
+ if block_given? && !!line.match(pattern)
53
+ line.gsub(pattern) { |match| yield match }
54
+ else
55
+ line
56
+ end
57
+ end
58
+ end
59
+
60
+ class ContentBuilder
61
+ attr_accessor :html
62
+
63
+ def initialize(html)
64
+ @html = html
65
+ end
66
+
67
+ def modify(tag, options={}, conditions=true)
68
+ if conditions.respond_to? :call
69
+ html_lines do |line|
70
+ if conditions.call(Matcher.new(tag, line))
71
+ set_options_for_tags_per_line(options, tag, line)
72
+ else
73
+ line
74
+ end
75
+ end
76
+ elsif conditions.is_a?(Hash)
77
+ html_lines do |line|
78
+ if conditions.keys.all? { |key| Matcher.new(tag, line).exact_match?(key, conditions[key]) }
79
+ set_options_for_tags_per_line(options, tag, line)
80
+ else
81
+ line
82
+ end
83
+ end
84
+ elsif !!conditions
85
+ set_options_for_tags(options, tag)
86
+ end
87
+ self.html
88
+ end
89
+
90
+ def wrap(tag, options={})
91
+ html_lines do |line|
92
+ line = Matcher.new(tag, line).find(:opening) do |match|
93
+ "<#{options[:wrapper]} class=\"#{options[:class]}\">#{match}"
94
+ end
95
+ line = Matcher.new(tag, line).find(:closing) do |match|
96
+ "#{match}</#{options[:wrapper]}>"
97
+ end
98
+ end
99
+ end
100
+
101
+ def replace(tag, new_tag, options={})
102
+ html_lines do |line|
103
+ line = Matcher.new(tag, line).find(:opening) do |match|
104
+ "<#{new_tag} class=\"#{options[:class]}\">"
105
+ end
106
+ line = Matcher.new(tag, line).find(:closing) do |match|
107
+ "</#{new_tag}>"
108
+ end
109
+ end
110
+ end # ContentBuilder
111
+
112
+ private
113
+
114
+ def html_lines(&block)
115
+ self.html = html.lines.map { |line| yield line }.join
116
+ end
117
+
118
+ def set_options_for_tags(options, tag)
119
+ html_lines { |line| set_options_for_tags_per_line(options, tag, line) }
120
+ end
121
+
122
+ def set_options_for_tags_per_line(options, tag, line)
123
+ options.each { |k, v| line = line.gsub(/<#{tag}/, "<#{tag} #{k}=\"#{v}\"") }
124
+ line
125
+ end
126
+ end
127
+
128
+ def render_content(file, options = markdown_extensions)
129
+ html = Redcarpet::Markdown.new(html_renderer, options).render(markdown(file))
130
+ if block_given?
131
+ yield(ContentBuilder.new(html))
132
+ else
133
+ html.strip
134
+ end
135
+ rescue OpenURI::HTTPError
136
+ "404: could not find '#{file}'"
137
+ rescue SocketError
138
+ 'Error: content_path not available'
139
+ end
140
+
141
+ private
142
+
143
+ def html_renderer
144
+ Redcarpet::Render::HTML.new(config.render_options)
145
+ end
146
+
147
+ def markdown_extensions
148
+ config.markdown_extensions
149
+ end
150
+
151
+ def markdown(file)
152
+ url = "#{content_path}/#{file}.md"
153
+ if caching?
154
+ cache.fetch(url) { cache[url] = open(url).read }
155
+ else
156
+ open(url).read
157
+ end
158
+ end
159
+
160
+ def config
161
+ ClientPages.config
162
+ end
163
+
164
+ def cache
165
+ ClientPages.cache
166
+ end
167
+
168
+ def caching?
169
+ config.caching
170
+ end
171
+
172
+ def remote?
173
+ config.remote
174
+ end
175
+
176
+ def content_path
177
+ remote? ? config.remote_content_path : config.content_path
178
+ end
179
+ end
180
+
181
+ class Configuration
182
+ attr_accessor :content_path, :remote, :remote_content_path, :caching, :fallback, :i18n
183
+ attr_reader :render_options, :markdown_extensions
184
+
185
+ def initialize
186
+ @content_path = 'content'
187
+ @render_options = {}
188
+ @markdown_extensions = {}
189
+ end
190
+
191
+ def render_options=(options)
192
+ @render_options.merge!(options)
193
+ end
194
+
195
+ def markdown_extensions=(options)
196
+ @markdown_extensions.merge!(options)
197
+ end
198
+
199
+ def to_hash
200
+ # TODO: instance vars get
201
+ {
202
+ content_path: content_path,
203
+ render_options: render_options,
204
+ markdown_extensions: markdown_extensions
205
+ }
206
+ end
207
+ end
208
+ end
@@ -0,0 +1,3 @@
1
+ + [link1](/link1)
2
+ + [link2](/link2)
3
+ + [link3](/link3 "i haz title")
@@ -0,0 +1,5 @@
1
+ # Content from [somewhere](http://somewhere.com)
2
+
3
+ Lorem do *incididunt* ut labore
4
+
5
+ Pariatur: [Foo](/bar.com "baz") culpa
@@ -0,0 +1,2 @@
1
+ + Foo _Bar_
2
+ + Baz
@@ -0,0 +1,30 @@
1
+ require 'simplecov'
2
+ SimpleCov.start do
3
+ add_filter '/spec/'
4
+ end
5
+
6
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
7
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
8
+ require 'client_pages'
9
+
10
+ require 'webmock/rspec'
11
+
12
+ RSpec.configure do |config|
13
+ config.treat_symbols_as_metadata_keys_with_true_values = true
14
+ config.run_all_when_everything_filtered = true
15
+ config.filter_run :focus
16
+ config.order = 'random' # --seed 1234
17
+
18
+ config.expect_with :rspec do |c|
19
+ c.syntax = :expect
20
+ end
21
+
22
+ config.mock_with :rspec do |c|
23
+ c.syntax = :expect
24
+ end
25
+ end
26
+
27
+ # helper for markdown fixture files
28
+ def fixture(name)
29
+ File.open(File.expand_path("spec/fixtures/#{name}.md"), 'r')
30
+ end
@@ -0,0 +1,199 @@
1
+ require 'spec_helper'
2
+
3
+ module ClientPages
4
+ describe MarkdownContent do
5
+ describe 'Renderer' do
6
+ subject { Class.send(:include, ClientPages::MarkdownContent).new }
7
+ let(:markdown) { fixture('test_content') }
8
+ let(:content) { subject.render_content(:test_content) }
9
+
10
+ before do
11
+ ClientPages.config do |c|
12
+ c.remote = true
13
+ c.caching = false
14
+ c.remote_content_path = 'http://somewhere.com'
15
+ end
16
+ stub_request(:get, 'http://somewhere.com/test_content.md').
17
+ to_return(body: markdown, status: 200)
18
+ end
19
+
20
+ it 'renders HTML content for given markdown file from somewhere' do
21
+ expect(content).to include('<h1>Content from <a href="http://somewhere.com">somewhere</a></h1>')
22
+ end
23
+
24
+ context 'with a block' do
25
+ let(:link_list) { fixture('link_list') }
26
+ let(:text_list) { fixture('text_list') }
27
+ before do
28
+ stub_request(:get, 'http://somewhere.com/link_list.md').to_return(body: link_list, status: 200)
29
+ stub_request(:get, 'http://somewhere.com/text_list.md').to_return(body: text_list, status: 200)
30
+ end
31
+
32
+ it 'returns a content builder' do
33
+ expect(
34
+ subject.render_content(:test_content) { |c| c }
35
+ ).to be_kind_of(MarkdownContent::ContentBuilder)
36
+ end
37
+
38
+ it 'modifies tags and html attributes' do
39
+ expect(
40
+ subject.render_content(:test_content) do |c|
41
+ c.modify :h1, class: 'mycss_class', 'data-foo' => 'bar'
42
+ c.modify :a, class: 'fancy', title: 'woah'
43
+ end
44
+ ).to include('<h1 data-foo="bar" class="mycss_class">Content from <a title="woah" class="fancy" href="http://somewhere.com">somewhere</a></h1>')
45
+ end
46
+
47
+ it 'adds css classes conditionally' do
48
+ expect(
49
+ subject.render_content(:test_content) do |c|
50
+ c.modify :h1, { class: 'add_me cool' }, true
51
+ c.modify :a, { class: 'add_me_not' }, false
52
+ end
53
+ ).to include('<h1 class="add_me cool">Content from <a href="http://somewhere.com">somewhere</a></h1>')
54
+ end
55
+
56
+ it 'adds any attribute conditionally and selective' do
57
+ expect(
58
+ subject.render_content(:link_list) do |c|
59
+ c.modify :li, { class: 'yay' }, ->(m) { m.attr?(:href, '/link1') }
60
+ c.modify :a, { class: 'active' }, href: '/link2'
61
+ c.modify :a, { class: 'important' }, title: 'i haz title'
62
+ end
63
+ ).to include("<li class=\"yay\"><a href=\"/link1\">link1</a></li>\n<li><a class=\"active\" href=\"/link2\">link2</a></li>\n<li><a class=\"important\" href=\"/link3\" title=\"i haz title\">link3</a></li>")
64
+ end
65
+
66
+ it 'wraps multiple tags with container' do
67
+ expect(
68
+ subject.render_content(:text_list) do |c|
69
+ c.wrap :li, wrapper: :span, class: 'wrapper'
70
+ c.wrap :em, wrapper: :span, class: 'special'
71
+ end
72
+ ).to eql("<ul>\n<span class=\"wrapper\"><li>Foo <span class=\"special\"><em>Bar</em></span></li></span>\n<span class=\"wrapper\"><li>Baz</li></span>\n</ul>\n")
73
+ end
74
+
75
+ it 'wraps and modifies tags' do
76
+ expect(
77
+ subject.render_content(:text_list) do |c|
78
+ c.wrap :ul, wrapper: :div, class: 'container'
79
+ c.modify :em, style: 'color: #c0ffee'
80
+ end
81
+ ).to eql("<div class=\"container\"><ul>\n<li>Foo <em style=\"color: #c0ffee\">Bar</em></li>\n<li>Baz</li>\n</ul></div>\n")
82
+ end
83
+
84
+ it 'replaces tags and adds class' do
85
+ expect(
86
+ subject.render_content(:test_content) do |c|
87
+ c.replace :p, :div, class: 'byebye'
88
+ c.replace :em, :span, class: 'cooler'
89
+ end
90
+ ).to eql("<h1>Content from <a href=\"http://somewhere.com\">somewhere</a></h1>\n\n<div class=\"byebye\">Lorem do <span class=\"cooler\">incididunt</span> ut labore</div>\n\n<div class=\"byebye\">Pariatur: <a href=\"/bar.com\" title=\"baz\">Foo</a> culpa</div>\n")
91
+ end
92
+ end
93
+
94
+ describe "caching" do
95
+ before do
96
+ ClientPages.config do |c|
97
+ c.caching = true
98
+ c.remote = true
99
+ c.remote_content_path = "http://c.ly"
100
+ end
101
+ end
102
+ after { ClientPages.config { |c| c.caching = false } }
103
+ before(:each) { ClientPages.clear_cache }
104
+
105
+ it 'populates cache when empty' do
106
+ request = stub_request(:get, %r[/caching.md]).to_return(body: '**cache me**')
107
+ expect { subject.render_content(:caching) }.to change { ClientPages.cache }.to eql({"http://c.ly/caching.md"=>"**cache me**"})
108
+ expect(request).to have_been_made.times(1)
109
+ end
110
+
111
+ it 'makes request only once' do
112
+ request = stub_request(:get, %r[/caching.md]).to_return(body: '**cache me**')
113
+ 5.times { subject.render_content(:caching) }
114
+ expect { subject.render_content(:caching) }.to_not change { ClientPages.cache }
115
+ expect(request).to have_been_made.times(1)
116
+ end
117
+
118
+ context 'disabled' do
119
+ before do
120
+ ClientPages.config do |c|
121
+ c.caching = false
122
+ c.remote = true
123
+ c.remote_content_path = "http://c.ly"
124
+ end
125
+ end
126
+
127
+ it 'will not cache' do
128
+ stub_request(:get, %r[/no_caching.md]).to_return(body: '_u_no_cache_me_')
129
+ subject.render_content(:no_caching)
130
+ expect(ClientPages.cache).to be_empty
131
+ end
132
+
133
+ it 'makes a request per render_content call' do
134
+ request = stub_request(:get, %r[/no_caching.md]).to_return(body: '_u_no_cache_me_')
135
+ 5.times { subject.render_content(:no_caching) }
136
+ expect(request).to have_been_made.times(5)
137
+ end
138
+ end
139
+ end
140
+ end
141
+
142
+ describe 'configuration' do
143
+ subject { ClientPages }
144
+ before { subject.configuration = nil }
145
+
146
+ it 'has default config' do
147
+ config = {
148
+ content_path: 'content',
149
+ render_options: {},
150
+ markdown_extensions: {}
151
+ }
152
+ expect(subject.config.to_hash).to eql(config)
153
+ end
154
+
155
+ it 'is configurable' do
156
+ config = {
157
+ content_path: 'somewhere',
158
+ render_options: { foo: "bar" },
159
+ markdown_extensions: { bam: true }
160
+ }
161
+ expect {
162
+ subject.config do |c|
163
+ c.content_path = 'somewhere'
164
+ c.render_options = { foo: 'bar' }
165
+ c.markdown_extensions = { bam: true }
166
+ end
167
+ }.to change {
168
+ subject.config.to_hash
169
+ }.to eql(config)
170
+ end
171
+
172
+ describe 'overwritable config' do
173
+ before do
174
+ subject.config do |c|
175
+ c.render_options = { opt1: true }
176
+ c.markdown_extensions = { ext1: true }
177
+ end
178
+ end
179
+
180
+ it 'overwrites config and keeps untouched config settings' do
181
+ config = {
182
+ content_path: 'here',
183
+ render_options: { opt1: false, opt2: true },
184
+ markdown_extensions: { ext1: true, ext2: false }
185
+ }
186
+ expect {
187
+ subject.config do |c|
188
+ c.content_path = 'here'
189
+ c.render_options = { opt1: false, opt2: true }
190
+ c.markdown_extensions = { ext2: false }
191
+ end
192
+ }.to change {
193
+ subject.config.to_hash
194
+ }.to eql(config)
195
+ end
196
+ end
197
+ end
198
+ end
199
+ end
metadata ADDED
@@ -0,0 +1,179 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: client_pages
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1.alpha
5
+ platform: ruby
6
+ authors:
7
+ - Marco Schaden
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-02-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: redcarpet
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: 3.1.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 3.1.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: 1.5.3
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: 1.5.3
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: 10.1.1
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 10.1.1
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 2.14.1
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: 2.14.1
69
+ - !ruby/object:Gem::Dependency
70
+ name: webmock
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: 1.17.3
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: 1.17.3
83
+ - !ruby/object:Gem::Dependency
84
+ name: pry-plus
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ version: 1.0.0
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ~>
95
+ - !ruby/object:Gem::Version
96
+ version: 1.0.0
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ~>
102
+ - !ruby/object:Gem::Version
103
+ version: 0.18.1
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ~>
109
+ - !ruby/object:Gem::Version
110
+ version: 0.18.1
111
+ - !ruby/object:Gem::Dependency
112
+ name: simplecov
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ~>
116
+ - !ruby/object:Gem::Version
117
+ version: 0.8.2
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ~>
123
+ - !ruby/object:Gem::Version
124
+ version: 0.8.2
125
+ description: |2
126
+ With client_pages you can separate your content from html markup and css styles.
127
+ use it for small content parts of your app which need to be updated regulary by someone
128
+ or outsource all your content together, it's up to you.
129
+ email:
130
+ - ms@donschado.de
131
+ executables: []
132
+ extensions: []
133
+ extra_rdoc_files: []
134
+ files:
135
+ - .gitignore
136
+ - Gemfile
137
+ - LICENSE.txt
138
+ - README.md
139
+ - Rakefile
140
+ - client_pages.gemspec
141
+ - lib/client_pages.rb
142
+ - lib/client_pages/version.rb
143
+ - spec/fixtures/link_list.md
144
+ - spec/fixtures/test_content.md
145
+ - spec/fixtures/text_list.md
146
+ - spec/spec_helper.rb
147
+ - spec/unit/client_pages_spec.rb
148
+ homepage: ''
149
+ licenses:
150
+ - MIT
151
+ metadata: {}
152
+ post_install_message:
153
+ rdoc_options: []
154
+ require_paths:
155
+ - lib
156
+ required_ruby_version: !ruby/object:Gem::Requirement
157
+ requirements:
158
+ - - '>='
159
+ - !ruby/object:Gem::Version
160
+ version: '0'
161
+ required_rubygems_version: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - '>'
164
+ - !ruby/object:Gem::Version
165
+ version: 1.3.1
166
+ requirements: []
167
+ rubyforge_project:
168
+ rubygems_version: 2.1.11
169
+ signing_key:
170
+ specification_version: 4
171
+ summary: With client_pages you can separate your content from html markup and css
172
+ styles
173
+ test_files:
174
+ - spec/fixtures/link_list.md
175
+ - spec/fixtures/test_content.md
176
+ - spec/fixtures/text_list.md
177
+ - spec/spec_helper.rb
178
+ - spec/unit/client_pages_spec.rb
179
+ has_rdoc: