diff options
| author | s-ol <s-ol@users.noreply.github.com> | 2018-11-01 10:17:55 +0000 |
|---|---|---|
| committer | s-ol <s-ol@users.noreply.github.com> | 2018-11-01 10:17:55 +0000 |
| commit | 30fb0dc40d595b9e0b7747ad8e5c4e8cf7e3023b (patch) | |
| tree | dc56f20ec4d78115e15761c402589b5aec94ef55 /lib | |
| parent | defer all scripts (diff) | |
| download | mmm-30fb0dc40d595b9e0b7747ad8e5c4e8cf7e3023b.tar.gz mmm-30fb0dc40d595b9e0b7747ad8e5c4e8cf7e3023b.zip | |
move mmm code from lib to mmm etc
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/canvasapp.client.moon | 88 | ||||
| -rw-r--r-- | lib/color.moon | 20 | ||||
| -rw-r--r-- | lib/component.client.moon | 158 | ||||
| -rw-r--r-- | lib/component.server.moon | 130 | ||||
| -rw-r--r-- | lib/dom.client.moon | 33 | ||||
| -rw-r--r-- | lib/dom.server.moon | 40 | ||||
| -rw-r--r-- | lib/duct_tape.server.moon | 130 | ||||
| -rw-r--r-- | lib/init.client.moon | 49 | ||||
| -rw-r--r-- | lib/init.server.moon | 60 | ||||
| -rw-r--r-- | lib/mmmfs/browser.moon | 122 | ||||
| -rw-r--r-- | lib/mmmfs/conversion.moon | 118 | ||||
| -rw-r--r-- | lib/mmmfs/fileder.moon | 155 | ||||
| -rw-r--r-- | lib/mmmfs/init.moon | 34 | ||||
| -rw-r--r-- | lib/ordered.moon | 27 |
14 files changed, 0 insertions, 1164 deletions
diff --git a/lib/canvasapp.client.moon b/lib/canvasapp.client.moon deleted file mode 100644 index 71ffa59..0000000 --- a/lib/canvasapp.client.moon +++ /dev/null @@ -1,88 +0,0 @@ -window = js.global -js = require 'js' - -import a, canvas, div, button, script from require 'lib.dom' - -class CanvasApp - width: 500 - height: 400 - new: (show_menu=false, @paused) => - @canvas = canvas width: @width, height: @height - - @ctx = @canvas\getContext '2d' - @time = 0 - - @canvas.tabIndex = 0 - @canvas\addEventListener 'click', (_, e) -> @click and @click e.offsetX, e.offsetY, e.button - @canvas\addEventListener 'keydown', (_, e) -> @keydown and @keydown e.key, e.code - - lastMillis = window.performance\now! - - animationFrame = (_, millis) -> - @update (millis - lastMillis) / 1000 - @ctx\resetTransform! - @draw! - lastMillis = millis - - if not @paused - window\setTimeout (-> - window\requestAnimationFrame animationFrame - ), 0 - window\requestAnimationFrame animationFrame - - @node = if show_menu - div { - className: 'canvas_app' - @canvas - div { - className: 'overlay', - button 'render 30fps', onclick: -> @\render 30 - button 'render 60fps', onclick: -> @\render 60 - } - } - else - @canvas - - - update: (dt) => - @time += dt - - if @length and @time > @length - @time -= @length - true - - render: (fps=60) => - assert @length, 'cannot render CanvasApp without length set' - @paused = true - - actual_render = -> - writer = js.new window.Whammy.Video, fps - - doFrame = -> - done = @update 1/fps - @ctx\resetTransform! - @draw! - - writer\add @canvas - - if done or @time >= @length - blob = writer\compile! - name = "#{@@__name}_#{fps}fps.webm" - @node.lastChild\appendChild a name, download: name, href: window.URL\createObjectURL blob - else - window\setTimeout doFrame - - @time = 0 - doFrame! - - if window.Whammy - actual_render! - else - window.global = window.global or window - document.body\appendChild script - onload: actual_render - src: 'https://cdn.jsdelivr.net/npm/whammy@0.0.1/whammy.min.js' - -{ - :CanvasApp -} diff --git a/lib/color.moon b/lib/color.moon deleted file mode 100644 index 6233b47..0000000 --- a/lib/color.moon +++ /dev/null @@ -1,20 +0,0 @@ -rgb = (r, g, b) -> - r, g, b = table.unpack r if 'table' == type r - "rgb(#{r * 255}, #{g * 255}, #{b * 255})" - -rgba = (r, g, b, a) -> - r, g, b, a = table.unpack r if 'table' == type r - "rgba(#{r * 255}, #{g * 255}, #{b * 255}, #{a or 1})" - -hsl = (h, s, l) -> - h, s, l = table.unpack h if 'table' == type h - "hsl(#{h * 360}, #{s * 100}%, #{l * 100}%)" - -hsla = (h, s, l, a) -> - h, s, l, a = table.unpack h if 'table' == type h - "hsla(#{h * 360}, #{s * 100}%, #{l * 100}%, #{a or 1})" - -{ - :rgb, :rgba, - :hsl, :hsla, -} diff --git a/lib/component.client.moon b/lib/component.client.moon deleted file mode 100644 index ffeb084..0000000 --- a/lib/component.client.moon +++ /dev/null @@ -1,158 +0,0 @@ --- 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 tohtml -tohtml = (val) -> - if 'string' == type val - return document\createTextNode val - if 'table' == type val - assert val.node, "Table doesn't have .node" - val = val.node - if 'userdata' == type val - assert (js.instanceof val, js.global.Node), "userdata is not a Node" - 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 = (...) -> document\createTextNode table.concat { ... }, ' ' - -class ReactiveVar - @isinstance: (val) -> 'table' == (type val) and val.subscribe - - new: (@value) => - @listeners = setmetatable {}, __mode: 'kv' - - set: (value) => - old = @value - @value = value - for k, callback in pairs @listeners - callback @value, old - - get: => @value - - transform: (transform) => @set transform @get! - - subscribe: (callback) => - with -> @listeners[callback] = nil - @listeners[callback] = callback - - map: (transform) => - with ReactiveVar transform @value - .upstream = @subscribe (...) -> \set transform ... - --- join = do --- update = (k, new) -> (old) -> --- with copy = { k, v for k,v in pairs old } --- copy[k] = new --- --- (inputs) -> --- values = {} --- with ReactiveVar values --- for k, input in pairs inputs --- input = inputs[k] --- values[i] = input\get! --- input\subscribe (new) -> \transform update k, new - -class ReactiveElement - @isinstance: (val) -> 'table' == (type val) and val.node - - new: (element, ...) => - if 'userdata' == type element - @node = element - else - @node = document\createElement element - @_subscriptions = {} - - 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: => - for unsub in *@_subscriptions do unsub! - - set: (attr, value) => - attr = 'className' if attr == 'class' - if 'table' == (type value) and ReactiveVar.isinstance value - table.insert @_subscriptions, value\subscribe (...) -> @set attr, ... - value = value\get! - - if attr == 'style' and 'table' == type value - for k,v in pairs value - @node.style[k] = v - return - - @node[attr] = value - - prepend: (child, last) => @append child, last, 'prepend' - append: (child, last, mode='append') => - if ReactiveVar.isinstance child - table.insert @_subscriptions, child\subscribe (...) -> @append ... - child = child\get! - - if 'string' == type last - error 'cannot replace string node' - - if child == nil - if last - @remove last - return - - child = tohtml child - ok, last = pcall tohtml, last - if ok - @node\replaceChild child, last - else - switch mode - when 'append' then @node\appendChild child - when 'prepend' then @node\insertBefore child, @node.firstChild - - remove: (child) => - @node\removeChild tohtml child - if 'table' == (type child) and child.destroy - child\destroy! - -get_or_create = (elem, id, ...) -> - elem = (document\getElementById id) or elem - - with ReactiveElement elem, ... - \set 'id', id - -elements = setmetatable {}, __index: (name) => - with val = (...) -> ReactiveElement name, ... - @[name] = val - -{ - :ReactiveVar, - :ReactiveElement, - :get_or_create, --- :join, - :tohtml, - :append, - :text, - :elements, -} diff --git a/lib/component.server.moon b/lib/component.server.moon deleted file mode 100644 index 0026d32..0000000 --- a/lib/component.server.moon +++ /dev/null @@ -1,130 +0,0 @@ -import opairs from require 'lib.ordered' - -void_tags = { 'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', 'track', 'wbr' } -void_tags = { t,t for t in *void_tags } - --- 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) => - warn "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 opairs 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 opairs @attrs - if 'table' == type v - tmp = '' - for kk, vv in opairs v - tmp ..= "#{kk}: #{vv}; " - v = tmp - b ..= " #{k}=\"#{v}\"" - - if void_tags[@element] - assert #@children == 0, "void tag #{element} cannot have children!" - b .. ">" - else - b .. ">" - b ..= ">" .. table.concat @children, '' - b ..= "</#{@element}>" - b - -elements = setmetatable {}, __index: (name) => - with val = (...) -> ReactiveElement name, ... - @[name] = val - -get_or_create = (elem, id, ...) -> - with ReactiveElement elem, ... - \set 'id', id - -{ - :ReactiveVar, - :ReactiveElement, - :get_or_create, - :tohtml, - :flush, - :append, - :text, - :elements, -} diff --git a/lib/dom.client.moon b/lib/dom.client.moon deleted file mode 100644 index acdbfa4..0000000 --- a/lib/dom.client.moon +++ /dev/null @@ -1,33 +0,0 @@ -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 = {} - - with e = document\createElement element - for k,v in pairs attributes - k = 'className' if k == 'class' - if k == 'style' and 'table' == type v - for kk,vv in pairs v - e.style[kk] = vv - elseif 'string' == type k - e[k] = v - - -- if there is only one argument, - -- children can be in attributes table too - if #children == 0 - children = attributes - - for child in *children - if 'string' == type child - child = document\createTextNode child - - e\appendChild child - -setmetatable {}, __index: (name) => - with val = element name - @[name] = val diff --git a/lib/dom.server.moon b/lib/dom.server.moon deleted file mode 100644 index fe6b60c..0000000 --- a/lib/dom.server.moon +++ /dev/null @@ -1,40 +0,0 @@ -import opairs from require 'lib.ordered' - -void_tags = { 'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', 'track', 'wbr' } -void_tags = { t,t for t in *void_tags } - -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 opairs attributes - if k == 'style' and 'table' == type v - tmp = '' - for kk, vv in opairs 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 - - if void_tags[element] - assert #children == 0, "void tag #{element} cannot have children!" - b .. ">" - else - b ..= ">" .. table.concat children, '' - b ..= "</#{element}>" - b - -setmetatable {}, __index: (name) => - with val = element name - @[name] = val diff --git a/lib/duct_tape.server.moon b/lib/duct_tape.server.moon deleted file mode 100644 index b019ac8..0000000 --- a/lib/duct_tape.server.moon +++ /dev/null @@ -1,130 +0,0 @@ -package.noompath = './?.moon;./?/init.moon' - -export __FNDEF_NOOM_CACHE -__FNDEF_NOOM_CACHE = setmetatable {}, __mode: 'k' - -assert MODE == 'SERVER', "duct_tape only works on the server" - -compile = require 'moonscript.compile' -parse = require 'moonscript.parse' - -import smart_node, build from require 'moonscript.types' -import dirsep from require 'moonscript.base' -import get_options, unpack from require 'moonscript.util' - -line_tables = require 'moonscript.line_tables' -lua = :loadstring, :load - -local * - -escape_str = (str) -> (str\gsub('\\', '\\\\')\gsub '"', '\\"'), nil - -deep_clone = (value) -> - if 'table' == type value - { deep_clone(k), deep_clone(v) for k,v in pairs value } - else -- number, string, boolean, etc - value - -transform_fndef = (fndef, parent, i) -> - -- compile the function to Lua separately - code, ltable, pos = compile.tree { deep_clone fndef } - if not code - return compile.format_error(ltable, pos, text) - - code = "(function() #{code} end)()" - - -- assign the lua code to __FNDEF_NOOM_CACHE[function] so it can be retrieved by `compile` - fn = -> { 'ref', 'fn' } - cache = build.chain { - base: '__FNDEF_NOOM_CACHE', - { 'index', fn! } - } - - parent[i] = build.do { - { 'declare_with_shadows', { 'fn' } } - build.assign_one fn!, fndef - build.assign_one cache, { 'string', '"', escape_str code } - -- build.assign_one cache, { 'string', '[[', code } - fn! - } - - nil - -find_fndefs = (node, p, i) -> - if node[1] == "fndef" - transform_fndef node, p, i - else - for i = 1,#node - v = node[i] - find_fndefs v, node, i if 'table' == type v - -to_lua = (text, options={}) -> - if "string" != type text - t = type text - return nil, "expecting string (got ".. t ..")" - - tree, err = parse.string text - if not tree - return nil, err - - find_fndefs tree - - code, ltable, pos = compile.tree tree, options - if not code - return nil, compile.format_error(ltable, pos, text) - - code, ltable - -noom_loader = (name, ...) -> - name_path = name\gsub "%.", dirsep - - local file, file_path - for path in package.noompath\gmatch "[^;]+" - file_path = path\gsub "?", name_path - file = io.open file_path - break if file - - if file - text = file\read "*a" - file\close! - res, err = loadstring text, "@#{file_path}" - if not res - error file_path .. ": " .. err - - return res - - return nil, "Could not find noom file" - -loadstring = (...) -> - options, str, chunk_name, mode, env = get_options ... - chunk_name or= "=(noom.loadstring)" - - code, ltable_or_err = to_lua str, options - unless code - return nil, ltable_or_err - - line_tables[chunk_name] = ltable_or_err if chunk_name - - -- the unpack prevents us from passing nil - (lua.loadstring or lua.load) code, chunk_name, unpack { mode, env } - -do - local compile - insert_loader = (pos=2) -> - -- if not package.moonpath - -- package.moonpath = create_moonpath package.path - - loaders = package.loaders or package.searchers - for loader in *loaders - return false if loader == noom_loader - - table.insert loaders, pos, noom_loader - true - - compile = (fn) -> with code = __FNDEF_NOOM_CACHE[fn] - assert code, 'cannot compile function not loaded from noomscript source.' - - { - :insert_loader - :compile - } diff --git a/lib/init.client.moon b/lib/init.client.moon deleted file mode 100644 index 144543b..0000000 --- a/lib/init.client.moon +++ /dev/null @@ -1,49 +0,0 @@ -export MODE, print, warn, relative, on_client -export window, document - -window = js.global -{ :document, :console } = window - -MODE = 'CLIENT' - -deep_tostring = (tbl, space='') -> - return tbl if 'userdata' == type tbl - - buf = space .. tostring tbl - return buf unless 'table' == type tbl - - buf = buf .. ' {\n' - for k,v in pairs tbl - buf = buf .. "#{space} [#{k}]: #{deep_tostring v, space .. ' '}\n" - buf = buf .. "#{space}}" - buf - -print = (...) -> - contents = [deep_tostring v for v in *{ ... } ] - console\log table.unpack contents - -warn = (...) -> - contents = [deep_tostring v for v in *{ ... } ] - console\warn table.unpack contents - --- package.path = '/?.client.moon.lua;/?.moon.lua;/?/init.moon.lua;/?.lua;/?/init.lua' -package.path = '/?.lua;/?/init.lua' - --- relative imports -relative = do - _require = require - - (base, sub) -> - sub = 0 unless 'number' == type sub - - for i=1, sub - base = base\match '^(.*)%.%w+$' - - (name, x) -> - name = base .. name if '.' == name\sub 1, 1 - _require name - -on_client = (f, ...) -> f ... - -if on_load - for f in *on_load do f! diff --git a/lib/init.server.moon b/lib/init.server.moon deleted file mode 100644 index cc3851d..0000000 --- a/lib/init.server.moon +++ /dev/null @@ -1,60 +0,0 @@ -export MODE, print, warn, relative, on_client -MODE = 'SERVER' - -deep_tostring = (tbl, space='') -> - buf = space .. tostring tbl - - return buf unless 'table' == type tbl - - buf = buf .. ' {\n' - for k,v in pairs tbl - buf = buf .. "#{space} [#{k}]: #{deep_tostring v, space .. ' '}\n" - buf = buf .. "#{space}}" - buf - -print = do - _print = print - (...) -> - contents = [deep_tostring v for v in *{ ... } ] - _print table.unpack contents - --- warning messages -warn = (...) -> - contents = [deep_tostring v for v in *{ ... } ] - io.stderr\write table.concat contents, '\t' - io.stderr\write '\n' - --- relative imports -relative = do - _require = require - - (base, sub) -> - sub = 0 unless 'number' == type sub - - for i=1, sub - base = base\match '^(.*)%.%w+$' - - (name, x) -> - name = base .. name if '.' == name\sub 1, 1 - _require name - -import compile, insert_loader from require 'lib.duct_tape' -insert_loader! - -on_client = (fn, ...) -> - args = {...} - -- warn code - "<script type=\"application/lua\"> - local fn = #{compile fn} - on_load = on_load or {} - table.insert(on_load, function() - fn(#{table.concat [string.format '%q', v for v in *args ], ', '}) - end) - </script>" - -{ - -- access / flush the appended data - flush: -> - with x = buffer - buffer = '' -} diff --git a/lib/mmmfs/browser.moon b/lib/mmmfs/browser.moon deleted file mode 100644 index ce7709f..0000000 --- a/lib/mmmfs/browser.moon +++ /dev/null @@ -1,122 +0,0 @@ -require = relative ..., 1 -import Key from require '.fileder' -import get_conversions from require '.conversion' -import ReactiveVar, get_or_create, text, elements from require 'lib.component' -import div, span, a, select, option from elements - -class Browser - new: (@root, path='/', rehydrate=false) => - -- root fileder - assert @root, 'root fileder is nil' - - -- active path - @path = ReactiveVar path - - if MODE == 'CLIENT' - -- update URL bar - @path\subscribe (path) -> - path ..= '/' unless path\match '/$' - window.history\pushState nil, '', path - - -- active fileder - -- (re)set every time @path changes - @active = @path\map @root\walk - - -- currently active property - -- (re)set to default every time @active changes - @prop = @active\map (fileder) -> - return unless fileder - (fileder\find 'mmm/dom') or next fileder.props - - -- retrieve or create the root - @dom = get_or_create 'div', 'browser-root' - - -- prepend the navbar - if MODE == 'SERVER' - @dom\append div id: 'browser-navbar' - else - @dom\prepend get_or_create 'div', 'browser-navbar', { - span 'path: ', @path\map (path) -> with div style: { display: 'inline-block' } - path_segment = (name, href) -> - a name, :href, onclick: (_, e) -> - e\preventDefault! - @navigate href - - href = '' - path = path\match '^/(.*)' - - \append path_segment 'root', '/' - - while path - name, rest = path\match '^(%w+)/(.*)' - if not name - name = path - - path = rest - href = "#{href}/#{name}" - - \append '/' - \append path_segment name, href - - span 'view property: ', @active\map (fileder) -> - onchange = (_, e) -> - @prop\set Key e.target.value - - 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! - \append option value, :value, selected: value == current - } - - -- append or patch #browser-content - @dom\append with get_or_create 'div', 'browser-content' - \append @get_content!, (rehydrate and .node.lastChild) - - if rehydrate - -- force one rerender to set onclick handlers etc - @prop\set @prop\get! - - -- export mmm/component interface - @node = @dom.node - @render = @dom\render - - -- render #browser-content - get_content: () => - disp_error = (msg) -> span msg, style: { color: '#f00' } - @prop\map (prop) -> - active = @active\get! - - return disp_error "fileder not found!" unless active - return disp_error "property not found!" unless prop - - convert = -> - 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 - - ok, res = if MODE == 'CLIENT' - pcall convert - else - true, convert! - - if ok - res or disp_error "[no conversion path to mmm/dom]" - else - warn "error: ", res unless ok - disp_error "[unknown error displaying]" - - navigate: (new) => @path\set new - -{ - :Browser -} diff --git a/lib/mmmfs/conversion.moon b/lib/mmmfs/conversion.moon deleted file mode 100644 index 7f86aa4..0000000 --- a/lib/mmmfs/conversion.moon +++ /dev/null @@ -1,118 +0,0 @@ -import text, code from require 'lib.dom' -import tohtml from require 'lib.component' - --- limit function to one argument -single = (func) -> (val) -> func val - --- list of converts --- converts each have --- * inp - input type. can capture subtypes using `(.+)` --- * out - output type. can substitute subtypes from inp with %1, %2 etc. --- * transform - function (val: inp, fileder) -> val: out -converts = { - { - inp: 'moon -> (.+)', - out: '%1', - transform: (val, fileder) -> val fileder - }, - { - inp: 'text/plain', - out: 'mmm/dom', - transform: single text - }, - { - inp: 'alpha', - out: 'mmm/dom', - transform: single code - }, - { - inp: 'URL -> .*', - out: 'mmm/dom', - transform: single code - }, - { - inp: 'mmm/component', - out: 'mmm/dom', - transform: single tohtml - }, - { - inp: 'mmm/dom', - out: 'text/html', - transform: (node) -> if MODE == 'SERVER' then node else node.outerHTML - }, - { - inp: 'text/html', - out: 'mmm/dom', - transform: if MODE == 'SERVER' - (...) -> ... - else - (html) -> - tmp = document\createElement 'div' - tmp.innerHTML = html - if tmp.childElementCount == 1 - tmp.firstChild - else - tmp - } -} - -do - local markdown - if MODE == 'SERVER' - success, discount = pcall require, 'discount' - markdown = discount if success - else - markdown = window and window.marked and window\marked - - if markdown - table.insert converts, { - inp: 'text/markdown', - out: 'text/html', - transform: single markdown - } - -count = (base, pattern='->') -> select 2, base\gsub pattern, '' -escape_inp = (inp) -> "^#{inp\gsub '([-/])', '%%%1'}$" - --- attempt to find a conversion path from 'have' to 'want' --- * have - start type string or list of type strings --- * want - stop type string --- * limit - limit conversion amount --- returns a list of conversion steps -get_conversions = (want, have, limit=3) -> - assert have, 'need starting type(s)' - - if 'string' == type have - have = { have } - - assert #have > 0, 'need starting type(s) (list was empty)' - - iterations = limit + math.max table.unpack [count type for type in *have] - have = [{ :start, rest: start, conversions: {} } for start in *have] - - for i=1, iterations - next_have, c = {}, 1 - for { :start, :rest, :conversions } in *have - if want == rest - return conversions, start - else - for convert in *converts - inp = escape_inp convert.inp - matches = { rest\match inp } - continue unless #matches > 0 - result = rest\gsub inp, convert.out - if result - next_have[c] = { - :start, - rest: result, - conversions: { convert, table.unpack conversions } - } - c += 1 - - have = next_have - return unless #have > 0 - -{ - :converts - :get_conversions -} diff --git a/lib/mmmfs/fileder.moon b/lib/mmmfs/fileder.moon deleted file mode 100644 index c3e40f7..0000000 --- a/lib/mmmfs/fileder.moon +++ /dev/null @@ -1,155 +0,0 @@ -require = relative ..., 1 -import get_conversions from require '.conversion' - --- Key of a Fileder Property --- contains: --- * @name - key name or '' for main content --- * @type - type string (type -> type -> type) -class Key - -- instantiate from table w/ keys described above - -- or string like '@name: @type' (name optional) - new: (opts, second) => - if 'string' == type second - @name, @type = (opts or ''), second - elseif 'string' == type opts - @name, @type = opts\match '(%w+): *(.+)' - if not @name - @name = '' - @type = opts - elseif 'table' == type opts - @name = opts.name - @type = opts.type - else - error "wrong argument type: #{type opts}, #{type second}" - - -- format as a string (see constructor) - tostring: => - if @name == '' - @type - else - "#{@name}: #{@type}" - --- Fileder itself --- contains: --- * @props - Property Map (Key to Value) --- * @children - Children Array -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 - props[i] = nil - child - - -- 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 - -- * path - the path to walk to - walk: (path) => - -- early-out if we are outside of the path already - return unless path\match '^' .. @path - - -- gotcha - return @ if path == @path - - for child in *@children - result = child\walk path - return result 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 - -- * ... - arguments like Key - find: (...) => - want = Key ... - - -- filter props by name - matching = [ key for key in pairs @props when key.name == want.name ] - return unless #matching > 0 - - -- get shortest conversion path - shortest_path, start = get_conversions want.type, [ key.type for key in *matching ] - - if start - for key in *matching - if key.type == start - return key, shortest_path - - error "couldn't find key after resolution?" - - -- get property according to criteria, nil if no value or conversion path - -- * ... - arguments like Key - get: (...) => - want = Key ... - - -- find matching key and shortest conversion path - key, conversions = @find want - - if key - value = @props[key] - - -- apply conversions (in reverse order) - for i=#conversions,1,-1 - { :inp, :out, :transform } = conversions[i] - value = transform value, @ - - value, key - - -- like @get, throw if no value or conversion path - gett: (...) => - want = Key ... - - value, key = @get want - assert value, "node doesn't have value for '#{want\tostring!}'" - value, key - -{ - :Key - :Fileder -} diff --git a/lib/mmmfs/init.moon b/lib/mmmfs/init.moon deleted file mode 100644 index d0de45b..0000000 --- a/lib/mmmfs/init.moon +++ /dev/null @@ -1,34 +0,0 @@ -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 - - content = tohtml BROWSER - content, on_client rehydrate, path - -{ - :Key - :Fileder - :render - :define_fileders - :module_roots -} diff --git a/lib/ordered.moon b/lib/ordered.moon deleted file mode 100644 index 59c07bf..0000000 --- a/lib/ordered.moon +++ /dev/null @@ -1,27 +0,0 @@ --- ordered table iterator, for stable(r) renderers - -sort = (t, order_fn) -> - with index = [k for k,v in pairs t when 'string' == type k] - table.sort index, order_fn - --- ordered next(t) -onext = (state, key) -> - state.i += 1 - { :t, :index, :i } = state - - if key = index[i] - key, t[key] - --- ordered pairs(t). order_fn is optional; see table.sort -opairs = (t, order_fn) -> - state = { - :t, - i: 0, - index: sort t, order_fn - } - onext, state, nil - -{ - :onext - :opairs -} |
