Skip to content

Commit

Permalink
feat: allow plain css passed as option (#588)
Browse files Browse the repository at this point in the history
See #291 and #584
  • Loading branch information
bezoerb committed Jan 28, 2024
1 parent 4942583 commit 526c767
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 9 deletions.
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -256,7 +256,7 @@ generate({
| inline | `boolean`\|`object` | `false` | Inline critical-path CSS using filamentgroup's loadCSS. Pass an object to configure [`inline-critical`](https://github.com/bezoerb/inline-critical#inlinehtml-styles-options) |
| base | `string` | `path.dirname(src)` or `process.cwd()` | Base directory in which the source and destination are to be written |
| html | `string` | | HTML source to be operated against. This option takes precedence over the `src` option. |
| css | `array` | `[]` | An array of paths to css files, file globs or [Vinyl](https://www.npmjs.com/package/vinyl) file objects. |
| css | `array` | `[]` | An array of paths to css files, file globs, [Vinyl](https://www.npmjs.com/package/vinyl) file objects or source CSS strings. |
| src | `string` | | Location of the HTML source to be operated against |
| target | `string` or `object` | | Location of where to save the output of an operation. Use an object with 'html' and 'css' props if you want to store both |
| width | `integer` | `1300` | Width of the target viewport |
Expand Down
13 changes: 7 additions & 6 deletions package-lock.json

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

1 change: 1 addition & 0 deletions package.json
Expand Up @@ -32,6 +32,7 @@
"node": ">=18"
},
"dependencies": {
"@adobe/css-tools": "^4.3.3",
"clean-css": "^5.3.3",
"common-tags": "^1.8.2",
"css-url-parser": "^1.1.3",
Expand Down
29 changes: 27 additions & 2 deletions src/file.js
@@ -1,3 +1,4 @@
/* eslint-disable complexity */
import {Buffer} from 'node:buffer';
import fs from 'node:fs';
import os from 'node:os';
Expand All @@ -10,6 +11,7 @@ import {dataUriToBuffer} from 'data-uri-to-buffer';
import debugBase from 'debug';
import {findUpMultiple} from 'find-up';
import {globby} from 'globby';
import {parse} from '@adobe/css-tools';
import got from 'got';
import isGlob from 'is-glob';
import makeDir from 'make-dir';
Expand Down Expand Up @@ -408,6 +410,7 @@ function getStylesheetObjects(file, options) {
throw new Error('Parameter file needs to be a vinyl object');
}

// Already computed stylesheetObjects
if (file.stylesheetObjects) {
return file.stylesheetObjects;
}
Expand Down Expand Up @@ -927,18 +930,40 @@ export async function getStylesheet(document, filepath, options = {}) {
return file;
}

const isCssSource = (string) => {
try {
parse(string);
return true;
} catch {
return false;
}
};

/**
* Get css for document
* @param {Vinyl} document Vinyl representation of HTML document
* @param {object} options Critical options
* @returns {Promise<string>} Css string unoptimized, Multiple stylesheets are concatenated with EOL
*/
async function getCss(document, options = {}) {
export async function getCss(document, options = {}) {
const {css} = options;
let stylesheets = [];

if (checkCssOption(css)) {
const files = await glob(css, options);
const cssArray = Array.isArray(css) ? css : [css];

// merge css files & css source strings passed as css option
const filesRaw = await Promise.all(
cssArray.map((value) => {
if (isCssSource(value)) {
return Buffer.from(value);
}

return glob(value, options);
})
);

const files = filesRaw.flat();
stylesheets = await mapAsync(files, (file) => getStylesheet(document, file, options));
debug('(getCss) css option set', files, stylesheets);
} else {
Expand Down
17 changes: 17 additions & 0 deletions test/blackbox.test.js
Expand Up @@ -316,6 +316,23 @@ describe('generate (local)', () => {
);
});

test('should evaluate css passed as source string', (done) => {
const expected = 'html{display:block}';
const target = path.resolve('.source-string.css');

generate(
{
base: FIXTURES_DIR,
src: 'generate-default-nostyle.html',
css: ['html{display:block}.someclass{color:red}'],
target,
width: 1300,
height: 900,
},
assertCritical(target, expected, done)
);
});

test('should inline relative images', (done) => {
const expected = read('expected/generate-image.css');
const target = path.resolve('.image-relative.css');
Expand Down
14 changes: 14 additions & 0 deletions test/file.test.js
Expand Up @@ -25,6 +25,7 @@ import {
vinylize,
normalizePath,
getStylesheetHrefs,
getCss,
getAssets,
getDocumentPath,
getStylesheetPath,
Expand Down Expand Up @@ -663,3 +664,16 @@ test('Does not rebase when rebase is disabled via option', async () => {
}
}
});

test('Handle css source option', async () => {
const document = await getDocument(path.join(__dirname, 'fixtures/generate-adaptive.html'));

const source1 = 'html{display:block;}';
const source2 = '.someclass{color:red}';
const css = await getCss(document, {
css: [source1, path.join(__dirname, 'fixtures/styles/adaptive.css'), source2],
});

expect(css.startsWith(source1)).toBeTruthy();
expect(css.endsWith(source2)).toBeTruthy();
});

0 comments on commit 526c767

Please sign in to comment.