From 7977d1817e9d5114f2c2877773199103f3501142 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Mon, 1 Aug 2011 14:40:49 -0600 Subject: [PATCH] expose the `scribble' command-line driver as `racket/render' --- collects/scribble/render.rkt | 76 ++++++++++++++ collects/scribble/run.rkt | 72 +++++-------- collects/scribblings/scribble/renderer.scrbl | 103 +++++++++++++++++-- 3 files changed, 194 insertions(+), 57 deletions(-) create mode 100644 collects/scribble/render.rkt diff --git a/collects/scribble/render.rkt b/collects/scribble/render.rkt new file mode 100644 index 0000000000..de4f1717e2 --- /dev/null +++ b/collects/scribble/render.rkt @@ -0,0 +1,76 @@ +#lang racket/base + +(require "core.rkt" + "base-render.rkt" + "xref.rkt" + racket/file + racket/class + racket/contract + (prefix-in html: "html-render.rkt")) + +(provide/contract + [render ((listof part?) + (listof path-string?) + #:render-mixin (class? . -> . class?) + #:dest-dir (or/c #f path-string?) + #:prefix-file (or/c #f path-string?) + #:style-file (or/c #f path-string?) + #:style-extra-files (listof path-string?) + #:extra-files (listof path-string?) + #:redirect (or/c #f string?) + #:redirect-main (or/c #f string?) + #:xrefs (listof xref?) + #:info-in-files (listof path?) + #:info-out-file (or/c #f path-string?) + #:quiet? any/c + . -> . void?)]) + +(define (render docs + names + #:render-mixin [render-mixin html:render-mixin] + #:dest-dir [dest-dir #f] + #:prefix-file [prefix-file #f] + #:style-file [style-file #f] + #:style-extra-files [style-extra-files null] + #:extra-files [extra-files null] + #:redirect [redirect #f] + #:redirect-main [redirect-main #f] + #:xrefs [xrefs null] + #:info-in-files [info-input-files null] + #:info-out-file [info-output-file #f] + #:quiet? [quiet? #t]) + (when dest-dir (make-directory* dest-dir)) + (let ([renderer (new (render-mixin render%) + [dest-dir dest-dir] + [prefix-file prefix-file] + [style-file style-file] + [style-extra-files style-extra-files] + [extra-files extra-files])]) + (when redirect + (send renderer set-external-tag-path redirect)) + (when redirect-main + (send renderer set-external-root-url redirect-main)) + (unless quiet? + (send renderer report-output!)) + (let* ([fns (map (lambda (fn) + (let-values ([(base name dir?) (split-path fn)]) + (let ([fn (path-replace-suffix + name + (send renderer get-suffix))]) + (if dest-dir (build-path dest-dir fn) fn)))) + names)] + [fp (send renderer traverse docs fns)] + [info (send renderer collect docs fns fp)]) + (for ([file (in-list info-input-files)]) + (let ([s (with-input-from-file file read)]) + (send renderer deserialize-info s info))) + (for ([xr (in-list xrefs)]) + (xref-transfer-info renderer info xr)) + (let ([r-info (send renderer resolve docs fns info)]) + (send renderer render docs fns r-info) + (when info-output-file + (let ([s (send renderer serialize-info r-info)]) + (with-output-to-file info-output-file + #:exists 'truncate/replace + (lambda () (write s)))))) + (void)))) diff --git a/collects/scribble/run.rkt b/collects/scribble/run.rkt index 6ffdb8a6cf..3b080fe624 100644 --- a/collects/scribble/run.rkt +++ b/collects/scribble/run.rkt @@ -1,11 +1,8 @@ #lang racket/base -(require "core.rkt" - "base-render.rkt" - "xref.rkt" +(require "xref.rkt" + "render.rkt" scheme/cmdline - scheme/file - scheme/class raco/command-name (prefix-in text: "text-render.rkt") (prefix-in html: "html-render.rkt") @@ -103,46 +100,29 @@ files)))) (define (build-docs docs files) - (define dir (current-dest-directory)) - (when dir (make-directory* dir)) - (let ([renderer (new ((current-render-mixin) render%) - [dest-dir dir] - [prefix-file (current-prefix-file)] - [style-file (current-style-file)] - [style-extra-files (reverse (current-style-extra-files))] - [extra-files (reverse (current-extra-files))])]) - (when (current-redirect) - (send renderer set-external-tag-path (current-redirect))) - (when (current-redirect-main) - (send renderer set-external-root-url (current-redirect-main))) - (unless (current-quiet) - (send renderer report-output!)) - (let* ([fns (map (lambda (fn) - (let-values ([(base name dir?) (split-path fn)]) - (let ([fn (path-replace-suffix - (or (current-dest-name) name) - (send renderer get-suffix))]) - (if dir (build-path dir fn) fn)))) - files)] - [fp (send renderer traverse docs fns)] - [info (send renderer collect docs fns fp)]) - (for ([file (in-list (reverse (current-info-input-files)))]) - (let ([s (with-input-from-file file read)]) - (send renderer deserialize-info s info))) - (for ([mod+id (in-list (reverse (current-xref-input-modules)))]) - (let* ([get-xref (dynamic-require (car mod+id) (cdr mod+id))] - [xr (get-xref)]) - (unless (xref? xr) - (raise-user-error - 'scribble "result from `~s' of `~s' is not an xref: ~e" - (cdr mod+id) (car mod+id) xr)) - (xref-transfer-info renderer info xr))) - (let ([r-info (send renderer resolve docs fns info)]) - (send renderer render docs fns r-info) - (when (current-info-output-file) - (let ([s (send renderer serialize-info r-info)]) - (with-output-to-file (current-info-output-file) - #:exists 'truncate/replace - (lambda () (write s))))))))) + (render docs + (map (lambda (fn) + (let-values ([(base name dir?) (split-path fn)]) + (or (current-dest-name) name))) + files) + #:dest-dir (current-dest-directory) + #:render-mixin (current-render-mixin) + #:prefix-file (current-prefix-file) + #:style-file (current-style-file) + #:style-extra-files (reverse (current-style-extra-files)) + #:extra-files (reverse (current-extra-files)) + #:redirect (current-redirect) + #:redirect-main (current-redirect-main) + #:quiet? (current-quiet) + #:info-in-files (reverse (current-info-input-files)) + #:xrefs (for/list ([mod+id (in-list (reverse (current-xref-input-modules)))]) + (let* ([get-xref (dynamic-require (car mod+id) (cdr mod+id))] + [xr (get-xref)]) + (unless (xref? xr) + (raise-user-error + 'scribble "result from `~s' of `~s' is not an xref: ~e" + (cdr mod+id) (car mod+id) xr)) + xr)) + #:info-out-file (current-info-output-file))) (run) diff --git a/collects/scribblings/scribble/renderer.scrbl b/collects/scribblings/scribble/renderer.scrbl index 5b1db33253..e0b66a66e3 100644 --- a/collects/scribblings/scribble/renderer.scrbl +++ b/collects/scribblings/scribble/renderer.scrbl @@ -1,5 +1,9 @@ #lang scribble/doc -@(require scribble/manual "utils.rkt" (for-label racket/class)) +@(require scribble/manual + "utils.rkt" + (for-label racket/class + scribble/render + scribble/xref)) @(define-syntax-rule (defmodule/local lib . content) (begin @@ -10,15 +14,73 @@ . content)) (intro))) -@title[#:tag "renderer"]{Renderer} +@(begin + (define-syntax-rule (def-render-mixin id) + (begin + (require (for-label scribble/html-render)) + (define id @racket[render-mixin]))) + (def-render-mixin html:render-mixin)) + +@title[#:tag "renderer"]{Renderers} + +A renderer is an object that provides four main methods: +@racket[traverse], @racket[collect], @racket[resolve], and +@racketidfont{render}. Each method corresponds to a pass described in +@secref["core"], and they are chained together by the @racket[render] +function to render a document. + +@section{Rendering Driver} + +@defmodule[scribble/render] + +@defproc[(render [docs (listof part?)] + [names (listof path-string?)] + [#:render-mixin render-mixin (class? . -> . class?) @#,html:render-mixin] + [#:dest-dir dest-dir (or/c #f path-string?) #f] + [#:prefix-file prefix-file (or/c #f path-string?) #f] + [#:style-file style-file (or/c #f path-string?) #f] + [#:style-extra-files style-extra-files (listof path-string?) #f] + [#:extra-files extra-files (listof path-string?) #f] + [#:xrefs xrefs (listof xref?) null] + [#:info-in-files info-in-files (listof path?) null] + [#:info-out-file info-out-file (or/c #f path-string?) #f] + [#:redirect redirect (or/c #f string?) #f] + [#:redirect-main redirect-main (or/c #f string?) #f] + [#:quiet? quiet? any/c #f]) + void?]{ + +Renders the given @racket[docs], each with an output name derived from +the corresponding element of @racket[names]. A directory path (if any) +for a name in @racket[names] is discarded, and the file suffix is +replaced (if any) with a suitable suffix for the output format. + +The @racket[render-mixin] argument determines the output format. By +default, it is @html:render-mixin from @racketmodname[scribble/html-render]. + +The @racket[dest-dir] argument determines the output directory, which +is created using @racket[make-directory*] if it is non-@racket[#f] and +does not exist already. + +The @racket[prefix-file], @racket[style-file], +@racket[extra-style-files], and @racket[extra-files] arguments are +passed on to the @racket[render%] constructor. + +The @racket[xrefs] argument provides extra cross-reference information +to be used during the documents' @tech{resolve pass}. The +@racket[info-in-files] arguments supply additional cross-reference +information in serialized form. When the @racket[info-out-file] +argument is not @racket[#f], cross-reference information for the +rendered documents is written in serialized for to the specified file. + +The @racket[redirect] and @racket[redirect-main] arguments correspond +to the @racket[set-external-tag-path] and +@racket[set-external-root-url] methods of @|html:render-mixin| from +@racketmodname[scribble/html-render], so they should be +non-@racket[#f] only for HTML rendering. + +If @racket[quiet?] is a true value, output-file information is written +to the current output port.} -A renderer is an object that provides two main methods: -@racket[collect] and @racket[render]. The first method is called to -collect global information about the document, including information -that spans multiple documents rendered together; the collection pass -tends to be format-independent, and it usually implemented completely -by the base renderer. The latter method generates the actual output, -which is naturally specific to a particular format. @section{Base Renderer} @@ -45,7 +107,11 @@ Represents a renderer. @defconstructor[([dest-dir path-string?] [refer-to-existing-files any/c #f] - [root-path (or/c path-string? false/c) #f])]{ + [root-path (or/c path-string? #f) #f] + [prefix-file (or/c path-string? #f) #f] + [style-file (or/c path-string? #f) #f] + [style-extra-files (listof path-string?) null] + [extra-files (listof path-string?) null])]{ Creates a renderer whose output will go to @racket[dest-dir]. For example, @racket[dest-dir] could name the directory containing the @@ -58,7 +124,15 @@ cross-reference information to record destination files relative to @racket[root-path]; when cross-reference information is serialized, it can be deserialized via @method[render% deserialize-info] with a different root path (indicating that the destination files have -moved).} +moved). + +The @racket[prefix-file], @racket[style-file], and +@racket[style-extra-files] arguments set files that control output +styles in a formal-specific way; see @secref["config-style"] for more +information. + +The @racket[extra-files] argument names files to be copied to the +output location, such as image files or extra configuration files.} @defmethod[(traverse [srcs (listof part?)] @@ -149,6 +223,13 @@ Configures the renderer to redirect links to external via URL that contains the Base64-encoded, @racket[print]ed, serialized original tag (in the sense of @racket[link-element]) for the link.} +@defmethod[(set-external-root-url [url string?]) void?]{ + +Configures the renderer to redirect links to documents installed in +the distribution's documentation directory to the given URL, using the +URL as a replacement to the path of the distribution's document +directory.} + } @defmixin[render-multi-mixin (render%) ()]{