hologram 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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +0 -1
  3. data/CHANGELOG.md +37 -0
  4. data/README.md +243 -5
  5. data/hologram.gemspec +2 -0
  6. data/lib/hologram.rb +2 -0
  7. data/lib/hologram/block_code_renderer.rb +45 -0
  8. data/lib/hologram/code_example_renderer.rb +73 -0
  9. data/lib/hologram/code_example_renderer/example.rb +27 -0
  10. data/lib/hologram/code_example_renderer/factory.rb +60 -0
  11. data/lib/hologram/code_example_renderer/renderers/haml_renderer.rb +17 -0
  12. data/lib/hologram/code_example_renderer/renderers/html_renderer.rb +6 -0
  13. data/lib/hologram/code_example_renderer/renderers/js_renderer.rb +5 -0
  14. data/lib/hologram/code_example_renderer/renderers/jsx_renderer.rb +4 -0
  15. data/lib/hologram/code_example_renderer/renderers/react_renderer.rb +21 -0
  16. data/lib/hologram/code_example_renderer/renderers/slim_renderer.rb +16 -0
  17. data/lib/hologram/code_example_renderer/template.rb +33 -0
  18. data/lib/hologram/display_message.rb +13 -0
  19. data/lib/hologram/doc_block_collection.rb +5 -1
  20. data/lib/hologram/doc_builder.rb +58 -7
  21. data/lib/hologram/doc_parser.rb +20 -4
  22. data/lib/hologram/document_block.rb +22 -4
  23. data/lib/hologram/link_helper.rb +18 -0
  24. data/lib/hologram/markdown_renderer.rb +56 -35
  25. data/lib/hologram/version.rb +1 -1
  26. data/lib/template/code_example_templates/js_example_template.html.erb +7 -0
  27. data/lib/template/code_example_templates/jsx_example_template.html.erb +7 -0
  28. data/lib/template/code_example_templates/markup_example_template.html.erb +10 -0
  29. data/lib/template/code_example_templates/markup_table_template.html.erb +23 -0
  30. data/lib/template/hologram_config.yml +23 -0
  31. data/spec/block_code_renderer_spec.rb +279 -0
  32. data/spec/code_example_renderer/example_spec.rb +26 -0
  33. data/spec/code_example_renderer/factory_spec.rb +102 -0
  34. data/spec/code_example_renderer/template_spec.rb +50 -0
  35. data/spec/display_message_spec.rb +18 -0
  36. data/spec/doc_block_collection_spec.rb +26 -1
  37. data/spec/doc_builder_spec.rb +28 -5
  38. data/spec/doc_parser_spec.rb +67 -7
  39. data/spec/document_block_spec.rb +33 -2
  40. data/spec/fixtures/source/components/button/buttons.css +8 -6
  41. data/spec/fixtures/source/components/button/skin/buttonSkins.css +17 -0
  42. data/spec/fixtures/styleguide/base_css.html +176 -52
  43. data/spec/fixtures/styleguide/index.html +6 -14
  44. data/spec/link_helper_spec.rb +57 -0
  45. data/spec/markdown_renderer_spec.rb +82 -0
  46. metadata +75 -19
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe Hologram::CodeExampleRenderer::Example do
4
+ let(:code) { 'goto 12' }
5
+ let(:example) { described_class.new(code) }
6
+
7
+ describe '#rendered_example' do
8
+ subject { example.rendered_example }
9
+ it { is_expected.to eq 'goto 12' }
10
+ end
11
+
12
+ describe '#code_example' do
13
+ let(:formatter) { double(:formatter) }
14
+ let(:lexer) { double(:lexer, lex: 'lexed_code') }
15
+
16
+ before do
17
+ allow(Rouge::Lexer).to receive(:find_fancy).with('guess', code) { lexer }
18
+ allow(Rouge::Formatters::HTML).to receive(:new) { formatter }
19
+ allow(formatter).to receive(:format).with('lexed_code') { 'formatted_lexed_code' }
20
+ end
21
+
22
+ subject { example.code_example }
23
+
24
+ it { is_expected.to eq 'formatted_lexed_code' }
25
+ end
26
+ end
@@ -0,0 +1,102 @@
1
+ require 'spec_helper'
2
+
3
+ Hologram::CodeExampleRenderer.load_renderers_and_templates
4
+
5
+ describe Hologram::CodeExampleRenderer::Factory do
6
+ describe '.define' do
7
+ let(:example_type) { 'foobar' }
8
+
9
+ before do
10
+ allow(Hologram::CodeExampleRenderer::Template).to receive(:new).with('custom_example_template') { double(template: 'the full custom example template') }
11
+ allow(Hologram::CodeExampleRenderer::Template).to receive(:new).with('custom_table_template') { double(template: 'the full custom table template') }
12
+ allow(Hologram::CodeExampleRenderer::Template).to receive(:new).with(nil).and_call_original
13
+ end
14
+
15
+ context "when a renderer is registered with all of the options" do
16
+ before do
17
+ custom_lexer = double(:lexer, lex: 'lexed code from supplied lexer')
18
+
19
+ Hologram::CodeExampleRenderer::Factory.define(example_type) do
20
+ example_template 'custom_example_template'
21
+ table_template 'custom_table_template'
22
+ lexer { custom_lexer }
23
+ rendered_example { |code| "special rendering for #{code}" }
24
+ end
25
+ end
26
+
27
+ after { Hologram::CodeExampleRenderer.unregister(example_type) }
28
+
29
+ describe "the registered example class" do
30
+ let(:example_class) { Hologram::CodeExampleRenderer.example_class_for(example_type) }
31
+ let(:example) { example_class.new('some code') }
32
+
33
+ it "renders the example using the block supplied to the factory" do
34
+ expect(example.rendered_example).to eq "special rendering for some code"
35
+ end
36
+
37
+ it "formats the code uses the supplied lexer" do
38
+ formatter = double(:formatter)
39
+ allow(Rouge::Formatters::HTML).to receive(:new) { formatter }
40
+
41
+ expect(formatter).to receive(:format).with('lexed code from supplied lexer') { 'formatted code' }
42
+ example.code_example
43
+ end
44
+ end
45
+
46
+ describe "the registered templates" do
47
+ let(:example_template) { Hologram::CodeExampleRenderer.example_template_for(example_type) }
48
+ let(:table_template) { Hologram::CodeExampleRenderer.table_template_for(example_type) }
49
+
50
+ it "uses the supplied example template" do
51
+ expect(example_template).to eq 'the full custom example template'
52
+ end
53
+
54
+ it "uses the supplied table template" do
55
+ expect(table_template).to eq 'the full custom table template'
56
+ end
57
+ end
58
+ end
59
+
60
+ context "when a renderer is registered with only some of the options" do
61
+ before do
62
+
63
+ Hologram::CodeExampleRenderer::Factory.define(example_type) do
64
+ example_template 'custom_example_template'
65
+ end
66
+ end
67
+
68
+ after { Hologram::CodeExampleRenderer.unregister(example_type) }
69
+
70
+ describe "the registered example class" do
71
+ let(:example_class) { Hologram::CodeExampleRenderer.example_class_for(example_type) }
72
+ let(:example) { example_class.new('some code') }
73
+
74
+ it "renders the example as is" do
75
+ expect(example.rendered_example).to eq "some code"
76
+ end
77
+
78
+ it "formats the code uses the default lexer" do
79
+ formatter = double(:formatter)
80
+ allow(Rouge::Lexer).to receive(:find_fancy).with('guess', 'some code') { double(lex: 'default lexed code') }
81
+ allow(Rouge::Formatters::HTML).to receive(:new) { formatter }
82
+
83
+ expect(formatter).to receive(:format).with('default lexed code') { 'formatted code' }
84
+ example.code_example
85
+ end
86
+ end
87
+
88
+ describe "the registered templates" do
89
+ let(:example_template) { Hologram::CodeExampleRenderer.example_template_for(example_type) }
90
+ let(:table_template) { Hologram::CodeExampleRenderer.table_template_for(example_type) }
91
+
92
+ it "uses the supplied example template" do
93
+ expect(example_template).to eq 'the full custom example template'
94
+ end
95
+
96
+ it "does not have a table template" do
97
+ expect(table_template).to be_nil
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+
3
+ describe Hologram::CodeExampleRenderer::Template do
4
+ describe '#template' do
5
+ subject { described_class.new(template_name).template }
6
+
7
+ context 'when template_name is nil' do
8
+ let(:template_name) { nil }
9
+ it { is_expected.to be_nil }
10
+ end
11
+
12
+ context 'when template_name is not nil' do
13
+ let(:template_name) { 'bar' }
14
+
15
+ let(:custom_template_filename) { 'custom/bar.html.erb' }
16
+ let(:default_template_filename) { 'cwd/../../template/code_example_templates/bar.html.erb' }
17
+
18
+ before do
19
+ allow(File).to receive(:dirname) { 'cwd/' }
20
+ allow(File).to receive(:read).with(custom_template_filename) { 'custom template' }
21
+ allow(File).to receive(:read).with(default_template_filename) { 'default template' }
22
+ end
23
+
24
+ context 'when path_to_custom_example_templates is defined' do
25
+ before do
26
+ described_class.path_to_custom_example_templates = 'custom/'
27
+ allow(File).to receive(:file?).with(custom_template_filename) { has_custom_template? }
28
+ end
29
+
30
+ after do
31
+ described_class.path_to_custom_example_templates = nil
32
+ end
33
+
34
+ context 'when a custom template exists' do
35
+ let(:has_custom_template?) { true }
36
+ it { is_expected.to eq 'custom template' }
37
+ end
38
+
39
+ context 'when a custom template does not exist' do
40
+ let(:has_custom_template?) { false }
41
+ it { is_expected.to eq 'default template' }
42
+ end
43
+ end
44
+
45
+ context 'when a path_to_custom_example_templates is not defined' do
46
+ it { is_expected.to eq 'default template' }
47
+ end
48
+ end
49
+ end
50
+ end
@@ -60,10 +60,28 @@ describe Hologram::DisplayMessage do
60
60
  end
