Skip to content

Commit

Permalink
Initial Commit
Browse files Browse the repository at this point in the history
  • Loading branch information
moonglum committed Sep 27, 2018
0 parents commit 149675d
Show file tree
Hide file tree
Showing 27 changed files with 382 additions and 0 deletions.
20 changes: 20 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# http://editorconfig.org

root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
max_line_length = 80
indent_style = tab
indent_size = 4

[*.md]
indent_style = space

[COMMIT_EDITMSG]
trim_trailing_whitespace = false
max_line_length = 72
indent_style = space
2 changes: 2 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
root: true
extends: fnd
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/node_modules
/.eslintcache

/samples/css.json
/samples/output/
/package-lock.json
8 changes: 8 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
language: node_js
node_js:
- 6
- 8
- 10

script:
- npm test
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# faucet-pipeline-css
[![npm](https://img.shields.io/npm/v/faucet-pipeline-css.svg)](https://www.npmjs.com/package/faucet-pipeline-css)
[![Build Status](https://travis-ci.org/faucet-pipeline/faucet-pipeline-css.svg?branch=master)](https://travis-ci.org/faucet-pipeline/faucet-pipeline-css)
[![Greenkeeper badge](https://badges.greenkeeper.io/faucet-pipeline/faucet-pipeline-css.svg)](https://greenkeeper.io)

You can find the documentation [here](http://www.faucet-pipeline.org).

## License

faucet-pipeline-css is licensed under Apache 2.0 License.
84 changes: 84 additions & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
let { abort } = require("faucet-pipeline-core/lib/util");
let path = require("path");
let makePostCSS = require("./make-postcss");

module.exports = (config, assetManager, { browsers, compact, sourcemaps } = {}) => {
let bundlers = config.map(bundleConfig =>
makeBundler(bundleConfig, assetManager, { browsers, compact, sourcemaps }));

return filepaths => Promise.all(bundlers.map(bundle => bundle(filepaths)));
};

function makeBundler(config, assetManager, { browsers, compact, sourcemaps } = {}) {
let { browserslist, fingerprint } = config;

if(!config.source || !config.target) {
abort("ERROR: CSS configuration requires both target and source");
}

let source = assetManager.resolvePath(config.source);
let target = assetManager.resolvePath(config.target, { enforceRelative: true });

if(browserslist === false) {
browsers = null;
} else if(browserslist) {
browsers = browsers[browserslist];
} else {
browsers = browsers.defaults;
}

let postCSS = makePostCSS(source, target, assetManager, sourcemaps, browsers);

let previouslyIncludedFiles;

return filepaths => {
// If this is the first run or the changed file is one of the
// previously included ones, run the compiler
if(previouslyIncluded(filepaths, previouslyIncludedFiles)) {
postCSS().
then(result => {
previouslyIncludedFiles = result.stats.includedFiles.
map(filepath => path.normalize(filepath));

let options = {};
if(fingerprint !== undefined) {
options.fingerprint = fingerprint;
}
assetManager.writeFile(target, result.css, options);
}).
catch(error => {
let options = { error };
if(fingerprint !== undefined) {
options.fingerprint = fingerprint;
}
assetManager.writeFile(target, errorOutput(error.message,
assetManager.referenceDir),
options);
});
}
};
}

function previouslyIncluded(filepaths, previouslyIncludedFiles) {
return previouslyIncludedFiles === undefined ||
filepaths.some(filepath => {
return previouslyIncludedFiles.
find(candidate => candidate === path.normalize(filepath));
});
}

let MESSAGE_PATTERN = /^(\S+)(:\d+:\d+:)\s+(.+)$/;

function errorOutput(message, referenceDir) {
// eslint-disable-next-line no-unused-vars
let [_, file, locator, description] = MESSAGE_PATTERN.exec(message);
let error = `${path.relative(referenceDir, file)}${locator} ${description}`;

return `body:before {
content: "\\26a0 CSS Error: ${error.replace(/"/g, "'").replace(/\s+/g, " ")}";
font-weight: bold;
display: block;
border: 5px solid red;
padding: 5px;
}\n`;
}
50 changes: 50 additions & 0 deletions lib/make-postcss.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
let postcss = require("postcss");
let atImport = require("postcss-import");
let { promisify } = require("faucet-pipeline-core/lib/util");
let readFile = promisify(require("fs").readFile);

module.exports = function(input, target, assetManager, sourcemaps, browsers) {
// if(browsers && browsers.length > 0) {
// let filepath = path.relative(assetManager.referenceDir, input);
// console.error(`compiling CSS ${repr(filepath)} for ${browsers.join(", ")}`);

let processor = postcss([
atImport()
]);

let options = {
from: input,
target: target
};

if(sourcemaps) {
options.map = { inline: true };
}

return () => {
return readFile(input).then(code => {
return processor.process(code, options);
}).then(result => {
let warnings = result.warnings();

// TODO: Maybe do the manipulation of the message here
if(warnings.length > 0) {
let errorMessage = warnings.
map(warning => warning.toString()).
join("\n");
throw new Error(errorMessage);
}

let includedFiles = result.messages.
filter(message => message.type === "dependency").
map(message => message.file);

return {
css: result.css,
stats: {
includedFiles: [input].concat(includedFiles)
}
};
});
};
};
33 changes: 33 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"name": "faucet-pipeline-css",
"version": "0.1.0",
"description": "CSS for faucet-pipeline",
"main": "lib/index.js",
"scripts": {
"test": "npm-run-all --parallel lint test:cli",
"test:cli": "./test/run",
"lint": "eslint --cache lib test && echo ✓"
},
"repository": {
"type": "git",
"url": "git+https://github.com/faucet-pipeline/faucet-pipeline-css.git"
},
"author": "Lucas Dohmen <[email protected]> (https://lucas.dohmen.io/)",
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/faucet-pipeline/faucet-pipeline-css/issues"
},
"homepage": "https://www.faucet-pipeline.org",
"dependencies": {
"faucet-pipeline-core": "^1.0.0",
"postcss": "~7.0.3",
"postcss-import": "^12.0.0"
},
"devDependencies": {
"eslint-config-fnd": "^1.6.0",
"eslint-plugin-import": "^2.13.0",
"json-diff": "^0.5.2",
"npm-run-all": "^4.1.3",
"release-util-fnd": "^1.1.1"
}
}
11 changes: 11 additions & 0 deletions release
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/usr/bin/env bash

set -eu

. ./node_modules/release-util-fnd/lib.sh

pre_release_checks
npm run test

create_package > /dev/null
publish_package
32 changes: 32 additions & 0 deletions test/run
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/usr/bin/env bash
set -euo pipefail

root=`dirname "$0"`
root=`node -r fs -p "fs.realpathSync(process.argv[1]);" "$root"`

. "$root/../node_modules/faucet-pipeline-core/test/cli_harness.sh"

begin "$root/test_basic"
faucet
assert_identical "./dist/bundle.css" "./expected.css"
assert_missing "./expected.json"
end

begin "$root/test_error"
faucet || echo "Crashed successfully"
assert_identical "./dist/bundle.css" "./expected.css"
end

begin "$root/test_fingerprinting"
faucet --fingerprint
assert_identical "./dist/fingerprint/bundle-12c46b3f47e2c83fc4f31fb2d6564c51.css" "./expected.css"
assert_identical "./dist/no-fingerprint/bundle.css" "./expected.css"
assert_json "./dist/manifest.json" "./expected.json"
end

begin "$root/test_sourcemap"
faucet --sourcemaps
assert_identical_sourcemap "./dist/bundle.css" "./expected.css" "./expected.css.map"
end

echo; echo "SUCCESS: all tests passed"
7 changes: 7 additions & 0 deletions test/test_basic/expected.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.bar {
color: red;
}

.foo {
color: green;
}
15 changes: 15 additions & 0 deletions test/test_basic/faucet.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
"use strict";
let path = require("path");

module.exports = {
css: [{
source: "./src/index.css",
target: "./dist/bundle.css"
}],
plugins: {
css: {
plugin: path.resolve("../.."),
bucket: "styles"
}
}
};
5 changes: 5 additions & 0 deletions test/test_basic/src/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@import "./lib.css";

.foo {
color: green;
}
3 changes: 3 additions & 0 deletions test/test_basic/src/lib.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.bar {
color: red;
}
7 changes: 7 additions & 0 deletions test/test_error/expected.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
body:before {
content: "\26a0 CSS Error: src/index.css:3:1: Unexpected }";
font-weight: bold;
display: block;
border: 5px solid red;
padding: 5px;
}
15 changes: 15 additions & 0 deletions test/test_error/faucet.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
"use strict";
let path = require("path");

module.exports = {
css: [{
source: "./src/index.css",
target: "./dist/bundle.css"
}],
plugins: {
css: {
plugin: path.resolve("../.."),
bucket: "styles"
}
}
};
3 changes: 3 additions & 0 deletions test/test_error/src/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.foo
color: green;
}
7 changes: 7 additions & 0 deletions test/test_fingerprinting/expected.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.bar {
color: red;
}

.foo {
color: green;
}
1 change: 1 addition & 0 deletions test/test_fingerprinting/expected.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"dist/fingerprint/bundle.css":"/assets/dist/fingerprint/bundle-12c46b3f47e2c83fc4f31fb2d6564c51.css","dist/no-fingerprint/bundle.css":"/assets/dist/no-fingerprint/bundle.css"}
23 changes: 23 additions & 0 deletions test/test_fingerprinting/faucet.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"use strict";
let path = require("path");

module.exports = {
css: [{
source: "./src/index.css",
target: "./dist/fingerprint/bundle.css"
}, {
source: "./src/index.css",
target: "./dist/no-fingerprint/bundle.css",
fingerprint: false
}],
manifest: {
target: "./dist/manifest.json",
value: f => `/assets/${f}`
},
plugins: {
css: {
plugin: path.resolve("../.."),
bucket: "styles"
}
}
};
5 changes: 5 additions & 0 deletions test/test_fingerprinting/src/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@import "./lib.css";

.foo {
color: green;
}
3 changes: 3 additions & 0 deletions test/test_fingerprinting/src/lib.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.bar {
color: red;
}
8 changes: 8 additions & 0 deletions test/test_sourcemap/expected.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.bar {
color: red;
}

.foo {
color: green;
}

1 change: 1 addition & 0 deletions test/test_sourcemap/expected.css.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions test/test_sourcemap/faucet.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
"use strict";
let path = require("path");

module.exports = {
css: [{
source: "./src/index.css",
target: "./dist/bundle.css"
}],
plugins: {
css: {
plugin: path.resolve("../.."),
bucket: "styles"
}
}
};
Loading

0 comments on commit 149675d

Please sign in to comment.