You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
vizality/renderer/src/compilers/SCSS.js

97 lines
2.6 KiB

const { promises: { readFile }, existsSync, statSync } = require('fs');
const { info: sassInfo } = require('sass');
const { join, dirname, posix, sep } = require('path');
const Compiler = require('./Compiler');
/**
* SCSS compiler.
* @class
* @extends Compiler
*/
module.exports = class SCSS extends Compiler {
async listFiles () {
return [
this.file,
...(await this._resolveDeps(this.file))
];
}
_compile () {
return vizality.native?._compileSass(this.file);
}
/**
* Resolve dependencies imported in SCSS files.
* @param {string} file File to crawl
* @param {Array} [resolvedFiles] Array of currently resolved dependencies
* @returns {Promise<string[]>}
*/
async _resolveDeps (file, resolvedFiles = []) {
const scss = await readFile(file, 'utf8');
const basePath = dirname(file);
/*
* @import: Deprecated; let's treat it as @use.
* @use: https://sass-lang.com/documentation/at-rules/use
* @forward: https://sass-lang.com/documentation/at-rules/forward
*/
for (const match of scss.matchAll(/@(?:import|use|forward) ['"]([^'"]+)/ig)) {
const filePath = this._resolveFile(join(basePath, match[1]).split(sep).join(posix.sep));
if (filePath) {
if (!resolvedFiles.includes(filePath)) {
resolvedFiles.push(filePath);
await this._resolveDeps(filePath, resolvedFiles);
}
}
}
return resolvedFiles;
}
/**
* @private
*/
_resolveFile (partialFile) {
if (existsSync(partialFile) && statSync(partialFile).isDirectory()) {
// https://sass-lang.com/documentation/at-rules/use#index-files
partialFile = join(partialFile, '_index.scss');
if (existsSync(partialFile)) {
return partialFile;
}
return null;
}
const extensions = [ 'scss', 'css' ];
if (!extensions.some(ext => partialFile.endsWith(`.${ext}`))) {
for (const ext of extensions) {
const resolved = this._resolveFile0(`${partialFile}.${ext}`);
if (resolved) {
return resolved;
}
}
}
return this._resolveFile0(partialFile);
}
/**
* @private
*/
_resolveFile0 (partialFile) {
if (!existsSync(partialFile)) {
// https://sass-lang.com/documentation/at-rules/use#partials
const f = partialFile.split('/');
f[f.length - 1] = `_${f[f.length - 1]}`;
partialFile = f.join('/');
if (!existsSync(partialFile)) {
return null;
}
}
if (statSync(partialFile).isDirectory()) {
return null;
}
return partialFile;
}
get _metadata () {
return `${sassInfo}; Vizality import resolver v1`;
}
};