isomorfeus-preact 10.9.0 → 22.9.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (266) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +14 -3
  3. data/README.md +23 -39
  4. data/lib/browser/delegate_native.rb +94 -72
  5. data/lib/browser/document.rb +38 -0
  6. data/lib/browser/element.rb +160 -176
  7. data/lib/browser/event.rb +99 -94
  8. data/lib/browser/history.rb +40 -20
  9. data/lib/browser/location.rb +59 -0
  10. data/lib/browser/window.rb +58 -0
  11. data/lib/data_uri/open_uri.rb +18 -0
  12. data/lib/data_uri/uri.rb +61 -0
  13. data/lib/data_uri.rb +4 -0
  14. data/lib/isomorfeus/preact/config.rb +42 -54
  15. data/lib/isomorfeus/preact/imports.rb +5 -20
  16. data/lib/isomorfeus/preact/ssr.rb +34 -0
  17. data/lib/isomorfeus/preact/thread_local_component_cache.rb +9 -11
  18. data/lib/isomorfeus/preact/version.rb +5 -0
  19. data/lib/isomorfeus/preact/view_helper.rb +72 -0
  20. data/lib/isomorfeus/props/validator.rb +19 -11
  21. data/lib/isomorfeus/top_level.rb +55 -33
  22. data/lib/isomorfeus-preact.rb +78 -103
  23. data/lib/link.rb +52 -0
  24. data/lib/lucid_app.rb +117 -0
  25. data/lib/lucid_component.rb +154 -0
  26. data/lib/nano_css.rb +282 -465
  27. data/lib/preact/component.rb +222 -0
  28. data/lib/preact/component_resolution.rb +49 -83
  29. data/lib/preact/context.rb +68 -0
  30. data/lib/preact/elements.rb +2 -9
  31. data/lib/preact/module_component_resolution.rb +50 -0
  32. data/lib/preact/prop_declaration_mixin.rb +73 -0
  33. data/lib/preact.rb +1548 -257
  34. data/lib/redirect.rb +34 -0
  35. data/lib/route.rb +15 -0
  36. data/lib/router.rb +145 -0
  37. data/lib/switch.rb +70 -0
  38. data/opal/iso_uri.rb +29 -0
  39. data/opal/uri/common.rb +18 -0
  40. data/opal/uri/generic.rb +47 -0
  41. metadata +45 -309
  42. data/lib/isomorfeus/preact/memcached_component_cache.rb +0 -19
  43. data/lib/isomorfeus/preact/redis_component_cache.rb +0 -19
  44. data/lib/isomorfeus/preact/ssr/history.rb +0 -23
  45. data/lib/isomorfeus/preact/ssr/render_core.rb +0 -117
  46. data/lib/isomorfeus/preact/ssr/top_level.rb +0 -37
  47. data/lib/isomorfeus/preact_view_helper.rb +0 -129
  48. data/lib/isomorfeus_preact/lucid_app/api.rb +0 -38
  49. data/lib/isomorfeus_preact/lucid_app/base.rb +0 -7
  50. data/lib/isomorfeus_preact/lucid_app/mixin.rb +0 -14
  51. data/lib/isomorfeus_preact/lucid_app/native_component_constructor.rb +0 -101
  52. data/lib/isomorfeus_preact/lucid_component/api.rb +0 -123
  53. data/lib/isomorfeus_preact/lucid_component/app_store_proxy.rb +0 -32
  54. data/lib/isomorfeus_preact/lucid_component/base.rb +0 -7
  55. data/lib/isomorfeus_preact/lucid_component/class_store_proxy.rb +0 -37
  56. data/lib/isomorfeus_preact/lucid_component/initializer.rb +0 -9
  57. data/lib/isomorfeus_preact/lucid_component/mixin.rb +0 -13
  58. data/lib/isomorfeus_preact/lucid_component/native_component_constructor.rb +0 -87
  59. data/lib/isomorfeus_preact/lucid_component/styles_wrapper.rb +0 -40
  60. data/lib/isomorfeus_preact/lucid_func/base.rb +0 -7
  61. data/lib/isomorfeus_preact/lucid_func/initializer.rb +0 -8
  62. data/lib/isomorfeus_preact/lucid_func/mixin.rb +0 -10
  63. data/lib/isomorfeus_preact/lucid_func/native_component_constructor.rb +0 -56
  64. data/lib/isomorfeus_preact/preact/function_component/api.rb +0 -164
  65. data/lib/isomorfeus_preact/preact/function_component/base.rb +0 -7
  66. data/lib/isomorfeus_preact/preact/function_component/initializer.rb +0 -6
  67. data/lib/isomorfeus_preact/preact/function_component/mixin.rb +0 -8
  68. data/lib/isomorfeus_preact/preact/function_component/native_component_constructor.rb +0 -47
  69. data/lib/lucid_app/context.rb +0 -24
  70. data/lib/lucid_prop_declaration/mixin.rb +0 -126
  71. data/lib/preact/component/api.rb +0 -137
  72. data/lib/preact/component/base.rb +0 -7
  73. data/lib/preact/component/callbacks.rb +0 -111
  74. data/lib/preact/component/initializer.rb +0 -7
  75. data/lib/preact/component/mixin.rb +0 -11
  76. data/lib/preact/component/native_component_constructor.rb +0 -77
  77. data/lib/preact/context_wrapper.rb +0 -48
  78. data/lib/preact/native_constant_wrapper.rb +0 -29
  79. data/lib/preact/option_hooks.rb +0 -98
  80. data/lib/preact/params.rb +0 -16
  81. data/lib/preact/props.rb +0 -69
  82. data/lib/preact/ref.rb +0 -17
  83. data/lib/preact/state.rb +0 -87
  84. data/lib/preact/version.rb +0 -3
  85. data/node_modules/.package-lock.json +0 -38
  86. data/node_modules/preact/LICENSE +0 -21
  87. data/node_modules/preact/README.md +0 -188
  88. data/node_modules/preact/compat/LICENSE +0 -21
  89. data/node_modules/preact/compat/client.js +0 -19
  90. data/node_modules/preact/compat/client.mjs +0 -17
  91. data/node_modules/preact/compat/dist/compat.js +0 -2
  92. data/node_modules/preact/compat/dist/compat.js.map +0 -1
  93. data/node_modules/preact/compat/dist/compat.mjs +0 -2
  94. data/node_modules/preact/compat/dist/compat.module.js +0 -2
  95. data/node_modules/preact/compat/dist/compat.module.js.map +0 -1
  96. data/node_modules/preact/compat/dist/compat.umd.js +0 -2
  97. data/node_modules/preact/compat/dist/compat.umd.js.map +0 -1
  98. data/node_modules/preact/compat/jsx-dev-runtime.js +0 -3
  99. data/node_modules/preact/compat/jsx-dev-runtime.mjs +0 -3
  100. data/node_modules/preact/compat/jsx-runtime.js +0 -3
  101. data/node_modules/preact/compat/jsx-runtime.mjs +0 -3
  102. data/node_modules/preact/compat/package.json +0 -49
  103. data/node_modules/preact/compat/scheduler.js +0 -15
  104. data/node_modules/preact/compat/scheduler.mjs +0 -23
  105. data/node_modules/preact/compat/server.browser.js +0 -4
  106. data/node_modules/preact/compat/server.js +0 -15
  107. data/node_modules/preact/compat/server.mjs +0 -4
  108. data/node_modules/preact/compat/src/Children.js +0 -21
  109. data/node_modules/preact/compat/src/PureComponent.js +0 -15
  110. data/node_modules/preact/compat/src/forwardRef.js +0 -44
  111. data/node_modules/preact/compat/src/index.d.ts +0 -164
  112. data/node_modules/preact/compat/src/index.js +0 -223
  113. data/node_modules/preact/compat/src/internal.d.ts +0 -47
  114. data/node_modules/preact/compat/src/memo.js +0 -34
  115. data/node_modules/preact/compat/src/portals.js +0 -82
  116. data/node_modules/preact/compat/src/render.js +0 -238
  117. data/node_modules/preact/compat/src/suspense-list.d.ts +0 -14
  118. data/node_modules/preact/compat/src/suspense-list.js +0 -126
  119. data/node_modules/preact/compat/src/suspense.d.ts +0 -15
  120. data/node_modules/preact/compat/src/suspense.js +0 -270
  121. data/node_modules/preact/compat/src/util.js +0 -28
  122. data/node_modules/preact/compat/test-utils.js +0 -1
  123. data/node_modules/preact/debug/LICENSE +0 -21
  124. data/node_modules/preact/debug/dist/debug.js +0 -2
  125. data/node_modules/preact/debug/dist/debug.js.map +0 -1
  126. data/node_modules/preact/debug/dist/debug.mjs +0 -2
  127. data/node_modules/preact/debug/dist/debug.module.js +0 -2
  128. data/node_modules/preact/debug/dist/debug.module.js.map +0 -1
  129. data/node_modules/preact/debug/dist/debug.umd.js +0 -2
  130. data/node_modules/preact/debug/dist/debug.umd.js.map +0 -1
  131. data/node_modules/preact/debug/package.json +0 -26
  132. data/node_modules/preact/debug/src/check-props.js +0 -54
  133. data/node_modules/preact/debug/src/component-stack.js +0 -146
  134. data/node_modules/preact/debug/src/constants.js +0 -3
  135. data/node_modules/preact/debug/src/debug.js +0 -437
  136. data/node_modules/preact/debug/src/index.js +0 -6
  137. data/node_modules/preact/debug/src/internal.d.ts +0 -82
  138. data/node_modules/preact/debug/src/util.js +0 -11
  139. data/node_modules/preact/devtools/LICENSE +0 -21
  140. data/node_modules/preact/devtools/dist/devtools.js +0 -2
  141. data/node_modules/preact/devtools/dist/devtools.js.map +0 -1
  142. data/node_modules/preact/devtools/dist/devtools.mjs +0 -2
  143. data/node_modules/preact/devtools/dist/devtools.module.js +0 -2
  144. data/node_modules/preact/devtools/dist/devtools.module.js.map +0 -1
  145. data/node_modules/preact/devtools/dist/devtools.umd.js +0 -2
  146. data/node_modules/preact/devtools/dist/devtools.umd.js.map +0 -1
  147. data/node_modules/preact/devtools/package.json +0 -25
  148. data/node_modules/preact/devtools/src/devtools.js +0 -10
  149. data/node_modules/preact/devtools/src/index.d.ts +0 -8
  150. data/node_modules/preact/devtools/src/index.js +0 -15
  151. data/node_modules/preact/dist/preact.js +0 -2
  152. data/node_modules/preact/dist/preact.js.map +0 -1
  153. data/node_modules/preact/dist/preact.min.js +0 -2
  154. data/node_modules/preact/dist/preact.min.js.map +0 -1
  155. data/node_modules/preact/dist/preact.mjs +0 -2
  156. data/node_modules/preact/dist/preact.module.js +0 -2
  157. data/node_modules/preact/dist/preact.module.js.map +0 -1
  158. data/node_modules/preact/dist/preact.umd.js +0 -2
  159. data/node_modules/preact/dist/preact.umd.js.map +0 -1
  160. data/node_modules/preact/hooks/LICENSE +0 -21
  161. data/node_modules/preact/hooks/dist/hooks.js +0 -2
  162. data/node_modules/preact/hooks/dist/hooks.js.map +0 -1
  163. data/node_modules/preact/hooks/dist/hooks.mjs +0 -2
  164. data/node_modules/preact/hooks/dist/hooks.module.js +0 -2
  165. data/node_modules/preact/hooks/dist/hooks.module.js.map +0 -1
  166. data/node_modules/preact/hooks/dist/hooks.umd.js +0 -2
  167. data/node_modules/preact/hooks/dist/hooks.umd.js.map +0 -1
  168. data/node_modules/preact/hooks/package.json +0 -35
  169. data/node_modules/preact/hooks/src/index.d.ts +0 -139
  170. data/node_modules/preact/hooks/src/index.js +0 -417
  171. data/node_modules/preact/hooks/src/internal.d.ts +0 -78
  172. data/node_modules/preact/jsx-runtime/LICENSE +0 -21
  173. data/node_modules/preact/jsx-runtime/dist/jsxRuntime.js +0 -2
  174. data/node_modules/preact/jsx-runtime/dist/jsxRuntime.js.map +0 -1
  175. data/node_modules/preact/jsx-runtime/dist/jsxRuntime.mjs +0 -2
  176. data/node_modules/preact/jsx-runtime/dist/jsxRuntime.module.js +0 -2
  177. data/node_modules/preact/jsx-runtime/dist/jsxRuntime.module.js.map +0 -1
  178. data/node_modules/preact/jsx-runtime/dist/jsxRuntime.umd.js +0 -2
  179. data/node_modules/preact/jsx-runtime/dist/jsxRuntime.umd.js.map +0 -1
  180. data/node_modules/preact/jsx-runtime/package.json +0 -28
  181. data/node_modules/preact/jsx-runtime/src/index.d.ts +0 -50
  182. data/node_modules/preact/jsx-runtime/src/index.js +0 -77
  183. data/node_modules/preact/package.json +0 -304
  184. data/node_modules/preact/src/cjs.js +0 -3
  185. data/node_modules/preact/src/clone-element.js +0 -34
  186. data/node_modules/preact/src/component.js +0 -225
  187. data/node_modules/preact/src/constants.js +0 -3
  188. data/node_modules/preact/src/create-context.js +0 -68
  189. data/node_modules/preact/src/create-element.js +0 -98
  190. data/node_modules/preact/src/diff/catch-error.js +0 -40
  191. data/node_modules/preact/src/diff/children.js +0 -335
  192. data/node_modules/preact/src/diff/index.js +0 -533
  193. data/node_modules/preact/src/diff/props.js +0 -158
  194. data/node_modules/preact/src/index.d.ts +0 -317
  195. data/node_modules/preact/src/index.js +0 -13
  196. data/node_modules/preact/src/internal.d.ts +0 -155
  197. data/node_modules/preact/src/jsx.d.ts +0 -1014
  198. data/node_modules/preact/src/options.js +0 -16
  199. data/node_modules/preact/src/render.js +0 -75
  200. data/node_modules/preact/src/util.js +0 -27
  201. data/node_modules/preact/test-utils/dist/testUtils.js +0 -2
  202. data/node_modules/preact/test-utils/dist/testUtils.js.map +0 -1
  203. data/node_modules/preact/test-utils/dist/testUtils.mjs +0 -2
  204. data/node_modules/preact/test-utils/dist/testUtils.module.js +0 -2
  205. data/node_modules/preact/test-utils/dist/testUtils.module.js.map +0 -1
  206. data/node_modules/preact/test-utils/dist/testUtils.umd.js +0 -2
  207. data/node_modules/preact/test-utils/dist/testUtils.umd.js.map +0 -1
  208. data/node_modules/preact/test-utils/package.json +0 -28
  209. data/node_modules/preact/test-utils/src/index.d.ts +0 -3
  210. data/node_modules/preact/test-utils/src/index.js +0 -118
  211. data/node_modules/preact-render-to-string/LICENSE +0 -21
  212. data/node_modules/preact-render-to-string/README.md +0 -102
  213. data/node_modules/preact-render-to-string/dist/commonjs.js +0 -2
  214. data/node_modules/preact-render-to-string/dist/commonjs.js.map +0 -1
  215. data/node_modules/preact-render-to-string/dist/index.d.ts +0 -16
  216. data/node_modules/preact-render-to-string/dist/index.js +0 -1
  217. data/node_modules/preact-render-to-string/dist/index.js.map +0 -1
  218. data/node_modules/preact-render-to-string/dist/index.mjs +0 -2
  219. data/node_modules/preact-render-to-string/dist/index.module.js +0 -2
  220. data/node_modules/preact-render-to-string/dist/index.module.js.map +0 -1
  221. data/node_modules/preact-render-to-string/dist/jsx-entry.js +0 -2
  222. data/node_modules/preact-render-to-string/dist/jsx-entry.js.map +0 -1
  223. data/node_modules/preact-render-to-string/dist/jsx.d.ts +0 -13
  224. data/node_modules/preact-render-to-string/dist/jsx.js +0 -1
  225. data/node_modules/preact-render-to-string/dist/jsx.js.map +0 -1
  226. data/node_modules/preact-render-to-string/dist/jsx.mjs +0 -2
  227. data/node_modules/preact-render-to-string/dist/jsx.modern.js +0 -2
  228. data/node_modules/preact-render-to-string/dist/jsx.modern.js.map +0 -1
  229. data/node_modules/preact-render-to-string/dist/jsx.module.js +0 -2
  230. data/node_modules/preact-render-to-string/dist/jsx.module.js.map +0 -1
  231. data/node_modules/preact-render-to-string/dist/preact-render-to-string-tests.d.ts +0 -1
  232. data/node_modules/preact-render-to-string/jsx.js +0 -1
  233. data/node_modules/preact-render-to-string/package.json +0 -142
  234. data/node_modules/preact-render-to-string/src/index.d.ts +0 -16
  235. data/node_modules/preact-render-to-string/src/index.js +0 -462
  236. data/node_modules/preact-render-to-string/src/jsx.d.ts +0 -13
  237. data/node_modules/preact-render-to-string/src/jsx.js +0 -76
  238. data/node_modules/preact-render-to-string/src/polyfills.js +0 -8
  239. data/node_modules/preact-render-to-string/src/preact-render-to-string-tests.d.ts +0 -1
  240. data/node_modules/preact-render-to-string/src/util.js +0 -78
  241. data/node_modules/preact-render-to-string/typings.json +0 -5
  242. data/node_modules/pretty-format/.npmignore +0 -3
  243. data/node_modules/pretty-format/LICENSE.md +0 -15
  244. data/node_modules/pretty-format/README.md +0 -94
  245. data/node_modules/pretty-format/index.js +0 -343
  246. data/node_modules/pretty-format/package.json +0 -26
  247. data/node_modules/pretty-format/plugins/ReactElement.js +0 -74
  248. data/node_modules/pretty-format/plugins/ReactTestComponent.js +0 -58
  249. data/node_modules/pretty-format/printString.js +0 -7
  250. data/node_modules/wouter-preact/cjs/index.js +0 -180
  251. data/node_modules/wouter-preact/cjs/matcher.js +0 -72
  252. data/node_modules/wouter-preact/cjs/package.json +0 -1
  253. data/node_modules/wouter-preact/cjs/react-deps.js +0 -75
  254. data/node_modules/wouter-preact/cjs/static-location.js +0 -21
  255. data/node_modules/wouter-preact/cjs/use-location.js +0 -94
  256. data/node_modules/wouter-preact/index.d.ts +0 -110
  257. data/node_modules/wouter-preact/index.js +0 -178
  258. data/node_modules/wouter-preact/matcher.d.ts +0 -30
  259. data/node_modules/wouter-preact/matcher.js +0 -66
  260. data/node_modules/wouter-preact/package.json +0 -33
  261. data/node_modules/wouter-preact/react-deps.js +0 -15
  262. data/node_modules/wouter-preact/static-location.d.ts +0 -16
  263. data/node_modules/wouter-preact/static-location.js +0 -17
  264. data/node_modules/wouter-preact/use-location.d.ts +0 -43
  265. data/node_modules/wouter-preact/use-location.js +0 -86
  266. data/package.json +0 -8
