diff options
| author | s-ol <s-ol@users.noreply.github.com> | 2018-10-27 12:31:00 +0000 |
|---|---|---|
| committer | s-ol <s-ol@users.noreply.github.com> | 2018-10-27 12:31:00 +0000 |
| commit | b88545ac5126b96ac27d9aa2278f9c9ee22a21f0 (patch) | |
| tree | 285ba37ca1eaca12672476d13e4240e03f88b98f | |
| parent | render mmmfs in client (diff) | |
| download | mmm-b88545ac5126b96ac27d9aa2278f9c9ee22a21f0.tar.gz mmm-b88545ac5126b96ac27d9aa2278f9c9ee22a21f0.zip | |
mmmfs browser etc
| -rw-r--r-- | app/mmmfs/browser.moon | 96 | ||||
| -rw-r--r-- | app/mmmfs/init.moon | 91 | ||||
| -rw-r--r-- | app/mmmfs/tree.moon | 27 |
3 files changed, 185 insertions, 29 deletions
diff --git a/app/mmmfs/browser.moon b/app/mmmfs/browser.moon new file mode 100644 index 0000000..822b957 --- /dev/null +++ b/app/mmmfs/browser.moon @@ -0,0 +1,96 @@ +import ReactiveVar, text, elements from require 'lib.component' +import div, span, a, select, option from elements + +append = (list, val) -> + list = [x for x in *list] + table.insert list, val + list + +class Browser + new: (@root) => + @path = ReactiveVar {} + @path\subscribe (path) -> window.location.hash = '/' .. table.concat path, '/' + @prop = ReactiveVar 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 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 {} + link = {} + for name in *path + link = append link, name + \append '/' + \append a name, href: '#', onclick: (_, e) -> + e\preventDefault! + @navigate link + + 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! + val, key = active\get prop.name, prop.type + + res = CONVERT 'mmm/dom', val, key + res or span "cannot display!", style: { color: '#f00' } + } + } + + @node = @tree.node + + navigate: (new) => @path\set new + +{ + :Browser, +} diff --git a/app/mmmfs/init.moon b/app/mmmfs/init.moon index d6ed9fe..1f2d2f6 100644 --- a/app/mmmfs/init.moon +++ b/app/mmmfs/init.moon @@ -48,6 +48,22 @@ class Key assert overrides[_name] or interps[_name], "interp not found: '#{_name}'" + -- format as a string (see constructor) + tostring: => + list = { table.unpack @interps } + table.insert list, @type + + type = table.concat list, ' -> ' + + if @name == '' + type + else + "#{@name}: #{type}" + + +import text, code from require 'lib.html' +import tohtml from require 'lib.component' + -- list of converts -- converts each have -- * inp - input type @@ -55,6 +71,16 @@ class Key -- * transform - function (inp) -> out converts = { { + inp: 'text/plain', + out: 'mmm/dom', + transform: text + }, + { + inp: 'alpha', + out: 'mmm/dom', + transform: code + }, + { inp: 'mmm/dom', out: 'text/html', transform: (node) -> if MODE == 'SERVER' then node else node.outerHTML @@ -62,17 +88,13 @@ converts = { { inp: 'mmm/component', out: 'mmm/dom', - transform: (...) -> - import tohtml from require 'lib.component' - tohtml ... + transform: tohtml }, { -- @TODO this chained rule *should* be inferred, but that's way too hot rn inp: 'mmm/component', out: 'text/html', transform: (node) -> - import tohtml from require 'lib.component' - node = tohtml node if MODE == 'SERVER' then node else node.outerHTML }, @@ -133,11 +155,11 @@ class Fileder @props = { (Key k), v for k, v in pairs props } - -- get property according to criteria, crash if no value or conversion path + -- 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 - -- * overrides - map of interp overrides (optional) - get: (name='', type, overrides) => + -- * convert - allow conversion (optional: default true) + find: (name='', type, convert=true) => if not type type = name name = '' @@ -146,26 +168,59 @@ class Fileder for key, value in pairs @props continue unless key.name == name and key.type == type - interp = key\get_interp overrides - - return interp @, value + return key - if not overrides + if convert -- second pass, interps + converts for key, value in pairs @props continue unless key.name == name - interp = key\get_interp! - for { :inp, :out, :transform } in *converts - return transform interp @, value if inp == key.type and out == type + return key if inp == key.type and out == type + + -- get property according to criteria, nil if no value or conversion path + -- * name - property name (optional: defaults to main content) + -- * type - wanted result type + -- * overrides - map of interp overrides (optional) + get: (name='', type, overrides) => + if not type + type = name + name = '' + + key = @find name, type, not overrides + + if key + interp = key\get_interp overrides - nil, "node doesn't have value for #{name}:#{type}" + return (interp @, @props[key]), key if key.type == type + + for { :inp, :out, :transform } in *converts + return (transform interp @, @props[key]), key if inp == key.type and out == type + + nil, nil -- like get, throw if no value or conversion path - gett: (...) => assert @get ... + gett: (name='', type, overrides) => + if not type + type = name + name = '' + + val, key = @get name, type, overrides + assert val, "node doesn't have value for #{name}:#{type}" + val, key + +CONVERT = (type, val, key) -> + return unless val and key + + if key.type == type + val + else + for { :inp, :out, :transform } in *converts + return transform val if inp == key.type and out == type require = relative ... +import Browser from require '.browser' root = require '.tree' -append root\gett 'mmm/dom' +BROWSER = Browser root +append BROWSER.node diff --git a/app/mmmfs/tree.moon b/app/mmmfs/tree.moon index e84ff2a..b90d8cd 100644 --- a/app/mmmfs/tree.moon +++ b/app/mmmfs/tree.moon @@ -13,11 +13,7 @@ Fileder { _code = code (str) -> _code str\match '^ *(..-) *$' - center = (contents) -> - contents.style = { margin: 'auto', 'max-width': '750px' } - article contents - - center with _this = {} + article with _this = {} append = (a) -> table.insert _this, a footnote, getnotes = do @@ -78,7 +74,7 @@ Fileder { specific to the function key/type, but I haven't built or thought about any of that yet. Sorry." append do - github = footnote a 's-ol/mmm', href: 'https://github.com/s-ol/mmm' + github = footnote a 's-ol/mmm', href: 'https://github.com/s-ol/mmm/tree/master/app/mmmfs' p "Anyway, this node is set up as some sort of wiki/index thing and just lists its children-fileders' ", (code 'title: text/plain'), " values and ", (code 'preview: mmm/dom'), " previews (if set). Oh and also everything is on github and stuff", github, " if you care about that." @@ -86,8 +82,8 @@ Fileder { append p "Here's the Children:" -- render a preview block - preview = (title, content) -> div { - h3 title, style: { margin: 0 }, + preview = (title, content, name) -> div { + h3 title, style: { margin: 0, cursor: 'pointer' }, onclick: -> BROWSER\navigate { name } content or span '(no renderable content)', style: { color: 'red' }, style: { display: 'inline-block', @@ -107,7 +103,10 @@ Fileder { -- get 'preview' as a DOM description (nil if no value or conversion possible) content = child\get 'preview', 'mmm/dom' - preview title, content + -- get 'preview' as a DOM description (nil if no value or conversion possible) + name = child\gett 'name', 'alpha' + + preview title, content, name append h3 "converts" append p "Well actually it's a bit more complex. You see, the code that renders these previews ", (html.i "asks"), " for those @@ -204,14 +203,18 @@ Fileder { 'text/markdown': "this is a markdown version or something. There's no content here so switch back to the real one! -(Assuming there is a switching UI by the time you are reading this, which I am presupposing since you are reading this at all. -If you are reading this in the source, then c'mon, just scroll past and give me a break.)" +(Assuming there is a switching UI by the time you are reading this, which I assume since you are reading this at all. +If you are reading this in the source, then c'mon, just scroll past and give me a break.) + +(the switching UI has now been built.)" Fileder { + 'name: alpha': 'empty', 'title: text/plain': "Hey I'm an ad-hoc child with no content for shit", } Fileder { + 'name: alpha': 'image', 'title: text/plain': "Hey I'm like a link to picture or smth", -- main content is image/png, to be interpreted by URL to access @@ -226,6 +229,7 @@ If you are reading this in the source, then c'mon, just scroll past and give me } Fileder { + 'name: alpha': 'markdown', 'title: text/plain': "I'm not even five lines of markdown but i render myself!", -- preview can be rendered using global convert @@ -239,6 +243,7 @@ and some bold **text** and `code tags` with me.", -- if we are on client (mmm.s-ol.nu/?client=mmmfs), throw in twisted as a child if MODE == 'CLIENT' then Fileder { + 'name: alpha': 'twisted', 'title: text/plain': "canvas animation that doesn't quite fit", 'preview: moon -> mmm/component': => require '.twisted' } |
