lookbook 2.0.0.beta.2 → 2.0.0.beta.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (126) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/lookbook/css/fonts.css +33 -0
  3. data/app/assets/lookbook/css/lookbook.css +7 -0
  4. data/app/assets/lookbook/css/themes/blue.css +4 -1
  5. data/app/assets/lookbook/css/themes/green.css +4 -1
  6. data/app/assets/lookbook/css/themes/indigo.css +4 -1
  7. data/app/assets/lookbook/css/themes/rose.css +4 -1
  8. data/app/assets/lookbook/css/themes/zinc.css +4 -1
  9. data/app/assets/lookbook/fonts/Inter-italic.var.woff2 +0 -0
  10. data/app/assets/lookbook/fonts/Inter-roman.var.woff2 +0 -0
  11. data/app/assets/lookbook/fonts/SourceCodeVariable-Italic.ttf.woff2 +0 -0
  12. data/app/assets/lookbook/fonts/SourceCodeVariable-Roman.ttf.woff2 +0 -0
  13. data/app/assets/lookbook/img/lucide-sprite.svg +869 -869
  14. data/app/assets/lookbook/js/lib/lookbook.js +12 -2
  15. data/app/components/lookbook/code/highlight_github.css +16 -17
  16. data/app/components/lookbook/dimensions_display/component.js +4 -7
  17. data/app/components/lookbook/file_source/component.html.erb +9 -0
  18. data/app/components/lookbook/file_source/component.rb +73 -0
  19. data/app/components/lookbook/header/component.html.erb +11 -8
  20. data/app/components/lookbook/icon/component.css +1 -1
  21. data/app/components/lookbook/icon/component.html.erb +1 -1
  22. data/app/components/lookbook/icon/component.rb +4 -1
  23. data/app/components/lookbook/logo/component.html.erb +6 -0
  24. data/app/components/lookbook/logo/component.rb +15 -0
  25. data/app/components/lookbook/message/component.css +33 -0
  26. data/app/components/lookbook/message/component.html.erb +26 -0
  27. data/app/components/lookbook/message/component.rb +13 -0
  28. data/app/components/lookbook/nav/entity/component.html.erb +2 -2
  29. data/app/components/lookbook/nav/entity/component.rb +1 -1
  30. data/app/components/lookbook/page_tabs/component.html.erb +2 -2
  31. data/app/components/lookbook/params/field/component.css +3 -3
  32. data/app/components/lookbook/prose/component.css +8 -1
  33. data/app/components/lookbook/prose/component.html.erb +6 -1
  34. data/app/components/lookbook/prose/component.rb +2 -2
  35. data/app/controllers/concerns/lookbook/targetable_concern.rb +2 -16
  36. data/app/controllers/lookbook/application_controller.rb +38 -14
  37. data/app/controllers/lookbook/embeds_controller.rb +3 -4
  38. data/app/controllers/lookbook/inspector_controller.rb +4 -12
  39. data/app/controllers/lookbook/pages_controller.rb +15 -27
  40. data/app/controllers/lookbook/preview_controller.rb +30 -2
  41. data/app/controllers/lookbook/previews_controller.rb +13 -15
  42. data/app/views/layouts/lookbook/application.html.erb +1 -0
  43. data/app/views/layouts/lookbook/skeleton.html.erb +2 -2
  44. data/app/views/lookbook/errors/default.html.erb +40 -0
  45. data/app/views/lookbook/errors/not_found.html.erb +10 -0
  46. data/app/views/lookbook/index.html.erb +29 -24
  47. data/app/views/lookbook/pages/show.html.erb +9 -8
  48. data/app/views/lookbook/partials/_blank_slate.html.erb +7 -0
  49. data/config/app.yml +8 -0
  50. data/config/routes.rb +2 -0
  51. data/lib/lookbook/engine.rb +12 -5
  52. data/lib/lookbook/entities/concerns/annotatable_entity.rb +26 -1
  53. data/lib/lookbook/entities/concerns/inspectable_entity.rb +17 -2
  54. data/lib/lookbook/entities/concerns/locatable_entity.rb +51 -7
  55. data/lib/lookbook/entities/concerns/navigable_entity.rb +14 -1
  56. data/lib/lookbook/entities/entity.rb +34 -12
  57. data/lib/lookbook/entities/page_entity.rb +68 -10
  58. data/lib/lookbook/entities/page_section_entity.rb +4 -0
  59. data/lib/lookbook/entities/preview_entity.rb +107 -17
  60. data/lib/lookbook/entities/renderable_entity.rb +47 -9
  61. data/lib/lookbook/entities/rendered_scenario_entity.rb +17 -6
  62. data/lib/lookbook/entities/scenario_entity.rb +77 -16
  63. data/lib/lookbook/entities/scenario_group_entity.rb +82 -9
  64. data/lib/lookbook/helpers/page_helper.rb +26 -1
  65. data/lib/lookbook/helpers/ui_elements_helper.rb +0 -24
  66. data/lib/lookbook/param.rb +1 -1
  67. data/lib/lookbook/services/markdown_renderer.rb +2 -4
  68. data/lib/lookbook/stores/config_store.rb +0 -12
  69. data/lib/lookbook/support/errors/config_error.rb +1 -1
  70. data/lib/lookbook/support/errors/error.rb +64 -0
  71. data/lib/lookbook/support/errors/parser_error.rb +1 -1
  72. data/lib/lookbook/support/errors/preview_template_error.rb +1 -1
  73. data/lib/lookbook/support/errors/routing_error.rb +7 -0
  74. data/lib/lookbook/support/errors/template_error.rb +7 -0
  75. data/lib/lookbook/version.rb +1 -1
  76. data/public/lookbook-assets/Inter-italic.var.69eb0fe1.woff2 +0 -0
  77. data/public/lookbook-assets/Inter-italic.var.736a7044.woff2 +0 -0
  78. data/public/lookbook-assets/Inter-roman.var.b695afbe.woff2 +0 -0
  79. data/public/lookbook-assets/Inter-roman.var.fbdd51d0.woff2 +0 -0
  80. data/public/lookbook-assets/SourceCodeVariable-Italic.cad97b83.otf +0 -0
  81. data/public/lookbook-assets/SourceCodeVariable-Italic.ttf.09b4354a.woff2 +0 -0
  82. data/public/lookbook-assets/SourceCodeVariable-Italic.ttf.fcd7e9f4.woff2 +0 -0
  83. data/public/lookbook-assets/SourceCodeVariable-Roman.185ddb17.otf +0 -0
  84. data/public/lookbook-assets/SourceCodeVariable-Roman.ttf.118e9f22.woff2 +0 -0
  85. data/public/lookbook-assets/SourceCodeVariable-Roman.ttf.91043609.woff2 +0 -0
  86. data/public/lookbook-assets/css/lookbook.css +417 -58
  87. data/public/lookbook-assets/css/lookbook.css.map +1 -1
  88. data/public/lookbook-assets/css/themes/blue.css +4 -1
  89. data/public/lookbook-assets/css/themes/blue.css.map +1 -1
  90. data/public/lookbook-assets/css/themes/green.css +4 -1
  91. data/public/lookbook-assets/css/themes/green.css.map +1 -1
  92. data/public/lookbook-assets/css/themes/indigo.css +4 -1
  93. data/public/lookbook-assets/css/themes/indigo.css.map +1 -1
  94. data/public/lookbook-assets/css/themes/rose.css +4 -1
  95. data/public/lookbook-assets/css/themes/rose.css.map +1 -1
  96. data/public/lookbook-assets/css/themes/zinc.css +4 -1
  97. data/public/lookbook-assets/css/themes/zinc.css.map +1 -1
  98. data/public/lookbook-assets/img/lucide-sprite.svg +869 -869
  99. data/public/lookbook-assets/js/index.js +173 -173
  100. data/public/lookbook-assets/js/index.js.map +1 -1
  101. data/public/lookbook-assets/js/lookbook-core.js +4 -2
  102. data/public/lookbook-assets/js/lookbook.js +4 -2
  103. metadata +31 -26
  104. data/app/views/layouts/lookbook/shell.html.erb +0 -25
  105. data/app/views/lookbook/404.html.erb +0 -15
  106. data/app/views/lookbook/error.html.erb +0 -46
  107. data/lib/lookbook/error.rb +0 -120
  108. data/lib/lookbook/support/errors/lookbook_error.rb +0 -21
  109. data/lib/tasks/lookbook_tasks.rake +0 -10
  110. data/public/lookbook-assets/css/app.css +0 -2341
  111. data/public/lookbook-assets/css/app.css.map +0 -11
  112. data/public/lookbook-assets/css/themes/zinc.css.map.91837.5 +0 -1
  113. data/public/lookbook-assets/feather-sprite.svg +0 -1
  114. data/public/lookbook-assets/js/app.js +0 -10862
  115. data/public/lookbook-assets/js/app.js.map +0 -2571
  116. data/public/lookbook-assets/js/embed.js +0 -1427
  117. data/public/lookbook-assets/js/embed.js.91837.6 +0 -0
  118. data/public/lookbook-assets/js/embed.js.map +0 -1
  119. data/public/lookbook-assets/js/lookbook-core.js.map +0 -1
  120. data/public/lookbook-assets/js/lookbook.js.map +0 -1
  121. data/public/lookbook-assets/lookbook-esm.js +0 -1427
  122. data/public/lookbook-assets/lookbook-esm.js.map +0 -1
  123. data/public/lookbook-assets/lookbook-global.js +0 -1427
  124. data/public/lookbook-assets/lookbook-global.js.map +0 -1
  125. data/public/lookbook-assets/lookbook.js +0 -1427
  126. data/public/lookbook-assets/lookbook.js.map +0 -1
