inhouse-tailor 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e6c1aaabda93e65ef7363506db4cc357312c6a4bb91775c2a4e7834ff8bbadfc
4
+ data.tar.gz: b7b1373ec7f1dade3faffa697f481c8d32a845dff2de36e0846904d5b4771476
5
+ SHA512:
6
+ metadata.gz: 4619496c1f187f75ce549e45a595cc59b670a133fb9bfc5f0f1d4e68589aaf6ccdc9cddc8949ac2debce628d0e5f360d6e5ff5f803adb0273cfa37df817abf71
7
+ data.tar.gz: 5e3b987dce364ee6cf1c2fa9bc2aa71667d92e41d6211143e3b001624541953c4c2472292213c91cb563eed26bbcd2ea18909c7f009b6e2ac3ebd45f71ba9086
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,6 @@
1
+ require:
2
+ - rubocop-inhouse
3
+
4
+ inherit_gem:
5
+ rubocop-inhouse:
6
+ - config/default.yml
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ## [Unreleased]
2
+
3
+ ## [0.1.0] - 2023-10-31
4
+
5
+ - Initial release
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2023 Nolan J Tait
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,71 @@
1
+ # Tailor
2
+
3
+ Tailor your CSS utility classes to your components.
4
+
5
+ ## Installation
6
+
7
+ Install the gem and add to the application's Gemfile by executing:
8
+
9
+ $ bundle add inhouse-tailor
10
+
11
+ If bundler is not being used to manage dependencies, install the gem by executing:
12
+
13
+ $ gem install inhouse-tailor
14
+
15
+ ## Usage
16
+
17
+ ```ruby
18
+ theme = Tailor.new(container: "block")
19
+ theme.add(:container, "p-sm")
20
+ theme.add(:container, "flex")
21
+ theme.remove(:container, "p-sm")
22
+
23
+ theme[:container].to_s #=> "block flex"
24
+ ```
25
+
26
+ ```ruby
27
+ theme = Tailor.new(container: "block")
28
+ other_theme = Tailor.new(container: "inline-block")
29
+
30
+ merged = theme.merge(other_theme)
31
+ merged[:container].to_s #=> "block inline-block"
32
+
33
+ inherited = theme.inherit(other_theme)
34
+ inherited[:container].to_s #=> "block"
35
+
36
+ overridden = theme.override(other_theme)
37
+ overridden[:container].to_s #=> "inline-block"
38
+ ```
39
+
40
+ ```ruby
41
+ class MyStyle
42
+ include Tailor::DSL
43
+
44
+ style :container, ["justify-between"]
45
+ end
46
+
47
+ component = MyStyle.new
48
+ component.style[:container].to_s #=> "justify-between"
49
+ ```
50
+
51
+ ## Development
52
+
53
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run
54
+ `rake spec` to run the tests. You can also run `bin/console` for an interactive
55
+ prompt that will allow you to experiment.
56
+
57
+ To install this gem onto your local machine, run `bundle exec rake install`. To
58
+ release a new version, update the version number in `version.rb`, and then run
59
+ `bundle exec rake release`, which will create a git tag for the version, push
60
+ git commits and the created tag, and push the `.gem` file to
61
+ [rubygems.org](https://rubygems.org).
62
+
63
+ ## Contributing
64
+
65
+ Bug reports and pull requests are welcome on GitHub at
66
+ https://github.com/nolantait/tailor.
67
+
68
+ ## License
69
+
70
+ The gem is available as open source under the terms of the [MIT
71
+ License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ require "rubocop/rake_task"
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ task default: %i[spec rubocop]
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/tailor/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "inhouse-tailor"
7
+ spec.version = Tailor::VERSION
8
+ spec.authors = ["Nolan J Tait"]
9
+ spec.email = ["nolanjtait@gmail.com"]
10
+
11
+ spec.summary = "Tailor your utility based css styles into your components"
12
+ spec.description = spec.summary
13
+ spec.homepage = "https://github.com/nolantait/tailor"
14
+ spec.license = "MIT"
15
+ spec.required_ruby_version = ">= 3.2.0"
16
+
17
+ spec.metadata["homepage_uri"] = spec.homepage
18
+ spec.metadata["source_code_uri"] = spec.homepage
19
+ spec.metadata["changelog_uri"] = spec.homepage
20
+
21
+ # Specify which files should be added to the gem when it is released. The `git
22
+ # ls-files -z` loads the files in the RubyGem that have been added into git.
23
+ spec.files = Dir.chdir(__dir__) do
24
+ `git ls-files -z`.split("\x0").reject do |f|
25
+ (File.expand_path(f) == __FILE__) ||
26
+ f.start_with?(
27
+ *%w[
28
+ bin/
29
+ test/
30
+ spec/
31
+ features/
32
+ .git
33
+ .circleci
34
+ appveyor
35
+ Gemfile
36
+ ]
37
+ )
38
+ end
39
+ end
40
+ spec.bindir = "exe"
41
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
42
+ spec.require_paths = ["lib"]
43
+
44
+ # Uncomment to register a new dependency of your gem
45
+ spec.add_dependency "dry-struct", "~> 1.6"
46
+ spec.add_dependency "dry-types", "~> 1.7"
47
+ spec.add_dependency "hashie", "~> 5"
48
+
49
+ # For more information and examples about making a new gem, check out our
50
+ # guide at: https://bundler.io/guides/creating_gem.html
51
+ spec.metadata["rubygems_mfa_required"] = "true"
52
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "tailor"
data/lib/tailor/dsl.rb ADDED
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tailor
4
+ module DSL
5
+ module ClassMethods
6
+ def __tailor_namespace
7
+ @__tailor_namespace ||= Namespace.new
8
+ end
9
+
10
+ def style(key, css_classes)
11
+ __tailor_namespace.style(key, css_classes)
12
+ end
13
+
14
+ def tailor(key, &block)
15
+ __tailor_namespace.namespace(key, &block)
16
+ end
17
+ end
18
+
19
+ def self.included(klass)
20
+ klass.extend ClassMethods
21
+ end
22
+
23
+ def style
24
+ @style ||= self.class.__tailor_namespace
25
+ end
26
+
27
+ def style=(other_style)
28
+ @style = other_style
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tailor
4
+ class Namespace
5
+ # DOCS: Represents the public interface of Theme.
6
+ # DSL uses this to manage nested themes.
7
+
8
+ attr_reader :theme
9
+
10
+ def initialize(...)
11
+ @theme = Theme.new(...)
12
+ end
13
+
14
+ def [](key)
15
+ @theme[key]
16
+ end
17
+
18
+ def add(key, styleable)
19
+ case styleable
20
+ when Namespace then @theme.add_namespace(key, styleable)
21
+ when Style then @theme.add_style(key, styleable)
22
+ when String then @theme.add(key, styleable)
23
+ else
24
+ raise ArgumentError, "Invalid styleable: #{styleable.inspect}"
25
+ end
26
+ end
27
+
28
+ def style(key, classes)
29
+ classes << "" if classes.empty?
30
+ add key, Style.new(classes:)
31
+ end
32
+
33
+ def namespace(key, &block)
34
+ self.class.new.tap do |namespace|
35
+ namespace.instance_eval(&block)
36
+ add key, namespace
37
+ end
38
+ end
39
+
40
+ protected
41
+
42
+ def respond_to_missing?(method, *)
43
+ theme.styles.respond_to?(method)
44
+ end
45
+
46
+ def method_missing(method, *, &block)
47
+ if theme.styles.respond_to?(method)
48
+ theme.styles.send(method, *, &block)
49
+ else
50
+ super
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tailor
4
+ class Style < Dry::Struct
5
+ attribute :classes, Types::Array.of(Types::String).default([].freeze)
6
+
7
+ def add(style)
8
+ self.class.new(
9
+ classes: classes + style.classes
10
+ )
11
+ end
12
+
13
+ def remove(style)
14
+ self.class.new(
15
+ classes: classes - style.classes
16
+ )
17
+ end
18
+
19
+ def merge(other_style)
20
+ self.class.new(
21
+ classes: (classes + other_style.classes).uniq
22
+ )
23
+ end
24
+
25
+ def to_s
26
+ classes.to_a.join(" ")
27
+ end
28
+
29
+ def to_str
30
+ to_s
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tailor
4
+ class Theme
5
+ attr_accessor :styles
6
+
7
+ class Collection < Hash
8
+ include Hashie::Extensions::MergeInitializer
9
+ include Hashie::Extensions::MethodAccess
10
+ include Hashie::Extensions::DeepMerge
11
+ end
12
+
13
+ CollectionFactory = -> do
14
+ Collection.new do |hash, key|
15
+ hash[key] = Style.new
16
+ end
17
+ end
18
+
19
+ private_constant :CollectionFactory
20
+
21
+ def initialize_copy(other)
22
+ self.styles = CollectionFactory.call
23
+ other.styles.each do |key, style|
24
+ add_style(key, style)
25
+ end
26
+ super
27
+ end
28
+
29
+ def initialize(**theme)
30
+ @styles = CollectionFactory.call
31
+
32
+ theme.each do |key, css_classes|
33
+ add(key, css_classes)
34
+ end
35
+ end
36
+
37
+ def add_namespace(key, namespace)
38
+ tap do
39
+ styles[key] = namespace
40
+ end
41
+ end
42
+
43
+ def add_style(key, style)
44
+ tap do
45
+ styles[key] = styles[key].add style
46
+ end
47
+ end
48
+
49
+ def add(key, classes)
50
+ tap do
51
+ Array(classes).tap do |classes|
52
+ classes << "" if classes.empty?
53
+ styles[key] = styles[key].add Style.new(classes:)
54
+ end
55
+ end
56
+ end
57
+
58
+ def remove(key, classes)
59
+ tap do
60
+ Array(classes).tap do |classes|
61
+ styles[key] = styles[key].remove Style.new(classes:)
62
+ end
63
+ end
64
+ end
65
+
66
+ def [](key)
67
+ styles[key]
68
+ end
69
+
70
+ def inherit(other_theme)
71
+ other_theme.override(self)
72
+ end
73
+
74
+ def override(other_theme)
75
+ styles.merge(other_theme.styles)
76
+ end
77
+
78
+ def merge(other_theme)
79
+ dup.tap do |theme|
80
+ other_theme.styles.each do |key, style|
81
+ theme.styles[key] = theme.styles[key].merge(style)
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tailor
4
+ module Types
5
+ include Dry.Types
6
+ end
7
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tailor
4
+ VERSION = "0.1.0"
5
+ public_constant :VERSION
6
+ end
data/lib/tailor.rb ADDED
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/types"
4
+ require "dry/struct"
5
+ require "hashie"
6
+
7
+ require_relative "tailor/version"
8
+ require_relative "tailor/types"
9
+ require_relative "tailor/style"
10
+ require_relative "tailor/theme"
11
+ require_relative "tailor/namespace"
12
+ require_relative "tailor/dsl"
13
+
14
+ module Tailor
15
+ module_function
16
+
17
+ class Error < StandardError; end
18
+ # Your code goes here...
19
+
20
+ def new(...)
21
+ Namespace.new(...)
22
+ end
23
+ end
metadata ADDED
@@ -0,0 +1,104 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: inhouse-tailor
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Nolan J Tait
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2023-11-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: dry-struct
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: dry-types
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.7'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.7'
41
+ - !ruby/object:Gem::Dependency
42
+ name: hashie
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '5'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '5'
55
+ description: Tailor your utility based css styles into your components
56
+ email:
57
+ - nolanjtait@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".rspec"
63
+ - ".rubocop.yml"
64
+ - CHANGELOG.md
65
+ - LICENSE.txt
66
+ - README.md
67
+ - Rakefile
68
+ - inhouse-tailor.gemspec
69
+ - lib/inhouse-tailor.rb
70
+ - lib/tailor.rb
71
+ - lib/tailor/dsl.rb
72
+ - lib/tailor/namespace.rb
73
+ - lib/tailor/style.rb
74
+ - lib/tailor/theme.rb
75
+ - lib/tailor/types.rb
76
+ - lib/tailor/version.rb
77
+ homepage: https://github.com/nolantait/tailor
78
+ licenses:
79
+ - MIT
80
+ metadata:
81
+ homepage_uri: https://github.com/nolantait/tailor
82
+ source_code_uri: https://github.com/nolantait/tailor
83
+ changelog_uri: https://github.com/nolantait/tailor
84
+ rubygems_mfa_required: 'true'
85
+ post_install_message:
86
+ rdoc_options: []
87
+ require_paths:
88
+ - lib
89
+ required_ruby_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: 3.2.0
94
+ required_rubygems_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ requirements: []
100
+ rubygems_version: 3.4.21
101
+ signing_key:
102
+ specification_version: 4
103
+ summary: Tailor your utility based css styles into your components
104
+ test_files: []