/** * @license * Copyright (c) 2018 The Polymer Project Authors. All rights reserved. * This code may only be used under the BSD style license found at * http://polymer.github.io/LICENSE.txt * The complete set of authors may be found at * http://polymer.github.io/AUTHORS.txt * The complete set of contributors may be found at * http://polymer.github.io/CONTRIBUTORS.txt * Code distributed by Google as part of the polymer project is also * subject to an additional IP rights grant found at * http://polymer.github.io/PATENTS.txt */ import * as dom5 from 'dom5/lib/index-next'; import {Document, isPositionInsideRange, ParsedHtmlDocument, Replacement, Severity, Warning} from 'prax-analyzer'; import {HtmlRule} from '../html/rule'; import {getIndentationInside} from '../html/util'; import {registry} from '../registry'; import {indentSourceRange, stripIndentation} from '../util'; const p = dom5.predicates; const isCustomStyleV1 = p.AND( (node: dom5.Node) => !node.parentNode || !p.hasTagName('custom-style')(node.parentNode), p.hasTagName('style'), p.hasAttrValue('is', 'custom-style')); class CustomStyleExtension extends HtmlRule { code = 'custom-style-extension'; description = stripIndentation(` Warns when \`custom-style\` is used as type extension on the main document. This: Should instead be written as: `); async checkDocument(parsedDocument: ParsedHtmlDocument, _document: Document) { const warnings: Warning[] = []; const customStyleTags = [...dom5.queryAll( parsedDocument.ast, isCustomStyleV1, dom5.childNodesIncludeTemplate)]; if (customStyleTags.length === 0) { return warnings; // Early exit quick in the trivial case. } const domModules = Array.from(_document.getFeatures({kind: 'dom-module'})); for (const customStyle of customStyleTags) { const sourceRange = parsedDocument.sourceRangeForNode(customStyle); if (sourceRange === undefined) { continue; } const inDomModule = domModules .filter((domModule) => { return isPositionInsideRange( sourceRange.start, domModule.sourceRange); }) .length > 0; if (inDomModule) { continue; } const indentation = getIndentationInside(customStyle).slice(2); const fix: Replacement[] = indentSourceRange(sourceRange, ` `, parsedDocument); fix.push({ range: { file: parsedDocument.url, start: sourceRange.start, end: sourceRange.start }, replacementText: `\n${indentation}` }); fix.push({ range: { file: parsedDocument.url, start: sourceRange.end, end: sourceRange.end }, replacementText: `\n${indentation}` }); warnings.push(new Warning({ parsedDocument, code: this.code, message: `