aboutsummaryrefslogtreecommitdiffstats
path: root/app
diff options
context:
space:
mode:
authors-ol <s-ol@users.noreply.github.com>2018-10-27 12:31:00 +0000
committers-ol <s-ol@users.noreply.github.com>2018-10-27 12:31:00 +0000
commitb88545ac5126b96ac27d9aa2278f9c9ee22a21f0 (patch)
tree285ba37ca1eaca12672476d13e4240e03f88b98f /app
parentrender mmmfs in client (diff)
downloadmmm-b88545ac5126b96ac27d9aa2278f9c9ee22a21f0.tar.gz
mmm-b88545ac5126b96ac27d9aa2278f9c9ee22a21f0.zip
mmmfs browser etc
Diffstat (limited to 'app')
-rw-r--r--app/mmmfs/browser.moon96
-rw-r--r--app/mmmfs/init.moon91
-rw-r--r--app/mmmfs/tree.moon27
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'
}