rhales 0.4.0 → 0.5.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/.github/renovate.json5 +52 -0
- data/.github/workflows/ci.yml +123 -0
- data/.github/workflows/claude-code-review.yml +69 -0
- data/.github/workflows/claude.yml +49 -0
- data/.github/workflows/code-smells.yml +146 -0
- data/.github/workflows/ruby-lint.yml +78 -0
- data/.github/workflows/yardoc.yml +126 -0
- data/.gitignore +55 -0
- data/.pr_agent.toml +63 -0
- data/.pre-commit-config.yaml +89 -0
- data/.prettierignore +8 -0
- data/.prettierrc +38 -0
- data/.reek.yml +98 -0
- data/.rubocop.yml +428 -0
- data/.serena/.gitignore +3 -0
- data/.yardopts +56 -0
- data/CHANGELOG.md +44 -0
- data/CLAUDE.md +1 -1
- data/Gemfile +29 -0
- data/Gemfile.lock +189 -0
- data/README.md +686 -868
- data/Rakefile +46 -0
- data/debug_context.rb +25 -0
- data/demo/rhales-roda-demo/.gitignore +7 -0
- data/demo/rhales-roda-demo/Gemfile +32 -0
- data/demo/rhales-roda-demo/Gemfile.lock +151 -0
- data/demo/rhales-roda-demo/MAIL.md +405 -0
- data/demo/rhales-roda-demo/README.md +376 -0
- data/demo/rhales-roda-demo/RODA-TEMPLATE-ENGINES.md +192 -0
- data/demo/rhales-roda-demo/Rakefile +49 -0
- data/demo/rhales-roda-demo/app.rb +325 -0
- data/demo/rhales-roda-demo/bin/rackup +26 -0
- data/demo/rhales-roda-demo/config.ru +13 -0
- data/demo/rhales-roda-demo/db/migrate/001_create_rodauth_tables.rb +266 -0
- data/demo/rhales-roda-demo/db/migrate/002_create_rodauth_password_tables.rb +79 -0
- data/demo/rhales-roda-demo/db/migrate/003_add_admin_account.rb +68 -0
- data/demo/rhales-roda-demo/templates/change_login.rue +31 -0
- data/demo/rhales-roda-demo/templates/change_password.rue +36 -0
- data/demo/rhales-roda-demo/templates/close_account.rue +31 -0
- data/demo/rhales-roda-demo/templates/create_account.rue +40 -0
- data/demo/rhales-roda-demo/templates/dashboard.rue +150 -0
- data/demo/rhales-roda-demo/templates/home.rue +78 -0
- data/demo/rhales-roda-demo/templates/layouts/main.rue +168 -0
- data/demo/rhales-roda-demo/templates/login.rue +65 -0
- data/demo/rhales-roda-demo/templates/logout.rue +25 -0
- data/demo/rhales-roda-demo/templates/reset_password.rue +26 -0
- data/demo/rhales-roda-demo/templates/verify_account.rue +27 -0
- data/demo/rhales-roda-demo/test_full_output.rb +27 -0
- data/demo/rhales-roda-demo/test_simple.rb +24 -0
- data/docs/.gitignore +9 -0
- data/docs/architecture/data-flow.md +499 -0
- data/examples/dashboard-with-charts.rue +271 -0
- data/examples/form-with-validation.rue +180 -0
- data/examples/simple-page.rue +61 -0
- data/examples/vue.rue +136 -0
- data/generate-json-schemas.ts +158 -0
- data/json_schemer_migration_summary.md +172 -0
- data/lib/rhales/adapters/base_auth.rb +2 -0
- data/lib/rhales/adapters/base_request.rb +2 -0
- data/lib/rhales/adapters/base_session.rb +2 -0
- data/lib/rhales/adapters.rb +7 -0
- data/lib/rhales/configuration.rb +47 -0
- data/lib/rhales/core/context.rb +354 -0
- data/lib/rhales/{rue_document.rb → core/rue_document.rb} +56 -38
- data/lib/rhales/{template_engine.rb → core/template_engine.rb} +66 -59
- data/lib/rhales/{view.rb → core/view.rb} +112 -135
- data/lib/rhales/{view_composition.rb → core/view_composition.rb} +78 -8
- data/lib/rhales/core.rb +9 -0
- data/lib/rhales/errors/hydration_collision_error.rb +2 -0
- data/lib/rhales/errors.rb +2 -0
- data/lib/rhales/{earliest_injection_detector.rb → hydration/earliest_injection_detector.rb} +4 -0
- data/lib/rhales/hydration/hydration_data_aggregator.rb +487 -0
- data/lib/rhales/{hydration_endpoint.rb → hydration/hydration_endpoint.rb} +16 -12
- data/lib/rhales/{hydration_injector.rb → hydration/hydration_injector.rb} +4 -0
- data/lib/rhales/{hydration_registry.rb → hydration/hydration_registry.rb} +2 -0
- data/lib/rhales/hydration/hydrator.rb +102 -0
- data/lib/rhales/{link_based_injection_detector.rb → hydration/link_based_injection_detector.rb} +4 -0
- data/lib/rhales/{mount_point_detector.rb → hydration/mount_point_detector.rb} +4 -0
- data/lib/rhales/{safe_injection_validator.rb → hydration/safe_injection_validator.rb} +4 -0
- data/lib/rhales/hydration.rb +13 -0
- data/lib/rhales/{refinements → integrations/refinements}/require_refinements.rb +3 -1
- data/lib/rhales/{tilt.rb → integrations/tilt.rb} +22 -15
- data/lib/rhales/integrations.rb +6 -0
- data/lib/rhales/middleware/json_responder.rb +191 -0
- data/lib/rhales/middleware/schema_validator.rb +300 -0
- data/lib/rhales/middleware.rb +6 -0
- data/lib/rhales/parsers/handlebars_parser.rb +2 -0
- data/lib/rhales/parsers/rue_format_parser.rb +9 -7
- data/lib/rhales/parsers.rb +9 -0
- data/lib/rhales/{csp.rb → security/csp.rb} +27 -3
- data/lib/rhales/utils/json_serializer.rb +114 -0
- data/lib/rhales/utils/logging_helpers.rb +75 -0
- data/lib/rhales/utils/schema_extractor.rb +132 -0
- data/lib/rhales/utils/schema_generator.rb +194 -0
- data/lib/rhales/utils.rb +40 -0
- data/lib/rhales/version.rb +3 -1
- data/lib/rhales.rb +41 -24
- data/lib/tasks/rhales_schema.rake +197 -0
- data/package.json +10 -0
- data/pnpm-lock.yaml +345 -0
- data/pnpm-workspace.yaml +2 -0
- data/proofs/error_handling.rb +79 -0
- data/proofs/expanded_object_inheritance.rb +82 -0
- data/proofs/partial_context_scoping_fix.rb +168 -0
- data/proofs/ui_context_partial_inheritance.rb +236 -0
- data/rhales.gemspec +14 -6
- data/schema_vs_data_comparison.md +254 -0
- data/test_direct_access.rb +36 -0
- metadata +141 -23
- data/CLAUDE.locale.txt +0 -7
- data/lib/rhales/context.rb +0 -239
- data/lib/rhales/hydration_data_aggregator.rb +0 -221
- data/lib/rhales/hydrator.rb +0 -141
- data/lib/rhales/parsers/handlebars-grammar-review.txt +0 -39
data/pnpm-lock.yaml
ADDED
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
lockfileVersion: '9.0'
|
|
2
|
+
|
|
3
|
+
settings:
|
|
4
|
+
autoInstallPeers: true
|
|
5
|
+
excludeLinksFromLockfile: false
|
|
6
|
+
|
|
7
|
+
importers:
|
|
8
|
+
|
|
9
|
+
.:
|
|
10
|
+
dependencies:
|
|
11
|
+
zod:
|
|
12
|
+
specifier: ^4.1.12
|
|
13
|
+
version: 4.1.12
|
|
14
|
+
devDependencies:
|
|
15
|
+
'@prettier/plugin-ruby':
|
|
16
|
+
specifier: ^4.0.4
|
|
17
|
+
version: 4.0.4(prettier@3.6.2)
|
|
18
|
+
tsx:
|
|
19
|
+
specifier: ^4.20.6
|
|
20
|
+
version: 4.20.6
|
|
21
|
+
|
|
22
|
+
packages:
|
|
23
|
+
|
|
24
|
+
'@esbuild/aix-ppc64@0.25.11':
|
|
25
|
+
resolution: {integrity: sha512-Xt1dOL13m8u0WE8iplx9Ibbm+hFAO0GsU2P34UNoDGvZYkY8ifSiy6Zuc1lYxfG7svWE2fzqCUmFp5HCn51gJg==}
|
|
26
|
+
engines: {node: '>=18'}
|
|
27
|
+
cpu: [ppc64]
|
|
28
|
+
os: [aix]
|
|
29
|
+
|
|
30
|
+
'@esbuild/android-arm64@0.25.11':
|
|
31
|
+
resolution: {integrity: sha512-9slpyFBc4FPPz48+f6jyiXOx/Y4v34TUeDDXJpZqAWQn/08lKGeD8aDp9TMn9jDz2CiEuHwfhRmGBvpnd/PWIQ==}
|
|
32
|
+
engines: {node: '>=18'}
|
|
33
|
+
cpu: [arm64]
|
|
34
|
+
os: [android]
|
|
35
|
+
|
|
36
|
+
'@esbuild/android-arm@0.25.11':
|
|
37
|
+
resolution: {integrity: sha512-uoa7dU+Dt3HYsethkJ1k6Z9YdcHjTrSb5NUy66ZfZaSV8hEYGD5ZHbEMXnqLFlbBflLsl89Zke7CAdDJ4JI+Gg==}
|
|
38
|
+
engines: {node: '>=18'}
|
|
39
|
+
cpu: [arm]
|
|
40
|
+
os: [android]
|
|
41
|
+
|
|
42
|
+
'@esbuild/android-x64@0.25.11':
|
|
43
|
+
resolution: {integrity: sha512-Sgiab4xBjPU1QoPEIqS3Xx+R2lezu0LKIEcYe6pftr56PqPygbB7+szVnzoShbx64MUupqoE0KyRlN7gezbl8g==}
|
|
44
|
+
engines: {node: '>=18'}
|
|
45
|
+
cpu: [x64]
|
|
46
|
+
os: [android]
|
|
47
|
+
|
|
48
|
+
'@esbuild/darwin-arm64@0.25.11':
|
|
49
|
+
resolution: {integrity: sha512-VekY0PBCukppoQrycFxUqkCojnTQhdec0vevUL/EDOCnXd9LKWqD/bHwMPzigIJXPhC59Vd1WFIL57SKs2mg4w==}
|
|
50
|
+
engines: {node: '>=18'}
|
|
51
|
+
cpu: [arm64]
|
|
52
|
+
os: [darwin]
|
|
53
|
+
|
|
54
|
+
'@esbuild/darwin-x64@0.25.11':
|
|
55
|
+
resolution: {integrity: sha512-+hfp3yfBalNEpTGp9loYgbknjR695HkqtY3d3/JjSRUyPg/xd6q+mQqIb5qdywnDxRZykIHs3axEqU6l1+oWEQ==}
|
|
56
|
+
engines: {node: '>=18'}
|
|
57
|
+
cpu: [x64]
|
|
58
|
+
os: [darwin]
|
|
59
|
+
|
|
60
|
+
'@esbuild/freebsd-arm64@0.25.11':
|
|
61
|
+
resolution: {integrity: sha512-CmKjrnayyTJF2eVuO//uSjl/K3KsMIeYeyN7FyDBjsR3lnSJHaXlVoAK8DZa7lXWChbuOk7NjAc7ygAwrnPBhA==}
|
|
62
|
+
engines: {node: '>=18'}
|
|
63
|
+
cpu: [arm64]
|
|
64
|
+
os: [freebsd]
|
|
65
|
+
|
|
66
|
+
'@esbuild/freebsd-x64@0.25.11':
|
|
67
|
+
resolution: {integrity: sha512-Dyq+5oscTJvMaYPvW3x3FLpi2+gSZTCE/1ffdwuM6G1ARang/mb3jvjxs0mw6n3Lsw84ocfo9CrNMqc5lTfGOw==}
|
|
68
|
+
engines: {node: '>=18'}
|
|
69
|
+
cpu: [x64]
|
|
70
|
+
os: [freebsd]
|
|
71
|
+
|
|
72
|
+
'@esbuild/linux-arm64@0.25.11':
|
|
73
|
+
resolution: {integrity: sha512-Qr8AzcplUhGvdyUF08A1kHU3Vr2O88xxP0Tm8GcdVOUm25XYcMPp2YqSVHbLuXzYQMf9Bh/iKx7YPqECs6ffLA==}
|
|
74
|
+
engines: {node: '>=18'}
|
|
75
|
+
cpu: [arm64]
|
|
76
|
+
os: [linux]
|
|
77
|
+
|
|
78
|
+
'@esbuild/linux-arm@0.25.11':
|
|
79
|
+
resolution: {integrity: sha512-TBMv6B4kCfrGJ8cUPo7vd6NECZH/8hPpBHHlYI3qzoYFvWu2AdTvZNuU/7hsbKWqu/COU7NIK12dHAAqBLLXgw==}
|
|
80
|
+
engines: {node: '>=18'}
|
|
81
|
+
cpu: [arm]
|
|
82
|
+
os: [linux]
|
|
83
|
+
|
|
84
|
+
'@esbuild/linux-ia32@0.25.11':
|
|
85
|
+
resolution: {integrity: sha512-TmnJg8BMGPehs5JKrCLqyWTVAvielc615jbkOirATQvWWB1NMXY77oLMzsUjRLa0+ngecEmDGqt5jiDC6bfvOw==}
|
|
86
|
+
engines: {node: '>=18'}
|
|
87
|
+
cpu: [ia32]
|
|
88
|
+
os: [linux]
|
|
89
|
+
|
|
90
|
+
'@esbuild/linux-loong64@0.25.11':
|
|
91
|
+
resolution: {integrity: sha512-DIGXL2+gvDaXlaq8xruNXUJdT5tF+SBbJQKbWy/0J7OhU8gOHOzKmGIlfTTl6nHaCOoipxQbuJi7O++ldrxgMw==}
|
|
92
|
+
engines: {node: '>=18'}
|
|
93
|
+
cpu: [loong64]
|
|
94
|
+
os: [linux]
|
|
95
|
+
|
|
96
|
+
'@esbuild/linux-mips64el@0.25.11':
|
|
97
|
+
resolution: {integrity: sha512-Osx1nALUJu4pU43o9OyjSCXokFkFbyzjXb6VhGIJZQ5JZi8ylCQ9/LFagolPsHtgw6himDSyb5ETSfmp4rpiKQ==}
|
|
98
|
+
engines: {node: '>=18'}
|
|
99
|
+
cpu: [mips64el]
|
|
100
|
+
os: [linux]
|
|
101
|
+
|
|
102
|
+
'@esbuild/linux-ppc64@0.25.11':
|
|
103
|
+
resolution: {integrity: sha512-nbLFgsQQEsBa8XSgSTSlrnBSrpoWh7ioFDUmwo158gIm5NNP+17IYmNWzaIzWmgCxq56vfr34xGkOcZ7jX6CPw==}
|
|
104
|
+
engines: {node: '>=18'}
|
|
105
|
+
cpu: [ppc64]
|
|
106
|
+
os: [linux]
|
|
107
|
+
|
|
108
|
+
'@esbuild/linux-riscv64@0.25.11':
|
|
109
|
+
resolution: {integrity: sha512-HfyAmqZi9uBAbgKYP1yGuI7tSREXwIb438q0nqvlpxAOs3XnZ8RsisRfmVsgV486NdjD7Mw2UrFSw51lzUk1ww==}
|
|
110
|
+
engines: {node: '>=18'}
|
|
111
|
+
cpu: [riscv64]
|
|
112
|
+
os: [linux]
|
|
113
|
+
|
|
114
|
+
'@esbuild/linux-s390x@0.25.11':
|
|
115
|
+
resolution: {integrity: sha512-HjLqVgSSYnVXRisyfmzsH6mXqyvj0SA7pG5g+9W7ESgwA70AXYNpfKBqh1KbTxmQVaYxpzA/SvlB9oclGPbApw==}
|
|
116
|
+
engines: {node: '>=18'}
|
|
117
|
+
cpu: [s390x]
|
|
118
|
+
os: [linux]
|
|
119
|
+
|
|
120
|
+
'@esbuild/linux-x64@0.25.11':
|
|
121
|
+
resolution: {integrity: sha512-HSFAT4+WYjIhrHxKBwGmOOSpphjYkcswF449j6EjsjbinTZbp8PJtjsVK1XFJStdzXdy/jaddAep2FGY+wyFAQ==}
|
|
122
|
+
engines: {node: '>=18'}
|
|
123
|
+
cpu: [x64]
|
|
124
|
+
os: [linux]
|
|
125
|
+
|
|
126
|
+
'@esbuild/netbsd-arm64@0.25.11':
|
|
127
|
+
resolution: {integrity: sha512-hr9Oxj1Fa4r04dNpWr3P8QKVVsjQhqrMSUzZzf+LZcYjZNqhA3IAfPQdEh1FLVUJSiu6sgAwp3OmwBfbFgG2Xg==}
|
|
128
|
+
engines: {node: '>=18'}
|
|
129
|
+
cpu: [arm64]
|
|
130
|
+
os: [netbsd]
|
|
131
|
+
|
|
132
|
+
'@esbuild/netbsd-x64@0.25.11':
|
|
133
|
+
resolution: {integrity: sha512-u7tKA+qbzBydyj0vgpu+5h5AeudxOAGncb8N6C9Kh1N4n7wU1Xw1JDApsRjpShRpXRQlJLb9wY28ELpwdPcZ7A==}
|
|
134
|
+
engines: {node: '>=18'}
|
|
135
|
+
cpu: [x64]
|
|
136
|
+
os: [netbsd]
|
|
137
|
+
|
|
138
|
+
'@esbuild/openbsd-arm64@0.25.11':
|
|
139
|
+
resolution: {integrity: sha512-Qq6YHhayieor3DxFOoYM1q0q1uMFYb7cSpLD2qzDSvK1NAvqFi8Xgivv0cFC6J+hWVw2teCYltyy9/m/14ryHg==}
|
|
140
|
+
engines: {node: '>=18'}
|
|
141
|
+
cpu: [arm64]
|
|
142
|
+
os: [openbsd]
|
|
143
|
+
|
|
144
|
+
'@esbuild/openbsd-x64@0.25.11':
|
|
145
|
+
resolution: {integrity: sha512-CN+7c++kkbrckTOz5hrehxWN7uIhFFlmS/hqziSFVWpAzpWrQoAG4chH+nN3Be+Kzv/uuo7zhX716x3Sn2Jduw==}
|
|
146
|
+
engines: {node: '>=18'}
|
|
147
|
+
cpu: [x64]
|
|
148
|
+
os: [openbsd]
|
|
149
|
+
|
|
150
|
+
'@esbuild/openharmony-arm64@0.25.11':
|
|
151
|
+
resolution: {integrity: sha512-rOREuNIQgaiR+9QuNkbkxubbp8MSO9rONmwP5nKncnWJ9v5jQ4JxFnLu4zDSRPf3x4u+2VN4pM4RdyIzDty/wQ==}
|
|
152
|
+
engines: {node: '>=18'}
|
|
153
|
+
cpu: [arm64]
|
|
154
|
+
os: [openharmony]
|
|
155
|
+
|
|
156
|
+
'@esbuild/sunos-x64@0.25.11':
|
|
157
|
+
resolution: {integrity: sha512-nq2xdYaWxyg9DcIyXkZhcYulC6pQ2FuCgem3LI92IwMgIZ69KHeY8T4Y88pcwoLIjbed8n36CyKoYRDygNSGhA==}
|
|
158
|
+
engines: {node: '>=18'}
|
|
159
|
+
cpu: [x64]
|
|
160
|
+
os: [sunos]
|
|
161
|
+
|
|
162
|
+
'@esbuild/win32-arm64@0.25.11':
|
|
163
|
+
resolution: {integrity: sha512-3XxECOWJq1qMZ3MN8srCJ/QfoLpL+VaxD/WfNRm1O3B4+AZ/BnLVgFbUV3eiRYDMXetciH16dwPbbHqwe1uU0Q==}
|
|
164
|
+
engines: {node: '>=18'}
|
|
165
|
+
cpu: [arm64]
|
|
166
|
+
os: [win32]
|
|
167
|
+
|
|
168
|
+
'@esbuild/win32-ia32@0.25.11':
|
|
169
|
+
resolution: {integrity: sha512-3ukss6gb9XZ8TlRyJlgLn17ecsK4NSQTmdIXRASVsiS2sQ6zPPZklNJT5GR5tE/MUarymmy8kCEf5xPCNCqVOA==}
|
|
170
|
+
engines: {node: '>=18'}
|
|
171
|
+
cpu: [ia32]
|
|
172
|
+
os: [win32]
|
|
173
|
+
|
|
174
|
+
'@esbuild/win32-x64@0.25.11':
|
|
175
|
+
resolution: {integrity: sha512-D7Hpz6A2L4hzsRpPaCYkQnGOotdUpDzSGRIv9I+1ITdHROSFUWW95ZPZWQmGka1Fg7W3zFJowyn9WGwMJ0+KPA==}
|
|
176
|
+
engines: {node: '>=18'}
|
|
177
|
+
cpu: [x64]
|
|
178
|
+
os: [win32]
|
|
179
|
+
|
|
180
|
+
'@prettier/plugin-ruby@4.0.4':
|
|
181
|
+
resolution: {integrity: sha512-lCpvfS/dQU5WrwN3AQ5vR8qrvj2h5gE41X08NNzAAXvHdM4zwwGRcP2sHSxfu6n6No+ljWCVx95NvJPFTTjCTg==}
|
|
182
|
+
peerDependencies:
|
|
183
|
+
prettier: ^3.0.0
|
|
184
|
+
|
|
185
|
+
esbuild@0.25.11:
|
|
186
|
+
resolution: {integrity: sha512-KohQwyzrKTQmhXDW1PjCv3Tyspn9n5GcY2RTDqeORIdIJY8yKIF7sTSopFmn/wpMPW4rdPXI0UE5LJLuq3bx0Q==}
|
|
187
|
+
engines: {node: '>=18'}
|
|
188
|
+
hasBin: true
|
|
189
|
+
|
|
190
|
+
fsevents@2.3.3:
|
|
191
|
+
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
|
|
192
|
+
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
|
|
193
|
+
os: [darwin]
|
|
194
|
+
|
|
195
|
+
get-tsconfig@4.12.0:
|
|
196
|
+
resolution: {integrity: sha512-LScr2aNr2FbjAjZh2C6X6BxRx1/x+aTDExct/xyq2XKbYOiG5c0aK7pMsSuyc0brz3ibr/lbQiHD9jzt4lccJw==}
|
|
197
|
+
|
|
198
|
+
prettier@3.6.2:
|
|
199
|
+
resolution: {integrity: sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==}
|
|
200
|
+
engines: {node: '>=14'}
|
|
201
|
+
hasBin: true
|
|
202
|
+
|
|
203
|
+
resolve-pkg-maps@1.0.0:
|
|
204
|
+
resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
|
|
205
|
+
|
|
206
|
+
tsx@4.20.6:
|
|
207
|
+
resolution: {integrity: sha512-ytQKuwgmrrkDTFP4LjR0ToE2nqgy886GpvRSpU0JAnrdBYppuY5rLkRUYPU1yCryb24SsKBTL/hlDQAEFVwtZg==}
|
|
208
|
+
engines: {node: '>=18.0.0'}
|
|
209
|
+
hasBin: true
|
|
210
|
+
|
|
211
|
+
zod@4.1.12:
|
|
212
|
+
resolution: {integrity: sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==}
|
|
213
|
+
|
|
214
|
+
snapshots:
|
|
215
|
+
|
|
216
|
+
'@esbuild/aix-ppc64@0.25.11':
|
|
217
|
+
optional: true
|
|
218
|
+
|
|
219
|
+
'@esbuild/android-arm64@0.25.11':
|
|
220
|
+
optional: true
|
|
221
|
+
|
|
222
|
+
'@esbuild/android-arm@0.25.11':
|
|
223
|
+
optional: true
|
|
224
|
+
|
|
225
|
+
'@esbuild/android-x64@0.25.11':
|
|
226
|
+
optional: true
|
|
227
|
+
|
|
228
|
+
'@esbuild/darwin-arm64@0.25.11':
|
|
229
|
+
optional: true
|
|
230
|
+
|
|
231
|
+
'@esbuild/darwin-x64@0.25.11':
|
|
232
|
+
optional: true
|
|
233
|
+
|
|
234
|
+
'@esbuild/freebsd-arm64@0.25.11':
|
|
235
|
+
optional: true
|
|
236
|
+
|
|
237
|
+
'@esbuild/freebsd-x64@0.25.11':
|
|
238
|
+
optional: true
|
|
239
|
+
|
|
240
|
+
'@esbuild/linux-arm64@0.25.11':
|
|
241
|
+
optional: true
|
|
242
|
+
|
|
243
|
+
'@esbuild/linux-arm@0.25.11':
|
|
244
|
+
optional: true
|
|
245
|
+
|
|
246
|
+
'@esbuild/linux-ia32@0.25.11':
|
|
247
|
+
optional: true
|
|
248
|
+
|
|
249
|
+
'@esbuild/linux-loong64@0.25.11':
|
|
250
|
+
optional: true
|
|
251
|
+
|
|
252
|
+
'@esbuild/linux-mips64el@0.25.11':
|
|
253
|
+
optional: true
|
|
254
|
+
|
|
255
|
+
'@esbuild/linux-ppc64@0.25.11':
|
|
256
|
+
optional: true
|
|
257
|
+
|
|
258
|
+
'@esbuild/linux-riscv64@0.25.11':
|
|
259
|
+
optional: true
|
|
260
|
+
|
|
261
|
+
'@esbuild/linux-s390x@0.25.11':
|
|
262
|
+
optional: true
|
|
263
|
+
|
|
264
|
+
'@esbuild/linux-x64@0.25.11':
|
|
265
|
+
optional: true
|
|
266
|
+
|
|
267
|
+
'@esbuild/netbsd-arm64@0.25.11':
|
|
268
|
+
optional: true
|
|
269
|
+
|
|
270
|
+
'@esbuild/netbsd-x64@0.25.11':
|
|
271
|
+
optional: true
|
|
272
|
+
|
|
273
|
+
'@esbuild/openbsd-arm64@0.25.11':
|
|
274
|
+
optional: true
|
|
275
|
+
|
|
276
|
+
'@esbuild/openbsd-x64@0.25.11':
|
|
277
|
+
optional: true
|
|
278
|
+
|
|
279
|
+
'@esbuild/openharmony-arm64@0.25.11':
|
|
280
|
+
optional: true
|
|
281
|
+
|
|
282
|
+
'@esbuild/sunos-x64@0.25.11':
|
|
283
|
+
optional: true
|
|
284
|
+
|
|
285
|
+
'@esbuild/win32-arm64@0.25.11':
|
|
286
|
+
optional: true
|
|
287
|
+
|
|
288
|
+
'@esbuild/win32-ia32@0.25.11':
|
|
289
|
+
optional: true
|
|
290
|
+
|
|
291
|
+
'@esbuild/win32-x64@0.25.11':
|
|
292
|
+
optional: true
|
|
293
|
+
|
|
294
|
+
'@prettier/plugin-ruby@4.0.4(prettier@3.6.2)':
|
|
295
|
+
dependencies:
|
|
296
|
+
prettier: 3.6.2
|
|
297
|
+
|
|
298
|
+
esbuild@0.25.11:
|
|
299
|
+
optionalDependencies:
|
|
300
|
+
'@esbuild/aix-ppc64': 0.25.11
|
|
301
|
+
'@esbuild/android-arm': 0.25.11
|
|
302
|
+
'@esbuild/android-arm64': 0.25.11
|
|
303
|
+
'@esbuild/android-x64': 0.25.11
|
|
304
|
+
'@esbuild/darwin-arm64': 0.25.11
|
|
305
|
+
'@esbuild/darwin-x64': 0.25.11
|
|
306
|
+
'@esbuild/freebsd-arm64': 0.25.11
|
|
307
|
+
'@esbuild/freebsd-x64': 0.25.11
|
|
308
|
+
'@esbuild/linux-arm': 0.25.11
|
|
309
|
+
'@esbuild/linux-arm64': 0.25.11
|
|
310
|
+
'@esbuild/linux-ia32': 0.25.11
|
|
311
|
+
'@esbuild/linux-loong64': 0.25.11
|
|
312
|
+
'@esbuild/linux-mips64el': 0.25.11
|
|
313
|
+
'@esbuild/linux-ppc64': 0.25.11
|
|
314
|
+
'@esbuild/linux-riscv64': 0.25.11
|
|
315
|
+
'@esbuild/linux-s390x': 0.25.11
|
|
316
|
+
'@esbuild/linux-x64': 0.25.11
|
|
317
|
+
'@esbuild/netbsd-arm64': 0.25.11
|
|
318
|
+
'@esbuild/netbsd-x64': 0.25.11
|
|
319
|
+
'@esbuild/openbsd-arm64': 0.25.11
|
|
320
|
+
'@esbuild/openbsd-x64': 0.25.11
|
|
321
|
+
'@esbuild/openharmony-arm64': 0.25.11
|
|
322
|
+
'@esbuild/sunos-x64': 0.25.11
|
|
323
|
+
'@esbuild/win32-arm64': 0.25.11
|
|
324
|
+
'@esbuild/win32-ia32': 0.25.11
|
|
325
|
+
'@esbuild/win32-x64': 0.25.11
|
|
326
|
+
|
|
327
|
+
fsevents@2.3.3:
|
|
328
|
+
optional: true
|
|
329
|
+
|
|
330
|
+
get-tsconfig@4.12.0:
|
|
331
|
+
dependencies:
|
|
332
|
+
resolve-pkg-maps: 1.0.0
|
|
333
|
+
|
|
334
|
+
prettier@3.6.2: {}
|
|
335
|
+
|
|
336
|
+
resolve-pkg-maps@1.0.0: {}
|
|
337
|
+
|
|
338
|
+
tsx@4.20.6:
|
|
339
|
+
dependencies:
|
|
340
|
+
esbuild: 0.25.11
|
|
341
|
+
get-tsconfig: 4.12.0
|
|
342
|
+
optionalDependencies:
|
|
343
|
+
fsevents: 2.3.3
|
|
344
|
+
|
|
345
|
+
zod@4.1.12: {}
|
data/pnpm-workspace.yaml
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# proofs/error_handling.rb
|
|
3
|
+
|
|
4
|
+
require_relative 'lib/rhales'
|
|
5
|
+
|
|
6
|
+
# Example demonstrating the new error hierarchy
|
|
7
|
+
|
|
8
|
+
puts '=== Rhales Error Hierarchy Demo ==='
|
|
9
|
+
puts
|
|
10
|
+
|
|
11
|
+
# 1. Catching all Rhales errors
|
|
12
|
+
begin
|
|
13
|
+
template = '{{#if user}}Hello{{else' # Missing closing {{/if}}
|
|
14
|
+
context = Rhales::Context.minimal(client: { user: 'John' })
|
|
15
|
+
Rhales::TemplateEngine.render(template, context)
|
|
16
|
+
rescue Rhales::Error => ex
|
|
17
|
+
puts "Caught any Rhales error: #{ex.class} - #{ex.message}"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
puts
|
|
21
|
+
|
|
22
|
+
# 2. Catching render errors (which wrap parse errors)
|
|
23
|
+
begin
|
|
24
|
+
template = '{{unclosed'
|
|
25
|
+
context = Rhales::Context.minimal(client: {})
|
|
26
|
+
Rhales::TemplateEngine.render(template, context)
|
|
27
|
+
rescue Rhales::TemplateEngine::RenderError => ex
|
|
28
|
+
puts 'Render error wrapping parse error:'
|
|
29
|
+
puts " Class: #{ex.class}"
|
|
30
|
+
puts " Message: #{ex.message}"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
puts
|
|
34
|
+
|
|
35
|
+
# 2b. Catching parse errors directly from parser
|
|
36
|
+
begin
|
|
37
|
+
parser = Rhales::HandlebarsParser.new('{{unclosed')
|
|
38
|
+
parser.parse!
|
|
39
|
+
rescue Rhales::ParseError => ex
|
|
40
|
+
puts 'Direct parse error details:'
|
|
41
|
+
puts " Class: #{ex.class}"
|
|
42
|
+
puts " Message: #{ex.message}"
|
|
43
|
+
puts " Source type: #{ex.source_type}"
|
|
44
|
+
puts " Line: #{ex.line}, Column: #{ex.column}"
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
puts
|
|
48
|
+
|
|
49
|
+
# 3. Validation error from Parser
|
|
50
|
+
begin
|
|
51
|
+
template = <<~RUE
|
|
52
|
+
<logic>
|
|
53
|
+
# Missing required sections
|
|
54
|
+
</logic>
|
|
55
|
+
RUE
|
|
56
|
+
|
|
57
|
+
parser = Rhales::RueDocument.new(template)
|
|
58
|
+
parser.parse!
|
|
59
|
+
rescue Rhales::ValidationError => ex
|
|
60
|
+
puts "Validation error: #{ex.class} - #{ex.message}"
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
puts
|
|
64
|
+
|
|
65
|
+
# 4. Render error example
|
|
66
|
+
begin
|
|
67
|
+
template = '{{> missing_partial}}'
|
|
68
|
+
context = Rhales::Context.minimal(client: {})
|
|
69
|
+
Rhales::TemplateEngine.render(template, context)
|
|
70
|
+
rescue Rhales::RenderError => ex
|
|
71
|
+
puts "Render error: #{ex.class} - #{ex.message}"
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
puts
|
|
75
|
+
puts '=== Benefits of the new hierarchy ==='
|
|
76
|
+
puts '1. Single rescue for all Rhales errors: rescue Rhales::Error'
|
|
77
|
+
puts '2. Stage-specific handling: ParseError, ValidationError, RenderError'
|
|
78
|
+
puts '3. Consistent error attributes across all parse errors'
|
|
79
|
+
puts '4. Better error messages with source context'
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
# Proof that partials can now access parent's expanded object properties
|
|
4
|
+
# This specifically tests that {{authenticated}} and {{ui}} from {{{onetime_window}}} are accessible
|
|
5
|
+
|
|
6
|
+
require_relative '../lib/rhales'
|
|
7
|
+
|
|
8
|
+
puts "=== Testing Expanded Object Inheritance in Partials ==="
|
|
9
|
+
puts "Verifying that properties from parent's {{{onetime_window}}} are accessible in partials\n\n"
|
|
10
|
+
|
|
11
|
+
# Create context with onetime_window object that will be expanded
|
|
12
|
+
props = {
|
|
13
|
+
greeting: 'Hello World',
|
|
14
|
+
user: { name: 'John Doe' },
|
|
15
|
+
onetime_window: {
|
|
16
|
+
authenticated: true,
|
|
17
|
+
ui: {
|
|
18
|
+
theme: 'dark',
|
|
19
|
+
language: 'en'
|
|
20
|
+
},
|
|
21
|
+
features: {
|
|
22
|
+
account_creation: true,
|
|
23
|
+
social_login: false
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
# Test: Direct TemplateEngine test to show the inheritance
|
|
29
|
+
puts "Test: Direct test showing expanded context inheritance"
|
|
30
|
+
puts "-" * 50
|
|
31
|
+
|
|
32
|
+
# Simulate what View does - expand the onetime_window object into the context
|
|
33
|
+
expanded_props = props.dup
|
|
34
|
+
expanded_props.merge!(props[:onetime_window])
|
|
35
|
+
|
|
36
|
+
expanded_context = Rhales::Context.minimal(props: expanded_props)
|
|
37
|
+
|
|
38
|
+
simple_main = <<~RUE
|
|
39
|
+
<template>
|
|
40
|
+
<div>
|
|
41
|
+
<p>Main sees authenticated: {{authenticated}}</p>
|
|
42
|
+
{{> simple_partial}}
|
|
43
|
+
</div>
|
|
44
|
+
</template>
|
|
45
|
+
RUE
|
|
46
|
+
|
|
47
|
+
simple_partial = <<~RUE
|
|
48
|
+
<data>
|
|
49
|
+
{
|
|
50
|
+
"partial_var": "I'm from partial"
|
|
51
|
+
}
|
|
52
|
+
</data>
|
|
53
|
+
|
|
54
|
+
<template>
|
|
55
|
+
<div class="simple-partial">
|
|
56
|
+
<p>{{partial_var}}</p>
|
|
57
|
+
<p>Partial sees authenticated: {{authenticated}}</p>
|
|
58
|
+
<p>Partial sees ui.theme: {{ui.theme}}</p>
|
|
59
|
+
</div>
|
|
60
|
+
</template>
|
|
61
|
+
RUE
|
|
62
|
+
|
|
63
|
+
partial_resolver2 = proc do |name|
|
|
64
|
+
case name
|
|
65
|
+
when 'simple_partial' then simple_partial
|
|
66
|
+
else nil
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
engine = Rhales::TemplateEngine.new(simple_main, expanded_context, partial_resolver: partial_resolver2)
|
|
71
|
+
result2 = engine.render
|
|
72
|
+
|
|
73
|
+
puts result2
|
|
74
|
+
puts "\nDirect Test Checks:"
|
|
75
|
+
puts "✅ Partial inherits expanded authenticated" if result2.include?("Partial sees authenticated: true")
|
|
76
|
+
puts "✅ Partial inherits expanded ui.theme" if result2.include?("Partial sees ui.theme: dark")
|
|
77
|
+
|
|
78
|
+
puts "\n\n=== Summary ==="
|
|
79
|
+
puts "The fix confirms that partials can now access properties from the parent's"
|
|
80
|
+
puts "expanded objects (like {{{onetime_window}}}). This means {{authenticated}}"
|
|
81
|
+
puts "and {{ui}} are no longer empty in partials - they correctly inherit from"
|
|
82
|
+
puts "the parent's expanded context."
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
# Proof that partials now correctly inherit parent context and can access their own data sections
|
|
4
|
+
# This demonstrates the fix for issue #16 - Context Scoping
|
|
5
|
+
|
|
6
|
+
require_relative '../lib/rhales'
|
|
7
|
+
|
|
8
|
+
puts "=== Testing Partial Context Scoping Fix ==="
|
|
9
|
+
puts "Issue #16: Partials should access both inherited context and local data\n\n"
|
|
10
|
+
|
|
11
|
+
# Create context with some props
|
|
12
|
+
props = {
|
|
13
|
+
greeting: 'Hello World',
|
|
14
|
+
user: { name: 'John Doe' },
|
|
15
|
+
authenticated: true,
|
|
16
|
+
main_message: 'From main props'
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
context = Rhales::Context.minimal(props: props)
|
|
20
|
+
|
|
21
|
+
# Test 1: Basic partial with data section
|
|
22
|
+
puts "Test 1: Basic partial with local data section"
|
|
23
|
+
puts "-" * 50
|
|
24
|
+
|
|
25
|
+
main_template = <<~RUE
|
|
26
|
+
<template>
|
|
27
|
+
<div class="main">
|
|
28
|
+
<h1>Main Template</h1>
|
|
29
|
+
<p>Props: {{greeting}}</p>
|
|
30
|
+
{{> basic_partial}}
|
|
31
|
+
</div>
|
|
32
|
+
</template>
|
|
33
|
+
RUE
|
|
34
|
+
|
|
35
|
+
basic_partial = <<~RUE
|
|
36
|
+
<data>
|
|
37
|
+
{
|
|
38
|
+
"partial_message": "I am from the partial's data section",
|
|
39
|
+
"computed_value": "Greeting is: {{greeting}}"
|
|
40
|
+
}
|
|
41
|
+
</data>
|
|
42
|
+
|
|
43
|
+
<template>
|
|
44
|
+
<div class="partial">
|
|
45
|
+
<p>Local data: {{partial_message}}</p>
|
|
46
|
+
<p>Computed: {{computed_value}}</p>
|
|
47
|
+
<p>Inherited: {{main_message}}</p>
|
|
48
|
+
</div>
|
|
49
|
+
</template>
|
|
50
|
+
RUE
|
|
51
|
+
|
|
52
|
+
partial_resolver = proc do |name|
|
|
53
|
+
case name
|
|
54
|
+
when 'basic_partial' then basic_partial
|
|
55
|
+
else nil
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
engine = Rhales::TemplateEngine.new(main_template, context, partial_resolver: partial_resolver)
|
|
60
|
+
result = engine.render
|
|
61
|
+
|
|
62
|
+
puts result
|
|
63
|
+
puts "\nChecks:"
|
|
64
|
+
puts "✅ Partial's local data accessible" if result.include?("I am from the partial's data section")
|
|
65
|
+
puts "✅ Partial can use parent context in data section" if result.include?("Greeting is: Hello World")
|
|
66
|
+
puts "✅ Partial inherits parent props" if result.include?("From main props")
|
|
67
|
+
|
|
68
|
+
# Test 2: Partial with window attribute
|
|
69
|
+
puts "\n\nTest 2: Partial with window attribute (head.rue scenario)"
|
|
70
|
+
puts "-" * 50
|
|
71
|
+
|
|
72
|
+
head_partial = <<~RUE
|
|
73
|
+
<data window="headData">
|
|
74
|
+
{
|
|
75
|
+
"page_title": "One Time Secret",
|
|
76
|
+
"theme_color": "#dc4a22"
|
|
77
|
+
}
|
|
78
|
+
</data>
|
|
79
|
+
|
|
80
|
+
<template>
|
|
81
|
+
<head>
|
|
82
|
+
<title>{{page_title}}</title>
|
|
83
|
+
<meta name="theme-color" content="{{theme_color}}">
|
|
84
|
+
<meta name="authenticated" content="{{authenticated}}">
|
|
85
|
+
</head>
|
|
86
|
+
</template>
|
|
87
|
+
RUE
|
|
88
|
+
|
|
89
|
+
main_with_head = <<~RUE
|
|
90
|
+
<template>
|
|
91
|
+
<html>
|
|
92
|
+
{{> head}}
|
|
93
|
+
<body>
|
|
94
|
+
<h1>{{greeting}}</h1>
|
|
95
|
+
</body>
|
|
96
|
+
</html>
|
|
97
|
+
</template>
|
|
98
|
+
RUE
|
|
99
|
+
|
|
100
|
+
partial_resolver2 = proc do |name|
|
|
101
|
+
case name
|
|
102
|
+
when 'head' then head_partial
|
|
103
|
+
else nil
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
engine2 = Rhales::TemplateEngine.new(main_with_head, context, partial_resolver: partial_resolver2)
|
|
108
|
+
result2 = engine2.render
|
|
109
|
+
|
|
110
|
+
puts result2
|
|
111
|
+
puts "\nChecks:"
|
|
112
|
+
puts "✅ page_title from partial's data section" if result2.include?("<title>One Time Secret</title>")
|
|
113
|
+
puts "✅ theme_color from partial's data section" if result2.include?('content="#dc4a22"')
|
|
114
|
+
puts "✅ authenticated from parent context" if result2.include?('content="true"')
|
|
115
|
+
|
|
116
|
+
# Test 3: Variable precedence (local data overrides parent)
|
|
117
|
+
puts "\n\nTest 3: Variable precedence (local overrides parent)"
|
|
118
|
+
puts "-" * 50
|
|
119
|
+
|
|
120
|
+
override_partial = <<~RUE
|
|
121
|
+
<data>
|
|
122
|
+
{
|
|
123
|
+
"greeting": "Overridden greeting from partial",
|
|
124
|
+
"new_var": "Only in partial"
|
|
125
|
+
}
|
|
126
|
+
</data>
|
|
127
|
+
|
|
128
|
+
<template>
|
|
129
|
+
<div class="override-test">
|
|
130
|
+
<p>Greeting: {{greeting}}</p>
|
|
131
|
+
<p>New var: {{new_var}}</p>
|
|
132
|
+
<p>User: {{user.name}}</p>
|
|
133
|
+
</div>
|
|
134
|
+
</template>
|
|
135
|
+
RUE
|
|
136
|
+
|
|
137
|
+
main_override = <<~RUE
|
|
138
|
+
<template>
|
|
139
|
+
<div>
|
|
140
|
+
<p>Main greeting: {{greeting}}</p>
|
|
141
|
+
{{> override_partial}}
|
|
142
|
+
</div>
|
|
143
|
+
</template>
|
|
144
|
+
RUE
|
|
145
|
+
|
|
146
|
+
partial_resolver3 = proc do |name|
|
|
147
|
+
case name
|
|
148
|
+
when 'override_partial' then override_partial
|
|
149
|
+
else nil
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
engine3 = Rhales::TemplateEngine.new(main_override, context, partial_resolver: partial_resolver3)
|
|
154
|
+
result3 = engine3.render
|
|
155
|
+
|
|
156
|
+
puts result3
|
|
157
|
+
puts "\nChecks:"
|
|
158
|
+
puts "✅ Main still has original greeting" if result3.include?("Main greeting: Hello World")
|
|
159
|
+
puts "✅ Partial overrides greeting locally" if result3.include?("Greeting: Overridden greeting from partial")
|
|
160
|
+
puts "✅ Partial has new local variable" if result3.include?("New var: Only in partial")
|
|
161
|
+
puts "✅ Partial inherits user from parent" if result3.include?("User: John Doe")
|
|
162
|
+
|
|
163
|
+
puts "\n\n=== Summary ==="
|
|
164
|
+
puts "The fix successfully implements the intended behavior from spec documents 080 & 082:"
|
|
165
|
+
puts "1. Partials can access their local <data> section variables"
|
|
166
|
+
puts "2. Partials inherit parent context (including expanded objects)"
|
|
167
|
+
puts "3. Local data takes precedence over inherited data"
|
|
168
|
+
puts "4. Window attributes work correctly for client-side hydration"
|