UNPKG

@shopify/react-html

Version:

A component to render your React app with no static HTML

102 lines (99 loc) 2.51 kB
import { getSerializationsFromDocument } from './utilities.mjs'; const EFFECT_ID = Symbol('html'); class HtmlManager { constructor() { this.effect = { id: EFFECT_ID, betweenEachPass: () => this.reset() }; this.serializations = getSerializationsFromDocument(); this.titles = []; this.metas = []; this.links = []; this.inlineStyles = []; this.htmlAttributes = []; this.bodyAttributes = []; this.subscriptions = new Set(); } get state() { const lastTitle = this.titles[this.titles.length - 1]; return { title: lastTitle && lastTitle.title, metas: this.metas, links: this.links, inlineStyles: this.inlineStyles, bodyAttributes: Object.assign({}, ...this.bodyAttributes), htmlAttributes: Object.assign({}, ...this.htmlAttributes) }; } reset({ includeSerializations = false } = {}) { this.titles = []; this.metas = []; this.links = []; this.inlineStyles = []; this.subscriptions.clear(); if (includeSerializations) { this.serializations.clear(); } } subscribe(subscription) { this.subscriptions.add(subscription); return () => { this.subscriptions.delete(subscription); }; } addTitle(title) { return this.addDescriptor({ title }, this.titles); } addMeta(meta) { return this.addDescriptor(meta, this.metas); } addLink(link) { return this.addDescriptor(link, this.links); } addInlineStyle(inlineStyle) { return this.addDescriptor(inlineStyle, this.inlineStyles); } addHtmlAttributes(attributes) { return this.addDescriptor(attributes, this.htmlAttributes); } addBodyAttributes(attributes) { return this.addDescriptor(attributes, this.bodyAttributes); } setSerialization(id, data) { this.serializations.set(id, data); } getSerialization(id) { return this.serializations.get(id); } extract() { return { ...this.state, serializations: [...this.serializations.entries()].map(([id, data]) => ({ id, data })) }; } addDescriptor(item, list) { list.push(item); this.updateSubscriptions(); return () => { const index = list.indexOf(item); if (index >= 0) { list.splice(index, 1); this.updateSubscriptions(); } }; } updateSubscriptions() { for (const subscription of this.subscriptions) { subscription(this.state); } } } export { EFFECT_ID, HtmlManager };