malva 0.9.0

Configurable, smart and fast CSS, SCSS, Sass and Less formatter.
Documentation
use super::super::DocGen;
use crate::{ctx::Ctx, state::State};
use raffia::{ast::*, Spanned};
use tiny_pretty::Doc;

impl<'s> DocGen<'s> for SupportsAnd<'s> {
    fn doc(&self, ctx: &Ctx<'_, 's>, state: &State) -> Doc<'s> {
        use crate::config::OperatorLineBreak;

        let mut docs = match ctx.options.operator_linebreak {
            OperatorLineBreak::Before => vec![Doc::line_or_space(), Doc::text("and"), Doc::space()],
            OperatorLineBreak::After => vec![Doc::space(), Doc::text("and"), Doc::line_or_space()],
        };
        docs.extend(ctx.end_spaced_comments(
            ctx.get_comments_between(self.keyword.span.end, self.condition.span.start),
        ));
        docs.push(self.condition.doc(ctx, state));

        Doc::list(docs).group().nest(ctx.indent_width)
    }
}

impl<'s> DocGen<'s> for SupportsCondition<'s> {
    fn doc(&self, ctx: &Ctx<'_, 's>, state: &State) -> Doc<'s> {
        Doc::list(
            self.conditions
                .iter()
                .fold(
                    (Vec::with_capacity(self.conditions.len()), self.span.start),
                    |(mut docs, pos), condition| {
                        let span = condition.span();
                        docs.extend(
                            ctx.start_spaced_comments(ctx.get_comments_between(pos, span.start)),
                        );
                        docs.push(condition.doc(ctx, state));
                        (docs, span.end)
                    },
                )
                .0,
        )
    }
}

impl<'s> DocGen<'s> for SupportsConditionKind<'s> {
    fn doc(&self, ctx: &Ctx<'_, 's>, state: &State) -> Doc<'s> {
        match self {
            SupportsConditionKind::SupportsInParens(supports_in_parens) => {
                supports_in_parens.doc(ctx, state)
            }
            SupportsConditionKind::And(and) => and.doc(ctx, state),
            SupportsConditionKind::Or(or) => or.doc(ctx, state),
            SupportsConditionKind::Not(not) => not.doc(ctx, state),
        }
    }
}

impl<'s> DocGen<'s> for SupportsDecl<'s> {
    fn doc(&self, ctx: &Ctx<'_, 's>, state: &State) -> Doc<'s> {
        Doc::text("(")
            .concat(ctx.end_spaced_comments(
                ctx.get_comments_between(self.span.start, self.decl.span.start),
            ))
            .append(self.decl.doc(ctx, state))
            .concat(
                ctx.start_spaced_comments(
                    ctx.get_comments_between(self.decl.span.end, self.span.end),
                ),
            )
            .append(Doc::text(")"))
    }
}

impl<'s> DocGen<'s> for SupportsInParens<'s> {
    fn doc(&self, ctx: &Ctx<'_, 's>, state: &State) -> Doc<'s> {
        match &self.kind {
            SupportsInParensKind::Feature(feature) => feature.doc(ctx, state),
            SupportsInParensKind::SupportsCondition(condition) => Doc::text("(")
                .concat(ctx.end_spaced_comments(
                    ctx.get_comments_between(self.span.start, condition.span.start),
                ))
                .append(condition.doc(ctx, state))
                .concat(ctx.start_spaced_comments(
                    ctx.get_comments_between(condition.span.end, self.span.end),
                ))
                .append(Doc::text(")")),
            SupportsInParensKind::Selector(selector) => Doc::text("selector(")
                .append(
                    Doc::line_or_nil()
                        .concat(ctx.end_spaced_comments(
                            ctx.get_comments_between(self.span.start, selector.span.start),
                        ))
                        .append(selector.doc(ctx, state))
                        .concat(ctx.start_spaced_comments(
                            ctx.get_comments_between(selector.span.end, self.span.end),
                        ))
                        .nest(ctx.indent_width)
                        .append(Doc::line_or_nil())
                        .group(),
                )
                .append(Doc::text(")")),
            SupportsInParensKind::Function(function) => function.doc(ctx, state),
        }
    }
}

impl<'s> DocGen<'s> for SupportsNot<'s> {
    fn doc(&self, ctx: &Ctx<'_, 's>, state: &State) -> Doc<'s> {
        use crate::config::OperatorLineBreak;

        let mut docs = match ctx.options.operator_linebreak {
            OperatorLineBreak::Before => vec![Doc::line_or_nil(), Doc::text("not"), Doc::space()],
            OperatorLineBreak::After => vec![Doc::text("not"), Doc::line_or_space()],
        };
        docs.extend(ctx.end_spaced_comments(
            ctx.get_comments_between(self.keyword.span.end, self.condition.span.start),
        ));
        docs.push(self.condition.doc(ctx, state));

        Doc::list(docs).group().nest(ctx.indent_width)
    }
}

impl<'s> DocGen<'s> for SupportsOr<'s> {
    fn doc(&self, ctx: &Ctx<'_, 's>, state: &State) -> Doc<'s> {
        use crate::config::OperatorLineBreak;

        let mut docs = match ctx.options.operator_linebreak {
            OperatorLineBreak::Before => vec![Doc::line_or_space(), Doc::text("or"), Doc::space()],
            OperatorLineBreak::After => vec![Doc::space(), Doc::text("or"), Doc::line_or_space()],
        };
        docs.extend(ctx.end_spaced_comments(
            ctx.get_comments_between(self.keyword.span.end, self.condition.span.start),
        ));
        docs.push(self.condition.doc(ctx, state));

        Doc::list(docs).group().nest(ctx.indent_width)
    }
}