You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
112 lines
3.0 KiB
JavaScript
112 lines
3.0 KiB
JavaScript
"use strict";
|
|
|
|
const Promise = require("bluebird");
|
|
const path = require("path");
|
|
const core = require("../core");
|
|
const nodeSass = Promise.promisifyAll(require("node-sass"));
|
|
const copyProps = require("copy-props");
|
|
|
|
const replaceExtension = require("../core/util/replace-extension");
|
|
const createSyntaxError = require("../core/errors/syntax-error");
|
|
|
|
let optionsToCopy = [
|
|
"functions",
|
|
"indentedSyntax",
|
|
"indentType",
|
|
"indentWidth",
|
|
"linefeed",
|
|
"omitSourceMapUrl", // FIXME: outFile stuff
|
|
"outputStyle",
|
|
"precision",
|
|
"sourceComments",
|
|
"sourceMap", // FIXME: outFile stuff
|
|
"sourceMapContents",
|
|
"sourceMapEmbed",
|
|
"sourceMapRoot"
|
|
];
|
|
|
|
module.exports = function (options = {}) {
|
|
return core.createSingleFileTransform({
|
|
displayName: "SCSS (node-sass)",
|
|
// stream: where 'contents' is a stream
|
|
supportsStreams: false,
|
|
// virtual files: files with a contents buffer/stream but without a path
|
|
supportsVirtualFiles: true,
|
|
// virtual filesystem: not-on-disk, eg. for includes of transformed files
|
|
supportsVirtualFilesystem: (options.virtualFilesystemSupport === true),
|
|
transform: ({metadata, contents}) => {
|
|
let includePaths;
|
|
|
|
if (!metadata.isVirtual) {
|
|
includePaths = [path.dirname(metadata.path)];
|
|
} else {
|
|
includePaths = [];
|
|
}
|
|
|
|
if (options.includePaths != null) {
|
|
includePaths = includePaths.concat(options.includePaths);
|
|
}
|
|
|
|
let importer;
|
|
|
|
if (options.virtualFilesystemSupport === true && metadata.virtualFilesystem != null) {
|
|
importer = function include(target, previousPath, done) {
|
|
if (/^[a-z]+:/i.test(target)) {
|
|
/* Probably a URL; don't handle this. */
|
|
return null;
|
|
} else {
|
|
return Promise.try(() => {
|
|
return metadata.virtualFilesystem.readFile(target);
|
|
}).then((contents) => {
|
|
done(contents.toString());
|
|
}).catch((err) => {
|
|
done(err);
|
|
});
|
|
}
|
|
};
|
|
}
|
|
|
|
return Promise.try(() => {
|
|
let stringContents = contents.toString();
|
|
|
|
if (stringContents.length > 0) {
|
|
let renderOptions = {
|
|
data: stringContents,
|
|
includePaths: includePaths,
|
|
importer: importer,
|
|
};
|
|
|
|
copyProps(options, renderOptions, optionsToCopy);
|
|
|
|
return nodeSass.renderAsync(renderOptions);
|
|
} else {
|
|
return {css: contents};
|
|
}
|
|
}).then((result) => {
|
|
return {
|
|
metadata: {
|
|
/* FIXME: Implement a check that throws errors when a transform returns isVirtual:false for a non-existent path on a non-virtual FS */
|
|
isVirtual: true,
|
|
/* FIXME: Verify that every transform returns a relativePath? */
|
|
relativePath: replaceExtension(metadata.relativePath, "css")
|
|
},
|
|
contents: result.css
|
|
};
|
|
}).catch({status: 1}, (err) => {
|
|
/* Syntax error */
|
|
throw createSyntaxError({
|
|
error: err.message,
|
|
line: err.line,
|
|
column: err.column
|
|
});
|
|
}).catch({status: 3}, (err) => {
|
|
// no input provided
|
|
throw new Error(err.message);
|
|
}).catch((err) => {
|
|
// console.log(require("util").inspect(err, {colors: true, depth: null}));
|
|
throw err;
|
|
}); /* FIXME: Error mapping! */
|
|
}
|
|
});
|
|
};
|