Skip to content

Commit

Permalink
Add CLI - generates css and writes to a file
Browse files Browse the repository at this point in the history
  • Loading branch information
opsb committed Jul 15, 2017
1 parent 5c8196c commit 4684daf
Show file tree
Hide file tree
Showing 5 changed files with 206 additions and 1 deletion.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@ elm-stuff/
repl-temp-*
.DS_Store
*/index.html
index.html
index.html
node_modules

47 changes: 47 additions & 0 deletions bin/style-elements.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#!/usr/bin/env node

var styleElements = require("../");
var pkg = require("../package.json");
var program = require("commander");
var fs = require("fs");
var chalk = require("chalk");
var requiredOptions = ["stylesheetModule", "stylesheetFunction", "output"];
var { writeFile, assertKeysPresent } = require("../js/utils");

var { output, stylesheetModule, stylesheetFunction } = getOptions(
process.argv,
program
);

styleElements({ stylesheetModule, stylesheetFunction })
.then(result => writeFile(output, result))
.then(() => {
console.warn(
chalk.green(`\n----> Success! styles were written to ${program.output}\n`)
);
});

function getOptions(argv, program) {
program
.version(pkg.version)
.usage("[options] <stylesheetModule> <stylesheetFunction>")
.option(
"-o, --output [outputFile]",
"(optional) file to write the CSS to",
"out.css"
)
.parse(argv);

var options = {
stylesheetModule: program.args[0],
stylesheetFunction: program.args[1],
output: program.output
};

assertKeysPresent(options, requiredOptions, _missingOptions => {
program.outputHelp();
process.exit(1);
});

return options;
}
76 changes: 76 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
var path = require("path");
var compileElm = require("node-elm-compiler").compile;
var {
unindent,
writeFile,
withTmpDir,
assertKeysPresent
} = require("./js/utils.js");

var requiredOptions = ["stylesheetModule", "stylesheetFunction"];

function generateCss(opts) {
assertKeysPresent(opts, requiredOptions, missingOptions => {
throw new Error(`Missing options: ${missingOptions.join(", ")}`);
});

return withTmpDir().then(tmpDirPath => {
var emitterSourceFile = path.join(tmpDirPath, "StyleElementsEmitter.elm");
var emitterWorkerFile = path.join(tmpDirPath, "style-elements-emitter.js");
var emitterTemplate = buildEmitterTemplate(
opts.stylesheetModule,
opts.stylesheetFunction
);

return writeFile(emitterSourceFile, emitterTemplate)
.then(() => compile(emitterSourceFile, { output: emitterWorkerFile, yes: true }))
.then(() => extractCssResults(emitterWorkerFile));
});
}

function buildEmitterTemplate(stylesheetModule, stylesheetFunction) {
return unindent(
`
port module StyleElementsEmitter exposing (..)
import ${stylesheetModule}
port result : String -> Cmd msg
stylesheet =
${stylesheetModule}.${stylesheetFunction}
main : Program Never () Never
main =
Platform.program
{ init = ( (), result stylesheet.css )
, update = \\_ _ -> ( (), Cmd.none )
, subscriptions = \\_ -> Sub.none
}
`
);
}

function compile(src, options) {
return new Promise(function(resolve, reject) {
compileElm(src, options).on("close", function(exitCode) {
if (exitCode === 0) {
resolve();
} else {
reject("Errored with exit code " + exitCode);
}
});
});
}

function extractCssResults(destFile) {
var emitter = require(destFile).StyleElementsEmitter;
var worker = emitter.worker();

return new Promise(resolve => worker.ports.result.subscribe(resolve));
}

module.exports = generateCss;
48 changes: 48 additions & 0 deletions js/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
var tmp = require("tmp");
var fs = require("fs");

module.exports = {
unindent: function(text) {
var indentation = text.split("\n")
.map(line => {
var match = line.match(/([\s]+)[^\s]+/);
return match && match[1];
})
.find(value => value);

return indentation
? text.replace(new RegExp(`^${indentation}`, "gm"), "")
: text;
},

writeFile: function(...args) {
return new Promise((resolve, reject) => {
return fs.writeFile(...args, err => (err ? reject(err) : resolve()));
});
},

withTmpDir: function() {
return new Promise(function(resolve, reject) {
tmp.dir({ unsafeCleanup: true }, function(err, tmpDirPath) {
if (err) {
reject(err);
} else {
resolve(tmpDirPath);
}
});
});
},

assertKeysPresent: function(object = {}, requiredKeys, missingCallback) {
var providedKeys = Object.keys(object);
var missingKeys = requiredKeys.filter(key => {
return (
!providedKeys.includes(key) || providedKeys[key] === ""
);
});

if (missingKeys.length > 0) {
missingCallback(missingKeys);
}
}
};
32 changes: 32 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"name": "style-elements",
"version": "3.2.3",
"description": "CSS Preprocoessor for Elm's style-elements",
"main": "index.js",
"bin": {
"style-elements": "./bin/style-elements.js"
},
"directories": {
"example": "examples",
"test": "tests"
},
"files": [
"js/utils.js"
],
"dependencies": {
"chalk": "^2.0.1",
"commander": "^2.11.0",
"postcss": "^6.0.6",
"tmp": "0.0.31"
},
"devDependencies": {},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "http://package.elm-lang.org/packages/mdgriffith/style-elements"
},
"author": "Matthew Griffith",
"license": "BSD-3-Clause"
}

0 comments on commit 4684daf

Please sign in to comment.