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,45 @@
|
|
1
|
+
module Lookbook
|
2
|
+
class EntityTreeBuilder < Service
|
3
|
+
attr_reader :include_hidden
|
4
|
+
|
5
|
+
def initialize(entities, include_hidden: false)
|
6
|
+
@entities = entities.to_a
|
7
|
+
@include_hidden = include_hidden
|
8
|
+
end
|
9
|
+
|
10
|
+
def call
|
11
|
+
root_node = TreeNode.new
|
12
|
+
entities.each do |entity|
|
13
|
+
current_node = root_node
|
14
|
+
path_segments = parse_segments(entity.logical_path)
|
15
|
+
path_segments.each.with_index(1) do |segment, i|
|
16
|
+
name, position_prefix = segment
|
17
|
+
content = entity if entity.depth == i # entities are always on the leaf nodes
|
18
|
+
|
19
|
+
current_node.add_child(name, content, position: position_prefix) unless current_node.has_child?(name)
|
20
|
+
current_node = current_node.get_child(name)
|
21
|
+
|
22
|
+
if content && content.type == :preview
|
23
|
+
content.visible_examples.each do |example|
|
24
|
+
current_node.add_child(example.name, example)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
root_node
|
30
|
+
end
|
31
|
+
|
32
|
+
def parse_segments(path)
|
33
|
+
path.split("/").map do |segment|
|
34
|
+
unless segment.start_with?(".")
|
35
|
+
position, name = PositionPrefixParser.call(segment)
|
36
|
+
[name, position || 10000]
|
37
|
+
end
|
38
|
+
end.compact
|
39
|
+
end
|
40
|
+
|
41
|
+
def entities
|
42
|
+
include_hidden ? @entities : @entities.select(&:visible?)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "redcarpet"
|
2
|
+
|
3
|
+
module Lookbook
|
4
|
+
class MarkdownRenderer < Service
|
5
|
+
attr_reader :text, :opts
|
6
|
+
|
7
|
+
def initialize(text, opts = {})
|
8
|
+
@text = text
|
9
|
+
@opts = opts.to_h
|
10
|
+
end
|
11
|
+
|
12
|
+
def call
|
13
|
+
clean_text = ActionViewAnnotationsStripper.call(text)
|
14
|
+
md = Redcarpet::Markdown.new(LookbookMarkdownRenderer, opts)
|
15
|
+
md.render(clean_text).html_safe
|
16
|
+
end
|
17
|
+
|
18
|
+
class LookbookMarkdownRenderer < Redcarpet::Render::HTML
|
19
|
+
def block_code(code, language = "ruby")
|
20
|
+
line_numbers = language.to_s.end_with? "-numbered"
|
21
|
+
ApplicationController.render(Lookbook::Code::Component.new(**{
|
22
|
+
source: code,
|
23
|
+
language: language.to_s.chomp("-numbered"),
|
24
|
+
line_numbers: line_numbers
|
25
|
+
}), layout: nil)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Lookbook
|
2
|
+
class PositionPrefixParser < Service
|
3
|
+
POSITION_PREFIX_REGEX = /^(\d+?)[-_]/
|
4
|
+
|
5
|
+
attr_reader :input
|
6
|
+
|
7
|
+
def initialize(input)
|
8
|
+
@input = String(input)
|
9
|
+
end
|
10
|
+
|
11
|
+
def call
|
12
|
+
matches = input.match(POSITION_PREFIX_REGEX)
|
13
|
+
matches ? [matches[1].to_i, input.gsub(POSITION_PREFIX_REGEX, "")] : [nil, input]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require "active_model"
|
2
|
+
|
3
|
+
module Lookbook
|
4
|
+
class StringValueCaster < Service
|
5
|
+
def initialize(value, type = "string")
|
6
|
+
@value = value.to_s
|
7
|
+
@type = type.to_s.downcase
|
8
|
+
@cast_method = :"cast_to_#{@type}"
|
9
|
+
|
10
|
+
unless respond_to?(@cast_method)
|
11
|
+
raise ArgumentError.new "'#{@type}' is not a valid value type to cast to."
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def call
|
16
|
+
return @nil if @value.empty?
|
17
|
+
public_send(@cast_method)
|
18
|
+
rescue => exception
|
19
|
+
Lookbook.logger.debug "Failed to parse '#{@value}' into a '#{@type}' [#{exception}]"
|
20
|
+
raise exception
|
21
|
+
end
|
22
|
+
|
23
|
+
def cast_to_string
|
24
|
+
@value
|
25
|
+
end
|
26
|
+
|
27
|
+
def cast_to_symbol
|
28
|
+
@value.delete_prefix(":").to_sym if @value.present?
|
29
|
+
end
|
30
|
+
|
31
|
+
def cast_to_hash
|
32
|
+
result = YamlParser.call(@value)
|
33
|
+
unless result.is_a?(Hash)
|
34
|
+
raise ParserError.new "'#{@value}' is not a YAML Hash"
|
35
|
+
end
|
36
|
+
result
|
37
|
+
end
|
38
|
+
|
39
|
+
def cast_to_array
|
40
|
+
result = YamlParser.call(@value)
|
41
|
+
unless result.is_a?(Array)
|
42
|
+
raise ParserError.new "'#{@value}' is not a YAML Array"
|
43
|
+
end
|
44
|
+
result
|
45
|
+
end
|
46
|
+
|
47
|
+
def cast_to_datetime
|
48
|
+
DateTime.parse(@value)
|
49
|
+
end
|
50
|
+
|
51
|
+
def active_model_cast
|
52
|
+
type_class = "ActiveModel::Type::#{@type.camelize}".constantize
|
53
|
+
type_class.new.cast(@value)
|
54
|
+
end
|
55
|
+
|
56
|
+
alias_method :cast_to_boolean, :active_model_cast
|
57
|
+
alias_method :cast_to_integer, :active_model_cast
|
58
|
+
alias_method :cast_to_float, :active_model_cast
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Lookbook
|
2
|
+
class TagOptionsParser < Service
|
3
|
+
RESOLVERS = [
|
4
|
+
FileResolver,
|
5
|
+
MethodResolver,
|
6
|
+
EvalResolver,
|
7
|
+
YamlResolver
|
8
|
+
]
|
9
|
+
|
10
|
+
def initialize(input, resolver_opts = {})
|
11
|
+
@input = input.to_s.strip
|
12
|
+
@resolver_opts = resolver_opts
|
13
|
+
@fallback = resolver_opts.fetch(:fallback, {})
|
14
|
+
end
|
15
|
+
|
16
|
+
def call
|
17
|
+
options_string, remaining_text = parse_input(@input)
|
18
|
+
resolved_options = resolver(options_string).call(options_string, **@resolver_opts)
|
19
|
+
options = prepare_options(resolved_options)
|
20
|
+
[options, remaining_text]
|
21
|
+
end
|
22
|
+
|
23
|
+
protected
|
24
|
+
|
25
|
+
def resolver(options_string)
|
26
|
+
if options_string.present?
|
27
|
+
handler = RESOLVERS.find { |r| r.resolveable?(options_string) }
|
28
|
+
if handler.nil?
|
29
|
+
Lookbook.logger.error "Invalid tag options string '#{options_string}'"
|
30
|
+
method(:fallback_resolver)
|
31
|
+
else
|
32
|
+
handler
|
33
|
+
end
|
34
|
+
else
|
35
|
+
method(:fallback_resolver)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def fallback_resolver(*args)
|
40
|
+
@fallback
|
41
|
+
end
|
42
|
+
|
43
|
+
def parse_input(input)
|
44
|
+
matchers.each_with_object(["", input]) do |matcher, result|
|
45
|
+
input.match(matcher) do |match_data|
|
46
|
+
result[0] = match_data[1] # options string
|
47
|
+
result[1] = input.gsub(matcher, "").strip # any remaining text
|
48
|
+
return result
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def matchers
|
54
|
+
RESOLVERS.map { |r| r::MATCHER }
|
55
|
+
end
|
56
|
+
|
57
|
+
def prepare_options(options)
|
58
|
+
options = options.is_a?(Array) ? {choices: options} : options
|
59
|
+
options.is_a?(Hash) ? Store.new(options) : options
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Lookbook
|
2
|
+
class ActionViewAnnotationsHandler < Service
|
3
|
+
attr_reader :disable_annotations
|
4
|
+
|
5
|
+
def initialize(disable_annotations: true)
|
6
|
+
@disable_annotations = disable_annotations
|
7
|
+
end
|
8
|
+
|
9
|
+
def call
|
10
|
+
if ActionView::Base.respond_to?(:annotate_rendered_view_with_filenames) && disable_annotations
|
11
|
+
original_value = ActionView::Base.annotate_rendered_view_with_filenames
|
12
|
+
ActionView::Base.annotate_rendered_view_with_filenames = false
|
13
|
+
res = yield
|
14
|
+
ActionView::Base.annotate_rendered_view_with_filenames = original_value
|
15
|
+
res
|
16
|
+
else
|
17
|
+
yield
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Lookbook
|
2
|
+
class ActionViewAnnotationsStripper < Service
|
3
|
+
attr_reader :text
|
4
|
+
|
5
|
+
ANNOTATIONS_REGEX = /<!-- (BEGIN|END) (.*) -->/
|
6
|
+
|
7
|
+
def initialize(text)
|
8
|
+
@text = text.to_s
|
9
|
+
end
|
10
|
+
|
11
|
+
def call
|
12
|
+
text.gsub(ANNOTATIONS_REGEX, "")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Lookbook
|
2
|
+
class FrontmatterExtractor < Service
|
3
|
+
FRONTMATTER_REGEX = /\A---(.|\n)*?---/
|
4
|
+
|
5
|
+
attr_reader :content
|
6
|
+
|
7
|
+
def initialize(content)
|
8
|
+
@content = content.to_s
|
9
|
+
end
|
10
|
+
|
11
|
+
def call
|
12
|
+
frontmatter = extract_frontmatter(content)
|
13
|
+
rest = strip_frontmatter(content)
|
14
|
+
[frontmatter, rest]
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
|
19
|
+
def extract_frontmatter(text)
|
20
|
+
matches = text.match(FRONTMATTER_REGEX)
|
21
|
+
matches ? YAML.safe_load(matches[0]).deep_symbolize_keys : {}
|
22
|
+
end
|
23
|
+
|
24
|
+
def strip_frontmatter(text)
|
25
|
+
text.gsub(FRONTMATTER_REGEX, "").strip
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require "css_parser"
|
2
|
+
|
3
|
+
module Lookbook
|
4
|
+
class StylesExtractor < Service
|
5
|
+
STYLE_TAGS_REGEX = /<style(?:\s[^>]*)?>((?:(?!<\/style>).)*)<\/style>/m
|
6
|
+
|
7
|
+
attr_reader :content
|
8
|
+
|
9
|
+
def initialize(content)
|
10
|
+
@content = content.to_s
|
11
|
+
end
|
12
|
+
|
13
|
+
def call
|
14
|
+
styles = extract_styles(content)
|
15
|
+
rest = strip_styles(content)
|
16
|
+
[styles, rest]
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
|
21
|
+
def extract_styles(text)
|
22
|
+
css_parser = ::CssParser::Parser.new
|
23
|
+
text.scan(STYLE_TAGS_REGEX).flatten.map(&:strip).each do |css|
|
24
|
+
css_parser.load_string!(css.strip)
|
25
|
+
end
|
26
|
+
|
27
|
+
styles = []
|
28
|
+
css_parser.each_selector do |selector, declarations, specificity|
|
29
|
+
styles << "#{selector} { #{declarations} }"
|
30
|
+
end
|
31
|
+
styles
|
32
|
+
end
|
33
|
+
|
34
|
+
def strip_styles(text)
|
35
|
+
text.gsub(STYLE_TAGS_REGEX, "").strip
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -10,17 +10,19 @@ module Lookbook
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def project_name=(name)
|
13
|
-
store[:project_name] = name == false ? nil : name
|
13
|
+
store[:project_name] = (name == false) ? nil : name
|
14
14
|
end
|
15
15
|
|
16
16
|
def page_paths=(paths = nil)
|
17
|
-
store[:page_paths]
|
18
|
-
|
17
|
+
store[:page_paths].push(*paths.to_a)
|
18
|
+
end
|
19
|
+
|
20
|
+
def page_extensions=(extensions = nil)
|
21
|
+
store[:page_extensions].push(*extensions.to_a).uniq!
|
19
22
|
end
|
20
23
|
|
21
24
|
def preview_paths=(paths = nil)
|
22
|
-
store[:preview_paths]
|
23
|
-
store[:preview_paths] += paths.to_a
|
25
|
+
store[:preview_paths].push(*paths.to_a)
|
24
26
|
end
|
25
27
|
|
26
28
|
def preview_display_params
|
@@ -34,16 +36,17 @@ module Lookbook
|
|
34
36
|
end
|
35
37
|
|
36
38
|
def listen_extensions=(extensions = nil)
|
37
|
-
store[:listen_extensions]
|
38
|
-
store[:listen_extensions] += extensions.to_a
|
39
|
-
store[:listen_extensions].uniq!
|
39
|
+
store[:listen_extensions].push(*extensions.to_a).uniq!
|
40
40
|
end
|
41
41
|
|
42
42
|
def markdown_options=(options = nil)
|
43
|
-
store[:markdown_options] ||= {}
|
44
43
|
store[:markdown_options].merge!(options.to_h)
|
45
44
|
end
|
46
45
|
|
46
|
+
def highlighter_options=(options = nil)
|
47
|
+
store[:highlighter_options].merge!(options.to_h)
|
48
|
+
end
|
49
|
+
|
47
50
|
def ui_theme=(name)
|
48
51
|
name = name.to_s
|
49
52
|
if Theme.valid_theme?(name)
|
@@ -18,11 +18,11 @@ module Lookbook
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def add_input(input, *args)
|
21
|
-
store[input
|
21
|
+
store[normalize_name(input)] = build_config(input, *args)
|
22
22
|
end
|
23
23
|
|
24
24
|
def get_input(input)
|
25
|
-
store[input
|
25
|
+
store[normalize_name(input)]
|
26
26
|
end
|
27
27
|
|
28
28
|
def self.init_from_config
|
@@ -35,6 +35,10 @@ module Lookbook
|
|
35
35
|
|
36
36
|
protected
|
37
37
|
|
38
|
+
def normalize_name(name)
|
39
|
+
name.to_s.tr("-", "_").to_sym
|
40
|
+
end
|
41
|
+
|
38
42
|
def build_config(name, *args)
|
39
43
|
partial = nil
|
40
44
|
opts = nil
|
@@ -48,7 +52,7 @@ module Lookbook
|
|
48
52
|
Store.new({
|
49
53
|
name: name.to_sym,
|
50
54
|
partial: partial,
|
51
|
-
|
55
|
+
options: DEFAULTS.merge(opts.to_h)
|
52
56
|
})
|
53
57
|
else
|
54
58
|
raise ConfigError.new("inputs must define a partial path", scope: "inputs.config")
|
@@ -96,7 +96,7 @@ module Lookbook
|
|
96
96
|
config.each do |group, panels|
|
97
97
|
panels.map! do |opts|
|
98
98
|
opts.transform_values! do |value|
|
99
|
-
value.is_a?(String) && value.start_with?("->") ? eval(value) : value # standard:disable Security/Eval
|
99
|
+
(value.is_a?(String) && value.start_with?("->")) ? eval(value) : value # standard:disable Security/Eval
|
100
100
|
end
|
101
101
|
end
|
102
102
|
end
|
@@ -111,7 +111,7 @@ module Lookbook
|
|
111
111
|
end
|
112
112
|
|
113
113
|
def insert_index(position, items_count)
|
114
|
-
index = position == 0 ? 1 : (position || 0).to_int
|
114
|
+
index = (position == 0) ? 1 : (position || 0).to_int
|
115
115
|
last_position = items_count + 1
|
116
116
|
index = last_position if index > last_position
|
117
117
|
index - 1
|
@@ -7,7 +7,7 @@ module Lookbook
|
|
7
7
|
|
8
8
|
def initialize(config = nil)
|
9
9
|
@store = {}
|
10
|
-
config.to_h.each { add_tag(
|
10
|
+
config.to_h.each { |k, v| add_tag(k, v) }
|
11
11
|
end
|
12
12
|
|
13
13
|
def add_tag(name, opts = nil)
|
@@ -34,12 +34,10 @@ module Lookbook
|
|
34
34
|
protected
|
35
35
|
|
36
36
|
def build_config(name, opts = nil)
|
37
|
-
opts = opts.to_h
|
38
37
|
Store.new({
|
39
38
|
name: name.to_sym,
|
40
|
-
label:
|
41
|
-
|
42
|
-
opts: opts[:opts].to_h
|
39
|
+
label: name.to_s.titleize,
|
40
|
+
options: opts.to_h
|
43
41
|
})
|
44
42
|
end
|
45
43
|
end
|
@@ -3,7 +3,7 @@ module Lookbook
|
|
3
3
|
def initialize(initial_data = nil, opts = {})
|
4
4
|
@recursive = opts[:recursive] || false
|
5
5
|
super()
|
6
|
-
initial_data.to_h.each { self[
|
6
|
+
initial_data.to_h.each { |k, v| self[k] = v }
|
7
7
|
end
|
8
8
|
|
9
9
|
def []=(key, value)
|
@@ -25,39 +25,6 @@ module Lookbook
|
|
25
25
|
true
|
26
26
|
end
|
27
27
|
|
28
|
-
# def [](key)
|
29
|
-
# key = key.to_sym
|
30
|
-
# if respond_to? key
|
31
|
-
# public_send(key)
|
32
|
-
# else
|
33
|
-
# self[key]
|
34
|
-
# end
|
35
|
-
# end
|
36
|
-
|
37
|
-
# def []=(key, value)
|
38
|
-
# setter_key = "#{key}=".to_sym
|
39
|
-
# if respond_to? setter_key
|
40
|
-
# public_send(setter_key, value)
|
41
|
-
# else
|
42
|
-
# _set(key.to_sym, normalize_value(value))
|
43
|
-
# end
|
44
|
-
# end
|
45
|
-
|
46
|
-
# def method_missing(key, *args)
|
47
|
-
# if key.to_s.end_with?("=")
|
48
|
-
# args[0] = normalize_value(args[0])
|
49
|
-
# end
|
50
|
-
# public_send(key.to_sym, *args)
|
51
|
-
# end
|
52
|
-
|
53
|
-
# def respond_to_missing?(key, *args)
|
54
|
-
# key?(key.to_sym)
|
55
|
-
# end
|
56
|
-
|
57
|
-
# def fetch(key, *args)
|
58
|
-
# super.fetch(key.to_sym, *args)
|
59
|
-
# end
|
60
|
-
|
61
28
|
def to_h
|
62
29
|
transform_values do |value|
|
63
30
|
value.is_a?(Store) ? value.to_h : value
|
@@ -71,7 +38,7 @@ module Lookbook
|
|
71
38
|
protected
|
72
39
|
|
73
40
|
def normalize_value(value)
|
74
|
-
@recursive && !value.is_a?(Store) && value.is_a?(Hash) ? Store.new(value, recursive: @recursive) : value
|
41
|
+
(@recursive && !value.is_a?(Store) && value.is_a?(Hash)) ? Store.new(value, recursive: @recursive) : value
|
75
42
|
end
|
76
43
|
end
|
77
44
|
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module Lookbook
|
2
|
+
class TreeNode
|
3
|
+
include Enumerable
|
4
|
+
include Comparable
|
5
|
+
|
6
|
+
delegate_missing_to :content
|
7
|
+
|
8
|
+
attr_accessor :path, :content
|
9
|
+
attr_reader :children
|
10
|
+
|
11
|
+
def initialize(path = nil, content = nil, position: 10000)
|
12
|
+
@path = path.to_s
|
13
|
+
@content = content
|
14
|
+
@position = position
|
15
|
+
@children = []
|
16
|
+
end
|
17
|
+
|
18
|
+
def id
|
19
|
+
Utils.id(content_value(:id, path))
|
20
|
+
end
|
21
|
+
|
22
|
+
def name
|
23
|
+
segments.last
|
24
|
+
end
|
25
|
+
|
26
|
+
def label
|
27
|
+
content_value(:label, name.titleize)
|
28
|
+
end
|
29
|
+
|
30
|
+
def position
|
31
|
+
content_value(:position, @position)
|
32
|
+
end
|
33
|
+
|
34
|
+
def type
|
35
|
+
content_value(:type, :directory)
|
36
|
+
end
|
37
|
+
|
38
|
+
def depth
|
39
|
+
path.split("/").size
|
40
|
+
end
|
41
|
+
|
42
|
+
def add_child(name, content = nil, position: 10000)
|
43
|
+
children << TreeNode.new("#{path}/#{name}", content, position: position)
|
44
|
+
end
|
45
|
+
|
46
|
+
def has_child?(name)
|
47
|
+
!!get_child(name)
|
48
|
+
end
|
49
|
+
|
50
|
+
def get_child(name)
|
51
|
+
children.find { |child| child.name == name }
|
52
|
+
end
|
53
|
+
|
54
|
+
def content?
|
55
|
+
content.present?
|
56
|
+
end
|
57
|
+
|
58
|
+
def each(&block)
|
59
|
+
if block
|
60
|
+
children.sort.each do |child|
|
61
|
+
yield child
|
62
|
+
end
|
63
|
+
else
|
64
|
+
to_enum(:each)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def <=>(other)
|
69
|
+
if content?
|
70
|
+
content <=> (other.content? ? other.content : other)
|
71
|
+
else
|
72
|
+
[position, label] <=> [other.position, other.label]
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
protected
|
77
|
+
|
78
|
+
def content_value(method_name, fallback = nil)
|
79
|
+
value = content.send(method_name) if content
|
80
|
+
value || fallback
|
81
|
+
end
|
82
|
+
|
83
|
+
def segments
|
84
|
+
path.split("/")
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -5,15 +5,42 @@ module Lookbook
|
|
5
5
|
File.absolute_path(path.to_s, Rails.root)
|
6
6
|
end
|
7
7
|
|
8
|
-
def
|
9
|
-
|
10
|
-
|
8
|
+
def to_lookup_path(file_path)
|
9
|
+
path = file_path.to_s.downcase
|
10
|
+
|
11
|
+
directory_path = File.dirname(path)
|
12
|
+
directory_path = nil if directory_path.start_with?(".")
|
13
|
+
|
14
|
+
file_name = File.basename(path).split(".").first
|
15
|
+
|
16
|
+
segments = [*directory_path&.split("/"), file_name].compact
|
17
|
+
stripped_segments = segments.map! do |segment|
|
18
|
+
PositionPrefixParser.call(segment).last.tr("-", "_")
|
19
|
+
end
|
20
|
+
|
21
|
+
to_path(stripped_segments)
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_path(*args)
|
25
|
+
args.flatten.compact.map(&:to_s).join("/")
|
26
|
+
end
|
27
|
+
|
28
|
+
def normalize_paths(paths, allow_root: false)
|
29
|
+
Array(paths).map do |path|
|
11
30
|
full_path = to_absolute(path)
|
12
|
-
if
|
13
|
-
full_path if allow_root || full_path
|
31
|
+
if File.exist?(full_path)
|
32
|
+
full_path if allow_root || !root_path?(full_path)
|
14
33
|
end
|
15
34
|
end.compact.uniq
|
16
35
|
end
|
36
|
+
|
37
|
+
def root_path?(path)
|
38
|
+
Rails.application.root.to_s == path.to_s
|
39
|
+
end
|
40
|
+
|
41
|
+
def strip_slashes(path)
|
42
|
+
path.to_s.gsub(/\A\/|\/\z/, "")
|
43
|
+
end
|
17
44
|
end
|
18
45
|
end
|
19
46
|
end
|