@nent/core
Version:
205 lines (204 loc) • 6.52 kB
JavaScript
/*!
* NENT 2022
*/
import { Component, Element, h, Host, Prop } from '@stencil/core';
import { commonState, CommonStateSubscriber, debugIf, warn, } from '../../services/common';
import { replaceHtmlInElement } from '../../services/content/elements';
import { resolveRemoteContent } from '../../services/content/remote';
import { resolveChildElementXAttributes } from '../../services/data/elements';
import { DATA_EVENTS } from '../../services/data/interfaces';
import { filterData } from '../../services/data/jsonata.worker';
import { ROUTE_EVENTS } from '../n-views/services/interfaces';
import { routingState } from '../n-views/services/state';
/**
* This element fetches remote HTML and renders it safely and directly
* into the page when and where you tell it too, as soon as it renders.
*
* @system content
* @extension data
* @extension elements
*/
export class ContentInclude {
constructor() {
this.contentClass = 'remote-content';
this.contentElement = null;
/**
* Cross Origin Mode
*/
this.mode = 'cors';
/**
* Before rendering HTML, replace any data-tokens with their
* resolved values. This also commands this element to
* re-render it's HTML for data-changes. This can affect
* performance.
*/
this.resolveTokens = false;
/**
* If set, disables auto-rendering of this instance.
* To fetch the contents change to false or remove
* attribute.
*/
this.deferLoad = false;
}
componentWillLoad() {
if (this.resolveTokens || this.when != undefined) {
this.dataSubscription = new CommonStateSubscriber(this, 'dataEnabled', DATA_EVENTS.DataChanged);
this.routeSubscription = new CommonStateSubscriber(this, 'routingEnabled', ROUTE_EVENTS.RouteChanged);
}
}
async componentWillRender() {
let shouldRender = !this.deferLoad;
if (commonState.dataEnabled && this.when) {
const { evaluatePredicate } = await import('../../services/data/expressions');
shouldRender = await evaluatePredicate(this.when);
}
if (shouldRender)
this.contentElement = this.src
? await this.resolveContentElement()
: null;
else if (this.resolveTokens)
this.contentElement = null;
}
async resolveContentElement() {
var _a;
try {
let content = await resolveRemoteContent(window, this.src, this.mode, this.resolveTokens);
if (content && this.json) {
debugIf(commonState.debug, `n-content-include: filtering: ${this.json}`);
const data = JSON.parse(content);
content = await filterData(this.json, data);
}
if (content == null)
return null;
const div = document.createElement('div');
div.innerHTML = content;
div.className = this.contentClass;
if (commonState.elementsEnabled)
resolveChildElementXAttributes(div);
(_a = routingState.router) === null || _a === void 0 ? void 0 : _a.captureInnerLinks(div);
return div;
}
catch (_b) {
warn(`n-content: unable to retrieve from ${this.src}`);
return null;
}
}
render() {
replaceHtmlInElement(this.el, `.${this.contentClass}`, this.contentElement);
return h(Host, { hidden: this.contentElement == null });
}
disconnectedCallback() {
var _a, _b;
(_a = this.dataSubscription) === null || _a === void 0 ? void 0 : _a.destroy();
(_b = this.routeSubscription) === null || _b === void 0 ? void 0 : _b.destroy();
}
static get is() { return "n-content-include"; }
static get properties() { return {
"src": {
"type": "string",
"mutable": false,
"complexType": {
"original": "string",
"resolved": "string",
"references": {}
},
"required": true,
"optional": false,
"docs": {
"tags": [],
"text": "Remote Template URL"
},
"attribute": "src",
"reflect": false
},
"mode": {
"type": "string",
"mutable": false,
"complexType": {
"original": "'cors' | 'navigate' | 'no-cors' | 'same-origin'",
"resolved": "\"cors\" | \"navigate\" | \"no-cors\" | \"same-origin\"",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Cross Origin Mode"
},
"attribute": "mode",
"reflect": false,
"defaultValue": "'cors'"
},
"resolveTokens": {
"type": "boolean",
"mutable": false,
"complexType": {
"original": "boolean",
"resolved": "boolean",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "Before rendering HTML, replace any data-tokens with their\nresolved values. This also commands this element to\nre-render it's HTML for data-changes. This can affect\nperformance."
},
"attribute": "resolve-tokens",
"reflect": false,
"defaultValue": "false"
},
"deferLoad": {
"type": "boolean",
"mutable": true,
"complexType": {
"original": "boolean",
"resolved": "boolean",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "If set, disables auto-rendering of this instance.\nTo fetch the contents change to false or remove\nattribute."
},
"attribute": "defer-load",
"reflect": false,
"defaultValue": "false"
},
"when": {
"type": "string",
"mutable": true,
"complexType": {
"original": "string",
"resolved": "string | undefined",
"references": {}
},
"required": false,
"optional": true,
"docs": {
"tags": [],
"text": "A data-token predicate to advise this element when\nto render (useful if used in a dynamic route or if\ntokens are used in the 'src' attribute)"
},
"attribute": "when",
"reflect": false
},
"json": {
"type": "string",
"mutable": false,
"complexType": {
"original": "string",
"resolved": "string | undefined",
"references": {}
},
"required": false,
"optional": true,
"docs": {
"tags": [],
"text": "The JSONata expression to select the HTML from a json response.\nsee <https://try.jsonata.org> for more info."
},
"attribute": "json",
"reflect": false
}
}; }
static get elementRef() { return "el"; }
}