All files / src/internal/client/dom/blocks html.js

100% Statements 79/79
100% Branches 24/24
100% Functions 2/2
100% Lines 73/73

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 742x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 91x 91x 91x 157x 157x 157x 157x 157x 91x 91x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 157x 157x 43x 43x 114x 114x 157x 100x 114x 114x 114x 114x 114x 114x 157x 15x 15x 114x 143x 101x 101x 101x 101x 13x 13x 13x 13x 157x 1x 5x 5x 124x 12x 12x 13x 13x 13x  
import { derived } from '../../reactivity/deriveds.js';
import { render_effect } from '../../reactivity/effects.js';
import { get } from '../../runtime.js';
import { hydrate_start, hydrating } from '../hydration.js';
import { remove_nodes } from '../operations.js';
import { create_fragment_from_html } from '../reconciler.js';
 
/**
 * @param {Element | Text | Comment} anchor
 * @param {() => string} get_value
 * @param {boolean} svg
 * @param {boolean} mathml
 * @returns {void}
 */
export function html(anchor, get_value, svg, mathml) {
	let value = derived(get_value);
 
	render_effect(() => {
		var [start, end] = html_to_dom(anchor, get(value), svg, mathml);
 
		return () => {
			remove_nodes(start, end);
		};
	});
}
 
/**
 * Creates the content for a `@html` tag from its string value,
 * inserts it before the target anchor and returns the new nodes.
 * @template V
 * @param {Element | Text | Comment} target
 * @param {V} value
 * @param {boolean} svg
 * @param {boolean} mathml
 * @returns {[import('#client').TemplateNode, import('#client').TemplateNode]}
 */
function html_to_dom(target, value, svg, mathml) {
	if (hydrating) {
		return [hydrate_start, hydrate_start];
	}
 
	var html = value + '';
	if (svg) html = `<svg>${html}</svg>`;
	else if (mathml) html = `<math>${html}</math>`;
 
	// Don't use create_fragment_with_script_from_html here because that would mean script tags are executed.
	// @html is basically `.innerHTML = ...` and that doesn't execute scripts either due to security reasons.
	/** @type {DocumentFragment | Element} */
	var node = create_fragment_from_html(html);
 
	if (svg || mathml) {
		node = /** @type {Element} */ (node.firstChild);
	}
 
	if (node.childNodes.length === 1) {
		var child = /** @type {Text | Element | Comment} */ (node.firstChild);
		target.before(child);
		return [child, child];
	}
 
	var first = /** @type {import('#client').TemplateNode} */ (node.firstChild);
	var last = /** @type {import('#client').TemplateNode} */ (node.lastChild);
 
	if (svg || mathml) {
		while (node.firstChild) {
			target.before(node.firstChild);
		}
	} else {
		target.before(node);
	}
 
	return [first, last];
}