aboutsummaryrefslogtreecommitdiff
path: root/wrapper.lua
blob: d89ebc98fd0eeab29acc76087e86a1e37f2f2400 (plain)
  1. #!/usr/bin/env luajit
  2. local ffi = require("ffi")
  3. cmark = ffi.load("libcmark")
  4. ffi.cdef[[
  5. char *cmark_markdown_to_html(const char *text, int len);
  6. typedef enum {
  7. /* Block */
  8. CMARK_NODE_DOCUMENT,
  9. CMARK_NODE_BLOCK_QUOTE,
  10. CMARK_NODE_LIST,
  11. CMARK_NODE_LIST_ITEM,
  12. CMARK_NODE_CODE_BLOCK,
  13. CMARK_NODE_HTML,
  14. CMARK_NODE_PARAGRAPH,
  15. CMARK_NODE_HEADER,
  16. CMARK_NODE_HRULE,
  17. CMARK_NODE_REFERENCE_DEF,
  18. CMARK_NODE_FIRST_BLOCK = CMARK_NODE_DOCUMENT,
  19. CMARK_NODE_LAST_BLOCK = CMARK_NODE_REFERENCE_DEF,
  20. /* Inline */
  21. CMARK_NODE_TEXT,
  22. CMARK_NODE_SOFTBREAK,
  23. CMARK_NODE_LINEBREAK,
  24. CMARK_NODE_INLINE_CODE,
  25. CMARK_NODE_INLINE_HTML,
  26. CMARK_NODE_EMPH,
  27. CMARK_NODE_STRONG,
  28. CMARK_NODE_LINK,
  29. CMARK_NODE_IMAGE,
  30. CMARK_NODE_FIRST_INLINE = CMARK_NODE_TEXT,
  31. CMARK_NODE_LAST_INLINE = CMARK_NODE_IMAGE,
  32. } cmark_node_type;
  33. typedef enum {
  34. CMARK_NO_LIST,
  35. CMARK_BULLET_LIST,
  36. CMARK_ORDERED_LIST
  37. } cmark_list_type;
  38. typedef enum {
  39. CMARK_PERIOD_DELIM,
  40. CMARK_PAREN_DELIM
  41. } cmark_delim_type;
  42. typedef struct cmark_node cmark_node;
  43. typedef struct cmark_parser cmark_parser;
  44. cmark_node* cmark_node_new(cmark_node_type type);
  45. void
  46. cmark_node_free(cmark_node *node);
  47. cmark_node* cmark_node_next(cmark_node *node);
  48. cmark_node* cmark_node_previous(cmark_node *node);
  49. cmark_node* cmark_node_parent(cmark_node *node);
  50. cmark_node* cmark_node_first_child(cmark_node *node);
  51. cmark_node* cmark_node_last_child(cmark_node *node);
  52. cmark_node_type cmark_node_get_type(cmark_node *node);
  53. const char* cmark_node_get_string_content(cmark_node *node);
  54. int cmark_node_set_string_content(cmark_node *node, const char *content);
  55. int cmark_node_get_header_level(cmark_node *node);
  56. int cmark_node_set_header_level(cmark_node *node, int level);
  57. cmark_list_type cmark_node_get_list_type(cmark_node *node);
  58. int cmark_node_set_list_type(cmark_node *node, cmark_list_type type);
  59. int cmark_node_get_list_start(cmark_node *node);
  60. int cmark_node_set_list_start(cmark_node *node, int start);
  61. int cmark_node_get_list_tight(cmark_node *node);
  62. int cmark_node_set_list_tight(cmark_node *node, int tight);
  63. const char* cmark_node_get_fence_info(cmark_node *node);
  64. int cmark_node_set_fence_info(cmark_node *node, const char *info);
  65. const char* cmark_node_get_url(cmark_node *node);
  66. int cmark_node_set_url(cmark_node *node, const char *url);
  67. const char* cmark_node_get_title(cmark_node *node);
  68. int cmark_node_set_title(cmark_node *node, const char *title);
  69. int cmark_node_get_start_line(cmark_node *node);
  70. int cmark_node_get_start_column(cmark_node *node);
  71. int cmark_node_get_end_line(cmark_node *node);
  72. void cmark_node_unlink(cmark_node *node);
  73. int cmark_node_insert_before(cmark_node *node, cmark_node *sibling);
  74. int cmark_node_insert_after(cmark_node *node, cmark_node *sibling);
  75. int cmark_node_prepend_child(cmark_node *node, cmark_node *child);
  76. int cmark_node_append_child(cmark_node *node, cmark_node *child);
  77. cmark_parser *cmark_parser_new();
  78. void cmark_parser_free(cmark_parser *parser);
  79. cmark_node *cmark_parser_finish(cmark_parser *parser);
  80. void cmark_parser_feed(cmark_parser *parser, const char *buffer, size_t len);
  81. cmark_node *cmark_parse_document(const char *buffer, size_t len);
  82. char *cmark_render_ast(cmark_node *root);
  83. char *cmark_render_html(cmark_node *root);
  84. ]]
  85. local doc = cmark.cmark_parse_document("hi *there*", 10)
  86. local cur = doc
  87. local next
  88. local child
  89. local walk = function(action)
  90. level = 0
  91. while cur ~= nil do
  92. action(cur, level)
  93. child = cmark.cmark_node_first_child(cur)
  94. if child == nil then
  95. next = cmark.cmark_node_next(cur)
  96. while next == nil do
  97. cur = cmark.cmark_node_parent(cur)
  98. level = level - 1
  99. if cur == nil then
  100. break
  101. else
  102. next = cmark.cmark_node_next(cur)
  103. end
  104. end
  105. cur = next
  106. else
  107. level = level + 1
  108. cur = child
  109. end
  110. end
  111. end
  112. local type_table = {
  113. 'BLOCK_QUOTE',
  114. 'LIST',
  115. 'LIST_ITEM',
  116. 'CODE_BLOCK',
  117. 'HTML',
  118. 'PARAGRAPH',
  119. 'HEADER',
  120. 'HRULE',
  121. 'REFERENCE_DEF',
  122. 'TEXT',
  123. 'SOFTBREAK',
  124. 'LINEBREAK',
  125. 'INLINE_CODE',
  126. 'INLINE_HTML',
  127. 'EMPH',
  128. 'STRONG',
  129. 'LINK',
  130. 'IMAGE',
  131. }
  132. type_table[0] = 'DOCUMENT'
  133. local function print_type(node, level)
  134. local t = tonumber(cmark.cmark_node_get_type(node))
  135. io.write(string.rep(' ', level) .. type_table[t])
  136. if t == cmark.CMARK_NODE_TEXT then
  137. io.write(' ' .. ffi.string(cmark.cmark_node_get_string_content(node)))
  138. end
  139. io.write('\n')
  140. end
  141. walk(print_type)
  142. local t1 = cmark.cmark_node_get_type(doc)
  143. print(t1 == cmark.CMARK_NODE_DOCUMENT)
  144. local html = ffi.string(cmark.cmark_render_html(doc))
  145. print(html)