diff --git a/.eslintrc b/.eslintrc index c56567513e3c0299242e6e06f885a1c49e24e79c..4afe180f1489ad71e5bb8a95020b0f8ef4c08afe 100644 --- a/.eslintrc +++ b/.eslintrc @@ -3,6 +3,7 @@ "browser": true, "es6": true }, + "extends": ["prettier"], "plugins": [ "react", //on react based application "import", diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000000000000000000000000000000000000..5a80b5fa1ecc512db8512eb091d1116f36a151e8 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,13 @@ +{ + "printWidth": 100, + "arrowParens": "always", + "singleQuote": true, + "tabWidth": 2, + "useTabs": false, + "semi": true, + "bracketSpacing": true, + "jsxBracketSameLine": false, + "requirePragma": false, + "proseWrap": "preserve", + "trailingComma": "all" +} \ No newline at end of file diff --git a/examples/shared/page1/page1.js b/examples/shared/page1/page1.js index c0f9eb33823700214bc7250efe762dd9388d101a..1f1b9bb67add711a39d4df22e824474296e46a01 100644 --- a/examples/shared/page1/page1.js +++ b/examples/shared/page1/page1.js @@ -8,17 +8,25 @@ class Page1 extends React.Component { <MetaTags> <title>React Meta Tags | Page1</title> <link rel="canonical" href="/page1" /> - <meta name="description" content="React meta tags handles document meta/head tags in isomorphic react with ease." /> + <meta + name="description" + content="React meta tags handles document meta/head tags in isomorphic react with ease." + /> <meta property="og:title" content="MyApp-Page1" /> <meta itemProp="test" content="Page1" /> </MetaTags> <div> <p> - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor + incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud + exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure + dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. + Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt + mollit anim id est laborum. </p> </div> </div> - ) + ); } } diff --git a/examples/shared/page2/page2.js b/examples/shared/page2/page2.js index 12f3f1f26bd385a7be166f911cfdf4e05afa4571..43f0a24c6a24fd6f3d551fabb481bbb00ce34382 100644 --- a/examples/shared/page2/page2.js +++ b/examples/shared/page2/page2.js @@ -7,18 +7,28 @@ class Page2 extends React.Component { <div className="page1"> <MetaTags> <title>React Meta Tags | Page2</title> - <link rel="canonical" href="/page2" ></link> + <link rel="canonical" href="/page2"></link> <meta name="description" content="This is page 2 description." /> <meta property="og:title" content="MyApp-page2" /> <meta itemProp="test" content="Page2" /> </MetaTags> <div> <p> - Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur? + Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque + laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi + architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas + sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione + voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit + amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut + labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis + nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi + consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam + nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla + pariatur? </p> </div> </div> - ) + ); } } diff --git a/package.json b/package.json index 05fb1d393751887107f826c173583a4751efbb01..cd5861d869737a73fc5c16d91291b615e67f9f53 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "react-meta-tags", "description": "Handle document meta/head tags in isomorphic react with ease.", - "version": "0.7.4", + "version": "1.0.0", "main": "lib/index.js", "author": "Sudhanshu Yadav", "license": "MIT", @@ -44,10 +44,12 @@ "classnames": "^2.2.3", "cross-env": "^3.1.4", "eslint": "^5.6.0", + "eslint-config-prettier": "^6.15.0", "eslint-loader": "^2.1.0", "eslint-plugin-import": "^2.14.0", "eslint-plugin-react": "^7.11.1", "nodemon": "^1.12.1", + "prettier": "^2.2.0", "react": "^16.6.0", "react-dom": "^16.6.0", "react-router": "3", diff --git a/src/meta_tags.js b/src/meta_tags.js index 31420004a12c89298f946c80d46f9e99f327f5fd..618a5c6269b69175289deca331821fdf463f69bc 100644 --- a/src/meta_tags.js +++ b/src/meta_tags.js @@ -1,9 +1,15 @@ -import React, {Component} from 'react'; +import React, { Component } from 'react'; import ReactDOM from 'react-dom'; -import {getDuplicateTitle, getDuplicateCanonical, getDuplicateMeta, appendChild, removeChild} from './utils'; +import { + getDuplicateTitle, + getDuplicateCanonical, + getDuplicateMeta, + getDuplicateElementById, + appendChild, + removeChild, +} from './utils'; import { MetaContext } from './meta_tags_context'; - /** An wrapper component to wrap element which need to shifted to head **/ class MetaTags extends Component { static contextType = MetaContext; @@ -23,10 +29,10 @@ class MetaTags extends Component { } } extractChildren() { - const {extract} = this.context; - const {children} = this.props; + const { extract } = this.context; + const { children } = this.props; - if(!children) { + if (!children) { return; } @@ -35,8 +41,8 @@ class MetaTags extends Component { } } handleChildrens() { - const {children} = this.props; - if (this.context.extract || !children){ + const { children } = this.props; + if (this.context.extract || !children) { return; } @@ -46,7 +52,7 @@ class MetaTags extends Component { const childStr = this.temporaryElement.innerHTML; //if html is not changed return - if(this.lastChildStr === childStr){ + if (this.lastChildStr === childStr) { return; } @@ -78,6 +84,10 @@ class MetaTags extends Component { if (tag === 'title') { const title = getDuplicateTitle(); if (title) removeChild(head, title); + } else if (child.id) { + // if the element has id defined remove the existing element with that id + const elm = getDuplicateElementById(child); + if (elm) removeChild(head, elm); } else if (tag === 'meta') { const meta = getDuplicateMeta(child); if (meta) removeChild(head, meta); @@ -89,7 +99,6 @@ class MetaTags extends Component { appendChild(document.head, childNodes); }); - } render() { this.extractChildren(); diff --git a/src/utils.js b/src/utils.js index 4ec014892b5af87680a00bd78e416e20f51ea55a..5f626b6c7b23579985ec91fc7646ff9f0af6cd27 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,5 +1,5 @@ -const camelCaseProps = ['itemProp']; -const uniqueIdentifiersI = ['property', 'name', 'itemprop']; +const camelCaseProps = ['itemProp']; +const uniqueIdentifiersI = ['property', 'name', 'itemprop']; const uniqueIdentifiers = uniqueIdentifiersI.concat(camelCaseProps); //case sensitive props is defined in case anyone defined the lowercase prop const uniqueIdentifiersAll = uniqueIdentifiers.concat(['id']); @@ -12,41 +12,41 @@ const uniqueIdentifiersAll = uniqueIdentifiers.concat(['id']); function filterOutMetaWithId(metas) { metas = Array.prototype.slice.call(metas || []); - return metas.filter(meta => !meta.id); + return metas.filter((meta) => !meta.id); } - export function filterAndArrangeTags(headElms) { - let title = null, canonicalLink = null; - const metas = [], rest = []; - - headElms.forEach((elm) => { - const { type, props } = elm; - if (type === 'title') { - title = elm; - } else if (type === 'link' && props.rel === 'canonical') { - canonicalLink = elm; - } else if (type === 'meta') { - metas.push(elm); - } else { - rest.push(elm); - } - }); + let title = null; + let canonicalLink = null; + const metas = []; + const rest = []; + + headElms.forEach((elm) => { + const { type, props } = elm; + if (type === 'title') { + title = elm; + } else if (type === 'link' && props.rel === 'canonical') { + canonicalLink = elm; + } else if (type === 'meta') { + metas.push(elm); + } else { + rest.push(elm); + } + }); - return [title, ...removeDuplicateMetas(metas), canonicalLink, ...rest]; + return [title, ...removeDuplicateMetas(metas), canonicalLink, ...rest]; } - function removeDuplicateMetas(metas) { const addedMeta = {}; - + //initialize all the identifiers with empty array uniqueIdentifiersAll.forEach((identifier) => { addedMeta[identifier] = []; }); const filteredMetas = []; - for (let i = metas.length - 1; i >=0 ; i--) { + for (let i = metas.length - 1; i >= 0; i--) { const meta = metas[i]; const { id } = meta.props; @@ -56,22 +56,23 @@ function removeDuplicateMetas(metas) { if (id) { addMeta = !addedMeta.id[id]; - //for any other unique identifier check if meta already available with same identifier which doesn't have id + //for any other unique identifier check if meta already available with same identifier which doesn't have id } else { - addMeta = uniqueIdentifiers.filter((identifier) => { - const identifierValue = meta.props[identifier]; - const existing = addedMeta[identifier][identifierValue]; - return existing && !existing.props.id; - }).length === 0; + addMeta = + uniqueIdentifiers.filter((identifier) => { + const identifierValue = meta.props[identifier]; + const existing = addedMeta[identifier][identifierValue]; + return existing && !existing.props.id; + }).length === 0; } if (addMeta) { filteredMetas.unshift(meta); - //add meta as added + //add meta as added uniqueIdentifiersAll.forEach((identifier) => { const identifierValue = meta.props[identifier]; - if (identifierValue) addedMeta[identifier][identifierValue] = meta; + if (identifierValue) addedMeta[identifier][identifierValue] = meta; }); } } @@ -87,28 +88,26 @@ export function getDuplicateCanonical() { return document.head.querySelectorAll('link[rel="canonical"]'); } +export function getDuplicateElementById({ id }) { + return id && document.head.querySelector(`#${id}`); +} + export function getDuplicateMeta(meta) { const head = document.head; - const { id } = meta; - - //if has id and element with id is not present than return the element - if (id) { - return id && head.querySelector(`#${id}`); - } //for any other unique identifier check if metas already available with same identifier which doesn't have id return uniqueIdentifiersI.reduce((duplicates, identifier) => { const identifierValue = meta.getAttribute(identifier); - return (identifierValue ? - duplicates.concat(filterOutMetaWithId(head.querySelectorAll(`[${identifier} = "${identifierValue}"]`))) : - duplicates); + return identifierValue + ? duplicates.concat( + filterOutMetaWithId(head.querySelectorAll(`[${identifier} = "${identifierValue}"]`)), + ) + : duplicates; }, []); } - //function to append childrens on a parent export function appendChild(parent, childrens) { - if (childrens.length === undefined) childrens = [childrens]; const docFrag = document.createDocumentFragment(); diff --git a/yarn.lock b/yarn.lock index 494c43fefdb7f2a4a6f60af76f3c84ec7400a537..d3a8de8a3d74d72b4b9857afafd1f5dc49e6c1bb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1910,6 +1910,13 @@ escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" +eslint-config-prettier@^6.15.0: + version "6.15.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.15.0.tgz#7f93f6cb7d45a92f1537a70ecc06366e1ac6fed9" + integrity sha512-a1+kOYLR8wMGustcgAjdydMsQ2A/2ipRPwRKUmfYaSxc9ZPcrku080Ctl6zrZzZNs/U82MjSv+qKREkoq3bJaw== + dependencies: + get-stdin "^6.0.0" + eslint-import-resolver-node@^0.3.1: version "0.3.2" resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz#58f15fb839b8d0576ca980413476aab2472db66a" @@ -2460,6 +2467,11 @@ get-caller-file@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" +get-stdin@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" + integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g== + get-stream@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" @@ -4120,6 +4132,11 @@ preserve@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" +prettier@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.2.0.tgz#8a03c7777883b29b37fb2c4348c66a78e980418b" + integrity sha512-yYerpkvseM4iKD/BXLYUkQV5aKt4tQPqaGW6EsZjzyu0r7sVZZNPJW4Y8MyKmicp6t42XUPcBVA+H6sB3gqndw== + private@^0.1.6: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff"