Processors
Definition processors are a feature of Modulo that allows for component parts and other definitions to support special attributes that trigger certain behavior. They are commonly used for configuring, loading, or tranforming definitions.
Definition processors are conventionally prefixed with a dash (that is, -
).
This distinguishes them from regular attributes. Some processors can only be
used with a certain type of component parts or definitions. For example,
examine the -store=
processor for State:
Others are supported by all component parts. For example, examine the -src=
processor for loading content from external files.
Behavior
Definition processors have three important rules of behavior:
As the name implies, definition processors are run while Modulo first loads definitions, meaning all the Processors will all complete before your web components register their tag names. Definition processors are applied before any other behavior. That is to say, every processor finishes its tasks before any components are mounted on the screen.
Processors can be asyncronous, load data, process data, and can even do "slow" operations compared to other aspects of Modulo. CParts can load asyncronously, or even block loading if they choose to do so. This is what allows Modulo to self-configure and users to "invent" their own CParts:
<Configuration -src="...">
will block loading any future-src=
attributes until it's finished with all it's Processors; however,<Template -src="...">
is written to assumed to not need any particular ordering, and will be loaded asynchrously.Definition processors are not run in built or packed scripts. That is, the definitions stored in the compiled JS file are "pre-processed", and thus the processor only will run during development or when building. If accumulating many files and definition processors is slowing down your growing site, the good news is that after building, no one will notice, since Processors are (typically) only run during development. See Building Apps with Modulo Part 3 for more on pre-building.
Built-in Processors
Why no dash for
<Component name="...">
? Note that for Component, you usename=
(without the-
), and use a valid JavaScript identifier as the Web Component name. However, that behavior is specific to the Component definition, and is not available on Component Parts or other definitions. Definition types (e.g. core definitions like Library or a component parts like State) can each specify their own, unique behavior for processors.
-name
- Supported by: All Definitions
The -name
directive allows you to override the default name that Modulo will
generate with something else. This allows you to have multiple Component Parts
of the same type without conflict.
For a simple example, see below:
Example: -name
for multiple Component Parts
Note that Template has special behavior around -name
. If you specify a
name, it will not by default still render, since it will assume you are going
to include it somewhere else.
-src
- Supported by: All Definitions
Note that the -src= combines the retrieved content with whatever is embedded between the opening and closing tag. It does not replace the embedded content, but instead places the retrieved content before content BEFORE the embedded content. This ordering is important, since it allows the internal content to "extend" the content that is being brought in.
-src for extension
The -src
attribute is designed to allow for many types of "inheritence" or a
sort of primitive extension, depending on the CPart. For example, Components
can "inherit" CParts of base components (e.g., the Template and Script
could be the same across two Components, but they only differ in Style), or
Style can "inherit" another style file, but get to append some modifications
to the end. (e.g., loading from a third party, then override certain
properties). Similarly, Library or Modulo can load entire Modulo libraries,
and then apply Configuration scripts at the end to modify configuration
settings within that other libraries' execution context.
-filter-content
- Supported by: Template (Alpha 71), StaticData, Style (Alpha 72+)
Allows you to apply template filters at load time.
Example 1: Trim excess code
You can use trim
to remove excess characters from a remotely loaded file. For
example, here we load content from an external document file, and then use
|trim
to clean up the doctype information, text we don't want in the Template:
In this case, the trim
filter will remove the XML doctype and an HTML opening
tag, along withe the HTML closing tag, if they are found at the beginning and
end of the document retrieved from:
https://some-site.com/some-old-document.xhtml
. Processors all happen during
initial loading of components and definitions, meaning the trimmed text will be
ignored and omitted from the JS builds.
Example 2: Style template with trim
By defining a style Template
, we can template style for inclusion. By using
trim
we can use a placeholder of x { .. }
to make editing this CSS easier
to read. Note that this is, in fact, a Template CPart, however, we will use a
style
initial tag to make it easier to read and syntax highlight.
See below for a concrete example of how to use this technique for making a quick button designer component:
Example 3: Tagswap for <table>
Modulo uses HTML syntax for most everything. This, unfortunately, means that
<table>
tags can behave differently when it comes to how content is processed
and loaded, causing content to "escape" when you are still just assembling the
initial Template's DOM. Similarly, the closing script
tag can have special
meanings as well. To get around limitations like this, we can use the
|tagswap
to convert innocuous placeholder tags into other ones:
This will be applied at load time, so there are ultimately no performance penalties, as the final JavaScript file will have the tag transpositions "baked in" (and with no trace of the original template, either).
Gotcha: Applied at runtime
Remember that it is applied "pre-baked" to the content itself during initial
content load, and NOT at Template run time, meaning it will affect (and
potentially disrupt) the tempting language itself as well (e.g. using
-filter-content="upper"
will cause {{ state.stuff }}
to become {{
STATE.STUFF }}
, which will not work since capitalization matters in this
case).