⌂ Use page up/page down (Mac: FN + up/down) to turn pages

Your browser doesn't support the features required by impress.js, so you are presented with a simplified version of this presentation.

For the best experience please use the latest Chrome, Safari or Firefox browser.

Conveying Layout Information with CSSa

Gerrit Imsieke (@gimsieke)

XML Prague 2013

CSSa in a Nutshell

I might look stupid to someone but #xmlprague is an event just about XML? You know, that thing you can learn in 2 hours? -- Antonín Daněk (@TondaCZE)

CSSa adds another simple concept to the stack.

Motivation: Need for a Neutral Intermediate Format

n times m converters

n times m converters

n×m

n+m

The Importance of Layout
in Conversion Pipelines

Typical document conversion workflows

 

Technologies: XProc, XSLT2, Relax NG, Schematron

Layout information comes in two flavors:
central styles and local overrides.

.foo {
  font-size: 10pt;
  line-height:1.3em;
  hyphens: auto;
}

central style (here: class) ⇒ named rule

<css:rule name="foo"
  css:font-size="10pt" 
  css:line-height="1.3em"
  css:hyphens="auto"/>
<p style="margin-bottom:6pt; color:red">
  text
</p>

local overrides ⇒ prefixed attributes

<p css:margin-bottom="6pt" 
   css:color="red">
  text
</p>

Heterogeneous Input I

InDesign’s native layout representation

IDML

Test text in InDesign

           <ParagraphStyle Self="ParagraphStyle/test"
                Name="test"
                Imported="false"
                NextStyle="ParagraphStyle/test"
                KeyboardShortcut="0 0"
                FillColor="Color/C=75 M=5 Y=100 K=0"
                FontStyle="Bold"
                PointSize="14"
                SpaceBefore="5.669291338582678"
                SpaceAfter="5.669291338582678">
            <Properties>
               <BasedOn type="string">$ID/[No paragraph style]</BasedOn>
               <PreviewColor type="enumeration">Nothing</PreviewColor>
               <AppliedFont type="string">Minion Pro</AppliedFont>
            </Properties>
            

Heterogeneous Input II

Word’s native layout representation

OOXML

Test text in Word

    <w:style w:type="paragraph" w:customStyle="1" w:styleId="test">
      <w:name w:val="test"/>
      <w:pPr>
        <w:spacing w:before="113" w:after="113"/>
      </w:pPr>
      <w:rPr>
        <w:rFonts w:ascii="Minion Pro" w:hAnsi="Minion Pro"/>
        <w:b/>
        <w:color w:val="339966"/>
        <w:sz w:val="28"/>
      </w:rPr>
    </w:style>
            

Normalized Representation:
CSSa named rules

OOXML

IDML

         <css:rule name="test"
           layout-type="para"
           css:color="#339966"
           css:font-family="Minion Pro"
           css:font-size="14pt"
           css:font-weight="bold"
           css:margin-bottom="5.65pt"
           css:margin-top="5.65pt"/>
            
         <css:rule name="test"
           layout-type="para"
           css:color="device-cmyk(0.75,0.05,1,0)"
           css:font-family="Minion Pro"
           css:font-size="14pt"
           css:font-weight="bold"
           css:margin-bottom="5.65pt"
           css:margin-top="5.65pt"/>
            

Selectors? Precedence?

Not part of the CSSa spec.

But we’ve developed a CSS expander for HTML:

Input

<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <style type="text/css">
      .foo > p { color:red; }
      p { color:blue; }
      p { color:green; }
    </style>
  </head>
  <body>
    <div class="foo">
      <p>foo</p>
    </div>
    <p>plain</p>
  </body>
</html>        
      
  <style type="text/css" xml:space="preserve">
    .foo &gt; p { color:red; }
    p { color:blue; }
    p { color:green; }
  </style>
</head>
<body>
  <div class="foo">
    <p css:color="red">foo</p>
  </div>
  <p css:color="green">plain</p>
</body>
      

$ calabash.sh -i source=test.xhtml \
  -o result=out.xhtml css-expand/xpl/css.xpl

Custom Schematron Rules for epubcheck

<s:pattern id="css-text">
  <s:rule 
    context="*[@css:text-transform]">
    <s:report 
      test="@css:text-transform eq 'uppercase'">
      <s:span class="severity">WRN</s:span>
      <s:span class="msgid">SCH_Kindle_0013</s:span> 
      text-transform:uppercase not supported 
    </s:report>
  </s:rule>
  ……
      

Mobipocket Compatibility Check

mobipocket check report

Creating IDML Tables
from an HTML Preview

When synthesizing IDML, you can use centralized styles, except for table widths.

Style HTML with central CSS; selectively CSS-expand it; trivially transform td/@css:width to the corresponding IDML property. XProc step:

<css:expand 
  path-constraint="[self::*:td]" 
  prop-constraint="width"/>

CSSa Specification

