by Before Semicolon

Custom attributes

Custom attributes must all be a class that may extend the CustomAttribute class. This class must also contain a render method which is called with the value of the attribute and the Element instance.

An optional method of your custom attribute is the process method which is called with the value of the attribute which you can tweak into a different string to be bind or executed before the rendering.

The below WrapWith custom attribute will receive a comma separated name of tags and wrap the tag it is placed on with those.

const {CustomAttribute} = request('@beforesemicolon/html-plus');

class WrapWith extends CustomAttribute {
	process(value) {
		this.tags = value.split(',');

		return value;
	}

	render(value, node) {
		return this.tags.reduce((content, tag) => {
			return `<${tag}>${content}<${tag}>`;
		}, node.outerHTML));
	}
}

Attributes are processed, bind and executed in that order before rendering. These steps are ignored if you don't provide the process method or set the execute or bind booleans to TRUE.

Register CustomAttribute

With the class, we register it with the engine setup.

const {engine} = require('@beforesemicolon/html-plus');
const {WrapWith} = require('./WrapWith.js');

const app = express();

engine(app, path.resolve(__dirname, './pages'), {
	customAttributes: [WrapWith]
});

Use CustomAttribute

We can now use it it the template as such.

<p #wrap-with="div">wrapped</p>
<!-- becomes: <div><p>wrapped</p></div> -->
<p #wrap-with="section,div">wrapped</p>
<!-- becomes: <section><div><p>wrapped</p></div></section> -->

Attributes dont necessary need to render anything. Your attribute can simply change something about the node provided like setting attribute or update the node context.

Custom Tag Custom Attributes

Your custom tags can also contain specific attributes. These attributes won't be marked with hash symbol(#).

You may define them as a static property on a class or function.

const {CustomAttribute} = request('@beforesemicolon/html-plus');

class SearchField {
	render() {
		return `
			<label class="search-field" aria-label="search field">
				<input type="search" name="search" placeholder="Search...">
			</label>
		`;
	}

	static get customAttributes() {
		return {
			value: new CustomAttribute('value', '', false, true)
		};
	}
}

If you use a function it would look like this:

function SearchField {
	return () => `
		<label class="search-field" aria-label="search field">
			<input type="search" name="search" placeholder="Search...">
		</label>
	`;
}

SearchField.customAttributes = {
	value: new CustomAttribute('value', '', false, true)
}

These custom attributes can be simple objects as well. Not necessary a CustomAttribute instance unless you want to calculate something more complex.

class SearchField {
	render() {
		return `
			<label class="search-field" aria-label="search field">
				<input type="search" name="search" placeholder="Search...">
			</label>
		`;
	}

	static get customAttributes() {
		return {
			value: {execute: true}
		}
	}
}

Please refer to the Element object documentation for a full list of methods and properties.