UNPKG

eslint-plugin-vue-scoped-css

Version:
274 lines (273 loc) 11.5 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.CSSParser = void 0; const postcss = __importStar(require("postcss")); const postcss_safe_parser_1 = __importDefault(require("postcss-safe-parser")); const css_selector_parser_1 = require("./selector/css-selector-parser"); const ast_1 = require("../ast"); const utils_1 = require("./utils"); const css_nodes_1 = require("../utils/css-nodes"); const utils_2 = require("../../utils/utils"); class CSSParser { constructor(sourceCode, lang) { this._selectorParser = null; this.anyErrors = []; this.sourceCode = sourceCode; this.commentContainer = []; this.lang = lang; } parse(css, offsetLocation) { const { sourceCode } = this; this.commentContainer = []; this._selectorParser = this.createSelectorParser(); this.anyErrors = []; try { const postcssRoot = this.parseInternal(css); const rootNode = this._postcssNodeToASTNode(offsetLocation, postcssRoot); rootNode.comments = this.commentContainer; rootNode.errors.push(...this.collectErrors(this.anyErrors, offsetLocation)); return rootNode; } catch (e) { const startIndex = sourceCode.getIndexFromLoc(offsetLocation); const endIndex = startIndex + css.length; const styleLoc = { start: offsetLocation, end: sourceCode.getLocFromIndex(endIndex), }; return new ast_1.VCSSStyleSheet(null, styleLoc, startIndex, endIndex, { errors: this.collectErrors([...this.anyErrors, e], offsetLocation), lang: this.lang, }); } } addError(error) { this.anyErrors.push(error); } collectErrors(errors, offsetLocation) { const errorNodes = []; const duplicate = new Set(); for (const error of errors) { const errorLoc = error.line != null && error.column != null ? getESLintLineAndColumnFromPostCSSPosition(offsetLocation, error) : offsetLocation; const message = error.reason || error.message; const key = `[${errorLoc.line}:${errorLoc.column}]: ${message}`; if (duplicate.has(key)) { continue; } duplicate.add(key); const errorIndex = this.sourceCode.getIndexFromLoc(errorLoc); errorNodes.push(new ast_1.VCSSParsingError(null, { start: errorLoc, end: errorLoc, }, errorIndex, errorIndex, { lang: this.lang, message, })); } return errorNodes; } get selectorParser() { return (this._selectorParser || (this._selectorParser = this.createSelectorParser())); } _postcssNodeToASTNode(offsetLocation, node, parent) { const { sourceCode } = this; const startLoc = getESLintLineAndColumnFromPostCSSNode(offsetLocation, node, "start") || { line: 0, column: 1 }; const start = sourceCode.getIndexFromLoc(startLoc); const endLoc = getESLintLineAndColumnFromPostCSSNode(offsetLocation, node, "end") || sourceCode.getLocFromIndex(sourceCode.getIndexFromLoc(offsetLocation) + node.source.input.css.length); const end = sourceCode.getIndexFromLoc(endLoc); const loc = { start: startLoc, end: endLoc, }; const astNode = this[typeToConvertMethodName(node.type)](node, loc, start, end, parent); if (astNode == null) { return null; } if ((0, utils_1.isPostCSSContainer)(node) && (0, css_nodes_1.isVCSSContainerNode)(astNode)) { astNode.nodes = node.nodes .map((n) => this._postcssNodeToASTNode(offsetLocation, n, astNode)) .filter(utils_2.isDefined); } return astNode; } parseInternal(css) { try { return postcss.parse(css); } catch (e) { this.addError(e); return (0, postcss_safe_parser_1.default)(css); } } createSelectorParser() { return new css_selector_parser_1.CSSSelectorParser(this.sourceCode, this.commentContainer); } convertRootNode(node, loc, start, end) { return new ast_1.VCSSStyleSheet(node, loc, start, end, { lang: this.lang }); } convertRuleNode(node, loc, start, end, parent) { var _a, _b, _c; const astNode = new ast_1.VCSSStyleRule(node, loc, start, end, { parent, rawSelectorText: (_b = (_a = this.getRaw(node, "selector")) === null || _a === void 0 ? void 0 : _a.raw) !== null && _b !== void 0 ? _b : null, }); astNode.selectors = this.selectorParser.parse(astNode.rawSelectorText, astNode.loc.start, astNode); if ((_c = this.getRaw(node, "between")) === null || _c === void 0 ? void 0 : _c.trim()) { this.parseRuleRawsBetween(node, astNode); } return astNode; } parseRuleRawsBetween(node, astNode) { var _a, _b; const between = this.getRaw(node, "between"); const rawSelector = (_b = (_a = this.getRaw(node, "selector")) === null || _a === void 0 ? void 0 : _a.raw) !== null && _b !== void 0 ? _b : node.selector; const betweenStart = astNode.range[0] + rawSelector.length; const postcssRoot = this.parseInternal(between || ""); this._postcssNodeToASTNode(this.sourceCode.getLocFromIndex(betweenStart), postcssRoot); } convertAtruleNode(node, loc, start, end, parent) { var _a, _b, _c, _d, _e; const astNode = new ast_1.VCSSAtRule(node, loc, start, end, { parent, rawParamsText: (_b = (_a = this.getRaw(node, "params")) === null || _a === void 0 ? void 0 : _a.raw) !== null && _b !== void 0 ? _b : null, identifier: (_c = this.getRaw(node, "identifier")) !== null && _c !== void 0 ? _c : "@", }); if (node.name === "nest") { const paramsStartIndex = astNode.range[0] + astNode.identifier.length + astNode.name.length + (this.getRaw(node, "afterName") || "").length; astNode.selectors = this.selectorParser.parse(astNode.rawParamsText, this.sourceCode.getLocFromIndex(paramsStartIndex), astNode); } if ((_d = this.getRaw(node, "afterName")) === null || _d === void 0 ? void 0 : _d.trim()) { this.parseAtruleRawsAfterName(node, astNode); } if ((_e = this.getRaw(node, "between")) === null || _e === void 0 ? void 0 : _e.trim()) { this.parseAtruleRawsBetween(node, astNode); } return astNode; } parseAtruleRawsAfterName(node, astNode) { const afterName = this.getRaw(node, "afterName"); const afterNameStart = astNode.range[0] + astNode.identifier.length + astNode.name.length; const postcssRoot = this.parseInternal(afterName || ""); this._postcssNodeToASTNode(this.sourceCode.getLocFromIndex(afterNameStart), postcssRoot); } parseAtruleRawsBetween(node, astNode) { var _a, _b; const between = this.getRaw(node, "between"); const rawParams = (_b = (_a = this.getRaw(node, "params")) === null || _a === void 0 ? void 0 : _a.raw) !== null && _b !== void 0 ? _b : node.params; const betweenStart = astNode.range[0] + astNode.identifier.length + astNode.name.length + (this.getRaw(node, "afterName") || "").length + rawParams.length; const postcssRoot = this.parseInternal(between || ""); this._postcssNodeToASTNode(this.sourceCode.getLocFromIndex(betweenStart), postcssRoot); } convertDeclNode(node, loc, start, end, parent) { let property = node.prop; let starLength = 1; let textProp = this.sourceCode.text.slice(start, start + property.length); while (property !== textProp) { property = textProp.slice(0, starLength) + node.prop; starLength++; textProp = this.sourceCode.text.slice(start, start + property.length); } return new ast_1.VCSSDeclarationProperty(node, loc, start, end, { parent, property, }); } convertCommentNode(node, loc, start, end, parent) { this.commentContainer.push(new ast_1.VCSSComment(node, node.text, loc, start, end, { parent })); return null; } convertUnknownTypeNode(node, loc, start, end, parent) { return new ast_1.VCSSUnknown(node, loc, start, end, { parent, unknownType: node.type, }); } getRaw(node, keyName) { return node.raws[keyName]; } } exports.CSSParser = CSSParser; function getESLintLineAndColumnFromPostCSSPosition(offsetLocation, loc) { let { line } = loc; let column = loc.column - 1; if (line === 1) { line = offsetLocation.line; column = offsetLocation.column + column; } else { line = offsetLocation.line + line - 1; } return { line, column }; } function getESLintLineAndColumnFromPostCSSNode(offsetLocation, node, locName) { const sourceLoc = node.source[locName]; if (!sourceLoc) { return null; } const { line, column } = getESLintLineAndColumnFromPostCSSPosition(offsetLocation, sourceLoc); if (locName === "end" && node.type !== "root") { return { line, column: column + 1 }; } return { line, column }; } const convertNodeTypes = { root: "convertRootNode", atrule: "convertAtruleNode", rule: "convertRuleNode", decl: "convertDeclNode", comment: "convertCommentNode", }; function typeToConvertMethodName(type) { return convertNodeTypes[type] || "convertUnknownTypeNode"; }