function escape_html(str, is_attr) {
	const dict = is_attr ? escape_html_attr_dict : escape_html_dict;
	const escaped_str = str.replace(is_attr ? escape_html_attr_regex : escape_html_regex, (match) => {
		if (match.length === 2) {
			// valid surrogate pair
			return match;
		}

		return dict[match] ?? `&#${match.charCodeAt(0)};`;
	});

	return escaped_str;
}
Escapes unpaired surrogates (which are allowed in js strings but invalid in HTML) and
escapes characters that are special.

@param {string} str
@param {boolean} [is_attr]
@returns {string} escaped string
@example const html = `<tag data-value="${escape_html('value', true)}">...</tag>`;