sass-formatter
Version:
TypeScript Sass formatter
241 lines (240 loc) • 11.2 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.SassFormatter = exports.defaultSassFormatterConfig = void 0;
const format_atForwardOrAtUse_1 = require("./formatters/format.atForwardOrAtUse");
const format_blockComment_1 = require("./formatters/format.blockComment");
const format_header_1 = require("./formatters/format.header");
const format_property_1 = require("./formatters/format.property");
const logger_1 = require("./logger");
const regex_1 = require("./regex/regex");
const sassTextLine_1 = require("./sassTextLine");
const state_1 = require("./state");
const utility_1 = require("./utility");
var config_1 = require("./config");
Object.defineProperty(exports, "defaultSassFormatterConfig", { enumerable: true, get: function () { return config_1.defaultSassFormatterConfig; } });
class SassFormatter {
static Format(text, config) {
const STATE = new state_1.FormattingState();
STATE.lines = text.split(/\r?\n/);
STATE.CONFIG = {
...STATE.CONFIG,
...config,
};
STATE.LINE_ENDING = STATE.CONFIG.lineEnding === 'LF' ? '\n' : '\r\n';
for (let i = 0; i < STATE.lines.length; i++) {
STATE.currentLine = i;
this.formatLine(new sassTextLine_1.SassTextLine(STATE.lines[i]), STATE);
}
if (!STATE.RESULT.endsWith(STATE.LINE_ENDING)) {
this.addNewLine(STATE);
}
if (STATE.CONFIG.debug) {
(0, logger_1.LogDebugResult)(STATE.RESULT);
(0, logger_1.ResetDebugLog)();
}
return STATE.RESULT;
}
static formatLine(line, STATE) {
if ((0, regex_1.isBlockCommentStart)(line.get())) {
STATE.CONTEXT.isInBlockComment = true;
STATE.CONTEXT.blockCommentDistance = (0, regex_1.getDistance)(line.get(), STATE.CONFIG.tabSize);
}
else if (!line.isEmptyOrWhitespace &&
STATE.CONTEXT.isInBlockComment &&
STATE.CONTEXT.blockCommentDistance >= (0, regex_1.getDistance)(line.get(), STATE.CONFIG.tabSize)) {
STATE.CONTEXT.isInBlockComment = false;
STATE.CONTEXT.blockCommentDistance = 0;
}
if (STATE.CONTEXT.ignoreLine) {
STATE.CONTEXT.ignoreLine = false;
this.addNewLine(STATE);
STATE.RESULT += line.get();
(0, logger_1.PushDebugInfo)({
title: 'IGNORED',
lineNumber: STATE.currentLine,
oldLineText: line.get(),
debug: STATE.CONFIG.debug,
newLineText: 'NULL'
});
}
else if (STATE.CONTEXT.isInBlockComment) {
this.handleCommentBlock(STATE, line);
}
else {
if ((0, regex_1.isIgnore)(line.get())) {
STATE.CONTEXT.ignoreLine = true;
this.addNewLine(STATE);
STATE.RESULT += line.get();
(0, logger_1.PushDebugInfo)({
title: 'IGNORE',
lineNumber: STATE.currentLine,
oldLineText: line.get(),
debug: STATE.CONFIG.debug,
newLineText: 'NULL'
});
}
else {
if ((0, regex_1.isSassSpace)(line.get())) {
STATE.CONTEXT.allowSpace = true;
}
// ####### Empty Line #######
if (line.isEmptyOrWhitespace ||
(STATE.CONFIG.convert ? (0, regex_1.isBracketOrWhitespace)(line.get()) : false)) {
this.handleEmptyLine(STATE, line);
}
else {
STATE.setLocalContext({
isAtKeyframesPoint: (0, utility_1.isKeyframePointAndSetIndentation)(line, STATE), // IMPORTANT: has to be first
indentation: (0, utility_1.getIndentationOffset)(line.get(), STATE.CONTEXT.indentation, STATE.CONFIG.tabSize),
isIf: /[\t ]*@if/i.test(line.get()),
isElse: /[\t ]*@else/i.test(line.get()),
isAtKeyframes: (0, regex_1.isKeyframes)(line.get()),
isReset: (0, regex_1.isReset)(line.get()),
isAnd: (0, regex_1.isAnd)(line.get()),
isProp: (0, regex_1.isProperty)(line.get()),
isAdjacentSelector: (0, regex_1.isAdjacentSelector)(line.get()),
isHtmlTag: (0, regex_1.isHtmlTag)(line.get()),
isClassOrIdSelector: (0, regex_1.isClassOrId)(line.get()),
isAtExtend: (0, regex_1.isAtExtend)(line.get()),
isInterpolatedProp: (0, regex_1.isInterpolatedProperty)(line.get()),
isInclude: (0, regex_1.isInclude)(line.get()),
isVariable: (0, regex_1.isVar)(line.get()),
isImport: (0, regex_1.isAtImport)(line.get()),
isNestPropHead: /^[\t ]* \S*[\t ]*:[\t ]*\{?$/.test(line.get())
});
if (STATE.CONFIG.debug) {
if (/\/\/[\t ]*info[\t ]*$/.test(line.get())) {
(0, logger_1.SetDebugLOCAL_CONTEXT)(STATE.LOCAL_CONTEXT);
}
}
// ####### Is @forward or @use #######
if ((0, regex_1.isAtForwardOrAtUse)(line.get())) {
this.addNewLine(STATE);
STATE.RESULT += (0, format_atForwardOrAtUse_1.FormatAtForwardOrAtUse)(line, STATE);
}
// ####### Block Header #######
else if (this.isBlockHeader(line, STATE)) {
this.addNewLine(STATE);
STATE.RESULT += (0, format_header_1.FormatBlockHeader)(line, STATE);
}
// ####### Properties or Vars #######
else if (this.isProperty(STATE)) {
STATE.CONTEXT.firstCommaHeader.exists = false;
this.addNewLine(STATE);
STATE.RESULT += (0, format_property_1.FormatProperty)(line, STATE);
}
else {
(0, logger_1.PushDebugInfo)({
title: 'NO CHANGE',
lineNumber: STATE.currentLine,
oldLineText: line.get(),
debug: STATE.CONFIG.debug,
newLineText: 'NULL'
});
this.addNewLine(STATE);
STATE.RESULT += line.get();
}
// set CONTEXT Variables
STATE.CONTEXT.wasLastLineSelector =
STATE.LOCAL_CONTEXT.isClassOrIdSelector ||
STATE.LOCAL_CONTEXT.isAdjacentSelector ||
STATE.LOCAL_CONTEXT.isHtmlTag;
}
}
}
}
static handleCommentBlock(STATE, line) {
this.addNewLine(STATE);
const edit = line.isEmptyOrWhitespace ? "" : (0, format_blockComment_1.FormatHandleBlockComment)(line.get(), STATE);
STATE.RESULT += edit;
if ((0, regex_1.isBlockCommentEnd)(line.get())) {
STATE.CONTEXT.isInBlockComment = false;
}
(0, logger_1.PushDebugInfo)({
title: 'COMMENT BLOCK',
lineNumber: STATE.currentLine,
oldLineText: STATE.lines[STATE.currentLine],
newLineText: edit,
debug: STATE.CONFIG.debug,
});
}
static handleEmptyLine(STATE, line) {
STATE.CONTEXT.firstCommaHeader.exists = false;
let pass = true; // its not useless, trust me.
/*istanbul ignore else */
if (STATE.CONFIG.deleteEmptyRows && !STATE.CONTEXT.isLastLine) {
const nextLine = new sassTextLine_1.SassTextLine(STATE.lines[STATE.currentLine + 1]);
const compact = !(0, regex_1.isProperty)(nextLine.get());
const nextLineWillBeDeleted = STATE.CONFIG.convert
? (0, regex_1.isBracketOrWhitespace)(nextLine.get())
: false;
if ((compact && !STATE.CONTEXT.allowSpace && nextLine.isEmptyOrWhitespace) ||
(compact && !STATE.CONTEXT.allowSpace && nextLineWillBeDeleted)) {
(0, logger_1.PushDebugInfo)({
title: 'EMPTY LINE: DELETE',
nextLine,
lineNumber: STATE.currentLine,
oldLineText: STATE.lines[STATE.currentLine],
newLineText: 'DELETED',
debug: STATE.CONFIG.debug,
});
pass = false;
}
}
if (line.get().length > 0 && pass) {
(0, logger_1.PushDebugInfo)({
title: 'EMPTY LINE: WHITESPACE',
lineNumber: STATE.currentLine,
oldLineText: STATE.lines[STATE.currentLine],
newLineText: 'NEWLINE',
debug: STATE.CONFIG.debug,
});
this.addNewLine(STATE);
}
else if (pass) {
(0, logger_1.PushDebugInfo)({
title: 'EMPTY LINE',
lineNumber: STATE.currentLine,
oldLineText: STATE.lines[STATE.currentLine],
newLineText: 'NEWLINE',
debug: STATE.CONFIG.debug,
});
this.addNewLine(STATE);
}
}
static isBlockHeader(line, STATE) {
return (!STATE.LOCAL_CONTEXT.isInterpolatedProp &&
!STATE.LOCAL_CONTEXT.isAtExtend &&
!STATE.LOCAL_CONTEXT.isImport &&
(STATE.LOCAL_CONTEXT.isAdjacentSelector ||
STATE.LOCAL_CONTEXT.isReset ||
STATE.LOCAL_CONTEXT.isAnd ||
(STATE.LOCAL_CONTEXT.isHtmlTag && !/^[\t ]*style[\t ]*:/.test(line.get())) ||
STATE.LOCAL_CONTEXT.isInclude ||
STATE.LOCAL_CONTEXT.isNestPropHead ||
(0, regex_1.isPseudo)(line.get()) ||
(0, regex_1.isSelectorOperator)(line.get()) ||
(0, regex_1.isStar)(line.get()) ||
(0, regex_1.isBracketSelector)(line.get()) ||
(0, regex_1.isCssSelector)(line.get())) // adds all lines that start with [@.#%=]
);
}
static isProperty(STATE) {
return (STATE.LOCAL_CONTEXT.isImport ||
STATE.LOCAL_CONTEXT.isAtExtend ||
STATE.LOCAL_CONTEXT.isVariable ||
STATE.LOCAL_CONTEXT.isInterpolatedProp ||
STATE.LOCAL_CONTEXT.isProp ||
STATE.LOCAL_CONTEXT.isAtKeyframesPoint);
}
/** Adds new Line If not first line. */
static addNewLine(STATE) {
if (!STATE.CONTEXT.isFirstLine) {
STATE.RESULT += STATE.LINE_ENDING;
}
else {
STATE.CONTEXT.isFirstLine = false;
}
}
}
exports.SassFormatter = SassFormatter;