mmm​.s‑ol.nu

new experiments and mostly code
an error occured while rendering this view:
local p = package.preload
if not p["mmm.component"] then p["mmm.component"] = load("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.lua") end
if not p["mmm.dom"] then p["mmm.dom"] = load("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.lua") end
if not p["mmm.mmmfs.stores.fs"] then p["mmm.mmmfs.stores.fs"] = load("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))\
            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))\
      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.lua") end
if not p["mmm.mmmfs.stores"] then p["mmm.mmmfs.stores"] = load("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.lua") end
if not p["mmm.mmmfs.stores.sql"] then p["mmm.mmmfs.stores.sql"] = load("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.lua") end
if not p["mmm.mmmfs.stores.web"] then p["mmm.mmmfs.stores.web"] = load("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.lua") end
if not p["mmm.mmmfs.browser"] then p["mmm.mmmfs.browser"] = load("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.lua") end
if not p["mmm.mmmfs.builtins"] then p["mmm.mmmfs.builtins"] = load("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 == 'SERVER' then\
  local ok, moon = pcall(require, 'moonscript.base')\
  if ok then\
    local _load = moon.load or moon.loadstring\
    if UNSAFE then\
      table.insert(converts, {\
        inp = 'text/moonscript -> (.+)',\
        out = '%1',\
        cost = 1,\
        transform = loadwith(moon.load or moon.loadstring)\
      })\
    end\
    table.insert(converts, {\
      inp = 'text/moonscript -> (.+)',\
      out = 'text/lua -> %1',\
      cost = 2,\
      transform = single(moon.to_lua)\
    })\
  else\
    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\
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.lua") end
if not p["mmm.mmmfs.conversion"] then p["mmm.mmmfs.conversion"] = load("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.lua") end
if not p["mmm.mmmfs.fileder"] then p["mmm.mmmfs.fileder"] = load("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\
      local key, conversions = self:find(want)\
      if key then\
        local value = apply_conversions(self, conversions, self.facets[key], key)\
        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.lua") end
if not p["mmm.mmmfs.layout"] then p["mmm.mmmfs.layout"] = load("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.lua") end if not p["mmm.mmmfs.meta"] then p["mmm.mmmfs.meta"] = load("local yield_ancestors\ do\ local step\ step = function(self, path)\ if '/' ~= path:sub(1, 1) then\ path = tostring(self.path) .. \"/\" .. tostring(path)\ end\ if not (self.path == path:sub(1, #self.path)) then\ return \ end\ if #path == #self.path then\ return \ end\ coroutine.yield(self)\ local _list_0 = self.children\ for _index_0 = 1, #_list_0 do\ local child = _list_0[_index_0]\ step(child, path)\ end\ end\ yield_ancestors = function(self, path)\ return coroutine.wrap(function()\ return step(self, path)\ end)\ end\ end\ local get_meta\ get_meta = function(fileder, path)\ if path then\ path = \"$mmm/\" .. tostring(path)\ else\ path = '$mmm'\ end\ local guard_self\ local max_path = fileder.path\ do\ local closest = max_path:match('(.-)/$mmm')\ if closest then\ max_path = closest\ guard_self = true\ end\ end\ assert(fileder.root, \"'\" .. tostring(fileder) .. \"' has no root!\")\ return coroutine.wrap(function()\ for ancestor in yield_ancestors(fileder.root, max_path) do\ if guard_self and ancestor.path == max_path then\ break\ end\ do\ local result = ancestor:walk(path)\ if result then\ coroutine.yield(result)\ end\ end\ end\ 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.lua") end if not p["mmm.mmmfs.queue"] then p["mmm.mmmfs.queue"] = load("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.lua") end if not p["mmm.mmmfs.util"] then p["mmm.mmmfs.util"] = load("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.lua") end if not p["mmm.canvasapp"] then p["mmm.canvasapp"] = load("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.lua") end if not p["mmm.color"] then p["mmm.color"] = load("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.lua") end if not p["mmm.highlighting"] then p["mmm.highlighting"] = load("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.lua") end if not p["mmm"] then p["mmm"] = load("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.lua") end if not p["mmm.ordered"] then p["mmm.ordered"] = load("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.lua") end if not p["mmm.refs"] then p["mmm.refs"] = load("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.lua") end