diff --git a/lib/index.js b/lib/index.js index a3c93c2..1b40a18 100644 --- a/lib/index.js +++ b/lib/index.js @@ -12,6 +12,7 @@ 'use strict'; var doctypeRe = new RegExp(/^]*>\n?/im); + var metaTagRe = new RegExp(/^]*>?/igm); function hashof(string) { var hash = 0; @@ -31,13 +32,26 @@ return hash.toString(16); } - function insert(source, needle, value) { + function stripMetaTags(meta) { + if (meta) { + var replaced = meta.replace(metaTagRe, '').trim() + '\n'; + return replaced; + } + return meta; + } + + function insert(source, needle, value, after) { if (source.toLowerCase().indexOf(needle.toLowerCase()) === -1) { return null; } - var left = source.substring(0, source.toLowerCase().lastIndexOf(needle.toLowerCase())); - var right = source.substring(source.toLowerCase().lastIndexOf(needle.toLowerCase())); + var left = after + ? source.substring(0, source.toLowerCase().lastIndexOf(needle.toLowerCase()) + needle.length) + : source.substring(0, source.toLowerCase().lastIndexOf(needle.toLowerCase())); + var right = after + ? source.substring(source.toLowerCase().lastIndexOf(needle.toLowerCase()) + needle.length) + : source.substring(source.toLowerCase().lastIndexOf(needle.toLowerCase())); + var result = ''; if (left && right) { @@ -127,16 +141,19 @@ } } - // only look for a doctype at the top of the document - var doctype = (html.trim().split('\n').shift().trim().match(doctypeRe) || [])[0] || ''; - - if (doctype) { - file = file.replace(doctypeRe, doctype + '\n' + meta); - // strip from original html - } else { - file = meta + file; - } - + // Check for head tags + if (file.toLowerCase().indexOf("
") !== -1 && meta) { + file = insert(file, "", meta, true); + } else if (meta) { // there is no head, but there is meta + // only look for a doctype at the top of the document + var doctype = (html.trim().split('\n').shift().trim().match(doctypeRe) || [])[0] || ''; + if (doctype) { + // put †ry to strip out any meta tags that exist in the meta string + file = file.replace(doctypeRe, doctype + '\n' + stripMetaTags(meta)); + } else { + file = stripMetaTags(meta) + file; + } + } if (javascript) { if (file.indexOf('%code%') !== -1) { diff --git a/test/fixtures/no-doctype-no-head.html b/test/fixtures/no-doctype-no-head.html new file mode 100644 index 0000000..52b9799 --- /dev/null +++ b/test/fixtures/no-doctype-no-head.html @@ -0,0 +1,5 @@ + + +Nicely done sir.
+ + \ No newline at end of file diff --git a/test/fixtures/no-head.html b/test/fixtures/no-head.html new file mode 100644 index 0000000..21f38b7 --- /dev/null +++ b/test/fixtures/no-head.html @@ -0,0 +1,6 @@ + + + +Nicely done sir.
+ + \ No newline at end of file diff --git a/test/meta.test.js b/test/meta.test.js new file mode 100644 index 0000000..f855bce --- /dev/null +++ b/test/meta.test.js @@ -0,0 +1,83 @@ +'use strict'; +/*global describe, it, beforeEach */ +var assert = require('assert'); +var toFile = require('../'); +var fs = require('fs'); +var path = require('path'); +var cheerio = require('cheerio'); + +describe('meta', function () { + + it('should be inserted in the head, if head tag exists', function () { + var html = fs.readFileSync(path.join(__dirname, 'fixtures', 'simple.html'), 'utf8'); + + var file = toFile({ html: html, meta: '' }); + + var $ = cheerio.load(file); + assert($('head meta[name=robots]').length === 1, 'meta tag not found'); + }); + + it('should be inserted in the head, when head tag exists and no doctype', function () { + var html = fs.readFileSync(path.join(__dirname, 'fixtures', 'no-doctype.html'), 'utf8'); + + var file = toFile({ html: html, meta: '' }); + + var $ = cheerio.load(file); + assert($('head meta[name=robots]').length === 1, 'meta tag not found'); + }); + + it('should not change content if there is no meta specified', function () { + var html = fs.readFileSync(path.join(__dirname, 'fixtures', 'simple.html'), 'utf8'); + + var file = toFile({ html: html}); + + assert(html === file, 'files should match'); + }); + + it('should be prepended to file when no doctype and no head', function () { + var meta = ''; + var html = fs.readFileSync(path.join(__dirname, 'fixtures', 'no-doctype-no-head.html'), 'utf8'); + + var file = toFile({ html: html, meta: meta}); + + var header = file.substring(0, file.indexOf('')).trim(); + assert(header === meta, 'header was not prepended to file'); + }); + + it('should be prepended with tags stripped content to file when no doctype and head', function () { + var metaComment = ''; + var metaTag = '\n'; + var html = fs.readFileSync(path.join(__dirname, 'fixtures', 'no-doctype-no-head.html'), 'utf8'); + + var file = toFile({ html: html, meta: metaComment + '\n' + metaTag}); + + var header = file.substring(0, file.indexOf('')).trim(); + assert(header === metaComment, 'header was not prepended to file'); + }); + + it('should be placed after doctype when doctype exists and no head', function () { + var doctype = ''; + var meta = ''; + var html = fs.readFileSync(path.join(__dirname, 'fixtures', 'no-head.html'), 'utf8'); + + var file = toFile({ html: html, meta: meta}); + + var doctypeEnd = file.lastIndexOf(doctype) + doctype.length; + var header = file.substring(doctypeEnd, file.indexOf('')).trim(); + assert(header === meta, 'header was not prepended to file'); + }); + + it('should be placed after doctype and have meta tags stripped when doctype exists and no head', function () { + var doctype = ''; + var metaComment = ''; + var metaTag = '\n'; + var html = fs.readFileSync(path.join(__dirname, 'fixtures', 'no-head.html'), 'utf8'); + + var file = toFile({ html: html, meta: metaComment + '\n' + metaTag}); + + var doctypeEnd = file.lastIndexOf(doctype) + doctype.length; + var header = file.substring(doctypeEnd, file.indexOf('')).trim(); + assert(header === metaComment, 'header was not prepended to file'); + }); + +}); \ No newline at end of file