parkdown 1.4.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +68 -0
  3. data/README.markdown +86 -0
  4. data/Rakefile +170 -0
  5. data/bin/parkdown +13 -0
  6. data/ext/extconf.h +3 -0
  7. data/ext/extconf.rb +15 -0
  8. data/ext/markdown.c +104 -0
  9. data/ext/markdown_lib.c +186 -0
  10. data/ext/markdown_lib.h +44 -0
  11. data/ext/markdown_output.c +1275 -0
  12. data/ext/markdown_parser.c +7275 -0
  13. data/ext/markdown_peg.h +90 -0
  14. data/ext/parsing_functions.c +128 -0
  15. data/ext/utility_functions.c +217 -0
  16. data/lib/markdown.rb +1 -0
  17. data/lib/peg_markdown.rb +104 -0
  18. data/test/MarkdownTest_1.0/MarkdownTest.pl +157 -0
  19. data/test/MarkdownTest_1.0/Tests/Amps and angle encoding.html +17 -0
  20. data/test/MarkdownTest_1.0/Tests/Amps and angle encoding.text +21 -0
  21. data/test/MarkdownTest_1.0/Tests/Auto links.html +18 -0
  22. data/test/MarkdownTest_1.0/Tests/Auto links.text +13 -0
  23. data/test/MarkdownTest_1.0/Tests/Backslash escapes.html +102 -0
  24. data/test/MarkdownTest_1.0/Tests/Backslash escapes.text +104 -0
  25. data/test/MarkdownTest_1.0/Tests/Blockquotes with code blocks.html +15 -0
  26. data/test/MarkdownTest_1.0/Tests/Blockquotes with code blocks.text +11 -0
  27. data/test/MarkdownTest_1.0/Tests/Hard-wrapped paragraphs with list-like lines.html +8 -0
  28. data/test/MarkdownTest_1.0/Tests/Hard-wrapped paragraphs with list-like lines.text +8 -0
  29. data/test/MarkdownTest_1.0/Tests/Horizontal rules.html +71 -0
  30. data/test/MarkdownTest_1.0/Tests/Horizontal rules.text +67 -0
  31. data/test/MarkdownTest_1.0/Tests/Inline HTML (Advanced).html +14 -0
  32. data/test/MarkdownTest_1.0/Tests/Inline HTML (Advanced).text +14 -0
  33. data/test/MarkdownTest_1.0/Tests/Inline HTML (Simple).html +72 -0
  34. data/test/MarkdownTest_1.0/Tests/Inline HTML (Simple).text +69 -0
  35. data/test/MarkdownTest_1.0/Tests/Inline HTML comments.html +13 -0
  36. data/test/MarkdownTest_1.0/Tests/Inline HTML comments.text +13 -0
  37. data/test/MarkdownTest_1.0/Tests/Links, inline style.html +9 -0
  38. data/test/MarkdownTest_1.0/Tests/Links, inline style.text +9 -0
  39. data/test/MarkdownTest_1.0/Tests/Links, reference style.html +18 -0
  40. data/test/MarkdownTest_1.0/Tests/Links, reference style.text +31 -0
  41. data/test/MarkdownTest_1.0/Tests/Literal quotes in titles.html +3 -0
  42. data/test/MarkdownTest_1.0/Tests/Literal quotes in titles.text +7 -0
  43. data/test/MarkdownTest_1.0/Tests/Markdown Documentation - Basics.html +314 -0
  44. data/test/MarkdownTest_1.0/Tests/Markdown Documentation - Basics.text +306 -0
  45. data/test/MarkdownTest_1.0/Tests/Markdown Documentation - Syntax.html +942 -0
  46. data/test/MarkdownTest_1.0/Tests/Markdown Documentation - Syntax.text +888 -0
  47. data/test/MarkdownTest_1.0/Tests/Nested blockquotes.html +9 -0
  48. data/test/MarkdownTest_1.0/Tests/Nested blockquotes.text +5 -0
  49. data/test/MarkdownTest_1.0/Tests/Ordered and unordered lists.html +137 -0
  50. data/test/MarkdownTest_1.0/Tests/Ordered and unordered lists.text +122 -0
  51. data/test/MarkdownTest_1.0/Tests/Strong and em together.html +7 -0
  52. data/test/MarkdownTest_1.0/Tests/Strong and em together.text +7 -0
  53. data/test/MarkdownTest_1.0/Tests/Tabs.html +25 -0
  54. data/test/MarkdownTest_1.0/Tests/Tabs.text +21 -0
  55. data/test/MarkdownTest_1.0/Tests/Tidyness.html +8 -0
  56. data/test/MarkdownTest_1.0/Tests/Tidyness.text +5 -0
  57. data/test/MarkdownTest_1.0.3/MarkdownTest.pl +176 -0
  58. data/test/MarkdownTest_1.0.3/Tests/Amps and angle encoding.html +17 -0
  59. data/test/MarkdownTest_1.0.3/Tests/Amps and angle encoding.text +21 -0
  60. data/test/MarkdownTest_1.0.3/Tests/Auto links.html +18 -0
  61. data/test/MarkdownTest_1.0.3/Tests/Auto links.text +13 -0
  62. data/test/MarkdownTest_1.0.3/Tests/Backslash escapes.html +118 -0
  63. data/test/MarkdownTest_1.0.3/Tests/Backslash escapes.text +120 -0
  64. data/test/MarkdownTest_1.0.3/Tests/Blockquotes with code blocks.html +15 -0
  65. data/test/MarkdownTest_1.0.3/Tests/Blockquotes with code blocks.text +11 -0
  66. data/test/MarkdownTest_1.0.3/Tests/Code Blocks.html +18 -0
  67. data/test/MarkdownTest_1.0.3/Tests/Code Blocks.text +14 -0
  68. data/test/MarkdownTest_1.0.3/Tests/Code Spans.html +6 -0
  69. data/test/MarkdownTest_1.0.3/Tests/Code Spans.text +6 -0
  70. data/test/MarkdownTest_1.0.3/Tests/Hard-wrapped paragraphs with list-like lines.html +8 -0
  71. data/test/MarkdownTest_1.0.3/Tests/Hard-wrapped paragraphs with list-like lines.text +8 -0
  72. data/test/MarkdownTest_1.0.3/Tests/Horizontal rules.html +71 -0
  73. data/test/MarkdownTest_1.0.3/Tests/Horizontal rules.text +67 -0
  74. data/test/MarkdownTest_1.0.3/Tests/Inline HTML (Advanced).html +15 -0
  75. data/test/MarkdownTest_1.0.3/Tests/Inline HTML (Advanced).text +15 -0
  76. data/test/MarkdownTest_1.0.3/Tests/Inline HTML (Simple).html +72 -0
  77. data/test/MarkdownTest_1.0.3/Tests/Inline HTML (Simple).text +69 -0
  78. data/test/MarkdownTest_1.0.3/Tests/Inline HTML comments.html +13 -0
  79. data/test/MarkdownTest_1.0.3/Tests/Inline HTML comments.text +13 -0
  80. data/test/MarkdownTest_1.0.3/Tests/Links, inline style.html +11 -0
  81. data/test/MarkdownTest_1.0.3/Tests/Links, inline style.text +12 -0
  82. data/test/MarkdownTest_1.0.3/Tests/Links, reference style.html +52 -0
  83. data/test/MarkdownTest_1.0.3/Tests/Links, reference style.text +71 -0
  84. data/test/MarkdownTest_1.0.3/Tests/Links, shortcut references.html +9 -0
  85. data/test/MarkdownTest_1.0.3/Tests/Links, shortcut references.text +20 -0
  86. data/test/MarkdownTest_1.0.3/Tests/Literal quotes in titles.html +3 -0
  87. data/test/MarkdownTest_1.0.3/Tests/Literal quotes in titles.text +7 -0
  88. data/test/MarkdownTest_1.0.3/Tests/Markdown Documentation - Basics.html +314 -0
  89. data/test/MarkdownTest_1.0.3/Tests/Markdown Documentation - Basics.text +306 -0
  90. data/test/MarkdownTest_1.0.3/Tests/Markdown Documentation - Syntax.html +942 -0
  91. data/test/MarkdownTest_1.0.3/Tests/Markdown Documentation - Syntax.text +888 -0
  92. data/test/MarkdownTest_1.0.3/Tests/Nested blockquotes.html +9 -0
  93. data/test/MarkdownTest_1.0.3/Tests/Nested blockquotes.text +5 -0
  94. data/test/MarkdownTest_1.0.3/Tests/Ordered and unordered lists.html +148 -0
  95. data/test/MarkdownTest_1.0.3/Tests/Ordered and unordered lists.text +131 -0
  96. data/test/MarkdownTest_1.0.3/Tests/Strong and em together.html +7 -0
  97. data/test/MarkdownTest_1.0.3/Tests/Strong and em together.text +7 -0
  98. data/test/MarkdownTest_1.0.3/Tests/Tabs.html +25 -0
  99. data/test/MarkdownTest_1.0.3/Tests/Tabs.text +21 -0
  100. data/test/MarkdownTest_1.0.3/Tests/Tidyness.html +8 -0
  101. data/test/MarkdownTest_1.0.3/Tests/Tidyness.text +5 -0
  102. data/test/benchmark.rb +49 -0
  103. data/test/markdown_test.rb +84 -0
  104. metadata +150 -0
