Skip to content

Commit 413530c

Browse files
committed
type state builder
1 parent 52f1456 commit 413530c

1 file changed

Lines changed: 82 additions & 6 deletions

File tree

src/lib.rs

Lines changed: 82 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ pub use advanced::{HighlightError, HighlightQueryErrorKind};
215215
/// Source text to highlight at runtime.
216216
///
217217
/// Available with the `runtime` feature. Build one with [`SourceCode::new`],
218-
/// then pass it to [`Code()`].
218+
/// or with [`SourceCode::builder`], then pass it to [`Code()`].
219219
///
220220
/// ```rust
221221
/// use dioxus_code::{Language, SourceCode};
@@ -230,11 +230,39 @@ pub struct SourceCode {
230230
}
231231

232232
/// Source-first builder for [`SourceCode`].
233+
///
234+
/// Call [`SourceCodeBuilder::with_language`] to set the language, then
235+
/// `build()` to produce [`SourceCode`]. With the `detection` feature enabled,
236+
/// `build()` may also be called without an explicit language to detect from
237+
/// the source text.
238+
///
239+
/// ```rust
240+
/// use dioxus_code::{Language, SourceCode};
241+
///
242+
/// let _src = SourceCode::builder("fn main() {}")
243+
/// .with_language(Language::Rust)
244+
/// .build();
245+
/// ```
233246
#[cfg(feature = "runtime")]
234247
#[cfg_attr(docsrs, doc(cfg(feature = "runtime")))]
235248
#[derive(Debug, Clone, PartialEq, Eq)]
236-
pub struct SourceCodeBuilder {
249+
pub struct SourceCodeBuilder<State = SourceCodeBuilderMissingLanguage> {
237250
source: String,
251+
state: State,
252+
}
253+
254+
/// Builder state before a [`SourceCodeBuilder`] has a language.
255+
#[cfg(feature = "runtime")]
256+
#[cfg_attr(docsrs, doc(cfg(feature = "runtime")))]
257+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
258+
pub struct SourceCodeBuilderMissingLanguage;
259+
260+
/// Builder state after a [`SourceCodeBuilder`] has a language.
261+
#[cfg(feature = "runtime")]
262+
#[cfg_attr(docsrs, doc(cfg(feature = "runtime")))]
263+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
264+
pub struct SourceCodeBuilderWithLanguage {
265+
language: Language,
238266
}
239267

240268
#[cfg(feature = "runtime")]
@@ -257,6 +285,7 @@ impl SourceCode {
257285
pub fn builder(source: impl ToString) -> SourceCodeBuilder {
258286
SourceCodeBuilder {
259287
source: source.to_string(),
288+
state: SourceCodeBuilderMissingLanguage,
260289
}
261290
}
262291

@@ -294,10 +323,38 @@ impl SourceCode {
294323

295324
#[cfg(feature = "runtime")]
296325
#[cfg_attr(docsrs, doc(cfg(feature = "runtime")))]
297-
impl SourceCodeBuilder {
298-
/// Finish the builder with an explicit language.
299-
pub fn with_language(self, language: Language) -> SourceCode {
300-
SourceCode::new(language, self.source)
326+
impl SourceCodeBuilder<SourceCodeBuilderMissingLanguage> {
327+
/// Set the language that will be used to highlight this source.
328+
pub fn with_language(
329+
self,
330+
language: Language,
331+
) -> SourceCodeBuilder<SourceCodeBuilderWithLanguage> {
332+
SourceCodeBuilder {
333+
source: self.source,
334+
state: SourceCodeBuilderWithLanguage { language },
335+
}
336+
}
337+
338+
/// Finish the builder, detecting the language from the source text.
339+
#[cfg(feature = "detection")]
340+
#[cfg_attr(docsrs, doc(cfg(feature = "detection")))]
341+
pub fn build(self) -> SourceCode {
342+
SourceCode::new(Language::Auto, self.source)
343+
}
344+
}
345+
346+
#[cfg(feature = "runtime")]
347+
#[cfg_attr(docsrs, doc(cfg(feature = "runtime")))]
348+
impl SourceCodeBuilder<SourceCodeBuilderWithLanguage> {
349+
/// Replace the language that will be used to highlight this source.
350+
pub fn with_language(mut self, language: Language) -> Self {
351+
self.state.language = language;
352+
self
353+
}
354+
355+
/// Finish the builder.
356+
pub fn build(self) -> SourceCode {
357+
SourceCode::new(self.state.language, self.source)
301358
}
302359
}
303360

@@ -501,6 +558,25 @@ mod tests {
501558
}));
502559
}
503560

561+
#[cfg(feature = "runtime")]
562+
#[test]
563+
fn source_code_builder_builds_after_language_is_set() {
564+
let tree: advanced::HighlightedSource = SourceCode::builder("fn main() {}")
565+
.with_language(Language::Rust)
566+
.build()
567+
.into();
568+
assert_eq!(tree.language(), Language::Rust);
569+
assert_eq!(tree.source(), "fn main() {}");
570+
}
571+
572+
#[cfg(feature = "detection")]
573+
#[test]
574+
fn source_code_builder_can_detect_language_when_enabled() {
575+
let tree: advanced::HighlightedSource = SourceCode::builder("fn main() {}").build().into();
576+
assert_eq!(tree.language(), Language::Rust);
577+
assert_eq!(tree.source(), "fn main() {}");
578+
}
579+
504580
#[cfg(feature = "macro")]
505581
#[test]
506582
fn code_str_macro_highlights_inline_source() {

0 commit comments

Comments
 (0)