sass-compiler
Version:
Compile Sass or Scss to CSS.
247 lines (246 loc) • 10 kB
JavaScript
;
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 (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__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.App = void 0;
const glob_1 = __importDefault(require("glob"));
const path = __importStar(require("path"));
const fs_1 = require("fs");
const FileHelper_1 = require("./FileHelper");
const SassCompileHelper_1 = require("./SassCompileHelper");
const Util_1 = require("./Util");
const helper_1 = require("./helper");
const autoprefixer_1 = __importDefault(require("autoprefixer"));
const error_1 = __importDefault(require("browserslist/error"));
const postcss_1 = __importDefault(require("postcss"));
class App {
constructor() {
this.isWatching = false;
}
static get basePath() {
return process.cwd(); //|| path.basename(vscode.window.activeTextEditor.document.fileName);
}
/**
* Compile All scss files with watch mode.
*
*/
compileAllFiles() {
this.GenerateAllCssAndMap();
}
async isSassFileIncluded(sassPath, queryPatten = '**/[^_]*.s[a|c]ss') {
let files = await this.getSassFiles(queryPatten);
return files.find(e => e === sassPath) ? true : false;
}
isASassFile(pathUrl, partialSass = false) {
const filename = path.basename(pathUrl);
return (partialSass || !filename.startsWith('_')) && (filename.endsWith('sass') || filename.endsWith('scss'));
}
//@ts-ignore
getSassFiles(queryPatten = '**/[^_]*.s[a|c]ss') {
let excludedList = helper_1.Helper.getConfigSettings('excludeList');
let includeItems = helper_1.Helper.getConfigSettings('includeItems');
let options = {
ignore: excludedList,
mark: true,
cwd: App.basePath
};
if (includeItems && includeItems.length) {
if (includeItems.length === 1) {
queryPatten = includeItems[0];
}
else {
queryPatten = `{${includeItems.join(',')}}`;
}
}
return new Promise(resolve => {
(0, glob_1.default)(queryPatten, options, (err, files) => {
if (err) {
resolve([]);
return;
}
const filePaths = files
.filter(file => this.isASassFile(file))
.map(file => path.join(App.basePath, file));
return resolve(filePaths || []);
});
});
}
findAllSaasFilesAsync(callback) {
this.getSassFiles().then(files => callback(files));
}
/**
* To Generate one One Css & Map file from Sass/Scss
* @param sassPath Sass/Scss file URI (string)
* @param targetCssUri Target CSS file URI (string)
* @param mapFileUri Target MAP file URI (string)
* @param options - Object - It includes target CSS style and some more.
*/
async GenerateCssAndMap(sassPath, targetCssUri, mapFileUri, options) {
const generateMap = helper_1.Helper.getConfigSettings("generateMap");
const compileResult = SassCompileHelper_1.SassHelper.compileOne(sassPath, targetCssUri, mapFileUri, options);
const promises = [];
let autoprefixerTarget = helper_1.Helper.getConfigSettings("autoprefix");
if (compileResult.errorString !== null) {
return false;
}
let css = compileResult.result?.css;
let map = compileResult.result?.map;
if (css === undefined) {
return false;
}
if (autoprefixerTarget === null) {
autoprefixerTarget = false;
}
if (autoprefixerTarget != false) {
try {
const autoprefixerResult = await this.autoprefix(css, map, targetCssUri, autoprefixerTarget);
css = autoprefixerResult.css;
map = autoprefixerResult.map;
}
catch (err) {
if (err instanceof error_1.default) {
return false;
}
else {
throw err;
}
}
}
if (map && generateMap) {
css += `/*# sourceMappingURL=${path.basename(targetCssUri)}.map */`;
promises.push(FileHelper_1.FileHelper.writeToOneFile(mapFileUri, map));
}
promises.push(FileHelper_1.FileHelper.writeToOneFile(targetCssUri, css));
const fileResolvers = await Promise.all(promises);
fileResolvers.forEach((fileResolver) => {
if (fileResolver.Exception) {
console.error("error :", fileResolver);
}
else {
}
});
return true;
}
static getWorkspaceFolder(filePath) {
const workspaceFolder = this.basePath;
return workspaceFolder;
}
getSassOptions(format) {
return SassCompileHelper_1.SassHelper.toSassOptions(format);
}
async GenerateAllCssAndMap() {
const sassPaths = await this.getSassFiles();
await Promise.all(sassPaths.map(async (sassPath, pathIndex) => {
const workspaceFolder = App.getWorkspaceFolder(sassPath);
const formats = helper_1.Helper.getConfigSettings("formats");
await Promise.all(formats.map(async (format, formatIndex) => {
// Each format
const options = this.getSassOptions(format), cssMapUri = await this.generateCssAndMapUri(sassPath, format);
await this.GenerateCssAndMap(sassPath, cssMapUri.css, cssMapUri.map, options);
}));
}));
}
async watch() {
const sassFiles = [];
while (true) {
this.findAllSaasFilesAsync((sassPaths) => {
sassPaths.forEach(sassPath => {
if (!sassFiles.includes(sassPath)) {
sassFiles.push(sassPath);
let formats = helper_1.Helper.getConfigSettings('formats');
//First compile
formats.forEach(async (format) => {
let options = this.getSassOptions(format);
let cssMapUri = await this.generateCssAndMapUri(sassPath, format);
this.GenerateCssAndMap(sassPath, cssMapUri.css, cssMapUri.map, options);
});
(0, fs_1.watchFile)(sassPath, () => {
formats.forEach(async (format) => {
let options = this.getSassOptions(format);
let cssMapUri = await this.generateCssAndMapUri(sassPath, format);
this.GenerateCssAndMap(sassPath, cssMapUri.css, cssMapUri.map, options);
});
});
}
});
});
await (0, Util_1.delay)(500);
}
}
async generateCssAndMapUri(filePath, format) {
const extensionName = format.extensionName || ".css";
const cssUri = filePath.substring(0, filePath.lastIndexOf(".")) + extensionName;
return {
css: cssUri,
map: cssUri + ".map",
};
}
/**
* Autoprefixes CSS properties
*
* @param css String representation of CSS to transform
* @param target What browsers to be targeted, as supported by [Browserslist](https://github.com/ai/browserslist)
*/
async autoprefix(css, map, savePath, browsers) {
const generateMap = helper_1.Helper.getConfigSettings("generateMap"), prefixer = (0, postcss_1.default)((0, autoprefixer_1.default)({
overrideBrowserslist: browsers === true ? undefined : browsers,
}));
// TODO: REMOVE - when autoprefixer can stop caching the browsers
const oldBrowserlistCache = process.env.BROWSERSLIST_DISABLE_CACHE;
if (browsers === true) {
process.env.BROWSERSLIST_DISABLE_CACHE = "1";
}
try {
const result = await prefixer.process(css, {
from: savePath,
to: savePath,
map: {
inline: false,
prev: map,
annotation: false,
},
});
result.warnings().forEach((warn) => {
const body = [];
if (warn.node.source?.input.file) {
body.push(warn.node.source.input.file + `:${warn.line}:${warn.column}`);
}
body.push(warn.text);
});
return {
css: result.css,
map: generateMap ? result.map.toString() : null,
};
}
finally {
if (browsers === true) {
process.env.BROWSERSLIST_DISABLE_CACHE = oldBrowserlistCache;
}
}
}
}
exports.App = App;