1 module spasm.spa;
2 
3 version (LDC)
4 import ldc.attributes;
5 public import spasm.types;
6 public import spasm.dom;
7 public import spasm.node;
8 public import spasm.event;
9 public import spasm.array;
10 public import spasm.css;
11 
12 nothrow:
13 
14 extern(C) {
15   Handle getRoot();
16 }
17 
18 version (unittest) {
19   auto assumeNoThrow(T)(lazy T block) {
20     try {
21       return block();
22     } catch (Exception e) {
23       assert(false, e.msg);
24     }
25   }
26   auto renderToNode(T)(auto ref T t) {
27     import unit_threaded;
28     Handle rootIdx = cast(Handle)unittest_dom_nodes.data.length;
29     auto rootNode = new UnittestDomNode(NodeType.root, rootIdx + 1);
30     unittest_dom_nodes.put(rootNode);
31     t.setPointers();
32     spasm.dom.render(JsHandle(rootIdx + 1), t);
33     // assert(t.getNamedNode().node != invalidHandle);
34     // assert(t.getNamedNode().mounted == true);
35     return rootNode;
36   }
37   string renderToString(T)(auto ref T t) {
38     import std.format : format;
39     static if (is(T : UnittestDomNode)) {
40       auto node = t;
41     } else
42       auto node = t.renderToNode;
43     return format("%s", node).assumeNoThrow;
44   }
45   string renderToString(T)() {
46     T t;
47     return t.renderToString();
48   }
49 }
50 
51 void addApplicationCss(Application, Theme)() {
52   enum css = GetCss!(Application, Theme);
53   static if (css.length > 0)
54     addCss(css);
55 }
56 
57 mixin template Spa(Application) {
58   struct Empty{}
59   mixin Spa!(Application,Empty);
60 }
61 
62 mixin template Spa(Application, Theme) {
63   import spasm.rt.gc;
64   __gshared Application application;
65   pragma(mangle, "_start")
66   extern(C)
67   export
68   @trusted void _start(uint heap_base) {
69     import spasm.rt.memory;
70     alloc_init(heap_base);
71     addRoot(&application);
72     auto root = getRoot();
73     addApplicationCss!(Application, Theme)();
74     application.setPointers();
75     spasm.dom.render(root, application);
76   }
77   version(hmr) {
78     pragma(msg, "spasm with HMR");
79     import spasm.hmr;
80     pragma(mangle, "dumpApp")
81     extern(C) export string dumpApp() {
82       return application.dumpState();
83     }
84     pragma(mangle, "loadApp")
85     extern(C) export void loadApp(string state) {
86       application.loadState(state);
87     }
88   }
89 }
90 
91 struct Parameters(Ps...) {
92   static template opDispatch(string name) {
93     alias opDispatch(alias P) = Parameters!(Ps, Param!(name, P));
94   }
95 }
96 
97 auto param() {
98   return Parameters!()();
99 }
100 
101 struct Param(string name, alias field) {
102   alias Name = name;
103   alias Field = field;
104 }