From 30fb0dc40d595b9e0b7747ad8e5c4e8cf7e3023b Mon Sep 17 00:00:00 2001 From: s-ol Date: Thu, 1 Nov 2018 21:17:55 +1100 Subject: move mmm code from lib to mmm etc --- lib/mmmfs/browser.moon | 122 ------------------------------------ lib/mmmfs/conversion.moon | 118 ----------------------------------- lib/mmmfs/fileder.moon | 155 ---------------------------------------------- lib/mmmfs/init.moon | 34 ---------- 4 files changed, 429 deletions(-) delete mode 100644 lib/mmmfs/browser.moon delete mode 100644 lib/mmmfs/conversion.moon delete mode 100644 lib/mmmfs/fileder.moon delete mode 100644 lib/mmmfs/init.moon (limited to 'lib/mmmfs') 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 -} -- cgit v1.2.3