Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

react-document-meta

Package Overview
Dependencies
Maintainers
1
Versions
23
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-document-meta - npm Package Compare versions

Comparing version 0.1.4 to 1.0.0

.eslintignore

90

dist/__tests__/basic.test.js

@@ -9,71 +9,55 @@ 'use strict';

var _React = require('react/addons');
var _reactAddons = require('react/addons');
var _React2 = _interopRequireDefault(_React);
var _reactAddons2 = _interopRequireDefault(_reactAddons);
var _DocumentMeta = require('../index');
var _ = require('../');
var _DocumentMeta2 = _interopRequireDefault(_DocumentMeta);
var _2 = _interopRequireDefault(_);
var _removeDocumentMeta = require('../utils');
describe('DocumentMeta', function () {
before(function () {
_2['default'].canUseDOM = false;
});
var _getElements$getElement$getAttr = require('./test-utils');
describe('.rewind()', function () {
it('clears the mounted instances', function () {
_reactAddons2['default'].renderToStaticMarkup(_reactAddons2['default'].createElement(_2['default'], { title: 'a' }, _reactAddons2['default'].createElement(_2['default'], { title: 'b' }, _reactAddons2['default'].createElement(_2['default'], { title: 'c' }))));
_assert2['default'].deepEqual(_2['default'].peek(), { title: 'c' });
_2['default'].rewind();
_assert2['default'].strictEqual(_2['default'].peek(), undefined);
});
describe('React Document Meta', function () {
var document = global.document;
it('returns the latest document meta', function () {
var title = 'cheese';
_reactAddons2['default'].renderToStaticMarkup(_reactAddons2['default'].createElement(_2['default'], { title: 'a' }, _reactAddons2['default'].createElement(_2['default'], { title: 'b' }, _reactAddons2['default'].createElement(_2['default'], { title: title }))));
_assert2['default'].deepEqual(_2['default'].rewind(), { title: title });
});
var docMeta = {
title: 'This is a document title',
description: 'This meta value is describing the page we are looking at',
canonical: 'http://domain.tld/path/to/page',
meta: {
charset: 'utf-8',
name: {
keywords: 'react,document,meta,tags'
}
},
link: {
rel: {
stylesheet: ['http://domain.tld/css/vendor.css', 'http://domain.tld/css/styles.css']
}
}
};
beforeEach(function () {
_removeDocumentMeta.removeDocumentMeta();
_React2['default'].addons.TestUtils.renderIntoDocument(_React2['default'].createElement(_DocumentMeta2['default'], docMeta));
it('returns undefined if no mounted instances exist', function () {
_reactAddons2['default'].renderToStaticMarkup(_reactAddons2['default'].createElement(_2['default'], { title: 'a' }, _reactAddons2['default'].createElement(_2['default'], { title: 'b' }, _reactAddons2['default'].createElement(_2['default'], { title: 'c' }))));
_2['default'].rewind();
_assert2['default'].strictEqual(_2['default'].peek(), undefined);
});
});
it('should render document.title / <title> according to the title-attr', function () {
_assert2['default'].strictEqual(document.title, docMeta.title);
});
describe('.renderAsReact()', function () {
it('returns the latest document meta as an array of React components', function () {
_reactAddons2['default'].renderToStaticMarkup(_reactAddons2['default'].createElement(_2['default'], { title: 'a' }, _reactAddons2['default'].createElement(_2['default'], { title: 'b' }, _reactAddons2['default'].createElement(_2['default'], { title: 'c' }))));
it('should render <meta name="description" content="..."> according to the description-attr', function () {
_assert2['default'].strictEqual(_getElements$getElement$getAttr.getAttr('meta[name=description]', 'content'), docMeta.description);
});
var rendered = _2['default'].renderAsReact();
it('should render <link rel="canonical" href="..." according to the canonical-attr', function () {
_assert2['default'].strictEqual(_getElements$getElement$getAttr.getAttr('link[rel=canonical]', 'href'), docMeta.canonical);
});
it('should render simple meta tags, eg. <meta charset="...">', function () {
_assert2['default'].strictEqual(_getElements$getElement$getAttr.getAttr('meta[charset]', 'charset'), docMeta.meta.charset);
});
it('should render normal meta tags, eg. <meta name="..." content="...">', function () {
Object.keys(docMeta.meta.name).reduce(function (name) {
_assert2['default'].strictEqual(_getElements$getElement$getAttr.getAttr('meta[name=' + name + ']', 'content'), docMeta.meta.name[name], '<meta name="' + name + '" ... /> has not been rendered correctly');
_assert2['default'].ok(Array.isArray(rendered));
_assert2['default'].strictEqual(rendered.length, 1);
_assert2['default'].strictEqual(rendered[0].type, 'title');
_assert2['default'].strictEqual(rendered[0]._store.props.children, 'c');
});
});
it('should render normal link tags, eg. <link rel="..." href="...">', function () {
Object.keys(docMeta.link.rel).reduce(function (rel) {
var values = Array.isArray(docMeta.link.rel[rel]) ? docMeta.link.rel[rel] : [docMeta.link.rel[rel]];
var elements = _getElements$getElement$getAttr.getElements('link[rel=' + rel + ']');
elements.forEach(function (element, idx) {
_assert2['default'].strictEqual(element.getAttribute('content'), values[idx], '<link rel="' + rel + '" ... /> has not been rendered correctly');
});
// assert.strictEqual( getAttr(`link[rel=${ rel }]`, 'content'), docMeta.link.rel[rel], `<link rel="${ rel }" ... /> has not been rendered correctly` );
describe('.renderAsHTML()', function () {
it('returns the latest document meta as HTML', function () {
_reactAddons2['default'].renderToStaticMarkup(_reactAddons2['default'].createElement(_2['default'], { title: 'a' }, _reactAddons2['default'].createElement(_2['default'], { title: 'b' }, _reactAddons2['default'].createElement(_2['default'], { title: 'c' }))));
_assert2['default'].strictEqual(_2['default'].renderAsHTML(), '<title>c</title>');
});
});
});

@@ -13,19 +13,19 @@ 'use strict';

function _defineProperty(obj, key, value) { return Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
var _React = require('react');
var _react = require('react');
var _React2 = _interopRequireDefault(_React);
var _react2 = _interopRequireDefault(_react);
var _canUseDOM = require('react/lib/ExecutionEnvironment');
var _reactLibExecutionEnvironment = require('react/lib/ExecutionEnvironment');
var _createSideEffect = require('react-side-effect');
var _reactSideEffect = require('react-side-effect');
var _createSideEffect2 = _interopRequireDefault(_createSideEffect);
var _reactSideEffect2 = _interopRequireDefault(_reactSideEffect);
var _clone$defaults$forEach = require('./utils');
var _utils = require('./utils');
var _meta = {};
function getProps(propsList) {
function reducePropsTostate(propsList) {
var props = {};

@@ -36,12 +36,12 @@

for (var i = propsList.length - 1; extend && i >= 0; i--) {
var _props = _clone$defaults$forEach.clone(propsList[i]);
var _props = (0, _utils.clone)(propsList[i]);
if (_props.description) {
_clone$defaults$forEach.defaults(_props, { meta: { name: { description: _props.description } } });
(0, _utils.defaults)(_props, { meta: { name: { description: _props.description } } });
}
if (_props.canonical) {
_clone$defaults$forEach.defaults(_props, { link: { rel: { canonical: _props.canonical } } });
(0, _utils.defaults)(_props, { link: { rel: { canonical: _props.canonical } } });
}
_clone$defaults$forEach.defaults(props, _props);
(0, _utils.defaults)(props, _props);
extend = _props.hasOwnProperty('extend');

@@ -65,2 +65,11 @@ }

function handleStateChangeOnClient(props) {
_meta = props;
if (_reactLibExecutionEnvironment.canUseDOM) {
document.title = props.title || '';
insertDocumentMeta(props);
}
}
function ograph(p) {

@@ -90,3 +99,3 @@ if (!p.meta) {

function parseTags(tagName) {
var props = arguments[1] === undefined ? {} : arguments[1];
var props = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];

@@ -99,3 +108,4 @@ var tags = [];

tags.push(_defineProperty({
tagName: tagName }, groupKey, group));
tagName: tagName
}, groupKey, group));
return;

@@ -109,3 +119,4 @@ }

tags.push((_tags$push2 = {
tagName: tagName }, _defineProperty(_tags$push2, groupKey, key), _defineProperty(_tags$push2, contentKey, value), _tags$push2));
tagName: tagName
}, _defineProperty(_tags$push2, groupKey, key), _defineProperty(_tags$push2, contentKey, value), _tags$push2));
});

@@ -126,3 +137,3 @@ });

function removeDocumentMeta() {
_clone$defaults$forEach.forEach(document.querySelectorAll('head [data-rdm]'), removeNode);
(0, _utils.forEach)(document.querySelectorAll('head [data-rdm]'), removeNode);
}

@@ -148,3 +159,3 @@

_clone$defaults$forEach.forEach(getTags(props), insertDocumentMetaNode);
(0, _utils.forEach)(getTags(props), insertDocumentMetaNode);
}

@@ -166,5 +177,5 @@

if (tagName === 'meta') {
return _React2['default'].createElement('meta', _extends({}, attr, { key: i++, 'data-rdm': true }));
return _react2['default'].createElement('meta', _extends({}, attr, { key: i++, 'data-rdm': true }));
} else if (tagName === 'link') {
return _React2['default'].createElement('link', _extends({}, attr, { key: i++, 'data-rdm': true }));
return _react2['default'].createElement('link', _extends({}, attr, { key: i++, 'data-rdm': true }));
}

@@ -176,3 +187,3 @@

if (meta.title) {
tags.push(_React2['default'].createElement(
tags.push(_react2['default'].createElement(
'title',

@@ -193,3 +204,3 @@ { key: i++ },

return _React2['default'].renderToStaticMarkup(_React2['default'].createElement(
return _react2['default'].renderToStaticMarkup(_react2['default'].createElement(
'div',

@@ -201,39 +212,34 @@ null,

function handleChange(propsList) {
_meta = getProps(propsList);
if (_canUseDOM.canUseDOM) {
document.title = _meta.title || '';
insertDocumentMeta(_meta);
}
}
var mixin = {
var DocumentMeta = _react2['default'].createClass({
displayName: 'DocumentMeta',
propTypes: {
title: _React2['default'].PropTypes.string,
description: _React2['default'].PropTypes.string,
canonical: _React2['default'].PropTypes.string,
meta: _React2['default'].PropTypes.objectOf(_React2['default'].PropTypes.oneOfType([_React2['default'].PropTypes.string, _React2['default'].PropTypes.objectOf(_React2['default'].PropTypes.string)])),
link: _React2['default'].PropTypes.objectOf(_React2['default'].PropTypes.objectOf(_React2['default'].PropTypes.oneOfType([_React2['default'].PropTypes.string, _React2['default'].PropTypes.arrayOf(_React2['default'].PropTypes.string)]))),
auto: _React2['default'].PropTypes.objectOf(_React2['default'].PropTypes.bool)
title: _react2['default'].PropTypes.string,
description: _react2['default'].PropTypes.string,
canonical: _react2['default'].PropTypes.string,
meta: _react2['default'].PropTypes.objectOf(_react2['default'].PropTypes.oneOfType([_react2['default'].PropTypes.string, _react2['default'].PropTypes.objectOf(_react2['default'].PropTypes.string)])),
link: _react2['default'].PropTypes.objectOf(_react2['default'].PropTypes.objectOf(_react2['default'].PropTypes.oneOfType([_react2['default'].PropTypes.string, _react2['default'].PropTypes.arrayOf(_react2['default'].PropTypes.string)]))),
auto: _react2['default'].PropTypes.objectOf(_react2['default'].PropTypes.bool)
},
statics: {
peek: function peek() {
return _meta;
},
render: function render() {
return this.props.children ? _react2['default'].Children.only(this.props.children) : null;
}
});
rewind: function rewind(opts) {
var meta = _clone$defaults$forEach.clone(_meta);
this.dispose();
return render(meta, opts);
}
}
var DocumentMetaWithSideEffect = (0, _reactSideEffect2['default'])(reducePropsTostate, handleStateChangeOnClient)(DocumentMeta);
DocumentMetaWithSideEffect.renderAsReact = function rewindAsReact() {
var meta = (0, _utils.clone)(DocumentMetaWithSideEffect.peek());
DocumentMetaWithSideEffect.rewind();
return render(meta, { asReact: true });
};
var DocumentMeta = _createSideEffect2['default'](handleChange, mixin);
DocumentMetaWithSideEffect.renderAsHTML = function rewindAsHTML() {
var meta = DocumentMetaWithSideEffect.peek();
DocumentMetaWithSideEffect.rewind();
return render(meta, { asHtml: true });
};
exports['default'] = DocumentMeta;
exports['default'] = DocumentMetaWithSideEffect;
module.exports = exports['default'];

@@ -0,1 +1,5 @@

/**
* Tools
*/
'use strict';

@@ -6,6 +10,2 @@

});
/**
* Tools
*/
exports.clone = clone;

@@ -12,0 +12,0 @@ exports.defaults = defaults;

import assert from 'assert';
import React from 'react/addons';
import DocumentMeta from '../index';
import { removeDocumentMeta } from '../utils';
import { getElements, getElement, getAttr } from './test-utils';
import DocumentMeta from '../';
describe('React Document Meta', () => {
const document = global.document;
describe('DocumentMeta', () => {
before(() => {
DocumentMeta.canUseDOM = false;
});
const docMeta = {
title: 'This is a document title',
description: 'This meta value is describing the page we are looking at',
canonical: 'http://domain.tld/path/to/page',
meta: {
charset: 'utf-8',
name: {
keywords: 'react,document,meta,tags'
}
},
link: {
rel: {
stylesheet: [
'http://domain.tld/css/vendor.css',
'http://domain.tld/css/styles.css'
]
}
}
};
describe('.rewind()', () => {
it('clears the mounted instances', () => {
React.renderToStaticMarkup(
React.createElement(DocumentMeta, {title: 'a'},
React.createElement(DocumentMeta, {title: 'b'},
React.createElement(DocumentMeta, {title: 'c'})
)
)
);
assert.deepEqual(DocumentMeta.peek(), {title: 'c'});
DocumentMeta.rewind();
assert.strictEqual(DocumentMeta.peek(), undefined);
});
beforeEach(() => {
removeDocumentMeta();
React.addons.TestUtils.renderIntoDocument( <DocumentMeta {...docMeta} /> );
});
it('returns the latest document meta', () => {
const title = 'cheese';
React.renderToStaticMarkup(
React.createElement(DocumentMeta, {title: 'a'},
React.createElement(DocumentMeta, {title: 'b'},
React.createElement(DocumentMeta, {title})
)
)
);
assert.deepEqual(DocumentMeta.rewind(), { title });
});
it('should render document.title / <title> according to the title-attr', () => {
assert.strictEqual( document.title, docMeta.title );
it('returns undefined if no mounted instances exist', () => {
React.renderToStaticMarkup(
React.createElement(DocumentMeta, {title: 'a'},
React.createElement(DocumentMeta, {title: 'b'},
React.createElement(DocumentMeta, {title: 'c'})
)
)
);
DocumentMeta.rewind();
assert.strictEqual(DocumentMeta.peek(), undefined);
});
});
it('should render <meta name="description" content="..."> according to the description-attr', () => {
assert.strictEqual( getAttr('meta[name=description]', 'content'), docMeta.description );
});
describe('.renderAsReact()', () => {
it('returns the latest document meta as an array of React components', () => {
React.renderToStaticMarkup(
React.createElement(DocumentMeta, {title: 'a'},
React.createElement(DocumentMeta, {title: 'b'},
React.createElement(DocumentMeta, {title: 'c'})
)
)
);
it('should render <link rel="canonical" href="..." according to the canonical-attr', () => {
assert.strictEqual( getAttr('link[rel=canonical]', 'href'), docMeta.canonical );
});
const rendered = DocumentMeta.renderAsReact();
it('should render simple meta tags, eg. <meta charset="...">', () => {
assert.strictEqual( getAttr('meta[charset]', 'charset'), docMeta.meta.charset );
assert.ok(Array.isArray(rendered));
assert.strictEqual(rendered.length, 1);
assert.strictEqual(rendered[0].type, 'title');
assert.strictEqual(rendered[0]._store.props.children, 'c');
});
});
it('should render normal meta tags, eg. <meta name="..." content="...">', () => {
Object.keys( docMeta.meta.name ).reduce(( name ) => {
assert.strictEqual( getAttr(`meta[name=${ name }]`, 'content'), docMeta.meta.name[name], `<meta name="${ name }" ... /> has not been rendered correctly` );
describe('.renderAsHTML()', () => {
it('returns the latest document meta as HTML', () => {
React.renderToStaticMarkup(
React.createElement(DocumentMeta, {title: 'a'},
React.createElement(DocumentMeta, {title: 'b'},
React.createElement(DocumentMeta, {title: 'c'})
)
)
);
assert.strictEqual(DocumentMeta.renderAsHTML(), '<title>c</title>');
});
});
it('should render normal link tags, eg. <link rel="..." href="...">', () => {
Object.keys( docMeta.link.rel ).reduce(( rel ) => {
const values = Array.isArray(docMeta.link.rel[rel]) ? docMeta.link.rel[rel] : [ docMeta.link.rel[rel] ];
const elements = getElements( `link[rel=${ rel }]` );
elements.forEach(( element, idx ) => {
assert.strictEqual( element.getAttribute('content'), values[idx], `<link rel="${ rel }" ... /> has not been rendered correctly` );
});
// assert.strictEqual( getAttr(`link[rel=${ rel }]`, 'content'), docMeta.link.rel[rel], `<link rel="${ rel }" ... /> has not been rendered correctly` );
});
});
});
});
import React from 'react';
import { canUseDOM } from 'react/lib/ExecutionEnvironment';
import createSideEffect from 'react-side-effect';
import withSideEffect from 'react-side-effect';

@@ -13,3 +13,3 @@ import {

function getProps ( propsList ) {
function reducePropsTostate ( propsList ) {
const props = {};

@@ -29,3 +29,2 @@

defaults(props, _props);

@@ -50,2 +49,11 @@ extend = _props.hasOwnProperty('extend');

function handleStateChangeOnClient ( props ) {
_meta = props;
if ( canUseDOM ) {
document.title = props.title || '';
insertDocumentMeta( props );
}
}
function ograph ( p ) {

@@ -140,3 +148,3 @@ if (!p.meta) {

function renderTag ( entry ) {
function renderTag ( entry ) {
const { tagName, ...attr } = entry;

@@ -170,12 +178,5 @@

function handleChange ( propsList ) {
_meta = getProps( propsList );
if ( canUseDOM ) {
document.title = _meta.title || '';
insertDocumentMeta( _meta );
}
}
const mixin = {
const DocumentMeta = React.createClass({
displayName: 'DocumentMeta',

@@ -204,17 +205,24 @@

statics: {
peek: function () {
return _meta;
},
render: function render () {
return this.props.children ? React.Children.only(this.props.children) : null;
}
});
rewind: function ( opts ) {
const meta = clone(_meta);
this.dispose();
return render( meta, opts );
}
}
const DocumentMetaWithSideEffect = withSideEffect(
reducePropsTostate,
handleStateChangeOnClient
)(DocumentMeta);
DocumentMetaWithSideEffect.renderAsReact = function rewindAsReact () {
const meta = clone(DocumentMetaWithSideEffect.peek());
DocumentMetaWithSideEffect.rewind();
return render( meta, { asReact: true } );
};
const DocumentMeta = createSideEffect( handleChange, mixin );
DocumentMetaWithSideEffect.renderAsHTML = function rewindAsHTML () {
const meta = DocumentMetaWithSideEffect.peek();
DocumentMetaWithSideEffect.rewind();
return render( meta, { asHtml: true } );
};
export default DocumentMeta;
export default DocumentMetaWithSideEffect;
{
"name": "react-document-meta",
"version": "0.1.4",
"version": "1.0.0",
"description": "Declarative, nested and stateful HTML document meta tags for React",

@@ -18,18 +18,20 @@ "main": "./dist/index",

"peerDependencies": {
"react": ">= 0.11.0"
"react": ">= 0.13.0"
},
"devDependencies": {
"babel": "5.2.9",
"babel-core": "5.2.9",
"babel-loader": "5.0.0",
"jsdom": "5.3.0",
"mocha": "2.2.4",
"mocha-clean": "0.4.0",
"react": "0.13.2",
"react-hot-loader": "1.2.6",
"webpack": "1.8.11",
"webpack-dev-server": "1.8.2"
"babel": "^5.8.23",
"babel-core": "^5.8.23",
"babel-eslint": "^4.1.1",
"babel-loader": "^5.3.2",
"eslint": "^1.3.1",
"eslint-plugin-react": "^3.3.1",
"jsdom": "^6.3.0",
"mocha": "^2.3.0",
"react": "^0.13.0",
"react-hot-loader": "^1.3.0",
"webpack": "^1.12.1",
"webpack-dev-server": "^1.10.1"
},
"dependencies": {
"react-side-effect": "0.3.0"
"react-side-effect": "^1.0.1"
},

@@ -36,0 +38,0 @@ "repository": "kodyl/react-document-meta",

@@ -1,2 +0,2 @@

React Document Meta [![Build Status](https://travis-ci.org/boligbesked/react-document-meta.svg)](https://travis-ci.org/boligbesked/react-document-meta) [![npm version](https://badge.fury.io/js/react-document-meta.svg)](http://badge.fury.io/js/react-document-meta)
React Document Meta [![Build Status](https://travis-ci.org/kodyl/react-document-meta.svg)](https://travis-ci.org/kodyl/react-document-meta) [![npm version](https://badge.fury.io/js/react-document-meta.svg)](http://badge.fury.io/js/react-document-meta)
===================

@@ -17,7 +17,11 @@

Peer dependencies: React >= 0.11.0
Note: React Side Effect requires React 0.13+ - and so does React Document Meta.
It has only been testes with React 0.13, but should work back to 0.11 - testing is more than welcome!
Upgrading from 0.1.x to 1.x
-------------------
As React Side Effect has been upgraded there is a few breaking changes, which is found in the [changelog](CHANGELOG.md).
Features

@@ -32,3 +36,3 @@ -------------------

```
```javascript
import React from 'react';

@@ -66,4 +70,4 @@ import DocumentMeta from 'react-document-meta';

### Automatic meta tags
`react-document-meta` has the ability to generate meta tags based on the already provided meta data. Currently only open graph title, description and url is supported, which uses the data from `title`, `description` and `canonical`, and only in the case where the values has not be explicit set for `og:title`, `og:description` or `og:url` respectively.
### Automatic Meta Tags
`react-document-meta` has the ability to generate meta tags based on the already provided meta data. Currently only open graph title, description and url is supported, which uses the data from `title`, `description` and `canonical`, and only in the case where the values has not been explicit set for `og:title`, `og:description` or `og:url` respectively.

@@ -73,6 +77,7 @@

-------------------
When using `react-document-meta` in a project with server-side rendering, you would like to have the final meta data chunk available in your HTML output. You can achieve this by calling `DocumentMeta.rewind();` with an optional argument, about how you would like the response. When called with no arguments, you will get the combined meta data as an object as set. `DocumentMeta.rewind( { asReact: true } );` will render to React markup and `DocumentMeta.rewind( { asHtml: true } );` will render to static markup.
When using `react-document-meta` in a project with server-side rendering, you would like to have the final meta data chunk available in your HTML output. You can achieve this by calling `DocumentMeta.rewind()`.
**Notice: This argument syntax is very likely to change in v1.0.0**
Instead of getting a plain object, you can have the module return the meta as either React components or a HTML string. This is achieved by calling `DocumentMeta.renderAsReact()` or `DocumentMeta.renderAsHTML()`.
TODO:

@@ -79,0 +84,0 @@ -------------------

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc