hologram 1.2.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
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,73 @@
1
+ require 'hologram/code_example_renderer/example'
2
+ require 'hologram/code_example_renderer/template'
3
+
4
+ module Hologram
5
+ module CodeExampleRenderer
6
+ class << self
7
+ def register(example_type, args)
8
+ puts "Adding renderer for #{example_type} examples"
9
+ example_types[example_type] = {
10
+ example_class: args[:example_class],
11
+ example_template: args[:example_template],
12
+ table_template: args[:table_template]
13
+ }
14
+ end
15
+
16
+ def unregister(example_type)
17
+ example_types.delete(example_type)
18
+ end
19
+
20
+ def example_class_for(example_type)
21
+ if example_types.has_key?(example_type)
22
+ example_types[example_type][:example_class]
23
+ else
24
+ Example
25
+ end
26
+ end
27
+
28
+ def example_template_for(example_type)
29
+ if example_types.has_key?(example_type)
30
+ example_types[example_type][:example_template]
31
+ else
32
+ [
33
+ "<div class=\"codeBlock\">",
34
+ " <div class=\"highlight\">",
35
+ " <pre><%= code_example %></pre>",
36
+ " </div>",
37
+ "</div>",
38
+ ].join("\n")
39
+ end
40
+ end
41
+
42
+ def table_template_for(example_type)
43
+ if example_types.has_key?(example_type)
44
+ example_types[example_type][:table_template]
45
+ else
46
+ nil
47
+ end
48
+ end
49
+
50
+ def load_renderers_and_templates
51
+ require 'hologram/code_example_renderer/factory'
52
+
53
+ Dir[File.join(File.dirname(__FILE__), 'code_example_renderer', 'renderers', '*.rb')].each do |file|
54
+ require file
55
+ end
56
+
57
+ if path_to_custom_example_renderers
58
+ Dir[File.join(path_to_custom_example_renderers, '*.rb')].each do |file|
59
+ require file
60
+ end
61
+ end
62
+ end
63
+
64
+ attr_accessor :path_to_custom_example_renderers
65
+
66
+ private
67
+
68
+ def example_types
69
+ @example_types ||= Hash.new
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,27 @@
1
+ module Hologram
2
+ module CodeExampleRenderer
3
+ class Example < Struct.new(:code)
4
+ def rendered_example
5
+ code
6
+ end
7
+
8
+ def code_example
9
+ formatter.format(lexer.lex(code)).strip
10
+ end
11
+
12
+ def get_binding
13
+ binding
14
+ end
15
+
16
+ private
17
+
18
+ def formatter
19
+ @_formatter ||= Rouge::Formatters::HTML.new(wrap: false)
20
+ end
21
+
22
+ def lexer
23
+ @_lexer ||= Rouge::Lexer.find_fancy('guess', code)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,60 @@
1
+ require 'hologram/code_example_renderer'
2
+
3
+ module Hologram
4
+ module CodeExampleRenderer
5
+ class Factory
6
+ def self.define(example_type, &block)
7
+ definition_proxy = DefinitionProxy.new
8
+ definition_proxy.instance_eval(&block)
9
+
10
+ example_class = Class.new(Example) do
11
+ if definition_proxy.rendered_example_block
12
+ define_method :rendered_example do
13
+ definition_proxy.rendered_example_block.call(code)
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ if definition_proxy.lexer_block
20
+ define_method :lexer do
21
+ definition_proxy.lexer_block.call
22
+ end
23
+ end
24
+ end
25
+
26
+ CodeExampleRenderer.register(example_type,
27
+ example_class: example_class,
28
+ example_template: Template.new(definition_proxy.example_template_name).template,
29
+ table_template: Template.new(definition_proxy.table_template_name).template,
30
+ )
31
+ end
32
+ end
33
+
34
+ class DefinitionProxy
35
+ attr_reader :example_template_name, :table_template_name,
36
+ :lexer_block, :rendered_example_block
37
+
38
+ def example_template(template_name)
39
+ self.example_template_name = template_name
40
+ end
41
+
42
+ def table_template(template_name)
43
+ self.table_template_name = template_name
44
+ end
45
+
46
+ def lexer(&block)
47
+ self.lexer_block = block
48
+ end
49
+
50
+ def rendered_example(&block)
51
+ self.rendered_example_block = block
52
+ end
53
+
54
+ private
55
+
56
+ attr_writer :example_template_name, :table_template_name,
57
+ :lexer_block, :rendered_example_block
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,17 @@
1
+ Hologram::CodeExampleRenderer::Factory.define 'haml' do
2
+ example_template 'markup_example_template'
3
+ table_template 'markup_table_template'
4
+ lexer { Rouge::Lexer.find('haml') }
5
+
6
+ rendered_example do |code|
7
+ begin
8
+ require 'haml'
9
+ rescue LoadError
10
+ raise "haml must be present for you to use haml"
11
+ end
12
+
13
+ haml_engine = Haml::Engine.new(code.strip)
14
+ haml_engine.render(Object.new, {})
15
+ end
16
+ end
17
+
@@ -0,0 +1,6 @@
1
+ Hologram::CodeExampleRenderer::Factory.define 'html' do
2
+ example_template 'markup_example_template'
3
+ table_template 'markup_table_template'
4
+ lexer { Rouge::Lexer.find('html') }
5
+ end
6
+
@@ -0,0 +1,5 @@
1
+ Hologram::CodeExampleRenderer::Factory.define 'js' do
2
+ example_template 'js_example_template'
3
+ lexer { Rouge::Lexer.find('js') }
4
+ end
5
+
@@ -0,0 +1,4 @@
1
+ Hologram::CodeExampleRenderer::Factory.define 'jsx' do
2
+ example_template 'jsx_example_template'
3
+ lexer { Rouge::Lexer.find('html') }
4
+ end
@@ -0,0 +1,21 @@
1
+ require 'securerandom'
2
+
3
+ Hologram::CodeExampleRenderer::Factory.define 'react' do
4
+ example_template 'markup_example_template'
5
+ table_template 'markup_table_template'
6
+
7
+ lexer { Rouge::Lexer.find(:html) }
8
+
9
+ rendered_example do |code|
10
+ div_id = SecureRandom.hex(10)
11
+ [
12
+ "<div id=\"#{div_id}\"></div>",
13
+ "<script type=\"text/jsx\">",
14
+ " React.render(",
15
+ " #{code.strip},",
16
+ " document.getElementById('#{div_id}')",
17
+ " );",
18
+ "</script>"
19
+ ].join("\n")
20
+ end
21
+ end
@@ -0,0 +1,16 @@
1
+ Hologram::CodeExampleRenderer::Factory.define 'slim' do
2
+ example_template 'markup_example_template'
3
+ table_template 'markup_table_template'
4
+ lexer { Rouge::Lexer.find('slim') }
5
+
6
+ rendered_example do |code|
7
+ begin
8
+ require 'slim'
9
+ rescue LoadError
10
+ raise "slim must be present for you to use slim"
11
+ end
12
+
13
+ slim_engine = Slim::Template.new { code.strip }
14
+ slim_engine.render(Object.new, {})
15
+ end
16
+ end
@@ -0,0 +1,33 @@
1
+ module Hologram
2
+ module CodeExampleRenderer
3
+ class Template < Struct.new(:template_name)
4
+ def template
5
+ return nil if !template_filename
6
+ File.read(template_filename)
7
+ end
8
+
9
+ class << self
10
+ attr_accessor :path_to_custom_example_templates
11
+ end
12
+
13
+ private
14
+
15
+ def template_filename
16
+ return nil if !template_name
17
+ custom_file_exists? ? custom_file : default_file
18
+ end
19
+
20
+ def custom_file_exists?
21
+ !!self.class.path_to_custom_example_templates && File.file?(custom_file)
22
+ end
23
+
24
+ def custom_file
25
+ File.join(self.class.path_to_custom_example_templates, "#{template_name}.html.erb")
26
+ end
27
+
28
+ def default_file
29
+ File.join(File.dirname(__FILE__), '..', '..', 'template', 'code_example_templates', "#{template_name}.html.erb")
30
+ end
31
+ end
32
+ end
33
+ end
@@ -1,6 +1,7 @@
1
1
  module Hologram
