easol-canvas 1.5.0 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c61a6785fbf34da110e1fe2b01a9f096ff4aaf8ea3cfbef780491b5e94e68998
4
- data.tar.gz: 3acb2a3215a5fd874ad5e54cc719204cb0a4698218935f2546ce5cacf3f73777
3
+ metadata.gz: 988493985d369b518ca9bb2b802c8d2bc639e7a632090434b9c558e3fc5d6256
4
+ data.tar.gz: 3d9d3df30a6d5a6db096e570d3cba97fc9e4d26284d7b4596b535bf57080991f
5
5
  SHA512:
6
- metadata.gz: 660512a56bea758cae95483fdaefd41a75156a7c15723e661749a64feb6dbc847bab31e279fecd733af807c33491a138b9c4afc850bfd2db84e8b1ae5d3c848a
7
- data.tar.gz: 75fdbbefd7cfccc1849bf26e1c42e9f24f274c1d1ed27774d6b1a5085a5caafd30b4b8a0499d418686320157b6335116e0a25bf973b24fedee60210bb64c8d0d
6
+ metadata.gz: de8eb335498a0fd7dea007d77ac4cd25503ee85da121dfd9fa9c0eec96932294f532194abecbc57a40e1411449f14baecfda8006f3ce4a09aff6c52bc2afb03d
7
+ data.tar.gz: 55c0d63a5758238e008f9a88642c8e77df735192b67c0fa32d35f7e6562001d19dbd082fdada888f7fb679286f864275bc7c50aeb129bbc65ca16ae0e24e7f8d
@@ -22,8 +22,9 @@ module Canvas
22
22
  def run
23
23
  custom_types = Canvas::FetchCustomTypes.call
24
24
  block_files.each do |filename|
25
- file = File.read(filename)
26
- front_matter = extract_front_matter(file)
25
+ front_matter = extract_front_matter(filename)
26
+ next unless front_matter
27
+
27
28
  validate_format(filename, front_matter) &&
28
29
  validate_schema(filename, front_matter, custom_types)
29
30
  end
@@ -57,10 +58,18 @@ module Canvas
57
58
  end
58
59
  end
59
60
 
60
- def extract_front_matter(file)
61
+ def extract_front_matter(filename)
62
+ file = File.read(filename)
63
+
61
64
  extractor = Canvas::FrontMatterExtractor.new(file)
62
65
  front_matter = extractor.front_matter
63
66
  front_matter.nil? ? {} : YAML.safe_load(front_matter)
67
+ rescue Psych::SyntaxError
68
+ @offenses << Offense.new(
69
+ message: "Invalid Block Schema: #{filename} - \nFront matter's YAML is not in a valid format"
70
+ )
71
+
72
+ nil
64
73
  end
65
74
  end
66
75
  end
@@ -51,8 +51,7 @@ module Canvas
51
51
  front_matter["attributes"].values.all? { |attr| attr.is_a?(Hash) }
52
52
  end
53
53
 