@@ -0,0 +1,1275 @@
1
+ /**********************************************************************
2
+
3
+ markdown_output.c - functions for printing Elements parsed by
4
+ markdown_peg.
5
+ (c) 2008 John MacFarlane (jgm at berkeley dot edu).
6
+
7
+ This program is free software; you can redistribute it and/or modify
8
+ it under the terms of the GNU General Public License or the MIT
9
+ license. See LICENSE for details.
10
+
11
+ This program is distributed in the hope that it will be useful,
12
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ GNU General Public License for more details.
15
+
16
+ ***********************************************************************/
17
+
18
+ #include <stdbool.h>
19
+ #include <stdio.h>
20
+ #include <stdlib.h>
21
+ #include <string.h>
22
+ #include <assert.h>
23
+ #include <glib.h>
24
+ #include "markdown_peg.h"
25
+ #include "odf.h"
26
+
27
+ static int extensions;
28
+ static int odf_type = 0;
29
+
30
+ static void print_html_string(GString *out, char *str, bool obfuscate);
31
+ static void print_html_element_list(GString *out, element *list, bool obfuscate);
32
+ static void print_html_element(GString *out, element *elt, bool obfuscate);
33
+ static void print_latex_string(GString *out, char *str);
34
+ static void print_latex_element_list(GString *out, element *list);
35
+ static void print_latex_element(GString *out, element *elt);
36
+ static void print_groff_string(GString *out, char *str);
37
+ static void print_groff_mm_element_list(GString *out, element *list);
38
+ static void print_groff_mm_element(GString *out, element *elt, int count);
39
+ static void print_odf_code_string(GString *out, char *str);
40
+ static void print_odf_string(GString *out, char *str);
41
+ static void print_odf_element_list(GString *out, element *list);
42
+ static void print_odf_element(GString *out, element *elt);
43
+ static bool list_contains_key(element *list, int key);
44
+
45
+ /**********************************************************************
46
+
47
+ Utility functions for printing
48
+
49
+ ***********************************************************************/
50
+
51
+ static int padded = 2; /* Number of newlines after last output.
52
+ Starts at 2 so no newlines are needed at start.
53
+ */
54
+
55
+ static GSList *endnotes = NULL; /* List of endnotes to print after main content. */
56
+ static int notenumber = 0; /* Number of footnote. */
57
+
58
+ /* pad - add newlines if needed */
59
+ static void pad(GString *out, int num) {
60
+ while (num-- > padded)
61
+ g_string_append_printf(out, "\n");;
62
+ padded = num;
63
+ }
64
+
65
+ /* determine whether a certain element is contained within a given list */
66
+ static bool list_contains_key(element *list, int key) {
67
+ element *step = NULL;
68
+
69
+ step = list;
70
+ while ( step != NULL ) {
71
+ if (step->key == key) {
72
+ return TRUE;
73
+ }
74
+ if (step->children != NULL) {
75
+ if (list_contains_key(step->children, key)) {
76
+ return TRUE;
77
+ }
78
+ }
79
+ step = step->next;
80
+ }
81
+ return FALSE;
82
+ }
83
+
84
+ /**********************************************************************
85
+
86
+ Functions for printing Elements as HTML
87
+
88
+ ***********************************************************************/
89
+
90
+ /* print_html_string - print string, escaping for HTML
91
+ * If obfuscate selected, convert characters to hex or decimal entities at random */
92
+ static void print_html_string(GString *out, char *str, bool obfuscate) {
93
+ while (*str != '\0') {
94
+ switch (*str) {
95
+ case '&':
96
+ g_string_append_printf(out, "&amp;");
97
+ break;
98
+ case '<':
99
+ g_string_append_printf(out, "&lt;");
100
+ break;
101
+ case '>':
102
+ g_string_append_printf(out, "&gt;");
103
+ break;
104
+ case '"':
105
+ g_string_append_printf(out, "&quot;");
106
+ break;
107
+ default:
108
+ if (obfuscate && ((int) *str < 128) && ((int) *str >= 0)){
109
+ if (rand() % 2 == 0)
110
+ g_string_append_printf(out, "&#%d;", (int) *str);
111
+ else
112
+ g_string_append_printf(out, "&#x%x;", (unsigned int) *str);
113
+ }
114
+ else
115
+ g_string_append_c(out, *str);
116
+ }
117
+ str++;
118
+ }
119
+ }
120
+
121
+ /* print_html_element_list - print a list of elements as HTML */
122
+ static void print_html_element_list(GString *out, element *list, bool obfuscate) {
123
+ while (list != NULL) {
124
+ print_html_element(out, list, obfuscate);
125
+ list = list->next;
126
+ }
127
+ }
128
+
129
+ /* add_endnote - add an endnote to global endnotes list. */
130
+ static void add_endnote(element *elt) {
131
+ endnotes = g_slist_prepend(endnotes, elt);
132
+ }
133
+
134
+ /* print_html_element - print an element as HTML */
135
+ static void print_html_element(GString *out, element *elt, bool obfuscate) {
136
+ int lev;
137
+ switch (elt->key) {
138
+ case SPACE:
139
+ g_string_append_printf(out, "%s", elt->contents.str);
140
+ break;
141
+ case LINEBREAK:
142
+ g_string_append_printf(out, "<br/>\n");
143
+ break;
144
+ case STR:
145
+ print_html_string(out, elt->contents.str, obfuscate);
146
+ break;
147
+ case ELLIPSIS:
148
+ g_string_append_printf(out, "&hellip;");
149
+ break;
150
+ case EMDASH:
151
+ g_string_append_printf(out, "&mdash;");
152
+ break;
153
+ case ENDASH:
154
+ g_string_append_printf(out, "&ndash;");
155
+ break;
156
+ case ENSPACE:
157
+ g_string_append_printf(out, "&ensp;");
158
+ break;
159
+ case APOSTROPHE:
160
+ g_string_append_printf(out, "&rsquo;");
161
+ break;
162
+ case SINGLEQUOTED:
163
+ g_string_append_printf(out, "&lsquo;");
164
+ print_html_element_list(out, elt->children, obfuscate);
165
+ g_string_append_printf(out, "&rsquo;");
166
+ break;
167
+ case DOUBLEQUOTED:
168
+ g_string_append_printf(out, "&ldquo;");
169
+ print_html_element_list(out, elt->children, obfuscate);
170
+ g_string_append_printf(out, "&rdquo;");
171
+ break;
172
+ case CODE:
173
+ g_string_append_printf(out, "<code>");
174
+ print_html_string(out, elt->contents.str, obfuscate);
175
+ g_string_append_printf(out, "</code>");
176
+ break;
177
+ case HTML:
178
+ g_string_append_printf(out, "%s", elt->contents.str);
179
+ break;
180
+ case HASHTAG:
181
+ g_string_append_printf(out, "<span rel='hashtag'>%s</span>", elt->contents.str);
182
+ break;
183
+ case USERNAME:
184
+ g_string_append_printf(out, "<span rel='username'>%s</span>", elt->contents.str);
185
+ break;
186
+ case LINK:
187
+ if (strstr(elt->contents.link->url, "mailto:") == elt->contents.link->url)
188
+ obfuscate = true; /* obfuscate mailto: links */
189
+ g_string_append_printf(out, "<a href=\"");
190
+ print_html_string(out, elt->contents.link->url, obfuscate);
191
+ g_string_append_printf(out, "\"");
192
+ if (strlen(elt->contents.link->title) > 0) {
193
+ g_string_append_printf(out, " title=\"");
194
+ print_html_string(out, elt->contents.link->title, obfuscate);
195
+ g_string_append_printf(out, "\"");
196
+ }
197
+ g_string_append_printf(out, ">");
198
+ print_html_element_list(out, elt->contents.link->label, obfuscate);
199
+ g_string_append_printf(out, "</a>");
200
+ break;
201
+ case IMAGE:
202
+ g_string_append_printf(out, "<img src=\"");
203
+ print_html_string(out, elt->contents.link->url, obfuscate);
204
+ g_string_append_printf(out, "\" alt=\"");
205
+ print_html_element_list(out, elt->contents.link->label, obfuscate);
206
+ g_string_append_printf(out, "\"");
207
+ if (strlen(elt->contents.link->title) > 0) {
208
+ g_string_append_printf(out, " title=\"");
209
+ print_html_string(out, elt->contents.link->title, obfuscate);
210
+ g_string_append_printf(out, "\"");
211
+ }
212
+ g_string_append_printf(out, " />");
213
+ break;
214
+ case AUDIO:
215
+ pad(out, 2);
216
+ g_string_append_printf(out, "<audio controls=\"true\">\n");
217
+ g_string_append_printf(out, " <source src=\"");
218
+ print_html_string(out, elt->contents.media->source1, obfuscate);
219
+ g_string_append_printf(out, "\" />\n");
220
+ if (strcmp(elt->contents.media->source2, "")) {
221
+ g_string_append_printf(out, " <source src=\"");
222
+ print_html_string(out, elt->contents.media->source2, obfuscate);
223
+ g_string_append_printf(out, "\" />\n");
224
+ }
225
+ g_string_append_printf(out, "</audio>\n");
226
+ g_string_append_printf(out, "<div class=\"audio-file-title\">");
227
+ print_html_element_list(out, elt->contents.link->label, obfuscate);
228
+ g_string_append_printf(out, "</div>");
229
+ padded = 0;
230
+ break;
231
+ case VIDEO:
232
+ pad(out, 2);
233
+ g_string_append_printf(out, "<video controls=\"true\">\n");
234
+ g_string_append_printf(out, " <source src=\"");
235
+ print_html_string(out, elt->contents.media->source1, obfuscate);
236
+ g_string_append_printf(out, "\" />\n");
237
+ if (strcmp(elt->contents.media->source2, "")) {
238
+ g_string_append_printf(out, " <source src=\"");
239
+ print_html_string(out, elt->contents.media->source2, obfuscate);
240
+ g_string_append_printf(out, "\" />\n");
241
+ }
242
+ g_string_append_printf(out, "</video>\n");
243
+ g_string_append_printf(out, "<div class=\"video-file-title\">");
244
+ print_html_element_list(out, elt->contents.link->label, obfuscate);
245
+ g_string_append_printf(out, "</div>");
246
+ padded = 0;
247
+ break;
248
+ case EMPH:
249
+ g_string_append_printf(out, "<em>");
250
+ print_html_element_list(out, elt->children, obfuscate);
251
+ g_string_append_printf(out, "</em>");
252
+ break;
253
+ case STRONG:
254
+ g_string_append_printf(out, "<strong>");
255
+ print_html_element_list(out, elt->children, obfuscate);
256
+ g_string_append_printf(out, "</strong>");
257
+ break;
258
+ case STRIKE:
259
+ g_string_append_printf(out, "<del>");
260
+ print_html_element_list(out, elt->children, obfuscate);
261
+ g_string_append_printf(out, "</del>");
262
+ break;
263
+ case LIST:
264
+ print_html_element_list(out, elt->children, obfuscate);
265
+ break;
266
+ case RAW:
267
+ /* Shouldn't occur - these are handled by process_raw_blocks() */
268
+ assert(elt->key != RAW);
269
+ break;
270
+ case H1: case H2: case H3: case H4: case H5: case H6:
271
+ lev = elt->key - H1 + 1; /* assumes H1 ... H6 are in order */
272
+ pad(out, 2);
273
+ g_string_append_printf(out, "<h%1d>", lev);
274
+ print_html_element_list(out, elt->children, obfuscate);
275
+ g_string_append_printf(out, "</h%1d>", lev);
276
+ padded = 0;
277
+ break;
278
+ case PLAIN:
279
+ pad(out, 1);
280
+ print_html_element_list(out, elt->children, obfuscate);
281
+ padded = 0;
282
+ break;
283
+ case PARA:
284
+ pad(out, 2);
285
+ g_string_append_printf(out, "<p>");
286
+ print_html_element_list(out, elt->children, obfuscate);
287
+ g_string_append_printf(out, "</p>");
288
+ padded = 0;
289
+ break;
290
+ case HRULE:
291
+ pad(out, 2);
292
+ g_string_append_printf(out, "<hr />");
293
+ padded = 0;
294
+ break;
295
+ case HTMLBLOCK:
296
+ pad(out, 2);
297
+ g_string_append_printf(out, "%s", elt->contents.str);
298
+ padded = 0;
299
+ break;
300
+ case VERBATIM:
301
+ pad(out, 2);
302
+ g_string_append_printf(out, "%s", "<pre><code>");
303
+ print_html_string(out, elt->contents.str, obfuscate);
304
+ g_string_append_printf(out, "%s", "</code></pre>");
305
+ padded = 0;
306
+ break;
307
+ case BULLETLIST:
308
+ pad(out, 2);
309
+ g_string_append_printf(out, "%s", "<ul>");
310
+ padded = 0;
311
+ print_html_element_list(out, elt->children, obfuscate);
312
+ pad(out, 1);
313
+ g_string_append_printf(out, "%s", "</ul>");
314
+ padded = 0;
315
+ break;
316
+ case ORDEREDLIST:
317
+ pad(out, 2);
318
+ g_string_append_printf(out, "%s", "<ol>");
319
+ padded = 0;
320
+ print_html_element_list(out, elt->children, obfuscate);
321
+ pad(out, 1);
322
+ g_string_append_printf(out, "</ol>");
323
+ padded = 0;
324
+ break;
325
+ case LISTITEM:
326
+ pad(out, 1);
327
+ g_string_append_printf(out, "<li>");
328
+ padded = 2;
329
+ print_html_element_list(out, elt->children, obfuscate);
330
+ g_string_append_printf(out, "</li>");
331
+ padded = 0;
332
+ break;
333
+ case BLOCKQUOTE:
334
+ pad(out, 2);
335
+ g_string_append_printf(out, "<blockquote>\n");
336
+ padded = 2;
337
+ print_html_element_list(out, elt->children, obfuscate);
338
+ pad(out, 1);
339
+ g_string_append_printf(out, "</blockquote>");
340
+ padded = 0;
341
+ break;
342
+ case SPOILERBLOCK:
343
+ pad(out, 2);
344
+ g_string_append_printf(out, "<div class='spoilers'>\n");
345
+ padded = 2;
346
+ print_html_element_list(out, elt->children, obfuscate);
347
+ pad(out, 1);
348
+ g_string_append_printf(out, "</div>");
349
+ padded = 0;
350
+ break;
351
+ case REFERENCE:
352
+ /* Nonprinting */
353
+ break;
354
+ case NOTE:
355
+ /* if contents.str == 0, then print note; else ignore, since this
356
+ * is a note block that has been incorporated into the notes list */
357
+ if (elt->contents.str == 0) {
358
+ add_endnote(elt);
359
+ ++notenumber;
360
+ g_string_append_printf(out, "<a class=\"noteref\" id=\"fnref%d\" href=\"#fn%d\" title=\"Jump to note %d\">[%d]</a>",
361
+ notenumber, notenumber, notenumber, notenumber);
362
+ }
363
+ break;
364
+ default:
365
+ fprintf(stderr, "print_html_element encountered unknown element key = %d\n", elt->key);
366
+ exit(EXIT_FAILURE);
367
+ }
368
+ }
369
+
370
+ static void print_html_endnotes(GString *out) {
371
+ int counter = 0;
372
+ GSList *note;
373
+ element *note_elt;
374
+ if (endnotes == NULL)
375
+ return;
376
+ note = g_slist_reverse(endnotes);
377
+ g_string_append_printf(out, "<hr/>\n<ol id=\"notes\">");
378
+ while (note != NULL) {
379
+ note_elt = note->data;
380
+ counter++;
381
+ pad(out, 1);
382
+ g_string_append_printf(out, "<li id=\"fn%d\">\n", counter);
383
+ padded = 2;
384
+ print_html_element_list(out, note_elt->children, false);
385
+ g_string_append_printf(out, " <a href=\"#fnref%d\" title=\"Jump back to reference\">[⤴]</a>", counter);
386
+ pad(out, 1);
387
+ g_string_append_printf(out, "</li>");
388
+ note = note->next;
389
+ }
390
+ pad(out, 1);
391
+ g_string_append_printf(out, "</ol>");
392
+ g_slist_free(endnotes);
393
+ }
394
+
395
+ /**********************************************************************
396
+
397
+ Functions for printing Elements as LaTeX
398
+
399
+ ***********************************************************************/
400
+
401
+ /* print_latex_string - print string, escaping for LaTeX */
402
+ static void print_latex_string(GString *out, char *str) {
403
+ while (*str != '\0') {
404
+ switch (*str) {
405
+ case '{': case '}': case '$': case '%':
406
+ case '&': case '_': case '#':
407
+ g_string_append_printf(out, "\\%c", *str);
408
+ break;
409
+ case '^':
410
+ g_string_append_printf(out, "\\^{}");
411
+ break;
412
+ case '\\':
413
+ g_string_append_printf(out, "\\textbackslash{}");
414
+ break;
415
+ case '~':
416
+ g_string_append_printf(out, "\\ensuremath{\\sim}");
417
+ break;
418
+ case '|':
419
+ g_string_append_printf(out, "\\textbar{}");
420
+ break;
421
+ case '<':
422
+ g_string_append_printf(out, "\\textless{}");
423
+ break;
424
+ case '>':
425
+ g_string_append_printf(out, "\\textgreater{}");
426
+ break;
427
+ default:
428
+ g_string_append_c(out, *str);
429
+ }
430
+ str++;
431
+ }
432
+ }
433
+
434
+ /* print_latex_element_list - print a list of elements as LaTeX */
435
+ static void print_latex_element_list(GString *out, element *list) {
436
+ while (list != NULL) {
437
+ print_latex_element(out, list);
438
+ list = list->next;
439
+ }
440
+ }
441
+
442
+ /* print_latex_element - print an element as LaTeX */
443
+ static void print_latex_element(GString *out, element *elt) {
444
+ int lev;
445
+ int i;
446
+ switch (elt->key) {
447
+ case SPACE:
448
+ g_string_append_printf(out, "%s", elt->contents.str);
449
+ break;
450
+ case LINEBREAK:
451
+ g_string_append_printf(out, "\\\\\n");
452
+ break;
453
+ case STR:
454
+ print_latex_string(out, elt->contents.str);
455
+ break;
456
+ case ELLIPSIS:
457
+ g_string_append_printf(out, "\\ldots{}");
458
+ break;
459
+ case EMDASH:
460
+ g_string_append_printf(out, "---");
461
+ break;
462
+ case ENDASH:
463
+ g_string_append_printf(out, "--");
464
+ break;
465
+ case ENSPACE:
466
+ g_string_append_printf(out, " ");
467
+ break;
468
+ case APOSTROPHE:
469
+ g_string_append_printf(out, "'");
470
+ break;
471
+ case SINGLEQUOTED:
472
+ g_string_append_printf(out, "`");
473
+ print_latex_element_list(out, elt->children);
474
+ g_string_append_printf(out, "'");
475
+ break;
476
+ case DOUBLEQUOTED:
477
+ g_string_append_printf(out, "``");
478
+ print_latex_element_list(out, elt->children);
479
+ g_string_append_printf(out, "''");
480
+ break;
481
+ case CODE:
482
+ g_string_append_printf(out, "\\texttt{");
483
+ print_latex_string(out, elt->contents.str);
484
+ g_string_append_printf(out, "}");
485
+ break;
486
+ case HTML:
487
+ /* don't print HTML */
488
+ break;
489
+ case LINK:
490
+ g_string_append_printf(out, "\\href{%s}{", elt->contents.link->url);
491
+ print_latex_element_list(out, elt->contents.link->label);
492
+ g_string_append_printf(out, "}");
493
+ break;
494
+ case IMAGE:
495
+ g_string_append_printf(out, "\\includegraphics{%s}", elt->contents.link->url);
496
+ break;
497
+ case AUDIO:
498
+ g_string_append_printf(out, "\n\n[AUDIO: {%s}]", elt->contents.media->source1);
499
+ padded = 0;
500
+ /* not supported */
501
+ break;
502
+ case VIDEO:
503
+ pad(out, 2);
504
+ g_string_append_printf(out, "\n\n[VIDEO: {%s}]", elt->contents.media->source1);
505
+ padded = 0;
506
+ /* not supported */
507
+ break;
508
+ case EMPH:
509
+ g_string_append_printf(out, "\\emph{");
510
+ print_latex_element_list(out, elt->children);
511
+ g_string_append_printf(out, "}");
512
+ break;
513
+ case STRONG:
514
+ g_string_append_printf(out, "\\textbf{");
515
+ print_latex_element_list(out, elt->children);
516
+ g_string_append_printf(out, "}");
517
+ break;
518
+ case STRIKE:
519
+ g_string_append_printf(out, "\\sout{");
520
+ print_latex_element_list(out, elt->children);
521
+ g_string_append_printf(out, "}");
522
+ break;
523
+ case LIST:
524
+ print_latex_element_list(out, elt->children);
525
+ break;
526
+ case RAW:
527
+ /* Shouldn't occur - these are handled by process_raw_blocks() */
528
+ assert(elt->key != RAW);
529
+ break;
530
+ case H1: case H2: case H3:
531
+ pad(out, 2);
532
+ lev = elt->key - H1 + 1; /* assumes H1 ... H6 are in order */
533
+ g_string_append_printf(out, "\\");
534
+ for (i = elt->key; i > H1; i--)
535
+ g_string_append_printf(out, "sub");
536
+ g_string_append_printf(out, "section{");
537
+ print_latex_element_list(out, elt->children);
538
+ g_string_append_printf(out, "}");
539
+ padded = 0;
540
+ break;
541
+ case H4: case H5: case H6:
542
+ pad(out, 2);
543
+ g_string_append_printf(out, "\\noindent\\textbf{");
544
+ print_latex_element_list(out, elt->children);
545
+ g_string_append_printf(out, "}");
546
+ padded = 0;
547
+ break;
548
+ case PLAIN:
549
+ pad(out, 1);
550
+ print_latex_element_list(out, elt->children);
551
+ padded = 0;
552
+ break;
553
+ case PARA:
554
+ pad(out, 2);
555
+ print_latex_element_list(out, elt->children);
556
+ padded = 0;
557
+ break;
558
+ case HRULE:
559
+ pad(out, 2);
560
+ g_string_append_printf(out, "\\begin{center}\\rule{3in}{0.4pt}\\end{center}\n");
561
+ padded = 0;
562
+ break;
563
+ case HTMLBLOCK:
564
+ /* don't print HTML block */
565
+ break;
566
+ case HASHTAG:
567
+ print_latex_string(out, elt->contents.str);
568
+ break;
569
+ case USERNAME:
570
+ print_latex_string(out, elt->contents.str);
571
+ break;
572
+ case VERBATIM:
573
+ pad(out, 1);
574
+ g_string_append_printf(out, "\\begin{verbatim}\n");
575
+ print_latex_string(out, elt->contents.str);
576
+ g_string_append_printf(out, "\n\\end{verbatim}");
577
+ padded = 0;
578
+ break;
579
+ case BULLETLIST:
580
+ pad(out, 1);
581
+ g_string_append_printf(out, "\\begin{itemize}");
582
+ padded = 0;
583
+ print_latex_element_list(out, elt->children);
584
+ pad(out, 1);
585
+ g_string_append_printf(out, "\\end{itemize}");
586
+ padded = 0;
587
+ break;
588
+ case ORDEREDLIST:
589
+ pad(out, 1);
590
+ g_string_append_printf(out, "\\begin{enumerate}");
591
+ padded = 0;
592
+ print_latex_element_list(out, elt->children);
593
+ pad(out, 1);
594
+ g_string_append_printf(out, "\\end{enumerate}");
595
+ padded = 0;
596
+ break;
597
+ case LISTITEM:
598
+ pad(out, 1);
599
+ g_string_append_printf(out, "\\item ");
600
+ padded = 2;
601
+ print_latex_element_list(out, elt->children);
602
+ g_string_append_printf(out, "\n");
603
+ break;
604
+ case BLOCKQUOTE:
605
+ pad(out, 1);
606
+ g_string_append_printf(out, "\\begin{quote}");
607
+ padded = 0;
608
+ print_latex_element_list(out, elt->children);
609
+ pad(out, 1);
610
+ g_string_append_printf(out, "\\end{quote}");
611
+ padded = 0;
612
+ break;
613
+ case SPOILERBLOCK:
614
+ pad(out, 1);
615
+ print_latex_element_list(out, elt->children);
616
+ padded = 0;
617
+ break;
618
+ case NOTE:
619
+ /* if contents.str == 0, then print note; else ignore, since this
620
+ * is a note block that has been incorporated into the notes list */
621
+ if (elt->contents.str == 0) {
622
+ g_string_append_printf(out, "\\footnote{");
623
+ padded = 2;
624
+ print_latex_element_list(out, elt->children);
625
+ g_string_append_printf(out, "}");
626
+ padded = 0;
627
+ }
628
+ break;
629
+ case REFERENCE:
630
+ /* Nonprinting */
631
+ break;
632
+ default:
633
+ fprintf(stderr, "print_latex_element encountered unknown element key = %d\n", elt->key);
634
+ exit(EXIT_FAILURE);
635
+ }
636
+ }
637
+
638
+ /**********************************************************************
639
+
640
+ Functions for printing Elements as groff (mm macros)
641
+
642
+ ***********************************************************************/
643
+
644
+ static bool in_list_item = false; /* True if we're parsing contents of a list item. */
645
+
646
+ /* print_groff_string - print string, escaping for groff */
647
+ static void print_groff_string(GString *out, char *str) {
648
+ /* escape dots if it is the first character */
649
+ if (*str == '.') {
650
+ g_string_append_printf(out, "\\[char46]");
651
+ str++;
652
+ }
653
+
654
+ while (*str != '\0') {
655
+ switch (*str) {
656
+ case '\\':
657
+ g_string_append_printf(out, "\\e");
658
+ break;
659
+ default:
660
+ g_string_append_c(out, *str);
661
+ }
662
+ str++;
663
+ }
664
+ }
665
+
666
+ /* print_groff_mm_element_list - print a list of elements as groff ms */
667
+ static void print_groff_mm_element_list(GString *out, element *list) {
668
+ int count = 1;
669
+ while (list != NULL) {
670
+ print_groff_mm_element(out, list, count);
671
+ list = list->next;
672
+ count++;
673
+ }
674
+ }
675
+
676
+ /* print_groff_mm_element - print an element as groff ms */
677
+ static void print_groff_mm_element(GString *out, element *elt, int count) {
678
+ int lev;
679
+ switch (elt->key) {
680
+ case SPACE:
681
+ g_string_append_printf(out, "%s", elt->contents.str);
682
+ padded = 0;
683
+ break;
684
+ case LINEBREAK:
685
+ pad(out, 1);
686
+ g_string_append_printf(out, ".br\n");
687
+ padded = 0;
688
+ break;
689
+ case STR:
690
+ print_groff_string(out, elt->contents.str);
691
+ padded = 0;
692
+ break;
693
+ case ELLIPSIS:
694
+ g_string_append_printf(out, "...");
695
+ break;
696
+ case EMDASH:
697
+ g_string_append_printf(out, "\\[em]");
698
+ break;
699
+ case ENDASH:
700
+ g_string_append_printf(out, "\\[en]");
701
+ break;
702
+ case ENSPACE:
703
+ g_string_append_printf(out, " ");
704
+ break;
705
+ case APOSTROPHE:
706
+ g_string_append_printf(out, "'");
707
+ break;
708
+ case SINGLEQUOTED:
709
+ g_string_append_printf(out, "`");
710
+ print_groff_mm_element_list(out, elt->children);
711
+ g_string_append_printf(out, "'");
712
+ break;
713
+ case DOUBLEQUOTED:
714
+ g_string_append_printf(out, "\\[lq]");
715
+ print_groff_mm_element_list(out, elt->children);
716
+ g_string_append_printf(out, "\\[rq]");
717
+ break;
718
+ case CODE:
719
+ g_string_append_printf(out, "\\fC");
720
+ print_groff_string(out, elt->contents.str);
721
+ g_string_append_printf(out, "\\fR");
722
+ padded = 0;
723
+ break;
724
+ case HTML:
725
+ /* don't print HTML */
726
+ break;
727
+ case HASHTAG:
728
+ print_groff_string(out, elt->contents.str);
729
+ break;
730
+ case USERNAME:
731
+ print_groff_string(out, elt->contents.str);
732
+ break;
733
+ case LINK:
734
+ print_groff_mm_element_list(out, elt->contents.link->label);
735
+ g_string_append_printf(out, " (%s)", elt->contents.link->url);
736
+ padded = 0;
737
+ break;
738
+ case IMAGE:
739
+ g_string_append_printf(out, "[IMAGE: ");
740
+ print_groff_mm_element_list(out, elt->contents.link->label);
741
+ g_string_append_printf(out, "]");
742
+ padded = 0;
743
+ /* not supported */
744
+ break;
745
+ case AUDIO:
746
+ pad(out, 2);
747
+ g_string_append_printf(out, "[AUDIO: ");
748
+ print_groff_string(out, elt->contents.media->source1);
749
+ g_string_append_printf(out, "]");
750
+ padded = 0;
751
+ /* not supported */
752
+ break;
753
+ case VIDEO:
754
+ pad(out, 2);
755
+ g_string_append_printf(out, "[VIDEO: ");
756
+ print_groff_string(out, elt->contents.media->source1);
757
+ g_string_append_printf(out, "]");
758
+ padded = 0;
759
+ /* not supported */
760
+ break;
761
+ case EMPH:
762
+ g_string_append_printf(out, "\\fI");
763
+ print_groff_mm_element_list(out, elt->children);
764
+ g_string_append_printf(out, "\\fR");
765
+ padded = 0;
766
+ break;
767
+ case STRONG:
768
+ g_string_append_printf(out, "\\fB");
769
+ print_groff_mm_element_list(out, elt->children);
770
+ g_string_append_printf(out, "\\fR");
771
+ padded = 0;
772
+ break;
773
+ case STRIKE:
774
+ g_string_append_printf(out, "\\c\n.ST \"");
775
+ print_groff_mm_element_list(out, elt->children);
776
+ g_string_append_printf(out, "\"");
777
+ pad(out, 1);
778
+ break;
779
+ case LIST:
780
+ print_groff_mm_element_list(out, elt->children);
781
+ padded = 0;
782
+ break;
783
+ case RAW:
784
+ /* Shouldn't occur - these are handled by process_raw_blocks() */
785
+ assert(elt->key != RAW);
786
+ break;
787
+ case H1: case H2: case H3: case H4: case H5: case H6:
788
+ lev = elt->key - H1 + 1;
789
+ pad(out, 1);
790
+ g_string_append_printf(out, ".H %d \"", lev);
791
+ print_groff_mm_element_list(out, elt->children);
792
+ g_string_append_printf(out, "\"");
793
+ padded = 0;
794
+ break;
795
+ case PLAIN:
796
+ pad(out, 1);
797
+ print_groff_mm_element_list(out, elt->children);
798
+ padded = 0;
799
+ break;
800
+ case PARA:
801
+ pad(out, 1);
802
+ if (!in_list_item || count != 1)
803
+ g_string_append_printf(out, ".P\n");
804
+ print_groff_mm_element_list(out, elt->children);
805
+ padded = 0;
806
+ break;
807
+ case HRULE:
808
+ pad(out, 1);
809
+ g_string_append_printf(out, "\\l'\\n(.lu*8u/10u'");
810
+ padded = 0;
811
+ break;
812
+ case HTMLBLOCK:
813
+ /* don't print HTML block */
814
+ break;
815
+ case VERBATIM:
816
+ pad(out, 1);
817
+ g_string_append_printf(out, ".VERBON 2\n");
818
+ print_groff_string(out, elt->contents.str);
819
+ g_string_append_printf(out, ".VERBOFF");
820
+ padded = 0;
821
+ break;
822
+ case BULLETLIST:
823
+ pad(out, 1);
824
+ g_string_append_printf(out, ".BL");
825
+ padded = 0;
826
+ print_groff_mm_element_list(out, elt->children);
827
+ pad(out, 1);
828
+ g_string_append_printf(out, ".LE 1");
829
+ padded = 0;
830
+ break;
831
+ case ORDEREDLIST:
832
+ pad(out, 1);
833
+ g_string_append_printf(out, ".AL");
834
+ padded = 0;
835
+ print_groff_mm_element_list(out, elt->children);
836
+ pad(out, 1);
837
+ g_string_append_printf(out, ".LE 1");
838
+ padded = 0;
839
+ break;
840
+ case LISTITEM:
841
+ pad(out, 1);
842
+ g_string_append_printf(out, ".LI\n");
843
+ in_list_item = true;
844
+ padded = 2;
845
+ print_groff_mm_element_list(out, elt->children);
846
+ in_list_item = false;
847
+ break;
848
+ case BLOCKQUOTE:
849
+ pad(out, 1);
850
+ g_string_append_printf(out, ".DS I\n");
851
+ padded = 2;
852
+ print_groff_mm_element_list(out, elt->children);
853
+ pad(out, 1);
854
+ g_string_append_printf(out, ".DE");
855
+ padded = 0;
856
+ break;
857
+ case SPOILERBLOCK:
858
+ pad(out, 1);
859
+ print_groff_mm_element_list(out, elt->children);
860
+ padded = 0;
861
+ break;
862
+ case NOTE:
863
+ /* if contents.str == 0, then print note; else ignore, since this
864
+ * is a note block that has been incorporated into the notes list */
865
+ if (elt->contents.str == 0) {
866
+ g_string_append_printf(out, "\\*F\n");
867
+ g_string_append_printf(out, ".FS\n");
868
+ padded = 2;
869
+ print_groff_mm_element_list(out, elt->children);
870
+ pad(out, 1);
871
+ g_string_append_printf(out, ".FE\n");
872
+ padded = 1;
873
+ }
874
+ break;
875
+ case REFERENCE:
876
+ /* Nonprinting */
877
+ break;
878
+ default:
879
+ fprintf(stderr, "print_groff_mm_element encountered unknown element key = %d\n", elt->key);
880
+ exit(EXIT_FAILURE);
881
+ }
882
+ }
883
+
884
+ /**********************************************************************
885
+
886
+ Functions for printing Elements as ODF
887
+
888
+ ***********************************************************************/
889
+
890
+ /* print_odf_code_string - print string, escaping for HTML and saving newlines
891
+ */
892
+ static void print_odf_code_string(GString *out, char *str) {
893
+ char *tmp;
894
+ while (*str != '\0') {
895
+ switch (*str) {
896
+ case '&':
897
+ g_string_append_printf(out, "&amp;");
898
+ break;
899
+ case '<':
900
+ g_string_append_printf(out, "&lt;");
901
+ break;
902
+ case '>':
903
+ g_string_append_printf(out, "&gt;");
904
+ break;
905
+ case '"':
906
+ g_string_append_printf(out, "&quot;");
907
+ break;
908
+ case '\n':
909
+ g_string_append_printf(out, "<text:line-break/>");
910
+ break;
911
+ case ' ':
912
+ tmp = str;
913
+ tmp++;
914
+ if (*tmp == ' ') {
915
+ tmp++;
916
+ if (*tmp == ' ') {
917
+ tmp++;
918
+ if (*tmp == ' ') {
919
+ g_string_append_printf(out, "<text:tab/>");
920
+ str = tmp;
921
+ } else {
922
+ g_string_append_printf(out, " ");
923
+ }
924
+ } else {
925
+ g_string_append_printf(out, " ");
926
+ }
927
+ } else {
928
+ g_string_append_printf(out, " ");
929
+ }
930
+ break;
931
+ default:
932
+ g_string_append_c(out, *str);
933
+ }
934
+ str++;
935
+ }
936
+ }
937
+
938
+ /* print_odf_string - print string, escaping for HTML and saving newlines */
939
+ static void print_odf_string(GString *out, char *str) {
940
+ char *tmp;
941
+ while (*str != '\0') {
942
+ switch (*str) {
943
+ case '&':
944
+ g_string_append_printf(out, "&amp;");
945
+ break;
946
+ case '<':
947
+ g_string_append_printf(out, "&lt;");
948
+ break;
949
+ case '>':
950
+ g_string_append_printf(out, "&gt;");
951
+ break;
952
+ case '"':
953
+ g_string_append_printf(out, "&quot;");
954
+ break;
955
+ case '\n':
956
+ tmp = str;
957
+ tmp--;
958
+ if (*tmp == ' ') {
959
+ tmp--;
960
+ if (*tmp == ' ') {
961
+ g_string_append_printf(out, "<text:line-break/>");
962
+ } else {
963
+ g_string_append_printf(out, "\n");
964
+ }
965
+ } else {
966
+ g_string_append_printf(out, "\n");
967
+ }
968
+ break;
969
+ case ' ':
970
+ tmp = str;
971
+ tmp++;
972
+ if (*tmp == ' ') {
973
+ tmp++;
974
+ if (*tmp == ' ') {
975
+ tmp++;
976
+ if (*tmp == ' ') {
977
+ g_string_append_printf(out, "<text:tab/>");
978
+ str = tmp;
979
+ } else {
980
+ g_string_append_printf(out, " ");
981
+ }
982
+ } else {
983
+ g_string_append_printf(out, " ");
984
+ }
985
+ } else {
986
+ g_string_append_printf(out, " ");
987
+ }
988
+ break;
989
+ default:
990
+ g_string_append_c(out, *str);
991
+ }
992
+ str++;
993
+ }
994
+ }
995
+
996
+ /* print_odf_element_list - print an element list as ODF */
997
+ static void print_odf_element_list(GString *out, element *list) {
998
+ while (list != NULL) {
999
+ print_odf_element(out, list);
1000
+ list = list->next;
1001
+ }
1002
+ }
1003
+
1004
+ /* print_odf_element - print an element as ODF */
1005
+ static void print_odf_element(GString *out, element *elt) {
1006
+ int lev;
1007
+ int old_type = 0;
1008
+ switch (elt->key) {
1009
+ case SPACE:
1010
+ g_string_append_printf(out, "%s", elt->contents.str);
1011
+ break;
1012
+ case LINEBREAK:
1013
+ g_string_append_printf(out, "<text:line-break/>");
1014
+ break;
1015
+ case STR:
1016
+ print_html_string(out, elt->contents.str, 0);
1017
+ break;
1018
+ case ELLIPSIS:
1019
+ g_string_append_printf(out, "&hellip;");
1020
+ break;
1021
+ case EMDASH:
1022
+ g_string_append_printf(out, "&mdash;");
1023
+ break;
1024
+ case ENDASH:
1025
+ g_string_append_printf(out, "&ndash;");
1026
+ break;
1027
+ case ENSPACE:
1028
+ g_string_append_printf(out, "&ensp;");
1029
+ break;
1030
+ case APOSTROPHE:
1031
+ g_string_append_printf(out, "&rsquo;");
1032
+ break;
1033
+ case SINGLEQUOTED:
1034
+ g_string_append_printf(out, "&lsquo;");
1035
+ print_odf_element_list(out, elt->children);
1036
+ g_string_append_printf(out, "&rsquo;");
1037
+ break;
1038
+ case DOUBLEQUOTED:
1039
+ g_string_append_printf(out, "&ldquo;");
1040
+ print_odf_element_list(out, elt->children);
1041
+ g_string_append_printf(out, "&rdquo;");
1042
+ break;
1043
+ case CODE:
1044
+ g_string_append_printf(out, "<text:span text:style-name=\"Source_20_Text\">");
1045
+ print_html_string(out, elt->contents.str, 0);
1046
+ g_string_append_printf(out, "</text:span>");
1047
+ break;
1048
+ case HTML:
1049
+ break;
1050
+ case HASHTAG:
1051
+ print_html_string(out, elt->contents.str, 0);
1052
+ break;
1053
+ case USERNAME:
1054
+ print_html_string(out, elt->contents.str, 0);
1055
+ break;
1056
+ case LINK:
1057
+ g_string_append_printf(out, "<text:a xlink:type=\"simple\" xlink:href=\"");
1058
+ print_html_string(out, elt->contents.link->url, 0);
1059
+ g_string_append_printf(out, "\"");
1060
+ if (strlen(elt->contents.link->title) > 0) {
1061
+ g_string_append_printf(out, " office:name=\"");
1062
+ print_html_string(out, elt->contents.link->title, 0);
1063
+ g_string_append_printf(out, "\"");
1064
+ }
1065
+ g_string_append_printf(out, ">");
1066
+ print_odf_element_list(out, elt->contents.link->label);
1067
+ g_string_append_printf(out, "</text:a>");
1068
+ break;
1069
+ case IMAGE:
1070
+ g_string_append_printf(out, "<draw:frame text:anchor-type=\"as-char\"\ndraw:z-index=\"0\" draw:style-name=\"fr1\" svg:width=\"95%%\"");
1071
+ g_string_append_printf(out, ">\n<draw:text-box><text:p><draw:frame text:anchor-type=\"as-char\" draw:z-index=\"1\" ");
1072
+ g_string_append_printf(out, "><draw:image xlink:href=\"");
1073
+ print_odf_string(out, elt->contents.link->url);
1074
+ g_string_append_printf(out,"\" xlink:type=\"simple\" xlink:show=\"embed\" xlink:actuate=\"onLoad\" draw:filter-name=\"&lt;All formats&gt;\"/>\n</draw:frame></text:p>");
1075
+ g_string_append_printf(out, "</draw:text-box></draw:frame>\n");
1076
+ break;
1077
+ case EMPH:
1078
+ g_string_append_printf(out,
1079
+ "<text:span text:style-name=\"MMD-Italic\">");
1080
+ print_odf_element_list(out, elt->children);
1081
+ g_string_append_printf(out, "</text:span>");
1082
+ break;
1083
+ case STRONG:
1084
+ g_string_append_printf(out,
1085
+ "<text:span text:style-name=\"MMD-Bold\">");
1086
+ print_odf_element_list(out, elt->children);
1087
+ g_string_append_printf(out, "</text:span>");
1088
+ break;
1089
+ case STRIKE:
1090
+ g_string_append_printf(out,
1091
+ "<text:span text:style-name=\"StrikeThrough\">");
1092
+ print_odf_element_list(out, elt->children);
1093
+ g_string_append_printf(out, "</text:span>");
1094
+ break;
1095
+ case LIST:
1096
+ print_odf_element_list(out, elt->children);
1097
+ break;
1098
+ case RAW:
1099
+ /* Shouldn't occur - these are handled by process_raw_blocks() */
1100
+ assert(elt->key != RAW);
1101
+ break;
1102
+ case H1: case H2: case H3: case H4: case H5: case H6:
1103
+ lev = elt->key - H1 + 1; /* assumes H1 ... H6 are in order */
1104
+ g_string_append_printf(out, "<text:h text:outline-level=\"%d\">", lev);
1105
+ print_odf_element_list(out, elt->children);
1106
+ g_string_append_printf(out, "</text:h>\n");
1107
+ padded = 0;
1108
+ break;
1109
+ case PLAIN:
1110
+ print_odf_element_list(out, elt->children);
1111
+ padded = 0;
1112
+ break;
1113
+ case PARA:
1114
+ g_string_append_printf(out, "<text:p");
1115
+ switch (odf_type) {
1116
+ case BLOCKQUOTE:
1117
+ g_string_append_printf(out," text:style-name=\"Quotations\"");
1118
+ break;
1119
+ case CODE:
1120
+ g_string_append_printf(out," text:style-name=\"Preformatted Text\"");
1121
+ break;
1122
+ case VERBATIM:
1123
+ g_string_append_printf(out," text:style-name=\"Preformatted Text\"");
1124
+ break;
1125
+ case ORDEREDLIST:
1126
+ case BULLETLIST:
1127
+ g_string_append_printf(out," text:style-name=\"P2\"");
1128
+ break;
1129
+ case NOTE:
1130
+ g_string_append_printf(out," text:style-name=\"Footnote\"");
1131
+ break;
1132
+ default:
1133
+ g_string_append_printf(out," text:style-name=\"Standard\"");
1134
+ break;
1135
+ }
1136
+ g_string_append_printf(out, ">");
1137
+ print_odf_element_list(out, elt->children);
1138
+ g_string_append_printf(out, "</text:p>\n");
1139
+ break;
1140
+ case HRULE:
1141
+ g_string_append_printf(out,"<text:p text:style-name=\"Horizontal_20_Line\"/>\n");
1142
+ break;
1143
+ case HTMLBLOCK:
1144
+ /* don't print HTML block */
1145
+ /* but do print HTML comments for raw ODF */
1146
+ if (strncmp(elt->contents.str,"<!--",4) == 0) {
1147
+ /* trim "-->" from end */
1148
+ elt->contents.str[strlen(elt->contents.str)-3] = '\0';
1149
+ g_string_append_printf(out, "%s", &elt->contents.str[4]);
1150
+ }
1151
+ break;
1152
+ case VERBATIM:
1153
+ old_type = odf_type;
1154
+ odf_type = VERBATIM;
1155
+ g_string_append_printf(out, "<text:p text:style-name=\"Preformatted Text\">");
1156
+ print_odf_code_string(out, elt->contents.str);
1157
+ g_string_append_printf(out, "</text:p>\n");
1158
+ odf_type = old_type;
1159
+ break;
1160
+ case BULLETLIST:
1161
+ if ((odf_type == BULLETLIST) ||
1162
+ (odf_type == ORDEREDLIST)) {
1163
+ /* I think this was made unnecessary by another change.
1164
+ Same for ORDEREDLIST below */
1165
+ /* g_string_append_printf(out, "</text:p>"); */
1166
+ }
1167
+ old_type = odf_type;
1168
+ odf_type = BULLETLIST;
1169
+ g_string_append_printf(out, "%s", "<text:list>");
1170
+ print_odf_element_list(out, elt->children);
1171
+ g_string_append_printf(out, "%s", "</text:list>");
1172
+ odf_type = old_type;
1173
+ break;
1174
+ case ORDEREDLIST:
1175
+ if ((odf_type == BULLETLIST) ||
1176
+ (odf_type == ORDEREDLIST)) {
1177
+ /* g_string_append_printf(out, "</text:p>"); */
1178
+ }
1179
+ old_type = odf_type;
1180
+ odf_type = ORDEREDLIST;
1181
+ g_string_append_printf(out, "%s", "<text:list>\n");
1182
+ print_odf_element_list(out, elt->children);
1183
+ g_string_append_printf(out, "%s", "</text:list>\n");
1184
+ odf_type = old_type;
1185
+ break;
1186
+ case LISTITEM:
1187
+ g_string_append_printf(out, "<text:list-item>\n");
1188
+ if (elt->children->children->key != PARA) {
1189
+ g_string_append_printf(out, "<text:p text:style-name=\"P2\">");
1190
+ }
1191
+ print_odf_element_list(out, elt->children);
1192
+
1193
+ if ((list_contains_key(elt->children,BULLETLIST) ||
1194
+ (list_contains_key(elt->children,ORDEREDLIST)))) {
1195
+ } else {
1196
+ if (elt->children->children->key != PARA) {
1197
+ g_string_append_printf(out, "</text:p>");
1198
+ }
1199
+ }
1200
+ g_string_append_printf(out, "</text:list-item>\n");
1201
+ break;
1202
+ case BLOCKQUOTE:
1203
+ old_type = odf_type;
1204
+ odf_type = BLOCKQUOTE;
1205
+ print_odf_element_list(out, elt->children);
1206
+ odf_type = old_type;
1207
+ break;
1208
+ case SPOILERBLOCK:
1209
+ old_type = odf_type;
1210
+ odf_type = SPOILERBLOCK;
1211
+ print_odf_element_list(out, elt->children);
1212
+ odf_type = old_type;
1213
+ break;
1214
+ case REFERENCE:
1215
+ break;
1216
+ case NOTE:
1217
+ old_type = odf_type;
1218
+ odf_type = NOTE;
1219
+ /* if contents.str == 0 then print; else ignore - like above */
1220
+ if (elt->contents.str == 0) {
1221
+ g_string_append_printf(out, "<text:note text:id=\"\" text:note-class=\"footnote\"><text:note-body>\n");
1222
+ print_odf_element_list(out, elt->children);
1223
+ g_string_append_printf(out, "</text:note-body>\n</text:note>\n");
1224
+ }
1225
+ elt->children = NULL;
1226
+ odf_type = old_type;
1227
+ break;
1228
+ break; default:
1229
+ fprintf(stderr, "print_odf_element encountered unknown element key = %d\n", elt->key);
1230
+ exit(EXIT_FAILURE);
1231
+ }
1232
+ }
1233
+
1234
+ /**********************************************************************
1235
+
1236
+ Parameterized function for printing an Element.
1237
+
1238
+ ***********************************************************************/
1239
+
1240
+ void print_element_list(GString *out, element *elt, int format, int exts) {
1241
+ /* Initialize globals */
1242
+ endnotes = NULL;
1243
+ notenumber = 0;
1244
+
1245
+ extensions = exts;
1246
+ padded = 2; /* set padding to 2, so no extra blank lines at beginning */
1247
+ switch (format) {
1248
+ case HTML_FORMAT:
1249
+ print_html_element_list(out, elt, false);
1250
+ if (endnotes != NULL) {
1251
+ pad(out, 2);
1252
+ print_html_endnotes(out);
1253
+ }
1254
+ break;
1255
+ case LATEX_FORMAT:
1256
+ print_latex_element_list(out, elt);
1257
+ break;
1258
+ case GROFF_MM_FORMAT:
1259
+ if (extensions & EXT_STRIKE) {
1260
+ g_string_append_printf(out,
1261
+ ".de ST\n.nr width \\w'\\\\$1'\n\\Z@\\v'-.25m'\\l'\\\\n[width]u'@\\\\$1\\c\n..\n.\n");
1262
+ }
1263
+ print_groff_mm_element_list(out, elt);
1264
+ break;
1265
+ case ODF_FORMAT:
1266
+ print_odf_header(out);
1267
+ g_string_append_printf(out, "<office:body>\n<office:text>\n");
1268
+ if (elt != NULL) print_odf_element_list(out,elt);
1269
+ print_odf_footer(out);
1270
+ break;
1271
+ default:
1272
+ fprintf(stderr, "print_element - unknown format = %d\n", format);
1273
+ exit(EXIT_FAILURE);
1274
+ }
1275
+ }