@@ -1,7 +1,6 @@
1
1
  module Lookbook
2
2
  # Represents a preview scenario method within a preview class
3
3
  #
4
- # @ignore methods
5
4
  # @api public
6
5
  class ScenarioEntity < Entity
7
6
  include InspectableEntity
@@ -10,8 +9,15 @@ module Lookbook
10
9
 
11
10
  delegate :group, to: :code_object
12
11
 
12
+ # The preview that this scenario belongs to.
13
+ #
14
+ # @return [PreviewEntity] The parent preview entity
13
15
  attr_reader :preview
14
16
 
17
+ # @api private
18
+ alias_method :parent, :preview
19
+
20
+ # @api private
15
21
  def initialize(code_object, preview, priority: nil)
16
22
  @code_object = code_object
17
23
  @preview = preview
@@ -19,61 +25,116 @@ module Lookbook
19
25
  @lookup_path = "#{parent.lookup_path}/#{name}"
20
26
  end
21
27
 
28
+ # @!group Identity
29
+
30
+ # Human-readable unique scenario ID
31
+ #
32
+ # @return [String] The ID
22
33
  def id
23
34
  @_id ||= Utils.id(fetch_config(:id) { "#{parent.id}-#{code_object.name}" })
24
35
  end
25
36
 
37
+ # Parameter-safe scenario name.
38
+ #
39
+ # @return [String] The name
26
40
  def name