@@ -0,0 +1,58 @@
1
+ module Browser
2
+ module Window
3
+ extend DelegateNative
4
+ extend EventTarget
5
+
6
+ @native = `window`
7
+
8
+ module_function
9
+
10
+ if `#@native.requestAnimationFrame !== undefined`
11
+ # Add the given block to the current iteration of the event loop. If this
12
+ # is called from another `animation_frame` call, the block is run in the
13
+ # following iteration of the event loop.
14
+ def animation_frame &block
15
+ `requestAnimationFrame(function(now) { #{block.call `now`} })`
16
+ self
17
+ end
18
+ else
19
+ def animation_frame &block
20
+ after(0, &block)
21
+ self
22
+ end
23
+ end
24
+
25
+ # Run the given block every `duration` seconds
26
+ #
27
+ # @param duration [Numeric] the number of seconds between runs
28
+ def set_interval duration, &block
29
+ `setInterval(function() { #{block.call} }, duration)`
30
+ end
31
+
32
+ def set_timeout duration, &block
33
+ `setTimeout(function() { #{block.call} }, duration)`
34
+ end
35
+
36
+ # return [History] the browser's History object
37
+ def history
38
+ Browser::History.new(`window.history`)
39
+ end
40
+
41
+ # @return [Location] the browser's Location object
42
+ def location
43
+ Browser::Location.new(`window.location`)
44
+ end
45
+
46
+ # Scroll to the specified (x,y) coordinates
47
+ def scroll x, y
48
+ `window.scrollTo(x, y)`
49
+ end
50
+ end
51
+
52
+ module_function
53
+
54
+ # return [Window] the browser's Window object
55
+ def window
56
+ Window
57
+ end
58
+ end
@@ -0,0 +1,18 @@
1
+ module URI
2
+ class Data
3
+ def open
4
+ io = StringIO.new(data)
5
+ OpenURI::Meta.init(io)
6
+ io.meta_add_field('content-type', content_type)
7
+ if block_given?
8
+ begin
9
+ yield io
10
+ ensure
11
+ io.close
12
+ end
13
+ else
14
+ io
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,61 @@
1
+ module URI
2
+ class Data < Generic
3
+ COMPONENT = [:scheme, :opaque]
4
+ MIME_TYPE_RE = %r{^([-\w.+]+/[-\w.+]*)}
5
+ MIME_PARAM_RE = /^;([-\w.+]+)=([^;,]+)/
6
+
7
+ attr_reader :content_type, :data
8
+
9
+ def initialize(*args)
10
+ if args.length == 1
11
+ uri = args.first.to_s
12
+ unless uri.match(/^data:/)
13
+ raise URI::InvalidURIError.new('Invalid Data URI: ' + args.first.inspect)
14
+ end
15
+ @scheme = 'data'
16
+ @opaque = uri[5 .. -1]
17
+ else
18
+ super(*args)
19
+ end
20
+ @data = @opaque
21
+ if md = MIME_TYPE_RE.match(@data)
22
+ @content_type = md[1]
23
+ @data = @data[@content_type.length .. -1]
24
+ end
25
+ @content_type ||= 'text/plain'
26
+ @mime_params = {}
27
+ while md = MIME_PARAM_RE.match(@data)
28
+ @mime_params[md[1]] = md[2]
29
+ @data = @data[md[0].length .. -1]
30
+ end
31
+ if base64 = /^;base64/.match(@data)
32
+ @data = @data[7 .. -1]
33
+ end
34
+ unless /^,/.match(@data)
35
+ raise URI::InvalidURIError.new('Invalid data URI')
36
+ end
37
+ @data = @data[1 .. -1]
38
+ @data = base64 ? Base64.decode64(@data) : URI.decode(@data)
39
+ if @data.respond_to?(:force_encoding) && charset = @mime_params['charset']
40
+ @data.force_encoding(charset)
41
+ end
42
+ end
43
+
44
+ def self.build(arg)
45
+ data = nil
46
+ content_type = nil
47
+ case arg
48
+ when IO
49
+ data = arg
50
+ when Hash
51
+ data = arg[:data]
52
+ content_type = arg[:content_type]
53
+ end
54
+ raise 'Invalid build argument: ' + arg.inspect unless data
55
+ if !content_type && data.respond_to?(:content_type)
56
+ content_type = data.content_type
57
+ end
58
+ new('data', nil, nil, nil, nil, nil, "#{content_type};base64,#{Base64.encode64(data.read).chop}", nil, nil)
59
+ end
60
+ end
61
+ end
data/lib/data_uri.rb ADDED
@@ -0,0 +1,4 @@
1
+ require 'uri'
2
+ require 'base64'
3
+ require 'stringio'
4
+ require 'data_uri/uri'
@@ -2,13 +2,13 @@ module Isomorfeus
2
2
  if RUBY_ENGINE == 'opal'
