This tutorial is based on the style-sheet play.dsl posted by an Anonymous author and posted by Jon Bosak. It is rather simplistic and not very well documented, but it should be understandable.
Paul Prescod has published another DSSSL tutorial which can be found at: http://itrc.uwaterloo.ca/~papresco/dsssl/tutorial.html. His tutorial is more detailed and does not assume Scheme knowledge.
The objective of the tutorial is to introduce you to the basics of DSSSL. We will build a DSSSL style-sheet for plays (based on the one posted by Jon Bosak (play.dsl).
You can download a copy of the examples from:
We already have a SGML file and its DTD. The first step is to generate an RTF file with all the text of the play, without any format:
; This dumps the text of the plays without any particular format (root (make simple-page-sequence (process-children)) )
The RTF file is just a sequence of characters. No margins, no paragraphs. It uses the Jade's defaults for the font family, font size, page size, etc.
(root (make simple-page-sequence ; margins left-margin: 1in right-margin: 1in top-margin: 1in bottom-margin: 1in (process-children)) )
We will work top-down, adding format as we encounter elements in the SGML file.
(element (PLAY TITLE) ;the play's title (make paragraph quadding: 'center font-size: 18pt line-spacing: 18pt font-weight: 'bold keep-with-next?: #t (process-children)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Front matter ; (element (FM) (make paragraph font-size: 8pt line-spacing: 8pt ; left and right indentation start-indent: 5cm end-indent: 5cm ; space before space-before: .5cm ; space after space-after: .5cm (process-children)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Adding constants (define *titleFontSize* 18pt) (define *fmFontSize* (/ *titleFontSize* 2)) (define *fmIndent* 3cm) (define *fmSpaceBefore* .5cm) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; TITLE of the PLAY (element (PLAY TITLE) (make paragraph quadding: 'center font-size: *titleFontSize* line-spacing: *titleFontSize* font-weight: 'bold keep-with-next?: #t (process-children))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Front matter ; (element (FM) (make paragraph font-size: *fmFontSize* line-spacing: *fmFontSize* ; left and right indentation start-indent: *fmIndent* end-indent: *fmIndent* ; space before space-before: *fmSpaceBefore* ; space after space-after: *fmSpaceBefore* (process-children)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; PERSONAE (element PERSONAE (process-children)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; PERSONA (element PERSONA ;a person (make paragraph space-before: *personaSpaceBefore* start-indent: *personaIndent* (process-children))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; TITLE inside PERSONAE (element (PERSONAE TITLE) (make paragraph font-size: *personaetitleFontSize* line-spacing: *personaetitleFontSize* font-weight: 'bold keep-with-next?: #t (process-children))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; PGROUP ; We have to extract the description of the group (located ; at the end of the PGROUP, and displayed at _the beginning_ (define (*groupName*) ; First set x to GRPDESCR content (let ((x (data (select-elements (children (if (equal? (gi) "PGROUP") (current-node) (ancestor "PGROUP"))) '(GRPDESCR)))) ) ; if x ends in "." drop the latter. then concatenate ":" (string-append (if (string=? (substring x (- (string-length x) 1) (string-length x)) ".") (substring x 0 (- (string-length x) 1)) x) ":" ) ) ) (element PGROUP (make paragraph start-indent: *personaIndent* space-before: *textSpaceBefore* font-weight: 'bold (literal (*groupName*)) (process-children))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; PERSONA inside a PGROUP (element (PGROUP PERSONA ) (make paragraph space-before: *personaSpaceBefore* start-indent: *pgroupIndent* font-weight: #f (process-children))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; GRPDESCR ; it has been extracted, so ignore (element GRPDESCR (empty-sosofo))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Scndescr (define *sceneStyle* ;style for all scene descriptions (style quadding: 'center font-size: (+ *textFontSize* 4pt) line-spacing: *textFontSize* font-weight: #f font-posture: 'italic start-indent: *sceneIndent* end-indent: *sceneIndent*)) (element SCNDESCR (make paragraph use: *sceneStyle* space-before: *sceneSpaceBefore* (process-children)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; STAGEDIR ; (element STAGEDIR (make paragraph font-posture: 'italic ; If it is inside a line or speech, don't put space-before, otherwise ; skip some space space-before: (if (or (equal? (gi (parent)) "LINE") (equal? (gi (parent)) "SPEECH")) 0pt *textFontSize*) ; surround so not spoken accidentally (literal "[") (process-children) (literal "]")))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; SPEECH (element SPEECH ;a set of lines by one or more speakers (make table ;use a table to accommodate multiple speakers space-before: (/ *textFontSize* 2) may-violate-keep-after?: #t (make table-column ;ensure speaker column is narrow column-number: 1 width: *speakerWidth*) (make table-cell ;collect all speakers (make paragraph (with-mode *speechSpeaker* (process-matching-children "SPEAKER")))) (make table-cell ;collect all lines and instructions (process-children)))) (mode *speechSpeaker* ;collect all speakers into single column (element SPEAKER ;separate with ampersands to indicate multiple (if (= (child-number) 1) (make sequence font-posture: 'italic (process-children)) (make sequence font-posture: 'italic (literal " & ") (process-children)))) (default ;fail-safe - this should not trigger (empty-sosofo))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; SPEAKER ; This has been taken care of in speechSpeaker mode, therefore ignore in ; normal mode (element SPEAKER ;this should not trigger - only in mode (empty-sosofo)) (element LINE ;all of the lines for a given set of speakers (make paragraph (process-children)))
DSSSL is a complex language. I had outlined very few of its characteristics. Don't expect be an expert after understanding this tutorial. At this point you should have a feeling of what it can accomplish. Furthermore, you should be ready to take the draft of the Standard and better understand it.
Good luck!
If you have comments regarding this tutorial, please feel free to drop me a line at dmg@csg.uwaterloo.ca