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