From d4a145b96b6373effce788e2202506472fec0d2e Mon Sep 17 00:00:00 2001 From: Sir Robert Burbridge Date: Wed, 15 Nov 2023 14:52:05 -0500 Subject: [PATCH] Update docs. --- README.md | 25 +++++----- docs/components.md | 83 ------------------------------- docs/markup.md | 107 ---------------------------------------- docs/process.md | 86 -------------------------------- docs/transformations.md | 56 +++++++++++++++++++++ docs/usage.md | 3 -- 6 files changed, 68 insertions(+), 292 deletions(-) delete mode 100644 docs/components.md delete mode 100644 docs/markup.md delete mode 100644 docs/process.md create mode 100644 docs/transformations.md delete mode 100644 docs/usage.md diff --git a/README.md b/README.md index a986277..8907d37 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@ # @thefarce/loom - ## What is this? Loom is a tool for weaving form data with content data in nodejs. It does @@ -39,7 +38,8 @@ console.log( interpolate( transform( parseHtml('

Hello, {name}!

'), - [], + () => { ... }, + [funcA, funcB, funcC], ), { name: 'Othello' }, ) @@ -55,31 +55,30 @@ Running this script produces the following output: ## API -### renderHtml(ast) +### astToHtml(ast) -### parseHtml(html) +### htmlToAst(html) ### interpolate(ast, data) ### transform(ast, plugins) +See the [transformations documentation](./docs/transformations.md) for more +information. + Transform the AST according to plugins. -#### ast +## Glossary + +### ast The AST to be transformed. This can be any AST that conforms to the Unified.js specification, especially the [hast](https://github.com/syntax-tree/hast) AST. -#### plugins +## Contributing to Loom -Plugins are pairs of functions. - -The *selector* function - -The *transformer* function - -## Development +Contributions to Loom are welcome. ### VIM diff --git a/docs/components.md b/docs/components.md deleted file mode 100644 index 671b488..0000000 --- a/docs/components.md +++ /dev/null @@ -1,83 +0,0 @@ -# Components - -## Architecture - -Fundamentally, we want to do (approximately) 4 steps, some of which are -optional. - -1. Template parsing. Transforms templates into ASTs. -1. Template integration. Combines two templates into a single template. -1. Content parsing. Structures content for template AST rendering. -1. Rendering. Concretize the AST into a document structure with - the available content added. - - -## Thoughts - -It is not at all clear to me that components should be in HTML. It seems -like a natural starting point, though, since we want to stay close to our -bare-metal technologies. - -Perhaps components should be in the style of HTML or JSX fragments. I -borrowed heavily from Svelte for this. - -I'm somewhat dissatisfied with the syntax of svelte's "directives" like -{#if} and {/if}. They feel like they were put in as a concession to -script interpolation. I think I prefer the JSX approach that uses {} -to run arbitrary script content. - -I don't know if there's any concepts we should bring in from XSLT for -this, but it's already a technology mechanis, - - - -``` -// This "" tag could be created automatically before inserting. - - - -
    -
  • Allow multiple comment styles?
  • -
  • Plugin-based transformations (AST)
  • -
  • Some kind of script scoping
  • -
  • Allow some bits of code using JSX-style {} syntax.
  • -
- - - -
-``` - - -If the component defines something like this: - -``` - - - -``` - -Then the "import" node of the AST would be replaced by a function that -provides the requested content (from Item.component.xml) like a macro. When -the `` node is hit, it will be interpreted according to the imported -component macro. - diff --git a/docs/markup.md b/docs/markup.md deleted file mode 100644 index 4f26720..0000000 --- a/docs/markup.md +++ /dev/null @@ -1,107 +0,0 @@ -# Markup - -## Considerations - -Hypothetically, markup doesn't really matter for this. A component is a -component if it can be translated into an AST that a renderer can render. - -Practically, markup matters a lot. People will have strong preferences -about their favourite versions of things. One solution to this is to open -everything wide: "Just make parsers, transformers, and renderers that suit -your need." The advantage of this is it gives people a lot of power to do -whatever they want. Practically, the disadvantage is that poor taste will -prevail. This is mostly just because good taste requires lots of hard work -and most people haven't had time to do sufficient hard work to have good -taste (disregarding the tendency not to want to do that work). It's -probably worth noting that good taste can have strong aesthetic differences. -Two people who disagree strongly can both have excellent tastes, differing -in influences. - -I think the approach I prefer is to leave it open in principle but obscured -from most consumers of the tool. This would be effectively to make the Loom -toolkit work with any style of markup and plugins, but not to popularize -that feature (for quite some time), preferring instead to create -concretizations of the toolkit in the form of frameworks. These will help -guide consumers in taste, while not restricting those who want to apply more -work to develop their own aesthetic sensibilities. - -## Key Elements - -Fundamentally, we want to integrate _form data_ with _content data_. There -are probably better and worse paradigms for how to accomplish this. I'd say -probably _logic_ style. This is a paradigm that would let -producers ignore the mechanisms of integration. - -Another excellent (and opposite) approach could be a _functional_ style. In -this paradigm, the producer is concerned with mechanisms of data -transformation. - -## Other thoughts - -It is not at all clear to me that components should be in HTML. It seems -like a natural starting point, though, since we want to stay close to our -bare-metal technologies. - -Perhaps components should be in the style of HTML or JSX fragments. I -borrowed heavily from Svelte for this. - -I'm somewhat dissatisfied with the syntax of svelte's "directives" like -{#if} and {/if}. They feel like they were put in as a concession to -script interpolation. I think I prefer the JSX approach that uses {} -to run arbitrary script content. - -I don't know if there's any concepts we should bring in from XSLT for -this, but it's already a technology mechanism that operates in this domain. - - - -``` -// This "" tag could be created automatically before inserting. - - - -
    -
  • Allow multiple comment styles?
  • -
  • Plugin-based transformations (AST)
  • -
  • Some kind of script scoping
  • -
  • Allow some bits of code using JSX-style {} syntax.
  • -
