~ultradvorka/+junk/mindforger

« back to all changes in this revision

Viewing changes to deps/cmark/src/xml.c

  • Committer: Martin Dvorak (Dvorka)
  • Date: 2018-06-13 20:11:59 UTC
  • Revision ID: martin.dvorak@mindforger.com-20180613201159-r20v2aelwr8x8mb5
Update for mindforger_1.42.6 at 2018-06-13--22-11-36.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <stdlib.h>
 
2
#include <stdio.h>
 
3
#include <string.h>
 
4
#include <assert.h>
 
5
 
 
6
#include "config.h"
 
7
#include "cmark.h"
 
8
#include "node.h"
 
9
#include "buffer.h"
 
10
#include "houdini.h"
 
11
 
 
12
#define BUFFER_SIZE 100
 
13
 
 
14
// Functions to convert cmark_nodes to XML strings.
 
15
 
 
16
static void escape_xml(cmark_strbuf *dest, const unsigned char *source,
 
17
                       bufsize_t length) {
 
18
  houdini_escape_html0(dest, source, length, 0);
 
19
}
 
20
 
 
21
struct render_state {
 
22
  cmark_strbuf *xml;
 
23
  int indent;
 
24
};
 
25
 
 
26
static CMARK_INLINE void indent(struct render_state *state) {
 
27
  int i;
 
28
  for (i = 0; i < state->indent; i++) {
 
29
    cmark_strbuf_putc(state->xml, ' ');
 
30
  }
 
31
}
 
