prog="Accessibility CSS Generator, (c) Silas S. Brown 2006-2012. Version 0.974" # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # (NB - make sure htaccess has AddType text/css css # otherwise the 'try stylesheet' script might not work on Firefox 2) pixel_sizes_to_generate = [18,20,25,30,35,40,45,50,60,75,100] colour_schemes_to_generate = [ ("yellow on black","", {"text":"yellow","background":"black", "headings":"#8080FF","link":"#00FF00", "hover":"#0000C0","visited":"#00FFFF", "bold":"#FFFF80","italic":"white","button":"#600040", "coloured":"pink", # used for text inside any FONT COLOR= markup "reset_button":"#400060", "form_disabled":"#404040", # GrayText requires CSS 2.1 "image_transparency_compromise":"#808000" # non-black and non-white background for transparent images, so at least stand a chance of seeing transparent imgs that were meant for white bkg (or black bkg) }), ("green on black","green", {"text":"#00FF00","background":"black", "headings":"#40C080","link":"#0040FF", "hover":"#400000","visited":"#00FFFF", "bold":"#80FF80","italic":"white","button":"#600040", "coloured":"#80C040", "reset_button":"#400060", "form_disabled":"#404040", "image_transparency_compromise":"#808000" }), ("white on black","WonB", {"text":"white","background":"black", "headings":"#40C090","link":"#0080FF", "hover":"#400000","visited":"#00FFFF", "bold":"yellow","italic":"#FFFF80","button":"#600040", "coloured":"#FFFF40", "reset_button":"#400060", "form_disabled":"#404040", "image_transparency_compromise":"#808080" }), ("black on linen","BonL", # LyX's background colour is "linen", 240/230/220 {"text":"black","background":"#faf0e6", "headings":"#404040","link":"#0000FF", "hover":"#80C0C0","visited":"#008020", "bold":"black","italic":"#400000","button":"#608040", "coloured":"#001040", "reset_button":"#408060", "form_disabled":"#A0A0A0", "image_transparency_compromise":"#faf0e6" }), ("black on white","BonW", # cld call this "black on bright white" (as opposed to "black on linen white") but that causes the list to take up more width {"text":"black","background":"white", "headings":"#404040","link":"#0000FF", "hover":"#80C0C0","visited":"#008020", "bold":"black","italic":"#400000","button":"#608040", "coloured":"#001040", "reset_button":"#408060", "form_disabled":"#A0A0A0", "image_transparency_compromise":"white" }), ] # DEBUGGING BY BINARY CHOP: If a complex stylesheet exhibits # a behaviour you weren't expecting (maybe due to a browser # bug but maybe not) then it might not be obvious how to fix # it. This program has a debug mode that helps you do it by # binary chop. Run like this: # python css-generate.py chop # which will generate a single debug .css file with half # the attributes disabled. Try that debug .css; if the # problem persisted, then do # python css-generate.py chop 1 # or if the problem did not persist, do # python css-generate.py chop 0 # and then try again. Then add another 1 or 0 depending on # whether or not the problem persisted the next time, e.g. # python css-generate.py chop 01 # Hopefully it will narrow down the problem to one thing. # You will see which one that is from the debug messages # it prints on standard output (these will appear instead of # the HTML index of stylesheets that is usually generated). # TODO consider forcing "display" to its normal value (not "none") # if some sites are going to use stock scripts that switch them on and # off every few seconds inadvertently making the rest of the page dance around # TODO why do some sites still hide scrollbars (e.g. MSDN) # TODO why do some sites still have iframes that obscure the text def do_one_stylesheet(pixelSize,colour,filename): outfile = open(filename,"w") smallestHeadingSize = pixelSize*5.0/6.0 largestHeadingSize = pixelSize*10.0/6.0 defaultStyle={ "font-family":"Times New Roman, times, utopia, /* charter, */ serif /* TNR is listed first for the benefit of broken Xft systems that need the MS fonts to make them look OK. Shouldn't have any effect on other systems. */", "font-size":"%.1fpx" % pixelSize, "color":colour["text"], "background":colour["background"], # background-color is handled by aliases # We have to specify more or less everything even if # it's OK by default, otherwise a web author's # stylesheet may override the default and cause a # not-so-good author/user stylesheet combination. "font-style":"normal", "font-weight":"normal", "font-variant":"normal", "font-size-adjust":"none", "background-image":"none", "letter-spacing":"normal", "line-height":"normal", "width":"auto", "height":"auto", "border-width":"0.05em", "position":"static", "visibility":"visible /* because we're forcing position to static, we must also force visibility to visible otherwise will get large gaps. Unfortunately some authors use visibility:hidden when they should be using display:none, and CSS does not provide a way of saying '[visibility=hidden] {display:none}' */", "float":"none","clear":"none", "min-height":"0px", "max-height":"none", "max-width":"none", # see comments below on "max-width" "min-width":"0px", "text-decoration":"none","text-shadow":"none", "text-align":"left /* not full justification */", "margin":"0px", "padding":"0px", "text-indent":"0px", "white-space":"normal /* don't \"nowrap\" */", "cursor":"auto", "overflow":"visible", # the default. NOT "auto" - it may put the scroll bar of a table off-screen at the bottom. If (e.g.) "pre" overflows, we want the whole window to be scrollable to see it. "filter":"none","opacity":"1","-moz-opacity":"1", "-moz-appearance":"none", "-moz-transform":"none", "-webkit-transform":"none", } # have to explicitly set for every type of element, # because wildcards don't always work and inheritance can # be overridden by author stylesheets resulting in poor # combinations. NB however we don't list ALL elements in # mostElements (see code later). mostElements="a,blockquote,caption,center,cite,code,col,colgroup,html,iframe,pre,body,div,P,input,select,option,textarea,table,tr,td,th,h1,h2,h3,h4,h5,h6,font,basefont,small,big,span,ul,ol,li,i,em,s,strike,nobr,tt,kbd,b,strong,dl,dt,dd,blink,button,address,dfn,form,marquee,fieldset,legend,listing,abbr,q,menu,dir,multicol,img,plaintext,xmp,label,sup,sub,u,var,acronym,object,embed,canvas".split(",") html5Elements = "article,aside,bdi,command,details,summary,figure,figcaption,footer,header,hgroup,mark,meter,nav,progress,section,time".split(",") # (and ruby/rt/rp/rb) mostElements += html5Elements css={} for e in mostElements: css[e]=defaultStyle.copy() # but there are some exceptions: for t in ["textarea","html","body","input"]: css[t]["overflow"] = "auto" # 'html' is there for IE7. But Firefox needs it to be 'visible'. See hack at end. # TODO previously excluded 'body' (and deleted 'body' overflow 'visible') # as it somehow disables keyboard scrolling in IE7, however do need to # set 'body' to "auto' to work around CouchDB's "overflow:none" in both # 'html' and 'body' (at least in Firefox); need to find an IE7 to re-test # (if broken, consider re-instating the delete and move body:auto to the # non-IE7 override hack at end) # del css["body"]["overflow"] # Do not set both "body" and "html" in IE7 - it disables keyboard-only scrolling! for e in ["object","embed","img"]: del css[e]["width"], css[e]["height"] # object/embed should not be forced to 'auto' as that can sometimes break Flash applications (when the Flash application is actually useful), and if img is 'auto' then that can break on some versions of IE css["textarea"]["width"]="100%" # not "auto", as that can cause Firefox to sometimes indent the textarea's contents off-screen css["frame"]={} for e in ["frame","iframe"]: css[e]["overflow"]="auto /* overrides 'scrolling=no' which can go wrong in large print */ " css["sup"]["vertical-align"] = "super /* in case authors try to do it with font size instead */" css["sub"]["vertical-align"] = "sub" css["marquee"]["-moz-binding"]="/* make sure firefox doesn't scroll marquee elements */ none" css["marquee"]["display"]="block" css["center"]["text-align"] = "center" for s in ['s','strike']: css[s]["text-decoration"]="line-through" # TODO: not sure if really want this for the 's' alias of 'strike', since some sites e.g. http://www.elgin.free-online.co.uk/qp_intro.htm (2007-10) use CSS to override its presentation into something other than strikeout # Margin exceptions: css["body"]["margin"]="/* keep away from window borders */ 1ex %.1fpx 1ex %.1fpx" % (pixelSize*5/18.0,pixelSize*5/18.0) for i in "P,multicol,listing,plaintext,xmp,pre".split(","): css[i]["margin"]="1em 0" listStuff="ul,ol,dir,menu,dl,li".split(",") for l in listStuff: css[l]["margin"]="0 1em 0 %.1fpx" % (pixelSize*10/18.0) listStuff.remove("li") for l in listStuff: for l2 in listStuff: css[l+" "+l2]={"margin":"0px"} css["blockquote"]["margin"]="1em 4em" css["blockquote[type=cite]"]={"margin":"1em 0px","padding":"1em 0px 0px 0px"} for t in ["th","td"]: css[t]["padding"]="%.1fpx" % (pixelSize/18.0,) # Don't say white-space normal on user input elements or pre # Galeon 1.25: we also have to exclude "body" and "div" for some reason # TODO: is it REALLY a good idea to leave 'div' on this list? for e in "pre,input,textarea,body,div".split(","): del css[e]["white-space"] for e in "font,code".split(","): css["pre "+e]={"white-space":"inherit"} # some mailing lists etc have "font" within "pre", and some sites have "code" within "pre" # Monospaced elements for t in "pre,code,tt,kbd,var".split(","): css[t]["font-family"]="monospace" css["spacer"]={"display":"none"} # no point in keeping the spacers now we've changed the layout so much # max-width (if supported, i.e. not IE6) can reduce left/right scrolling - # if one line's linebox needs to expand (e.g. due to a long word), then we # don't want to expand the whole block (e.g. the table cell) and all its # other line boxes. BUT: if a max-width'd TD (or even a DIV etc) does # have to overflow in a big way (e.g. due to map images), and there is # something else to the right (e.g. nested tables with rowspans), # overprinting can result, unless also using 'overflow:auto' which can # create too many nested or offscreen scrollbars. No way to say "use this # width for internal formatting, then expand to overflows for external # bounds" or "use this width if you are a leaf node with mostly text" or # whatever. Only alternative for now is to say "none" and have to # horizontally scroll. (Even "P" is not safe to set - consider a # table containing a P containing another table that overflows.) # (If set td max-width to "-moz-available" later in the stylesheet, will # cause Firefox 3 to do less overprinting than it would have done while # Firefox 2 takes the previous one and does a better job incorrectly, but # then there are still some instances of overprinting regardless of # version etc., especially on mapping sites) # (Note: On Firefox 2 (not 3), max-width works in a nice way, see Bugzilla # bug report at https://bugzilla.mozilla.org/show_bug.cgi?id=452840 - so # you may want to uncomment the following if you are particularly on Firefox 2.) # for e in mostElements: css[e]["max-width"]=("%.1fpx" % min(1200,pixelSize*470/18)) # Headings stuff: indent = 0 for h in range(6): el="h%d" % (h+1) css[el]["color"]=colour["headings"] css[el]["font-weight"]="bold" css[el]["font-family"]="helvetica, arial, verdana" size = (largestHeadingSize-h*(largestHeadingSize-smallestHeadingSize)/(6-1.0)) indent += size css[el]["font-size"]="%.1fpx" % size # ensure links in headings inherit size and family: css[el+" center"]=css[el].copy() # rather than the default for 'center' css[el+" a"]=css[el].copy() # because it's usually A NAME (in the case of HREF, the specificity of a:link should be greater) css[el+" abbr"]=css[el].copy() ; del css[el+" abbr"]["text-decoration"] css[el+" span"]=css[el].copy() css[el+" a b"]=css[el].copy() # and now (AFTER the above) set margins on headings css[el]["margin"]="0px 0px 0px %.1fpx" % indent # Links stuff: for linkInside in ",font,big,small,basefont,br,b,i,u,em,strong,abbr,span,code,tt,kbd,var,acronym,h1,h2,h3,h4,h5,h6".split(","): for type in [":link",":visited","[onclick]"]: css["a"+type+" "+linkInside]={"color":colour["link"],"text-decoration":"underline","cursor":"pointer"} css["a"+type+":hover "+linkInside]={"background":colour["hover"]} css["a"+type+":active "+linkInside]={"color":"red","text-decoration":"underline","cursor":"pointer"} if linkInside in ["b","i","em","u","strong"] and not css[linkInside]["color"]==colour["text"]: css["a"+type+" "+linkInside]["color"]=css[linkInside]["color"] css["a:visited "+linkInside]={"color":colour["visited"],"text-decoration":"underline","cursor":"pointer"} # set cursor:pointer for links and ANYTHING inside them (including images etc). The above cursor:auto should theoretically do the right thing anyway, but it seems that some versions of Firefox need help. for linkInside in mostElements: for type in [":link",":visited","[onclick]"]: key="a"+type+" "+linkInside if not css.has_key(key): css[key]={} css[key]["cursor"]="pointer" # Italic and bold: for i in "i,em,cite,address,dfn,u".split(","): css[i]["font-family"]="helvetica, arial, verdana" css[i]["color"]=colour["italic"] for i in "b,strong".split(","): css[i]["font-weight"]="bold" css[i]["color"]=colour["bold"] css["acronym"]["color"]=colour["bold"] # Images and buttons: css["img"]["background"]=colour["image_transparency_compromise"] css["img"]["background-color"]=colour["image_transparency_compromise"] css["button"]["background"]=colour["button"] css["input[type=submit]"]={"background":colour["button"]} css["input[type=reset]"]={"background":colour["reset_button"]} for dType in ['[disabled="disabled"]','.disabled']: for f in ["select","input","textarea","button"]: css[f+dType]={"background":colour["form_disabled"]} # Separate adjacent links (CSS2+) for l in [":link",":visited","[onclick]"]: css[":not(:empty) a"+l+":before"]={"content":'"["',"color":colour["text"],"text-decoration":"none"} css[":not(:empty) a"+l+":after"]={"content":'"]"',"color":colour["text"],"text-decoration":"none"} # Avoid style overrides from :first-letter, :first-line, # :before and :after in author's CSS. However be careful # which elements you do this because of various bugs in # many versions of Mozilla's Gecko (used in Firefox etc) # that create havoc when you type into certain forms. firstLetterBugs=[ "div", # messes up textarea when enter multiple paragraphs "input","select","option","textarea","table","img", # probably best to avoid these "a" # causes problems in IE ] # TODO: old version had th:first-letter but not tr,td & no documentation of why; similar with first-line # TODO Chrome 12 bug - OL/LI:first-letter ends up being default size rather than css size (harmless if have default size set similarly anyway) firstLineBugs=[ "div", # on firefox 2 causes some google iframes to occlude page content "input","select","option","textarea","table","img", "td","th", # causes problems on Firefox 2 if there's a form inside "a" # causes problems in IE ] inheritDic={"color":"inherit","background":"inherit","letter-spacing":"inherit","font-size":"inherit","font-family":"inherit"} # (NB must say inherit, because consider things like P:first-line / A HREF... - the first-line may have higher specificity. # If IE7 seems to be getting first lines and first letters wrong, check that Ignore Document Colours is NOT set - "document" can include parts of the CSS. and try toggling high-contrast mode twice.) for e in mostElements: if not e in firstLetterBugs: css[e+":first-letter"]=inheritDic.copy() if not e in firstLineBugs: css[e+":first-line"]=inheritDic.copy() for i in map(lambda x:":not(:empty) "+e+x,[":before",":after"]): css[i]=defaultStyle.copy() del css[i]["margin"] del css[i]["padding"] # CSS 2+ markup for viewing XML+CSS pages that don't use HTML. Not perfect but should be better than nothing. xmlKey=":root:not(HTML), :root:not(HTML) :not(:empty)" # Careful not to use the universal selector, because it can mess up Mozilla's UI css[xmlKey]=defaultStyle.copy() del css[xmlKey]["text-decoration"] # because this CSS won't be able to put it back in for links (since it doesn't know which elements ARE links in arbitrary XML) # Exception to above for Mozilla scrollbars: css[":root:not(HTML) slider:not(:empty)"]={"background":"#301090"} # In many versions of firefox, a

with an