27
41
  @_name ||= Utils.name(code_object.name)
28
42
  end
29
43
 
44
+ # Entity type identifier.
45
+ # Returns `:scenario` for scenarios.
46
+ #
47
+ # @return [Symbol] The entity type
48
+ def type
49
+ :scenario
50
+ end
51
+
52
+ # @!endgroup
53
+
54
+ # @!group Display options
55
+
56
+ # Display options hash.
57
+ #
58
+ # Contains all display options defined via the `@display` tag
59
+ # merged with any globally-defined options.
60
+ #
61
+ # @return [Hash] The resolved display options
30
62
  def display_options
31
63
  parent.display_options.merge(fetch_config(:display_options, {}))
32
64
  end
33
65
 
66
+ # @!endgroup
67
+
68
+ # @!group Render Targets
69
+
70
+ # @api private
34
71
  def render_targets
35
72
  @_render_targets ||= RenderTargetCollection.new(load_render_targets)
36
73
  end
37
74
 
75
+ # @api private
76
+ alias_method :components, :render_targets
77
+
78
+ # The item (component or partial) that the scenario renders.
79
+ #
80
+ # The render target is guessed where possible (based on the preview class name)
81
+ # but can also be manually specified using the `@renders` tag.
82
+ #
83
+ # @example :ruby
84
+ # "This scenario renders: #{scenario.render_target.label}"
85
+ #
86
+ # @return [RenderableEntity] The render target
38
87
  def render_target
