|
| 1 | +// Copyright 2018-2026 the Deno authors. MIT license. |
| 2 | +// This module is browser compatible. |
| 3 | + |
| 4 | +/** |
| 5 | + * A template literal tag function for creating HTML strings with interpolated |
| 6 | + * values. |
| 7 | + * |
| 8 | + * @experimental **UNSTABLE**: New API, yet to be vetted. |
| 9 | + * |
| 10 | + * This function processes template literals and concatenates them with |
| 11 | + * interpolated values. Values are inserted as-is without any HTML escaping or |
| 12 | + * sanitization. Undefined values are treated as empty strings. |
| 13 | + * |
| 14 | + * > [!WARNING] |
| 15 | + * > **Security Warning**: This function does NOT escape HTML. When |
| 16 | + * > interpolating user-provided data, you must manually escape it to prevent |
| 17 | + * > XSS (Cross-Site Scripting) attacks. Only use this function with trusted |
| 18 | + * > data or data that has been properly sanitized. Use |
| 19 | + * > {@linkcode https://jsr.io/@std/html/doc/~/escape | escape()} for escaping. |
| 20 | + * |
| 21 | + * @param strings The template string array containing the static parts of the template |
| 22 | + * @param values The values to be interpolated into the template |
| 23 | + * @returns The resulting HTML string with interpolated values |
| 24 | + * |
| 25 | + * @example Usage with trusted content |
| 26 | + * ```ts |
| 27 | + * import { html } from "@std/html/unstable-html"; |
| 28 | + * import { assertEquals } from "@std/assert/equals"; |
| 29 | + * |
| 30 | + * const name = "Alice"; |
| 31 | + * const color = "blue"; |
| 32 | + * const htmlContent = html` |
| 33 | + * <div> |
| 34 | + * <h1>Hello, ${name}!</h1> |
| 35 | + * <p style="color: ${color};">Welcome to our site.</p> |
| 36 | + * </div> |
| 37 | + * `; |
| 38 | + * |
| 39 | + * assertEquals(htmlContent, ` |
| 40 | + * <div> |
| 41 | + * <h1>Hello, Alice!</h1> |
| 42 | + * <p style="color: blue;">Welcome to our site.</p> |
| 43 | + * </div> |
| 44 | + * `); |
| 45 | + * ``` |
| 46 | + * |
| 47 | + * @example Usage with untrusted content that needs to be escaped |
| 48 | + * ```ts |
| 49 | + * import { html } from "@std/html/unstable-html"; |
| 50 | + * import { assertEquals } from "@std/assert/equals"; |
| 51 | + * import { escape } from "@std/html/entities"; |
| 52 | + * |
| 53 | + * // WARNING: This is vulnerable to XSS attacks! |
| 54 | + * const userInput = '<script>alert("XSS")</script>'; |
| 55 | + * const unsafeHtml = html`<div>${userInput}</div>`; |
| 56 | + * |
| 57 | + * const safeHtml = html`<div>${escape(userInput)}</div>`; |
| 58 | + * |
| 59 | + * assertEquals(unsafeHtml, '<div><script>alert("XSS")</script></div>'); |
| 60 | + * assertEquals(safeHtml, "<div><script>alert("XSS")</script></div>"); |
| 61 | + * ``` |
| 62 | + */ |
| 63 | +export function html( |
| 64 | + strings: TemplateStringsArray, |
| 65 | + ...values: unknown[] |
| 66 | +): string { |
| 67 | + return strings.reduce( |
| 68 | + (result, str, i) => result + str + (values[i] ?? ""), |
| 69 | + "", |
| 70 | + ); |
| 71 | +} |
0 commit comments