lookbook 1.3.4 → 1.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +11 -11
  3. data/app/assets/lookbook/css/themes/blue.css +1 -1
  4. data/app/assets/lookbook/css/themes/green.css +1 -1
  5. data/app/assets/lookbook/css/themes/indigo.css +1 -1
  6. data/app/assets/lookbook/css/themes/rose.css +1 -1
  7. data/app/assets/lookbook/css/themes/zinc.css +1 -1
  8. data/app/components/lookbook/code/component.rb +2 -4
  9. data/app/components/lookbook/header/component.html.erb +1 -1
  10. data/app/components/lookbook/inspector_panel/component.rb +1 -1
  11. data/app/components/lookbook/nav/component.rb +8 -15
  12. data/app/components/lookbook/nav/directory/component.html.erb +28 -0
  13. data/app/components/lookbook/nav/directory/component.rb +4 -0
  14. data/app/components/lookbook/nav/{item → entity}/component.html.erb +7 -7
  15. data/app/components/lookbook/nav/entity/component.rb +49 -0
  16. data/app/components/lookbook/nav/item/component.css +15 -0
  17. data/app/components/lookbook/nav/item/component.js +4 -0
  18. data/app/components/lookbook/nav/item/component.rb +13 -56
  19. data/app/controllers/concerns/lookbook/targetable_concern.rb +13 -38
  20. data/app/controllers/lookbook/application_controller.rb +9 -7
  21. data/app/controllers/lookbook/page_controller.rb +2 -2
  22. data/app/controllers/lookbook/pages_controller.rb +9 -15
  23. data/app/helpers/lookbook/application_helper.rb +1 -1
  24. data/app/helpers/lookbook/page_helper.rb +7 -4
  25. data/app/views/layouts/lookbook/application.html.erb +3 -4
  26. data/app/views/layouts/lookbook/page.html.erb +2 -2
  27. data/app/views/layouts/lookbook/shell.html.erb +2 -2
  28. data/app/views/layouts/lookbook/skeleton.html.erb +7 -7
  29. data/app/views/lookbook/index.html.erb +3 -3
  30. data/app/views/lookbook/inspector/panels/_params.html.erb +2 -2
  31. data/config/languages.yml +41 -0
  32. data/config/panels.yml +1 -1
  33. data/config/tags.yml +4 -0
  34. data/lib/lookbook/engine.rb +65 -43
  35. data/lib/lookbook/entities/collections/component_collection.rb +4 -0
  36. data/lib/lookbook/entities/collections/concerns/hierarchical_collection.rb +23 -0
  37. data/lib/lookbook/entities/collections/entity_collection.rb +61 -0
  38. data/lib/lookbook/entities/collections/page_collection.rb +30 -0
  39. data/lib/lookbook/entities/collections/preview_collection.rb +35 -0
  40. data/lib/lookbook/entities/collections/preview_example_collection.rb +4 -0
  41. data/lib/lookbook/entities/component.rb +31 -0
  42. data/lib/lookbook/entities/concerns/annotatable.rb +58 -0
  43. data/lib/lookbook/entities/concerns/inspectable.rb +44 -0
  44. data/lib/lookbook/entities/concerns/locatable.rb +73 -0
  45. data/lib/lookbook/entities/concerns/navigable.rb +43 -0
  46. data/lib/lookbook/entities/entity.rb +53 -0
  47. data/lib/lookbook/entities/page.rb +80 -0
  48. data/lib/lookbook/entities/page_section.rb +43 -0
  49. data/lib/lookbook/entities/preview.rb +87 -0
  50. data/lib/lookbook/entities/preview_example.rb +100 -0
  51. data/lib/lookbook/entities/preview_group.rb +48 -0
  52. data/lib/lookbook/file_watcher.rb +1 -1
  53. data/lib/lookbook/lang.rb +12 -35
  54. data/lib/lookbook/param.rb +2 -2
  55. data/lib/lookbook/preview_parser.rb +1 -1
  56. data/lib/lookbook/rendered_example.rb +37 -0
  57. data/lib/lookbook/services/code/code_indenter.rb +14 -0
  58. data/lib/lookbook/services/data/resolvers/data_resolver.rb +2 -2
  59. data/lib/lookbook/services/data/resolvers/file_resolver.rb +1 -1
  60. data/lib/lookbook/services/data/resolvers/method_resolver.rb +1 -1
  61. data/lib/lookbook/services/entities/entity_tree_builder.rb +45 -0
  62. data/lib/lookbook/services/position_prefix_parser.rb +16 -0
  63. data/lib/lookbook/support/store.rb +0 -33
  64. data/lib/lookbook/support/tree_node.rb +87 -0
  65. data/lib/lookbook/support/utils/path_utils.rb +26 -2
  66. data/lib/lookbook/support/utils/utils.rb +24 -0
  67. data/lib/lookbook/tags/component_tag.rb +6 -0
  68. data/lib/lookbook/tags/custom_tag.rb +2 -0
  69. data/lib/lookbook/tags/id_tag.rb +1 -1
  70. data/lib/lookbook/tags/logical_path_tag.rb +3 -0
  71. data/lib/lookbook/tags/param_tag.rb +2 -0
  72. data/lib/lookbook/tags/source_tag.rb +7 -0
  73. data/lib/lookbook/tags/yard_tag.rb +35 -7
  74. data/lib/lookbook/version.rb +1 -1
  75. data/lib/lookbook.rb +11 -7
  76. data/public/lookbook-assets/css/lookbook.css +33 -21
  77. data/public/lookbook-assets/css/lookbook.css.map +1 -1
  78. data/public/lookbook-assets/js/lookbook.js +56 -55
  79. data/public/lookbook-assets/js/lookbook.js.map +1 -1
  80. metadata +35 -18
  81. data/lib/lookbook/collection.rb +0 -161
  82. data/lib/lookbook/component.rb +0 -34
  83. data/lib/lookbook/entity.rb +0 -47
  84. data/lib/lookbook/page.rb +0 -194
  85. data/lib/lookbook/page_collection.rb +0 -19
  86. data/lib/lookbook/page_section.rb +0 -29
  87. data/lib/lookbook/preview.rb +0 -181
  88. data/lib/lookbook/preview_collection.rb +0 -23
  89. data/lib/lookbook/preview_example.rb +0 -93
  90. data/lib/lookbook/preview_group.rb +0 -58
  91. data/lib/lookbook/source_inspector.rb +0 -76
  92. data/lib/lookbook/support/utils/attribute_utils.rb +0 -14
  93. data/lib/lookbook/utils.rb +0 -65