61
61
 
62
62
  context '.warning' do
63
+ around do |example|
64
+ display.quiet!
65
+ example.run
66
+ display.show!
67
+ end
68
+
63
69
  it 'displays a warning message in yellow' do
64
70
  expect(display).to receive(:puts).with("\e[33mWarning: foo\e[0m")
65
71
  display.warning('foo')
66
72
  end
73
+
74
+ context 'when .exit_on_warnings! has been called' do
75
+ around do |example|
76
+ display.exit_on_warnings!
77
+ example.run
78
+ display.continue_on_warnings!
79
+ end
80
+
81
+ it 'exits' do
82
+ expect{ display.warning('foo') }.to raise_error SystemExit
83
+ end
84
+ end
67
85
  end
68
86
 
69
87
  context '.colorize' do
@@ -2,7 +2,7 @@ require 'spec_helper'
2
2
 
3
3
  describe Hologram::DocBlockCollection do
4
4
  let(:comment) do
5
- comment = <<comment
5
+ <<-comment
6
6
  /*doc
7
7
  ---
8
8
  title: Buttons
@@ -49,6 +49,31 @@ comment
49
49
  expect(collection.doc_blocks.size).to eql 0
50
50
  end
51
51
  end
52
+
53
+ context 'when the block has the same name as another block in the collection' do
54
+ let(:duplicate_comment) do
55
+ <<-comment
56
+ /*doc
57
+ ---
58
+ title: Imposter Buttons
59
+ name: button
60
+ category: Base CSS
61
+ ---
62
+
63
+ Same old stuff
64
+ */
65
+ comment
66
+ end
67
+
68
+ before do
69
+ collection.add_doc_block(comment, 'fake_file.sass')
70
+ end
71
+
72
+ it 'displays a warning' do
73
+ expect(Hologram::DisplayMessage).to receive(:warning)
74
+ collection.add_doc_block(duplicate_comment, 'fake_file.sass')
75
+ end
76
+ end
52
77
  end