39
88
  render_targets.first
40
89
  end
41
90
 
91
+ alias_method :component, :render_target
92
+
93
+ # @!endgroup
94
+
95
+ # @!group URLs
96
+
97
+ # The inspector URL path for this preview
98
+ #
99
+ # @return [String] URL path
100
+ def inspect_path
101
+ lookbook_inspect_path(lookup_path)
102
+ end
103
+
104
+ # The standalone preview URL path for this preview
105
+ #
106
+ # @return [String] URL path
107
+ def preview_path
108
+ lookbook_preview_path(lookup_path)
109
+ end
110
+
111
+ # @!endgroup
112
+
113
+ # @api private
42
114
  def scenarios
43
115
  [self]
44
116
  end
45
117
 
118
+ # @api private
46
119
  def template_source(template_path)
47
120
  source_path = template_file_path(template_path)
48
121
  source_path ? File.read(source_path) : nil
49
122
  end
50
123
 
124
+ # @api private
51
125
  def template_lang(template_path)
52
126
  path = template_file_path(template_path)
53
127
  Lookbook::Lang.guess(path) || Lookbook::Lang.find(:html)
54
128
  end
55
129
 
130
+ # @api private
56
131
  def search_terms
57
132
  [parent.label, label]
58
133
  end
59
134
 
60
- def url_path
61
- lookbook_inspect_path(lookup_path)
62
- end
63
-
64
- def preview_path
65
- lookbook_preview_path(lookup_path)
66
- end
67
-
68
- def type
69
- :scenario
70
- end
71
-
72
- alias_method :parent, :preview
73
- alias_method :components, :render_targets
74
- alias_method :component, :render_target
75
135
  alias_method :lang, :source_lang
76
136
  alias_method :examples, :scenarios
137
+ alias_method :url_path, :inspect_path
77
138
 
78
139
  deprecate lang: :source_lang, deprecator: Deprecation
79
140
  deprecate examples: :scenarios, deprecator: Deprecation
@@ -1,13 +1,28 @@
1
1
  module Lookbook
2
2
  # Represents a group of preview scenarios within a preview class
3
3
  #
4
- # @ignore methods
5
4
  # @api public
6
5
  class ScenarioGroupEntity < Entity
7
6
  include NavigableEntity
8
7
 
9
- attr_reader :scenarios, :preview
8
+ # @!group Scenarios
10
9
 
10
+ # Returns all scenarios within the group.
11
+ #
12
+ # @return [Array<ScenarioEntity>] All scenarios
13
+ attr_reader :scenarios
14
+
15
+ # @!endgroup
16
+
17
+ # The preview that this scenario belongs to.
18
+ #
19
+ # @return [PreviewEntity] The parent preview entity
20
+ attr_reader :preview
21
+
22
+ # @api private
23
+ alias_method :parent, :preview
24
+
25
+ # @api private
11
26
  def initialize(name, scenarios, preview)
12
27
  @name = Utils.name(name)
13
28
  @scenarios = ScenarioCollection.new(scenarios)
