easol-canvas 1.3.0 → 2.0.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: 4b413ee9262a5f7b363a8f53950da655c1c85aaf71474a331b412c62d5ae8f62
4
- data.tar.gz: ecae8f840fffee09e161857beb61cb002d3006f63e00e7e52283342c228234a9
3
+ metadata.gz: 5446d70b87d779a13b4a5b3f132b91a29722d84167fcc2ac9b61a142e7b5a45c
4
+ data.tar.gz: ccc2f5bc197c2f7ec72969289989742f3400f69e2a2eb468c001fd994237f2bc
5
5
  SHA512:
6
- metadata.gz: 42fe4d0cdede7d029e2e4c6ced43c23defb19a109bf11df3a4933d9411d2c6c83173042f4f2fee148573042760e62645eeb44b2e3af53e28b9bc91588c23d0a1
7
- data.tar.gz: 492e9fbeb71dfc80b56874d83e441ec799ae7ab04dedd668dc3e47c0cdfaabb0c9c9312fdeff2b792039ca44fb127af1eb1d876072c12d4c468567c6e20b6d6a
6
+ metadata.gz: a1b2ab985beac4aef8812c35fcda2707c52fc204c26435d7bf9dd7b33441dc9666739e4a9319e64e1fab31fab8f46d73e7af79c63b14ae21a084f517c0e7f9ea
7
+ data.tar.gz: f57a9566ebb142092e574dc0889a636c673342e5a71e5ccc1f111951c4ac1fa78995dbbe090cd2de7d5c3cd073dbecd3999aca06889a3beb5419d72616547090
@@ -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
@@ -37,7 +38,8 @@ module Canvas
37
38
 
38
39
  def validate_format(filename, front_matter)
39
40
  return true if front_matter.is_a?(Hash) &&
40
- front_matter.values.all? { |attr| attr.is_a?(Hash) }
41
+ (front_matter.key?("attributes") ? front_matter["attributes"] : front_matter).values.all? { |attr| attr.is_a?(Hash) }
42
+
41
43
 
42
44
  @offenses << Offense.new(
43
45
  message: "Invalid Block Schema: #{filename} - \nSchema is not in a valid format"
@@ -45,8 +47,7 @@ module Canvas
45
47
  false
46
48
  end
47
49
 
48
- def validate_schema(filename, front_matter, custom_types)
49
- schema = extract_schema(front_matter)
50
+ def validate_schema(filename, schema, custom_types)
50
51
  validator = Validator::BlockSchema.new(schema: schema, custom_types: custom_types)
51
52
  return if validator.validate
52
53
 
@@ -57,16 +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)
64
- end
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
+ )
65
71
 
66
- def extract_schema(front_matter)
67
- {
68
- "attributes" => Canvas::ExpandAttributes.call(front_matter)
69
- }
72
+ nil
70
73
  end
71
74
  end
72
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
@@ -30,6 +30,7 @@ module Canvas
30
30
  # @return [Array<Hash>] array of hashes that represent each attribute
31
31
  def call(attributes_hash)
32
32
  return [] if attributes_hash.nil?
33
+ return attributes_hash if attributes_hash.is_a?(Array)
33
34
 
34
35
  attributes_hash.each_with_object([]) do |(name, attribute_hash), attrs|
35
36
  attrs << attribute_hash.merge("name" => name)
@@ -9,35 +9,46 @@ 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
26
- PERMITTED_KEYS = %w[attributes].freeze
34
+ PERMITTED_KEYS = %w[attributes layout].freeze
27
35
 
28
36
  attr_reader :errors, :schema
29
37
 
30
38
  # @param schema [Hash] the schema to be validated
31
39
  # @param custom_types [Array<Hash>] a list of custom types
32
40
  def initialize(schema:, custom_types: [])
33
- @schema = schema
41
+ @schema = normalize_schema(schema)
34
42
  @custom_types = custom_types
35
43
  @errors = []
36
44
  end
37
45
 
38
46
  def validate
47
+ @errors = []
48
+
39
49
  if ensure_valid_format
40
50
  ensure_no_unrecognized_keys
51
+ ensure_layout_is_valid
41
52
  ensure_attributes_are_valid
42
53
  end
43
54
 