- - - -
-``` - - -If the component defines something like this: - -``` - - - -``` - -Then the "import" node of the AST would be replaced by a function that -provides the requested content (from Item.component.xml) like a macro. When -the `` node is hit, it will be interpreted according to the imported -component macro. - diff --git a/docs/process.md b/docs/process.md deleted file mode 100644 index a53b625..0000000 --- a/docs/process.md +++ /dev/null @@ -1,86 +0,0 @@ - -# Process - - * Load one or more modules - * Load one or more HTML fragments - * Render each fragment against the relevant data. - -# Loom Modules - -Loom modules are bundles of: - - 1. Form data - 2. Process data - 3. Event data - 4. Content data - -Each element of a module is sandboxed. The data can be accessed externally, -but need not be. - -Loom modules are represented by an abstract syntax tree. - -The `content` element of a node can be any single value that is one of an -boolean, string, number, object/map, array, or undefined/null. - -The `process` element of a node can be any set of functions that can be fully -serialized to a string round-trip. - -The `event` element of a node is a dictionary of events keyed to a name with -a value that is always an array of handlers. Each handler takes an event -object as the first (or only) argument. Handler functions can either be -functions or registry names of `process` functions. - -In this way, data and processes can be attached to any node as local state. - -Consider the following HTML snippet - -
Title
- -and (an elided form of) its AST: - -``` -{ - "type" : "root", - "children" : [ - { - "type" : "element", - "tagName" : "div", - "properties" : {}, - "children" : [ - { - "type" : "text", - "value" : "Test", - } - ], - }, - ], -} -``` - -Going further - -The following defines an HTML template with inline process data. - -``` -
{ $.content = 'New Title' } - }} ->Title
-``` - -As written, the `changeTitle` process will never be called. Let's attach -it to an event. - -``` -
$.process.changeTitle('New Title'), - }} - - loom-process={{ - 'changeTitle': ($) => { $.content = 'New Title' }, - }} ->Title
-``` - diff --git a/docs/transformations.md b/docs/transformations.md new file mode 100644 index 0000000..741cfc9 --- /dev/null +++ b/docs/transformations.md @@ -0,0 +1,56 @@ +# Transformation + +In Loom, *transformation* refers to the process of modifying an abstract +syntax tree (AST), especially through the use of *transformers*. + +Transformers are arrays of functions. + +The mechanism provided by loom for these transformations is the +`transform()` function. + +The first argument to the `transform` function is an AST. Each node in the +AST will be considered for transformation. + +After the AST, any number of additional arguments may be passed to the +`transform` function. Each of these should be a *transformer function* or +an array of such. + +## Transformation functions + +Transformer functions take _a copy_ of an AST node. Because it is a copy, +the changes made to the node received by the transformer function will have +no effect on the tree. To change the tree, return a new AST node. + +### Return values + +Transformation functions may return one of three recognized value types. If +a different value is returned, the `transform` function will throw an error. + +#### AST node + +If the transformation function returns an AST node, that node will be used +to replace the original node in the original tree. Subsequent transformer +functions will recieve a copy of the _new_ node, not the original. + +For convenience, new tree nodes can be created with the +`util.createAstNode()` or `util.cloneNode(node)` function. The +determination of whether or not the returned value is an AST node is made +using the `util.isAstNode()` utility function. + +#### null + +If the transformation function returns `null`, the original node will be +removed from the AST. No further transformation functions will be called on +the same node. + +#### undefined + +If the transformation function returns `undefined`, the original node will +be left in the AST unchanged. The next transformation function will be +called on the same node. + +### _other values_ + +In the event that a transformation function returns any other value than +`null`, `undefined`, or an AST node--as determined by `util.isAstNode()`, +the `transform()` function will throw an error. \ No newline at end of file diff --git a/docs/usage.md b/docs/usage.md deleted file mode 100644 index 69ead10..0000000 --- a/docs/usage.md +++ /dev/null @@ -1,3 +0,0 @@ -# Loading templates - -