aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/init.client.moon6
-rw-r--r--lib/init.server.moon9
-rw-r--r--lib/mmmfs/browser.moon105
-rw-r--r--lib/mmmfs/fileder.moon75
-rw-r--r--lib/mmmfs/init.moon28
5 files changed, 168 insertions, 55 deletions
diff --git a/lib/init.client.moon b/lib/init.client.moon
index 981cd25..77ff0ee 100644
--- a/lib/init.client.moon
+++ b/lib/init.client.moon
@@ -1,4 +1,4 @@
-export MODE, print, warn, relative, append, on_client
+export MODE, print, warn, relative, on_client
export window, document
window = js.global
@@ -7,8 +7,9 @@ window = js.global
MODE = 'CLIENT'
deep_tostring = (tbl, space='') ->
- buf = space .. tostring tbl
+ return tbl if 'userdata' == type tbl
+ buf = space .. tostring tbl
return buf unless 'table' == type tbl
buf = buf .. ' {\n'
@@ -42,5 +43,4 @@ relative = do
name = base .. name if '.' == name\sub 1, 1
_require name
-append = document.body\appendChild
on_client = (f, ...) -> f ...
diff --git a/lib/init.server.moon b/lib/init.server.moon
index f81a2dc..198c64e 100644
--- a/lib/init.server.moon
+++ b/lib/init.server.moon
@@ -1,4 +1,4 @@
-export MODE, print, warn, relative, append, on_client
+export MODE, print, warn, relative, on_client
MODE = 'SERVER'
deep_tostring = (tbl, space='') ->
@@ -38,18 +38,13 @@ relative = do
name = base .. name if '.' == name\sub 1, 1
_require name
--- shorthand to append elements to body
-buffer = ''
-append = (val) ->
- buffer ..= val
-
import compile, insert_loader from require 'lib.duct_tape'
insert_loader!
on_client = (fn, ...) ->
args = {...}
-- warn code
- append "<script type=\"application/lua\">
+ "<script type=\"application/lua\">
local fn = #{compile fn}
fn(#{table.concat [string.format '%q', v for v in *args ], ', '})
</script>"
diff --git a/lib/mmmfs/browser.moon b/lib/mmmfs/browser.moon
index a4080c2..5f70174 100644
--- a/lib/mmmfs/browser.moon
+++ b/lib/mmmfs/browser.moon
@@ -6,28 +6,47 @@ import div, span, a, select, option from elements
limit = (list, num) -> [v for i,v in ipairs list when i <= num]
-class Browser
- new: (@root, @path={}, rehydrate=false) =>
- @path = ReactiveVar @path
- -- @path\subscribe (path) -> window.location.hash = '/' .. table.concat path, '/'
- @prop = ReactiveVar (@root\find 'mmm/dom') or next @root.props
- @active = @path\map (path) ->
- fileder = @root
- for name in *path
- local next
- for child in *fileder.children
- if name == child\get 'name', 'alpha'
- next = child
- break
+path2tbl = (path) ->
+ switch type path
+ when 'string'
+ path
+ when 'table'
+ str = table.concat path, '/'
+ if '/' != str\sub 1, 1
+ str = '/' .. str
+ str
+ else
+ error "path is of wrong type: #{type path}"
- if not next
- return
-
- fileder = next
+class Browser
+ new: (@root, path={}, rehydrate=false) =>
+ @path = ReactiveVar path2tbl path
- fileder
+ assert @root, 'root fileder is nil'
- @active\subscribe (fileder) -> @prop\set (fileder\find 'mmm/dom') or next fileder.props
+ -- @path\subscribe (path) -> window.location.hash = '/' .. table.concat path, '/'
+ @active = @path\map (path) -> @root\walk path
+
+-- fileder = @root
+--
+-- for name in *path
+-- local next
+-- for child in *fileder.children
+-- if name == child\get 'name', 'alpha'
+-- next = child
+-- break
+--
+-- if not next
+-- warn "couldn't find node '#{name}'"
+-- return
+--
+-- fileder = next
+--
+-- fileder
+
+ @prop = @active\map (fileder) ->
+ return unless fileder
+ (fileder\find 'mmm/dom') or next fileder.props
-- retrieve or create the root
root = 'div'
@@ -72,8 +91,9 @@ class Browser
onchange = (_, e) ->
@prop\set Key e.target.value
- current = @prop\get!\tostring!
- with select :onchange
+ current = @prop\get!
+ current = current and current\tostring!
+ with select :onchange, disabled: not fileder
if fileder
for key, _ in pairs fileder.props
value = key\tostring!
@@ -83,46 +103,59 @@ class Browser
-- append or patch #browser-content
node = 'div'
node = document\getElementById 'browser-content' if rehydrate
- @dom\append ReactiveElement node, {
- id: 'browser-content',
- style: {
- flex: '1 0 0',
- overflow: 'auto',
- padding: '1em 2em',
- },
- @get_content rehydrate and node
- }
+ @dom\append with ReactiveElement node, {
+ id: 'browser-content',
+ style: {
+ flex: '1 0 0',
+ overflow: 'auto',
+ padding: '1em 2em',
+ },
+ }
+ \append @get_content rehydrate and node
+
+ if rehydrate
+ -- force one update to update onclick handlers etc
+ @prop\set @prop\get!
@node = @dom.node
@render = @dom\render
get_content: (wrapper) =>
+ disp_error = (msg) -> span msg, style: { color: '#f00' }
var = @prop\map (prop) ->
active = @active\get!
+ if not active
+ return disp_error "fileder not found!"
+
+ if not prop
+ return disp_error "property not found!"
+
ok, res = pcall ->
- conversions = assert (get_conversions 'mmm/dom', prop.type), "no conversion path"
+ conversions = get_conversions 'mmm/dom', prop.type
value = assert (active\get prop), "value went missing?"
+ return unless conversions
+
for i=#conversions,1,-1
{ :inp, :out, :transform } = conversions[i]
value = transform value, active
value
- if ok and res
- res
+ if ok
+ res or disp_error "[no conversion path to mmm/dom]"
else
warn "error: ", res unless ok
- span "cannot display!", style: { color: '#f00' }
+ disp_error "[unknown error displaying]"
-- wrapper was built already so take over the old value
if wrapper
- var\set wrapper.lastElementChild
+ return var, wrapper.lastChild -- var\set wrapper.lastElementChild
var
- navigate: (new) => @path\set new
+ navigate: (new) => @path\set path2tbl new
{
:Browser,
diff --git a/lib/mmmfs/fileder.moon b/lib/mmmfs/fileder.moon
index 75659d4..a1f689e 100644
--- a/lib/mmmfs/fileder.moon
+++ b/lib/mmmfs/fileder.moon
@@ -37,17 +37,75 @@ class Fileder
-- instantiate from props and children tables
-- or mix in one table (numeric keys are children, remainder props)
-- prop-keys are passed to Key constructor
- new: (props, @children) =>
- if not @children
- @children = for i, child in ipairs props
+ new: (props, children) =>
+ if not children
+ children = for i, child in ipairs props
props[i] = nil
child
- @props = { (Key k), v for k, v in pairs props }
+ -- automatically mount children on insert
+ @children = setmetatable {}, __newindex: (t, k, child) ->
+ rawset t, k, child
+ if @path == '/'
+ child\mount '/'
+ elseif @path
+ child\mount @path .. '/'
+
+ -- copy children
+ for i, child in ipairs children
+ @children[i] = child
+
+ -- automatically reify string keys on insert
+ @props = setmetatable {}, __newindex: (t, key, v) ->
+ rawset t, key, nil -- fix for fengari.io
+ rawset t, (Key key), v
+
+ -- copy props
+ for k, v in pairs props
+ @props[k] = v
+
+ -- recursively walk to and return the fileder with @path == path
+ walk: (path) =>
+ -- early-out if we are outside of the path already
+ return unless @path\match '^' .. path
+
+ -- gotcha
+ return @ if path == @path
+
+ -- @TODO: obviously there is better ways
+ for child in *@children
+ result = child\walk path
+ return if result
+
+ -- recursively mount fileder and children at path
+ -- * path - the path to mount at (default: '/')
+ -- * mount_as - dont append own name to path
+ mount: (path='/', mount_as=false) =>
+ assert not @path, "mounted twice: #{@path} and now #{path}"
+
+ if mount_as
+ @path = path
+ else
+ @path = path .. @gett 'name: alpha'
+
+ if @path == '/'
+ for child in *@children
+ child\mount '/'
+ else
+ for child in *@children
+ child\mount @path .. '/'
+
+ -- recursively iterate all children (coroutine)
+ -- * depth - depth to stop after; 1 = yield only self (default: infinite)
+ iterate: (depth=0) =>
+ coroutine.yield @
+ return if depth == 1
+
+ for child in *@children
+ child\iterate depth - 1
-- find property key according to criteria, nil if no value or conversion path
- -- * name - property name (optional: defaults to main content)
- -- * type - wanted result type
+ -- * ... - arguments like Key
find: (...) =>
want = Key ...
@@ -66,8 +124,7 @@ class Fileder
error "couldn't find key after resolution?"
-- get property according to criteria, nil if no value or conversion path
- -- * name - property name (optional: defaults to main content)
- -- * type - wanted result type
+ -- * ... - arguments like Key
get: (...) =>
want = Key ...
@@ -89,7 +146,7 @@ class Fileder
want = Key ...
value, key = @get want
- assert value, "node doesn't have value for #{want\tostring!}"
+ assert value, "node doesn't have value for '#{want\tostring!}'"
value, key
{
diff --git a/lib/mmmfs/init.moon b/lib/mmmfs/init.moon
index bb26505..172f0ef 100644
--- a/lib/mmmfs/init.moon
+++ b/lib/mmmfs/init.moon
@@ -1,7 +1,35 @@
require = relative ...
import Key, Fileder from require '.fileder'
+import Browser from require '.browser'
+import tohtml from require 'lib.component'
+
+define_fileders = (...) ->
+ source_module = ...
+
+ (...) ->
+ with fileder = Fileder ...
+ .source_module = source_module
+
+rehydrate = (path) ->
+ import Browser from require 'lib.mmmfs.browser'
+ root = require 'root'
+ root\mount!
+
+ export BROWSER
+ BROWSER = Browser root, path, true
+
+render = (root, path) ->
+ export BROWSER
+ BROWSER = Browser root, path
+
+ str = tohtml BROWSER
+ str ..= on_client rehydrate, path
+ str
{
:Key
:Fileder
+ :render
+ :define_fileders
+ :module_roots
}