]>
git.cameronkatri.com Git - mandoc.git/blob - html.c
1 /* $Id: html.c,v 1.19 2008/12/10 00:52:46 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 /* TODO: allow head/tail-less invocations (just "div" start). */
38 int argc
[ROFF_MAXLINEARG
];
39 char *argv
[ROFF_MAXLINEARG
];
40 struct htmlnode
*parent
;
44 struct htmlnode
*last
;
48 static int html_loadcss(struct md_mbuf
*,
50 static int html_alloc(void **);
51 static void html_free(void *);
52 static ssize_t
html_endtag(struct md_mbuf
*, void *,
53 const struct md_args
*,
55 static ssize_t
html_beginstring(struct md_mbuf
*,
56 const struct md_args
*,
57 const char *, size_t);
58 static ssize_t
html_beginhttp(struct md_mbuf
*,
59 const struct md_args
*,
60 const char *, size_t);
61 static ssize_t
html_endstring(struct md_mbuf
*,
62 const struct md_args
*,
63 const char *, size_t);
64 static ssize_t
html_endhttp(struct md_mbuf
*,
65 const struct md_args
*,
66 const char *, size_t);
67 static ssize_t
html_begintag(struct md_mbuf
*, void *,
68 const struct md_args
*,
70 const int *, const char **);
71 static int html_begin(struct md_mbuf
*,
72 const struct md_args
*,
74 const char *, const char *,
75 enum roffmsec
, const char *);
76 static int html_printargs(struct md_mbuf
*, int,
77 const char *, const int *,
78 const char **, size_t *);
79 static int html_end(struct md_mbuf
*,
80 const struct md_args
*);
81 static int html_blocktagname(struct md_mbuf
*,
82 const struct md_args
*, int,
83 struct htmlq
*, const int *,
84 const char **, size_t *);
85 static int html_blocktagargs(struct md_mbuf
*,
86 const struct md_args
*, int,
87 const int *, const char **, size_t *);
88 static int html_headtagname(struct md_mbuf
*,
89 const struct md_args
*, int,
90 struct htmlq
*, const int *,
91 const char **, size_t *);
92 static int html_headtagargs(struct md_mbuf
*,
93 const struct md_args
*, int,
94 const int *, const char **, size_t *);
95 static int html_bodytagname(struct md_mbuf
*,
96 const struct md_args
*,
97 int, struct htmlq
*, const int *,
98 const char **, size_t *);
99 static int html_bodytagargs(struct md_mbuf
*,
100 const struct md_args
*, int,
101 const int *, const char **, size_t *);
102 static int html_inlinetagname(struct md_mbuf
*,
103 const struct md_args
*, int, size_t *);
104 static int html_inlinetagargs(struct md_mbuf
*,
105 const struct md_args
*, int,
106 const int *, const char **, size_t *);
107 static int html_Bl_bodytagname(struct md_mbuf
*,
108 struct htmlq
*, const int *,
109 const char **, size_t *);
110 static int html_It_blocktagname(struct md_mbuf
*,
111 struct htmlq
*, const int *,
112 const char **, size_t *);
113 static int html_It_headtagname(struct md_mbuf
*,
114 struct htmlq
*, const int *,
115 const char **, size_t *);
116 static int html_It_bodytagname(struct md_mbuf
*,
117 struct htmlq
*, const int *,
118 const char **, size_t *);
119 static int html_tputln(struct md_mbuf
*,
120 enum ml_scope
, int, enum html_tag
);
121 static int html_aputln(struct md_mbuf
*, enum ml_scope
,
123 int, const struct html_pair
*);
128 html_It_headtagname(struct md_mbuf
*mbuf
, struct htmlq
*q
,
129 const int *argc
, const char **argv
, size_t *res
)
134 for (n
= q
->last
; n
; n
= n
->parent
)
135 if (n
->tok
== ROFF_Bl
)
141 for (i
= 0; ROFF_ARGMAX
!= n
->argc
[i
] &&
142 i
< ROFF_MAXLINEARG
; i
++) {
143 switch (n
->argc
[i
]) {
145 return(html_stput(mbuf
, HTML_TAG_DIV
, res
));
149 return(html_stput(mbuf
, HTML_TAG_TD
, res
));
161 html_It_bodytagname(struct md_mbuf
*mbuf
, struct htmlq
*q
,
162 const int *argc
, const char **argv
, size_t *res
)
167 for (n
= q
->last
; n
; n
= n
->parent
)
168 if (n
->tok
== ROFF_Bl
)
174 for (i
= 0; ROFF_ARGMAX
!= n
->argc
[i
] &&
175 i
< ROFF_MAXLINEARG
; i
++) {
176 switch (n
->argc
[i
]) {
194 return(html_stput(mbuf
, HTML_TAG_DIV
, res
));
198 return(html_stput(mbuf
, HTML_TAG_TD
, res
));
204 assert(i
!= ROFF_MAXLINEARG
);
211 html_Bl_bodytagname(struct md_mbuf
*mbuf
, struct htmlq
*q
,
212 const int *argc
, const char **argv
, size_t *res
)
216 for (i
= 0; ROFF_ARGMAX
!= argc
[i
]
217 && i
< ROFF_MAXLINEARG
; i
++) {
220 return(html_stput(mbuf
, HTML_TAG_OL
, res
));
236 return(html_stput(mbuf
, HTML_TAG_UL
, res
));
240 return(html_stput(mbuf
, HTML_TAG_TABLE
, res
));
246 assert(i
!= ROFF_MAXLINEARG
);
253 html_It_blocktagname(struct md_mbuf
*mbuf
, struct htmlq
*q
,
254 const int *argc
, const char **argv
, size_t *res
)
259 for (n
= q
->last
; n
; n
= n
->parent
)
260 if (n
->tok
== ROFF_Bl
)
266 for (i
= 0; ROFF_ARGMAX
!= n
->argc
[i
] &&
267 i
< ROFF_MAXLINEARG
; i
++) {
268 switch (n
->argc
[i
]) {
286 return(html_stput(mbuf
, HTML_TAG_LI
, res
));
290 return(html_stput(mbuf
, HTML_TAG_TR
, res
));
296 assert(i
!= ROFF_MAXLINEARG
);
302 html_loadcss(struct md_mbuf
*mbuf
, const char *css
)
314 if (-1 == (fd
= open(css
, O_RDONLY
, 0))) {
319 if (-1 == fstat(fd
, &st
)) {
324 bufsz
= MAX(st
.st_blksize
, BUFSIZ
);
325 if (NULL
== (buf
= malloc(bufsz
))) {
331 if (-1 == (ssz
= read(fd
, buf
, bufsz
))) {
336 if ( ! ml_nputs(mbuf
, buf
, (size_t)ssz
, &res
))
343 if (-1 == close(fd
)) {
356 html_tputln(struct md_mbuf
*mbuf
, enum ml_scope scope
,
357 int i
, enum html_tag tag
)
360 if ( ! ml_putchars(mbuf
, ' ', INDENT(i
) * INDENT_SZ
, NULL
))
362 if ( ! html_tput(mbuf
, scope
, tag
, NULL
))
364 return(ml_nputs(mbuf
, "\n", 1, NULL
));
369 html_aputln(struct md_mbuf
*mbuf
, enum ml_scope scope
, int i
,
370 enum html_tag tag
, int sz
, const struct html_pair
*p
)
373 if ( ! ml_putchars(mbuf
, ' ', INDENT(i
) * INDENT_SZ
, NULL
))
375 if ( ! html_aput(mbuf
, scope
, tag
, NULL
, sz
, p
))
377 return(ml_nputs(mbuf
, "\n", 1, NULL
));
383 html_begin(struct md_mbuf
*mbuf
, const struct md_args
*args
,
384 const struct tm
*tm
, const char *os
,
385 const char *name
, enum roffmsec msec
, const char *vol
)
387 struct html_pair attr
[4];
391 (void)snprintf(ts
, sizeof(ts
), "%s(%s)",
392 name
, roff_msecname(msec
));
396 if ( ! html_typeput(mbuf
, HTML_TYPE_4_01_STRICT
, NULL
))
398 if ( ! html_tputln(mbuf
, ML_OPEN
, i
, HTML_TAG_HTML
))
400 if ( ! html_tputln(mbuf
, ML_OPEN
, i
++, HTML_TAG_HEAD
))
403 attr
[0].attr
= HTML_ATTR_HTTP_EQUIV
;
404 attr
[0].val
= "content-type";
405 attr
[1].attr
= HTML_ATTR_CONTENT
;
406 attr
[1].val
= "text/html;charset=utf-8";
408 if ( ! html_aputln(mbuf
, ML_OPEN
, i
, HTML_TAG_META
, 2, attr
))
411 attr
[0].attr
= HTML_ATTR_NAME
;
412 attr
[0].val
= "resource-type";
413 attr
[1].attr
= HTML_ATTR_CONTENT
;
414 attr
[1].val
= "document";
416 if ( ! html_aputln(mbuf
, ML_OPEN
, i
, HTML_TAG_META
, 2, attr
))
419 if ( ! html_tputln(mbuf
, ML_OPEN
, i
, HTML_TAG_TITLE
))
421 if ( ! ml_putstring(mbuf
, ts
, NULL
))
423 if ( ! html_tputln(mbuf
, ML_CLOSE
, i
, HTML_TAG_TITLE
))
426 if (HTML_CSS_EMBED
& args
->params
.html
.flags
) {
427 attr
[0].attr
= HTML_ATTR_TYPE
;
428 attr
[0].val
= "text/css";
430 if ( ! html_aputln(mbuf
, ML_OPEN
, i
,
431 HTML_TAG_STYLE
, 1, attr
))
433 if ( ! html_commentput(mbuf
, ML_OPEN
, NULL
))
436 if ( ! html_loadcss(mbuf
, args
->params
.html
.css
))
439 if ( ! html_commentput(mbuf
, ML_CLOSE
, NULL
))
441 if ( ! html_tputln(mbuf
, ML_CLOSE
, i
, HTML_TAG_STYLE
))
444 attr
[0].attr
= HTML_ATTR_REL
;
445 attr
[0].val
= "stylesheet";
446 attr
[1].attr
= HTML_ATTR_TYPE
;
447 attr
[1].val
= "text/css";
448 attr
[2].attr
= HTML_ATTR_HREF
;
449 attr
[2].val
= args
->params
.html
.css
;
451 if ( ! html_aputln(mbuf
, ML_OPEN
, i
,
452 HTML_TAG_LINK
, 3, attr
))
456 if ( ! html_tputln(mbuf
, ML_CLOSE
, --i
, HTML_TAG_HEAD
))
458 if ( ! html_tputln(mbuf
, ML_OPEN
, i
, HTML_TAG_BODY
))
461 attr
[0].attr
= HTML_ATTR_CLASS
;
462 attr
[0].val
= "mdoc";
464 if ( ! html_aputln(mbuf
, ML_OPEN
, i
, HTML_TAG_DIV
, 1, attr
))
467 attr
[0].attr
= HTML_ATTR_WIDTH
;
468 attr
[0].val
= "100%";
470 if ( ! html_aputln(mbuf
, ML_OPEN
, i
++, HTML_TAG_TABLE
, 1, attr
))
472 if ( ! html_tputln(mbuf
, ML_OPEN
, i
++, HTML_TAG_TR
))
475 if ( ! html_tputln(mbuf
, ML_OPEN
, i
, HTML_TAG_TD
))
477 if ( ! ml_putstring(mbuf
, ts
, NULL
))
479 if ( ! html_tputln(mbuf
, ML_CLOSE
, i
, HTML_TAG_TD
))
482 if ( ! html_tputln(mbuf
, ML_OPEN
, i
, HTML_TAG_TD
))
485 if ( ! html_tputln(mbuf
, ML_CLOSE
, i
, HTML_TAG_TD
))
488 if ( ! html_tputln(mbuf
, ML_OPEN
, i
, HTML_TAG_TD
))
490 if ( ! ml_putstring(mbuf
, ts
, NULL
))
492 if ( ! html_tputln(mbuf
, ML_CLOSE
, i
, HTML_TAG_TD
))
495 if ( ! html_tputln(mbuf
, ML_CLOSE
, --i
, HTML_TAG_TR
))
497 return(html_tputln(mbuf
, ML_CLOSE
, --i
, HTML_TAG_TABLE
));
503 html_end(struct md_mbuf
*mbuf
, const struct md_args
*args
)
506 if ( ! html_tputln(mbuf
, ML_CLOSE
, 0, HTML_TAG_DIV
))
508 if ( ! html_tputln(mbuf
, ML_CLOSE
, 0, HTML_TAG_BODY
))
510 return(html_tputln(mbuf
, ML_CLOSE
, 0, HTML_TAG_HTML
));
516 html_bodytagname(struct md_mbuf
*mbuf
,
517 const struct md_args
*args
, int tok
, struct htmlq
*q
,
518 const int *argc
, const char **argv
, size_t *res
)
523 return(html_Bl_bodytagname(mbuf
, q
, argc
, argv
, res
));
525 return(html_stput(mbuf
, HTML_TAG_SPAN
, res
));
527 return(html_It_bodytagname(mbuf
, q
, argc
, argv
, res
));
529 return(html_stput(mbuf
, HTML_TAG_SPAN
, res
));
534 return(html_stput(mbuf
, HTML_TAG_DIV
, res
));
540 html_headtagname(struct md_mbuf
*mbuf
,
541 const struct md_args
*args
, int tok
, struct htmlq
*q
,
542 const int *argc
, const char **argv
, size_t *res
)
547 return(html_It_headtagname(mbuf
, q
, argc
, argv
, res
));
551 return(html_stput(mbuf
, HTML_TAG_SPAN
, res
));
553 return(html_stput(mbuf
, HTML_TAG_H1
, res
));
555 return(html_stput(mbuf
, HTML_TAG_H2
, res
));
560 return(html_stput(mbuf
, HTML_TAG_DIV
, res
));
566 html_blocktagname(struct md_mbuf
*mbuf
, const struct md_args
*args
,
567 int tok
, struct htmlq
*q
, const int *argc
,
568 const char **argv
, size_t *res
)
575 return(html_stput(mbuf
, HTML_TAG_SPAN
, res
));
577 return(html_It_blocktagname(mbuf
, q
, argc
, argv
, res
));
582 return(html_stput(mbuf
, HTML_TAG_DIV
, res
));
588 html_printargs(struct md_mbuf
*mbuf
, int tok
, const char *ns
,
589 const int *argc
, const char **argv
, size_t *res
)
592 /* FIXME: use API in ml.h. */
594 if ( ! ml_puts(mbuf
, " class=\"", res
))
596 if ( ! ml_puts(mbuf
, ns
, res
))
598 if ( ! ml_puts(mbuf
, "-", res
))
600 if ( ! ml_puts(mbuf
, toknames
[tok
], res
))
602 return(ml_puts(mbuf
, "\"", res
));
608 html_headtagargs(struct md_mbuf
*mbuf
,
609 const struct md_args
*args
, int tok
,
610 const int *argc
, const char **argv
, size_t *res
)
613 return(html_printargs(mbuf
, tok
, "head", argc
, argv
, res
));
619 html_bodytagargs(struct md_mbuf
*mbuf
,
620 const struct md_args
*args
, int tok
,
621 const int *argc
, const char **argv
, size_t *res
)
624 return(html_printargs(mbuf
, tok
, "body", argc
, argv
, res
));
630 html_blocktagargs(struct md_mbuf
*mbuf
,
631 const struct md_args
*args
, int tok
,
632 const int *argc
, const char **argv
, size_t *res
)
635 return(html_printargs(mbuf
, tok
, "block", argc
, argv
, res
));
641 html_inlinetagargs(struct md_mbuf
*mbuf
,
642 const struct md_args
*args
, int tok
,
643 const int *argc
, const char **argv
, size_t *res
)
646 if ( ! html_printargs(mbuf
, tok
, "inline", argc
, argv
, res
))
652 /* FIXME: use API in ml.h. */
655 if ( ! ml_nputs(mbuf
, " href=\"#", 8, res
))
657 if ( ! ml_putstring(mbuf
, *argv
, res
))
659 if ( ! ml_nputs(mbuf
, "\"", 1, res
))
672 html_inlinetagname(struct md_mbuf
*mbuf
,
673 const struct md_args
*args
, int tok
, size_t *res
)
678 return(html_stput(mbuf
, HTML_TAG_DIV
, res
));
680 return(html_stput(mbuf
, HTML_TAG_A
, res
));
685 return(html_stput(mbuf
, HTML_TAG_SPAN
, res
));
690 html_begintag(struct md_mbuf
*mbuf
, void *data
,
691 const struct md_args
*args
, enum md_ns ns
,
692 int tok
, const int *argc
, const char **argv
)
696 struct htmlnode
*node
;
699 assert(ns
!= MD_NS_DEFAULT
);
703 q
= (struct htmlq
*)data
;
705 if (NULL
== (node
= calloc(1, sizeof(struct htmlnode
)))) {
710 node
->parent
= q
->last
;
719 for (i
= 0; ROFF_ARGMAX
!= argc
[i
]
720 && i
< ROFF_MAXLINEARG
; i
++)
721 node
->argc
[i
] = argc
[i
];
722 assert(i
!= ROFF_MAXLINEARG
);
730 if ( ! html_blocktagname(mbuf
, args
, tok
,
731 q
, argc
, argv
, &res
))
733 if ( ! html_blocktagargs(mbuf
, args
, tok
,
738 if ( ! html_bodytagname(mbuf
, args
, tok
,
739 q
, argc
, argv
, &res
))
741 if ( ! html_bodytagargs(mbuf
, args
, tok
,
746 if ( ! html_headtagname(mbuf
, args
, tok
, q
,
749 if ( ! html_headtagargs(mbuf
, args
, tok
,
754 if ( ! html_inlinetagname(mbuf
, args
, tok
, &res
))
756 if ( ! html_inlinetagargs(mbuf
, args
, tok
,
762 return((ssize_t
)res
);
767 html_endtag(struct md_mbuf
*mbuf
, void *data
,
768 const struct md_args
*args
, enum md_ns ns
, int tok
)
772 struct htmlnode
*node
;
774 assert(ns
!= MD_NS_DEFAULT
);
778 q
= (struct htmlq
*)data
;
783 if ( ! html_blocktagname(mbuf
, args
, tok
,
785 (const char **)node
->argv
, &res
))
789 if ( ! html_bodytagname(mbuf
, args
, tok
,
791 (const char **)node
->argv
, &res
))
795 if ( ! html_headtagname(mbuf
, args
, tok
,
797 (const char **)node
->argv
, &res
))
801 if ( ! html_inlinetagname(mbuf
, args
, tok
, &res
))
806 q
->last
= node
->parent
;
810 return((ssize_t
)res
);
818 if (NULL
== (*p
= calloc(1, sizeof(struct htmlq
)))) {
833 q
= (struct htmlq
*)p
;
836 while ((n
= q
->last
)) {
846 html_beginhttp(struct md_mbuf
*mbuf
,
847 const struct md_args
*args
,
848 const char *buf
, size_t sz
)
851 struct html_pair pair
;
854 pair
.attr
= HTML_ATTR_HREF
;
855 pair
.val
= (char *)buf
;
857 if ( ! html_aput(mbuf
, ML_OPEN
, HTML_TAG_A
, &res
, 1, &pair
))
859 return((ssize_t
)res
);
864 html_endhttp(struct md_mbuf
*mbuf
,
865 const struct md_args
*args
,
866 const char *buf
, size_t sz
)
871 if ( ! html_tput(mbuf
, ML_CLOSE
, HTML_TAG_A
, &res
))
873 return((ssize_t
)res
);
879 html_beginstring(struct md_mbuf
*mbuf
,
880 const struct md_args
*args
,
881 const char *buf
, size_t sz
)
884 if (0 == strncmp(buf
, "http://", 7))
885 return(html_beginhttp(mbuf
, args
, buf
, sz
));
893 html_endstring(struct md_mbuf
*mbuf
,
894 const struct md_args
*args
,
895 const char *buf
, size_t sz
)
898 if (0 == strncmp(buf
, "http://", 7))
899 return(html_endhttp(mbuf
, args
, buf
, sz
));
906 md_line_html(void *data
, char *buf
)
909 return(mlg_line((struct md_mlg
*)data
, buf
));
914 md_exit_html(void *data
, int flush
)
917 return(mlg_exit((struct md_mlg
*)data
, flush
));
922 md_init_html(const struct md_args
*args
,
923 struct md_mbuf
*mbuf
, const struct md_rbuf
*rbuf
)
927 cbs
.ml_alloc
= html_alloc
;
928 cbs
.ml_free
= html_free
;
929 cbs
.ml_begintag
= html_begintag
;
930 cbs
.ml_endtag
= html_endtag
;
931 cbs
.ml_begin
= html_begin
;
932 cbs
.ml_end
= html_end
;
933 cbs
.ml_beginstring
= html_beginstring
;
934 cbs
.ml_endstring
= html_endstring
;
936 return(mlg_alloc(args
, rbuf
, mbuf
, &cbs
));