@@ -48,12 +59,22 @@ module Canvas
48
59
 
49
60
  def ensure_valid_format
50
61
  return true if schema.is_a?(Hash) &&
51
- (schema["attributes"].nil? || attributes_array_of_hashes?(schema))
62
+ (schema["attributes"].nil? || attributes_hash_of_hashes?(schema))
52
63
 
53
64
  @errors << "Schema is not in a valid format"
54
65
  false
55
66
  end
56
67
 
68
+ def ensure_layout_is_valid
69
+ return true unless schema["layout"]
70
+
71
+ layout_validator = LayoutSchema.new(schema: @schema)
72
+ return true if layout_validator.validate
73
+
74
+ @errors += layout_validator.errors
75
+ false
76
+ end
77
+
57
78
  def ensure_no_unrecognized_keys
58
79
  unrecognized_keys = schema.keys - PERMITTED_KEYS
59
80
  return true if unrecognized_keys.empty?
@@ -65,7 +86,8 @@ module Canvas
65
86
  def ensure_attributes_are_valid
66
87
  return true unless schema["attributes"]
67
88
 
68
- schema["attributes"].each do |attribute_schema|
89
+ attributes = Canvas::ExpandAttributes.call(schema["attributes"])
90
+ attributes.each do |attribute_schema|
69
91
  attr_validator = Validator::SchemaAttribute.new(
70
92
  attribute: attribute_schema,
71
93
  custom_types: @custom_types
@@ -77,9 +99,17 @@ module Canvas
77
99
  end
78
100
  end
79
101
 
80
- def attributes_array_of_hashes?(schema)
81
- schema["attributes"].is_a?(Array) &&
82
- 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) }
105
+ end
106
+
107
+ # To support older schemas that do not nest the attributes
108
+ # under the `attributes` key.
109
+ def normalize_schema(schema)
110
+ return schema if schema.key?("attributes")
111
+
112
+ { "attributes" => schema }
83
113
  end
84
114
  end
