joys 0.1.0 → 0.1.2

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.
data/joys-0.1.0.gem ADDED
Binary file
data/joys-0.1.1.gem ADDED
Binary file
data/lib/joys/core.rb ADDED
@@ -0,0 +1,161 @@
1
+ # frozen_string_literal: true
2
+ # lib/joys/core.rb
3
+ module Joys
4
+ @css_path = "public/css";@cache={};@templates={};@compiled_styles={};@consolidated_cache={};@current_component = nil;@layouts={}
5
+ class << self
6
+ attr_reader :cache, :templates, :compiled_styles, :consolidated_cache, :layouts
7
+ attr_accessor :current_component, :current_page, :css_path
8
+ end
9
+ def self.reset!
10
+ @cache.clear
11
+ @templates.clear
12
+ @compiled_styles.clear
13
+ @consolidated_cache.clear
14
+ @layouts.clear
15
+ @current_component = nil
16
+ @current_page = nil
17
+ end
18
+
19
+ def self.cache(cache_id, *args, &block);cache_key = [cache_id, args.hash];@cache[cache_key] ||= block.call;end
20
+ def self.define(type, name, &template)
21
+ full_name = "#{type}_#{name}";@templates[full_name] = template
22
+ case type
23
+ when :layout
24
+ @layouts[name] = Joys::Render.layout(&template)
25
+ define_singleton_method(full_name) { @layouts[name] }
26
+ when :page
27
+ define_singleton_method(full_name) do |**locals|
28
+ old_component = @current_component
29
+ old_page = @current_page
30
+ @current_page = full_name
31
+ @current_component = nil
32
+ result = cache(full_name, locals.hash) do
33
+ renderer = Object.new
34
+ renderer.extend(Render::Helpers)
35
+ renderer.extend(Tags)
36
+ locals.each { |k, v| renderer.instance_variable_set("@#{k}", v) }
37
+ renderer.instance_eval do
38
+ @bf = String.new(capacity: 8192)
39
+ @slots={}
40
+ @used_components = Set.new
41
+ @current_page = full_name # Pass page context to renderer
42
+ end
43
+ renderer.instance_exec(&template)
44
+ renderer.instance_variable_get(:@bf)
45
+ end
46
+ @current_component = old_component
47
+ @current_page = old_page
48
+ result.freeze
49
+ end
50
+ else
51
+ define_singleton_method(full_name) do |*args|
52
+ old_component = @current_component
53
+ @current_component = full_name if type == :comp
54
+ result = cache(full_name, *args) do
55
+ Joys::Render.compile { instance_exec(*args, &template) }
56
+ end
57
+ @current_component = old_component
58
+ result
59
+ end
60
+ end
61
+ end
62
+ def self.clear_cache!
63
+ @cache.clear
64
+ @compiled_styles.clear
65
+ @consolidated_cache.clear
66
+ end
67
+ def self.page(name, **locals)
68
+ page_name = "page_#{name}"
69
+ renderer = Object.new
70
+ renderer.extend(Render::Helpers)
71
+ renderer.extend(Tags)
72
+ locals.each { |k, v| renderer.instance_variable_set("@#{k}", v) }
73
+ renderer.instance_eval do
74
+ @bf = String.new(capacity: 8192)
75
+ @slots={}
76
+ @used_components = Set.new
77
+ @current_page = page_name
78
+ @used_components.add(page_name) if Joys.compiled_styles[page_name]
79
+ end
80
+ page_template = @templates[page_name]
81
+ raise "No page template defined for #{name}" unless page_template
82
+ old_page = @current_page
83
+ @current_page = page_name
84
+ renderer.instance_exec(&page_template)
85
+ @current_page = old_page
86
+ renderer.instance_variable_get(:@bf).freeze
87
+ end
88
+ def self.comp(name, *args, **locals, &block)
89
+ renderer = Object.new
90
+ renderer.extend(Render::Helpers)
91
+ renderer.extend(Tags)
92
+ locals.each { |k, v| renderer.instance_variable_set("@#{k}", v) }
93
+ renderer.instance_eval do
94
+ @bf = String.new(capacity: 8192)
95
+ @slots = {}
96
+ @used_components = Set.new
97
+ end
98
+
99
+ comp_template = @templates["comp_#{name}"]
100
+ raise "No comp template defined for #{name}" unless comp_template
101
+
102
+ old_component = @current_component
103
+ @current_component = "comp_#{name}"
104
+
105
+ # Pass the block as a regular argument to the template
106
+ renderer.instance_exec(*args, block, &comp_template)
107
+
108
+ @current_component = old_component
109
+ renderer.instance_variable_get(:@bf).freeze
110
+ end
111
+ def self.html(&block)
112
+ renderer = Object.new
113
+ renderer.extend(Render::Helpers)
114
+ renderer.extend(Tags)
115
+ renderer.instance_variable_set(:@bf, String.new)
116
+
117
+ # Only inherit page context for style compilation
118
+ renderer.instance_variable_set(:@current_page, current_page) if current_page
119
+
120
+ renderer.instance_eval(&block)
121
+ renderer.instance_variable_get(:@bf)
122
+ end
123
+ module Render
124
+ def self.compile(&block)
125
+ context = Object.new;context.extend(Helpers);context.extend(Tags)
126
+ context.instance_eval { @bf = String.new(capacity: 8192);@slots={};@used_components = Set.new}
127
+ context.instance_eval(&block)
128
+ context.instance_variable_get(:@bf).freeze
129
+ end
130
+ def self.layout(&layout_block)
131
+ template = Object.new;template.extend(Helpers);template.extend(Tags)
132
+ template.instance_eval { @bf = String.new;@slots={};@used_components = Set.new }
133
+ template.define_singleton_method(:pull) { |name = :main| @bf << "<!--SLOT:#{name}-->"; nil }
134
+ template.instance_eval(&layout_block)
135
+ precompiled = template.instance_variable_get(:@bf).freeze
136
+ ->(context, &content_block) {
137
+ context.instance_eval(&content_block) if content_block
138
+ slots = context.instance_variable_get(:@slots) || {}
139
+ used_components = context.instance_variable_get(:@used_components)
140
+ if used_components && !used_components.empty?
141
+ auto_styles = Joys::Styles.render_consolidated_styles(used_components)
142
+ else
143
+ auto_styles = ""
144
+ end
145
+ slot_regex = /<!--SLOT:(.*?)-->/.freeze
146
+ result = precompiled.gsub(slot_regex) do |match|
147
+ slot_name = $1.to_sym
148
+ slots[slot_name] || ""
149
+ end
150
+ if result.include?('<!--STYLES-->')
151
+ result = result.gsub(/<!--STYLES-->/, auto_styles)
152
+ end
153
+ if result.include?('<!--EXTERNAL_STYLES-->')
154
+ external_styles = Joys::Styles.render_external_styles(used_components)
155
+ result = result.gsub(/<!--EXTERNAL_STYLES-->/, external_styles)
156
+ end
157
+ result
158
+ }
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
2
+ # lib/joys/helpers.rb
3
+ module Joys
4
+ module Render
5
+ module Helpers
6
+ def txt(content); @bf << CGI.escapeHTML(content.to_s); nil; end
7
+ def raw(content); @bf << content.to_s; nil; end
8
+ def push(name, &block)
9
+ old_buffer = @bf;@slots ||= {}
10
+ @bf = String.new;instance_eval(&block)
11
+ content = @bf;@slots[name] = content
12
+ @bf = old_buffer;nil
13
+ end
14
+ def pull(name = :main)
15
+ @slots ||= {};@bf << @slots[name].to_s if @slots[name];nil
16
+ end
17
+ def pull_styles;@bf << "<!--STYLES-->";nil;end
18
+ def pull_external_styles;@bf << "<!--EXTERNAL_STYLES-->";nil;end
19
+
20
+ def comp(name, *args, **kwargs, &block)
21
+ comp_name = "comp_#{name}"
22
+ @used_components ||= Set.new
23
+ @used_components.add(comp_name)
24
+ raw Joys.send(comp_name, *args, **kwargs, &block)
25
+ end
26
+ def layout(name, &block)
27
+ layout_lambda = Joys.layouts[name]
28
+ raise ArgumentError, "Layout `#{name}` not registered" unless layout_lambda
29
+ raw layout_lambda.call(self, &block)
30
+ end
31
+ def styles(scoped: false, &block)
32
+ context_name = Joys.current_component
33
+ context_name ||= Joys.current_page
34
+ context_name ||= @current_page
35
+ return nil unless context_name
36
+ return nil if Joys.compiled_styles[context_name]
37
+ @style_base_css = []
38
+ @style_media_queries = {}
39
+ @style_scoped = scoped
40
+ instance_eval(&block)
41
+ Joys::Styles.compile_component_styles(
42
+ context_name,
43
+ @style_base_css,
44
+ @style_media_queries,
45
+ @style_scoped
46
+ )
47
+ if context_name&.start_with?('page_')
48
+ @used_components ||= Set.new
49
+ @used_components.add(context_name)
50
+ end
51
+ @style_base_css = @style_media_queries = @style_scoped = nil;nil
52
+ end
53
+ def doctype;raw "<!doctype html>";end
54
+ def css(content);@style_base_css&.push(content);nil;end
55
+ def media_max(breakpoint, content)
56
+ return nil unless @style_media_queries
57
+ key = "m-max-#{breakpoint}"
58
+ @style_media_queries[key] ||= []
59
+ @style_media_queries[key] << content;nil
60
+ end
61
+ def media_min(breakpoint, content)
62
+ return nil unless @style_media_queries
63
+ key = "m-min-#{breakpoint}"
64
+ @style_media_queries[key] ||= []
65
+ @style_media_queries[key] << content;nil
66
+ end
67
+ def media_minmax(min_bp, max_bp, content)
68
+ return nil unless @style_media_queries
69
+ key = "m-minmax-#{min_bp}-#{max_bp}"
70
+ @style_media_queries[key] ||= []
71
+ @style_media_queries[key] << content;nil
72
+ end
73
+ def container_min(size, content)
74
+ return nil unless @style_media_queries
75
+ key = "c-min-#{size}"
76
+ @style_media_queries[key] ||= []
77
+ @style_media_queries[key] << content;nil
78
+ end
79
+ def container_max(size, content)
80
+ return nil unless @style_media_queries
81
+ key = "c-max-#{size}"
82
+ @style_media_queries[key] ||= []
83
+ @style_media_queries[key] << content;nil
84
+ end
85
+ def container_minmax(min_size, max_size, content)
86
+ return nil unless @style_media_queries
87
+ key = "c-minmax-#{min_size}-#{max_size}"
88
+ @style_media_queries[key] ||= []
89
+ @style_media_queries[key] << content;nil
90
+ end
91
+ def named_container_min(name, size, content)
92
+ return nil unless @style_media_queries
93
+ key = "c-#{name}-min-#{size}"
94
+ @style_media_queries[key] ||= []
95
+ @style_media_queries[key] << content;nil
96
+ end
97
+ def named_container_max(name, size, content)
98
+ return nil unless @style_media_queries
99
+ key = "c-#{name}-max-#{size}"
100
+ @style_media_queries[key] ||= []
101
+ @style_media_queries[key] << content;nil
102
+ end
103
+ def named_container_minmax(name, min_size, max_size, content)
104
+ return nil unless @style_media_queries
105
+ key = "c-#{name}-minmax-#{min_size}-#{max_size}"
106
+ @style_media_queries[key] ||= []
107
+ @style_media_queries[key] << content;nil
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,156 @@
1
+ # frozen_string_literal: true
2
+ # lib/joys/styles.rb - Simplified Component Styling
3
+ require 'fileutils'
4
+ require 'set'
5
+ module Joys
6
+ module Styles
7
+ def self.compile_component_styles(comp_name, base_css, media_queries, scoped)
8
+ scope_prefix = scoped ? ".#{comp_name.tr('_', '-')} " : ""
9
+ processed_base_css = base_css.map { |css| scope_css(css, scope_prefix) }
10
+ processed_media_queries = {}
11
+
12
+ # FIX: Actually iterate over the media_queries parameter
13
+ media_queries.each do |key, css_rules|
14
+ scoped_rules = css_rules.map { |css| scope_css(css, scope_prefix) }
15
+ processed_media_queries[key] = scoped_rules
16
+ end
17
+
18
+ Joys.compiled_styles[comp_name] = {
19
+ base_css: processed_base_css,
20
+ media_queries: processed_media_queries,
21
+ container_queries: {} # Keep this for compatibility, but media_queries contains all now
22
+ }.freeze
23
+ end
24
+
25
+ private
26
+
27
+ def self.render_consolidated_styles(used_components)
28
+ return "" if used_components.empty?
29
+ cache_key = used_components.to_a.sort.join(',')
30
+ return Joys.consolidated_cache[cache_key] if Joys.consolidated_cache.key?(cache_key)
31
+ buffer = String.new(capacity: 4096)
32
+ min_queries = Hash.new { |h,k| h[k] = [] }
33
+ max_queries = Hash.new { |h,k| h[k] = [] }
34
+ minmax_queries = []
35
+ container_min_queries = Hash.new { |h,k| h[k] = [] }
36
+ container_max_queries = Hash.new { |h,k| h[k] = [] }
37
+ container_minmax_queries = []
38
+ container_named_queries = Hash.new { |h,k| h[k] = {min: Hash.new { |h,k| h[k] = [] }, max: Hash.new { |h,k| h[k] = [] }, minmax: []} }
39
+ seen_base = Set.new
40
+
41
+ used_components.each do |comp|
42
+ styles = Joys.compiled_styles[comp] || next
43
+ styles[:base_css].each do |rule|
44
+ next if seen_base.include?(rule)
45
+ buffer << rule
46
+ seen_base << rule
47
+ end
48
+ styles[:media_queries].each do |key, rules|
49
+ case key
50
+ # FIX: Updated regex patterns to match the actual key formats
51
+ when /^m-min-(\d+)$/
52
+ min_queries[$1.to_i].concat(rules)
53
+ when /^m-max-(\d+)$/
54
+ max_queries[$1.to_i].concat(rules)
55
+ when /^m-minmax-(\d+)-(\d+)$/
56
+ minmax_queries << { min: $1.to_i, max: $2.to_i, css: rules }
57
+ when /^c-min-(\d+)$/
58
+ container_min_queries[$1.to_i].concat(rules)
59
+ when /^c-max-(\d+)$/
60
+ container_max_queries[$1.to_i].concat(rules)
61
+ when /^c-minmax-(\d+)-(\d+)$/
62
+ container_minmax_queries << { min: $1.to_i, max: $2.to_i, css: rules }
63
+ when /^c-([^-]+)-min-(\d+)$/
64
+ name, size = $1, $2.to_i
65
+ container_named_queries[name][:min][size].concat(rules)
66
+ when /^c-([^-]+)-max-(\d+)$/
67
+ name, size = $1, $2.to_i
68
+ container_named_queries[name][:max][size].concat(rules)
69
+ when /^c-([^-]+)-minmax-(\d+)-(\d+)$/
70
+ name, min_size, max_size = $1, $2.to_i, $3.to_i
71
+ container_named_queries[name][:minmax] << { min: min_size, max: max_size, css: rules }
72
+ end
73
+ end
74
+ end
75
+
76
+ max_queries.sort.reverse.each do |bp, rules|
77
+ buffer << "@media (max-width: #{bp}px){"
78
+ rules.uniq.each { |r| buffer << r }
79
+ buffer << "}"
80
+ end
81
+ min_queries.sort.each do |bp, rules|
82
+ buffer << "@media (min-width: #{bp}px){"
83
+ rules.uniq.each { |r| buffer << r }
84
+ buffer << "}"
85
+ end
86
+ minmax_queries.sort_by { |q| [q[:min], q[:max]] }.each do |q|
87
+ buffer << "@media (min-width: #{q[:min]}px) and (max-width: #{q[:max]}px){"
88
+ q[:css].uniq.each { |r| buffer << r }
89
+ buffer << "}"
90
+ end
91
+ container_max_queries.sort.reverse.each do |size, rules|
92
+ buffer << "@container (max-width: #{size}px){"
93
+ rules.uniq.each { |r| buffer << r }
94
+ buffer << "}"
95
+ end
96
+ container_min_queries.sort.each do |size, rules|
97
+ buffer << "@container (min-width: #{size}px){"
98
+ rules.uniq.each { |r| buffer << r }
99
+ buffer << "}"
100
+ end
101
+ container_minmax_queries.sort_by { |q| [q[:min], q[:max]] }.each do |q|
102
+ buffer << "@container (min-width: #{q[:min]}px) and (max-width: #{q[:max]}px){"
103
+ q[:css].uniq.each { |r| buffer << r }
104
+ buffer << "}"
105
+ end
106
+ container_named_queries.each do |name, queries|
107
+ queries[:max].sort.reverse.each do |size, rules|
108
+ buffer << "@container #{name} (max-width: #{size}px){"
109
+ rules.uniq.each { |r| buffer << r }
110
+ buffer << "}"
111
+ end
112
+ queries[:min].sort.each do |size, rules|
113
+ buffer << "@container #{name} (min-width: #{size}px){"
114
+ rules.uniq.each { |r| buffer << r }
115
+ buffer << "}"
116
+ end
117
+ queries[:minmax].sort_by { |q| [q[:min], q[:max]] }.each do |q|
118
+ buffer << "@container #{name} (min-width: #{q[:min]}px) and (max-width: #{q[:max]}px){"
119
+ q[:css].uniq.each { |r| buffer << r }
120
+ buffer << "}"
121
+ end
122
+ end
123
+ buffer.freeze.tap { |css| Joys.consolidated_cache[cache_key] = css }
124
+ end
125
+
126
+ def self.render_external_styles(used_components)
127
+ return "" if used_components.empty?
128
+ cache_key = used_components.to_a.sort.join(',')
129
+ css_filename = "#{cache_key}.css"
130
+ #css_filename = "#{Digest::SHA256.hexdigest(cache_key)[0..12]}.css"
131
+ css_path = Joys.css_path || "public/css"
132
+ full_path = File.join(css_path, css_filename)
133
+ FileUtils.mkdir_p(css_path)
134
+ unless File.exist?(full_path)
135
+ css_content = render_consolidated_styles(used_components)
136
+ File.write(full_path, css_content)
137
+ end
138
+ "<link rel=\"stylesheet\" href=\"/css/#{css_filename}\">"
139
+ end
140
+
141
+ def self.scope_css(css, scope_prefix)
142
+ return css if scope_prefix.empty?
143
+ selectors = css.split(',')
144
+ scoped_selectors = selectors.map do |selector|
145
+ selector.strip!
146
+ if match = selector.match(/^\s*\.([a-zA-Z][\w-]*)/)
147
+ #if selector.match(/^\s*\.([a-zA-Z][\w-]*)/)
148
+ "#{scope_prefix}#{selector}"
149
+ else
150
+ selector
151
+ end
152
+ end
153
+ scoped_selectors.join(', ')
154
+ end
155
+ end
156
+ end
data/lib/joys/tags.rb ADDED
@@ -0,0 +1,120 @@
1
+ # lib/joys/tags.rb
2
+ module Joys
3
+ module Tags
4
+ VOID_TAGS = %w[area base br col embed hr img input link meta param source track wbr].freeze
5
+ TAGS = %w[
6
+ a abbr address article aside audio b bdi bdo blockquote body button canvas
7
+ caption cite code colgroup data datalist dd del details dfn dialog div dl dt
8
+ em fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6 head header hgroup
9
+ html i iframe ins kbd label legend li main map mark menu meter nav noscript
10
+ object ol optgroup option output p picture pre progress q rp rt ruby s samp
11
+ script section select small span strong style sub summary sup table tbody td
12
+ template textarea tfoot th thead time title tr u ul var video
13
+ ].freeze
14
+ BOOLEAN_ATTRS = %w[
15
+ disabled readonly read_only multiple checked selected
16
+ auto_focus autofocus no_validate novalidate form_novalidate formnovalidate
17
+ hidden required open reversed scoped seamless muted auto_play autoplay
18
+ controls loop default inert item_scope itemscope
19
+ ].to_set.freeze
20
+
21
+ CLS = ' class="'.freeze
22
+ QUO = '"'.freeze
23
+ BC = '>'.freeze
24
+ BO = '<'.freeze
25
+ GTS = '</'.freeze
26
+ EQ = '="'.freeze
27
+
28
+ VOID_TAGS.each do |tag|
29
+ define_method(tag) do |cs: nil, **attrs|
30
+ class_string = case cs
31
+ when String, Symbol then cs.to_s
32
+ when Array then cs.compact.reject { |c| c == false }.map(&:to_s).join(" ")
33
+ else ""
34
+ end
35
+
36
+ @bf << BO << tag
37
+ @bf << CLS << class_string << QUO unless class_string.empty?
38
+
39
+ attrs.each do |k, v|
40
+ key = k.to_s
41
+
42
+ if v.is_a?(Hash) && (key == "data" || key.start_with?("aria"))
43
+ prefix = key.tr('_', '-')
44
+ v.each do |sk, sv|
45
+ next if sv.nil? || sv == false # Skip nil and boolean false
46
+ attr_name = "#{prefix}-#{sk.to_s.tr('_', '-')}"
47
+ @bf << " #{attr_name}#{EQ}#{CGI.escapeHTML(sv.to_s)}#{QUO}"
48
+ end
49
+ else
50
+ next if v.nil?
51
+
52
+ if BOOLEAN_ATTRS.include?(key)
53
+ @bf << " #{key.tr('_', '')}" if v
54
+ elsif v == false
55
+ next
56
+ else
57
+ attr_name = key.tr('_', '-')
58
+ @bf << " #{attr_name}#{EQ}#{CGI.escapeHTML(v.to_s)}#{QUO}"
59
+ end
60
+ end
61
+ end
62
+
63
+ @bf << BC
64
+ nil
65
+ end
66
+ end
67
+
68
+ TAGS.each do |tag|
69
+ define_method(tag) do |content = nil, cs: nil, raw: false, **attrs, &block|
70
+ class_string = case cs
71
+ when String, Symbol then cs.to_s
72
+ when Array then cs.compact.reject { |c| c == false }.map(&:to_s).join(" ")
73
+ else ""
74
+ end
75
+
76
+ @bf << BO << tag
77
+ @bf << CLS << class_string << QUO unless class_string.empty?
78
+
79
+ attrs.each do |k, v|
80
+ key = k.to_s
81
+
82
+ if v.is_a?(Hash) && (key == "data" || key.start_with?("aria"))
83
+ prefix = key.tr('_', '-')
84
+ v.each do |sk, sv|
85
+ next if sv.nil? || sv == false # Skip nil and boolean false
86
+ attr_name = "#{prefix}-#{sk.to_s.tr('_', '-')}"
87
+ @bf << " #{attr_name}#{EQ}#{CGI.escapeHTML(sv.to_s)}#{QUO}"
88
+ end
89
+ else
90
+ next if v.nil?
91
+
92
+ if BOOLEAN_ATTRS.include?(key)
93
+ @bf << " #{key.tr('_', '')}" if v
94
+ elsif v == false
95
+ next
96
+ else
97
+ attr_name = key.tr('_', '-')
98
+ @bf << " #{attr_name}#{EQ}#{CGI.escapeHTML(v.to_s)}#{QUO}"
99
+ end
100
+ end
101
+ end
102
+
103
+ @bf << BC
104
+
105
+ if block
106
+ instance_eval(&block)
107
+ elsif content
108
+ @bf << (raw ? content.to_s : CGI.escapeHTML(content.to_s))
109
+ end
110
+
111
+ @bf << GTS << tag << BC
112
+ nil
113
+ end
114
+
115
+ define_method("#{tag}!") do |content = nil, cs: nil, **attrs, &block|
116
+ send(tag, content, cs: cs, raw: true, **attrs, &block)
117
+ end
118
+ end
119
+ end
120
+ end
data/lib/joys/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Joys
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.2"
5
5
  end
data/lib/joys.rb CHANGED
@@ -1,8 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "joys/version"
4
-
5
- module Joys
6
- class Error < StandardError; end
7
- # Your code goes here...
8
- end
4
+ require_relative "joys/core"
5
+ require_relative "joys/helpers"
6
+ require_relative "joys/styles"
7
+ require_relative "joys/tags"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: joys
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steven Garcia
@@ -25,8 +25,14 @@ files:
25
25
  - LICENSE.txt
26
26
  - README.md
27
27
  - Rakefile
28
+ - joys-0.1.0.gem
29
+ - joys-0.1.1.gem
28
30
  - lib/.DS_Store
29
31
  - lib/joys.rb
32
+ - lib/joys/core.rb
33
+ - lib/joys/helpers.rb
34
+ - lib/joys/styles.rb
35
+ - lib/joys/tags.rb
30
36
  - lib/joys/version.rb
31
37
  - sig/joys.rbs
32
38
  homepage: https://github.com/activestylus/joys.git