From b615a7cf0fc9d81b4b905a9d4e1db0beebdebd3d Mon Sep 17 00:00:00 2001 From: s-ol Date: Sun, 8 May 2022 21:14:58 +0200 Subject: initial commit --- static/mmm/text$lua.lua | 3757 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 3757 insertions(+) create mode 100644 static/mmm/text$lua.lua (limited to 'static/mmm/text$lua.lua') diff --git a/static/mmm/text$lua.lua b/static/mmm/text$lua.lua new file mode 100644 index 0000000..6192113 --- /dev/null +++ b/static/mmm/text$lua.lua @@ -0,0 +1,3757 @@ + +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\ + if guard_self and ancestor.path == max_path then\ + break\ + end\ + do\ + local result = ancestor:walk(path)\ + if result then\ + coroutine.yield(result)\ + end\ + 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, _view)\ + path = path .. '/'\ + if STATIC and STATIC.root then\ + path = STATIC.root .. path\ + end\ + if _view then\ + path = path .. _view\ + 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, _view)\ + 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, _view),\ + 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, name, origin, opts)\ + if name == nil then\ + name = ''\ + 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, name, 'mmm/dom')\ + if not ok then\ + warn(\"couldn't embed \" .. tostring(fileder) .. \" \" .. tostring(name) .. \": \" .. tostring(node))\ + return span({\ + class = 'embed',\ + style = {\ + background = 'var(--gray-fail)',\ + padding = '1em'\ + },\ + \"couldn't embed \" .. tostring(fileder) .. \" \" .. tostring(name),\ + (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)\ + 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"} -- cgit v1.2.3