All files / src liquid.ts

70.83% Statements 17/24
20% Branches 1/5
66.66% Functions 6/9
72.72% Lines 16/22

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 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101  1x   21x                                                                     1x     19x   19x           19x 58x   58x                                   1x     1x 1x 1x 1x 1x                       1x             1x        
import { DefaultState } from "./utils/state"
import { Liquid } from "liquidjs"
 
export { defaultLiquidTemplate } from "./defaults/_generated"
 
/**
 * Render a liquid template into a container
 *
 * @param template Liquid template
 * @returns Render function
 * @group Autocomplete
 * @category Liquid
 * @example
 * ```js
 * import { fromLiquidTemplate } from "@nosto/autocomplete/liquid";
 *
 * const render = fromLiquidTemplate(`
 *   <div>
 *      <h1>{{title}}</h1>
 *    <ul>
 *    {% for product in products %}
 *     <li>{{product.name}}</li>
 *  {% endfor %}
 *  </ul>
 *  </div>
 *  `);
 *
 * render(document.getElementById("container"), {
 *   title: "My Title",
 *   products: [
 *     { name: "Product 1" },
 *     { name: "Product 2" },
 *     { name: "Product 3" }
 *   ]
 * });
 
 * ```
 */
export function fromLiquidTemplate<State extends object = DefaultState>(
    template: string
): (container: HTMLElement, state: State) => PromiseLike<void> {
    const instance = Liquid ? new Liquid() : undefined
 
    Iif (instance === undefined) {
        throw new Error(
            "Liquid is not defined. Please include the Liquid library in your page."
        )
    }
 
    return (container, state) => {
        container.innerHTML = instance.parseAndRenderSync(template, state)
 
        return Promise.resolve(undefined)
    }
}
 
/**
 * Load a remote liquid template and render it into a container
 *
 * @param url Remote Liquid template URL
 * @returns Render function
 * @group Autocomplete
 * @category Liquid
 * @example
 * ```js
 * import { fromRemoteLiquidTemplate } from "@nosto/autocomplete/liquid";
 *
 * const render = fromRemoteLiquidTemplate("https://example.com/template.liquid");
 * ```
 */
export function fromRemoteLiquidTemplate<State extends object = DefaultState>(
    url: string
): (container: HTMLElement, state: State) => PromiseLike<void> {
    return (container, state) => {
        return new Promise((resolve, reject) => {
            const xhr = new XMLHttpRequest()
            xhr.open("GET", url)
            xhr.onload = async () => {
                if (xhr.status === 200) {
                    await fromLiquidTemplate(xhr.responseText)(container, state)
                    resolve(undefined)
                } else {
                    reject(
                        new Error(
                            `Failed to fetch remote liquid template: ${xhr.statusText}`
                        )
                    )
                }
            }
            xhr.onerror = () => {
                reject(
                    new Error(
                        `Failed to fetch remote liquid template: ${xhr.statusText}`
                    )
                )
            }
            xhr.send()
        })
    }
}