2
2
  module DisplayMessage
3
3
  @@quiet = false
4
+ @@exit_on_warnings = false
4
5
 
5
6
  def self.quiet!
6
7
  @@quiet = true
@@ -16,6 +17,14 @@ module Hologram
16
17
  @@quiet
17
18
  end
18
19
 
20
+ def self.exit_on_warnings!
21
+ @@exit_on_warnings = true
22
+ end
23
+
24
+ def self.continue_on_warnings!
25
+ @@exit_on_warnings = false
26
+ end
27
+
19
28
  def self.puts(str)
20
29
  return if quiet?
21
30
  super(str)
@@ -45,6 +54,10 @@ module Hologram
45
54
 
46
55
  def self.warning(message)
47
56
  puts yellow("Warning: #{message}")
57
+ if @@exit_on_warnings
58
+ puts red("Exiting due to warning")
59
+ exit 1
60
+ end
48
61
  end
49
62
 
50
63
  def self.success(message)
@@ -15,7 +15,11 @@ module Hologram
15
15
  return
16
16
  end
17
17
 
18
- @doc_blocks[doc_block.name] = doc_block
18
+ if @doc_blocks.has_key?(doc_block.name)
19
+ DisplayMessage.warning("Multiple Hologram comments with name: #{doc_block.name}.")
20
+ else
21
+ @doc_blocks[doc_block.name] = doc_block
22
+ end
19
23
  return doc_block
