package folioxml.css; import folioxml.core.InvalidMarkupException; import folioxml.slx.SlxRecord; import folioxml.slx.SlxToken; /** * Operates on SLX valid only (that has been CssClassCleaner proccessed inside SlxTransformer) * * @author nathanael */ public class StylesheetBuilder { private SlxRecord root = null; public StylesheetBuilder(SlxRecord root) { this.root = root; } public static final String DEFAULT_FONT_SIZE = "12pt"; private void getDefaultCss(String applySelector, StringBuilder sb) { sb.append("a.folio_pagination_link {display:block; margin:1em;}\n"); sb.append(applySelector + "td p:first {margin:0 0 0 0;}\n"); //The first P tag shouldn't have margins... sb.append(applySelector + "th p:first {margin:0 0 0 0;}\n"); //The first P tag shouldn't have margins... sb.append(applySelector + "p {margin:0; margin-top:0.2em;} p._empty{ padding-top:1em; }\n"); //Empty paragraphs get padding to mimic folio model. //Set the default font size and face. Folio uses TimesNewRoman 12 //white-space-collapse: preserve; - Tries to maintain compatibility with Folio's treatment of whitespace. //font-weight: bolder; text-align: center // margin:30px; sb.append(applySelector.length() == 0 ? "body" : applySelector + " {font-family: \"Times New Roman\"; font-size:" + DEFAULT_FONT_SIZE + "; line-height:1.0em; white-space-collapse: preserve; white-space:pre-wrap;}\n"); sb.append(applySelector + "th {font-weight:auto;text-align:auto;}\n"); //Reset to act like td - what is folio behavior? //Add faux-tabulation rules. Remove width restriction since faux-tabs can make it bigger. sb.append(applySelector + "p.faux_tabulation {white-space: pre-wrap; white-space-collapse: preserve; font-family: \"Courier New\", monospace; width:auto !important; }\n"); } public String getCss(String applySelector, boolean selectorIsRecordDiv) throws InvalidMarkupException { StringBuilder sb = new StringBuilder(); if (applySelector == null) applySelector = ""; if (applySelector.length() > 0 && !applySelector.endsWith(" ")) applySelector += " "; if (applySelector.isEmpty()) selectorIsRecordDiv = false; getDefaultCss(applySelector, sb); StringBuilder replace_underline = new StringBuilder(applySelector + ".replace_underline, "); String text_underline = "text-decoration:underline;"; for (SlxToken t : root.getTokens()) { if (t.matches("style-def")) { String cls = t.get("class"); String style = t.get("style"); String type = t.get("type"); if (cls != null && style != null) { String selector = ""; /* style-def types: level, highlighter, character-style, paragraph, link, field */ if (type.equalsIgnoreCase("level")) selector = "div"; if (type.equalsIgnoreCase("paragraph")) selector = "p"; if (type.equalsIgnoreCase("link")) selector = "a"; if (selector.length() == 0) selector = "span"; if (type.equalsIgnoreCase("level") && selectorIsRecordDiv) { selector = applySelector.trim() + "." + cls; //the selector for level styles applies to the same div; not a child! } else { selector = applySelector + selector + "." + cls; } //Factor out non-link underlines into a single rule. if (!type.equalsIgnoreCase("link") && style.indexOf(text_underline, 0) >= 0) { replace_underline.append(selector); replace_underline.append(", "); style = style.replace(text_underline, ""); } sb.append(selector + " {\n "); sb.append(style.replace(";", ";\n ")); sb.append("}\n"); } } } //Write underlining rule last sb.append(replace_underline.toString().replaceFirst(", \\Z", "")); sb.append("{\n "); sb.append(text_underline); sb.append("\n}\n"); return sb.toString(); } public String getCssAndStyleTags() throws InvalidMarkupException { return "<style type=\"text/css\">\n" + getCss(null, false) + "</style>"; } } /* Default stylesheet for HTML 4 - we have to modify things so they mimic folio behavior... * * html, address, blockquote, body, dd, div, dl, dt, fieldset, form, frame, frameset, h1, h2, h3, h4, h5, h6, noframes, ol, p, ul, center, dir, hr, menu, pre { display: block } li { display: list-item } head { display: none } table { display: table } tr { display: table-row } thead { display: table-header-group } tbody { display: table-row-group } tfoot { display: table-footer-group } col { display: table-column } colgroup { display: table-column-group } td, th { display: table-cell } caption { display: table-caption } th { font-weight: bolder; text-align: center } caption { text-align: center } body { margin: 8px } h1 { font-size: 2em; margin: .67em 0 } h2 { font-size: 1.5em; margin: .75em 0 } h3 { font-size: 1.17em; margin: .83em 0 } h4, p, blockquote, ul, fieldset, form, ol, dl, dir, menu { margin: 1.12em 0 } h5 { font-size: .83em; margin: 1.5em 0 } h6 { font-size: .75em; margin: 1.67em 0 } h1, h2, h3, h4, h5, h6, b, strong { font-weight: bolder } blockquote { margin-left: 40px; margin-right: 40px } i, cite, em, var, address { font-style: italic } pre, tt, code, kbd, samp { font-family: monospace } pre { white-space: pre } button, textarea, input, select { display: inline-block } big { font-size: 1.17em } small, sub, sup { font-size: .83em } sub { vertical-align: sub } sup { vertical-align: super } table { border-spacing: 2px; } thead, tbody, tfoot { vertical-align: middle } td, th, tr { vertical-align: inherit } s, strike, del { text-decoration: line-through } hr { border: 1px inset } ol, ul, dir, menu, dd { margin-left: 40px } ol { list-style-type: decimal } ol ul, ul ol, ul ul, ol ol { margin-top: 0; margin-bottom: 0 } u, ins { text-decoration: underline } br:before { content: "\A"; white-space: pre-line } center { text-align: center } :link, :visited { text-decoration: underline } :focus { outline: thin dotted invert } Begin bidirectionality settings (do not change) BDO[DIR="ltr"] { direction: ltr; unicode-bidi: bidi-override } BDO[DIR="rtl"] { direction: rtl; unicode-bidi: bidi-override } *[DIR="ltr"] { direction: ltr; unicode-bidi: embed } *[DIR="rtl"] { direction: rtl; unicode-bidi: embed } @media print { h1 { page-break-before: always } h1, h2, h3, h4, h5, h6 { page-break-after: avoid } ul, ol, dl { page-break-before: avoid } } */