53
78
 
54
79
  context '#create_nested_structure' do
@@ -131,6 +131,32 @@ describe Hologram::DocBuilder do
131
131
  end
132
132
  end
133
133
 
134
+ context '#initialize' do
135
+ subject { Hologram::DocBuilder.new(config) }
136
+
137
+ context 'when the "exit_on_warnings" option is passed in as true' do
138
+ let(:config) do
139
+ { 'exit_on_warnings' => true }
140
+ end
141
+
142
+ it 'calls DisplayMessage.exit_on_warnings!' do
143
+ expect(Hologram::DisplayMessage).to receive(:exit_on_warnings!)
144
+ subject
145
+ end
146
+ end
147
+
148
+ context 'when the "exit_on_warnings" option is not passed in' do
149
+ let(:config) do
150
+ { }
151
+ end
152
+
153
+ it 'does not call DisplayMessage.exit_on_warnings!' do
154
+ expect(Hologram::DisplayMessage).not_to receive(:exit_on_warnings!)
155
+ subject
156
+ end
157
+ end
158
+ end
159
+
134
160
  context '#is_valid?' do
135
161
 
136
162
  let(:config) do
@@ -204,8 +230,6 @@ describe Hologram::DocBuilder do
204
230
  end
205
231
 
206
232
  context '#build' do