There isn’t (yet). But there is a Relax NG schema

<define name="css_pattern.length">
  <data type="token">
    <param name="pattern">\+?(\.[0-9]+|[0-9]+\.?([0-9]+)?)(px|em|ex|in|cm|mm|pt|pc)</param>
  </data>
</define>
<define name="css_pattern.padding">
  <choice>
    <ref name="css_pattern.length"/>
    <ref name="css_pattern.percentage"/>
  </choice>
</define>
<define name="css_att.padding-left">
  <optional>
    <attribute name="css:padding-left">
      <ref name="css_pattern.padding"/>
    </attribute>
  </optional>
</define>
<define name="css_attributes">
  <interleave>
    ……
    <ref name="css_att.padding-left"/>
    ……
    <ref name="css_pseudo_att.marker_font-weight"/>
    <ref name="custom.css-like.attributes"/>
  </interleave>
</define>

The schema comprises:

To Do

Summary

Thank you!

Appendix:
Hub XML

Hub XML

flat DocBook + CSSa + Tabs + <br/>

<?xml version="1.0" encoding="utf-8"?>
<?xml-model href="http://www.le-tex.de/resource/schema/hub/1.1/hub.rng" type="application/xml" schematypens="http://relaxng.org/ns/structure/1.0"?>
<?xml-model href="http://www.le-tex.de/resource/schema/hub/1.1/hub.rng" type="application/xml" schematypens="http://purl.oclc.org/dsdl/schematron"?>
<hub xmlns="http://docbook.org/ns/docbook"
  xmlns:css="http://www.w3.org/1996/css"
  version="5.1-variant le-tex_Hub-1.1"
  css:version="3.0-variant le-tex_Hub-1.1"
  css:rule-selection-attribute="role">

docx2hub and idml2hub converters available

   <info>
      <keywordset role="hub"> 
         <keyword role="source-basename">muster1</keyword>
         <keyword role="source-dir-uri">file://…/muster1.idml.tmp/</keyword>
         <keyword role="source-paths">false</keyword>
         <keyword role="formatting-deviations-only">true</keyword>
         <keyword role="source-type">idml</keyword>
      </keywordset>
      <css:rules>
         <css:rule name="p_Musterseite_p_column_left"
                   native-name="p:Musterseite:p_column_left"
                   layout-type="para"
                   css:font-size="9pt"
                   xml:lang="de"
                   css:text-align="center"
                   css:text-align-last="center">
            <tabs>
               <tab align="center"
                    alignment-char="."
                    leader=""
                    horizontal-position="170pt"/>
            </tabs>
         </css:rule>

Appendix:
CSS constituents

CSS constituents

(back to CSS parser)

Appendix:
Style Inheritance

Style Inheritance

IDML example

<ParagraphStyle Self="ParagraphStyle/AB_Text_List_Item"
  Name="AB_Text_List_Item"
  LeftIndent="14.173228346456694"
  FirstLineIndent="-14.173228346456694">
  <Properties>
    <BasedOn type="object">ParagraphStyle/AB_Text</BasedOn>
    <BulletChar BulletCharacterType="UnicodeWithFont" BulletCharacterValue="8226"/>
    <BulletsFont type="string">Arial Unicode MS</BulletsFont>
  </Properties>
</ParagraphStyle>

Style Inheritance resolved

Translates to (including props inherited from AB_Text):

<css:rule name="AB_Text_List_Item"
  layout-type="para"
  css:font-size="9.5pt"
  xml:lang="de"
  css:font-family="Arial Unicode MS"
  css:pseudo-marker_content="'•'"
  css:pseudo-marker_font-family="Arial Unicode MS"
  css:margin-left="14.15pt"
  css:text-indent="-14.15pt"/>

Style Inheritance vs. Style Composition

No based-on inheritance in named rules (simplification).

Allowed: style composition

<para role="foo bar">

If named rules foo and bar define the same property, the last-defined in document order wins, as in CSS.

Schematron author has to make sure
that the last defined wins

<rule context="dbk:para">
  <let name="roles" 
    value="tokenize(@role, '\s+')"/>
  <let name="rules" 
    value="/*/dbk:info/css:rules/css:rule[@name = $roles]"/>
  <report 
    test="matches( 
      ('', ($rules | .)/@css:font-weight)[last()], 
      '^(bold|[6-9]00)$' 
    )">Is this all-boldface paragraph
    a heading?</report>

Appendix:
Isn’t Everybody Adopting CSS Syntax Now?

Why CSS as attributes?

The Web is moving in the opposite direction:

CSS-like selectors in jQuery, …

CSS-like Schematron Rules from Robin Berjon’s XML Prague 2012 slides

CSS-like Schematron Rules, …

<div id="content">
  ……
  <video src="movie.mp4" preload="auto">
  ……

video {
  preload: metadata;
}
#content video {
  preload: auto;
}

Cascading Attribute Sheets

CSS from an XML perspective