diff options
| author | s-ol <s-ol@users.noreply.github.com> | 2018-10-30 08:00:19 +0000 |
|---|---|---|
| committer | s-ol <s-ol@users.noreply.github.com> | 2018-10-30 08:11:45 +0000 |
| commit | fa79588be9c10edac27427dd2530b098abce3fea (patch) | |
| tree | 7ada333f2468df8dab6e956f3000da3bb1703192 | |
| parent | fix inline code (diff) | |
| download | mmm-fa79588be9c10edac27427dd2530b098abce3fea.tar.gz mmm-fa79588be9c10edac27427dd2530b098abce3fea.zip | |
REHYDRATION
| -rw-r--r-- | app/init.moon | 1 | ||||
| -rw-r--r-- | app/mmmfs/init.moon | 301 | ||||
| -rw-r--r-- | app/mmmfs/tree.moon | 286 | ||||
| -rw-r--r-- | lib/component.client.moon | 12 | ||||
| -rw-r--r-- | lib/component.server.moon | 2 | ||||
| -rw-r--r-- | lib/mmmfs/browser.moon | 81 |
6 files changed, 363 insertions, 320 deletions
diff --git a/app/init.moon b/app/init.moon index 5e38966..8bc95e3 100644 --- a/app/init.moon +++ b/app/init.moon @@ -35,7 +35,6 @@ articles = { { name: 'mmmfs' desc: 'a file and operating system to live in (wip)' - render: 'client' }, } diff --git a/app/mmmfs/init.moon b/app/mmmfs/init.moon index 626c323..0cf66a0 100644 --- a/app/mmmfs/init.moon +++ b/app/mmmfs/init.moon @@ -1,292 +1,23 @@ require = relative ... -import Fileder from require 'lib.mmmfs' - -root = Fileder { - -- main content - -- doesn't have a name prefix (e.g. preview: moon -> mmm/dom) - -- uses the 'moon ->' conversion to execute the lua/pre moon function on get - -- resolves to a value of type mmm/dom - 'moon -> mmm/dom': () => - html = require 'lib.dom' - import article, h1, h2, h3, p, div, a, sup, ol, li, span, code, pre, br from html - - moon = (str) -> - result = window.hljs\highlight 'moonscript', (str\match '^ *(..-) *$'), true - with code class: 'hljs' - .innerHTML = result.value - - article with _this = {} - append = (a) -> table.insert _this, a - - footnote, getnotes = do - local * - notes = {} - - id = (i) -> "footnote-#{i}" - - footnote = (stuff) -> - i = #notes + 1 - notes[i] = stuff - sup a "[#{i}]", style: { 'text-decoration': 'none' }, href: '#' .. id i - - footnote, -> - args = for i, note in ipairs notes - li (span (tostring i), id: id i), ': ', note - notes = {} - table.insert args, style: { 'list-style': 'none', 'font-size': '0.8em' } - ol table.unpack args - - append h1 'mmmfs', style: { 'margin-bottom': 0 } - -- @TODO: s/filesystem/a way of organizing files/g - append p "a file and operating system to live in", style: { 'margin-top': 0, 'margin-bottom': '1em' } - - -- @TODO: motivation / outline problem + need - -- @TODO: quote http://pchiusano.github.io/2013-05-22/future-of-software.html on Applications - - append p do - fileder = footnote "fileder: file + folder. 'node', 'table' etc. are too general to be used all over." - - -- @TODO: mention: - -- can store anything - text, an image, a link to a website or video, - -- a program and anything else you can think of. - "in mmmfs, directories, files and applications are all kind of the same thing, or something like that. - Listen, I don't really know yet either. The idea is that there is only one type of 'thing' - - a fileder", fileder, ". A fileder can store multiple variants and metadata of its content, - such as a markdown text and a rendered HTML version of the same document. - It could also store a script that transforms the markdown version into HTML and is executed on demand, - automatically." - - append p "Fileders can also have other fileders as their children (just like directories do in a normal - filesystem). You can make a fileder view query these children and display them however you want. - A 'Pictures' fileder, for example, could contain a script within itself that renders all the picture files - you put into it as little previews and lets you click on them to view the full image." - - append p "This means the 'Pictures' fileder can also have an alternate slideshow mode, with fullscreen view and - everything (some of this is built, check out the gallery example below), or one that displays geotagged images - on a world map, if you really want that. Maybe you could build a music folder that contains links to youtube - videos, spotify tracks and just plain mp3 files, and the folder knows how to play them all.", br!, " - In this way fileders fulfil the purpose of 'Applications' too." - - -- @TODO: BUT doesn't have to be only for one type of file: - -- @TODO: rework - -- making a multi-media collage representing your thoughts and mental organization of a topic - append p "A fileder is also responsible for how it's children are sorted, filtered and interacted with. - For example you should be able to create a fileder that is essentially a 'word document' equivalent: it can - contain images, websites, links and of course text as children and let you reorder, layout and edit them - whenever you open the fileder." - - append p "Sounds cool, no? Here's some examples of things a fileder can be or embed:" - - -- render a preview block - 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', - width: '300px', - height: '200px', - padding: '4px', - margin: '8px', - border: '4px solid #eeeeee', - overflow: 'hidden', - }, - } - - append div for child in *@children - -- get 'title' as 'text/plain' (error if no value or conversion possible) - title = child\gett 'title', 'text/plain' - - -- get 'preview' as a DOM description (nil if no value or conversion possible) - content = child\get 'preview', 'mmm/dom' - - -- get 'name' as a DOM description (nil if no value or conversion possible) - name = child\gett 'name', 'alpha' - - preview title, content, name - - append h2 "details" - -- @TODO s/parts: dimensions, aspects? - -- @TODO: first mention both properties & children; then go into detail - -- @TODO: main content - append do - name = html.i 'name' - type = html.i 'type' - - p "Fileders are made up of two main parts. The first is the list of ", (html.i 'properties'), ", - which are values identified by a ", name, " and ", type, ". These values are queried using strings like ", - (code 'title: text/plain'), " or ", (code 'mmm/dom'), ", which describe both the ", name, - " of a property (", (moon '"title"'), " and ", (moon '""'), ", the unnamed/main property) and the ", type, - " of a property. Property types can be something resembling a MIME-type or a more complex structure - (see ", (html.i "type chains"), " below). A fileder can have multiple properties of different types - set that share a ", name, ". In this case the overlapping properties are considered equivalent and the one - with the most appropriate ", type, " is selected, depending on the query. - The unnamed property is considered a fileder's 'main content', i.e. what you are interested in when viewing it." - - append p "The second part of a fileder is the list of it's children, which are fileders itself. - The children are stored in an ordered list and currently identified by their ", (code 'name: alpha'), - " property for UI and navigation purposes only (not sure if this is a good idea tbh)." - --- append do --- github = footnote a 's-ol/mmm', href: 'https://github.com/s-ol/mmm/tree/master/app/mmmfs' --- "Oh and also everything is on github and stuff", github, --- " if you care about that." - - append do - mmmdom = code ('mmm/dom'), footnote span (code 'mmm/dom'), " is a polymorphic content type; - on the server it is just an HTML string (like ", (code 'text/html'), "), - but on the client it is a JS DOM Element instance." - - p "What you are viewing right now is the main property of the root fileder. - The property is queried as ", mmmdom, ", a website fragment (DOM node). This website fragment - is then added to the page in the main content area, where you are most likely reading it right now." - - p "Anyway, this node is set up as a very generic sort of index thing and just lists its children-fileders' - alongside this text part you are reading.", br!, "For each child it displays the ", (code 'title: text/plain'), - " and shows the ", (code 'preview: mmm/dom'), " property (if set)." - - append h3 "converts" - append p "So far I have always listed properties as they are being queried, but a main feature of mmmfs is - type conversion. This means that you generally ask for content in whichever format suits your application, - and rely on the type resolution mechanism to make that happen." - - append pre moon [[ --- render a preview block -preview = (title, content) -> div { - h3 title, style: { ... }, - content or span '(no renderable content)', style: { ... }, - style: { ... } -} - -append div for child in *@children - -- get 'title' as 'text/plain' (error if no value or conversion possible) - title = child\gett 'title', 'text/plain' - - -- get 'preview' as a DOM description (nil if no value or conversion possible) - content = child\get 'preview', 'mmm/dom' - - preview title, content - ]] - - append p "Here the code that renders these previews. You can see it ", (html.i "asks"), " for the - properties ", (code 'title: text/plain'), ' and ', (code 'preview: mmm/dom'), "), but the values don't actually have to - be ", (html.i "defined"), " as these types. - For example, the markdown child below only provides ", (code 'preview'), " as ", (code 'text/markdown'), ":" - - append pre moon [[ -Fileder { - 'title: text/plain': "I'm not even five lines of markdown but i render myself!", - 'preview: text/markdown': "See I have like - -- a list of things -- (two things) - -and some bold **text** and `code tags` with me.", -} - ]] - - append p "Then, globally, there are some conversion paths specified; such as one that maps from ", - (code 'text/markdown'), " to ", (code 'mmm/dom'), ":" - - append pre moon [[ -{ - inp: 'text/markdown', - out: 'mmm/dom', - transform: (md) -> - -- polymorphic client/serverside implementation here, - -- uses lua-discount on the server, marked.js on the client -} - ]] - - append h3 "type chains" - append p "In addition, a property type can be encoded using multiple types in a ", (code 'type chain'), ". - For example the root node you are viewing currently is actually defined as ", (code 'moon -> mmm/dom'), ", - meaning it's value is a pre moon function returing a regular ", (code 'mmm/dom'), " value." - - append p "Both value chains and 'sideways' converts are resolved using the same mechanism, - so this page is being rendered just using ", (moon "append root\\get 'mmm/dom'"), " as well. - The convert that resolves the moon type is defined as follows:" - - append pre moon [[ -{ - inp: 'moon -> (.+)', - out: '%1', - transform: (val, fileder) -> val fileder -} - ]] - - append p "The example with the image is curious as well. In mmmfs, you might want to save a link to an image, - without ever saving the actual image on your hard drive (or wherever the data may ever be stored - it is - quite transient currently). The image Fileder below has it's main (unnamed) value tagged as ", - (code 'URL -> image/png'), " - a png image, encoded as an URL. When accessed as ", (code 'image/png'), " - the URL should be resolved, and the binary data provided in it's place (yeah right - I haven't build that yet)." - - append p "However, if a script is aware of URLs and knows a better way to handle them, then it can ask for and - use the URL directly instead. - This is what the image demo does in order to pass the URL to an ", (code 'img'), " tag's ", (code 'src'), " attribute:" - - append pre moon [[ -Fileder { - 'title: text/plain': "Hey I'm like a link to picture or smth", - 'URL -> image/png': 'https://picsum.photos/200?random', - 'preview: moon -> mmm/dom': => - import img from require 'lib.dom' - img src: @gett 'URL -> image/png' -- look for main content with 'URL to png' type -} - ]] - - append getnotes! - - '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 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 at all", - } - - 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 - 'URL -> image/png': 'https://picsum.photos/200?random', - - -- preview is a lua/pre moon function that neturns an mmm/dom value - 'preview: moon -> mmm/dom': => - import img from require 'lib.dom' - img src: @gett 'URL -> image/png' -- look for main content with 'URL to png' type - } - - 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 - 'preview: text/markdown': "See I have like - -- a list of things -- (two things) +render = (path) -> + import Browser from require 'lib.mmmfs.browser' + import tohtml from require 'lib.component' + root = require '.tree' -and some bold **text** and `code tags` with me.", - } + export BROWSER + BROWSER = Browser root, path + append tohtml BROWSER - require '.gallery', + if MODE == 'SERVER' + rehydrate = (path) -> + require = relative ... - -- if we are on client, throw in twisted as a child - if MODE == 'CLIENT' then require '.twisted' -} + import Browser from require 'lib.mmmfs.browser' + root = require '.tree' -if MODE == 'CLIENT' - import Browser from require 'lib.mmmfs.browser' + export BROWSER + BROWSER = Browser root, path, true + window.hljs\initHighlightingOnLoad! - export BROWSER - BROWSER = Browser root - append BROWSER.node -else - append root\get 'mmm/dom' + on_client init, path diff --git a/app/mmmfs/tree.moon b/app/mmmfs/tree.moon new file mode 100644 index 0000000..23e1a89 --- /dev/null +++ b/app/mmmfs/tree.moon @@ -0,0 +1,286 @@ +require = relative ..., 1 + +import Fileder from require 'lib.mmmfs' + +Fileder { + -- main content + -- doesn't have a name prefix (e.g. preview: moon -> mmm/dom) + -- uses the 'moon ->' conversion to execute the lua/pre moon function on get + -- resolves to a value of type mmm/dom + 'moon -> mmm/dom': () => + html = require 'lib.dom' + import article, h1, h2, h3, p, div, a, sup, ol, li, span, code, pre, br from html + + moon = if MODE == 'SERVER' + (str) -> code (str\match '^ *(..-) *$'), class: 'hljs' + else + (str) -> + result = window.hljs\highlight 'moonscript', (str\match '^ *(..-) *$'), true + with code class: 'hljs' + .innerHTML = result.value + + article with _this = {} + append = (a) -> table.insert _this, a + + footnote, getnotes = do + local * + notes = {} + + id = (i) -> "footnote-#{i}" + + footnote = (stuff) -> + i = #notes + 1 + notes[i] = stuff + sup a "[#{i}]", style: { 'text-decoration': 'none' }, href: '#' .. id i + + footnote, -> + args = for i, note in ipairs notes + li (span (tostring i), id: id i), ': ', note + notes = {} + table.insert args, style: { 'list-style': 'none', 'font-size': '0.8em' } + ol table.unpack args + + append h1 'mmmfs', style: { 'margin-bottom': 0 } + -- @TODO: s/filesystem/a way of organizing files/g + append p "a file and operating system to live in", style: { 'margin-top': 0, 'margin-bottom': '1em' } + + -- @TODO: motivation / outline problem + need + -- @TODO: quote http://pchiusano.github.io/2013-05-22/future-of-software.html on Applications + + append p do + fileder = footnote "fileder: file + folder. 'node', 'table' etc. are too general to be used all over." + + -- @TODO: mention: + -- can store anything - text, an image, a link to a website or video, + -- a program and anything else you can think of. + "in mmmfs, directories, files and applications are all kind of the same thing, or something like that. + Listen, I don't really know yet either. The idea is that there is only one type of 'thing' - + a fileder", fileder, ". A fileder can store multiple variants and metadata of its content, + such as a markdown text and a rendered HTML version of the same document. + It could also store a script that transforms the markdown version into HTML and is executed on demand, + automatically." + + append p "Fileders can also have other fileders as their children (just like directories do in a normal + filesystem). You can make a fileder view query these children and display them however you want. + A 'Pictures' fileder, for example, could contain a script within itself that renders all the picture files + you put into it as little previews and lets you click on them to view the full image." + + append p "This means the 'Pictures' fileder can also have an alternate slideshow mode, with fullscreen view and + everything (some of this is built, check out the gallery example below), or one that displays geotagged images + on a world map, if you really want that. Maybe you could build a music folder that contains links to youtube + videos, spotify tracks and just plain mp3 files, and the folder knows how to play them all.", br!, " + In this way fileders fulfil the purpose of 'Applications' too." + + -- @TODO: BUT doesn't have to be only for one type of file: + -- @TODO: rework + -- making a multi-media collage representing your thoughts and mental organization of a topic + append p "A fileder is also responsible for how it's children are sorted, filtered and interacted with. + For example you should be able to create a fileder that is essentially a 'word document' equivalent: it can + contain images, websites, links and of course text as children and let you reorder, layout and edit them + whenever you open the fileder." + + append p "Sounds cool, no? Here's some examples of things a fileder can be or embed:" + + -- render a preview block + 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', + width: '300px', + height: '200px', + padding: '4px', + margin: '8px', + border: '4px solid #eeeeee', + overflow: 'hidden', + }, + } + + append div for child in *@children + -- get 'title' as 'text/plain' (error if no value or conversion possible) + title = child\gett 'title', 'text/plain' + + -- get 'preview' as a DOM description (nil if no value or conversion possible) + content = child\get 'preview', 'mmm/dom' + + -- get 'name' as a DOM description (nil if no value or conversion possible) + name = child\gett 'name', 'alpha' + + preview title, content, name + + append h2 "details" + -- @TODO s/parts: dimensions, aspects? + -- @TODO: first mention both properties & children; then go into detail + -- @TODO: main content + append do + name = html.i 'name' + type = html.i 'type' + + p "Fileders are made up of two main parts. The first is the list of ", (html.i 'properties'), ", + which are values identified by a ", name, " and ", type, ". These values are queried using strings like ", + (code 'title: text/plain'), " or ", (code 'mmm/dom'), ", which describe both the ", name, + " of a property (", (moon '"title"'), " and ", (moon '""'), ", the unnamed/main property) and the ", type, + " of a property. Property types can be something resembling a MIME-type or a more complex structure + (see ", (html.i "type chains"), " below). A fileder can have multiple properties of different types + set that share a ", name, ". In this case the overlapping properties are considered equivalent and the one + with the most appropriate ", type, " is selected, depending on the query. + The unnamed property is considered a fileder's 'main content', i.e. what you are interested in when viewing it." + + append p "The second part of a fileder is the list of it's children, which are fileders itself. + The children are stored in an ordered list and currently identified by their ", (code 'name: alpha'), + " property for UI and navigation purposes only (not sure if this is a good idea tbh)." + +-- append do +-- github = footnote a 's-ol/mmm', href: 'https://github.com/s-ol/mmm/tree/master/app/mmmfs' +-- "Oh and also everything is on github and stuff", github, +-- " if you care about that." + + append do + mmmdom = code ('mmm/dom'), footnote span (code 'mmm/dom'), " is a polymorphic content type; + on the server it is just an HTML string (like ", (code 'text/html'), "), + but on the client it is a JS DOM Element instance." + + p "What you are viewing right now is the main property of the root fileder. + The property is queried as ", mmmdom, ", a website fragment (DOM node). This website fragment + is then added to the page in the main content area, where you are most likely reading it right now." + + p "Anyway, this node is set up as a very generic sort of index thing and just lists its children-fileders' + alongside this text part you are reading.", br!, "For each child it displays the ", (code 'title: text/plain'), + " and shows the ", (code 'preview: mmm/dom'), " property (if set)." + + append h3 "converts" + append p "So far I have always listed properties as they are being queried, but a main feature of mmmfs is + type conversion. This means that you generally ask for content in whichever format suits your application, + and rely on the type resolution mechanism to make that happen." + + append pre moon [[ +-- render a preview block +preview = (title, content) -> div { + h3 title, style: { ... }, + content or span '(no renderable content)', style: { ... }, + style: { ... } +} + +append div for child in *@children + -- get 'title' as 'text/plain' (error if no value or conversion possible) + title = child\gett 'title', 'text/plain' + + -- get 'preview' as a DOM description (nil if no value or conversion possible) + content = child\get 'preview', 'mmm/dom' + + preview title, content + ]] + + append p "Here the code that renders these previews. You can see it ", (html.i "asks"), " for the + properties ", (code 'title: text/plain'), ' and ', (code 'preview: mmm/dom'), "), but the values don't actually have to + be ", (html.i "defined"), " as these types. + For example, the markdown child below only provides ", (code 'preview'), " as ", (code 'text/markdown'), ":" + + append pre moon [[ +Fileder { + 'title: text/plain': "I'm not even five lines of markdown but i render myself!", + 'preview: text/markdown': "See I have like + +- a list of things +- (two things) + +and some bold **text** and `code tags` with me.", +} + ]] + + append p "Then, globally, there are some conversion paths specified; such as one that maps from ", + (code 'text/markdown'), " to ", (code 'mmm/dom'), ":" + + append pre moon [[ +{ + inp: 'text/markdown', + out: 'mmm/dom', + transform: (md) -> + -- polymorphic client/serverside implementation here, + -- uses lua-discount on the server, marked.js on the client +} + ]] + + append h3 "type chains" + append p "In addition, a property type can be encoded using multiple types in a ", (code 'type chain'), ". + For example the root node you are viewing currently is actually defined as ", (code 'moon -> mmm/dom'), ", + meaning it's value is a pre moon function returing a regular ", (code 'mmm/dom'), " value." + + append p "Both value chains and 'sideways' converts are resolved using the same mechanism, + so this page is being rendered just using ", (moon "append root\\get 'mmm/dom'"), " as well. + The convert that resolves the moon type is defined as follows:" + + append pre moon [[ +{ + inp: 'moon -> (.+)', + out: '%1', + transform: (val, fileder) -> val fileder +} + ]] + + append p "The example with the image is curious as well. In mmmfs, you might want to save a link to an image, + without ever saving the actual image on your hard drive (or wherever the data may ever be stored - it is + quite transient currently). The image Fileder below has it's main (unnamed) value tagged as ", + (code 'URL -> image/png'), " - a png image, encoded as an URL. When accessed as ", (code 'image/png'), " + the URL should be resolved, and the binary data provided in it's place (yeah right - I haven't build that yet)." + + append p "However, if a script is aware of URLs and knows a better way to handle them, then it can ask for and + use the URL directly instead. + This is what the image demo does in order to pass the URL to an ", (code 'img'), " tag's ", (code 'src'), " attribute:" + + append pre moon [[ +Fileder { + 'title: text/plain': "Hey I'm like a link to picture or smth", + 'URL -> image/png': 'https://picsum.photos/200?random', + 'preview: moon -> mmm/dom': => + import img from require 'lib.dom' + img src: @gett 'URL -> image/png' -- look for main content with 'URL to png' type +} + ]] + + append getnotes! + + '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 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 at all", + } + + 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 + 'URL -> image/png': 'https://picsum.photos/200?random', + + -- preview is a lua/pre moon function that neturns an mmm/dom value + 'preview: moon -> mmm/dom': => + import img from require 'lib.dom' + img src: @gett 'URL -> image/png' -- look for main content with 'URL to png' type + } + + 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 + 'preview: text/markdown': "See I have like + +- a list of things +- (two things) + +and some bold **text** and `code tags` with me.", + } + + require '.gallery', + + -- if we are on client, throw in twisted as a child + if MODE == 'CLIENT' then require '.twisted' +} diff --git a/lib/component.client.moon b/lib/component.client.moon index 7357f50..6e0e8d8 100644 --- a/lib/component.client.moon +++ b/lib/component.client.moon @@ -65,7 +65,10 @@ class ReactiveElement @isinstance: (val) -> 'table' == (type val) and val.node new: (element, ...) => - @node = document\createElement element + if 'userdata' == type element + @node = element + else + @node = document\createElement element @_subscriptions = {} children = { ... } @@ -105,7 +108,8 @@ class ReactiveElement @node[attr] = value - append: (child, last) => + prepend: (child, last) => @append child, last, 'prepend' + append: (child, last, mode='append') => if ReactiveVar.isinstance child table.insert @_subscriptions, child\subscribe (...) -> @append ... child = child\get! @@ -123,7 +127,9 @@ class ReactiveElement if ok @node\replaceChild child, last else - @node\appendChild child + switch mode + when 'append' then @node\appendChild child + when 'prepend' then @node\insertBefore child, @node.firstChild remove: (child) => @node\removeChild tohtml child diff --git a/lib/component.server.moon b/lib/component.server.moon index 91858c0..85d97eb 100644 --- a/lib/component.server.moon +++ b/lib/component.server.moon @@ -32,7 +32,7 @@ class ReactiveVar get: => @value subscribe: (callback) => - error "attempting to subscribe to ReactiveVar serverside" + warn "attempting to subscribe to ReactiveVar serverside" map: (transform) => ReactiveVar transform @value diff --git a/lib/mmmfs/browser.moon b/lib/mmmfs/browser.moon index 1a9bca9..a4080c2 100644 --- a/lib/mmmfs/browser.moon +++ b/lib/mmmfs/browser.moon @@ -1,15 +1,15 @@ require = relative ..., 1 import Key from require '.fileder' import get_conversions from require '.conversion' -import ReactiveVar, text, elements from require 'lib.component' +import ReactiveVar, ReactiveElement, 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, '/' + new: (@root, @path={}, rehydrate=false) => + @path = ReactiveVar @path + -- @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 @@ -29,7 +29,11 @@ class Browser @active\subscribe (fileder) -> @prop\set (fileder\find 'mmm/dom') or next fileder.props - @tree = div { + -- retrieve or create the root + root = 'div' + root = document\getElementById 'browser-root' if rehydrate + @dom = ReactiveElement root, { + id: 'browser-root' style: { position: 'absolute', top: 0, @@ -40,8 +44,12 @@ class Browser overflow: 'hidden', 'flex-direction': 'column', 'justify-content': 'space-between', - }, - div { + } + } + + -- add or prepend the navbar + if MODE == 'CLIENT' + @dom\prepend div { style: { padding: '1em', flex: '0 0 auto', @@ -72,34 +80,47 @@ class Browser \append option value, :value, selected: value == current } - div { - style: { - flex: '1 0 0', - overflow: 'auto', - padding: '1em 2em', - }, - @prop\map (prop) -> - active = @active\get! + -- append or patch #browser-content + node = 'div' + node = document\getElementById 'browser-content' if rehydrate + @dom\append ReactiveElement node, { + id: 'browser-content', + style: { + flex: '1 0 0', + overflow: 'auto', + padding: '1em 2em', + }, + @get_content rehydrate and node + } - ok, res = pcall -> - conversions = assert (get_conversions 'mmm/dom', prop.type), "no conversion path" - value = assert (active\get prop), "value went missing?" + @node = @dom.node + @render = @dom\render - for i=#conversions,1,-1 - { :inp, :out, :transform } = conversions[i] - value = transform value, active + get_content: (wrapper) => + var = @prop\map (prop) -> + active = @active\get! - value + ok, res = pcall -> + conversions = assert (get_conversions 'mmm/dom', prop.type), "no conversion path" + value = assert (active\get prop), "value went missing?" - if ok and res - res - else - warn "error: ", res unless ok - span "cannot display!", style: { color: '#f00' } - } - } + for i=#conversions,1,-1 + { :inp, :out, :transform } = conversions[i] + value = transform value, active + + value + + if ok and res + res + else + warn "error: ", res unless ok + span "cannot display!", style: { color: '#f00' } + + -- wrapper was built already so take over the old value + if wrapper + var\set wrapper.lastElementChild - @node = @tree.node + var navigate: (new) => @path\set new |