@@ -1,181 +0,0 @@
1
- module Lookbook
2
- class Preview < Collection
3
- include Utils
4
-
5
- delegate :name, :render_args, to: :@preview
6
- delegate :position, :group, :notes, :hidden?, :tags, :tag, to: :@preview_inspector
7
-
8
- def initialize(preview, code_object)
9
- @preview = preview
10
- @preview_inspector = SourceInspector.new(code_object, eval_scope: preview_class.new)
11
- preview_path = preview_class_path(name)
12
-
13
- if @preview_inspector.logical_path
14
- basename = preview_path.split("/").last
15
- preview_path = "#{@preview_inspector.logical_path}/#{basename}"
16
- end
17
-
18
- super(preview_path)
19
- end
20
-
21
- def id
22
- @preview_inspector&.id || generate_id(lookup_path)
23
- end
24
-
25
- def preview_class_name
26
- @preview.name
27
- end
28
-
29
- def preview_class
30
- @preview
31
- end
32
-
33
- def label
34
- @preview_inspector&.label&.presence || lookup_path.split("/").last.titleize
35
- end
36
-
37
- def type
38
- :preview
39
- end
40
-
41
- def example(example_name)
42
- examples.find { |m| m.name == example_name.to_s }
43
- end
44
-
45
- def examples
46
- return @examples if @examples.present?
47
- public_methods = @preview.public_instance_methods(false)
48
- public_method_objects = @preview_inspector&.methods&.select { |m| public_methods.include?(m.name) }
49
- examples = (public_method_objects || []).map { |m| PreviewExample.new(m.name.to_s, self, m) }
50
- sorted = Lookbook.config.sort_examples ? examples.sort_by(&:label) : examples
51
- @examples = []
52
- if @preview_inspector&.groups&.any?
53
- sorted.group_by { |m| m.group }.each do |name, examples|
54
- if name.nil?
55
- @examples += examples
56
- else
57
- name = label if name.strip == ""
58
- @examples << PreviewGroup.new(name.underscore, self, examples)
59
- end
60
- end
61
- else
62
- @examples = sorted
63
- end
64
- @examples = @examples.compact
65
- end
66
-
67
- def items
68
- examples.reject { |i| i.hidden? }
69
- end
70
-
71
- def default_example
72
- examples.first
73
- end
74
-
75
- def rel_path
76
- "#{name.underscore}.rb"
77
- end
78
-
79
- def full_path
80
- base_path = preview_paths.detect do |preview_path|
81
- Dir["#{preview_path}/#{rel_path}"].first
82
- end
83
- Pathname.new(Dir["#{base_path}/#{rel_path}"].first)
84
- end
85
-
86
- def url_path
87
- lookbook_inspect_path lookup_path
88
- end
89
-
90
- def parent_collections_names
91
- File.dirname(path).split("/")
92
- end
93
-
94
- def hierarchy_depth
95
- path.split("/").size
96
- end
97
-
98
- def layout
99
- @preview.instance_variable_get(:@layout)
100
- end
101
-
102
- def display_options
103
- Lookbook.config.preview_display_options.deep_merge(@preview_inspector&.display_options)
104
- end
105
-
106
- def collapsible?
107
- true
108
- end
109
-
110
- def component
111
- components.first
112
- end
113
-
114
- def components
115
- component_classes = @preview_inspector&.components&.any? ? @preview_inspector&.components : [guess_component]
116
- component_classes.map do |class_name|
117
- Component.new(class_name.to_s)
118
- end
119
- end
120
-
121
- def preview_paths
122
- PathUtils.normalize_all(Lookbook.config.preview_paths)
123
- end
124
-
125
- protected
126
-
127
- @preview_objects = nil
128
- @previews = nil
129
-
130
- def guess_component
131
- name.chomp("Preview").constantize
132
- rescue
133
- nil
134
- end
135
-
136
- class << self
137
- def find(path)
138
- all.find { |p| p.lookup_path == path }
139
- end
140
-
141
- def exists?(path)
142
- !!find(path)
143
- end
144
-
145
- def any?
146
- all.any?
147
- end
148
-
149
- def all
150
- if @previews.nil? && @preview_objects.present?
151
- previews = @preview_objects.map do |code_object|
152
- klass = code_object.path.constantize
153
- new(klass, code_object) if klass.ancestors.include?(ViewComponent::Preview)
154
- rescue => exception
155
- Lookbook.logger.error Lookbook::Error.new(exception)
156
- nil
157
- end.compact
158
-
159
- sorted_previews = previews.compact.sort_by { |preview| [preview.position, preview.label] }
160
- @previews = PreviewCollection.new(sorted_previews)
161
- @previews
162
- elsif !@preview_objects.present?
163
- PreviewCollection.new([])
164
- else
165
- @previews
166
- end
167
- end
168
-
169
- def errors
170
- @errors ||= []
171
- end
172
-
173
- def load!(preview_objects)
174
- @preview_objects = preview_objects
175
- @previews = nil
176
- end
177
- end
178
-
179
- alias_method :lookup_path, :path
180
- end
181
- end
@@ -1,23 +0,0 @@
1
- module Lookbook
2
- class PreviewCollection < Collection
3
- def id
4
- generate_id("preview-collection", lookup_path || "root")
5
- end
6
-
7
- def label
8
- "Previews"
9
- end
10
-
11
- def find_example(path)
12
- Lookbook::PreviewExample.all.find { |e| e.lookup_path == path }
13
- end
14
-
15
- def type
16
- :preview_collection
17
- end
18
-
19
- def self.describe_as
20
- "previews"
21
- end
22
- end
23
- end
@@ -1,93 +0,0 @@
1
- module Lookbook
2
- class PreviewExample < Entity
3
- attr_reader :name, :preview
4
- delegate :position, :group, :notes, :hidden?, :source, :tags, :tag, to: :@example_inspector
5
-
6
- def initialize(name, preview, code_object)
7
- @name = name
8
- @preview = preview
9
- @example_inspector = SourceInspector.new(code_object, eval_scope: @preview.preview_class.new)
10
- super("#{@preview.path}/#{name}")
11
- end
12
-
13
- def id
14
- @example_inspector&.id || generate_id(@preview.id, name)
15
- end
16
-
17
- def url_path
18
- lookbook_inspect_path lookup_path
19
- end
20
-
21
- def label
22
- @example_inspector.label.presence || name.titleize
23
- end
24
-
25
- def display_options
26
- @preview.display_options.merge(@example_inspector.display_options)
27
- end
28
-
29
- def method_source
30
- @example_inspector.source.sub(/^def \w+\s?(\([^)]+\))?/m, "").split("\n")[0..-2].join("\n").strip_heredoc.strip
31
- end
32
-
33
- def lang
34
- Lookbook::Lang.find(:ruby)
35
- end
36
-
37
- def template_source(template_path)
38
- source_path = full_template_path(template_path)
39
- source_path ? File.read(source_path) : nil
40
- end
41
-
42
- def template_lang(template_path)
43
- Lookbook::Lang.guess(full_template_path(template_path)) || Lookbook::Lang.find(:html)
44
- end
45
-
46
- def type
47
- :example
48
- end
49
-
50
- def matchers
51
- normalize_matchers(@preview.label, label)
52
- end
53
-
54
- def hierarchy_depth
55
- @preview.hierarchy_depth + 1
56
- end
57
-
58
- protected
59
-
60
- def strip_ext(path)
61
- path.sub(/\..*$/, "")
62
- end
63
-
64
- def full_template_path(template_path)
65
- template_path = strip_ext template_path
66
- base_path = preview_paths.detect do |p|
67
- Dir["#{p}/#{template_path}.html.*"].first
68
- end
69
- path = Dir["#{base_path}/#{template_path}.html.*"].first
70
- path ? Pathname.new(path) : nil
71
- end
72
-
73
- def preview_paths
74
- PathUtils.normalize_all(Lookbook.config.preview_paths)
75
- end
76
-
77
- class << self
78
- def all
79
- Preview.all.map { |preview| preview.examples }.flatten
80
- end
81
-
82
- def find(path)
83
- all.find { |p| p.lookup_path == path }
84
- end
85
-
86
- def exists?(path)
87
- !!find(path)
88
- end
89
- end
90
-
91
- alias_method :lookup_path, :path
92
- end
93
- end
@@ -1,58 +0,0 @@
1
- module Lookbook
2
- class PreviewGroup < Entity
3
- attr_reader :name, :examples, :preview
4
-
5
- def initialize(name, preview, examples)
6
- @name = name
7
- @preview = preview
8
- @examples = examples
9
- super("#{@preview.path}/#{name}")
10
- end
11
-
12
- def url_path
13
- lookbook_inspect_path lookup_path
14
- end
15
-
16
- def label
17
- name.titleize
18
- end
19
-
20
- def type
21
- :group
22
- end
23
-
24
- def display_options
25
- merged = {}
26
- examples.reverse.map do |example|
27
- merged.merge! example.display_options
28
- end
29
- merged
30
- end
31
-
32
- def hidden?
33
- false
34
- end
35
-
36
- def position
37
- 10000
38
- end
39
-
40
- def matchers
41
- normalize_matchers(@preview.label, label)
42
- end
43
-
44
- def hierarchy_depth
45
- @preview.hierarchy_depth + 1
46
- end
47
-
48
- def tags(name = nil)
49
- examples.map { |example| example.tags(name) }.flatten
50
- end
51
-
52
- def tag(name = nil)
53
- tags(name).first
54
- end
55
-
56
- alias_method :lookup_path, :path
57
- end
58
- end
@@ -1,76 +0,0 @@
1
- module Lookbook
2
- class SourceInspector
3
- include Utils
4
-
5
- attr_reader :code_object
6
- delegate :groups, :source, to: :@code_object, allow_nil: true
7
-
8
- def initialize(code_object, eval_scope: nil)
9
- @code_object = code_object
10
- @eval_scope = eval_scope
11
- end
12
-
13
- def hidden?
14
- @hidden ||= tag_value(:hidden) || false
15
- end
16
-
17
- def id
18
- @id ||= tag_value(:id)
19
- end
20
-
21
- def label
22
- @label ||= tag_value(:label)
23
- end
24
-
25
- def notes
26
- @notes ||= code_object.docstring&.to_s&.strip
27
- end
28
-
29
- def group
30
- @group ||= code_object.group
31
- end
32
-
33
- def position
34
- @position ||= tag_value(:position) || 10000
35
- end
36
-
37
- def components
38
- @components ||= Array(code_object.tags(:component)).map(&:value)
39
- end
40
-
41
- def logical_path
42
- path = tag_value(:logical_path)
43
- path&.delete_prefix("/")&.delete_suffix("/")
44
- end
45
-
46
- def display_options
47
- return @display_options unless @display_options.nil?
48
-
49
- # Dynamic params set at the entity level are
50
- # not (yet?) supported so filter them out.
51
- display_tags = Array(code_object.tags(:display)).select do |tag|
52
- !(tag.value.is_a?(Array) || tag.value.is_a?(Hash))
53
- end
54
-
55
- display_tags.map { |tag| [tag.key.to_sym, tag.value] }.to_h
56
- end
57
-
58
- def methods
59
- @methods ||= code_object.meths
60
- end
61
-
62
- def tags(name = nil)
63
- code_object.tags(name)
64
- end
65
-
66
- def tag(name = nil)
67
- tags(name).first
68
- end
69
-
70
- protected
71
-
72
- def tag_value(tag_name)
73
- code_object.tag(tag_name).value if code_object.has_tag?(tag_name)
74
- end
75
- end
76
- end
@@ -1,14 +0,0 @@
1
- module Lookbook
2
- module AttributeUtils
3
- class << self
4
- def dom_id(*args)
5
- entity_id(["lookbook", *args])
6
- end
7
-
8
- def entity_id(*args)
9
- parts = args.map { |arg| arg.to_s.force_encoding("UTF-8").parameterize.dasherize }
10
- parts.join("-").tr("/_", "-").delete_prefix("-").delete_suffix("-").gsub("--", "-")
11
- end
12
- end
13
- end
14
- end
@@ -1,65 +0,0 @@
1
- module Lookbook
2
- module Utils
3
- include Lookbook::Engine.routes.url_helpers
4
-
5
- POSITION_PREFIX_REGEX = /^(\d+?)[-_]/
6
- FRONTMATTER_REGEX = /\A---(.|\n)*?---/
7
-
8
- protected
9
-
10
- def generate_id(*args)
11
- parts = args.map { |arg| arg.to_s.force_encoding("UTF-8").parameterize.underscore }
12
- parts.join("-").tr("/_", "-").delete_prefix("-").delete_suffix("-").gsub("--", "-")
13
- end
14
-
15
- def preview_class_basename(klass)
16
- class_name(klass).to_s.chomp("ComponentPreview").chomp("Component::Preview").chomp("::Preview").chomp("Component").chomp("Preview").chomp("::")
17
- end
18
-
19
- def preview_class_path(klass)
20
- preview_class_basename(klass).underscore
21
- end
22
-
23
- def class_name(klass)
24
- klass.is_a?(Class) ? klass.name : klass
25
- end
26
-
27
- def normalize_matchers(*matchers)
28
- matchers.flatten.map { |m| m.gsub(/\s/, "").downcase }
29
- end
30
-
31
- def get_position_prefix(str)
32
- parse_position_prefix(str).first
33
- end
34
-
35
- def remove_position_prefix(str)
36
- parse_position_prefix(str).last
37
- end
38
-
39
- def to_lookup_path(path)
40
- path.split("/").map { |segment| remove_position_prefix(segment) }.join("/")
41
- end
42
-
43
- def to_preview_path(*args)
44
- args.flatten.map { |arg| preview_class_path(arg) }.join("/")
45
- end
46
-
47
- protected
48
-
49
- def default_url_options
50
- {}
51
- end
52
-
53
- private
54
-
55
- def parse_position_prefix(str)
56
- pos = str.match(POSITION_PREFIX_REGEX)
57
- if pos.nil?
58
- [10000, str]
59
- else
60
- cleaned_str = str.gsub(POSITION_PREFIX_REGEX, "")
61
- [pos[1].to_i, cleaned_str]
62
- end
63
- end
64
- end
65
- end