Skip to content

Commit daba5ef

Browse files
committed
Add CLI - generates css and writes to a file
1 parent 5c8196c commit daba5ef

5 files changed

Lines changed: 202 additions & 1 deletion

File tree

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,6 @@ elm-stuff/
44
repl-temp-*
55
.DS_Store
66
*/index.html
7-
index.html
7+
index.html
8+
node_modules
9+

bin/style-elements.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#!/usr/bin/env node
2+
3+
var styleElements = require("../");
4+
var pkg = require("../package.json");
5+
var program = require("commander");
6+
var fs = require("fs");
7+
var chalk = require("chalk");
8+
var requiredOptions = ["stylesheetModule", "stylesheetFunction", "output"];
9+
var { writeFile, assertKeysPresent } = require("../js/utils");
10+
11+
var { output, stylesheetModule, stylesheetFunction } = getOptions(
12+
process.argv,
13+
program
14+
);
15+
16+
styleElements({ stylesheetModule, stylesheetFunction })
17+
.then(result => writeFile(output, result))
18+
.then(() => {
19+
console.warn(
20+
chalk.green(`\n----> Success! styles were written to ${program.output}\n`)
21+
);
22+
});
23+
24+
function getOptions(argv, program) {
25+
program
26+
.version(pkg.version)
27+
.usage("[options] <stylesheetModule> <stylesheetFunction>")
28+
.option(
29+
"-o, --output [outputFile]",
30+
"(optional) file to write the CSS to",
31+
"out.css"
32+
)
33+
.parse(argv);
34+
35+
var options = {
36+
stylesheetModule: program.args[0],
37+
stylesheetFunction: program.args[1],
38+
output: program.output
39+
};
40+
41+
assertKeysPresent(options, requiredOptions, _missingOptions => {
42+
program.outputHelp();
43+
process.exit(1);
44+
});
45+
46+
return options;
47+
}

index.js

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
var path = require("path");
2+
var compileElm = require("node-elm-compiler").compile;
3+
var {
4+
unindent,
5+
writeFile,
6+
withTmpDir,
7+
assertKeysPresent
8+
} = require("./js/utils.js");
9+
10+
var requiredOptions = ["stylesheetModule", "stylesheetFunction"];
11+
12+
function generateCss(opts) {
13+
assertKeysPresent(opts, requiredOptions, missingOptions => {
14+
throw new Error(`Missing options: ${missingOptions.join(", ")}`);
15+
});
16+
17+
return withTmpDir().then(tmpDirPath => {
18+
var emitterSourceFile = path.join(tmpDirPath, "StyleElementsEmitter.elm");
19+
var emitterWorkerFile = path.join(tmpDirPath, "style-elements-emitter.js");
20+
var emitterTemplate = buildEmitterTemplate(
21+
opts.stylesheetModule,
22+
opts.stylesheetFunction
23+
);
24+
25+
return writeFile(emitterSourceFile, emitterTemplate)
26+
.then(() => compile(emitterSourceFile, { output: emitterWorkerFile, yes: true }))
27+
.then(() => extractCssResults(emitterWorkerFile));
28+
});
29+
}
30+
31+
function buildEmitterTemplate(stylesheetModule, stylesheetFunction) {
32+
return unindent(
33+
`
34+
port module StyleElementsEmitter exposing (..)
35+
36+
import ${stylesheetModule}
37+
38+
39+
port result : String -> Cmd msg
40+
41+
42+
stylesheet =
43+
${stylesheetModule}.${stylesheetFunction}
44+
45+
46+
main : Program Never () Never
47+
main =
48+
Platform.program
49+
{ init = ( (), result stylesheet.css )
50+
, update = \\_ _ -> ( (), Cmd.none )
51+
, subscriptions = \\_ -> Sub.none
52+
}
53+
`
54+
);
55+
}
56+
57+
function compile(src, options) {
58+
return new Promise(function(resolve, reject) {
59+
compileElm(src, options).on("close", function(exitCode) {
60+
if (exitCode === 0) {
61+
resolve();
62+
} else {
63+
reject("Errored with exit code " + exitCode);
64+
}
65+
});
66+
});
67+
}
68+
69+
function extractCssResults(destFile) {
70+
var emitter = require(destFile).StyleElementsEmitter;
71+
var worker = emitter.worker();
72+
73+
return new Promise(resolve => worker.ports.result.subscribe(resolve));
74+
}
75+
76+
module.exports = generateCss;

js/utils.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
var tmp = require("tmp");
2+
var fs = require("fs");
3+
4+
module.exports = {
5+
unindent: function(text) {
6+
var indentation = text.split("\n")
7+
.map(line => {
8+
var match = line.match(/([\s]+)[^\s]+/);
9+
return match && match[1];
10+
})
11+
.find(value => value);
12+
13+
return indentation
14+
? text.replace(new RegExp(`^${indentation}`, "gm"), "")
15+
: text;
16+
},
17+
18+
writeFile: function(...args) {
19+
return new Promise((resolve, reject) => {
20+
return fs.writeFile(...args, err => (err ? reject(err) : resolve()));
21+
});
22+
},
23+
24+
withTmpDir: function() {
25+
return new Promise(function(resolve, reject) {
26+
tmp.dir({ unsafeCleanup: true }, function(err, tmpDirPath) {
27+
if (err) {
28+
reject(err);
29+
} else {
30+
resolve(tmpDirPath);
31+
}
32+
});
33+
});
34+
},
35+
36+
assertKeysPresent: function(object = {}, requiredKeys, missingCallback) {
37+
var providedKeys = Object.keys(object);
38+
var missingKeys = requiredKeys.filter(key => {
39+
return (
40+
!providedKeys.includes(key) || providedKeys[key] === ""
41+
);
42+
});
43+
44+
if (missingKeys.length > 0) {
45+
missingCallback(missingKeys);
46+
}
47+
}
48+
};

package.json

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"name": "style-elements",
3+
"version": "3.2.3",
4+
"description": "CSS Preprocoessor for Elm's style-elements",
5+
"main": "index.js",
6+
"bin": {
7+
"style-elements": "./bin/style-elements.js"
8+
},
9+
"files": [
10+
"js/utils.js"
11+
],
12+
"dependencies": {
13+
"chalk": "^2.0.1",
14+
"commander": "^2.11.0",
15+
"postcss": "^6.0.6",
16+
"tmp": "0.0.31"
17+
},
18+
"devDependencies": {},
19+
"scripts": {
20+
"test": "echo \"Error: no test specified\" && exit 1"
21+
},
22+
"repository": {
23+
"type": "git",
24+
"url": "http://package.elm-lang.org/packages/mdgriffith/style-elements"
25+
},
26+
"author": "Matthew Griffith",
27+
"license": "BSD-3-Clause"
28+
}

0 commit comments

Comments
 (0)