UNPKG

@nent/core

Version:

Functional elements to add routing, data-binding, dynamic HTML, declarative actions, audio, video, and so much more. Supercharge static HTML files into web apps without script or builds.

205 lines (204 loc) 6.52 kB
/*! * 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"; } }