207
- let(:style_files) { Dir[File.expand_path('../fixtures/styleguide/**/*.*', __FILE__)] }
208
- let(:processed_files) { Dir[File.join(builder.destination, '.', '**/*.*')] }
209
233
  let(:config_path) { File.join(Dir.pwd, 'spec/fixtures/source/config.yml') }
210
234
  let(:config_copy_path) { File.join(Dir.pwd, 'spec/fixtures/source/config.yml.copy') }
211
235
  let(:builder) { Hologram::DocBuilder.from_yaml(config_copy_path) }
@@ -226,9 +250,8 @@ describe Hologram::DocBuilder do
226
250
 
227
251
  it 'builds a styleguide' do
228
252
  builder.build
229
- style_files.each_with_index do |file, index|
230
- expect(FileUtils.cmp(file, processed_files[index])).to be_truthy
231
- end
253
+ expect(File.read(File.expand_path('../fixtures/styleguide/base_css.html', __FILE__))).to eq File.read(File.join(builder.destination, '.', 'base_css.html'))
254
+ expect(File.read(File.expand_path('../fixtures/styleguide/index.html', __FILE__))).to eq File.read(File.join(builder.destination, '.', 'index.html'))
232
255
  end
233
256
  end
234
257
  end
@@ -15,6 +15,19 @@ Markdown stuff
15
15
  eos
16
16
  end
17
17
 
18
+ let(:docs_child) do
19
+ <<-eos
20
+ /*doc
21
+ ---
22
+ parent: otherStyle
23
+ title: Other Style Child
24
+ name: otherStyleChild
25
+ ---
26
+ Markdown stuff
27
+ */
28
+ eos
29
+ end
30
+
18
31
  let(:child_doc) do
19
32
  <<-eos
20
33
  /*doc
@@ -28,6 +41,19 @@ Markdown stuff
28
41
  eos
29
42
  end
30
43
 
44
+ let(:grandchild_doc) do
45
+ <<-eos
46
+ /*doc
47
+ ---
48
+ parent: otherStyle
49
+ name: grandbaby
50
+ title: Grandbaby
51
+ ---
52
+ Markdown stuff
53
+ */
54
+ eos
55
+ end
56
+
31
57
  let(:multi_category_child_doc) do
32
58
  <<-eos
33
59
  /*doc
@@ -77,10 +103,10 @@ multi-parent
77
103
  expect(output_files_by_category).to be_a Hash
78
104
  end
79
105
 
80
- context "when the source has multiple paths" do
106
+ context 'when the source has multiple paths' do
81
107
  subject(:parser) { Hologram::DocParser.new(['spec/fixtures/source/colors', 'spec/fixtures/source/components'], nil, plugins) }
82
108
 
83
- it "parses all sources" do
109
+ it 'parses all sources' do
84
110
  expect(pages['base_css.html'][:md]).to include 'Base colors'
85
111
  expect(pages['base_css.html'][:md]).to include 'Background Colors'
86
112
  end
@@ -123,6 +149,30 @@ multi-parent
123
149
  it 'takes the category in a collection and treats them as the page names' do
124
150
  expect(pages.keys).to include 'foo.html'
125
151
  end
152
+
153
+ context 'when nav_level is set to section' do
154
+ before do
155
+ File.open(temp_doc, 'a+'){ |io| io << docs_child }
156
+ parser.nav_level = 'section'
157
+ end
158
+
159
+ it 'generates navigation to children from their parent' do
160
+ parser.parse
161
+ expect(pages['foo.html'][:md]).to include '<li><a href="#otherStyleChild">Other Style Child</a></li>'
162
+ end
163
+ end
164
+
165
+ context 'when nav_level is not set' do
166
+ before do
167
+ File.open(temp_doc, 'a+'){ |io| io << docs_child }
168
+ parser.nav_level = nil
169
+ end
170
+
171
+ it 'should not generate sub navigation' do
172
+ parser.parse
173
+ expect(pages['foo.html'][:md]).not_to include '<li><a href="#otherStyleChild">Other Style Child</a></li>'
174
+ end
175
+ end
126
176
  end
127
177
 
128
178
  context 'when a source doc is a child' do
@@ -132,16 +182,26 @@ multi-parent
132
182
  FileUtils.rm(temp_doc)
133
183
  end
134
184
 
135
- before do
136
- parser.parse
137
- end
138
-
139
185
  it 'appends the child doc to the category page' do
186
+ parser.parse
140
187
  expect(pages['base_css.html'][:md]).to include 'Some other style'
141
188
  end
142
189
 
143
190
  it 'assigns the child doc a deeper header' do
144
- expect(pages['base_css.html'][:md]).to include '<h2 id="otherStyle">Some other style</h2>'
191
+ parser.parse
192
+ expect(pages['base_css.html'][:md]).to include '<h2 id="otherStyle" class="styleguide">Some other style</h2>'
193
+ end
194
+
195
+ context 'when nav_level is set to all' do
196
+ before do
197
+ File.open(temp_doc, 'a+'){ |io| io << grandchild_doc }
198
+ parser.nav_level = 'all'
199
+ end
200
+
201
+ it 'generates navigation to grandchildren from their parent' do
202
+ parser.parse
203
+ expect(pages['base_css.html'][:md]).to include '<li><a href="#grandbaby">Grandbaby</a></li>'
204
+ end
145
205
  end
146
206
  end
147
207
 
@@ -116,8 +116,39 @@ eos
116
116
  end
117
117
 
118
118
  context '#markdown_with_heading' do
119
- it 'returns markdown with a specified header' do
120
- expect(doc_block.markdown_with_heading(2)).to eql "\n\n<h2 id=\"foo\">baz</h2>blah"
119
+ context 'when include_sub_nav is false' do
120
+ it 'returns markdown with a specified header' do
121
+ expect(doc_block.markdown_with_heading(2)).to eql "\n\n<h2 id=\"foo\" class=\"styleguide\">baz</h2>blah"
122
+ end
123
+ end
124
+
125
+ context 'when include_sub_nav is true' do
126
+ context 'when the component has no children' do
127
+ it 'returns markdown with no nav' do
128
+ expect(doc_block.markdown_with_heading(2, include_sub_nav: true)).to eql "\n\n<h2 id=\"foo\" class=\"styleguide\">baz</h2>blah"
129
+ end
130
+ end
131
+
132
+ context 'when the component has children' do
133
+ before do
134
+ doc_block.children['child-one'] = double( name: 'child-one', title: 'Child 1' )
135
+ doc_block.children['child-two'] = double( name: 'child-two', title: 'Child 2' )
136
+ end
137
+
138
+ it 'returns markdown with no nav' do
139
+ expected_output = <<-eos
140
+
141
+
142
+ <h2 id="foo" class="styleguide">baz</h2>
143
+ <ul class="section-nav">
144
+ <li><a href="#child-one">Child 1</a></li>
145
+ <li><a href="#child-two">Child 2</a></li>
146
+ </ul>
147
+ blah
148
+ eos
149
+ expect(doc_block.markdown_with_heading(2, include_sub_nav: true)).to eql expected_output.rstrip
150
+ end
151
+ end
121
152
  end
122
153
  end
123
154
  end