UNPKG

@hint/hint-meta-charset-utf-8

Version:

hint for best practices related to the meta charset

152 lines (151 loc) 7.13 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const utils_string_1 = require("@hint/utils-string"); const utils_types_1 = require("@hint/utils-types"); const meta_1 = require("./meta"); const i18n_import_1 = require("./i18n.import"); class MetaCharsetUTF8Hint { constructor(context) { let validated = false; context.on('scan::end', () => { validated = false; }); context.on('parse::end::html', ({ document, html, resource }) => { if (validated) { return; } validated = true; if (document.isFragment) { return; } const charsetMetaElements = document.querySelectorAll('meta[charset], meta[http-equiv="content-type" i]'); const headElement = document.querySelectorAll('head')[0]; if (charsetMetaElements.length === 0) { const fixes = []; const headElementLocation = headElement.getLocation(); if (headElementLocation.line !== -1) { const text = headElement.prependChildOuterHtml('<meta charset="utf-8">'); const fix = { location: headElement.getLocation(), text }; fixes.push(fix); } else { const htmlElement = document.querySelectorAll('html')[0]; const htmlElementLocation = htmlElement.getLocation(); if (htmlElementLocation.line !== -1) { const text = htmlElement.prependChildOuterHtml('<head><meta charset="utf-8"></head>'); const fix = { location: htmlElement.getLocation(), text }; fixes.push(fix); } } context.report(resource, (0, i18n_import_1.getMessage)('metaElementNotSpecified', context.language), { fixes, severity: utils_types_1.Severity.warning }); return; } const charsetMetaElement = charsetMetaElements[0]; if (charsetMetaElement.getAttribute('http-equiv') !== null) { context.report(resource, (0, i18n_import_1.getMessage)('metaElementShorter', context.language), { element: charsetMetaElement, fixes: [ { location: charsetMetaElement.getLocation(), text: '<meta charset="utf-8">' } ], severity: utils_types_1.Severity.warning }); } else { const metaValue = (0, utils_string_1.normalizeString)(charsetMetaElement.getAttribute('charset')); if (metaValue !== 'utf-8') { const severity = metaValue === 'utf8' ? utils_types_1.Severity.warning : utils_types_1.Severity.error; context.report(resource, (0, i18n_import_1.getMessage)('metaElementWrongValue', context.language), { element: charsetMetaElement, fixes: [ { location: charsetMetaElement.getAttributeLocation('charset'), text: 'charset="utf-8"' } ], severity }); } } const firstHeadElement = document.querySelectorAll('head :first-child')[0]; const isCharsetMetaFirstHeadElement = charsetMetaElement && firstHeadElement && charsetMetaElement.isSame(firstHeadElement); const headElementContent = document.querySelectorAll('head')[0].outerHTML; const isMetaElementFirstHeadContent = (/^<head[^>]*>\s*<meta/).test(headElementContent); const prependMetaInHeadFix = { location: headElement.getLocation(), text: headElement.prependChildOuterHtml(charsetMetaElement.outerHTML, true) }; const removeMetaElementFix = { location: charsetMetaElement.getLocation(), text: '' }; if (!isCharsetMetaFirstHeadElement || !isMetaElementFirstHeadContent) { const fixes = [prependMetaInHeadFix]; let isMetaWithinHead = false; let checkParent = charsetMetaElement.parentElement; while (checkParent) { if (headElement.isSame(checkParent)) { isMetaWithinHead = true; break; } checkParent = checkParent.parentElement; } if (!isMetaWithinHead) { fixes.unshift(removeMetaElementFix); } const severity = ((firstHeadElement === null || firstHeadElement === void 0 ? void 0 : firstHeadElement.getLocation().endOffset) || 0) <= 1024 ? utils_types_1.Severity.hint : utils_types_1.Severity.error; context.report(resource, (0, i18n_import_1.getMessage)('metaElementFirstThing', context.language), { element: charsetMetaElement, fixes, severity }); } const bodyMetaElements = document.querySelectorAll('body meta[charset], body meta[http-equiv="content-type" i]'); if (bodyMetaElements[0] && bodyMetaElements[0].isSame(charsetMetaElement)) { const fixes = [ removeMetaElementFix, prependMetaInHeadFix ]; context.report(resource, (0, i18n_import_1.getMessage)('metaElementInBody', context.language), { element: charsetMetaElement, fixes, severity: utils_types_1.Severity.error }); return; } if (charsetMetaElements.length > 1) { const metaElements = charsetMetaElements.slice(1); for (const metaElement of metaElements) { const fixes = [ { location: metaElement.getLocation(), text: '' } ]; context.report(resource, (0, i18n_import_1.getMessage)('metaElementDuplicated', context.language), { element: metaElement, fixes, severity: utils_types_1.Severity.warning }); } } }); } } exports.default = MetaCharsetUTF8Hint; MetaCharsetUTF8Hint.meta = meta_1.default;