easol-canvas 1.0.0 → 1.3.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: 8570c1c4d1a8f7097f621722730ca8c882b633b901c8d22fb13f7dcbcb2ac8df
4
- data.tar.gz: d10b1319c6e1be3e0e43a77575fbf73f71f4a9f77582486d5b34d374d9c42105
3
+ metadata.gz: 4b413ee9262a5f7b363a8f53950da655c1c85aaf71474a331b412c62d5ae8f62
4
+ data.tar.gz: ecae8f840fffee09e161857beb61cb002d3006f63e00e7e52283342c228234a9
5
5
  SHA512:
6
- metadata.gz: 2dbfd55872ab41728e9243392a02c64551379cf42b99f59e455ade832fc028aa154b78e93600ec8bba8ac4fdcc52001850f2fd9cead452d64b896e1a997a0c63
7
- data.tar.gz: d6507b81b2fe0f72aad4407601606fa305b45e0d2142753eccc03cda5760277ceeaf54f83b6d8468274490e33afa4360da7174dd23599b4e5aa0a9fe484ab5d3
6
+ metadata.gz: 42fe4d0cdede7d029e2e4c6ced43c23defb19a109bf11df3a4933d9411d2c6c83173042f4f2fee148573042760e62645eeb44b2e3af53e28b9bc91588c23d0a1
7
+ data.tar.gz: 492e9fbeb71dfc80b56874d83e441ec799ae7ab04dedd668dc3e47c0cdfaabb0c9c9312fdeff2b792039ca44fb127af1eb1d876072c12d4c468567c6e20b6d6a
data/lib/canvas/check.rb CHANGED
@@ -1,6 +1,9 @@
1
- require 'cli/ui'
1
+ # frozen_string_literal: true
2
+
3
+ require "cli/ui"
2
4
 
3
5
  module Canvas
6
+ # :documented:
4
7
  class Check
5
8
  attr_reader :offenses
6
9
 
@@ -1,4 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Canvas
4
+ # :documented:
2
5
  class RequiredFilesCheck < Check
