Restrict mixin values and throw exception when invalid value is provided

爱⌒轻易说出口 提交于 2019-12-22 12:19:49

问题


I have the following Less mixin:

.box-sizing(@value) {
    -webkit-box-sizing: @value;
    -moz-box-sizing: @value;
    box-sizing: @value;
}

and I would like to allow only the values 'border-box' and 'content-box' as parameter, otherwise the Less engine should throw an exception. How can I achieve this? Because without this validation I can write any value to the mixin and it will work, but it will also generate invalid CSS and no one will notice that there is an error.


回答1:


As far as I know, there is no way to make the Less compiler throw an error for an invalid value like described in question. However, you can make the Less compiler not to produce any output at all when an invalid value is provided by making use of the guards feature.

In the below snippet, the mixin is invoked only when either of the two valid values are passed as input. If a different value is provided, Less compiler would find no match and hence wouldn't output anything.

.box-sizing(@value){
    & when (@value=content-box) , (@value=border-box){ /* comma is the or operator */
        -webkit-box-sizing: @value;
        -moz-box-sizing: @value;
        box-sizing: @value;
    }
}
#demo{
    .box-sizing(content-box);
}

Less also has some built-in type functions which can be used along with guards to check if a value is valid or not (like if the input is a number or is a color etc). There is also an iskeyword function but none of these would check for an invalid CSS value.


If you have a wide list of valid values then you could make use of the loops feature like below. Here, we extract each value from the array of valid values and if the input value matches one of them, we output the properties. If the input does not match any input value, nothing is output (again).

@valid-values: content-box, border-box, padding-box;
.box-sizing(@value){
    .loop-valid-values(@index) when (@index > 0){
        @valid-value: extract(@valid-values, @index);
        & when (@value= @valid-value){
            -webkit-box-sizing: @value;
            -moz-box-sizing: @value;
            box-sizing: @value;
        }
        .loop-valid-values(@index - 1);
    }
    .loop-valid-values(length(@valid-values));
}
#demo{
    .box-sizing(content-box);
}

Strictly not recommended but if you insist on making the compiler throw some exception or the other when an invalid value is provided then you could deliberately introduce an error in the not-valid-value part.

.box-sizing(@value){
    & when (@value= content-box), (@value= border-box){
        -webkit-box-sizing: @value;
        -moz-box-sizing: @value;
        box-sizing: @value;
    }
    & when not (@value= content-box), (@value= border-box){
        output: @bwahahaha; /* there is no such variable and hence when the input value is not valid, compiler will complain that variable is undefined */
    }
}
#demo{
    .box-sizing(conten-box);
}



回答2:


You can hide actual mixin implementation under another name and provide only content-box/border-box overloads for .box-sizing:

// impl.:

.box-sizing(border-box)  {.box-sizing-impl(border-box)}
.box-sizing(content-box) {.box-sizing-impl(content-box)}
.box-sizing-impl(@value) {
    -webkit-box-sizing: @value;
    -moz-box-sizing: @value;
    box-sizing: @value;
}

// usage:

usage {
    .box-sizing(content-box); // OK
    .box-sizing(content-foo); // Error: No matching definition was found for `.box-sizing(content-foo)`
}

(Unlike guards, "argument pattern matching" (aka overloading) does not silently skip if not matched).

A slightly less repetitive variant of above:

.box-sizing(@value) {
    .-(@value);
    .-(border-box)  {.ok}
    .-(content-box) {.ok}

    .ok() {
        -webkit-box-sizing: @value;
        -moz-box-sizing: @value;
        box-sizing: @value;
    }
}

The error message is less descriptive this way: No matching definition was found for '.-(content-foo)' so you may find it better to use .box-sizing_ or so instead of .-.

-

Though the idea of testing every mixin parameter and throwing errors if it does not fit is sort of strange. (Are you going to do this for every mixin you write? That's a lot of boredom...) You'd better to put some CSS validator/lint into your build-chain instead.

And the usual remark for vendor prefixing: stop writing mixins for this and use Autoprefixer.



来源:https://stackoverflow.com/questions/30556401/restrict-mixin-values-and-throw-exception-when-invalid-value-is-provided

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!