3
3
  class << self
4
4
  attr_accessor :browser_history
5
- attr_accessor :current_user_sid
5
+ attr_accessor :browser_location
6
+ attr_accessor :current_user_sid_s
6
7
  attr_accessor :initial_state_fetched
7
- attr_accessor :top_component
8
8
  attr_accessor :ssr_response_status
9
+ attr_accessor :top_component
9
10
  attr_reader :initialized
10
11
  attr_reader :env
11
- attr_accessor :zeitwerk
12
12
 
13
13
  def init
14
14
  return if initialized
@@ -23,74 +23,63 @@ module Isomorfeus
23
23
  execute_init_classes
24
24
  end
25
25
 
26
- def add_client_init_class_name(init_class_name)
27
- client_init_class_names << init_class_name
28
- end
29
-
30
- def add_client_init_after_store_class_name(init_class_name)
31
- client_init_after_store_class_names << init_class_name
26
+ def start_app!
27
+ Isomorfeus.zeitwerk.setup
28
+ Isomorfeus::TopLevel.mount!
32
29
  end
33
30
 
34
- def add_client_option(key, value = nil)
35
- self.class.attr_accessor(key)
36
- self.send("#{key}=", value)
31
+ def force_render
32
+ root_element = `document.querySelector('div[data-iso-root]')`
33
+ Preact.unmount_component_at_node(root_element)
34
+ Isomorfeus::TopLevel.do_the_mount!(init: false)
35
+ nil
36
+ rescue Exception => e
37
+ `console.error("force_render failed'! Error: " + #{e.message} + "! Reloading page.")`
38
+ `location.reload()`
37
39
  end
