easol-canvas 1.5.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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