UNPKG

sass-compiler

Version:

Compile Sass or Scss to CSS.

247 lines (246 loc) 10 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 (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;