32
 
 
33
static int S_render_node(cmark_node *node, cmark_event_type ev_type,
 
34
                         struct render_state *state, int options) {
 
35
  cmark_strbuf *xml = state->xml;
 
36
  bool literal = false;
 
37
  cmark_delim_type delim;
 
38
  bool entering = (ev_type == CMARK_EVENT_ENTER);
 
39
  char buffer[BUFFER_SIZE];
 
40
 
 
41
  if (entering) {
 
42
    indent(state);
 
43
    cmark_strbuf_putc(xml, '<');
 
44
    cmark_strbuf_puts(xml, cmark_node_get_type_string(node));
 
45
 
 
46
    if (options & CMARK_OPT_SOURCEPOS && node->start_line != 0) {
 
47
      snprintf(buffer, BUFFER_SIZE, " sourcepos=\"%d:%d-%d:%d\"",
 
48
               node->start_line, node->start_column, node->end_line,
 
49
               node->end_column);
 
50
      cmark_strbuf_puts(xml, buffer);
 
51
    }
 
52
 
 
53
    literal = false;
 
54
 
 
55
    switch (node->type) {
 
56
    case CMARK_NODE_DOCUMENT:
 
57
      cmark_strbuf_puts(xml, " xmlns=\"http://commonmark.org/xml/1.0\"");
 
58
      break;
 
59
    case CMARK_NODE_TEXT:
 
60
    case CMARK_NODE_CODE:
 
61
    case CMARK_NODE_HTML_BLOCK:
 
62
    case CMARK_NODE_HTML_INLINE:
 
63
      cmark_strbuf_puts(xml, ">");
 
64
      escape_xml(xml, node->as.literal.data, node->as.literal.len);
 
65
      cmark_strbuf_puts(xml, "</");
 
66
      cmark_strbuf_puts(xml, cmark_node_get_type_string(node));
 
67
      literal = true;
 
68
      break;
 
69
    case CMARK_NODE_LIST:
 
70
      switch (cmark_node_get_list_type(node)) {
 
71
      case CMARK_ORDERED_LIST:
 
72
        cmark_strbuf_puts(xml, " type=\"ordered\"");
 
73
        snprintf(buffer, BUFFER_SIZE, " start=\"%d\"",
 
74
                 cmark_node_get_list_start(node));
 
75
        cmark_strbuf_puts(xml, buffer);
 
76
        delim = cmark_node_get_list_delim(node);
 
77
        if (delim == CMARK_PAREN_DELIM) {
 
78
          cmark_strbuf_puts(xml, " delim=\"paren\"");
 
79
        } else if (delim == CMARK_PERIOD_DELIM) {
 
80
          cmark_strbuf_puts(xml, " delim=\"period\"");
 
81
        }
 
82
        break;
 
83
      case CMARK_BULLET_LIST:
 
84
        cmark_strbuf_puts(xml, " type=\"bullet\"");
 
85
        break;
 
86
      default:
 
87
        break;
 
88
      }
 
89
      snprintf(buffer, BUFFER_SIZE, " tight=\"%s\"",
 
90
               (cmark_node_get_list_tight(node) ? "true" : "false"));
 
91
      cmark_strbuf_puts(xml, buffer);
 
92
      break;
 
93
    case CMARK_NODE_HEADING:
 
94
      snprintf(buffer, BUFFER_SIZE, " level=\"%d\"", node->as.heading.level);
 
95
      cmark_strbuf_puts(xml, buffer);
 
96
      break;
 
97
    case CMARK_NODE_CODE_BLOCK:
 
98
      if (node->as.code.info.len > 0) {
 
99
        cmark_strbuf_puts(xml, " info=\"");
 
100
        escape_xml(xml, node->as.code.info.data, node->as.code.info.len);
 
101
        cmark_strbuf_putc(xml, '"');
 
102
      }
 
103
      cmark_strbuf_puts(xml, ">");
 
104
      escape_xml(xml, node->as.code.literal.data, node->as.code.literal.len);
 
105
      cmark_strbuf_puts(xml, "</");
 
106
      cmark_strbuf_puts(xml, cmark_node_get_type_string(node));
 
107
      literal = true;
 
108
      break;
 
109
    case CMARK_NODE_CUSTOM_BLOCK:
 
110
    case CMARK_NODE_CUSTOM_INLINE:
 
111
      cmark_strbuf_puts(xml, " on_enter=\"");
 
112
      escape_xml(xml, node->as.custom.on_enter.data,
 
113
                 node->as.custom.on_enter.len);
 
114
      cmark_strbuf_putc(xml, '"');
 
115
      cmark_strbuf_puts(xml, " on_exit=\"");
 
116
      escape_xml(xml, node->as.custom.on_exit.data,
 
117
                 node->as.custom.on_exit.len);
 
118
      cmark_strbuf_putc(xml, '"');
 
119
      break;
 
120
    case CMARK_NODE_LINK:
 
121
    case CMARK_NODE_IMAGE:
 
122
      cmark_strbuf_puts(xml, " destination=\"");
 
123
      escape_xml(xml, node->as.link.url.data, node->as.link.url.len);
 
124
      cmark_strbuf_putc(xml, '"');
 
125
      cmark_strbuf_puts(xml, " title=\"");
 
126
      escape_xml(xml, node->as.link.title.data, node->as.link.title.len);
 
127
      cmark_strbuf_putc(xml, '"');
 
128
      break;
 
129
    default:
 
130
      break;
 
131
    }
 
132
    if (node->first_child) {
 
133
      state->indent += 2;
 
134
    } else if (!literal) {
 
135
      cmark_strbuf_puts(xml, " /");
 
136
    }
 
137
    cmark_strbuf_puts(xml, ">\n");
 
138
 
 
139
  } else if (node->first_child) {
 
140
    state->indent -= 2;
 
141
    indent(state);
 
142
    cmark_strbuf_puts(xml, "</");
 
143
    cmark_strbuf_puts(xml, cmark_node_get_type_string(node));
 
144
    cmark_strbuf_puts(xml, ">\n");
 
145
  }
 
146
 
 
147
  return 1;
 
148
}
 
149
 
 
150
char *cmark_render_xml(cmark_node *root, int options) {
 
151
  return cmark_render_xml_with_mem(root, options, cmark_node_mem(root));
 
152
}
 
153
 
 
154
char *cmark_render_xml_with_mem(cmark_node *root, int options, cmark_mem *mem) {
 
155
  char *result;
 
156
  cmark_strbuf xml = CMARK_BUF_INIT(mem);
 
157
  cmark_event_type ev_type;
 
158
  cmark_node *cur;
 
159
  struct render_state state = {&xml, 0};
 
160
 
 
161
  cmark_iter *iter = cmark_iter_new(root);
 
162
 
 
163
  cmark_strbuf_puts(state.xml, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
 
164
  cmark_strbuf_puts(state.xml,
 
165
                    "<!DOCTYPE document SYSTEM \"CommonMark.dtd\">\n");
 
166
  while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) {
 
167
    cur = cmark_iter_get_node(iter);
 
168
    S_render_node(cur, ev_type, &state, options);
 
169
  }
 
170
  result = (char *)cmark_strbuf_detach(&xml);
 
171
 
 
172
  cmark_iter_free(iter);
 
173
  return result;
 
174
}