Skip to content

Commit

Permalink
0.1.3
Browse files Browse the repository at this point in the history
  • Loading branch information
lonelyhentxi committed Feb 19, 2024
1 parent 213503d commit a1e8eef
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 44 deletions.
34 changes: 17 additions & 17 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,32 @@
authors = ["lonelyhentxi <master@evernightfireworks.com>"]
edition = "2021"
name = "grasslands"
version = "0.1.0"
version = "0.1.3"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[lib]
crate-type = ["cdylib"]

[dependencies]
anyhow = { version = "1.0.75", features = [] }
codemap = "0.1.3"
dunce = "1.0.4"
lazy_static = { version = "1.4.0", features = [] }
napi = "2"
napi-derive = "2"
nodejs-resolver = "0.1.0"
path-slash = "0.2.1"
regex = "1.10.2"
serde_json = "1.0.108"
sugar_path = "0.0.12"
swc_common = "0.33.9"
tracing = "0.1.40"
anyhow = { version = "1.0.75", features = [] }
codemap = "0.1.3"
dunce = "1.0.4"
lazy_static = { version = "1.4.0", features = [] }
napi = "2"
napi-derive = "2"
nodejs-resolver = "0.1.0"
path-slash = "0.2.1"
regex = "1.10.2"
serde_json = "1.0.108"
sugar_path = "0.0.12"
swc_common = "0.33.9"
tracing = "0.1.40"
tracing-subscriber = "0.3.18"

[dependencies.grass]
git = "https://github.com/lonelyhentxi/grass.git"
rev = "0d53312"
[dependencies.grass]
git = "https://github.com/lonelyhentxi/grass.git"
rev = "0d53312"

[build-dependencies]
napi-build = "2"
Expand Down
11 changes: 8 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

