hologram 0.6.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +7 -4
- data/Rakefile +5 -0
- data/hologram.gemspec +1 -1
- data/lib/hologram.rb +13 -445
- data/lib/hologram/display_message.rb +79 -0
- data/lib/hologram/doc_block_collection.rb +48 -0
- data/lib/hologram/doc_builder.rb +196 -0
- data/lib/hologram/doc_parser.rb +125 -0
- data/lib/hologram/document_block.rb +36 -0
- data/lib/hologram/template_variables.rb +21 -0
- data/lib/hologram/version.rb +1 -1
- data/lib/template/doc_assets/_header.html +7 -2
- data/lib/template/hologram_config.yml +3 -0
- data/spec/display_message_spec.rb +115 -0
- data/spec/doc_block_collection_spec.rb +80 -0
- data/spec/doc_builder_spec.rb +92 -0
- data/spec/doc_parser_spec.rb +89 -0
- data/spec/document_block_spec.rb +62 -0
- data/spec/fixtures/source/components/background/backgrounds.css +46 -0
- data/spec/fixtures/source/components/button/buttons.css +87 -0
- data/spec/fixtures/source/components/button/skin/buttonSkins.css +113 -0
- data/spec/fixtures/source/components/index.md +23 -0
- data/spec/fixtures/source/config.yml +17 -0
- data/spec/fixtures/source/extra/css/screen.css +1 -0
- data/spec/fixtures/source/templates/_footer.html +9 -0
- data/spec/fixtures/source/templates/_header.html +57 -0
- data/spec/fixtures/source/templates/static/css/doc.css +132 -0
- data/spec/fixtures/styleguide/base_css.html +170 -0
- data/spec/fixtures/styleguide/extra/css/screen.css +1 -0
- data/spec/fixtures/styleguide/index.html +84 -0
- data/spec/fixtures/styleguide/static/css/doc.css +132 -0
- data/spec/spec_helper.rb +7 -0
- metadata +66 -22
@@ -0,0 +1,36 @@
|
|
1
|
+
module Hologram
|
2
|
+
class DocumentBlock
|
3
|
+
attr_accessor :name, :parent, :children, :title, :category, :markdown, :config, :heading
|
4
|
+
|
5
|
+
def initialize(config = nil, markdown = nil)
|
6
|
+
@children = {}
|
7
|
+
set_members(config, markdown) if config and markdown
|
8
|
+
end
|
9
|
+
|
10
|
+
def set_members(config, markdown)
|
11
|
+
@name = config['name']
|
12
|
+
@category = config['category']
|
13
|
+
@title = config['title']
|
14
|
+
@parent = config['parent']
|
15
|
+
@markdown = markdown
|
16
|
+
end
|
17
|
+
|
18
|
+
def get_hash
|
19
|
+
{:name => @name,
|
20
|
+
:parent => @parent,
|
21
|
+
:category => @category,
|
22
|
+
:title => @title
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def is_valid?
|
27
|
+
!!(@name && @markdown)
|
28
|
+
end
|
29
|
+
|
30
|
+
# sets the header tag based on how deep your nesting is
|
31
|
+
def markdown_with_heading(heading = 1)
|
32
|
+
@markdown = "\n\n<h#{heading.to_s} id=\"#{@name}\">#{@title}</h#{heading.to_s}>" + @markdown
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Hologram
|
2
|
+
|
3
|
+
#Helper class for binding things for ERB
|
4
|
+
class TemplateVariables
|
5
|
+
attr_accessor :title, :file_name, :blocks, :categories
|
6
|
+
|
7
|
+
def initialize(args)
|
8
|
+
set_args(args)
|
9
|
+
end
|
10
|
+
|
11
|
+
def set_args(args)
|
12
|
+
args.each do |k,v|
|
13
|
+
instance_variable_set("@#{k}", v) unless v.nil?
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def get_binding
|
18
|
+
binding()
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/hologram/version.rb
CHANGED
@@ -8,11 +8,16 @@
|
|
8
8
|
|
9
9
|
<nav>
|
10
10
|
<ul>
|
11
|
-
<%
|
12
|
-
<li><a href="
|
11
|
+
<% @categories.each do |category, file_name| %>
|
12
|
+
<li><a href="<%= file_name %>"><%= category %></a></li>
|
13
13
|
<% end %>
|
14
14
|
</ul>
|
15
15
|
</nav>
|
16
16
|
|
17
17
|
<h1>a brand new style guide, it's super effective</h1>
|
18
18
|
<section class="content">
|
19
|
+
<ul>
|
20
|
+
<% @blocks.each do |b| %>
|
21
|
+
<li><a href="#<%= b[:name] %>"><%= b[:title] %></a></li>
|
22
|
+
<% end %>
|
23
|
+
</ul>
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'tempfile'
|
3
|
+
|
4
|
+
describe Hologram::DisplayMessage do
|
5
|
+
subject(:display) { Hologram::DisplayMessage }
|
6
|
+
|
7
|
+
#Rails kernerl helper
|
8
|
+
def capture(stream)
|
9
|
+
stream = stream.to_s
|
10
|
+
captured_stream = Tempfile.new(stream)
|
11
|
+
stream_io = eval("$#{stream}")
|
12
|
+
origin_stream = stream_io.dup
|
13
|
+
stream_io.reopen(captured_stream)
|
14
|
+
|
15
|
+
yield
|
16
|
+
|
17
|
+
stream_io.rewind
|
18
|
+
return captured_stream.read
|
19
|
+
ensure
|
20
|
+
captured_stream.unlink
|
21
|
+
stream_io.reopen(origin_stream)
|
22
|
+
end
|
23
|
+
|
24
|
+
context '.quiet!' do
|
25
|
+
around do |example|
|
26
|
+
display.quiet!
|
27
|
+
example.run
|
28
|
+
display.show!
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'sets quiet to true' do
|
32
|
+
display.quiet!
|
33
|
+
expect(display.quiet?).to be_true
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context '.puts' do
|
38
|
+
let(:message) { capture(:stdout) { display.puts('foo') } }
|
39
|
+
|
40
|
+
it 'puts to console' do
|
41
|
+
expect(message).to eql "foo\n"
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'when quiet' do
|
45
|
+
around do |example|
|
46
|
+
display.quiet!
|
47
|
+
example.run
|
48
|
+
display.show!
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'does nothing' do
|
52
|
+
expect(message).to be_empty
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context '.error' do
|
58
|
+
around do |example|
|
59
|
+
display.quiet!
|
60
|
+
example.run
|
61
|
+
display.show!
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'displays an error in red' do
|
65
|
+
expect(display).to receive(:puts).with("\e[32m(╯°□°)╯\e[0m\e[31m︵ ┻━┻ \e[0m\e[31m Build not complete.\e[0m")
|
66
|
+
expect(display).to receive(:puts).with(" foo")
|
67
|
+
|
68
|
+
begin
|
69
|
+
display.error('foo')
|
70
|
+
rescue SystemExit
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'exits' do
|
75
|
+
expect{ display.error('foo') }.to raise_error SystemExit
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context '.warning' do
|
80
|
+
it 'displays a warning message in yellow' do
|
81
|
+
expect(display).to receive(:puts).with("\e[33mWarning: foo\e[0m")
|
82
|
+
display.warning('foo')
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
context '.colorize' do
|
87
|
+
it 'returns a colorized string' do
|
88
|
+
expect(display.colorize(31, 'foo')).to eql "\e[31mfoo\e[0m"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
context '.red' do
|
93
|
+
it 'returns a red colorized string' do
|
94
|
+
expect(display.red('foo')).to eql display.colorize(31, 'foo')
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
context '.green' do
|
99
|
+
it 'returns a green colorized string' do
|
100
|
+
expect(display.green('foo')).to eql display.colorize(32, 'foo')
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
context '.yellow' do
|
105
|
+
it 'returns a yellow colorized string' do
|
106
|
+
expect(display.yellow('foo')).to eql display.colorize(33, 'foo')
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
context '.pink' do
|
111
|
+
it 'returns a pink colorized string' do
|
112
|
+
expect(display.pink('foo')).to eql display.colorize(35, 'foo')
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Hologram::DocBlockCollection do
|
4
|
+
let(:comment) do
|
5
|
+
comment = <<comment
|
6
|
+
/*doc
|
7
|
+
---
|
8
|
+
title: Buttons
|
9
|
+
name: button
|
10
|
+
category: Base CSS
|
11
|
+
---
|
12
|
+
|
13
|
+
Button styles can be applied to any element. Typically you'll want
|
14
|
+
to use either a `<button>` or an `<a>` element:
|
15
|
+
|
16
|
+
```html_example
|
17
|
+
<button class="btn btnDefault">Click</button>
|
18
|
+
<a class="btn btnDefault" href="trulia.com">Trulia!</a>
|
19
|
+
```
|
20
|
+
|
21
|
+
If your button is actually a link to another page, please use the
|
22
|
+
`<a>` element, while if your button performs an action, such as
|
23
|
+
submitting a form or triggering some javascript event, then use a
|
24
|
+
`<button>` element.
|
25
|
+
|
26
|
+
*/
|
27
|
+
comment
|
28
|
+
end
|
29
|
+
|
30
|
+
let(:collection){ Hologram::DocBlockCollection.new }
|
31
|
+
|
32
|
+
context '#add_doc_block' do
|
33
|
+
context 'when the comment is valid' do
|
34
|
+
before do
|
35
|
+
collection.add_doc_block(comment)
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'adds a doc block to the collection' do
|
39
|
+
expect(collection.doc_blocks.size).to eql 1
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'when no yaml is provided' do
|
44
|
+
before do
|
45
|
+
collection.add_doc_block('')
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'does not add a new block' do
|
49
|
+
expect(collection.doc_blocks.size).to eql 0
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context '#create_nested_structure' do
|
55
|
+
context 'when the collection has blocks with parents' do
|
56
|
+
before do
|
57
|
+
collection.add_doc_block(comment)
|
58
|
+
collection.add_doc_block(%q{
|
59
|
+
/*doc
|
60
|
+
---
|
61
|
+
title: foo
|
62
|
+
name: bah
|
63
|
+
parent: button
|
64
|
+
---
|
65
|
+
some other button style
|
66
|
+
*/})
|
67
|
+
|
68
|
+
collection.create_nested_structure
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'removes the child block from the collection level' do
|
72
|
+
expect(collection.doc_blocks.size).to eql 1
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'nests the doc block as a child of the parent block' do
|
76
|
+
expect(collection.doc_blocks['button'].children.size).to eql 1
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Hologram::DocBuilder do
|
4
|
+
subject(:builder) { Hologram::DocBuilder.new }
|
5
|
+
|
6
|
+
context '#init' do
|
7
|
+
around do |example|
|
8
|
+
Hologram::DisplayMessage.quiet!
|
9
|
+
example.run
|
10
|
+
Hologram::DisplayMessage.show!
|
11
|
+
end
|
12
|
+
|
13
|
+
context 'when passed an invalid config' do
|
14
|
+
before do
|
15
|
+
File.open('bad_config.yml', 'w'){ |io| io << '%' }
|
16
|
+
end
|
17
|
+
|
18
|
+
after do
|
19
|
+
FileUtils.rm('bad_config.yml')
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'exits the process' do
|
23
|
+
expect { builder.init(['bad_config.yml']) }.to raise_error SystemExit
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'when passed a config file' do
|
28
|
+
let(:style_files) { Dir[File.expand_path('../fixtures/styleguide/**/*.*', __FILE__)] }
|
29
|
+
let(:config_path) { File.join(Dir.pwd, 'spec/fixtures/source/config.yml') }
|
30
|
+
let(:config_copy_path) { File.join(Dir.pwd, 'spec/fixtures/source/config.yml.copy') }
|
31
|
+
|
32
|
+
around do |example|
|
33
|
+
Dir.mktmpdir do |tmpdir|
|
34
|
+
FileUtils.cp(config_path, config_copy_path)
|
35
|
+
File.open(config_copy_path, 'a'){ |io| io << "destination: #{tmpdir}" }
|
36
|
+
current_dir = Dir.pwd
|
37
|
+
Dir.chdir(tmpdir)
|
38
|
+
|
39
|
+
example.run
|
40
|
+
|
41
|
+
Dir.chdir(current_dir)
|
42
|
+
FileUtils.rm(config_copy_path)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
before do
|
47
|
+
builder.init([config_copy_path])
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'builds a styleguide' do
|
51
|
+
processed_files = Dir[File.join('.', '**/*.*')]
|
52
|
+
processed_files.each_with_index do |file, index|
|
53
|
+
expect(FileUtils.cmp(file, style_files[index])).to be_true
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context 'when passed "init" as arg' do
|
59
|
+
around do |example|
|
60
|
+
Dir.mktmpdir do |dir|
|
61
|
+
Dir.chdir(dir) do
|
62
|
+
example.run
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
before do
|
68
|
+
builder.init(['init'])
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'creates a config file' do
|
72
|
+
expect(File.exists?('hologram_config.yml')).to be_true
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'creates default assets' do
|
76
|
+
Dir.chdir('doc_assets') do
|
77
|
+
['_header.html', '_footer.html'].each do |asset|
|
78
|
+
expect(File.exists?(asset)).to be_true
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context 'when a hologram_config.yml already exists' do
|
84
|
+
it 'does nothing' do
|
85
|
+
open('hologram_config.yml', 'w') {|io|io << 'foo'}
|
86
|
+
builder.init(['init'])
|
87
|
+
expect(IO.read('hologram_config.yml')).to eql('foo')
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Hologram::DocParser do
|
4
|
+
|
5
|
+
let(:doc) do
|
6
|
+
<<-eos
|
7
|
+
/*doc
|
8
|
+
---
|
9
|
+
title: Some other style
|
10
|
+
name: otherStyle
|
11
|
+
category: Foo
|
12
|
+
---
|
13
|
+
Markdown stuff
|
14
|
+
*/
|
15
|
+
eos
|
16
|
+
end
|
17
|
+
|
18
|
+
let(:child_doc) do
|
19
|
+
<<-eos
|
20
|
+
/*doc
|
21
|
+
---
|
22
|
+
parent: button
|
23
|
+
name: otherStyle
|
24
|
+
title: Some other style
|
25
|
+
---
|
26
|
+
Markdown stuff
|
27
|
+
*/
|
28
|
+
eos
|
29
|
+
end
|
30
|
+
|
31
|
+
let(:source_path) { 'spec/fixtures/source' }
|
32
|
+
let(:temp_doc) { File.join(source_path, 'components', 'button', 'skin', 'testSkin.css') }
|
33
|
+
|
34
|
+
subject(:parser) { Hologram::DocParser.new('spec/fixtures/source') }
|
35
|
+
|
36
|
+
context '#parse' do
|
37
|
+
let(:result) { parser.parse }
|
38
|
+
|
39
|
+
it 'builds and returns a hash of pages' do
|
40
|
+
expect(result).to be_a Hash
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'when an index page is specified' do
|
44
|
+
subject(:parser) { Hologram::DocParser.new('spec/fixtures/source', 'foo') }
|
45
|
+
|
46
|
+
around do |example|
|
47
|
+
File.open(temp_doc, 'a+'){ |io| io << doc }
|
48
|
+
example.run
|
49
|
+
FileUtils.rm(temp_doc)
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'uses that page as the index' do
|
53
|
+
expect(result['index.html'][:md]).to include 'Markdown stuff'
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'when the source is a parent doc' do
|
58
|
+
around do |example|
|
59
|
+
File.open(temp_doc, 'a+'){ |io| io << doc }
|
60
|
+
example.run
|
61
|
+
FileUtils.rm(temp_doc)
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'takes the category in a collection and treats them as the page names' do
|
65
|
+
expect(result.keys).to include 'foo.html'
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context 'when a source doc is a child' do
|
70
|
+
around do |example|
|
71
|
+
File.open(temp_doc, 'a+'){ |io| io << child_doc }
|
72
|
+
example.run
|
73
|
+
FileUtils.rm(temp_doc)
|
74
|
+
end
|
75
|
+
|
76
|
+
before do
|
77
|
+
parser.parse
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'appends the child doc to the category page' do
|
81
|
+
expect(result['base_css.html'][:md]).to include 'Some other style'
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'assigns the child doc a deeper header' do
|
85
|
+
expect(result['base_css.html'][:md]).to include '<h2 id="otherStyle">Some other style</h2>'
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|