]>
git.cameronkatri.com Git - mandoc.git/blob - html.c
c969b8f0ec4d51cfd5cd21cc19b022db256d85d6
1 /* $Id: html.c,v 1.17 2008/12/09 17:09:12 kristaps Exp $ */
3 * Copyright (c) 2008 Kristaps Dzonsons <kristaps@kth.se>
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the
7 * above copyright notice and this permission notice appear in all
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
19 #include <sys/param.h>
33 #define TAG_HTML "<html>"
34 #define TAG_BODY "<body>"
35 #define TAG_DIV_MDOC "<div class=\"mdoc\">"
36 #define TAG_STYLE_CSS "<style type=\"text/css\"><!--"
37 #define TAG_STYLE_END "--></style>"
38 #define TAG_HEAD "<head>"
39 #define TAG_HEAD_END "</head>"
40 #define TAG_TITLE "<title>"
41 #define TAG_TITLE_END "</title>"
42 #define TAG_LINK_CSS "<link rel=\"stylesheet\" " \
43 "type=\"text/css\" href=\"%s\">"
44 #define TAG_DOCTYPE "<!DOCTYPE HTML PUBLIC " \
45 "\"-//W3C//DTD HTML 4.01//EN\" " \
46 "\"http://www.w3.org/TR/html4/strict.dtd\">"
47 #define TAG_RESTYPE "<meta name=\"resource-type\" " \
48 "content=\"document\">"
49 #define TAG_CONTTYPE "<meta http-equiv=\"Content-Type\" " \
50 "content=\"text/html;charset=utf-8\">"
52 /* TODO: allow head/tail-less invocations (just "div" start). */
57 int argc
[ROFF_MAXLINEARG
];
58 char *argv
[ROFF_MAXLINEARG
];
59 struct htmlnode
*parent
;
64 struct htmlnode
*last
;
68 static int html_loadcss(struct md_mbuf
*, const char *);
70 static int html_alloc(void **);
71 static void html_free(void *);
72 static ssize_t
html_endtag(struct md_mbuf
*, void *,
73 const struct md_args
*,
75 static ssize_t
html_beginstring(struct md_mbuf
*,
76 const struct md_args
*,
77 const char *, size_t);
78 static ssize_t
html_beginhttp(struct md_mbuf
*,
79 const struct md_args
*,
80 const char *, size_t);
81 static ssize_t
html_endstring(struct md_mbuf
*,
82 const struct md_args
*,
83 const char *, size_t);
84 static ssize_t
html_endhttp(struct md_mbuf
*,
85 const struct md_args
*,
86 const char *, size_t);
87 static ssize_t
html_begintag(struct md_mbuf
*, void *,
88 const struct md_args
*,
90 const int *, const char **);
91 static int html_begin(struct md_mbuf
*,
92 const struct md_args
*,
94 const char *, const char *,
95 enum roffmsec
, const char *);
96 static int html_printargs(struct md_mbuf
*, int,
97 const char *, const int *,
98 const char **, size_t *);
99 static int html_end(struct md_mbuf
*,
100 const struct md_args
*);
101 static int html_blocktagname(struct md_mbuf
*,
102 const struct md_args
*, int,
103 struct htmlq
*, const int *,
104 const char **, size_t *);
105 static int html_blocktagargs(struct md_mbuf
*,
106 const struct md_args
*, int,
107 const int *, const char **, size_t *);
108 static int html_headtagname(struct md_mbuf
*,
109 const struct md_args
*, int,
110 struct htmlq
*, const int *,
111 const char **, size_t *);
112 static int html_headtagargs(struct md_mbuf
*,
113 const struct md_args
*, int,
114 const int *, const char **, size_t *);
115 static int html_bodytagname(struct md_mbuf
*,
116 const struct md_args
*,
117 int, struct htmlq
*, const int *,
118 const char **, size_t *);
119 static int html_bodytagargs(struct md_mbuf
*,
120 const struct md_args
*, int,
121 const int *, const char **, size_t *);
122 static int html_inlinetagname(struct md_mbuf
*,
123 const struct md_args
*, int, size_t *);
124 static int html_inlinetagargs(struct md_mbuf
*,
125 const struct md_args
*, int,
126 const int *, const char **, size_t *);
127 static int html_Bl_bodytagname(struct md_mbuf
*,
128 struct htmlq
*, const int *,
129 const char **, size_t *);
130 static int html_It_blocktagname(struct md_mbuf
*,
131 struct htmlq
*, const int *,
132 const char **, size_t *);
133 static int html_It_headtagname(struct md_mbuf
*,
134 struct htmlq
*, const int *,
135 const char **, size_t *);
136 static int html_It_bodytagname(struct md_mbuf
*,
137 struct htmlq
*, const int *,
138 const char **, size_t *);
143 html_It_headtagname(struct md_mbuf
*mbuf
, struct htmlq
*q
,
144 const int *argc
, const char **argv
, size_t *res
)
149 for (n
= q
->last
; n
; n
= n
->parent
)
150 if (n
->tok
== ROFF_Bl
)
156 for (i
= 0; ROFF_ARGMAX
!= n
->argc
[i
] &&
157 i
< ROFF_MAXLINEARG
; i
++) {
158 switch (n
->argc
[i
]) {
160 return(ml_nputs(mbuf
, "div", 3, res
));
164 return(ml_nputs(mbuf
, "td", 2, res
));
176 html_It_bodytagname(struct md_mbuf
*mbuf
, struct htmlq
*q
,
177 const int *argc
, const char **argv
, size_t *res
)
182 for (n
= q
->last
; n
; n
= n
->parent
)
183 if (n
->tok
== ROFF_Bl
)
189 for (i
= 0; ROFF_ARGMAX
!= n
->argc
[i
] &&
190 i
< ROFF_MAXLINEARG
; i
++) {
191 switch (n
->argc
[i
]) {
209 return(ml_nputs(mbuf
, "div", 3, res
));
213 return(ml_nputs(mbuf
, "td", 2, res
));
219 assert(i
!= ROFF_MAXLINEARG
);
226 html_Bl_bodytagname(struct md_mbuf
*mbuf
, struct htmlq
*q
,
227 const int *argc
, const char **argv
, size_t *res
)
231 for (i
= 0; ROFF_ARGMAX
!= argc
[i
]
232 && i
< ROFF_MAXLINEARG
; i
++) {
235 return(ml_nputs(mbuf
, "ol", 2, res
));
251 return(ml_nputs(mbuf
, "ul", 2, res
));
255 return(ml_nputs(mbuf
, "table", 5, res
));
261 assert(i
!= ROFF_MAXLINEARG
);
268 html_It_blocktagname(struct md_mbuf
*mbuf
, struct htmlq
*q
,
269 const int *argc
, const char **argv
, size_t *res
)
274 for (n
= q
->last
; n
; n
= n
->parent
)
275 if (n
->tok
== ROFF_Bl
)
281 for (i
= 0; ROFF_ARGMAX
!= n
->argc
[i
] &&
282 i
< ROFF_MAXLINEARG
; i
++) {
283 switch (n
->argc
[i
]) {
301 return(ml_nputs(mbuf
, "li", 2, res
));
305 return(ml_nputs(mbuf
, "tr", 2, res
));
311 assert(i
!= ROFF_MAXLINEARG
);
317 html_loadcss(struct md_mbuf
*mbuf
, const char *css
)
329 if (-1 == (fd
= open(css
, O_RDONLY
, 0))) {
334 if (-1 == fstat(fd
, &st
)) {
339 bufsz
= MAX(st
.st_blksize
, BUFSIZ
);
340 if (NULL
== (buf
= malloc(bufsz
))) {
346 if (-1 == (ssz
= read(fd
, buf
, bufsz
))) {
351 if ( ! ml_nputs(mbuf
, buf
, (size_t)ssz
, &res
))
358 if (-1 == close(fd
)) {
372 html_begin(struct md_mbuf
*mbuf
, const struct md_args
*args
,
373 const struct tm
*tm
, const char *os
,
374 const char *title
, enum roffmsec section
,
377 char mtitle
[128], css
[128];
380 (void)snprintf(mtitle
, sizeof(mtitle
),
381 "Manual Page for %s(%s)",
382 title
, roff_msecname(section
));
383 (void)snprintf(css
, sizeof(css
),
384 TAG_LINK_CSS
, args
->params
.html
.css
);
388 if ( ! ml_puts(mbuf
, TAG_DOCTYPE
, &res
))
390 if ( ! ml_nputs(mbuf
, "\n", 1, &res
))
392 if ( ! ml_puts(mbuf
, TAG_HTML
, &res
))
394 if ( ! ml_nputs(mbuf
, "\n", 1, &res
))
396 if ( ! ml_puts(mbuf
, TAG_BODY
, &res
))
398 if ( ! ml_nputs(mbuf
, "\n", 1, &res
))
400 if ( ! ml_puts(mbuf
, TAG_CONTTYPE
, &res
))
402 if ( ! ml_nputs(mbuf
, "\n", 1, &res
))
404 if ( ! ml_puts(mbuf
, TAG_RESTYPE
, &res
))
406 if ( ! ml_nputs(mbuf
, "\n", 1, &res
))
408 if ( ! ml_puts(mbuf
, TAG_TITLE
, &res
))
410 if ( ! ml_putstring(mbuf
, mtitle
, &res
))
412 if ( ! ml_puts(mbuf
, TAG_TITLE_END
, &res
))
414 if ( ! ml_nputs(mbuf
, "\n", 1, &res
))
417 if (HTML_CSS_EMBED
& args
->params
.html
.flags
) {
418 if ( ! ml_puts(mbuf
, TAG_STYLE_CSS
, &res
))
420 if ( ! ml_puts(mbuf
, "\n", &res
))
422 if ( ! html_loadcss(mbuf
, args
->params
.html
.css
))
424 if ( ! ml_puts(mbuf
, TAG_STYLE_END
, &res
))
426 } else if ( ! ml_puts(mbuf
, css
, &res
))
429 if ( ! ml_puts(mbuf
, "\n", &res
))
432 if ( ! ml_puts(mbuf
, TAG_HEAD_END
, &res
))
434 if ( ! ml_nputs(mbuf
, "\n", 1, &res
))
436 if ( ! ml_puts(mbuf
, TAG_BODY
, &res
))
438 if ( ! ml_nputs(mbuf
, "\n", 1, &res
))
440 if ( ! ml_puts(mbuf
, TAG_DIV_MDOC
, &res
))
442 return(ml_nputs(mbuf
, "\n", 1, &res
));
448 html_end(struct md_mbuf
*mbuf
, const struct md_args
*args
)
451 return(ml_puts(mbuf
, "</div></body>\n</html>", NULL
));
457 html_bodytagname(struct md_mbuf
*mbuf
,
458 const struct md_args
*args
, int tok
, struct htmlq
*q
,
459 const int *argc
, const char **argv
, size_t *res
)
464 return(html_Bl_bodytagname(mbuf
, q
, argc
, argv
, res
));
466 return(ml_nputs(mbuf
, "span", 4, res
));
468 return(html_It_bodytagname(mbuf
, q
, argc
, argv
, res
));
470 return(ml_nputs(mbuf
, "span", 4, res
));
475 return(ml_puts(mbuf
, "div", res
));
481 html_headtagname(struct md_mbuf
*mbuf
,
482 const struct md_args
*args
, int tok
, struct htmlq
*q
,
483 const int *argc
, const char **argv
, size_t *res
)
488 return(html_It_headtagname(mbuf
, q
, argc
, argv
, res
));
490 return(ml_nputs(mbuf
, "span", 4, res
));
492 return(ml_nputs(mbuf
, "span", 4, res
));
494 return(ml_nputs(mbuf
, "h1", 2, res
));
496 return(ml_nputs(mbuf
, "h2", 2, res
));
501 return(ml_nputs(mbuf
, "div", 3, res
));
507 html_blocktagname(struct md_mbuf
*mbuf
, const struct md_args
*args
,
508 int tok
, struct htmlq
*q
, const int *argc
,
509 const char **argv
, size_t *res
)
514 return(ml_nputs(mbuf
, "span", 4, res
));
516 return(ml_nputs(mbuf
, "span", 4, res
));
518 return(html_It_blocktagname(mbuf
, q
, argc
, argv
, res
));
523 return(ml_puts(mbuf
, "div", res
));
529 html_printargs(struct md_mbuf
*mbuf
, int tok
, const char *ns
,
530 const int *argc
, const char **argv
, size_t *res
)
533 if ( ! ml_puts(mbuf
, " class=\"", res
))
535 if ( ! ml_puts(mbuf
, ns
, res
))
537 if ( ! ml_puts(mbuf
, "-", res
))
539 if ( ! ml_puts(mbuf
, toknames
[tok
], res
))
541 return(ml_puts(mbuf
, "\"", res
));
547 html_headtagargs(struct md_mbuf
*mbuf
,
548 const struct md_args
*args
, int tok
,
549 const int *argc
, const char **argv
, size_t *res
)
552 return(html_printargs(mbuf
, tok
, "head", argc
, argv
, res
));
558 html_bodytagargs(struct md_mbuf
*mbuf
,
559 const struct md_args
*args
, int tok
,
560 const int *argc
, const char **argv
, size_t *res
)
563 return(html_printargs(mbuf
, tok
, "body", argc
, argv
, res
));
569 html_blocktagargs(struct md_mbuf
*mbuf
,
570 const struct md_args
*args
, int tok
,
571 const int *argc
, const char **argv
, size_t *res
)
574 return(html_printargs(mbuf
, tok
, "block", argc
, argv
, res
));
580 html_inlinetagargs(struct md_mbuf
*mbuf
,
581 const struct md_args
*args
, int tok
,
582 const int *argc
, const char **argv
, size_t *res
)
585 if ( ! html_printargs(mbuf
, tok
, "inline", argc
, argv
, res
))
591 if ( ! ml_nputs(mbuf
, " href=\"#", 8, res
))
593 if ( ! ml_putstring(mbuf
, *argv
, res
))
595 if ( ! ml_nputs(mbuf
, "\"", 1, res
))
608 html_inlinetagname(struct md_mbuf
*mbuf
,
609 const struct md_args
*args
, int tok
, size_t *res
)
614 return(ml_nputs(mbuf
, "div", 3, res
));
616 return(ml_nputs(mbuf
, "a", 1, res
));
621 return(ml_puts(mbuf
, "span", res
));
626 html_begintag(struct md_mbuf
*mbuf
, void *data
,
627 const struct md_args
*args
, enum md_ns ns
,
628 int tok
, const int *argc
, const char **argv
)
632 struct htmlnode
*node
;
635 assert(ns
!= MD_NS_DEFAULT
);
639 q
= (struct htmlq
*)data
;
641 if (NULL
== (node
= calloc(1, sizeof(struct htmlnode
)))) {
646 node
->parent
= q
->last
;
655 for (i
= 0; ROFF_ARGMAX
!= argc
[i
]
656 && i
< ROFF_MAXLINEARG
; i
++)
657 node
->argc
[i
] = argc
[i
];
658 assert(i
!= ROFF_MAXLINEARG
);
666 if ( ! html_blocktagname(mbuf
, args
, tok
,
667 q
, argc
, argv
, &res
))
669 if ( ! html_blocktagargs(mbuf
, args
, tok
,
674 if ( ! html_bodytagname(mbuf
, args
, tok
,
675 q
, argc
, argv
, &res
))
677 if ( ! html_bodytagargs(mbuf
, args
, tok
,
682 if ( ! html_headtagname(mbuf
, args
, tok
, q
,
685 if ( ! html_headtagargs(mbuf
, args
, tok
,
690 if ( ! html_inlinetagname(mbuf
, args
, tok
, &res
))
692 if ( ! html_inlinetagargs(mbuf
, args
, tok
,
698 return((ssize_t
)res
);
703 html_endtag(struct md_mbuf
*mbuf
, void *data
,
704 const struct md_args
*args
, enum md_ns ns
, int tok
)
708 struct htmlnode
*node
;
710 assert(ns
!= MD_NS_DEFAULT
);
714 q
= (struct htmlq
*)data
;
719 if ( ! html_blocktagname(mbuf
, args
, tok
,
721 (const char **)node
->argv
, &res
))
725 if ( ! html_bodytagname(mbuf
, args
, tok
,
727 (const char **)node
->argv
, &res
))
731 if ( ! html_headtagname(mbuf
, args
, tok
,
733 (const char **)node
->argv
, &res
))
737 if ( ! html_inlinetagname(mbuf
, args
, tok
, &res
))
742 q
->last
= node
->parent
;
746 return((ssize_t
)res
);
754 if (NULL
== (*p
= calloc(1, sizeof(struct htmlq
)))) {
769 q
= (struct htmlq
*)p
;
772 while ((n
= q
->last
)) {
782 html_beginhttp(struct md_mbuf
*mbuf
,
783 const struct md_args
*args
,
784 const char *buf
, size_t sz
)
790 if ( ! ml_puts(mbuf
, "<a href=\"", &res
))
792 if (1 != ml_nputstring(mbuf
, buf
, sz
, &res
))
794 if ( ! ml_puts(mbuf
, "\">", &res
))
797 return((ssize_t
)res
);
802 html_endhttp(struct md_mbuf
*mbuf
,
803 const struct md_args
*args
,
804 const char *buf
, size_t sz
)
810 if ( ! ml_puts(mbuf
, "</a>", &res
))
813 return((ssize_t
)res
);
819 html_beginstring(struct md_mbuf
*mbuf
,
820 const struct md_args
*args
,
821 const char *buf
, size_t sz
)
824 if (0 == strncmp(buf
, "http://", 7))
825 return(html_beginhttp(mbuf
, args
, buf
, sz
));
833 html_endstring(struct md_mbuf
*mbuf
,
834 const struct md_args
*args
,
835 const char *buf
, size_t sz
)
838 if (0 == strncmp(buf
, "http://", 7))
839 return(html_endhttp(mbuf
, args
, buf
, sz
));
846 md_line_html(void *data
, char *buf
)
849 return(mlg_line((struct md_mlg
*)data
, buf
));
854 md_exit_html(void *data
, int flush
)
857 return(mlg_exit((struct md_mlg
*)data
, flush
));
862 md_init_html(const struct md_args
*args
,
863 struct md_mbuf
*mbuf
, const struct md_rbuf
*rbuf
)
867 cbs
.ml_alloc
= html_alloc
;
868 cbs
.ml_free
= html_free
;
869 cbs
.ml_begintag
= html_begintag
;
870 cbs
.ml_endtag
= html_endtag
;
871 cbs
.ml_begin
= html_begin
;
872 cbs
.ml_end
= html_end
;
873 cbs
.ml_beginstring
= html_beginstring
;
874 cbs
.ml_endstring
= html_endstring
;
876 return(mlg_alloc(args
, rbuf
, mbuf
, &cbs
));