54
- def validate_schema(front_matter)
55
- schema = extract_schema(front_matter)
54
+ def validate_schema(schema)
56
55
  validator = Validator::FooterSchema.new(
57
56
  schema: schema,
58
57
  custom_types: Canvas::FetchCustomTypes.call
@@ -71,11 +70,5 @@ module Canvas
71
70
  front_matter = extractor.front_matter
72
71
  front_matter.nil? ? {} : YAML.safe_load(front_matter)
73
72
  end
74
-
75
- def extract_schema(front_matter)
76
- front_matter.merge(
77
- "attributes" => Canvas::ExpandAttributes.call(front_matter["attributes"])
78
- )
79
- end
80
73
  end
81
74
  end
@@ -51,8 +51,7 @@ module Canvas
51
51
  front_matter["attributes"].values.all? { |attr| attr.is_a?(Hash) }
52
52
  end
53
53
 
54
- def validate_schema(front_matter)
55
- schema = extract_schema(front_matter)
54
+ def validate_schema(schema)
56
55
  validator = Validator::MenuSchema.new(
57
56
  schema: schema,
58
57
  custom_types: Canvas::FetchCustomTypes.call
@@ -71,11 +70,5 @@ module Canvas
71
70
  front_matter = extractor.front_matter
72
71
  front_matter.nil? ? {} : YAML.safe_load(front_matter)
73
72
  end
74
-
75
- def extract_schema(front_matter)
76
- front_matter.merge(
77
- "attributes" => Canvas::ExpandAttributes.call(front_matter["attributes"])
78
- )
79
- end
80
73
  end
81
74
  end
@@ -9,17 +9,25 @@ module Canvas
9
9
  # This class is used to validate a schema for a block.
10
10
  # Example of a valid block schema:
11
11
  # {
12
- # "attributes" => [
13
- # {
14
- # "name" => "my_title",
12
+ # "attributes" => {
13
+ # "my_title" => {
15
14
  # "type" => "string"
16
15
  # },
17
- # {
18
- # "name" => "my_color",
16
+ # "my_color" => {
19
17
  # "type" => "color",
20
18
  # "label" => "My color",
21
19
  # "hint" => "Select your favourite color"
22
20
  # }
21
+ # },
22
+ # "layout" => [
23
+ # {
24
+ # "type" => "tab",
25
+ # "label" => "Content",
26
+ # "elements" => [
27
+ # "my_title",
28
+ # "my_color"
29
+ # ]
30
+ # }
23
31
  # ]
24
32
  # }
25
33
  class BlockSchema
@@ -51,7 +59,7 @@ module Canvas
51
59
 
52
60
  def ensure_valid_format
53
61
  return true if schema.is_a?(Hash) &&
54
- (schema["attributes"].nil? || attributes_array_of_hashes?(schema))
62
+ (schema["attributes"].nil? || attributes_hash_of_hashes?(schema))
55
63
 
56
64
  @errors << "Schema is not in a valid format"
57
65
  false
@@ -78,7 +86,8 @@ module Canvas
78
86
  def ensure_attributes_are_valid
79
87
  return true unless schema["attributes"]
80
88
 
81
- schema["attributes"].each do |attribute_schema|
89
+ attributes = Canvas::ExpandAttributes.call(schema["attributes"])
90
+ attributes.each do |attribute_schema|
82
91
  attr_validator = Validator::SchemaAttribute.new(
83
92
  attribute: attribute_schema,
84
93
  custom_types: @custom_types
@@ -90,22 +99,17 @@ module Canvas
90
99
  end
91
100
  end
92
101
 
93
- def attributes_array_of_hashes?(schema)
94
- schema["attributes"].is_a?(Array) &&
95
- schema["attributes"].all? { |attr| attr.is_a?(Hash) }
102
+ def attributes_hash_of_hashes?(schema)
103
+ schema["attributes"].is_a?(Hash) &&
104
+ schema["attributes"].values.all? { |attr| attr.is_a?(Hash) }
96
105
  end
97
106
 
107
+ # To support older schemas that do not nest the attributes
108
+ # under the `attributes` key.
98
109
  def normalize_schema(schema)
99
- if schema.key?("attributes")
100
- {
101
- **schema,
102
- "attributes" => Canvas::ExpandAttributes.call(schema["attributes"])
103
- }
104
- else
105
- {
106
- "attributes" => Canvas::ExpandAttributes.call(schema)
107
- }
108
- end
110
+ return schema if schema.key?("attributes")
111
+
112
+ { "attributes" => schema }
109
113
  end
110
114
  end
111
115
  end
@@ -11,19 +11,27 @@ module Canvas
11
11
  #
12
12
  # Example:
13
13
  # {
14
- # "max_item_levels": 2,
15
- # "supports_open_new_tab": "true",
16
- # "attributes": {
17
- # "fixed": {
18
- # "group": "design",
19
- # "label": "Fixed when scrolling",
20
- # "hint": "The menu will stay fixed to the top when scrolling down the page.",
21
- # "type": "boolean",
22
- # "default: "false"
14
+ # "max_item_levels" => 2,
15
+ # "supports_open_new_tab" => "true",
16
+ # "attributes" => {
17
+ # "text_color" => {
18
+ # "type" => "color"
19
+ # },
20
+ # "background_color" => {
21
+ # "type" => "color"
23
22
  # }
24
- # }
23
+ # },
24
+ # "layout" => [
25
+ # {
26
+ # "type" => "tab",
27
+ # "label" => "Content",
28
+ # "elements" => [
29
+ # "text_color",
30
+ # "background_color"
31
+ # ]
32
+ # }
33
+ # ]
25
34
  # }
26
- #
27
35
  class FooterSchema < MenuSchema; end
28
36
  end
29
37
  end
@@ -9,13 +9,12 @@ module Canvas
9
9
  # This class is used to validate a layout definition, part of block schema.
10
10
  # Example of a valid layout definition:
11
11
  # {
12
- # "attributes" => [
13
- # {
14
- # "name" => "title",
12
+ # "attributes" => {
13
+ # "title" => {
15
14
  # "type" => "string"
16
15
  # }
17
16
  # ...
18
- # ],
17
+ # },
19
18
  # "layout" => [
20
19
  # {
21
20
  # "label" => "Design",
@@ -58,6 +57,7 @@ module Canvas
58
57
  ensure_no_unrecognized_keys
59
58
  ensure_no_duplicate_keys
60
59
  ensure_accordion_toggles_are_valid
60
+ ensure_unique_tabs
61
61
  end
62
62
 
63
63
  @errors.empty?
@@ -67,6 +67,21 @@ module Canvas
67
67
 
68
68
  attr_reader :schema
69
69
 
70
+ def ensure_unique_tabs
71
+ tabs = fetch_elements_of_type("tab")
72
+ duplicates =
73
+ tabs
74
+ .map { |item| [item[0]["label"], item[1]] }
75
+ .group_by { |(key, _)| key }
76
+ .filter { |key, usage| usage.size > 1 }
77
+
78
+ unless duplicates.empty?
79
+ duplicates.each do |tab, usage|
80
+ @errors << "Duplicated tab label `#{tab}` found. Location: #{usage.map { |(_, location)| location }.join(", ")}"
81
+ end
82
+ end
83
+ end
84
+
70
85
  def ensure_no_duplicate_keys
71
86
  attributes = fetch_all_attribute_names
72
87
  duplicates =
@@ -83,7 +98,7 @@ module Canvas
83
98
 
84
99
  def ensure_no_unrecognized_keys
85
100
  attributes = fetch_all_attribute_names
86
- defined_attributes = schema["attributes"]&.map { |definition| normalize_attribute(definition["name"]) } || []
101
+ defined_attributes = expanded_attributes.map { |definition| normalize_attribute(definition["name"]) } || []
87
102
 
88
103
  attributes.each do |attribute, location|
89
104
  @errors << "Unrecognized attribute `#{attribute}`. Location: #{location}" unless defined_attributes.include?(attribute)
@@ -144,13 +159,13 @@ module Canvas
144
159
  def ensure_accordion_toggles_are_valid
145
160
  accordion_toggles = fetch_elements_of_type("accordion_toggle")
146
161
  accordion_toggles.each do |accordion_toggle, location|
147
- toggle_attribute = schema["attributes"]&.detect { |attr|
162
+ toggle_attribute = expanded_attributes.detect { |attr|
148
163
  attr["name"] == accordion_toggle["toggle_attribute"]
149
164
  }
150
165
 
151
166
  if toggle_attribute.nil?
152
167
  @errors << "The toggle_attribute in accordion_toggle is unrecognized. Location: #{location}"
153
- elsif toggle_attribute["type"] != "boolean"
168
+ elsif toggle_attribute["type"]&.downcase != "boolean"
154
169
  @errors << "The toggle_attribute in accordion_toggle must be a boolean. Location: #{location}"
155
170
  end
156
171
  end
@@ -162,13 +177,19 @@ module Canvas
162
177
 
163
178
  def schema_definition
164
179
  File.read(
165
- File.join(File.dirname(__FILE__), "../../../", "schema_definitions", "block_layout.json")
180
+ File.join(File.dirname(__FILE__), "../../../", "schema_definitions", "layout.json")
166
181
  )
167
182
  end
168
183
 
169
184
  def normalize_attribute(name)
170
185
  name.strip.downcase
171
186
  end
187
+
188
+ def expanded_attributes
189
+ return [] if schema["attributes"].nil?
190
+
191
+ @_expanded_attributes ||= Canvas::ExpandAttributes.call(schema["attributes"])
192
+ end
172
193
  end
173
194
  end
174
195
  end
@@ -7,21 +7,33 @@ module Canvas
7
7
  #
8
8
  # Example:
9
9
  # {
10
- # "max_item_levels": 2,
11
- # "supports_open_new_tab": "true",
12
- # "attributes": {
13
- # "fixed": {
14
- # "group": "design",
15
- # "label": "Fixed when scrolling",
16
- # "hint": "The menu will stay fixed to the top when scrolling down the page.",
17
- # "type": "boolean",
18
- # "default: "false"
10
+ # "max_item_levels" => 2,
11
+ # "supports_open_new_tab" => "true",
12
+ # "attributes" => {
13
+ # "fixed" => {
14
+ # "group" => "design",
15
+ # "label" => "Fixed when scrolling",
16
+ # "hint" => "The menu will stay fixed to the top when scrolling down the page.",
17
+ # "type" => "boolean",
18
+ # "default" => "false"
19
+ # },
20
+ # "background_color" => {
21
+ # "type" => "color"
19
22
  # }
20
- # }
23
+ # },
24
+ # "layout" => [
25
+ # {
26
+ # "type" => "tab",
27
+ # "label" => "Content",
28
+ # "elements" => [
29
+ # "fixed",
30
+ # "background_color"
31
+ # ]
32
+ # }
33
+ # ]
21
34
  # }
22
- #
23
35
  class MenuSchema
24
- PERMITTED_KEYS = %w[max_item_levels supports_open_new_tab attributes].freeze
36
+ PERMITTED_KEYS = %w[max_item_levels supports_open_new_tab attributes layout].freeze
25
37
  ADDITIONAL_RESERVED_NAMES = %w[items type].freeze
26
38
 
27
39
  attr_reader :schema, :errors
@@ -38,6 +50,7 @@ module Canvas
38
50
  if ensure_valid_format
39
51
  ensure_no_unrecognized_keys
40
52
  ensure_max_item_levels_is_valid
53
+ ensure_layout_is_valid
41
54
  ensure_attributes_are_valid
42
55
  end
43
56
 
@@ -48,7 +61,7 @@ module Canvas
48
61
 
49
62
  def ensure_valid_format
50
63
  return true if schema.is_a?(Hash) &&
51
- (schema["attributes"].nil? || attributes_array_of_hashes?(schema))
64
+ (schema["attributes"].nil? || attributes_hash_of_hashes?(schema))
52
65
 
53
66
  @errors << "Schema is not in a valid format"
54
67
  false
@@ -70,10 +83,21 @@ module Canvas
70
83
  false
71
84
  end
72
85
 
86
+ def ensure_layout_is_valid
87
+ return true unless schema["layout"]
88
+
89
+ layout_validator = LayoutSchema.new(schema: @schema)
90
+ return true if layout_validator.validate
91
+
92
+ @errors += layout_validator.errors
93
+ false
94
+ end
95
+
73
96
  def ensure_attributes_are_valid
74
97
  return true unless schema["attributes"]
75
98
 
76
- schema["attributes"].each do |attribute_schema|
99
+ attributes = Canvas::ExpandAttributes.call(schema["attributes"])
100
+ attributes.each do |attribute_schema|
77
101
  attr_validator = Validator::SchemaAttribute.new(
78
102
  attribute: attribute_schema,
79
103
  custom_types: @custom_types,
@@ -86,9 +110,9 @@ module Canvas
86
110
  end
87
111
  end
88
112
 
89
- def attributes_array_of_hashes?(schema)
90
- schema["attributes"].is_a?(Array) &&
91
- schema["attributes"].all? { |attr| attr.is_a?(Hash) }
113
+ def attributes_hash_of_hashes?(schema)
114
+ schema["attributes"].is_a?(Hash) &&
115
+ schema["attributes"].values.all? { |attr| attr.is_a?(Hash) }
92
116
  end
93
117
  end
94
118
  end
@@ -6,9 +6,9 @@ module Canvas
6
6
  # :documented:
7
7
  # Attribute validations specific to link-type variables.
8
8
  class Link < Base
9
- ALLOWED_DEFAULT_KEYS = %w[url page post product].freeze
9
+ ALLOWED_DEFAULT_KEYS = %w[url page post experience accommodation].freeze
10
10
  INVALID_DEFAULT_ERROR = "\"default\" for link-type variables must include "\
11
- "a single url, page, post or product value"
11
+ "a single url, page, post, experience or accommodation value"
12
12
 
13
13
  def validate
14
14
  super &&
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Canvas
4
- VERSION = "1.5.0"
4
+ VERSION = "2.2.0"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: easol-canvas
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.0
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kyle Byrne
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2022-07-21 00:00:00.000000000 Z
12
+ date: 2022-08-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: thor
@@ -150,7 +150,7 @@ files:
150
150
  - lib/canvas/validators/schema_attributes/variant.rb
151
151
  - lib/canvas/version.rb
152
152
  - lib/easol/canvas.rb
153
- - schema_definitions/block_layout.json
153
+ - schema_definitions/layout.json
154
154
  homepage: https://rubygems.org/gems/easol-canvas
155
155
  licenses:
156
156
  - MIT
@@ -170,7 +170,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
170
170
  - !ruby/object:Gem::Version
171
171
  version: '0'
172
172
  requirements: []
173
- rubygems_version: 3.1.6
173
+ rubygems_version: 3.0.3.1
174
174
  signing_key:
175
175
  specification_version: 4
176
176
  summary: CLI to help with building themes for Easol