20
24
  end
21
25
 
@@ -1,3 +1,5 @@
1
+ require 'hologram/link_helper'
2
+
1
3
  module Hologram
2
4
  class DocBuilder
3
5
  attr_accessor :source, :destination, :documentation_assets, :dependencies, :index, :base_path, :renderer, :doc_blocks, :pages, :config_yml
@@ -31,7 +33,17 @@ module Hologram
31
33
  end
32
34
 
33
35
  FileUtils.cp_r INIT_TEMPLATE_FILES, Dir.pwd
34
- new_files = ["hologram_config.yml", "doc_assets/", "doc_assets/_header.html", "doc_assets/_footer.html"]
36
+ new_files = [
37
+ "hologram_config.yml",
38
+ "doc_assets/",
39
+ "doc_assets/_header.html",
40
+ "doc_assets/_footer.html",
41
+ "code_example_templates/",
42
+ "code_example_templates/markdown_example_template.html.erb",
43
+ "code_example_templates/markdown_table_template.html.erb",
44
+ "code_example_templates/js_example_template.html.erb",
45
+ "code_example_templates/jsx_example_template.html.erb",
46
+ ]
35
47
  DisplayMessage.created(new_files)
36
48
  end
37
49
 
@@ -47,6 +59,14 @@ module Hologram
47
59
  @documentation_assets = options['documentation_assets']
48
60
  @config_yml = options['config_yml']
49
61
  @plugins = Plugins.new(options.fetch('config_yml', {}), extra_args)
62
+ @nav_level = options['nav_level'] || 'page'
63
+ @exit_on_warnings = options['exit_on_warnings']
64
+ @code_example_templates = options['code_example_templates']
65
+ @code_example_renderers = options['code_example_renderers']
66
+
67
+ if @exit_on_warnings
68
+ DisplayMessage.exit_on_warnings!
69
+ end
50
70
  end
51
71
 
52
72
  def build
@@ -112,7 +132,7 @@ module Hologram
112
132
  end
113
133
 
114
134
  def build_docs
115
- doc_parser = DocParser.new(input_dir, index, @plugins)
135
+ doc_parser = DocParser.new(input_dir, index, @plugins, nav_level: @nav_level)
116
136
  @pages, @categories = doc_parser.parse
117
137
 
118
138
  if index && !@pages.has_key?(index + '.html')
@@ -131,8 +151,8 @@ module Hologram
131
151
  # ignore . and .. directories and files that start with
132
152
  # underscore
133
153
  next if item == '.' or item == '..' or item.start_with?('_')
134
- `rm -rf #{output_dir}/#{item}`
135
- `cp -R #{doc_assets_dir}/#{item} #{output_dir}/#{item}`
154
+ FileUtils.rm "#{output_dir}/#{item}", :force => true
155
+ FileUtils.cp_r "#{doc_assets_dir}/#{item}", "#{output_dir}/#{item}"
136
156
  end
137
157
  end
138
158
 
@@ -141,8 +161,8 @@ module Hologram
141
161
  begin
142
162
  dirpath = Pathname.new(dir).realpath
143
163
  if File.directory?("#{dir}")
144
- `rm -rf #{output_dir}/#{dirpath.basename}`
145
- `cp -R #{dirpath} #{output_dir}/#{dirpath.basename}`
164
+ FileUtils.rm "#{output_dir}/#{dirpath.basename}", :force => true
165
+ FileUtils.cp_r "#{dirpath}", "#{output_dir}/#{dirpath.basename}"
146
166
  end
147
167
  rescue
148
168
  DisplayMessage.warning("Could not copy dependency: #{dir}")
@@ -151,7 +171,10 @@ module Hologram
151
171
  end
152
172
 
153
173
  def write_docs