85
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
@@ -0,0 +1,179 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+ require "json-schema"
5
+
6
+ module Canvas
7
+ module Validator
8
+ # :documented:
9
+ # This class is used to validate a layout definition, part of block schema.
10
+ # Example of a valid layout definition:
11
+ # {
12
+ # "attributes" => {
13
+ # "title" => {
14
+ # "type" => "string"
15
+ # }
16
+ # ...
17
+ # },
18
+ # "layout" => [
19
+ # {
20
+ # "label" => "Design",
21
+ # "type" => "tab",
22
+ # "elements" => [
23
+ # "heading",
24
+ # {
25
+ # "type" => "accordion",
26
+ # "label" => "Logo",
27
+ # "elements" => [
28
+ # "description",
29
+ # { "type" => "attribute", "name" => "logo_alt" },
30
+ # "title"
31
+ # ]
32
+ # },
33
+ # {
34
+ # "type" => "accordion_toggle",
35
+ # "toggle_attribute" => "cta_enabled",
36
+ # "elements" => [
37
+ # "cta_text",
38
+ # "cta_target"
39
+ # ]
40
+ # }
41
+ # ]
42
+ # }
43
+ # ]
44
+ # }
45
+ class LayoutSchema
46
+ attr_reader :errors
47
+
48
+ def initialize(schema:)
49
+ @schema = schema
50
+ @errors = []
51
+ end
52
+
53
+ def validate
54
+ @errors = []
55
+
56
+ if ensure_valid_format
57
+ ensure_no_unrecognized_keys
58
+ ensure_no_duplicate_keys
59
+ ensure_accordion_toggles_are_valid
60
+ end
61
+
62
+ @errors.empty?
63
+ end
64
+
65
+ private
66
+
67
+ attr_reader :schema
68
+
69
+ def ensure_no_duplicate_keys
70
+ attributes = fetch_all_attribute_names
71
+ duplicates =
72
+ attributes
73
+ .group_by { |(key)| key }
74
+ .filter { |key, usage| usage.size > 1 }
75
+
76
+ unless duplicates.empty?
77
+ duplicates.each do |attribute, usage|
78
+ @errors << "Duplicated attribute key `#{attribute}` found. Location: #{usage.map { |(_, location)| location }.join(", ")}"
79
+ end
80
+ end
81
+ end
82
+
83
+ def ensure_no_unrecognized_keys
84
+ attributes = fetch_all_attribute_names
85
+ defined_attributes = expanded_attributes.map { |definition| normalize_attribute(definition["name"]) } || []
86
+
87
+ attributes.each do |attribute, location|
88
+ @errors << "Unrecognized attribute `#{attribute}`. Location: #{location}" unless defined_attributes.include?(attribute)
89
+ end
90
+ end
91
+
92
+ # @return [Array<Array(String, String)>] an array of all the attribute names that
93
+ # are mentioned in the layout schema, along with its path. The names are
94
+ # normalized, i.e. downcased.
95
+ def fetch_all_attribute_names
96
+ attributes = fetch_elements_of_type("attribute")
97
+ attributes.map do |(node, path)|
98
+ [
99
+ normalize_attribute(node.is_a?(Hash) ? node["name"] : node),
100
+ path
101
+ ]
102
+ end
103
+ end
104
+
105
+ # @param type [String] the element type to fetch
106
+ # @return [Array<Array(<Hash, String>, String)] an array of elements that match
107
+ # the given type. Each element is an array containing the node and its path.
108
+ def fetch_elements_of_type(type)
109
+ elements = []
110
+
111
+ fetch_element = ->(node, path) {
112
+ if type == "attribute" && node.is_a?(String)
113
+ elements << [node, path]
114
+ elsif node["type"] == type
115
+ elements << [node, path]
116
+ end
117
+
118
+ if node.is_a?(Hash) && node.key?("elements")
119
+ node["elements"].each_with_index do |element, i|
120
+ current_path = "#{path}/elements/#{i}"
121
+ fetch_element.call(element, current_path)
122
+ end
123
+ end
124
+ }
125
+
126
+ layout_schema.each_with_index do |tab, i|
127
+ current_path = "layout/#{i}"
128
+ fetch_element.call(tab, current_path)
129
+ end
130
+
131
+ elements
132
+ end
133
+
134
+ def ensure_valid_format
135
+ result = JSON::Validator.fully_validate(schema_definition, { "layout" => layout_schema }, strict: true, clear_cache: true)
136
+
137
+ return true if result.empty?
138
+
139
+ @errors += result
140
+ false
141
+ end
142
+
143
+ def ensure_accordion_toggles_are_valid
144
+ accordion_toggles = fetch_elements_of_type("accordion_toggle")
145
+ accordion_toggles.each do |accordion_toggle, location|
146
+ toggle_attribute = expanded_attributes.detect { |attr|
147
+ attr["name"] == accordion_toggle["toggle_attribute"]
148
+ }
149
+
150
+ if toggle_attribute.nil?
151
+ @errors << "The toggle_attribute in accordion_toggle is unrecognized. Location: #{location}"
152
+ elsif toggle_attribute["type"]&.downcase != "boolean"
153
+ @errors << "The toggle_attribute in accordion_toggle must be a boolean. Location: #{location}"
154
+ end
155
+ end
156
+ end
157
+
158
+ def layout_schema
159
+ schema["layout"] || []
160
+ end
161
+
162
+ def schema_definition
163
+ File.read(
164
+ File.join(File.dirname(__FILE__), "../../../", "schema_definitions", "layout.json")
165
+ )
166
+ end
167
+
168
+ def normalize_attribute(name)
169
+ name.strip.downcase
170
+ end
171
+
172
+ def expanded_attributes
173
+ return [] if schema["attributes"].nil?
174
+
175
+ @_expanded_attributes ||= Canvas::ExpandAttributes.call(schema["attributes"])
176
+ end
177
+ end
178
+ end
179
+ 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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Canvas
4
- VERSION = "1.3.0"
4
+ VERSION = "2.0.0"
5
5
  end