@@ -15,6 +30,14 @@ module Lookbook
15
30
  @lookup_path = "#{parent.lookup_path}/#{@name}"
16
31
  end
17
32
 
33
+ # @!group Display options
34
+
35
+ # Display options hash.
36
+ #
37
+ # Contains all display options defined via the `@display` tag
38
+ # for each scenario in the group, merged with any globally-defined options.
39
+ #
40
+ # @return [Hash] The resolved display options
18
41
  def display_options
19
42
  merged = {}
20
43
  scenarios.to_a.reverse.map do |scenario|
@@ -23,35 +46,85 @@ module Lookbook
23
46
  merged
24
47
  end
25
48
 
49
+ # @!endgroup
50
+
51
+ # @!group Render Targets
52
+
53
+ # Collection of render targets (components or partials)
54
+ # from each of the scenarios in the group.
55
+ #
56
+ # Render targets are guessed where possible (based on the preview class name)
57
+ # but can also be manually specified using the `@renders` tag.
58
+ #
59
+ # @example :ruby
60
+ # "This group renders: #{group.render_targets.map(&:label).join(", ")}"
61
+ #
62
+ # @return [Array<RenderableEntity>] Render target entities
26
63
  def render_targets
27
64
  @_render_targets ||= RenderTargetCollection.new(scenarios.flat_map(&:render_targets).uniq(&:lookup_path))
28
65
  end
29
66
 
30
- def search_terms
31
- [parent.label, label]
32
- end
67
+ alias_method :components, :render_targets
68
+
69
+ # @!endgroup
33
70
 
71
+ # @!group Annotations
72
+
73
+ # Collection of tags from each of the scenarios in the group.
74
+ # Can be filtered by tag name by providing the name as an argument.
75
+ #
76
+ # @example :ruby
77
+ # all_tags = group.tags
78
+ # display_tags = group.tags(:display)
79
+ #
80
+ # @param tag_name [Symbol] Optional tag type to filter by
81
+ # @return [Array<YardTag>] Array of tags
34
82
  def tags(tag_name = nil)
35
83
  scenarios.flat_map { |scenario| scenario.tags(tag_name) }
36
84
  end
37
85
 
86
+ # @api private
38
87
  def tag(tag_name = nil)
39
88
  tags(tag_name).first
40
89
  end
41
90
 
42
- def url_path
91
+ # @!endgroup
92
+
93
+ # @!group URLs
94
+
95
+ # The inspector URL path for this scenario group
96
+ #
97
+ # @return [String] URL path
98
+ def inspect_path
43
99
  lookbook_inspect_path(lookup_path)
44
100
  end
45
101
 
102
+ # The standalone preview URL path for this scenario group
103
+ #
104
+ # @return [String] URL path
46
105
  def preview_path
47
106
  lookbook_preview_path(lookup_path)
48
107
  end
49
108
 
109
+ alias_method :url_path, :inspect_path
110
+
111
+ # @!endgroup
112
+
113
+ # @!group Identity
114
+
115
+ # Entity type identifier.
116
+ # Returns `:scenario_group` for scenario groups.
117
+ #
118
+ # @return [Symbol] The entity type
50
119
  def type
51
- :group
120
+ :scenario_group
52
121
  end
53
122
 
54
- alias_method :parent, :preview
55
- alias_method :components, :render_targets
123
+ # @!endgroup
124
+
125
+ # @api private
126
+ def search_terms
127
+ [parent.label, label]
128
+ end
56
129
  end
57
130
  end
@@ -5,14 +5,39 @@ module Lookbook
5
5
  module PageHelper
6
6
  # Returns the URL path to a page.
7
7
  #
8
+ # @api private
8
9
  # @param id [String, PageEntity] The id or PageEntity instance to generate a URL path for
9
10
  def page_path(id)
10
11
  page = id.is_a?(PageEntity) ? id : Engine.pages.find_by_id(id)
11
12
  if page.present?