3
6
  REQUIRED_FILES = [
4
7
  "templates/product/index.{html,liquid}",
@@ -11,11 +14,18 @@ module Canvas
11
14
 
12
15
  def run
13
16
  REQUIRED_FILES.each do |filename|
14
- next unless Dir.glob(filename).empty?
17
+ file_paths = Dir.glob(filename)
18
+
15
19
 
16
- @offenses << Offense.new(
17
- message: "Missing file: #{filename}"
18
- )
20
+ if file_paths.empty?
21
+ @offenses << Offense.new(
22
+ message: "Missing file: #{filename}"
23
+ )
24
+ elsif File.zero?(file_paths.first)
25
+ @offenses << Offense.new(
26
+ message: "Empty file: #{file_paths.first}"
27
+ )
28
+ end
19
29
  end
20
30
  end
21
31
  end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Canvas
4
+ # :documented:
5
+ # This check will validate the JSON objects that represent the
6
+ # custom types that are defined in the /types directory.
7
+ class ValidCustomTypesCheck < Check
8
+ def run
9
+ custom_type_files.each do |filename|
10
+ schema = extract_json(filename)
11
+ validator = Validator::CustomType.new(schema: schema)
12
+
13
+ next if validator.validate
14
+
15
+ validator.errors.each do |message|
16
+ @offenses << Offense.new(
17
+ message: "Invalid Custom Type: #{filename} - \n#{message}"
18
+ )
19
+ end
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def custom_type_files
26
+ Dir.glob("types/*.json")
27
+ end
28
+
29
+ def extract_json(filename)
30
+ file = File.read(filename)
31
+ JSON.parse(file)
32
+ rescue JSON::ParserError
33
+ nil
34
+ end
35
+ end
36
+ end
@@ -1,4 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Canvas
4
+ # :documented:
2
5
  class ValidHtmlCheck < Check
3
6
  def run
4
7
  html_files.each do |filename|
@@ -1,4 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Canvas
4
+ # :documented:
2
5
  class ValidJsonCheck < Check
3
6
  def run
4
7
  json_files.each do |filename|
@@ -1,4 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Canvas
4
+ # :documented:
2
5
  class ValidLiquidCheck < Check
3
6
  def run
4
7
  register_tags!
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Canvas
4
+ # :documented:
5
+ #
6
+ # This check will find all files ending in .css, .scss or .sass
7
+ # and run them through the sass validator - {Canvas::Validator::Sass}.
8
+ class ValidSassCheck < Check
9
+ def run
10
+ sass_files.each do |filename|
11
+ file = File.read(filename)
12
+ validator = Validator::Sass.new(file)
13
+
14
+ next if validator.validate
15
+
16
+ validator.errors.each do |message|
17
+ @offenses << Offense.new(
18
+ message: "Invalid Sass: #{filename} - \n#{message}"
19
+ )
20
+ end
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ def sass_files
27
+ Dir.glob("**/*.{css,scss,sass}")
28
+ end
29
+ end
30
+ end
data/lib/canvas/checks.rb CHANGED
@@ -1,4 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Canvas
4
+ # :documented:
2
5
  class Checks
3
6
  class << self
4
7
  def registered
@@ -10,7 +13,7 @@ module Canvas
10
13
  return if @checks.include?(klass)
11
14
  @checks << klass
12
15
  end
13
-
16
+
14
17
  def deregister_all!
15
18
  @checks = []
16
19
  end
data/lib/canvas/cli.rb CHANGED
@@ -1,12 +1,21 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "thor"
2
- require 'cli/ui'
4
+ require "cli/ui"
3
5
 
4
6
  module Canvas
7
+ # :documented:
5
8
  class Cli < Thor
6
9
  desc "lint", "Prints a hello world message"
7
10
  def lint
8
11
  CLI::UI::StdoutRouter.enable
9
12
  Canvas::Lint.new.run
10
13
  end
14
+
15
+ map %w[--version -v] => :__print_version
16
+ desc "--version, -v", "print the version"
17
+ def __print_version
18
+ puts Canvas::VERSION
19
+ end
11
20
  end
12
21
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :documented:
4
+ # This file is used to define globally accessible constants.
3
5
  module Canvas
4
6
  module Constants
5
7
  COLOR_PALETTE_VALUES = %w[
@@ -8,5 +10,22 @@ module Canvas
8
10
  body-bg
9
11
  body-color
10
12
  ].freeze
13
+
14
+ PRIMITIVE_TYPES = %w[
15
+ image
16
+ product
17
+ post
18
+ page
19
+ link
20
+ text
21
+ string
22
+ boolean
23
+ number
24
+ color
25
+ select
26
+ range
27
+ radio
28
+ variant
29
+ ].freeze
11
30
  end
12
31
  end
data/lib/canvas/lint.rb CHANGED
@@ -1,6 +1,9 @@
1
- require 'cli/ui'
1
+ # frozen_string_literal: true
2
+
3
+ require "cli/ui"
2
4
 
3
5
  module Canvas
6
+ #:documented:
4
7
  class Lint
5
8
  def run
6
9
  output_context = CLI::UI::SpinGroup.new(auto_debrief: false)
@@ -29,13 +32,13 @@ module Canvas
29
32
  end
30
33
 
31
34
  def debrief_message
32
- CLI::UI::Frame.open('Failures', color: :red) do
35
+ CLI::UI::Frame.open("Failures", color: :red) do
33
36
  failed_checks = @checks.filter(&:failed?)
34
37
  failed_checks.map do |check|
35
38
  CLI::UI::Frame.open(check.class.name, color: :red) do
36
- output = check.offenses.map do |offense|
39
+ output = check.offenses.map { |offense|
37
40
  CLI::UI.fmt "{{x}} #{offense.message}"
38
- end
41
+ }
39
42
  puts output.join("\n")
40
43
  end
41
44
  end
@@ -1,4 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Canvas
4
+ # :documented:
2
5
  class Offense
3
6
  attr_reader :message
4
7
 
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Canvas
3
4
  # :documented:
4
5
  # This service can be used to extract front matter from a liquid string.
@@ -0,0 +1,141 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Canvas
4
+ module Validator
5
+ # :documented:
6
+ # This class is used to validate the JSON defining a custom type.
7
+ #
8
+ # An example of a valid custom type:
9
+ # {
10
+ # "key": "faq",
11
+ # "name": "Faq",
12
+ # "attributes": [
13
+ # {
14
+ # "name": "question",
15
+ # "label": "Question",
16
+ # "type": "string"
17
+ # },
18
+ # {
19
+ # "name": "answer",
20
+ # "label": "Answer",
21
+ # "type": "text"
22
+ # }
23
+ # ]
24
+ # }
25
+ #
26
+ class CustomType
27
+ REQUIRED_KEYS = %w[key name attributes].freeze
28
+
29
+ attr_reader :schema, :errors
30
+
31
+ def initialize(schema:)
32
+ @schema = schema
33
+ @errors = []
34
+ end
35
+
36
+ def validate
37
+ ensure_valid_format &&
38
+ ensure_has_required_keys &&
39
+ ensure_no_unrecognized_keys &&
40
+ ensure_keys_are_correct_types &&
41
+ ensure_key_value_is_not_reserved &&
42
+ ensure_no_duplicate_attributes &&
43
+ ensure_attributes_are_valid &&
44
+ ensure_first_attribute_not_array
45
+
46
+ errors.empty?
47
+ end
48
+
49
+ private
50
+
51
+ def ensure_valid_format
52
+ return true if schema.is_a?(Hash)
53
+
54
+ @errors << "Schema is not in a valid format"
55
+ false
56
+ end
57
+
58
+ def ensure_has_required_keys
59
+ missing_keys = REQUIRED_KEYS - schema.keys
60
+ return true if missing_keys.empty?
61
+
62
+ @errors << "Missing required keys: #{missing_keys.join(', ')}"
63
+ false
64
+ end
65
+
66
+ def ensure_no_unrecognized_keys
67
+ unrecognized_keys = schema.keys - REQUIRED_KEYS
68
+ return true if unrecognized_keys.empty?
69
+
70
+ @errors << "Unrecognized keys: #{unrecognized_keys.join(', ')}"
71
+ false
72
+ end
73
+
74
+ def ensure_keys_are_correct_types
75
+ if !schema["key"].is_a?(String)
76
+ @errors << "\"key\" must be a string"
77
+ return false
78
+ end
79
+
80
+ if !schema["name"].is_a?(String)
81
+ @errors << "\"name\" must be a string"
82
+ return false
83
+ end
84
+
85
+ if !schema["attributes"].is_a?(Array) ||
86
+ schema["attributes"].empty? ||
87
+ schema["attributes"].any? { |a| !a.is_a?(Hash) }
88
+ @errors << "\"attributes\" must be an array of objects"
89
+ return false
90
+ end
91
+
92
+ true
93
+ end
94
+
95
+ # Ensuring the value for key doesn't clash with our primitive type keys.
96
+ # See {Canvas::Constants::PRIMITIVE_TYPES}
97
+ def ensure_key_value_is_not_reserved
98
+ if schema["key"] && Constants::PRIMITIVE_TYPES.include?(schema["key"].downcase)
99
+ @errors << "\"key\" can't be one of these reserved words: #{Constants::PRIMITIVE_TYPES.join(', ')}"
100
+ return false
101
+ end
102
+
103
+ true
104
+ end
105
+
106
+ def ensure_no_duplicate_attributes
107
+ attribute_names = schema["attributes"].map { |a| a["name"] }
108
+ duplicated_names = attribute_names.select { |a| attribute_names.count(a) > 1 }.uniq
109
+
110
+ return true if duplicated_names.empty?
111
+
112
+ @errors << "Some attributes are duplicated: #{duplicated_names.join(', ')}"
113
+ false
114
+ end
115
+
116
+ def ensure_attributes_are_valid
117
+ return true unless schema["attributes"]
118
+
119
+ schema["attributes"].each do |attribute_schema|
120
+ attr_validator = Validator::SchemaAttribute.new(
121
+ attribute: attribute_schema,
122
+ custom_types: []
123
+ )
124
+ next if attr_validator.validate
125
+
126
+ @errors << "Attribute \"#{attribute_schema['name']}\" is invalid "\
127
+ "- #{attr_validator.errors.join(', ')}"
128
+ end
129
+ end
130
+
131
+ def ensure_first_attribute_not_array
132
+ first_attribute = schema.fetch("attributes").first
133
+
134
+ return true if first_attribute.nil? || first_attribute["array"] != true
135
+
136
+ @errors << "The first attribute cannot be an array"
137
+ false
138
+ end
139
+ end
140
+ end
141
+ end
@@ -1,8 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "nokogiri"
2
4
  require "liquid"
3
5
 
4
6
  module Canvas
5
7
  module Validator
8
+ # :documented:
6
9
  class Html
7
10
  LIQUID_TAG = /#{::Liquid::TagStart}.*?#{::Liquid::TagEnd}/om
8
11
  LIQUID_VARIABLE = /#{::Liquid::VariableStart}.*?#{::Liquid::VariableEnd}/om
@@ -1,7 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "json"
2
4
 
3
5
  module Canvas
4
6
  module Validator
7
+ # :documented:
5
8
  class Json
6
9
  attr_reader :errors
7
10
 
@@ -1,8 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "nokogiri"
2
4
  require "liquid"
3
5
 
4
6
  module Canvas
5
7
  module Validator
8
+ # :documented:
6
9
  class Liquid
7
10
  attr_reader :errors
8
11
 
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "sassc"
4
+
5
+ module Canvas
6
+ module Validator
7
+ # :documented:
8
+ #
9
+ # This validator can be used to validate Sass.
10
+ class Sass
11
+ attr_reader :errors
12
+
13
+ def initialize(file)
14
+ @file = file
15
+ end
16
+
17
+ def validate
18
+ SassC::Engine.new(@file, style: :compressed).render
19
+ true
20
+ rescue SassC::SyntaxError => e
21
+ @errors = [e.message]
22
+ false
23
+ end
24
+ end
25
+ end
26
+ end
@@ -34,7 +34,6 @@ module Canvas
34
34
  "radio" => SchemaAttribute::Radio,
35
35
  "variant" => SchemaAttribute::Variant,
36
36
  }.freeze
