UNPKG

@oothkoo/seo-js

Version:

A simple vanilla JavaScript SEO library for SPAs (Single Page Applications).

183 lines (176 loc) 5.36 kB
function Seo (options) { this.options = Object.assign(this.getDefaultOptions(), options) this.clearMetas() this.clearTerms() } Seo.prototype.version = '1.0.5' Seo.prototype.getDefaultOptions = function () { return { debug: false, headSelector: 'head', ignoreEmptyTagValue: true } } Seo.prototype.use = function (metas) { if (Array.isArray(metas)) { metas.forEach(function (meta) { this.metas[meta.name] = meta }.bind(this)) } else if (typeof metas === 'object') { this.metas[metas.name] = metas } } Seo.prototype.getMessageText = function (message) { return '[Seo.js] - ' + message + '.' } Seo.prototype.log = function (message) { console.log(this.getMessageText(message)) } Seo.prototype.clearMetas = function () { this.metas = {} } Seo.prototype.getMetaTypeTag = function (name) { return { name: name, selector: name, template: '<' + name + '>{value}</' + name + '>' } } Seo.prototype.tag = function (names) { if (Array.isArray(names)) { return names.map(function (name) { return this.getMetaTypeTag(name) }.bind(this)) } else if (typeof names === 'string') { return this.getMetaTypeTag(names) } } Seo.prototype.getMetaTypeName = function (name) { return { name: name, selector: 'meta[name="' + name + '"]', template: '<meta name="' + name + '" content="{value}" />' } } Seo.prototype.metaName = function (names) { if (Array.isArray(names)) { return names.map(function (name) { return this.getMetaTypeName(name) }.bind(this)) } else if (typeof names === 'string') { return this.getMetaTypeName(names) } } Seo.prototype.getMetaTypeProperty = function (name) { return { name: name, selector: 'meta[property="' + name + '"]', template: '<meta property="' + name + '" content="{value}" />' } } Seo.prototype.metaProperty = function (names) { if (Array.isArray(names)) { return names.map(function (name) { return this.getMetaTypeProperty(name) }.bind(this)) } else if (typeof names === 'string') { return this.getMetaTypeProperty(names) } } Seo.prototype.getMetaTypeLink = function (name) { return { name: name, selector: 'link[rel="' + name + '"]', template: '<link rel="' + name + '" href="{value}" />' } } Seo.prototype.link = function (names) { if (Array.isArray(names)) { return names.map(function (name) { return this.getMetaTypeLink(name) }.bind(this)) } else if (typeof names === 'string') { return this.getMetaTypeLink(names) } } Seo.prototype.throwError = function (message) { throw new Error(this.getMessageText(message)) } Seo.prototype.domRemove = function (el) { this.domFind(this.options.headSelector).removeChild(el) } Seo.prototype.domFind = function (selector) { return document.querySelector(selector) } Seo.prototype.domCreate = function (html) { var node = document.implementation.createHTMLDocument() node.body.innerHTML = html return node.body.firstChild; } Seo.prototype.domAppend = function (el1, el2) { return el1.appendChild(el2) } Seo.prototype.clear = function () { Object.keys(this.metas).forEach(function (name) { var meta = this.metas[name] var metaNode = this.domFind(meta.selector) if (metaNode) { this.domRemove(metaNode) } }.bind(this)) } Seo.prototype.update = function (metas, only) { var finalMetas = {} if (only) { finalMetas = metas } else { var defMetas = {} Object.keys(this.metas).forEach(function (name) { defMetas[name] = '' }) finalMetas = Object.assign(defMetas, metas) } Object.keys(finalMetas).forEach(function (name) { var meta = this.metas[name] if (!meta) { this.throwError('meta (' + name + ') not registered') return } var headSelector = this.options.headSelector var headNode = this.domFind(headSelector) if (!headNode) { this.throwError('head (' + headSelector + ') element not found') } var value = metas[name] || null if (value || !this.options.ignoreEmptyTagValue) { Object.keys(this.terms).forEach(function (term) { var regex = new RegExp('\{' + term + '\}', 'gi') value = value.replace(regex, this.terms[term]) }.bind(this)) var html = meta.template.replace(/\{value\}/g, value) this.options.debug && this.log(html) var metaNode = this.domFind(meta.selector) if (metaNode) { this.domRemove(metaNode) this.options.debug && this.log('meta (' + name + ') removed') } this.domAppend(headNode, this.domCreate(html)) } this.options.debug && this.log('meta name[' + name + '] value[' + value + ']') }.bind(this)) } Seo.prototype.clearTerms = function () { this.terms = {} } Seo.prototype.updateTerms = function (terms) { this.terms = Object.assign(this.terms, terms) } if (module) { module.exports = Seo }