40
+ end
41
+ else # RUBY_ENGINE
42
+ class << self
43
+ attr_reader :component_cache_init_block
44
+ attr_accessor :server_side_rendering
45
+ attr_accessor :ssr_hot_asset_url
38
46
 
39
- def execute_init_classes
40
- client_init_class_names.each do |constant|
41
- constant.constantize.send(:init)
42
- end
47
+ def ssr_response_status
48
+ Thread.current[:@_isomorfeus_preact_ssr_response_status]
43
49
  end
44
50
 
45
- def execute_init_after_store_classes
46
- client_init_after_store_class_names.each do |constant_name|
47
- constant_name.constantize.send(:init)
48
- end
51
+ def ssr_response_status=(s)
52
+ Thread.current[:@_isomorfeus_preact_ssr_response_status] = s
49
53
  end
50
54
 
51
- # server side env is set in isomorfeus-asset-manager
52
- def env=(env_string)
53
- @env = env_string ? env_string : 'development'
54
- @development = (@env == 'development') ? true : false
55
- @production = (@env == 'production') ? true : false
56
- @test = (@env == 'test') ? true : false
55
+ def init
56
+ return if Thread.current[:@_isomorfeus_initialized]
57
+ Thread.current[:@_isomorfeus_initialized] = true
58
+ Isomorfeus.init_store
59
+ execute_init_classes
57
60
  end
