aboutsummaryrefslogtreecommitdiffstats
path: root/lib/mmmfs
diff options
context:
space:
mode:
Diffstat (limited to 'lib/mmmfs')
-rw-r--r--lib/mmmfs/browser.moon122
-rw-r--r--lib/mmmfs/conversion.moon118
-rw-r--r--lib/mmmfs/fileder.moon155
-rw-r--r--lib/mmmfs/init.moon34
4 files changed, 0 insertions, 429 deletions
diff --git a/lib/mmmfs/browser.moon b/lib/mmmfs/browser.moon
deleted file mode 100644
index ce7709f..0000000
--- a/lib/mmmfs/browser.moon
+++ /dev/null
@@ -1,122 +0,0 @@
-require = relative ..., 1
-import Key from require '.fileder'
-import get_conversions from require '.conversion'
-import ReactiveVar, get_or_create, text, elements from require 'lib.component'
-import div, span, a, select, option from elements
-
-class Browser
- new: (@root, path='/', rehydrate=false) =>
- -- root fileder
- assert @root, 'root fileder is nil'
-
- -- active path
- @path = ReactiveVar path
-
- if MODE == 'CLIENT'
- -- update URL bar
- @path\subscribe (path) ->
- path ..= '/' unless path\match '/$'
- window.history\pushState nil, '', path
-
- -- active fileder
- -- (re)set every time @path changes
- @active = @path\map @root\walk
-
- -- currently active property
- -- (re)set to default every time @active changes
- @prop = @active\map (fileder) ->
- return unless fileder
- (fileder\find 'mmm/dom') or next fileder.props
-
- -- retrieve or create the root
- @dom = get_or_create 'div', 'browser-root'
-
- -- prepend the navbar
- if MODE == 'SERVER'
- @dom\append div id: 'browser-navbar'
- else
- @dom\prepend get_or_create 'div', 'browser-navbar', {
- span 'path: ', @path\map (path) -> with div style: { display: 'inline-block' }
- path_segment = (name, href) ->
- a name, :href, onclick: (_, e) ->
- e\preventDefault!
- @navigate href
-
- href = ''
- path = path\match '^/(.*)'
-
- \append path_segment 'root', '/'
-
- while path
- name, rest = path\match '^(%w+)/(.*)'
- if not name
- name = path
-
- path = rest
- href = "#{href}/#{name}"
-
- \append '/'
- \append path_segment name, href
-
- span 'view property: ', @active\map (fileder) ->
- onchange = (_, e) ->
- @prop\set Key e.target.value
-
- current = @prop\get!
- current = current and current\tostring!
- with select :onchange, disabled: not fileder
- if fileder
- for key, _ in pairs fileder.props
- value = key\tostring!
- \append option value, :value, selected: value == current
- }
-
- -- append or patch #browser-content
- @dom\append with get_or_create 'div', 'browser-content'
- \append @get_content!, (rehydrate and .node.lastChild)
-
- if rehydrate
- -- force one rerender to set onclick handlers etc
- @prop\set @prop\get!
-
- -- export mmm/component interface
- @node = @dom.node
- @render = @dom\render
-
- -- render #browser-content
- get_content: () =>
- disp_error = (msg) -> span msg, style: { color: '#f00' }
- @prop\map (prop) ->
- active = @active\get!
-
- return disp_error "fileder not found!" unless active
- return disp_error "property not found!" unless prop
-
- convert = ->
- conversions = get_conversions 'mmm/dom', prop.type
- value = assert (active\get prop), "value went missing?"
-
- return unless conversions
-
- for i=#conversions,1,-1
- { :inp, :out, :transform } = conversions[i]
- value = transform value, active
-
- value
-
- ok, res = if MODE == 'CLIENT'
- pcall convert
- else
- true, convert!
-
- if ok
- res or disp_error "[no conversion path to mmm/dom]"
- else
- warn "error: ", res unless ok
- disp_error "[unknown error displaying]"
-
- navigate: (new) => @path\set new
-
-{
- :Browser
-}
diff --git a/lib/mmmfs/conversion.moon b/lib/mmmfs/conversion.moon
deleted file mode 100644
index 7f86aa4..0000000
--- a/lib/mmmfs/conversion.moon
+++ /dev/null
@@ -1,118 +0,0 @@
-import text, code from require 'lib.dom'
-import tohtml from require 'lib.component'
-
--- limit function to one argument
-single = (func) -> (val) -> func val
-
--- list of converts
--- converts each have
--- * inp - input type. can capture subtypes using `(.+)`
--- * out - output type. can substitute subtypes from inp with %1, %2 etc.
--- * transform - function (val: inp, fileder) -> val: out
-converts = {
- {
- inp: 'moon -> (.+)',
- out: '%1',
- transform: (val, fileder) -> val fileder
- },
- {
- inp: 'text/plain',
- out: 'mmm/dom',
- transform: single text
- },
- {
- inp: 'alpha',
- out: 'mmm/dom',
- transform: single code
- },
- {
- inp: 'URL -> .*',
- out: 'mmm/dom',
- transform: single code
- },
- {
- inp: 'mmm/component',
- out: 'mmm/dom',
- transform: single tohtml
- },
- {
- inp: 'mmm/dom',
- out: 'text/html',
- transform: (node) -> if MODE == 'SERVER' then node else node.outerHTML
- },
- {
- inp: 'text/html',
- out: 'mmm/dom',
- transform: if MODE == 'SERVER'
- (...) -> ...
- else
- (html) ->
- tmp = document\createElement 'div'
- tmp.innerHTML = html
- if tmp.childElementCount == 1
- tmp.firstChild
- else
- tmp
- }
-}
-
-do
- local markdown
- if MODE == 'SERVER'
- success, discount = pcall require, 'discount'
- markdown = discount if success
- else
- markdown = window and window.marked and window\marked
-
- if markdown
- table.insert converts, {
- inp: 'text/markdown',
- out: 'text/html',
- transform: single markdown
- }
-
-count = (base, pattern='->') -> select 2, base\gsub pattern, ''
-escape_inp = (inp) -> "^#{inp\gsub '([-/])', '%%%1'}$"
-
--- attempt to find a conversion path from 'have' to 'want'
--- * have - start type string or list of type strings
--- * want - stop type string
--- * limit - limit conversion amount
--- returns a list of conversion steps
-get_conversions = (want, have, limit=3) ->
- assert have, 'need starting type(s)'
-
- if 'string' == type have
- have = { have }
-
- assert #have > 0, 'need starting type(s) (list was empty)'
-
- iterations = limit + math.max table.unpack [count type for type in *have]
- have = [{ :start, rest: start, conversions: {} } for start in *have]
-
- for i=1, iterations
- next_have, c = {}, 1
- for { :start, :rest, :conversions } in *have
- if want == rest
- return conversions, start
- else
- for convert in *converts
- inp = escape_inp convert.inp
- matches = { rest\match inp }
- continue unless #matches > 0
- result = rest\gsub inp, convert.out
- if result
- next_have[c] = {
- :start,
- rest: result,
- conversions: { convert, table.unpack conversions }
- }
- c += 1
-
- have = next_have
- return unless #have > 0
-
-{
- :converts
- :get_conversions
-}
diff --git a/lib/mmmfs/fileder.moon b/lib/mmmfs/fileder.moon
deleted file mode 100644
index c3e40f7..0000000
--- a/lib/mmmfs/fileder.moon
+++ /dev/null
@@ -1,155 +0,0 @@
-require = relative ..., 1
-import get_conversions from require '.conversion'
-
--- Key of a Fileder Property
--- contains:
--- * @name - key name or '' for main content
--- * @type - type string (type -> type -> type)
-class Key
- -- instantiate from table w/ keys described above
- -- or string like '@name: @type' (name optional)
- new: (opts, second) =>
- if 'string' == type second
- @name, @type = (opts or ''), second
- elseif 'string' == type opts
- @name, @type = opts\match '(%w+): *(.+)'
- if not @name
- @name = ''
- @type = opts
- elseif 'table' == type opts
- @name = opts.name
- @type = opts.type
- else
- error "wrong argument type: #{type opts}, #{type second}"
-
- -- format as a string (see constructor)
- tostring: =>
- if @name == ''
- @type
- else
- "#{@name}: #{@type}"
-
--- Fileder itself
--- contains:
--- * @props - Property Map (Key to Value)
--- * @children - Children Array
-class Fileder
- -- instantiate from props and children tables
- -- or mix in one table (numeric keys are children, remainder props)
- -- prop-keys are passed to Key constructor
- new: (props, children) =>
- if not children
- children = for i, child in ipairs props
- props[i] = nil
- child
-
- -- automatically mount children on insert
- @children = setmetatable {}, __newindex: (t, k, child) ->
- rawset t, k, child
- if @path == '/'
- child\mount '/'
- elseif @path
- child\mount @path .. '/'
-
- -- copy children
- for i, child in ipairs children
- @children[i] = child
-
- -- automatically reify string keys on insert
- @props = setmetatable {}, __newindex: (t, key, v) ->
- rawset t, key, nil -- fix for fengari.io
- rawset t, (Key key), v
-
- -- copy props
- for k, v in pairs props
- @props[k] = v
-
- -- recursively walk to and return the fileder with @path == path
- -- * path - the path to walk to
- walk: (path) =>
- -- early-out if we are outside of the path already
- return unless path\match '^' .. @path
-
- -- gotcha
- return @ if path == @path
-
- for child in *@children
- result = child\walk path
- return result if result
-
- -- recursively mount fileder and children at path
- -- * path - the path to mount at (default: '/')
- -- * mount_as - dont append own name to path
- mount: (path='/', mount_as=false) =>
- assert not @path, "mounted twice: #{@path} and now #{path}"
-
- if mount_as
- @path = path
- else
- @path = path .. @gett 'name: alpha'
-
- if @path == '/'
- for child in *@children
- child\mount '/'
- else
- for child in *@children
- child\mount @path .. '/'
-
- -- recursively iterate all children (coroutine)
- -- * depth - depth to stop after; 1 = yield only self (default: infinite)
- iterate: (depth=0) =>
- coroutine.yield @
- return if depth == 1
-
- for child in *@children
- child\iterate depth - 1
-
- -- find property key according to criteria, nil if no value or conversion path
- -- * ... - arguments like Key
- find: (...) =>
- want = Key ...
-
- -- filter props by name
- matching = [ key for key in pairs @props when key.name == want.name ]
- return unless #matching > 0
-
- -- get shortest conversion path
- shortest_path, start = get_conversions want.type, [ key.type for key in *matching ]
-
- if start
- for key in *matching
- if key.type == start
- return key, shortest_path
-
- error "couldn't find key after resolution?"
-
- -- get property according to criteria, nil if no value or conversion path
- -- * ... - arguments like Key
- get: (...) =>
- want = Key ...
-
- -- find matching key and shortest conversion path
- key, conversions = @find want
-
- if key
- value = @props[key]
-
- -- apply conversions (in reverse order)
- for i=#conversions,1,-1
- { :inp, :out, :transform } = conversions[i]
- value = transform value, @
-
- value, key
-
- -- like @get, throw if no value or conversion path
- gett: (...) =>
- want = Key ...
-
- value, key = @get want
- assert value, "node doesn't have value for '#{want\tostring!}'"
- value, key
-
-{
- :Key
- :Fileder
-}
diff --git a/lib/mmmfs/init.moon b/lib/mmmfs/init.moon
deleted file mode 100644
index d0de45b..0000000
--- a/lib/mmmfs/init.moon
+++ /dev/null
@@ -1,34 +0,0 @@
-require = relative ...
-import Key, Fileder from require '.fileder'
-import Browser from require '.browser'
-import tohtml from require 'lib.component'
-
-define_fileders = (...) ->
- source_module = ...
-
- (...) ->
- with fileder = Fileder ...
- .source_module = source_module
-
-rehydrate = (path) ->
- import Browser from require 'lib.mmmfs.browser'
- root = require 'root'
- root\mount!
-
- export BROWSER
- BROWSER = Browser root, path, true
-
-render = (root, path) ->
- export BROWSER
- BROWSER = Browser root, path
-
- content = tohtml BROWSER
- content, on_client rehydrate, path
-
-{
- :Key
- :Fileder
- :render
- :define_fileders
- :module_roots
-}