mirror of https://github.com/vizality/vizality
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.
97 lines
2.6 KiB
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`;
|
|
}
|
|
};
|