Skip to content

Commit a606fb9

Browse files
authored
feat: serde features (#19)
1 parent e95ea12 commit a606fb9

15 files changed

+277
-211
lines changed

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ include = ["**/*.rs", "ext/sass/sass-embedded.proto"]
1515
[features]
1616
default = []
1717
legacy = ["dep:regex", "dep:serde_json", "dep:urlencoding"]
18+
serde = ["dep:serde", "url/serde"]
1819

1920
[dependencies]
2021
prost = "0.11"
@@ -27,6 +28,7 @@ rustc-hash = "1"
2728
regex = { version = "1", optional = true }
2829
serde_json = { version = "1", optional = true }
2930
urlencoding = { version = "2", optional = true }
31+
serde = { version = "1", optional = true, features = ["derive"] }
3032

3133
[dev-dependencies]
3234
serde_json = "1"

src/api.rs

Lines changed: 153 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -3,55 +3,49 @@ use std::{
33
path::{Path, PathBuf},
44
};
55

6+
#[cfg(feature = "serde")]
7+
use serde::{Deserialize, Serialize};
8+
69
use crate::{
710
protocol::{
11+
self,
812
outbound_message::{
913
compile_response::{self, CompileSuccess},
1014
CompileResponse,
1115
},
12-
OutputStyle, SourceSpan, Syntax,
1316
},
1417
Exception, Result, Url,
1518
};
1619

1720
/// Options that can be passed to [Sass::compile].
1821
///
19-
/// More information:
20-
/// - [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/Options)
22+
/// More information: [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/Options)
23+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2124
#[derive(Debug)]
2225
pub struct Options {
23-
/// More information:
24-
/// - [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/Options#alertAscii)
26+
/// More information: [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/Options#alertAscii)
2527
pub alert_ascii: bool,
26-
/// More information:
27-
/// - [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/Options#alertColor)
28+
/// More information: [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/Options#alertColor)
2829
pub alert_color: Option<bool>,
29-
/// More information:
30-
/// - [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/Options#importers)
30+
/// More information: [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/Options#importers)
31+
#[serde(skip)]
3132
pub importers: Vec<SassImporter>,
32-
/// More information:
33-
/// - [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/Options#loadPaths)
33+
/// More information: [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/Options#loadPaths)
3434
pub load_paths: Vec<PathBuf>,
35-
/// More information:
36-
/// - [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/Options#logger)
35+
/// More information: [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/Options#logger)
36+
#[serde(skip)]
3737
pub logger: Option<BoxedLogger>,
38-
/// More information:
39-
/// - [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/Options#quietDeps)
38+
/// More information: [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/Options#quietDeps)
4039
pub quiet_deps: bool,
41-
/// More information:
42-
/// - [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/Options#sourceMap)
40+
/// More information: [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/Options#sourceMap)
4341
pub source_map: bool,
44-
/// More information:
45-
/// - [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/Options#sourceMapIncludeSources)
42+
/// More information: [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/Options#sourceMapIncludeSources)
4643
pub source_map_include_sources: bool,
47-
/// More information:
48-
/// - [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/Options#style)
44+
/// More information: [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/Options#style)
4945
pub style: OutputStyle,
50-
/// More information:
51-
/// - [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/Options#verbose)
46+
/// More information: [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/Options#verbose)
5247
pub verbose: bool,
53-
/// More information:
54-
/// - [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/Options#charset)
48+
/// More information: [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/Options#charset)
5549
pub charset: bool,
5650
}
5751

@@ -192,21 +186,19 @@ impl OptionsBuilder {
192186

193187
/// Options that can be passed to [Sass::compile_string].
194188
///
195-
/// More information:
196-
/// - [Sass documentation](https://sass-lang.com/documentation/js-api/modules#StringOptions)
189+
/// More information: [Sass documentation](https://sass-lang.com/documentation/js-api/modules#StringOptions)
190+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
197191
#[derive(Debug, Default)]
198192
pub struct StringOptions {
199193
/// Field for [Options]
200194
pub common: Options,
201-
/// More information:
202-
/// - [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/StringOptionsWithImporter#importer)
195+
/// More information: [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/StringOptionsWithImporter#importer)
196+
#[serde(skip)]
203197
pub input_importer: Option<SassImporter>,
204-
/// More information:
205-
/// - [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/StringOptionsWithoutImporter#syntax)
198+
/// More information: [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/StringOptionsWithoutImporter#syntax)
206199
/// - [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/StringOptionsWithImporter#syntax)
207200
pub syntax: Syntax,
208-
/// More information:
209-
/// - [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/StringOptionsWithoutImporter#url)
201+
/// More information: [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/StringOptionsWithoutImporter#url)
210202
/// - [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/StringOptionsWithImporter#url)
211203
pub url: Option<Url>,
212204
}
@@ -373,26 +365,22 @@ impl StringOptionsBuilder {
373365
/// A type alias for [Box<dyn Logger>].
374366
pub type BoxedLogger = Box<dyn Logger>;
375367

376-
/// More information
377-
/// - [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/Logger)
368+
/// More information: [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/Logger)
378369
pub trait Logger: Debug + Send + Sync {
379-
/// More information
380-
/// - [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/Logger#warn)
370+
/// More information: [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/Logger#warn)
381371
fn warn(&self, _message: &str, options: &LoggerWarnOptions) {
382372
eprintln!("{}", options.formatted);
383373
}
384374

385-
/// More information
386-
/// - [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/Logger#debug)
375+
/// More information: [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/Logger#debug)
387376
fn debug(&self, _message: &str, options: &LoggerDebugOptions) {
388377
eprintln!("{}", options.formatted);
389378
}
390379
}
391380

392381
/// Options for [Logger::warn].
393382
///
394-
/// More information
395-
/// - [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/Logger#warn)
383+
/// More information: [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/Logger#warn)
396384
pub struct LoggerWarnOptions {
397385
/// Whether this is a deprecation warning.
398386
pub deprecation: bool,
@@ -405,8 +393,7 @@ pub struct LoggerWarnOptions {
405393

406394
/// Options for [Logger::debug].
407395
///
408-
/// More information
409-
/// - [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/Logger#debug)
396+
/// More information: [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/Logger#debug)
410397
pub struct LoggerDebugOptions {
411398
/// The location in the Sass source code that generated this debug message.
412399
pub span: Option<SourceSpan>,
@@ -428,70 +415,57 @@ pub type BoxedImporter = Box<dyn Importer>;
428415
/// A type alias for [Box<dyn FileImporter>].
429416
pub type BoxedFileImporter = Box<dyn FileImporter>;
430417

431-
/// More information
432-
/// - [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/Importer)
418+
/// More information: [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/Importer)
433419
pub trait Importer: Debug + Send + Sync {
434-
/// More information
435-
/// - [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/Importer#canonicalize)
420+
/// More information: [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/Importer#canonicalize)
436421
fn canonicalize(
437422
&self,
438423
url: &str,
439424
options: &ImporterOptions,
440425
) -> Result<Option<Url>>;
441426

442-
/// More information
443-
/// - [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/Importer#load)
427+
/// More information: [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/Importer#load)
444428
fn load(&self, canonical_url: &Url) -> Result<Option<ImporterResult>>;
445429
}
446430

447431
/// Options for [Importer::canonicalize] or [Importer::load].
448432
///
449-
/// More information
450-
/// - [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/Importer#canonicalize)
433+
/// More information: [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/Importer#canonicalize)
451434
pub struct ImporterOptions {
452435
/// Whether this is being invoked because of a Sass @import rule, as opposed to a @use
453436
/// or @forward rule.
454437
pub from_import: bool,
455438
}
456439

457-
/// More information
458-
/// - [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/FileImporter)
440+
/// More information: [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/FileImporter)
459441
pub trait FileImporter: Debug + Send + Sync {
460-
/// More information
461-
/// - [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/FileImporter#findFileUrl)
442+
/// More information: [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/FileImporter#findFileUrl)
462443
fn find_file_url(
463444
&self,
464445
url: &str,
465446
options: &ImporterOptions,
466447
) -> Result<Option<Url>>;
467448
}
468449

469-
/// More information
470-
/// - [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/ImporterResult)
450+
/// More information: [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/ImporterResult)
471451
pub struct ImporterResult {
472-
/// More information
473-
/// - [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/ImporterResult#contents)
452+
/// More information: [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/ImporterResult#contents)
474453
pub contents: String,
475-
/// More information
476-
/// - [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/ImporterResult#sourceMapUrl)
454+
/// More information: [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/ImporterResult#sourceMapUrl)
477455
pub source_map_url: Option<Url>,
478-
/// More information
479-
/// - [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/ImporterResult#syntax)
456+
/// More information: [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/ImporterResult#syntax)
480457
pub syntax: Syntax,
481458
}
482459

483-
/// More information
484-
/// - [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/CompileResult)
460+
/// More information: [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/CompileResult)
461+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
485462
#[derive(Debug, Clone)]
486463
pub struct CompileResult {
487-
/// More information
488-
/// - [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/CompileResult#css)
464+
/// More information: [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/CompileResult#css)
489465
pub css: String,
490-
/// More information
491-
/// - [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/CompileResult#loadedUrls)
466+
/// More information: [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/CompileResult#loadedUrls)
492467
pub loaded_urls: Vec<Url>,
493-
/// More information
494-
/// - [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/CompileResult#sourceMap)
468+
/// More information: [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/CompileResult#sourceMap)
495469
pub source_map: Option<String>,
496470
}
497471

@@ -526,3 +500,111 @@ impl From<CompileSuccess> for CompileResult {
526500
}
527501
}
528502
}
503+
504+
/// More information: [Sass documentation](https://sass-lang.com/documentation/js-api/modules#OutputStyle)
505+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
506+
#[derive(Debug)]
507+
pub enum OutputStyle {
508+
/// Writes each selector and declaration on its own line.
509+
Expanded,
510+
/// Removes as many extra characters as possible, and writes the entire stylesheet on a single line.
511+
Compressed,
512+
}
513+
514+
impl Default for OutputStyle {
515+
fn default() -> Self {
516+
Self::Expanded
517+
}
518+
}
519+
520+
impl From<OutputStyle> for protocol::OutputStyle {
521+
fn from(o: OutputStyle) -> Self {
522+
match o {
523+
OutputStyle::Expanded => Self::Expanded,
524+
OutputStyle::Compressed => Self::Compressed,
525+
}
526+
}
527+
}
528+
529+
/// More information: [Sass documentation](https://sass-lang.com/documentation/js-api/modules#Syntax)
530+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
531+
#[derive(Debug)]
532+
pub enum Syntax {
533+
/// the [scss syntax](https://sass-lang.com/documentation/syntax#scss)
534+
Scss,
535+
/// the [indented syntax](https://sass-lang.com/documentation/syntax#the-indented-syntax)
536+
Indented,
537+
/// the plain css syntax, which is parsed like SCSS but forbids the use of any special Sass features.
538+
Css,
539+
}
540+
541+
impl Default for Syntax {
542+
fn default() -> Self {
543+
Self::Scss
544+
}
545+
}
546+
547+
impl From<Syntax> for protocol::Syntax {
548+
fn from(s: Syntax) -> Self {
549+
match s {
550+
Syntax::Scss => Self::Scss,
551+
Syntax::Indented => Self::Indented,
552+
Syntax::Css => Self::Css,
553+
}
554+
}
555+
}
556+
557+
/// More information: [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/SourceSpan)
558+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
559+
#[derive(Debug)]
560+
pub struct SourceSpan {
561+
/// More information: [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/SourceSpan#context)
562+
pub context: Option<String>,
563+
/// More information: [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/SourceSpan#end)
564+
pub end: SourceLocation,
565+
/// More information: [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/SourceSpan#start)
566+
pub start: SourceLocation,
567+
/// More information: [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/SourceSpan#url)
568+
pub url: Option<Url>,
569+
/// More information: [Sass documentation](https://sass-lang.com/documentation/js-api/interfaces/SourceSpan#text)
570+
pub text: String,
571+
}
572+
573+
impl From<protocol::SourceSpan> for SourceSpan {
574+
fn from(span: protocol::SourceSpan) -> Self {
575+
let start = span.start.unwrap();
576+
Self {
577+
context: if span.context.is_empty() {
578+
None
579+
} else {
580+
Some(span.context)
581+
},
582+
end: span.end.unwrap_or_else(|| start.clone()).into(),
583+
start: start.into(),
584+
url: if span.url.is_empty() {
585+
None
586+
} else {
587+
Some(Url::parse(&span.url).unwrap())
588+
},
589+
text: span.text,
590+
}
591+
}
592+
}
593+
594+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
595+
#[derive(Debug)]
596+
pub struct SourceLocation {
597+
pub offset: usize,
598+
pub line: usize,
599+
pub column: usize,
600+
}
601+
602+
impl From<protocol::source_span::SourceLocation> for SourceLocation {
603+
fn from(location: protocol::source_span::SourceLocation) -> Self {
604+
Self {
605+
offset: location.offset as usize,
606+
line: location.line as usize,
607+
column: location.column as usize,
608+
}
609+
}
610+
}

0 commit comments

Comments
 (0)