58
61
 
59
- def development?
60
- @development
62
+ def force_init!
63
+ Thread.current[:@_isomorfeus_initialized] = true
64
+ Isomorfeus.force_init_store!
65
+ execute_init_classes
61
66
  end
62
67
 
63
- def production?
64
- @production
68
+ def browser_history
69
+ @_isomorfeus_browser_history
65
70
  end
66
71
 
67
- def test?
68
- @test
72
+ def browser_history=(h)
73
+ @_isomorfeus_browser_history = h
69
74
  end
70
75
 
71
- def start_app!
72
- Isomorfeus.zeitwerk.setup
73
- Isomorfeus::TopLevel.mount! unless on_ssr?
76
+ def browser_location
77
+ Thread.current[:@_isomorfeus_browser_location]
74
78
  end
75
79
 
76
- def force_render
77
- `Opal.Preact.deep_force_update(#{Isomorfeus.top_component})`
78
- nil
79
- rescue Exception => e
80
- `console.error("force_render failed'! Error: " + #{e.message} + "! Reloading page.")`
81
- `location.reload()` if on_browser?
80
+ def browser_location=(l)
81
+ Thread.current[:@_isomorfeus_browser_location] = l
82
82
  end
83
- end
84
-
85
- self.add_client_option(:client_init_class_names, [])
86
- self.add_client_option(:client_init_after_store_class_names, [])
87
- else
88
- class << self
89
- attr_reader :component_cache_init_block
90
- attr_accessor :server_side_rendering
91
- attr_accessor :ssr_hot_asset_url
92
- attr_accessor :zeitwerk
93
- attr_accessor :zeitwerk_lock
94
83
 
95
84
  def component_cache_init(&block)
96
85
  @component_cache_init_block = block
@@ -114,7 +103,7 @@ module Isomorfeus
114
103
  end
115
104
  end
116
105
  end
117
- end
106
+ end # RUBY_ENGINE
118
107
 
119
108
  class << self
120
109
  def raise_error(error: nil, error_class: nil, message: nil, stack: nil)
@@ -122,7 +111,6 @@ module Isomorfeus
122
111
 
123
112
  error_class = RuntimeError unless error_class
124
113
  execution_environment = if on_browser? then 'on Browser'
125
- elsif on_ssr? then 'in Server Side Rendering'
126
114
  elsif on_server? then 'on Server'
127
115
  else
