joys 0.1.2 → 0.1.4
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/CHANGELOG.md +13 -0
- data/README.md +321 -150
- data/joys-0.1.2.gem +0 -0
- data/joys-0.1.3.gem +0 -0
- data/lib/.DS_Store +0 -0
- data/lib/joys/cli.rb +1554 -0
- data/lib/joys/config.rb +133 -0
- data/lib/joys/core.rb +70 -42
- data/lib/joys/data.rb +477 -0
- data/lib/joys/helpers.rb +36 -9
- data/lib/joys/ssg.rb +597 -0
- data/lib/joys/tags.rb +4 -1
- data/lib/joys/toys.rb +328 -0
- data/lib/joys/version.rb +1 -1
- data/lib/joys.rb +2 -1
- metadata +9 -3
- data/.DS_Store +0 -0
data/lib/joys/config.rb
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Joys
|
3
|
+
def self.html(&block)
|
4
|
+
renderer = Object.new
|
5
|
+
renderer.extend(Render::Helpers)
|
6
|
+
renderer.extend(Tags)
|
7
|
+
renderer.instance_variable_set(:@bf, String.new)
|
8
|
+
renderer.instance_variable_set(:@current_page, "page_standalone")
|
9
|
+
renderer.instance_variable_set(:@used_components, Set.new)
|
10
|
+
renderer.instance_variable_set(:@slots, {})
|
11
|
+
renderer.instance_eval(&block)
|
12
|
+
renderer.instance_variable_get(:@bf)
|
13
|
+
end
|
14
|
+
module Config
|
15
|
+
class << self
|
16
|
+
attr_accessor :env,:pages,:layouts,:components,:css_parts,:helpers,:markup_parser
|
17
|
+
def markup_parser
|
18
|
+
@markup_parser ||= ->(content) { content.to_s }
|
19
|
+
end
|
20
|
+
def env;@env||=ENV['JOYS_ENV']||(defined?(::Rails) ? ::Rails.env.to_s : "development");end
|
21
|
+
def dev?;env!="production";end
|
22
|
+
def pages;@pages||=path("pages");end
|
23
|
+
def layouts;@layouts||=path("layouts");end
|
24
|
+
def components;@components||=path("components");end
|
25
|
+
def css_parts;@css_parts||=path("css");end
|
26
|
+
def helpers;@helpers||=path("helpers");end
|
27
|
+
private
|
28
|
+
def path(t);defined?(::Rails) ? ::Rails.root.join("app/views/joys/#{t}").to_s : "views/joys/#{t}";end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
module Adapters
|
32
|
+
class Base
|
33
|
+
def integrate!;raise NotImplementedError;end
|
34
|
+
def inject_helpers!;raise NotImplementedError;end
|
35
|
+
def controller_context(controller);{};end
|
36
|
+
end
|
37
|
+
class Rails < Base
|
38
|
+
def integrate!
|
39
|
+
return unless defined?(ActionController::Base)
|
40
|
+
ActionController::Base.include(ControllerMethods)
|
41
|
+
inject_helpers!
|
42
|
+
::Rails.application.config.to_prepare do
|
43
|
+
Joys.preload! if ::Rails.env.production?
|
44
|
+
Joys::Render::Helpers.include(::Rails.application.helpers)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
def inject_helpers!
|
48
|
+
Joys::Render::Helpers.include(ActionView::Helpers)
|
49
|
+
Joys::Render::Helpers.module_eval do
|
50
|
+
def request;Thread.current[:joys_request];end
|
51
|
+
def params;Thread.current[:joys_params];end
|
52
|
+
def current_user;Thread.current[:joys_current_user];end
|
53
|
+
def session;Thread.current[:joys_session];end
|
54
|
+
def _(content);raw(content);end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
def controller_context(controller)
|
58
|
+
{
|
59
|
+
joys_request: controller.request,
|
60
|
+
joys_params: controller.params,
|
61
|
+
joys_current_user: (controller.current_user if controller.respond_to?(:current_user)),
|
62
|
+
joys_session: controller.session
|
63
|
+
}
|
64
|
+
end
|
65
|
+
module ControllerMethods
|
66
|
+
def render_joy(path,**locals)
|
67
|
+
context=Joys.adapter.controller_context(self)
|
68
|
+
context.each{|k,v|Thread.current[k]=v}
|
69
|
+
result=Joys.render_joy(path,**locals)
|
70
|
+
render html:result.html_safe,layout:false
|
71
|
+
ensure
|
72
|
+
context&.keys&.each{|k|Thread.current[k]=nil}
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
class Sinatra < Base
|
77
|
+
def integrate!;end
|
78
|
+
def inject_helpers!;end
|
79
|
+
end
|
80
|
+
class Hanami < Base
|
81
|
+
def integrate!;end
|
82
|
+
def inject_helpers!;end
|
83
|
+
end
|
84
|
+
class Roda < Base
|
85
|
+
def integrate!;end
|
86
|
+
def inject_helpers!;end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
class << self
|
90
|
+
attr_accessor :adapter,:css_registry
|
91
|
+
def render_joy(path,**locals)
|
92
|
+
reload! if Config.dev?
|
93
|
+
file=File.join(Config.pages,"#{path}.rb")
|
94
|
+
raise "Template not found: #{file}" unless File.exist?(file)
|
95
|
+
locals.each{|k,v|eval("@#{k}=v",binding)}
|
96
|
+
result=eval(File.read(file),binding,file)
|
97
|
+
result.is_a?(String) ? result.freeze : ""
|
98
|
+
end
|
99
|
+
def preload!;load_helpers;load_dir(Config.layouts);load_dir(Config.components);load_css_parts;end
|
100
|
+
def load_helpers
|
101
|
+
return unless Dir.exist?(Config.helpers)
|
102
|
+
Dir.glob("#{Config.helpers}/**/*.rb").each do |f|
|
103
|
+
helper_module = Module.new
|
104
|
+
helper_module.module_eval(File.read(f), f)
|
105
|
+
Joys::Render::Helpers.include(helper_module)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
def load_css_parts
|
109
|
+
return unless Dir.exist?(Config.css_parts)
|
110
|
+
Dir.glob("#{Config.css_parts}/**/*.css").each do |f|
|
111
|
+
relative_path = f.sub("#{Config.css_parts}/", '').sub('.css', '')
|
112
|
+
@css_registry[relative_path] = File.read(f).gsub(/\r\n?|\n/, '')
|
113
|
+
end
|
114
|
+
end
|
115
|
+
def detect_framework!
|
116
|
+
@css_registry={}
|
117
|
+
@adapter=if defined?(ActionController::Base)&&defined?(::Rails)
|
118
|
+
Adapters::Rails.new
|
119
|
+
elsif defined?(Sinatra::Base)
|
120
|
+
Adapters::Sinatra.new
|
121
|
+
elsif defined?(Hanami::Action)
|
122
|
+
Adapters::Hanami.new
|
123
|
+
elsif defined?(Roda)
|
124
|
+
Adapters::Roda.new
|
125
|
+
end
|
126
|
+
@adapter&.integrate!
|
127
|
+
end
|
128
|
+
private
|
129
|
+
def reload!;clear_cache!;@css_registry={};preload!;end
|
130
|
+
def load_dir(dir);Dir.exist?(dir)&&Dir.glob("#{dir}/**/*.rb").each{|f|load f};end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
Joys.detect_framework!
|
data/lib/joys/core.rb
CHANGED
@@ -4,18 +4,27 @@ module Joys
|
|
4
4
|
@css_path = "public/css";@cache={};@templates={};@compiled_styles={};@consolidated_cache={};@current_component = nil;@layouts={}
|
5
5
|
class << self
|
6
6
|
attr_reader :cache, :templates, :compiled_styles, :consolidated_cache, :layouts
|
7
|
-
attr_accessor :current_component, :current_page, :css_path
|
7
|
+
attr_accessor :current_component, :current_page, :css_path,:adapter,:css_registry
|
8
|
+
# def load_css_parts
|
9
|
+
# return unless Dir.exist?(Config.css_parts)
|
10
|
+
# Dir.glob("#{Config.css_parts}/**/*.css").each do |f|
|
11
|
+
# relative_path = f.sub("#{Config.css_parts}/", '').sub('.css', '')
|
12
|
+
# @css_registry[relative_path] = File.read(f).gsub(/\r?\n/, "")
|
13
|
+
# end
|
14
|
+
# end
|
8
15
|
end
|
16
|
+
def self.make(name, *args, **kwargs, &block)
|
17
|
+
Joys.define :comp, name, *args, **kwargs, &block
|
18
|
+
end
|
9
19
|
def self.reset!
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
end
|
18
|
-
|
20
|
+
@cache.clear
|
21
|
+
@templates.clear
|
22
|
+
@compiled_styles.clear
|
23
|
+
@consolidated_cache.clear
|
24
|
+
@layouts.clear
|
25
|
+
@current_component = nil
|
26
|
+
@current_page = nil
|
27
|
+
end
|
19
28
|
def self.cache(cache_id, *args, &block);cache_key = [cache_id, args.hash];@cache[cache_key] ||= block.call;end
|
20
29
|
def self.define(type, name, &template)
|
21
30
|
full_name = "#{type}_#{name}";@templates[full_name] = template
|
@@ -52,7 +61,8 @@ end
|
|
52
61
|
old_component = @current_component
|
53
62
|
@current_component = full_name if type == :comp
|
54
63
|
result = cache(full_name, *args) do
|
55
|
-
|
64
|
+
# This call now returns a hash, and the hash will be cached.
|
65
|
+
Joys::Render.compile(full_name) { instance_exec(*args, &template) }
|
56
66
|
end
|
57
67
|
@current_component = old_component
|
58
68
|
result
|
@@ -85,47 +95,65 @@ end
|
|
85
95
|
@current_page = old_page
|
86
96
|
renderer.instance_variable_get(:@bf).freeze
|
87
97
|
end
|
88
|
-
def self.comp(name, *args, **locals, &block)
|
98
|
+
def self.comp(name, *args, **locals, &block)
|
99
|
+
renderer = Object.new
|
100
|
+
renderer.extend(Render::Helpers)
|
101
|
+
renderer.extend(Tags)
|
102
|
+
locals.each { |k, v| renderer.instance_variable_set("@#{k}", v) }
|
103
|
+
renderer.instance_eval do
|
104
|
+
@bf = String.new(capacity: 8192)
|
105
|
+
@slots = {}
|
106
|
+
@used_components = Set.new
|
107
|
+
end
|
108
|
+
|
109
|
+
comp_template = @templates["comp_#{name}"]
|
110
|
+
raise "No comp template defined for #{name}" unless comp_template
|
111
|
+
|
112
|
+
old_component = @current_component
|
113
|
+
@current_component = "comp_#{name}"
|
114
|
+
|
115
|
+
# Pass the block as a regular argument to the template
|
116
|
+
renderer.instance_exec(*args, block, &comp_template)
|
117
|
+
|
118
|
+
@current_component = old_component
|
119
|
+
renderer.instance_variable_get(:@bf).freeze
|
120
|
+
end
|
121
|
+
def self.html(&block)
|
122
|
+
# Clear any previous tracking
|
123
|
+
clear_tracked_components
|
124
|
+
|
89
125
|
renderer = Object.new
|
90
126
|
renderer.extend(Render::Helpers)
|
91
127
|
renderer.extend(Tags)
|
92
|
-
|
93
|
-
renderer.
|
94
|
-
|
95
|
-
|
96
|
-
@used_components = Set.new
|
97
|
-
end
|
128
|
+
renderer.instance_variable_set(:@bf, String.new)
|
129
|
+
renderer.instance_variable_set(:@current_page, "page_standalone")
|
130
|
+
renderer.instance_variable_set(:@used_components, Set.new)
|
131
|
+
renderer.instance_variable_set(:@slots, {})
|
98
132
|
|
99
|
-
|
100
|
-
raise "No comp template defined for #{name}" unless comp_template
|
133
|
+
renderer.instance_eval(&block)
|
101
134
|
|
102
|
-
|
103
|
-
|
135
|
+
# Merge globally tracked components
|
136
|
+
tracked = get_tracked_components
|
137
|
+
used = renderer.instance_variable_get(:@used_components)
|
138
|
+
used.merge(tracked) if tracked
|
104
139
|
|
105
|
-
#
|
106
|
-
|
140
|
+
# Clear tracking after use
|
141
|
+
clear_tracked_components
|
107
142
|
|
108
|
-
|
109
|
-
renderer.instance_variable_get(:@bf).freeze
|
143
|
+
renderer.instance_variable_get(:@bf)
|
110
144
|
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
145
|
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)
|
146
|
+
def self.compile(context_name = nil, &block)
|
147
|
+
context = Object.new; context.extend(Helpers); context.extend(Tags)
|
148
|
+
context.instance_eval { @bf = String.new(capacity: 8192); @slots={}; @used_components = Set.new }
|
149
|
+
context.instance_variable_set(:@current_page, context_name) if context_name
|
127
150
|
context.instance_eval(&block)
|
128
|
-
|
151
|
+
|
152
|
+
# CHANGE: Return a hash containing both html and the used components set
|
153
|
+
{
|
154
|
+
html: context.instance_variable_get(:@bf).freeze,
|
155
|
+
components: context.instance_variable_get(:@used_components)
|
156
|
+
}
|
129
157
|
end
|
130
158
|
def self.layout(&layout_block)
|
131
159
|
template = Object.new;template.extend(Helpers);template.extend(Tags)
|