wehjit is a Python library
for building XHTML widgets for web applications and web pages. It
encapusaltes the XML (a Genshi
template), CSS, and JavaScript for each widget into a plugin. A
tutorial plus full API documentation is available here.
wehjit has some unique features in how it handless CSS.
When you create an application (a collection of pages),
wehjit will render a single CSS file containing the styles
for all the widget plugins that your application uses. Each widget
plugin typically provides some default style, but you can override any
of this default style via a simple
JSON-encoded
configuration file. Even with overrides, a single CSS file is rendered.
The details are best explained with an example. The table below contains the exact style information used by these demo pages. The left column contains the total style definition in JavaScript Object Notation (JSON). The right column contains the same style information rendered as CSS.
| Style config dumped to JSON | Rendered CSS |
|---|---|
{ "styles": { "": { ".hide": { "display": "none !important" }, ".numeric": { "text-align": "right" }, "body": { "background-color": "%(colorbg)s", "color": "%(color)s", "font-family": "%(font_family)s", "font-size": "%(font_size)s" }, "code": { "background-color": "%(colorbg_code)s", "padding": "1px" }, "code, pre": { "font-family": "monospace", "font-size": "%(font_size_mono)s" }, "input, select, option, textarea, button": { "font-family": "monospace", "font-size": "%(font_size_mono)s", "line-height": "%(height_bar)s" }, "label.associate": { "-moz-appearance": "button", "display": "inline-block", "padding": "0.1em 0.2em" } }, "Actions": { "": { "height": "100%%", "text-align": "right" }, "button": { "margin": "0 0.25em" }, "input": { "border": "none", "margin": "0 0.25em", "padding": "%(padding_input)s" }, "label": { "margin": "0 0.25em" } }, "Dialog": { "": { "background-color": "#fff", "bottom": "1em", "left": "1em", "position": "fixed", "right": "1em", "top": "1em", "z-index": "100" }, "div.bar": { "background": "%(colorbg_bar)s", "color": "%(color_bar)s", "height": "%(height_bar)s", "left": "0", "line-height": "%(height_bar)s", "position": "absolute", "right": "0", "top": "0" }, "div.bar button": { "margin": "0 0.5em" }, "div.bar label": { "margin": "0 0.5em" }, "div.center": { "float": "left", "font-weight": "bold", "text-align": "center", "width": "33%%" }, "div.left": { "float": "left", "width": "33%%" }, "div.message p": { "-moz-border-radius": "100%%", "background-color": "%(colorbg_dialog_message)s", "border-color": "%(colorborder_dialog_summary)s", "border-style": "solid", "border-width": "2px", "font-weight": "bold", "margin": "1em 2em", "padding": "0.5em", "text-align": "center" }, "div.message p.error": { "border-color": "%(colorborder_dialog_error)s", "color": "%(color_error)s" }, "div.right": { "text-align": "right" }, "div.view": { "bottom": "0", "left": "0", "overflow": "auto", "position": "absolute", "right": "0", "text-align": "center", "top": "%(height_bar)s" } }, "DialogSet": { "div.overlay": { "background-color": "#000", "bottom": "0", "left": "0", "opacity": "0.5", "position": "fixed", "right": "0", "top": "0", "z-index": "100" } }, "Display": { "": { "border-collapse": "collapse", "empty-cells": "show", "margin": "1em 2em" }, "td": { "line-height": "%(height_bar)s", "padding": "0.25em 0.5em", "text-align": "left", "vertical-align": "top" }, "th": { "line-height": "%(height_bar)s", "padding": "0.25em 0.5em", "text-align": "right", "vertical-align": "top" }, "tr.error": { "background-color": "#ddd" } }, "FieldTable": { "": { "border-collapse": "collapse", "empty-cells": "show", "margin": "1em 2em" }, "td": { "padding": "0.25em 0.5em", "text-align": "left", "vertical-align": "top" }, "td.error": { "color": "%(color_error)s" }, "th": { "font-weight": "normal", "line-height": "%(height_bar)s", "padding": "0.25em 0.5em", "text-align": "right", "vertical-align": "top" }, "tr.error": { "background-color": "#ddd" }, "tr.required th": { "font-weight": "bold" } }, "Fieldset": { "": { "-moz-border-radius": "0.75em", "border": "2px solid %(colorborder_fieldset)s", "margin": "2em 0", "width": "%(width_content)s" }, "> legend": { "background-color": "%(colorbg_legend)s", "border": "inherit", "color": "%(color_legend)s", "font-weight": "bold", "letter-spacing": "0.15em", "padding": "0 0.5em", "word-spacing": "0.25em" } }, "Grid": { "": { "bottom": "0", "left": "0", "position": "fixed", "right": "0", "top": "2em" }, "div.message": { "font-weight": "bold", "height": "%(height_bar)s", "line-height": "%(height_bar)s", "text-align": "center" }, "div.message.error": { "color": "%(color_error)s !important" }, "span.arrow": { "font-size": "12pt", "visibility": "hidden" }, "table": { "border-collapse": "separate", "border-spacing": "2px", "bottom": "0", "cursor": "default", "display": "block", "empty-cells": "show", "font-family": "monospace", "font-size": "%(font_size_mono)s", "left": "0", "overflow-x": "auto", "overflow-y": "hidden", "position": "absolute", "right": "0", "top": "2em", "white-space": "nowrap" }, "tbody": { "overflow-x": "hidden", "overflow-y": "auto" }, "tbody tr": { "background-color": "%(colorbg_grid_tr)s" }, "tbody tr.selected": { "background-color": "%(colorbg_grid_tr_selected)s !important" }, "tbody tr:hover": { "background-color": "%(colorbg_grid_tr_hover)s" }, "td": { "padding": "0 0.5em" }, "th": { "color": "#fff", "padding": "0 0.5em", "text-align": "left" }, "th.sort": { "color": "yellow" }, "th.sort span.arrow": { "visibility": "visible" }, "th.sortable:hover": { "background-color": "%(colorbg_grid_th_hover)s" }, "th.space": { "width": "100%%" }, "thead": { "background-color": "%(colorbg_grid_th)s" }, "thead input": { "border": "0" }, "tr": { "line-height": "2em" } }, "H1": { "": { "font-size": "1.5em", "margin": "0.25em 0" } }, "HighlighterLexers": { "": { "font-family": "monospace", "font-size": "%(font_size_mono)s" }, "h2": { "font-family": "monospace", "font-weight": "normal", "margin-bottom": "0", "margin-top": "1.5em" }, "h2 a": { "color": "inherit", "text-decoration": "none" }, "h2 a:hover": { "background-color": "#eee" }, "h2:target": { "color": "#e02" }, "pre": { "margin": "0" }, "td": { "padding": "0.5em 1em", "vertical-align": "top" }, "th": { "padding": "0.5em 1em", "text-align": "right", "vertical-align": "top" }, "tr": { "background-color": "#eee" }, "tr.even": { "background-color": "#ddd" } }, "Menu": { "": { "color": "%(color_bar)s", "cursor": "default", "margin": "0", "padding": "0" }, ":hover": { "background-color": "%(colorbg_hover_menu)s" }, "> span": { "color": "%(color_bar)s", "display": "block", "line-height": "%(height_bar)s", "padding": "%(padding_menu)s", "text-decoration": "none", "white-space": "nowrap" }, "> ul": { "-moz-box-shadow": "black 0.5em 0.5em 0.5em", "background-color": "%(colorbg_bar)s", "border-color": "%(colorborder_menu)s", "border-style": "solid", "border-width": "1px", "list-style-type": "none", "margin": "0", "padding": "0", "position": "fixed", "z-index": "60" } }, "MenuItem": { "": { "color": "%(color_bar)s", "cursor": "default", "margin": "0", "padding": "0" }, ":hover > a": { "background": "%(colorbg_hover_menu)s" }, "a": { "color": "%(color_bar)s", "display": "block", "line-height": "%(height_bar)s", "padding": "%(padding_menu)s", "text-decoration": "none", "white-space": "nowrap" }, "a.target": { "background-color": "%(colorbg_target_menu)s" } }, "MenuSet": { "": { "float": "left", "list-style-type": "none", "margin": "0", "padding": "0" }, "> li": { "float": "left" } }, "PasswordRow": { "input": { "padding": "%(padding_input)s" } }, "PluginDetails": { "": { "font-family": "monospace", "font-size": "%(font_size_mono)s" }, "h2": { "font-family": "monospace", "font-weight": "normal", "margin-bottom": "0", "margin-top": "1.5em" }, "h2 a": { "color": "inherit", "text-decoration": "none" }, "h2 a:hover": { "background-color": "#eee" }, "h2:target": { "color": "#e02" }, "pre": { "margin": "0" }, "td": { "padding": "0.5em 1em", "vertical-align": "top" }, "th": { "padding": "0.5em 1em", "text-align": "right", "vertical-align": "top" }, "tr": { "background-color": "#eee" }, "tr.even": { "background-color": "#ddd" } }, "TextAreaRow": { "textarea": { "padding": "%(padding_input)s" } }, "TextRow": { "input": { "padding": "%(padding_input)s" } }, "TopBar": { "": { "background": "-moz-linear-gradient(top, %(colorbg_bar_top)s, %(colorbg_bar)s)", "background-color": "%(colorbg_bar)s", "color": "%(color_bar)s", "height": "%(height_bar)s", "left": "0", "line-height": "%(height_bar)s", "position": "fixed", "right": "0", "top": "0", "z-index": "50" } }, "View": { "": { "bottom": "0", "left": "0", "overflow": "auto", "padding": "0 1em", "position": "fixed", "right": "0", "top": "%(height_bar)s" } }, "Welcome": { "": { "width": "%(width_content)s" }, "table": { "border-collapse": "separate", "border-spacing": "2px" }, "td": { "background-color": "#eee", "padding": "0.5em", "vertical-align": "top" }, "th": { "background-color": "#ddd", "padding": "0.5em" } } }, "vars": { "color": "#000", "color_bar": "#fff", "color_error": "#d02", "color_legend": "#fff", "colorbg": "#fff", "colorbg_bar": "#446", "colorbg_bar_top": "#5b5b7e", "colorbg_code": "#eee", "colorbg_dialog_message": "#eee", "colorbg_grid_th": "#777", "colorbg_grid_th_hover": "#977", "colorbg_grid_tr": "#eee", "colorbg_grid_tr_hover": "#ddd", "colorbg_grid_tr_selected": "#ddf", "colorbg_hover_menu": "#669", "colorbg_legend": "#966", "colorbg_target_menu": "#966", "colorborder_dialog_error": "#b55", "colorborder_dialog_summary": "#595", "colorborder_fieldset": "#966", "colorborder_menu": "#000", "font_family": "sans-serif", "font_size": "11pt", "font_size_mono": "10pt", "height_bar": "2em", "padding_input": "2px", "padding_menu": "0 0.5em", "width_content": "50em" } } |
/* ---- [GLOBAL] ---- */ .hide { display: none !important; } .numeric { text-align: right; } body { background-color: #fff; color: #000; font-family: sans-serif; font-size: 11pt; } code { background-color: #eee; padding: 1px; } code, pre { font-family: monospace; font-size: 10pt; } input, select, option, textarea, button { font-family: monospace; font-size: 10pt; line-height: 2em; } label.associate { -moz-appearance: button; display: inline-block; padding: 0.1em 0.2em; } /* ---- Actions ---- */ div.Actions { height: 100%; text-align: right; } div.Actions button { margin: 0 0.25em; } div.Actions input { border: none; margin: 0 0.25em; padding: 2px; } div.Actions label { margin: 0 0.25em; } /* ---- Dialog ---- */ div.Dialog { background-color: #fff; bottom: 1em; left: 1em; position: fixed; right: 1em; top: 1em; z-index: 100; } div.Dialog div.bar { background: #446; color: #fff; height: 2em; left: 0; line-height: 2em; position: absolute; right: 0; top: 0; } div.Dialog div.bar button { margin: 0 0.5em; } div.Dialog div.bar label { margin: 0 0.5em; } div.Dialog div.center { float: left; font-weight: bold; text-align: center; width: 33%; } div.Dialog div.left { float: left; width: 33%; } div.Dialog div.message p { -moz-border-radius: 100%; background-color: #eee; border-color: #595; border-style: solid; border-width: 2px; font-weight: bold; margin: 1em 2em; padding: 0.5em; text-align: center; } div.Dialog div.message p.error { border-color: #b55; color: #d02; } div.Dialog div.right { text-align: right; } div.Dialog div.view { bottom: 0; left: 0; overflow: auto; position: absolute; right: 0; text-align: center; top: 2em; } /* ---- DialogSet ---- */ div.DialogSet div.overlay { background-color: #000; bottom: 0; left: 0; opacity: 0.5; position: fixed; right: 0; top: 0; z-index: 100; } /* ---- Display ---- */ table.Display { border-collapse: collapse; empty-cells: show; margin: 1em 2em; } table.Display td { line-height: 2em; padding: 0.25em 0.5em; text-align: left; vertical-align: top; } table.Display th { line-height: 2em; padding: 0.25em 0.5em; text-align: right; vertical-align: top; } table.Display tr.error { background-color: #ddd; } /* ---- FieldTable ---- */ table.FieldTable { border-collapse: collapse; empty-cells: show; margin: 1em 2em; } table.FieldTable td { padding: 0.25em 0.5em; text-align: left; vertical-align: top; } table.FieldTable td.error { color: #d02; } table.FieldTable th { font-weight: normal; line-height: 2em; padding: 0.25em 0.5em; text-align: right; vertical-align: top; } table.FieldTable tr.error { background-color: #ddd; } table.FieldTable tr.required th { font-weight: bold; } /* ---- Fieldset ---- */ fieldset.Fieldset { -moz-border-radius: 0.75em; border: 2px solid #966; margin: 2em 0; width: 50em; } fieldset.Fieldset > legend { background-color: #966; border: inherit; color: #fff; font-weight: bold; letter-spacing: 0.15em; padding: 0 0.5em; word-spacing: 0.25em; } /* ---- Grid ---- */ div.Grid { bottom: 0; left: 0; position: fixed; right: 0; top: 2em; } div.Grid div.message { font-weight: bold; height: 2em; line-height: 2em; text-align: center; } div.Grid div.message.error { color: #d02 !important; } div.Grid span.arrow { font-size: 12pt; visibility: hidden; } div.Grid table { border-collapse: separate; border-spacing: 2px; bottom: 0; cursor: default; display: block; empty-cells: show; font-family: monospace; font-size: 10pt; left: 0; overflow-x: auto; overflow-y: hidden; position: absolute; right: 0; top: 2em; white-space: nowrap; } div.Grid tbody { overflow-x: hidden; overflow-y: auto; } div.Grid tbody tr { background-color: #eee; } div.Grid tbody tr.selected { background-color: #ddf !important; } div.Grid tbody tr:hover { background-color: #ddd; } div.Grid td { padding: 0 0.5em; } div.Grid th { color: #fff; padding: 0 0.5em; text-align: left; } div.Grid th.sort { color: yellow; } div.Grid th.sort span.arrow { visibility: visible; } div.Grid th.sortable:hover { background-color: #977; } div.Grid th.space { width: 100%; } div.Grid thead { background-color: #777; } div.Grid thead input { border: 0; } div.Grid tr { line-height: 2em; } /* ---- H1 ---- */ h1.H1 { font-size: 1.5em; margin: 0.25em 0; } /* ---- HighlighterLexers ---- */ div.HighlighterLexers { font-family: monospace; font-size: 10pt; } div.HighlighterLexers h2 { font-family: monospace; font-weight: normal; margin-bottom: 0; margin-top: 1.5em; } div.HighlighterLexers h2 a { color: inherit; text-decoration: none; } div.HighlighterLexers h2 a:hover { background-color: #eee; } div.HighlighterLexers h2:target { color: #e02; } div.HighlighterLexers pre { margin: 0; } div.HighlighterLexers td { padding: 0.5em 1em; vertical-align: top; } div.HighlighterLexers th { padding: 0.5em 1em; text-align: right; vertical-align: top; } div.HighlighterLexers tr { background-color: #eee; } div.HighlighterLexers tr.even { background-color: #ddd; } /* ---- Menu ---- */ li.Menu { color: #fff; cursor: default; margin: 0; padding: 0; } li.Menu:hover { background-color: #669; } li.Menu > span { color: #fff; display: block; line-height: 2em; padding: 0 0.5em; text-decoration: none; white-space: nowrap; } li.Menu > ul { -moz-box-shadow: black 0.5em 0.5em 0.5em; background-color: #446; border-color: #000; border-style: solid; border-width: 1px; list-style-type: none; margin: 0; padding: 0; position: fixed; z-index: 60; } /* ---- MenuItem ---- */ li.MenuItem { color: #fff; cursor: default; margin: 0; padding: 0; } li.MenuItem:hover > a { background: #669; } li.MenuItem a { color: #fff; display: block; line-height: 2em; padding: 0 0.5em; text-decoration: none; white-space: nowrap; } li.MenuItem a.target { background-color: #966; } /* ---- MenuSet ---- */ ul.MenuSet { float: left; list-style-type: none; margin: 0; padding: 0; } ul.MenuSet > li { float: left; } /* ---- PasswordRow ---- */ tr.PasswordRow input { padding: 2px; } /* ---- PluginDetails ---- */ div.PluginDetails { font-family: monospace; font-size: 10pt; } div.PluginDetails h2 { font-family: monospace; font-weight: normal; margin-bottom: 0; margin-top: 1.5em; } div.PluginDetails h2 a { color: inherit; text-decoration: none; } div.PluginDetails h2 a:hover { background-color: #eee; } div.PluginDetails h2:target { color: #e02; } div.PluginDetails pre { margin: 0; } div.PluginDetails td { padding: 0.5em 1em; vertical-align: top; } div.PluginDetails th { padding: 0.5em 1em; text-align: right; vertical-align: top; } div.PluginDetails tr { background-color: #eee; } div.PluginDetails tr.even { background-color: #ddd; } /* ---- TextAreaRow ---- */ tr.TextAreaRow textarea { padding: 2px; } /* ---- TextRow ---- */ tr.TextRow input { padding: 2px; } /* ---- TopBar ---- */ div.TopBar { background: -moz-linear-gradient(top, #5b5b7e, #446); background-color: #446; color: #fff; height: 2em; left: 0; line-height: 2em; position: fixed; right: 0; top: 0; z-index: 50; } /* ---- View ---- */ div.View { bottom: 0; left: 0; overflow: auto; padding: 0 1em; position: fixed; right: 0; top: 2em; } /* ---- Welcome ---- */ div.Welcome { width: 50em; } div.Welcome table { border-collapse: separate; border-spacing: 2px; } div.Welcome td { background-color: #eee; padding: 0.5em; vertical-align: top; } div.Welcome th { background-color: #ddd; padding: 0.5em; } |