|
|
|
@ -1,5 +1,5 @@
|
|
|
|
|
import { derived } from '../../reactivity/deriveds.js';
|
|
|
|
|
import { render_effect } from '../../reactivity/effects.js';
|
|
|
|
|
import { block, branch, destroy_effect, render_effect } from '../../reactivity/effects.js';
|
|
|
|
|
import { get } from '../../runtime.js';
|
|
|
|
|
import { is_array } from '../../utils.js';
|
|
|
|
|
import { hydrate_nodes, hydrating } from '../hydration.js';
|
|
|
|
@ -14,22 +14,53 @@ import { assign_nodes } from '../template.js';
|
|
|
|
|
* @returns {void}
|
|
|
|
|
*/
|
|
|
|
|
export function html(anchor, get_value, svg, mathml) {
|
|
|
|
|
let value = derived(get_value);
|
|
|
|
|
var value = '';
|
|
|
|
|
|
|
|
|
|
render_effect(() => {
|
|
|
|
|
var dom = html_to_dom(anchor, get(value), svg, mathml);
|
|
|
|
|
/** @type {import('#client').Effect | null} */
|
|
|
|
|
var effect;
|
|
|
|
|
|
|
|
|
|
if (dom) {
|
|
|
|
|
if (is_array(dom)) {
|
|
|
|
|
assign_nodes(dom[0], dom[dom.length - 1]);
|
|
|
|
|
} else {
|
|
|
|
|
assign_nodes(dom, dom);
|
|
|
|
|
block(anchor, 0, () => {
|
|
|
|
|
if (value === (value = get_value())) return;
|
|
|
|
|
|
|
|
|
|
if (effect) {
|
|
|
|
|
destroy_effect(effect);
|
|
|
|
|
effect = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return () => {
|
|
|
|
|
remove(dom);
|
|
|
|
|
};
|
|
|
|
|
if (value === '') return;
|
|
|
|
|
|
|
|
|
|
effect = branch(() => {
|
|
|
|
|
if (hydrating) {
|
|
|
|
|
assign_nodes(hydrate_nodes[0], hydrate_nodes[hydrate_nodes.length - 1]);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assign_nodes(
|
|
|
|
|
/** @type {import('#client').TemplateNode} */ (node.firstChild),
|
|
|
|
|
/** @type {import('#client').TemplateNode} */ (node.lastChild)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (svg || mathml) {
|
|
|
|
|
while (node.firstChild) {
|
|
|
|
|
anchor.before(node.firstChild);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
anchor.before(node);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -37,13 +68,13 @@ export function html(anchor, get_value, svg, mathml) {
|
|
|
|
|
* 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 {Element | Text | Comment} anchor
|
|
|
|
|
* @param {V} value
|
|
|
|
|
* @param {boolean} svg
|
|
|
|
|
* @param {boolean} mathml
|
|
|
|
|
* @returns {Element | Comment | (Element | Comment | Text)[]}
|
|
|
|
|
*/
|
|
|
|
|
function html_to_dom(target, value, svg, mathml) {
|
|
|
|
|
function html_to_dom(anchor, value, svg, mathml) {
|
|
|
|
|
if (hydrating) return hydrate_nodes;
|
|
|
|
|
|
|
|
|
|
var html = value + '';
|
|
|
|
@ -61,7 +92,7 @@ function html_to_dom(target, value, svg, mathml) {
|
|
|
|
|
|
|
|
|
|
if (node.childNodes.length === 1) {
|
|
|
|
|
var child = /** @type {Text | Element | Comment} */ (node.firstChild);
|
|
|
|
|
target.before(child);
|
|
|
|
|
anchor.before(child);
|
|
|
|
|
return child;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -69,10 +100,10 @@ function html_to_dom(target, value, svg, mathml) {
|
|
|
|
|
|
|
|
|
|
if (svg || mathml) {
|
|
|
|
|
while (node.firstChild) {
|
|
|
|
|
target.before(node.firstChild);
|
|
|
|
|
anchor.before(node.firstChild);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
target.before(node);
|
|
|
|
|
anchor.before(node);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nodes;
|
|
|
|
|