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 +4 -4
- data/lib/canvas/checks/valid_block_schemas_check.rb +14 -11
- data/lib/canvas/checks/valid_footer_schema_check.rb +1 -8
- data/lib/canvas/checks/valid_menu_schema_check.rb +1 -8
- data/lib/canvas/services/expand_attributes.rb +1 -0
- data/lib/canvas/validators/block_schema.rb +42 -12
- data/lib/canvas/validators/footer_schema.rb +19 -11
- data/lib/canvas/validators/layout_schema.rb +179 -0
- data/lib/canvas/validators/menu_schema.rb +41 -17
- data/lib/canvas/version.rb +1 -1
- data/schema_definitions/layout.json +87 -0
- metadata +22 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5446d70b87d779a13b4a5b3f132b91a29722d84167fcc2ac9b61a142e7b5a45c
|
4
|
+
data.tar.gz: ccc2f5bc197c2f7ec72969289989742f3400f69e2a2eb468c001fd994237f2bc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
26
|
-
|
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,
|
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(
|
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
|
-
|
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
|
-
|
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(
|
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(
|
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? ||
|
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"]
|
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
|
81
|
-
schema["attributes"].is_a?(
|
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"
|
15
|
-
# "supports_open_new_tab"
|
16
|
-
# "attributes"
|
17
|
-
# "
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
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"
|
11
|
-
# "supports_open_new_tab"
|
12
|
-
# "attributes"
|
13
|
-
# "fixed"
|
14
|
-
# "group"
|
15
|
-
# "label"
|
16
|
-
# "hint"
|
17
|
-
# "type"
|
18
|
-
# "default
|
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? ||
|
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"]
|
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
|
90
|
-
schema["attributes"].is_a?(
|
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
|
data/lib/canvas/version.rb
CHANGED
@@ -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:
|
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-
|
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.
|
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: []
|