12
- lookbook_page_path page.lookup_path
13
+ page.docs_path
13
14
  else
14
15
  Lookbook.logger.warn "Could not find page with id ':#{id}'"
15
16
  end
16
17
  end
18
+
19
+ # Render a 'live' embed of a component preview.
20
+ #
21
+ # If no scenario name is provided then the default (first) preview
22
+ # scenario will be rendered in the embed.
23
+ #
24
+ # @param preview [String] Name of the preview class to embed
25
+ # @param scenario [String] Example method name
26
+ # @param opts [Hash] Options hash
27
+ def embed(preview, scenario = nil, **opts)
28
+ preview_entity = if preview.is_a?(Symbol)
29
+ Engine.previews.find_by_path(preview)
30
+ else
31
+ Engine.previews.find_by_preview_class(preview)
32
+ end
33
+ scenario_entity = scenario ? preview_entity&.scenario(scenario) : preview_entity&.default_scenario
34
+ opts[:actions] ||= ["inspect", "open"]
35
+
36
+ lookbook_render Embed::Component.new(
37
+ scenario: scenario_entity,
38
+ params: opts.fetch(:params, {}),
39
+ options: opts.except(:params)
40
+ )
41
+ end
17
42
  end
18
43
  end
@@ -34,30 +34,6 @@ module Lookbook
34
34
  lookbook_render :code, **opts, &block
35
35
  end
36
36
 
37
- # Render a 'live' embed of a component preview.
38
- #
39
- # If no scenario name is provided then the default (first) preview
40
- # scenario will be rendered in the embed.
41
- #
42
- # @param preview [String] Name of the preview class to embed
43
- # @param scenario [String] Example method name
44
- # @param opts [Hash] Options hash
45
- def embed(preview, scenario = nil, **opts)
46
- preview_entity = if preview.is_a?(Symbol)
47
- Engine.previews.find_by_path(preview)
48
- else
49
- Engine.previews.find_by_preview_class(preview)
50
- end
51
- scenario_entity = scenario ? preview_entity&.scenario(scenario) : preview_entity&.default_scenario
52
- opts[:actions] ||= ["inspect", "open"]
53
-
54
- lookbook_render Embed::Component.new(
55
- scenario: scenario_entity,
56
- params: opts.fetch(:params, {}),
57
- options: opts.except(:params)
58
- )
59
- end
60
-
61
37
  # @api private
62
38
  def prose(**opts, &block)
63
39
  lookbook_render :prose, **opts, &block
@@ -65,7 +65,7 @@ module Lookbook
65
65
 
66
66
  def input_config
67
67
  config = Lookbook::Engine.inputs.get_input(input)
68
- config || raise(LookbookError.new("Unknown input type '#{input}'"))
68
+ config || raise(Lookbook::Error.new("Unknown input type '#{input}'"))
69
69
  end
70
70
 
71
71
  def guess_input
@@ -18,11 +18,9 @@ module Lookbook
18
18
  class LookbookMarkdownRenderer < Redcarpet::Render::HTML
19
19
  def block_code(code, language = "ruby")
20
20
  line_numbers = language.to_s.end_with? "-numbered"
21
- ApplicationController.render(Lookbook::Code::Component.new(**{
22
- source: code,
21
+ ApplicationController.render(Lookbook::Code::Component.new(source: code,
23
22
  language: language.to_s.chomp("-numbered"),
24
- line_numbers: line_numbers
25
- }), layout: nil)
23
+ line_numbers: line_numbers), layout: nil)
26
24
  end
27
25
 
28
26
  def postprocess(full_document)
@@ -27,22 +27,10 @@ module Lookbook
27
27
  store[:project_name] = (name == false) ? nil : name
28
28
  end
29
29
 
30
- def page_paths=(paths = nil)
31
- store[:page_paths].push(*paths.to_a)
32
- end
33
-
34
30
  def page_extensions=(extensions = nil)
