Skip to main content

Plugin

Enum Plugin 

Source
pub enum Plugin<Str, ArrayStr, MapStr, MapArrayStr, ArrayMatched> {
    ListProperties(ListProperties<Str, ArrayStr, MapStr, MapArrayStr>),
    ListValues(ListValues<Str, ArrayStr, MapStr>),
    Spacing(Spacing<Str, ArrayStr, MapStr>),
    Color(Color<Str, ArrayStr, MapStr>),
    Number(Number<Str, ArrayStr, MapStr>),
    Arbitrary(Arbitrary<Str, ArrayStr, MapStr, ArrayMatched>),
    Functional(Functional<Str>),
}
Expand description

A plugin is a structure capable of generating CSS styles from a CSS selector.

Several kinds of plugins exist and define what values are accepted as selector or modifier and what CSS is generated based on the input selector. The API is designed to be fully declarative (so that plugin declarations are serializable), except for the functional kind.

Each plugin kind has a set of required parameters and a set of default parameters which can be automatically filled in Rust using the struct update syntax.

It’s common to define several plugins to handle a single utility class, and to define static plugins as constants (the default function on each plugin kind is a const fn).

After you have defined a plugin, you need to register it in the Config structure by calling Config::register_plugin.

§Simple example (defines the static values of the font-family plugin)

use encre_css::prelude::build_plugin::*;

const PLUGIN: StaticPlugin = Plugin::ListValues(ListValues {
    prop: SingleProp("font-family"),
    values: map! {
        "font-sans" => r#"ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont"#,
        "font-serif" => r#"Georgia, Cambria, "Times New Roman", Times, serif"#,
        "font-mono" => r#"Menlo, Monaco, Consolas, "Liberation Mono", monospace"#,
    },
    ..ListValues::default()
});

§More advanced example (defines the stroke-width plugin)

use encre_css::prelude::build_plugin::*;

const PLUGIN: StaticPlugin = Plugin::Number(Number {
    namespace: "stroke",
    prop: SingleProp("stroke-width"),
    template: Some(SingleProp("{}px")),
    ..Number::default()
});

// There's also a plugin sharing the same `stroke` namespace (which helps changing the
// stroke color, e.g `stroke-red-500`), so it's required to define `hints` and `matchers`
const PLUGIN_ARBITRARY: StaticPlugin = Plugin::Arbitrary(Arbitrary {
    namespace: "stroke",
    prop: SingleProp("stroke-width"),
    disambiguate: Some(ArbitraryDisambiguate {
        matched: &[CssType::Length, CssType::Percentage, CssType::LineWidth, CssType::Number],
        separation: ArbitraryDisambiguateSeparation::None,
    }),
    ..Arbitrary::default()
});

§More powerful usage

If you need to have full control over the CSS rule generated, you can use the Functional plugin kind. It allows executing a full-blown Rust function for each selector having a specific namespace. However, it’s (of course) not serializable, and thus cannot be used in, e.g a TOML configuration.

§Example

use encre_css::Config;
use encre_css::prelude::build_plugin::*;

/// Reads the `emoji` extra field of the configuration to find the replacement emoji.
fn extract_emoji_value<'a>(config: &'a Config, value: &str) -> Option<&'a str> {
    config.extra.get("emoji")
        .and_then(|r| r.as_table())
        .and_then(|r| r.get(value))
        .and_then(|r| r.as_str())
}

const PLUGIN: StaticPlugin = Plugin::Functional(Functional {
    namespace: "emoji",
    can_handle: |context| matches!(context.modifier, Modifier::Builtin {
        value,
        ..
    } if extract_emoji_value(context.config, value).is_some()),
    handle: |context| {
        // Only accept static modifiers, and dynamically fetch them from the
        // `emoji` extra field of the configuration
        if let Modifier::Builtin { value, .. } = context.modifier
        && let Some(value) = extract_emoji_value(&context.config, value) {
            generate_at_rules(context, |context| {
                generate_class(
                    context,
                    |context| {
                        context.buffer.line(format_args!("content: \"{value}\";"));
                    },
                    "",
                );
            });
        }
    },
});

