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,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