@addasoft/skeleton-component-generator
Version:
Create skeleton web components using Lit based on given Custom Elements Manifest
291 lines (254 loc) • 8.67 kB
Markdown
# /skeleton-component-generator
> Create skeleton web components using Lit based on given Custom Elements Manifest.
## Install
```bash
npm install /skeleton-component-generator
```
Project has a dependency `prettier`.
## Usage
### Specify input and output
`skeleton-component-generator --cem=[path to cem] --gen=[path to output generated files]`.
### Speficy custom templates
Added in `1.1.0`. Ability to override the template(s) that are used to generate parts of the skeleton class. Use the parameter `--templates <path>` to point to a specific directory containing the overrides.
If no override for a template is found in the given path the internal default will be used instead. Templates need to include a `render()` function that returns the output of the template. The `render()` function accepts parameters as defined in the `customElement` template. By default the parameter points to the object with the same name in CEM. So for example the `slots` template uses the `slots` object in CEM as the parameter.
#### Example
```javascript
export const render = slots => {
return `
${
slots
? `
<h2>Slots</h2>
<ul>
${slots
.map(slot => {
return `<li>Slot ${slot.name} (${slot.description}):
<slot name="${slot.name}"></slot>
</li>\n`;
})
.join('')}
</ul>
`
: ``
}
`;
};
```
If you override the `customElement` template (the root template) you need to include the list of available templates. By overriding the `customElement` template you can also use different Custom Elements libraries instead of Lit, you are in full control.
#### Example
```javascript
export const render = (
{ description, name, tagName, cssProperties, attributes, events, slots },
{ classComment, cssPropertiesMembers, attributeMembers, eventsMembers, nameRenderer, descriptionRenderer, cssPropertiesRenderer, attributesRenderer, eventsRenderer, slotRenderer },
) => {
return `
import { html, css, LitElement } from 'lit';
import { customElement, property } from 'lit/decorators.js';
${classComment({ cssProperties, description, slots })}
export class ${name} extends LitElement {
${cssPropertiesMembers(cssProperties)}
${attributeMembers(attributes)}
${eventsMembers(events)}
render() {
return html\`
${nameRenderer(name, tagName)}
${descriptionRenderer(description)}
${cssPropertiesRenderer(cssProperties)}
${attributesRenderer(attributes)}
${eventsRenderer(events)}
${slotRenderer(slots)}
\`
}
}
`;
};
```
### Available templates
- customElement - base template. accepts <declaration> and <templates>
- attributeMembers - template to render the attributes as a list. accepts <attributes>
- attributesRenderer - template for showing the attributes. accepts <attributes>
- classComment - template to render comments at the top of the class. accepts <declaration>
- cssPropertiesMembers - template to render the CSS properties. accepts <cssProperties>
- cssPropertiesRenderer - template to render the CSS properties as a list. accepts <cssProperties>
- descriptionRenderer - template to render the description. accepts <description>
- eventsMembers - template to create a function that triggers the event. accepts <events>
- eventsRenderer - template to render buttons to trigger the event functions. accepts <events>
- nameRenderer - template to render the class name and custom element name. accepts <name> and <tagName>
- slotRenderer - template to render a slot. accepts <slots>
## Example
### CEM
```json
{
"schemaVersion": "1.0.0",
"readme": "",
"modules": [
{
"kind": "javascript-module",
"path": "components/hello-world.ts",
"declarations": [
{
"kind": "class",
"description": "Hello generated world! Click for a gift or a bomb",
"name": "HelloWorld",
"cssProperties": [
{
"description": "Controls the text colour",
"name": "--text-color",
"default": "black"
},
{
"description": "Controls the background colour",
"name": "--background-color",
"default": "red"
}
],
"members": [
{
"kind": "field",
"name": "type",
"type": {
"text": "string"
},
"default": "\"wonderful\"",
"description": "What type is the world today?",
"attribute": "type"
},
{
"kind": "method",
"name": "eventFunctionGift",
"privacy": "private",
"description": "Write function that dispatches the event Gift"
},
{
"kind": "method",
"name": "eventFunctionBomb",
"privacy": "private",
"description": "Write function that dispatches the event Bomb"
}
],
"events": [
{
"name": "Gift",
"type": {
"text": "Event"
},
"description": "gift - I'm bearing a gift"
},
{
"name": "Bomb",
"type": {
"text": "Event"
},
"description": "bomb - This was a mistake..."
}
],
"attributes": [
{
"name": "type",
"type": {
"text": "string"
},
"default": "\"wonderful\"",
"description": "What type is the world today?",
"fieldName": "type"
}
],
"superclass": {
"name": "LitElement",
"package": "lit"
},
"tagName": "hello-world",
"customElement": true
}
],
"exports": [
{
"kind": "js",
"name": "HelloWorld",
"declaration": {
"name": "HelloWorld",
"module": "components/hello-world.ts"
}
},
{
"kind": "custom-element-definition",
"name": "hello-world",
"declaration": {
"name": "HelloWorld",
"module": "components/hello-world.ts"
}
}
]
}
]
}
```
### Generated lit element
```typescript
import { html, css, LitElement } from "lit"
import { customElement, property } from "lit/decorators.js"
/**
* Hello generated world! Click for a gift or a bomb
*
* @cssprop [--text-color=black] - Controls the text colour
* @cssprop [--background-color=red] - Controls the background colour
*/
export class HelloWorld extends LitElement {
static styles = css`
h1,
h2 {
margin: 0;
}
ul {
margin: 0;
}
:host {
--text-color: var(--text-color, black);
--background-color: var(--background-color, red);
}
`
/** What type is the world today? */
type = "wonderful"
/** Write function that dispatches the event Gift */
private eventFunctionGift() {
/** @type {Event} gift - I'm bearing a gift */
this.dispatchEvent(new Event("Gift"))
}
/** Write function that dispatches the event Bomb */
private eventFunctionBomb() {
/** @type {Event} bomb - This was a mistake... */
this.dispatchEvent(new Event("Bomb"))
}
render() {
return html`
<h1>HelloWorld - <hello-world></hello-world></h1>
<p>Hello generated world! Click for a gift or a bomb</p>
<h2>CSS variables</h2>
<ul>
<li>
<span style="color: var(--text-color, black)"
>current text-color: --text-color default value: black</span
>
</li>
<li>
<span style="color: var(--background-color, red)"
>current text-color: --background-color default value: red</span
>
</li>
</ul>
<h2>Attributes</h2>
<ul>
<li>type = ${this.type}</li>
</ul>
<h2>Events</h2>
<ul>
<li><button =${this.eventFunctionGift}>trigger Gift</button></li>
<li><button =${this.eventFunctionBomb}>trigger Bomb</button></li>
</ul>
`
}
}
```