apeman-react-head
Version:
apeman react package for head component.
181 lines (168 loc) • 4.49 kB
JSX
/**
* apeman react package for head component.
* @class ApHead
*/
import React, {PropTypes as types} from 'react'
import stringcase from 'stringcase'
/** @lends ApHead */
const ApHead = React.createClass({
// --------------------
// Specs
// --------------------
propTypes: {
/** CharSet */
charset: types.string,
/** Document Title */
title: types.string,
/** Favicon */
icon: types.string,
/** Meta data */
meta: types.oneOfType([
types.arrayOf(types.object),
types.object
]),
/** Micro data settings */
itemProps: types.oneOfType([
types.arrayOf(types.object),
types.object
]),
/** CSS file urls */
css: types.array,
/** JS file urls */
js: types.array,
/** Version string */
version: types.string,
/** Querystring key for version */
versionKey: types.string,
/** Global variables */
globals: types.object,
/** View port settings */
viewport: types.object
},
mixins: [],
statics: {
renderCharset (charset) {
if (!charset) {
return null
}
return (
<meta className="ap-head-meta" charSet={charset}/>
)
},
renderTitle (title) {
if (!title) {
return null
}
return (
<title className="ap-head-title">{title}</title>
)
},
renderIcon (url, query) {
if (!url) {
return null
}
return (
<link rel="icon" href={ ApHead._addQuery(url, query) }/>
)
},
renderMetaValues (values) {
if (!values) {
return null
}
return [].concat(values).map((values, i) =>
Object.keys(values).map((name, j) =>
<meta name={ name }
content={ values[name] }
key={ `meta-${i}-${j}` }/>
)
).reduce((a, b) => [].concat(a, b), [])
},
renderItemProps (values) {
if (!values) {
return null
}
return [].concat(values).map((values, i) =>
Object.keys(values).map((name, j) =>
<meta itemProp={ name }
content={ values[name] }
key={ `item-prop${i}-${j}` }/>
)
).reduce((a, b) => [].concat(a, b), [])
},
renderCss (urls, query) {
if (!urls) {
return null
}
return [].concat(urls).map((url, i) =>
<link rel="stylesheet"
type="text/css"
key={ `css-${i}-${url}` }
href={ ApHead._addQuery(url, query) }/>
)
},
renderJs (urls, query) {
if (!urls) {
return null
}
return [].concat(urls).map((url, i) =>
<script type="text/javascript"
key={ `js-${i}-${url}` }
src={ ApHead._addQuery(url,query)}></script>
)
},
renderGlobals (values) {
let _stringify = (data) => data ? JSON.stringify(data || {}) : "null"
return Object.keys(values || {}).map((key, i) =>
<script type="text/javascript"
key={ `global-${i}-${key}` }
dangerouslySetInnerHTML={
{__html: `window.${key}=${_stringify(values[key])}`}
}></script>
)
},
renderViewPort (values) {
let content = Object.keys(values || {}).map((key) =>
[ stringcase.spinalcase(key), values[ key ] ].join('=')
).join(',')
return <meta name="viewport" content={ content }/>
},
_addQuery (url, query) {
let joiner = /\?/.test(url) ? '&' : '?'
return [ url, query ].join(joiner)
}
},
getInitialState () {
return {}
},
getDefaultProps () {
return {
version: 'unknown',
versionKey: 'v',
viewport: {
width: 'device-width',
initialScale: '1.0'
}
}
},
render () {
const s = this
let { props } = s
let query = [ props.versionKey, props.version ].join('=')
return (
<head className="ap-head">
{ ApHead.renderCharset(props.charset) }
{ ApHead.renderTitle(props.title) }
{ ApHead.renderMetaValues(props.meta) }
{ ApHead.renderItemProps(props.itemProps) }
{ ApHead.renderIcon(props.icon, query) }
{ ApHead.renderJs(props.js, query) }
{ ApHead.renderCss(props.css, query) }
{ ApHead.renderGlobals(props.globals) }
{ ApHead.renderViewPort(props.viewport) }
{ props.children }
</head>
)
}
})
export default ApHead