37
- PRIMITIVE_TYPES = VALIDATORS.keys
38
37
  RESERVED_NAMES = %w[
39
38
  page
40
39
  company
@@ -71,7 +70,7 @@ module Canvas
71
70
  end
72
71
 
73
72
  def valid_types
74
- PRIMITIVE_TYPES + custom_type_keys
73
+ Constants::PRIMITIVE_TYPES + custom_type_keys
75
74
  end
76
75
 
77
76
  def validator_for_type
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Canvas
2
- VERSION = "1.0.0"
4
+ VERSION = "1.3.0"
3
5
  end
data/lib/canvas.rb CHANGED
@@ -1,28 +1,35 @@
1
- require_relative "canvas/version"
2
- require_relative "canvas/constants"
3
- require_relative "canvas/cli"
4
- require_relative "canvas/lint"
5
- require_relative "canvas/check"
6
- require_relative "canvas/offense"
7
- require_relative "canvas/checks"
1
+ # frozen_string_literal: true
2
+
3
+ module Canvas
4
+ autoload :Check, "canvas/check"
5
+ autoload :Checks, "canvas/checks"
6
+ autoload :Cli, "canvas/cli"
7
+ autoload :Constants, "canvas/constants"
8
+ autoload :Lint, "canvas/lint"
9
+ autoload :Offense, "canvas/offense"
10
+ autoload :Version, "canvas/version"
11
+ end
8
12
 
9
13
  # We need to ensure Canvas::Validator::SchemaAttribute::Base is required first
10
14
  require_relative "canvas/validators/schema_attributes/base"
11
15
 
12
16
  # The attribute validators need to be required before Canvas::Validator::SchemaAttribute
13
17
  attribute_validators = Dir["#{__dir__}/canvas/validators/schema_attributes/*.rb"]
14
- attribute_validators.each { |file| require file }
18
+ attribute_validators.each do |file|
19
+ require file
20
+ end
15
21
 
16
22
  files = Dir["#{__dir__}/canvas/{checks,services,validators}/*.rb"]
17
- files.each { |file| require file }
23
+ files.each do |file|
24
+ require file
25
+ end
18
26
 
19
27
  Canvas::Checks.register(Canvas::RequiredFilesCheck)
20
28
  Canvas::Checks.register(Canvas::ValidHtmlCheck)
21
29
  Canvas::Checks.register(Canvas::ValidLiquidCheck)
30
+ Canvas::Checks.register(Canvas::ValidJsonCheck)
31
+ Canvas::Checks.register(Canvas::ValidSassCheck)
22
32
  Canvas::Checks.register(Canvas::ValidBlockSchemasCheck)
23
33
  Canvas::Checks.register(Canvas::ValidMenuSchemaCheck)
24
34
  Canvas::Checks.register(Canvas::ValidFooterSchemaCheck)
25
- Canvas::Checks.register(Canvas::ValidJsonCheck)
26
-
27
- module Canvas
28
- end
35
+ Canvas::Checks.register(Canvas::ValidCustomTypesCheck)
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Enables using this gem "as is"
4
+ require_relative "../canvas"
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.0.0
4
+ version: 1.3.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-05-27 00:00:00.000000000 Z
12
+ date: 2022-07-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: thor
@@ -67,6 +67,20 @@ dependencies:
67
67
  - - "~>"
68
68
  - !ruby/object:Gem::Version
69
69
  version: '5.3'
70
+ - !ruby/object:Gem::Dependency
71
+ name: sassc
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - "~>"
75
+ - !ruby/object:Gem::Version
76
+ version: '2.4'
77
+ type: :runtime
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - "~>"
82
+ - !ruby/object:Gem::Version
83
+ version: '2.4'
70
84
  description: |
71
85
  Canvas is a command line tool to help with building themes for Easol.
72
86
  It provides tooling to check theme directories for errors and to make sure
@@ -84,11 +98,13 @@ files:
84
98
  - lib/canvas/checks.rb
85
99
  - lib/canvas/checks/required_files_check.rb
86
100
  - lib/canvas/checks/valid_block_schemas_check.rb
101
+ - lib/canvas/checks/valid_custom_types_check.rb
87
102
  - lib/canvas/checks/valid_footer_schema_check.rb
88
103
  - lib/canvas/checks/valid_html_check.rb
89
104
  - lib/canvas/checks/valid_json_check.rb
90
105
  - lib/canvas/checks/valid_liquid_check.rb
91
106
  - lib/canvas/checks/valid_menu_schema_check.rb
107
+ - lib/canvas/checks/valid_sass_check.rb
92
108
  - lib/canvas/cli.rb
93
109
  - lib/canvas/constants.rb
94
110
  - lib/canvas/lint.rb
@@ -97,11 +113,13 @@ files:
97
113
  - lib/canvas/services/fetch_custom_types.rb
98
114
  - lib/canvas/services/front_matter_extractor.rb
99
115
  - lib/canvas/validators/block_schema.rb
116
+ - lib/canvas/validators/custom_type.rb
100
117
  - lib/canvas/validators/footer_schema.rb
101
118
  - lib/canvas/validators/html.rb
102
119
  - lib/canvas/validators/json.rb
103
120
  - lib/canvas/validators/liquid.rb
104
121
  - lib/canvas/validators/menu_schema.rb
122
+ - lib/canvas/validators/sass.rb
105
123
  - lib/canvas/validators/schema_attribute.rb
106
124
  - lib/canvas/validators/schema_attributes/base.rb
107
125
  - lib/canvas/validators/schema_attributes/color.rb
@@ -116,11 +134,12 @@ files:
116
134
  - lib/canvas/validators/schema_attributes/select.rb
117
135
  - lib/canvas/validators/schema_attributes/variant.rb
118
136
  - lib/canvas/version.rb
137
+ - lib/easol/canvas.rb
119
138
  homepage: https://rubygems.org/gems/easol-canvas
120
139
  licenses:
121
140
  - MIT
122
141
  metadata: {}
123
- post_install_message:
142
+ post_install_message:
124
143
  rdoc_options: []
125
144
  require_paths:
126
145
  - lib
@@ -135,8 +154,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
135
154
  - !ruby/object:Gem::Version
136
155
  version: '0'
137
156
  requirements: []
138
- rubygems_version: 3.1.6
139
- signing_key:
157
+ rubygems_version: 3.3.7
158
+ signing_key:
140
159
  specification_version: 4
141
160
  summary: CLI to help with building themes for Easol
142
161
  test_files: []