funicular 0.3.0 → 0.4.0

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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +57 -0
  3. data/demo/test_chartjs.html +9 -9
  4. data/demo/test_component.html +8 -8
  5. data/demo/test_error_boundary.html +44 -41
  6. data/demo/test_router.html +48 -48
  7. data/demo/tic-tac-toe.html +25 -25
  8. data/docs/architecture.md +46 -9
  9. data/lib/funicular/ssr/runtime.rb +1 -0
  10. data/lib/funicular/vendor/mrbc/VERSION +1 -1
  11. data/lib/funicular/vendor/mrbc/mrbc.js +613 -486
  12. data/lib/funicular/vendor/mrbc/mrbc.wasm +0 -0
  13. data/lib/funicular/vendor/picoruby/VERSION +1 -1
  14. data/lib/funicular/vendor/picoruby/debug/picoruby.js +669 -449
  15. data/lib/funicular/vendor/picoruby/debug/picoruby.wasm +0 -0
  16. data/lib/funicular/vendor/picoruby/dist/picoruby.js +2 -2
  17. data/lib/funicular/vendor/picoruby/dist/picoruby.wasm +0 -0
  18. data/lib/funicular/vendor/picoruby-test-node/VERSION +1 -1
  19. data/lib/funicular/vendor/picoruby-test-node/picoruby.js +921 -629
  20. data/lib/funicular/vendor/picoruby-test-node/picoruby.wasm +0 -0
  21. data/lib/funicular/vendor/picoruby-test-node/picoruby.wasm.map +1 -1
  22. data/lib/funicular/version.rb +1 -1
  23. data/lib/generators/funicular/chat/templates/funicular_chat_component.rb.tt +37 -38
  24. data/minitest/dsl_test.rb +237 -0
  25. data/minitest/fixtures/funicular_app/components/greeting_component.rb +5 -5
  26. data/minitest/form_for_test.rb +2 -2
  27. data/minitest/hydration_test.rb +2 -2
  28. data/minitest/sig_tags_test.rb +30 -0
  29. data/minitest/view_context_test.rb +15 -15
  30. data/mrblib/0_tags.rb +62 -0
  31. data/mrblib/component.rb +113 -23
  32. data/mrblib/error_boundary.rb +25 -19
  33. data/mrblib/form_builder.rb +10 -10
  34. data/mrblib/funicular.rb +1 -1
  35. data/mrblib/styles.rb +102 -12
  36. data/mrblib/view_context.rb +3 -32
  37. data/sig/component.rbs +18 -4
  38. data/sig/error_boundary.rbs +4 -4
  39. data/sig/styles.rbs +18 -5
  40. data/sig/tags.rbs +54 -0
  41. data/sig/view_context.rbs +47 -34
  42. metadata +5 -1
data/sig/styles.rbs CHANGED
@@ -7,18 +7,31 @@ module Funicular
7
7
  def to_s: () -> String
8
8
  end
9
9
 
10
- # StyleAccessor provides explicit access to defined styles.
11
- class StyleAccessor
10
+ # Read-side accessor. A subclass is generated per component class with a
11
+ # real method per declared style name; those methods are app-defined and
12
+ # therefore untyped (use the [] form where static checking matters).
13
+ class StyleAccessor < BasicObject
14
+ @definitions: Hash[Symbol, Hash[Symbol, untyped]]
15
+
16
+ def self.accessor_for: (Hash[Symbol, Hash[Symbol, untyped]] definitions) -> singleton(StyleAccessor)
12
17
  def initialize: (Hash[Symbol, Hash[Symbol, untyped]] definitions) -> void
13
18
  def []: (Symbol name, ?(Symbol | bool) variant) -> StyleValue
19
+ def method_missing: (Symbol name, *untyped args) -> bot
20
+ def respond_to_missing?: (Symbol name, ?bool include_private) -> bool
14
21
  end
15
22
 
16
- # StyleBuilder is used to define styles within the styles {} block
17
- class StyleBuilder
23
+ # Definition-side cleanroom builder for the class-level styles block.
24
+ # Barewords resolve through method_missing and define styles.
25
+ class StyleBuilder < BasicObject
26
+ RESERVED_NAMES: Array[Symbol]
27
+
18
28
  @definitions: Hash[Symbol, Hash[Symbol, untyped]]
19
29
 
20
30
  def initialize: () -> void
21
- def define: (Symbol name, ?(String | Hash[Symbol, untyped]) value, **untyped options) -> void
31
+ def define: (Symbol name, ?(String | Hash[Symbol, untyped])? value, **untyped options) -> self
32
+ def validate_options: (Symbol name, Hash[Symbol, untyped] options) -> Hash[Symbol, untyped]
22
33
  def to_definitions: () -> Hash[Symbol, Hash[Symbol, untyped]]
