lookbook 1.2.1 → 1.4.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE.txt +1 -1
- data/README.md +47 -14
- data/app/assets/lookbook/css/themes/blue.css +4 -2
- data/app/assets/lookbook/css/themes/green.css +66 -0
- data/app/assets/lookbook/css/themes/indigo.css +4 -2
- data/app/assets/lookbook/css/themes/rose.css +66 -0
- data/app/assets/lookbook/css/themes/zinc.css +4 -2
- data/app/components/lookbook/base_component.rb +2 -2
- data/app/components/lookbook/code/component.css +2 -2
- data/app/components/lookbook/code/component.html.erb +3 -2
- data/app/components/lookbook/code/component.rb +13 -2
- data/app/components/lookbook/code/highlight_github.css +406 -0
- data/app/components/lookbook/header/component.html.erb +1 -1
- data/app/components/lookbook/inspector_panel/component.rb +4 -6
- data/app/components/lookbook/nav/component.rb +8 -15
- data/app/components/lookbook/nav/directory/component.html.erb +28 -0
- data/app/components/lookbook/nav/directory/component.rb +4 -0
- data/app/components/lookbook/nav/{item → entity}/component.html.erb +8 -8
- data/app/components/lookbook/nav/entity/component.rb +49 -0
- data/app/components/lookbook/nav/item/component.css +15 -0
- data/app/components/lookbook/nav/item/component.js +4 -0
- data/app/components/lookbook/nav/item/component.rb +13 -56
- data/app/components/lookbook/params/editor/component.html.erb +2 -2
- data/app/components/lookbook/params/editor/component.rb +3 -10
- data/app/components/lookbook/params/field/component.css +3 -3
- data/app/components/lookbook/params/field/component.html.erb +8 -8
- data/app/components/lookbook/params/field/component.rb +21 -72
- data/app/components/lookbook/split_layout/component.html.erb +1 -1
- data/app/components/lookbook/tabs/component.html.erb +1 -1
- data/app/components/lookbook/tabs/component.js +4 -0
- data/app/components/lookbook/tag_component.rb +1 -1
- data/app/components/lookbook/viewport/component.css +1 -1
- data/app/components/lookbook/viewport/component.html.erb +1 -1
- data/app/components/lookbook/viewport/component.rb +1 -1
- data/app/controllers/concerns/lookbook/targetable_concern.rb +131 -0
- data/app/controllers/concerns/lookbook/with_preview_controller_concern.rb +13 -0
- data/app/controllers/lookbook/application_controller.rb +21 -9
- data/app/controllers/lookbook/inspector_controller.rb +45 -0
- data/app/controllers/lookbook/page_controller.rb +13 -9
- data/app/controllers/lookbook/pages_controller.rb +9 -15
- data/app/controllers/lookbook/previews_controller.rb +4 -210
- data/app/helpers/lookbook/application_helper.rb +2 -2
- data/app/helpers/lookbook/output_helper.rb +5 -5
- data/app/helpers/lookbook/page_helper.rb +7 -4
- data/app/views/layouts/lookbook/application.html.erb +40 -38
- data/app/views/layouts/lookbook/page.html.erb +2 -2
- data/app/views/layouts/lookbook/shell.html.erb +3 -2
- data/app/views/layouts/lookbook/skeleton.html.erb +7 -7
- data/app/views/lookbook/index.html.erb +13 -2
- data/app/views/lookbook/{previews → inspector}/inputs/_color.html.erb +0 -0
- data/app/views/lookbook/{previews → inspector}/inputs/_range.html.erb +0 -0
- data/app/views/lookbook/{previews → inspector}/inputs/_select.html.erb +0 -0
- data/app/views/lookbook/{previews → inspector}/inputs/_text.html.erb +0 -0
- data/app/views/lookbook/{previews → inspector}/inputs/_textarea.html.erb +0 -0
- data/app/views/lookbook/{previews → inspector}/inputs/_toggle.html.erb +5 -5
- data/app/views/lookbook/{previews → inspector}/panels/_content.html.erb +0 -0
- data/app/views/lookbook/{previews → inspector}/panels/_notes.html.erb +2 -2
- data/app/views/lookbook/{previews → inspector}/panels/_output.html.erb +0 -0
- data/app/views/lookbook/inspector/panels/_params.html.erb +15 -0
- data/app/views/lookbook/{previews → inspector}/panels/_preview.html.erb +0 -0
- data/app/views/lookbook/{previews → inspector}/panels/_source.html.erb +0 -0
- data/app/views/lookbook/{previews → inspector}/show.html.erb +5 -2
- data/config/app.yml +11 -1
- data/config/inputs.yml +12 -12
- data/config/languages.yml +41 -0
- data/config/panels.yml +6 -6
- data/config/routes.rb +5 -5
- data/config/tags.yml +8 -1
- data/lib/lookbook/engine.rb +103 -130
- data/lib/lookbook/entities/collections/component_collection.rb +4 -0
- data/lib/lookbook/entities/collections/concerns/hierarchical_collection.rb +23 -0
- data/lib/lookbook/entities/collections/entity_collection.rb +61 -0
- data/lib/lookbook/entities/collections/page_collection.rb +30 -0
- data/lib/lookbook/entities/collections/preview_collection.rb +41 -0
- data/lib/lookbook/entities/collections/preview_example_collection.rb +4 -0
- data/lib/lookbook/entities/component.rb +31 -0
- data/lib/lookbook/entities/concerns/annotatable.rb +58 -0
- data/lib/lookbook/entities/concerns/inspectable.rb +44 -0
- data/lib/lookbook/entities/concerns/locatable.rb +73 -0
- data/lib/lookbook/entities/concerns/navigable.rb +43 -0
- data/lib/lookbook/entities/entity.rb +53 -0
- data/lib/lookbook/entities/page.rb +80 -0
- data/lib/lookbook/entities/page_section.rb +43 -0
- data/lib/lookbook/entities/preview.rb +87 -0
- data/lib/lookbook/entities/preview_example.rb +100 -0
- data/lib/lookbook/entities/preview_group.rb +48 -0
- data/lib/lookbook/file_watcher.rb +47 -0
- data/lib/lookbook/lang.rb +12 -35
- data/lib/lookbook/param.rb +99 -0
- data/lib/lookbook/{preview_controller.rb → preview_actions.rb} +14 -3
- data/lib/lookbook/preview_parser.rb +53 -0
- data/lib/lookbook/process.rb +21 -0
- data/lib/lookbook/rendered_example.rb +37 -0
- data/lib/lookbook/services/code/code_beautifier.rb +21 -0
- data/lib/lookbook/services/code/code_highlighter.rb +69 -0
- data/lib/lookbook/services/code/code_indenter.rb +14 -0
- data/lib/lookbook/services/data/parsers/data_parser.rb +22 -0
- data/lib/lookbook/services/data/parsers/json_parser.rb +7 -0
- data/lib/lookbook/services/data/parsers/yaml_parser.rb +7 -0
- data/lib/lookbook/services/data/resolvers/data_resolver.rb +70 -0
- data/lib/lookbook/services/data/resolvers/eval_resolver.rb +10 -0
- data/lib/lookbook/services/data/resolvers/file_resolver.rb +28 -0
- data/lib/lookbook/services/data/resolvers/method_resolver.rb +10 -0
- data/lib/lookbook/services/data/resolvers/yaml_resolver.rb +18 -0
- data/lib/lookbook/services/entities/entity_tree_builder.rb +45 -0
- data/lib/lookbook/services/markdown_renderer.rb +29 -0
- data/lib/lookbook/services/position_prefix_parser.rb +16 -0
- data/lib/lookbook/services/string_value_caster.rb +60 -0
- data/lib/lookbook/services/tags/tag_options_parser.rb +62 -0
- data/lib/lookbook/services/templates/action_view_annotations_handler.rb +21 -0
- data/lib/lookbook/services/templates/action_view_annotations_stripper.rb +15 -0
- data/lib/lookbook/services/templates/frontmatter_extractor.rb +28 -0
- data/lib/lookbook/services/templates/styles_extractor.rb +38 -0
- data/lib/lookbook/services/{search_param_builder.rb → urls/search_param_builder.rb} +1 -1
- data/lib/lookbook/services/{search_param_parser.rb → urls/search_param_parser.rb} +1 -1
- data/lib/lookbook/stores/config_store.rb +12 -9
- data/lib/lookbook/stores/input_store.rb +7 -3
- data/lib/lookbook/stores/panel_store.rb +2 -2
- data/lib/lookbook/stores/tag_store.rb +3 -5
- data/lib/lookbook/support/null_object.rb +10 -0
- data/lib/lookbook/support/service.rb +2 -2
- data/lib/lookbook/support/store.rb +2 -35
- data/lib/lookbook/support/tree_node.rb +87 -0
- data/lib/lookbook/support/utils/path_utils.rb +32 -5
- data/lib/lookbook/support/utils/utils.rb +24 -0
- data/lib/lookbook/tags/component_tag.rb +13 -0
- data/lib/lookbook/tags/custom_tag.rb +61 -0
- data/lib/lookbook/tags/display_tag.rb +15 -0
- data/lib/lookbook/tags/hidden_tag.rb +13 -0
- data/lib/lookbook/tags/id_tag.rb +7 -0
- data/lib/lookbook/tags/label_tag.rb +4 -0
- data/lib/lookbook/tags/logical_path_tag.rb +7 -0
- data/lib/lookbook/tags/param_tag.rb +63 -0
- data/lib/lookbook/tags/position_tag.rb +16 -0
- data/lib/lookbook/tags/source_tag.rb +7 -0
- data/lib/lookbook/tags/tag_provider.rb +18 -0
- data/lib/lookbook/tags/yard_tag.rb +90 -0
- data/lib/lookbook/theme.rb +8 -0
- data/lib/lookbook/version.rb +1 -1
- data/lib/lookbook/websocket.rb +60 -0
- data/lib/lookbook.rb +13 -8
- data/public/lookbook-assets/css/lookbook.css +487 -411
- data/public/lookbook-assets/css/lookbook.css.map +1 -1
- data/public/lookbook-assets/css/themes/blue.css +3 -1
- data/public/lookbook-assets/css/themes/blue.css.map +1 -1
- data/public/lookbook-assets/css/themes/green.css +68 -0
- data/public/lookbook-assets/css/themes/green.css.map +1 -0
- data/public/lookbook-assets/css/themes/indigo.css +3 -1
- data/public/lookbook-assets/css/themes/indigo.css.map +1 -1
- data/public/lookbook-assets/css/themes/rose.css +68 -0
- data/public/lookbook-assets/css/themes/rose.css.map +1 -0
- data/public/lookbook-assets/css/themes/zinc.css +3 -1
- data/public/lookbook-assets/css/themes/zinc.css.map +1 -1
- data/public/lookbook-assets/js/embed.js +10 -1
- data/public/lookbook-assets/js/embed.js.map +1 -1
- data/public/lookbook-assets/js/lookbook.js +358 -629
- data/public/lookbook-assets/js/lookbook.js.map +1 -1
- metadata +96 -44
- data/app/components/lookbook/code/highlight_github_light.css +0 -217
- data/app/views/lookbook/previews/panels/_params.html.erb +0 -15
- data/lib/lookbook/code_formatter.rb +0 -68
- data/lib/lookbook/collection.rb +0 -161
- data/lib/lookbook/component.rb +0 -34
- data/lib/lookbook/entity.rb +0 -47
- data/lib/lookbook/markdown.rb +0 -22
- data/lib/lookbook/page.rb +0 -195
- data/lib/lookbook/page_collection.rb +0 -19
- data/lib/lookbook/page_section.rb +0 -29
- data/lib/lookbook/params.rb +0 -157
- data/lib/lookbook/parser.rb +0 -42
- data/lib/lookbook/preview.rb +0 -174
- data/lib/lookbook/preview_collection.rb +0 -23
- data/lib/lookbook/preview_example.rb +0 -93
- data/lib/lookbook/preview_group.rb +0 -62
- data/lib/lookbook/source_inspector.rb +0 -95
- data/lib/lookbook/support/utils/attribute_utils.rb +0 -9
- data/lib/lookbook/tag.rb +0 -122
- data/lib/lookbook/tag_options.rb +0 -111
- data/lib/lookbook/tags.rb +0 -17
- data/lib/lookbook/template_parser.rb +0 -72
- data/lib/lookbook/utils.rb +0 -105
@@ -0,0 +1,41 @@
|
|
1
|
+
module Lookbook
|
2
|
+
class PreviewCollection < EntityCollection
|
3
|
+
include HierarchicalCollection
|
4
|
+
|
5
|
+
def find_example_by_path(lookup_path)
|
6
|
+
examples.find_by_path(lookup_path)
|
7
|
+
end
|
8
|
+
|
9
|
+
def find_by_preview_class(klass)
|
10
|
+
find { |preview| preview.preview_class.name == klass.to_s }
|
11
|
+
end
|
12
|
+
|
13
|
+
def load(code_objects)
|
14
|
+
@entities = []
|
15
|
+
clear_cache
|
16
|
+
|
17
|
+
previews = Array(code_objects).map { |obj| PreviewCollection.preview_from_code_object(obj) }.compact
|
18
|
+
add(previews)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.preview_from_code_object(code_object)
|
22
|
+
klass = code_object.path.constantize
|
23
|
+
Preview.new(code_object) if preview_class?(klass)
|
24
|
+
rescue => exception
|
25
|
+
Lookbook.logger.error exception.to_s
|
26
|
+
nil
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.preview_class?(klass)
|
30
|
+
if klass.ancestors.include?(ViewComponent::Preview)
|
31
|
+
!klass.respond_to?(:abstract_class) || klass.abstract_class != true
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
protected
|
36
|
+
|
37
|
+
def examples
|
38
|
+
@_cache[:examples] ||= PreviewExampleCollection.new(flat_map(&:examples))
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Lookbook
|
2
|
+
class Component < Entity
|
3
|
+
include Locatable
|
4
|
+
|
5
|
+
attr_reader :component_class
|
6
|
+
|
7
|
+
def initialize(component_class)
|
8
|
+
@component_class = component_class
|
9
|
+
@file_path = "#{Engine.component_paths.first}/#{name.underscore}.rb"
|
10
|
+
@base_directories = Engine.component_paths
|
11
|
+
@lookup_path = PathUtils.to_lookup_path(relative_file_path)
|
12
|
+
end
|
13
|
+
|
14
|
+
def name
|
15
|
+
component_class.name
|
16
|
+
end
|
17
|
+
|
18
|
+
def template_file_path
|
19
|
+
Dir.glob("#{directory_path}/#{file_name(true)}.*.erb").first
|
20
|
+
end
|
21
|
+
|
22
|
+
def inline?
|
23
|
+
template_file_path.present?
|
24
|
+
end
|
25
|
+
|
26
|
+
def template_path
|
27
|
+
Lookbook.logger.warn "The `template_path` method has been deprecated - use `template_file_path` instead. `template_file_path` will be removed in v2.0"
|
28
|
+
template_file_path
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Lookbook
|
2
|
+
module Annotatable
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
delegate :has_tag?, to: :code_object
|
7
|
+
|
8
|
+
def notes
|
9
|
+
code_object.docstring.to_s.strip
|
10
|
+
end
|
11
|
+
|
12
|
+
def tags(name = nil)
|
13
|
+
code_object.tags(name)
|
14
|
+
end
|
15
|
+
|
16
|
+
def tag(name = nil)
|
17
|
+
tags(name).first
|
18
|
+
end
|
19
|
+
|
20
|
+
protected
|
21
|
+
|
22
|
+
attr_reader :code_object
|
23
|
+
|
24
|
+
def fetch_config(key, fallback = nil, &block)
|
25
|
+
value = case key.to_sym
|
26
|
+
when :components
|
27
|
+
components_config
|
28
|
+
when :display_options
|
29
|
+
display_options_config
|
30
|
+
else
|
31
|
+
tag(key).value if has_tag?(key)
|
32
|
+
end
|
33
|
+
|
34
|
+
Utils.value_or_fallback(value, fallback, &block)
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def components_config
|
40
|
+
return unless has_tag?(:component)
|
41
|
+
|
42
|
+
Array(tags(:component)).map(&:value).compact
|
43
|
+
end
|
44
|
+
|
45
|
+
def display_options_config
|
46
|
+
return unless has_tag?(:display)
|
47
|
+
|
48
|
+
# Dynamic params set at the entity level are
|
49
|
+
# not (yet?) supported so filter them out.
|
50
|
+
display_tags = tags(:display).select do |tag|
|
51
|
+
!tag.value.is_a?(Hash) && !tag.value.is_a?(Array)
|
52
|
+
end
|
53
|
+
|
54
|
+
display_tags.map { |tag| [tag.key.to_sym, tag.value] }.to_h
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Lookbook
|
2
|
+
module Inspectable
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
def source
|
7
|
+
source_code = if custom_source?
|
8
|
+
File.read(source_file_path)
|
9
|
+
else
|
10
|
+
src = CodeIndenter.call(code_object.source)
|
11
|
+
begin
|
12
|
+
send(:format_source, src)
|
13
|
+
rescue NoMethodError
|
14
|
+
src
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
source_code.strip_heredoc.strip
|
19
|
+
end
|
20
|
+
|
21
|
+
def source_lang
|
22
|
+
custom_source? ? Lang.guess(source_file_path, :ruby) : Lang.find(:ruby)
|
23
|
+
end
|
24
|
+
|
25
|
+
def custom_source?
|
26
|
+
source_file_path.present?
|
27
|
+
end
|
28
|
+
|
29
|
+
protected
|
30
|
+
|
31
|
+
attr_reader :code_object
|
32
|
+
|
33
|
+
def source_file_path
|
34
|
+
@_source_path ||= if code_object.has_tag?(:source)
|
35
|
+
source_path = code_object.tag(:source).value
|
36
|
+
unless source_path.present? && File.exist?(source_path)
|
37
|
+
raise LookbookError, "Could not find source file '#{source_path}'"
|
38
|
+
end
|
39
|
+
source_path
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module Lookbook
|
2
|
+
module Locatable
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
attr_reader :file_path, :base_directories
|
7
|
+
|
8
|
+
def file_name(strip_ext = false)
|
9
|
+
basename = file_pathname.basename
|
10
|
+
(strip_ext ? basename.to_s.split(".").first : basename).to_s
|
11
|
+
end
|
12
|
+
|
13
|
+
def file_name_base
|
14
|
+
@_file_name_slug ||= file_name(true).gsub(/(_component_preview|component_preview|preview)$/, "")
|
15
|
+
end
|
16
|
+
|
17
|
+
def file_extension
|
18
|
+
@_file_extension ||= file_pathname.extname
|
19
|
+
end
|
20
|
+
|
21
|
+
def directory_path
|
22
|
+
@_directory_path ||= Pathname(file_pathname.dirname)
|
23
|
+
end
|
24
|
+
|
25
|
+
def relative_file_path
|
26
|
+
@_relative_file_path ||= file_pathname.relative_path_from(base_directory)
|
27
|
+
end
|
28
|
+
|
29
|
+
def relative_directory_path
|
30
|
+
@_relative_directory_path ||= directory_path.relative_path_from(base_directory)
|
31
|
+
end
|
32
|
+
|
33
|
+
def last_modified
|
34
|
+
@_last_modified ||= File.mtime(file_path)
|
35
|
+
end
|
36
|
+
|
37
|
+
def logical_path
|
38
|
+
return @_logical_path if @_logical_path
|
39
|
+
|
40
|
+
directory = fetch_config(:logical_path) { relative_directory_path.to_s }
|
41
|
+
@_logical_path ||= PathUtils.to_path(directory, file_name_base)
|
42
|
+
end
|
43
|
+
|
44
|
+
def full_path
|
45
|
+
Lookbook.logger.warn "The `full_path` method has been deprecated - use `file_path` instead. `full_path` will be removed in v2.0"
|
46
|
+
file_path
|
47
|
+
end
|
48
|
+
|
49
|
+
def rel_path
|
50
|
+
Lookbook.logger.warn "The `rel_path` method has been deprecated - use `relative_file_path` instead. `rel_path` will be removed in v2.0"
|
51
|
+
relative_file_path
|
52
|
+
end
|
53
|
+
|
54
|
+
def dir_path
|
55
|
+
Lookbook.logger.warn "The `dir_path` method has been deprecated - use `directory_path` instead. `dir_path` will be removed in v2.0"
|
56
|
+
directory_path
|
57
|
+
end
|
58
|
+
|
59
|
+
protected
|
60
|
+
|
61
|
+
def file_pathname
|
62
|
+
Pathname(file_path)
|
63
|
+
end
|
64
|
+
|
65
|
+
def base_directory
|
66
|
+
return @_base_directory if @_base_directory
|
67
|
+
|
68
|
+
directories = Array(base_directories).map(&:to_s).sort_by { |path| path.split("/").size }.reverse
|
69
|
+
@_base_directory ||= directories.find { |dir| file_path.to_s.start_with?(dir) }
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Lookbook
|
2
|
+
module Navigable
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
def hidden?
|
7
|
+
fetch_config(:hidden, false)
|
8
|
+
end
|
9
|
+
|
10
|
+
def visible?
|
11
|
+
!hidden?
|
12
|
+
end
|
13
|
+
|
14
|
+
def position
|
15
|
+
return @_position if @_position
|
16
|
+
|
17
|
+
pos = if @position_prefixes && respond_to?(:file_name)
|
18
|
+
PositionPrefixParser.call(file_name).first || default_position
|
19
|
+
else
|
20
|
+
fetch_config(:position, default_position)
|
21
|
+
end
|
22
|
+
|
23
|
+
@_position ||= pos.to_i
|
24
|
+
end
|
25
|
+
|
26
|
+
def depth
|
27
|
+
path.split("/").size
|
28
|
+
end
|
29
|
+
|
30
|
+
def default_position
|
31
|
+
@default_position || 10000
|
32
|
+
end
|
33
|
+
|
34
|
+
def <=>(other)
|
35
|
+
if respond_to?(:sort_handler, true)
|
36
|
+
sort_handler(other)
|
37
|
+
else
|
38
|
+
[position, label] <=> [other.position, other.label]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Lookbook
|
2
|
+
class Entity
|
3
|
+
include Comparable
|
4
|
+
include Lookbook::Engine.routes.url_helpers
|
5
|
+
|
6
|
+
def initialize(lookup_path = nil)
|
7
|
+
@lookup_path = lookup_path
|
8
|
+
end
|
9
|
+
|
10
|
+
def id
|
11
|
+
Utils.id(fetch_config(:id) { lookup_path.tr("/", "-") })
|
12
|
+
end
|
13
|
+
|
14
|
+
def name
|
15
|
+
@_name ||= Utils.name(File.basename(@lookup_path))
|
16
|
+
end
|
17
|
+
|
18
|
+
def label
|
19
|
+
@_label ||= fetch_config(:label) { name.titleize }
|
20
|
+
end
|
21
|
+
|
22
|
+
def lookup_path
|
23
|
+
return @_lookup_path if @_lookup_path
|
24
|
+
|
25
|
+
directory = fetch_config(:logical_path) do
|
26
|
+
dir = File.dirname(@lookup_path)
|
27
|
+
dir if !dir.start_with?(".")
|
28
|
+
end
|
29
|
+
@_lookup_path ||= PathUtils.strip_slashes(PathUtils.to_path(directory, name))
|
30
|
+
end
|
31
|
+
|
32
|
+
def url_path
|
33
|
+
nil
|
34
|
+
end
|
35
|
+
|
36
|
+
def type
|
37
|
+
@_type ||= self.class.name.demodulize.underscore.downcase.to_sym
|
38
|
+
end
|
39
|
+
|
40
|
+
def <=>(other)
|
41
|
+
label <=> other.label
|
42
|
+
end
|
43
|
+
|
44
|
+
alias_method :path, :lookup_path
|
45
|
+
alias_method :logical_path, :lookup_path
|
46
|
+
|
47
|
+
protected
|
48
|
+
|
49
|
+
def fetch_config(key, fallback = nil, &block)
|
50
|
+
Utils.value_or_fallback(nil, fallback, &block)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module Lookbook
|
2
|
+
class Page < Entity
|
3
|
+
include Locatable
|
4
|
+
include Navigable
|
5
|
+
|
6
|
+
attr_reader :content, :sections
|
7
|
+
|
8
|
+
def initialize(file_path)
|
9
|
+
@file_path = Pathname(file_path)
|
10
|
+
@base_directories = Engine.page_paths
|
11
|
+
@lookup_path = PathUtils.to_lookup_path(relative_file_path)
|
12
|
+
@frontmatter, @content = FrontmatterExtractor.call(file_contents)
|
13
|
+
@position_prefixes = true
|
14
|
+
@sections = []
|
15
|
+
end
|
16
|
+
|
17
|
+
def title
|
18
|
+
@_title ||= fetch_config(:title, label)
|
19
|
+
end
|
20
|
+
|
21
|
+
def landing?
|
22
|
+
@_landing ||= fetch_config(:landing, false)
|
23
|
+
end
|
24
|
+
|
25
|
+
def markdown?
|
26
|
+
@_markdown ||= fetch_config(:markdown) { file_path.to_s.match?(/(.*)\.md\.(.*)$/) }
|
27
|
+
end
|
28
|
+
|
29
|
+
def header?
|
30
|
+
@_header ||= fetch_config(:header, true)
|
31
|
+
end
|
32
|
+
|
33
|
+
def footer?
|
34
|
+
@_footer ||= fetch_config(:footer, true)
|
35
|
+
end
|
36
|
+
|
37
|
+
def data
|
38
|
+
return @_data if @_data
|
39
|
+
|
40
|
+
config_data = fetch_config(:data, {})
|
41
|
+
@_data ||= config_data.is_a?(Hash) ? Store.new(config_data) : config_data
|
42
|
+
end
|
43
|
+
|
44
|
+
def search_terms
|
45
|
+
label
|
46
|
+
end
|
47
|
+
|
48
|
+
def url_path
|
49
|
+
lookbook_page_path(path)
|
50
|
+
end
|
51
|
+
|
52
|
+
def add_section(section)
|
53
|
+
@sections << section
|
54
|
+
@sections.sort_by! { |section| [section.position, section.label] }
|
55
|
+
end
|
56
|
+
|
57
|
+
def method_missing(method_name, *args, &block)
|
58
|
+
method_name.to_s.end_with?("=") ? super : frontmatter.fetch(method_name, nil)
|
59
|
+
end
|
60
|
+
|
61
|
+
def respond_to_missing?(method_name, include_private = false)
|
62
|
+
frontmatter.key?(method_name) || super
|
63
|
+
end
|
64
|
+
|
65
|
+
protected
|
66
|
+
|
67
|
+
def fetch_config(key, fallback = nil, &block)
|
68
|
+
value = frontmatter[key]
|
69
|
+
Utils.value_or_fallback(value, fallback, &block)
|
70
|
+
end
|
71
|
+
|
72
|
+
def file_contents
|
73
|
+
@_file_contents ||= File.read(file_path)
|
74
|
+
end
|
75
|
+
|
76
|
+
def frontmatter
|
77
|
+
@_merged_frontmatter ||= Lookbook.config.page_options.deep_merge(@frontmatter.to_h).deep_symbolize_keys
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Lookbook
|
2
|
+
class PageSection < Page
|
3
|
+
attr_accessor :parent
|
4
|
+
|
5
|
+
def initialize(file_path)
|
6
|
+
@file_path = Pathname(file_path)
|
7
|
+
@parent = nil
|
8
|
+
super
|
9
|
+
end
|
10
|
+
|
11
|
+
def name
|
12
|
+
Utils.name(name_parts[:name])
|
13
|
+
end
|
14
|
+
|
15
|
+
def lookup_path
|
16
|
+
directory = if relative_directory_path.present? && !relative_directory_path.to_s.start_with?(".")
|
17
|
+
relative_directory_path
|
18
|
+
end
|
19
|
+
|
20
|
+
path = PathUtils.to_path(directory, name_parts[:parent_name])
|
21
|
+
PathUtils.to_lookup_path(path)
|
22
|
+
end
|
23
|
+
|
24
|
+
def landing?
|
25
|
+
false
|
26
|
+
end
|
27
|
+
|
28
|
+
def url_path
|
29
|
+
nil
|
30
|
+
end
|
31
|
+
|
32
|
+
alias_method :page, :parent
|
33
|
+
|
34
|
+
protected
|
35
|
+
|
36
|
+
def name_parts
|
37
|
+
return @_name_parts if @_name_parts
|
38
|
+
|
39
|
+
matches = file_name(true).match(/(?<parent_name>.*)\[(?<name>.*)\]/)
|
40
|
+
@_name_parts ||= {name: matches[:name], parent_name: matches[:parent_name]}
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module Lookbook
|
2
|
+
class Preview < Entity
|
3
|
+
include Annotatable
|
4
|
+
include Locatable
|
5
|
+
include Navigable
|
6
|
+
|
7
|
+
delegate :render_args, to: :preview_class
|
8
|
+
|
9
|
+
attr_reader :preview_class
|
10
|
+
|
11
|
+
def initialize(code_object)
|
12
|
+
@code_object = code_object
|
13
|
+
@preview_class = code_object.path.constantize
|
14
|
+
@file_path = Pathname(code_object.file)
|
15
|
+
@base_directories = Engine.preview_paths
|
16
|
+
|
17
|
+
cleaned_path = relative_file_path.to_s
|
18
|
+
.gsub(/\/(component_preview|preview)(\..*)$/, "")
|
19
|
+
.gsub(/(_component_preview|_preview)(\..*)$/, "")
|
20
|
+
|
21
|
+
@lookup_path = PathUtils.to_lookup_path(cleaned_path)
|
22
|
+
end
|
23
|
+
|
24
|
+
def examples
|
25
|
+
@_examples ||= PreviewExampleCollection.new(load_examples)
|
26
|
+
end
|
27
|
+
|
28
|
+
def example(example_name)
|
29
|
+
examples.find { |m| m.name == example_name.to_s }
|
30
|
+
end
|
31
|
+
|
32
|
+
def visible_examples
|
33
|
+
@_visible_examples ||= PreviewExampleCollection.new(examples.select(&:visible?))
|
34
|
+
end
|
35
|
+
|
36
|
+
def default_example
|
37
|
+
visible_examples.first
|
38
|
+
end
|
39
|
+
|
40
|
+
def components
|
41
|
+
@_components ||= ComponentCollection.new(examples.flat_map(&:components).uniq(&:path))
|
42
|
+
end
|
43
|
+
|
44
|
+
def component
|
45
|
+
components.first
|
46
|
+
end
|
47
|
+
|
48
|
+
def display_options
|
49
|
+
global_options = Lookbook.config.preview_display_options
|
50
|
+
global_options.deep_merge(fetch_config(:display_options, {}))
|
51
|
+
end
|
52
|
+
|
53
|
+
def layout
|
54
|
+
preview_class.instance_variable_get(:@layout)
|
55
|
+
end
|
56
|
+
|
57
|
+
def url_path
|
58
|
+
lookbook_inspect_path(path)
|
59
|
+
end
|
60
|
+
|
61
|
+
def preview_class_name
|
62
|
+
preview_class.name
|
63
|
+
end
|
64
|
+
|
65
|
+
def guess_components
|
66
|
+
[preview_class.name.chomp("Preview").constantize]
|
67
|
+
rescue
|
68
|
+
[]
|
69
|
+
end
|
70
|
+
|
71
|
+
protected
|
72
|
+
|
73
|
+
def load_examples
|
74
|
+
return example_entities unless code_object.groups.any?
|
75
|
+
|
76
|
+
example_entities.group_by(&:group).flat_map do |group_name, grouped_examples|
|
77
|
+
group_name.nil? ? grouped_examples : PreviewGroup.new(group_name.presence || label.pluralize, grouped_examples, self)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def example_entities
|
82
|
+
public_methods = preview_class.public_instance_methods(false)
|
83
|
+
method_objects = code_object.meths.select { |m| public_methods.include?(m.name) }
|
84
|
+
method_objects.map.with_index { |code_object, i| PreviewExample.new(code_object, self, position: i) }
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
module Lookbook
|
2
|
+
class PreviewExample < Entity
|
3
|
+
include Inspectable
|
4
|
+
include Annotatable
|
5
|
+
include Navigable
|
6
|
+
|
7
|
+
delegate :group, to: :code_object
|
8
|
+
|
9
|
+
attr_reader :preview
|
10
|
+
|
11
|
+
def initialize(code_object, preview, position: nil)
|
12
|
+
@code_object = code_object
|
13
|
+
@preview = preview
|
14
|
+
@default_position = position
|
15
|
+
@lookup_path = "#{parent.lookup_path}/#{name}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def id
|
19
|
+
@_id ||= Utils.id(fetch_config(:id) { "#{parent.id}-#{code_object.name}" })
|
20
|
+
end
|
21
|
+
|
22
|
+
def name
|
23
|
+
@_name ||= Utils.name(code_object.name)
|
24
|
+
end
|
25
|
+
|
26
|
+
def display_options
|
27
|
+
parent.display_options.merge(fetch_config(:display_options, {}))
|
28
|
+
end
|
29
|
+
|
30
|
+
def components
|
31
|
+
@_components ||= ComponentCollection.new(load_components)
|
32
|
+
end
|
33
|
+
|
34
|
+
def component
|
35
|
+
components.first
|
36
|
+
end
|
37
|
+
|
38
|
+
def examples
|
39
|
+
[self]
|
40
|
+
end
|
41
|
+
|
42
|
+
def template_source(template_path)
|
43
|
+
source_path = template_file_path(template_path)
|
44
|
+
source_path ? File.read(source_path) : nil
|
45
|
+
end
|
46
|
+
|
47
|
+
def template_lang(template_path)
|
48
|
+
path = template_file_path(template_path)
|
49
|
+
Lookbook::Lang.guess(path) || Lookbook::Lang.find(:html)
|
50
|
+
end
|
51
|
+
|
52
|
+
def search_terms
|
53
|
+
[parent.label, label]
|
54
|
+
end
|
55
|
+
|
56
|
+
def url_path
|
57
|
+
lookbook_inspect_path(path)
|
58
|
+
end
|
59
|
+
|
60
|
+
def type
|
61
|
+
:example
|
62
|
+
end
|
63
|
+
|
64
|
+
alias_method :parent, :preview
|
65
|
+
alias_method :lang, :source_lang
|
66
|
+
|
67
|
+
protected
|
68
|
+
|
69
|
+
def sort_handler(other_entity)
|
70
|
+
if Lookbook.config.sort_examples
|
71
|
+
label <=> other_entity.label
|
72
|
+
else
|
73
|
+
[position, label] <=> [other_entity.position, other_entity.label]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def format_source(source)
|
78
|
+
source.sub(/^def \w+\s?(\([^)]+\))?/m, "").split("\n")[0..-2].join("\n")
|
79
|
+
end
|
80
|
+
|
81
|
+
def template_file_path(template_path)
|
82
|
+
return full_template_path(template_path) if respond_to?(:full_template_path, true)
|
83
|
+
|
84
|
+
template_path = template_path.to_s.sub(/\..*$/, "")
|
85
|
+
base_path = Engine.preview_paths.detect do |p|
|
86
|
+
Dir["#{p}/#{template_path}.html.*"].first
|
87
|
+
end
|
88
|
+
path = Dir["#{base_path}/#{template_path}.html.*"].first
|
89
|
+
Pathname(path) if path
|
90
|
+
end
|
91
|
+
|
92
|
+
def load_components
|
93
|
+
component_classes = [*fetch_config(:components, []), *preview.send(:fetch_config, :components, [])]
|
94
|
+
component_classes = preview.guess_components if component_classes.empty?
|
95
|
+
|
96
|
+
components = component_classes.map { |klass| Component.new(klass) }
|
97
|
+
components.uniq(&:path)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|