A wrapper with nodejs import resolver and an adapter between [grass](https://github.com/connorskees/grass) and sass-loader? etc.

>**Performance**
> **Performance**
> grass is benchmarked against dart-sass and sassc (libsass) here. In general, grass appears to be ~2x faster than dart-sass and ~1.7x faster than sassc.
And In my tests, it is **5~10x** faster than `sass` package.
Expand Down Expand Up @@ -44,13 +44,18 @@ npm install -D grasslands
includePaths: [
path.resolve('your/include_paths1'),
path.resolve('your/include_paths2')
]
],
resolveAlias: {
'@utils': ['src/utils']
}
},
}
}
// your other configs
```

Currently not support sassOptions.importer/importers as it 2x ~ 4x slower.

# Support

### Operating Systems
Expand All @@ -65,4 +70,4 @@ npm install -D grasslands
| Linux x64 musl ||||
| Linux arm64 gnu ||||
| Linux arm64 musl ||||
| FreeBSD x64 ||||
| FreeBSD x64 ||||
2 changes: 2 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export interface SassOptions {
alertColor?: boolean
quietDeps?: boolean
verbose?: boolean
resolveAlias?: Record<string, Array<string>>
}
export interface SassResult {
css: string
Expand Down Expand Up @@ -81,6 +82,7 @@ export interface LegacySassOptions {
data?: string
file?: string
indentedSyntax?: boolean
resolveAlias?: Record<string, Array<string>>
}
export interface LegacySassResult {
css: string
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "grasslands",
"version": "0.1.2",
"version": "0.1.3",
"keywords": [
"sass",
"scss",
Expand Down Expand Up @@ -51,7 +51,7 @@
"bench": "node -r @swc-node/register benchmark/bench.ts",
"build-ts": "tsc --project ./tsconfig.build.json",
"build-rs": "napi build --platform --release --pipe \"prettier -w\"",
"build-rs:debug": "napi build --platform --debug --pipe \"prettier -w\"",
"build-rs:debug": "napi build --platform --pipe \"prettier -w\"",
"build": "npm run build-rs && npm run build-ts",
"build:debug": "npm run build-rs:debug && npm run build-ts",
"format": "run-p format:prettier format:rs format:toml",
Expand Down
35 changes: 29 additions & 6 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

use lazy_static::lazy_static;
use napi_derive::napi;
use nodejs_resolver::{Options as ResolverOptions, ResolveResult, Resolver};
use nodejs_resolver::{AliasMap, Options as ResolverOptions, ResolveResult, Resolver};
use path_slash::PathExt;
use regex::Regex;
use std::collections::HashMap;
use std::fmt::Debug;
use std::panic::{RefUnwindSafe, UnwindSafe};
use std::path::{Path, PathBuf};
Expand All @@ -17,6 +18,8 @@ lazy_static! {
pub static ref WEBPACK_TILDE_PATTERN_PREFIX: Regex = Regex::new(r"^~([^/]+)").unwrap();
}

pub type ResolveAlias = HashMap<String, Vec<String>>;

#[derive(Debug)]
pub struct GrasslandsImporter {
pwd: PathBuf,
Expand All @@ -26,7 +29,14 @@ pub struct GrasslandsImporter {
}

impl GrasslandsImporter {
pub fn new(file: Option<String>) -> Self {
fn convert_resolve_alias(alias: ResolveAlias) -> Vec<(String, Vec<AliasMap>)> {
alias
.into_iter()
.map(|(k, vs)| (k, vs.into_iter().map(AliasMap::Target).collect()))
.collect()
}

pub fn new(file: Option<String>, alias: Option<ResolveAlias>) -> Self {
let sass_file_resolver = Resolver::new(ResolverOptions {
extensions: vec![
".sass".to_owned(),
Expand All @@ -41,6 +51,10 @@ impl GrasslandsImporter {
symlinks: true,
resolve_to_context: false,
main_files: vec!["_index".to_owned(), "index".to_owned()],
alias: alias
.clone()
.map(Self::convert_resolve_alias)
.unwrap_or_default(),
..Default::default()
});
let sass_module_resolver = Resolver::new(ResolverOptions {
Expand All @@ -57,6 +71,7 @@ impl GrasslandsImporter {
symlinks: true,
resolve_to_context: true,
main_files: vec!["_index".to_owned(), "index".to_owned()],
alias: alias.map(Self::convert_resolve_alias).unwrap_or_default(),
..Default::default()
});
Self {
Expand Down Expand Up @@ -244,6 +259,7 @@ pub struct SassOptions {
// pub logger
pub quiet_deps: Option<bool>,
pub verbose: Option<bool>,
pub resolve_alias: Option<HashMap<String, Vec<String>>>,
}

#[napi(object)]
Expand Down Expand Up @@ -333,6 +349,7 @@ pub struct LegacySassOptions {
pub data: Option<String>,
pub file: Option<String>,
pub indented_syntax: Option<bool>,
pub resolve_alias: Option<HashMap<String, Vec<String>>>,
}

#[napi(object)]
Expand Down Expand Up @@ -555,8 +572,11 @@ pub fn to_legacy_sass_error(options: &LegacySassOptions, err: grass::Error) -> L

#[napi]
pub fn compile(source: String, options: Option<SassOptions>) -> SassCompileResult {
let options = options.unwrap_or_default();
let grass_fs = Arc::new(GrasslandsImporter::new(options.file.clone()));
let mut options = options.unwrap_or_default();
let grass_fs = Arc::new(GrasslandsImporter::new(
options.file.clone(),
options.resolve_alias.take(),
));
let grass_opts = sass_to_grass_options(options.clone(), grass_fs.as_ref(), grass_fs.as_ref());
let ret = grass::from_string(source, &grass_opts);

Expand All @@ -581,7 +601,7 @@ pub fn compile_legacy(
source: String,
options: Option<LegacySassOptions>,
) -> LegacySassCompileResult {
let options = options.unwrap_or_default();
let mut options = options.unwrap_or_default();
let start_time = SystemTime::now();
let entry = if let Some(file) = &options.file {
PathBuf::from(file)
Expand All @@ -591,7 +611,10 @@ pub fn compile_legacy(
} else {
"data".to_string()
};
let grass_fs = Arc::new(GrasslandsImporter::new(options.file.clone()));
let grass_fs = Arc::new(GrasslandsImporter::new(
options.file.clone(),
options.resolve_alias.take(),
));
let grass_opts =
legacy_sass_to_grass_options(options.clone(), grass_fs.as_ref(), grass_fs.as_ref());
let ret = grass::from_string(source, &grass_opts);
Expand Down
48 changes: 36 additions & 12 deletions src/sass-loader-adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,38 +8,54 @@ type LoggerOptions = {
stack: string
}

type Options = SassOptions & {
type ResolveAliasEntry = string | Array<string>
type ResolveAliasOptions = Array<[string, ResolveAliasEntry]> | Record<string, ResolveAliasEntry>

type Options = Omit<SassOptions, 'resolveAlias'> & {
importers: { canonicalize: () => Promise<void>; load: () => void }[]
logger: {
debug: (message: string, options: LoggerOptions) => void
warn: (message: string, options: LoggerOptions) => void
}
url: URL
resolveAlias: ResolveAliasOptions
}

type LegacyOptions = LegacySassOptions & {
type LegacyOptions = Omit<LegacySassOptions, 'resolveAlias'> & {
importer: ((originalUrl: string, prev: any, done: any) => void)[]
logger: {
debug: (message: string, options: LoggerOptions) => void
warn: (message: string, options: LoggerOptions) => void
}
resolveAlias: ResolveAliasOptions
}

export const info = `dart-sass\t1.69.5`

export function compileStringSync(source: string, options?: Options): SassResult {
const ret = compile(source, options ? { ...options, file: (options.file ?? '').toString() } : undefined)

if (ret.success) {
return ret.success
export function normalizeResolveAlias(options: ResolveAliasOptions | null): Record<string, Array<string>> | undefined {
let items: Array<[string, Array<string>]> = []
if (Array.isArray(options)) {
items = options.map(([k, v]) => [k, Array.isArray(v) ? v : [v]])
} else if (typeof options === 'object' && options) {
items = Object.entries(options).map(([k, v]) => [k, Array.isArray(v) ? v : [v]])
}

// eslint-disable-next-line @typescript-eslint/no-throw-literal
throw ret.failure
if (!items.length) {
return undefined
}
return Object.fromEntries(items)
}

export async function compileStringAsync(source: string, options?: Options): Promise<SassResult> {
const ret = compile(source, options ? { ...options, file: (options.file ?? '').toString() } : undefined)
const ret = compile(
source,
options
? {
...options,

Check failure on line 53 in src/sass-loader-adapter.ts

View workflow job for this annotation

GitHub Actions / Lint

Insert `··`
file: (options.file ?? '').toString(),

Check failure on line 54 in src/sass-loader-adapter.ts

View workflow job for this annotation

GitHub Actions / Lint

Insert `··`
resolveAlias: normalizeResolveAlias(options.resolveAlias),

Check failure on line 55 in src/sass-loader-adapter.ts

View workflow job for this annotation

GitHub Actions / Lint

Insert `··`
}

Check failure on line 56 in src/sass-loader-adapter.ts

View workflow job for this annotation

GitHub Actions / Lint

Insert `··`
: undefined,
)

if (ret.success) {
// eslint-disable-next-line @typescript-eslint/return-await,@typescript-eslint/await-thenable
Expand All @@ -54,7 +70,15 @@ export function render(
options: LegacyOptions,
callback: (error?: LegacySassError, result?: LegacySassResult) => void,
): void {
const ret = compileLegacy(options.data ?? '', options)
const ret = compileLegacy(
options.data ?? '',
options
? {
...options,

Check failure on line 77 in src/sass-loader-adapter.ts

View workflow job for this annotation

GitHub Actions / Lint

Insert `··`
resolveAlias: normalizeResolveAlias(options.resolveAlias),

Check failure on line 78 in src/sass-loader-adapter.ts

View workflow job for this annotation

GitHub Actions / Lint

Insert `··`
}

Check failure on line 79 in src/sass-loader-adapter.ts

View workflow job for this annotation

GitHub Actions / Lint

Insert `··`
: undefined,
)

if (ret.success) {
return callback(undefined, ret.success)
Expand Down
12 changes: 8 additions & 4 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"compilerOptions": {
"target": "ES2018",
"target": "ES2019",
"strict": true,
"moduleResolution": "node",
"module": "CommonJS",
Expand All @@ -10,6 +10,10 @@
"allowSyntheticDefaultImports": true,
"resolveJsonModule": true
},
"include": ["."],
"exclude": ["node_modules"]
}
"include": [
"."
],
"exclude": [
"node_modules"
]
}

0 comments on commit a1e8eef

Please sign in to comment.