mmd-ruby 5.2.0.1
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.
- checksums.yaml +7 -0
- data/LICENSE +78 -0
- data/MultiMarkdown-5/src/GLibFacade.c +310 -0
- data/MultiMarkdown-5/src/GLibFacade.h +100 -0
- data/MultiMarkdown-5/src/beamer.c +182 -0
- data/MultiMarkdown-5/src/beamer.h +11 -0
- data/MultiMarkdown-5/src/critic.c +117 -0
- data/MultiMarkdown-5/src/critic.h +15 -0
- data/MultiMarkdown-5/src/glib.h +11 -0
- data/MultiMarkdown-5/src/html.c +1171 -0
- data/MultiMarkdown-5/src/html.h +14 -0
- data/MultiMarkdown-5/src/latex.c +1234 -0
- data/MultiMarkdown-5/src/latex.h +16 -0
- data/MultiMarkdown-5/src/libMultiMarkdown.h +257 -0
- data/MultiMarkdown-5/src/lyx.c +2269 -0
- data/MultiMarkdown-5/src/lyx.h +37 -0
- data/MultiMarkdown-5/src/lyxbeamer.c +265 -0
- data/MultiMarkdown-5/src/lyxbeamer.h +11 -0
- data/MultiMarkdown-5/src/memoir.c +80 -0
- data/MultiMarkdown-5/src/memoir.h +10 -0
- data/MultiMarkdown-5/src/multimarkdown.c +559 -0
- data/MultiMarkdown-5/src/odf.c +1241 -0
- data/MultiMarkdown-5/src/odf.h +18 -0
- data/MultiMarkdown-5/src/opml.c +189 -0
- data/MultiMarkdown-5/src/opml.h +15 -0
- data/MultiMarkdown-5/src/parse_utilities.c +912 -0
- data/MultiMarkdown-5/src/parser.c +17341 -0
- data/MultiMarkdown-5/src/parser.h +190 -0
- data/MultiMarkdown-5/src/rng.c +117 -0
- data/MultiMarkdown-5/src/rtf.c +665 -0
- data/MultiMarkdown-5/src/rtf.h +17 -0
- data/MultiMarkdown-5/src/strtok.c +56 -0
- data/MultiMarkdown-5/src/strtok.h +9 -0
- data/MultiMarkdown-5/src/text.c +56 -0
- data/MultiMarkdown-5/src/text.h +11 -0
- data/MultiMarkdown-5/src/toc.c +157 -0
- data/MultiMarkdown-5/src/toc.h +15 -0
- data/MultiMarkdown-5/src/transclude.c +335 -0
- data/MultiMarkdown-5/src/transclude.h +28 -0
- data/MultiMarkdown-5/src/version.h +59 -0
- data/MultiMarkdown-5/src/writer.c +767 -0
- data/MultiMarkdown-5/src/writer.h +38 -0
- data/README.md +77 -0
- data/Rakefile +88 -0
- data/bin/mmd-ruby +123 -0
- data/ext/extconf.h +3 -0
- data/ext/extconf.rb +10 -0
- data/ext/multimarkdown.c +133 -0
- data/lib/mmd-jekyll.rb +19 -0
- data/lib/mmd-ruby.rb +1 -0
- data/lib/mmd.rb +1 -0
- data/lib/multimarkdown-ruby.rb +1 -0
- data/lib/multimarkdown.bundle +0 -0
- data/lib/multimarkdown.rb +69 -0
- data/lib/multimarkdown/version.rb +6 -0
- data/mmd-ruby.gemspec +37 -0
- data/test/extensions_test.rb +174 -0
- data/test/multimarkdown_test.rb +77 -0
- metadata +120 -0
@@ -0,0 +1,28 @@
|
|
1
|
+
/*
|
2
|
+
|
3
|
+
transclude.h -- miscellaneous support functions
|
4
|
+
|
5
|
+
(c) 2013 Fletcher T. Penney (http://fletcherpenney.net/).
|
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 <stdio.h>
|
19
|
+
#include <string.h>
|
20
|
+
#include <stdlib.h>
|
21
|
+
#include <stdbool.h>
|
22
|
+
#include <libgen.h>
|
23
|
+
#include "GLibFacade.h"
|
24
|
+
|
25
|
+
char * source_without_metadata(char * source, unsigned long extensions);
|
26
|
+
void transclude_source(GString *source, char *basedir, char *stack, int format, GString *manifest);
|
27
|
+
void append_mmd_footer(GString *source);
|
28
|
+
void prepend_mmd_header(GString *source);
|
@@ -0,0 +1,59 @@
|
|
1
|
+
/*
|
2
|
+
|
3
|
+
***NOTE*** -- this version of the file is only for use with
|
4
|
+
"make deprecated". It will not be automatically updated with the latest
|
5
|
+
version information.
|
6
|
+
|
7
|
+
|
8
|
+
version_deprecated.h -- MultiMarkdown
|
9
|
+
|
10
|
+
Copyright © 2013-2016 Fletcher T. Penney.
|
11
|
+
|
12
|
+
|
13
|
+
The `c-template` project is released under the MIT License.
|
14
|
+
|
15
|
+
|
16
|
+
MMD 5 is released under the MIT License.
|
17
|
+
|
18
|
+
|
19
|
+
CuTest is released under the zlib/libpng license. See CuTest.c for the text
|
20
|
+
of the license.
|
21
|
+
|
22
|
+
|
23
|
+
## The MIT License ##
|
24
|
+
|
25
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
26
|
+
of this software and associated documentation files (the "Software"), to deal
|
27
|
+
in the Software without restriction, including without limitation the rights
|
28
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
29
|
+
copies of the Software, and to permit persons to whom the Software is
|
30
|
+
furnished to do so, subject to the following conditions:
|
31
|
+
|
32
|
+
The above copyright notice and this permission notice shall be included in
|
33
|
+
all copies or substantial portions of the Software.
|
34
|
+
|
35
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
36
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
37
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
38
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
39
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
40
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
41
|
+
THE SOFTWARE.
|
42
|
+
|
43
|
+
*/
|
44
|
+
|
45
|
+
/**
|
46
|
+
|
47
|
+
@file
|
48
|
+
|
49
|
+
@brief MultiMarkdown - lightweight markup processor - project version header
|
50
|
+
|
51
|
+
**/
|
52
|
+
|
53
|
+
|
54
|
+
#ifndef FILE_MULTIMARKDOWN_VERSION_H
|
55
|
+
#define FILE_MULTIMARKDOWN_VERSION_H
|
56
|
+
|
57
|
+
#define MULTIMARKDOWN_VERSION "5.2.0-dep"
|
58
|
+
|
59
|
+
#endif
|
@@ -0,0 +1,767 @@
|
|
1
|
+
/*
|
2
|
+
|
3
|
+
writer.c -- General routines for converting parse structure to various
|
4
|
+
output formats.
|
5
|
+
|
6
|
+
(c) 2013-2016 Fletcher T. Penney (http://fletcherpenney.net/).
|
7
|
+
|
8
|
+
Derived from peg-multimarkdown, which was forked from peg-markdown,
|
9
|
+
which is (c) 2008 John MacFarlane (jgm at berkeley dot edu), and
|
10
|
+
licensed under GNU GPL or MIT.
|
11
|
+
|
12
|
+
This program is free software; you can redistribute it and/or modify
|
13
|
+
it under the terms of the GNU General Public License or the MIT
|
14
|
+
license. See LICENSE for details.
|
15
|
+
|
16
|
+
This program is distributed in the hope that it will be useful,
|
17
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
18
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
19
|
+
GNU General Public License for more details.
|
20
|
+
|
21
|
+
*/
|
22
|
+
|
23
|
+
#include "writer.h"
|
24
|
+
|
25
|
+
/* export_node_tree -- given a tree, export as specified format */
|
26
|
+
char * export_node_tree(node *list, int format, unsigned long extensions) {
|
27
|
+
char *output;
|
28
|
+
char *temp;
|
29
|
+
GString *out = g_string_new("");
|
30
|
+
scratch_pad *scratch = mk_scratch_pad(extensions);
|
31
|
+
scratch->result_tree = list; /* Pointer to result tree to use later */
|
32
|
+
|
33
|
+
#ifdef DEBUG_ON
|
34
|
+
fprintf(stderr, "export_node_tree\n");
|
35
|
+
#endif
|
36
|
+
|
37
|
+
#ifdef DEBUG_ON
|
38
|
+
fprintf(stderr, "extract_references\n");
|
39
|
+
#endif
|
40
|
+
|
41
|
+
if ((format != OPML_FORMAT) &&
|
42
|
+
(format != CRITIC_ACCEPT_FORMAT) &&
|
43
|
+
(format != CRITIC_REJECT_FORMAT) &&
|
44
|
+
(format != CRITIC_HTML_HIGHLIGHT_FORMAT)) {
|
45
|
+
/* Find defined abbreviations */
|
46
|
+
extract_abbreviations(list, scratch);
|
47
|
+
/* Apply those abbreviations to source text */
|
48
|
+
find_abbreviations(list, scratch);
|
49
|
+
|
50
|
+
/* Parse for link, images, etc reference definitions */
|
51
|
+
extract_references(list, scratch);
|
52
|
+
}
|
53
|
+
|
54
|
+
/* Change our desired format based on metadata */
|
55
|
+
if (format == LATEX_FORMAT)
|
56
|
+
format = find_latex_mode(format, list);
|
57
|
+
|
58
|
+
switch (format) {
|
59
|
+
case TEXT_FORMAT:
|
60
|
+
print_text_node_tree(out, list, scratch);
|
61
|
+
break;
|
62
|
+
case HTML_FORMAT:
|
63
|
+
if (scratch->extensions & EXT_COMPLETE) {
|
64
|
+
temp = metavalue_for_key("lang", scratch->result_tree);
|
65
|
+
if (temp != NULL) {
|
66
|
+
g_string_append_printf(out,
|
67
|
+
"<!DOCTYPE html>\n<html lang=\"%s\">\n<head>\n\t<meta charset=\"utf-8\"/>\n",temp);
|
68
|
+
free(temp);
|
69
|
+
} else {
|
70
|
+
g_string_append_printf(out,
|
71
|
+
"<!DOCTYPE html>\n<html>\n<head>\n\t<meta charset=\"utf-8\"/>\n");
|
72
|
+
}
|
73
|
+
}
|
74
|
+
#ifdef DEBUG_ON
|
75
|
+
fprintf(stderr, "print_html output\n");
|
76
|
+
#endif
|
77
|
+
print_html_node_tree(out, list, scratch);
|
78
|
+
#ifdef DEBUG_ON
|
79
|
+
fprintf(stderr, "print html endnotes\n");
|
80
|
+
#endif
|
81
|
+
print_html_endnotes(out, scratch);
|
82
|
+
#ifdef DEBUG_ON
|
83
|
+
fprintf(stderr, "finished printing html endnotes\n");
|
84
|
+
#endif
|
85
|
+
|
86
|
+
if (scratch->html_footer != NULL) {
|
87
|
+
// Print html footer if present
|
88
|
+
pad(out, 2, scratch);
|
89
|
+
g_string_append_printf(out,"%s\n", scratch->html_footer);
|
90
|
+
}
|
91
|
+
|
92
|
+
if (scratch->extensions & EXT_COMPLETE) {
|
93
|
+
pad(out,2, scratch);
|
94
|
+
g_string_append_printf(out, "</body>\n</html>");
|
95
|
+
}
|
96
|
+
#ifdef DEBUG_ON
|
97
|
+
fprintf(stderr, "closed HTML document\n");
|
98
|
+
#endif
|
99
|
+
break;
|
100
|
+
case LATEX_FORMAT:
|
101
|
+
if ((list != NULL) && (list->key != METADATA)) {
|
102
|
+
print_latex_node_tree(out, scratch->abbreviations, scratch);
|
103
|
+
}
|
104
|
+
print_latex_node_tree(out, list, scratch);
|
105
|
+
break;
|
106
|
+
case MEMOIR_FORMAT:
|
107
|
+
if ((list != NULL) && (list->key != METADATA)) {
|
108
|
+
print_memoir_node_tree(out, scratch->abbreviations, scratch);
|
109
|
+
}
|
110
|
+
print_memoir_node_tree(out, list, scratch);
|
111
|
+
break;
|
112
|
+
case BEAMER_FORMAT:
|
113
|
+
if ((list != NULL) && (list->key != METADATA)) {
|
114
|
+
print_beamer_node_tree(out, scratch->abbreviations, scratch);
|
115
|
+
}
|
116
|
+
print_beamer_node_tree(out, list, scratch);
|
117
|
+
break;
|
118
|
+
case LYX_FORMAT:
|
119
|
+
perform_lyx_output(out,list,scratch);
|
120
|
+
break;
|
121
|
+
case OPML_FORMAT:
|
122
|
+
#ifdef DEBUG_ON
|
123
|
+
fprintf(stderr, "export OPML\n");
|
124
|
+
#endif
|
125
|
+
begin_opml_output(out, list, scratch);
|
126
|
+
print_opml_node_tree(out, list, scratch);
|
127
|
+
end_opml_output(out, list, scratch);
|
128
|
+
break;
|
129
|
+
case ODF_FORMAT:
|
130
|
+
#ifdef DEBUG_ON
|
131
|
+
fprintf(stderr, "export ODF\n");
|
132
|
+
#endif
|
133
|
+
begin_odf_output(out, list, scratch);
|
134
|
+
print_odf_node_tree(out, list, scratch);
|
135
|
+
end_odf_output(out, list, scratch);
|
136
|
+
break;
|
137
|
+
case RTF_FORMAT:
|
138
|
+
#ifdef DEBUG_ON
|
139
|
+
fprintf(stderr, "export RTF\n");
|
140
|
+
#endif
|
141
|
+
if (!(scratch->extensions & EXT_SNIPPET))
|
142
|
+
begin_rtf_output(out, list, scratch);
|
143
|
+
print_rtf_node_tree(out, list, scratch);
|
144
|
+
if (!(scratch->extensions & EXT_SNIPPET))
|
145
|
+
end_rtf_output(out, list, scratch);
|
146
|
+
break;
|
147
|
+
case CRITIC_ACCEPT_FORMAT:
|
148
|
+
print_critic_accept_node_tree(out, list, scratch);
|
149
|
+
break;
|
150
|
+
case CRITIC_REJECT_FORMAT:
|
151
|
+
print_critic_reject_node_tree(out, list, scratch);
|
152
|
+
break;
|
153
|
+
case CRITIC_HTML_HIGHLIGHT_FORMAT:
|
154
|
+
print_critic_html_highlight_node_tree(out, list, scratch);
|
155
|
+
break;
|
156
|
+
case TOC_FORMAT:
|
157
|
+
scratch->toc_level = 0;
|
158
|
+
print_toc_node_tree(out,list,scratch);
|
159
|
+
break;
|
160
|
+
default:
|
161
|
+
fprintf(stderr, "Unknown export format = %d\n",format);
|
162
|
+
exit(EXIT_FAILURE);
|
163
|
+
}
|
164
|
+
|
165
|
+
output = out->str;
|
166
|
+
g_string_free(out, false);
|
167
|
+
free_scratch_pad(scratch);
|
168
|
+
|
169
|
+
#ifdef DEBUG_ON
|
170
|
+
fprintf(stderr, "finish export_node_tree\n");
|
171
|
+
#endif
|
172
|
+
return output;
|
173
|
+
}
|
174
|
+
|
175
|
+
/* extract_references -- go through node tree and find elements we need to reference;
|
176
|
+
e.g. links, images, citations, footnotes
|
177
|
+
Copy them from main parse tree */
|
178
|
+
void extract_references(node *list, scratch_pad *scratch) {
|
179
|
+
node *temp;
|
180
|
+
char * temp_str;
|
181
|
+
link_data *l;
|
182
|
+
|
183
|
+
while (list != NULL) {
|
184
|
+
switch (list->key) {
|
185
|
+
case LINKREFERENCE:
|
186
|
+
l = list->link_data;
|
187
|
+
temp_str = lower_string(l->label);
|
188
|
+
|
189
|
+
temp = mk_link(list->children, temp_str, l->source, l->title, NULL);
|
190
|
+
temp->link_data->attr = copy_node_tree(l->attr);
|
191
|
+
|
192
|
+
/* store copy of link reference */
|
193
|
+
scratch->links = cons(temp, scratch->links);
|
194
|
+
|
195
|
+
free(temp_str);
|
196
|
+
|
197
|
+
break;
|
198
|
+
case NOTESOURCE:
|
199
|
+
case GLOSSARYSOURCE:
|
200
|
+
temp = copy_node(list);
|
201
|
+
scratch->notes = cons(temp, scratch->notes);
|
202
|
+
break;
|
203
|
+
case H1: case H2: case H3: case H4: case H5: case H6:
|
204
|
+
if ((list->children->key != AUTOLABEL) && !(scratch->extensions & EXT_NO_LABELS)
|
205
|
+
&& !(scratch->extensions & EXT_COMPATIBILITY)) {
|
206
|
+
char *label = label_from_node_tree(list->children);
|
207
|
+
|
208
|
+
/* create a label from header */
|
209
|
+
temp = mk_autolink(label);
|
210
|
+
scratch->links = cons(temp, scratch->links);
|
211
|
+
free(label);
|
212
|
+
}
|
213
|
+
break;
|
214
|
+
case TABLE:
|
215
|
+
if (list->children->key != TABLELABEL) {
|
216
|
+
char *label = label_from_node(list->children);
|
217
|
+
|
218
|
+
/* create a label from header */
|
219
|
+
temp = mk_autolink(label);
|
220
|
+
scratch->links = cons(temp, scratch->links);
|
221
|
+
free(label);
|
222
|
+
}
|
223
|
+
|
224
|
+
break;
|
225
|
+
case HEADINGSECTION:
|
226
|
+
case RAW:
|
227
|
+
case LIST:
|
228
|
+
extract_references(list->children, scratch);
|
229
|
+
break;
|
230
|
+
default:
|
231
|
+
break;
|
232
|
+
}
|
233
|
+
list = list->next;
|
234
|
+
}
|
235
|
+
}
|
236
|
+
|
237
|
+
/* extract_abbreviations -- traverse node tree and find abbreviation definitions */
|
238
|
+
void extract_abbreviations(node *list, scratch_pad *scratch) {
|
239
|
+
node *temp;
|
240
|
+
|
241
|
+
while (list != NULL) {
|
242
|
+
switch (list->key) {
|
243
|
+
case ABBREVIATION:
|
244
|
+
temp = copy_node(list);
|
245
|
+
list->key = KEY_COUNTER; /* Mark this as dead; we will use it elsewhere */
|
246
|
+
trim_trailing_whitespace(temp->str);
|
247
|
+
scratch->abbreviations = cons(temp, scratch->abbreviations);
|
248
|
+
break;
|
249
|
+
case HEADINGSECTION:
|
250
|
+
case RAW:
|
251
|
+
case LIST:
|
252
|
+
case BLOCKQUOTEMARKER:
|
253
|
+
case BLOCKQUOTE:
|
254
|
+
extract_abbreviations(list->children, scratch);
|
255
|
+
break;
|
256
|
+
default:
|
257
|
+
/* Try to boost performance by skipping dead ends */
|
258
|
+
break;
|
259
|
+
}
|
260
|
+
list = list->next;
|
261
|
+
}
|
262
|
+
}
|
263
|
+
|
264
|
+
|
265
|
+
/* find_abbreviations -- use abbreviations to look for matching strings */
|
266
|
+
void find_abbreviations(node *list, scratch_pad *scratch) {
|
267
|
+
node *abbr = scratch->abbreviations;
|
268
|
+
node *temp, *target, *end = NULL;
|
269
|
+
bool ismatch;
|
270
|
+
|
271
|
+
// Don't look if we didn't define any abbreviations */
|
272
|
+
if (abbr->key == KEY_COUNTER)
|
273
|
+
return;
|
274
|
+
|
275
|
+
while (list != NULL) {
|
276
|
+
switch (list->key) {
|
277
|
+
case STR:
|
278
|
+
/* Look for matching abbrevation */
|
279
|
+
/*fprintf(stderr, "Check '%s' for matching abbr\n", list->str); */
|
280
|
+
abbr = scratch->abbreviations;
|
281
|
+
while (abbr != NULL) {
|
282
|
+
if (abbr->key != KEY_COUNTER) {
|
283
|
+
ismatch = true;
|
284
|
+
temp = abbr->children->children;
|
285
|
+
target = list;
|
286
|
+
|
287
|
+
while((ismatch) && (temp != NULL) && (target != NULL)) {
|
288
|
+
switch (temp->key) {
|
289
|
+
case STR:
|
290
|
+
if (strcmp(temp->str, target->str) != 0) {
|
291
|
+
ismatch = false;
|
292
|
+
}
|
293
|
+
case SPACE:
|
294
|
+
case KEY_COUNTER:
|
295
|
+
break;
|
296
|
+
default:
|
297
|
+
if (temp->key != target->key)
|
298
|
+
ismatch = false;
|
299
|
+
break;
|
300
|
+
}
|
301
|
+
temp = temp->next;
|
302
|
+
end = target;
|
303
|
+
target = target->next;
|
304
|
+
}
|
305
|
+
if ((ismatch) && (temp == NULL)) {
|
306
|
+
temp = copy_node(abbr);
|
307
|
+
temp->next = NULL;
|
308
|
+
list->children = temp;
|
309
|
+
if (list != end) {
|
310
|
+
list->key = ABBRSTART;
|
311
|
+
if (end != NULL)
|
312
|
+
end->key = ABBRSTOP;
|
313
|
+
} else {
|
314
|
+
list->key = ABBR;
|
315
|
+
}
|
316
|
+
}
|
317
|
+
}
|
318
|
+
abbr = abbr->next;
|
319
|
+
}
|
320
|
+
break;
|
321
|
+
case LIST:
|
322
|
+
case ORDEREDLIST:
|
323
|
+
case BULLETLIST:
|
324
|
+
case LISTITEM:
|
325
|
+
case HEADINGSECTION:
|
326
|
+
case PARA:
|
327
|
+
case PLAIN:
|
328
|
+
case LINK:
|
329
|
+
case LINKREFERENCE:
|
330
|
+
case NOTEREFERENCE:
|
331
|
+
case NOTESOURCE:
|
332
|
+
case GLOSSARYSOURCE:
|
333
|
+
case BLOCKQUOTEMARKER:
|
334
|
+
case BLOCKQUOTE:
|
335
|
+
case STRONG:
|
336
|
+
case EMPH:
|
337
|
+
case TABLE:
|
338
|
+
case TABLEBODY:
|
339
|
+
case TABLEROW:
|
340
|
+
case TABLECELL:
|
341
|
+
/* Check children of these elements */
|
342
|
+
find_abbreviations(list->children, scratch);
|
343
|
+
break;
|
344
|
+
default:
|
345
|
+
/* Everything else we skip */
|
346
|
+
break;
|
347
|
+
}
|
348
|
+
list = list->next;
|
349
|
+
}
|
350
|
+
}
|
351
|
+
|
352
|
+
|
353
|
+
/* extract_link_data -- given a label, parse the link data and return */
|
354
|
+
link_data * extract_link_data(char *label, scratch_pad *scratch) {
|
355
|
+
char *temp;
|
356
|
+
char *temp2;
|
357
|
+
link_data *d;
|
358
|
+
node *ref = scratch->links;
|
359
|
+
bool debug = 0;
|
360
|
+
|
361
|
+
if (debug)
|
362
|
+
fprintf(stderr, "try to extract link for '%s'\n",label);
|
363
|
+
|
364
|
+
if ((label == NULL) || (strlen(label) == 0))
|
365
|
+
return NULL;
|
366
|
+
|
367
|
+
temp2 = clean_string(label);
|
368
|
+
temp = lower_string(temp2);
|
369
|
+
|
370
|
+
/* look for label string as is */
|
371
|
+
while (ref != NULL) {
|
372
|
+
if (ref->key == KEY_COUNTER) {
|
373
|
+
ref = ref->next;
|
374
|
+
|
375
|
+
continue;
|
376
|
+
}
|
377
|
+
if (strcmp(ref->link_data->label, temp) == 0) {
|
378
|
+
if (debug)
|
379
|
+
fprintf(stderr,"a:matched %s to %s\n",ref->link_data->label, label);
|
380
|
+
/* matched */
|
381
|
+
d = ref->link_data;
|
382
|
+
d = mk_link_data(d->label, d->source, d->title, d->attr);
|
383
|
+
|
384
|
+
free(temp);
|
385
|
+
free(temp2);
|
386
|
+
|
387
|
+
return d;
|
388
|
+
} else {
|
389
|
+
if (debug)
|
390
|
+
fprintf(stderr,"a:did not match %s to %s\n",ref->link_data->label, label);
|
391
|
+
}
|
392
|
+
ref = ref->next;
|
393
|
+
}
|
394
|
+
|
395
|
+
free(temp);
|
396
|
+
free(temp2);
|
397
|
+
|
398
|
+
/* No match. Check for label()version */
|
399
|
+
|
400
|
+
if (scratch->extensions & EXT_COMPATIBILITY) {
|
401
|
+
/* not in compat mode */
|
402
|
+
return NULL;
|
403
|
+
}
|
404
|
+
temp = label_from_string(label);
|
405
|
+
|
406
|
+
ref = scratch->links;
|
407
|
+
|
408
|
+
while (ref != NULL) {
|
409
|
+
if (ref->key == KEY_COUNTER) {
|
410
|
+
ref = ref->next;
|
411
|
+
|
412
|
+
continue;
|
413
|
+
}
|
414
|
+
if (strcmp(ref->link_data->label, temp) == 0) {
|
415
|
+
if (debug)
|
416
|
+
fprintf(stderr,"b:matched %s to %s\n",ref->link_data->label, label);
|
417
|
+
/* matched */
|
418
|
+
d = ref->link_data;
|
419
|
+
d = mk_link_data(d->label, d->source, d->title, d->attr);
|
420
|
+
|
421
|
+
free(temp);
|
422
|
+
|
423
|
+
return d;
|
424
|
+
} else {
|
425
|
+
if (debug)
|
426
|
+
fprintf(stderr,"b:did not match %s to %s\n",ref->link_data->label, label);
|
427
|
+
}
|
428
|
+
ref = ref->next;
|
429
|
+
}
|
430
|
+
|
431
|
+
free(temp);
|
432
|
+
|
433
|
+
if (debug)
|
434
|
+
fprintf(stderr, "finish extract\n");
|
435
|
+
return NULL;
|
436
|
+
}
|
437
|
+
|
438
|
+
/* pad -- ensure that at least 'x' newlines are at end of output */
|
439
|
+
void pad(GString *out, int num, scratch_pad *scratch) {
|
440
|
+
while (num-- > scratch->padded)
|
441
|
+
g_string_append_c(out, '\n');
|
442
|
+
|
443
|
+
scratch->padded = num;
|
444
|
+
}
|
445
|
+
|
446
|
+
/* note_number_for_label -- given a label to match, determine number to be used*/
|
447
|
+
int note_number_for_label(char *text, scratch_pad *scratch) {
|
448
|
+
node *n = NULL;
|
449
|
+
char *clean;
|
450
|
+
char *label;
|
451
|
+
#ifdef DEBUG_ON
|
452
|
+
fprintf(stderr, "find note number for: %s\n",text);
|
453
|
+
#endif
|
454
|
+
|
455
|
+
if ((text == NULL) || (strlen(text) == 0))
|
456
|
+
return 0; /* Nothing to find */
|
457
|
+
|
458
|
+
clean = clean_string(text);
|
459
|
+
label = label_from_string(clean);
|
460
|
+
|
461
|
+
/* have we used this note already? */
|
462
|
+
|
463
|
+
/* look for label string as is */
|
464
|
+
n = node_matching_label(clean, scratch->used_notes);
|
465
|
+
|
466
|
+
/* if not, look in reserve queue */
|
467
|
+
if (n == NULL) {
|
468
|
+
n = node_matching_label(clean, scratch->notes);
|
469
|
+
|
470
|
+
if (n != NULL) {
|
471
|
+
/* move to used queue */
|
472
|
+
move_note_to_used(n, scratch);
|
473
|
+
#ifdef DEBUG_ON
|
474
|
+
fprintf(stderr, "note has not already been used for: %s\n",text);
|
475
|
+
#endif
|
476
|
+
}
|
477
|
+
} else {
|
478
|
+
#ifdef DEBUG_ON
|
479
|
+
fprintf(stderr, "note has already been used for: %s\n",text);
|
480
|
+
#endif
|
481
|
+
}
|
482
|
+
|
483
|
+
/* Check label version */
|
484
|
+
if (n == NULL)
|
485
|
+
n = node_matching_label(label, scratch->used_notes);
|
486
|
+
|
487
|
+
if (n == NULL) {
|
488
|
+
n = node_matching_label(label, scratch->notes);
|
489
|
+
|
490
|
+
if (n != NULL) {
|
491
|
+
/* move to used queue */
|
492
|
+
move_note_to_used(n, scratch);
|
493
|
+
#ifdef DEBUG_ON
|
494
|
+
fprintf(stderr, "note has not already been used for: %s\n",label);
|
495
|
+
#endif
|
496
|
+
}
|
497
|
+
} else {
|
498
|
+
#ifdef DEBUG_ON
|
499
|
+
fprintf(stderr, "note has already been used for: %s\n",label);
|
500
|
+
#endif
|
501
|
+
|
502
|
+
}
|
503
|
+
|
504
|
+
/* CAN recursively drill down to start counter at 0 and ++ */
|
505
|
+
/* if found, move to used queue and return the number */
|
506
|
+
|
507
|
+
free(label);
|
508
|
+
free(clean);
|
509
|
+
if (n != NULL) {
|
510
|
+
#ifdef DEBUG_ON
|
511
|
+
fprintf(stderr, "note number is: %d\n",count_node_from_end(n));
|
512
|
+
#endif
|
513
|
+
return count_node_from_end(n);
|
514
|
+
}
|
515
|
+
else
|
516
|
+
return 0;
|
517
|
+
}
|
518
|
+
|
519
|
+
/* note_number_for_node -- given a note reference to match, determine number to be used*/
|
520
|
+
int note_number_for_node(node *ref, scratch_pad *scratch) {
|
521
|
+
char *label = ref->str;
|
522
|
+
node *n = NULL;
|
523
|
+
int num = 0;
|
524
|
+
|
525
|
+
num = note_number_for_label(label, scratch);
|
526
|
+
|
527
|
+
if (num > 0)
|
528
|
+
return num;
|
529
|
+
|
530
|
+
/* None found, so treat as inline note */
|
531
|
+
n = ref->children;
|
532
|
+
use_inline_footnote(ref, scratch);
|
533
|
+
|
534
|
+
return count_node_from_end(n);
|
535
|
+
}
|
536
|
+
|
537
|
+
|
538
|
+
/* node_matching_label -- given a string, return the node matching the string */
|
539
|
+
node * node_matching_label(char *label, node *n) {
|
540
|
+
while (n != NULL) {
|
541
|
+
if (n->key == KEY_COUNTER) {
|
542
|
+
n = n->next;
|
543
|
+
continue;
|
544
|
+
}
|
545
|
+
if (strcmp(n->str, label) == 0) {
|
546
|
+
return n;
|
547
|
+
}
|
548
|
+
n = n->next;
|
549
|
+
}
|
550
|
+
|
551
|
+
return NULL;
|
552
|
+
}
|
553
|
+
|
554
|
+
/* since lists are stored in reverse order, need to count from end */
|
555
|
+
int count_node_from_end(node *n) {
|
556
|
+
if (n->next == NULL) {
|
557
|
+
if (n->key == KEY_COUNTER)
|
558
|
+
return 0;
|
559
|
+
#ifdef DEBUG_ON
|
560
|
+
fprintf(stderr, "note %d: '%s'\n",1,n->str);
|
561
|
+
#endif
|
562
|
+
return 1; /* reserve 0 for not found */
|
563
|
+
}
|
564
|
+
#ifdef DEBUG_ON
|
565
|
+
fprintf(stderr, "note %d: '%s'\n",count_node_from_end(n->next) +1,n->str);
|
566
|
+
#endif
|
567
|
+
return (count_node_from_end(n->next) + 1);
|
568
|
+
}
|
569
|
+
|
570
|
+
/* since lists are stored in reverse order, need to count from end
|
571
|
+
Only count cites (not footnotes) */
|
572
|
+
int cite_count_node_from_end(node *n) {
|
573
|
+
if (n->next == NULL) {
|
574
|
+
/* we're the last node */
|
575
|
+
if (n->key == CITATIONSOURCE)
|
576
|
+
return 1;
|
577
|
+
return 0; /* reserve 0 for not found */
|
578
|
+
}
|
579
|
+
if (n->key == CITATIONSOURCE) {
|
580
|
+
return (cite_count_node_from_end(n->next) + 1);
|
581
|
+
} else {
|
582
|
+
return (cite_count_node_from_end(n->next));
|
583
|
+
}
|
584
|
+
}
|
585
|
+
|
586
|
+
/* node_for_count -- given a number, get that node */
|
587
|
+
node * node_for_count(node *n, int count) {
|
588
|
+
if (n == NULL)
|
589
|
+
return NULL;
|
590
|
+
|
591
|
+
int total = count_node_from_end(n);
|
592
|
+
|
593
|
+
if (count > total)
|
594
|
+
return NULL;
|
595
|
+
|
596
|
+
if (count == total)
|
597
|
+
return n;
|
598
|
+
|
599
|
+
while (total > count) {
|
600
|
+
n = n->next;
|
601
|
+
if (n == NULL)
|
602
|
+
return NULL;
|
603
|
+
total--;
|
604
|
+
}
|
605
|
+
|
606
|
+
return n;
|
607
|
+
}
|
608
|
+
|
609
|
+
/* move_note_to_used -- snip note from ->notes and move to used_notes */
|
610
|
+
void move_note_to_used(node *list, scratch_pad *scratch) {
|
611
|
+
node * n = scratch->notes;
|
612
|
+
node * last = NULL;
|
613
|
+
|
614
|
+
while (n != NULL) {
|
615
|
+
if (n == list) {
|
616
|
+
if (last != NULL) {
|
617
|
+
last->next = n->next;
|
618
|
+
} else {
|
619
|
+
scratch->notes = n->next;
|
620
|
+
}
|
621
|
+
scratch->used_notes = cons(n, scratch->used_notes);
|
622
|
+
return;
|
623
|
+
}
|
624
|
+
last = n;
|
625
|
+
n = n->next;
|
626
|
+
}
|
627
|
+
}
|
628
|
+
|
629
|
+
/* use_inline_footnote -- create a new note definition from inline footnote */
|
630
|
+
void use_inline_footnote(node *ref, scratch_pad *scratch) {
|
631
|
+
scratch->used_notes = cons(ref->children, scratch->used_notes);
|
632
|
+
ref->children = NULL;
|
633
|
+
}
|
634
|
+
|
635
|
+
/* find attribute, if present */
|
636
|
+
node * node_for_attribute(char *querystring, node *list) {
|
637
|
+
#ifdef DEBUG_ON
|
638
|
+
fprintf(stderr, "start node_for_attribute\n");
|
639
|
+
#endif
|
640
|
+
node *step = NULL;
|
641
|
+
step = list;
|
642
|
+
char *query;
|
643
|
+
|
644
|
+
if (querystring == NULL)
|
645
|
+
return NULL;
|
646
|
+
|
647
|
+
query = label_from_string(querystring);
|
648
|
+
#ifdef DEBUG_ON
|
649
|
+
fprintf(stderr, "node_for_attribute 2: '%s'\n",query);
|
650
|
+
#endif
|
651
|
+
|
652
|
+
while (step != NULL) {
|
653
|
+
if ((step->str != NULL) && (strcmp(step->str,query) == 0)) {
|
654
|
+
free(query);
|
655
|
+
#ifdef DEBUG_ON
|
656
|
+
fprintf(stderr, "matched node_for_attribute\n");
|
657
|
+
#endif
|
658
|
+
return step;
|
659
|
+
}
|
660
|
+
#ifdef DEBUG_ON
|
661
|
+
fprintf(stderr, "'%s' doesn't match '%s'\n",query,step->str);
|
662
|
+
if (step->next == NULL)
|
663
|
+
fprintf(stderr, "no next node\n");
|
664
|
+
#endif
|
665
|
+
step = step->next;
|
666
|
+
}
|
667
|
+
free(query);
|
668
|
+
#ifdef DEBUG_ON
|
669
|
+
fprintf(stderr, "stop node_for_attribute\n");
|
670
|
+
#endif
|
671
|
+
return NULL;
|
672
|
+
}
|
673
|
+
|
674
|
+
|
675
|
+
/* convert attribute to dimensions suitable for LaTeX or ODF */
|
676
|
+
/* returns c string that needs to be freed */
|
677
|
+
char * dimension_for_attribute(char *querystring, node *list) {
|
678
|
+
#ifdef DEBUG_ON
|
679
|
+
fprintf(stderr, "start dimension_for_attribute\n");
|
680
|
+
#endif
|
681
|
+
node *attribute;
|
682
|
+
char *dimension;
|
683
|
+
char *ptr;
|
684
|
+
int i;
|
685
|
+
char *upper;
|
686
|
+
GString *result;
|
687
|
+
|
688
|
+
attribute = node_for_attribute(querystring, list);
|
689
|
+
if (attribute == NULL) return NULL;
|
690
|
+
#ifdef DEBUG_ON
|
691
|
+
fprintf(stderr, "a\n");
|
692
|
+
#endif
|
693
|
+
|
694
|
+
dimension = strdup(attribute->children->str);
|
695
|
+
upper = strdup(attribute->children->str);
|
696
|
+
|
697
|
+
for(i = 0; dimension[ i ]; i++)
|
698
|
+
dimension[i] = tolower(dimension[ i ]);
|
699
|
+
|
700
|
+
for(i = 0; upper[ i ]; i++)
|
701
|
+
upper[i] = toupper(upper[ i ]);
|
702
|
+
#ifdef DEBUG_ON
|
703
|
+
fprintf(stderr, "b\n");
|
704
|
+
#endif
|
705
|
+
|
706
|
+
if (strstr(dimension, "px")) {
|
707
|
+
ptr = strstr(dimension,"px");
|
708
|
+
ptr[0] = '\0';
|
709
|
+
strcat(ptr,"pt");
|
710
|
+
}
|
711
|
+
|
712
|
+
result = g_string_new(dimension);
|
713
|
+
|
714
|
+
if ((strcmp(dimension,upper) == 0) && (dimension[strlen(dimension) -1] != '%')) {
|
715
|
+
/* no units */
|
716
|
+
g_string_append_printf(result, "pt");
|
717
|
+
}
|
718
|
+
|
719
|
+
free(upper);
|
720
|
+
free(dimension);
|
721
|
+
|
722
|
+
dimension = result->str;
|
723
|
+
g_string_free(result, false);
|
724
|
+
#ifdef DEBUG_ON
|
725
|
+
fprintf(stderr, "finish dimension_for_attribute\n");
|
726
|
+
#endif
|
727
|
+
return(dimension);
|
728
|
+
}
|
729
|
+
|
730
|
+
|
731
|
+
/* Load available info for a link */
|
732
|
+
link_data * load_link_data(node *n, scratch_pad *scratch) {
|
733
|
+
link_data *r = NULL;
|
734
|
+
GString *temp_str = NULL;
|
735
|
+
char *temp;
|
736
|
+
|
737
|
+
r = mk_link_data(n->link_data->label, n->link_data->source, n->link_data->title, n->link_data->attr);
|
738
|
+
|
739
|
+
/* Do we have proper info? */
|
740
|
+
if ((r->label == NULL) &&
|
741
|
+
(r->source == NULL)) {
|
742
|
+
/* we seem to be a [foo][] style link */
|
743
|
+
/* so load a label */
|
744
|
+
temp_str = g_string_new("");
|
745
|
+
print_raw_node_tree(temp_str, n->children);
|
746
|
+
r->label = temp_str->str;
|
747
|
+
g_string_free(temp_str, FALSE);
|
748
|
+
}
|
749
|
+
/* Load data by reference */
|
750
|
+
if (r->label != NULL) {
|
751
|
+
temp = strdup(r->label);
|
752
|
+
|
753
|
+
r->attr = NULL;
|
754
|
+
free_link_data(r);
|
755
|
+
|
756
|
+
r = extract_link_data(temp, scratch);
|
757
|
+
if (r == NULL) {
|
758
|
+
/* return NULL since no definition found */
|
759
|
+
|
760
|
+
free(temp);
|
761
|
+
return NULL;
|
762
|
+
}
|
763
|
+
free(temp);
|
764
|
+
}
|
765
|
+
|
766
|
+
return r;
|
767
|
+
}
|