1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
| import { createRequire } from 'module'; import path from 'path'; import { promisify } from 'util';
import resolve from 'resolve'; import PQueue from 'p-queue';
function loadModule(moduleId) { try { return require(moduleId); } catch { }
try { return createRequire(path.resolve(process.cwd(), 'noop.js'))(moduleId); } catch { } }
const threadPoolSize = process.env.UV_THREADPOOL_SIZE || 4; const workQueue = new PQueue({ concurrency: threadPoolSize - 1 });
const moduleRe = /^~([a-z\d]|@).+/i;
const getUrlOfPartial = (url) => { const parsedUrl = path.parse(url); return `${parsedUrl.dir}${path.sep}_${parsedUrl.base}`; };
const resolvePromise = promisify(resolve);
const sassModuleIds = ['node-sass', 'sass'];
export default { name: 'sass', test: /\.(sass|scss)$/, process({ code }) { return new Promise((resolve, reject) => { const sass = loadSassOrThrow(); const render = promisify(sass.render.bind(sass)); const data = this.options.data || ''; workQueue.add(() => render({ ...this.options, file: this.id, data: data + code, indentedSyntax: /\.sass$/.test(this.id), sourceMap: this.sourceMap, importer: [ (url, importer, done) => { if (!moduleRe.test(url)) { if (/^@styles/.test(url)) { return done({ file: url.replace( /^@styles/, path.resolve(__dirname, './src/styles'), ), }); } return done({ file: url }); } const moduleUrl = url.slice(1); const partialUrl = getUrlOfPartial(moduleUrl);
const options = { basedir: path.dirname(importer), extensions: ['.scss', '.sass', '.css'], }; const finishImport = (id) => { done({ file: id.endsWith('.css') ? id.replace(/\.css$/, '') : id, }); };
const next = () => { done({ file: url }); };
resolvePromise(partialUrl, options) .then(finishImport) .catch((error) => { if ( error.code === 'MODULE_NOT_FOUND' || error.code === 'ENOENT' ) { resolvePromise(moduleUrl, options) .then(finishImport) .catch(next); } else { next(); } }); }, ].concat(this.options.importer || []), }) .then((result) => { for (const file of result.stats.includedFiles) { this.dependencies.add(file); }
resolve({ code: result.css.toString(), map: result.map && result.map.toString(), }); }) .catch(reject), ); }); }, };
|