@@ -0,0 +1,87 @@
1
+ {
2
+ "type": "object",
3
+ "properties": {
4
+ "layout": {
5
+ "type": "array",
6
+ "items": { "$ref": "#/$defs/tab" }
7
+ }
8
+ },
9
+ "$defs": {
10
+ "tab": {
11
+ "type": "object",
12
+ "required": ["type", "label"],
13
+ "properties": {
14
+ "type": {
15
+ "type": "string",
16
+ "const": "tab"
17
+ },
18
+ "label": {
19
+ "type": "string"
20
+ },
21
+ "elements": {
22
+ "type": "array",
23
+ "minItems": 1,
24
+ "items": {
25
+ "oneOf": [
26
+ { "type": "string" },
27
+ { "$ref": "#/$defs/accordion" },
28
+ { "$ref": "#/$defs/accordion_toggle" },
29
+ { "$ref": "#/$defs/attribute" }
30
+ ]
31
+ }
32
+ }
33
+ }
34
+ },
35
+ "accordion": {
36
+ "type": "object",
37
+ "required": ["label", "type"],
38
+ "properties": {
39
+ "type": {
40
+ "type": "string",
41
+ "const": "accordion"
42
+ },
43
+ "label": {
44
+ "type": "string"
45
+ },
46
+ "elements": {
47
+ "type": "array",
48
+ "items": {
49
+ "oneOf": [{ "type": "string" }, { "$ref": "#/$defs/attribute" }]
50
+ }
51
+ }
52
+ }
53
+ },
54
+ "accordion_toggle": {
55
+ "type": "object",
56
+ "required": ["type", "toggle_attribute", "elements"],
57
+ "properties": {
58
+ "type": {
59
+ "type": "string",
60
+ "const": "accordion_toggle"
61
+ },
62
+ "toggle_attribute": {
63
+ "type": "string"
64
+ },
65
+ "elements": {
66
+ "type": "array",
67
+ "items": {
68
+ "oneOf": [{ "type": "string" }, { "$ref": "#/$defs/attribute" }]
69
+ }
70
+ }
71
+ }
72
+ },
73
+ "attribute": {
74
+ "type": "object",
75
+ "required": ["name", "type"],
76
+ "properties": {
77
+ "type": {
78
+ "type": "string",
79
+ "const": "attribute"
80
+ },
81
+ "name": {
82
+ "type": "string"
83
+ }
84
+ }
85
+ }
86
+ }
87
+ }
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: easol-canvas
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kyle Byrne
8
8
  - Ian Mooney
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2022-07-06 00:00:00.000000000 Z
12
+ date: 2022-07-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: thor
@@ -81,6 +81,20 @@ dependencies:
81
81
  - - "~>"
82
82
  - !ruby/object:Gem::Version
83
83
  version: '2.4'
84
+ - !ruby/object:Gem::Dependency
85
+ name: json-schema
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - "~>"
89
+ - !ruby/object:Gem::Version
90
+ version: '3'
91
+ type: :runtime
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - "~>"
96
+ - !ruby/object:Gem::Version
97
+ version: '3'
84
98
  description: |
85
99
  Canvas is a command line tool to help with building themes for Easol.
86
100
  It provides tooling to check theme directories for errors and to make sure
@@ -117,6 +131,7 @@ files:
117
131
  - lib/canvas/validators/footer_schema.rb
118
132
  - lib/canvas/validators/html.rb
119
133
  - lib/canvas/validators/json.rb
134
+ - lib/canvas/validators/layout_schema.rb
120
135
  - lib/canvas/validators/liquid.rb
121
136
  - lib/canvas/validators/menu_schema.rb
122
137
  - lib/canvas/validators/sass.rb
@@ -135,11 +150,12 @@ files:
135
150
  - lib/canvas/validators/schema_attributes/variant.rb
136
151
  - lib/canvas/version.rb
137
152
  - lib/easol/canvas.rb
153
+ - schema_definitions/layout.json
138
154
  homepage: https://rubygems.org/gems/easol-canvas
139
155
  licenses:
140
156
  - MIT
141
157
  metadata: {}
142
- post_install_message:
158
+ post_install_message:
143
159
  rdoc_options: []
144
160
  require_paths:
145
161
  - lib
@@ -154,8 +170,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
154
170
  - !ruby/object:Gem::Version
155
171
  version: '0'
156
172
  requirements: []
157
- rubygems_version: 3.3.7
158
- signing_key:
173
+ rubygems_version: 3.1.6
174
+ signing_key:
159
175
  specification_version: 4
160
176
  summary: CLI to help with building themes for Easol
161
177
  test_files: []