@shopify/react-html
Version:
A component to render your React app with no static HTML
107 lines (102 loc) • 2.6 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var utilities = require('./utilities.js');
const EFFECT_ID = Symbol('html');
class HtmlManager {
constructor() {
this.effect = {
id: EFFECT_ID,
betweenEachPass: () => this.reset()
};
this.serializations = utilities.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);
}
}
}
exports.EFFECT_ID = EFFECT_ID;
exports.HtmlManager = HtmlManager;