local p = {}
table.insert(package.searchers, 1, function (mod)
print('?',mod, not not p[mod])
local mod = p[mod]
return mod and function ()
return load(table.unpack(mod))()
end
end)
p["mmm.component"] = {"local tohtml\
tohtml = function(val)\
if 'string' == type(val) then\
return document:createTextNode(val)\
end\
if 'table' == type(val) then\
assert(val.node, \"Table doesn't have .node\")\
val = val.node\
end\
if 'userdata' == type(val) then\
assert((js.instanceof(val, js.global.Node)), \"userdata is not a Node\")\
return val\
else\
return error(\"not a Node: \" .. tostring(val) .. \", \" .. tostring(type(val)))\
end\
end\
local fromhtml\
fromhtml = function(node)\
return {\
node = node\
}\
end\
local text\
text = function(str)\
return document:createTextNode(tostring(str))\
end\
local ReactiveVar\
do\
local _class_0\
local _base_0 = {\
set = function(self, value)\
local old = self.value\
self.value = value\
for k, callback in pairs(self.listeners) do\
callback(self.value, old)\
end\
end,\
get = function(self)\
return self.value\
end,\
transform = function(self, transform)\
return self:set(transform(self:get()))\
end,\
subscribe = function(self, callback)\
do\
local _with_0\
_with_0 = function()\
self.listeners[callback] = nil\
end\
self.listeners[callback] = callback\
return _with_0\
end\
end,\
map = function(self, transform)\
do\
local _with_0 = ReactiveVar(transform(self.value))\
_with_0.upstream = self:subscribe(function(...)\
return _with_0:set(transform(...))\
end)\
return _with_0\
end\
end\
}\
_base_0.__index = _base_0\
_class_0 = setmetatable({\
__init = function(self, value)\
self.value = value\
self.listeners = setmetatable({ }, {\
__mode = 'kv'\
})\
end,\
__base = _base_0,\
__name = \"ReactiveVar\"\
}, {\
__index = _base_0,\
__call = function(cls, ...)\
local _self_0 = setmetatable({}, _base_0)\
cls.__init(_self_0, ...)\
return _self_0\
end\
})\
_base_0.__class = _class_0\
local self = _class_0\
self.isinstance = function(val)\
return 'table' == (type(val)) and val.subscribe\
end\
ReactiveVar = _class_0\
end\
local ReactiveElement\
do\
local _class_0\
local _base_0 = {\
destroy = function(self)\
local _list_0 = self._subscriptions\
for _index_0 = 1, #_list_0 do\
local unsub = _list_0[_index_0]\
unsub()\
end\
end,\
set = function(self, attr, value)\
if attr == 'class' then\
attr = 'className'\
end\
if 'table' == (type(value)) and ReactiveVar.isinstance(value) then\
table.insert(self._subscriptions, value:subscribe(function(...)\
return self:set(attr, ...)\
end))\
value = value:get()\
end\
if attr == 'style' and 'table' == type(value) then\
for k, v in pairs(value) do\
self.node.style[k] = v\
end\
return \
end\
self.node[attr] = value\
end,\
prepend = function(self, child, last)\
return self:append(child, last, 'prepend')\
end,\
append = function(self, child, last, mode)\
if mode == nil then\
mode = 'append'\
end\
if ReactiveVar.isinstance(child) then\
table.insert(self._subscriptions, child:subscribe(function(...)\
return self:append(...)\
end))\
child = child:get()\
end\
if 'string' == type(last) then\
error('cannot replace string node')\
end\
if child == nil then\
if last then\
self:remove(last)\
end\
return \
end\
child = tohtml(child)\
if last then\
return self.node:replaceChild(child, tohtml(last))\
else\
local _exp_0 = mode\
if 'append' == _exp_0 then\
return self.node:appendChild(child)\
elseif 'prepend' == _exp_0 then\
return self.node:insertBefore(child, self.node.firstChild)\
end\
end\
end,\
remove = function(self, child)\
self.node:removeChild(tohtml(child))\
if 'table' == (type(child)) and child.destroy then\
return child:destroy()\
end\
end\
}\
_base_0.__index = _base_0\
_class_0 = setmetatable({\
__init = function(self, element, ...)\
if 'userdata' == type(element) then\
self.node = element\
else\
self.node = document:createElement(element)\
end\
self._subscriptions = { }\
local children = {\
...\
}\
local attributes = children[#children]\
if 'table' == (type(attributes)) and (not ReactiveElement.isinstance(attributes)) and (not ReactiveVar.isinstance(attributes)) then\
table.remove(children)\
else\
attributes = { }\
end\
for k, v in pairs(attributes) do\
if 'string' == type(k) then\
self:set(k, v)\
end\
end\
if #children == 0 then\
children = attributes\
end\
for _index_0 = 1, #children do\
local child = children[_index_0]\
self:append(child)\
end\
end,\
__base = _base_0,\
__name = \"ReactiveElement\"\
}, {\
__index = _base_0,\
__call = function(cls, ...)\
local _self_0 = setmetatable({}, _base_0)\
cls.__init(_self_0, ...)\
return _self_0\
end\
})\
_base_0.__class = _class_0\
local self = _class_0\
self.isinstance = function(val)\
return 'table' == (type(val)) and val.node\
end\
ReactiveElement = _class_0\
end\
local get_or_create\
get_or_create = function(elem, id, ...)\
elem = (document:getElementById(id)) or elem\
do\
local _with_0 = ReactiveElement(elem, ...)\
_with_0:set('id', id)\
return _with_0\
end\
end\
local elements = setmetatable({ }, {\
__index = function(self, name)\
do\
local val\
val = function(...)\
return ReactiveElement(name, ...)\
end\
self[name] = val\
return val\
end\
end\
})\
return {\
ReactiveVar = ReactiveVar,\
ReactiveElement = ReactiveElement,\
get_or_create = get_or_create,\
tohtml = tohtml,\
fromhtml = fromhtml,\
text = text,\
elements = elements\
}", "mmm/component/init.client.moon"}
p["mmm.refs"] = {"return {\
depth = 0,\
count = 0,\
push = function(self)\
self.depth = self.depth + 1\
end,\
pop = function(self)\
self.depth = self.depth - 1\
if self.depth == 0 then\
self.count = 0\
end\
end,\
get = function(self)\
self.count = self.count + 1\
return self.count\
end\
}", "mmm/refs.moon"}
p["mmm.color"] = {"local rgb\
rgb = function(r, g, b)\
if 'table' == type(r) then\
r, g, b = table.unpack(r)\
end\
return \"rgb(\" .. tostring(r * 255) .. \", \" .. tostring(g * 255) .. \", \" .. tostring(b * 255) .. \")\"\
end\
local rgba\
rgba = function(r, g, b, a)\
if 'table' == type(r) then\
r, g, b, a = table.unpack(r)\
end\
return \"rgba(\" .. tostring(r * 255) .. \", \" .. tostring(g * 255) .. \", \" .. tostring(b * 255) .. \", \" .. tostring(a or 1) .. \")\"\
end\
local hsl\
hsl = function(h, s, l)\
if 'table' == type(h) then\
h, s, l = table.unpack(h)\
end\
return \"hsl(\" .. tostring(h * 360) .. \", \" .. tostring(s * 100) .. \"%, \" .. tostring(l * 100) .. \"%)\"\
end\
local hsla\
hsla = function(h, s, l, a)\
if 'table' == type(h) then\
h, s, l, a = table.unpack(h)\
end\
return \"hsla(\" .. tostring(h * 360) .. \", \" .. tostring(s * 100) .. \"%, \" .. tostring(l * 100) .. \"%, \" .. tostring(a or 1) .. \")\"\
end\
return {\
rgb = rgb,\
rgba = rgba,\
hsl = hsl,\
hsla = hsla\
}", "mmm/color.moon"}
p["mmm.highlighting"] = {"local code\
code = require('mmm.dom').code\
local trim\
trim = function(str)\
return str:match('^ *(..-) *$')\
end\
local highlight\
if MODE == 'SERVER' then\
highlight = function(lang, str)\
assert(str, 'no string to highlight')\
return code((trim(str)), {\
class = \"hljs lang-\" .. tostring(lang)\
})\
end\
else\
highlight = function(lang, str)\
assert(str, 'no string to highlight')\
if not window.hljs:getLanguage(lang) then\
lang = 'markdown'\
end\
local result = window.hljs:highlight(lang, (trim(str)), true)\
do\
local _with_0 = code({\
class = \"hljs lang-\" .. tostring(lang)\
})\
_with_0.innerHTML = result.value\
return _with_0\
end\
end\
end\
local languages = setmetatable({ }, {\
__index = function(self, name)\
do\
local val\
val = function(str)\
return highlight(name, str)\
end\
self[name] = val\
return val\
end\
end\
})\
return {\
highlight = highlight,\
languages = languages\
}", "mmm/highlighting.moon"}
p["mmm.dom"] = {"local element\
element = function(element)\
return function(...)\
local children = {\
...\
}\
local attributes = children[#children]\
if 'table' == (type(attributes)) and not attributes.node then\
table.remove(children)\
else\
attributes = { }\
end\
local e\
if element then\
e = document:createElement(element)\
else\
e = document:createDocumentFragment()\
end\
for k, v in pairs(attributes) do\
if k == 'class' then\
k = 'className'\
end\
if k == 'style' and 'table' == type(v) then\
for kk, vv in pairs(v) do\
e.style[kk] = vv\
end\
elseif 'string' == type(k) then\
e[k] = v\
end\
end\
if #children == 0 then\
children, attributes = attributes, { }\
end\
if not element then\
assert(not (next(attributes)), \"_frag cannot take attributes\")\
end\
for _index_0 = 1, #children do\
local child = children[_index_0]\
if 'string' == type(child) then\
child = document:createTextNode(child)\
end\
e:appendChild(child)\
end\
return e\
end\
end\
return setmetatable({\
_frag = element()\
}, {\
__index = function(self, name)\
do\
local val = element(name)\
self[name] = val\
return val\
end\
end\
})", "mmm/dom/init.client.moon"}
p["mmm.canvasapp"] = {"local window = js.global\
local js = require('js')\
local a, canvas, div, button, script\
do\
local _obj_0 = require('mmm.dom')\
a, canvas, div, button, script = _obj_0.a, _obj_0.canvas, _obj_0.div, _obj_0.button, _obj_0.script\
end\
local CanvasApp\
do\
local _class_0\
local _base_0 = {\
width = 500,\
height = 400,\
update = function(self, dt)\
self.time = self.time + dt\
if self.length and self.time > self.length then\
self.time = self.time - self.length\
return true\
end\
end,\
render = function(self, fps)\
if fps == nil then\
fps = 60\
end\
assert(self.length, 'cannot render CanvasApp without length set')\
self.paused = true\
local actual_render\
actual_render = function()\
local writer = js.new(window.Whammy.Video, fps)\
local doFrame\
doFrame = function()\
local done = self:update(1 / fps)\
self.ctx:resetTransform()\
self:draw()\
writer:add(self.canvas)\
if done or self.time >= self.length then\
local blob = writer:compile()\
local name = tostring(self.__class.__name) .. \"_\" .. tostring(fps) .. \"fps.webm\"\
return self.node.lastChild:appendChild(a(name, {\
download = name,\
href = window.URL:createObjectURL(blob)\
}))\
else\
return window:setTimeout(doFrame)\
end\
end\
self.time = 0\
return doFrame()\
end\
if window.Whammy then\
return actual_render()\
else\
window.global = window.global or window\
return document.body:appendChild(script({\
onload = actual_render,\
src = 'https://cdn.jsdelivr.net/npm/whammy@0.0.1/whammy.min.js'\
}))\
end\
end\
}\
_base_0.__index = _base_0\
_class_0 = setmetatable({\
__init = function(self, show_menu, paused)\
if show_menu == nil then\
show_menu = false\
end\
self.paused = paused\
self.canvas = canvas({\
width = self.width,\
height = self.height\
})\
self.ctx = self.canvas:getContext('2d')\
self.time = 0\
self.canvas.tabIndex = 0\
self.canvas:addEventListener('click', function(_, e)\
return self.click and self:click(e.offsetX, e.offsetY, e.button)\
end)\
self.canvas:addEventListener('keydown', function(_, e)\
return self.keydown and self:keydown(e.key, e.code)\
end)\
local lastMillis = window.performance:now()\
local animationFrame\
animationFrame = function(_, millis)\
self:update((millis - lastMillis) / 1000)\
self.ctx:resetTransform()\
self:draw()\
lastMillis = millis\
if not self.paused then\
return window:setTimeout((function()\
return window:requestAnimationFrame(animationFrame)\
end), 0)\
end\
end\
window:requestAnimationFrame(animationFrame)\
if show_menu then\
self.node = div({\
className = 'canvas_app',\
self.canvas,\
div({\
className = 'overlay',\
button('render 30fps', {\
onclick = function()\
return self:render(30)\
end\
}),\
button('render 60fps', {\
onclick = function()\
return self:render(60)\
end\
})\
})\
})\
else\
self.node = self.canvas\
end\
end,\
__base = _base_0,\
__name = \"CanvasApp\"\
}, {\
__index = _base_0,\
__call = function(cls, ...)\
local _self_0 = setmetatable({}, _base_0)\
cls.__init(_self_0, ...)\
return _self_0\
end\
})\
_base_0.__class = _class_0\
CanvasApp = _class_0\
end\
return {\
CanvasApp = CanvasApp\
}", "mmm/canvasapp.client.moon"}
p["mmm.ordered"] = {"local sort\
sort = function(t, order_fn, only_strings)\
do\
local index\
do\
local _accum_0 = { }\
local _len_0 = 1\
for k, v in pairs(t) do\
if (not only_strings) or 'string' == type(k) then\
_accum_0[_len_0] = k\
_len_0 = _len_0 + 1\
end\
end\
index = _accum_0\
end\
table.sort(index, order_fn)\
return index\
end\
end\
local onext\
onext = function(state, key)\
state.i = state.i + state.step\
local t, index, i\
t, index, i = state.t, state.index, state.i\
do\
key = index[i]\
if key then\
return key, t[key]\
end\
end\
end\
local opairs\
opairs = function(t, order_fn, only_strings)\
if only_strings == nil then\
only_strings = false\
end\
local state = {\
t = t,\
i = 0,\
step = 1,\
index = sort(t, order_fn, only_strings)\
}\
return onext, state, nil\
end\
local ropairs\
ropairs = function(t, order_fn, only_strings)\
if only_strings == nil then\
only_strings = false\
end\
local index = sort(t, order_fn, only_strings)\
local state = {\
t = t,\
index = index,\
i = #index + 1,\
step = -1\
}\
return onext, state, nil\
end\
return {\
onext = onext,\
opairs = opairs,\
ropairs = ropairs\
}", "mmm/ordered.moon"}
p["mmm.mmmfs.fileder"] = {"local get_conversions, apply_conversions\
do\
local _obj_0 = require('mmm.mmmfs.conversion')\
get_conversions, apply_conversions = _obj_0.get_conversions, _obj_0.apply_conversions\
end\
local dir_base\
dir_base = function(path)\
local dir, base = path:match('(.-)([^/]-)$')\
if dir and #dir > 0 then\
dir = dir:sub(1, #dir - 1)\
end\
return dir, base\
end\
local Key\
do\
local _class_0\
local _base_0 = {\
tostring = function(self, strict)\
if strict == nil then\
strict = false\
end\
if not strict and self.name == '' then\
return self.type\
else\
return tostring(self.name) .. \": \" .. tostring(self.type)\
end\
end,\
__tostring = function(self)\
return self:tostring()\
end\
}\
_base_0.__index = _base_0\
_class_0 = setmetatable({\
__init = function(self, opts, second)\
if 'string' == type(second) then\
self.name, self.type = (opts or ''), second\
elseif 'string' == type(opts) then\
self.name, self.type = opts:match('^([%w-_]*): *(.+)$')\
if not self.name then\
self.name = ''\
self.type = opts:match('^ *(.+)$')\
end\
elseif 'table' == type(opts) then\
self.name = opts.name or ''\
self.type = opts.type\
else\
error(\"wrong argument type: \" .. tostring(type(opts)) .. \", \" .. tostring(type(second)))\
end\
assert(('string' == type(self.name)), \"name is not a string: '\" .. tostring(self.name) .. \"'\")\
return assert(('string' == type(self.type)), \"type is not a string: '\" .. tostring(self.type) .. \"'\")\
end,\
__base = _base_0,\
__name = \"Key\"\
}, {\
__index = _base_0,\
__call = function(cls, ...)\
local _self_0 = setmetatable({}, _base_0)\
cls.__init(_self_0, ...)\
return _self_0\
end\
})\
_base_0.__class = _class_0\
Key = _class_0\
end\
local inext\
inext = function(tbl, i)\
i = i + 1\
do\
local v = tbl[i]\
if v then\
return i, v\
end\
end\
end\
local Fileder\
do\
local _class_0\
local _base_0 = {\
load = function(self, index)\
assert(not self.loaded, \"already loaded!\")\
self.loaded = true\
index = index or self.store:get_index(self.path)\
local _list_0 = index.children\
for _index_0 = 1, #_list_0 do\
local path_or_index = _list_0[_index_0]\
local child = Fileder(self.store, path_or_index, self.root)\
local name = child:get('name: alpha')\
if '$' ~= name:sub(1, 1) then\
table.insert(self.children, child)\
else\
self.children[name] = child\
end\
end\
local _list_1 = index.facets\
for _index_0 = 1, #_list_1 do\
local key = _list_1[_index_0]\
key = Key(key)\
self.facet_keys[key] = key\
if MODE == 'CLIENT' and key.type:match('text/moonscript') then\
local copy = Key(key.name, key.type:gsub('text/moonscript', 'text/lua'))\
self.facet_keys[copy] = copy\
end\
end\
local _, name = dir_base(self.path)\
local name_key = Key('name: alpha')\
self.facet_keys[name_key] = name_key\
self.facets[name_key] = name\
end,\
walk = function(self, path)\
if path == '' then\
return self\
end\
if '/' ~= path:sub(1, 1) then\
path = tostring(self.path) .. \"/\" .. tostring(path)\
end\
if not (self.path == path:sub(1, #self.path)) then\
return \
end\
if #path == #self.path then\
return self\
end\
if not (self.loaded) then\
self:load()\
end\
do\
local match = self.children['$mmm'] and self.children['$mmm']:walk(path)\
if match then\
return match\
end\
end\
local _list_0 = self.children\
for _index_0 = 1, #_list_0 do\
local child = _list_0[_index_0]\
do\
local match = child:walk(path)\
if match then\
return match\
end\
end\
end\
end,\
mount = function(self, path, mount_as)\
if not mount_as then\
path = path .. self:gett('name: alpha')\
end\
assert(not self.path or self.path == path, \"mounted twice: \" .. tostring(self.path) .. \" and now \" .. tostring(path))\
self.path = path\
local _list_0 = self.children\
for _index_0 = 1, #_list_0 do\
local child = _list_0[_index_0]\
child:mount(self.path .. '/')\
end\
end,\
iterate = function(self, depth)\
if depth == nil then\
depth = 0\
end\
coroutine.yield(self)\
if depth == 1 then\
return \
end\
local _list_0 = self.children\
for _index_0 = 1, #_list_0 do\
local child = _list_0[_index_0]\
child:iterate(depth - 1)\
end\
end,\
get_facets = function(self)\
local names = { }\
for str, key in pairs(self.facet_keys) do\
names[key.name] = true\
end\
local _accum_0 = { }\
local _len_0 = 1\
for name in pairs(names) do\
_accum_0[_len_0] = name\
_len_0 = _len_0 + 1\
end\
return _accum_0\
end,\
has = function(self, ...)\
local want = Key(...)\
return self.facet_keys[want]\
end,\
has_facet = function(self, want)\
for str, key in pairs(self.facet_keys) do\
local _continue_0 = false\
repeat\
if key.original then\
_continue_0 = true\
break\
end\
if key.name == want then\
return key\
end\
_continue_0 = true\
until true\
if not _continue_0 then\
break\
end\
end\
end,\
find = function(self, key, key2, ...)\
local want = Key(key, key2)\
local matching\
do\
local _accum_0 = { }\
local _len_0 = 1\
for str, key in pairs(self.facet_keys) do\
if key.name == want.name then\
_accum_0[_len_0] = key\
_len_0 = _len_0 + 1\
end\
end\
matching = _accum_0\
end\
if not (#matching > 0) then\
return \
end\
local shortest_path, start = get_conversions(self, want.type, (function()\
local _accum_0 = { }\
local _len_0 = 1\
for _index_0 = 1, #matching do\
local key = matching[_index_0]\
_accum_0[_len_0] = key.type\
_len_0 = _len_0 + 1\
end\
return _accum_0\
end)(), ...)\
if start then\
for _index_0 = 1, #matching do\
local key = matching[_index_0]\
if key.type == start then\
return key, shortest_path\
end\
end\
return error(\"couldn't find key after resolution?\")\
end\
end,\
get = function(self, ...)\
local want = Key(...)\
do\
local val = self.facets[want]\
if val then\
return val, want\
end\
end\
do\
local val = CACHE and CACHE:get(self, want)\
if val then\
return val, want\
end\
end\
local key, conversions = self:find(want)\
if key then\
local value = apply_conversions(self, conversions, self.facets[key], key)\
if CACHE then\
CACHE:set(self, want, value)\
end\
return value, key\
end\
end,\
gett = function(self, ...)\
local want = Key(...)\
local value, key = self:get(want)\
assert(value, tostring(self) .. \" doesn't have value for '\" .. tostring(want) .. \"'\")\
return value, key\
end,\
set = function(self, key, key2, value)\
if value then\
key = Key(key, key2)\
else\
key = Key(key)\
value = key2\
end\
if value == nil then\
self.store:remove_facet(self.path, key.name, key.type)\
elseif self.facet_keys[key] then\
self.store:update_facet(self.path, key.name, key.type, value)\
else\
self.store:create_facet(self.path, key.name, key.type, value)\
end\
self.facets[key] = value\
end,\
add_child = function(self, name)\
local new_path = self.store:create_fileder(self.path, name)\
do\
local new_child = Fileder(self.store, new_path, self.root)\
table.insert(self.children, new_child)\
return new_child\
end\
end,\
remove_child = function(self, i)\
local removed = table.remove(self.children, i)\
assert(removed, \"no such child fileder\")\
return self.store:remove_fileder(removed.path)\
end,\
swap_children = function(self, ia, ib)\
local a, b = self.children[ia], self.children[ib]\
self.store:swap_fileders(self.path, (a:gett('name: alpha')), (b:gett('name: alpha')))\
self.children[ia], self.children[ib] = b, a\
end,\
__tostring = function(self)\
return \"Fileder:\" .. tostring(self.path)\
end\
}\
_base_0.__index = _base_0\
_class_0 = setmetatable({\
__init = function(self, store, path, root)\
if path == nil then\
path = ''\
end\
if root == nil then\
root = self\
end\
self.store, self.path, self.root = store, path, root\
self.loaded = false\
self.children = setmetatable({ }, {\
__len = function(t)\
if not (self.loaded) then\
self:load()\
end\
return rawlen(t)\
end,\
__ipairs = function(t)\
if not (self.loaded) then\
self:load()\
end\
return inext, t, 0\
end,\
__index = function(t, k)\
if not (self.loaded) then\
self:load()\
end\
if 'string' == type(k) and '$' ~= k:sub(1, 1) then\
return self:walk(tostring(self.path) .. \"/\" .. tostring(k))\
end\
end,\
__newindex = function(t, k, child)\
rawset(t, k, child)\
if child.path then\
return \
end\
return child:mount(self.path .. '/')\
end\
})\
self.facet_keys = setmetatable({ }, {\
__pairs = function(t)\
if not (self.loaded) then\
self:load()\
end\
return next, t\
end,\
__index = function(t, k)\
local canonical = rawget(t, tostring(k))\
return canonical\
end,\
__newindex = function(t, k, v)\
k = Key(k)\
return rawset(t, (tostring(k)), v)\
end\
})\
self.facets = setmetatable({ }, {\
__index = function(t, k)\
if not (self.loaded) then\
self:load()\
end\
k = self.facet_keys[k]\
if not (k) then\
return \
end\
do\
local v = rawget(t, k)\
if v then\
return v\
end\
end\
do\
local v = self.store:load_facet(self.path, k.name, k.type)\
rawset(t, k, v)\
return v\
end\
end,\
__pairs = function(t)\
if not (self.loaded) then\
self:load()\
end\
for k, v in pairs(self.facet_keys) do\
local _ = t[v]\
end\
return next, t\
end,\
__newindex = function(t, k, v)\
local key = self.facet_keys[k]\
if not key then\
key = Key(k)\
self.facet_keys[key] = key\
end\
rawset(t, key, v)\
if not v then\
self.facet_keys[key] = nil\
end\
end\
})\
if 'table' == type(self.path) then\
local index = self.path\
self.path = index.path\
self:load(index)\
end\
return assert(('string' == type(self.path)), \"invalid path: '\" .. tostring(self.path) .. \"'\")\
end,\
__base = _base_0,\
__name = \"Fileder\"\
}, {\
__index = _base_0,\
__call = function(cls, ...)\
local _self_0 = setmetatable({}, _base_0)\
cls.__init(_self_0, ...)\
return _self_0\
end\
})\
_base_0.__class = _class_0\
Fileder = _class_0\
end\
return {\
Key = Key,\
Fileder = Fileder,\
dir_base = dir_base\
}", "mmm/mmmfs/fileder.moon"}
p["mmm.mmmfs.conversion"] = {"local refs = require('mmm.refs')\
local Queue\
Queue = require('mmm.mmmfs.queue').Queue\
local get_plugins\
get_plugins = require('mmm.mmmfs.meta').get_plugins\
local builtins = require('mmm.mmmfs.builtins')\
local count\
count = function(base, pattern)\
if pattern == nil then\
pattern = '->'\
end\
return select(2, base:gsub(pattern, ''))\
end\
local escape_pattern\
escape_pattern = function(inp)\
if '*' == inp:sub(-1) then\
inp = inp:sub(1, -2)\
return \"^\" .. tostring(inp:gsub('([^%w])', '%%%1'))\
else\
return \"^\" .. tostring(inp:gsub('([^%w])', '%%%1')) .. \"$\"\
end\
end\
local escape_inp\
escape_inp = function(inp)\
return \"^\" .. tostring(inp:gsub('([-/])', '%%%1')) .. \"$\"\
end\
local MermaidDebugger\
do\
local _class_0\
local _base_0 = {\
prepend = function(self, line)\
self.buf = \" \" .. tostring(line) .. \"\\n\" .. self.buf\
end,\
append = function(self, line)\
self.buf = self.buf .. \" \" .. tostring(line) .. \"\\n\"\
end,\
found_type = function(self, type)\
local type_id = self.type_id[type]\
end,\
type_cost = function(self, type, cost)\
do\
local old_cost = self.cost[type]\
if old_cost then\
cost = math.min(old_cost, cost)\
end\
end\
self.cost[type] = cost\
end,\
type_class = function(self, type, klass)\
return self:append(\"class \" .. tostring(self.type_id[type]) .. \" \" .. tostring(klass))\
end,\
found_link = function(self, frm, to, cost)\
return self:prepend(tostring(self.type_id[frm]) .. \" -- cost: \" .. tostring(cost) .. \" --> \" .. tostring(self.type_id[to]))\
end,\
render = function(self)\
for type, id in pairs(self.type_id) do\
local cost = self.cost[type] or -1\
self:prepend(tostring(id) .. \"[\\\"\" .. tostring(type) .. \" [\" .. tostring(cost) .. \"]\\\"]\")\
end\
self:append(\"classDef have fill:#ada\")\
self:append(\"classDef want fill:#add\")\
self:append(\"classDef cant fill:#daa\")\
return \"graph TD\\n\" .. self.buf\
end\
}\
_base_0.__index = _base_0\
_class_0 = setmetatable({\
__init = function(self)\
local nextid = 0\
self.type_id = setmetatable({ }, {\
__index = function(t, k)\
nextid = nextid + 1\
do\
local val = \"type-\" .. tostring(nextid)\
t[k] = val\
return val\
end\
end\
})\
self.cost = { }\
self.buf = \"\"\
end,\
__base = _base_0,\
__name = \"MermaidDebugger\"\
}, {\
__index = _base_0,\
__call = function(cls, ...)\
local _self_0 = setmetatable({}, _base_0)\
cls.__init(_self_0, ...)\
return _self_0\
end\
})\
_base_0.__class = _class_0\
MermaidDebugger = _class_0\
end\
local get_converts\
get_converts = function(fileder)\
local converts\
do\
local _accum_0 = { }\
local _len_0 = 1\
local _list_0 = builtins.converts\
for _index_0 = 1, #_list_0 do\
local c = _list_0[_index_0]\
_accum_0[_len_0] = c\
_len_0 = _len_0 + 1\
end\
converts = _accum_0\
end\
for plugin in get_plugins(fileder) do\
local _list_0 = (plugin:get('converts: table') or { })\
for _index_0 = 1, #_list_0 do\
local c = _list_0[_index_0]\
table.insert(converts, c)\
end\
end\
return converts\
end\
local get_conversions\
get_conversions = function(fileder, want, have, converts, limit, debug)\
if limit == nil then\
limit = 5\
end\
converts = converts or get_converts(fileder)\
assert(have, 'need starting type(s)')\
assert(converts, 'need to pass list of converts')\
if 'string' == type(have) then\
have = {\
have\
}\
end\
assert(#have > 0, 'need starting type(s) (list was empty)')\
want = escape_pattern(want)\
limit = limit + 3 * math.max(table.unpack((function()\
local _accum_0 = { }\
local _len_0 = 1\
for _index_0 = 1, #have do\
local type = have[_index_0]\
_accum_0[_len_0] = count(type)\
_len_0 = _len_0 + 1\
end\
return _accum_0\
end)()))\
if debug then\
debug:found_type(want)\
debug:type_cost(want, limit)\
debug:type_class(want, 'want')\
end\
local had = { }\
local queue = Queue()\
for _index_0 = 1, #have do\
local start = have[_index_0]\
if start:match(want) then\
return { }, start\
end\
queue:add({\
start = start,\
rest = start,\
conversions = { }\
}, 0, start)\
if debug then\
debug:found_type(start)\
debug:type_cost(start, 0)\
debug:type_class(start, 'have')\
end\
end\
local best = Queue()\
while true do\
local entry, cost = queue:pop()\
if not entry then\
break\
end\
if cost > limit then\
if debug then\
debug:type_class(entry.rest, 'cant')\
end\
break\
end\
local start, rest, conversions\
start, rest, conversions = entry.start, entry.rest, entry.conversions\
had[rest] = true\
for _index_0 = 1, #converts do\
local _continue_0 = false\
repeat\
local convert = converts[_index_0]\
local inp = escape_inp(convert.inp)\
if not (rest:match(inp)) then\
_continue_0 = true\
break\
end\
local result = rest:gsub(inp, convert.out)\
if not (result) then\
_continue_0 = true\
break\
end\
if had[result] then\
_continue_0 = true\
break\
end\
local next_entry = {\
start = start,\
rest = result,\
cost = cost + convert.cost,\
conversions = {\
{\
convert = convert,\
from = rest,\
to = result\
},\
table.unpack(conversions)\
}\
}\
if debug then\
debug:found_type(result)\
debug:type_cost(result, next_entry.cost)\
debug:found_link(rest, result, convert.cost)\
end\
if result:match(want) then\
best:add(next_entry, next_entry.cost)\
if debug then\
debug:found_link(result, want, 0)\
end\
else\
queue:add(next_entry, next_entry.cost, result)\
end\
_continue_0 = true\
until true\
if not _continue_0 then\
break\
end\
end\
end\
do\
local solution = best:pop()\
if solution then\
if solution then\
return solution.conversions, solution.start\
end\
end\
end\
end\
local print_conversions\
print_conversions = function(conversions)\
print(\"converting:\")\
for i = #conversions, 1, -1 do\
local step = conversions[i]\
print(\"- \" .. tostring(step.from) .. \" -> \" .. tostring(step.to) .. \" (\" .. tostring(step.convert.cost) .. \")\")\
end\
end\
local err_and_trace\
err_and_trace = function(msg)\
return debug.traceback(msg, 2)\
end\
local apply_conversions\
apply_conversions = function(fileder, conversions, value, key)\
for i = #conversions, 1, -1 do\
refs:push()\
local step = conversions[i]\
local ok\
ok, value = xpcall(step.convert.transform, err_and_trace, step, value, fileder, key)\
refs:pop()\
if not ok then\
error(\"error while converting \" .. tostring(fileder) .. \" \" .. tostring(key) .. \" from '\" .. tostring(step.from) .. \"' to '\" .. tostring(step.to) .. \"':\\n\" .. tostring(value))\
end\
end\
return value\
end\
local convert\
convert = function(have, want, value, fileder, key)\
local conversions, start = get_conversions(fileder, want, have)\
if not conversions then\
warn(\"couldn't convert from '\" .. tostring(have) .. \"' to '\" .. tostring(want) .. \"'\")\
return \
end\
if 'string' ~= type(have) then\
value = value[start]\
end\
return apply_conversions(fileder, conversions, value, key)\
end\
return {\
MermaidDebugger = MermaidDebugger,\
get_conversions = get_conversions,\
apply_conversions = apply_conversions,\
convert = convert\
}", "mmm/mmmfs/conversion.moon"}
p["mmm.mmmfs.cache"] = {"local Cache\
do\
local _class_0\
local _base_0 = {\
get = function(self, fileder, key)\
key = tostring(key)\
local _update_0 = fileder.path\
self.cache[_update_0] = self.cache[_update_0] or { }\
return self.cache[fileder.path][key]\
end,\
set = function(self, fileder, key, val)\
key = tostring(key)\
local _update_0 = fileder.path\
self.cache[_update_0] = self.cache[_update_0] or { }\
self.cache[fileder.path][key] = val\
end\
}\
_base_0.__index = _base_0\
_class_0 = setmetatable({\
__init = function(self)\
self.cache = { }\
end,\
__base = _base_0,\
__name = \"Cache\"\
}, {\
__index = _base_0,\
__call = function(cls, ...)\
local _self_0 = setmetatable({}, _base_0)\
cls.__init(_self_0, ...)\
return _self_0\
end\
})\
_base_0.__class = _class_0\
Cache = _class_0\
end\
local init_cache\
init_cache = function()\
CACHE = Cache()\
end\
return {\
init_cache = init_cache\
}", "mmm/mmmfs/cache.moon"}
p["mmm.mmmfs.queue"] = {"local Queue\
do\
local _class_0\
local _base_0 = {\
add = function(self, value, priority, key)\
local entry = {\
value = value,\
key = key,\
priority = priority\
}\
if key then\
do\
local old_entry = self.index[key]\
if old_entry then\
if old_entry.priority < priority then\
return \
end\
local i\
for ii, entry in ipairs(self.values) do\
if entry == old_entry then\
i = ii\
break\
end\
end\
table.remove(self.values, i)\
end\
end\
self.index[key] = entry\
end\
for i, v in ipairs(self.values) do\
if v.priority < priority then\
table.insert(self.values, i, entry)\
return \
end\
end\
return table.insert(self.values, entry)\
end,\
peek = function(self)\
local entry = self.values[#self.values]\
if entry then\
local value, priority, key\
value, priority, key = entry.value, entry.priority, entry.key\
if key then\
self.index[key] = nil\
end\
return value, priority\
end\
end,\
pop = function(self)\
local entry = table.remove(self.values)\
if entry then\
local value, priority, key\
value, priority, key = entry.value, entry.priority, entry.key\
if key then\
self.index[key] = nil\
end\
return value, priority\
end\
end,\
poll = function(self)\
return self.pop, self\
end\
}\
_base_0.__index = _base_0\
_class_0 = setmetatable({\
__init = function(self)\
self.values = { }\
self.index = { }\
end,\
__base = _base_0,\
__name = \"Queue\"\
}, {\
__index = _base_0,\
__call = function(cls, ...)\
local _self_0 = setmetatable({}, _base_0)\
cls.__init(_self_0, ...)\
return _self_0\
end\
})\
_base_0.__class = _class_0\
Queue = _class_0\
end\
return {\
Queue = Queue\
}", "mmm/mmmfs/queue.moon"}
p["mmm.mmmfs.stores"] = {"local Store\
do\
local _class_0\
local _base_0 = {\
list_fileders_in = function(self)\
return error(\"not implemented\")\
end,\
list_all_fileders = function(self, path)\
if path == nil then\
path = ''\
end\
return coroutine.wrap(function()\
for path in self:list_fileders_in(path) do\
coroutine.yield(path)\
for p in self:list_all_fileders(path) do\
coroutine.yield(p)\
end\
end\
end)\
end,\
get_index = function(self, path, depth)\
if path == nil then\
path = ''\
end\
if depth == nil then\
depth = 1\
end\
if depth == 0 then\
return path\
end\
return {\
path = path,\
facets = (function()\
local _accum_0 = { }\
local _len_0 = 1\
for name, type in self:list_facets(path) do\
_accum_0[_len_0] = {\
name = name,\
type = type\
}\
_len_0 = _len_0 + 1\
end\
return _accum_0\
end)(),\
children = (function()\
local _accum_0 = { }\
local _len_0 = 1\
for child in self:list_fileders_in(path) do\
_accum_0[_len_0] = self:get_index(child, depth - 1)\
_len_0 = _len_0 + 1\
end\
return _accum_0\
end)()\
}\
end,\
create_fileder = function(self)\
return error(\"not implemented\")\
end,\
remove_fileder = function(self)\
return error(\"not implemented\")\
end,\
rename_fileder = function(self)\
return error(\"not implemented\")\
end,\
move_fileder = function(self)\
return error(\"not implemented\")\
end,\
list_facets = function(self)\
return error(\"not implemented\")\
end,\
create_facet = function(self)\
return error(\"not implemented\")\
end,\
remove_facet = function(self)\
return error(\"not implemented\")\
end,\
load_facet = function(self)\
return error(\"not implemented\")\
end,\
rename_facet = function(self, path, name, type, next_name)\
self:log(\"renaming facet \" .. tostring(path) .. \" | \" .. tostring(name) .. \": \" .. tostring(type) .. \" -> \" .. tostring(next_name))\
local blob = assert(\"no such facet\", self:load_facet(path, name, type))\
self:create_facet(path, next_name, type, blob)\
return self:remove_facet(path, name, type({\
update_facet = function(self)\
return error(\"not implemented\")\
end\
}))\
end,\
close = function(self) end,\
fsck = function(self) end,\
log = function(self, ...)\
return print(\"[\" .. tostring(self.__class.__name) .. \"]\", ...)\
end\
}\
_base_0.__index = _base_0\
_class_0 = setmetatable({\
__init = function(self, opts)\
opts.verbose = opts.verbose or false\
if not opts.verbose then\
self.log = function() end\
end\
end,\
__base = _base_0,\
__name = \"Store\"\
}, {\
__index = _base_0,\
__call = function(cls, ...)\
local _self_0 = setmetatable({}, _base_0)\
cls.__init(_self_0, ...)\
return _self_0\
end\
})\
_base_0.__class = _class_0\
Store = _class_0\
end\
local get_store\
get_store = function(args, opts)\
if args == nil then\
args = 'fs'\
end\
if opts == nil then\
opts = { }\
end\
local type, arg = args:match('(%w+):(.*)')\
if not (type) then\
type = args\
end\
local _exp_0 = type:lower()\
if 'sql' == _exp_0 then\
local SQLStore\
SQLStore = require('mmm.mmmfs.stores.sql').SQLStore\
if arg == 'MEMORY' then\
opts.memory = true\
else\
opts.file = arg\
end\
return SQLStore(opts)\
elseif 'fs' == _exp_0 then\
local FSStore\
FSStore = require('mmm.mmmfs.stores.fs').FSStore\
opts.root = arg\
return FSStore(opts)\
else\
warn(\"unknown or missing value for STORE: valid types values are sql, fs\")\
return os.exit(1)\
end\
end\
return {\
Store = Store,\
get_store = get_store\
}", "mmm/mmmfs/stores/init.moon"}
p["mmm.mmmfs.stores.web"] = {"local Store\
Store = require('mmm.mmmfs.stores').Store\
local location, XMLHttpRequest, JSON, Object, Array\
do\
local _obj_0 = js.global\
location, XMLHttpRequest, JSON, Object, Array = _obj_0.location, _obj_0.XMLHttpRequest, _obj_0.JSON, _obj_0.Object, _obj_0.Array\
end\
local dir_base\
dir_base = function(path)\
local dir, base = path:match('(.-)([^/]-)$')\
if dir and #dir > 0 then\
dir = dir:sub(1, #dir - 1)\
end\
return dir, base\
end\
local req\
req = function(method, url, content)\
if content == nil then\
content = js.null\
end\
if not url then\
url = method\
method = 'GET'\
end\
local request = js.new(XMLHttpRequest)\
request:open(method, url, false)\
request:send(content)\
assert(request.status == 200, \"unexpected status code: \" .. tostring(request.status))\
return request.responseText\
end\
local parse_json\
do\
local fix\
fix = function(val)\
local _exp_0 = type(val)\
if 'userdata' == _exp_0 then\
if Array:isArray(val) then\
local _accum_0 = { }\
local _len_0 = 1\
for x in js.of(val) do\
_accum_0[_len_0] = fix(x)\
_len_0 = _len_0 + 1\
end\
return _accum_0\
else\
local _tbl_0 = { }\
for e in js.of(Object:entries(val)) do\
_tbl_0[(fix(e[0]))] = (fix(e[1]))\
end\
return _tbl_0\
end\
else\
return val\
end\
end\
parse_json = function(string)\
return fix(JSON:parse(string))\
end\
end\
local WebStore\
do\
local _class_0\
local _parent_0 = Store\
local _base_0 = {\
get_index = function(self, path, depth)\
if path == nil then\
path = ''\
end\
if depth == nil then\
depth = 1\
end\
local pseudo\
if depth > 1 or depth < 0 then\
pseudo = '?tree'\
else\
pseudo = '?index'\
end\
local json = req(tostring(self.host .. path) .. \"/\" .. tostring(pseudo) .. \": text/json\")\
return parse_json(json)\
end,\
list_fileders_in = function(self, path)\
if path == nil then\
path = ''\
end\
return coroutine.wrap(function()\
local json = req(tostring(self.host .. path) .. \"/?index: text/json\")\
local index = parse_json(json)\
for child in js.of(index.children) do\
coroutine.yield(child.path)\
end\
end)\
end,\
create_fileder = function(self, parent, name)\
local path = tostring(parent) .. \"/\" .. tostring(name)\
self:log(\"creating fileder \" .. tostring(path))\
return req('POST', tostring(self.host .. path) .. \"/\")\
end,\
remove_fileder = function(self, path)\
self:log(\"removing fileder \" .. tostring(path))\
return req('DELETE', tostring(self.host .. path) .. \"/\")\
end,\
rename_fileder = function(self, path, next_name)\
self:log(\"renaming fileder \" .. tostring(path) .. \" -> '\" .. tostring(next_name) .. \"'\")\
return error(\"not implemented\")\
end,\
move_fileder = function(self, path, next_parent)\
self:log(\"moving fileder \" .. tostring(path) .. \" -> \" .. tostring(next_parent) .. \"/\")\
return error(\"not implemented\")\
end,\
swap_fileders = function(self, parent, child_a, child_b)\
return req('PUT', tostring(self.host .. parent) .. \"/\", \"swap\\n\" .. tostring(child_a) .. \"\\n\" .. tostring(child_b))\
end,\
list_facets = function(self, path)\
return coroutine.wrap(function()\
local json = req(tostring(self.host .. path) .. \"/?index: text/json\")\
local index = JSON:parse(json)\
for facet in js.of(index.facets) do\
coroutine.yield(facet.name, facet.type)\
end\
end)\
end,\
load_facet = function(self, path, name, type)\
self:log(\"loading facet \" .. tostring(path) .. \" \" .. tostring(name) .. \": \" .. tostring(type))\
return req(tostring(self.host .. path) .. \"/\" .. tostring(name) .. \": \" .. tostring(type))\
end,\
create_facet = function(self, path, name, type, blob)\
self:log(\"creating facet \" .. tostring(path) .. \" | \" .. tostring(name) .. \": \" .. tostring(type))\
return req('POST', tostring(self.host .. path) .. \"/\" .. tostring(name) .. \": \" .. tostring(type), blob)\
end,\
remove_facet = function(self, path, name, type)\
self:log(\"removing facet \" .. tostring(path) .. \" | \" .. tostring(name) .. \": \" .. tostring(type))\
return req('DELETE', tostring(self.host .. path) .. \"/\" .. tostring(name) .. \": \" .. tostring(type))\
end,\
rename_facet = function(self, path, name, type, next_name)\
self:log(\"renaming facet \" .. tostring(path) .. \" | \" .. tostring(name) .. \": \" .. tostring(type) .. \" -> \" .. tostring(next_name))\
local blob = assert(\"no such facet\", self:load_facet(path, name, type))\
self:create_facet(path, next_name, type, blob)\
return self:remove_facet(path, name, type)\
end,\
update_facet = function(self, path, name, type, blob)\
self:log(\"updating facet \" .. tostring(path) .. \" | \" .. tostring(name) .. \": \" .. tostring(type))\
return req('PUT', tostring(self.host .. path) .. \"/\" .. tostring(name) .. \": \" .. tostring(type), blob)\
end\
}\
_base_0.__index = _base_0\
setmetatable(_base_0, _parent_0.__base)\
_class_0 = setmetatable({\
__init = function(self, opts)\
if opts == nil then\
opts = { }\
end\
_class_0.__parent.__init(self, opts)\
if MODE == 'CLIENT' then\
local origin = location.origin\
opts.host = opts.host or origin\
end\
self.host = opts.host:match('^(.-)/?$')\
return self:log(\"connecting to '\" .. tostring(self.host) .. \"'...\")\
end,\
__base = _base_0,\
__name = \"WebStore\",\
__parent = _parent_0\
}, {\
__index = function(cls, name)\
local val = rawget(_base_0, name)\
if val == nil then\
local parent = rawget(cls, \"__parent\")\
if parent then\
return parent[name]\
end\
else\
return val\
end\
end,\
__call = function(cls, ...)\
local _self_0 = setmetatable({}, _base_0)\
cls.__init(_self_0, ...)\
return _self_0\
end\
})\
_base_0.__class = _class_0\
if _parent_0.__inherited then\
_parent_0.__inherited(_parent_0, _class_0)\
end\
WebStore = _class_0\
end\
return {\
WebStore = WebStore\
}", "mmm/mmmfs/stores/web.moon"}
p["mmm.mmmfs.stores.sql"] = {"local sqlite = require('sqlite3')\
local Store\
Store = require('mmm.mmmfs.stores').Store\
local SQLStore\
do\
local _class_0\
local _parent_0 = Store\
local _base_0 = {\
close = function(self)\
return self.db:close()\
end,\
fetch = function(self, q, ...)\
local stmt = assert(self.db:prepare(q))\
if 0 < select('#', ...) then\
stmt:bind(...)\
end\
return stmt:irows()\
end,\
fetch_one = function(self, q, ...)\
local stmt = assert(self.db:prepare(q))\
if 0 < select('#', ...) then\
stmt:bind(...)\
end\
return stmt:first_irow()\
end,\
exec = function(self, q, ...)\
local stmt = assert(self.db:prepare(q))\
if 0 < select('#', ...) then\
stmt:bind(...)\
end\
local res = assert(stmt:exec())\
end,\
list_fileders_in = function(self, path)\
if path == nil then\
path = ''\
end\
return coroutine.wrap(function()\
for _des_0 in self:fetch('SELECT path\\n FROM fileder WHERE parent IS ?', path) do\
path = _des_0[1]\
coroutine.yield(path)\
end\
end)\
end,\
create_fileder = function(self, parent, name)\
local path = tostring(parent) .. \"/\" .. tostring(name)\
self:log(\"creating fileder \" .. tostring(path))\
self:exec('INSERT INTO fileder (path, parent)\\n VALUES (:path, :parent)', {\
path = path,\
parent = parent\
})\
local changes = self:fetch_one('SELECT changes()')\
assert(changes[1] == 1, \"couldn't create fileder - parent missing?\")\
return path\
end,\
remove_fileder = function(self, path)\
self:log(\"removing fileder \" .. tostring(path))\
return self:exec('DELETE FROM fileder\\n WHERE path LIKE :path || \"/%\"\\n OR path = :path', path)\
end,\
rename_fileder = function(self, path, next_name)\
self:log(\"renaming fileder \" .. tostring(path) .. \" -> '\" .. tostring(next_name) .. \"'\")\
error('not implemented')\
return self:exec('UPDATE fileder\\n SET path = parent || \"/\" || :next_name\\n WHERE path = :path', {\
path = path,\
next_name = next_name\
})\
end,\
move_fileder = function(self, path, next_parent)\
self:log(\"moving fileder \" .. tostring(path) .. \" -> \" .. tostring(next_parent) .. \"/\")\
return error('not implemented')\
end,\
list_facets = function(self, path)\
return coroutine.wrap(function()\
for _des_0 in self:fetch('SELECT facet.name, facet.type\\n FROM facet\\n INNER JOIN fileder ON facet.fileder_id = fileder.id\\n WHERE fileder.path = ?', path) do\
local name, type\
name, type = _des_0[1], _des_0[2]\
coroutine.yield(name, type)\
end\
end)\
end,\
load_facet = function(self, path, name, type)\
local v = self:fetch_one('SELECT facet.value\\n FROM facet\\n INNER JOIN fileder ON facet.fileder_id = fileder.id\\n WHERE fileder.path = :path\\n AND facet.name = :name\\n AND facet.type = :type', {\
path = path,\
name = name,\
type = type\
})\
return v and v[1]\
end,\
create_facet = function(self, path, name, type, blob)\
self:log(\"creating facet \" .. tostring(path) .. \" | \" .. tostring(name) .. \": \" .. tostring(type))\
self:exec('INSERT INTO facet (fileder_id, name, type, value)\\n SELECT id, :name, :type, :blob\\n FROM fileder\\n WHERE fileder.path = :path', {\
path = path,\
name = name,\
type = type,\
blob = blob\
})\
local changes = self:fetch_one('SELECT changes()')\
return assert(changes[1] == 1, \"couldn't create facet - fileder missing?\")\
end,\
remove_facet = function(self, path, name, type)\
self:log(\"removing facet \" .. tostring(path) .. \" | \" .. tostring(name) .. \": \" .. tostring(type))\
self:exec('DELETE FROM facet\\n WHERE name = :name\\n AND type = :type\\n AND fileder_id = (SELECT id FROM fileder WHERE path = :path)', {\
path = path,\
name = name,\
type = type\
})\
local changes = self:fetch_one('SELECT changes()')\
return assert(changes[1] == 1, \"no such facet\")\
end,\
rename_facet = function(self, path, name, type, next_name)\
self:log(\"renaming facet \" .. tostring(path) .. \" | \" .. tostring(name) .. \": \" .. tostring(type) .. \" -> \" .. tostring(next_name))\
self:exec('UPDATE facet\\n SET name = :next_name\\n WHERE name = :name\\n AND type = :type\\n AND fileder_id = (SELECT id FROM fileder WHERE path = :path)', {\
path = path,\
name = name,\
next_name = next_name,\
type = type\
})\
local changes = self:fetch_one('SELECT changes()')\
return assert(changes[1] == 1, \"no such facet\")\
end,\
update_facet = function(self, path, name, type, blob)\
self:log(\"updating facet \" .. tostring(path) .. \" | \" .. tostring(name) .. \": \" .. tostring(type))\
self:exec('UPDATE facet\\n SET value = :blob\\n WHERE facet.name = :name\\n AND facet.type = :type\\n AND facet.fileder_id = (SELECT id FROM fileder WHERE path = :path)', {\
path = path,\
name = name,\
type = type,\
blob = blob\
})\
local changes = self:fetch_one('SELECT changes()')\
return assert(changes[1] == 1, \"no such facet\")\
end\
}\
_base_0.__index = _base_0\
setmetatable(_base_0, _parent_0.__base)\
_class_0 = setmetatable({\
__init = function(self, opts)\
if opts == nil then\
opts = { }\
end\
_class_0.__parent.__init(self, opts)\
opts.file = opts.file or 'db.sqlite3'\
opts.memory = opts.memory or false\
if opts.memory then\
self:log(\"opening in-memory DB...\")\
self.db = sqlite.open_memory()\
else\
self:log(\"opening '\" .. tostring(opts.file) .. \"'...\")\
self.db = sqlite.open(opts.file)\
end\
return assert(self.db:exec([[ PRAGMA foreign_keys = ON;\
PRAGMA case_sensitive_like = ON;\
CREATE TABLE IF NOT EXISTS fileder (\
id INTEGER NOT NULL PRIMARY KEY,\
path TEXT NOT NULL UNIQUE,\
parent TEXT REFERENCES fileder(path)\
ON DELETE CASCADE\
ON UPDATE CASCADE\
);\
INSERT OR IGNORE INTO fileder (path, parent) VALUES (\"\", NULL);\
\
CREATE TABLE IF NOT EXISTS facet (\
fileder_id INTEGER NOT NULL\
REFERENCES fileder\
ON UPDATE CASCADE\
ON DELETE CASCADE,\
name TEXT NOT NULL,\
type TEXT NOT NULL,\
value BLOB NOT NULL,\
PRIMARY KEY (fileder_id, name, type)\
);\
CREATE INDEX IF NOT EXISTS facet_fileder_id ON facet(fileder_id);\
CREATE INDEX IF NOT EXISTS facet_name ON facet(name);\
]]))\
end,\
__base = _base_0,\
__name = \"SQLStore\",\
__parent = _parent_0\
}, {\
__index = function(cls, name)\
local val = rawget(_base_0, name)\
if val == nil then\
local parent = rawget(cls, \"__parent\")\
if parent then\
return parent[name]\
end\
else\
return val\
end\
end,\
__call = function(cls, ...)\
local _self_0 = setmetatable({}, _base_0)\
cls.__init(_self_0, ...)\
return _self_0\
end\
})\
_base_0.__class = _class_0\
if _parent_0.__inherited then\
_parent_0.__inherited(_parent_0, _class_0)\
end\
SQLStore = _class_0\
end\
return {\
SQLStore = SQLStore\
}", "mmm/mmmfs/stores/sql.moon"}
p["mmm.mmmfs.stores.fs"] = {"local lfs = require('lfs')\
local Store\
Store = require('mmm.mmmfs.stores').Store\
local dir_base\
dir_base = function(path)\
local dir, base = path:match('(.-)([^/]-)$')\
if dir and #dir > 0 then\
dir = dir:sub(1, #dir - 1)\
end\
return dir, base\
end\
local FSStore\
do\
local _class_0\
local _parent_0 = Store\
local _base_0 = {\
get_order = function(self, path, forgiving, include_meta)\
if forgiving == nil then\
forgiving = false\
end\
if include_meta == nil then\
include_meta = false\
end\
local entries = { }\
local sorted = { }\
for name in lfs.dir(self.root .. path) do\
local _continue_0 = false\
repeat\
if '.' == name:sub(1, 1) then\
_continue_0 = true\
break\
end\
if '$' == name:sub(1, 1) and not include_meta then\
_continue_0 = true\
break\
end\
local entry_path = tostring(self.root) .. tostring(path) .. \"/\" .. tostring(name)\
if 'directory' ~= lfs.attributes(entry_path, 'mode') then\
_continue_0 = true\
break\
end\
local entry = {\
name = name,\
path = tostring(path) .. \"/\" .. tostring(name)\
}\
entries[name] = entry\
if '$' == name:sub(1, 1) then\
table.insert(sorted, entry)\
sorted[name] = true\
end\
_continue_0 = true\
until true\
if not _continue_0 then\
break\
end\
end\
local order_file = tostring(self.root) .. tostring(path) .. \"/$order\"\
if 'file' == lfs.attributes(order_file, 'mode') then\
for line in io.lines(order_file) do\
local _continue_0 = false\
repeat\
local entry = entries[line]\
if not entry then\
if forgiving then\
self:log(\"removed stale entry '\" .. tostring(line) .. \"' from \" .. tostring(path) .. \"/$order\")\
_continue_0 = true\
break\
end\
error(\"entry in $order but not on disk: \" .. tostring(line) .. \" (at \" .. tostring(path) .. \")\")\
end\
table.insert(sorted, entry)\
sorted[line] = true\
_continue_0 = true\
until true\
if not _continue_0 then\
break\
end\
end\
else\
forgiving = true\
end\
local unsorted\
do\
local _accum_0 = { }\
local _len_0 = 1\
for name, entry in pairs(entries) do\
if not sorted[entry.name] then\
_accum_0[_len_0] = entry\
_len_0 = _len_0 + 1\
end\
end\
unsorted = _accum_0\
end\
if forgiving then\
for _index_0 = 1, #unsorted do\
local entry = unsorted[_index_0]\
self:log(\"adding new entry '\" .. tostring(entry.name) .. \"' in \" .. tostring(path) .. \"/$order\")\
table.insert(sorted, entry)\
end\
else\
assert(#unsorted == 0, unsorted[1] and \"entry on disk but not in $order: \" .. tostring(unsorted[1].path) .. \" (at \" .. tostring(path) .. \")\")\
end\
return sorted\
end,\
write_order = function(self, path, order)\
if order == nil then\
order = self:get_order(path, true)\
end\
local order_file = tostring(self.root) .. tostring(path) .. \"/$order\"\
if #order == 0 then\
os.remove(order_file)\
return \
end\
local file = assert(io.open(order_file, 'w'))\
for _index_0 = 1, #order do\
local _des_0 = order[_index_0]\
local name\
name = _des_0.name\
file:write(tostring(name) .. \"\\n\")\
end\
return file:close()\
end,\
list_fileders_in = function(self, path)\
if path == nil then\
path = ''\
end\
local sorted = self:get_order(path, nil, true)\
return coroutine.wrap(function()\
for _index_0 = 1, #sorted do\
local _des_0 = sorted[_index_0]\
path = _des_0.path\
coroutine.yield(path)\
end\
end)\
end,\
create_fileder = function(self, parent, name)\
local path = tostring(parent) .. \"/\" .. tostring(name)\
self:log(\"creating fileder \" .. tostring(path))\
assert(lfs.mkdir(self.root .. path))\
self:write_order(parent)\
return path\
end,\
remove_fileder = function(self, path)\
self:log(\"removing fileder \" .. tostring(path))\
local rmdir\
rmdir = function(path)\
for file in lfs.dir(path) do\
local _continue_0 = false\
repeat\
if '.' == file:sub(1, 1) then\
_continue_0 = true\
break\
end\
local file_path = tostring(path) .. \"/\" .. tostring(file)\
local _exp_0 = lfs.attributes(file_path, 'mode')\
if 'file' == _exp_0 then\
assert(os.remove(file_path))\
elseif 'directory' == _exp_0 then\
assert(rmdir(file_path))\
end\
_continue_0 = true\
until true\
if not _continue_0 then\
break\
end\
end\
return lfs.rmdir(path)\
end\
rmdir(self.root .. path)\
local parent = dir_base(path)\
return self:write_order(parent)\
end,\
rename_fileder = function(self, path, next_name)\
self:log(\"renaming fileder \" .. tostring(path) .. \" -> '\" .. tostring(next_name) .. \"'\")\
local parent, name = dir_base(path)\
return assert(os.rename(path, tostring(self.root) .. tostring(parent) .. \"/\" .. tostring(next_name)))\
end,\
move_fileder = function(self, path, next_parent)\
self:log(\"moving fileder \" .. tostring(path) .. \" -> \" .. tostring(next_parent) .. \"/\")\
local parent, name = dir_base(path)\
return assert(os.rename(self.root .. path, tostring(self.root) .. tostring(next_parent) .. \"/\" .. tostring(name)))\
end,\
swap_fileders = function(self, parent, name_a, name_b)\
self:log(\"swapping \" .. tostring(name_a) .. \" and \" .. tostring(name_b) .. \" in \" .. tostring(parent))\
local order = self:get_order(parent)\
local a, b\
for i, entry in ipairs(order) do\
if entry.name == name_a then\
a = i\
end\
if entry.name == name_b then\
b = i\
end\
if a and b then\
break\
end\
end\
assert(a, \"couldn't find \" .. tostring(parent) .. \"/\" .. tostring(name_a) .. \" in $order\")\
assert(b, \"couldn't find \" .. tostring(parent) .. \"/\" .. tostring(name_b) .. \" in $order\")\
order[a], order[b] = order[b], order[a]\
return self:write_order(parent, order)\
end,\
list_facets = function(self, path)\
return coroutine.wrap(function()\
for entry_name in lfs.dir(self.root .. path) do\
local _continue_0 = false\
repeat\
if '.' == entry_name:sub(1, 1) then\
_continue_0 = true\
break\
end\
if entry_name == '$order' then\
_continue_0 = true\
break\
end\
local entry_path = tostring(self.root .. path) .. \"/\" .. tostring(entry_name)\
if 'file' == lfs.attributes(entry_path, 'mode') then\
entry_name = (entry_name:match('(.*)%.%w+')) or entry_name\
entry_name = entry_name:gsub('%$', '/')\
local name, type = entry_name:match('([%w-_]+): *(.+)')\
if not name then\
name = ''\
type = entry_name\
end\
coroutine.yield(name, type)\
end\
_continue_0 = true\
until true\
if not _continue_0 then\
break\
end\
end\
end)\
end,\
tofp = function(self, path, name, type)\
if #name > 0 then\
type = tostring(name) .. \": \" .. tostring(type)\
end\
type = type:gsub('%/', '$')\
return self.root .. tostring(path) .. \"/\" .. tostring(type)\
end,\
locate = function(self, path, name, type)\
if not (lfs.attributes(self.root .. path, 'mode')) then\
return \
end\
type = type:gsub('%/', '$')\
if #name > 0 then\
name = tostring(name) .. \": \"\
end\
name = name .. type\
name = name:gsub('([^%w])', '%%%1')\
local file_name\
for entry_name in lfs.dir(self.root .. path) do\
local _continue_0 = false\
repeat\
if '.' == entry_name:sub(1, 1) then\
_continue_0 = true\
break\
end\
if (entry_name:match(\"^\" .. tostring(name) .. \"$\")) or entry_name:match(\"^\" .. tostring(name) .. \"%.%w+$\") then\
if file_name then\
error(\"two files match \" .. tostring(name) .. \": \" .. tostring(file_name) .. \" and \" .. tostring(entry_name) .. \"!\")\
end\
file_name = entry_name\
end\
_continue_0 = true\
until true\
if not _continue_0 then\
break\
end\
end\
return file_name and self.root .. tostring(path) .. \"/\" .. tostring(file_name)\
end,\
load_facet = function(self, path, name, type)\
local filepath = self:locate(path, name, type)\
if not (filepath) then\
return \
end\
local file = assert((io.open(filepath, 'rb')), \"couldn't open facet file '\" .. tostring(filepath) .. \"'\")\
do\
local _with_0 = file:read('*all')\
file:close()\
return _with_0\
end\
end,\
create_facet = function(self, path, name, type, blob)\
self:log(\"creating facet \" .. tostring(path) .. \" | \" .. tostring(name) .. \": \" .. tostring(type))\
assert(blob, \"cant create facet without value!\")\
local filepath = self:locate(path, name, type)\
assert(not filepath, \"facet file already exists!\")\
filepath = self:tofp(path, name, type)\
local file = assert((io.open(filepath, 'wb')), \"couldn't open facet file '\" .. tostring(filepath) .. \"'\")\
file:write(blob)\
return file:close()\
end,\
remove_facet = function(self, path, name, type)\
self:log(\"removing facet \" .. tostring(path) .. \" | \" .. tostring(name) .. \": \" .. tostring(type))\
local filepath = self:locate(path, name, type)\
assert(filepath, \"couldn't locate facet!\")\
return assert(os.remove(filepath))\
end,\
rename_facet = function(self, path, name, type, next_name)\
self:log(\"renaming facet \" .. tostring(path) .. \" | \" .. tostring(name) .. \": \" .. tostring(type) .. \" -> \" .. tostring(next_name))\
local filepath = self:locate(path, name, type)\
assert(filepath, \"couldn't locate facet!\")\
return assert(os.rename(filepath, self:tofp(path, next_name, type)))\
end,\
update_facet = function(self, path, name, type, blob)\
self:log(\"updating facet \" .. tostring(path) .. \" | \" .. tostring(name) .. \": \" .. tostring(type))\
local filepath = self:locate(path, name, type)\
assert(filepath, \"couldn't locate facet!\")\
local file = assert((io.open(filepath, 'wb')), \"couldn't open facet file '\" .. tostring(filepath) .. \"'\")\
file:write(blob)\
return file:close()\
end,\
fsck = function(self, path)\
if path == nil then\
path = ''\
end\
local order = self:get_order(path, true)\
self:write_order(path, order)\
for _index_0 = 1, #order do\
local _des_0 = order[_index_0]\
path = _des_0.path\
self:fsck(path)\
end\
end\
}\
_base_0.__index = _base_0\
setmetatable(_base_0, _parent_0.__base)\
_class_0 = setmetatable({\
__init = function(self, opts)\
if opts == nil then\
opts = { }\
end\
_class_0.__parent.__init(self, opts)\
opts.root = opts.root or 'root'\
self.root = opts.root:match('^(.-)/?$')\
return self:log(\"opening '\" .. tostring(opts.root) .. \"'...\")\
end,\
__base = _base_0,\
__name = \"FSStore\",\
__parent = _parent_0\
}, {\
__index = function(cls, name)\
local val = rawget(_base_0, name)\
if val == nil then\
local parent = rawget(cls, \"__parent\")\
if parent then\
return parent[name]\
end\
else\
return val\
end\
end,\
__call = function(cls, ...)\
local _self_0 = setmetatable({}, _base_0)\
cls.__init(_self_0, ...)\
return _self_0\
end\
})\
_base_0.__class = _class_0\
if _parent_0.__inherited then\
_parent_0.__inherited(_parent_0, _class_0)\
end\
FSStore = _class_0\
end\
return {\
FSStore = FSStore\
}", "mmm/mmmfs/stores/fs.moon"}
p["mmm.mmmfs.browser"] = {"local Key\
Key = require('mmm.mmmfs.fileder').Key\
local converts\
converts = require('mmm.mmmfs.builtins').converts\
local get_conversions, apply_conversions\
do\
local _obj_0 = require('mmm.mmmfs.conversion')\
get_conversions, apply_conversions = _obj_0.get_conversions, _obj_0.apply_conversions\
end\
local ReactiveVar, get_or_create, text, elements, tohtml\
do\
local _obj_0 = require('mmm.component')\
ReactiveVar, get_or_create, text, elements, tohtml = _obj_0.ReactiveVar, _obj_0.get_or_create, _obj_0.text, _obj_0.elements, _obj_0.tohtml\
end\
local pre, div, nav, span, button, a, code, select, option\
pre, div, nav, span, button, a, code, select, option = elements.pre, elements.div, elements.nav, elements.span, elements.button, elements.a, elements.code, elements.select, elements.option\
local link_to\
link_to = (require('mmm.mmmfs.util'))(elements).link_to\
local languages\
languages = require('mmm.highlighting').languages\
local keep\
keep = function(var)\
local last = var:get()\
return var:map(function(val)\
last = val or last\
return last\
end)\
end\
local combine\
combine = function(...)\
local res = { }\
local lists = {\
...\
}\
for _index_0 = 1, #lists do\
local list = lists[_index_0]\
for _index_1 = 1, #list do\
local val = list[_index_1]\
table.insert(res, val)\
end\
end\
return res\
end\
local casts = {\
{\
inp = 'URL.*',\
out = 'mmm/dom',\
cost = 0,\
transform = function(self, href)\
return span(a((code(href)), {\
href = href\
}))\
end\
}\
}\
local get_casts\
get_casts = function()\
return combine(casts, converts)\
end\
local Browser\
do\
local _class_0\
local err_and_trace, default_convert\
local _base_0 = {\
refresh = function(self, facet)\
if facet == nil then\
facet = self.facet:get()\
end\
if facet == true then\
return self.fileder:transform(function(i)\
return i\
end)\
else\
return self.content:set(self:get_content(facet))\
end\
end,\
get_content = function(self, prop, err, convert)\
if err == nil then\
err = self.error\
end\
if convert == nil then\
convert = default_convert\
end\
local clear_error\
clear_error = function()\
if MODE == 'CLIENT' then\
return err:set()\
end\
end\
local disp_error\
disp_error = function(msg)\
if MODE == 'CLIENT' then\
err:set(pre(msg))\
end\
warn(\"ERROR rendering content: \" .. tostring(msg))\
return div()\
end\
local active = self.fileder:get()\
if not (active) then\
return disp_error(\"fileder not found!\")\
end\
if not (prop) then\
return disp_error(\"facet not found!\")\
end\
local ok, res = xpcall(convert, err_and_trace, active, prop)\
if MODE == 'CLIENT' then\
document.body.classList:remove('loading')\
end\
if ok and res then\
clear_error()\
return res\
elseif ok then\
return div(\"[no conversion path to \" .. tostring(prop.type) .. \"]\")\
elseif res and res:match('%[nossr%]') then\
return div(\"[this page could not be pre-rendered on the server]\")\
else\
return disp_error(res)\
end\
end,\
get_inspector = function(self)\
self.inspect_prop = self.facet:map(function(prop)\
local active = self.fileder:get()\
local key = active and active:find(prop)\
if key and key.original then\
key = key.original\
end\
return key\
end)\
self.inspect_err = ReactiveVar()\
do\
local _with_0 = div({\
class = 'view inspector'\
})\
_with_0:append(nav({\
span('inspector'),\
button('close', {\
onclick = function(_, e)\
return self.inspect:set(false)\
end\
})\
}))\
_with_0:append(div({\
class = 'subnav',\
self.inspect_prop:map(function(current)\
current = current and current:tostring()\
local fileder = self.fileder:get()\
local onchange\
onchange = function(_, e)\
local facet = e.target.value\
if facet == '' then\
return \
end\
return self.inspect_prop:set(Key(facet))\
end\
do\
local _with_1 = select({\
onchange = onchange\
})\
_with_1:append(option('(none)', {\
value = '',\
disabled = true,\
selected = not value\
}))\
if fileder then\
for value in pairs(fileder.facet_keys) do\
_with_1:append(option(value, {\
value = value,\
selected = value == current\
}))\
end\
end\
return _with_1\
end\
end),\
div({\
style = {\
flex = '1'\
}\
})\
}))\
_with_0:append((function()\
do\
local _with_1 = div({\
class = self.inspect_err:map(function(e)\
if e then\
return 'error-wrap'\
else\
return 'error-wrap empty'\
end\
end)\
})\
_with_1:append(span(\"an error occured while rendering this view:\"))\
_with_1:append(self.inspect_err)\
return _with_1\
end\
end)())\
_with_0:append((function()\
do\
local _with_1 = pre({\
class = 'content'\
})\
_with_1:append(keep(self.inspect_prop:map(function(prop, old)\
return self:get_content(prop, self.inspect_err, function(fileder, facet)\
local value, key = fileder:get(facet)\
assert(key, \"couldn't @get \" .. tostring(facet))\
local conversions = get_conversions(fileder, 'mmm/dom', key.type, get_casts())\
assert(conversions, \"cannot cast '\" .. tostring(key.type) .. \"'\")\
return apply_conversions(fileder, conversions, value, facet)\
end)\
end)))\
return _with_1\
end\
end)())\
_with_0:append(nav({\
class = 'thing',\
span('children'),\
button('add', {\
onclick = function(_, e)\
local name = window:prompt(\"please enter the name of the child fileder:\", 'unnamed_fileder')\
if not name or name == '' or name == js.null then\
return \
end\
local child = self.fileder:get():add_child(name)\
return self:refresh(true)\
end\
})\
}))\
_with_0:append(self.fileder:map(function(fileder)\
do\
local _with_1 = div({\
class = 'children'\
})\
local num = #fileder.children\
for i, child in ipairs(fileder.children) do\
local name = child:gett('name: alpha')\
_with_1:append(div({\
style = {\
display = 'flex',\
['justify-content'] = 'space-between'\
},\
span('- ', (link_to(child, code(name))), {\
style = {\
flex = 1\
}\
})\
}))\
end\
return _with_1\
end\
end))\
return _with_0\
end\
end,\
navigate = function(self, new)\
return self.path:set(new)\
end,\
todom = function(self)\
return tohtml(self)\
end\
}\
_base_0.__index = _base_0\
_class_0 = setmetatable({\
__init = function(self, root, path, facet, rehydrate)\
if rehydrate == nil then\
rehydrate = false\
end\
self.root = root\
BROWSER = self\
assert(self.root, 'root fileder is nil')\
self.path = ReactiveVar(path or '')\
self.fileder = self.path:map((function()\
local _base_1 = self.root\
local _fn_0 = _base_1.walk\
return function(...)\
return _fn_0(_base_1, ...)\
end\
end)())\
self.facet = ReactiveVar(Key(facet, 'mmm/dom'))\
if MODE == 'CLIENT' then\
self.fileder:subscribe(function(fileder)\
if not (fileder) then\
return \
end\
local last = self.facet and self.facet:get()\
return self.facet:set(Key((function()\
if last then\
return last.type\
else\
return 'mmm/dom'\
end\
end)()))\
end)\
end\
if MODE == 'CLIENT' then\
local logo = document:querySelector('header h1 > a > svg')\
local spin\
spin = function()\
logo.classList:add('spin')\
local _ = logo.parentElement.offsetWidth\
return logo.classList:remove('spin')\
end\
self.facet:subscribe(function(facet)\
document.body.classList:add('loading')\
spin()\
if self.skip then\
return \
end\
path = self.path:get()\
local state = js.global:eval('new Object()')\
state.path = path\
state.name = facet.name\
state.type = facet.type\
return window.history:pushState(state, '', tostring(path) .. \"/\" .. tostring((Key(facet.name, 'text/html+interactive')):tostring(true)))\
end)\
window.onpopstate = function(_, event)\
local state = event.state\
if state ~= js.null then\
self.skip = true\
self.path:set(state.path)\
self.facet:set(Key(state.name, state.type))\
self.skip = nil\
end\
end\
end\
self.inspect = ReactiveVar((MODE == 'CLIENT' and window.location.hash == '#inspect'))\
local main = get_or_create('div', 'browser-root', {\
class = 'main view'\
})\
if MODE == 'SERVER' then\
main:append(nav({\
id = 'browser-navbar',\
span('please stand by... interactivity loading :)')\
}))\
else\
main:prepend((function()\
do\
local _with_0 = get_or_create('nav', 'browser-navbar')\
_with_0.node.innerHTML = ''\
_with_0:append(span('path: ', self.path:map(function(path)\
do\
local _with_1 = div({\
class = 'path',\
style = {\
display = 'inline-block'\
}\
})\
local path_segment\
path_segment = function(name, href)\
return a(name, {\
href = tostring(href) .. \"/\",\
onclick = function(_, e)\
e:preventDefault()\
return self:navigate(href)\
end\
})\
end\
local href = ''\
path = path:match('^/(.*)')\
_with_1:append(path_segment('root', ''))\
while path do\
local name, rest = path:match('^([%w%-_%.]+)/(.*)')\
if not name then\
name = path\
end\
path = rest\
href = tostring(href) .. \"/\" .. tostring(name)\
_with_1:append('/')\
_with_1:append(path_segment(name, href))\
end\
return _with_1\
end\
end)))\
_with_0:append(span('view facet:', {\
style = {\
['margin-right'] = '0'\
}\
}))\
_with_0:append(self.fileder:map(function(fileder)\
local onchange\
onchange = function(_, e)\
local type\
type = self.facet:get().type\
return self.facet:set(Key({\
name = e.target.value,\
type = type\
}))\
end\
local current = self.facet:get()\
current = current and current.name\
do\
local _with_1 = elements.select({\
onchange = onchange,\
disabled = not fileder,\
value = self.facet:map(function(f)\
return f and f.name\
end)\
})\
local has_main = fileder and fileder:has_facet('')\
_with_1:append(option('(main)', {\
value = '',\
disabled = not has_main,\
selected = current == ''\
}))\
if fileder then\
for i, value in ipairs(fileder:get_facets()) do\
local _continue_0 = false\
repeat\
if value == '' then\
_continue_0 = true\
break\
end\
_with_1:append(option(value, {\
value = value,\
selected = value == current\
}))\
_continue_0 = true\
until true\
if not _continue_0 then\
break\
end\
end\
end\
return _with_1\
end\
end))\
_with_0:append(self.inspect:map(function(enabled)\
if not enabled then\
return button('inspect', {\
onclick = function(_, e)\
return self.inspect:set(true)\
end\
})\
end\
end))\
return _with_0\
end\
end)())\
end\
self.error = ReactiveVar()\
main:append((function()\
do\
local _with_0 = get_or_create('div', 'browser-error', {\
class = self.error:map(function(e)\
if e then\
return 'error-wrap'\
else\
return 'error-wrap empty'\
end\
end)\
})\
_with_0:append((span(\"an error occured while rendering this view:\")), (rehydrate and _with_0.node.firstChild))\
_with_0:append(self.error)\
return _with_0\
end\
end)())\
main:append((function()\
do\
local _with_0 = get_or_create('div', 'browser-content', {\
class = 'content'\
})\
self.content = ReactiveVar((function()\
if rehydrate then\
return _with_0.node.lastChild\
else\
return self:get_content(self.facet:get())\
end\
end)())\
_with_0:append(keep(self.content))\
if MODE == 'CLIENT' then\
self.facet:subscribe(function(p)\
return window:setTimeout((function()\
return self:refresh(p)\
end), 150)\
end)\
end\
return _with_0\
end\
end)())\
if rehydrate then\
self.facet:set(self.facet:get())\
end\
local inspector = self.inspect:map(function(enabled)\
if enabled then\
return self:get_inspector()\
end\
end)\
local wrapper = get_or_create('div', 'browser-wrapper', main, inspector, {\
class = 'browser'\
})\
self.node = wrapper.node\
do\
local _base_1 = wrapper\
local _fn_0 = _base_1.render\
self.render = function(...)\
return _fn_0(_base_1, ...)\
end\
end\
end,\
__base = _base_0,\
__name = \"Browser\"\
}, {\
__index = _base_0,\
__call = function(cls, ...)\
local _self_0 = setmetatable({}, _base_0)\
cls.__init(_self_0, ...)\
return _self_0\
end\
})\
_base_0.__class = _class_0\
local self = _class_0\
err_and_trace = function(msg)\
return debug.traceback(msg, 2)\
end\
default_convert = function(self, key)\
return self:get(key.name, 'mmm/dom')\
end\
default_convert = function(self, key)\
return self:get(key.name, 'mmm/dom')\
end\
Browser = _class_0\
end\
return {\
Browser = Browser\
}", "mmm/mmmfs/browser.moon"}
p["mmm.mmmfs.meta"] = {"local yield_ancestors\
do\
local step\
step = function(self, path)\
if '/' ~= path:sub(1, 1) then\
path = tostring(self.path) .. \"/\" .. tostring(path)\
end\
if not (self.path == path:sub(1, #self.path)) then\
return \
end\
if #path == #self.path then\
return \
end\
coroutine.yield(self)\
local _list_0 = self.children\
for _index_0 = 1, #_list_0 do\
local child = _list_0[_index_0]\
step(child, path)\
end\
end\
yield_ancestors = function(self, path)\
return coroutine.wrap(function()\
return step(self, path)\
end)\
end\
end\
local get_meta\
get_meta = function(fileder, path)\
if path then\
path = \"$mmm/\" .. tostring(path)\
else\
path = '$mmm'\
end\
local guard_self\
local max_path = fileder.path\
do\
local closest = max_path:match('(.-)/$mmm')\
if closest then\
max_path = closest\
guard_self = true\
end\
end\
assert(fileder.root, \"'\" .. tostring(fileder) .. \"' has no root!\")\
return coroutine.wrap(function()\
for ancestor in yield_ancestors(fileder.root, max_path) do\
local _continue_0 = false\
repeat\
if guard_self and ancestor.path == max_path then\
break\
end\
if ancestor == fileder then\
_continue_0 = true\
break\
end\
do\
local result = ancestor:walk(path)\
if result then\
coroutine.yield(result)\
end\
end\
_continue_0 = true\
until true\
if not _continue_0 then\
break\
end\
end\
do\
local result = not guard_self and fileder:walk(path)\
if result then\
return coroutine.yield(result)\
end\
end\
end)\
end\
local get_plugins\
get_plugins = function(fileder)\
return coroutine.wrap(function()\
for plugins in get_meta(fileder, 'plugins') do\
local _list_0 = plugins.children\
for _index_0 = 1, #_list_0 do\
local plugin = _list_0[_index_0]\
coroutine.yield(plugin)\
end\
end\
end)\
end\
return {\
get_meta = get_meta,\
get_plugins = get_plugins\
}", "mmm/mmmfs/meta.moon"}
p["mmm.mmmfs.util"] = {"local refs = require('mmm.refs')\
local merge\
merge = function(orig, extra)\
if orig == nil then\
orig = { }\
end\
if extra == nil then\
extra = { }\
end\
do\
local attr\
do\
local _tbl_0 = { }\
for k, v in pairs(orig) do\
_tbl_0[k] = v\
end\
attr = _tbl_0\
end\
for k, v in pairs(extra) do\
attr[k] = v\
end\
return attr\
end\
end\
local tourl\
tourl = function(path, facet)\
path = path .. '/'\
if STATIC and STATIC.root then\
path = STATIC.root .. path\
end\
if facet then\
path = path .. facet\
end\
return path\
end\
return function(elements)\
local a, div, span, sup, b, pre\
a, div, span, sup, b, pre = elements.a, elements.div, elements.span, elements.sup, elements.b, elements.pre\
local find_fileder\
find_fileder = function(path, origin)\
if 'string' == type(path) then\
if path == '' then\
assert(origin, \"cannot resolve empty path without origin!\")\
return origin\
end\
if '/' ~= path:sub(1, 1) then\
assert(origin, \"cannot resolve relative path '\" .. tostring(path) .. \"' without origin!\")\
path = tostring(origin.path) .. \"/\" .. tostring(path)\
end\
while path:match('/([^/]-)/%.%./') do\
path = path:gsub('/([^/]-)/%.%./', '/')\
end\
if origin.path == path:sub(1, #origin.path) then\
return assert((origin:walk(path)), \"couldn't resolve path '\" .. tostring(path) .. \"' from \" .. tostring(origin))\
else\
return assert((origin.root:walk(path)), \"couldn't resolve path '\" .. tostring(path) .. \"'\")\
end\
else\
return assert(path, \"no path passed.\")\
end\
end\
local navigate_to\
navigate_to = function(path, name, opts)\
if opts == nil then\
opts = { }\
end\
opts.href = tourl(path)\
if MODE == 'CLIENT' then\
opts.onclick = function(self, e)\
e:preventDefault()\
return BROWSER:navigate(path)\
end\
end\
return a(name, opts)\
end\
local link_to\
link_to = function(fileder, name, origin, attr, facet)\
fileder = find_fileder(fileder, origin)\
name = name or fileder:get('title: mmm/dom')\
name = name or fileder:gett('name: alpha')\
do\
local href = fileder:get('link: URL*')\
if href then\
return a(name, merge(attr, {\
href = href,\
target = '_blank'\
}))\
else\
return a(name, merge(attr, {\
href = tourl(fileder.path, facet),\
onclick = (function()\
if MODE == 'CLIENT' then\
return function(self, e)\
e:preventDefault()\
return BROWSER:navigate(fileder.path)\
end\
end\
end)()\
}))\
end\
end\
end\
local interactive_link\
interactive_link = function(text, view)\
if view == nil then\
view = ':text/html+interactive'\
end\
assert(MODE == 'SERVER')\
local path = BROWSER.path\
if 'table' == type(BROWSER.path) then\
path = table.concat(path, '/')\
end\
return a(text, {\
href = tourl(path, view)\
})\
end\
local embed\
embed = function(fileder, facet, origin, opts)\
if facet == nil then\
facet = ''\
end\
if opts == nil then\
opts = { }\
end\
if opts.raw then\
warn(\"deprecated option 'raw' set on embed\")\
assert(not opts.wrap, \"raw and wrap cannot both be set on embed\")\
opts.wrap = 'raw'\
end\
opts.wrap = opts.wrap or 'well'\
fileder = find_fileder(fileder, origin)\
local ok, node = pcall(fileder.gett, fileder, facet, 'mmm/dom')\
if not ok then\
warn(\"couldn't embed \" .. tostring(fileder) .. \" \" .. tostring(facet) .. \": \" .. tostring(node))\
return span({\
class = 'embed',\
style = {\
background = 'var(--gray-fail)',\
padding = '1em'\
},\
\"couldn't embed \" .. tostring(fileder) .. \" \" .. tostring(facet),\
(pre(node))\
})\
end\
local klass = 'embed'\
if opts.desc then\
klass = klass .. ' desc'\
end\
if opts.inline then\
klass = klass .. ' inline'\
end\
local _exp_0 = opts.wrap\
if 'raw' == _exp_0 then\
return node\
elseif 'well' == _exp_0 then\
node = span({\
class = klass,\
style = opts.style,\
node,\
(function()\
if opts.desc then\
return div(opts.desc, {\
class = 'description'\
})\
end\
end)()\
})\
if opts.nolink then\
return node\
else\
return link_to(fileder, node, nil, opts.attr, facet)\
end\
elseif 'sidenote' == _exp_0 then\
local key = tostring(refs:get())\
local id = \"sideref-\" .. tostring(key)\
local intext = sup(a(key, {\
href = \"#\" .. tostring(id)\
}))\
return span(intext, div({\
class = 'sidenote',\
style = opts.style or 'margin-top: -1.25rem;',\
div({\
id = id,\
class = 'hook'\
}),\
b(key, {\
class = 'ref'\
}),\
' ',\
opts.desc or '',\
node\
}))\
elseif 'marginnote' == _exp_0 then\
return div({\
class = 'sidenote',\
style = opts.style,\
opts.desc or '',\
node\
})\
else\
return error(\"unknown embed 'wrap': '\" .. tostring(opts.wrap) .. \"'\")\
end\
end\
return {\
tourl = tourl,\
find_fileder = find_fileder,\
link_to = link_to,\
interactive_link = interactive_link,\
navigate_to = navigate_to,\
embed = embed\
}\
end", "mmm/mmmfs/util.moon"}
p["mmm.mmmfs.builtins"] = {"local div, pre, code, img, video, span, source\
do\
local _obj_0 = require('mmm.dom')\
div, pre, code, img, video, span, source = _obj_0.div, _obj_0.pre, _obj_0.code, _obj_0.img, _obj_0.video, _obj_0.span, _obj_0.source\
end\
local find_fileder, link_to, embed\
do\
local _obj_0 = (require('mmm.mmmfs.util'))(require('mmm.dom'))\
find_fileder, link_to, embed = _obj_0.find_fileder, _obj_0.link_to, _obj_0.embed\
end\
local tohtml\
tohtml = require('mmm.component').tohtml\
local js_fix\
if MODE == 'CLIENT' then\
js_fix = function(arg)\
if arg == js.null then\
return \
end\
if arg == '' then\
return \
end\
return arg\
end\
end\
local js_bool\
if MODE == 'CLIENT' then\
js_bool = function(arg)\
if arg == js.null then\
return nil\
end\
if arg == 'false' then\
return false\
end\
return true\
end\
end\
local single\
single = function(func)\
return function(self, val)\
return func(val)\
end\
end\
local loadwith\
loadwith = function(_load)\
return function(self, val, fileder, key)\
local func = assert(_load(val, tostring(fileder) .. \"#\" .. tostring(key)))\
return func()\
end\
end\
string.yieldable_gsub = function(str, pat, f)\
str = str:gsub('%%', '%%|')\
local matches = { }\
local cnt\
str, cnt = str:gsub(pat, function(...)\
table.insert(matches, {\
...\
})\
return \"%\" .. tostring(#matches)\
end)\
for _index_0 = 1, #matches do\
local match = matches[_index_0]\
match.replacement = f(table.unpack(match))\
end\
str = str:gsub('%%(%d+)', function(i)\
i = tonumber(i)\
return matches[i].replacement\
end)\
str = str:gsub('%%|', '%%')\
return str, cnt\
end\
local converts = {\
{\
inp = 'fn -> (.+)',\
out = '%1',\
cost = 1,\
transform = function(self, val, fileder)\
return val(fileder)\
end\
},\
{\
inp = 'mmm/component',\
out = 'mmm/dom',\
cost = 3,\
transform = single(tohtml)\
},\
{\
inp = 'mmm/dom',\
out = 'text/html+frag',\
cost = 3,\
transform = function(self, node)\
if MODE == 'SERVER' then\
return node\
else\
return node.outerHTML\
end\
end\
},\
{\
inp = 'text/html%+frag',\
out = 'mmm/dom',\
cost = 0.1,\
transform = (function()\
if MODE == 'SERVER' then\
return function(self, html, fileder)\
html = html:yieldable_gsub('(.-) ', function(attrs, text)\
if #text == 0 then\
text = nil\
end\
local path, facet = '', ''\
while attrs and attrs ~= '' do\
local key, val, _attrs = attrs:match('^(%w+)=\"([^\"]-)\"%s*(.*)')\
if not key then\
key, _attrs = attrs:match('^(%w+)%s*(.*)$')\
val = true\
end\
attrs = _attrs\
local _exp_0 = key\
if 'path' == _exp_0 then\
path = val\
elseif 'facet' == _exp_0 then\
facet = val\
else\
warn(\"unkown attribute '\" .. tostring(key) .. \"=\\\"\" .. tostring(val) .. \"\\\"' in \")\
end\
end\
return link_to(path, text, fileder)\
end)\
html = html:yieldable_gsub('(.-) ', function(attrs, desc)\
local path, facet = '', ''\
local opts = { }\
if #desc ~= 0 then\
opts.desc = desc\
end\
while attrs and attrs ~= '' do\
local key, val, _attrs = attrs:match('^(%w+)=\"([^\"]-)\"%s*(.*)')\
if not key then\
key, _attrs = attrs:match('^(%w+)%s*(.*)$')\
val = true\
end\
attrs = _attrs\
local _exp_0 = key\
if 'path' == _exp_0 then\
path = val\
elseif 'facet' == _exp_0 then\
facet = val\
elseif 'wrap' == _exp_0 then\
opts.wrap = val\
elseif 'style' == _exp_0 then\
opts.style = val\
elseif 'nolink' == _exp_0 then\
opts.nolink = true\
elseif 'inline' == _exp_0 then\
opts.inline = true\
elseif 'raw' == _exp_0 then\
opts.raw = true\
else\
warn(\"unkown attribute '\" .. tostring(key) .. \"=\\\"\" .. tostring(val) .. \"\\\"' in \")\
end\
end\
return embed(path, facet, fileder, opts)\
end)\
return html\
end\
else\
return function(self, html, fileder)\
local parent\
do\
local _with_0 = document:createElement('div')\
_with_0.innerHTML = html\
local embeds = _with_0:getElementsByTagName('mmm-embed')\
do\
local _accum_0 = { }\
local _len_0 = 1\
for i = 0, embeds.length - 1 do\
_accum_0[_len_0] = embeds[i]\
_len_0 = _len_0 + 1\
end\
embeds = _accum_0\
end\
for _index_0 = 1, #embeds do\
local element = embeds[_index_0]\
local path = js_fix(element:getAttribute('path'))\
local facet = js_fix(element:getAttribute('facet'))\
local wrap = js_fix(element:getAttribute('wrap'))\
local style = js_fix(element:getAttribute('style'))\
local nolink = js_bool(element:getAttribute('nolink'))\
local inline = js_bool(element:getAttribute('inline'))\
local desc = js_fix(element.innerText)\
if desc == '' then\
desc = nil\
end\
local raw = js_bool(element:getAttribute('raw'))\
local opts = {\
wrap = wrap,\
style = style,\
nolink = nolink,\
inline = inline,\
desc = desc,\
raw = raw\
}\
element:replaceWith(embed(path or '', facet or '', fileder, opts))\
end\
embeds = _with_0:getElementsByTagName('mmm-link')\
do\
local _accum_0 = { }\
local _len_0 = 1\
for i = 0, embeds.length - 1 do\
_accum_0[_len_0] = embeds[i]\
_len_0 = _len_0 + 1\
end\
embeds = _accum_0\
end\
for _index_0 = 1, #embeds do\
local element = embeds[_index_0]\
local text = js_fix(element.innerText)\
local path = js_fix(element:getAttribute('path'))\
element:replaceWith(link_to(path or '', text, fileder))\
end\
parent = _with_0\
end\
assert(1 == parent.childElementCount, \"text/html with more than one child!\")\
return parent.firstElementChild\
end\
end\
end)()\
},\
{\
inp = 'mmm/tpl -> (.+)',\
out = '%1',\
cost = 1,\
transform = function(self, source, fileder)\
return source:yieldable_gsub('{{(.-)}}', function(expr)\
local path, facet = expr:match('^([%w%-_%./]*)%+(.*)')\
assert(path, \"couldn't match TPL expression '\" .. tostring(expr) .. \"'\")\
return (find_fileder(path, fileder)):gett(facet)\
end)\
end\
},\
{\
inp = 'time/iso8601-date',\
out = 'time/unix',\
cost = 0.5,\
transform = function(self, val)\
local year, _, month, day = val:match('^%s*(%d%d%d%d)(%-?)([01]%d)%2([0-3]%d)%s*$')\
assert(year, \"failed to parse ISO 8601 date: '\" .. tostring(val) .. \"'\")\
return os.time({\
year = year,\
month = month,\
day = day\
})\
end\
},\
{\
inp = 'URL -> image/.+',\
out = 'mmm/dom',\
cost = -4,\
transform = function(self, src, fileder)\
return img({\
src = src\
})\
end\
},\
{\
inp = 'URL -> video/.+%+gif',\
out = 'mmm/dom',\
cost = -4.01,\
transform = function(self, src)\
return video((source({\
src = src\
})), {\
controls = 'auto',\
loop = true,\
autoplay = true,\
muted = true\
})\
end\
},\
{\
inp = 'URL -> video/.+',\
out = 'mmm/dom',\
cost = -4,\
transform = function(self, src)\
return video((source({\
src = src\
})), {\
controls = true,\
loop = true\
})\
end\
},\
{\
inp = 'text/plain',\
out = 'mmm/dom',\
cost = 2,\
transform = function(self, val)\
return span(val)\
end\
},\
{\
inp = 'alpha',\
out = 'mmm/dom',\
cost = 2,\
transform = single(code)\
},\
{\
inp = 'URL -> (.+)',\
out = '%1',\
cost = 4,\
transform = (function()\
if MODE == 'CLIENT' then\
return function(self, uri)\
local request = js.new(js.global.XMLHttpRequest)\
request:open('GET', uri, false)\
request:send(js.null)\
assert(request.status == 200, \"unexpected status code: \" .. tostring(request.status))\
return request.responseText\
end\
else\
return function(self, uri)\
local request = require('http.request')\
local req = request.new_from_uri(uri)\
req.headers:upsert('origin', 'null')\
local headers, stream = assert(req:go(8))\
return assert(stream:get_body_as_string())\
end\
end\
end)()\
},\
{\
inp = 'table',\
out = 'mmm/dom',\
cost = 5,\
transform = (function()\
local deep_tostring\
deep_tostring = function(tbl, space)\
if space == nil then\
space = ''\
end\
local buf = space .. tostring(tbl)\
if not ('table' == type(tbl)) then\
return buf\
end\
buf = buf .. ' {\\n'\
for k, v in pairs(tbl) do\
buf = buf .. tostring(space) .. \" [\" .. tostring(k) .. \"]: \" .. tostring(deep_tostring(v, space .. ' ')) .. \"\\n\"\
end\
buf = buf .. tostring(space) .. \"}\"\
return buf\
end\
return function(self, tbl)\
return pre(code(deep_tostring(tbl)))\
end\
end)()\
}\
}\
if STATIC then\
local extensions = {\
['image/jpeg'] = 'jpg',\
['image/png'] = 'png',\
['image/svg+xml'] = 'svg',\
['video/webm'] = 'webm',\
['video/mp4'] = 'mp4',\
['text/javascript'] = 'js',\
['text/css'] = 'css',\
['model/gltf-binary'] = 'glb'\
}\
table.insert(converts, {\
inp = '(.+)',\
out = 'URL -> %1',\
cost = 5,\
transform = function(self, val, fileder, key)\
local escaped_from = self.from:gsub('/', '_')\
do\
local ext = extensions[self.from]\
if ext then\
escaped_from = escaped_from .. \".\" .. tostring(ext)\
end\
end\
local prefix = STATIC.root or ''\
return prefix .. (function()\
do\
local url = tostring(fileder.path) .. \"/\" .. tostring(key.name) .. \":\" .. tostring(escaped_from)\
print(\" rendering asset \" .. tostring(url))\
STATIC.spit(url, val)\
return url\
end\
end)()\
end\
})\
else\
table.insert(converts, {\
inp = '(.+)',\
out = 'URL -> %1',\
cost = 5,\
transform = function(self, _, fileder, key)\
return tostring(fileder.path) .. \"/\" .. tostring(key.name) .. \":\" .. tostring(self.from)\
end\
})\
end\
if MODE == 'CLIENT' or UNSAFE then\
table.insert(converts, {\
inp = 'text/lua -> (.+)',\
out = '%1',\
cost = 0.5,\
transform = loadwith(load or loadstring)\
})\
end\
if MODE == 'CLIENT' then\
table.insert(converts, {\
inp = 'text/javascript -> (.+)',\
out = '%1',\
cost = 1,\
transform = function(self, source)\
local f = js.new(window.Function, source)\
return f()\
end\
})\
end\
local json_encode\
json_encode = function(obj)\
local _exp_0 = type(obj)\
if 'string' == _exp_0 then\
return string.format('%q', obj)\
elseif 'table' == _exp_0 then\
if obj[1] or not next(obj) then\
return \"[\" .. tostring(table.concat((function()\
local _accum_0 = { }\
local _len_0 = 1\
for _index_0 = 1, #obj do\
local c = obj[_index_0]\
_accum_0[_len_0] = json_encode(c)\
_len_0 = _len_0 + 1\
end\
return _accum_0\
end)(), ',')) .. \"]\"\
else\
return \"{\" .. tostring(table.concat((function()\
local _accum_0 = { }\
local _len_0 = 1\
for k, v in pairs(obj) do\
_accum_0[_len_0] = tostring(json_encode(k)) .. \": \" .. tostring(json_encode(v))\
_len_0 = _len_0 + 1\
end\
return _accum_0\
end)(), ', ')) .. \"}\"\
end\
elseif 'number' == _exp_0 then\
return tostring(obj)\
elseif 'boolean' == _exp_0 then\
return tostring(obj)\
elseif 'nil' == _exp_0 then\
return 'null'\
else\
return error(\"unknown type '\" .. tostring(type(obj)) .. \"'\")\
end\
end\
local json_decode\
if MODE == 'CLIENT' then\
local Array, Object, JSON\
do\
local _obj_0 = js.global\
Array, Object, JSON = _obj_0.Array, _obj_0.Object, _obj_0.JSON\
end\
local fix\
fix = function(val)\
local _exp_0 = type(val)\
if 'userdata' == _exp_0 then\
if Array:isArray(val) then\
local _accum_0 = { }\
local _len_0 = 1\
for x in js.of(val) do\
_accum_0[_len_0] = fix(x)\
_len_0 = _len_0 + 1\
end\
return _accum_0\
else\
local _tbl_0 = { }\
for e in js.of(Object:entries(val)) do\
_tbl_0[(fix(e[0]))] = (fix(e[1]))\
end\
return _tbl_0\
end\
else\
return val\
end\
end\
json_decode = function(str)\
return fix(JSON:parse(str))\
end\
else\
do\
local cjson = require('cjson')\
if cjson then\
json_decode = cjson.decode\
else\
warn('only partial JSON support, please install cjson')\
json_decode = nil\
end\
end\
end\
table.insert(converts, {\
inp = 'table',\
out = 'text/json',\
cost = 2,\
transform = function(self, val)\
return json_encode(val)\
end\
})\
if json_decode then\
table.insert(converts, {\
inp = 'text/json',\
out = 'table',\
cost = 1,\
transform = function(self, val)\
return json_decode(val)\
end\
})\
end\
return {\
converts = converts\
}", "mmm/mmmfs/builtins.moon"}
p["mmm"] = {"window = js.global\
local console\
document, console = window.document, window.console\
MODE = 'CLIENT'\
UNSAFE = true\
local deep_tostring\
deep_tostring = function(tbl, space, recur)\
if space == nil then\
space = ''\
end\
if recur == nil then\
recur = { }\
end\
local buf = space .. tostring(tbl)\
if not ('table' == (type(tbl)) and not tbl.__tostring and not recur[tbl]) then\
return buf\
end\
recur[tbl] = true\
buf = buf .. ' {\\n'\
for k, v in pairs(tbl) do\
buf = buf .. tostring(space) .. \" [\" .. tostring(k) .. \"]: \" .. tostring(deep_tostring(v, space .. ' ', recur)) .. \"\\n\"\
end\
buf = buf .. tostring(space) .. \"}\"\
return buf\
end\
print = function(...)\
local contents\
do\
local _accum_0 = { }\
local _len_0 = 1\
local _list_0 = {\
...\
}\
for _index_0 = 1, #_list_0 do\
local v = _list_0[_index_0]\
_accum_0[_len_0] = deep_tostring(v)\
_len_0 = _len_0 + 1\
end\
contents = _accum_0\
end\
return console:log(table.unpack(contents))\
end\
warn = function(...)\
local contents\
do\
local _accum_0 = { }\
local _len_0 = 1\
local _list_0 = {\
...\
}\
for _index_0 = 1, #_list_0 do\
local v = _list_0[_index_0]\
_accum_0[_len_0] = deep_tostring(v)\
_len_0 = _len_0 + 1\
end\
contents = _accum_0\
end\
return console:warn(table.unpack(contents))\
end\
package.path = '/?.lua;/?/init.lua'\
if on_load then\
for _index_0 = 1, #on_load do\
local f = on_load[_index_0]\
f()\
end\
end\
on_load = setmetatable({ }, {\
__newindex = function(t, k, v)\
rawset(t, k, v)\
return v()\
end\
})", "mmm/init.client.moon"}
an error occured while rendering this view: