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 }
}
*/