mmm​.s‑ol.nu

interesting projects and hardware
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 require = relative(..., 1)\
local lfs = require('lfs')\
local Store\
Store = require('.').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)\
      if forgiving == nil then\
        forgiving = false\
      end\
      local entries = { }\
      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\
          local entry_path = self.root .. tostring(path) .. \"/\" .. tostring(name)\
          if 'directory' ~= lfs.attributes(entry_path, 'mode') then\
            _continue_0 = true\
            break\
          end\
          entries[name] = {\
            name = name,\
            path = tostring(path) .. \"/\" .. tostring(name)\
          }\
          _continue_0 = true\
        until true\
        if not _continue_0 then\
          break\
        end\
      end\
      local sorted = { }\
      local order_file = 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\
      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 = 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)\
      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, 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, 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 require = relative(..., 0)\
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 = 'sql'\
  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('.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('.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 require = relative(..., 1)\
local sqlite = require('sqlite3')\
local Store\
Store = require('.').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 require = relative(..., 1)\
local Store\
Store = require('.').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.plugins.cites"] then p["mmm.mmmfs.plugins.cites"] = load("local div, span, sup, a, i, b\
do\
  local _obj_0 = require('mmm.dom')\
  div, span, sup, a, i, b = _obj_0.div, _obj_0.span, _obj_0.sup, _obj_0.a, _obj_0.i, _obj_0.b\
end\
local parse_bibtex\
parse_bibtex = function(src)\
  local type, key, kv = src:match('@(%w+){(.-),(.*)}')\
  do\
    local info = {\
      _type = type,\
      _key = key\
    }\
    for key, val in kv:gmatch('([a-z]-)%s*=%s*(%b{})') do\
      val:sub(2, -2)\
      info[key] = val:gsub('[{}]', '')\
    end\
    for key, val in kv:gmatch('([a-z]-)%s*=%s*(%d+)') do\
      info[key] = val\
    end\
    return info\
  end\
end\
local title\
title = function(self)\
  assert(self.title, \"cite doesn't have title\")\
  local inner = i(self.title)\
  if self.url then\
    return a(inner, {\
      href = self.url,\
      style = {\
        display = 'inline'\
      }\
    })\
  else\
    return b(inner)\
  end\
end\
local format_full\
format_full = function(self)\
  local tt = title(self)\
  local dot, com\
  if self.title:match('[.?!]$') then\
    dot, com = '', ''\
  else\
    dot, com = '.', ','\
  end\
  self.author = self.author or 'N. N.'\
  local _exp_0 = self._type\
  if 'book' == _exp_0 or 'article' == _exp_0 then\
    return span((function()\
      do\
        local _with_0 = setmetatable({ }, {\
          __index = table\
        })\
        _with_0:insert(tostring(self.author) .. \" (\" .. tostring(self.year) .. \"), \")\
        _with_0:insert(tt)\
        if self.journal then\
          _with_0:insert(tostring(dot) .. \" \")\
          _with_0:insert(i(self.journal))\
          if self.volume then\
            _with_0:insert(\", volume \" .. tostring(self.volume))\
          end\
        else\
          if self.series then\
            _with_0:insert(tostring(dot) .. \" \")\
            _with_0:insert(i(self.series))\
            if self.number then\
              _with_0:insert(\", No. \" .. tostring(self.number))\
            end\
          end\
        end\
        if self.pages then\
          _with_0:insert(\", pages \" .. tostring(self.pages))\
        end\
        if self.publisher then\
          _with_0:insert(tostring(dot) .. \" \" .. tostring(self.publisher))\
        end\
        if self.doi then\
          _with_0:insert(tostring(dot) .. \" \")\
          _with_0:insert(a(\"doi:\" .. tostring(self.doi), {\
            href = \"https://doi.org/\" .. tostring(self.doi)\
          }))\
        end\
        return _with_0\
      end\
    end)())\
  elseif 'web' == _exp_0 or 'online' == _exp_0 then\
    return span((function()\
      do\
        local _with_0 = setmetatable({ }, {\
          __index = table\
        })\
        _with_0:insert(tostring(self.author))\
        if self.year then\
          _with_0:insert(\" (\" .. tostring(self.year) .. \")\")\
        end\
        _with_0:insert(\", \")\
        _with_0:insert(tt)\
        _with_0:insert(tostring(com) .. \" \" .. tostring(self.url))\
        if self.visited then\
          _with_0:insert(\" from \" .. tostring(self.visited))\
        end\
        return _with_0\
      end\
    end)())\
  else\
    span((function()\
      do\
        local _with_0 = setmetatable({ }, {\
          __index = table\
        })\
        _with_0:insert(tostring(self.author) .. \" (\" .. tostring(self.year) .. \"), \")\
        _with_0:insert(tt)\
        if self.publisher then\
          _with_0:insert(tostring(dot) .. \" \" .. tostring(self.publisher))\
        end\
        return _with_0\
      end\
    end)())\
    return span(tbl)\
  end\
end\
return {\
  converts = {\
    {\
      inp = 'cite/doi',\
      out = 'URL -> text/bibtex',\
      cost = 0.1,\
      transform = function(self, doi)\
        doi = doi:match('(10%.%d%d%d%d%d?%d?%d?%d?%d?/[%d%w%.%-_:;%(%)]+)')\
        return \"http://api.crossref.org/works/\" .. tostring(doi) .. \"/transform/application/x-bibtex\"\
      end\
    },\
    {\
      inp = 'text/bibtex',\
      out = 'mmm/dom',\
      cost = 1,\
      transform = function(self, bib)\
        return format_full(parse_bibtex(bib))\
      end\
    }\
  }\
}\
", "mmm/mmmfs/plugins/cites.lua") end
if not p["mmm.mmmfs.plugins.code"] then p["mmm.mmmfs.plugins.code"] = load("local pre, div, button\
do\
  local _obj_0 = require('mmm.dom')\
  pre, div, button = _obj_0.pre, _obj_0.div, _obj_0.button\
end\
local languages\
languages = require('mmm.highlighting').languages\
local Editor\
do\
  local _class_0\
  local o\
  local _base_0 = {\
    EDITOR = true,\
    change = function(self)\
      self.timeout = nil\
      local doc = self.cm:getDoc()\
      if self.lastPreview and doc:isClean(self.lastPreview) then\
        return \
      end\
      self.lastPreview = doc:changeGeneration()\
      local value = doc:getValue()\
      self.fileder.facets[self.key] = value\
      return BROWSER:refresh()\
    end,\
    save = function(self, e)\
      e:preventDefault()\
      local doc = self.cm:getDoc()\
      self.fileder:set(self.key, doc:getValue())\
      self.lastSave = doc:changeGeneration(true)\
    end\
  }\
  _base_0.__index = _base_0\
  _class_0 = setmetatable({\
    __init = function(self, value, mode, fileder, key)\
      self.fileder, self.key = fileder, key\
      self.node = div({\
        class = 'editor'\
      })\
      do\
        local _with_0 = button('save')\
        _with_0.disabled = true\
        _with_0.onclick = function(_, e)\
          return self:save(e)\
        end\
        self.saveBtn = _with_0\
      end\
      self.cm = window:CodeMirror(self.node, o({\
        value = value,\
        mode = mode,\
        lineNumber = true,\
        lineWrapping = true,\
        autoRefresh = true,\
        theme = 'hybrid'\
      }))\
      self.lastSave = self.cm:getDoc():changeGeneration(true)\
      return self.cm:on('changes', function(_, mirr)\
        local doc = self.cm:getDoc()\
        self.saveBtn.disabled = doc:isClean(self.lastSave)\
        if self.timeout then\
          window:clearTimeout(self.timeout)\
        end\
        self.timeout = window:setTimeout((function()\
          return self:change()\
        end), 300)\
      end)\
    end,\
    __base = _base_0,\
    __name = \"Editor\"\
  }, {\
    __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\
  if MODE == 'CLIENT' then\
    local mkobj = window:eval(\"(function () { return {}; })\")\
    o = function(tbl)\
      do\
        local obj = mkobj()\
        for k, v in pairs(tbl) do\
          obj[k] = v\
        end\
        return obj\
      end\
    end\
  end\
  Editor = _class_0\
end\
return {\
  converts = {\
    {\
      inp = 'text/([^ ]*).*',\
      out = 'mmm/dom',\
      cost = 5,\
      transform = function(self, val)\
        local lang = self.from:match(self.convert.inp)\
        return pre(languages[lang](val))\
      end\
    }\
  },\
  editors = (function()\
    if MODE == 'CLIENT' then\
      return {\
        {\
          inp = 'text/([^ ]*).*',\
          out = 'mmm/dom',\
          cost = 0,\
          transform = function(self, value, fileder, key)\
            local mode = self.from:match(self.convert.inp)\
            return Editor(value, mode, fileder, key)\
          end\
        },\
        {\
          inp = 'URL.*',\
          out = 'mmm/dom',\
          cost = 0,\
          transform = function(self, value, fileder, key)\
            return Editor(value, nil, fileder, key)\
          end\
        }\
      }\
    end\
  end)()\
}\
", "mmm/mmmfs/plugins/code.lua") end
if not p["mmm.mmmfs.plugins"] then p["mmm.mmmfs.plugins"] = load("local require = relative(..., 1)\
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('.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 editors = { }\
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 = 1,\
    transform = function(self, src, fileder)\
      return img({\
        src = src\
      })\
    end\
  },\
  {\
    inp = 'URL -> video/.+%+gif',\
    out = 'mmm/dom',\
    cost = 0.99,\
    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 = 1,\
    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 MODE == 'CLIENT' or UNSAFE then\
  table.insert(converts, {\
    inp = 'text/lua -> (.+)',\
    out = '%1',\
    cost = 0.5,\
    transform = loadwith(load or loadstring)\
  })\
end\
local add_converts\
add_converts = function(module)\
  local ok, plugin = pcall(require, \".plugins.\" .. tostring(module))\
  if not ok then\
    print(\"[Plugins] couldn't load plugins.\" .. tostring(module) .. \": \" .. tostring(plugin))\
    return \
  end\
  print(\"[Plugins] loaded plugins.\" .. tostring(module))\
  if plugin.converts then\
    local _list_0 = plugin.converts\
    for _index_0 = 1, #_list_0 do\
      local convert = _list_0[_index_0]\
      table.insert(converts, convert)\
    end\
  end\
  if plugin.editors then\
    local _list_0 = plugin.editors\
    for _index_0 = 1, #_list_0 do\
      local editor = _list_0[_index_0]\
      table.insert(editors, editor)\
    end\
  end\
end\
add_converts('code')\
add_converts('json')\
add_converts('markdown')\
add_converts('mermaid')\
add_converts('twitter')\
add_converts('youtube')\
add_converts('cites')\
if STATIC then\
  add_converts('static')\
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 == '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)\
    })\
  end\
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\
return {\
  converts = converts,\
  editors = editors\
}\
", "mmm/mmmfs/plugins/init.lua") end
if not p["mmm.mmmfs.plugins.json"] then p["mmm.mmmfs.plugins.json"] = load("local encode\
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] = 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(encode(k)) .. \": \" .. tostring(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 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\
  local _ = encode\
  decode = function(str)\
    return fix(JSON:parse(str))\
  end\
else\
  do\
    local cjson = require('cjson')\
    if cjson then\
      decode = cjson.decode\
    else\
      decode = warn('only partial JSON support, please install cjson')\
    end\
  end\
end\
return {\
  converts = {\
    {\
      inp = 'table',\
      out = 'text/json',\
      cost = 2,\
      transform = function(self, val)\
        return encode(val)\
      end\
    },\
    (function()\
      if decode then\
        return {\
          inp = 'text/json',\
          out = 'table',\
          cost = 1,\
          transform = function(self, val)\
            return decode(val)\
          end\
        }\
      end\
    end)()\
  }\
}\
", "mmm/mmmfs/plugins/json.lua") end
if not p["mmm.mmmfs.plugins.markdown"] then p["mmm.mmmfs.plugins.markdown"] = load("local markdown\
if MODE == 'SERVER' then\
  local success, discount = pcall(require, 'discount')\
  assert(success, \"couldn't require 'discount'\")\
  markdown = function(md)\
    local res = assert(discount.compile(md, 'githubtags', 'fencedcode'))\
    return res.body\
  end\
else\
  assert(window and window.marked, \"marked.js not found\")\
  local o\
  do\
    local mkobj = window:eval(\"(function () { return {}; })\")\
    o = function(tbl)\
      do\
        local obj = mkobj()\
        for k, v in pairs(tbl) do\
          obj[k] = v\
        end\
        return obj\
      end\
    end\
  end\
  local trim\
  trim = function(str)\
    return str:match('^ *(..-) *$')\
  end\
  window.marked:setOptions(o({\
    gfm = true,\
    smartypants = true,\
    langPrefix = 'lang-',\
    highlight = function(self, code, lang)\
      code = trim(code)\
      local result\
      if lang and #lang > 0 then\
        result = window.hljs:highlight(lang, code, true)\
      else\
        result = window.hljs:highlightAuto(code)\
      end\
      return result.value\
    end\
  }))\
  do\
    local _base_0 = window\
    local _fn_0 = _base_0.marked\
    markdown = function(...)\
      return _fn_0(_base_0, ...)\
    end\
  end\
end\
assert(markdown, \"no markdown implementation found\")\
return {\
  converts = {\
    {\
      inp = 'text/markdown',\
      out = 'text/html+frag',\
      cost = 1,\
      transform = function(self, md)\
        return \"
\" .. tostring(markdown(md)) .. \"
\"\ end\ },\ {\ inp = 'text/markdown%+sidenotes',\ out = 'text/html+frag',\ cost = 1,\ transform = function(self, md)\ return \"
\" .. tostring(markdown(md)) .. \"
\"\ end\ },\ {\ inp = 'text/markdown%+wide',\ out = 'text/html+frag',\ cost = 1,\ transform = function(self, md)\ return \"
\" .. tostring(markdown(md)) .. \"
\"\ end\ },\ {\ inp = 'text/markdown%+span',\ out = 'text/html+frag',\ cost = 1,\ transform = function(self, source)\ local html = markdown(source)\ html = html:gsub('^%s*

%s*', '')\ html = html:gsub('%s*

%s*$', '')\ return html\ end\ }\ }\ }\ ", "mmm/mmmfs/plugins/markdown.lua") end if not p["mmm.mmmfs.plugins.mermaid"] then p["mmm.mmmfs.plugins.mermaid"] = load("assert(window and window.mermaid, \"mermaid.js not found\")\ window.mermaid:initialize({\ startOnLoad = false,\ fontFamily = 'monospace'\ })\ local id_counter = 1\ return {\ converts = {\ {\ inp = 'text/mermaid-graph',\ out = 'mmm/dom',\ cost = 1,\ transform = function(self, source, fileder, key)\ id_counter = id_counter + 1\ local id = \"mermaid-\" .. tostring(id_counter)\ do\ local container = document:createElement('div')\ local cb\ cb = function(self, svg)\ container.innerHTML = svg\ container.firstElementChild.style.width = '100%'\ container.firstElementChild.style.height = 'auto'\ end\ window:setImmediate(function(_)\ return window.mermaid:render(id, source, cb, container)\ end)\ return container\ end\ end\ }\ }\ }\ ", "mmm/mmmfs/plugins/mermaid.lua") end if not p["mmm.mmmfs.plugins.static"] then p["mmm.mmmfs.plugins.static"] = load("local extensions = {\ ['image/jpeg'] = 'jpg',\ ['image/png'] = 'png',\ ['image/svg+xml'] = 'svg',\ ['video/webm'] = 'webm',\ ['video/mp4'] = 'mp4',\ ['text/javascript'] = 'js',\ ['text/css'] = 'css'\ }\ return {\ 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\ }\ }\ }\ ", "mmm/mmmfs/plugins/static.lua") end if not p["mmm.mmmfs.plugins.twitter"] then p["mmm.mmmfs.plugins.twitter"] = load("local div, blockquote, a\ do\ local _obj_0 = require('mmm.dom')\ div, blockquote, a = _obj_0.div, _obj_0.blockquote, _obj_0.a\ end\ return {\ converts = {\ {\ inp = 'URL -> twitter/tweet',\ out = 'mmm/dom',\ cost = 1,\ transform = function(self, href)\ local id = assert((href:match('twitter.com/[^/]-/status/(%d*)')), \"couldn't parse twitter/tweet URL: '\" .. tostring(href) .. \"'\")\ if MODE == 'CLIENT' then\ do\ local parent = div()\ window.twttr.widgets:createTweet(id, parent)\ return parent\ end\ else\ return div(blockquote({\ class = 'twitter-tweet',\ ['data-lang'] = 'en',\ a('(linked tweet)', {\ href = href\ })\ }))\ end\ end\ }\ }\ }\ ", "mmm/mmmfs/plugins/twitter.lua") end if not p["mmm.mmmfs.plugins.youtube"] then p["mmm.mmmfs.plugins.youtube"] = load("local iframe\ iframe = require('mmm.dom').iframe\ return {\ converts = {\ {\ inp = 'URL -> youtube/video',\ out = 'mmm/dom',\ cost = 1,\ transform = function(self, link)\ local id = link:match('youtu%.be/([^/]+)')\ id = id or link:match('youtube.com/watch.*[?&]v=([^&]+)')\ id = id or link:match('youtube.com/[ev]/([^/]+)')\ id = id or link:match('youtube.com/embed/([^/]+)')\ assert(id, \"couldn't parse youtube URL: '\" .. tostring(link) .. \"'\")\ return iframe({\ width = 560,\ height = 315,\ frameborder = 0,\ allowfullscreen = true,\ frameBorder = 0,\ src = \"//www.youtube.com/embed/\" .. tostring(id)\ })\ end\ }\ }\ }\ ", "mmm/mmmfs/plugins/youtube.lua") end if not p["mmm.mmmfs.browser"] then p["mmm.mmmfs.browser"] = load("local require = relative(..., 1)\ local Key\ Key = require('.fileder').Key\ local get_conversions, apply_conversions\ do\ local _obj_0 = require('.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('.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, PLUGINS.converts, PLUGINS.editors)\ 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(prop, self.inspect_err, function(fileder, prop)\ local value, key = fileder:get(prop)\ assert(key, \"couldn't @get \" .. tostring(prop))\ local conversions = get_conversions('mmm/dom', key.type, get_casts())\ assert(conversions, \"cannot cast '\" .. tostring(key.type) .. \"'\")\ do\ local res = apply_conversions(conversions, value, fileder, prop)\ 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.conversion"] then p["mmm.mmmfs.conversion"] = load("local require = relative(..., 1)\ local refs = require('mmm.refs')\ local Queue\ Queue = require('.queue').Queue\ 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 print_conversions\ local MermaidDebugger\ do\ local _class_0\ local _base_0 = {\ 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:append(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:append(tostring(id) .. \"[\\\"\" .. tostring(type) .. \" [\" .. tostring(cost) .. \"]\\\"]\")\ end\ self:append(\"classDef have fill:#ada\")\ self:append(\"classDef want fill:#add\")\ return 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 = \"graph TD\\n\"\ 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_conversions\ get_conversions = function(want, have, converts, limit, debug)\ if converts == nil then\ converts = PLUGINS and PLUGINS.converts\ end\ if limit == nil then\ limit = 5\ end\ 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)()))\ 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 or cost > limit then\ 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\ if debug then\ debug:type_class(result, 'want')\ end\ best:add(next_entry, next_entry.cost)\ 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\ 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(conversions, value, ...)\ 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, ...)\ refs:pop()\ if not ok then\ local f, k = ...\ error(\"error while converting \" .. tostring(f) .. \" \" .. tostring(k) .. \" from '\" .. tostring(step.from) .. \"' to '\" .. tostring(step.to) .. \"':\\n\" .. tostring(value))\ end\ end\ return value\ end\ local convert\ convert = function(have, want, value, ...)\ local conversions, start = get_conversions(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(conversions, value, ...)\ 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 require = relative(..., 1)\ local get_conversions, apply_conversions\ do\ local _obj_0 = require('.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\ if not index then\ index = self.store:get_index(self.path)\ end\ local _list_0 = index.children\ for _index_0 = 1, #_list_0 do\ local path_or_index = _list_0[_index_0]\ table.insert(self.children, Fileder(self.store, path_or_index))\ 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\ 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(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(conversions, self.facets[key], self, 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)\ 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)\ if path == nil then\ path = ''\ end\ self.store, self.path = store, path\ 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) then\ return self:walk(tostring(self.path) .. \"/\" .. tostring(k))\ else\ return rawget(t, k)\ end\ end,\ __newindex = function(t, k, child)\ rawset(t, k, child)\ if child.path then\ return \ end\ if self.path == '/' then\ return child:mount('/')\ elseif self.path then\ return child:mount(self.path .. '/')\ end\ 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"] then p["mmm.mmmfs"] = load("local require = relative(..., 0)\ PLUGINS = require('.plugins')\ ", "mmm/mmmfs/init.lua") end if not p["mmm.mmmfs.layout"] then p["mmm.mmmfs.layout"] = load("local require = relative(..., 1)\ 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 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_meta\ get_meta = 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 render\ render = function(content, fileder, opts)\ if opts == nil then\ opts = { }\ end\ opts.meta = opts.meta or get_meta(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(get_meta(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\ buf = buf .. (function()\ if STATIC then\ return STATIC.scripts\ else\ return ''\ end\ end)()\ buf = buf .. \"\\n \\n\"\ return buf\ end\ return {\ render = render\ }\ ", "mmm/mmmfs/layout.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(fileder, origin)\ if 'string' == type(fileder) then\ if fileder == '' then\ assert(origin, \"cannot resolve empty path without origin!\")\ return origin\ end\ if '/' ~= fileder:sub(1, 1) then\ assert(origin, \"cannot resolve relative path '\" .. tostring(fileder) .. \"' without origin!\")\ fileder = tostring(origin.path) .. \"/\" .. tostring(fileder)\ end\ while fileder:match('/([^/]-)/%.%./') do\ fileder = fileder:gsub('/([^/]-)/%.%./', '/')\ end\ if origin.path == fileder:sub(1, #origin.path) then\ return assert((origin:walk(fileder)), \"couldn't resolve path '\" .. tostring(fileder) .. \"' from \" .. tostring(origin))\ else\ assert(BROWSER and BROWSER.root, \"cannot resolve absolute path '\" .. tostring(fileder) .. \"' without BROWSER and root set!\")\ return assert((BROWSER.root:walk(fileder)), \"couldn't resolve path '\" .. tostring(fileder) .. \"'\")\ end\ else\ return assert(fileder, \"no fileder 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 {\ 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'\ do\ local _require = require\ relative = function(base, sub)\ if not ('number' == type(sub)) then\ sub = 0\ end\ for i = 1, sub do\ base = base:match('^(.*)%.%w+$')\ end\ return function(name, x)\ if name == '.' then\ name = base\ else\ if '.' == name:sub(1, 1) then\ name = base .. name\ end\ end\ return _require(name)\ end\ end\ end\ 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