Sketch of Simple Formatting Primitives

C.M. Sperberg-McQueen

1994-09-13 original version
1995-07-04 retagged and minor changes made for clarity

These may be used to construct a semi-declarative stylesheet language; in a more imperative style, they can be regarded as variables instantiated for each element type. Notation is not specified here, but various options are obviously suitable. In list of primitives, I use functional notation for functions; in the examples below, I use Scheme/Lisp style.

1 Blocks vs. Inline (phrase-level) elements:

block flag
is this a block with shape of own, or not?
flow flag
are line breaks respected, or do we reflow? N.B. Lexx finds it necessary to indicate break at start and end using two separate flags; we may too, if we don't find a better way of handling the GT - GD pairs of glossary lists.
Flow defaults to TRUE, block to ???

Alternate spec:

break flag flag
do we have forced line break before? after?
flow flag
are line breaks ignored in content?

2 Layout:

These apply only if block=TRUE. If we use the alternative formulation, then we have the following cases:

block='Y Y'
these all apply
block='Y N'
the block is made up of this and all following elements until we have a block='YY' or 'YN' or 'NY'
block='N Y'
if there is a preceding element with block='Y N' these are ignored; else this is treated as 'Y Y'
block='N N'
these all are ignored. if we don't have a current block, we're screwed, that is, it's an error.
vspace dist dist
vertical space before and after element
margins dist dist
margins to use in setting this element; may be relative
shape shapename
one of a fixed set of options (or: this could be analyzed into simpler primitives)


3 Hiding:

display-level int
default: hide 0, display > 0, default = 1

4 Fonts:

font-family name
may be system dependent; perhaps allow list of family names in descending order of preference?
font-size int
point size; may be absolute or relative -- OR --
font-size normal | lg | vlg | sm | vsm | huge
absolute or relative interpretation under end-user control
roman | italic | bold
normal | underlined | redlined
color name

Or possibly allow association of arbitrary names with a font family, style, treatment, etc., and then simply specify a font-name for each element (more or less like GML).

All variables can also take keyword CURRENT (or INHERIT) as value.

5 Content:

concatenation of one or more of:

Default value is content(), and low-level browsers may accept no more. Higher levels will allow attribute values and string literals. Even higher levels will allow arguments to content and attval indicating which element node is concerned, using tf syntax or a derivative, e.g.:

-- i.e. attribute value of type on left sibling with gi of P

6 Actions:

Possible style-sheet primitives:

with sample values like:

Examples from HTML:

a (anchor) element has attribute href, and is formatted in blue:

  (style a
    (block #f)     ; format as inline phrase
    (color blue)   ; in blue if you've got it
    (click (follow (attval 'href)))  ; and on click, follow url

It's not clear what to do about low-level browsers which don't support attribute-value extraction; perhaps a special form is needed to allow a definition like:

  (style a
    (block #f)     ; format as inline phrase
    (color blue)   ; in blue if you've got it
    (click 'follow-URL 'HREF))         ; and on click, follow url

p (paragraph) has blank line above, prints smooth L and R, with initial indent and last line flush left:

  (style p
    (block #t)
    (shape 'normal-para)
    (vspace '0.5l '0))

h1 (chapter title) has big vertical space, prints very large, respects line breaks

  (style h1
    (block #t)
    (vspace '24pt '8pt)
    (shape 'centered)
    (font-size 'vlg)
    (font-style 'bold)
    (flow #f))

Miscellaneous other element types, with formatting as described in the HTML spec:

  (style address
    (font-style 'italic)
    (block #t)
    (shape 'flush-left)
    (flow #f)
    (margins '+10pica '0))
  (style blockquote
    (margins '+10pica '-10pica)
    (block #t)
    (shape 'block-para))
  ; alternative block quote for VT100s etc.:  print each line preceded
  ; by >
  (style blockquote
    (margins '+5  '0)
    (block #t)
    (shape 'netnews-quote))
  (style h2
    (block #t)
    (vspace '12pt '8pt)
    (shape 'flush-left)
    (font-size 'lg)
    (font-style 'bold)
    (flow #f))
  (style h3
    (block #t)
    (vspace '8pt '8pt)
    (shape 'indent-left)
    (font-size 'lg)
    (font-style 'ital)
    (flow #f))
  (style h4
    (block #t)
    (vspace '8pt '8pt)
    (shape 'indent-twice-left)
    (font-size 'normal)
    (font-style 'bold)
    (flow #f))

Other issues

Not considered here are:

Fallbacks are probably best handled with a combination of conditionals and system-set parameters describing what is supported and possibly what user's or implementor's preferences are, so as to allow statements like 'if color is supported, then color=blue and font-style=inherited, else font-style=italic' and 'if multi-column is preferred, then ... else ...'

Variables pose a language design problem: if they are fully supported, e.g. in a macro scripting language like tcl or Scheme, there is no reason to use anything but the normal assignment syntax. Low-end implementors may balk, however, at providing full support for variables and arithmetic, so we might have to extend the Actions section above to accept actions like:

which will at least handle item numbers in a list.
1994-9-13 / C.M. Sperberg-McQueen /