123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459 |
- /*!
- * node-sass: lib/extensions.js
- */
-
- var eol = require('os').EOL,
- fs = require('fs'),
- pkg = require('../package.json'),
- mkdir = require('mkdirp'),
- path = require('path'),
- defaultBinaryDir = path.join(__dirname, '..', 'vendor'),
- trueCasePathSync = require('true-case-path');
-
- /**
- * Get the human readable name of the Platform that is running
- *
- * @param {string} platform - An OS platform to match, or null to fallback to
- * the current process platform
- * @return {Object} The name of the platform if matched, false otherwise
- *
- * @api public
- */
- function getHumanPlatform(platform) {
- switch (platform || process.platform) {
- case 'darwin': return 'OS X';
- case 'freebsd': return 'FreeBSD';
- case 'linux': return 'Linux';
- case 'linux_musl': return 'Linux/musl';
- case 'win32': return 'Windows';
- default: return false;
- }
- }
-
- /**
- * Provides a more readable version of the architecture
- *
- * @param {string} arch - An instruction architecture name to match, or null to
- * lookup the current process architecture
- * @return {Object} The value of the process architecture, or false if unknown
- *
- * @api public
- */
- function getHumanArchitecture(arch) {
- switch (arch || process.arch) {
- case 'ia32': return '32-bit';
- case 'x86': return '32-bit';
- case 'x64': return '64-bit';
- default: return false;
- }
- }
-
- /**
- * Get the friendly name of the Node environment being run
- *
- * @param {Object} abi - A Node Application Binary Interface value, or null to
- * fallback to the current Node ABI
- * @return {Object} Returns a string name of the Node environment or false if
- * unmatched
- *
- * @api public
- */
- function getHumanNodeVersion(abi) {
- switch (parseInt(abi || process.versions.modules, 10)) {
- case 11: return 'Node 0.10.x';
- case 14: return 'Node 0.12.x';
- case 42: return 'io.js 1.x';
- case 43: return 'io.js 1.1.x';
- case 44: return 'io.js 2.x';
- case 45: return 'io.js 3.x';
- case 46: return 'Node.js 4.x';
- case 47: return 'Node.js 5.x';
- case 48: return 'Node.js 6.x';
- case 49: return 'Electron 1.3.x';
- case 50: return 'Electron 1.4.x';
- case 51: return 'Node.js 7.x';
- case 53: return 'Electron 1.6.x';
- case 57: return 'Node.js 8.x';
- case 59: return 'Node.js 9.x';
- case 64: return 'Node.js 10.x';
- default: return false;
- }
- }
-
- /**
- * Get a human readable description of where node-sass is running to support
- * user error reporting when something goes wrong
- *
- * @param {string} env - The name of the native bindings that is to be parsed
- * @return {string} A description of what os, architecture, and Node version
- * that is being run
- *
- * @api public
- */
- function getHumanEnvironment(env) {
- var binding = env.replace(/_binding\.node$/, ''),
- parts = binding.split('-'),
- platform = getHumanPlatform(parts[0]),
- arch = getHumanArchitecture(parts[1]),
- runtime = getHumanNodeVersion(parts[2]);
-
- if (parts.length !== 3) {
- return 'Unknown environment (' + binding + ')';
- }
-
- if (!platform) {
- platform = 'Unsupported platform (' + parts[0] + ')';
- }
-
- if (!arch) {
- arch = 'Unsupported architecture (' + parts[1] + ')';
- }
-
- if (!runtime) {
- runtime = 'Unsupported runtime (' + parts[2] + ')';
- }
-
- return [
- platform, arch, 'with', runtime,
- ].join(' ');
- }
-
- /**
- * Get the value of the binaries under the default path
- *
- * @return {Array} The currently installed node-sass bindings
- *
- * @api public
- */
- function getInstalledBinaries() {
- return fs.readdirSync(getBinaryDir());
- }
-
- /**
- * Check that an environment matches the whitelisted values or the current
- * environment if no parameters are passed
- *
- * @param {string} platform - The name of the OS platform(darwin, win32, etc...)
- * @param {string} arch - The instruction set architecture of the Node environment
- * @param {string} abi - The Node Application Binary Interface
- * @return {Boolean} True, if node-sass supports the current platform, false otherwise
- *
- * @api public
- */
- function isSupportedEnvironment(platform, arch, abi) {
- return (
- false !== getHumanPlatform(platform) &&
- false !== getHumanArchitecture(arch) &&
- false !== getHumanNodeVersion(abi)
- );
- }
-
- /**
- * Get the value of a CLI argument
- *
- * @param {String} name
- * @param {Array} args
- * @api private
- */
-
- function getArgument(name, args) {
- var flags = args || process.argv.slice(2),
- index = flags.lastIndexOf(name);
-
- if (index === -1 || index + 1 >= flags.length) {
- return null;
- }
-
- return flags[index + 1];
- }
-
- /**
- * Get binary name.
- * If environment variable SASS_BINARY_NAME,
- * .npmrc variable sass_binary_name or
- * process argument --binary-name is provided,
- * return it as is, otherwise make default binary
- * name: {platform}-{arch}-{v8 version}.node
- *
- * @api public
- */
-
- function getBinaryName() {
- var binaryName,
- variant,
- platform = process.platform;
-
- if (getArgument('--sass-binary-name')) {
- binaryName = getArgument('--sass-binary-name');
- } else if (process.env.SASS_BINARY_NAME) {
- binaryName = process.env.SASS_BINARY_NAME;
- } else if (process.env.npm_config_sass_binary_name) {
- binaryName = process.env.npm_config_sass_binary_name;
- } else if (pkg.nodeSassConfig && pkg.nodeSassConfig.binaryName) {
- binaryName = pkg.nodeSassConfig.binaryName;
- } else {
- variant = getPlatformVariant();
- if (variant) {
- platform += '_' + variant;
- }
-
- binaryName = [
- platform, '-',
- process.arch, '-',
- process.versions.modules
- ].join('');
- }
-
- return [binaryName, 'binding.node'].join('_');
- }
-
- /**
- * Determine the URL to fetch binary file from.
- * By default fetch from the node-sass distribution
- * site on GitHub.
- *
- * The default URL can be overriden using
- * the environment variable SASS_BINARY_SITE,
- * .npmrc variable sass_binary_site or
- * or a command line option --sass-binary-site:
- *
- * node scripts/install.js --sass-binary-site http://example.com/
- *
- * The URL should to the mirror of the repository
- * laid out as follows:
- *
- * SASS_BINARY_SITE/
- *
- * v3.0.0
- * v3.0.0/freebsd-x64-14_binding.node
- * ....
- * v3.0.0
- * v3.0.0/freebsd-ia32-11_binding.node
- * v3.0.0/freebsd-x64-42_binding.node
- * ... etc. for all supported versions and platforms
- *
- * @api public
- */
-
- function getBinaryUrl() {
- var site = getArgument('--sass-binary-site') ||
- process.env.SASS_BINARY_SITE ||
- process.env.npm_config_sass_binary_site ||
- (pkg.nodeSassConfig && pkg.nodeSassConfig.binarySite) ||
- 'https://github.com/sass/node-sass/releases/download';
-
- return [site, 'v' + pkg.version, getBinaryName()].join('/');
- }
-
- /**
- * Get binary dir.
- * If environment variable SASS_BINARY_DIR,
- * .npmrc variable sass_binary_dir or
- * process argument --sass-binary-dir is provided,
- * select it by appending binary name, otherwise
- * use default binary dir.
- * Once the primary selection is made, check if
- * callers wants to throw if file not exists before
- * returning.
- *
- * @api public
- */
-
- function getBinaryDir() {
- var binaryDir;
-
- if (getArgument('--sass-binary-dir')) {
- binaryDir = getArgument('--sass-binary-dir');
- } else if (process.env.SASS_BINARY_DIR) {
- binaryDir = process.env.SASS_BINARY_DIR;
- } else if (process.env.npm_config_sass_binary_dir) {
- binaryDir = process.env.npm_config_sass_binary_dir;
- } else if (pkg.nodeSassConfig && pkg.nodeSassConfig.binaryDir) {
- binaryDir = pkg.nodeSassConfig.binaryDir;
- } else {
- binaryDir = defaultBinaryDir;
- }
-
- return binaryDir;
- }
-
- /**
- * Get binary path.
- * If environment variable SASS_BINARY_PATH,
- * .npmrc variable sass_binary_path or
- * process argument --sass-binary-path is provided,
- * select it by appending binary name, otherwise
- * make default binary path using binary name.
- * Once the primary selection is made, check if
- * callers wants to throw if file not exists before
- * returning.
- *
- * @api public
- */
-
- function getBinaryPath() {
- var binaryPath;
-
- if (getArgument('--sass-binary-path')) {
- binaryPath = getArgument('--sass-binary-path');
- } else if (process.env.SASS_BINARY_PATH) {
- binaryPath = process.env.SASS_BINARY_PATH;
- } else if (process.env.npm_config_sass_binary_path) {
- binaryPath = process.env.npm_config_sass_binary_path;
- } else if (pkg.nodeSassConfig && pkg.nodeSassConfig.binaryPath) {
- binaryPath = pkg.nodeSassConfig.binaryPath;
- } else {
- binaryPath = path.join(getBinaryDir(), getBinaryName().replace(/_(?=binding\.node)/, '/'));
- }
-
- if (process.versions.modules < 46) {
- return binaryPath;
- }
-
- try {
- return trueCasePathSync(binaryPath) || binaryPath;
- } catch (e) {
- return binaryPath;
- }
- }
-
- /**
- * An array of paths suitable for use as a local disk cache of the binding.
- *
- * @return {[]String} an array of paths
- * @api public
- */
- function getCachePathCandidates() {
- return [
- process.env.npm_config_sass_binary_cache,
- process.env.npm_config_cache,
- ].filter(function(_) { return _; });
- }
-
- /**
- * The most suitable location for caching the binding on disk.
- *
- * Given the candidates directories provided by `getCachePathCandidates()` this
- * returns the first writable directory. By treating the candidate directories
- * as a prioritised list this method is deterministic, assuming no change to the
- * local environment.
- *
- * @return {String} directory to cache binding
- * @api public
- */
- function getBinaryCachePath() {
- var i,
- cachePath,
- cachePathCandidates = getCachePathCandidates();
-
- for (i = 0; i < cachePathCandidates.length; i++) {
- cachePath = path.join(cachePathCandidates[i], pkg.name, pkg.version);
-
- try {
- mkdir.sync(cachePath);
- return cachePath;
- } catch (e) {
- // Directory is not writable, try another
- }
- }
-
- return '';
- }
-
- /**
- * The cached binding
- *
- * Check the candidates directories provided by `getCachePathCandidates()` for
- * the binding file, if it exists. By treating the candidate directories
- * as a prioritised list this method is deterministic, assuming no change to the
- * local environment.
- *
- * @return {String} path to cached binary
- * @api public
- */
- function getCachedBinary() {
- var i,
- cachePath,
- cacheBinary,
- cachePathCandidates = getCachePathCandidates(),
- binaryName = getBinaryName();
-
- for (i = 0; i < cachePathCandidates.length; i++) {
- cachePath = path.join(cachePathCandidates[i], pkg.name, pkg.version);
- cacheBinary = path.join(cachePath, binaryName);
-
- if (fs.existsSync(cacheBinary)) {
- return cacheBinary;
- }
- }
-
- return '';
- }
-
- /**
- * Does the supplied binary path exist
- *
- * @param {String} binaryPath
- * @api public
- */
-
- function hasBinary(binaryPath) {
- return fs.existsSync(binaryPath);
- }
-
- /**
- * Get Sass version information
- *
- * @api public
- */
-
- function getVersionInfo(binding) {
- return [
- ['node-sass', pkg.version, '(Wrapper)', '[JavaScript]'].join('\t'),
- ['libsass ', binding.libsassVersion(), '(Sass Compiler)', '[C/C++]'].join('\t'),
- ].join(eol);
- }
-
- /**
- * Gets the platform variant, currently either an empty string or 'musl' for Linux/musl platforms.
- *
- * @api public
- */
-
- function getPlatformVariant() {
- var contents = '';
-
- if (process.platform !== 'linux') {
- return '';
- }
-
- try {
- contents = fs.readFileSync(process.execPath);
-
- // Buffer.indexOf was added in v1.5.0 so cast to string for old node
- // Delay contents.toStrings because it's expensive
- if (!contents.indexOf) {
- contents = contents.toString();
- }
-
- if (contents.indexOf('libc.musl-x86_64.so.1') !== -1) {
- return 'musl';
- }
- } catch (err) { } // eslint-disable-line no-empty
-
- return '';
- }
-
- module.exports.hasBinary = hasBinary;
- module.exports.getBinaryUrl = getBinaryUrl;
- module.exports.getBinaryName = getBinaryName;
- module.exports.getBinaryDir = getBinaryDir;
- module.exports.getBinaryPath = getBinaryPath;
- module.exports.getBinaryCachePath = getBinaryCachePath;
- module.exports.getCachedBinary = getCachedBinary;
- module.exports.getCachePathCandidates = getCachePathCandidates;
- module.exports.getVersionInfo = getVersionInfo;
- module.exports.getHumanEnvironment = getHumanEnvironment;
- module.exports.getInstalledBinaries = getInstalledBinaries;
- module.exports.isSupportedEnvironment = isSupportedEnvironment;
|