Have a look at https://gitlab.com/encre-org/encre-css/tree/main/crates/encre-css/src/plugins for more examples.

§Define a plugin in TOML

Instead of defining plugins in Rust, you can also define them in encre-css’s TOML configuration (or every other language that uses a serde deserializer). The sole exception is plugins using the Functional kind which are not serializable.

To do that, you need to add a new entry in the custom_plugins list of the configuration. You can then define plugins as you would do in Rust.

§Example

[[custom_plugins]]

[custom_plugins.Number]
namespace = "stroke"
prop = "stroke-width"
template = "{}px"

[[custom_plugins]]

[custom_plugins.Arbitrary]
namespace = "stroke"
prop = "stroke-width"
hints = ["Length", "Percentage"]
matchers = [["Length", "Percentage", "LineWidth", "Number"], "None"]

§Advice

encre-css builds a trie structure based on the namespace of the plugins to optimize matching a utility class to a specific plugin, so it’s highly discouraged to leave the namespace of a plugin empty, otherwise the performances will decrease heavily.

§Release a plugin as a crate

If you want to release your custom plugins as a crate, you can export a register function taking a mutable reference to a Config structure and use the Config::register_plugin function to register them.

pub fn register(config: &mut Config) {
    config.register_plugin(&PLUGIN);
    config.register_plugin(&PLUGIN_ARBITRARY);
}

Variants§

§

ListProperties(ListProperties<Str, ArrayStr, MapStr, MapArrayStr>)

§

ListValues(ListValues<Str, ArrayStr, MapStr>)

§

Spacing(Spacing<Str, ArrayStr, MapStr>)

See Spacing.

§

Color(Color<Str, ArrayStr, MapStr>)

See Color.

§

Number(Number<Str, ArrayStr, MapStr>)

See Number.

§

Arbitrary(Arbitrary<Str, ArrayStr, MapStr, ArrayMatched>)

See Arbitrary.

§

Functional(Functional<Str>)

See Functional.

Not serializable.

Trait Implementations§

Source§

impl<Str: Clone, ArrayStr: Clone, MapStr: Clone, MapArrayStr: Clone, ArrayMatched: Clone> Clone for Plugin<Str, ArrayStr, MapStr, MapArrayStr, ArrayMatched>

Source§

fn clone(&self) -> Plugin<Str, ArrayStr, MapStr, MapArrayStr, ArrayMatched>

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<Str: Debug, ArrayStr: Debug, MapStr: Debug, MapArrayStr: Debug, ArrayMatched: Debug> Debug for Plugin<Str, ArrayStr, MapStr, MapArrayStr, ArrayMatched>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'de, Str, ArrayStr, MapStr, MapArrayStr, ArrayMatched> Deserialize<'de> for Plugin<Str, ArrayStr, MapStr, MapArrayStr, ArrayMatched>
where Str: Deserialize<'de>, ArrayStr: Deserialize<'de>, MapStr: Deserialize<'de>, MapArrayStr: Deserialize<'de>, ArrayMatched: Deserialize<'de>,

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl<Str, ArrayStr, MapStr, MapArrayStr, ArrayMatched> Serialize for Plugin<Str, ArrayStr, MapStr, MapArrayStr, ArrayMatched>
where Str: Serialize, ArrayStr: Serialize, MapStr: Serialize, MapArrayStr: Serialize, ArrayMatched: Serialize,

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

§

impl<Str, ArrayStr, MapStr, MapArrayStr, ArrayMatched> Freeze for Plugin<Str, ArrayStr, MapStr, MapArrayStr, ArrayMatched>
where ListProperties<Str, ArrayStr, MapStr, MapArrayStr>: Freeze, ListValues<Str, ArrayStr, MapStr>: Freeze, Spacing<Str, ArrayStr, MapStr>: Freeze, Color<Str, ArrayStr, MapStr>: Freeze, Number<Str, ArrayStr, MapStr>: Freeze, Arbitrary<Str, ArrayStr, MapStr, ArrayMatched>: Freeze, Functional<Str>: Freeze,

§

