Open TheJaredWilcurt opened 2 years ago
Thank you for your feature, your goals are well documented, I will try to match the scope so that in the future we can create a prototype.
Some time ago I experimented creating a render based on directives https://github.com/UpperCod/dollars.js
The development of a template engine that considers a new syntax is complex, do you happen to know of a compiler that interprets the majority of the objective? I have been seeing this library to apply in the prototype https://www.npmjs.com/package/sax-wasm
Most of what I've outlined is based on Vue's template syntax. There is the official Vue-Template-Compiler, which does have an option to return an AST. But there are many other libraries around Vue-like syntax. Though I haven't evaluated them to know the pros/cons of these options. It may be easiest to take the officially maintained compiler and add a transform at the end of it's AST to map to what this project's needs are. Then you only need to maintain a high level translation layer, instead of the syntax itself.
This means that you'd be stuck with v-if
instead of a-if
. Similarly, for things like 2-way data binding being more complex in Vue 3, you wouldn't be able to use the simpler Vue-2 style. But alternatively it means that you could just link to Vue's official docs for documentation on the syntax, so that is beneficial in a sense. It's literally the same syntax, not a similar, but custom alternative. Though technically in Vue, you can create and globally install your own custom directives, (a-if, a-model, etc). So if you do want to alias the Vue directives, or create your own, that may be possible.
found another related project, https://github.com/stalniy/react-template-compiler
Is your feature request related to a problem? Please describe.
JSX/Lit/Uhtml/etc all look and act basically the same. For those that care about the very very subtle differences between them, it is nice to have those options, but another template syntax should be supported that differs more greatly to appeal to those coming from frameworks other than React.
Describe the solution you'd like
Dynamic attributes:
Dynamic attributes, or props, should be discerned by prefixing the attribute with a colon.
Boolean Attributes
Some HTML attributes are considered boolean attributes. Meaning they don't require a value to be valid, and their existence represents value. For example
disabled
,required
,checked
, etc.In these cases, the syntax should accept a variable, and if truthy, it will append the attribute in the DOM.
Special attribute syntax for "class"
The most commonly used attribute in all of HTML, by a landslide, is
class
. Because it is so common, and has some common dynamic uses, we should support a few special syntax's to make life more convenient.Event Bindings:
Dynamic event bindings should be discerned by replacing the "on" prefix with an at-sign.
Event Modifiers:
Several event modifiers should be supported to improve code readability. At the very least
prevent
andstop
. For exampleBAD:
Can become the far more readable: GOOD:
In Vue, "Handle X" is considered an anti-pattern, because the framework can handle most events for you, and it obscures the actual functionality being performed.
Inline expressions
Double curlies should be used to indicate a text node be created with the evaluated result of an expression.
Two-Way data binding (text)
Two-way data binding is a common feature of framworks, like Polymer, Vue, and many others. This could be handled via an
a-model
attribute.This will set the
value
attribute of the input any time thesomeValue
variable is modified. It would also add an event listener to the element for input events, retrieve theevent.currentTarget.value
and use that to update the value of thesomeValue
variable.This approach would be the same as doing:
This matches the intuitive approach used by Vue 2. In Vue 3 it was changed to a less intuitive approach, in which it sets
modelValue
instead ofvalue
and expectsupdate:modelValue
instead ofinput
. This change was made to allow applying multiplev-model
's on an element. Something not possible in Vue 2, but also, not really needed, as you could emit an object if needed.This would work on
<input>
elements with no type attribute (since it defaults to text) and most other input types (liketype="email"
ortype="password"
, etc).Two-way data binding (Boolean)
<input v-model="someValue" type="checkbox">
would be equivalent toThe 5 basic directives
You should be able to add a simple directive to your template to control common flow logic.
a-model
a-if
a-for
a-html
a-text
a-show
isn't needed but is cleaner than doing by handExamples:
<input a-model="value">
- See the two-way data binding section above<div a-if="someBool"></div>
- IfsomeBool
is false, this element is removed from the DOM. Can be performant by removing a large set of DOM nodes from memory when not needed.<div a-show="someBool"></div>
- IfsomeBool
is false, this attribute is givenstyle="display: none"
. Can be more performant if toggling visibility on a lot of DOM nodes often<div a-for="(item, index) in items"></div>
- Creates an element (div
in this case) for every item in theitems
array.item
andindex
can be renamed to anything.<div a-for="(value, key) in item"></div>
- Creates an element for everykey
in theitem
object.value
andkey
can be renamed to anything.<div a-html="'<strong>Text</strong>'"></div>
- AppliesinnerHTML
, can be dangerous if it contains any data supplied by a user or network request, but also useful when the value is generated internally<a a-text="'text'"></a>
- AppliesinnerText
, can be useful when you don't want additional whitespace that could occur when using returns and indentation in your code.I probably should have started this ~wishlist~ issue with "Dear Santa,".