1:- module(tailwind_generate, [text_tw_css/2,
2 tw_from_file/2]).
10:- use_module(library(apply_macros)). 11:- use_module(library(apply), [maplist/2, convlist/3]). 12:- use_module(library(pcre), [re_replace/4]). 13:- use_module(library(ordsets), [list_to_ord_set/2]). 14:- use_module(library(yall)). 15
16:- use_module(tailwind_generate/grammar, [tailwind//1, prefixes//2]). 17
18tw_selector(Media, Variants, Styles) -->
19 prefixes(Media, Variants), tailwind(Styles).
20
21word_style(Word, Style) :-
22 string_codes(Word, Codes),
23 re_replace("([^-a-zA-Z0-9])"/g, "\\$1", Word, EscapedWord),
24 format(atom(Sel), ".~w", [EscapedWord]),
25 phrase(tw_selector(Media, Variants, Styles), Codes),
26 ( is_list(Styles)
27 -> partition(['@keyframes'(_, _)]>>true, Styles, Anims, Styles0)
28 ; ( Anims = [], Styles0 = Styles) ),
29 make_style(Sel, Media, Variants, Styles0, Style_),
30 ( Anims == []
31 -> Style = Style_
32 ; Style = [Style_|Anims]).
33
34apply_inner(BaseSel, [], BaseSel) :- !.
35apply_inner(BaseSel, Inners, Selector) :-
36 maplist([inner(Attr), Attr]>>true, Inners, Attrs),
37 atomic_list_concat(Attrs, ':', PseudoClasses),
38 format(atom(Selector), "~w:~w", [BaseSel, PseudoClasses]).
39
40wrap_outers(BaseSel, [], BaseSel) :- !.
41wrap_outers(BaseSel, Outers, Selector) :-
42 maplist([outer(Sel), Sel]>>true, Outers, OuterSels),
43 44 atomic_list_concat(OuterSels, '', OuterSel),
45 format(atom(Selector), "~w ~w", [OuterSel, BaseSel]).
46
47make_style(ClsName, [], [], &(ChildSel), Style) :- !,
48 Style =.. [ClsName, [], ChildSel].
49make_style(ClsName, [], [], Styles, Style) :- !,
50 Style =.. [ClsName, Styles].
51make_style(ClsName, [], Variants, Styles, Css) :- !,
52 partition([outer(_)]>>true, Variants, Outers, Inners),
53 apply_inner(ClsName, Inners, InnerSelector),
54 wrap_outers(InnerSelector, Outers, Selector),
55 make_style(Selector, [], [], Styles, Css).
56make_style(ClsName, Media, Variants, Styles, '@media'(and(Media), NestedStyle)) :-
57 make_style(ClsName, [], Variants, Styles, NestedStyle).
65text_tw_css(Text, Css) :-
66 text_to_string(Text, String),
67 split_string(String, " ", "", Strs),
68 convlist(word_style, Strs, Css0),
69 merge_keyframe_styles(Css0, Css, []).
70
71merge_keyframe_styles([], Tail, Tail) :- !.
72merge_keyframe_styles([C|Cs], Tail0, Tail) :-
73 is_list(C), !,
74 append(C, Tail1, Tail0),
75 merge_keyframe_styles(Cs, Tail1, Tail).
76merge_keyframe_styles([C|Cs], [C|Tail0], Tail) :-
77 merge_keyframe_styles(Cs, Tail0, Tail).
78
82read_file_to_terms_noqq(File, Terms) :-
83 setup_call_cleanup(
84 open(File, read, Stream),
85 read_stream_to_terms_noqq(Stream, Terms),
86 close(Stream)
87 ).
88
89read_stream_to_terms_noqq(Stream, Terms) :-
90 read_term(Stream, C0, [quasi_quotations(_), syntax_errors(quiet)]),
91 read_stream_to_terms_noqq(C0, Stream, Terms).
92
93read_stream_to_terms_noqq(end_of_file, _, []) :- !.
94read_stream_to_terms_noqq(C, Stream, [C|Ts]) :-
95 read_term(Stream, C2, [quasi_quotations(_), syntax_errors(quiet)]),
96 read_stream_to_terms_noqq(C2, Stream, Ts).
97
98text_from_file(File, UniqTexts) :-
99 read_file_to_terms_noqq(File, Terms), !,
100 extract_text_from_terms(Terms, Texts, []),
101 list_to_ord_set(Texts, UniqTexts).
102text_from_file(_, []).
103
104extract_text_from_terms([], Tail, Tail1) => Tail = Tail1.
105extract_text_from_terms([Term|Terms], Tail, Tail0), string(Term) =>
106 Tail = [Term|NewTail],
107 extract_text_from_terms(Terms, NewTail, Tail0).
108extract_text_from_terms([Term|Terms], Tail, Tail0), atom(Term) =>
109 Tail = [Term|NewTail],
110 extract_text_from_terms(Terms, NewTail, Tail0).
111extract_text_from_terms([Term|Terms], Tail, Tail0), is_list(Term) =>
112 extract_text_from_terms(Term, Tail, NewTail),
113 extract_text_from_terms(Terms, NewTail, Tail0).
114extract_text_from_terms([Term|Terms], Tail, Tail0), compound(Term) =>
115 Term =.. [_|Children],
116 extract_text_from_terms(Children, Tail, NewTail),
117 extract_text_from_terms(Terms, NewTail, Tail0).
([_|Terms], Tail, Tail0) =>
119 extract_text_from_terms(Terms, Tail, Tail0).
127tw_from_file(File, Css) :-
128 text_from_file(File, Texts),
129 all_tws_from(Texts, Css).
130
131all_tws_from(Text, Css) :-
132 all_tws_from(Text, Css-Css, _-[]).
133
134all_tws_from([], List-Tail, List-Tail) :- !.
135all_tws_from([Text|Texts], Csses-Tail0, Csses-Tail) :-
136 text_tw_css(Text, Css),
137 append(Css, Tail1, Tail0),
138 all_tws_from(Texts, Csses-Tail1, Csses-Tail)
generate CSS from text containing selectors
Predicates for generating tailwind CSS stylesheets based on used selectors