UNPKG

2.83 kBJavaScriptView Raw
1const React = require('react');
2const createClass = require('create-react-class');
3
4const reduce = (obj, fn, init)=>Object.keys(obj).reduce((acc, key)=>fn(acc, obj[key], key), init);
5const map = (obj, fn)=>Object.keys(obj).map((key)=>fn(obj[key], key));
6
7let Storage={meta:[], noscript : []};
8
9const mapProps = (props)=>map(props, (val, key)=>`${key}="${val}"`).join(' ');
10const processData = (data)=>{
11 return reduce(data, (acc, val, key)=>{
12 if(key == 'type') key = '@type';
13 if(key == 'context') key = '@context';
14 acc[key] = (typeof val == 'object'
15 ? processData(val)
16 : val
17 );
18 return acc;
19 }, {});
20};
21
22const HeadTags = {
23 Title : createClass({
24 componentWillMount(){ Storage.title = this.props.children; },
25 render(){
26 if(typeof document !== 'undefined') document.title = this.props.children;
27 return null;
28 }
29 }),
30 Favicon : createClass({
31 getDefaultProps(){ return { type : 'image/png', href : ''}},
32 componentWillMount(){ Storage.favicon = this.props; },
33 render(){
34 if(typeof document !== 'undefined') document.getElementById('favicon').href=this.props.href;
35 return null;
36 }
37 }),
38 Noscript : createClass({
39 componentWillMount(){ Storage.noscript.push(this.props.children); },
40 render(){ return null; }
41 }),
42 Meta : createClass({
43 componentWillMount(){ Storage.meta.push(this.props); },
44 render(){ return null; }
45 }),
46 Structured : createClass({
47 componentWillMount(){ Storage.structuredData = processData(this.props.data); },
48 render(){ return null; }
49 }),
50 Bulk : createClass({
51 componentWillMount(){
52 if(this.props.title) Storage.title = this.props.title;
53 if(this.props.favicon) Storage.favicon = this.props.favicon;
54 if(this.props.meta) Storage.meta = Storage.meta.concat(map(this.props.meta, (content, name)=>{return {content, name}}));
55 if(this.props.structuredData) Storage.structuredData = processData(this.props.structuredData);
56 },
57 componentDidMount(){
58 if(typeof document !== 'undefined' && this.props.title) document.title = this.props.title;
59 },
60 render(){ return null; }
61 }),
62 flush : ()=>Storage = {meta:[], noscript : []},
63 generate : ()=>{
64 let res = [];
65 if(Storage.title) res.push(`<title>${Storage.title}</title>`);
66 if(Storage.favicon) res.push(`<link id='favicon' rel='shortcut icon' type='${Storage.favicon.type}' href='${Storage.favicon.href}' />`);
67 if(Storage.meta && Storage.meta.length){
68 res = res.concat(Storage.meta.map((metaProps)=>`<meta ${mapProps(metaProps)} />`));
69 }
70 if(Storage.noscript && Storage.noscript.length){
71 res = res.concat(`<noscript>${Storage.noscript.join('\n')}</noscript>`);
72 }
73 if(Storage.structuredData){
74 res.push(`<script type='application/ld+json'>${JSON.stringify(Storage.structuredData, null, ' ')}</script>`);
75 }
76 HeadTags.flush();
77 return res.join('\n');
78 }
79};
80
81module.exports = HeadTags;
\No newline at end of file