UNPKG

3.35 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;
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 Description : createClass({
31 componentWillMount(){ Storage.description = this.props.children; },
32 render(){ return null; }
33 }),
34 Favicon : createClass({
35 getDefaultProps(){ return { type : 'image/png', href : ''}},
36 componentWillMount(){ Storage.favicon = this.props; },
37 render(){
38 if(typeof document !== 'undefined') document.getElementById('favicon').href=this.props.href;
39 return null;
40 }
41 }),
42 Noscript : createClass({
43 componentWillMount(){ Storage.noscript.push(this.props.children); },
44 render(){ return null; }
45 }),
46 Script : createClass({
47 getDefaultProps(){ return { id : '', src : ''}},
48 componentWillMount(){ Storage.script.push(this.props); },
49 render(){ return null; }
50 }),
51 Meta : createClass({
52 componentWillMount(){
53 const addTag = (props)=>{
54 (props.property || props.name)
55 ? Storage.namedMeta[props.property || props.name] = props
56 : Storage.unnamedMeta.push(props);
57 }
58 this.props.bulk
59 ? map(this.props.bulk, (content, property)=>addTag({ content, property }))
60 : addTag(this.props);
61 },
62 render(){ return null; }
63 }),
64 Structured : createClass({
65 componentWillMount(){ Storage.structuredData = processData(this.props.data); },
66 render(){ return null; }
67 }),
68 flush : ()=>{
69 Storage = {
70 title : null,
71 description : null,
72 namedMeta : {},
73 unnamedMeta : [],
74 noscript : [],
75 script : []
76 }
77 },
78 generate : ()=>{
79 let res = [];
80 if(Storage.title){
81 res.push(`<title>${Storage.title}</title>`);
82 }
83 if(Storage.favicon){
84 res.push(`<link id='favicon' rel='shortcut icon' type='${Storage.favicon.type}' href='${Storage.favicon.href}' />`);
85 }
86 if(Storage.description){
87 res.push(`<meta content='${Storage.description}' name='description' />`);
88 }
89 const Meta = Object.values(Storage.namedMeta).concat(Storage.unnamedMeta);
90 if(Meta && Meta.length){
91 res = res.concat(Meta.reverse().map((metaProps)=>`<meta ${mapProps(metaProps)} />`));
92 }
93 if(Storage.noscript && Storage.noscript.length){
94 res = res.concat(`<noscript>${Storage.noscript.join('\n')}</noscript>`);
95 }
96 if(Storage.script && Storage.script.length){
97 res = res.concat(Storage.script.map((script)=>{
98 return `<script id='${script.id}' src='${script.src}'>${script.children}</script>`;
99 }).join('\n'));
100 }
101 if(Storage.structuredData){
102 res.push(`<script type='application/ld+json'>${JSON.stringify(Storage.structuredData, null, ' ')}</script>`);
103 }
104 HeadTags.flush();
105 return res.join('\n');
106 }
107};
108
109HeadTags.flush();
110module.exports = HeadTags;
\No newline at end of file