34
+ def method_missing: (Symbol name, ?untyped value, **untyped options) -> self
35
+ def respond_to_missing?: (Symbol name, ?bool include_private) -> bool
23
36
  end
24
37
  end
data/sig/tags.rbs ADDED
@@ -0,0 +1,54 @@
1
+ module Funicular
2
+ class DSLCollisionError < StandardError
3
+ end
4
+
5
+ class RenderContextError < StandardError
6
+ end
7
+
8
+ module Tags
9
+ HTML_TAGS: Array[String]
10
+ HELPER_NAMES: Array[String]
11
+ RESERVED_DSL: Hash[Symbol, Symbol]
12
+
13
+ def tag: (Symbol | String name, ?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
14
+ def div: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
15
+ def span: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
16
+ def p: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
17
+ def a: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
18
+ def data: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
19
+ def h1: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
20
+ def h2: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
21
+ def h3: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
22
+ def h4: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
23
+ def h5: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
24
+ def h6: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
25
+ def ul: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
26
+ def ol: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
27
+ def li: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
28
+ def table: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
29
+ def thead: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
30
+ def tbody: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
31
+ def tr: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
32
+ def th: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
33
+ def td: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
34
+ def form: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
35
+ def input: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
36
+ def textarea: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
37
+ def button: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
38
+ def select: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
39
+ def option: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
40
+ def label: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
41
+ def header: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
42
+ def footer: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
43
+ def nav: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
44
+ def section: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
45
+ def article: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
46
+ def aside: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
47
+ def img: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
48
+ def video: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
49
+ def audio: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
50
+ def canvas: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
51
+ def br: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
52
+ def hr: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
53
+ end
54
+ end
data/sig/view_context.rbs CHANGED
@@ -1,47 +1,60 @@
1
1
  module Funicular
2
+ # Internal element factory. Application code uses the bareword tag DSL
3
+ # on Component (see sig/tags.rbs); ViewContext is what FormBuilder, the
4
+ # framework helpers, and ErrorBoundary fallback procs build through.
2
5
  class ViewContext
3
6
  HTML_TAGS: Array[String]
4
7
 
5
8
  def initialize: (Component component) -> void
6
- def state: () -> Component::StateAccessor
7
- def props: () -> Hash[Symbol, untyped]
8
- def resources: () -> Component::ResourceAccessor
9
- def styles: () -> StyleAccessor
10
- def routes: () -> untyped
11
- def tag: (Symbol | String name, ?Hash[Symbol, untyped] props) ?{ (ViewContext) -> untyped } -> VDOM::Element
12
- def component: (singleton(Component) component_class, ?Hash[Symbol, untyped] props) ?{ (ViewContext) -> untyped } -> VDOM::Component
9
+ def tag: (Symbol | String name, ?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
10
+ def component: (singleton(Component) component_class, ?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Component
13
11
  def form_for: (Symbol model_key, ?Hash[Symbol, untyped] options) { (FormBuilder) -> void } -> VDOM::Element
14
- def suspense: (Symbol name, fallback: untyped, ?error: untyped) { (ViewContext, Component::ResourceAccessor) -> untyped } -> untyped
12
+ def suspense: (Symbol name, fallback: untyped, ?error: untyped) { (Component::ResourceAccessor) -> untyped } -> untyped
15
13
  def link_to: (String path, **untyped options) ?{ -> untyped } -> VDOM::Element
16
14
  def button_to: (String path, ?method: Symbol, **untyped options) ?{ -> untyped } -> VDOM::Element
17
- def capture: () { (ViewContext) -> untyped } -> Array[VDOM::child_t]
15
+ def capture: () { () -> untyped } -> Array[VDOM::child_t]
18
16
  def add_child: (untyped child) -> void
19
- private def build_element: (Symbol | String tag_name, ?Hash[Symbol, untyped] props) ?{ (ViewContext) -> untyped } -> VDOM::Element
17
+ private def build_element: (Symbol | String tag_name, ?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
20
18
  private def normalize_props: (Hash[Symbol, untyped] props) -> Hash[Symbol, untyped]
21
19
 
22
- def div: (?Hash[Symbol, untyped] props) ?{ (ViewContext) -> untyped } -> VDOM::Element
23
- def span: (?Hash[Symbol, untyped] props) ?{ (ViewContext) -> untyped } -> VDOM::Element
24
- def p: (?Hash[Symbol, untyped] props) ?{ (ViewContext) -> untyped } -> VDOM::Element
25
- def a: (?Hash[Symbol, untyped] props) ?{ (ViewContext) -> untyped } -> VDOM::Element
26
- def data: (?Hash[Symbol, untyped] props) ?{ (ViewContext) -> untyped } -> VDOM::Element
27
- def h1: (?Hash[Symbol, untyped] props) ?{ (ViewContext) -> untyped } -> VDOM::Element
28
- def h2: (?Hash[Symbol, untyped] props) ?{ (ViewContext) -> untyped } -> VDOM::Element
29
- def h3: (?Hash[Symbol, untyped] props) ?{ (ViewContext) -> untyped } -> VDOM::Element
30
- def h4: (?Hash[Symbol, untyped] props) ?{ (ViewContext) -> untyped } -> VDOM::Element
31
- def h5: (?Hash[Symbol, untyped] props) ?{ (ViewContext) -> untyped } -> VDOM::Element
32
- def h6: (?Hash[Symbol, untyped] props) ?{ (ViewContext) -> untyped } -> VDOM::Element
33
- def ul: (?Hash[Symbol, untyped] props) ?{ (ViewContext) -> untyped } -> VDOM::Element
34
- def ol: (?Hash[Symbol, untyped] props) ?{ (ViewContext) -> untyped } -> VDOM::Element
35
- def li: (?Hash[Symbol, untyped] props) ?{ (ViewContext) -> untyped } -> VDOM::Element
36
- def table: (?Hash[Symbol, untyped] props) ?{ (ViewContext) -> untyped } -> VDOM::Element
37
- def form: (?Hash[Symbol, untyped] props) ?{ (ViewContext) -> untyped } -> VDOM::Element
38
- def input: (?Hash[Symbol, untyped] props) ?{ (ViewContext) -> untyped } -> VDOM::Element
39
- def textarea: (?Hash[Symbol, untyped] props) ?{ (ViewContext) -> untyped } -> VDOM::Element
40
- def button: (?Hash[Symbol, untyped] props) ?{ (ViewContext) -> untyped } -> VDOM::Element
41
- def select: (?Hash[Symbol, untyped] props) ?{ (ViewContext) -> untyped } -> VDOM::Element
42
- def option: (?Hash[Symbol, untyped] props) ?{ (ViewContext) -> untyped } -> VDOM::Element
43
- def label: (?Hash[Symbol, untyped] props) ?{ (ViewContext) -> untyped } -> VDOM::Element
44
- def nav: (?Hash[Symbol, untyped] props) ?{ (ViewContext) -> untyped } -> VDOM::Element
45
- def canvas: (?Hash[Symbol, untyped] props) ?{ (ViewContext) -> untyped } -> VDOM::Element
20
+ def div: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
21
+ def span: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
22
+ def p: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
23
+ def a: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
24
+ def data: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
25
+ def h1: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
26
+ def h2: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
27
+ def h3: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
28
+ def h4: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
29
+ def h5: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
30
+ def h6: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
31
+ def ul: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
32
+ def ol: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
33
+ def li: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
34
+ def table: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
35
+ def thead: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
36
+ def tbody: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
37
+ def tr: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
38
+ def th: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
39
+ def td: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
40
+ def form: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
41
+ def input: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
42
+ def textarea: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
43
+ def button: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
44
+ def select: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
45
+ def option: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
46
+ def label: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
47
+ def header: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
48
+ def footer: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
49
+ def nav: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
50
+ def section: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
51
+ def article: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
52
+ def aside: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
53
+ def img: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
54
+ def video: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
55
+ def audio: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
56
+ def canvas: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
57
+ def br: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
58
+ def hr: (?Hash[Symbol, untyped] props) ?{ () -> untyped } -> VDOM::Element
46
59
  end
47
60
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: funicular
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - HASUMI Hitoshi
@@ -99,6 +99,7 @@ files:
99
99
  - minitest/commands_routes_test.rb
100
100
  - minitest/compiler_test.rb
101
101
  - minitest/configuration_test.rb
102
+ - minitest/dsl_test.rb
102
103
  - minitest/fixtures/funicular_app/components/greeting_component.rb
103
104
  - minitest/fixtures/funicular_app/initializer.rb
104
105
  - minitest/form_for_test.rb
@@ -109,6 +110,7 @@ files:
109
110
  - minitest/plugin_test.rb
110
111
  - minitest/route_parser_test.rb
111
112
  - minitest/schema_test.rb
113
+ - minitest/sig_tags_test.rb
112
114
  - minitest/ssr_test.rb
113
115
  - minitest/support/rails_stub.rb
114
116
  - minitest/test_helper.rb
@@ -116,6 +118,7 @@ files:
116
118
  - minitest/validations_test.rb
117
119
  - minitest/view_context_test.rb
118
120
  - mrbgem.rake
121
+ - mrblib/0_tags.rb
119
122
  - mrblib/0_validations.rb
120
123
  - mrblib/1_validators.rb
121
124
  - mrblib/cable.rb
@@ -158,6 +161,7 @@ files:
158
161
  - sig/store_collection.rbs
159
162
  - sig/store_singleton.rbs
160
163
  - sig/styles.rbs
164
+ - sig/tags.rbs
161
165
  - sig/validations.rbs
162
166
  - sig/vdom.rbs
163
167
  - sig/view_context.rbs