impl<Str, ArrayStr, MapStr, MapArrayStr, ArrayMatched> RefUnwindSafe for Plugin<Str, ArrayStr, MapStr, MapArrayStr, ArrayMatched>
where ListProperties<Str, ArrayStr, MapStr, MapArrayStr>: RefUnwindSafe, ListValues<Str, ArrayStr, MapStr>: RefUnwindSafe, Spacing<Str, ArrayStr, MapStr>: RefUnwindSafe, Color<Str, ArrayStr, MapStr>: RefUnwindSafe, Number<Str, ArrayStr, MapStr>: RefUnwindSafe, Arbitrary<Str, ArrayStr, MapStr, ArrayMatched>: RefUnwindSafe, Functional<Str>: RefUnwindSafe,

§

impl<Str, ArrayStr, MapStr, MapArrayStr, ArrayMatched> Send for Plugin<Str, ArrayStr, MapStr, MapArrayStr, ArrayMatched>
where ListProperties<Str, ArrayStr, MapStr, MapArrayStr>: Send, ListValues<Str, ArrayStr, MapStr>: Send, Spacing<Str, ArrayStr, MapStr>: Send, Color<Str, ArrayStr, MapStr>: Send, Number<Str, ArrayStr, MapStr>: Send, Arbitrary<Str, ArrayStr, MapStr, ArrayMatched>: Send, Functional<Str>: Send,

§

impl<Str, ArrayStr, MapStr, MapArrayStr, ArrayMatched> Sync for Plugin<Str, ArrayStr, MapStr, MapArrayStr, ArrayMatched>
where ListProperties<Str, ArrayStr, MapStr, MapArrayStr>: Sync, ListValues<Str, ArrayStr, MapStr>: Sync, Spacing<Str, ArrayStr, MapStr>: Sync, Color<Str, ArrayStr, MapStr>: Sync, Number<Str, ArrayStr, MapStr>: Sync, Arbitrary<Str, ArrayStr, MapStr, ArrayMatched>: Sync, Functional<Str>: Sync,

§

impl<Str, ArrayStr, MapStr, MapArrayStr, ArrayMatched> Unpin for Plugin<Str, ArrayStr, MapStr, MapArrayStr, ArrayMatched>
where ListProperties<Str, ArrayStr, MapStr, MapArrayStr>: Unpin, ListValues<Str, ArrayStr, MapStr>: Unpin, Spacing<Str, ArrayStr, MapStr>: Unpin, Color<Str, ArrayStr, MapStr>: Unpin, Number<Str, ArrayStr, MapStr>: Unpin, Arbitrary<Str, ArrayStr, MapStr, ArrayMatched>: Unpin, Functional<Str>: Unpin,

§

impl<Str, ArrayStr, MapStr, MapArrayStr, ArrayMatched> UnsafeUnpin for Plugin<Str, ArrayStr, MapStr, MapArrayStr, ArrayMatched>
where ListProperties<Str, ArrayStr, MapStr, MapArrayStr>: UnsafeUnpin, ListValues<Str, ArrayStr, MapStr>: UnsafeUnpin, Spacing<Str, ArrayStr, MapStr>: UnsafeUnpin, Color<Str, ArrayStr, MapStr>: UnsafeUnpin, Number<Str, ArrayStr, MapStr>: UnsafeUnpin, Arbitrary<Str, ArrayStr, MapStr, ArrayMatched>: UnsafeUnpin, Functional<Str>: UnsafeUnpin,

§

impl<Str, ArrayStr, MapStr, MapArrayStr, ArrayMatched> UnwindSafe for Plugin<Str, ArrayStr, MapStr, MapArrayStr, ArrayMatched>
where ListProperties<Str, ArrayStr, MapStr, MapArrayStr>: UnwindSafe, ListValues<Str, ArrayStr, MapStr>: UnwindSafe, Spacing<Str, ArrayStr, MapStr>: UnwindSafe, Color<Str, ArrayStr, MapStr>: UnwindSafe, Number<Str, ArrayStr, MapStr>: UnwindSafe, Arbitrary<Str, ArrayStr, MapStr, ArrayMatched>: UnwindSafe, Functional<Str>: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.