128
116
  'on Client'
@@ -1,24 +1,9 @@
1
1
  module Isomorfeus
2
- module Preact
3
- module Imports
4
- def self.add
5
- Isomorfeus.add_web_js_import('preact/debug') if Isomorfeus.development?
6
- Isomorfeus.add_common_js_import('preact', 'Preact', '*')
7
- Isomorfeus.add_common_js_import('preact/hooks', 'PreactHooks', '*')
8
- Isomorfeus.add_common_js_import('wouter-preact', nil, ['Router', 'Link', 'Redirect', 'Route', 'Switch'])
9
-
10
- Isomorfeus.add_ssr_js_import('preact-render-to-string', 'Preact', ['render'], nil, 'renderToString')
11
- Isomorfeus.add_ssr_js_import('wouter-preact/static-location', 'staticLocationHook')
12
-
13
- Isomorfeus.add_web_js_import('wouter-preact/use-location', 'locationHook')
14
-
15
- if Dir.exist?(Isomorfeus.app_root)
16
- if File.exist?(File.join(Isomorfeus.app_root, 'isomorfeus_loader.rb'))
17
- Isomorfeus.add_common_ruby_import('isomorfeus_loader')
18
- Isomorfeus.add_ssr_ruby_import('isomorfeus/preact/ssr/top_level')
19
- Isomorfeus.add_ssr_ruby_import('isomorfeus/preact/ssr/render_core')
20
- Isomorfeus.add_ssr_ruby_import('isomorfeus/preact/ssr/history')
21
- end
2
+ module PreactImports
3
+ def self.add
4
+ if Dir.exist?(Isomorfeus.app_root)
5
+ if File.exist?(File.join(Isomorfeus.app_root, 'isomorfeus_loader.rb'))
6
+ Isomorfeus.add_web_ruby_import('isomorfeus_loader')
22
7
  end
23
8
  end
24
9
  end
@@ -0,0 +1,34 @@
1
+ module Isomorfeus
2
+ class PreactSSR
3
+ def self.mount_component(component_name, props, session_id, location, locale = nil)
4
+ rendered_tree = new(component_name, props, session_id, location, locale).render
5
+ [rendered_tree, Isomorfeus.store.get_state, NanoCSS.instance.renderer[:raw]]
6
+ end
7
+
8
+ def initialize(component_name, props, session_id, location, locale = nil)
9
+ @session_id = session_id
10
+ @component_name = component_name
11
+ @props = props
12
+ @location = location
13
+ @locale = locale
14
+ end
15
+
16
+ def render
17
+ Isomorfeus.browser_location = Browser::Location.new(@location)
18
+ Isomorfeus.current_locale = @locale
19
+ NanoCSS.instance = NanoCSS.new(given_renderer: NanoCSS.global_instance.renderer.deep_dup)
20
+ Isomorfeus.init_store
21
+ Isomorfeus.store.clear!
22
+ c = Isomorfeus.current_user
23
+ if c.respond_to?(:reload)
24
+ Thread.current[:isomorfeus_user] = LocalSystem.new
25
+ begin
26
+ c.reload
27
+ ensure
28
+ Thread.current[:isomorfeus_user] = c
29
+ end
30
+ end
31
+ Isomorfeus::TopLevel.render_component_to_string(@component_name, @props)
32
+ end
33
+ end
34
+ end
@@ -1,17 +1,15 @@
1
1
  module Isomorfeus
2
- module Preact
3
- class ThreadLocalComponentCache
4
- def initialize
5
- Thread.current[:local_cache] = {} unless Thread.current.key?(:local_cache)
6
- end
2
+ class ThreadLocalComponentCache
3
+ def initialize
4
+ Thread.current[:local_cache] = {} unless Thread.current.key?(:local_cache)
5
+ end
7
6
 
8
- def fetch(key)
9
- Thread.current[:local_cache][key]
10
- end
7
+ def fetch(key)
8
+ Thread.current[:local_cache][key]
9
+ end
11
10
 
12
- def store(key, rendered_tree, response_status, styles)
13
- Thread.current[:local_cache][key] = [rendered_tree, response_status, styles]
14
- end
11
+ def store(key, rendered_tree, response_status, styles)
12
+ Thread.current[:local_cache][key] = [rendered_tree, response_status, styles]
15
13
  end
16
14
  end
17
15
  end
