diff --git a/src/_includes/webc-attribute-guide.njk b/src/_includes/webc-attribute-guide.njk index 13199a50a8..414783415a 100644 --- a/src/_includes/webc-attribute-guide.njk +++ b/src/_includes/webc-attribute-guide.njk @@ -1,5 +1,14 @@ -{% callout "info", "md-block", "Comparing WebC Attribute Data Types" -%} -1. [Attributes](#attributes-and-webcroot): HTML attribute strings. -1. [Properties](#props-(properties)): server-only private HTML attribute strings (not rendered to output). -1. [Dynamic Attributes and Properties](#dynamic-attributes-and-properties): evaluate as JavaScript (any data type, not just strings). -{% endcallout %} \ No newline at end of file +#### Which one to use + +Attributes and props pass values into a component and are available inside it as variables by name (camelCased). Slots pass child markup. They differ in how the value is evaluated and whether it reaches the output HTML. + +| Syntax | Value | In output | Use when | +| ------------------------------------------------------- | -------------------- | --------- | ------------------------------------------------------------------------------------- | +| [Attribute](#attributes-and-webcroot) | String | Yes\* | The value belongs on an element in the output, such as `id`, `class`, or `data-*`. | +| [Prop](#props-properties) | String | No | The component needs the value but it should not appear in the HTML. | +| [Dynamic attribute](#dynamic-attributes-and-properties) | Any JavaScript value | Yes\* | The attribute value comes from page data or an expression. | +| [Dynamic prop](#dynamic-attributes-and-properties) | Any JavaScript value | No | Pass page data or a non-string value (number, object, array) into the component. | +| [Slot](#slots) | HTML | Yes\*\* | The page supplies markup, not just a value, or the component wraps arbitrary content. | + +\* Rendered when the host tag is kept in the output, or when the component places them with [`webc:root`](#attributes-and-webcroot) or [`@attributes`](#attributes).
+\*\* Rendered where the component places its ``. diff --git a/src/docs/languages/webc.md b/src/docs/languages/webc.md index c140bdd767..29e6393631 100644 --- a/src/docs/languages/webc.md +++ b/src/docs/languages/webc.md @@ -27,7 +27,7 @@ relatedLinks: ### Performance -- Create streamlined component-driven, cache-friendly page-specific JavaScript and CSS bundles. Users will only load the code they need to render that page (or that [island](/docs/plugins/is-land/)). +- Create streamlined component-driven, cache-friendly page-specific JavaScript and CSS bundles. Users load only the code they need to render that page (or that [island](/docs/plugins/is-land/)). - Easily [configurable boundaries](#asset-bucketing) for critical component CSS and JavaScript. - Works great with [is-land](/docs/plugins/is-land/) for web component hydration. - Get first-class **incremental builds** (for page templates, components, and Eleventy layouts) when [used with `--incremental`](/docs/usage/#incremental-for-partial-incremental-builds) @@ -40,7 +40,7 @@ relatedLinks: ### Authoring -- Encourages no-quirks mode HTML authoring (and a doctype is optional). WebC throws a helpful error if encounters quirks mode markup. +- Encourages no-quirks mode HTML authoring (and a doctype is optional). WebC throws a helpful error if it encounters quirks mode markup. - Easily scope component CSS (or use your own scoping utility). - Tired of importing components? Use global or per-page no-import components. - Async-friendly: All configuration extensions/hooks into WebC are async-friendly out of the box. @@ -117,9 +117,7 @@ View the [full options list for the Bundle plugin](/docs/plugins/bundle.md). As ### Syntax highlighting -Because WebC _is_ HTML you can configure your editor to treat `.webc` files as -HTML, this should correctly syntax highlight your WebC files. Your editor of -choice should have some documentation on how to get this working. +Because WebC _is_ HTML, you can configure your editor to treat `.webc` files as HTML for syntax highlighting. Your editor of choice should have some documentation on how to get this working. ## Usage @@ -127,7 +125,7 @@ There are a few different ways to use WebC in Eleventy: ### Add a new `.webc` file -Adding the plugin will enable support for `.webc` files in your Eleventy project. Just make a new `.webc` HTML file in your Eleventy input directory and Eleventy will process it for you! Notably, `.webc` files will operate [WebC in bundler mode](https://github.com/11ty/webc#aggregating-css-and-js), aggregating the CSS and JS in use on each individual page to create a bundle of the assets in use on the page. +[Adding the plugin](#installation) enables support for `.webc` files in your Eleventy project. Create a new `.webc` HTML file in your Eleventy input directory and Eleventy processes it for you. `.webc` files operate in [WebC bundler mode](https://github.com/11ty/webc#aggregating-css-and-js), aggregating the CSS and JS in use on each individual page into a bundle of the assets in use on the page. WebC uses an HTML parser to process input files: use any HTML here! @@ -160,12 +158,12 @@ You can use the configuration option to change the default HTML preprocessor (fr #### Post-process HTML output as WebC -This is a (last-resort?) catch-all option to let WebC process `.html` output files in your project (skipping any `.webc` input files to avoid double-processing templates). This feature makes use of [Eleventy transforms](/docs/config/#transforms) and is most useful when you want to get up and running with WebC on an existing project quickly. +This is a catch-all option that lets WebC process `.html` output files in your project (skipping any `.webc` input files to avoid double-processing templates). It uses [Eleventy transforms](/docs/config/#transforms) and is most useful when you want to get up and running with WebC on an existing project quickly. A few drawbacks to the transform method: 1. This is the slowest build-performance method to implement WebC in a project, so try the other methods first! -2. The WebC Eleventy transform operates with [bundler mode disabled](<#css-and-js-bundler-mode>), which means that processes WebC but _does not_ aggregate component JS or CSS. ([Upvote this enhancement request](https://github.com/11ty/eleventy-plugin-webc/issues/55)) +2. The WebC Eleventy transform operates with [bundler mode disabled](#css-and-js-bundler-mode), which means it processes WebC but _does not_ aggregate component JS or CSS. ([Upvote this enhancement request](https://github.com/11ty/eleventy-plugin-webc/issues/55))
The transform is disabled by default, you will need to use the useTransform option to enable it. @@ -183,137 +181,233 @@ export default function (eleventyConfig) {
-## WebC Reference - -**Note:** All `webc:` attributes are removed from the rendered output HTML. +## Components and output ### HTML-only components - _Related: [Defining Components in WebC](#defining-components)_ -When a component has only content HTML (no CSS or JavaScript) it will ignore the host component tag in the output HTML. This enables HTML-only components to have zero overhead HTML. _(You can opt-out of this behavior with `webc:keep`.)_ - -
-Expand for Example +When WebC **does not** find ` +{%- endset %} +{{ codeBlock | highlight("html") | safe }} +{% codetitle "index.webc" %} +{%- set codeBlock %} WebC Example + -``` - -{% codetitle "components/my-component.webc" %} - -```html -Components don’t need a root element, y’all. +{%- endset %} +{{ codeBlock | highlight("html") | safe }} +{% codetitle "_site/index.html", "Output example" %} +{%- set codeBlock %} + + + + WebC Example + + + +

Hello possum.

+ + +{%- endset %} +{{ codeBlock | highlight("html") | safe }} + +
+{% codetitle "_components/my-component.webc" %} +{%- set codeBlock %} +

Hello possum.

-``` - -Outputs: - -{% codetitle "_site/page.html" %} - -```html +{%- endset %} +{{ codeBlock | highlight("html") | safe }} +{% codetitle "index.webc" %} +{%- set codeBlock %} + +WebC Example + + +{%- endset %} +{{ codeBlock | highlight("html") | safe }} +{% codetitle "_site/index.html", "Output example" %} +{%- set codeBlock %} WebC Example + - Components don’t need a root element, y’all. +

Hello possum.

-``` - -
- -Eleventy runs WebC in Bundler mode. That means that when it finds ` - + + + ``` -You can also use `webc:keep` to save a [``](#slots) for use in a client-side custom element. +Keeps a `` element in the output for a client-side custom element to fill. Read more at [Slots](#slots). ### `webc:nokeep` -With an CSS/JS component (not an [HTML-only component](#html-only-components)), you can use `webc:nokeep` on the host component to drop the tag: +Drops the host tag of a [component with CSS or JavaScript](#asset-bundling) from the output. + +{% codetitle "index.webc" %} ```html - + ``` -### `webc:import` +Inserts content into the output as-is, without adding an element around it. -WebC will expand any component it finds using known components. You can also use `webc:import` to inline import a component definition. This import path is relative to the component file path. WebC checks for circular component dependencies and throws an error if one is encountered. +{% codetitle "_includes/layout.webc" %} -- _Related: [Defining Components in WebC](#defining-components) (global or scoped)_ +```html + +``` + +### `webc:is` + +Replaces the element’s tag name with a component name. Both examples are equivalent to ``. + +{% codetitle "index.webc" %} ```html - +
+ +
``` -{% addedin "@11ty/webc@0.6.2" %}You can import directly from an installed npm package. Eleventy will begin to supply WebC components with existing plugins. The Syntax Highlighter (`4.2.0` or newer) supplies one that you can use today: +### `webc:import` + +Imports the component definition for the element from a path relative to the current file, or from an npm package with the `npm:` prefix. + +**Note:** WebC expands any component it already knows about without an import, such as every file matching the default `_components/**/*.webc` glob. + +- _Related: [Defining Components in WebC](#defining-components) (global or scoped)_ + +{% codetitle "index.webc" %} ```html + + ``` -This uses the component tag name (`syntax-highlight`) to look for a WebC component at `node_modules/@11ty/eleventy-plugin-syntaxhighlight/syntax-highlight.webc` and imports it for use on this node. This works with a tag name override via `webc:is` too. +{% addedin "@11ty/webc@0.6.2" %}With the `npm:` prefix, WebC uses the tag name (`syntax-highlight`) to look for a component at `node_modules/@11ty/eleventy-plugin-syntaxhighlight/syntax-highlight.webc`. This also works with a tag name override via [`webc:is`](#webcis). Eleventy plugins can supply WebC components this way. See the [Syntax Highlighter plugin](/docs/plugins/syntaxhighlight/) (`4.2.0` or newer) for an example. -### `webc:if` +## Attributes, props and slots + +{% include "webc-attribute-guide.njk" %} -{% addedin "@11ty/webc@0.7.1" %} +### Attributes and `webc:root` + +Attributes on a host component are available inside the component definition. `webc:root` merges the element’s attributes onto the host component tag, and keeps that tag in the output even for an [HTML-only component](#html-only-components). WebC _merges_ the `class` and `style` attribute values from both. -Use `webc:if` to conditionally render elements. Accepts arbitrary JavaScript (and is async-friendly). Similar to dynamic attributes, this also has access to component attributes and properties. +{% codetitle "_components/my-component.webc" %} ```html -
This will render
-
This will not render
-
- If the helper promise resolves to a truthy value, this will render -
+ ``` -You can use `webc:type="js"` _(WebC v0.7.1+)_ to use JavaScript for more complex conditional logic (read more below). - -### `webc:elseif` and `webc:else` +{% codetitle "index.webc" %} -{% addedin "@11ty/webc@0.10.0" %} +```html + +``` -Adjacent siblings of `webc:if` can use `webc:elseif=""` and `webc:else` for additional conditional logic. +{% codetitle "_site/index.html", "Output example" %} ```html -
This will not render
- -
This will render
-
This will not render
+Hello possum. ``` -### `webc:for` Loops - -{% addedin "@11ty/webc@0.10.0" %} +**Note:** The `webc:root` element must be at the top level of the component definition. Nested inside another element, it has no effect. -Use `webc:for` to loop over data with HTML. It works with Objects and any [Iterable](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators#built-in_iterables) (String, Array, Map, Set, etc). +#### Override the host component tag -The syntax should feel similar to JavaScript’s `for` statement. +`webc:root="override"` replaces the host component tag with the element itself, with the attributes merged. -#### Arrays (or any other Iterable) +{% codetitle "_components/my-component.webc" %} ```html - -
+ +``` - -
+{% codetitle "index.webc" %} - -
-
+```html + +``` - -
+{% codetitle "_site/index.html", "Output example" %} + +```html + ``` -#### Objects +- {% addedin "@11ty/webc@0.9.0" %}Previously, this required `webc:root` and `webc:keep` together on an element. + +### Props (Properties) + +Any attribute prefixed with `@` becomes a prop: a server-only attribute that the component reads by name and that WebC removes from the output HTML. -Note the use of `in` instead of `of`. +{% codetitle "_components/story-card.webc" %} ```html - -
+
+

+

+
+``` - -
+{% codetitle "index.webc" %} - -
+```html + +``` - -
+{% codetitle "_site/index.html", "Output example" %} - -
-
+```html +
+

Top 10 Fashionable Possums

+

Possum Times

+
``` -#### Nesting `webc:for` +In the HTML specification, attribute names are lower-case. {% addedin "@11ty/webc@0.8.0" %}WebC converts attribute and prop names with dashes (i.e. `@author-name`) to camelCase for JavaScript (i.e. `authorName`), so `` is accessed within the component as `

`. More at [issue #71](https://github.com/11ty/webc/issues/71). -Loops can be nested but access to outer scope from the inner loop doesn't work currently. More at [issue #175](https://github.com/11ty/webc/issues/175). +### Dynamic attributes and properties -### Slots +A colon (`:`) prefix makes the value of an attribute or prop a JavaScript expression instead of a string. The expression has access to host component attributes, props, and page data. -Child content optionally precompiles using `` and `[slot]` too. This example is using an [HTML-only component](#html-only-components). +This example extends the [props example](#props-properties): the `title` prop and the `href` attribute now read from page data. -{% codetitle "page.webc" %} +{% codetitle "_components/story-card.webc" %} ```html - -This is the default slot +
+

+

+ Read more +
``` -{% codetitle "components/my-component.webc" %} +{% codetitle "top-ten.webc" %} ```html -

Fallback slot content

+--- +title: Top 10 Fashionable Possums +--- + ``` -Compiles to: +{% codetitle "_site/top-ten.html", "Output example" %} ```html -

Fallback slot content

-

This is the default slot

+
+

Top 10 Fashionable Possums

+

Possum Times

+ Read more +
``` -If your WebC component wants to _output_ a `` tag in the compiled markup (for use in client JavaScript), use the [`webc:keep` attribute](#webckeep) (e.g. ``). +- {% addedin "@11ty/webc@0.9.0" %}The `:@` prefix for dynamic props. +- WebC converts names with dashes to camelCase, as with [props](#props-properties). +- [`webc:bucket`](#asset-bucketing) is currently the only `webc:*` attribute that accepts a dynamic value. Follow [#143](https://github.com/11ty/webc/issues/143) and [#148](https://github.com/11ty/webc/issues/148) for more. -{% callout "info", "md" %}Per web component standard conventions, if your component file contains _no content markup_ (e.g. empty or only ` + +

This text will replace slot.

+ + +

This text is the default fallback.

``` -- {% addedin "@11ty/webc@0.9.0" %}Previously, the above used to be accomplished by using `webc:root` and `webc:keep` together on an element. +To output a `` element in the compiled markup (for use in client JavaScript), add the [`webc:keep` attribute](#webckeep) to it (e.g. ``). + +{% callout "info", "md" %}If your component file contains _no content markup_ (it is empty, or has only ` + + +

``` -This outputs: +{% codetitle "index.webc" %} ```html -Default slot + + ``` -and aggregates the following CSS to [the bundle](#asset-bundling): +{% codetitle "_site/index.html", "Output example" %} -```css -.wcl2xedjk { - color: blue; -} -.wcl2xedjk:defined { - color: rebeccapurple; -} +```html +

Hello Susan, do you enjoy being strong?

+

Hello Finn, do you enjoy dungeon crawling?

``` - +Works with `var`, `let`, `const`, `function`, and Array and Object [destructuring assignment](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment). Uses the [`node-retrieve-globals` package](https://github.com/zachleat/node-retrieve-globals/). -{% callout "info", "md" -%} -_**CSS bundling opinion alert**:_ Some folks recommend using Declarative Shadow DOM for component style encapsulation. This is a great method! It has 2 major drawbacks: +### `webc:type` -1. The progressive enhancement story requires [ubiquitous browser support](https://caniuse.com/declarative-shadow-dom) before using it for content in the critical rendering path. -2. It requires ` + +

Hello possum.

+``` - function alwaysBlue() { - return "blue"; +{% codetitle "_site/index.html", "Output example" %} + +```html + + + + WebC Example + + + + +

Hello possum.

+ + +``` + +The same component with the superseded `webc:type="render"`: + +{% codetitle "_components/possum-theme.webc" %} + +```html + +``` + +Notes: + +- To generate scoped CSS with JavaScript, add [`webc:scoped`](#webcscoped) to the element as well (` ``` -Works with `var`, `let`, `const`, `function`, `Array`, and `Object` [destructuring assignment](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment). +{% codetitle "index.webc" %} -- Uses the [`node-retrieve-globals` package](https://github.com/zachleat/node-retrieve-globals/). +```html +Susan Possum in a purple jacket +``` -### Using Template Syntax to Generate Content +{% codetitle "_site/index.html", "Output example" %} -The [Custom Transforms feature](https://github.com/11ty/webc#custom-transforms) (e.g. `webc:type`) in the Eleventy WebC plugin has been wired up to the [Eleventy Render plugin](/docs/plugins/render/) to allow you to use existing Eleventy template syntax inside of WebC. +```html +Susan Possum in a purple jacket +``` -{% callout "info", "md" %}**Note:** The `webc:type="11ty"` feature is exclusive to the **Eleventy** WebC plugin and is not available in non-Eleventy independent WebC.{% endcallout %} +#### `webc:type="11ty"` and `11ty:type` -Use `webc:type="11ty"` with the `11ty:type` attribute to specify a [valid template syntax](/docs/plugins/render/#rendertemplate-paired-shortcode). +Renders the content with the Eleventy template syntax, or comma-separated chain of syntaxes, named in `11ty:type`. The Eleventy WebC plugin wires the WebC [custom transforms feature](https://github.com/11ty/webc#custom-transforms) to the [Eleventy Render plugin](/docs/plugins/render/) to make this possible. -{% codetitle "my-page.webc" %} +{% callout "info", "md" %}**Note:** The `webc:type="11ty"` feature is exclusive to the **Eleventy** WebC plugin and is not available in standalone WebC.{% endcallout %} + +`11ty:type` accepts any [valid template syntax](/docs/plugins/render/#rendertemplate-paired-shortcode). + +{% codetitle "index.webc" %} {% raw %} ```liquid --- -frontmatterdata: "Hello from Front Matter" +title: Top 10 Fashionable Possums --- ``` {% endraw %} -- You have full access to the data cascade here (note `frontmatterdata` is [set in front matter](#front-matter) above). -- {% addedin "@11ty/webc@0.5.0" %}Content returned from custom transforms on `