Text::Markdown::Discount
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

103 lines
2.3 KiB

  1. /*
  2. * toc -- spit out a table of contents based on header blocks
  3. *
  4. * Copyright (C) 2008 Jjgod Jiang, David L Parsons.
  5. * The redistribution terms are provided in the COPYRIGHT file that must
  6. * be distributed with this source code.
  7. */
  8. #include "config.h"
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <ctype.h>
  12. #include "cstring.h"
  13. #include "markdown.h"
  14. #include "amalloc.h"
  15. /* write an header index
  16. */
  17. int
  18. mkd_toc(Document *p, char **doc)
  19. {
  20. Paragraph *tp, *srcp;
  21. int last_hnumber = 0;
  22. Cstring res;
  23. int size;
  24. if ( !(doc && p && p->ctx) ) return -1;
  25. *doc = 0;
  26. if ( ! (p->ctx->flags & MKD_TOC) ) return 0;
  27. CREATE(res);
  28. RESERVE(res, 100);
  29. for ( tp = p->code; tp ; tp = tp->next ) {
  30. if ( tp->typ == SOURCE ) {
  31. for ( srcp = tp->down; srcp; srcp = srcp->next ) {
  32. if ( srcp->typ == HDR && srcp->text ) {
  33. if ( last_hnumber >= srcp->hnumber ) {
  34. while ( last_hnumber > srcp->hnumber ) {
  35. Csprintf(&res, "%*s</ul></li>\n", last_hnumber-1,"");
  36. --last_hnumber;
  37. }
  38. }
  39. while ( srcp->hnumber > last_hnumber ) {
  40. Csprintf(&res, "%*s%s<ul>\n", last_hnumber, "",
  41. last_hnumber ? "<li>" : "");
  42. ++last_hnumber;
  43. }
  44. Csprintf(&res, "%*s<li><a href=\"#", srcp->hnumber, "");
  45. mkd_string_to_anchor(T(srcp->text->text),
  46. S(srcp->text->text),
  47. (mkd_sta_function_t)Csputc, &res,1);
  48. Csprintf(&res, "\">");
  49. mkd_string_to_anchor(T(srcp->text->text),
  50. S(srcp->text->text),
  51. (mkd_sta_function_t)Csputc, &res,0);
  52. Csprintf(&res, "</a>");
  53. Csprintf(&res, "</li>\n");
  54. }
  55. }
  56. }
  57. }
  58. while ( last_hnumber > 0 ) {
  59. --last_hnumber;
  60. Csprintf(&res, last_hnumber ? "%*s</ul></li>\n" : "%*s</ul>\n", last_hnumber, "");
  61. }
  62. if ( (size = S(res)) > 0 ) {
  63. EXPAND(res) = 0;
  64. /* HACK ALERT! HACK ALERT! HACK ALERT! */
  65. *doc = T(res); /* we know that a T(Cstring) is a character pointer
  66. * so we can simply pick it up and carry it away,
  67. * leaving the husk of the Ctring on the stack
  68. * END HACK ALERT
  69. */
  70. }
  71. else
  72. DELETE(res);
  73. return size;
  74. }
  75. /* write an header index
  76. */
  77. int
  78. mkd_generatetoc(Document *p, FILE *out)
  79. {
  80. char *buf = 0;
  81. int sz = mkd_toc(p, &buf);
  82. int ret = EOF;
  83. if ( sz > 0 )
  84. ret = fwrite(buf, 1, sz, out);
  85. if ( buf ) free(buf);
  86. return (ret == sz) ? ret : EOF;
  87. }