154
- markdown = Redcarpet::Markdown.new(renderer, { :fenced_code_blocks => true, :tables => true })
174
+ load_code_example_templates_and_renderers
175
+
176
+ renderer_instance = renderer.new(link_helper: link_helper)
177
+ markdown = Redcarpet::Markdown.new(renderer_instance, { :fenced_code_blocks => true, :tables => true })
155
178
  tpl_vars = TemplateVariables.new({:categories => @categories, :config => @config_yml, :pages => @pages})
156
179
  #generate html from markdown
157
180
  @pages.each do |file_name, page|
@@ -174,6 +197,34 @@ module Hologram
174
197
  end
175
198
  end
176
199
 
200
+ def load_code_example_templates_and_renderers
201
+ if @code_example_templates
202
+ CodeExampleRenderer::Template.path_to_custom_example_templates = real_path(@code_example_templates)
203
+ end
204
+
205
+ if @code_example_renderers
206
+ CodeExampleRenderer.path_to_custom_example_renderers = real_path(@code_example_renderers)
207
+ end
208
+
209
+ CodeExampleRenderer.load_renderers_and_templates
210
+ end
211
+
212
+ def link_helper
213
+ @_link_helper ||= LinkHelper.new(@pages.map { |page|
214
+ if not page[1][:blocks].nil?
215
+ {
216
+ name: page[0],
217
+ component_names: page[1][:blocks].map { |component| component[:name] }
218
+ }
219
+ else
220
+ {
221
+ name: page[0],
222
+ component_names: {}
223
+ }
224
+ end
225
+ })
226
+ end
227
+
177
228
  def write_erb(file_name, content, binding)
178
229
  fh = get_fh(output_dir, file_name)
179
230
  erb = ERB.new(content)
@@ -1,12 +1,13 @@
1
1
  module Hologram
2
2
  class DocParser
3
3
  SUPPORTED_EXTENSIONS = ['.css', '.scss', '.less', '.sass', '.styl', '.js', '.md', '.markdown', '.erb' ]
4
- attr_accessor :source_path, :pages, :doc_blocks
4
+ attr_accessor :source_path, :pages, :doc_blocks, :nav_level
5
5
 
6
- def initialize(source_path, index_name = nil, plugins)
6
+ def initialize(source_path, index_name = nil, plugins=[], opts={})
7
7
  @plugins = plugins
8
8
  @source_paths = Array(source_path)
9
9
  @index_name = index_name
10
+ @nav_level = opts[:nav_level] || 'page'
10
11
  @pages = {}
11
12
  @output_files_by_category = {}
12
13
  end
@@ -85,9 +86,16 @@ module Hologram
85
86
  # .sass: //doc (follow by other lines proceeded by a space)
86
87
  # other types: /*doc ... */
87
88
  if file.end_with?('.sass')
88
- hologram_comments = file_str.scan(/\s*\/\/doc\s*((( [^\n]*\n)|\n)+)/)
89
+ #For sass strip out leading white spaces after we get the
90
+ #comment, this fixes haml when using this comment style
91
+ hologram_comments = file_str.scan(/\s*\/\/doc\s*((( [^\n]*\n)|\n)+)/).map{ |arr| [arr[0].gsub(/^[ \t]{2}/,'')] }
89
92
  else
90
93
  hologram_comments = file_str.scan(/^\s*\/\*doc(.*?)\*\//m)
94
+
95
+ #check if scss file has sass comments
96
+ if hologram_comments.length == 0 and file.end_with?('.scss')
97
+ hologram_comments = file_str.scan(/\s*\/\/doc\s*((( [^\n]*\n)|\n)+)/).map{ |arr| [arr[0].gsub(/^[ \t]{2}/,'')] }
98
+ end
91
99
  end
92
100
  return unless hologram_comments
93
101
 
@@ -133,8 +141,16 @@ module Hologram
133
141
  @pages[output_file] = {:md => "", :blocks => []}
134
142
  end
135
143
 
144
+
145
+ if (@nav_level == 'section' && depth == 1) || @nav_level == 'all'
146
+ include_sub_nav = true
147
+ else
148
+ include_sub_nav = false
149
+ end
150
+
136
151
  @pages[output_file][:blocks].push(doc_block.get_hash)
137
- @pages[output_file][:md] << doc_block.markdown_with_heading(depth)
152
+ @pages[output_file][:md] << doc_block.markdown_with_heading(depth, include_sub_nav: include_sub_nav)
138
153
  end
154
+
139
155
  end
140
156
  end