%% @author Maas-Maarten Zeeman %% @copyright 2018 Maas-Maarten Zeeman %% @doc Javascript minifier. Based on cssmin.c %% Copyright 2018 Maas-Maarten Zeeman %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. %% You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, software %% distributed under the License is distributed on an "AS IS" BASIS, %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. %% cssmin is Copyright (c) 2010 (www.ryanday.org) %% see https://github.com/soldair/cssmin -module(z_cssmin). -export([ minify/1 ]). -spec minify( binary() ) -> binary(). minify( CSS ) -> machine(CSS, <<>>). machine(<<>>, Acc) -> Acc; machine(<<$/, $*, Rest/binary>>, Acc) -> machine(skip_comment(Rest), Acc); machine(<>, Acc) when C =:= 32 orelse C =:= 10 -> machine(Rest, Acc); machine(<<$@, Rest/binary>>, Acc) -> atrule(Rest, <>); machine(Bin, Acc) -> selector(Bin, Acc). selector(<<>>, Acc) -> Acc; selector(<<$/, $*, Rest/binary>>, Acc) -> selector(skip_comment(Rest), Acc); selector(<<${, Rest/binary>>, Acc) -> block(Rest, <>); selector(<<$@, Rest/binary>>, Acc) -> atrule(Rest, <>); selector(<<10, Rest/binary>>, Acc) -> selector(Rest, Acc); selector(<<32, Rest/binary>>, Acc) -> continue_selector(skip_space(Rest), Acc); selector(<>, Acc) -> selector(Rest, <>). continue_selector(<<${, _/binary>> = Rest, Acc) -> selector(Rest, Acc); continue_selector(Rest, Acc) -> case binary:last(Acc) of 32 -> selector(Rest, Acc); _ -> selector(Rest, <>) end. atrule(<<>>, Acc) -> Acc; atrule(<<$/, $*, Rest/binary>>, Acc) -> atrule(skip_comment(Rest), Acc); atrule(<<10, Rest/binary>>, Acc) -> case Rest of <<10, _/binary>> -> machine(Rest, <>); _ -> atrule(Rest, <>) end; atrule(<<$;, Rest/binary>>, Acc) -> machine(Rest, <>); atrule(<<${, Rest/binary>>, Acc) -> block(Rest, <>); atrule(<>, Acc) -> atrule(Rest, <>). block(<<>>, Acc) -> Acc; block(<<$/, $*, Rest/binary>>, Acc) -> block(skip_comment(Rest), Acc); block(<<$}, Rest/binary>>, Acc) -> machine(Rest, <>); block(Bin, Acc) -> declaration(skip_whitespace(Bin), Acc). declaration(<<>>, Acc) -> Acc; declaration(<<$/, $*, Rest/binary>>, Acc) -> declaration(skip_comment(Rest), Acc); declaration(<<$(, Rest/binary>>, Acc) -> declaration_in_paren(Rest, <>); declaration(<<$;, Rest/binary>>, Acc) -> case skip_whitespace(Rest) of <<$}, _/binary>> = Rest1 -> block(Rest1, Acc); <<$;, _/binary>> = Rest1 -> block(Rest1, Acc); _ -> block(Rest, <>) end; declaration(<<$}, Rest/binary>>, Acc) -> machine(Rest, <>); declaration(<<32, Rest/binary>>, Acc) -> case binary:last(Acc) of 32 -> declaration(Rest, Acc); _ -> declaration(Rest, <>) end; declaration(<>, Acc) -> declaration(Rest, <>). declaration_in_paren(<<>>, Acc) -> Acc; declaration_in_paren(<<$), Rest/binary>>, Acc) -> declaration(Rest, <>); declaration_in_paren(<>, Acc) -> declaration_in_paren(Rest, <>). skip_comment(<<>>) -> <<>>; skip_comment(<<$*, $/, Rest/binary>>) -> Rest; skip_comment(<<_C, Rest/binary>>) -> skip_comment(Rest). skip_space(<<32, Rest/binary>>) -> skip_space(Rest); skip_space(Bin) -> Bin. skip_whitespace(<>) when C =:= 32 orelse C =:= 10 -> skip_whitespace(Rest); skip_whitespace(Bin) -> Bin.