Skip to content
This repository was archived by the owner on Jan 25, 2024. It is now read-only.

Commit 7cb0a82

Browse files
author
ross-martin
committedDec 13, 2018
Production build
1 parent a455998 commit 7cb0a82

File tree

2 files changed

+919
-1
lines changed

2 files changed

+919
-1
lines changed
 

‎.gitignore

-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,5 @@
33
.idea
44
coverage
55
es
6-
lib
76
node_modules
87
npm-debug.log

‎lib/Helmet.js

+919
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,919 @@
1+
'use strict';
2+
3+
Object.defineProperty(exports, '__esModule', { value: true });
4+
5+
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
6+
7+
var PropTypes = _interopDefault(require('prop-types'));
8+
var withSideEffect = _interopDefault(require('react-side-effect'));
9+
var isEqual = _interopDefault(require('react-fast-compare'));
10+
var React = _interopDefault(require('react'));
11+
var objectAssign = _interopDefault(require('object-assign'));
12+
13+
var ATTRIBUTE_NAMES = {
14+
BODY: "bodyAttributes",
15+
HTML: "htmlAttributes",
16+
TITLE: "titleAttributes"
17+
};
18+
19+
var TAG_NAMES = {
20+
BASE: "base",
21+
BODY: "body",
22+
HEAD: "head",
23+
HTML: "html",
24+
LINK: "link",
25+
META: "meta",
26+
NOSCRIPT: "noscript",
27+
SCRIPT: "script",
28+
STYLE: "style",
29+
TITLE: "title"
30+
};
31+
32+
var VALID_TAG_NAMES = Object.keys(TAG_NAMES).map(function (name) {
33+
return TAG_NAMES[name];
34+
});
35+
36+
var TAG_PROPERTIES = {
37+
CHARSET: "charset",
38+
CSS_TEXT: "cssText",
39+
HREF: "href",
40+
HTTPEQUIV: "http-equiv",
41+
INNER_HTML: "innerHTML",
42+
ITEM_PROP: "itemprop",
43+
NAME: "name",
44+
PROPERTY: "property",
45+
REL: "rel",
46+
SRC: "src"
47+
};
48+
49+
var REACT_TAG_MAP = {
50+
accesskey: "accessKey",
51+
charset: "charSet",
52+
class: "className",
53+
contenteditable: "contentEditable",
54+
contextmenu: "contextMenu",
55+
"http-equiv": "httpEquiv",
56+
itemprop: "itemProp",
57+
tabindex: "tabIndex"
58+
};
59+
60+
var HELMET_PROPS = {
61+
DEFAULT_TITLE: "defaultTitle",
62+
DEFER: "defer",
63+
ENCODE_SPECIAL_CHARACTERS: "encodeSpecialCharacters",
64+
ON_CHANGE_CLIENT_STATE: "onChangeClientState",
65+
TITLE_TEMPLATE: "titleTemplate"
66+
};
67+
68+
var HTML_TAG_MAP = Object.keys(REACT_TAG_MAP).reduce(function (obj, key) {
69+
obj[REACT_TAG_MAP[key]] = key;
70+
return obj;
71+
}, {});
72+
73+
var SELF_CLOSING_TAGS = [TAG_NAMES.NOSCRIPT, TAG_NAMES.SCRIPT, TAG_NAMES.STYLE];
74+
75+
var HELMET_ATTRIBUTE = "data-react-helmet";
76+
77+
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
78+
return typeof obj;
79+
} : function (obj) {
80+
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
81+
};
82+
83+
var classCallCheck = function (instance, Constructor) {
84+
if (!(instance instanceof Constructor)) {
85+
throw new TypeError("Cannot call a class as a function");
86+
}
87+
};
88+
89+
var createClass = function () {
90+
function defineProperties(target, props) {
91+
for (var i = 0; i < props.length; i++) {
92+
var descriptor = props[i];
93+
descriptor.enumerable = descriptor.enumerable || false;
94+
descriptor.configurable = true;
95+
if ("value" in descriptor) descriptor.writable = true;
96+
Object.defineProperty(target, descriptor.key, descriptor);
97+
}
98+
}
99+
100+
return function (Constructor, protoProps, staticProps) {
101+
if (protoProps) defineProperties(Constructor.prototype, protoProps);
102+
if (staticProps) defineProperties(Constructor, staticProps);
103+
return Constructor;
104+
};
105+
}();
106+
107+
var _extends = Object.assign || function (target) {
108+
for (var i = 1; i < arguments.length; i++) {
109+
var source = arguments[i];
110+
111+
for (var key in source) {
112+
if (Object.prototype.hasOwnProperty.call(source, key)) {
113+
target[key] = source[key];
114+
}
115+
}
116+
}
117+
118+
return target;
119+
};
120+
121+
var inherits = function (subClass, superClass) {
122+
if (typeof superClass !== "function" && superClass !== null) {
123+
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
124+
}
125+
126+
subClass.prototype = Object.create(superClass && superClass.prototype, {
127+
constructor: {
128+
value: subClass,
129+
enumerable: false,
130+
writable: true,
131+
configurable: true
132+
}
133+
});
134+
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
135+
};
136+
137+
var objectWithoutProperties = function (obj, keys) {
138+
var target = {};
139+
140+
for (var i in obj) {
141+
if (keys.indexOf(i) >= 0) continue;
142+
if (!Object.prototype.hasOwnProperty.call(obj, i)) continue;
143+
target[i] = obj[i];
144+
}
145+
146+
return target;
147+
};
148+
149+
var possibleConstructorReturn = function (self, call) {
150+
if (!self) {
151+
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
152+
}
153+
154+
return call && (typeof call === "object" || typeof call === "function") ? call : self;
155+
};
156+
157+
var encodeSpecialCharacters = function encodeSpecialCharacters(str) {
158+
var encode = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
159+
160+
if (encode === false) {
161+
return String(str);
162+
}
163+
164+
return String(str).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#x27;");
165+
};
166+
167+
var getTitleFromPropsList = function getTitleFromPropsList(propsList) {
168+
var innermostTitle = getInnermostProperty(propsList, TAG_NAMES.TITLE);
169+
var innermostTemplate = getInnermostProperty(propsList, HELMET_PROPS.TITLE_TEMPLATE);
170+
171+
if (innermostTemplate && innermostTitle) {
172+
// use function arg to avoid need to escape $ characters
173+
return innermostTemplate.replace(/%s/g, function () {
174+
return Array.isArray(innermostTitle) ? innermostTitle.join("") : innermostTitle;
175+
});
176+
}
177+
178+
var innermostDefaultTitle = getInnermostProperty(propsList, HELMET_PROPS.DEFAULT_TITLE);
179+
180+
return innermostTitle || innermostDefaultTitle || undefined;
181+
};
182+
183+
var getOnChangeClientState = function getOnChangeClientState(propsList) {
184+
return getInnermostProperty(propsList, HELMET_PROPS.ON_CHANGE_CLIENT_STATE) || function () {};
185+
};
186+
187+
var getAttributesFromPropsList = function getAttributesFromPropsList(tagType, propsList) {
188+
return propsList.filter(function (props) {
189+
return typeof props[tagType] !== "undefined";
190+
}).map(function (props) {
191+
return props[tagType];
192+
}).reduce(function (tagAttrs, current) {
193+
return _extends({}, tagAttrs, current);
194+
}, {});
195+
};
196+
197+
var getBaseTagFromPropsList = function getBaseTagFromPropsList(primaryAttributes, propsList) {
198+
return propsList.filter(function (props) {
199+
return typeof props[TAG_NAMES.BASE] !== "undefined";
200+
}).map(function (props) {
201+
return props[TAG_NAMES.BASE];
202+
}).reverse().reduce(function (innermostBaseTag, tag) {
203+
if (!innermostBaseTag.length) {
204+
var keys = Object.keys(tag);
205+
206+
for (var i = 0; i < keys.length; i++) {
207+
var attributeKey = keys[i];
208+
var lowerCaseAttributeKey = attributeKey.toLowerCase();
209+
210+
if (primaryAttributes.indexOf(lowerCaseAttributeKey) !== -1 && tag[lowerCaseAttributeKey]) {
211+
return innermostBaseTag.concat(tag);
212+
}
213+
}
214+
}
215+
216+
return innermostBaseTag;
217+
}, []);
218+
};
219+
220+
var getTagsFromPropsList = function getTagsFromPropsList(tagName, primaryAttributes, propsList) {
221+
// Calculate list of tags, giving priority innermost component (end of the propslist)
222+
var approvedSeenTags = {};
223+
224+
return propsList.filter(function (props) {
225+
if (Array.isArray(props[tagName])) {
226+
return true;
227+
}
228+
if (typeof props[tagName] !== "undefined") {
229+
warn("Helmet: " + tagName + " should be of type \"Array\". Instead found type \"" + _typeof(props[tagName]) + "\"");
230+
}
231+
return false;
232+
}).map(function (props) {
233+
return props[tagName];
234+
}).reverse().reduce(function (approvedTags, instanceTags) {
235+
var instanceSeenTags = {};
236+
237+
instanceTags.filter(function (tag) {
238+
var primaryAttributeKey = void 0;
239+
var keys = Object.keys(tag);
240+
for (var i = 0; i < keys.length; i++) {
241+
var attributeKey = keys[i];
242+
var lowerCaseAttributeKey = attributeKey.toLowerCase();
243+
244+
// Special rule with link tags, since rel and href are both primary tags, rel takes priority
245+
if (primaryAttributes.indexOf(lowerCaseAttributeKey) !== -1 && !(primaryAttributeKey === TAG_PROPERTIES.REL && tag[primaryAttributeKey].toLowerCase() === "canonical") && !(lowerCaseAttributeKey === TAG_PROPERTIES.REL && tag[lowerCaseAttributeKey].toLowerCase() === "stylesheet")) {
246+
primaryAttributeKey = lowerCaseAttributeKey;
247+
}
248+
// Special case for innerHTML which doesn't work lowercased
249+
if (primaryAttributes.indexOf(attributeKey) !== -1 && (attributeKey === TAG_PROPERTIES.INNER_HTML || attributeKey === TAG_PROPERTIES.CSS_TEXT || attributeKey === TAG_PROPERTIES.ITEM_PROP)) {
250+
primaryAttributeKey = attributeKey;
251+
}
252+
}
253+
254+
if (!primaryAttributeKey || !tag[primaryAttributeKey]) {
255+
return false;
256+
}
257+
258+
var value = tag[primaryAttributeKey].toLowerCase();
259+
260+
if (!approvedSeenTags[primaryAttributeKey]) {
261+
approvedSeenTags[primaryAttributeKey] = {};
262+
}
263+
264+
if (!instanceSeenTags[primaryAttributeKey]) {
265+
instanceSeenTags[primaryAttributeKey] = {};
266+
}
267+
268+
if (!approvedSeenTags[primaryAttributeKey][value]) {
269+
instanceSeenTags[primaryAttributeKey][value] = true;
270+
return true;
271+
}
272+
273+
return false;
274+
}).reverse().forEach(function (tag) {
275+
return approvedTags.push(tag);
276+
});
277+
278+
// Update seen tags with tags from this instance
279+
var keys = Object.keys(instanceSeenTags);
280+
for (var i = 0; i < keys.length; i++) {
281+
var attributeKey = keys[i];
282+
var tagUnion = objectAssign({}, approvedSeenTags[attributeKey], instanceSeenTags[attributeKey]);
283+
284+
approvedSeenTags[attributeKey] = tagUnion;
285+
}
286+
287+
return approvedTags;
288+
}, []).reverse();
289+
};
290+
291+
var getInnermostProperty = function getInnermostProperty(propsList, property) {
292+
for (var i = propsList.length - 1; i >= 0; i--) {
293+
var props = propsList[i];
294+
295+
if (props.hasOwnProperty(property)) {
296+
return props[property];
297+
}
298+
}
299+
300+
return null;
301+
};
302+
303+
var reducePropsToState = function reducePropsToState(propsList) {
304+
return {
305+
baseTag: getBaseTagFromPropsList([TAG_PROPERTIES.HREF], propsList),
306+
bodyAttributes: getAttributesFromPropsList(ATTRIBUTE_NAMES.BODY, propsList),
307+
defer: getInnermostProperty(propsList, HELMET_PROPS.DEFER),
308+
encode: getInnermostProperty(propsList, HELMET_PROPS.ENCODE_SPECIAL_CHARACTERS),
309+
htmlAttributes: getAttributesFromPropsList(ATTRIBUTE_NAMES.HTML, propsList),
310+
linkTags: getTagsFromPropsList(TAG_NAMES.LINK, [TAG_PROPERTIES.REL, TAG_PROPERTIES.HREF], propsList),
311+
metaTags: getTagsFromPropsList(TAG_NAMES.META, [TAG_PROPERTIES.NAME, TAG_PROPERTIES.CHARSET, TAG_PROPERTIES.HTTPEQUIV, TAG_PROPERTIES.PROPERTY, TAG_PROPERTIES.ITEM_PROP], propsList),
312+
noscriptTags: getTagsFromPropsList(TAG_NAMES.NOSCRIPT, [TAG_PROPERTIES.INNER_HTML], propsList),
313+
onChangeClientState: getOnChangeClientState(propsList),
314+
scriptTags: getTagsFromPropsList(TAG_NAMES.SCRIPT, [TAG_PROPERTIES.SRC, TAG_PROPERTIES.INNER_HTML], propsList),
315+
styleTags: getTagsFromPropsList(TAG_NAMES.STYLE, [TAG_PROPERTIES.CSS_TEXT], propsList),
316+
title: getTitleFromPropsList(propsList),
317+
titleAttributes: getAttributesFromPropsList(ATTRIBUTE_NAMES.TITLE, propsList)
318+
};
319+
};
320+
321+
var rafPolyfill = function () {
322+
var clock = Date.now();
323+
324+
return function (callback) {
325+
var currentTime = Date.now();
326+
327+
if (currentTime - clock > 16) {
328+
clock = currentTime;
329+
callback(currentTime);
330+
} else {
331+
setTimeout(function () {
332+
rafPolyfill(callback);
333+
}, 0);
334+
}
335+
};
336+
}();
337+
338+
var cafPolyfill = function cafPolyfill(id) {
339+
return clearTimeout(id);
340+
};
341+
342+
var requestAnimationFrame = typeof window !== "undefined" ? window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || rafPolyfill : global.requestAnimationFrame || rafPolyfill;
343+
344+
var cancelAnimationFrame = typeof window !== "undefined" ? window.cancelAnimationFrame || window.webkitCancelAnimationFrame || window.mozCancelAnimationFrame || cafPolyfill : global.cancelAnimationFrame || cafPolyfill;
345+
346+
var warn = function warn(msg) {
347+
return console && typeof console.warn === "function" && console.warn(msg);
348+
};
349+
350+
var _helmetCallback = null;
351+
352+
var handleClientStateChange = function handleClientStateChange(newState) {
353+
if (_helmetCallback) {
354+
cancelAnimationFrame(_helmetCallback);
355+
}
356+
357+
if (newState.defer) {
358+
_helmetCallback = requestAnimationFrame(function () {
359+
commitTagChanges(newState, function () {
360+
_helmetCallback = null;
361+
});
362+
});
363+
} else {
364+
commitTagChanges(newState);
365+
_helmetCallback = null;
366+
}
367+
};
368+
369+
var commitTagChanges = function commitTagChanges(newState, cb) {
370+
var baseTag = newState.baseTag,
371+
bodyAttributes = newState.bodyAttributes,
372+
htmlAttributes = newState.htmlAttributes,
373+
linkTags = newState.linkTags,
374+
metaTags = newState.metaTags,
375+
noscriptTags = newState.noscriptTags,
376+
onChangeClientState = newState.onChangeClientState,
377+
scriptTags = newState.scriptTags,
378+
styleTags = newState.styleTags,
379+
title = newState.title,
380+
titleAttributes = newState.titleAttributes;
381+
382+
updateAttributes(TAG_NAMES.BODY, bodyAttributes);
383+
updateAttributes(TAG_NAMES.HTML, htmlAttributes);
384+
385+
updateTitle(title, titleAttributes);
386+
387+
var tagUpdates = {
388+
baseTag: updateTags(TAG_NAMES.BASE, baseTag),
389+
linkTags: updateTags(TAG_NAMES.LINK, linkTags),
390+
metaTags: updateTags(TAG_NAMES.META, metaTags),
391+
noscriptTags: updateTags(TAG_NAMES.NOSCRIPT, noscriptTags),
392+
scriptTags: updateTags(TAG_NAMES.SCRIPT, scriptTags),
393+
styleTags: updateTags(TAG_NAMES.STYLE, styleTags)
394+
};
395+
396+
var addedTags = {};
397+
var removedTags = {};
398+
399+
Object.keys(tagUpdates).forEach(function (tagType) {
400+
var _tagUpdates$tagType = tagUpdates[tagType],
401+
newTags = _tagUpdates$tagType.newTags,
402+
oldTags = _tagUpdates$tagType.oldTags;
403+
404+
405+
if (newTags.length) {
406+
addedTags[tagType] = newTags;
407+
}
408+
if (oldTags.length) {
409+
removedTags[tagType] = tagUpdates[tagType].oldTags;
410+
}
411+
});
412+
413+
cb && cb();
414+
415+
onChangeClientState(newState, addedTags, removedTags);
416+
};
417+
418+
var flattenArray = function flattenArray(possibleArray) {
419+
return Array.isArray(possibleArray) ? possibleArray.join("") : possibleArray;
420+
};
421+
422+
var updateTitle = function updateTitle(title, attributes) {
423+
if (typeof title !== "undefined" && document.title !== title) {
424+
document.title = flattenArray(title);
425+
}
426+
427+
updateAttributes(TAG_NAMES.TITLE, attributes);
428+
};
429+
430+
var updateAttributes = function updateAttributes(tagName, attributes) {
431+
var elementTag = document.getElementsByTagName(tagName)[0];
432+
433+
if (!elementTag) {
434+
return;
435+
}
436+
437+
var helmetAttributeString = elementTag.getAttribute(HELMET_ATTRIBUTE);
438+
var helmetAttributes = helmetAttributeString ? helmetAttributeString.split(",") : [];
439+
var attributesToRemove = [].concat(helmetAttributes);
440+
var attributeKeys = Object.keys(attributes);
441+
442+
for (var i = 0; i < attributeKeys.length; i++) {
443+
var attribute = attributeKeys[i];
444+
var value = attributes[attribute] || "";
445+
446+
if (elementTag.getAttribute(attribute) !== value) {
447+
elementTag.setAttribute(attribute, value);
448+
}
449+
450+
if (helmetAttributes.indexOf(attribute) === -1) {
451+
helmetAttributes.push(attribute);
452+
}
453+
454+
var indexToSave = attributesToRemove.indexOf(attribute);
455+
if (indexToSave !== -1) {
456+
attributesToRemove.splice(indexToSave, 1);
457+
}
458+
}
459+
460+
for (var _i = attributesToRemove.length - 1; _i >= 0; _i--) {
461+
elementTag.removeAttribute(attributesToRemove[_i]);
462+
}
463+
464+
if (helmetAttributes.length === attributesToRemove.length) {
465+
elementTag.removeAttribute(HELMET_ATTRIBUTE);
466+
} else if (elementTag.getAttribute(HELMET_ATTRIBUTE) !== attributeKeys.join(",")) {
467+
elementTag.setAttribute(HELMET_ATTRIBUTE, attributeKeys.join(","));
468+
}
469+
};
470+
471+
var updateTags = function updateTags(type, tags) {
472+
var headElement = document.head || document.querySelector(TAG_NAMES.HEAD);
473+
var tagNodes = headElement.querySelectorAll(type + "[" + HELMET_ATTRIBUTE + "]");
474+
var oldTags = Array.prototype.slice.call(tagNodes);
475+
var newTags = [];
476+
var indexToDelete = void 0;
477+
478+
if (tags && tags.length) {
479+
tags.forEach(function (tag) {
480+
var newElement = document.createElement(type);
481+
482+
for (var attribute in tag) {
483+
if (tag.hasOwnProperty(attribute)) {
484+
if (attribute === TAG_PROPERTIES.INNER_HTML) {
485+
newElement.innerHTML = tag.innerHTML;
486+
} else if (attribute === TAG_PROPERTIES.CSS_TEXT) {
487+
if (newElement.styleSheet) {
488+
newElement.styleSheet.cssText = tag.cssText;
489+
} else {
490+
newElement.appendChild(document.createTextNode(tag.cssText));
491+
}
492+
} else {
493+
var value = typeof tag[attribute] === "undefined" ? "" : tag[attribute];
494+
newElement.setAttribute(attribute, value);
495+
}
496+
}
497+
}
498+
499+
newElement.setAttribute(HELMET_ATTRIBUTE, "true");
500+
501+
// Remove a duplicate tag from domTagstoRemove, so it isn't cleared.
502+
if (oldTags.some(function (existingTag, index) {
503+
indexToDelete = index;
504+
return newElement.isEqualNode(existingTag);
505+
})) {
506+
oldTags.splice(indexToDelete, 1);
507+
} else {
508+
newTags.push(newElement);
509+
}
510+
});
511+
}
512+
513+
oldTags.forEach(function (tag) {
514+
return tag.parentNode.removeChild(tag);
515+
});
516+
newTags.forEach(function (tag) {
517+
return headElement.appendChild(tag);
518+
});
519+
520+
return {
521+
oldTags: oldTags,
522+
newTags: newTags
523+
};
524+
};
525+
526+
var generateElementAttributesAsString = function generateElementAttributesAsString(attributes) {
527+
return Object.keys(attributes).reduce(function (str, key) {
528+
var attr = typeof attributes[key] !== "undefined" ? key + "=\"" + attributes[key] + "\"" : "" + key;
529+
return str ? str + " " + attr : attr;
530+
}, "");
531+
};
532+
533+
var generateTitleAsString = function generateTitleAsString(type, title, attributes, encode) {
534+
var attributeString = generateElementAttributesAsString(attributes);
535+
var flattenedTitle = flattenArray(title);
536+
return attributeString ? "<" + type + " " + HELMET_ATTRIBUTE + "=\"true\" " + attributeString + ">" + encodeSpecialCharacters(flattenedTitle, encode) + "</" + type + ">" : "<" + type + " " + HELMET_ATTRIBUTE + "=\"true\">" + encodeSpecialCharacters(flattenedTitle, encode) + "</" + type + ">";
537+
};
538+
539+
var generateTagsAsString = function generateTagsAsString(type, tags, encode) {
540+
return tags.reduce(function (str, tag) {
541+
var attributeHtml = Object.keys(tag).filter(function (attribute) {
542+
return !(attribute === TAG_PROPERTIES.INNER_HTML || attribute === TAG_PROPERTIES.CSS_TEXT);
543+
}).reduce(function (string, attribute) {
544+
var attr = typeof tag[attribute] === "undefined" ? attribute : attribute + "=\"" + encodeSpecialCharacters(tag[attribute], encode) + "\"";
545+
return string ? string + " " + attr : attr;
546+
}, "");
547+
548+
var tagContent = tag.innerHTML || tag.cssText || "";
549+
550+
var isSelfClosing = SELF_CLOSING_TAGS.indexOf(type) === -1;
551+
552+
return str + "<" + type + " " + HELMET_ATTRIBUTE + "=\"true\" " + attributeHtml + (isSelfClosing ? "/>" : ">" + tagContent + "</" + type + ">");
553+
}, "");
554+
};
555+
556+
var convertElementAttributestoReactProps = function convertElementAttributestoReactProps(attributes) {
557+
var initProps = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
558+
559+
return Object.keys(attributes).reduce(function (obj, key) {
560+
obj[REACT_TAG_MAP[key] || key] = attributes[key];
561+
return obj;
562+
}, initProps);
563+
};
564+
565+
var convertReactPropstoHtmlAttributes = function convertReactPropstoHtmlAttributes(props) {
566+
var initAttributes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
567+
568+
return Object.keys(props).reduce(function (obj, key) {
569+
obj[HTML_TAG_MAP[key] || key] = props[key];
570+
return obj;
571+
}, initAttributes);
572+
};
573+
574+
var generateTitleAsReactComponent = function generateTitleAsReactComponent(type, title, attributes) {
575+
var _initProps;
576+
577+
// assigning into an array to define toString function on it
578+
var initProps = (_initProps = {
579+
key: title
580+
}, _initProps[HELMET_ATTRIBUTE] = true, _initProps);
581+
var props = convertElementAttributestoReactProps(attributes, initProps);
582+
583+
return [React.createElement(TAG_NAMES.TITLE, props, title)];
584+
};
585+
586+
var generateTagsAsReactComponent = function generateTagsAsReactComponent(type, tags) {
587+
return tags.map(function (tag, i) {
588+
var _mappedTag;
589+
590+
var mappedTag = (_mappedTag = {
591+
key: i
592+
}, _mappedTag[HELMET_ATTRIBUTE] = true, _mappedTag);
593+
594+
Object.keys(tag).forEach(function (attribute) {
595+
var mappedAttribute = REACT_TAG_MAP[attribute] || attribute;
596+
597+
if (mappedAttribute === TAG_PROPERTIES.INNER_HTML || mappedAttribute === TAG_PROPERTIES.CSS_TEXT) {
598+
var content = tag.innerHTML || tag.cssText;
599+
mappedTag.dangerouslySetInnerHTML = { __html: content };
600+
} else {
601+
mappedTag[mappedAttribute] = tag[attribute];
602+
}
603+
});
604+
605+
return React.createElement(type, mappedTag);
606+
});
607+
};
608+
609+
var getMethodsForTag = function getMethodsForTag(type, tags, encode) {
610+
switch (type) {
611+
case TAG_NAMES.TITLE:
612+
return {
613+
toComponent: function toComponent() {
614+
return generateTitleAsReactComponent(type, tags.title, tags.titleAttributes, encode);
615+
},
616+
toString: function toString() {
617+
return generateTitleAsString(type, tags.title, tags.titleAttributes, encode);
618+
}
619+
};
620+
case ATTRIBUTE_NAMES.BODY:
621+
case ATTRIBUTE_NAMES.HTML:
622+
return {
623+
toComponent: function toComponent() {
624+
return convertElementAttributestoReactProps(tags);
625+
},
626+
toString: function toString() {
627+
return generateElementAttributesAsString(tags);
628+
}
629+
};
630+
default:
631+
return {
632+
toComponent: function toComponent() {
633+
return generateTagsAsReactComponent(type, tags);
634+
},
635+
toString: function toString() {
636+
return generateTagsAsString(type, tags, encode);
637+
}
638+
};
639+
}
640+
};
641+
642+
var mapStateOnServer = function mapStateOnServer(_ref) {
643+
var baseTag = _ref.baseTag,
644+
bodyAttributes = _ref.bodyAttributes,
645+
encode = _ref.encode,
646+
htmlAttributes = _ref.htmlAttributes,
647+
linkTags = _ref.linkTags,
648+
metaTags = _ref.metaTags,
649+
noscriptTags = _ref.noscriptTags,
650+
scriptTags = _ref.scriptTags,
651+
styleTags = _ref.styleTags,
652+
_ref$title = _ref.title,
653+
title = _ref$title === undefined ? "" : _ref$title,
654+
titleAttributes = _ref.titleAttributes;
655+
return {
656+
base: getMethodsForTag(TAG_NAMES.BASE, baseTag, encode),
657+
bodyAttributes: getMethodsForTag(ATTRIBUTE_NAMES.BODY, bodyAttributes, encode),
658+
htmlAttributes: getMethodsForTag(ATTRIBUTE_NAMES.HTML, htmlAttributes, encode),
659+
link: getMethodsForTag(TAG_NAMES.LINK, linkTags, encode),
660+
meta: getMethodsForTag(TAG_NAMES.META, metaTags, encode),
661+
noscript: getMethodsForTag(TAG_NAMES.NOSCRIPT, noscriptTags, encode),
662+
script: getMethodsForTag(TAG_NAMES.SCRIPT, scriptTags, encode),
663+
style: getMethodsForTag(TAG_NAMES.STYLE, styleTags, encode),
664+
title: getMethodsForTag(TAG_NAMES.TITLE, { title: title, titleAttributes: titleAttributes }, encode)
665+
};
666+
};
667+
668+
var Helmet = function Helmet(Component) {
669+
var _class, _temp;
670+
671+
return _temp = _class = function (_React$Component) {
672+
inherits(HelmetWrapper, _React$Component);
673+
674+
function HelmetWrapper() {
675+
classCallCheck(this, HelmetWrapper);
676+
return possibleConstructorReturn(this, _React$Component.apply(this, arguments));
677+
}
678+
679+
HelmetWrapper.prototype.shouldComponentUpdate = function shouldComponentUpdate(nextProps) {
680+
return !isEqual(this.props, nextProps);
681+
};
682+
683+
HelmetWrapper.prototype.mapNestedChildrenToProps = function mapNestedChildrenToProps(child, nestedChildren) {
684+
if (!nestedChildren) {
685+
return null;
686+
}
687+
688+
switch (child.type) {
689+
case TAG_NAMES.SCRIPT:
690+
case TAG_NAMES.NOSCRIPT:
691+
return {
692+
innerHTML: nestedChildren
693+
};
694+
695+
case TAG_NAMES.STYLE:
696+
return {
697+
cssText: nestedChildren
698+
};
699+
}
700+
701+
throw new Error("<" + child.type + " /> elements are self-closing and can not contain children. Refer to our API for more information.");
702+
};
703+
704+
HelmetWrapper.prototype.flattenArrayTypeChildren = function flattenArrayTypeChildren(_ref) {
705+
var _babelHelpers$extends;
706+
707+
var child = _ref.child,
708+
arrayTypeChildren = _ref.arrayTypeChildren,
709+
newChildProps = _ref.newChildProps,
710+
nestedChildren = _ref.nestedChildren;
711+
712+
return _extends({}, arrayTypeChildren, (_babelHelpers$extends = {}, _babelHelpers$extends[child.type] = [].concat(arrayTypeChildren[child.type] || [], [_extends({}, newChildProps, this.mapNestedChildrenToProps(child, nestedChildren))]), _babelHelpers$extends));
713+
};
714+
715+
HelmetWrapper.prototype.mapObjectTypeChildren = function mapObjectTypeChildren(_ref2) {
716+
var _babelHelpers$extends2, _babelHelpers$extends3;
717+
718+
var child = _ref2.child,
719+
newProps = _ref2.newProps,
720+
newChildProps = _ref2.newChildProps,
721+
nestedChildren = _ref2.nestedChildren;
722+
723+
switch (child.type) {
724+
case TAG_NAMES.TITLE:
725+
return _extends({}, newProps, (_babelHelpers$extends2 = {}, _babelHelpers$extends2[child.type] = nestedChildren, _babelHelpers$extends2.titleAttributes = _extends({}, newChildProps), _babelHelpers$extends2));
726+
727+
case TAG_NAMES.BODY:
728+
return _extends({}, newProps, {
729+
bodyAttributes: _extends({}, newChildProps)
730+
});
731+
732+
case TAG_NAMES.HTML:
733+
return _extends({}, newProps, {
734+
htmlAttributes: _extends({}, newChildProps)
735+
});
736+
}
737+
738+
return _extends({}, newProps, (_babelHelpers$extends3 = {}, _babelHelpers$extends3[child.type] = _extends({}, newChildProps), _babelHelpers$extends3));
739+
};
740+
741+
HelmetWrapper.prototype.mapArrayTypeChildrenToProps = function mapArrayTypeChildrenToProps(arrayTypeChildren, newProps) {
742+
var newFlattenedProps = _extends({}, newProps);
743+
744+
Object.keys(arrayTypeChildren).forEach(function (arrayChildName) {
745+
var _babelHelpers$extends4;
746+
747+
newFlattenedProps = _extends({}, newFlattenedProps, (_babelHelpers$extends4 = {}, _babelHelpers$extends4[arrayChildName] = arrayTypeChildren[arrayChildName], _babelHelpers$extends4));
748+
});
749+
750+
return newFlattenedProps;
751+
};
752+
753+
HelmetWrapper.prototype.warnOnInvalidChildren = function warnOnInvalidChildren(child, nestedChildren) {
754+
if (process.env.NODE_ENV !== "production") {
755+
if (!VALID_TAG_NAMES.some(function (name) {
756+
return child.type === name;
757+
})) {
758+
if (typeof child.type === "function") {
759+
return warn("You may be attempting to nest <Helmet> components within each other, which is not allowed. Refer to our API for more information.");
760+
}
761+
762+
return warn("Only elements types " + VALID_TAG_NAMES.join(", ") + " are allowed. Helmet does not support rendering <" + child.type + "> elements. Refer to our API for more information.");
763+
}
764+
765+
if (nestedChildren && typeof nestedChildren !== "string" && (!Array.isArray(nestedChildren) || nestedChildren.some(function (nestedChild) {
766+
return typeof nestedChild !== "string";
767+
}))) {
768+
throw new Error("Helmet expects a string as a child of <" + child.type + ">. Did you forget to wrap your children in braces? ( <" + child.type + ">{``}</" + child.type + "> ) Refer to our API for more information.");
769+
}
770+
}
771+
772+
return true;
773+
};
774+
775+
HelmetWrapper.prototype.mapChildrenToProps = function mapChildrenToProps(children, newProps) {
776+
var _this2 = this;
777+
778+
var arrayTypeChildren = {};
779+
780+
React.Children.forEach(children, function (child) {
781+
if (!child || !child.props) {
782+
return;
783+
}
784+
785+
var _child$props = child.props,
786+
nestedChildren = _child$props.children,
787+
childProps = objectWithoutProperties(_child$props, ["children"]);
788+
789+
var newChildProps = convertReactPropstoHtmlAttributes(childProps);
790+
791+
_this2.warnOnInvalidChildren(child, nestedChildren);
792+
793+
switch (child.type) {
794+
case TAG_NAMES.LINK:
795+
case TAG_NAMES.META:
796+
case TAG_NAMES.NOSCRIPT:
797+
case TAG_NAMES.SCRIPT:
798+
case TAG_NAMES.STYLE:
799+
arrayTypeChildren = _this2.flattenArrayTypeChildren({
800+
child: child,
801+
arrayTypeChildren: arrayTypeChildren,
802+
newChildProps: newChildProps,
803+
nestedChildren: nestedChildren
804+
});
805+
break;
806+
807+
default:
808+
newProps = _this2.mapObjectTypeChildren({
809+
child: child,
810+
newProps: newProps,
811+
newChildProps: newChildProps,
812+
nestedChildren: nestedChildren
813+
});
814+
break;
815+
}
816+
});
817+
818+
newProps = this.mapArrayTypeChildrenToProps(arrayTypeChildren, newProps);
819+
return newProps;
820+
};
821+
822+
HelmetWrapper.prototype.render = function render() {
823+
var _props = this.props,
824+
children = _props.children,
825+
props = objectWithoutProperties(_props, ["children"]);
826+
827+
var newProps = _extends({}, props);
828+
829+
if (children) {
830+
newProps = this.mapChildrenToProps(children, newProps);
831+
}
832+
833+
return React.createElement(Component, newProps);
834+
};
835+
836+
createClass(HelmetWrapper, null, [{
837+
key: "canUseDOM",
838+
839+
840+
// Component.peek comes from react-side-effect:
841+
// For testing, you may use a static peek() method available on the returned component.
842+
// It lets you get the current state without resetting the mounted instance stack.
843+
// Don’t use it for anything other than testing.
844+
845+
/**
846+
* @param {Object} base: {"target": "_blank", "href": "http://mysite.com/"}
847+
* @param {Object} bodyAttributes: {"className": "root"}
848+
* @param {String} defaultTitle: "Default Title"
849+
* @param {Boolean} defer: true
850+
* @param {Boolean} encodeSpecialCharacters: true
851+
* @param {Object} htmlAttributes: {"lang": "en", "amp": undefined}
852+
* @param {Array} link: [{"rel": "canonical", "href": "http://mysite.com/example"}]
853+
* @param {Array} meta: [{"name": "description", "content": "Test description"}]
854+
* @param {Array} noscript: [{"innerHTML": "<img src='http://mysite.com/js/test.js'"}]
855+
* @param {Function} onChangeClientState: "(newState) => console.log(newState)"
856+
* @param {Array} script: [{"type": "text/javascript", "src": "http://mysite.com/js/test.js"}]
857+
* @param {Array} style: [{"type": "text/css", "cssText": "div { display: block; color: blue; }"}]
858+
* @param {String} title: "Title"
859+
* @param {Object} titleAttributes: {"itemprop": "name"}
860+
* @param {String} titleTemplate: "MySite.com - %s"
861+
*/
862+
set: function set$$1(canUseDOM) {
863+
Component.canUseDOM = canUseDOM;
864+
}
865+
}]);
866+
return HelmetWrapper;
867+
}(React.Component), _class.propTypes = {
868+
base: PropTypes.object,
869+
bodyAttributes: PropTypes.object,
870+
children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]),
871+
defaultTitle: PropTypes.string,
872+
defer: PropTypes.bool,
873+
encodeSpecialCharacters: PropTypes.bool,
874+
htmlAttributes: PropTypes.object,
875+
link: PropTypes.arrayOf(PropTypes.object),
876+
meta: PropTypes.arrayOf(PropTypes.object),
877+
noscript: PropTypes.arrayOf(PropTypes.object),
878+
onChangeClientState: PropTypes.func,
879+
script: PropTypes.arrayOf(PropTypes.object),
880+
style: PropTypes.arrayOf(PropTypes.object),
881+
title: PropTypes.string,
882+
titleAttributes: PropTypes.object,
883+
titleTemplate: PropTypes.string
884+
}, _class.defaultProps = {
885+
defer: true,
886+
encodeSpecialCharacters: true
887+
}, _class.peek = Component.peek, _class.rewind = function () {
888+
var mappedState = Component.rewind();
889+
if (!mappedState) {
890+
// provide fallback if mappedState is undefined
891+
mappedState = mapStateOnServer({
892+
baseTag: [],
893+
bodyAttributes: {},
894+
encodeSpecialCharacters: true,
895+
htmlAttributes: {},
896+
linkTags: [],
897+
metaTags: [],
898+
noscriptTags: [],
899+
scriptTags: [],
900+
styleTags: [],
901+
title: "",
902+
titleAttributes: {}
903+
});
904+
}
905+
906+
return mappedState;
907+
}, _temp;
908+
};
909+
910+
var NullComponent = function NullComponent() {
911+
return null;
912+
};
913+
914+
var HelmetSideEffects = withSideEffect(reducePropsToState, handleClientStateChange, mapStateOnServer)(NullComponent);
915+
916+
var HelmetExport = Helmet(HelmetSideEffects);
917+
HelmetExport.renderStatic = HelmetExport.rewind;
918+
919+
exports.Helmet = HelmetExport;

0 commit comments

Comments
 (0)
This repository has been archived.