123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- "use strict";
- Object.defineProperty(exports, "__esModule", {
- value: true
- });
- exports["default"] = findCommentsInRaws;
- /**
- * Finds comments, both CSS comments and double slash ones, in a CSS string
- * This helper exists because PostCSS drops some inline comments (those
- * between selectors, property values, etc.)
- * https://github.com/postcss/postcss/issues/845#issuecomment-232306259
- *
- * @param {string} rawString -- the source raw CSS string
- * @return {array} array of objects with these props:
- * � type -- "css" or "double-slash"
- * � source: { start, end }
- * IMPORTANT: the function itself considers \r as a character, and counts
- * it for `start` and `end`. But if their values are passed to PostCSS's
- * result.warn(), than "\r\n" is consideren ONE CHAR (newline)!
- * � raws
- * raws.startToken -- `/*`, `/**`, `/**!`, etc.
- * raws.left -- whitespace after the comment opening marker
- * raws.text -- the full comment, including markers (//, /*)
- * raws.right -- whitespace before the comment closing marker
- * raws.endToken -- `*\/`, `**\/` for CSS comments
- * � text -- the comment text only, excluding //, /*, trailing whitespaces
- * � inlineAfter -- true, if there is something before the comment on
- * the same line
- * � inlineBefore -- true, if there is something after the comment on
- * the same line
- */
- function findCommentsInRaws(rawString) {
- var result = [];
- var comment = {};
- // Keeps track of which structure the parser is inside (string, comment,
- // url function, parens). E.g., /* comment */ inside a string doesn't
- // constitute a comment, so as url(//path)
- var modesEntered = [{
- mode: "normal",
- character: null
- }];
- var commentStart = null;
- // postcss-scss transforms //-comments into CSS comments, like so:
- // `// comment` -> `/* comment*/`. So to have a correct intex we need to
- // keep track on the added `*/` sequences
- var offset = 0;
- for (var i = 0; i < rawString.length; i++) {
- var character = rawString[i];
- var prevChar = i > 0 ? rawString[i - 1] : null;
- var nextChar = i + 1 < rawString.length ? rawString[i + 1] : null;
- var lastModeIndex = modesEntered.length - 1;
- var mode = modesEntered[lastModeIndex] && modesEntered[lastModeIndex].mode;
- switch (character) {
- // If entering/exiting a string
- case '"':
- case "'":
- {
- if (mode === "comment") {
- break;
- }
- if (mode === "string" && modesEntered[lastModeIndex].character === character && prevChar !== "\\") {
- // Exiting a string
- modesEntered.pop();
- } else {
- // Entering a string
- modesEntered.push({
- mode: "string",
- character: character
- });
- }
- break;
- }
- // Entering url, other function or parens (only url matters)
- case "(":
- {
- if (mode === "comment" || mode === "string") {
- break;
- }
- var functionNameRegSearch = /(?:^|[\n\r]|\s-|[:\s,.(){}*+/%])([\w-]*)$/.exec(rawString.substring(0, i));
- // A `\S(` can be in, say, `@media(`
- if (!functionNameRegSearch) {
- modesEntered.push({
- mode: "parens",
- character: "("
- });
- break;
- }
- var functionName = functionNameRegSearch[1];
- modesEntered.push({
- mode: functionName === "url" ? "url" : "parens",
- character: "("
- });
- break;
- }
- // Exiting url, other function or parens
- case ")":
- {
- if (mode === "comment" || mode === "string") {
- break;
- }
- modesEntered.pop();
- break;
- }
- // checking for comment
- case "/":
- {
- // Break if the / is inside a comment because we leap over the second
- // slash in // and in */, so the / is not from a marker. Also break
- // if inside a string
- if (mode === "comment" || mode === "string") {
- break;
- }
- if (nextChar === "*") {
- modesEntered.push({
- mode: "comment",
- character: "/*"
- });
- comment = {
- type: "css",
- source: {
- start: i + offset
- },
- // If i is 0 then the file/the line starts with this comment
- inlineAfter: i > 0 && rawString.substring(0, i).search(/\n\s*$/) === -1
- };
- commentStart = i;
- // Skip the next iteration as the * is already checked
- i++;
- } else if (nextChar === "/") {
- // `url(//path/to/file)` has no comment
- if (mode === "url") {
- break;
- }
- modesEntered.push({
- mode: "comment",
- character: "//"
- });
- comment = {
- type: "double-slash",
- source: {
- start: i + offset
- },
- // If i is 0 then the file/the line starts with this comment
- inlineAfter: i > 0 && rawString.substring(0, i).search(/\n\s*$/) === -1
- };
- commentStart = i;
- // Skip the next iteration as the second slash in // is already checked
- i++;
- }
- break;
- }
- // Might be a closing `*/`
- case "*":
- {
- if (mode === "comment" && modesEntered[lastModeIndex].character === "/*" && nextChar === "/") {
- comment.source.end = i + 1 + offset;
- var commentRaw = rawString.substring(commentStart, i + 2);
- var matches = /^(\/\*+[!#]?)(\s*)([\s\S]*?)(\s*)(\*+\/)$/.exec(commentRaw);
- modesEntered.pop();
- comment.raws = {
- startToken: matches[1],
- left: matches[2],
- text: commentRaw,
- right: matches[4],
- endToken: matches[5]
- };
- comment.text = matches[3];
- comment.inlineBefore = rawString.substring(i + 2).search(/^\s*\S+\s*?\n/) !== -1;
- result.push(Object.assign({}, comment));
- comment = {};
- // Skip the next loop as the / in */ is already checked
- i++;
- }
- break;
- }
- default:
- {
- var isNewline = character === "\r" && rawString[i + 1] === "\n" || character === "\n" && rawString[i - 1] !== "\r";
- // //-comments end before newline and if the code string ends
- if (isNewline || i === rawString.length - 1) {
- if (mode === "comment" && modesEntered[lastModeIndex].character === "//") {
- comment.source.end = (isNewline ? i - 1 : i) + offset;
- var _commentRaw = rawString.substring(commentStart, isNewline ? i : i + 1);
- var _matches = /^(\/+)(\s*)(.*?)(\s*)$/.exec(_commentRaw);
- modesEntered.pop();
- comment.raws = {
- startToken: _matches[1],
- left: _matches[2],
- text: _commentRaw,
- right: _matches[4]
- };
- comment.text = _matches[3];
- comment.inlineBefore = false;
- result.push(Object.assign({}, comment));
- comment = {};
- // Compensate for the `*/` added by postcss-scss
- offset += 2;
- }
- }
- break;
- }
- }
- }
- return result;
- }
|