Home Reference Source Test Repository

js/lib/GlobImporter.js

import concat from 'unique-concat';
import fs from 'fs';
import glob from 'glob';
import path from 'path';

/**
 * Import files using glob patterns.
 */
export default class GlobImporter {
  /**
   * @param {Object} options - Configuration options.
   */
  constructor(options = {}) {
    const defaultOptions = {
      includePaths: [process.cwd()]
    };
    /** @type {Object} */
    this.options = Object.assign({}, defaultOptions, options);
  }

  /**
   * Synchronously resolve node-sass import url glob paths.
   * @param {string} url - Import url from node-sass.
   * @return {Array} File paths array.
   */
  resolveFilePathsSync(url) {
    let filePaths = [];

    if (glob.hasMagic(url)) {
      filePaths = this.options.includePaths
        .reduce((absolutePathStore, includePath) => {
          // Try to resolve the glob pattern.
          const newAbsolutePaths = glob
            .sync(url, { cwd: includePath })
            .map(relativePath => path.resolve(includePath, relativePath));
          // Merge new paths with previously found ones.
          return concat(absolutePathStore, newAbsolutePaths);
        }, []);
    }

    return filePaths;
  }

  /**
   * Asynchronously resolve node-sass import url glob paths.
   * @param {string} url - Import url from node-sass.
   * @return {Promise} Promise for a file paths array.
   */
  resolveFilePaths(url) {
    return new Promise((promiseResolve) => {
      promiseResolve(this.resolveFilePathsSync(url));
    });
  }

  /**
   * Synchronously resolve filtered contents from glob files with the given url.
   * @param {string} url - Import url from node-sass.
   * @return {Object|null} Contents object or null.
   */
  resolveSync(url) {
    const filePaths = this.resolveFilePathsSync(url);

    if (filePaths.length) {
      const contents = filePaths
        .map(x => fs.readFileSync(x, { encoding: `utf8` }))
        .join(`\n`);

      return { contents };
    }

    return null;
  }

  /**
   * Asynchronously resolve filtered contents
   * from glob files with the given url.
   * @param {string} url - Import url from node-sass.
   * @return {Promise} Promise for a contents object.
   */
  resolve(url) {
    return new Promise((promiseResolve) => {
      promiseResolve(this.resolveSync(url));
    });
  }
}