aboutsummaryrefslogtreecommitdiff
path: root/wrapper.lua
blob: 11c5183280ddb0969df2ef9941dbe8b61eca6a70 (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 inp = io.read("*all")
  86. local doc = cmark.cmark_parse_document(inp, string.len(inp))
  87. local cur = doc
  88. local next
  89. local child
  90. local walk = function(action)
  91. level = 0
  92. while cur ~= nil do
  93. action(cur, level)
  94. child = cmark.cmark_node_first_child(cur)
  95. if child == nil then
  96. next = cmark.cmark_node_next(cur)
  97. while next == nil do
  98. cur = cmark.cmark_node_parent(cur)
  99. level = level - 1
  100. if cur == nil then
  101. break
  102. else
  103. next = cmark.cmark_node_next(cur)
  104. end
  105. end
  106. cur = next
  107. else
  108. level = level + 1
  109. cur = child
  110. end
  111. end
  112. end
  113. local type_table = {
  114. 'BLOCK_QUOTE',
  115. 'LIST',
  116. 'LIST_ITEM',
  117. 'CODE_BLOCK',
  118. 'HTML',
  119. 'PARAGRAPH',
  120. 'HEADER',
  121. 'HRULE',
  122. 'REFERENCE_DEF',
  123. 'TEXT',
  124. 'SOFTBREAK',
  125. 'LINEBREAK',
  126. 'INLINE_CODE',
  127. 'INLINE_HTML',
  128. 'EMPH',
  129. 'STRONG',
  130. 'LINK',
  131. 'IMAGE',
  132. }
  133. type_table[0] = 'DOCUMENT'
  134. local function print_type(node, level)
  135. local t = tonumber(cmark.cmark_node_get_type(node))
  136. io.write(string.rep(' ', level) .. type_table[t])
  137. if t == cmark.CMARK_NODE_TEXT then
  138. io.write(' ' .. ffi.string(cmark.cmark_node_get_string_content(node)))
  139. end
  140. io.write('\n')
  141. end
  142. walk(print_type)
  143. -- local html = ffi.string(cmark.cmark_render_html(doc))
  144. -- print(html)