diff options
| author | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
|---|---|---|
| committer | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
| commit | 37da2899f40661e3e9631e497da8dc59b971cbd0 (patch) | |
| tree | cbc6d4680e347d906f5fa7fca73214418741df72 /appl/ebook/cssparser.b | |
| parent | 54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff) | |
20060303a
Diffstat (limited to 'appl/ebook/cssparser.b')
| -rw-r--r-- | appl/ebook/cssparser.b | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/appl/ebook/cssparser.b b/appl/ebook/cssparser.b new file mode 100644 index 00000000..13c78597 --- /dev/null +++ b/appl/ebook/cssparser.b @@ -0,0 +1,143 @@ +implement CSSparser; + +include "sys.m"; + sys: Sys; +include "string.m"; + str: String; +include "css.m"; + css: CSS; + Stylesheet, Statement, Select, Value: import css; +include "cssparser.m"; + +init() +{ + sys = load Sys Sys->PATH; + str = load String String->PATH; + css = load CSS CSS->PATH; + if (css == nil) { + sys->fprint(sys->fildes(2), "cssparser: cannot load %s: %r\n", CSS->PATH); + raise "fail:bad module"; + } + css->init(1); +} + +parse(s: string): list of (string, list of Decl) +{ + (stylesheet, e) := css->parse(s); + if (stylesheet == nil) { + warning("error parsing stylesheet: " + e); + return nil; + } + rules, r: list of (string, list of Decl); + for (stl := stylesheet.statements; stl != nil; stl = tl stl) { + pick st := hd stl { + Ruleset => + rules = ruleset2rule(st, rules); + } + } + for (; rules != nil; rules = tl rules) + r = hd rules :: r; + return r; +} + +ruleset2rule(statement: ref Statement.Ruleset, onto: list of (string, list of Decl)): list of (string, list of Decl) +{ + d := makedecls(statement.decls); + + names: list of string; + for (sels := statement.selectors; sels != nil; sels = tl sels) { + csel := hd sels; + if (len csel != 1) { + warning("context-specific selectors not allowed"); + continue; + } + (nil, l) := hd csel; + if ((name := selector2name(l)) != nil) + names = name :: names; + } + for (; names != nil; names = tl names) + onto = (hd names, d) :: onto; + + return onto; +} + +makedecls(decls: list of ref CSS->Decl): list of Decl +{ + d: list of Decl; + for (; decls != nil; decls = tl decls) { + nd: Decl; + nd.name = (hd decls).property; + nd.important = (hd decls).important; + s := ""; + for (vals := (hd decls).values; vals != nil; vals = tl vals) { + vs: string; + pick v := hd vals { + Percentage => + vs = v.value + "%"; + String or + Number or + Url or + Unicoderange => + vs = v.value; + Hexcolour => + vs = rgb2s(v.rgb); + RGB => + vs = rgb2s(v.rgb); + Ident => + vs = v.name; + Unit => + vs = v.value + v.units; + } + if (s != nil) + s[len s] = (hd vals).sep; + s += vs; + } + nd.val = s; + d = nd :: d; + } + return d; +} + +rgb2s(rgb: (int, int, int)): string +{ + (r, g, b) := rgb; + return sys->sprint("#%.2x%.2x%.2x", r, g, b); +} + +warning(s: string) +{ + sys->fprint(sys->fildes(2), "cssparser: %s\n", s); +} + +selector2name(sel: list of ref Select): string +{ + tag: string; + class: string; + pseudo: string; + + for (; sel != nil; sel = tl sel) { + pick v := hd sel { + Element => + tag = v.name; + Class => + class = "." + v.name; + Pseudo => + class = ":" + v.name; + * => + warning("unknown selector type " + string tagof(hd sel)); + } + } + return tag + class + pseudo; +} + +parsedecl(s: string): list of Decl +{ + if (s == nil) + return nil; + (d, e) := css->parsedecl(s); + if (d == nil) { + warning(e); + return nil; + } + return makedecls(d); +} |