35
31
  store[:page_extensions].push(*extensions.to_a).uniq!
36
32
  end
37
33
 
38
- def preview_paths=(paths = nil)
39
- store[:preview_paths].push(*paths.to_a)
40
- end
41
-
42
- def component_paths=(paths = nil)
43
- store[:component_paths].push(*paths.to_a)
44
- end
45
-
46
34
  def listen_extensions=(extensions = nil)
47
35
  store[:listen_extensions].push(*extensions.to_a).uniq!
48
36
  end
@@ -1,5 +1,5 @@
1
1
  module Lookbook
2
- class ConfigError < LookbookError
2
+ class ConfigError < Error
3
3
  def initialize(msg = nil, scope: "config", **kwargs)
4
4
  super(msg, scope: scope, **kwargs)
5
5
  end
@@ -0,0 +1,64 @@
1
+ module Lookbook
2
+ class Error < StandardError
3
+ attr_reader :scope, :original, :status, :detail, :source
4
+
5
+ def initialize(message = nil,
6
+ scope: nil, original: nil, status: nil, detail: nil,
7
+ file_path: nil, source: nil, line_number: nil, **kwargs)
8
+ @scope = scope
9
+ @original = original
10
+ @message = message
11
+ @status = status
12
+ @detail = detail
13
+ @file_path = file_path
14
+ @source = source
15
+ @line_number = line_number
16
+ super(message)
17
+ end
18
+
19
+ def message
20
+ @message || original&.message
21
+ end
22
+
23
+ def backtrace
24
+ original&.backtrace || super
25
+ end
26
+
27
+ def type
28
+ (original.presence || self).class.to_s
29
+ end
30
+
31
+ def file_path
32
+ return @file_path.to_s if @file_path.present?
33
+
34
+ parsed_backtrace[0][0] if parsed_backtrace.any?
35
+ end
36
+
37
+ def relative_file_path
38
+ file_path&.delete_prefix("#{Rails.root}/")
39
+ end
40
+
41
+ def line_number
42
+ return @line_number.to_i if @line_number.present?
43
+
44
+ if parsed_backtrace.any?
45
+ number = parsed_backtrace[0][1]
46
+ number.to_i if number.present?
47
+ end
48
+ end
49
+
50
+ def backtrace_lines
51
+ root = Rails.root.to_s
52
+ backtrace.map { |line| line.gsub(root, "") }
53
+ end
54
+
55
+ protected
56
+
57
+ def parsed_backtrace
58
+ backtrace.map do |line|
59
+ line =~ /^(.+?):(\d+)(|:in `(.+)')$/
60
+ [$1, $2, $4]
61
+ end
62
+ end
63
+ end
64
+ end
@@ -1,5 +1,5 @@
1
1
  module Lookbook
2
- class ParserError < LookbookError
2
+ class ParserError < Error
3
3
  def initialize(msg = nil, scope: "parser", **kwargs)
4
4
  super(msg, scope: scope, **kwargs)
5
5
  end
@@ -1,5 +1,5 @@
1
1
  module Lookbook
2
- class PreviewTemplateError < LookbookError
2
+ class PreviewTemplateError < Error
3
3
  def initialize(msg = nil, scope: "preview", **kwargs)
4
4
  super(msg, scope: scope, **kwargs)
5
5
  end
@@ -0,0 +1,7 @@
1
+ module Lookbook
2
+ class RoutingError < Error
3
+ def initialize(msg = nil, scope: "request", **kwargs)
4
+ super(msg, scope: scope, status: :not_found, **kwargs)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Lookbook
2
+ class TemplateError < Error
3
+ def initialize(msg = nil, scope: "template", **kwargs)
4
+ super(msg, scope: scope, **kwargs)
5
+ end
6
+ end
7
+ end
@@ -1,3 +1,3 @@
1
1
  module Lookbook
2
- VERSION = "2.0.0.beta.2"
2
+ VERSION = "2.0.0.beta.4"
3
3
  end