Comparing version 1.1.5 to 1.2.0
{ | ||
"name": "fp-stylus", | ||
"version": "1.1.5", | ||
"version": "1.2.0", | ||
"description": "Stylus extension for Fepper", | ||
"main": "stylus~extend.js", | ||
"scripts": { | ||
"coverage": "nyc report --reporter=text-lcov | coveralls", | ||
"lint": "eslint *.js && eslint test/*.js", | ||
"test": "nyc mocha --exit" | ||
}, | ||
"husky": { | ||
"hooks": { | ||
"pre-push": "npm run lint && npm test" | ||
} | ||
}, | ||
"repository": { | ||
@@ -40,4 +50,16 @@ "type": "git", | ||
"dependencies": { | ||
"gulp-sourcemaps": "^2.6.4", | ||
"gulp-stylus": "^2.7.0" | ||
}, | ||
"devDependencies": { | ||
"chai": "4.x", | ||
"coveralls": "^3.0.2", | ||
"eslint": "3.x", | ||
"fepper": "*", | ||
"fepper-utils": "*", | ||
"gulp": "https://github.com/electric-eloquence/gulp/tarball/v3-lts", | ||
"husky": "^1.3.1", | ||
"mocha": "5.x", | ||
"nyc": "^13.1.0" | ||
} | ||
} |
136
README.md
# Stylus extension for Fepper | ||
[![Known Vulnerabilities][snyk-image]][snyk-url] | ||
[![Mac/Linux Build Status][travis-image]][travis-url] | ||
[![Windows Build Status][appveyor-image]][appveyor-url] | ||
[![Coverage Status][coveralls-image]][coveralls-url] | ||
[![License][license-image]][license-url] | ||
### Install | ||
Add these tasks to `excludes/extend/custom.js`: | ||
```shell | ||
cd extend | ||
npm install --save-dev fp-stylus | ||
``` | ||
* Under gulp task 'custom:frontend-copy' | ||
* 'stylus:frontend-copy' | ||
* Under gulp task 'custom:once' | ||
* 'stylus:once' | ||
* Under gulp task 'custom:watch' | ||
* 'stylus:watch' | ||
### Use | ||
There is also a 'stylus:no-comment' task, which will output CSS without line | ||
comments. You probably want this to process CSS destined for production. | ||
Add these tasks to `extend/custom.js`: | ||
In a full ([main](https://github.com/electric-eloquence/fepper)) Fepper | ||
installation, there should already be a `source/_styles/src/stylus` directory. | ||
Create one if there isn't and put all Stylus code there. | ||
* Under gulp task `'custom:frontend-copy'` | ||
* `'stylus:frontend-copy'` | ||
* Under gulp task `'custom:once'` | ||
* `'stylus:once'` | ||
* Under gulp task `'custom:watch'` | ||
* `'stylus:watch'` | ||
Running any of these tasks will write the compiled CSS to the | ||
`paths.source.cssBld` directory as defined in `patternlab-config.json`. | ||
On the command line: | ||
```shell | ||
fp stylus[:subtask] | ||
``` | ||
The ([main](https://github.com/electric-eloquence/fepper)) Fepper distribution | ||
ships with a `source/_styles/src/stylus` directory by default. Create one if | ||
there isn't one, and put all Stylus code there. | ||
This extension will read one directory deep for files with a `.styl` extension. | ||
Partials must be nested deeper. Stylus code will be preprocessed into CSS and | ||
built into the `paths.source.cssBld` directory as declared in | ||
`patternlab-config.json`. | ||
This extension defaults toward the printing of line comments for debugging | ||
purposes. Doing so provides an unambiguous indication that the CSS was | ||
preprocessed and that direct edits to the CSS should be avoided. If a project | ||
decision is made to style with Stylus, it would be a good idea to have version | ||
control ignore CSS builds in the `source` directory. This would avoid committing | ||
line comments, which could otherwise lead to a morass of conflicts. | ||
Another debugging alternative is writing CSS sourcemaps. (However, this will not | ||
work if line comments are enabled.) Add the following to | ||
your `pref.yml` file: | ||
```yaml | ||
stylus: | ||
linenos: false | ||
sourcemap: true | ||
``` | ||
The `stylus.sourcemap` setting in `pref.yml` will accept any of the | ||
<a href="http://stylus-lang.com/docs/sourcemaps.html" target="_blank"> | ||
documented Stylus sourcemap options</a>. Just set `stylus.sourcemap` as an | ||
object and configure its properties as desired. Similarly, the `stylus` | ||
setting will accept any documented Stylus option and submit it to Stylus. | ||
### Tasks | ||
#### `'stylus'` | ||
* Builds Stylus into CSS. | ||
* Overwrites CSS whether or not it has direct edits. | ||
* Respects the `stylus.linenos` setting in `pref.yml`. | ||
* If `stylus.linenos` is not set, will default to printing line comments. | ||
#### `'stylus:diff-then-comment'` | ||
* Usually under gulp task `'custom:once'`. | ||
* Checks if the Stylus code was modified before overwriting CSS. | ||
* Allows direct edits to CSS without triggering Stylus builds. | ||
* Allows the choice of using Stylus exclusively or not using Stylus exclusively. | ||
* Respects the `stylus.linenos` setting in `pref.yml`. | ||
* If `stylus.linenos` is not set, will default to printing line comments. | ||
#### `'stylus:frontend-copy'` | ||
* Usually under gulp task `'custom:frontend-copy'`. | ||
* Checks if the CSS has line comments or not. | ||
* If it does, it builds Stylus without line comments and copies the CSS to the backend. | ||
* If it does not, it just copies the CSS to the backend. | ||
#### `'stylus:no-comment'` | ||
* Same as `'stylus'` and `'stylus:once'` but without line comments. | ||
* Ignores any `stylus.linenos` setting in `pref.yml`. | ||
#### `'stylus:once'` | ||
* Usually under gulp task `'custom:once'`. | ||
* Same as `'stylus'`. | ||
#### `'stylus:watch'` | ||
* Usually under gulp task `'custom:watch'`. | ||
* Watches the `source/_styles/src/stylus` directory for file modifications. | ||
* Triggers `stylus` and overwrites CSS whether or not it has direct edits. | ||
#### `'stylus:watch-no-comment'` | ||
* Usually under gulp task `'custom:watch'`. | ||
* Watches the `source/_styles/src/stylus` directory for file modifications. | ||
* Triggers `stylus:no-comment` and overwrites CSS whether or not it has direct | ||
edits. | ||
#### `'stylus:watch-write-tmp'` | ||
* Usually under gulp task `'custom:watch'`. | ||
* Watches the `source/_styles/src/stylus` directory for file modifications. | ||
* Triggers `stylus` and overwrites CSS whether or not it has direct edits. | ||
* Writes the tmp file for comparing the current Stylus build with the previous | ||
one. | ||
#### `'stylus:write-tmp'` | ||
* Writes the tmp file for comparing the current Stylus build with the previous | ||
one. | ||
[snyk-image]: https://snyk.io/test/github/electric-eloquence/fp-stylus/master/badge.svg | ||
[snyk-url]: https://snyk.io/test/github/electric-eloquence/fp-stylus/master | ||
[travis-image]: https://img.shields.io/travis/electric-eloquence/fp-stylus.svg?label=mac%20%26%20linux | ||
[travis-url]: https://travis-ci.org/electric-eloquence/fp-stylus | ||
[appveyor-image]: https://img.shields.io/appveyor/ci/e2tha-e/fp-stylus.svg?label=windows | ||
[appveyor-url]: https://ci.appveyor.com/project/e2tha-e/fp-stylus | ||
[coveralls-image]: https://img.shields.io/coveralls/electric-eloquence/fp-stylus/master.svg | ||
[coveralls-url]: https://coveralls.io/r/electric-eloquence/fp-stylus | ||
[license-image]: https://img.shields.io/github/license/electric-eloquence/fp-stylus.svg | ||
[license-url]: https://raw.githubusercontent.com/electric-eloquence/fp-stylus/master/LICENSE |
'use strict'; | ||
const path = require('path'); | ||
const {Transform} = require('stream'); | ||
@@ -8,3 +9,3 @@ const fs = require('fs-extra'); | ||
const gulpStylus = require('gulp-stylus'); | ||
const runSequence = require('run-sequence'); | ||
const sourcemaps = require('gulp-sourcemaps'); | ||
const stylus = require('stylus'); | ||
@@ -14,2 +15,3 @@ const utils = require('fepper-utils'); | ||
const conf = global.conf; | ||
const pref = global.pref; | ||
@@ -19,3 +21,54 @@ const cssBldDir = conf.ui.paths.source.cssBld; | ||
function diffThenRender(commentBool, cb) { | ||
function getSourcemapDest() { | ||
if (pref.stylus.sourcemap) { | ||
if (!pref.stylus.sourcemap.inline) { | ||
return '.'; | ||
} | ||
} | ||
return; | ||
} | ||
function getSourceRoot() { | ||
if (pref.stylus.sourcemap) { | ||
let sourceRoot; | ||
if (pref.stylus.sourcemap.sourceRoot) { | ||
sourceRoot = pref.stylus.sourcemap.sourceRoot; | ||
} | ||
else { | ||
const uiSourceDir = conf.ui.paths.source.root; | ||
if (cssSrcDir.indexOf(uiSourceDir) === 0) { | ||
sourceRoot = cssSrcDir.slice(uiSourceDir.length); | ||
sourceRoot += '/stylus'; | ||
} | ||
} | ||
return sourceRoot; | ||
} | ||
return; | ||
} | ||
function streamUntouched() { | ||
return new Transform({ | ||
readableObjectMode: true, | ||
writableObjectMode: true, | ||
transform(file, enc, cb) { | ||
this.push(file); | ||
cb(); | ||
} | ||
}); | ||
} | ||
// Set up pref.stylus. | ||
pref.stylus = pref.stylus || {}; | ||
// Opt for line comments by default. | ||
if (pref.stylus.linenos !== false) { | ||
pref.stylus.linenos = true; | ||
} | ||
function testForComments() { | ||
const cssFilesBld = fs.readdirSync(cssBldDir); | ||
@@ -27,2 +80,8 @@ let hasComments = false; | ||
const cssFileBld = `${cssBldDir}/${cssFilesBld[i]}`; | ||
/* istanbul ignore if */ | ||
if (!fs.existsSync(cssFileBld)) { | ||
continue; | ||
} | ||
const stat = fs.statSync(cssFileBld); | ||
@@ -36,3 +95,4 @@ | ||
hasComments = /^\/\* line \d+ : /m.test(cssOld) && /\.styl \*\/$/m.test(cssOld); | ||
hasComments = (/^\/\* line \d+ : /m.test(cssOld) && /\.styl \*\/$/m.test(cssOld)) || | ||
/^\/\*# sourceMappingURL=/m.test(cssOld); | ||
@@ -44,17 +104,14 @@ if (hasComments) { | ||
return hasComments; | ||
} | ||
function diffThenRender(cb) { | ||
const hasComments = testForComments(); | ||
if (hasComments) { | ||
if (commentBool) { | ||
runSequence( | ||
'stylus:write-tmp', | ||
'stylus', | ||
cb | ||
); | ||
} | ||
else { | ||
runSequence( | ||
'stylus:write-tmp', | ||
'stylus:no-comment', | ||
cb | ||
); | ||
} | ||
gulp.runSequence( | ||
'stylus:write-tmp', | ||
'stylus', | ||
cb | ||
); | ||
@@ -66,9 +123,9 @@ return; | ||
const stylFiles = fs.readdirSync(stylDir); | ||
i = stylFiles.length; | ||
let i = stylFiles.length; | ||
while (i--) { | ||
const stylFile = `${stylDir}/${stylFiles[i]}`; | ||
const stylFileObj = path.parse(stylFile); | ||
if (stylFileObj.ext !== '.styl') { | ||
/* istanbul ignore if */ | ||
if (!fs.existsSync(stylFile)) { | ||
if (i === 0) { | ||
@@ -91,2 +148,13 @@ cb(); | ||
const stylFileObj = path.parse(stylFile); | ||
if (stylFileObj.ext !== '.styl') { | ||
/* istanbul ignore if */ | ||
if (i === 0) { | ||
cb(); | ||
} | ||
continue; | ||
} | ||
const stylFileStr = fs.readFileSync(stylFile, conf.enc); | ||
@@ -101,5 +169,9 @@ | ||
if (err) { | ||
/* istanbul ignore next */ | ||
utils.error(err); | ||
} | ||
else { | ||
// Declare bld file. | ||
const cssFileBld = `${cssBldDir}/${stylFileObj.name}.css`; | ||
const cssFileBldExists = fs.existsSync(cssFileBld); | ||
// Declare tmp file for comparison. | ||
@@ -112,2 +184,12 @@ const cssFileTmp = `${cssSrcDir}/.tmp/${stylFileObj.name}.css`; | ||
} | ||
// We need to render Stylus if cssFileBld does not exist. This will likely be the case on the first | ||
// invocation of this function if cssFileBld is not version controlled. In that case, we need to skip the | ||
// next clause. | ||
else if (cssFileBldExists) { | ||
// In other cases where cssFileTmp does not exist, output cssFileTmp for future comparison. | ||
// Set cssFileTmpStr == cssNew to skip overwriting cssFileBld. | ||
fs.outputFileSync(cssFileTmp, cssNew); | ||
// Exit this iteration in next block. | ||
cssFileTmpStr = cssNew; | ||
} | ||
@@ -118,2 +200,3 @@ // Compare newly rendered css with the contents of the tmp file. | ||
if (cssFileTmpStr === cssNew) { | ||
/* istanbul ignore if */ | ||
if (iteration === 0) { | ||
@@ -129,32 +212,44 @@ cb(); | ||
// Now, compare against bld css. | ||
const cssFileBld = `${cssBldDir}/${stylFileObj.name}.css`; | ||
const stat = fs.statSync(cssFileBld); | ||
// Now, compare tmp css against bld css. | ||
const prefStylusClone = Object.assign({}, pref.stylus, {filename: stylFile}); | ||
let stat; | ||
if (stat.isFile()) { | ||
const cssOld = fs.readFileSync(cssFileBld, conf.enc); | ||
if (cssFileBldExists) { | ||
stat = fs.statSync(cssFileBld); | ||
} | ||
// The first time 'stylus:diff-then-comment' is run, cssNew should equal cssOld. | ||
// cssFileTmp will have been written at this point and will be used for future comparisons. | ||
// If users only edit bld css and do not modify Stylus files, they should never get to this point. | ||
if (!cssFileBldExists || stat.isFile()) { | ||
let cssOld = ''; | ||
if (cssFileBldExists) { | ||
cssOld = fs.readFileSync(cssFileBld, conf.enc); | ||
} | ||
// Only overwrite bld css if tmp css and bld css differ. | ||
if (cssNew !== cssOld) { | ||
stylus(stylFileStr) | ||
.set('filename', stylFile) | ||
.set('linenos', commentBool) | ||
.render( | ||
((iteration1) => { | ||
return (err1, cssNew1) => { | ||
if (err1) { | ||
utils.error(err1); | ||
const style = stylus(stylFileStr, prefStylusClone); | ||
style.render( | ||
((iteration1) => { | ||
return (err1, cssNew1) => { | ||
if (err1) { | ||
/* istanbul ignore next */ | ||
utils.error(err1); | ||
} | ||
else { | ||
fs.outputFileSync(cssFileBld, cssNew1); | ||
// Only write sourcemap if not printing line comments and not writing the sourcemap inline. | ||
if (style.sourcemap && !prefStylusClone.linenos && !prefStylusClone.sourcemap.inline) { | ||
fs.outputFileSync(`${cssFileBld}.map`, JSON.stringify(style.sourcemap)); | ||
} | ||
else { | ||
fs.outputFileSync(cssFileBld, cssNew1); | ||
} | ||
} | ||
if (iteration1 === 0) { | ||
cb(); | ||
} | ||
}; | ||
})(iteration) | ||
); | ||
/* istanbul ignore if */ | ||
if (iteration1 === 0) { | ||
cb(); | ||
} | ||
}; | ||
})(iteration) | ||
); | ||
} | ||
@@ -164,2 +259,3 @@ } | ||
/* istanbul ignore if */ | ||
if (iteration === 0) { | ||
@@ -172,2 +268,3 @@ cb(); | ||
/* istanbul ignore if */ | ||
if (i === 0) { | ||
@@ -180,11 +277,30 @@ cb(); | ||
function handleError(err) { | ||
/* istanbul ignore next */ | ||
utils.error(err.toString()); | ||
/* istanbul ignore next */ | ||
this.emit('end'); | ||
} | ||
// Declare gulp tasks. | ||
gulp.task('stylus', function () { | ||
const sourceRoot = getSourceRoot(); | ||
let sourcemapsInit = sourcemaps.init; | ||
let sourcemapsWrite = sourcemaps.write; | ||
// Do not write sourcemaps if pref.stylus.sourcemap is falsey. | ||
// Do not write sourcemaps if linenos === true, as the sourcemaps will be inaccurate and the linenos redundant. | ||
if (!pref.stylus.sourcemap || pref.stylus.linenos) { | ||
sourcemapsInit = () => { | ||
return streamUntouched(); | ||
}; | ||
sourcemapsWrite = () => { | ||
return streamUntouched(); | ||
}; | ||
} | ||
return gulp.src(cssSrcDir + '/stylus/*.styl') | ||
.pipe(gulpStylus({ | ||
linenos: true | ||
})) | ||
.pipe(sourcemapsInit()) | ||
.pipe(gulpStylus(pref.stylus)) | ||
.pipe(sourcemapsWrite(getSourcemapDest(), {sourceRoot})) | ||
.on('error', handleError) | ||
@@ -194,25 +310,42 @@ .pipe(gulp.dest(cssBldDir)); | ||
// This first checks if the old bld CSS has line comments. If so, it runs the 'stylus' task and returns. | ||
// If there are no line comments, it processes Stylus without line comments, to compare the new CSS with the old CSS. | ||
// If there's a difference, it then processes Stylus again with line comments and writes that CSS to the bld directory. | ||
// Otherwise, it leaves the old bld CSS alone. | ||
// The intended result is for users who use Fepper defaults never to notice Stylus being processed if they never edit | ||
// Stylus files, and for users who do edit Stylus files to have Stylus process as expected. | ||
// This first checks if the old bld CSS has line comments. If so, it runs the 'stylus' task. | ||
// It then renders Stylus into tmp CSS files without line comments for future comparison, and returns. | ||
// If the bld CSS has no line comments, it renders Stylus without line comments, to compare the new CSS with the old. | ||
// The first time it runs, it just writes the rendered CSS to a tmp file for future comparison. | ||
// On subsequent runs, it compares against the previously written tmp CSS. | ||
// If there's no difference, it exits for that file and moves on to the next file if there is one. | ||
// If there is a difference, it writes the new tmp CSS file. | ||
// It then checks for a difference between the new tmp CSS and the bld CSS. | ||
// If there is a difference, it renders Stylus again with line comments and writes that over the bld CSS. | ||
// The intent is for users who use Fepper defaults to never render Stylus if they never edit Stylus files, | ||
// and for users who do edit Stylus files to have Stylus render as expected. | ||
// Power-users should replace this with the 'stylus:once' or 'stylus:no-comment' task for better performance. | ||
gulp.task('stylus:diff-then-comment', function (cb) { | ||
diffThenRender(true, cb); | ||
diffThenRender(cb); | ||
}); | ||
// Same as 'stylus:diff-then-comment' but with no line comments in rendered CSS. | ||
gulp.task('stylus:diff-then-no-comment', function (cb) { | ||
diffThenRender(false, cb); | ||
// 'stylus:frontend-copy' checks if there are line comments in the bld CSS. | ||
// If there are, it renders Stylus without line comments for the full 'frontend-copy' task to copy to the backend. | ||
// If there are not, it does nothing and allows the full 'frontend-copy' task to copy the bld CSS to the backend. | ||
gulp.task('stylus:frontend-copy', function (cb) { | ||
const hasComments = testForComments(); | ||
if (hasComments) { | ||
gulp.runSequence( | ||
'stylus:no-comment', | ||
cb | ||
); | ||
} | ||
else { | ||
cb(); | ||
} | ||
}); | ||
// This runs the CSS processor without outputting line comments. | ||
// You probably want this to process CSS destined for production. | ||
// This renders Stylus without printing line comments. It also never writes sourcemaps. | ||
// You probably want this to preprocess CSS destined for production. | ||
gulp.task('stylus:no-comment', function () { | ||
const prefStylusClone = Object.assign({}, pref.stylus, {linenos: false}); | ||
return gulp.src(cssSrcDir + '/stylus/*.styl') | ||
.pipe(gulpStylus({ | ||
linenos: false | ||
})) | ||
.pipe(gulpStylus(prefStylusClone)) | ||
.on('error', handleError) | ||
@@ -222,12 +355,19 @@ .pipe(gulp.dest(cssBldDir)); | ||
gulp.task('stylus:frontend-copy', function (cb) { | ||
runSequence( | ||
'stylus:diff-then-no-comment', | ||
'ui:copy-styles', | ||
cb | ||
); | ||
gulp.task('stylus:once', ['stylus']); | ||
gulp.task('stylus:watch', function () { | ||
// Return the watcher so it can be closed after testing. | ||
return gulp.watch('stylus/**/*', {cwd: cssSrcDir}, ['stylus']); | ||
}); | ||
gulp.task('stylus:once', ['stylus']); | ||
gulp.task('stylus:watch-no-comment', function () { | ||
// Return the watcher so it can be closed after testing. | ||
return gulp.watch('stylus/**/*', {cwd: cssSrcDir}, ['stylus:no-comment']); | ||
}); | ||
gulp.task('stylus:watch-write-tmp', function () { | ||
// Return the watcher so it can be closed after testing. | ||
return gulp.watch('stylus/**/*', {cwd: cssSrcDir}, ['stylus:write-tmp', 'stylus']); | ||
}); | ||
// This outputs tmp files without line comments to check for modifications to Stylus code. | ||
@@ -242,13 +382,1 @@ gulp.task('stylus:write-tmp', function () { | ||
}); | ||
gulp.task('stylus:watch', function () { | ||
gulp.watch('stylus/**/*', {cwd: cssSrcDir}, ['stylus']); | ||
}); | ||
gulp.task('stylus:watch-no-comment', function () { | ||
gulp.watch('stylus/**/*', {cwd: cssSrcDir}, ['stylus:no-comment']); | ||
}); | ||
gulp.task('stylus:watch-write-tmp', function () { | ||
gulp.watch('stylus/**/*', {cwd: cssSrcDir}, ['stylus:write-tmp', 'stylus']); | ||
}); |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
18394
297
131
2
9
1
+ Addedgulp-sourcemaps@^2.6.4
+ Added@gulp-sourcemaps/identity-map@1.0.2(transitive)
+ Addedacorn@5.7.4(transitive)
+ Addedd@1.0.2(transitive)
+ Addeddebug@3.2.7(transitive)
+ Addeddebug-fabulous@1.1.0(transitive)
+ Addeddetect-newline@2.1.0(transitive)
+ Addedes5-ext@0.10.64(transitive)
+ Addedes6-iterator@2.0.3(transitive)
+ Addedes6-symbol@3.1.4(transitive)
+ Addedes6-weak-map@2.0.3(transitive)
+ Addedesniff@2.0.1(transitive)
+ Addedevent-emitter@0.3.5(transitive)
+ Addedext@1.7.0(transitive)
+ Addedgraceful-fs@4.2.11(transitive)
+ Addedgulp-sourcemaps@2.6.5(transitive)
+ Addedis-promise@2.2.2(transitive)
+ Addedlru-queue@0.1.0(transitive)
+ Addedmemoizee@0.4.17(transitive)
+ Addedms@2.1.3(transitive)
+ Addednext-tick@1.1.0(transitive)
+ Addednormalize-path@2.1.1(transitive)
+ Addedobject-assign@4.1.1(transitive)
+ Addedremove-trailing-separator@1.1.0(transitive)
+ Addedstrip-bom-string@1.0.0(transitive)
+ Addedtimers-ext@0.1.8(transitive)
+ Addedtype@2.7.3(transitive)