sheetloaf 1.26.0 → 1.26.1-beta.1

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/dist/configs.js CHANGED
@@ -1,28 +1,26 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.generateSassOptionsAsync = exports.generateSassOptions = exports.generatePostcssConfigFromUse = exports.generatePostcssConfigFromFile = void 0;
7
- const path_1 = __importDefault(require("path"));
8
- const fs_1 = __importDefault(require("fs"));
9
- const sass_embedded_1 = require("sass-embedded");
10
- function generatePostcssConfigFromFile(configPath = '') {
1
+ import path from "path";
2
+ import fs from "fs";
3
+ import {} from "postcss";
4
+ import { NodePackageImporter } from "sass-embedded";
5
+ import {} from "commander";
6
+ import { createRequire } from "module";
7
+ const require = createRequire(import.meta.url);
8
+ export function generatePostcssConfigFromFile(configPath = '') {
11
9
  let obj = {
12
10
  plugins: []
13
11
  };
14
- let configFileLoc = path_1.default.resolve(process.cwd(), configPath, 'postcss.config.js');
12
+ let configFileLoc = path.resolve(process.cwd(), configPath, 'postcss.config.js');
15
13
  try {
16
- fs_1.default.lstatSync(configFileLoc);
14
+ fs.lstatSync(configFileLoc);
17
15
  obj = require(configFileLoc);
18
16
  }
19
17
  catch (e) {
20
18
  console.log(`No postcss.config.js file found at location ${configPath}`);
19
+ // TODO
21
20
  }
22
21
  return obj;
23
22
  }
24
- exports.generatePostcssConfigFromFile = generatePostcssConfigFromFile;
25
- function generatePostcssConfigFromUse(useArg) {
23
+ export function generatePostcssConfigFromUse(useArg) {
26
24
  let obj = {
27
25
  plugins: []
28
26
  };
@@ -31,26 +29,24 @@ function generatePostcssConfigFromUse(useArg) {
31
29
  });
32
30
  return obj;
33
31
  }
34
- exports.generatePostcssConfigFromUse = generatePostcssConfigFromUse;
35
- function generateSassOptions(opts) {
32
+ export function generateSassOptions(opts) {
36
33
  return {
37
34
  style: opts.style,
38
35
  loadPaths: opts.loadPath ? opts.loadPath.split(',') : [],
39
36
  sourceMap: opts.sourceMap === false ? false : true,
40
37
  sourceMapIncludeSources: opts.sourceMap === false ? false : true,
41
- importers: opts.pkgImporter === 'node' ? [new sass_embedded_1.NodePackageImporter()] : [],
38
+ importers: opts.pkgImporter === 'node' ? [new NodePackageImporter()] : [],
42
39
  silenceDeprecations: opts.silenceDeprecation ? opts.silenceDeprecation.split(',') : []
43
40
  };
44
41
  }
45
- exports.generateSassOptions = generateSassOptions;
46
- function generateSassOptionsAsync(opts) {
42
+ export function generateSassOptionsAsync(opts) {
47
43
  return {
48
44
  style: opts.style,
49
45
  loadPaths: opts.loadPath ? opts.loadPath.split(',') : [],
50
46
  sourceMap: opts.sourceMap === false ? false : true,
51
47
  sourceMapIncludeSources: opts.sourceMap === false ? false : true,
52
- importers: opts.pkgImporter === 'node' ? [new sass_embedded_1.NodePackageImporter()] : [],
48
+ importers: opts.pkgImporter === 'node' ? [new NodePackageImporter()] : [],
53
49
  silenceDeprecations: opts.silenceDeprecation ? opts.silenceDeprecation.split(',') : []
54
50
  };
55
51
  }
56
- exports.generateSassOptionsAsync = generateSassOptionsAsync;
52
+ //# sourceMappingURL=configs.js.map
@@ -1,18 +1,13 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.buildDestinationPath = exports.getAllFilesPathsFromSources = void 0;
7
- const fs_1 = __importDefault(require("fs"));
8
- const path_1 = __importDefault(require("path"));
9
- const glob_1 = require("glob");
10
- function getAllFilesPathsFromSources(input, callback) {
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import { globSync } from 'glob';
4
+ export function getAllFilesPathsFromSources(input, callback) {
11
5
  let sourcesCompleted = 0;
12
6
  let filePaths = [];
13
7
  for (let i = 0; i < input.length; i++) {
14
- const result = (0, glob_1.globSync)(input[i], { withFileTypes: true });
15
- if (result.length === 1 && result[0].isDirectory()) {
8
+ const result = globSync(input[i], { withFileTypes: true });
9
+ // If user has supplied a directory, we do an extra step and read all files from directory.
10
+ if (result.length === 1 && result[0] && result[0].isDirectory()) {
16
11
  try {
17
12
  getAllFilePathsInDir(input[i], (files) => {
18
13
  filePaths.push(...files);
@@ -29,7 +24,7 @@ function getAllFilesPathsFromSources(input, callback) {
29
24
  else {
30
25
  for (const entry of result) {
31
26
  if (entry.isFile()) {
32
- filePaths.push(path_1.default.normalize(entry.relative()));
27
+ filePaths.push(path.normalize(entry.relative()));
33
28
  }
34
29
  }
35
30
  sourcesCompleted++;
@@ -39,17 +34,16 @@ function getAllFilesPathsFromSources(input, callback) {
39
34
  }
40
35
  }
41
36
  }
42
- exports.getAllFilesPathsFromSources = getAllFilesPathsFromSources;
43
37
  function getAllFilePathsInDir(dir, callback) {
44
38
  let files = [];
45
- fs_1.default.readdir(dir, (err, nodes) => {
39
+ fs.readdir(dir, (err, nodes) => {
46
40
  if (err) {
47
41
  throw err;
48
42
  }
49
43
  else {
50
44
  nodes.forEach((file) => {
51
- let fullname = path_1.default.join(dir, file);
52
- if (!fs_1.default.lstatSync(fullname).isDirectory()) {
45
+ let fullname = path.join(dir, file);
46
+ if (!fs.lstatSync(fullname).isDirectory()) {
53
47
  files.push(fullname);
54
48
  }
55
49
  });
@@ -57,7 +51,13 @@ function getAllFilePathsInDir(dir, callback) {
57
51
  }
58
52
  });
59
53
  }
60
- function buildDestinationPath(fileName, outFile = '', dir = '', base = '', extension = '.css', usingStdin) {
54
+ // TODO: returning a blank string seems super messy, this could use a refactor.
55
+ /**
56
+ *
57
+ * @param filename
58
+ * @returns path, or a blank string if the combination of options provided does not give a valid path.
59
+ */
60
+ export function buildDestinationPath(fileName, outFile = '', dir = '', base = '', extension = '.css', usingStdin) {
61
61
  let destination = '';
62
62
  let mirror = '';
63
63
  if (usingStdin === true) {
@@ -71,9 +71,9 @@ function buildDestinationPath(fileName, outFile = '', dir = '', base = '', exten
71
71
  else {
72
72
  if (dir.length > 0) {
73
73
  if (base.length > 0) {
74
- mirror = path_1.default.dirname(fileName.replace(path_1.default.join(base, '/'), ''));
74
+ mirror = path.dirname(fileName.replace(path.join(base, '/'), ''));
75
75
  }
76
- destination = path_1.default.join(dir, mirror, path_1.default.basename(fileName, path_1.default.extname(fileName)) + extension);
76
+ destination = path.join(dir, mirror, path.basename(fileName, path.extname(fileName)) + extension);
77
77
  }
78
78
  else if (outFile.length > 0) {
79
79
  destination = outFile;
@@ -84,4 +84,4 @@ function buildDestinationPath(fileName, outFile = '', dir = '', base = '', exten
84
84
  }
85
85
  return destination;
86
86
  }
87
- exports.buildDestinationPath = buildDestinationPath;
87
+ //# sourceMappingURL=fileFinder.js.map
package/dist/index.js CHANGED
@@ -1,310 +1,296 @@
1
1
  #!/usr/bin/env node
2
- "use strict";
3
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
- if (k2 === undefined) k2 = k;
5
- var desc = Object.getOwnPropertyDescriptor(m, k);
6
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
- desc = { enumerable: true, get: function() { return m[k]; } };
8
- }
9
- Object.defineProperty(o, k2, desc);
10
- }) : (function(o, m, k, k2) {
11
- if (k2 === undefined) k2 = k;
12
- o[k2] = m[k];
13
- }));
14
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
- Object.defineProperty(o, "default", { enumerable: true, value: v });
16
- }) : function(o, v) {
17
- o["default"] = v;
18
- });
19
- var __importStar = (this && this.__importStar) || function (mod) {
20
- if (mod && mod.__esModule) return mod;
21
- var result = {};
22
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
23
- __setModuleDefault(result, mod);
24
- return result;
25
- };
26
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
27
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
28
- return new (P || (P = Promise))(function (resolve, reject) {
29
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
30
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
31
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
32
- step((generator = generator.apply(thisArg, _arguments || [])).next());
33
- });
34
- };
35
- var __importDefault = (this && this.__importDefault) || function (mod) {
36
- return (mod && mod.__esModule) ? mod : { "default": mod };
37
- };
38
- Object.defineProperty(exports, "__esModule", { value: true });
39
- const commander_1 = require("commander");
40
- const chokidar_1 = __importDefault(require("chokidar"));
41
- const picocolors_1 = __importDefault(require("picocolors"));
42
- const fs_1 = __importDefault(require("fs"));
43
- const path_1 = __importDefault(require("path"));
44
- const sass_embedded_1 = require("sass-embedded");
45
- const postcss_1 = __importDefault(require("postcss"));
46
- const configs = __importStar(require("./configs"));
47
- const fileFinder = __importStar(require("./fileFinder"));
48
- const sources = __importStar(require("./sources"));
49
- const glob_1 = require("glob");
50
- const sheetloaf = new commander_1.Command();
51
- sheetloaf.version("1.26.0", '-v, --version', 'Print the version of Sheetloaf.');
52
- let usingStdin = false;
2
+ import chokidar from 'chokidar';
3
+ import color from 'picocolors';
4
+ import { Command } from 'commander';
5
+ import fs from 'fs';
6
+ import { globSync } from 'glob';
7
+ import postcss from 'postcss';
8
+ import path from 'path';
9
+ import { initCompiler, initAsyncCompiler } from 'sass-embedded';
10
+ import * as configs from "./configs.js";
11
+ import * as fileFinder from "./fileFinder.js";
12
+ import * as sources from "./sources.js";
13
+ const sheetloaf = new Command();
14
+ sheetloaf.version("1.26.1", '-v, --version', 'Print the version of Sheetloaf.');
53
15
  let postcssConfig = {
54
16
  plugins: []
55
17
  };
56
- let sassCompiler;
57
- let sassAsyncCompiler;
58
- sheetloaf
59
- .arguments('[sources...]')
60
- .description('📃🍞 Compile Sass to CSS and transform the output using PostCSS, all in one command.')
61
- .action((source) => __awaiter(void 0, void 0, void 0, function* () {
62
- if (sheetloaf.opts().use) {
63
- postcssConfig = configs.generatePostcssConfigFromUse(sheetloaf.opts().use);
64
- }
65
- else {
66
- postcssConfig = configs.generatePostcssConfigFromFile(sheetloaf.opts().config);
67
- }
68
- if (sheetloaf.opts().async === true) {
69
- sassAsyncCompiler = yield (0, sass_embedded_1.initAsyncCompiler)();
18
+ class CompWrapper {
19
+ initialized = false;
20
+ usingStdin = false;
21
+ source;
22
+ entries;
23
+ options;
24
+ compiler = {};
25
+ init(options, source = "") {
26
+ this.options = options;
27
+ this.source = source;
28
+ return new Promise((resolve, reject) => {
29
+ if (this.source.length > 0) {
30
+ fileFinder.getAllFilesPathsFromSources(this.source.split(','), (entries) => {
31
+ this.entries = entries;
32
+ if (this.entries.length > 0 && this.entries[0]) {
33
+ this.usingStdin = false;
34
+ }
35
+ else {
36
+ this.usingStdin = true;
37
+ }
38
+ if (this.options.async === true) {
39
+ initAsyncCompiler().then((compiler) => {
40
+ this.compiler.async = compiler;
41
+ this.initialized = true;
42
+ resolve("Compiler initialized.");
43
+ }).catch((e) => {
44
+ reject(e);
45
+ });
46
+ }
47
+ else {
48
+ this.compiler.sync = initCompiler();
49
+ this.initialized = true;
50
+ resolve("Compiler initialized.");
51
+ }
52
+ });
53
+ }
54
+ else {
55
+ this.usingStdin = true;
56
+ if (this.options.async === true) {
57
+ initAsyncCompiler().then((compiler) => {
58
+ this.compiler.async = compiler;
59
+ this.initialized = true;
60
+ resolve("Compiler initialized.");
61
+ }).catch((e) => {
62
+ reject(e);
63
+ });
64
+ }
65
+ else {
66
+ this.compiler.sync = initCompiler();
67
+ this.initialized = true;
68
+ resolve("Compiler initialized.");
69
+ }
70
+ }
71
+ });
70
72
  }
71
- else {
72
- sassCompiler = (0, sass_embedded_1.initCompiler)();
73
+ dispose() {
74
+ if (this.initialized) {
75
+ this.compiler.async?.dispose();
76
+ this.compiler.sync?.dispose();
77
+ }
78
+ else {
79
+ throw 'Compiler not initialized, therefore could not dispose.';
80
+ }
73
81
  }
74
- if (source.length > 0) {
75
- renderAllFiles(source);
76
- watch(source);
82
+ watch() {
83
+ if (this.source.length > 0) {
84
+ const toWatch = globSync(this.source.split(','));
85
+ chokidar
86
+ .watch(toWatch, {
87
+ usePolling: this.options.poll !== undefined,
88
+ interval: typeof this.options.poll === 'number' ? this.options.poll : 100,
89
+ ignoreInitial: true,
90
+ awaitWriteFinish: {
91
+ stabilityThreshold: 1500,
92
+ pollInterval: 100
93
+ }
94
+ })
95
+ .on('change', (changed) => {
96
+ console.log(`File changed: ${changed}`);
97
+ this.getFilesToRender(changed).then((filesToRender) => {
98
+ filesToRender.forEach((fileName) => {
99
+ this.render(fileName);
100
+ });
101
+ });
102
+ })
103
+ .on('add', (added) => {
104
+ console.log(`File added: ${added}`);
105
+ // Clear out old info.
106
+ sources.clearSourcesChecker();
107
+ this.renderAll();
108
+ });
109
+ }
77
110
  }
78
- else if (!process.stdin.isTTY) {
79
- let stdin = '';
80
- process.stdin.on('readable', () => {
81
- var chunk = process.stdin.read();
82
- if (chunk !== null) {
83
- stdin += chunk;
111
+ render(fileNameOrString = '') {
112
+ return new Promise((resolve, reject) => {
113
+ if (this.usingStdin === false) {
114
+ console.log(`Rendering ${fileNameOrString}...`);
84
115
  }
85
- });
86
- process.stdin.on('end', () => {
87
- usingStdin = true;
88
- renderSassFromStdin(stdin);
116
+ const destination = fileFinder.buildDestinationPath(fileNameOrString, this.options.output, this.options.dir, this.options.base, this.options.ext, this.usingStdin);
117
+ this.renderSass(fileNameOrString).then((sassResult) => {
118
+ this.renderPost(fileNameOrString, destination, sassResult).then((postedResult) => {
119
+ this.writeOut(postedResult, destination).then(() => {
120
+ resolve("File rendered and written successfully.");
121
+ });
122
+ }).catch((err) => {
123
+ if (destination !== '') {
124
+ console.log(color.red(err));
125
+ }
126
+ else {
127
+ process.stderr.write(err);
128
+ }
129
+ resolve("Error in file.");
130
+ });
131
+ }).catch((e) => {
132
+ this.sassErrorOut(e, destination);
133
+ resolve("Error in file.");
134
+ });
89
135
  });
90
136
  }
91
- }));
92
- sheetloaf
93
- .option('-o, --output <LOCATION>', 'Output file.')
94
- .option('--dir <LOCATION>', 'Output directory.')
95
- .option('--base <DIR>', 'Mirror the directory structure relative to this path in the output directory, for use with --dir.', '')
96
- .option('--ext <EXTENSION>', 'Override the output file extension; for use with --dir', '.css')
97
- .option('-s, --style <NAME>', 'Output style. ["expanded", "compressed"]', 'expanded')
98
- .option('--source-map', 'Generate a source map (this is the default option).')
99
- .option('--no-source-map', 'Do not generate a source map.')
100
- .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.')
101
- .option('--embed-sources', 'Embed the entire contents of the Sass files that contributed to the generated CSS in the source map.')
102
- .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')
103
- .option('--error-css', 'Emit a CSS file when an error occurs during compilation (this is the default option).')
104
- .option('--no-error-css', 'Do not emit a CSS file when an error occurs during compilation.')
105
- .option('--silence-deprecation <TYPE>', 'This option tells Sass to silence a particular type of deprecation.')
106
- .option('-I, --load-path <PATHS>', 'Adds an additional load path for Sass to look for stylesheets.')
107
- .option('-p, --pkg-importer <TYPE>', `Built-in importer(s) to use for pkg: URLs.\n[node] - Load files like Node.js package resolution.`)
108
- .option('-w, --watch', 'Watch stylesheets and recompile when they change.')
109
- .option('--config <LOCATION>', 'Set a custom directory to look for a postcss config file.')
110
- .option('--poll [DURATION]', 'Use polling for file watching. Can optionally pass polling interval; default 100 ms')
111
- .option('-u, --use <PLUGINS>', 'List of postcss plugins to use. Will cause sheetloaf to ignore any config files.')
112
- .option('--async', `Use sass' asynchronous API. This may be slower.`);
113
- sheetloaf.parse(process.argv);
114
- function renderAllFiles(source) {
115
- fileFinder.getAllFilesPathsFromSources(source[0].split(','), function (entries) {
116
- entries.forEach(function (fileName) {
117
- if (path_1.default.basename(fileName).charAt(0) !== '_') {
118
- renderSass(fileName);
119
- }
137
+ renderAll() {
138
+ return new Promise((resolve, reject) => {
139
+ const filesToRender = this.entries.filter((fileName) => path.basename(fileName).charAt(0) !== '_');
140
+ let rendered = 0;
141
+ filesToRender.forEach((fileName) => {
142
+ this.render(fileName).then(() => {
143
+ rendered++;
144
+ if (rendered == filesToRender.length) {
145
+ resolve("All files rendered");
146
+ }
147
+ });
148
+ });
120
149
  });
121
- });
122
- }
123
- function renderPartially(source, fileName) {
124
- if (path_1.default.basename(fileName).charAt(0) !== '_') {
125
- renderSass(fileName);
126
150
  }
127
- else {
128
- let partialExistsInSassSources = false;
129
- let ind = 0;
130
- while (ind < sources.getChecker().length) {
131
- const toCheck = sources.getChecker()[ind];
132
- if (toCheck.containsPartial(fileName)) {
133
- partialExistsInSassSources = true;
134
- renderSass(toCheck.getMain());
151
+ renderSass(fileNameOrString) {
152
+ return new Promise((resolve, reject) => {
153
+ if (this.compiler.async) {
154
+ const options = configs.generateSassOptionsAsync(this.options);
155
+ if (this.usingStdin === false) {
156
+ this.compiler.async.compileAsync(fileNameOrString, options).then((result) => {
157
+ sources.addResultToSourcesChecker(fileNameOrString, result);
158
+ resolve(result);
159
+ }).catch((err) => {
160
+ reject(err);
161
+ });
162
+ }
163
+ else {
164
+ this.compiler.async.compileStringAsync(fileNameOrString, options).then((result) => {
165
+ resolve(result);
166
+ }).catch((err) => {
167
+ reject(err);
168
+ });
169
+ }
135
170
  }
136
- ind = ind + 1;
137
- }
138
- if (partialExistsInSassSources === false) {
139
- sources.clearSourcesChecker();
140
- renderAllFiles(source);
141
- }
142
- }
143
- }
144
- function watch(source) {
145
- if (sheetloaf.opts().watch === true) {
146
- const toWatch = (0, glob_1.globSync)(source[0].split(','));
147
- chokidar_1.default
148
- .watch(toWatch, {
149
- usePolling: sheetloaf.opts().poll !== undefined,
150
- interval: typeof sheetloaf.opts().poll === 'number' ? sheetloaf.opts().poll : 100,
151
- ignoreInitial: true,
152
- awaitWriteFinish: {
153
- stabilityThreshold: 1500,
154
- pollInterval: 100
171
+ else if (this.compiler.sync) {
172
+ try {
173
+ const options = configs.generateSassOptions(this.options);
174
+ if (this.usingStdin === false) {
175
+ const result = this.compiler.sync.compile(fileNameOrString, options);
176
+ sources.addResultToSourcesChecker(fileNameOrString, result);
177
+ resolve(result);
178
+ }
179
+ else {
180
+ const result = this.compiler.sync.compileString(fileNameOrString, options);
181
+ resolve(result);
182
+ }
183
+ }
184
+ catch (err) {
185
+ reject(err);
186
+ }
155
187
  }
156
- })
157
- .on('change', (changed) => {
158
- console.log(`File changed: ${changed}`);
159
- renderPartially(source, changed);
160
- })
161
- .on('add', (added) => {
162
- console.log(`File added: ${added}`);
163
- sources.clearSourcesChecker();
164
- renderAllFiles(source);
165
188
  });
166
189
  }
167
- }
168
- function renderSass(fileName) {
169
- return __awaiter(this, void 0, void 0, function* () {
170
- console.log(`Rendering ${fileName}...`);
171
- const destination = fileFinder.buildDestinationPath(fileName, sheetloaf.opts().output, sheetloaf.opts().dir, sheetloaf.opts().base, sheetloaf.opts().ext, usingStdin);
172
- try {
173
- if (sheetloaf.opts().async === true) {
174
- const options = configs.generateSassOptionsAsync(sheetloaf.opts());
175
- const result = yield sassAsyncCompiler.compileAsync(fileName, options);
176
- renderPost(fileName, destination, result);
177
- sources.addResultToSourcesChecker(fileName, result);
178
- }
179
- else {
180
- const options = configs.generateSassOptions(sheetloaf.opts());
181
- const result = sassCompiler.compile(fileName, options);
182
- renderPost(fileName, destination, result);
183
- sources.addResultToSourcesChecker(fileName, result);
190
+ renderPost(fileNameOrString, destination, sassResult) {
191
+ return new Promise((resolve, reject) => {
192
+ let postcssMapOptions = {
193
+ annotation: true,
194
+ prev: sassResult.sourceMap,
195
+ inline: this.options.embedSourceMap === true ? true : false,
196
+ absolute: this.options.sourceMapUrls === 'absolute' ? true : false,
197
+ sourcesContent: this.options.embedSources === true ? true : false,
198
+ };
199
+ if (this.usingStdin === true || this.options.sourceMap === false) {
200
+ postcssMapOptions = false;
184
201
  }
185
- }
186
- catch (e) {
187
- sassErrorCatcher(e, destination);
188
- }
189
- });
190
- }
191
- function renderSassFromStdin(text) {
192
- return __awaiter(this, void 0, void 0, function* () {
193
- const destination = fileFinder.buildDestinationPath('', sheetloaf.opts().output, sheetloaf.opts().dir, sheetloaf.opts().base, sheetloaf.opts().ext, usingStdin);
194
- try {
195
- if (sheetloaf.opts().async === true) {
196
- const options = configs.generateSassOptionsAsync(sheetloaf.opts());
197
- const result = yield sassAsyncCompiler.compileStringAsync(text, options);
198
- renderPost('', destination, result);
202
+ postcss(postcssConfig.plugins)
203
+ .process(sassResult.css.toString(), {
204
+ from: fileNameOrString,
205
+ to: destination,
206
+ map: postcssMapOptions
207
+ })
208
+ .then((postedResult) => {
209
+ resolve(postedResult);
210
+ })
211
+ .catch((err) => {
212
+ reject(err);
213
+ });
214
+ });
215
+ }
216
+ getFilesToRender(fileChanged) {
217
+ return new Promise((resolve, reject) => {
218
+ let filesToRender = [];
219
+ if (path.basename(fileChanged).charAt(0) !== '_') {
220
+ filesToRender.push(fileChanged);
221
+ resolve(filesToRender);
199
222
  }
200
223
  else {
201
- const options = configs.generateSassOptions(sheetloaf.opts());
202
- const result = sassCompiler.compileString(text, options);
203
- renderPost('', destination, result);
224
+ let partialExistsInSassSources = false;
225
+ let ind = 0;
226
+ while (ind < sources.getChecker().length) {
227
+ const toCheck = sources.getChecker()[ind];
228
+ if (toCheck?.containsPartial(fileChanged)) {
229
+ partialExistsInSassSources = true;
230
+ filesToRender.push(toCheck.getMain());
231
+ }
232
+ ind = ind + 1;
233
+ }
234
+ if (partialExistsInSassSources === false) {
235
+ // SassSources are built with sass's CompileResult object when
236
+ // sheetloaf initially runs. However, if compilation fails, the
237
+ // SassSource will not be generated for that particular file.
238
+ // That means if a partial is later fixed to not error out and
239
+ // it will not render at all.
240
+ // We therefore check for this condition and rebuild everything
241
+ // if it doesn't exist.
242
+ sources.clearSourcesChecker();
243
+ fileFinder.getAllFilesPathsFromSources(this.source.split(','), (entries) => {
244
+ entries.forEach((entry) => {
245
+ filesToRender.push(entry);
246
+ resolve(filesToRender);
247
+ });
248
+ });
249
+ }
250
+ else {
251
+ resolve(filesToRender);
252
+ }
204
253
  }
205
- }
206
- catch (e) {
207
- sassErrorCatcher(e, destination);
208
- }
209
- });
210
- }
211
- function renderPost(fileName, destination, sassResult) {
212
- let postcssMapOptions = {
213
- annotation: true,
214
- prev: sassResult.sourceMap,
215
- inline: sheetloaf.opts().embedSourceMap === true ? true : false,
216
- absolute: sheetloaf.opts().sourceMapUrls === 'absolute' ? true : false,
217
- sourcesContent: sheetloaf.opts().embedSources === true ? true : false,
218
- };
219
- if (usingStdin === true || sheetloaf.opts().sourceMap === false) {
220
- postcssMapOptions = false;
221
- }
222
- (0, postcss_1.default)(postcssConfig.plugins)
223
- .process(sassResult.css.toString(), {
224
- from: fileName,
225
- to: destination,
226
- map: postcssMapOptions
227
- })
228
- .then((postedResult) => {
229
- postedResult.warnings().forEach((warn) => {
230
- process.stderr.write(warn.toString());
231
254
  });
255
+ }
256
+ sassErrorOut(e, destination) {
232
257
  if (destination !== '') {
258
+ console.log(e.message);
233
259
  try {
234
- fs_1.default.mkdirSync(path_1.default.dirname(destination), {
260
+ fs.mkdirSync(path.dirname(destination), {
235
261
  recursive: true
236
262
  });
237
263
  }
238
- catch (err) {
239
- if (err.code !== 'EEXIST' || err.code !== 'EISDIR')
240
- throw err;
264
+ catch (mkDirErr) {
265
+ if (mkDirErr.code !== 'EEXIST' || mkDirErr.code !== 'EISDIR')
266
+ throw mkDirErr;
241
267
  }
242
- fs_1.default.writeFile(destination, postedResult.css, (err) => {
243
- if (err) {
244
- console.log(err);
245
- }
246
- else {
247
- console.log(picocolors_1.default.green(`Successfully written to ${destination}`));
248
- }
249
- });
250
- if (postedResult.map) {
251
- fs_1.default.writeFile(destination + '.map', postedResult.map.toString(), (err) => {
252
- if (err)
253
- throw err;
268
+ if (this.options.errorCss !== false) {
269
+ fs.writeFile(destination, this.emitSassError(e), (writeFileErr) => {
270
+ // throws an error, you could also catch it here
271
+ if (writeFileErr)
272
+ throw writeFileErr;
273
+ // success case, the file was saved
274
+ console.log(color.yellow(`Emitted error to ${destination}`));
254
275
  });
255
276
  }
256
277
  }
257
278
  else {
258
- process.stdout.write(postedResult.css);
259
- if (!sheetloaf.opts().watch) {
260
- process.exit();
261
- }
279
+ process.stderr.write(e.message);
262
280
  }
263
- })
264
- .catch((err) => {
265
- if (destination !== '') {
266
- console.log(picocolors_1.default.red(err));
267
- }
268
- else {
269
- process.stderr.write(err);
270
- }
271
- if (!sheetloaf.opts().watch) {
272
- process.exit();
273
- }
274
- });
275
- }
276
- function sassErrorCatcher(e, destination) {
277
- if (destination !== '') {
278
- console.log(e.message);
279
- try {
280
- fs_1.default.mkdirSync(path_1.default.dirname(destination), {
281
- recursive: true
282
- });
283
- }
284
- catch (mkDirErr) {
285
- if (mkDirErr.code !== 'EEXIST' || mkDirErr.code !== 'EISDIR')
286
- throw mkDirErr;
287
- }
288
- if (sheetloaf.opts().errorCss !== false) {
289
- fs_1.default.writeFile(destination, emitSassError(e), (writeFileErr) => {
290
- if (writeFileErr)
291
- throw writeFileErr;
292
- console.log(picocolors_1.default.yellow(`Emitted error to ${destination}`));
293
- });
281
+ if (this.options.watch && (process.exitCode == null || process.exitCode === 0)) {
282
+ process.exitCode = 1;
294
283
  }
295
284
  }
296
- else {
297
- process.stderr.write(e.message);
298
- }
299
- if (!sheetloaf.opts().watch && (process.exitCode == null || process.exitCode === 0)) {
300
- process.exitCode = 1;
301
- process.exit();
302
- }
303
- }
304
- function emitSassError(err) {
305
- const message = err.sassMessage.toString().replace(/"/g, "'").replace(/\n/g, " ");
306
- const context = err.span.context.toString().replace(/"/g, "'").replace(/\n/g, " ");
307
- let css = `
285
+ /**
286
+ * Build a new CSS file that contains the error and puts its content in the body.
287
+ * @param {*} err
288
+ */
289
+ emitSassError(err) {
290
+ // Sanitize message so that it fits in a content attribute.
291
+ const message = err.sassMessage.toString().replace(/"/g, "'").replace(/\n/g, " ");
292
+ const context = err.span.context.toString().replace(/"/g, "'").replace(/\n/g, " ");
293
+ let css = `
308
294
  body:before {
309
295
  content: "Error at line ${err.span.start.line} in ${err.span.url.pathname}";
310
296
  display: table;
@@ -327,5 +313,115 @@ function emitSassError(err) {
327
313
  }
328
314
  body * { display: none; }
329
315
  `;
330
- return css;
316
+ return css;
317
+ }
318
+ writeOut(postedResult, destination) {
319
+ return new Promise((resolve, reject) => {
320
+ postedResult.warnings().forEach((warn) => {
321
+ process.stderr.write(warn.toString());
322
+ });
323
+ if (destination !== '') {
324
+ try {
325
+ fs.mkdirSync(path.dirname(destination), {
326
+ recursive: true
327
+ });
328
+ }
329
+ catch (err) {
330
+ if (err.code !== 'EEXIST' || err.code !== 'EISDIR')
331
+ throw err;
332
+ }
333
+ fs.writeFile(destination, postedResult.css, (err) => {
334
+ if (err) {
335
+ console.log(err);
336
+ }
337
+ else {
338
+ // success case, the file was saved
339
+ console.log(color.green(`Successfully written to ${destination}`));
340
+ resolve("Written to file.");
341
+ }
342
+ });
343
+ if (postedResult.map) {
344
+ fs.writeFile(destination + '.map', postedResult.map.toString(), (err) => {
345
+ if (err) {
346
+ throw err;
347
+ }
348
+ else {
349
+ resolve("Written to file.");
350
+ }
351
+ ;
352
+ });
353
+ }
354
+ }
355
+ else {
356
+ process.stdout.write(postedResult.css);
357
+ resolve("Written to file.");
358
+ }
359
+ });
360
+ }
331
361
  }
362
+ sheetloaf
363
+ .arguments('[sources...]')
364
+ .description('📃🍞 Compile Sass to CSS and transform the output using PostCSS, all in one command.')
365
+ .action((source) => {
366
+ //If user specifies --use, we ignore postcss config files.
367
+ if (sheetloaf.opts().use) {
368
+ postcssConfig = configs.generatePostcssConfigFromUse(sheetloaf.opts().use);
369
+ }
370
+ else {
371
+ postcssConfig = configs.generatePostcssConfigFromFile(sheetloaf.opts().config);
372
+ }
373
+ const compiler = new CompWrapper();
374
+ // If source is provided, we ignore pipes.
375
+ if (source.length > 0 && source[0]) {
376
+ compiler.init(sheetloaf.opts(), source[0]).then(() => {
377
+ compiler.renderAll().then(() => {
378
+ if (sheetloaf.opts().watch) {
379
+ compiler.watch();
380
+ }
381
+ else {
382
+ compiler.dispose();
383
+ }
384
+ });
385
+ });
386
+ }
387
+ else if (!process.stdin.isTTY) {
388
+ compiler.init(sheetloaf.opts()).then(() => {
389
+ //see github.com/tj/commander.js/issues/137
390
+ let stdin = '';
391
+ process.stdin.on('readable', () => {
392
+ var chunk = process.stdin.read();
393
+ if (chunk !== null) {
394
+ stdin += chunk;
395
+ }
396
+ });
397
+ process.stdin.on('end', () => {
398
+ compiler.render(stdin).then(() => {
399
+ compiler.dispose();
400
+ });
401
+ });
402
+ });
403
+ }
404
+ });
405
+ sheetloaf
406
+ .option('-o, --output <LOCATION>', 'Output file.')
407
+ .option('--dir <LOCATION>', 'Output directory.')
408
+ .option('--base <DIR>', 'Mirror the directory structure relative to this path in the output directory, for use with --dir.', '')
409
+ .option('--ext <EXTENSION>', 'Override the output file extension; for use with --dir', '.css')
410
+ .option('-s, --style <NAME>', 'Output style. ["expanded", "compressed"]', 'expanded')
411
+ .option('--source-map', 'Generate a source map (this is the default option).')
412
+ .option('--no-source-map', 'Do not generate a source map.')
413
+ .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.')
414
+ .option('--embed-sources', 'Embed the entire contents of the Sass files that contributed to the generated CSS in the source map.')
415
+ .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')
416
+ .option('--error-css', 'Emit a CSS file when an error occurs during compilation (this is the default option).')
417
+ .option('--no-error-css', 'Do not emit a CSS file when an error occurs during compilation.')
418
+ .option('--silence-deprecation <TYPE>', 'This option tells Sass to silence a particular type of deprecation.')
419
+ .option('-I, --load-path <PATHS>', 'Adds an additional load path for Sass to look for stylesheets.')
420
+ .option('-p, --pkg-importer <TYPE>', `Built-in importer(s) to use for pkg: URLs.\n[node] - Load files like Node.js package resolution.`)
421
+ .option('-w, --watch', 'Watch stylesheets and recompile when they change.')
422
+ .option('--config <LOCATION>', 'Set a custom directory to look for a postcss config file.')
423
+ .option('--poll [DURATION]', 'Use polling for file watching. Can optionally pass polling interval; default 100 ms')
424
+ .option('-u, --use <PLUGINS>', 'List of postcss plugins to use. Will cause sheetloaf to ignore any config files.')
425
+ .option('--async', `Use sass' asynchronous API. This may be slower.`);
426
+ sheetloaf.parse(process.argv);
427
+ //# sourceMappingURL=index.js.map
package/dist/sources.js CHANGED
@@ -1,29 +1,28 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.addResultToSourcesChecker = exports.clearSourcesChecker = exports.getChecker = exports.SassSources = void 0;
7
- const path_1 = __importDefault(require("path"));
8
- const url_1 = require("url");
1
+ import path from "path";
2
+ import {} from "sass-embedded";
3
+ import { fileURLToPath } from "url";
9
4
  let sourcesChecker = [];
10
- class SassSources {
5
+ export class SassSources {
6
+ absoluteMain;
7
+ main;
8
+ sources = [];
11
9
  constructor(fileName, sassResult) {
12
- this.sources = [];
13
10
  this.main = fileName;
14
- this.absoluteMain = path_1.default.resolve(fileName);
11
+ this.absoluteMain = path.resolve(fileName);
15
12
  this.setSources(sassResult.loadedUrls);
16
13
  }
17
14
  setSources(urls) {
18
15
  this.sources.splice(0, this.sources.length);
19
16
  urls.forEach(url => {
20
- if ((0, url_1.fileURLToPath)(url.href) !== this.absoluteMain) {
21
- this.sources.push((0, url_1.fileURLToPath)(url.href));
17
+ if (fileURLToPath(url.href) !== this.absoluteMain) {
18
+ this.sources.push(fileURLToPath(url.href));
22
19
  }
23
20
  });
24
21
  }
25
22
  containsPartial(filename) {
26
- if (this.sources.indexOf(path_1.default.resolve(filename)) >= 0) {
23
+ // FIXME: source paths are a little weird on windows which is making this check
24
+ // always return false.
25
+ if (this.sources.indexOf(path.resolve(filename)) >= 0) {
27
26
  return true;
28
27
  }
29
28
  else {
@@ -40,21 +39,18 @@ class SassSources {
40
39
  return this.main;
41
40
  }
42
41
  }
43
- exports.SassSources = SassSources;
44
- function getChecker() {
42
+ export function getChecker() {
45
43
  return sourcesChecker;
46
44
  }
47
- exports.getChecker = getChecker;
48
- function clearSourcesChecker() {
45
+ export function clearSourcesChecker() {
49
46
  sourcesChecker.splice(0, sourcesChecker.length);
50
47
  }
51
- exports.clearSourcesChecker = clearSourcesChecker;
52
- function addResultToSourcesChecker(fileName, result) {
48
+ export function addResultToSourcesChecker(fileName, result) {
53
49
  let resultExistsInChecker = false;
54
50
  let ind = 0;
55
51
  while (ind < sourcesChecker.length && resultExistsInChecker === false) {
56
- if (sourcesChecker[ind].getAbsoluteMain() === path_1.default.resolve(fileName)) {
57
- sourcesChecker[ind].setSources(result.loadedUrls);
52
+ if (sourcesChecker[ind]?.getAbsoluteMain() === path.resolve(fileName)) {
53
+ sourcesChecker[ind]?.setSources(result.loadedUrls);
58
54
  resultExistsInChecker = true;
59
55
  }
60
56
  ind = ind + 1;
@@ -63,4 +59,4 @@ function addResultToSourcesChecker(fileName, result) {
63
59
  sourcesChecker.push(new SassSources(fileName, result));
64
60
  }
65
61
  }
66
- exports.addResultToSourcesChecker = addResultToSourcesChecker;
62
+ //# sourceMappingURL=sources.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sheetloaf",
3
- "version": "1.26.0",
3
+ "version": "1.26.1-beta.1",
4
4
  "description": "freshmade stylesheets for the whole family.",
5
5
  "main": "./dist/index.js",
6
6
  "bin": {
@@ -9,7 +9,7 @@
9
9
  "scripts": {
10
10
  "build:development": "tsc --watch",
11
11
  "build:production": "tsc",
12
- "test": "mocha -r ts-node/register test/*.test.ts",
12
+ "test": "node --import tsx --test test/*.test.ts",
13
13
  "test2": "node . \"test/samples/styles/**/*.scss\" --dir \"test/samples/render/\" --load-path \"test/samples/lib\" --style compressed --base test/samples/styles/ --use autoprefixer,postcss-custom-properties --watch --pkg-importer node --silence-deprecation global-builtin",
14
14
  "test3": "cat test/samples/styles/file.scss | node . --style compressed --use autoprefixer --load-path test/samples/styles > test/samples/render/file.css",
15
15
  "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"
@@ -27,6 +27,7 @@
27
27
  "sass",
28
28
  "processor"
29
29
  ],
30
+ "type": "module",
30
31
  "author": "Benjamin Richardson",
31
32
  "license": "MIT",
32
33
  "bugs": {
@@ -34,18 +35,16 @@
34
35
  },
35
36
  "homepage": "https://github.com/benfuddled/sheetloaf#readme",
36
37
  "devDependencies": {
37
- "@types/mocha": "^10.0.10",
38
- "@types/node": "^18.6.3",
38
+ "@types/node": "^18.19.130",
39
39
  "autoprefixer": "^10.4.22",
40
40
  "bootstrap": "^5.3.8",
41
- "mocha": "^11.7.5",
42
41
  "postcss": "^8.5.15",
43
42
  "postcss-custom-properties": "^13.3.10",
44
- "ts-node": "^10.9.2",
45
- "typescript": "^4.7.4"
43
+ "tsx": "^4.22.4",
44
+ "typescript": "^6.0.3"
46
45
  },
47
46
  "peerDependencies": {
48
- "postcss": "^8.5.15"
47
+ "postcss": "^8.5.0"
49
48
  },
50
49
  "dependencies": {
51
50
  "chokidar": "^5.0.0",
@@ -54,4 +53,4 @@
54
53
  "picocolors": "^1.1.1",
55
54
  "sass-embedded": "1.100.0"
56
55
  }
57
- }
56
+ }