xref: /inferno-os/appl/ebook/cssparser.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsythimplement CSSparser;
2*37da2899SCharles.Forsyth
3*37da2899SCharles.Forsythinclude "sys.m";
4*37da2899SCharles.Forsyth	sys: Sys;
5*37da2899SCharles.Forsythinclude "string.m";
6*37da2899SCharles.Forsyth	str: String;
7*37da2899SCharles.Forsythinclude "css.m";
8*37da2899SCharles.Forsyth	css: CSS;
9*37da2899SCharles.Forsyth	Stylesheet, Statement, Select, Value: import css;
10*37da2899SCharles.Forsythinclude "cssparser.m";
11*37da2899SCharles.Forsyth
12*37da2899SCharles.Forsythinit()
13*37da2899SCharles.Forsyth{
14*37da2899SCharles.Forsyth	sys = load Sys Sys->PATH;
15*37da2899SCharles.Forsyth	str = load String String->PATH;
16*37da2899SCharles.Forsyth	css = load CSS CSS->PATH;
17*37da2899SCharles.Forsyth	if (css == nil) {
18*37da2899SCharles.Forsyth		sys->fprint(sys->fildes(2), "cssparser: cannot load %s: %r\n", CSS->PATH);
19*37da2899SCharles.Forsyth		raise "fail:bad module";
20*37da2899SCharles.Forsyth	}
21*37da2899SCharles.Forsyth	css->init(1);
22*37da2899SCharles.Forsyth}
23*37da2899SCharles.Forsyth
24*37da2899SCharles.Forsythparse(s: string): list of (string, list of Decl)
25*37da2899SCharles.Forsyth{
26*37da2899SCharles.Forsyth	(stylesheet, e) := css->parse(s);
27*37da2899SCharles.Forsyth	if (stylesheet == nil) {
28*37da2899SCharles.Forsyth		warning("error parsing stylesheet: " + e);
29*37da2899SCharles.Forsyth		return nil;
30*37da2899SCharles.Forsyth	}
31*37da2899SCharles.Forsyth	rules, r: list of (string, list of Decl);
32*37da2899SCharles.Forsyth	for (stl := stylesheet.statements; stl != nil; stl = tl stl) {
33*37da2899SCharles.Forsyth		pick st := hd stl {
34*37da2899SCharles.Forsyth		Ruleset =>
35*37da2899SCharles.Forsyth			rules = ruleset2rule(st, rules);
36*37da2899SCharles.Forsyth		}
37*37da2899SCharles.Forsyth	}
38*37da2899SCharles.Forsyth	for (; rules != nil; rules = tl rules)
39*37da2899SCharles.Forsyth		r = hd rules :: r;
40*37da2899SCharles.Forsyth	return r;
41*37da2899SCharles.Forsyth}
42*37da2899SCharles.Forsyth
43*37da2899SCharles.Forsythruleset2rule(statement: ref Statement.Ruleset, onto: list of (string, list of Decl)): list of (string, list of Decl)
44*37da2899SCharles.Forsyth{
45*37da2899SCharles.Forsyth	d := makedecls(statement.decls);
46*37da2899SCharles.Forsyth
47*37da2899SCharles.Forsyth	names: list of string;
48*37da2899SCharles.Forsyth	for (sels := statement.selectors; sels != nil; sels = tl sels) {
49*37da2899SCharles.Forsyth		csel := hd sels;
50*37da2899SCharles.Forsyth		if (len csel != 1) {
51*37da2899SCharles.Forsyth			warning("context-specific selectors not allowed");
52*37da2899SCharles.Forsyth			continue;
53*37da2899SCharles.Forsyth		}
54*37da2899SCharles.Forsyth		(nil, l) := hd csel;
55*37da2899SCharles.Forsyth		if ((name := selector2name(l)) != nil)
56*37da2899SCharles.Forsyth			names = name :: names;
57*37da2899SCharles.Forsyth	}
58*37da2899SCharles.Forsyth	for (; names != nil; names = tl names)
59*37da2899SCharles.Forsyth		onto = (hd names, d) :: onto;
60*37da2899SCharles.Forsyth
61*37da2899SCharles.Forsyth	return onto;
62*37da2899SCharles.Forsyth}
63*37da2899SCharles.Forsyth
64*37da2899SCharles.Forsythmakedecls(decls: list of ref CSS->Decl): list of Decl
65*37da2899SCharles.Forsyth{
66*37da2899SCharles.Forsyth	d: list of Decl;
67*37da2899SCharles.Forsyth	for (; decls != nil; decls = tl decls) {
68*37da2899SCharles.Forsyth		nd: Decl;
69*37da2899SCharles.Forsyth		nd.name = (hd decls).property;
70*37da2899SCharles.Forsyth		nd.important = (hd decls).important;
71*37da2899SCharles.Forsyth		s := "";
72*37da2899SCharles.Forsyth		for (vals := (hd decls).values; vals != nil; vals = tl vals) {
73*37da2899SCharles.Forsyth			vs: string;
74*37da2899SCharles.Forsyth			pick v := hd vals {
75*37da2899SCharles.Forsyth			Percentage =>
76*37da2899SCharles.Forsyth				vs = v.value + "%";
77*37da2899SCharles.Forsyth			String or
78*37da2899SCharles.Forsyth			Number or
79*37da2899SCharles.Forsyth			Url or
80*37da2899SCharles.Forsyth			Unicoderange =>
81*37da2899SCharles.Forsyth				vs = v.value;
82*37da2899SCharles.Forsyth			Hexcolour =>
83*37da2899SCharles.Forsyth				vs = rgb2s(v.rgb);
84*37da2899SCharles.Forsyth			RGB =>
85*37da2899SCharles.Forsyth				vs = rgb2s(v.rgb);
86*37da2899SCharles.Forsyth			Ident =>
87*37da2899SCharles.Forsyth				vs = v.name;
88*37da2899SCharles.Forsyth			Unit =>
89*37da2899SCharles.Forsyth				vs = v.value + v.units;
90*37da2899SCharles.Forsyth			}
91*37da2899SCharles.Forsyth			if (s != nil)
92*37da2899SCharles.Forsyth				s[len s] = (hd vals).sep;
93*37da2899SCharles.Forsyth			s += vs;
94*37da2899SCharles.Forsyth		}
95*37da2899SCharles.Forsyth		nd.val = s;
96*37da2899SCharles.Forsyth		d = nd :: d;
97*37da2899SCharles.Forsyth	}
98*37da2899SCharles.Forsyth	return d;
99*37da2899SCharles.Forsyth}
100*37da2899SCharles.Forsyth
101*37da2899SCharles.Forsythrgb2s(rgb: (int, int, int)): string
102*37da2899SCharles.Forsyth{
103*37da2899SCharles.Forsyth	(r, g, b) := rgb;
104*37da2899SCharles.Forsyth	return sys->sprint("#%.2x%.2x%.2x", r, g, b);
105*37da2899SCharles.Forsyth}
106*37da2899SCharles.Forsyth
107*37da2899SCharles.Forsythwarning(s: string)
108*37da2899SCharles.Forsyth{
109*37da2899SCharles.Forsyth	sys->fprint(sys->fildes(2), "cssparser: %s\n", s);
110*37da2899SCharles.Forsyth}
111*37da2899SCharles.Forsyth
112*37da2899SCharles.Forsythselector2name(sel: list of ref Select): string
113*37da2899SCharles.Forsyth{
114*37da2899SCharles.Forsyth	tag: string;
115*37da2899SCharles.Forsyth	class: string;
116*37da2899SCharles.Forsyth	pseudo: string;
117*37da2899SCharles.Forsyth
118*37da2899SCharles.Forsyth	for (; sel != nil; sel = tl sel) {
119*37da2899SCharles.Forsyth		pick v := hd sel {
120*37da2899SCharles.Forsyth		Element =>
121*37da2899SCharles.Forsyth			tag = v.name;
122*37da2899SCharles.Forsyth		Class =>
123*37da2899SCharles.Forsyth			class = "." + v.name;
124*37da2899SCharles.Forsyth		Pseudo =>
125*37da2899SCharles.Forsyth			class = ":" + v.name;
126*37da2899SCharles.Forsyth		* =>
127*37da2899SCharles.Forsyth			warning("unknown selector type " + string tagof(hd sel));
128*37da2899SCharles.Forsyth		}
129*37da2899SCharles.Forsyth	}
130*37da2899SCharles.Forsyth	return tag + class + pseudo;
131*37da2899SCharles.Forsyth}
132*37da2899SCharles.Forsyth
133*37da2899SCharles.Forsythparsedecl(s: string): list of Decl
134*37da2899SCharles.Forsyth{
135*37da2899SCharles.Forsyth	if (s == nil)
136*37da2899SCharles.Forsyth		return nil;
137*37da2899SCharles.Forsyth	(d, e) := css->parsedecl(s);
138*37da2899SCharles.Forsyth	if (d == nil) {
139*37da2899SCharles.Forsyth		warning(e);
140*37da2899SCharles.Forsyth		return nil;
141*37da2899SCharles.Forsyth	}
142*37da2899SCharles.Forsyth	return makedecls(d);
143*37da2899SCharles.Forsyth}
144