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.
openNG/build/transforms/scss.js

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! */
}
});
};