@staszek998/v-html
Version:
Simple Vue component capable of rendering the passed-in HTML string without wrapping it within a redundant HTML tag.
88 lines • 3 kB
JavaScript
;
/*******************************************************************************
* @copyright 2021 IDEALIGN Stanisław Gregor
******************************************************************************/
Object.defineProperty(exports, "__esModule", { value: true });
exports.VHTML = void 0;
const tslib_1 = require("tslib");
const vue_1 = tslib_1.__importDefault(require("vue"));
/**
* Extracts the contents from the passed-in `<slot>`.
*
* @param slot - The `<slot>` which contents we wont to resolve.
*
* @author Stanisław Gregor, Vitim.us
*
* @see https://stackoverflow.com/a/52749314/11869579
*/
const getSlotContents = (slot) => {
if (typeof slot === 'undefined' || !Array.isArray(slot) || slot.length === 0) {
return '';
}
/**
* The contents from all the VNodes in the `<slot>`.
*/
const textContents = slot.map(vnode => {
if (typeof vnode.text === 'string') {
return vnode.text;
}
if (typeof vnode.elm !== 'undefined' && typeof vnode.elm.textContent === 'string') {
return vnode.elm.textContent;
}
return '';
});
return textContents.join('');
};
/**
* Simple functional component that accepts HTML string and renders it as-is.
* Why? Because `v-html` directive is not always an option 😉
*
* @author Stanisław Gregor, Thorsten Lünborg
*
* @see https://forum.vuejs.org/t/raw-html-without-a-parent-element-via-v-html/87160
* @see https://jsfiddle.net/Linusborg/mfqjk5hm/
*/
exports.VHTML = vue_1.default.extend({
functional: true,
name: 'VHTML',
props: {
/**
* The HTML string to render.
*/
html: { type: String, required: false }
},
render(h, ctx) {
/**
* Determines whether the `[html]` prop has been specified.
*/
const hasHtmlProp = typeof ctx.props.html === 'string';
/**
* Determines whether the default `<slot>` has been populated.
*/
const hasDefaultSlot = typeof ctx.slots().default !== 'undefined' &&
Array.isArray(ctx.slots().default) &&
ctx.slots().default.length > 0;
/**
* The HTML that is to be rendered.
*/
let content;
if (hasHtmlProp && hasDefaultSlot) {
console.warn('VHTML: Received both [html] prop AND default <slot> - returning only the HTML from the <slot>.');
content = '';
}
else if (hasHtmlProp) {
content = ctx.props.html;
}
else if (hasDefaultSlot) {
content = getSlotContents(ctx.slots().default);
}
else {
console.warn('VHTML: Expected to find the HTML string in [html] prop OR inside the default <slot>, but none was present!');
content = '';
}
return new vue_1.default({
template: `<div>${content}</div>`
}).$mount()._vnode.children;
}
});
//# sourceMappingURL=VHTML.js.map