@@ -0,0 +1,5 @@
1
+ module Isomorfeus
2
+ module Preact
3
+ VERSION = '22.9.0.rc2'
4
+ end
5
+ end
@@ -0,0 +1,72 @@
1
+ module Preact
2
+ module ViewHelper
3
+ def self.included(base)
4
+ base.include Isomorfeus::AssetManager::ViewHelper
5
+ end
6
+
7
+ def cached_mount_component(component_name, props = {}, skip_ssr: false, use_ssr: false, refresh: false)
8
+ key = "#{Isomorfeus.current_user}#{component_name}#{props}"
9
+ if !Isomorfeus.development? && !refresh
10
+ render_result, @_ssr_styles, status = component_cache.fetch(key)
11
+ Isomorfeus.ssr_response_status = status
12
+ return render_result if render_result
13
+ end
14
+ render_result = mount_component(component_name, props, asset_key, skip_ssr: skip_ssr, use_ssr: use_ssr)
15
+ status = ssr_response_status
16
+ component_cache.store(key, render_result, ssr_styles, status) if status >= 200 && status < 300
17
+ render_result
18
+ end
19
+
20
+ def mount_component(component_name, props = {}, skip_ssr: false, use_ssr: false)
21
+ ssr_start_time = Time.now if Isomorfeus.development?
22
+ @ssr_styles = nil
23
+ render_result = "<div data-iso-env=\"#{Isomorfeus.env}\" data-iso-root=\"#{component_name}\" data-iso-props='#{Oj.dump(props, mode: :strict)}'"
24
+ if !skip_ssr && (Isomorfeus.server_side_rendering || use_ssr)
25
+ location_host = props[:location_host] ? props[:location_host] : 'localhost'
26
+ location = "#{props[:location_scheme] || 'http:'}//#{location_host}#{props[:location]}"
27
+
28
+ rendered_tree, application_state, @_ssr_styles = Isomorfeus::PreactSSR.mount_component(component_name, props, Thread.current[:isomorfeus_session_id], location, props[:locale])
29
+
30
+ render_result << " data-iso-hydrated='true'" if rendered_tree
31
+ if Isomorfeus.respond_to?(:current_user) && Isomorfeus.current_user && !Isomorfeus.current_user.anonymous?
32
+ render_result << " data-iso-usids=#{Oj.dump(Isomorfeus.current_user.sid.to_s, mode: :strict)}"
33
+ end
34
+ render_result << " data-iso-nloc='#{props[:locale]}'>"
35
+ render_result << (rendered_tree ? rendered_tree : "SSR didn't work")
36
+ else
37
+ if Isomorfeus.respond_to?(:current_user) && Isomorfeus.current_user && !Isomorfeus.current_user.anonymous?
38
+ render_result << " data-iso-usids=#{Oj.dump(Isomorfeus.current_user.sid.to_s, mode: :strict)}"
39
+ end
40
+ render_result << " data-iso-nloc='#{props[:locale]}'>"
41
+ end
42
+ render_result << '</div>'
43
+ if Isomorfeus.server_side_rendering && !skip_ssr
44
+ render_result = "<script type='application/javascript'>\nServerSideRenderingStateJSON = #{Oj.dump(application_state, mode: :strict)}\n</script>\n" << render_result
45
+ puts "Preact::ViewHelper Server Side Rendering took ~#{((Time.now - ssr_start_time)*1000).to_i}ms" if Isomorfeus.development?
46
+ end
47
+ render_result
48
+ end
49
+
50
+ def ssr_response_status
51
+ Isomorfeus.ssr_response_status
52
+ end
53
+
54
+ def ssr_styles
55
+ @_ssr_styles || ''
56
+ end
57
+
58
+ private
59
+
60
+ def component_cache
61
+ @_component_cache ||= Isomorfeus.component_cache_init_block.call
62
+ end
63
+
64
+ def ssr_mod
65
+ @_ssr_mod ||= Opal.compile(File.read(File.expand_path(File.join(File.dirname(__FILE__), 'ssr.rb'))), { use_strict: true })
66
+ end
67
+
68
+ def top_level_mod
69
+ @_top_level_mod ||= Opal.compile(File.read(File.expand_path(File.join(File.dirname(__FILE__), 'top_level_ssr.rb'))), { use_strict: true })
70
+ end
71
+ end
72
+ end
@@ -36,16 +36,24 @@ module Isomorfeus
36
36
  def cast!
37
37
  if @o.key?(:cast)
38
38
  begin
39
- @v = case @o[:class]
40
- when Integer then @v.to_i
41
- when String then @v.to_s
42
- when Float then @v.to_f
43
- when Array then @v.to_a
44
- when Hash then @v.to_h
39
+ return if @o[:is_a] && @v.is_a?(@o[:is_a])
40
+ return if @o[:class] && @v.class == @o[:class]
41
+ if @o[:type] == :boolean
42
+ @v = !!@v
43
+ return
44
+ end
45
+ cl = @o[:is_a] || @o[:class]
46
+ @v = case cl.name
47
+ when 'Integer' then @v.to_i
48
+ when 'String' then @v.to_s
49
+ when 'Float' then @v.to_f
50
+ when 'Array' then @v.to_a
51
+ when 'Hash' then @v.to_h
52
+ else
53
+ Isomorfeus.raise_error(message: "#{@c}: Dont know how to cast #{@p} to #{cl}!")
45
54
  end
46
- @v = !!@v if @o[:type] == :boolean
47
55
  rescue
48
- Isomorfeus.raise_error(message: "#{@c}: #{@p} cast failed") unless @v.class == @o[:class]
56
+ Isomorfeus.raise_error(message: "#{@c}: #{@p} cast to #{cl} failed!")
49
57
  end
50
58
  end
51
59
  end
@@ -105,7 +113,7 @@ module Isomorfeus
105
113
  end
106
114
 
107
115
  def c_size(v)
108
- Isomorfeus.raise_error(message: "#{@c}: #{@p} length/size is not #{v}") unless @v.size == v
116
+ Isomorfeus.raise_error(message: "#{@c}: #{@p} length/size is not #{v}") unless @v.length == v
109
117
  end
110
118
 
111
119
  def c_matches(v)
@@ -121,11 +129,11 @@ module Isomorfeus
121
129
  end
122
130
 
123
131
  def c_max_size(v)
124
- Isomorfeus.raise_error(message: "#{@c}: #{@p} is larger than #{v}") unless @v.size <= v
132
+ Isomorfeus.raise_error(message: "#{@c}: #{@p} is larger than #{v}") unless @v.length <= v
125
133
  end
126
134
 
127
135
  def c_min_size(v)
128
- Isomorfeus.raise_error(message: "#{@c}: #{@p} is smaller than #{v}") unless @v.size >= v
136
+ Isomorfeus.raise_error(message: "#{@c}: #{@p} is smaller than #{v}") unless @v.length >= v
129
137
  end
130
138
 
131
139
  def c_direction(v)
@@ -4,20 +4,19 @@ module Isomorfeus
4
4
  attr_accessor :hydrated
5
5
  attr_accessor :first_pass
6
6
 
