mmmfs cleanup
s-ol
3 years ago
0 | Drawbacks & Future Work | |
1 | ----------------------- | |
2 | ||
3 | There are multiple limitations in the proposed system that have become obvious in developing and working with the system. | |
4 | Some of these have been anticipated for some time and concrete research directions for solutions are apparent, | |
5 | while others may be intrinsic limitations in the approach taken. | |
6 | ||
7 | ### global set of converts | |
8 | In the current system, there exists only a single, global set of *converts* that can be potentially applied | |
9 | to facets anywhere in the system. | |
10 | Therefore it is necessary to encode behaviour directly (as code) in facets wherever exceptional behaviour is required. | |
11 | For example if a fileder conatining multiple images wants to provide custom UI for each image when viewed independently, | |
12 | this code has to either be attached to every image individually (and redundantly), or added as a global convert. | |
13 | To make sure this convert does not interfere with images elsewhere in the system, it would be necessary to introduce | |
14 | a new type and change the images to use it, which may present yet more propblems and works against the principle of | |
15 | compatibility the system has been constructed for. | |
16 | ||
17 | A potential direction of research in the future is to allow specifying *converts* as part of the fileder tree. | |
18 | Application of *converts* could then be scoped to their fileders' subtrees, such that for any facet only the *converts* | |
19 | stored in the chain of its parents upwards are considered. | |
20 | This way, *converts* can be added locally if they only make sense within a given context. | |
21 | Additionally it could be made possible to use this mechanism to locally override *converts* inherited from | |
22 | further up in the tree, for example to specialize types based on their context in the system. | |
23 | ||
24 | ### code outside of the system | |
25 | At the moment, a large part of the mmmfs codebase is still separate from the content, and developed outside of mmmfs itself. | |
26 | This is a result of the development process of mmmfs and was necessary to start the project as the filesystem itself matured, | |
27 | but has become a limitation of the user experience now: | |
28 | Potential users of mmmfs would generally start by becoming familiar with the operation of mmmfs from within the system, | |
29 | as this is the expected (and designated) experience developed for them. | |
30 | All of the code that lives outside of the mmmfs tree is therefore invisible and opaque to them, | |
31 | actively limiting their understanding of, and the customizability of the system. | |
32 | ||
33 | This is particularily relevant for the global set of *converts*, and the layout used to render the web view, | |
34 | which are expected to undergo changes as users adapt the system to their own content types and domains of interest, | |
35 | as well as their visual identity, respectively. | |
36 | ||
37 | ### superficial type system | |
38 | The currently used type system based on strings and pattern matching has been largely satisfactory, | |
39 | but has proven problematic for satisfying some anticipated use cases. | |
40 | It should be considered to switch to a more intricate, structural type system that allows encoding more concrete meta-data | |
41 | alongside the type, and to match *converts* based on a more flexible scheme of pattern matching. | |
42 | For example it is envisaged to store the resolution of an image file in its type. | |
43 | Many *converts* might choose to ignore this additional information, | |
44 | but others could use this information to generate lower-resolution 'thumbnails' of images automatically. | |
45 | Using these mechanisms for example images could be requested with a maximum-resolution constraint to save on bandwidth | |
46 | when embedded in other documents. | |
47 | ||
48 | ### type-coercion alienates | |
49 | By giving the system more information about the data it is dealing with, | |
50 | and then relying on the system to automatically transform between data-types, | |
51 | it is easy to lose track of which format data is concretely stored in. | |
52 | In much the same way that the application-centric paradigm alienates users from an understanding | |
53 | and feeling of ownership of their data by overemphasizing the tools in between, | |
54 | the automagical coercion of data types introduces distance between the user and an understanding of the data in the system. | |
55 | It remains to be seen whether this can be mitigated with careful UX and UI design. | |
56 | ||
57 | ### discrepancy between viewing/interacting and editing of content | |
58 | Because many *converts* are not necessarily reversible, | |
59 | it is very hard to implement generic ways of editing stored data in the same format it is viewed. | |
60 | For example, the system trivially converts markdown-formatted text sources into viewable HTML markup, | |
61 | but it is hardly possible to propagate changes to the viewable HTML back to the markdown source. | |
62 | This problem worsens when the conversion path becomes more complex: | |
63 | If the markdown source was fetched via HTTP from a remote URL (e.g. if the facet's type was `URL -> text/markdown`), | |
64 | it is not possible to edit the content at all, since the only data owned by the system is the URL string itself, | |
65 | which is not part of the viewable representation at all. | |
66 | Similarily, when viewing output that is generated by code (e.g. `text/moonscript -> mmm/dom`), | |
67 | the code itself is not visible to the user when interacting with the viewable representation, | |
68 | and if the user wishes to change parts of the representation the system is unable to relate these changes to elements | |
69 | of the code or assist the user in doing so. | |
70 | As a result, the experiences of interacting with the system at large is still a very different experience than | |
71 | editing content (and thereby extending the system) in it. | |
72 | This is expected to represent a major hurdle for users getting started with the system, | |
73 | and is a major shortcoming in enabling end-user programming as set as a goal for this project. |
0 | Hey I'm an almost empty Fileder. |
Binary diff not shown
Binary diff not shown
0 | https://picsum.photos/600/600/?image=101 |
0 | https://picsum.photos/200/200/?image=101 |
0 | import div, img, br from require 'mmm.dom' | |
1 | ||
2 | => div { | |
3 | 'the first pic as a little taste:', | |
4 | br!, | |
5 | img src: @children[1]\get 'preview', 'URL -> image/png' | |
6 | } |
+19
-0
0 | import ReactiveVar, text, elements from require 'mmm.component' | |
1 | import div, a, img from elements | |
2 | ||
3 | => | |
4 | index = ReactiveVar 1 | |
5 | ||
6 | prev = (i) -> math.max 1, i - 1 | |
7 | next = (i) -> math.min #@children, i + 1 | |
8 | ||
9 | div { | |
10 | div { | |
11 | a 'prev', href: '#', onclick: -> index\transform prev | |
12 | index\map (i) -> text " image ##{i} " | |
13 | a 'next', href: '#', onclick: -> index\transform next | |
14 | }, | |
15 | index\map (i) -> | |
16 | child = assert @children[i], "image not found!" | |
17 | img src: @children[i]\gett 'URL -> image/png' | |
18 | } |
0 | import div, h1, a, img, br from require 'mmm.dom' | |
1 | ||
2 | => | |
3 | link = (child) -> a { | |
4 | href: '#', | |
5 | onclick: -> BROWSER\navigate child.path | |
6 | img src: child\gett 'preview', 'URL -> image/png' | |
7 | } | |
8 | ||
9 | content = [link child for child in *@children] | |
10 | table.insert content, 1, h1 'gallery index' | |
11 | div content |
0 | A Gallery of 25 random pictures, come on in! |
0 | https://picsum.photos/200?random |
0 | import img from require 'mmm.dom' | |
1 | ||
2 | -- look for main content with 'URL to png' type | |
3 | -- and wrap in an mmm/dom image tag | |
4 | => img src: @gett 'URL -> image/png' |
0 | Hey I'm like a link to a picture or smth |
+15
-0
0 | const e = (elem, children) => { | |
1 | const node = document.createElement(elem); | |
2 | ||
3 | if (typeof children === 'string') | |
4 | node.innerText = children; | |
5 | else | |
6 | children.forEach(child => node.appendChild(child)); | |
7 | ||
8 | return node; | |
9 | }; | |
10 | ||
11 | return e('article', [ | |
12 | e('h1', 'JavaScript'), | |
13 | e('p', 'JavaScript is supported natively in the browser but is not currently pre-rendered on the server.'), | |
14 | ]); |
0 | JavaScript |
0 | local d = require 'mmm.dom' | |
1 | ||
2 | local lua = d.a { 'Lua', href = 'https://www.lua.org/' } | |
3 | local fengari = d.a { 'fengari.io', href = 'https://fengari.io/' } | |
4 | ||
5 | return d.article { | |
6 | d.h1 'Lua', | |
7 | d.p { lua, ' is fully supported using ', fengari, ' on the Client.' } | |
8 | } |
+10
-0
0 | import a, article, h1, p from require 'mmm.dom' | |
1 | ||
2 | moonscript = a 'MoonScript', href: 'https://moonscript.org/' | |
3 | lua = a 'Lua', href: 'https://www.lua.org/' | |
4 | fengari = a 'fengari.io', href: 'https://fengari.io/' | |
5 | ||
6 | article { | |
7 | h1 'MoonScript', | |
8 | p moonscript, " is compiled to ", lua, " on the server, which is then executed on the client using ", fengari, "." | |
9 | } |
0 | MoonScript |
0 | this Fileder contains some minimal examples showing support for various languages `mmmfs` supports currently. | |
1 | ||
2 | Language support is mostly limited by the fact that `mmmfs` currently targets web browsers, | |
3 | on the server any scripting language that can be executed can theoretically be integrated with minimal effort. | |
4 | ||
5 | Using the inspector mode to view the source of the Fileders below is encouraged. |
+16
-0
0 | import article, h1, p, ul, li, a from require 'mmm.dom' | |
1 | ||
2 | single = (a) -> a | |
3 | ||
4 | => | |
5 | children = for child in *@children | |
6 | title = child\gett 'title: text/plain' | |
7 | li a title, href: child.path, onclick: (e) => | |
8 | e\preventDefault! | |
9 | BROWSER\navigate child.path | |
10 | ||
11 | article { | |
12 | h1 single @gett 'title: text/plain' | |
13 | p single @gett 'preview: mmm/dom' | |
14 | ul children | |
15 | } |
0 | scripting language support |
0 | See I have like | |
1 | ||
2 | - a list of things | |
3 | - (two things) | |
4 | ||
5 | and some bold **text** and `code tags` with me. |
0 | I'm not even five lines of markdown but i render myself! |
0 | -- main content | |
1 | -- doesn't have a name prefix (e.g. preview: fn -> mmm/dom) | |
2 | -- uses the 'fn ->' conversion to execute the lua function on @get | |
3 | -- resolves to a value of type mmm/dom | |
4 | => | |
5 | html = require 'mmm.dom' | |
6 | import h4, div, a, span from html | |
7 | ||
8 | -- render a preview block | |
9 | preview = (child) -> | |
10 | -- get 'title' as 'text/plain' (error if no value or conversion possible) | |
11 | title = child\gett 'title', 'text/plain' | |
12 | ||
13 | -- get 'preview' as a DOM description (nil if no value or conversion possible) | |
14 | content = child\get 'preview', 'mmm/dom' | |
15 | ||
16 | div { | |
17 | h4 title, style: { margin: 0, cursor: 'pointer' }, onclick: -> BROWSER\navigate child.path | |
18 | content or span '(no renderable content)', style: { color: 'red' }, | |
19 | style: { | |
20 | display: 'inline-block', | |
21 | width: '300px', | |
22 | height: '200px', | |
23 | padding: '4px', | |
24 | margin: '8px', | |
25 | border: '4px solid #eeeeee', | |
26 | overflow: 'hidden', | |
27 | }, | |
28 | } | |
29 | ||
30 | div for child in *@children | |
31 | preview child |
0 | Based on this, a modern data storage and processing ecosystem should enable transclusion of both content and behaviours | |
1 | between contexts. | |
2 | Content should be able to be transcluded and referenced to facilitate the creation of flexible data formats and interactions, | |
3 | such that e.g. a slideshow slide can include content in a variety other formats (such as images and text) from anywhere else in the system. | |
4 | Behaviours should be able to be transcluded and reused to facilitate the creation of ad-hoc sytems and applets based on user needs. | |
5 | For example a user-created todo list should be able to take advantage of a sketching tool the user already has access to. | |
6 | ||
7 | The system should enable the quick creation of ad-hoc software. | |
8 | ||
9 | While there are drawbacks to cloud-storage of data (as outlined above), the utility of distributed systems is acknowledged, | |
10 | and the system should therefore be able to include content and behaviours via the network. | |
11 | This ability should be integrated deeply into the system, so that data can be treated independently of its origin and storage conditions, | |
12 | with as little caveats as possible. | |
13 | ||
14 | The system needs to be browsable and understandable by users. |
0 | https://picsum.photos/600/600/?image=101 |
0 | https://picsum.photos/200/200/?image=101 |
0 | import div, img, br from require 'mmm.dom' | |
1 | ||
2 | => div { | |
3 | 'the first pic as a little taste:', | |
4 | br!, | |
5 | img src: @children[1]\get 'preview', 'URL -> image/png' | |
6 | } |
0 | import ReactiveVar, text, elements from require 'mmm.component' | |
1 | import div, a, img from elements | |
2 | ||
3 | => | |
4 | index = ReactiveVar 1 | |
5 | ||
6 | prev = (i) -> math.max 1, i - 1 | |
7 | next = (i) -> math.min #@children, i + 1 | |
8 | ||
9 | div { | |
10 | div { | |
11 | a 'prev', href: '#', onclick: -> index\transform prev | |
12 | index\map (i) -> text " image ##{i} " | |
13 | a 'next', href: '#', onclick: -> index\transform next | |
14 | }, | |
15 | index\map (i) -> | |
16 | child = assert @children[i], "image not found!" | |
17 | img src: @children[i]\gett 'URL -> image/png' | |
18 | } |
0 | import div, h1, a, img, br from require 'mmm.dom' | |
1 | ||
2 | => | |
3 | link = (child) -> a { | |
4 | href: '#', | |
5 | onclick: -> BROWSER\navigate child.path | |
6 | img src: child\gett 'preview', 'URL -> image/png' | |
7 | } | |
8 | ||
9 | content = [link child for child in *@children] | |
10 | table.insert content, 1, h1 'gallery index' | |
11 | div content |
0 | A Gallery of 25 random pictures, come on in! |
0 | import img from require 'mmm.dom' | |
1 | ||
2 | -- look for main content with 'URL to png' type | |
3 | -- and wrap in an mmm/dom image tag | |
4 | => img src: @gett 'URL -> image/png' |
0 | Hey I'm like a link to a picture or smth |
0 | const e = (elem, children) => { | |
1 | const node = document.createElement(elem); | |
2 | ||
3 | if (typeof children === 'string') | |
4 | node.innerText = children; | |
5 | else | |
6 | children.forEach(child => node.appendChild(child)); | |
7 | ||
8 | return node; | |
9 | }; | |
10 | ||
11 | return e('article', [ | |
12 | e('h1', 'JavaScript'), | |
13 | e('p', 'JavaScript is supported natively in the browser but is not currently pre-rendered on the server.'), | |
14 | ]); |
0 | local d = require 'mmm.dom' | |
1 | ||
2 | local lua = d.a { 'Lua', href = 'https://www.lua.org/' } | |
3 | local fengari = d.a { 'fengari.io', href = 'https://fengari.io/' } | |
4 | ||
5 | return d.article { | |
6 | d.h1 'Lua', | |
7 | d.p { lua, ' is fully supported using ', fengari, ' on the Client.' } | |
8 | } |
0 | import a, article, h1, p from require 'mmm.dom' | |
1 | ||
2 | moonscript = a 'MoonScript', href: 'https://moonscript.org/' | |
3 | lua = a 'Lua', href: 'https://www.lua.org/' | |
4 | fengari = a 'fengari.io', href: 'https://fengari.io/' | |
5 | ||
6 | article { | |
7 | h1 'MoonScript', | |
8 | p moonscript, " is compiled to ", lua, " on the server, which is then executed on the client using ", fengari, "." | |
9 | } |
0 | this Fileder contains some minimal examples showing support for various languages `mmmfs` supports currently. | |
1 | ||
2 | Language support is mostly limited by the fact that `mmmfs` currently targets web browsers, | |
3 | on the server any scripting language that can be executed can theoretically be integrated with minimal effort. | |
4 | ||
5 | Using the inspector mode to view the source of the Fileders below is encouraged. |
0 | import article, h1, p, ul, li, a from require 'mmm.dom' | |
1 | ||
2 | single = (a) -> a | |
3 | ||
4 | => | |
5 | children = for child in *@children | |
6 | title = child\gett 'title: text/plain' | |
7 | li a title, href: child.path, onclick: (e) => | |
8 | e\preventDefault! | |
9 | BROWSER\navigate child.path | |
10 | ||
11 | article { | |
12 | h1 single @gett 'title: text/plain' | |
13 | p single @gett 'preview: mmm/dom' | |
14 | ul children | |
15 | } |
0 | See I have like | |
1 | ||
2 | - a list of things | |
3 | - (two things) | |
4 | ||
5 | and some bold **text** and `code tags` with me. |
0 | I'm not even five lines of markdown but i render myself! |
4 | 4 | |
5 | 5 | # The Fileder Unified Data Model |
6 | 6 | The Fileder Model is the underlying unified data storage model. |
7 | Like almost all current data storage and access models it is based fundamentally on the concept of a hierarchical tree-structure. | |
7 | Like many data storage models it is based fundamentally on the concept of a hierarchical tree-structure. | |
8 | 8 | |
9 | 9 | <mmm-embed path="tree_mainstream">schematic view of an example tree in a mainstream filesystem</mmm-embed> |
10 | 10 | |
11 | In common filesystems as pictured, data can be organized hierarchically into *folders* (or *directories*), | |
11 | In common filesystems, as pictured, data can be organized hierarchically into *folders* (or *directories*), | |
12 | 12 | which serve only as containers of *files*, in which data is actually stored. |
13 | 13 | While *directories* are fully transparent to both system and user (they can be created, browser, listed and viewed by both), |
14 | 14 | *files* are, from the system perspective, mostly opaque and inert blocks of data. |
15 | Some metadata is associated with them (filesize, access permissions), | |
15 | ||
16 | Some metadata, such as file size and access permissions, is associated with each file, | |
16 | 17 | but notably the type of data is generally not actually stored in the filesystem, |
17 | but is determined loosely based on multiple heuristics based on the system and context, notably: | |
18 | but determined loosely based on multiple heuristics depending on the system and context. | |
19 | Some notable mechanism are: | |
18 | 20 | - Suffixes in the name are often used to indicate what kind of data a file should contain. |
19 | 21 | However there is no standardization over this, and often a suffix is used for multiple incompatible versions of a file-format. |
20 | 22 | - Many file-formats specify a specific data-pattern either at the very beginning or very end of a given file. |
21 | 23 | On unix systems the `libmagic` database and library of these so-called *magic constants* is commonly used to guess the file-type based on |
22 | 24 | these fragments of data. |
23 | However, since not all file-formats use magic constants, and since the location and value of the magic constants varies between constants, | |
24 | files can often (considered to) be valid in multiple formats at the same time. | |
25 | [TODO: quote: "Abusing file formats; or, Corkami, the Novella", Ange Albertini, PoC||GTFO 7] | |
26 | 25 | - on UNIX systems files to be executed are checked by a variety of methods to determine which format would fit. |
27 | 26 | for script files, the "shebang" (`#!`) can be used to specify the program that should parse this file in the first line of the file. |
28 | 27 | [@TODO: src: https://stackoverflow.com/questions/23295724/how-does-linux-execute-a-file] |
30 | 29 | It should be clear already from this short list that to mainstream operating systems, as well as the applications running on them, |
31 | 30 | the format of a file is almost completely unknown and at best educated guesses can be made. |
32 | 31 | |
32 | Because these various mechanisms are applied at different times by the operating system and applications, | |
33 | it is possible for files to be labelled as or considered as being in different formats at the same time by different components of the system. | |
34 | This leads to confusion about the factual format of data among users (e.g. making unclear the difference between changing a file extension | |
35 | and converting a file between formats [TODO: quote below]), but can also pose a serious security risk. | |
36 | It is for example possible, under some circumstances, | |
37 | that a file contains maliciously-crafted code and is treated as an executable by one software component, | |
38 | while a security mechanism meant to detect such code determines the same file to be a legitimate image | |
39 | (the file may in fact be valid in both formats). | |
40 | [TODO: quote: "Abusing file formats; or, Corkami, the Novella", Ange Albertini, PoC||GTFO 7] | |
41 | ||
33 | 42 | Users renaming extensions: |
34 | 43 | https://askubuntu.com/questions/166602/why-is-it-possible-to-convert-a-file-just-by-renaming-its-extension |
35 | 44 | https://www.quora.com/What-happens-when-you-rename-a-jpg-to-a-png-file |
36 | 45 | |
37 | 46 | In mmmfs, the example above might look like this instead: |
38 | 47 | <mmm-embed path="tree_mmmfs">schematic view of an example mmmfs tree</mmm-embed> |
39 | ||
40 | 48 | |
41 | 49 | Superficially, this may look quite similar: there is still only two types of nodes (referred to as *fileders* and *facets*), |
42 | 50 | and again one of them, the *fileders* are used only to hierarchically organize *facets*. |
0 | 0 | # motivation |
1 | The application-centric computing paradigm common today is harmful to users, | |
2 | because it leaves behind "intert" data as D. Cragg calls it: | |
1 | 3 | |
2 | The state of sof | |
4 | [Cragg 2016] | |
5 | D. Cragg coins the term "inert data" for the data created, and left behind, by apps and applications in the computing model that is currently prevalent: | |
6 | Most data today is either intrinsically linked to one specific application, that controls and limits access to the actual information, | |
7 | or even worse, stored in the cloud where users have no direct access at all and depend soley on online tools that require a stable network connection | |
8 | and a modern browser, and that could be modified, removed or otherwise negatively impacted at any moment. | |
9 | ||
10 | This issue is worsened by the fact that the a lot of software we use today is deployed through the cloud computing and SaaS paradigms, | |
11 | which are far less reliable than earlier means of distributing software: | |
12 | Software that runs in the cloud is subject to outages due to network problems, | |
13 | pricing or availability changes etc. at the whim of the company providing it, as well as ISPs involved in the distribution. | |
14 | Cloud software, as well as subscription-model software with online-verification mechanisms are additionally subject | |
15 | to license changes, updates modifiying, restricting or simply removing past functionality etc. | |
16 | Additionally, many cloud software solutions and ecosystems store the users' data in the cloud, | |
17 | where they are subject to foreign laws and privacy concerns are intransparently handled by the companies. | |
18 | Should the company, for any reason, be unable or unwanting to continue servicing a customer, | |
19 | the data may be irrecoverably lost (or access prevented). | |
20 | ||
21 | However this lack of control over data access is not the only problem the application-centric approach induces: | |
22 | Another consequence is that interoperability between applications and data formats is hindered. | |
23 | Because applications are incentivised to keep customers, they make use of network effects to keep customers locked-in. | |
24 | As a result applications tend to accrete features rather then modularise and delegate to other software [P Chiusano]. | |
25 | ||
26 | This leads to massively complex file formats, | |
27 | such as for example the .docx format commonly used for storing mostly | |
28 | textual data enriched with images and videos on occasion. | |
29 | The docx format is in fact an archive that can contain many virtual files internally, | |
30 | such as the images and videos referenced before. | |
31 | However this is completely unknown to the operating system, | |
32 | and so users are unable to access the contents in this way. | |
33 | As a result, editing an image contained in a word document is far from a trivial task: | |
34 | first the document has to be opened in a word processing application, | |
35 | then the image has to be exported from it and saved in its own, temporary file. | |
36 | This file can then be edited and saved back to disk. | |
37 | Once updated, the image may be reimported into the .docx document. | |
38 | If the word-processing application supports this, | |
39 | the old image may be replaced directly, otherwise the user may have to remove the old image, | |
40 | insert the new one and carefully ensure that the positioning in the document remains intact. | |
41 | ||
42 | In fact all of this is unnecessary, since the image had been stored in a compatible format on disk in the first place: | |
43 | The system was simply unaware of this because the word document had to be archived into a single file | |
44 | for ease of use by the word processor, and this single file is opaque to the system. | |
45 | ||
46 | Data rarely really fits the metaphora of files very well, | |
47 | and even when it does it is rarely exposed to the user that way: | |
48 | The 'Contacts' app on a mobile phone or laptop for example does not store each contacts's information | |
49 | in a separate 'file' (as the metaphora may have initially suggested), | |
50 | but rather keeps this database hidden away from the user. | |
51 | Consequently, access to the information contained in the database is only enabled through the contacts applications GUI. | |
52 | ||
53 | -- | |
54 | ||
3 | 55 | According to some researchers in the field of Human-Computer-Interaction, the state of computing is rather dire. |
4 | 56 | |
5 | 57 | It seems that a huge majority of daily computer users have silently accepted |
9 | 61 | - Applications are bad |
10 | 62 | - Services are worse |
11 | 63 | |
12 | ||
13 | [Cragg 2016] | |
14 | D. Cragg coins the term "inert data" for the data created, and left behind, by apps and applications in the computing model that is currently prevalent: | |
15 | Most data today is either intrinsically linked to one specific application, that controls and limits access to the actual information, | |
16 | or even worse, stored in the cloud where users have no direct access at all and depend soley on online tools that require a stable network connection | |
17 | and a modern browser, and that could be modified, removed or otherwise negatively impacted at any moment. | |
18 | 64 | |
19 | 65 | Chiusano blames these issues on the metaphor of the *machine*, and likens apps and applications to appliances. |
20 | 66 | According to him, what should really be provided are *tools*: |
3 | 3 | -- resolves to a value of type mmm/dom |
4 | 4 | => |
5 | 5 | html = require 'mmm.dom' |
6 | import article, h1, h2, h3, p, div, a, sup, ol, li, span, code, pre, br from html | |
6 | import article, h1, h2, h3, section, p, div, a, sup, ol, li, span, code, pre, br from html | |
7 | 7 | import moon from (require 'mmm.highlighting').languages |
8 | 8 | |
9 | article with _this = {} | |
9 | article with _this = style: { margin: 'auto', 'max-width': '750px' } | |
10 | 10 | append = (a) -> table.insert _this, a |
11 | 11 | |
12 | 12 | footnote, getnotes = do |
31 | 31 | append h1 'mmmfs', style: { 'margin-bottom': 0 } |
32 | 32 | append p "a file and operating system to live in", style: { 'margin-top': 0, 'padding-bottom': '0.2em', 'border-bottom': '1px solid black' } |
33 | 33 | |
34 | ||
35 | append p "mmmfs tries to change all this. In mmmfs, files can contain other files and so the collage document | |
36 | becomes a container for the collected images and texts just as a regular directory would. This way the individual | |
37 | files remain accessible and can be modified whenever necessary, while the collage document can be edited to | |
38 | change the order, sizes and spatial arrangement of it's content if this is wanted, for example." | |
39 | ||
40 | append p "The mmmfs file-type system also allows storing types of information that have become impractical to use | |
41 | with current filesystems simply because noone has cared to make suitable applications for them. It is not common | |
42 | practice, for example, to store direct links to online content on the disk for example. In mmmfs, a link to a | |
43 | picture can be stored wherever an actual picture is expected for example, the system will take care of retrieving | |
44 | the real picture as necessary." | |
45 | ||
46 | -- @TODO: motivation / outline problem + need | |
47 | -- * applications don't let users *do* things (http://pchiusano.github.io/2013-05-22/future-of-software.html) | |
48 | -- * applications are just (collections of) files - most users don't know this (anymore) | |
49 | -- * users should know their system and how to move around in it | |
50 | -- * filesystem trees are only *okay* for organizing information: | |
51 | -- - users sooner or later choose something smarter because: | |
52 | -- * filesystems work the same in every folder, even though the context can be very different | |
53 | -- * appliances put their complex, structured data into opaque blocks | |
54 | -- * the FS should be able to solve the structure issue | |
55 | -- * the benefit is interoperability: edit the image of your report | |
56 | -- * in image editor while the document editor automatically refreshes | |
57 | -- * file formats dont mean much to users, they are meant for applications - let applications take care of converting them | |
58 | -- * report.doc, report.pdf, report_orignal.pdf, report_old.doc, report2.doc.... | |
59 | ||
60 | append p do | |
61 | fileder = footnote "fileder: file + folder. 'node', 'table' etc. are too general to be used all over." | |
62 | ||
63 | -- @TODO: mention: | |
64 | -- can store anything - text, an image, a link to a website or video, | |
65 | -- a program and anything else you can think of. | |
66 | "in mmmfs, directories, files and applications are all kind of the same thing, or something like that. | |
67 | Listen, I don't really know yet either. The idea is that there is only one type of 'thing' - | |
68 | a fileder", fileder, ". A fileder can store multiple variants and metadata of its content, | |
69 | such as a markdown text and a rendered HTML version of the same document. | |
70 | It could also store a script that transforms the markdown version into HTML and is executed on demand, | |
71 | automatically." | |
72 | ||
73 | append p "Fileders can also have other fileders as their children (just like directories do in a normal | |
74 | filesystem). You can make a fileder view query these children and display them however you want. | |
75 | A 'Pictures' fileder, for example, could contain a script within itself that renders all the picture files | |
76 | you put into it as little previews and lets you click on them to view the full image." | |
77 | ||
78 | append p "This means the 'Pictures' fileder can also have an alternate slideshow mode, with fullscreen view and | |
79 | everything (some of this is built, check out the gallery example below), or one that displays geotagged images | |
80 | on a world map, if you really want that. Maybe you could build a music folder that contains links to youtube | |
81 | videos, spotify tracks and just plain mp3 files, and the folder knows how to play them all.", br!, " | |
82 | In this way fileders fulfil the purpose of 'Applications' too." | |
83 | ||
84 | -- @TODO: BUT doesn't have to be only for one type of file: | |
85 | -- @TODO: rework | |
86 | -- making a multi-media collage representing your thoughts and mental organization of a topic | |
87 | append p "A fileder is also responsible for how it's children are sorted, filtered and interacted with. | |
88 | For example you should be able to create a fileder that is essentially a 'word document' equivalent: it can | |
89 | contain images, websites, links and of course text as children and let you reorder, layout and edit them | |
90 | whenever you open the fileder." | |
91 | ||
92 | append p "Sounds cool, no? Here's some examples of things a fileder can be or embed:" | |
93 | ||
94 | 34 | -- render a preview block |
95 | preview = (child) -> | |
35 | do_section = (child) -> | |
96 | 36 | -- get 'title' as 'text/plain' (error if no value or conversion possible) |
97 | title = child\gett 'title', 'text/plain' | |
37 | title = (child\get 'title: text/plain') or child\gett 'name: alpha' | |
98 | 38 | |
99 | 39 | -- get 'preview' as a DOM description (nil if no value or conversion possible) |
100 | content = child\get 'preview', 'mmm/dom' | |
40 | content = (child\get 'preview: mmm/dom') or child\get 'mmm/dom' | |
101 | 41 | |
102 | div { | |
42 | section { | |
103 | 43 | h3 title, style: { margin: 0, cursor: 'pointer' }, onclick: -> BROWSER\navigate child.path |
104 | 44 | content or span '(no renderable content)', style: { color: 'red' }, |
105 | style: { | |
106 | display: 'inline-block', | |
107 | width: '300px', | |
108 | height: '200px', | |
109 | padding: '4px', | |
110 | margin: '8px', | |
111 | border: '4px solid #eeeeee', | |
112 | overflow: 'hidden', | |
113 | }, | |
114 | 45 | } |
115 | 46 | |
116 | append div for child in *@children | |
117 | preview child | |
118 | ||
119 | append h2 "details" | |
120 | -- @TODO s/parts: dimensions, aspects? | |
121 | -- @TODO: first mention both facets & children; then go into detail | |
122 | -- @TODO: main content | |
123 | append do | |
124 | name = html.i 'name' | |
125 | type = html.i 'type' | |
126 | ||
127 | p "Fileders are made up of two main parts. The first is the list of ", (html.i 'facets'), ", | |
128 | which are values identified by a ", name, " and ", type, ". These values are queried using strings like ", | |
129 | (code 'title: text/plain'), " or ", (code 'mmm/dom'), ", which describe both the ", name, | |
130 | " of a facet (", (moon '"title"'), " and ", (moon '""'), ", the unnamed/main facet) and the ", type, | |
131 | " of a facet. Facet types can be something resembling a MIME-type or a more complex structure | |
132 | (see ", (html.i "type chains"), " below). A fileder can have multiple facets of different types | |
133 | set that share a ", name, ". In this case the overlapping facets are considered equivalent and the one | |
134 | with the most appropriate ", type, " is selected, depending on the query. | |
135 | The unnamed facet is considered a fileder's 'main content', i.e. what you are interested in when viewing it." | |
136 | ||
137 | append p "The second part of a fileder is the list of it's children, which are fileders itself. | |
138 | The children are stored in an ordered list and currently identified by their ", (code 'name: alpha'), | |
139 | " facet for UI and navigation purposes only (not sure if this is a good idea tbh)." | |
140 | ||
141 | append do | |
142 | mmmdom = code ('mmm/dom'), footnote span (code 'mmm/dom'), " is a polymorphic content type; | |
143 | on the server it is just an HTML string (like ", (code 'text/html'), "), | |
144 | but on the client it is a JS DOM Element instance." | |
145 | ||
146 | p "What you are viewing right now is the main facet of the root fileder. | |
147 | The facet is queried as ", mmmdom, ", a website fragment (DOM node). This website fragment | |
148 | is then added to the page in the main content area, where you are most likely reading it right now." | |
149 | ||
150 | p "Anyway, this node is set up as a very generic sort of index thing and just lists its children-fileders' | |
151 | alongside this text part you are reading.", br!, "For each child it displays the ", (code 'title: text/plain'), | |
152 | " and shows the ", (code 'preview: mmm/dom'), " facet (if set)." | |
153 | ||
154 | append h3 "converts" | |
155 | append p "So far I have always listed facets as they are being queried, but a main feature of mmmfs is | |
156 | type conversion. This means that you generally ask for content in whichever format suits your application, | |
157 | and rely on the type resolution mechanism to make that happen." | |
158 | ||
159 | append pre moon [[ | |
160 | -- render a preview block | |
161 | preview = (title, content) -> div { | |
162 | h3 title, style: { ... }, | |
163 | content or span '(no renderable content)', style: { ... }, | |
164 | style: { ... } | |
165 | } | |
166 | ||
167 | append div for child in *@children | |
168 | -- get 'title' as 'text/plain' (error if no value or conversion possible) | |
169 | title = child\gett 'title', 'text/plain' | |
170 | ||
171 | -- get 'preview' as a DOM description (nil if no value or conversion possible) | |
172 | content = child\get 'preview', 'mmm/dom' | |
173 | ||
174 | preview title, content | |
175 | ]] | |
176 | ||
177 | append p "Here the code that renders these previews. You can see it ", (html.i "asks"), " for the | |
178 | facets ", (code 'title: text/plain'), ' and ', (code 'preview: mmm/dom'), "), but the values don't actually have to | |
179 | be ", (html.i "defined"), " as these types. | |
180 | For example, the markdown child below only provides ", (code 'preview'), " as ", (code 'text/markdown'), ":" | |
181 | ||
182 | append pre moon [[ | |
183 | Fileder { | |
184 | 'title: text/plain': "I'm not even five lines of markdown but i render myself!", | |
185 | 'preview: text/markdown': "See I have like | |
186 | ||
187 | - a list of things | |
188 | - (two things) | |
189 | ||
190 | and some bold **text** and `code tags` with me.", | |
191 | } | |
192 | ]] | |
193 | ||
194 | append p "Then, globally, there are some conversion paths specified; such as one that maps from ", | |
195 | (code 'text/markdown'), " to ", (code 'mmm/dom'), ":" | |
196 | ||
197 | append pre moon [[ | |
198 | { | |
199 | inp: 'text/markdown', | |
200 | out: 'mmm/dom', | |
201 | transform: (md) -> | |
202 | -- polymorphic client/serverside implementation here, | |
203 | -- uses lua-discount on the server, marked.js on the client | |
204 | } | |
205 | ]] | |
206 | ||
207 | append h3 "type chains" | |
208 | append p "In addition, a facet type can be encoded using multiple types in a ", (code 'type chain'), ". | |
209 | For example the root node you are viewing currently is actually defined as ", (code 'fn -> mmm/dom'), ", | |
210 | meaning it's value is a pre moon function returing a regular ", (code 'mmm/dom'), " value." | |
211 | ||
212 | append p "Both value chains and 'sideways' converts are resolved using the same mechanism, | |
213 | so this page is being rendered just using ", (moon "append root\\get 'mmm/dom'"), " as well. | |
214 | The convert that resolves the moon type is defined as follows:" | |
215 | ||
216 | append pre moon [[ | |
217 | { | |
218 | inp: 'fn -> (.+)', | |
219 | out: '%1', | |
220 | transform: (val, fileder) -> val fileder | |
221 | } | |
222 | ]] | |
223 | ||
224 | append p "The example with the image is curious as well. In mmmfs, you might want to save a link to an image, | |
225 | without ever saving the actual image on your hard drive (or wherever the data may ever be stored - it is | |
226 | quite transient currently). The image Fileder below has it's main (unnamed) value tagged as ", | |
227 | (code 'URL -> image/png'), " - a png image, encoded as an URL. When accessed as ", (code 'image/png'), " | |
228 | the URL should be resolved, and the binary data provided in it's place (yeah right - I haven't build that yet)." | |
229 | ||
230 | append p "However, if a script is aware of URLs and knows a better way to handle them, then it can ask for and | |
231 | use the URL directly instead. | |
232 | This is what the image demo does in order to pass the URL to an ", (code 'img'), " tag's ", (code 'src'), " attribute:" | |
233 | ||
234 | append pre moon [[ | |
235 | Fileder { | |
236 | 'title: text/plain': "Hey I'm like a link to picture or smth", | |
237 | 'URL -> image/png': 'https://picsum.photos/200?random', | |
238 | 'preview: fn -> mmm/dom': => | |
239 | import img from require 'mmm.dom' | |
240 | img src: @gett 'URL -> image/png' -- look for main content with 'URL to png' type | |
241 | } | |
242 | ]] | |
47 | for child in *@children | |
48 | append child\gett 'mmm/dom' | |
49 | -- do_section child | |
243 | 50 | |
244 | 51 | append getnotes! |