aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authors-ol <s-ol@users.noreply.github.com>2018-09-05 00:36:00 +0000
committers-ol <s-ol@users.noreply.github.com>2018-09-05 00:36:00 +0000
commitece199a92220deaa3212fad30f6026693ae86c63 (patch)
treef576a8c160c8827050ef34f474961d89bdff1ac4
parentsome fixes (diff)
downloadmmm-ece199a92220deaa3212fad30f6026693ae86c63.tar.gz
mmm-ece199a92220deaa3212fad30f6026693ae86c63.zip
polymorphic!
-rw-r--r--app/center_of_mass.moon (renamed from app/centerofmass.moon)18
-rw-r--r--app/component.client.moon (renamed from app/component.moon)28
-rw-r--r--app/component.server.moon115
-rw-r--r--app/html.client.moon (renamed from app/html.moon)0
-rw-r--r--app/html.server.moon36
-rw-r--r--app/index.moon71
-rw-r--r--app/play_tags.moon6
-rw-r--r--app/realities.moon193
-rw-r--r--app/test_component.moon63
-rw-r--r--app/todo.moon2
-rw-r--r--app/twisted.moon4
m---------dist0
-rw-r--r--server.moon29
-rw-r--r--webpack.config.js45
14 files changed, 407 insertions, 203 deletions
diff --git a/app/centerofmass.moon b/app/center_of_mass.moon
index 6348937..d799b66 100644
--- a/app/centerofmass.moon
+++ b/app/center_of_mass.moon
@@ -1,9 +1,9 @@
window = js.global
document = window.document
-import CanvasApp from require './canvasapp.moon'
-import rgb from require './color.moon'
-import h1, p, div, span, input, button from require './html.moon'
+import CanvasApp from require 'app.canvasapp'
+import rgb from require 'app.color'
+import h1, p, div, span, input, button from require 'app.html'
fast = true
center_char = do
@@ -92,15 +92,15 @@ class CenterOfMass extends CanvasApp
@ctx\fillText char, x + w/2 - cx, y - cy
x += w
-document.body\appendChild h1 'Fonts aligned by Center-of-Mass'
-document.body\appendChild p 'Click below and type away :)'
+append h1 'Fonts aligned by Center-of-Mass'
+append p 'Click below and type away :)'
app = CenterOfMass "What's up", "Times New Roman", 40
-document.body\appendChild app.canvas
+append app.canvas
app.canvas.style.backgroundColor = '#eee'
add = =>
- document.body\appendChild div {
+ append div {
span 'font: ',
with @font_input = input!
.type = 'text'
@@ -109,7 +109,7 @@ add = =>
.onclick = (_, e) -> app.font = @font_input.value
}
- document.body\appendChild div {
+ append div {
span 'size: ',
input type: 'range', min: 2, max: 120, value: 40, onchange: (_, e) ->
size = e.target.value
@@ -119,7 +119,7 @@ add = =>
''
}
- document.body\appendChild div {
+ append div {
span 'optimize inner loop: ',
input type: 'checkbox', checked: fast, onchange: (_, e) ->
fast = e.target.checked
diff --git a/app/component.moon b/app/component.client.moon
index 6ce76bc..c012427 100644
--- a/app/component.moon
+++ b/app/component.client.moon
@@ -1,14 +1,12 @@
{ :document } = js.global
-warn = warn or -> print
-
-- convert anything to a DOM Node
-- val must be one of:
-- * DOM Node (instanceof window.Node)
-- * MMMElement (have a .node value that is instanceof window.Node)
-- * string
--- note that strings won't survive identity comparisons after asnode
-asnode = (val) ->
+-- note that strings won't survive identity comparisons after tohtml
+tohtml = (val) ->
if 'string' == type val
return document\createTextNode val
if 'table' == type val
@@ -20,9 +18,10 @@ asnode = (val) ->
else
error "not a Node: #{val}, #{type val}"
--- shorthand to append elements to body
--- see #asnode for permitted values
-append = (val) -> document.body\appendChild asnode val
+-- overloaded append
+-- see tohtml for acceptable values
+g_append = append
+append = (value) -> g_append tohtml value
-- shorthand to form a text node from strings
text = (...) -> document\createTextNode table.concat { ... }, ' '
@@ -98,25 +97,26 @@ class ReactiveElement
if ReactiveVar.isinstance child
table.insert @_subscriptions, child\subscribe (...) -> @append ...
child = child\get!
- if 'string' == type child
- warn 'string from ReactiveVar implicitly converted to TextNode, updating may fail'
- child = asnode child
- ok, last = pcall asnode, last
+ if 'string' == type last
+ error 'cannot replace string node'
+
+ child = tohtml child
+ ok, last = pcall tohtml, last
if ok
@node\replaceChild child, last
else
@node\appendChild child
remove: (child) =>
- @node\removeChild asnode child
+ @node\removeChild tohtml child
if 'table' == (type child) and child.destroy
child\destroy!
with exports = {
:ReactiveVar,
:ReactiveElement,
- :asnode,
+ :tohtml,
:append,
:text,
}
@@ -124,5 +124,5 @@ with exports = {
for e in *{'div', 'form', 'span', 'a', 'p', 'button', 'ul', 'ol', 'li', 'i', 'b', 'u', 'tt'} do add e
for e in *{'article', 'section', 'header', 'footer', 'content'} do add e
- for e in *{'br', 'img', 'input', 'p', 'textarea'} do add e
+ for e in *{'br', 'hr', 'img', 'input', 'p', 'textarea'} do add e
for i=1,8 do add "h" .. i
diff --git a/app/component.server.moon b/app/component.server.moon
new file mode 100644
index 0000000..456ca71
--- /dev/null
+++ b/app/component.server.moon
@@ -0,0 +1,115 @@
+-- convert anything to HTML string
+-- val must be one of:
+-- * MMMElement (have a .render method that returns a string)
+-- * string
+tohtml = (val) ->
+ if 'table' == type val
+ assert val.render, "Table doesn't have .render"
+ val = val\render!
+ if 'string' == type val
+ val
+ else
+ error "not a Node: #{val}, #{type val}"
+
+-- overloaded append
+-- see tohtml for acceptable values
+g_append = append
+append = (value) -> g_append tohtml value
+
+-- shorthand to form a text node from strings
+text = (...) -> table.concat { ... }, ' '
+
+class ReactiveVar
+ @isinstance: (val) -> 'table' == (type val) and val.subscribe
+
+ new: (@value) =>
+
+ set: (value) =>
+ error "attempting to update ReactiveVar serverside"
+
+ get: => @value
+
+ subscribe: (callback) =>
+ error "attempting to subscribe to ReactiveVar serverside"
+
+ map: (transform) =>
+ ReactiveVar transform @value
+
+class ReactiveElement
+ @isinstance: (val) -> 'table' == (type val) and val.render
+
+ new: (element, ...) =>
+ @element = element
+ @attrs = { style: {} }
+ @children = {}
+
+ children = { ... }
+
+ -- attributes are last arguments but mustn't be a ReactiveVar
+ attributes = children[#children]
+ if 'table' == (type attributes) and
+ (not ReactiveElement.isinstance attributes) and
+ (not ReactiveVar.isinstance attributes)
+ table.remove children
+ else
+ attributes = {}
+
+ for k,v in pairs attributes
+ @set k, v if 'string' == type k
+
+ -- if there is only one argument,
+ -- children can be in attributes table too
+ if #children == 0
+ children = attributes
+
+ for child in *children
+ @append child
+
+ destroy: =>
+
+ set: (attr, value) =>
+ if attr == 'style' and 'table' == type value
+ for k,v in pairs value
+ @attrs.style[k] = v
+ return
+
+ @attrs[attr] = value
+
+ append: (child, last) =>
+ assert not last, "last passed to append on server"
+ if ReactiveVar.isinstance child
+ child = child\get!
+
+ child = tohtml child
+ table.insert @children, child
+
+ remove: (child) =>
+ error "remove called serverside"
+
+ render: =>
+ b = "<#{@element}"
+ for k,v in pairs @attrs
+ if 'table' == type v
+ tmp = ''
+ for kk, vv in pairs v
+ tmp ..= "#{kk}: #{vv}; "
+ v = tmp
+ b ..= " #{k}=\"#{v}\""
+ b ..= ">" .. table.concat @children, ''
+ b ..= "</#{@element}>"
+ b
+
+with exports = {
+ :ReactiveVar,
+ :ReactiveElement,
+ :tohtml,
+ :flush,
+ :append,
+ :text,
+ }
+ add = (e) -> exports[e] = (...) -> ReactiveElement e, ...
+
+ for e in *{'div', 'form', 'span', 'a', 'p', 'button', 'ul', 'ol', 'li', 'i', 'b', 'u', 'tt'} do add e
+ for e in *{'article', 'section', 'header', 'footer', 'content'} do add e
+ for e in *{'br', 'hr', 'img', 'input', 'p', 'textarea'} do add e
+ for i=1,8 do add "h" .. i
diff --git a/app/html.moon b/app/html.client.moon
index fdec714..fdec714 100644
--- a/app/html.moon
+++ b/app/html.client.moon
diff --git a/app/html.server.moon b/app/html.server.moon
new file mode 100644
index 0000000..6bd05e1
--- /dev/null
+++ b/app/html.server.moon
@@ -0,0 +1,36 @@
+element = (element) -> (...) ->
+ children = { ... }
+
+ -- attributes are last arguments but mustn't be a ReactiveVar
+ attributes = children[#children]
+ if 'table' == (type attributes) and not attributes.node
+ table.remove children
+ else
+ attributes = {}
+
+ b = "<#{element}"
+ for k,v in pairs attributes
+ if 'table' == type v
+ tmp = ''
+ for kk, vv in pairs v
+ tmp ..= "#{kk}: #{vv}; "
+ v = tmp
+ b ..= " #{k}=\"#{v}\""
+
+ -- if there is only one argument,
+ -- children can be in attributes table too
+ if #children == 0
+ children = attributes
+
+ b ..= ">" .. table.concat children, ''
+ b ..= "</#{element}>"
+ b
+
+elements = {}
+add = (e) -> elements[e] = element e
+
+for e in *{'div', 'span', 'a', 'p', 'pre', 'button', 'ul', 'li', 'i', 'b', 'u', 'tt'} do add e
+for e in *{'br', 'img', 'input', 'p'} do add e
+for i=1,8 do add "h" .. i
+
+elements
diff --git a/app/index.moon b/app/index.moon
index daec767..581a4db 100644
--- a/app/index.moon
+++ b/app/index.moon
@@ -1,10 +1,15 @@
window = js.global
document = window.document
-import h1, p, a, br, ul, tt, li from require './html.moon'
+export MODE, append, print
+MODE = 'CLIENT'
+append = document.body\appendChild
+print = window.console\log
+
+import h1, p, a, br, ul, tt, li from require 'app.html'
moon = '\xe2\x98\xbd'
-demos =
+demos =
'twisted': 'canvas animation',
'todo': 'Todo demo of a simple reactive UI framework',
'realities': 'draft of a paper on virtual and other realities',
@@ -13,46 +18,36 @@ demos =
'play-tags': 'Playground for Functional Tags',
back_button = ->
- document.body\appendChild p a { '< back', href: '/' }
+ append p a { '< back', href: '/' }
-switch window.location.search
- when '?twisted'
- back_button!
- require './twisted.moon'
- when '?center-of-mass' then
- back_button!
- require './centerofmass.moon'
- when '?todo' then
- back_button!
- require './todo.moon'
- when '?test-component' then
- back_button!
- require './test_component.moon'
- when '?realities' then
- back_button!
- require './realities.moon'
- when '?play-tags' then
+if window.location.search and #window.location.search > 1
+ name = window.location.search\sub 2
+ if demos[name]
back_button!
- require './play_tags.moon'
+ filename = name\gsub '-', '_'
+ require "app.#{filename}"
else
- document.body\appendChild h1 'mmm'
- document.body\appendChild p {
- tt 'mmm'
- ' is not the '
- tt 'www'
- ', because it runs on '
- a { 'MoonScript', href: 'https://moonscript.org' }
- '.'
- br!
- 'You can find the source code of everything '
- a { 'here', href: 'https://github.com/s-ol/mmm' }
- '.'
- }
- document.body\appendChild p 'current demos:'
- document.body\appendChild ul for name, desc in pairs demos
- li (a name, href: "/?#{name}"), ': ', desc
+ append h1 'are you lost?'
+ append p a { '(go home)', href: '/' }
+else
+ append h1 'mmm'
+ append p {
+ tt 'mmm'
+ ' is not the '
+ tt 'www'
+ ', because it runs on '
+ a { 'MoonScript', href: 'https://moonscript.org' }
+ '.'
+ br!
+ 'You can find the source code of everything '
+ a { 'here', href: 'https://github.com/s-ol/mmm' }
+ '.'
+ }
+ append p 'current demos:'
+ append ul for name, desc in pairs demos
+ li (a name, href: "/?#{name}"), ': ', desc
-document.body\appendChild p {
+append p {
"made with #{moon} by "
a { 's-ol', href: 'https://twitter.com/S0lll0s' }
}
diff --git a/app/play_tags.moon b/app/play_tags.moon
index 68d6710..088f429 100644
--- a/app/play_tags.moon
+++ b/app/play_tags.moon
@@ -1,5 +1,5 @@
-import add_tag, rmv_tag, Node, Hierarchy, Toggle, NamespacedToggle from require './tags.moon'
-import ReactiveVar, append, asnode, text, div, form, span, h3, a, input, textarea, button from require './component.moon'
+import add_tag, rmv_tag, Node, Hierarchy, Toggle, NamespacedToggle from require 'app.tags'
+import ReactiveVar, append, tohtml, text, div, form, span, h3, a, input, textarea, button from require 'app.component'
clone = (set) ->
assert set and 'table' == (type set), 'not a set'
@@ -32,7 +32,7 @@ class ReactiveNode extends Node
margin: '0 5px',
}
}
- @node = asnode @_node
+ @node = tohtml @_node
has: (tag) => @tags\get![tag]
add: (tag) => @tags\transform set_append tag
diff --git a/app/realities.moon b/app/realities.moon
index 1ef4a01..0c9adc2 100644
--- a/app/realities.moon
+++ b/app/realities.moon
@@ -1,91 +1,105 @@
-window = js.global
-{ :document, :eval } = window
-
-import asnode, h1, h2, p, a, i, div, ol, li, br, span, button, section, article from require './component.moon'
-require 'svg.js'
-
-SVG =
- doc: window\eval "(function() { return SVG(document.createElement('svg')); })",
- G: window\eval "(function() { return new SVG.G(); })",
-setmetatable SVG, __call: => @doc!
-
-o = do
- mkobj = window\eval "(function () { return {}; })"
- (tbl) ->
- with obj = mkobj!
- for k,v in pairs(tbl)
- obj[k] = v
-
-print = window.console\log
+import append, tohtml, h1, h2, p, a, i, div, ol, li, br, hr, span, button, section, article from require 'app.component'
+local Diagram, o
GRID_W = 50
GRID_H = 40
-
-class Diagram
- new: =>
- @svg = SVG!
- @arrows = SVG.G!
- @width, @height = 0, 0
- @y = 0
-
- txtattr = o {
- fill: 'white',
- 'font-size': '14px',
- 'text-anchor': 'middle',
- }
- block: (color, label, h=1) =>
- @svg\add with SVG.G!
- with \rect GRID_W, h * GRID_H
- \attr o fill: color
- if label
- with \plain label
- \move GRID_W/2, 0
- \attr txtattr
-
- \move @width * GRID_W, (@y + h) * -GRID_H
- @y += h
- if @y > @height
- @height = @y
-
- arrattr = o {
- fill: 'white',
- 'font-size': '18px',
- 'text-anchor': 'middle',
- }
- arrow: (char, x, y) =>
- with @arrows\plain char
- \attr arrattr
- \move (x + 1) * GRID_W, (y - 0.5) * -GRID_H - 11
-
- -- inout: (x=@width, y=@y) => @arrow '⇋', x, y -- U+21CB
- -- inn: (x=@width, y=@y) => @arrow '↼', x, y+0.25 -- U+21BC
- -- out: (x=@width, y=@y) => @arrow '⇁', x, y-0.25 -- U+21C1
- inout: (x=@width, y=@y) => @arrow '⇆', x, y -- U+21C6
- inn: (x=@width, y=@y) => @arrow '←', x, y+0.25 -- U+2190
- out: (x=@width, y=@y) => @arrow '→', x, y-0.25 -- U+2192
-
- mind: (label='mind', ...) => @block '#fac710', label, ...
- phys: (label='phys', ...) => @block '#8fd13f', label, ...
- digi: (label='digi', ...) => @block '#9510ac', label, ...
-
- next: =>
- @y = 0
- @width += 1
-
- finish: =>
- return if @node
- @svg\add @arrows
-
- @width += 1
- w, h = @width * GRID_W, @height * GRID_H
-
- l = GRID_W / 6.5
- @svg\add with @svg\line 0, -GRID_H, w, -GRID_H
- \stroke o width: 2, color: '#ffffff', dasharray: "#{l}, #{l}"
-
- @svg\size w, h
- @svg\viewbox 0, -h, w, h
- @node = @svg.node
+if MODE == 'CLIENT'
+ require 'svg.js'
+ eval = js.global\eval
+
+
+ SVG =
+ doc: eval "(function() { return SVG(document.createElement('svg')); })",
+ G: eval "(function() { return new SVG.G(); })",
+ setmetatable SVG, __call: => @doc!
+
+ o = do
+ mkobj = eval "(function () { return {}; })"
+ (tbl) ->
+ with obj = mkobj!
+ for k,v in pairs(tbl)
+ obj[k] = v
+
+ class Diagram
+ new: =>
+ @svg = SVG!
+ @arrows = SVG.G!
+ @width, @height = 0, 0
+ @y = 0
+
+ txtattr = o {
+ fill: 'white',
+ 'font-size': '14px',
+ 'text-anchor': 'middle',
+ }
+ block: (color, label, h=1) =>
+ @svg\add with SVG.G!
+ with \rect GRID_W, h * GRID_H
+ \attr o fill: color
+ if label
+ with \plain label
+ \move GRID_W/2, 0
+ \attr txtattr
+
+ \move @width * GRID_W, (@y + h) * -GRID_H
+ @y += h
+ if @y > @height
+ @height = @y
+
+ arrattr = o {
+ fill: 'white',
+ 'font-size': '18px',
+ 'text-anchor': 'middle',
+ }
+ arrow: (char, x, y) =>
+ with @arrows\plain char
+ \attr arrattr
+ \move (x + 1) * GRID_W, (y - 0.5) * -GRID_H - 11
+
+ -- inout: (x=@width, y=@y) => @arrow '⇋', x, y -- U+21CB
+ -- inn: (x=@width, y=@y) => @arrow '↼', x, y+0.25 -- U+21BC
+ -- out: (x=@width, y=@y) => @arrow '⇁', x, y-0.25 -- U+21C1
+ inout: (x=@width, y=@y) => @arrow '⇆', x, y -- U+21C6
+ inn: (x=@width, y=@y) => @arrow '←', x, y+0.25 -- U+2190
+ out: (x=@width, y=@y) => @arrow '→', x, y-0.25 -- U+2192
+
+ mind: (label='mind', ...) => @block '#fac710', label, ...
+ phys: (label='phys', ...) => @block '#8fd13f', label, ...
+ digi: (label='digi', ...) => @block '#9510ac', label, ...
+
+ next: =>
+ @y = 0
+ @width += 1
+
+ finish: =>
+ return if @node
+ @svg\add @arrows
+
+ @width += 1
+ w, h = @width * GRID_W, @height * GRID_H
+
+ l = GRID_W / 6.5
+ @svg\add with @svg\line 0, -GRID_H, w, -GRID_H
+ \stroke o width: 2, color: '#ffffff', dasharray: "#{l}, #{l}"
+
+ @svg\size w, h
+ @svg\viewbox 0, -h, w, h
+ @node = @svg.node
+else
+ class Diagram
+ inout: =>
+ inn: =>
+ out: =>
+ block: =>
+ mind: =>
+ phys: =>
+ digi: =>
+ next: =>
+ finish: =>
+ render: =>
+ rplc = with div style: { display: 'inline-block', width: 200, height: 60 }
+ \append '(diagram goes here)'
+ rplc\render!
addlabel = (label, diagram) ->
with div style: { display: 'inline-block', margin: '20px', 'text-align': 'center' }
@@ -142,7 +156,7 @@ sources = do
}
ref = do
- fmt = (id) ->
+ fmt = (id) ->
a { (sources[id]\short id), href: "##{id}" }
ref = (...) ->
@@ -162,7 +176,7 @@ sect = (label) ->
with section style: 'page-break-inside': 'avoid'
\append h2 label
-document.body\append asnode with article style: { margin: 'auto', 'max-width': '750px' }
+append with article style: { margin: 'auto', 'max-width': '750px' }
\append div 'Sol Bekic', style: 'text-align': 'right'
\append h1 {
@@ -199,7 +213,7 @@ document.body\append asnode with article style: { margin: 'auto', 'max-width': '
"phys, mind, digi": "abbreviations for physical, mental and digital reality respectively.",
}
if 'number' == type definition
- \append document\createElement 'hr'
+ \append hr!
continue
\append with div style: { 'margin-left': '2rem' }
\append span term, style: {
@@ -395,7 +409,8 @@ document.body\append asnode with article style: { margin: 'auto', 'max-width': '
\next!
\block col, '', 2
- .svg\plain('phys + digi')\attr(o fill: 'white', 'font-size': '14px')\move 6, -2 * GRID_H
+ if MODE == 'CLIENT'
+ .svg\plain('phys + digi')\attr(o fill: 'white', 'font-size': '14px')\move 6, -2 * GRID_H
\finish!
\append p "Despite the similarities of VR and AR, the two can be considered polar opposites, as becomes evident when
diff --git a/app/test_component.moon b/app/test_component.moon
index 538368a..a8f8934 100644
--- a/app/test_component.moon
+++ b/app/test_component.moon
@@ -1,36 +1,42 @@
-{ :document, Node } = js.global
-
-import div, h1, ul, li, pre from require './html.moon'
+import div, h1, ul, li, pre from require 'app.html'
+last = nil
test_group = (name) ->
- list = ul!
- root = div (h1 name), list
- root, (name, test) ->
+ if last
+ append div (h1 name), ul last
+
+ last = {}
+ (name, test) ->
ok, err = pcall test
- list\appendChild li if ok
+ table.insert last, li if ok
"passed '#{name}'"
else
"failed '#{name}'", pre err
-node, run_test = test_group 'component.moon'
-document.body\appendChild node
+expect = (expected, note, ...) ->
+ ok, msg = pcall ...
+ print ok, msg\find expected
+ if ok or not msg\find expected
+ error note
+
+run_test = test_group 'component.moon'
local ReactiveVar, ReactiveElement
run_test "exports ReactiveVar, ReactiveElement", ->
- import ReactiveVar, ReactiveElement from require './component.moon'
+ import ReactiveVar, ReactiveElement from require 'app.component'
assert ReactiveVar, "ReactiveVar not exported"
assert ReactiveElement, "ReactiveElement not exported"
-run_test "exports asnode helper", ->
- import asnode from require './component.moon'
- assert 'function' == (type asnode), "asnode not exported"
+run_test "exports tohtml helper", ->
+ import tohtml from require 'app.component'
+ assert 'function' == (type tohtml), "tohtml not exported"
run_test "exports append helper", ->
- import append from require './component.moon'
+ import append from require 'app.component'
assert 'function' == (type append), "append not exported"
run_test "exports text helper", ->
- import text from require './component.moon'
+ import text from require 'app.component'
assert 'function' == (type text), "text not exported"
node = text 'a test string'
@@ -38,13 +44,12 @@ run_test "exports text helper", ->
assert node.data == 'a test string', "expected text to store the string"
run_test "text joins multiple arguments", ->
- import text from require './component.moon'
+ import text from require 'app.component'
node = text 'a', 'test', 'string'
assert node.data == 'a test string', "expected text to join arguments with spaces"
-node, run_test = test_group 'ReactiveVar'
-document.body\appendChild node
+run_test = test_group 'ReactiveVar'
run_test "stores a value", ->
reactive = ReactiveVar 'test'
@@ -137,8 +142,7 @@ run_test "tracks multiple subscriptions at once", ->
reactive\set 'test'
assert done, "expected to reach the end"
-node, run_test = test_group 'ReactiveElement'
-document.body\appendChild node
+run_test = test_group 'ReactiveElement'
run_test "creates a HTML element", ->
elem = ReactiveElement 'span'
@@ -190,21 +194,12 @@ run_test "can unwrap and track children from ReactiveVars", ->
assert elem.node.childElementCount == 2, "expected node to have two children"
run_test "warns when appending a string from a ReactiveVar", ->
- import text from require './component.moon'
- export print
- _print = print
-
- calls = 0
- print = (msg) -> calls += 1 if 'WARN: string' == msg\sub 1, 12
+ import text from require 'app.component'
str = ReactiveVar 'test'
elem = ReactiveElement 'div', str
- assert calls == 1, "expected to print warning"
-
- str\set 'string too'
- assert calls == 2, "expected to print warning again"
-
- str\set text 'this is text'
- assert calls == 2, "expected not to print warning with text node"
+ expect 'cannot replace string node', 'expected error', str\set, 'string too'
+ elem\destroy!
- print = _print
+ elem = ReactiveElement 'div', str\map text
+ str\set 'this is text'
diff --git a/app/todo.moon b/app/todo.moon
index 5bf4fef..0310e0d 100644
--- a/app/todo.moon
+++ b/app/todo.moon
@@ -1,4 +1,4 @@
-import ReactiveVar, append, text, div, form, span, h3, a, input, textarea, button from require './component.moon'
+import ReactiveVar, append, text, div, form, span, h3, a, input, textarea, button from require 'app.component'
parent = div!
todoItem = (desc, done) ->
diff --git a/app/twisted.moon b/app/twisted.moon
index f9ff282..1bc7a20 100644
--- a/app/twisted.moon
+++ b/app/twisted.moon
@@ -3,8 +3,8 @@ document = window.document
Math = window.Math
-import CanvasApp from require './canvasapp.moon'
-import hsl from require './color.moon'
+import CanvasApp from require 'app.canvasapp'
+import hsl from require 'app.color'
class TwistedDemo extends CanvasApp
width: 500
diff --git a/dist b/dist
-Subproject 94f4f68d7430c2729a88dcd431506bbbbda7aff
+Subproject 6ca5807dd956e75d19987cc230ec5143e0bb842
diff --git a/server.moon b/server.moon
new file mode 100644
index 0000000..5a79039
--- /dev/null
+++ b/server.moon
@@ -0,0 +1,29 @@
+package.moonpath = './?.server.moon;' .. package.moonpath
+
+export MODE, warn, append
+MODE = 'SERVER'
+warn = (...) ->
+ io.stderr\write table.concat { ... }, '\t'
+ io.stderr\write '\n'
+
+-- shorthand to append elements to body
+buffer = ''
+append = (val) ->
+ buffer ..= val
+flush = ->
+ with x = buffer
+ buffer = ''
+
+error "please specify the module to build as an argumnet" unless arg[1]
+
+require "app.#{arg[1]}"
+
+print "<!DOCTYPE html>
+<html>
+ <head>
+ <title>MMM: lunar low-gravity scripting playground</title>
+ </head>
+ <body>
+ #{flush!}
+ </body>
+</html>"
diff --git a/webpack.config.js b/webpack.config.js
index 1ac757b..6783e8f 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -1,22 +1,41 @@
+const fs = require('fs');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
-module.exports = {
+const config = {
context: path.resolve(__dirname, 'app'),
entry: './index.moon',
mode: 'development',
- module: {
- rules: [
- {
- test: /\.moon$/,
- use: [
- 'fengari-loader',
- 'moonscript-loader',
- ]
- },
- ]
- },
plugins: [
new HtmlWebpackPlugin({ title: 'MMM: lunar low-gravity scripting playground' }),
],
-}
+};
+
+const dependencies = {
+ 'svg.js': 'svg.js',
+};
+fs.readdirSync(config.context).forEach(file => {
+ if (file.endsWith('.moon') && !file.endsWith('.server.moon')) {
+ const basename = file.replace(/(\.client)?\.moon$/, '');
+ dependencies[`app.${basename}`] = `./${file}`;
+ }
+});
+
+config.module = {
+ rules: [
+ {
+ test: /\.moon$/,
+ use: [
+ {
+ loader: 'fengari-loader',
+ options: {
+ dependencies,
+ },
+ },
+ 'moonscript-loader',
+ ]
+ },
+ ]
+};
+
+module.exports = config;