7
- if on_browser?
8
- def mount!
9
- Isomorfeus.init
10
- Isomorfeus::TopLevel.on_ready do
11
- root_element = `document.querySelector('div[data-iso-root]')`
12
- Isomorfeus.raise_error(message: "Isomorfeus root element not found!") unless root_element
13
- component_name = root_element.JS.getAttribute('data-iso-root')
14
- Isomorfeus.env = root_element.JS.getAttribute('data-iso-env')
15
- user_sid = root_element.JS.getAttribute('data-iso-usid')
16
- Isomorfeus.current_user_sid =`JSON.parse(user_sid)` if user_sid
17
- component = nil
18
- begin
19
- component = component_name.constantize
20
- rescue Exception => e
7
+ if RUBY_ENGINE == 'opal'
8
+ def do_the_mount!(init: true)
9
+ NanoCSS.instance = NanoCSS.new({ sh: `document.getElementById('css-server-side')` })
10
+ root_element = `document.querySelector('div[data-iso-root]')`
11
+ Isomorfeus.raise_error(message: "Isomorfeus root element not found!") unless root_element
12
+ component_name = root_element.JS.getAttribute('data-iso-root')
13
+ Isomorfeus.env = root_element.JS.getAttribute('data-iso-env')
14
+ Isomorfeus.current_user_sid_s = root_element.JS.getAttribute('data-iso-usids')
15
+ component = nil
16
+ begin
17
+ component = component_name.constantize
18
+ rescue Exception => e
19
+ if init
21
20
  `console.warn("Deferring mount: " + #{e.message})`
22
21
  @timeout_start = Time.now unless @timeout_start
23
22
  if (Time.now - @timeout_start) < 10
@@ -25,33 +24,39 @@ module Isomorfeus
25
24
  else
26
25
  `console.error("Unable to mount '" + #{component_name} + "'!")`
27
26
  end
27
+ else
28
+ raise e
28
29
  end
29
- if component
30
- props_json = root_element.JS.getAttribute('data-iso-props')
31
- props = `Opal.Hash.$new(JSON.parse(props_json))`
30
+ end
31
+ if component
32
+ props_json = root_element.JS.getAttribute('data-iso-props')
33
+ props = JSON.parse(props_json)
34
+ if init
32
35
  raw_hydrated = root_element.JS.getAttribute('data-iso-hydrated')
33
- self.hydrated = (raw_hydrated && raw_hydrated == "true")
36
+ Isomorfeus::TopLevel.hydrated = (raw_hydrated && raw_hydrated == "true")
34
37
  %x{
35
38
  if (global.ServerSideRenderingStateJSON) {
36
39
  var state = global.ServerSideRenderingStateJSON;
37
40
  var keys = Object.keys(state);
38
41
  for(var i=0; i < keys.length; i++) {
39
42
  if (Object.keys(state[keys[i]]).length > 0) {
40
- global.Opal.Isomorfeus.store.native.dispatch({ type: keys[i].toUpperCase(), set_state: state[keys[i]] });
43
+ #{Isomorfeus.store.dispatch({ type: `keys[i].toUpperCase()`, set_state: Hash.new(`state[keys[i]]`) })}
41
44
  }
42
45
  }
43
46
  }
44
47
  }
45
48
  Isomorfeus.execute_init_after_store_classes
46
- begin
47
- self.first_pass = true
48
- result = Isomorfeus::TopLevel.mount_component(component, props, root_element, self.hydrated)
49
- self.first_pass = false
50
- @tried_another_time = false
51
- result
52
- rescue Exception => e
53
- self.first_pass = false
54
- if !@tried_another_time
49
+ end
50
+ begin
51
+ Isomorfeus::TopLevel.first_pass = true
52
+ result = Isomorfeus::TopLevel.mount_component(component, props, root_element, Isomorfeus::TopLevel.hydrated)
53
+ Isomorfeus::TopLevel.first_pass = false
54
+ @tried_another_time = false
55
+ result
56
+ rescue Exception => e
57
+ if init
58
+ Isomorfeus::TopLevel.first_pass = false
59
+ if !@tried_another_time
55
60
  @tried_another_time = true
56
61
  `console.warn("Deferring mount: " + #{e.message})`
57
62
  `console.error(#{e.backtrace.join("\n")})`
@@ -60,11 +65,20 @@ module Isomorfeus
60
65
  `console.error("Unable to mount '" + #{component_name} + "'! Error: " + #{e.message} + "!")`
61
66
  `console.error(#{e.backtrace.join("\n")})`
62
67
  end
68
+ else
69
+ raise e
63
70
  end
64
71
  end
65
72
  end
66
73
  end
67
74
 
75
+ def mount!
76
+ Isomorfeus.init
77
+ Isomorfeus::TopLevel.on_ready do
78
+ Isomorfeus::TopLevel.do_the_mount!
79
+ end
80
+ end
81
+
68
82
  def on_ready(&block)
69
83
  %x{
70
84
  function run() { block.$call() };
@@ -88,18 +102,26 @@ module Isomorfeus
88
102
  end
89
103
 
90
104
  def mount_component(component, props, element_or_query, hydrated = false)
91
- if `(typeof element_or_query === 'string')` || (`(typeof element_or_query.$class === 'function')` && element_or_query.class == String)
105
+ if `(element_or_query instanceof HTMLElement)`
106
+ element = element_or_query
107
+ elsif `(typeof element_or_query === 'string')` || element_or_query.is_a?(String)
92
108
  element = `document.body.querySelector(element_or_query)`
93
- elsif `(typeof element_or_query.$is_a === 'function')` && element_or_query.is_a?(Browser::Element)
109
+ elsif element_or_query.is_a?(Browser::Element)
94
110
  element = element_or_query.to_n
95
111
  else
96
112
  element = element_or_query
97
113
  end
98
-
99
- top = Preact.create_element(component, props)
100
- hydrated ? Preact.hydrate(top, element) : Preact.render(top, element)
114
+ raise "Element is required!" unless element
115
+ top = ::Preact.create_element(component, props)
116
+ hydrated ? ::Preact.hydrate(top, element) : ::Preact.render(top, element)
101
117
  Isomorfeus.top_component = top
102
118
  end
119
+ else
120
+ def render_component_to_string(component_name, props)
121
+ component = component_name.is_a?(String) ? const_get(component_name) : component_name
122
+ ::Preact._vnode_id = 0
123
+ ::Preact.render_to_string(::Preact.create_element(component, props))
124
+ end
103
125
  end
104
126
  end
105
127
  end