mmm​.s‑ol.nu

cool projects with electronics
an error occured while rendering this view:

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\
    do\
      local e = document:createElement(element)\
      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\
      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\
end\
return setmetatable({ }, {\
  __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.layout"] = {"local header, aside, footer, div, svg, script, g, circle, h1, span, b, a, img\
do\
  local _obj_0 = require('mmm.dom')\
  header, aside, footer, div, svg, script, g, circle, h1, span, b, a, img = _obj_0.header, _obj_0.aside, _obj_0.footer, _obj_0.div, _obj_0.svg, _obj_0.script, _obj_0.g, _obj_0.circle, _obj_0.h1, _obj_0.span, _obj_0.b, _obj_0.a, _obj_0.img\
end\
local navigate_to\
navigate_to = (require('mmm.mmmfs.util'))(require('mmm.dom')).navigate_to\
local get_plugins\
get_plugins = require('mmm.mmmfs.meta').get_plugins\
local pick\
pick = function(...)\
  local num = select('#', ...)\
  local i = math.ceil(math.random() * num)\
  return (select(i, ...))\
end\
local iconlink\
iconlink = function(href, src, alt, style)\
  return a({\
    class = 'iconlink',\
    target = '_blank',\
    rel = 'me',\
    href = href,\
    img({\
      src = src,\
      alt = alt,\
      style = style\
    })\
  })\
end\
local logo = svg({\
  class = 'sun',\
  viewBox = '-0.75 -1 1.5 2',\
  xmlns = 'http://www.w3.org/2000/svg',\
  baseProfile = 'full',\
  version = '1.1',\
  g({\
    transform = 'translate(0 .18)',\
    g({\
      class = 'circle out',\
      circle({\
        r = '.6',\
        fill = 'none',\
        ['stroke-width'] = '.12'\
      })\
    }),\
    g({\
      class = 'circle  in',\
      circle({\
        r = '.2',\
        stroke = 'none'\
      })\
    })\
  })\
})\
local gen_header\
gen_header = function()\
  return header({\
    div({\
      h1({\
        navigate_to('', logo),\
        span({\
          span('mmm', {\
            class = 'bold'\
          }),\
          '​',\
          '.s‑ol.nu'\
        })\
      }),\
      table.concat({\
        pick('fun', 'cool', 'weird', 'interesting', 'new', 'pleasant'),\
        pick('stuff', 'things', 'projects', 'experiments', 'visuals', 'ideas'),\
        pick(\"with\", 'and'),\
        pick('mostly code', 'code and wires', 'silicon', 'electronics', 'shaders', 'oscilloscopes', 'interfaces', 'hardware', 'FPGAs')\
      }, ' ')\
    }),\
    aside({\
      navigate_to('/about', 'about me'),\
      navigate_to('/portfolio', 'portfolio'),\
      navigate_to('/games', 'games'),\
      navigate_to('/projects', 'other'),\
      a({\
        href = 'mailto:s%20[removethis]%20[at]%20s-ol.nu',\
        'contact',\
        script(\"\\n          var l = document.currentScript.parentElement;\\n          l.href = l.href.replace('%20[at]%20', '@');\\n          l.href = l.href.replace('%20[removethis]', '') + '?subject=Hey there :)';\\n        \")\
      })\
    })\
  })\
end\
footer = footer({\
  span({\
    'made with \\xe2\\x98\\xbd by ',\
    a('s-ol', {\
      href = 'https://twitter.com/S0lll0s'\
    }),\
    \", \" .. tostring(os.date('%Y'))\
  }),\
  div({\
    class = 'icons',\
    iconlink('https://github.com/s-ol', 'https://cdn.jsdelivr.net/npm/simple-icons@latest/icons/github.svg', 'github'),\
    iconlink('https://merveilles.town/@s_ol', 'https://cdn.jsdelivr.net/npm/simple-icons@latest/icons/mastodon.svg', 'mastodon'),\
    iconlink('https://twitter.com/S0lll0s', 'https://cdn.jsdelivr.net/npm/simple-icons@latest/icons/twitter.svg', 'twitter'),\
    iconlink('https://webring.xxiivv.com/#random', 'https://webring.xxiivv.com/icon.black.svg', 'webring', {\
      height = '1.3em',\
      ['margin-left'] = '.3em',\
      ['margin-top'] = '-0.12em'\
    })\
  })\
})\
local get_header_tags\
get_header_tags = function(self)\
  local title = (self:get('title: text/plain')) or self:gett('name: alpha')\
  local l\
  l = function(str)\
    str = str:gsub('[%s\\n]+$', '')\
    return str:gsub('\\n', ' ')\
  end\
  local e\
  e = function(str)\
    return string.format('%q', l(str))\
  end\
  local meta = \"\\n    \\n    \" .. tostring(l(title)) .. \"\\n  \"\
  do\
    local page_meta = self:get('_meta: mmm/dom')\
    if page_meta then\
      meta = meta .. page_meta\
    else\
      meta = meta .. \"\\n    \\n\\n    \\n    \\n    \\n    \"\
      do\
        local desc = self:get('description: text/plain')\
        if desc then\
          meta = meta .. \"\\n    \"\
        end\
      end\
    end\
  end\
  return meta\
end\
local get_scripts\
get_scripts = function(self)\
  local scripts = ''\
  for plugin in get_plugins(self) do\
    do\
      local snippet = plugin:get('scripts: text/html+frag')\
      if snippet then\
        scripts = scripts .. snippet\
      end\
    end\
  end\
  return scripts\
end\
local render\
render = function(content, fileder, opts)\
  if opts == nil then\
    opts = { }\
  end\
  opts.meta = opts.meta or get_header_tags(fileder)\
  opts.scripts = opts.scripts or ''\
  if not (opts.noview) then\
    content = [[      
\
\ ]] .. content .. [[
\
\ ]]\ end\ local buf = [[\ \ ]]\ buf = buf .. (function()\ if STATIC then\ return STATIC.style\ else\ return [[]]\ end\ end)()\ buf = buf .. [[]]\ buf = buf .. \"\\n \" .. tostring(opts.meta) .. \"\\n \" .. tostring(get_scripts(fileder)) .. \"\\n \\n \\n \" .. tostring(gen_header()) .. \"\\n\\n \" .. tostring(content) .. \"\\n\\n \" .. tostring(footer)\ buf = buf .. (function()\ if STATIC then\ return ''\ else\ return [[ \ ]]\ end\ end)()\ buf = buf .. opts.scripts\ if STATIC then\ buf = buf .. STATIC.scripts\ end\ buf = buf .. \"\\n \\n\"\ return buf\ end\ return {\ render = render\ }", "mmm/mmmfs/layout.moon"} p["mmm.mmmfs.cache"] = {"local Cache\ do\ local _class_0\ local _base_0 = {\ get = function(self, fileder, key)\ key = tostring(key)\ self.cache[fileder.path] = self.cache[fileder.path] or { }\ return self.cache[fileder.path][key]\ end,\ set = function(self, fileder, key, val)\ key = tostring(key)\ self.cache[fileder.path] = self.cache[fileder.path] 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()\ self.editor = 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',\ ondrop = function()\ return print(\"dropped\")\ end,\ onpaste = function()\ return print(\"pasted\")\ end,\ 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),\ button('rm', {\ class = 'tight',\ onclick = function(_, e)\ if window:confirm(\"continuing will permanently remove the facet '\" .. tostring(self.inspect_prop:get()) .. \"'.\") then\ local fileder = self.fileder:get()\ fileder:set(self.inspect_prop:get(), nil)\ return self:refresh(true)\ end\ end\ }),\ button('add', {\ class = 'tight',\ onclick = function(_, e)\ local facet = window:prompt(\"please enter the facet string ('name: type' or 'type'):\", 'text/markdown')\ if not facet or facet == '' or facet == js.null then\ return \ end\ local fileder = self.fileder:get()\ fileder:set(facet, '')\ self.inspect_prop:set(Key(facet))\ return self:refresh()\ end\ }),\ div({\ style = {\ flex = '1'\ }\ }),\ self.editor:map(function(e)\ return e and e.saveBtn\ end)\ }))\ _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(facet, 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) .. \"'\")\ do\ local res = apply_conversions(fileder, conversions, value, facet)\ self.editor:set((function()\ if res.EDITOR then\ return res\ end\ end)())\ return res\ end\ 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\ }\ }),\ button('↑', {\ disabled = i == 1,\ onclick = function(_, e)\ fileder:swap_children(i, i - 1)\ return self:refresh(true)\ end\ }),\ button('↓', {\ disabled = i == num,\ onclick = function(_, e)\ fileder:swap_children(i, i + 1)\ return self:refresh(true)\ end\ }),\ button('rm', {\ onclick = function(_, e)\ if window:confirm(\"continuing will permanently remove all content in '\" .. tostring(child.path) .. \"'.\") then\ fileder:remove_child(i)\ return self:refresh(true)\ end\ end\ })\ }))\ 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\ print(\"GET META \" .. tostring(fileder) .. \" : \" .. tostring(max_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\ print(tostring(fileder) .. \": ... \" .. tostring(result))\ coroutine.yield(result)\ end\ end\ end\ do\ local result = not guard_self and fileder:walk(path)\ if result then\ print(tostring(fileder) .. \": ... \" .. tostring(result))\ 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 render\ render = require('mmm.mmmfs.layout').render\ 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 = 'mmm/dom',\ out = 'text/html',\ cost = 3,\ transform = function(self, html, fileder)\ return render(html, fileder)\ 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 = ''\ 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\ 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"}