diff options
| author | s-ol <s-ol@users.noreply.github.com> | 2018-10-30 02:41:14 +0000 |
|---|---|---|
| committer | s-ol <s-ol@users.noreply.github.com> | 2018-10-30 02:41:14 +0000 |
| commit | 3b02770e7f9ec14487493c68ff12ec42e0f2755b (patch) | |
| tree | 45c8d7d8ef4c813634321f280146e8ddad9c333e /lib | |
| parent | update interp docs (diff) | |
| download | mmm-3b02770e7f9ec14487493c68ff12ec42e0f2755b.tar.gz mmm-3b02770e7f9ec14487493c68ff12ec42e0f2755b.zip | |
reorganize lib
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/color.moon (renamed from lib/color.shared.moon) | 0 | ||||
| -rw-r--r-- | lib/init.client.moon | 2 | ||||
| -rw-r--r-- | lib/mmmfs/browser.moon | 99 | ||||
| -rw-r--r-- | lib/mmmfs/conversion.moon | 118 | ||||
| -rw-r--r-- | lib/mmmfs/init.moon | 98 | ||||
| -rw-r--r-- | lib/ordered.moon (renamed from lib/ordered.shared.moon) | 0 |
6 files changed, 316 insertions, 1 deletions
diff --git a/lib/color.shared.moon b/lib/color.moon index 6233b47..6233b47 100644 --- a/lib/color.shared.moon +++ b/lib/color.moon diff --git a/lib/init.client.moon b/lib/init.client.moon index d39143d..0fbaaf7 100644 --- a/lib/init.client.moon +++ b/lib/init.client.moon @@ -25,7 +25,7 @@ warn = (...) -> contents = [deep_tostring v for v in *{ ... } ] console\warn table.unpack contents -package.path = '/?.shared.moon.lua;/?.client.moon.lua;/?.moon.lua;/?/init.moon.lua;/?.lua;/?/init.lua' +package.path = '/?.client.moon.lua;/?.moon.lua;/?/init.moon.lua;/?.lua;/?/init.lua' -- relative imports relative = do diff --git a/lib/mmmfs/browser.moon b/lib/mmmfs/browser.moon new file mode 100644 index 0000000..427d952 --- /dev/null +++ b/lib/mmmfs/browser.moon @@ -0,0 +1,99 @@ +import ReactiveVar, text, elements from require 'lib.component' +import div, span, a, select, option from elements + +limit = (list, num) -> [v for i,v in ipairs list when i <= num] + +class Browser + new: (@root) => + @path = ReactiveVar {} + @path\subscribe (path) -> window.location.hash = '/' .. table.concat path, '/' + @prop = ReactiveVar (@root\find 'mmm/dom') or next @root.props + @active = @path\map (path) -> + fileder = @root + for name in *path + local next + for child in *fileder.children + if name == child\get 'name', 'alpha' + next = child + break + + if not next + return + + fileder = next + + fileder + + @active\subscribe (fileder) -> @prop\set (fileder\find 'mmm/dom') or next fileder.props + + @tree = div { + style: { + position: 'absolute', + top: 0, + bottom: 0, + left: 0, + right: 0, + display: 'flex', + overflow: 'hidden', + 'flex-direction': 'column', + 'justify-content': 'space-between', + }, + div { + style: { + padding: '1em', + flex: '0 0 auto', + display: 'flex', + 'justify-content': 'space-between', + background: '#eeeeee', + }, + span 'path: ', @path\map (path) -> with div style: { display: 'inline-block' } + \append a 'root', href: '#', onclick: (_, e) -> + e\preventDefault! + @navigate {} + + for i,name in ipairs path + \append '/' + \append a name, href: '#', onclick: (_, e) -> + e\preventDefault! + @navigate limit path, i + + span 'view property: ', @active\map (fileder) -> + onchange = (_, e) -> + @prop\set Key e.target.value + + with select :onchange + if fileder + for key, _ in pairs fileder.props + value = key\tostring! + \append option value, :value + } + + div { + style: { + flex: '1 0 0', + overflow: 'auto', + padding: '1em 2em', + }, + @prop\map (prop) -> + active = @active\get! + + ok, res = pcall -> + -- val, key = active\get prop.name, prop.type + -- CONVERT 'mmm/dom', val, key + active\get prop.name, 'mmm/dom' + + if ok and res + res + else + warn "error: ", res unless ok + span "cannot display!", style: { color: '#f00' } + } + } + + @node = @tree.node + + navigate: (new) => @path\set new + +{ + :Browser, +} diff --git a/lib/mmmfs/conversion.moon b/lib/mmmfs/conversion.moon new file mode 100644 index 0000000..7f86aa4 --- /dev/null +++ b/lib/mmmfs/conversion.moon @@ -0,0 +1,118 @@ +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/init.moon b/lib/mmmfs/init.moon new file mode 100644 index 0000000..2393c75 --- /dev/null +++ b/lib/mmmfs/init.moon @@ -0,0 +1,98 @@ +require = relative ... +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 + + @props = { (Key k), v for k, v in pairs props } + + -- find property key according to criteria, nil if no value or conversion path + -- * name - property name (optional: defaults to main content) + -- * type - wanted result type + 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 + -- * name - property name (optional: defaults to main content) + -- * type - wanted result type + 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/ordered.shared.moon b/lib/ordered.moon index 59c07bf..59c07bf 100644 --- a/lib/ordered.shared.moon +++ b/lib/ordered.moon |
