joys 0.1.1 → 0.1.3
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 +335 -160
- data/joys-0.1.0.gem +0 -0
- data/joys-0.1.1.gem +0 -0
- data/joys-0.1.2.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 +189 -0
- data/lib/joys/data.rb +477 -0
- data/lib/joys/helpers.rb +138 -0
- data/lib/joys/ssg.rb +597 -0
- data/lib/joys/styles.rb +156 -0
- data/lib/joys/tags.rb +124 -0
- data/lib/joys/toys.rb +328 -0
- data/lib/joys/version.rb +1 -1
- data/lib/joys.rb +5 -5
- metadata +13 -2
- data/.DS_Store +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e61c772b1a54599aa640ae7185d7c555584569b42a828a622585fe1926c5c875
|
4
|
+
data.tar.gz: 3386e6f05c3bf96bda1b3c89ee060896a4bf6d652a81044729929cb32ef21fdd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6b64267c0567828a6ef1ddf5682336f03e33e06a7e2b4ed1ef4fabf0712a835be9ab1f69c449dc6c8bfb172b1bcfb876f00bb9a3f424bf0a6d6537d67fe39e26
|
7
|
+
data.tar.gz: 307da8295d8df3b53cac60d55c3550c42e2b3926e9b5de5629011f814acc6bda73fd97f541fc95afe4f0b76ff16441e92e06f27f133533b102cce1d87b13f69c
|
data/CHANGELOG.md
CHANGED
@@ -7,3 +7,16 @@
|
|
7
7
|
## [0.1.1] - 2025-09-16
|
8
8
|
|
9
9
|
- Actual templating and CSS functionality added
|
10
|
+
|
11
|
+
## [0.1.2] - 2025-09-16
|
12
|
+
|
13
|
+
- Updated README
|
14
|
+
- Added main joys.rb
|
15
|
+
|
16
|
+
|
17
|
+
## [0.1.3] - 2025-09-29
|
18
|
+
|
19
|
+
- Added configurable markup parser
|
20
|
+
- Added Static Site Generator
|
21
|
+
- Added Static Data Layer
|
22
|
+
- Added CLI Utility
|
data/README.md
CHANGED
@@ -49,6 +49,9 @@ p { txt user_input } # "<script>alert('xss')</script>" becomes safe text
|
|
49
49
|
# raw outputs HTML (use with caution)
|
50
50
|
div { raw markdown_to_html(content) }
|
51
51
|
|
52
|
+
# raw shortcut is available for those who find it tedious
|
53
|
+
div { _ markdown_to_html(content) }
|
54
|
+
|
52
55
|
# Pass raw: true to any tag
|
53
56
|
div(content, raw: true) # content renders as HTML
|
54
57
|
```
|
@@ -243,66 +246,6 @@ Joys.define(:layout, :main) do
|
|
243
246
|
}
|
244
247
|
end
|
245
248
|
```
|
246
|
-
|
247
|
-
---
|
248
|
-
|
249
|
-
## Rails Integration
|
250
|
-
|
251
|
-
### Setup
|
252
|
-
|
253
|
-
```ruby
|
254
|
-
# config/initializers/joys.rb
|
255
|
-
require 'joys/rails'
|
256
|
-
```
|
257
|
-
|
258
|
-
### File Structure
|
259
|
-
|
260
|
-
```
|
261
|
-
app/views/joys/
|
262
|
-
├── layouts/
|
263
|
-
│ └── application.rb
|
264
|
-
├── comps/
|
265
|
-
│ ├── navbar.rb
|
266
|
-
│ └── user_card.rb
|
267
|
-
└── pages/
|
268
|
-
├── dashboard.rb
|
269
|
-
└── users_show.rb
|
270
|
-
```
|
271
|
-
|
272
|
-
### Rails Helpers Work Seamlessly
|
273
|
-
|
274
|
-
Joys is fully compatible with Rails `ActiveSupport::SafeBuffer`, so you can use all Rails helpers seamlessly.
|
275
|
-
|
276
|
-
```ruby
|
277
|
-
Joys.define(:page, :users_edit) do
|
278
|
-
layout(:main) {
|
279
|
-
push(:main) {
|
280
|
-
# Rails form helpers just work
|
281
|
-
form_with(model: @user) do |f|
|
282
|
-
div(cs: "field") {
|
283
|
-
f.label(:name)
|
284
|
-
f.text_field(:name, class: "input")
|
285
|
-
}
|
286
|
-
f.submit("Save", class: "btn btn-primary")
|
287
|
-
end
|
288
|
-
# As do route helpers
|
289
|
-
a("Back", href: users_path, cs: "link")
|
290
|
-
}
|
291
|
-
}
|
292
|
-
end
|
293
|
-
```
|
294
|
-
|
295
|
-
Rendering from controllers could not be more simple!
|
296
|
-
|
297
|
-
```
|
298
|
-
class UsersController < ApplicationController
|
299
|
-
def show
|
300
|
-
@user = User.find(params[:id])
|
301
|
-
render_joys :users_show # renders from #{Rails.root}/app/views/joys/users_show.rb
|
302
|
-
end
|
303
|
-
end
|
304
|
-
```
|
305
|
-
|
306
249
|
---
|
307
250
|
|
308
251
|
## Real-World Example
|
@@ -352,17 +295,19 @@ Using simple components and views (only 3 layers of nesting) we can see how Joy
|
|
352
295
|
|
353
296
|
#### ❄️ COLD RENDER (new object per call)
|
354
297
|
| | user | system | total | real. |
|
298
|
+
|------|--------|--------|--------|--------|
|
355
299
|
|Joys: |0.060535|0.000200|0.060735|0.060736|
|
356
300
|
|Slim: |0.048344|0.000183|0.048527|0.048530|
|
357
301
|
|ERB: |0.301811|0.000808|0.302619|0.302625|
|
358
302
|
|Phlex:|0.069636|0.000470|0.070106|0.071157|
|
359
303
|
|
360
304
|
#### 🔥 HOT RENDER (cached objects)
|
361
|
-
|
|
362
|
-
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
305
|
+
| | user | system | total | real |
|
306
|
+
|------|--------|---------|--------|--------|
|
307
|
+
|Joys: |0.065255| 0.000257|0.065512|0.065512|
|
308
|
+
|Slim: |0.049323| 0.000295|0.049618|0.049695|
|
309
|
+
|ERB: |0.309757| 0.001167|0.310924|0.310929|
|
310
|
+
|Phlex:|0.069663| 0.000141|0.069804|0.069805|
|
366
311
|
|
367
312
|
#### 💾 MEMORY USAGE
|
368
313
|
Joys memory: 532356 bytes
|
@@ -387,17 +332,19 @@ As template complexity grows, Joys starts to really show off its optimizations.
|
|
387
332
|
|
388
333
|
This is the bare bones benchmark, no "cheating" allowed.
|
389
334
|
|
390
|
-
|
|
391
|
-
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
335
|
+
| | user | system | total | real |
|
336
|
+
|------|--------|--------|--------|--------|
|
337
|
+
| Joys |0.051715|0.000364|0.052079|0.052080|
|
338
|
+
| ERB |0.520495|0.003696|0.524191|0.524187|
|
339
|
+
| Slim |6.001650|0.019418|6.021068|6.021013|
|
340
|
+
| Phlex|0.169567|0.000373|0.169940|0.169938|
|
395
341
|
|
396
342
|
Note: Joys achieves its 'cold render' speed by eliminating object overhead and using simple string operations with smart memory management.
|
397
343
|
|
398
344
|
### 🔥 HOT RENDER (cached objects)
|
399
345
|
|
400
346
|
| | user | system | total | real |
|
347
|
+
|------|---------|--------|---------|--------|
|
401
348
|
|JOYS: | 0.000463|0.000010| 0.000473|0.000473|
|
402
349
|
|SLIM: | 0.045881|0.000358| 0.046239|0.046243|
|
403
350
|
|PHLEX:| 0.167631|0.000760| 0.168391|0.168661|
|
@@ -815,130 +762,358 @@ Joys is designed to stay out of your way. At its core, it leans functional — y
|
|
815
762
|
The DSL is the same either way — Joys just adapts.
|
816
763
|
|
817
764
|
|
765
|
+
---
|
766
|
+
|
767
|
+
# Joys Rails Integration
|
768
|
+
|
769
|
+
## Installation
|
770
|
+
|
771
|
+
Add to your Rails app's initializer:
|
772
|
+
|
818
773
|
```ruby
|
819
|
-
|
820
|
-
|
774
|
+
require 'joys'
|
775
|
+
```
|
821
776
|
|
822
|
-
|
823
|
-
|
824
|
-
|
825
|
-
|
826
|
-
|
777
|
+
Auto-detects Rails and configures integration automatically.
|
778
|
+
|
779
|
+
## How It Works
|
780
|
+
|
781
|
+
- **Framework Detection**: Checks for `ActionController::Base` and `Rails`
|
782
|
+
- **Helper Injection**: Adds all `ActionView::Helpers` to `Joys::Render::Helpers`
|
783
|
+
- **Context Injection**: Provides `request`, `params`, `current_user`, `session` in templates
|
784
|
+
- **Controller Integration**: Adds `render_joy` method to all controllers
|
785
|
+
|
786
|
+
## Directory Structure
|
787
|
+
|
788
|
+
```
|
789
|
+
app/views/joys/
|
790
|
+
├── layouts/ # Auto-loaded at boot (production)
|
791
|
+
├── components/ # Auto-loaded at boot (production)
|
792
|
+
└── pages/ # Loaded on-demand
|
793
|
+
```
|
794
|
+
|
795
|
+
## Configuration
|
796
|
+
|
797
|
+
```ruby
|
798
|
+
# Optional - defaults shown
|
799
|
+
Joys::Config.env = "development" # or Rails.env
|
800
|
+
Joys::Config.pages = "app/views/joys/pages"
|
801
|
+
Joys::Config.layouts = "app/views/joys/layouts"
|
802
|
+
Joys::Config.components = "app/views/joys/components"
|
803
|
+
```
|
804
|
+
|
805
|
+
## Controller Usage
|
806
|
+
|
807
|
+
```ruby
|
808
|
+
class HomeController < ApplicationController
|
809
|
+
def index
|
810
|
+
render_joy :index # loads app/views/joys/pages/index.rb
|
811
|
+
end
|
812
|
+
|
813
|
+
def show
|
814
|
+
render_joy "users/show", user: User.find(params[:id])
|
827
815
|
end
|
828
816
|
end
|
817
|
+
```
|
829
818
|
|
830
|
-
|
819
|
+
## Page Templates
|
820
|
+
|
821
|
+
### Functional Pattern
|
822
|
+
|
823
|
+
```ruby
|
824
|
+
# app/views/joys/pages/index.rb
|
825
|
+
data = {title: "Home", nav: link_to("About", "/about")}.freeze
|
826
|
+
|
827
|
+
Joys.html {
|
828
|
+
layout(:main) {
|
829
|
+
push(:title) { txt data[:title] }
|
830
|
+
push(:body) { _ data[:nav] }
|
831
|
+
}
|
832
|
+
}
|
833
|
+
```
|
834
|
+
|
835
|
+
### Class Pattern
|
836
|
+
|
837
|
+
```ruby
|
838
|
+
# app/views/joys/pages/index.rb
|
839
|
+
class IndexPage
|
840
|
+
def initialize
|
841
|
+
@data = {title: "Home"}.freeze
|
842
|
+
end
|
843
|
+
|
831
844
|
def render
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
|
845
|
+
data = @data
|
846
|
+
Joys.html {
|
847
|
+
layout(:main) {
|
848
|
+
push(:title) { txt data[:title] }
|
849
|
+
push(:body) { _ link_to("About", "/about") }
|
837
850
|
}
|
838
851
|
}
|
839
852
|
end
|
840
853
|
end
|
841
854
|
|
842
|
-
|
843
|
-
# => <html><head><title>My App</title></head><body><div class="dashboard"><h1>Dashboard</h1><p>Rendered through OOP inheritance.</p><a class="btn" href="/logout">Logout</a></div></body></html>
|
855
|
+
IndexPage.new.render
|
844
856
|
```
|
845
857
|
|
846
|
-
|
858
|
+
## Rails Helpers
|
847
859
|
|
848
|
-
|
849
|
-
## 🧩 Bespoke Page Architecture: Content-Driven Flexibility
|
860
|
+
All Rails helpers available directly:
|
850
861
|
|
851
|
-
|
862
|
+
```ruby
|
863
|
+
Joys.html {
|
864
|
+
layout(:main) {
|
865
|
+
push(:body) {
|
866
|
+
_ link_to("Home", root_path)
|
867
|
+
_ image_tag("logo.png", class: "w-8")
|
868
|
+
_ form_with model: Post.new do |f|
|
869
|
+
f.text_field :title
|
870
|
+
end
|
871
|
+
}
|
872
|
+
}
|
873
|
+
}
|
874
|
+
```
|
852
875
|
|
853
|
-
|
876
|
+
## Context Access
|
854
877
|
|
855
|
-
|
878
|
+
```ruby
|
879
|
+
# Available in all templates
|
880
|
+
request.referer
|
881
|
+
params[:id]
|
882
|
+
current_user.name
|
883
|
+
session[:user_id]
|
884
|
+
```
|
885
|
+
|
886
|
+
## Components
|
856
887
|
|
857
888
|
```ruby
|
858
|
-
#
|
859
|
-
|
860
|
-
|
861
|
-
|
862
|
-
|
863
|
-
cta: "Start Free Trial"
|
864
|
-
},
|
865
|
-
features: {
|
866
|
-
items: [
|
867
|
-
{ title: "Lightning Fast", desc: "10x faster" },
|
868
|
-
{ title: "Secure", desc: "Bank-level security" }
|
869
|
-
]
|
870
|
-
}
|
871
|
-
}.freeze
|
889
|
+
# app/views/joys/components/card.rb
|
890
|
+
Joys.define :comp, :card do |title|
|
891
|
+
styles { css ".card {padding:1rem;border:1px solid #ddd}" }
|
892
|
+
div(cs: "card") { h3 title }
|
893
|
+
end
|
872
894
|
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
push(:main) {
|
877
|
-
raw hero(DATA[:hero])
|
878
|
-
raw features(DATA[:features])
|
879
|
-
|
880
|
-
# Custom sections between data-driven ones
|
881
|
-
div(cs: "demo") {
|
882
|
-
h2("See It In Action")
|
883
|
-
comp(:demo_video)
|
884
|
-
}
|
885
|
-
|
886
|
-
comp(:testimonials) # Reusable global component
|
887
|
-
}
|
888
|
-
}
|
889
|
-
end
|
890
|
-
end
|
895
|
+
# Usage in templates
|
896
|
+
comp :card, "Hello World"
|
897
|
+
```
|
891
898
|
|
892
|
-
|
899
|
+
## Page Components
|
893
900
|
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
901
|
+
For page-specific components:
|
902
|
+
|
903
|
+
```ruby
|
904
|
+
page_comp(:hero) {
|
905
|
+
styles { css ".hero {text-align:center}" }
|
906
|
+
section(cs: "hero") { h1 "Welcome" }
|
907
|
+
}
|
908
|
+
```
|
909
|
+
|
910
|
+
## Layouts
|
911
|
+
|
912
|
+
```ruby
|
913
|
+
# app/views/joys/layouts/main.rb
|
914
|
+
Joys.define :layout, :main do
|
915
|
+
html {
|
916
|
+
head {
|
917
|
+
title { pull(:title) }
|
918
|
+
pull_styles # Auto-compiled CSS
|
902
919
|
}
|
920
|
+
body { pull(:body) }
|
921
|
+
}
|
922
|
+
end
|
923
|
+
```
|
924
|
+
|
925
|
+
## Raw HTML
|
926
|
+
|
927
|
+
Use `_` for unescaped HTML:
|
928
|
+
|
929
|
+
```ruby
|
930
|
+
div {
|
931
|
+
_ "<strong>Bold</strong>"
|
932
|
+
_ link_to("Link", "/")
|
933
|
+
txt "Escaped text" # Auto-escaped
|
934
|
+
}
|
935
|
+
```
|
936
|
+
|
937
|
+
## Data Passing
|
938
|
+
|
939
|
+
```ruby
|
940
|
+
# Controller
|
941
|
+
render_joy :show, user: current_user, posts: @posts
|
942
|
+
|
943
|
+
# Template
|
944
|
+
user_name = @user.name
|
945
|
+
post_count = @posts.count
|
946
|
+
|
947
|
+
Joys.html {
|
948
|
+
layout(:main) {
|
949
|
+
push(:body) { h1 "Hello #{user_name}" }
|
950
|
+
}
|
951
|
+
}
|
952
|
+
```
|
953
|
+
|
954
|
+
## Environment Behavior
|
955
|
+
|
956
|
+
- **Development**: Templates reload on every request
|
957
|
+
- **Production**: Layouts/components preloaded at boot, pages cached after first render
|
958
|
+
|
959
|
+
---
|
960
|
+
|
961
|
+
## Markup Processing in Joys
|
962
|
+
|
963
|
+
Joys includes a powerful shorthand for processing markup content directly within your templates using the `?` suffix on any tag method.
|
964
|
+
|
965
|
+
### Basic Usage
|
966
|
+
|
967
|
+
Any tag method can be followed by `?` to process its content through a markup parser:
|
968
|
+
|
969
|
+
```ruby
|
970
|
+
# Process content with your configured markup parser
|
971
|
+
div?("# Welcome to Joys")
|
972
|
+
# => <div><h1>Welcome to Joys</h1></div>
|
973
|
+
|
974
|
+
p?("This is **bold** and *italic* text")
|
975
|
+
# => <p>This is <strong>bold</strong> and <em>italic</em> text</p>
|
976
|
+
|
977
|
+
article? do
|
978
|
+
h2?("## Getting Started")
|
979
|
+
p?("Learn how to use the `tag?` methods")
|
980
|
+
end
|
981
|
+
```
|
982
|
+
|
983
|
+
### Configuration
|
984
|
+
|
985
|
+
Configure your preferred markup parser globally:
|
986
|
+
|
987
|
+
```ruby
|
988
|
+
# Using Kramdown
|
989
|
+
Joys::Config.markup_parser = ->(content) {
|
990
|
+
Kramdown::Document.new(content).to_html
|
991
|
+
}
|
992
|
+
|
993
|
+
# Using CommonMarker
|
994
|
+
Joys::Config.markup_parser = ->(content) {
|
995
|
+
CommonMarker.render_html(content)
|
996
|
+
}
|
997
|
+
|
998
|
+
# Using any custom parser
|
999
|
+
Joys::Config.markup_parser = ->(content) {
|
1000
|
+
MyCustomParser.process(content)
|
1001
|
+
}
|
1002
|
+
```
|
1003
|
+
|
1004
|
+
### 🎯 Recommended: Sparx Parser
|
1005
|
+
|
1006
|
+
For the best developer experience, we recommend **[Sparx](https://github.com/activestylus/sparx)** - a modern markup language designed specifically for the Joys ecosystem:
|
1007
|
+
|
1008
|
+
```ruby
|
1009
|
+
# Install: gem install sparx
|
1010
|
+
Joys::Config.markup_parser = ->(content) {
|
1011
|
+
Sparx.parse(content)
|
1012
|
+
}
|
1013
|
+
```
|
1014
|
+
|
1015
|
+
#### Why Sparx?
|
1016
|
+
|
1017
|
+
Sparx eliminates the frustrations of traditional Markdown with:
|
1018
|
+
|
1019
|
+
- **Consistent syntax** - No more `**bold**` vs `__bold__` confusion
|
1020
|
+
- **Perfect nesting** - Formatting works reliably in complex content
|
1021
|
+
- **Semantic HTML** - Clean, accessible output throughout
|
1022
|
+
- **URL references** - Define URLs once, use them everywhere
|
1023
|
+
- **Responsive images** - Built-in support for modern image requirements
|
1024
|
+
- **Academic citations** - Proper citation handling out of the box
|
1025
|
+
|
1026
|
+
#### Sparx Examples
|
1027
|
+
|
1028
|
+
```ruby
|
1029
|
+
# Clean, consistent formatting
|
1030
|
+
div? do
|
1031
|
+
p?("*[Bold] and /[italic] with perfect */[nesting]https://example.com")
|
1032
|
+
# => <p><strong>Bold</strong> and <em>italic</em> with perfect <strong><em><a href="https://example.com">nesting</a></em></strong></p>
|
1033
|
+
end
|
1034
|
+
|
1035
|
+
# Responsive images with art direction
|
1036
|
+
div? do
|
1037
|
+
p?("i[Hero]@cdn/hero.jpg 400w|hero@2x.jpg 800w")
|
1038
|
+
# => Generates full <picture> element with responsive sources
|
1039
|
+
end
|
1040
|
+
|
1041
|
+
# Complex content with semantic structure
|
1042
|
+
article? do
|
1043
|
+
p?("+[Technical Details]{:Performance:100x faster parsing:Output:Semantic HTML5}")
|
1044
|
+
# => Creates <details> with definition list inside
|
1045
|
+
end
|
1046
|
+
```
|
1047
|
+
|
1048
|
+
### Comparison with Other Methods
|
1049
|
+
|
1050
|
+
```ruby
|
1051
|
+
# Raw text (no processing)
|
1052
|
+
div("## This won't parse")
|
1053
|
+
# => <div>## This won't parse</div>
|
1054
|
+
|
1055
|
+
# Raw HTML (dangerous with user content)
|
1056
|
+
div!("<h1>Raw HTML</h1>")
|
1057
|
+
# => <div><h1>Raw HTML</h1></div>
|
1058
|
+
|
1059
|
+
# Markup processing (recommended)
|
1060
|
+
div?("## This becomes H1")
|
1061
|
+
# => <div><h1>This becomes H1</h1></div>
|
1062
|
+
```
|
1063
|
+
|
1064
|
+
### Advanced Usage
|
1065
|
+
|
1066
|
+
#### Inline with Other Tags
|
1067
|
+
|
1068
|
+
```ruby
|
1069
|
+
div(cs: "content") do
|
1070
|
+
h1?("# Article Title")
|
1071
|
+
div?(css: "prose") do
|
1072
|
+
p?("First paragraph with *[bold] text")
|
1073
|
+
blockquote?("> Important quote here")
|
1074
|
+
ul?("- Item one\n- Item two\n- Item three")
|
903
1075
|
end
|
1076
|
+
end
|
1077
|
+
```
|
904
1078
|
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
|
912
|
-
|
913
|
-
|
914
|
-
|
915
|
-
}
|
1079
|
+
#### With Component Composition
|
1080
|
+
|
1081
|
+
```ruby
|
1082
|
+
Joys.register(:comp, :blog_post) do |title:, content:|
|
1083
|
+
article do
|
1084
|
+
header do
|
1085
|
+
h1(title)
|
1086
|
+
time(Time.now.iso8601)
|
1087
|
+
end
|
1088
|
+
div?(cs: "content") { raw content }
|
916
1089
|
end
|
917
1090
|
end
|
1091
|
+
|
1092
|
+
# Usage with Sparx content
|
1093
|
+
Joys.comp(:blog_post,
|
1094
|
+
title: "My Article",
|
1095
|
+
content: Sparx.parse("## Introduction\n\nThis is the *[content]")
|
1096
|
+
)
|
918
1097
|
```
|
919
1098
|
|
920
|
-
###
|
1099
|
+
### Performance Notes
|
921
1100
|
|
922
|
-
|
923
|
-
-
|
924
|
-
-
|
1101
|
+
- Markup parsing happens at **render time**, not registration time
|
1102
|
+
- Processing is **cached** along with the rest of your template
|
1103
|
+
- For maximum performance with user-generated content, consider pre-processing markup outside the template
|
925
1104
|
|
926
|
-
|
927
|
-
- Move sections by reordering method calls
|
928
|
-
- Client requests become 30-second changes
|
1105
|
+
### Security
|
929
1106
|
|
930
|
-
|
931
|
-
- Data-driven sections for consistency
|
932
|
-
- Custom HTML where needed
|
933
|
-
- Reusable global components
|
934
|
-
- Page-specific anonymous components
|
1107
|
+
When processing user-generated content, ensure your markup parser is configured for safe mode:
|
935
1108
|
|
936
|
-
|
937
|
-
|
938
|
-
|
939
|
-
|
1109
|
+
```ruby
|
1110
|
+
# With Sparx safe mode
|
1111
|
+
Joys::Config.markup_parser = ->(content) {
|
1112
|
+
Sparx.parse(content, safe: true)
|
1113
|
+
}
|
1114
|
+
```
|
940
1115
|
|
941
|
-
|
1116
|
+
The `?` suffix provides a clean, consistent way to integrate markup processing into your Joys templates while maintaining the framework's exceptional performance characteristics.
|
942
1117
|
|
943
1118
|
---
|
944
1119
|
|
data/joys-0.1.0.gem
ADDED
Binary file
|
data/joys-0.1.1.gem
ADDED
Binary file
|
data/joys-0.1.2.gem
ADDED
Binary file
|
data/lib/.DS_Store
CHANGED
Binary file
|