Skip to content

Commit

Permalink
Add option to specify sass implementation to use
Browse files Browse the repository at this point in the history
  • Loading branch information
jgerigmeyer committed Feb 22, 2024
1 parent bbcf2ce commit 7037bb8
Show file tree
Hide file tree
Showing 6 changed files with 334 additions and 17 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

## 8.0.0-beta.0 (unreleased)

- FEATURE: Add True `sass` option (`string` or Sass implementation instance,
defaults to `'sass'`) to allow using either `sass` or `embedded-sass`.
- BREAKING: Drop support for node < 18
- INTERNAL: Remove `sass` as a peer-dependency.
- INTERNAL: Update dependencies

## 7.0.1 (01/04/24)
Expand Down
4 changes: 1 addition & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,6 @@
"release": "run-s commit docs",
"prepack": "yarn run release"
},
"peerDependencies": {
"sass": ">=1.45.0"
},
"dependencies": {
"@adobe/css-tools": "^4.3.3",
"jest-diff": "^29.7.0",
Expand All @@ -92,6 +89,7 @@
"postcss": "^8.4.35",
"prettier": "^3.2.5",
"sass": "^1.71.1",
"sass-embedded": "^1.71.1",
"sassdoc": "^2.7.4",
"sassdoc-theme-herman": "^5.0.1",
"stylelint": "^16.2.1",
Expand Down
35 changes: 26 additions & 9 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
/* eslint-disable @typescript-eslint/no-use-before-define */
/* eslint-disable no-use-before-define */
/* eslint-disable @typescript-eslint/no-use-before-define */

import assert from 'node:assert';
import path from 'node:path';

import {
CssAtRuleAST,
Expand All @@ -9,12 +12,8 @@ import {
parse as cssParse,
stringify as cssStringify,
} from '@adobe/css-tools';
import * as assert from 'assert';
import { diffStringsUnified } from 'jest-diff';
import { find, forEach, last, startsWith } from 'lodash';
import * as path from 'path';
import type { Options, StringOptions } from 'sass';
import { compile, compileString } from 'sass';

import * as constants from './constants';
import {
Expand All @@ -28,6 +27,7 @@ import {
export interface TrueOptions {
describe: (description: string, fn: () => void) => void;
it: (description: string, fn: () => void) => void;
sass?: any;
sourceType?: 'path' | 'string';
contextLines?: number;
}
Expand Down Expand Up @@ -69,7 +69,7 @@ export type Parser = (rule: Rule, ctx: Context) => Parser;
export const runSass = function (
trueOptions: TrueOptions,
src: string,
sassOptions?: Options<'sync'> | StringOptions<'sync'>,
sassOptions?: any,
) {
const trueOpts = Object.assign({}, trueOptions);
const sassOpts = Object.assign({}, sassOptions);
Expand All @@ -83,12 +83,29 @@ export const runSass = function (
// Warn if arguments match v6 API
if (typeof src !== 'string' || !trueOptions.describe || !trueOptions.it) {
throw new Error(
'The arguments provided to `runSass` do not match the new API introduced in True v7. Refer to the v7 release notes for migration documentation: https://github.com/oddbird/true/releases/tag/v7.0.0',
'The arguments provided to `runSass` do not match the new API ' +
'introduced in True v7. Refer to the v7 release notes ' +
'for migration documentation: ' +
'https://github.com/oddbird/true/releases/tag/v7.0.0',
);
}

const compiler = trueOpts.sourceType === 'string' ? compileString : compile;
const parsedCss = compiler(src, sassOpts).css;
let compiler;
if (trueOpts.sass && typeof trueOpts.sass !== 'string') {
compiler = trueOpts.sass;
} else {
const sassPkg = trueOpts.sass ?? 'sass';
try {
// eslint-disable-next-line global-require
compiler = require(sassPkg);
} catch (err) {
throw new Error(`Cannot find Dart Sass (\`${sassPkg}\`) dependency.`);
}
}

const compilerFn =
trueOpts.sourceType === 'string' ? 'compileString' : 'compile';
const parsedCss = compiler[compilerFn](src, sassOpts).css;
const modules = parse(parsedCss, trueOpts.contextLines);

forEach(modules, (module) => {
Expand Down
66 changes: 65 additions & 1 deletion test/main.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/no-var-requires */
/* eslint-disable global-require */

const path = require('path');
const path = require('node:path');

const { expect } = require('chai');
const { diffStringsUnified } = require('jest-diff');
Expand Down Expand Up @@ -114,6 +114,70 @@ describe('#runSass', () => {
};
expect(attempt).not.to.throw();
});

it('can specify sass implementation to use [string]', () => {
const sass = [
'@use "true" as *;',
'@include test-module("Module") {',
' @include test("Test") {',
' @include assert("Assertion") {',
' @include output() {',
' -property: value;',
' }',
' @include expect() {',
' -property: value;',
' }',
' }',
' }',
'}',
].join('\n');
const mock = function (name, cb) {
cb();
};
const attempt = function () {
sassTrue.runSass(
{
describe: mock,
it: mock,
sourceType: 'string',
sass: 'sass-embedded',
},
sass,
);
};
expect(attempt).not.to.throw();
});

it('can specify sass implementation to use [object]', () => {
const mock = function (name, cb) {
cb();
};
const attempt = function () {
sassTrue.runSass(
{
describe: mock,
it: mock,
sass: {
compile() {
throw new Error('Custom sass implementation called');
},
},
},
'',
);
};
expect(attempt).to.throw('Custom sass implementation called');
});

it('throws if sass implementation is not found', () => {
const mock = function (name, cb) {
cb();
};
const attempt = function () {
sassTrue.runSass({ describe: mock, it: mock, sass: 'foobar' }, '');
};
expect(attempt).to.throw('Cannot find Dart Sass (`foobar`) dependency.');
});
});

describe('#parse', () => {
Expand Down
2 changes: 1 addition & 1 deletion test/sass.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/no-var-requires */
/* eslint-disable global-require */

const path = require('path');
const path = require('node:path');

const sassFile = path.join(__dirname, 'scss', 'test.scss');
let runSass;
Expand Down
Loading

0 comments on commit 7037bb8

Please sign in to comment.