sheetloaf 0.11.2 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -23
- package/dist/index.js +2 -0
- package/dist/parser.js +1 -0
- package/package.json +53 -50
- package/index.js +0 -243
- package/parser.js +0 -118
package/README.md
CHANGED
|
@@ -2,7 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
An alternative to postcss-cli for sass users. Compile sass files to CSS and transform using postcss, all in one command.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Using npm (or your package manager of choice):
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
npm install sheetloaf
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Sheetloaf also requires a peer dependency of postcss, so go ahead and run:
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
npm install postcss
|
|
17
|
+
```
|
|
6
18
|
|
|
7
19
|
## Usage
|
|
8
20
|
|
|
@@ -18,7 +30,7 @@ Usage:
|
|
|
18
30
|
Basic options:
|
|
19
31
|
-o, --output Output file [string]
|
|
20
32
|
-d, --dir Output directory [string]
|
|
21
|
-
-w, --watch Watch files for changes and recompile as needed [boolean]
|
|
33
|
+
-w, --watch Watch files for changes and recompile as needed [boolean]
|
|
22
34
|
|
|
23
35
|
Options for use without a postcss config file:
|
|
24
36
|
-u, --use List of postcss plugins to use [array]
|
|
@@ -26,37 +38,37 @@ Options for use without a postcss config file:
|
|
|
26
38
|
Options for use with --dir:
|
|
27
39
|
--ext Override the output file extension; for use with --dir [string]
|
|
28
40
|
--base Mirror the directory structure relative to this path [string]
|
|
29
|
-
in the output directory, for use with --dir
|
|
41
|
+
in the output directory, for use with --dir
|
|
30
42
|
|
|
31
43
|
Sass options:
|
|
32
44
|
-s, --style Output style. Possible values are "expanded", [string]
|
|
33
45
|
or "compressed". Default: "expanded".
|
|
34
46
|
--[no-]source-map Whether to generate source maps. Default is on. [boolean]
|
|
35
47
|
--embed-source-map Tells Sass to embed the contents of the source [boolean]
|
|
36
|
-
map file in the generated CSS, rather than
|
|
37
|
-
creating a separate file and linking to it
|
|
48
|
+
map file in the generated CSS, rather than
|
|
49
|
+
creating a separate file and linking to it
|
|
38
50
|
from the CSS.
|
|
39
51
|
--embed-sources Embed the entire contents of the Sass files that [boolean]
|
|
40
|
-
contributed to the generated CSS in the source map.
|
|
41
|
-
This may produce very large source maps, but it
|
|
42
|
-
guarantees that the source will be available on
|
|
52
|
+
contributed to the generated CSS in the source map.
|
|
53
|
+
This may produce very large source maps, but it
|
|
54
|
+
guarantees that the source will be available on
|
|
43
55
|
any computer no matter how the CSS is served.
|
|
44
56
|
-–source-map-urls Controls how the source maps that Sass generates [string]
|
|
45
|
-
link back to the Sass files that contributed to
|
|
57
|
+
link back to the Sass files that contributed to
|
|
46
58
|
the generated CSS. Possible values are "relative"
|
|
47
59
|
or "absolute". Default: "relative".
|
|
48
60
|
--[no-]error-css This flag tells Sass whether to emit a CSS file [boolean]
|
|
49
|
-
when an error occurs during compilation. This
|
|
61
|
+
when an error occurs during compilation. This
|
|
50
62
|
CSS file describes the error in a comment and in
|
|
51
|
-
the content property of body::before, so that
|
|
52
|
-
you can see the error message in the browser
|
|
53
|
-
without needing to switch back to the terminal.
|
|
63
|
+
the content property of body::before, so that
|
|
64
|
+
you can see the error message in the browser
|
|
65
|
+
without needing to switch back to the terminal.
|
|
54
66
|
-I, --load-path Adds an additional load path for Sass to look [string]
|
|
55
67
|
for stylesheets.
|
|
56
68
|
|
|
57
69
|
Advanced options:
|
|
58
70
|
--poll Use polling for file watching. Can optionally pass polling [boolean]
|
|
59
|
-
interval; default 100 ms
|
|
71
|
+
interval; default 100 ms
|
|
60
72
|
--config Set a custom directory to look for a config file [string]
|
|
61
73
|
|
|
62
74
|
Misc:
|
|
@@ -71,7 +83,7 @@ Misc:
|
|
|
71
83
|
sheetloaf scss/style.scss --output css/style.css --style compressed --use autoprefixer
|
|
72
84
|
```
|
|
73
85
|
|
|
74
|
-
Above is an example of transforming a sass file, compressing the output and using the
|
|
86
|
+
Above is an example of transforming a sass file, compressing the output and using the
|
|
75
87
|
postcss plugin autoprefixer to add vendor prefixes. Note that postcss plugins will need to be installed
|
|
76
88
|
separately, so to use autoprefixer you'd first run:
|
|
77
89
|
|
|
@@ -88,11 +100,10 @@ sheetloaf "scss/**/*.scss" --dir css --style compressed --use autoprefixer
|
|
|
88
100
|
sheetloaf scss --dir css --style compressed --use autoprefixer
|
|
89
101
|
```
|
|
90
102
|
|
|
91
|
-
In this case we're using the --dir option in place of output. Sheetloaf will automatically ignore partial files whose names begin with _.
|
|
103
|
+
In this case we're using the --dir option in place of output. Sheetloaf will automatically ignore partial files whose names begin with \_.
|
|
92
104
|
|
|
93
105
|
For best results when using a glob pattern, make sure to use quotes to avoid side-issues. See https://medium.com/@jakubsynowiec/you-should-always-quote-your-globs-in-npm-scripts-621887a2a784
|
|
94
106
|
|
|
95
|
-
|
|
96
107
|
Sheetloaf also allows for piping!
|
|
97
108
|
|
|
98
109
|
```
|
|
@@ -103,10 +114,10 @@ cat scss/style.scss | sheetloaf --use autoprefixer --output css/style.css
|
|
|
103
114
|
sheetloaf scss/style.scss --use autoprefixer > style.css
|
|
104
115
|
|
|
105
116
|
// stdout and logging to stderr
|
|
106
|
-
sheetloaf scss/style.scss --use autoprefixer 2> error.txt 1> style.css
|
|
117
|
+
sheetloaf scss/style.scss --use autoprefixer 2> error.txt 1> style.css
|
|
107
118
|
|
|
108
119
|
// all together now!
|
|
109
|
-
cat scss/style.scss | sheetloaf --use autoprefixer 2> error.txt 1> style.css
|
|
120
|
+
cat scss/style.scss | sheetloaf --use autoprefixer 2> error.txt 1> style.css
|
|
110
121
|
```
|
|
111
122
|
|
|
112
123
|
## FAQ
|
|
@@ -121,13 +132,13 @@ Postcss-scss combined with other plugins like postcss-mixins gets you in the bal
|
|
|
121
132
|
|
|
122
133
|
### Why not just use sass and pipe the output to postcss-cli?
|
|
123
134
|
|
|
124
|
-
This works great with single files but when you've got a filewatcher on multiple files this isn't possible.
|
|
135
|
+
This works great with single files but when you've got a filewatcher on multiple files this isn't possible.
|
|
125
136
|
|
|
126
|
-
You
|
|
137
|
+
You _could_ do something like render sass files, output them to a temp folder, and then when those files are modified, check that with chokidar and then call postcss-cli on them to do the rest of the job. This is what I did for a while and I found it to an extremely fiddly and inelegant solution.
|
|
127
138
|
|
|
128
139
|
### What's the benefit of using this over something like Gulp, Webpack, or Parcel?
|
|
129
140
|
|
|
130
|
-
For complex projects a more full-featured tool may be more useful, or if you prefer prefer processing all of your scripts/styles/etc in one place.
|
|
141
|
+
For complex projects a more full-featured tool may be more useful, or if you prefer prefer processing all of your scripts/styles/etc in one place.
|
|
131
142
|
|
|
132
143
|
The benefit of Sheetloaf is fewer dependencies and build simplicity. I've used this tool for all of my personal web projects, and figured I'd polish it up and see if it helps anyone else.
|
|
133
144
|
|
|
@@ -139,4 +150,8 @@ Likewise, if all you're looking for is to compile Sass with no transformations,
|
|
|
139
150
|
|
|
140
151
|
### Why doesn't sheetloaf support custom stringifiers/syntaxes/parsers?
|
|
141
152
|
|
|
142
|
-
I don't currently see a good use case for including these, since sheetloaf is currently intended to only be used with Sass files. I'm open to be proven wrong though!
|
|
153
|
+
I don't currently see a good use case for including these, since sheetloaf is currently intended to only be used with Sass files. I'm open to be proven wrong though!
|
|
154
|
+
|
|
155
|
+
### Why doesn't sheetloaf support custom stringifiers/syntaxes/parsers?
|
|
156
|
+
|
|
157
|
+
I don't currently see a good use case for including these, since sheetloaf is currently intended to only be used with Sass files. I'm open to be proven wrong though!
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const chokidar=require("chokidar"),color=require("picocolors"),{Command}=require("commander"),fs=require("fs"),path=require("path"),postcss=require("postcss"),sass=require("sass"),parser=require("./parser"),ver=require("../package.json").version,sheetloaf=new Command;let postcssConfig={plugins:[]},usingStdin=!1;sheetloaf.version(ver,"-v, --version","Print the version of Sheetloaf."),sheetloaf.arguments("[sources...]").description("\u{1F4C3}\u{1F35E} Compile Sass to CSS and transform the output using PostCSS all in one command.").action(o=>{if(o.length>0)init(o);else if(!process.stdin.isTTY){let e="";process.stdin.on("readable",function(){var t=this.read();t!==null&&(e+=t)}),process.stdin.on("end",function(){usingStdin=!0,init(e)})}}),sheetloaf.option("-o, --output <LOCATION>","Output file.").option("--dir <LOCATION>","Output directory.").option("--base <DIR>","Mirror the directory structure relative to this path in the output directory, for use with --dir.","").option("--ext <EXTENSION>","Override the output file extension; for use with --dir",".css").option("-s, --style <NAME>",'Output style. ["expanded", "compressed"]',"expanded").option("--source-map","Generate a source map (this is the default option).").option("--no-source-map","Do not generate a source map.").option("--embed-source-map","Embed the contents of the source map file in the generated CSS, rather than creating a separate file and linking to it from the CSS.").option("--embed-sources","Embed the entire contents of the Sass files that contributed to the generated CSS in the source map.").option("--source-map-urls <TYPE>",'Controls how the source maps that Sass generates link back to the Sass files that contributed to the generated CSS. ["relative", "absolute"]',"relative").option("--error-css","Emit a CSS file when an error occurs during compilation (this is the default option).").option("--no-error-css","Do not emit a CSS file when an error occurs during compilation.").option("-I, --load-path <PATHS>","Adds an additional load path for Sass to look for stylesheets.").option("-w, --watch","Watch stylesheets and recompile when they change.").option("--config <LOCATION>","Set a custom directory to look for a postcss config file.").option("--poll [DURATION]","Use polling for file watching. Can optionally pass polling interval; default 100 ms").option("-u, --use <PLUGINS>","List of postcss plugins to use. Will cause sheetloaf to ignore any config files."),sheetloaf.parse(process.argv);function init(o){postcssConfig=parser.generatePostcssConfig(sheetloaf.opts().config,sheetloaf.opts().use),usingStdin===!0?render(o):(parser.expandGlob(o[0].split(","),function(e){e.forEach(function(t){path.basename(t).charAt(0)!=="_"&&render(t)})}),watch(o))}function watch(o){sheetloaf.opts().watch===!0&&chokidar.watch(o[0].split(","),{usePolling:sheetloaf.opts().poll!==void 0,interval:typeof sheetloaf.opts().poll=="number"?sheetloaf.opts().poll:100,ignoreInitial:!0,awaitWriteFinish:{stabilityThreshold:1500,pollInterval:100}}).on("change",e=>{console.log(`File changed: ${e}`),parser.expandGlob(o[0].split(","),function(t){t.forEach(function(i){path.basename(i).charAt(0)!=="_"&&render(i)})})}).on("add",e=>{console.log(`File added: ${e}`),parser.expandGlob(o[0].split(","),function(t){t.forEach(function(i){path.basename(i).charAt(0)!=="_"&&render(i)})})})}function render(o){usingStdin===!1&&console.log(`Rendering ${o}...`);let e=parser.createDestination(o,sheetloaf.opts().output,sheetloaf.opts().dir,sheetloaf.opts().base,sheetloaf.opts().ext,usingStdin),t=generateSassOptions(o,e),i={inline:sheetloaf.opts().embedSourceMap===!0,absolute:sheetloaf.opts().sourceMapUrls==="absolute",sourcesContent:sheetloaf.opts().embedSources===!0};usingStdin===!1&&sheetloaf.opts().sourceMap!==!1&&(i=!1);try{let n=sass.renderSync(t);postcss(postcssConfig.plugins).process(n.css.toString(),{from:n.stats.entry,to:e,map:i}).then(s=>{if(s.warnings().forEach(r=>{process.stderr.write(r.toString())}),e!==""){try{fs.mkdirSync(path.dirname(e),{recursive:!0})}catch(r){if(r.code!=="EEXIST"||r.code!=="EISDIR")throw r}fs.writeFile(e,s.css,r=>{if(r)throw r;console.log(color.green(`Successfully written to ${e}`))}),s.map&&fs.writeFile(e+".map",s.map.toString(),r=>{if(r)throw r})}else process.stdout.write(s.css)}).catch(s=>{e!==""?console.log(color.red(s)):process.stderr.write(s)})}catch(n){if(e!==""){console.log(color.red(n.formatted));try{fs.mkdirSync(path.dirname(e),{recursive:!0})}catch(s){if(s.code!=="EEXIST"||s.code!=="EISDIR")throw s}sheetloaf.opts().errorCss!==!1&&fs.writeFile(e,emitSassError(n),s=>{if(s)throw s;console.log(color.yellow(`Emitted error to ${e}`))})}else process.stderr.write(n.formatted);!sheetloaf.opts().watch&&(process.exitCode==null||process.exitCode===0)&&(process.exitCode=1)}}function generateSassOptions(o,e){let t={outFile:e,outputStyle:sheetloaf.opts().style,includePaths:sheetloaf.opts().loadPath?sheetloaf.opts().loadPath.split(","):[]};return usingStdin===!0?(t.data=o,t.sourceMap=!1,t.sourceMapContents=!1,t.sourceMapEmbed=!1):(t.file=o,t.sourceMap=sheetloaf.opts().sourceMap!==!1,t.sourceMapContents=sheetloaf.opts().sourceMap!==!1,t.sourceMapEmbed=sheetloaf.opts().sourceMap!==!1),t}function emitSassError(o){let e=o.formatted.substr(0,o.formatted.indexOf("^")).replace(/(\r\n|\n|\r)/gm," ").replace(/'/,"").replace(/╷.*?│/,"").replace(/│/,"").replace("'","").replace("'",""),t=o.file.replace(/\\/g,"/");return`body:before { content: 'Line ${o.line}: ${e}';display: table;background-color:#cc0000;color:white;border-radius:5px;margin-bottom:5px;padding:5px;font-family:sans-serif}body:after { content: '${t}';display: table;background-color:#0e70b0;color:white;border-radius:5px;padding:5px;margin-bottom: 5px;font-family:sans-serif}body * { display: none; }`}
|
package/dist/parser.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const picomatch=require("picomatch"),fg=require("fast-glob"),fs=require("fs"),path=require("path");function generatePostcssConfig(t,r){let s={plugins:[]};if(r)r.split(",").forEach(function(e){s.plugins.push(require(e))});else{let e;t!==void 0?e=path.resolve(process.cwd(),t,"postcss.config.js"):e=path.resolve(process.cwd(),"postcss.config.js");try{fs.lstatSync(e),s=require(e)}catch{}}return s}function expandGlob(t,r,s=0,e=[]){if(s<t.length){let c=!1,f=!1,l=!1;if(c=picomatch.scan(t[s]).isGlob,c===!1)try{f=fs.lstatSync(path.normalize(t[s])).isDirectory(),l=fs.lstatSync(path.normalize(t[s])).isFile()}catch(o){throw o}if(c||l){let o=fg.sync(t[s],{dot:!0}).map(i=>path.normalize(i));e.push(...o),s=s+1,expandGlob(t,r,s,e)}else if(f){let o=t[s];fs.readdir(o,(i,n)=>{if(i)throw i;n.forEach(h=>{let a=path.join(o,h);fs.lstatSync(a).isDirectory()||e.push(a)}),s=s+1,expandGlob(t,r,s,e)})}}else r(e)}function createDestination(t,r,s,e,c,f){let l="",o="";return r||(r=""),c||(c=".css"),f===!0?r.length>0?l=r:l="":(s||(s=""),e||(e=""),s.length>0?(e.length>0&&(o=path.dirname(t.replace(path.join(e,"/"),""))),l=path.join(s,o,path.basename(t,path.extname(t))+c)):r.length>0?l=r:l=""),l}exports.expandGlob=expandGlob,exports.createDestination=createDestination,exports.generatePostcssConfig=generatePostcssConfig;
|
package/package.json
CHANGED
|
@@ -1,52 +1,55 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
2
|
+
"name": "sheetloaf",
|
|
3
|
+
"version": "1.0.2",
|
|
4
|
+
"description": "freshmade stylesheets for the whole family.",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"sheetloaf": "./dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "esbuild src/*.js --outdir=dist --platform=node --target=node10.4 --minify",
|
|
11
|
+
"test": "mocha",
|
|
12
|
+
"test2": "node . \"test/samples/styles/**/*.scss\" --dir \"test/samples/render/\" --load-path \"test/samples/lib\" --style expanded --base test/samples/styles/ --poll 500 --use autoprefixer,postcss-custom-properties",
|
|
13
|
+
"test3": "cat test/samples/styles/file.scss | node . --style compressed --use autoprefixer --load-path test/samples/styles > test/samples/render/file.css",
|
|
14
|
+
"test4": "cat test/samples/styles/file-with-error.scss | node . --style compressed --use autoprefixer > test/samples/render/file.css 2> test/samples/logs/error.log"
|
|
15
|
+
},
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/cheddarbread/sheetloaf.git"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"index.js",
|
|
22
|
+
"parser.js"
|
|
23
|
+
],
|
|
24
|
+
"keywords": [
|
|
25
|
+
"scss",
|
|
26
|
+
"css",
|
|
27
|
+
"sass",
|
|
28
|
+
"processor"
|
|
29
|
+
],
|
|
30
|
+
"author": "Benjamin Richardson",
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"bugs": {
|
|
33
|
+
"url": "https://github.com/cheddarbread/sheetloaf/issues"
|
|
34
|
+
},
|
|
35
|
+
"homepage": "https://github.com/cheddarbread/sheetloaf#readme",
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"autoprefixer": "^10.4.0",
|
|
38
|
+
"esbuild": "^0.13.15",
|
|
39
|
+
"lodash": "^4.17.21",
|
|
40
|
+
"mocha": "^9.1.3",
|
|
41
|
+
"postcss": "^8.3.11",
|
|
42
|
+
"postcss-custom-properties": "^12.0.0"
|
|
43
|
+
},
|
|
44
|
+
"peerDependencies": {
|
|
45
|
+
"postcss": "^8.2.0"
|
|
46
|
+
},
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"chokidar": "^3.5.2",
|
|
49
|
+
"commander": "^8.1.0",
|
|
50
|
+
"fast-glob": "^3.2.7",
|
|
51
|
+
"picocolors": "^1.0.0",
|
|
52
|
+
"picomatch": "^2.3.0",
|
|
53
|
+
"sass": "^1.43.4"
|
|
54
|
+
}
|
|
52
55
|
}
|
package/index.js
DELETED
|
@@ -1,243 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
const color = require('colorette');
|
|
3
|
-
const sass = require('sass');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
const fs = require('fs');
|
|
6
|
-
const version = require('./package.json').version;
|
|
7
|
-
const parser = require('./parser');
|
|
8
|
-
const {
|
|
9
|
-
Command
|
|
10
|
-
} = require('commander');
|
|
11
|
-
const postcss = require('postcss');
|
|
12
|
-
const chokidar = require('chokidar');
|
|
13
|
-
const program = new Command();
|
|
14
|
-
|
|
15
|
-
let stdin = '';
|
|
16
|
-
let postcssConfig = {
|
|
17
|
-
plugins: []
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
program.version(version, '-v, --version', 'Print the version of Sheetloaf.');
|
|
21
|
-
|
|
22
|
-
// Angled brackets denote required argument, square denote optional
|
|
23
|
-
program
|
|
24
|
-
.arguments('[sources...]')
|
|
25
|
-
.description('🍖 Compile Sass to CSS and transform the output using PostCSS all in one command.')
|
|
26
|
-
.action((source) => {
|
|
27
|
-
if (source.length > 0) {
|
|
28
|
-
start(source);
|
|
29
|
-
// If source is provided, ignore pipes.
|
|
30
|
-
} else if (!process.stdin.isTTY) {
|
|
31
|
-
//github.com/tj/commander.js/issues/137
|
|
32
|
-
process.stdin.on('readable', function () {
|
|
33
|
-
var chunk = this.read();
|
|
34
|
-
if (chunk !== null) {
|
|
35
|
-
stdin += chunk;
|
|
36
|
-
}
|
|
37
|
-
});
|
|
38
|
-
process.stdin.on('end', function () {
|
|
39
|
-
start(source);
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
});
|
|
43
|
-
program
|
|
44
|
-
.option('-o, --output <LOCATION>', 'Output file.')
|
|
45
|
-
.option('--dir <LOCATION>', 'Output directory.')
|
|
46
|
-
.option('--base <DIR>', 'Mirror the directory structure relative to this path in the output directory, for use with --dir.', '')
|
|
47
|
-
.option('--ext <EXTENSION>', 'Override the output file extension; for use with --dir', '.css')
|
|
48
|
-
.option('-s, --style <NAME>', 'Output style. ["expanded", "compressed"]', 'expanded')
|
|
49
|
-
.option('--source-map', 'Generate a source map (this is the default option).')
|
|
50
|
-
.option('--no-source-map', 'Do not generate a source map.')
|
|
51
|
-
.option('--embed-source-map', 'Embed the contents of the source map file in the generated CSS, rather than creating a separate file and linking to it from the CSS.')
|
|
52
|
-
.option('--embed-sources', 'Embed the entire contents of the Sass files that contributed to the generated CSS in the source map.')
|
|
53
|
-
.option('--source-map-urls <TYPE>', 'Controls how the source maps that Sass generates link back to the Sass files that contributed to the generated CSS. ["relative", "absolute"]', 'relative')
|
|
54
|
-
.option('--error-css', 'Emit a CSS file when an error occurs during compilation (this is the default option).')
|
|
55
|
-
.option('--no-error-css', 'Do not emit a CSS file when an error occurs during compilation.')
|
|
56
|
-
.option('-I, --load-path <PATHS>', 'Adds an additional load path for Sass to look for stylesheets.')
|
|
57
|
-
.option('-w, --watch', 'Watch stylesheets and recompile when they change.')
|
|
58
|
-
.option('--config <LOCATION>', 'Set a custom directory to look for a postcss config file.')
|
|
59
|
-
.option('--poll [DURATION]', 'Use polling for file watching. Can optionally pass polling interval; default 100 ms')
|
|
60
|
-
.option('-u, --use <PLUGINS>', 'List of postcss plugins to use. Will cause sheetloaf to ignore any config files.');
|
|
61
|
-
|
|
62
|
-
program.parse(process.argv);
|
|
63
|
-
|
|
64
|
-
function start(source) {
|
|
65
|
-
if (program.use !== undefined) {
|
|
66
|
-
// If user specifies --use, ignore postcss config files.
|
|
67
|
-
program.use.split(',').forEach(function (plugin) {
|
|
68
|
-
postcssConfig.plugins.push(require(plugin));
|
|
69
|
-
});
|
|
70
|
-
initialRender(source);
|
|
71
|
-
watchFiles(source);
|
|
72
|
-
} else {
|
|
73
|
-
parser.getPostCSSConfig(program.config, function (config) {
|
|
74
|
-
postcssConfig = config;
|
|
75
|
-
initialRender(source);
|
|
76
|
-
watchFiles(source);
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
function initialRender(source) {
|
|
82
|
-
if (stdin) {
|
|
83
|
-
renderSheet(null, stdin);
|
|
84
|
-
} else {
|
|
85
|
-
parser.expandGlob(source[0].split(','), function (entries) {
|
|
86
|
-
entries.forEach(function (filename) {
|
|
87
|
-
if (path.basename(filename).charAt(0) !== '_') {
|
|
88
|
-
renderSheet(filename);
|
|
89
|
-
}
|
|
90
|
-
});
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
function watchFiles(source) {
|
|
96
|
-
if (program.watch) {
|
|
97
|
-
|
|
98
|
-
chokidar.watch(source[0].split(','), {
|
|
99
|
-
usePolling: (program.poll !== undefined),
|
|
100
|
-
interval: (typeof program.poll === 'number' ? program.poll : 100),
|
|
101
|
-
ignoreInitial: true,
|
|
102
|
-
awaitWriteFinish: {
|
|
103
|
-
stabilityThreshold: 1500,
|
|
104
|
-
pollInterval: 100
|
|
105
|
-
}
|
|
106
|
-
}).on('change', (changed) => {
|
|
107
|
-
console.log(`File changed: ${changed}`);
|
|
108
|
-
|
|
109
|
-
parser.expandGlob(source[0].split(','), function (entries) {
|
|
110
|
-
entries.forEach(function (filename) {
|
|
111
|
-
if (path.basename(filename).charAt(0) !== '_') {
|
|
112
|
-
renderSheet(filename);
|
|
113
|
-
}
|
|
114
|
-
});
|
|
115
|
-
});
|
|
116
|
-
}).on('add', (added) => {
|
|
117
|
-
console.log(`File added: ${added}`);
|
|
118
|
-
|
|
119
|
-
parser.expandGlob(source[0].split(','), function (entries) {
|
|
120
|
-
entries.forEach(function (filename) {
|
|
121
|
-
if (path.basename(filename).charAt(0) !== '_') {
|
|
122
|
-
renderSheet(filename);
|
|
123
|
-
}
|
|
124
|
-
});
|
|
125
|
-
});
|
|
126
|
-
});
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
function renderSheet(filename = null, stdin = null) {
|
|
131
|
-
if (stdin === null) {
|
|
132
|
-
console.log(`Rendering ${filename}...`);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
let destination;
|
|
136
|
-
if (program.dir && stdin === null) {
|
|
137
|
-
destination = parser.parseDest(filename, program.dir, program.base, program.ext);
|
|
138
|
-
} else if (program.output) {
|
|
139
|
-
destination = parser.parseDest(filename, program.output);
|
|
140
|
-
} else {
|
|
141
|
-
destination = '';
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
let sassOptions = {
|
|
145
|
-
outFile: destination,
|
|
146
|
-
outputStyle: program.style
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
//https://sass-lang.com/documentation/cli/dart-sass#error-css
|
|
150
|
-
if (stdin !== null) {
|
|
151
|
-
sassOptions.data = stdin
|
|
152
|
-
sassOptions.sourceMap = false;
|
|
153
|
-
} else {
|
|
154
|
-
sassOptions.file = filename;
|
|
155
|
-
sassOptions.sourceMap = (program.sourceMap === false ? false : true);
|
|
156
|
-
sassOptions.sourceMapContents = (program.sourceMap === false ? false : true);
|
|
157
|
-
sassOptions.sourceMapEmbed = (program.sourceMap === false ? false : true);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
if (program.loadPath) {
|
|
161
|
-
sassOptions.includePaths = program.loadPath.split(',');
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
let postedMapOptions = false;
|
|
165
|
-
if (stdin !== null ? false : program.sourceMap !== false) {
|
|
166
|
-
postedMapOptions = {
|
|
167
|
-
inline: (program.embedSourceMap === true ? true : false),
|
|
168
|
-
absolute: (program.sourceMapUrls === 'absolute' ? true : false),
|
|
169
|
-
sourcesContent: (program.embedSources === true ? true : false)
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
try {
|
|
174
|
-
// When using Dart Sass, renderSync() is more than twice as fast as render(), due to the overhead of asynchronous callbacks.
|
|
175
|
-
let result = sass.renderSync(sassOptions);
|
|
176
|
-
postcss(postcssConfig.plugins).process(result.css.toString(), {
|
|
177
|
-
from: result.stats.entry,
|
|
178
|
-
to: destination,
|
|
179
|
-
map: postedMapOptions
|
|
180
|
-
}).then(postedResult => {
|
|
181
|
-
|
|
182
|
-
postedResult.warnings().forEach(warn => {
|
|
183
|
-
process.stderr.write(warn.toString())
|
|
184
|
-
})
|
|
185
|
-
|
|
186
|
-
if (destination !== '') {
|
|
187
|
-
try {
|
|
188
|
-
fs.mkdirSync(path.dirname(destination), {
|
|
189
|
-
recursive: true
|
|
190
|
-
});
|
|
191
|
-
} catch (err) {
|
|
192
|
-
if (err.code !== 'EEXIST' || err.code !== 'EISDIR') throw err
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
fs.writeFile(destination, postedResult.css, (err) => {
|
|
196
|
-
// throws an error, you could also catch it here
|
|
197
|
-
if (err) throw err;
|
|
198
|
-
|
|
199
|
-
// success case, the file was saved
|
|
200
|
-
console.log(color.green(`Successfully written to ${destination}`));
|
|
201
|
-
})
|
|
202
|
-
|
|
203
|
-
if (postedResult.map) {
|
|
204
|
-
fs.writeFile(destination + '.map', postedResult.map.toString(), (err) => {
|
|
205
|
-
if (err) throw err;
|
|
206
|
-
});
|
|
207
|
-
}
|
|
208
|
-
} else {
|
|
209
|
-
process.stdout.write(postedResult.css);
|
|
210
|
-
}
|
|
211
|
-
}).catch(err => {
|
|
212
|
-
if (destination !== '') {
|
|
213
|
-
console.log(color.red(err));
|
|
214
|
-
} else {
|
|
215
|
-
process.stderr.write(err);
|
|
216
|
-
}
|
|
217
|
-
})
|
|
218
|
-
} catch (e) {
|
|
219
|
-
if (destination !== '') {
|
|
220
|
-
console.log(color.red(e.formatted));
|
|
221
|
-
try {
|
|
222
|
-
fs.mkdirSync(path.dirname(destination), {
|
|
223
|
-
recursive: true
|
|
224
|
-
});
|
|
225
|
-
} catch (mkDirErr) {
|
|
226
|
-
if (mkDirErr.code !== 'EEXIST' || mkDirErr.code !== 'EISDIR') throw mkDirErr
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
if (program.errorCss !== false) {
|
|
230
|
-
fs.writeFile(destination, parser.emitSassError(e), (writeFileErr) => {
|
|
231
|
-
// throws an error, you could also catch it here
|
|
232
|
-
if (writeFileErr) throw writeFileErr;
|
|
233
|
-
|
|
234
|
-
// success case, the file was saved
|
|
235
|
-
console.log(color.yellow(`Emitted error to ${destination}`));
|
|
236
|
-
})
|
|
237
|
-
}
|
|
238
|
-
} else {
|
|
239
|
-
process.stderr.write(e.formatted);
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
}
|
package/parser.js
DELETED
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
const path = require('path');
|
|
2
|
-
const fs = require('fs');
|
|
3
|
-
const fg = require('fast-glob');
|
|
4
|
-
const picomatch = require('picomatch');
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Given an array of input sources, expand any globs and validate that inputs exist.
|
|
8
|
-
*
|
|
9
|
-
* @param {*} input
|
|
10
|
-
* @param {*} callback
|
|
11
|
-
* @param {*} index
|
|
12
|
-
* @param {*} expanded
|
|
13
|
-
*/
|
|
14
|
-
function expandGlob(input, callback, index = 0, expanded = []) {
|
|
15
|
-
|
|
16
|
-
if (index < input.length) {
|
|
17
|
-
let isGlob = false;
|
|
18
|
-
let isDir = false;
|
|
19
|
-
let isFile = false;
|
|
20
|
-
|
|
21
|
-
isGlob = picomatch.scan(input[index]).isGlob;
|
|
22
|
-
|
|
23
|
-
if (isGlob === false) {
|
|
24
|
-
try {
|
|
25
|
-
isDir = fs.lstatSync(path.normalize(input[index])).isDirectory();
|
|
26
|
-
isFile = fs.lstatSync(path.normalize(input[index])).isFile();
|
|
27
|
-
} catch (err) {
|
|
28
|
-
throw (err);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
if (isGlob || isFile) {
|
|
33
|
-
let files = fg.sync(input[index], {
|
|
34
|
-
dot: true
|
|
35
|
-
}).map(entry => path.normalize(entry));
|
|
36
|
-
expanded.push(...files);
|
|
37
|
-
|
|
38
|
-
index = index + 1;
|
|
39
|
-
expandGlob(input, callback, index, expanded);
|
|
40
|
-
} else if (isDir) {
|
|
41
|
-
let dir = input[index];
|
|
42
|
-
|
|
43
|
-
fs.readdir(dir, (err, files) => {
|
|
44
|
-
if (err) {
|
|
45
|
-
throw err;
|
|
46
|
-
} else {
|
|
47
|
-
files.forEach(file => {
|
|
48
|
-
|
|
49
|
-
let fullname = path.join(dir, file);
|
|
50
|
-
if (!fs.lstatSync(fullname).isDirectory()) {
|
|
51
|
-
expanded.push(fullname);
|
|
52
|
-
}
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
index = index + 1;
|
|
56
|
-
expandGlob(input, callback, index, expanded);
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
} else {
|
|
63
|
-
callback(expanded);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
*
|
|
69
|
-
* @param {*} filename
|
|
70
|
-
* @param {*} output
|
|
71
|
-
* @param {*} base
|
|
72
|
-
*/
|
|
73
|
-
function parseDest(filename, output, base = '', extension = '.css') {
|
|
74
|
-
if (path.extname(output) === '') {
|
|
75
|
-
let mirror = (base !== '' ? path.dirname(filename.replace(path.join(base, '/'), '')) : '');
|
|
76
|
-
return path.join(output, mirror, path.basename(filename, path.extname(filename)) + extension);
|
|
77
|
-
} else {
|
|
78
|
-
return output;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
function getPostCSSConfig(loc, callback) {
|
|
83
|
-
let configLoc;
|
|
84
|
-
if (loc != undefined) {
|
|
85
|
-
configLoc = path.resolve(process.cwd(), loc, 'postcss.config.js');
|
|
86
|
-
} else {
|
|
87
|
-
configLoc = path.resolve(process.cwd(), 'postcss.config.js');
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
fs.lstatSync(configLoc);
|
|
91
|
-
let config = require(configLoc);
|
|
92
|
-
callback(config);
|
|
93
|
-
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Build a new CSS file that contains the error and puts its content in the body.
|
|
98
|
-
* @param {*} err
|
|
99
|
-
*/
|
|
100
|
-
function emitSassError(err) {
|
|
101
|
-
let singleLineErr = err.formatted.substr(0, err.formatted.indexOf('^'))
|
|
102
|
-
.replace(/(\r\n|\n|\r)/gm, " ")
|
|
103
|
-
.replace(/'/, "")
|
|
104
|
-
.replace(/╷.*?│/, "")
|
|
105
|
-
.replace(/│/, "")
|
|
106
|
-
.replace(`'`, "");
|
|
107
|
-
|
|
108
|
-
let fileName = err.file.replace(/\\/g, "/");
|
|
109
|
-
|
|
110
|
-
let css = `body:before { content: 'Line ${err.line}: ${singleLineErr}';display: table;background-color:#cc0000;color:white;border-radius:5px;margin-bottom:5px;padding:5px;font-family:sans-serif}body:after { content: '${fileName}';display: table;background-color:#0e70b0;color:white;border-radius:5px;padding:5px;margin-bottom: 5px;font-family:sans-serif}body * { display: none; }`;
|
|
111
|
-
|
|
112
|
-
return css;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
exports.emitSassError = emitSassError;
|
|
116
|
-
exports.expandGlob = expandGlob;
|
|
117
|
-
exports.parseDest = parseDest;
|
|
118
|
-
exports.getPostCSSConfig = getPostCSSConfig;
|