easol-canvas 1.0.0 → 1.3.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: 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: []