Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@parcel/transformer-sass

Package Overview
Dependencies
Maintainers
1
Versions
884
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@parcel/transformer-sass - npm Package Compare versions

Comparing version 2.0.0-canary.1733 to 2.0.0-canary.1735

lib/legacy.js

223

lib/SassTransformer.js

@@ -21,33 +21,5 @@ "use strict";

}
function _os() {
const data = require("os");
_os = function () {
return data;
};
return data;
}
function _sourceMap() {
const data = _interopRequireDefault(require("@parcel/source-map"));
_sourceMap = function () {
return data;
};
return data;
}
function _sass() {
const data = _interopRequireDefault(require("sass"));
_sass = function () {
return data;
};
return data;
}
function _util() {
const data = require("util");
_util = function () {
return data;
};
return data;
}
var _legacy = require("./legacy");
var _modern = require("./modern");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
// E.g: ~library/file.sass
const NODE_MODULE_ALIAS_RE = /^~[^/\\]/;
var _default = exports.default = new (_plugin().Transformer)({

@@ -69,20 +41,33 @@ async loadConfig({

}
let version = detectVersion(configResult);
if (version === 'legacy') {
// Resolve relative paths from config file
if (configFile && configResult.includePaths) {
configResult.includePaths = configResult.includePaths.map(p => _path().default.resolve(_path().default.dirname(configFile.filePath), p));
}
if (configResult.importer === undefined) {
configResult.importer = [];
} else if (!Array.isArray(configResult.importer)) {
configResult.importer = [configResult.importer];
}
// Resolve relative paths from config file
if (configFile && configResult.includePaths) {
configResult.includePaths = configResult.includePaths.map(p => _path().default.resolve(_path().default.dirname(configFile.filePath), p));
// Always emit sourcemap
configResult.sourceMap = true;
// sources are created relative to the directory of outFile
configResult.outFile = _path().default.join(options.projectRoot, 'style.css.map');
configResult.omitSourceMapUrl = true;
configResult.sourceMapContents = false;
} else if (version === 'modern') {
// Resolve relative paths from config file
if (configFile && configResult.loadPaths) {
configResult.loadPaths = configResult.loadPaths.map(p => _path().default.resolve(_path().default.dirname(configFile.filePath), p));
}
// Always emit sourcemap
configResult.sourceMap = true;
}
if (configResult.importer === undefined) {
configResult.importer = [];
} else if (!Array.isArray(configResult.importer)) {
configResult.importer = [configResult.importer];
}
// Always emit sourcemap
configResult.sourceMap = true;
// sources are created relative to the directory of outFile
configResult.outFile = _path().default.join(options.projectRoot, 'style.css.map');
configResult.omitSourceMapUrl = true;
configResult.sourceMapContents = false;
return configResult;
return {
version,
config: configResult
};
},

@@ -92,133 +77,39 @@ async transform({

options,
config,
config: {
version,
config
},
resolve
}) {
let rawConfig = config ?? {};
let sassRender = (0, _util().promisify)(_sass().default.render.bind(_sass().default));
let css;
try {
let code = await asset.getCode();
let result = await sassRender({
...rawConfig,
file: asset.filePath,
data: rawConfig.data ? rawConfig.data + _os().EOL + code : code,
importer: [...rawConfig.importer, resolvePathImporter({
asset,
resolve,
includePaths: rawConfig.includePaths,
options
})],
indentedSyntax: typeof rawConfig.indentedSyntax === 'boolean' ? rawConfig.indentedSyntax : asset.type === 'sass'
});
css = result.css;
for (let included of result.stats.includedFiles) {
if (included !== asset.filePath) {
asset.invalidateOnFileChange(included);
}
}
if (result.map != null) {
let map = new (_sourceMap().default)(options.projectRoot);
map.addVLQMap(JSON.parse(result.map));
asset.setMap(map);
}
} catch (err) {
// Adapt the Error object for the reporter.
err.fileName = err.file;
err.loc = {
line: err.line,
column: err.column
};
throw err;
if (version === 'legacy') {
await (0, _legacy.transformLegacy)(asset, config, resolve, options);
} else {
await (0, _modern.transformModern)(asset, config, resolve, options);
}
asset.type = 'css';
asset.setCode(css);
return [asset];
}
});
function resolvePathImporter({
asset,
resolve,
includePaths,
options
}) {
// This is a reimplementation of the Sass resolution algorithm that uses Parcel's
// FS and tracks all tried files so they are watched for creation.
async function resolvePath(url, prev) {
/*
Imports are resolved by trying, in order:
* Loading a file relative to the file in which the `@import` appeared.
* Each custom importer.
* Loading a file relative to the current working directory (This rule doesn't really make sense for Parcel).
* Each load path in `includePaths`
* Each load path specified in the `SASS_PATH` environment variable, which should be semicolon-separated on Windows and colon-separated elsewhere.
See: https://sass-lang.com/documentation/js-api#importer
See also: https://github.com/sass/dart-sass/blob/006e6aa62f2417b5267ad5cdb5ba050226fab511/lib/src/importer/node/implementation.dart
*/
let paths = [_path().default.dirname(prev)];
if (includePaths) {
paths.push(...includePaths);
function detectVersion(config) {
for (let legacyOption of ['data', 'indentType', 'indentWidth', 'linefeed', 'outputStyle', 'importer', 'pkgImporter', 'includePaths', 'omitSourceMapUrl', 'outFile', 'sourceMapContents', 'sourceMapEmbed', 'sourceMapRoot']) {
if (config[legacyOption] != null) {
return 'legacy';
}
asset.invalidateOnEnvChange('SASS_PATH');
if (options.env.SASS_PATH) {
paths.push(...options.env.SASS_PATH.split(process.platform === 'win32' ? ';' : ':').map(p => _path().default.resolve(options.projectRoot, p)));
}
for (let modernOption of ['loadPaths', 'sourceMapIncludeSources', 'style', 'importers']) {
if (config[modernOption] != null) {
return 'modern';
}
const urls = [url];
const urlFileName = _path().default.basename(url);
if (urlFileName[0] !== '_') {
urls.push(_path().default.join(_path().default.dirname(url), `_${urlFileName}`));
}
if (url[0] !== '~') {
for (let p of paths) {
for (let u of urls) {
const filePath = _path().default.resolve(p, u);
try {
const contents = await asset.fs.readFile(filePath, 'utf8');
return {
filePath,
contents
};
} catch (err) {
asset.invalidateOnFileCreate({
filePath
});
}
}
}
if (typeof config.sourceMap === 'string') {
return 'legacy';
}
if (config.functions && typeof config.functions === 'object' && Object.keys(config.functions).length > 0) {
for (let key in config.functions) {
let fn = config.functions[key];
if (typeof fn === 'function' && fn.length > 1) {
return 'legacy';
}
}
// If none of the default sass rules apply, try Parcel's resolver.
for (let u of urls) {
if (NODE_MODULE_ALIAS_RE.test(u)) {
u = u.slice(1);
}
try {
const filePath = await resolve(prev, u, {
packageConditions: ['sass', 'style']
});
if (filePath) {
const contents = await asset.fs.readFile(filePath, 'utf8');
return {
filePath,
contents
};
}
} catch (err) {
continue;
}
}
}
return function (rawUrl, prev, done) {
const url = rawUrl.replace(/^file:\/\//, '');
resolvePath(url, prev).then(resolved => {
if (resolved) {
done({
file: resolved.filePath,
contents: resolved.contents
});
} else {
done();
}
}).catch(done);
};
return 'modern';
}
{
"name": "@parcel/transformer-sass",
"version": "2.0.0-canary.1733+96d88140e",
"version": "2.0.0-canary.1735+f53f45037",
"license": "MIT",

@@ -20,10 +20,10 @@ "publishConfig": {

"node": ">= 16.0.0",
"parcel": "^2.0.0-canary.1731+96d88140e"
"parcel": "^2.0.0-canary.1733+f53f45037"
},
"dependencies": {
"@parcel/plugin": "2.0.0-canary.1733+96d88140e",
"@parcel/plugin": "2.0.0-canary.1735+f53f45037",
"@parcel/source-map": "^2.1.1",
"sass": "^1.38.0"
"sass": "^1.79.4"
},
"gitHead": "96d88140e14585945921e4a0142511c29c0f7d0f"
"gitHead": "f53f4503799a07e3a01452f5e53ead44c30ebc53"
}
// @flow
import {Transformer} from '@parcel/plugin';
import path from 'path';
import {EOL} from 'os';
import SourceMap from '@parcel/source-map';
import sass from 'sass';
import {promisify} from 'util';
import {transformLegacy} from './legacy';
import {transformModern} from './modern';
// E.g: ~library/file.sass
const NODE_MODULE_ALIAS_RE = /^~[^/\\]/;
export default (new Transformer({

@@ -30,75 +25,46 @@ async loadConfig({config, options}) {

// Resolve relative paths from config file
if (configFile && configResult.includePaths) {
configResult.includePaths = configResult.includePaths.map(p =>
path.resolve(path.dirname(configFile.filePath), p),
);
}
let version = detectVersion(configResult);
if (configResult.importer === undefined) {
configResult.importer = [];
} else if (!Array.isArray(configResult.importer)) {
configResult.importer = [configResult.importer];
}
if (version === 'legacy') {
// Resolve relative paths from config file
if (configFile && configResult.includePaths) {
configResult.includePaths = configResult.includePaths.map(p =>
path.resolve(path.dirname(configFile.filePath), p),
);
}
// Always emit sourcemap
configResult.sourceMap = true;
// sources are created relative to the directory of outFile
configResult.outFile = path.join(options.projectRoot, 'style.css.map');
configResult.omitSourceMapUrl = true;
configResult.sourceMapContents = false;
return configResult;
},
async transform({asset, options, config, resolve}) {
let rawConfig = config ?? {};
let sassRender = promisify(sass.render.bind(sass));
let css;
try {
let code = await asset.getCode();
let result = await sassRender({
...rawConfig,
file: asset.filePath,
data: rawConfig.data ? rawConfig.data + EOL + code : code,
importer: [
...rawConfig.importer,
resolvePathImporter({
asset,
resolve,
includePaths: rawConfig.includePaths,
options,
}),
],
indentedSyntax:
typeof rawConfig.indentedSyntax === 'boolean'
? rawConfig.indentedSyntax
: asset.type === 'sass',
});
css = result.css;
for (let included of result.stats.includedFiles) {
if (included !== asset.filePath) {
asset.invalidateOnFileChange(included);
}
if (configResult.importer === undefined) {
configResult.importer = [];
} else if (!Array.isArray(configResult.importer)) {
configResult.importer = [configResult.importer];
}
if (result.map != null) {
let map = new SourceMap(options.projectRoot);
map.addVLQMap(JSON.parse(result.map));
asset.setMap(map);
// Always emit sourcemap
configResult.sourceMap = true;
// sources are created relative to the directory of outFile
configResult.outFile = path.join(options.projectRoot, 'style.css.map');
configResult.omitSourceMapUrl = true;
configResult.sourceMapContents = false;
} else if (version === 'modern') {
// Resolve relative paths from config file
if (configFile && configResult.loadPaths) {
configResult.loadPaths = configResult.loadPaths.map(p =>
path.resolve(path.dirname(configFile.filePath), p),
);
}
} catch (err) {
// Adapt the Error object for the reporter.
err.fileName = err.file;
err.loc = {
line: err.line,
column: err.column,
};
throw err;
// Always emit sourcemap
configResult.sourceMap = true;
}
asset.type = 'css';
asset.setCode(css);
return {version, config: configResult};
},
async transform({asset, options, config: {version, config}, resolve}) {
if (version === 'legacy') {
await transformLegacy(asset, config, resolve, options);
} else {
await transformModern(asset, config, resolve, options);
}
return [asset];

@@ -108,92 +74,52 @@ },

function resolvePathImporter({asset, resolve, includePaths, options}) {
// This is a reimplementation of the Sass resolution algorithm that uses Parcel's
// FS and tracks all tried files so they are watched for creation.
async function resolvePath(
url,
prev,
): Promise<{filePath: string, contents: string, ...} | void> {
/*
Imports are resolved by trying, in order:
* Loading a file relative to the file in which the `@import` appeared.
* Each custom importer.
* Loading a file relative to the current working directory (This rule doesn't really make sense for Parcel).
* Each load path in `includePaths`
* Each load path specified in the `SASS_PATH` environment variable, which should be semicolon-separated on Windows and colon-separated elsewhere.
See: https://sass-lang.com/documentation/js-api#importer
See also: https://github.com/sass/dart-sass/blob/006e6aa62f2417b5267ad5cdb5ba050226fab511/lib/src/importer/node/implementation.dart
*/
let paths = [path.dirname(prev)];
if (includePaths) {
paths.push(...includePaths);
function detectVersion(config: any) {
for (let legacyOption of [
'data',
'indentType',
'indentWidth',
'linefeed',
'outputStyle',
'importer',
'pkgImporter',
'includePaths',
'omitSourceMapUrl',
'outFile',
'sourceMapContents',
'sourceMapEmbed',
'sourceMapRoot',
]) {
if (config[legacyOption] != null) {
return 'legacy';
}
}
asset.invalidateOnEnvChange('SASS_PATH');
if (options.env.SASS_PATH) {
paths.push(
...options.env.SASS_PATH.split(
process.platform === 'win32' ? ';' : ':',
).map(p => path.resolve(options.projectRoot, p)),
);
for (let modernOption of [
'loadPaths',
'sourceMapIncludeSources',
'style',
'importers',
]) {
if (config[modernOption] != null) {
return 'modern';
}
}
const urls = [url];
const urlFileName = path.basename(url);
if (urlFileName[0] !== '_') {
urls.push(path.join(path.dirname(url), `_${urlFileName}`));
}
if (typeof config.sourceMap === 'string') {
return 'legacy';
}
if (url[0] !== '~') {
for (let p of paths) {
for (let u of urls) {
const filePath = path.resolve(p, u);
try {
const contents = await asset.fs.readFile(filePath, 'utf8');
return {
filePath,
contents,
};
} catch (err) {
asset.invalidateOnFileCreate({filePath});
}
}
if (
config.functions &&
typeof config.functions === 'object' &&
Object.keys(config.functions).length > 0
) {
for (let key in config.functions) {
let fn = config.functions[key];
if (typeof fn === 'function' && fn.length > 1) {
return 'legacy';
}
}
// If none of the default sass rules apply, try Parcel's resolver.
for (let u of urls) {
if (NODE_MODULE_ALIAS_RE.test(u)) {
u = u.slice(1);
}
try {
const filePath = await resolve(prev, u, {
packageConditions: ['sass', 'style'],
});
if (filePath) {
const contents = await asset.fs.readFile(filePath, 'utf8');
return {filePath, contents};
}
} catch (err) {
continue;
}
}
}
return function (rawUrl, prev, done) {
const url = rawUrl.replace(/^file:\/\//, '');
resolvePath(url, prev)
.then(resolved => {
if (resolved) {
done({
file: resolved.filePath,
contents: resolved.contents,
});
} else {
done();
}
})
.catch(done);
};
return 'modern';
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc