rmultimarkdown 4.7.1.1 → 6.2.2.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 +4 -4
- data/LICENSE +2 -2
- data/README.md +7 -9
- data/Rakefile +33 -18
- data/ext/Makefile +261 -0
- data/ext/extconf.rb +23 -3
- data/ext/mmd/aho-corasick.c +596 -0
- data/ext/mmd/aho-corasick.h +120 -0
- data/ext/mmd/beamer.c +344 -0
- data/ext/mmd/beamer.h +72 -0
- data/ext/mmd/char.c +156 -0
- data/ext/mmd/char.h +111 -0
- data/ext/mmd/char_lookup.c +212 -0
- data/ext/mmd/critic_markup.c +330 -0
- data/ext/mmd/critic_markup.h +94 -0
- data/ext/mmd/d_string.c +402 -0
- data/ext/mmd/epub.c +563 -0
- data/ext/mmd/epub.h +69 -0
- data/ext/mmd/fodt.c +2288 -0
- data/ext/mmd/fodt.h +81 -0
- data/ext/mmd/html.c +2460 -0
- data/ext/mmd/html.h +81 -0
- data/ext/mmd/i18n.h +170 -0
- data/ext/mmd/include/d_string.h +182 -0
- data/ext/mmd/include/libMultiMarkdown.h +548 -0
- data/ext/mmd/include/token.h +233 -0
- data/ext/mmd/latex.c +2435 -0
- data/ext/mmd/latex.h +83 -0
- data/ext/mmd/lexer.c +3001 -0
- data/ext/mmd/lexer.h +75 -0
- data/ext/mmd/memoir.c +138 -0
- data/ext/mmd/memoir.h +67 -0
- data/ext/mmd/miniz.c +7557 -0
- data/ext/mmd/miniz.h +1328 -0
- data/ext/mmd/mmd.c +2798 -0
- data/ext/mmd/mmd.h +120 -0
- data/ext/mmd/object_pool.c +141 -0
- data/ext/mmd/object_pool.h +101 -0
- data/ext/mmd/opendocument-content.c +2071 -0
- data/ext/mmd/opendocument-content.h +135 -0
- data/ext/mmd/opendocument.c +981 -0
- data/ext/mmd/opendocument.h +118 -0
- data/ext/mmd/parser.c +1760 -0
- data/ext/mmd/parser.h +39 -0
- data/{MultiMarkdown-4 → ext/mmd}/rng.c +90 -49
- data/ext/mmd/scanners.c +77512 -0
- data/ext/mmd/scanners.h +101 -0
- data/ext/mmd/stack.c +142 -0
- data/ext/mmd/stack.h +113 -0
- data/ext/mmd/textbundle.c +455 -0
- data/ext/mmd/textbundle.h +115 -0
- data/ext/mmd/token.c +773 -0
- data/ext/mmd/token_pairs.c +263 -0
- data/ext/mmd/token_pairs.h +123 -0
- data/ext/mmd/transclude.c +549 -0
- data/ext/mmd/transclude.h +87 -0
- data/ext/mmd/uthash.h +1074 -0
- data/ext/mmd/uuid.c +154 -0
- data/ext/mmd/uuid.h +77 -0
- data/ext/mmd/version.h +111 -0
- data/ext/mmd/writer.c +2652 -0
- data/ext/mmd/writer.h +260 -0
- data/ext/mmd/zip.c +210 -0
- data/ext/mmd/zip.h +120 -0
- data/ext/{multi_markdown.c → ruby_multi_markdown.c} +87 -18
- data/lib/multi_markdown.bundle +0 -0
- data/lib/multi_markdown.rb +5 -8
- data/lib/multi_markdown/version.rb +1 -1
- data/rmultimarkdown.gemspec +2 -2
- data/test/{extensions_test.rb.rb → extensions_test.rb} +10 -54
- data/test/multi_markdown_test.rb +13 -0
- metadata +67 -47
- data/MultiMarkdown-4/GLibFacade.c +0 -310
- data/MultiMarkdown-4/GLibFacade.h +0 -100
- data/MultiMarkdown-4/beamer.c +0 -182
- data/MultiMarkdown-4/beamer.h +0 -11
- data/MultiMarkdown-4/critic.c +0 -111
- data/MultiMarkdown-4/critic.h +0 -15
- data/MultiMarkdown-4/glib.h +0 -11
- data/MultiMarkdown-4/html.c +0 -1117
- data/MultiMarkdown-4/html.h +0 -14
- data/MultiMarkdown-4/latex.c +0 -1217
- data/MultiMarkdown-4/latex.h +0 -16
- data/MultiMarkdown-4/libMultiMarkdown.h +0 -177
- data/MultiMarkdown-4/lyx.c +0 -2265
- data/MultiMarkdown-4/lyx.h +0 -37
- data/MultiMarkdown-4/lyxbeamer.c +0 -265
- data/MultiMarkdown-4/lyxbeamer.h +0 -11
- data/MultiMarkdown-4/memoir.c +0 -80
- data/MultiMarkdown-4/memoir.h +0 -10
- data/MultiMarkdown-4/multimarkdown.c +0 -518
- data/MultiMarkdown-4/odf.c +0 -1222
- data/MultiMarkdown-4/odf.h +0 -18
- data/MultiMarkdown-4/opml.c +0 -189
- data/MultiMarkdown-4/opml.h +0 -15
- data/MultiMarkdown-4/parse_utilities.c +0 -884
- data/MultiMarkdown-4/parser.c +0 -16656
- data/MultiMarkdown-4/parser.h +0 -188
- data/MultiMarkdown-4/rtf.c +0 -665
- data/MultiMarkdown-4/rtf.h +0 -17
- data/MultiMarkdown-4/strtok.c +0 -56
- data/MultiMarkdown-4/strtok.h +0 -9
- data/MultiMarkdown-4/text.c +0 -53
- data/MultiMarkdown-4/text.h +0 -11
- data/MultiMarkdown-4/toc.c +0 -142
- data/MultiMarkdown-4/toc.h +0 -15
- data/MultiMarkdown-4/transclude.c +0 -307
- data/MultiMarkdown-4/transclude.h +0 -28
- data/MultiMarkdown-4/writer.c +0 -731
- data/MultiMarkdown-4/writer.h +0 -38
data/ext/mmd/mmd.h
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
|
|
3
|
+
MultiMarkdown 6 -- Lightweight markup processor to produce HTML, LaTeX, and more.
|
|
4
|
+
|
|
5
|
+
@file mmd.h
|
|
6
|
+
|
|
7
|
+
@brief Create MMD parsing engine
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@author Fletcher T. Penney
|
|
11
|
+
@bug
|
|
12
|
+
|
|
13
|
+
**/
|
|
14
|
+
|
|
15
|
+
/*
|
|
16
|
+
|
|
17
|
+
Copyright © 2016 - 2017 Fletcher T. Penney.
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
The `MultiMarkdown 6` project is released under the MIT License..
|
|
21
|
+
|
|
22
|
+
GLibFacade.c and GLibFacade.h are from the MultiMarkdown v4 project:
|
|
23
|
+
|
|
24
|
+
https://github.com/fletcher/MultiMarkdown-4/
|
|
25
|
+
|
|
26
|
+
MMD 4 is released under both the MIT License and GPL.
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
CuTest is released under the zlib/libpng license. See CuTest.c for the text
|
|
30
|
+
of the license.
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
## The MIT License ##
|
|
34
|
+
|
|
35
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
36
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
37
|
+
in the Software without restriction, including without limitation the rights
|
|
38
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
39
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
40
|
+
furnished to do so, subject to the following conditions:
|
|
41
|
+
|
|
42
|
+
The above copyright notice and this permission notice shall be included in
|
|
43
|
+
all copies or substantial portions of the Software.
|
|
44
|
+
|
|
45
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
46
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
47
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
48
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
49
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
50
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
51
|
+
THE SOFTWARE.
|
|
52
|
+
|
|
53
|
+
*/
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
#ifndef MMD_MULTIMARKDOWN_H
|
|
57
|
+
#define MMD_MULTIMARKDOWN_H
|
|
58
|
+
|
|
59
|
+
#include "d_string.h"
|
|
60
|
+
#include "libMultiMarkdown.h"
|
|
61
|
+
#include "stack.h"
|
|
62
|
+
#include "token.h"
|
|
63
|
+
#include "token_pairs.h"
|
|
64
|
+
#include "uthash.h"
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
#define kMaxParseRecursiveDepth 1000 //!< Maximum recursion depth when parsing -- to prevent stack overflow with "pathologic" input
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
struct mmd_engine {
|
|
71
|
+
DString * dstr;
|
|
72
|
+
token * root;
|
|
73
|
+
unsigned long extensions;
|
|
74
|
+
unsigned short recurse_depth;
|
|
75
|
+
|
|
76
|
+
bool allow_meta;
|
|
77
|
+
|
|
78
|
+
token_pair_engine * pairings1;
|
|
79
|
+
token_pair_engine * pairings2;
|
|
80
|
+
token_pair_engine * pairings3;
|
|
81
|
+
token_pair_engine * pairings4;
|
|
82
|
+
|
|
83
|
+
stack * abbreviation_stack;
|
|
84
|
+
stack * citation_stack;
|
|
85
|
+
stack * definition_stack;
|
|
86
|
+
stack * footnote_stack;
|
|
87
|
+
stack * glossary_stack;
|
|
88
|
+
stack * header_stack;
|
|
89
|
+
stack * link_stack;
|
|
90
|
+
stack * metadata_stack;
|
|
91
|
+
stack * table_stack;
|
|
92
|
+
|
|
93
|
+
short language;
|
|
94
|
+
short quotes_lang;
|
|
95
|
+
|
|
96
|
+
struct asset * asset_hash;
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
/// Expose routines to lemon parser
|
|
101
|
+
void recursive_parse_indent(mmd_engine * e, token * block);
|
|
102
|
+
void recursive_parse_list_item(mmd_engine * e, token * block);
|
|
103
|
+
void recursive_parse_blockquote(mmd_engine * e, token * block);
|
|
104
|
+
void strip_line_tokens_from_block(mmd_engine * e, token * block);
|
|
105
|
+
void is_para_html(mmd_engine * e, token * block);
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
void is_list_loose(token * list);
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
struct asset {
|
|
112
|
+
char * url;
|
|
113
|
+
char * asset_path;
|
|
114
|
+
UT_hash_handle hh;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
typedef struct asset asset;
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
#endif
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
|
|
3
|
+
MultiMarkdown 6 -- Lightweight markup processor to produce HTML, LaTeX, and more.
|
|
4
|
+
|
|
5
|
+
@file object_pool.c
|
|
6
|
+
|
|
7
|
+
@brief Allocate memory for "objects" in large slabs, rather than one at a time. Improves
|
|
8
|
+
performance when generating large numbers of small chunks of memory, as the expense of
|
|
9
|
+
allocating memory in larger units. Could cause difficulty in extreme low memory situations.
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@author Fletcher T. Penney
|
|
13
|
+
@bug
|
|
14
|
+
|
|
15
|
+
**/
|
|
16
|
+
|
|
17
|
+
/*
|
|
18
|
+
|
|
19
|
+
Copyright © 2016 - 2017 Fletcher T. Penney.
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
The `MultiMarkdown 6` project is released under the MIT License..
|
|
23
|
+
|
|
24
|
+
GLibFacade.c and GLibFacade.h are from the MultiMarkdown v4 project:
|
|
25
|
+
|
|
26
|
+
https://github.com/fletcher/MultiMarkdown-4/
|
|
27
|
+
|
|
28
|
+
MMD 4 is released under both the MIT License and GPL.
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
CuTest is released under the zlib/libpng license. See CuTest.c for the text
|
|
32
|
+
of the license.
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
## The MIT License ##
|
|
36
|
+
|
|
37
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
38
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
39
|
+
in the Software without restriction, including without limitation the rights
|
|
40
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
41
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
42
|
+
furnished to do so, subject to the following conditions:
|
|
43
|
+
|
|
44
|
+
The above copyright notice and this permission notice shall be included in
|
|
45
|
+
all copies or substantial portions of the Software.
|
|
46
|
+
|
|
47
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
48
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
49
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
50
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
51
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
52
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
53
|
+
THE SOFTWARE.
|
|
54
|
+
|
|
55
|
+
*/
|
|
56
|
+
|
|
57
|
+
#include <stdlib.h>
|
|
58
|
+
|
|
59
|
+
#include "object_pool.h"
|
|
60
|
+
|
|
61
|
+
#define kNumberOfObjects 1024
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
void pool_add_slab(pool * p) {
|
|
65
|
+
void * slab = malloc(p->object_size * kNumberOfObjects);
|
|
66
|
+
|
|
67
|
+
if (slab) {
|
|
68
|
+
stack_push(p->allocated, slab);
|
|
69
|
+
|
|
70
|
+
// Next object will come from beginning of this slab
|
|
71
|
+
p->next = slab;
|
|
72
|
+
|
|
73
|
+
// Set warning to trigger need for next slab
|
|
74
|
+
p->last = slab + (p->object_size * (kNumberOfObjects));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
/// Allocate a new object pool
|
|
80
|
+
pool * pool_new(short size) {
|
|
81
|
+
pool * p = malloc(sizeof(pool));
|
|
82
|
+
|
|
83
|
+
if (p) {
|
|
84
|
+
p->object_size = size;
|
|
85
|
+
|
|
86
|
+
p->allocated = stack_new(1024);
|
|
87
|
+
|
|
88
|
+
pool_add_slab(p);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return p;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
/// Free object pool
|
|
96
|
+
void pool_free(pool * p) {
|
|
97
|
+
if (p) {
|
|
98
|
+
pool_drain(p);
|
|
99
|
+
|
|
100
|
+
stack_free(p->allocated);
|
|
101
|
+
|
|
102
|
+
free(p);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
/// Drain pool -- free slabs previously allocated
|
|
108
|
+
void pool_drain(pool * p) {
|
|
109
|
+
if (p == NULL) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
void * slab;
|
|
114
|
+
|
|
115
|
+
while (p->allocated->size > 0) {
|
|
116
|
+
slab = stack_pop(p->allocated);
|
|
117
|
+
free(slab);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
p->next = NULL;
|
|
121
|
+
p->last = NULL;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
/// Request memory for a new object from the pool
|
|
126
|
+
void * pool_allocate_object(pool * p) {
|
|
127
|
+
void * a = NULL;
|
|
128
|
+
|
|
129
|
+
if (p->next == p->last) {
|
|
130
|
+
pool_add_slab(p);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (p->next < p->last) {
|
|
134
|
+
a = p->next;
|
|
135
|
+
|
|
136
|
+
p->next += (p->object_size);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return a;
|
|
140
|
+
}
|
|
141
|
+
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
|
|
3
|
+
MultiMarkdown 6 -- Lightweight markup processor to produce HTML, LaTeX, and more.
|
|
4
|
+
|
|
5
|
+
@file object_pool.h
|
|
6
|
+
|
|
7
|
+
@brief Allocate memory for "objects" in large slabs, rather than one at a time. Improves
|
|
8
|
+
performance when generating large numbers of small chunks of memory, as the expense of
|
|
9
|
+
allocating memory in larger units. Could cause difficulty in extreme low memory situations.
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@author Fletcher T. Penney
|
|
13
|
+
@bug
|
|
14
|
+
|
|
15
|
+
**/
|
|
16
|
+
|
|
17
|
+
/*
|
|
18
|
+
|
|
19
|
+
Copyright © 2016 - 2017 Fletcher T. Penney.
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
The `MultiMarkdown 6` project is released under the MIT License..
|
|
23
|
+
|
|
24
|
+
GLibFacade.c and GLibFacade.h are from the MultiMarkdown v4 project:
|
|
25
|
+
|
|
26
|
+
https://github.com/fletcher/MultiMarkdown-4/
|
|
27
|
+
|
|
28
|
+
MMD 4 is released under both the MIT License and GPL.
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
CuTest is released under the zlib/libpng license. See CuTest.c for the text
|
|
32
|
+
of the license.
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
## The MIT License ##
|
|
36
|
+
|
|
37
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
38
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
39
|
+
in the Software without restriction, including without limitation the rights
|
|
40
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
41
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
42
|
+
furnished to do so, subject to the following conditions:
|
|
43
|
+
|
|
44
|
+
The above copyright notice and this permission notice shall be included in
|
|
45
|
+
all copies or substantial portions of the Software.
|
|
46
|
+
|
|
47
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
48
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
49
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
50
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
51
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
52
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
53
|
+
THE SOFTWARE.
|
|
54
|
+
|
|
55
|
+
*/
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
#ifndef OBJECT_POOL_MULTIMARKDOWN_H
|
|
59
|
+
#define OBJECT_POOL_MULTIMARKDOWN_H
|
|
60
|
+
|
|
61
|
+
#include "stack.h"
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
/// Structure for an object allocator pool
|
|
65
|
+
struct pool {
|
|
66
|
+
stack * allocated; //!< Stack of pointers to slabs that have been allocated
|
|
67
|
+
void * next; //!< Pointer to next available memory for allocation
|
|
68
|
+
void * last; //!< Pointer to end of available memory
|
|
69
|
+
short object_size; //!< Size of individual objects to be allocated
|
|
70
|
+
|
|
71
|
+
char _PADDING[6]; //!< pad struct for alignment
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
typedef struct pool pool;
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
/// Allocate a new object pool
|
|
78
|
+
pool * pool_new(
|
|
79
|
+
short size //!< How big are the objects to be allocated
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
/// Free object pool
|
|
84
|
+
void pool_free(
|
|
85
|
+
pool * p //!< Pool to be freed
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
/// Drain pool -- free slabs previously allocated
|
|
90
|
+
void pool_drain(
|
|
91
|
+
pool * p //!< Pool to be drained
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
/// Request memory for a new object from the pool
|
|
96
|
+
void * pool_allocate_object(
|
|
97
|
+
pool * p //!< Pool to be used for allocation
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
#endif
|
|
@@ -0,0 +1,2071 @@
|
|
|
1
|
+
/**
|
|
2
|
+
|
|
3
|
+
MultiMarkdown -- Lightweight markup processor to produce HTML, LaTeX, and more.
|
|
4
|
+
|
|
5
|
+
@file opendocument-content.c
|
|
6
|
+
|
|
7
|
+
@brief Create the body content for OpenDocument files
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@author Fletcher T. Penney
|
|
11
|
+
@bug
|
|
12
|
+
|
|
13
|
+
**/
|
|
14
|
+
|
|
15
|
+
/*
|
|
16
|
+
|
|
17
|
+
Copyright © 2016 - 2017 Fletcher T. Penney.
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
The `MultiMarkdown 6` project is released under the MIT License..
|
|
21
|
+
|
|
22
|
+
GLibFacade.c and GLibFacade.h are from the MultiMarkdown v4 project:
|
|
23
|
+
|
|
24
|
+
https://github.com/fletcher/MultiMarkdown-4/
|
|
25
|
+
|
|
26
|
+
MMD 4 is released under both the MIT License and GPL.
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
CuTest is released under the zlib/libpng license. See CuTest.c for the
|
|
30
|
+
text of the license.
|
|
31
|
+
|
|
32
|
+
uthash library:
|
|
33
|
+
Copyright (c) 2005-2016, Troy D. Hanson
|
|
34
|
+
|
|
35
|
+
Licensed under Revised BSD license
|
|
36
|
+
|
|
37
|
+
miniz library:
|
|
38
|
+
Copyright 2013-2014 RAD Game Tools and Valve Software
|
|
39
|
+
Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
|
|
40
|
+
|
|
41
|
+
Licensed under the MIT license
|
|
42
|
+
|
|
43
|
+
argtable3 library:
|
|
44
|
+
Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann
|
|
45
|
+
<sheitmann@users.sourceforge.net>
|
|
46
|
+
All rights reserved.
|
|
47
|
+
|
|
48
|
+
Licensed under the Revised BSD License
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
## The MIT License ##
|
|
52
|
+
|
|
53
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
54
|
+
a copy of this software and associated documentation files (the
|
|
55
|
+
"Software"), to deal in the Software without restriction, including
|
|
56
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
57
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
58
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
59
|
+
the following conditions:
|
|
60
|
+
|
|
61
|
+
The above copyright notice and this permission notice shall be
|
|
62
|
+
included in all copies or substantial portions of the Software.
|
|
63
|
+
|
|
64
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
65
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
66
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
67
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
68
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
69
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
70
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
## Revised BSD License ##
|
|
74
|
+
|
|
75
|
+
Redistribution and use in source and binary forms, with or without
|
|
76
|
+
modification, are permitted provided that the following conditions are
|
|
77
|
+
met:
|
|
78
|
+
* Redistributions of source code must retain the above copyright
|
|
79
|
+
notice, this list of conditions and the following disclaimer.
|
|
80
|
+
* Redistributions in binary form must reproduce the above
|
|
81
|
+
copyright notice, this list of conditions and the following
|
|
82
|
+
disclaimer in the documentation and/or other materials provided
|
|
83
|
+
with the distribution.
|
|
84
|
+
* Neither the name of the <organization> nor the
|
|
85
|
+
names of its contributors may be used to endorse or promote
|
|
86
|
+
products derived from this software without specific prior
|
|
87
|
+
written permission.
|
|
88
|
+
|
|
89
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
90
|
+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
91
|
+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
92
|
+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT
|
|
93
|
+
HOLDER> BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
94
|
+
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
95
|
+
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES LOSS OF USE, DATA, OR
|
|
96
|
+
PROFITS OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
97
|
+
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
98
|
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
99
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
*/
|
|
103
|
+
|
|
104
|
+
#include <ctype.h>
|
|
105
|
+
#include <stdio.h>
|
|
106
|
+
#include <stdlib.h>
|
|
107
|
+
#include <string.h>
|
|
108
|
+
|
|
109
|
+
#include "char.h"
|
|
110
|
+
#include "opendocument-content.h"
|
|
111
|
+
#include "parser.h"
|
|
112
|
+
#include "scanners.h"
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
#define print(x) d_string_append(out, x)
|
|
116
|
+
#define print_const(x) d_string_append_c_array(out, x, sizeof(x) - 1)
|
|
117
|
+
#define print_char(x) d_string_append_c(out, x)
|
|
118
|
+
#define printf(...) d_string_append_printf(out, __VA_ARGS__)
|
|
119
|
+
#define print_token(t) d_string_append_c_array(out, &(source[t->start]), t->len)
|
|
120
|
+
#define print_localized(x) mmd_print_localized_char_opendocument(out, x, scratch)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
/// strdup() not available on all platforms
|
|
124
|
+
static char * my_strdup(const char * source) {
|
|
125
|
+
if (source == NULL) {
|
|
126
|
+
return NULL;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
char * result = malloc(strlen(source) + 1);
|
|
130
|
+
|
|
131
|
+
if (result) {
|
|
132
|
+
strcpy(result, source);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return result;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
void mmd_print_char_opendocument(DString * out, char c) {
|
|
140
|
+
switch (c) {
|
|
141
|
+
case '"':
|
|
142
|
+
print_const(""");
|
|
143
|
+
break;
|
|
144
|
+
|
|
145
|
+
case '&':
|
|
146
|
+
print_const("&");
|
|
147
|
+
break;
|
|
148
|
+
|
|
149
|
+
case '<':
|
|
150
|
+
print_const("<");
|
|
151
|
+
break;
|
|
152
|
+
|
|
153
|
+
case '>':
|
|
154
|
+
print_const(">");
|
|
155
|
+
break;
|
|
156
|
+
|
|
157
|
+
case '\t':
|
|
158
|
+
print_const("<text:tab/>");
|
|
159
|
+
|
|
160
|
+
default:
|
|
161
|
+
print_char(c);
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
void mmd_print_string_opendocument(DString * out, const char * str) {
|
|
168
|
+
if (str == NULL) {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
while (*str != '\0') {
|
|
173
|
+
mmd_print_char_opendocument(out, *str);
|
|
174
|
+
str++;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
void mmd_print_localized_char_opendocument(DString * out, unsigned short type, scratch_pad * scratch) {
|
|
180
|
+
switch (type) {
|
|
181
|
+
case DASH_N:
|
|
182
|
+
print_const("–");
|
|
183
|
+
break;
|
|
184
|
+
|
|
185
|
+
case DASH_M:
|
|
186
|
+
print_const("—");
|
|
187
|
+
break;
|
|
188
|
+
|
|
189
|
+
case ELLIPSIS:
|
|
190
|
+
print_const("…");
|
|
191
|
+
break;
|
|
192
|
+
|
|
193
|
+
case APOSTROPHE:
|
|
194
|
+
print_const("’");
|
|
195
|
+
break;
|
|
196
|
+
|
|
197
|
+
case QUOTE_LEFT_SINGLE:
|
|
198
|
+
switch (scratch->quotes_lang) {
|
|
199
|
+
case SWEDISH:
|
|
200
|
+
print( "’");
|
|
201
|
+
break;
|
|
202
|
+
|
|
203
|
+
case FRENCH:
|
|
204
|
+
print_const("'");
|
|
205
|
+
break;
|
|
206
|
+
|
|
207
|
+
case GERMAN:
|
|
208
|
+
print_const("‚");
|
|
209
|
+
break;
|
|
210
|
+
|
|
211
|
+
case GERMANGUILL:
|
|
212
|
+
print_const("›");
|
|
213
|
+
break;
|
|
214
|
+
|
|
215
|
+
default:
|
|
216
|
+
print_const("‘");
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
break;
|
|
220
|
+
|
|
221
|
+
case QUOTE_RIGHT_SINGLE:
|
|
222
|
+
switch (scratch->quotes_lang) {
|
|
223
|
+
case GERMAN:
|
|
224
|
+
print_const("‘");
|
|
225
|
+
break;
|
|
226
|
+
|
|
227
|
+
case GERMANGUILL:
|
|
228
|
+
print_const("‹");
|
|
229
|
+
break;
|
|
230
|
+
|
|
231
|
+
default:
|
|
232
|
+
print_const("’");
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
break;
|
|
236
|
+
|
|
237
|
+
case QUOTE_LEFT_DOUBLE:
|
|
238
|
+
switch (scratch->quotes_lang) {
|
|
239
|
+
case DUTCH:
|
|
240
|
+
case GERMAN:
|
|
241
|
+
print_const("„");
|
|
242
|
+
break;
|
|
243
|
+
|
|
244
|
+
case GERMANGUILL:
|
|
245
|
+
print_const("»");
|
|
246
|
+
break;
|
|
247
|
+
|
|
248
|
+
case FRENCH:
|
|
249
|
+
print_const("«");
|
|
250
|
+
break;
|
|
251
|
+
|
|
252
|
+
case SWEDISH:
|
|
253
|
+
print( "”");
|
|
254
|
+
break;
|
|
255
|
+
|
|
256
|
+
default:
|
|
257
|
+
print_const("“");
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
break;
|
|
261
|
+
|
|
262
|
+
case QUOTE_RIGHT_DOUBLE:
|
|
263
|
+
switch (scratch->quotes_lang) {
|
|
264
|
+
case GERMAN:
|
|
265
|
+
print_const("“");
|
|
266
|
+
break;
|
|
267
|
+
|
|
268
|
+
case GERMANGUILL:
|
|
269
|
+
print_const("«");
|
|
270
|
+
break;
|
|
271
|
+
|
|
272
|
+
case FRENCH:
|
|
273
|
+
print_const("»");
|
|
274
|
+
break;
|
|
275
|
+
|
|
276
|
+
case SWEDISH:
|
|
277
|
+
case DUTCH:
|
|
278
|
+
default:
|
|
279
|
+
print_const("”");
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
break;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
void mmd_export_token_opendocument_raw(DString * out, const char * source, token * t, scratch_pad * scratch) {
|
|
288
|
+
if (t == NULL) {
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
switch (t->type) {
|
|
293
|
+
case AMPERSAND:
|
|
294
|
+
print_const("&");
|
|
295
|
+
break;
|
|
296
|
+
|
|
297
|
+
case AMPERSAND_LONG:
|
|
298
|
+
print_const("&amp;");
|
|
299
|
+
break;
|
|
300
|
+
|
|
301
|
+
case ANGLE_RIGHT:
|
|
302
|
+
print_const(">");
|
|
303
|
+
break;
|
|
304
|
+
|
|
305
|
+
case ANGLE_LEFT:
|
|
306
|
+
print_const("<");
|
|
307
|
+
break;
|
|
308
|
+
|
|
309
|
+
case ESCAPED_CHARACTER:
|
|
310
|
+
print_const("\\");
|
|
311
|
+
mmd_print_char_opendocument(out, source[t->start + 1]);
|
|
312
|
+
break;
|
|
313
|
+
|
|
314
|
+
case HTML_ENTITY:
|
|
315
|
+
print_const("&");
|
|
316
|
+
d_string_append_c_array(out, &(source[t->start + 1]), t->len - 1);
|
|
317
|
+
break;
|
|
318
|
+
|
|
319
|
+
case INDENT_TAB:
|
|
320
|
+
print_const("<text:tab/>");
|
|
321
|
+
break;
|
|
322
|
+
|
|
323
|
+
case QUOTE_DOUBLE:
|
|
324
|
+
print_const(""");
|
|
325
|
+
break;
|
|
326
|
+
|
|
327
|
+
case MATH_BRACKET_OPEN:
|
|
328
|
+
case MATH_BRACKET_CLOSE:
|
|
329
|
+
case MATH_PAREN_OPEN:
|
|
330
|
+
case MATH_PAREN_CLOSE:
|
|
331
|
+
print_token(t);
|
|
332
|
+
break;
|
|
333
|
+
|
|
334
|
+
case SUBSCRIPT:
|
|
335
|
+
if (t->child) {
|
|
336
|
+
print_const("~");
|
|
337
|
+
mmd_export_token_tree_opendocument_raw(out, source, t->child, scratch);
|
|
338
|
+
} else {
|
|
339
|
+
print_token(t);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
break;
|
|
343
|
+
|
|
344
|
+
case SUPERSCRIPT:
|
|
345
|
+
if (t->child) {
|
|
346
|
+
print_const("^");
|
|
347
|
+
mmd_export_token_tree_opendocument_raw(out, source, t->child, scratch);
|
|
348
|
+
} else {
|
|
349
|
+
print_token(t);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
break;
|
|
353
|
+
|
|
354
|
+
case CODE_FENCE:
|
|
355
|
+
if (t->next) {
|
|
356
|
+
t->next->type = TEXT_EMPTY;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
case TEXT_EMPTY:
|
|
360
|
+
break;
|
|
361
|
+
|
|
362
|
+
case TEXT_NL:
|
|
363
|
+
print_const("<text:line-break/>");
|
|
364
|
+
break;
|
|
365
|
+
|
|
366
|
+
default:
|
|
367
|
+
if (t->child) {
|
|
368
|
+
mmd_export_token_tree_opendocument_raw(out, source, t->child, scratch);
|
|
369
|
+
} else {
|
|
370
|
+
print_token(t);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
break;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
void mmd_export_token_tree_opendocument_raw(DString * out, const char * source, token * t, scratch_pad * scratch) {
|
|
379
|
+
while (t != NULL) {
|
|
380
|
+
if (scratch->skip_token) {
|
|
381
|
+
scratch->skip_token--;
|
|
382
|
+
} else {
|
|
383
|
+
mmd_export_token_opendocument_raw(out, source, t, scratch);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
t = t->next;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
void mmd_export_token_tree_opendocument_math(DString * out, const char * source, token * t, scratch_pad * scratch) {
|
|
392
|
+
while (t != NULL) {
|
|
393
|
+
if (scratch->skip_token) {
|
|
394
|
+
scratch->skip_token--;
|
|
395
|
+
} else {
|
|
396
|
+
mmd_export_token_opendocument_math(out, source, t, scratch);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
t = t->next;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
|
|
404
|
+
void mmd_export_token_opendocument_math(DString * out, const char * source, token * t, scratch_pad * scratch) {
|
|
405
|
+
if (t == NULL) {
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
switch (t->type) {
|
|
410
|
+
case MATH_BRACKET_OPEN:
|
|
411
|
+
print_const("\\[");
|
|
412
|
+
break;
|
|
413
|
+
|
|
414
|
+
case MATH_BRACKET_CLOSE:
|
|
415
|
+
print_const("\\]");
|
|
416
|
+
break;
|
|
417
|
+
|
|
418
|
+
case MATH_PAREN_OPEN:
|
|
419
|
+
print_const("\\(");
|
|
420
|
+
break;
|
|
421
|
+
|
|
422
|
+
case MATH_PAREN_CLOSE:
|
|
423
|
+
print_const("\\)");
|
|
424
|
+
break;
|
|
425
|
+
|
|
426
|
+
default:
|
|
427
|
+
mmd_export_token_opendocument_raw(out, source, t, scratch);
|
|
428
|
+
break;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
void mmd_export_link_opendocument(DString * out, const char * source, token * text, link * link, scratch_pad * scratch) {
|
|
433
|
+
if (link->url) {
|
|
434
|
+
print_const("<text:a xlink:type=\"simple\" xlink:href=\"");
|
|
435
|
+
mmd_print_string_opendocument(out, link->url);
|
|
436
|
+
print_const("\"");
|
|
437
|
+
} else {
|
|
438
|
+
print_const("<a xlink:type=\"simple\" xlink:href=\"\"");
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
if (link->title && link->title[0] != '\0') {
|
|
442
|
+
print_const(" office:name=\"");
|
|
443
|
+
mmd_print_string_opendocument(out, link->title);
|
|
444
|
+
print_const("\"");
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
print_const(">");
|
|
448
|
+
|
|
449
|
+
// If we're printing contents of bracket as text, then ensure we include it all
|
|
450
|
+
if (text && text->child && text->child->len > 1) {
|
|
451
|
+
text->child->next->start--;
|
|
452
|
+
text->child->next->len++;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
if (text) {
|
|
456
|
+
mmd_export_token_tree_opendocument(out, source, text->child, scratch);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
print_const("</text:a>");
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
static char * correct_dimension_units(char *original) {
|
|
464
|
+
char *result;
|
|
465
|
+
int i;
|
|
466
|
+
|
|
467
|
+
result = my_strdup(original);
|
|
468
|
+
|
|
469
|
+
for (i = 0; result[i]; i++) {
|
|
470
|
+
result[i] = tolower(result[i]);
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
if (strstr(&result[strlen(result) - 2], "px")) {
|
|
474
|
+
result[strlen(result) - 2] = '\0';
|
|
475
|
+
strcat(result, "pt");
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
return result;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
|
|
482
|
+
void mmd_export_image_opendocument(DString * out, const char * source, token * text, link * link, scratch_pad * scratch, bool is_figure) {
|
|
483
|
+
attr * a = link->attributes;
|
|
484
|
+
char * height = NULL;
|
|
485
|
+
char * width = NULL;
|
|
486
|
+
|
|
487
|
+
print_const("<draw:frame text:anchor-type=\"as-char\"\ndraw:z-index=\"0\" draw:style-name=\"fr1\"");
|
|
488
|
+
|
|
489
|
+
// Check attributes for dimensions
|
|
490
|
+
while (a) {
|
|
491
|
+
if (strcmp("height", a->key) == 0) {
|
|
492
|
+
height = correct_dimension_units(a->value);
|
|
493
|
+
} else if (strcmp("width", a->key) == 0) {
|
|
494
|
+
width = correct_dimension_units(a->value);
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
a = a->next;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
if (width) {
|
|
501
|
+
printf(" svg:width=\"%s\">\n", width);
|
|
502
|
+
} else {
|
|
503
|
+
print_const(" svg:width=\"95%\">\n");
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
print_const("<draw:text-box><text:p><draw:frame text:anchor-type=\"as-char\" draw:z-index=\"1\" ");
|
|
507
|
+
|
|
508
|
+
if (height && width) {
|
|
509
|
+
printf("svg:height=\"%s\" ", height);
|
|
510
|
+
printf("svg:width=\"%s\" ", width);
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
if (height) {
|
|
514
|
+
free(height);
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
if (width) {
|
|
518
|
+
free(width);
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
if (link->url) {
|
|
522
|
+
if (scratch->store_assets) {
|
|
523
|
+
store_asset(scratch, link->url);
|
|
524
|
+
asset * a = extract_asset(scratch, link->url);
|
|
525
|
+
|
|
526
|
+
printf(">\n<draw:image xlink:href=\"Pictures/%s\"", a->asset_path);
|
|
527
|
+
} else {
|
|
528
|
+
printf(">\n<draw:image xlink:href=\"%s\"", link->url);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
print_const(" xlink:type=\"simple\" xlink:show=\"embed\" xlink:actuate=\"onLoad\" draw:filter-name=\"<All formats>\"/>\n</draw:frame></text:p>");
|
|
533
|
+
|
|
534
|
+
if (is_figure) {
|
|
535
|
+
if (text) {
|
|
536
|
+
print_const("\n<text:p>Figure <text:sequence text:name=\"Figure\" text:formula=\"ooow:Figure+1\" style:num-format=\"1\"> Update Fields to calculate numbers</text:sequence>: ");
|
|
537
|
+
mmd_export_token_tree_opendocument(out, source, text->child, scratch);
|
|
538
|
+
print_const("</text:p>");
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
print_const("\n</draw:text-box></draw:frame>\n");
|
|
543
|
+
|
|
544
|
+
scratch->padded = 1;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
|
|
548
|
+
void mmd_export_toc_entry_opendocument(DString * out, const char * source, scratch_pad * scratch, size_t * counter, short level) {
|
|
549
|
+
token * entry, * next;
|
|
550
|
+
short entry_level, next_level;
|
|
551
|
+
char * temp_char;
|
|
552
|
+
|
|
553
|
+
// Iterate over tokens
|
|
554
|
+
while (*counter < scratch->header_stack->size) {
|
|
555
|
+
// Get token for header
|
|
556
|
+
entry = stack_peek_index(scratch->header_stack, *counter);
|
|
557
|
+
entry_level = raw_level_for_header(entry);
|
|
558
|
+
|
|
559
|
+
if (entry_level >= level) {
|
|
560
|
+
// This entry is a direct descendant of the parent
|
|
561
|
+
temp_char = label_from_header(source, entry);
|
|
562
|
+
printf("<text:p text:style-name=\"TOC_Item\"><text:a xlink:type=\"simple\" xlink:href=\"#%s\" text:style-name=\"Index_20_Link\" text:visited-style-name=\"Index_20_Link\">", temp_char);
|
|
563
|
+
mmd_export_token_tree_opendocument(out, source, entry->child, scratch);
|
|
564
|
+
print_const(" <text:tab/>1</text:a></text:p>\n");
|
|
565
|
+
|
|
566
|
+
if (*counter < scratch->header_stack->size - 1) {
|
|
567
|
+
next = stack_peek_index(scratch->header_stack, *counter + 1);
|
|
568
|
+
next_level = next->type - BLOCK_H1 + 1;
|
|
569
|
+
|
|
570
|
+
if (next_level > entry_level) {
|
|
571
|
+
// This entry has children
|
|
572
|
+
(*counter)++;
|
|
573
|
+
mmd_export_toc_entry_opendocument(out, source, scratch, counter, entry_level + 1);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
free(temp_char);
|
|
578
|
+
} else if (entry_level < level ) {
|
|
579
|
+
// If entry < level, exit this level
|
|
580
|
+
// Decrement counter first, so that we can test it again later
|
|
581
|
+
(*counter)--;
|
|
582
|
+
break;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
// Increment counter
|
|
586
|
+
(*counter)++;
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
|
|
591
|
+
void mmd_export_toc_opendocument(DString * out, const char * source, scratch_pad * scratch) {
|
|
592
|
+
size_t counter = 0;
|
|
593
|
+
|
|
594
|
+
// TODO: Could use LC to internationalize this
|
|
595
|
+
print_const("<text:table-of-content text:style-name=\"Sect1\" text:protected=\"true\" text:name=\"Table of Contents1\">\n");
|
|
596
|
+
print_const("<text:table-of-content-source text:outline-level=\"10\">\n");
|
|
597
|
+
print_const("<text:index-title-template text:style-name=\"Contents_20_Heading\">Table of Contents</text:index-title-template>\n");
|
|
598
|
+
print_const("</text:table-of-content-source>\n<text:index-body>\n");
|
|
599
|
+
print_const("<text:index-title text:style-name=\"Sect1\" text:name=\"Table of Contents1_Head\">\n");
|
|
600
|
+
print_const("<text:p text:style-name=\"Contents_20_Heading\">Table of Contents</text:p>\n");
|
|
601
|
+
print_const("</text:index-title>\n");
|
|
602
|
+
|
|
603
|
+
mmd_export_toc_entry_opendocument(out, source, scratch, &counter, 0);
|
|
604
|
+
|
|
605
|
+
print_const("</text:index-body>\n</text:table-of-content>\n\n");
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
|
|
609
|
+
|
|
610
|
+
void mmd_export_token_opendocument(DString * out, const char * source, token * t, scratch_pad * scratch) {
|
|
611
|
+
if (t == NULL) {
|
|
612
|
+
return;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
short temp_short;
|
|
616
|
+
short temp_short2;
|
|
617
|
+
short temp_short3;
|
|
618
|
+
link * temp_link = NULL;
|
|
619
|
+
char * temp_char = NULL;
|
|
620
|
+
char * temp_char2 = NULL;
|
|
621
|
+
bool temp_bool = 0;
|
|
622
|
+
token * temp_token = NULL;
|
|
623
|
+
footnote * temp_note = NULL;
|
|
624
|
+
|
|
625
|
+
switch (t->type) {
|
|
626
|
+
case DOC_START_TOKEN:
|
|
627
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
628
|
+
break;
|
|
629
|
+
|
|
630
|
+
case AMPERSAND:
|
|
631
|
+
case AMPERSAND_LONG:
|
|
632
|
+
print_const("&");
|
|
633
|
+
break;
|
|
634
|
+
|
|
635
|
+
case ANGLE_LEFT:
|
|
636
|
+
print_const("<");
|
|
637
|
+
break;
|
|
638
|
+
|
|
639
|
+
case ANGLE_RIGHT:
|
|
640
|
+
print_const(">");
|
|
641
|
+
break;
|
|
642
|
+
|
|
643
|
+
case APOSTROPHE:
|
|
644
|
+
if (!(scratch->extensions & EXT_SMART)) {
|
|
645
|
+
print_token(t);
|
|
646
|
+
} else {
|
|
647
|
+
print_localized(APOSTROPHE);
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
break;
|
|
651
|
+
|
|
652
|
+
case BACKTICK:
|
|
653
|
+
if (t->mate == NULL) {
|
|
654
|
+
print_token(t);
|
|
655
|
+
} else if (t->mate->type == QUOTE_RIGHT_ALT)
|
|
656
|
+
if (!(scratch->extensions & EXT_SMART)) {
|
|
657
|
+
print_token(t);
|
|
658
|
+
} else {
|
|
659
|
+
print_localized(QUOTE_LEFT_DOUBLE);
|
|
660
|
+
} else if (t->start < t->mate->start) {
|
|
661
|
+
print_const("<text:span text:style-name=\"Source_20_Text\">");
|
|
662
|
+
} else {
|
|
663
|
+
print_const("</text:span>");
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
break;
|
|
667
|
+
|
|
668
|
+
case BLOCK_BLOCKQUOTE:
|
|
669
|
+
pad(out, 2, scratch);
|
|
670
|
+
scratch->padded = 2;
|
|
671
|
+
temp_short2 = scratch->odf_para_type;
|
|
672
|
+
|
|
673
|
+
scratch->odf_para_type = BLOCK_BLOCKQUOTE;
|
|
674
|
+
|
|
675
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
676
|
+
scratch->padded = 0;
|
|
677
|
+
scratch->odf_para_type = temp_short2;
|
|
678
|
+
break;
|
|
679
|
+
|
|
680
|
+
case BLOCK_CODE_FENCED:
|
|
681
|
+
pad(out, 2, scratch);
|
|
682
|
+
|
|
683
|
+
temp_char = get_fence_language_specifier(t->child->child, source);
|
|
684
|
+
|
|
685
|
+
if (temp_char) {
|
|
686
|
+
if (strncmp("{=", temp_char, 2) == 0) {
|
|
687
|
+
// Raw source
|
|
688
|
+
if (raw_filter_text_matches(temp_char, FORMAT_ODT)) {
|
|
689
|
+
switch (t->child->tail->type) {
|
|
690
|
+
case LINE_FENCE_BACKTICK_3:
|
|
691
|
+
case LINE_FENCE_BACKTICK_4:
|
|
692
|
+
case LINE_FENCE_BACKTICK_5:
|
|
693
|
+
temp_token = t->child->tail;
|
|
694
|
+
break;
|
|
695
|
+
|
|
696
|
+
default:
|
|
697
|
+
temp_token = NULL;
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
if (temp_token) {
|
|
701
|
+
d_string_append_c_array(out, &source[t->child->next->start], temp_token->start - t->child->next->start);
|
|
702
|
+
scratch->padded = 1;
|
|
703
|
+
} else {
|
|
704
|
+
d_string_append_c_array(out, &source[t->child->start + t->child->len], t->start + t->len - t->child->next->start);
|
|
705
|
+
scratch->padded = 0;
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
free(temp_char);
|
|
710
|
+
break;
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
free(temp_char);
|
|
715
|
+
|
|
716
|
+
print_const("<text:p text:style-name=\"Preformatted Text\">");
|
|
717
|
+
mmd_export_token_tree_opendocument_raw(out, source, t->child->next, scratch);
|
|
718
|
+
print_const("</text:p>");
|
|
719
|
+
scratch->padded = 0;
|
|
720
|
+
break;
|
|
721
|
+
|
|
722
|
+
case BLOCK_CODE_INDENTED:
|
|
723
|
+
pad(out, 2, scratch);
|
|
724
|
+
print_const("<text:p text:style-name=\"Preformatted Text\">");
|
|
725
|
+
mmd_export_token_tree_opendocument_raw(out, source, t->child, scratch);
|
|
726
|
+
print_const("</text:p>");
|
|
727
|
+
scratch->padded = 0;
|
|
728
|
+
break;
|
|
729
|
+
|
|
730
|
+
case BLOCK_DEFINITION:
|
|
731
|
+
pad(out, 2, scratch);
|
|
732
|
+
temp_short2 = scratch->odf_para_type;
|
|
733
|
+
scratch->odf_para_type = BLOCK_DEFINITION;
|
|
734
|
+
|
|
735
|
+
temp_short = scratch->list_is_tight;
|
|
736
|
+
|
|
737
|
+
if (!(t->child->next && (t->child->next->type == BLOCK_EMPTY) && t->child->next->next)) {
|
|
738
|
+
scratch->list_is_tight = true;
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
if (t->child && t->child->type != BLOCK_PARA) {
|
|
742
|
+
print_const("<text:p text:style-name=\"Quotations\">");
|
|
743
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
744
|
+
print_const("</text:p>");
|
|
745
|
+
} else {
|
|
746
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
scratch->padded = 0;
|
|
750
|
+
|
|
751
|
+
scratch->list_is_tight = temp_short;
|
|
752
|
+
scratch->odf_para_type = temp_short2;
|
|
753
|
+
break;
|
|
754
|
+
|
|
755
|
+
case BLOCK_DEFLIST:
|
|
756
|
+
pad(out, 2, scratch);
|
|
757
|
+
|
|
758
|
+
// Group consecutive definition lists into a single list.
|
|
759
|
+
// lemon's LALR(1) parser can't properly handle this (to my understanding).
|
|
760
|
+
|
|
761
|
+
// if (!(t->prev && (t->prev->type == BLOCK_DEFLIST)))
|
|
762
|
+
// print_const("<dl>\n");
|
|
763
|
+
|
|
764
|
+
scratch->padded = 2;
|
|
765
|
+
|
|
766
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
767
|
+
pad(out, 1, scratch);
|
|
768
|
+
|
|
769
|
+
// if (!(t->next && (t->next->type == BLOCK_DEFLIST)))
|
|
770
|
+
// print_const("</dl>\n");
|
|
771
|
+
|
|
772
|
+
scratch->padded = 1;
|
|
773
|
+
break;
|
|
774
|
+
|
|
775
|
+
case BLOCK_EMPTY:
|
|
776
|
+
break;
|
|
777
|
+
|
|
778
|
+
case BLOCK_H1:
|
|
779
|
+
case BLOCK_H2:
|
|
780
|
+
case BLOCK_H3:
|
|
781
|
+
case BLOCK_H4:
|
|
782
|
+
case BLOCK_H5:
|
|
783
|
+
case BLOCK_H6:
|
|
784
|
+
case BLOCK_SETEXT_1:
|
|
785
|
+
case BLOCK_SETEXT_2:
|
|
786
|
+
pad(out, 2, scratch);
|
|
787
|
+
|
|
788
|
+
switch (t->type) {
|
|
789
|
+
case BLOCK_SETEXT_1:
|
|
790
|
+
temp_short = 1;
|
|
791
|
+
break;
|
|
792
|
+
|
|
793
|
+
case BLOCK_SETEXT_2:
|
|
794
|
+
temp_short = 2;
|
|
795
|
+
break;
|
|
796
|
+
|
|
797
|
+
default:
|
|
798
|
+
temp_short = t->type - BLOCK_H1 + 1;
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
printf("<text:h text:outline-level=\"%d\">", temp_short + scratch->base_header_level - 1);
|
|
802
|
+
|
|
803
|
+
if (scratch->extensions & EXT_NO_LABELS) {
|
|
804
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
805
|
+
} else {
|
|
806
|
+
temp_char = label_from_header(source, t);
|
|
807
|
+
printf("<text:bookmark text:name=\"%s\"/>", temp_char);
|
|
808
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
809
|
+
//printf("<text:bookmark-end text:name=\"%s\"/>", temp_char);
|
|
810
|
+
free(temp_char);
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
print_const("</text:h>");
|
|
814
|
+
scratch->padded = 0;
|
|
815
|
+
break;
|
|
816
|
+
|
|
817
|
+
case BLOCK_HR:
|
|
818
|
+
pad(out, 2, scratch);
|
|
819
|
+
print_const("<text:p text:style-name=\"Horizontal_20_Line\"/>");
|
|
820
|
+
scratch->padded = 0;
|
|
821
|
+
break;
|
|
822
|
+
|
|
823
|
+
case BLOCK_HTML:
|
|
824
|
+
// Don't print HTML
|
|
825
|
+
break;
|
|
826
|
+
|
|
827
|
+
case BLOCK_LIST_BULLETED_LOOSE:
|
|
828
|
+
case BLOCK_LIST_BULLETED:
|
|
829
|
+
temp_short = scratch->list_is_tight;
|
|
830
|
+
|
|
831
|
+
switch (t->type) {
|
|
832
|
+
case BLOCK_LIST_BULLETED_LOOSE:
|
|
833
|
+
scratch->list_is_tight = false;
|
|
834
|
+
break;
|
|
835
|
+
|
|
836
|
+
case BLOCK_LIST_BULLETED:
|
|
837
|
+
scratch->list_is_tight = true;
|
|
838
|
+
break;
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
pad(out, 2, scratch);
|
|
842
|
+
print_const("<text:list text:style-name=\"L1\">");
|
|
843
|
+
scratch->padded = 1;
|
|
844
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
845
|
+
pad(out, 2, scratch);
|
|
846
|
+
print_const("</text:list>");
|
|
847
|
+
scratch->padded = 0;
|
|
848
|
+
scratch->list_is_tight = temp_short;
|
|
849
|
+
break;
|
|
850
|
+
|
|
851
|
+
case BLOCK_LIST_ENUMERATED_LOOSE:
|
|
852
|
+
case BLOCK_LIST_ENUMERATED:
|
|
853
|
+
temp_short = scratch->list_is_tight;
|
|
854
|
+
|
|
855
|
+
switch (t->type) {
|
|
856
|
+
case BLOCK_LIST_ENUMERATED_LOOSE:
|
|
857
|
+
scratch->list_is_tight = false;
|
|
858
|
+
break;
|
|
859
|
+
|
|
860
|
+
case BLOCK_LIST_ENUMERATED:
|
|
861
|
+
scratch->list_is_tight = true;
|
|
862
|
+
break;
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
pad(out, 2, scratch);
|
|
866
|
+
print_const("<text:list text:style-name=\"L2\">");
|
|
867
|
+
scratch->padded = 1;
|
|
868
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
869
|
+
pad(out, 2, scratch);
|
|
870
|
+
print_const("</text:list>");
|
|
871
|
+
scratch->padded = 0;
|
|
872
|
+
scratch->list_is_tight = temp_short;
|
|
873
|
+
break;
|
|
874
|
+
|
|
875
|
+
case BLOCK_LIST_ITEM:
|
|
876
|
+
pad(out, 2, scratch);
|
|
877
|
+
print_const("<text:list-item>\n");
|
|
878
|
+
scratch->padded = 2;
|
|
879
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
880
|
+
print_const("</text:list-item>");
|
|
881
|
+
scratch->padded = 0;
|
|
882
|
+
break;
|
|
883
|
+
|
|
884
|
+
case BLOCK_LIST_ITEM_TIGHT:
|
|
885
|
+
pad(out, 2, scratch);
|
|
886
|
+
print_const("<text:list-item>\n");
|
|
887
|
+
|
|
888
|
+
if (t->child && t->child->type != BLOCK_PARA) {
|
|
889
|
+
print_const("<text:p text:style-name=\"P1\">\n");
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
scratch->padded = 2;
|
|
893
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
894
|
+
|
|
895
|
+
if (t->child && t->child->type != BLOCK_PARA) {
|
|
896
|
+
print_const("</text:p>");
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
print_const("</text:list-item>");
|
|
900
|
+
scratch->padded = 0;
|
|
901
|
+
break;
|
|
902
|
+
|
|
903
|
+
case BLOCK_META:
|
|
904
|
+
break;
|
|
905
|
+
|
|
906
|
+
case BLOCK_PARA:
|
|
907
|
+
pad(out, 2, scratch);
|
|
908
|
+
print_const("<text:p");
|
|
909
|
+
|
|
910
|
+
switch (scratch->odf_para_type) {
|
|
911
|
+
case BLOCK_BLOCKQUOTE:
|
|
912
|
+
case BLOCK_DEFINITION:
|
|
913
|
+
print_const(" text:style-name=\"Quotations\">");
|
|
914
|
+
break;
|
|
915
|
+
|
|
916
|
+
case PAIR_BRACKET_ABBREVIATION:
|
|
917
|
+
case PAIR_BRACKET_CITATION:
|
|
918
|
+
case PAIR_BRACKET_FOOTNOTE:
|
|
919
|
+
case PAIR_BRACKET_GLOSSARY:
|
|
920
|
+
print_const(" text:style-name=\"Footnote\">");
|
|
921
|
+
break;
|
|
922
|
+
|
|
923
|
+
default:
|
|
924
|
+
print_const(" text:style-name=\"Standard\">");
|
|
925
|
+
break;
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
929
|
+
|
|
930
|
+
print_const("</text:p>");
|
|
931
|
+
scratch->padded = 0;
|
|
932
|
+
break;
|
|
933
|
+
|
|
934
|
+
case BLOCK_TABLE:
|
|
935
|
+
pad(out, 2, scratch);
|
|
936
|
+
print_const("<table:table>\n");
|
|
937
|
+
|
|
938
|
+
scratch->padded = 2;
|
|
939
|
+
read_table_column_alignments(source, t, scratch);
|
|
940
|
+
|
|
941
|
+
for (int i = 0; i < scratch->table_column_count; ++i) {
|
|
942
|
+
print_const("<table:table-column/>\n");
|
|
943
|
+
// switch (scratch->table_alignment[i]) {
|
|
944
|
+
// case 'l':
|
|
945
|
+
// print_const("<col style=\"text-align:left;\"/>\n");
|
|
946
|
+
// break;
|
|
947
|
+
// case 'L':
|
|
948
|
+
// print_const("<col style=\"text-align:left;\" class=\"extended\"/>\n");
|
|
949
|
+
// break;
|
|
950
|
+
// case 'r':
|
|
951
|
+
// print_const("<col style=\"text-align:right;\"/>\n");
|
|
952
|
+
// break;
|
|
953
|
+
// case 'R':
|
|
954
|
+
// print_const("<col style=\"text-align:right;\" class=\"extended\"/>\n");
|
|
955
|
+
// break;
|
|
956
|
+
// case 'c':
|
|
957
|
+
// print_const("<col style=\"text-align:center;\"/>\n");
|
|
958
|
+
// break;
|
|
959
|
+
// case 'C':
|
|
960
|
+
// print_const("<col style=\"text-align:center;\" class=\"extended\"/>\n");
|
|
961
|
+
// break;
|
|
962
|
+
// default:
|
|
963
|
+
// print_const("<col />\n");
|
|
964
|
+
// break;
|
|
965
|
+
// }
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
scratch->padded = 1;
|
|
969
|
+
|
|
970
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
971
|
+
pad(out, 1, scratch);
|
|
972
|
+
print_const("</table:table>\n");
|
|
973
|
+
|
|
974
|
+
// Are we followed by a caption?
|
|
975
|
+
if (table_has_caption(t)) {
|
|
976
|
+
temp_token = t->next->child;
|
|
977
|
+
|
|
978
|
+
if (temp_token->next &&
|
|
979
|
+
temp_token->next->type == PAIR_BRACKET) {
|
|
980
|
+
temp_token = temp_token->next;
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
temp_char = label_from_token(source, temp_token);
|
|
984
|
+
printf("<text:p><text:bookmark text:name=\"%s\"/>Table <text:sequence text:name=\"Table\" text:formula=\"ooow:Table+1\" style:num-format=\"1\"> Update Fields to calculate numbers</text:sequence>:", temp_char);
|
|
985
|
+
|
|
986
|
+
t->next->child->child->type = TEXT_EMPTY;
|
|
987
|
+
t->next->child->child->mate->type = TEXT_EMPTY;
|
|
988
|
+
mmd_export_token_tree_opendocument(out, source, t->next->child->child, scratch);
|
|
989
|
+
|
|
990
|
+
printf("<text:bookmark-end text:name=\"%s\"/></text:p>\n", temp_char);
|
|
991
|
+
|
|
992
|
+
free(temp_char);
|
|
993
|
+
temp_short = 1;
|
|
994
|
+
} else {
|
|
995
|
+
temp_short = 0;
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
scratch->padded = 0;
|
|
999
|
+
scratch->skip_token = temp_short;
|
|
1000
|
+
|
|
1001
|
+
break;
|
|
1002
|
+
|
|
1003
|
+
case BLOCK_TABLE_HEADER:
|
|
1004
|
+
pad(out, 2, scratch);
|
|
1005
|
+
scratch->in_table_header = 1;
|
|
1006
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
1007
|
+
scratch->in_table_header = 0;
|
|
1008
|
+
scratch->padded = 1;
|
|
1009
|
+
break;
|
|
1010
|
+
|
|
1011
|
+
case BLOCK_TABLE_SECTION:
|
|
1012
|
+
pad(out, 2, scratch);
|
|
1013
|
+
scratch->padded = 2;
|
|
1014
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
1015
|
+
scratch->padded = 0;
|
|
1016
|
+
break;
|
|
1017
|
+
|
|
1018
|
+
case BLOCK_TOC:
|
|
1019
|
+
pad(out, 2, scratch);
|
|
1020
|
+
|
|
1021
|
+
mmd_export_toc_opendocument(out, source, scratch);
|
|
1022
|
+
|
|
1023
|
+
scratch->padded = 1;
|
|
1024
|
+
break;
|
|
1025
|
+
|
|
1026
|
+
case BLOCK_TERM:
|
|
1027
|
+
pad(out, 2, scratch);
|
|
1028
|
+
print_const("<text:p><text:span text:style-name=\"MMD-Bold\">");
|
|
1029
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
1030
|
+
print_const("</text:span></text:p>\n");
|
|
1031
|
+
scratch->padded = 2;
|
|
1032
|
+
break;
|
|
1033
|
+
|
|
1034
|
+
case BRACE_DOUBLE_LEFT:
|
|
1035
|
+
print_const("{{");
|
|
1036
|
+
break;
|
|
1037
|
+
|
|
1038
|
+
case BRACE_DOUBLE_RIGHT:
|
|
1039
|
+
print_const("}}");
|
|
1040
|
+
break;
|
|
1041
|
+
|
|
1042
|
+
case BRACKET_ABBREVIATION_LEFT:
|
|
1043
|
+
print_const("[>");
|
|
1044
|
+
break;
|
|
1045
|
+
|
|
1046
|
+
case BRACKET_CITATION_LEFT:
|
|
1047
|
+
print_const("[#");
|
|
1048
|
+
break;
|
|
1049
|
+
|
|
1050
|
+
case BRACKET_LEFT:
|
|
1051
|
+
print_const("[");
|
|
1052
|
+
break;
|
|
1053
|
+
|
|
1054
|
+
case BRACKET_RIGHT:
|
|
1055
|
+
print_const("]");
|
|
1056
|
+
break;
|
|
1057
|
+
|
|
1058
|
+
case BRACKET_VARIABLE_LEFT:
|
|
1059
|
+
print_const("[\%");
|
|
1060
|
+
break;
|
|
1061
|
+
|
|
1062
|
+
case COLON:
|
|
1063
|
+
print_char(':');
|
|
1064
|
+
break;
|
|
1065
|
+
|
|
1066
|
+
case CRITIC_ADD_OPEN:
|
|
1067
|
+
print_const("{++");
|
|
1068
|
+
break;
|
|
1069
|
+
|
|
1070
|
+
case CRITIC_ADD_CLOSE:
|
|
1071
|
+
print_const("++}");
|
|
1072
|
+
break;
|
|
1073
|
+
|
|
1074
|
+
case CRITIC_COM_OPEN:
|
|
1075
|
+
print_const("{>>");
|
|
1076
|
+
break;
|
|
1077
|
+
|
|
1078
|
+
case CRITIC_COM_CLOSE:
|
|
1079
|
+
print_const("<<}");
|
|
1080
|
+
break;
|
|
1081
|
+
|
|
1082
|
+
case CRITIC_DEL_OPEN:
|
|
1083
|
+
print_const("{--");
|
|
1084
|
+
break;
|
|
1085
|
+
|
|
1086
|
+
case CRITIC_DEL_CLOSE:
|
|
1087
|
+
print_const("--}");
|
|
1088
|
+
break;
|
|
1089
|
+
|
|
1090
|
+
case CRITIC_HI_OPEN:
|
|
1091
|
+
print_const("{==");
|
|
1092
|
+
break;
|
|
1093
|
+
|
|
1094
|
+
case CRITIC_HI_CLOSE:
|
|
1095
|
+
print_const("==}");
|
|
1096
|
+
break;
|
|
1097
|
+
|
|
1098
|
+
case CRITIC_SUB_OPEN:
|
|
1099
|
+
print_const("{~~");
|
|
1100
|
+
break;
|
|
1101
|
+
|
|
1102
|
+
case CRITIC_SUB_DIV:
|
|
1103
|
+
print_const("~>");
|
|
1104
|
+
break;
|
|
1105
|
+
|
|
1106
|
+
case CRITIC_SUB_CLOSE:
|
|
1107
|
+
print_const("~~}");
|
|
1108
|
+
break;
|
|
1109
|
+
|
|
1110
|
+
case DASH_M:
|
|
1111
|
+
if (!(scratch->extensions & EXT_SMART)) {
|
|
1112
|
+
print_token(t);
|
|
1113
|
+
} else {
|
|
1114
|
+
print_localized(DASH_M);
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1117
|
+
break;
|
|
1118
|
+
|
|
1119
|
+
case DASH_N:
|
|
1120
|
+
if (!(scratch->extensions & EXT_SMART)) {
|
|
1121
|
+
print_token(t);
|
|
1122
|
+
} else {
|
|
1123
|
+
print_localized(DASH_N);
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
break;
|
|
1127
|
+
|
|
1128
|
+
case ELLIPSIS:
|
|
1129
|
+
if (!(scratch->extensions & EXT_SMART)) {
|
|
1130
|
+
print_token(t);
|
|
1131
|
+
} else {
|
|
1132
|
+
print_localized(ELLIPSIS);
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
break;
|
|
1136
|
+
|
|
1137
|
+
case EMPH_START:
|
|
1138
|
+
print_const("<text:span text:style-name=\"MMD-Italic\">");
|
|
1139
|
+
break;
|
|
1140
|
+
|
|
1141
|
+
case EMPH_STOP:
|
|
1142
|
+
print_const("</text:span>");
|
|
1143
|
+
break;
|
|
1144
|
+
|
|
1145
|
+
case EQUAL:
|
|
1146
|
+
print_char('=');
|
|
1147
|
+
break;
|
|
1148
|
+
|
|
1149
|
+
case ESCAPED_CHARACTER:
|
|
1150
|
+
if (!(scratch->extensions & EXT_COMPATIBILITY) &&
|
|
1151
|
+
(source[t->start + 1] == ' ')) {
|
|
1152
|
+
print_const(" "); // This is a non-breaking space character
|
|
1153
|
+
} else {
|
|
1154
|
+
mmd_print_char_opendocument(out, source[t->start + 1]);
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
break;
|
|
1158
|
+
|
|
1159
|
+
case HASH1:
|
|
1160
|
+
case HASH2:
|
|
1161
|
+
case HASH3:
|
|
1162
|
+
case HASH4:
|
|
1163
|
+
case HASH5:
|
|
1164
|
+
case HASH6:
|
|
1165
|
+
print_token(t);
|
|
1166
|
+
break;
|
|
1167
|
+
|
|
1168
|
+
case HTML_ENTITY:
|
|
1169
|
+
print_const("&");
|
|
1170
|
+
d_string_append_c_array(out, &(source[t->start + 1]), t->len - 1);
|
|
1171
|
+
break;
|
|
1172
|
+
|
|
1173
|
+
case HTML_COMMENT_START:
|
|
1174
|
+
if (!(scratch->extensions & EXT_SMART)) {
|
|
1175
|
+
print_const("<!--");
|
|
1176
|
+
} else {
|
|
1177
|
+
print_const("<!");
|
|
1178
|
+
print_localized(DASH_N);
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
break;
|
|
1182
|
+
|
|
1183
|
+
case HTML_COMMENT_STOP:
|
|
1184
|
+
if (!(scratch->extensions & EXT_SMART)) {
|
|
1185
|
+
print_const("-->");
|
|
1186
|
+
} else {
|
|
1187
|
+
print_localized(DASH_N);
|
|
1188
|
+
print_const(">");
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
break;
|
|
1192
|
+
|
|
1193
|
+
case INDENT_SPACE:
|
|
1194
|
+
print_char(' ');
|
|
1195
|
+
break;
|
|
1196
|
+
|
|
1197
|
+
case INDENT_TAB:
|
|
1198
|
+
print_const("<text:tab/>");
|
|
1199
|
+
break;
|
|
1200
|
+
|
|
1201
|
+
case LINE_LIST_BULLETED:
|
|
1202
|
+
case LINE_LIST_ENUMERATED:
|
|
1203
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
1204
|
+
break;
|
|
1205
|
+
|
|
1206
|
+
case LINE_SETEXT_2:
|
|
1207
|
+
case MANUAL_LABEL:
|
|
1208
|
+
case MARKER_BLOCKQUOTE:
|
|
1209
|
+
case MARKER_H1:
|
|
1210
|
+
case MARKER_H2:
|
|
1211
|
+
case MARKER_H3:
|
|
1212
|
+
case MARKER_H4:
|
|
1213
|
+
case MARKER_H5:
|
|
1214
|
+
case MARKER_H6:
|
|
1215
|
+
case MARKER_LIST_BULLET:
|
|
1216
|
+
case MARKER_LIST_ENUMERATOR:
|
|
1217
|
+
break;
|
|
1218
|
+
|
|
1219
|
+
case MATH_BRACKET_OPEN:
|
|
1220
|
+
if (t->mate) {
|
|
1221
|
+
print_const("<text:span text:style-name=\"math\">\\[");
|
|
1222
|
+
} else {
|
|
1223
|
+
print_const("\\[");
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1226
|
+
break;
|
|
1227
|
+
|
|
1228
|
+
case MATH_BRACKET_CLOSE:
|
|
1229
|
+
if (t->mate) {
|
|
1230
|
+
print_const("\\]</text:span>");
|
|
1231
|
+
} else {
|
|
1232
|
+
print_const("\\]");
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1235
|
+
break;
|
|
1236
|
+
|
|
1237
|
+
case MATH_DOLLAR_SINGLE:
|
|
1238
|
+
if (t->mate) {
|
|
1239
|
+
(t->start < t->mate->start) ? ( print_const("<text:span text:style-name=\"math\">\\(") ) : ( print_const("\\)</text:span>") );
|
|
1240
|
+
} else {
|
|
1241
|
+
print_const("$");
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
break;
|
|
1245
|
+
|
|
1246
|
+
case MATH_DOLLAR_DOUBLE:
|
|
1247
|
+
if (t->mate) {
|
|
1248
|
+
(t->start < t->mate->start) ? ( print_const("<text:span text:style-name=\"math\">\\[") ) : ( print_const("\\]</text:span>") );
|
|
1249
|
+
} else {
|
|
1250
|
+
print_const("$$");
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
break;
|
|
1254
|
+
|
|
1255
|
+
case MATH_PAREN_OPEN:
|
|
1256
|
+
if (t->mate) {
|
|
1257
|
+
print_const("<text:span text:style-name=\"math\">\\(");
|
|
1258
|
+
} else {
|
|
1259
|
+
print_const("\\(");
|
|
1260
|
+
}
|
|
1261
|
+
|
|
1262
|
+
break;
|
|
1263
|
+
|
|
1264
|
+
case MATH_PAREN_CLOSE:
|
|
1265
|
+
if (t->mate) {
|
|
1266
|
+
print_const("\\)</text:span>");
|
|
1267
|
+
} else {
|
|
1268
|
+
print_const("\\)");
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1271
|
+
break;
|
|
1272
|
+
|
|
1273
|
+
case NON_INDENT_SPACE:
|
|
1274
|
+
print_char(' ');
|
|
1275
|
+
break;
|
|
1276
|
+
|
|
1277
|
+
case PAIR_ANGLE:
|
|
1278
|
+
temp_char = url_accept(source, t->start + 1, t->len - 2, NULL, true);
|
|
1279
|
+
|
|
1280
|
+
if (temp_char) {
|
|
1281
|
+
print_const("<text:a xlink:type=\"simple\" xlink:href=\"");
|
|
1282
|
+
|
|
1283
|
+
if (scan_email(temp_char)) {
|
|
1284
|
+
temp_bool = true;
|
|
1285
|
+
|
|
1286
|
+
if (strncmp("mailto:", temp_char, 7) != 0) {
|
|
1287
|
+
print_const("mailto:");
|
|
1288
|
+
}
|
|
1289
|
+
} else {
|
|
1290
|
+
temp_bool = false;
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1293
|
+
mmd_print_string_opendocument(out, temp_char);
|
|
1294
|
+
print_const("\">");
|
|
1295
|
+
mmd_print_string_opendocument(out, temp_char);
|
|
1296
|
+
print_const("</text:a>");
|
|
1297
|
+
} else if (scan_html(&source[t->start])) {
|
|
1298
|
+
// We ignore HTML blocks
|
|
1299
|
+
if (scan_html_comment(&source[t->start])) {
|
|
1300
|
+
// But allow HTML comments as raw LaTeX
|
|
1301
|
+
d_string_append_c_array(out, &source[t->start + 4], t->len - 4 - 3);
|
|
1302
|
+
}
|
|
1303
|
+
} else {
|
|
1304
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1307
|
+
free(temp_char);
|
|
1308
|
+
break;
|
|
1309
|
+
|
|
1310
|
+
case PAIR_BACKTICK:
|
|
1311
|
+
|
|
1312
|
+
// Strip leading whitespace
|
|
1313
|
+
switch (t->child->next->type) {
|
|
1314
|
+
case TEXT_NL:
|
|
1315
|
+
case INDENT_TAB:
|
|
1316
|
+
case INDENT_SPACE:
|
|
1317
|
+
case NON_INDENT_SPACE:
|
|
1318
|
+
t->child->next->type = TEXT_EMPTY;
|
|
1319
|
+
break;
|
|
1320
|
+
|
|
1321
|
+
case TEXT_PLAIN:
|
|
1322
|
+
while (t->child->next->len && char_is_whitespace(source[t->child->next->start])) {
|
|
1323
|
+
t->child->next->start++;
|
|
1324
|
+
t->child->next->len--;
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1327
|
+
break;
|
|
1328
|
+
}
|
|
1329
|
+
|
|
1330
|
+
// Strip trailing whitespace
|
|
1331
|
+
switch (t->child->mate->prev->type) {
|
|
1332
|
+
case TEXT_NL:
|
|
1333
|
+
case INDENT_TAB:
|
|
1334
|
+
case INDENT_SPACE:
|
|
1335
|
+
case NON_INDENT_SPACE:
|
|
1336
|
+
t->child->mate->prev->type = TEXT_EMPTY;
|
|
1337
|
+
break;
|
|
1338
|
+
|
|
1339
|
+
case TEXT_PLAIN:
|
|
1340
|
+
while (t->child->mate->prev->len && char_is_whitespace(source[t->child->mate->prev->start + t->child->mate->prev->len - 1])) {
|
|
1341
|
+
t->child->mate->prev->len--;
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
break;
|
|
1345
|
+
}
|
|
1346
|
+
|
|
1347
|
+
t->child->type = TEXT_EMPTY;
|
|
1348
|
+
t->child->mate->type = TEXT_EMPTY;
|
|
1349
|
+
|
|
1350
|
+
if (t->next && t->next->type == PAIR_RAW_FILTER) {
|
|
1351
|
+
// Raw text?
|
|
1352
|
+
if (raw_filter_matches(t->next, source, FORMAT_FODT)) {
|
|
1353
|
+
d_string_append_c_array(out, &(source[t->child->start + t->child->len]), t->child->mate->start - t->child->start - t->child->len);
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
// Skip over PAIR_RAW_FILTER
|
|
1357
|
+
scratch->skip_token = 1;
|
|
1358
|
+
break;
|
|
1359
|
+
}
|
|
1360
|
+
|
|
1361
|
+
print_const("<text:span text:style-name=\"Source_20_Text\">");
|
|
1362
|
+
mmd_export_token_tree_opendocument_raw(out, source, t->child, scratch);
|
|
1363
|
+
print_const("</text:span>");
|
|
1364
|
+
break;
|
|
1365
|
+
|
|
1366
|
+
case PAIR_BRACE:
|
|
1367
|
+
case PAIR_BRACES:
|
|
1368
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
1369
|
+
break;
|
|
1370
|
+
|
|
1371
|
+
case PAIR_BRACKET:
|
|
1372
|
+
if ((scratch->extensions & EXT_NOTES) &&
|
|
1373
|
+
(t->next && t->next->type == PAIR_BRACKET_CITATION)) {
|
|
1374
|
+
goto parse_citation;
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
case PAIR_BRACKET_IMAGE:
|
|
1378
|
+
parse_brackets(source, scratch, t, &temp_link, &temp_short, &temp_bool);
|
|
1379
|
+
|
|
1380
|
+
if (temp_link) {
|
|
1381
|
+
if (t->type == PAIR_BRACKET) {
|
|
1382
|
+
// Link
|
|
1383
|
+
mmd_export_link_opendocument(out, source, t, temp_link, scratch);
|
|
1384
|
+
} else {
|
|
1385
|
+
// Image -- should it be a figure (e.g. image is only thing in paragraph)?
|
|
1386
|
+
temp_token = t->next;
|
|
1387
|
+
|
|
1388
|
+
if (temp_token &&
|
|
1389
|
+
((temp_token->type == PAIR_BRACKET) ||
|
|
1390
|
+
(temp_token->type == PAIR_PAREN))) {
|
|
1391
|
+
temp_token = temp_token->next;
|
|
1392
|
+
}
|
|
1393
|
+
|
|
1394
|
+
if (temp_token && temp_token->type == TEXT_NL) {
|
|
1395
|
+
temp_token = temp_token->next;
|
|
1396
|
+
}
|
|
1397
|
+
|
|
1398
|
+
if (temp_token && temp_token->type == TEXT_LINEBREAK) {
|
|
1399
|
+
temp_token = temp_token->next;
|
|
1400
|
+
}
|
|
1401
|
+
|
|
1402
|
+
if (t->prev || temp_token) {
|
|
1403
|
+
mmd_export_image_opendocument(out, source, t, temp_link, scratch, false);
|
|
1404
|
+
} else {
|
|
1405
|
+
mmd_export_image_opendocument(out, source, t, temp_link, scratch, true);
|
|
1406
|
+
}
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1409
|
+
if (temp_bool) {
|
|
1410
|
+
link_free(temp_link);
|
|
1411
|
+
}
|
|
1412
|
+
|
|
1413
|
+
scratch->skip_token = temp_short;
|
|
1414
|
+
|
|
1415
|
+
return;
|
|
1416
|
+
}
|
|
1417
|
+
|
|
1418
|
+
// No links exist, so treat as normal
|
|
1419
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
1420
|
+
break;
|
|
1421
|
+
|
|
1422
|
+
case PAIR_BRACKET_CITATION:
|
|
1423
|
+
parse_citation:
|
|
1424
|
+
temp_bool = true; // Track whether this is regular vs 'not cited'
|
|
1425
|
+
temp_token = t; // Remember whether we need to skip ahead
|
|
1426
|
+
|
|
1427
|
+
if (scratch->extensions & EXT_NOTES) {
|
|
1428
|
+
// Note-based syntax enabled
|
|
1429
|
+
|
|
1430
|
+
if (t->type == PAIR_BRACKET) {
|
|
1431
|
+
// This is a locator for a subsequent citation (e.g. `[foo][#bar]`)
|
|
1432
|
+
temp_char = text_inside_pair(source, t);
|
|
1433
|
+
temp_char2 = label_from_string(temp_char);
|
|
1434
|
+
|
|
1435
|
+
if (strcmp(temp_char2, "notcited") == 0) {
|
|
1436
|
+
free(temp_char);
|
|
1437
|
+
temp_char = my_strdup("");
|
|
1438
|
+
temp_bool = false;
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1441
|
+
free(temp_char2);
|
|
1442
|
+
|
|
1443
|
+
// Move ahead to actual citation
|
|
1444
|
+
t = t->next;
|
|
1445
|
+
} else {
|
|
1446
|
+
// This is the actual citation (e.g. `[#foo]`)
|
|
1447
|
+
// No locator
|
|
1448
|
+
temp_char = my_strdup("");
|
|
1449
|
+
}
|
|
1450
|
+
|
|
1451
|
+
// Classify this use
|
|
1452
|
+
temp_short2 = scratch->used_citations->size;
|
|
1453
|
+
citation_from_bracket(source, scratch, t, &temp_short);
|
|
1454
|
+
|
|
1455
|
+
if (temp_short == -1) {
|
|
1456
|
+
// This instance is not properly formed
|
|
1457
|
+
print_const("[#");
|
|
1458
|
+
mmd_export_token_tree_opendocument(out, source, t->child->next, scratch);
|
|
1459
|
+
print_const("]");
|
|
1460
|
+
|
|
1461
|
+
free(temp_char);
|
|
1462
|
+
break;
|
|
1463
|
+
}
|
|
1464
|
+
|
|
1465
|
+
|
|
1466
|
+
temp_short3 = scratch->odf_para_type;
|
|
1467
|
+
scratch->odf_para_type = PAIR_BRACKET_FOOTNOTE;
|
|
1468
|
+
|
|
1469
|
+
if (temp_bool) {
|
|
1470
|
+
// This is a regular citation
|
|
1471
|
+
|
|
1472
|
+
if (temp_char[0] == '\0') {
|
|
1473
|
+
// No locator
|
|
1474
|
+
|
|
1475
|
+
if (temp_short2 == scratch->used_citations->size) {
|
|
1476
|
+
// This is a re-use of a previously used note
|
|
1477
|
+
print_const("<text:span text:style-name=\"Footnote_20_anchor\"><text:note-ref text:note-class=\"endnote\" text:reference-format=\"text\" ");
|
|
1478
|
+
printf("text:ref-name=\"cite%d\">%d</text:note-ref></text:span>", temp_short, temp_short);
|
|
1479
|
+
} else {
|
|
1480
|
+
// This is the first time this note was used
|
|
1481
|
+
printf("<text:note text:id=\"cite%d\" text:note-class=\"endnote\"><text:note-body>", temp_short);
|
|
1482
|
+
temp_note = stack_peek_index(scratch->used_citations, temp_short - 1);
|
|
1483
|
+
|
|
1484
|
+
mmd_export_token_tree_opendocument(out, source, temp_note->content, scratch);
|
|
1485
|
+
print_const("</text:note-body></text:note>");
|
|
1486
|
+
}
|
|
1487
|
+
} else {
|
|
1488
|
+
// Locator present
|
|
1489
|
+
|
|
1490
|
+
if (temp_short2 == scratch->used_citations->size) {
|
|
1491
|
+
// This is a re-use of a previously used note
|
|
1492
|
+
print_const("<text:span text:style-name=\"Footnote_20_anchor\"><text:note-ref text:note-class=\"endnote\" text:reference-format=\"text\" ");
|
|
1493
|
+
printf("text:ref-name=\"cite%d\">%d</text:note-ref></text:span>", temp_short, temp_short);
|
|
1494
|
+
} else {
|
|
1495
|
+
// This is the first time this note was used
|
|
1496
|
+
printf("<text:note text:id=\"cite%d\" text:note-class=\"endnote\"><text:note-body>", temp_short);
|
|
1497
|
+
temp_note = stack_peek_index(scratch->used_citations, temp_short - 1);
|
|
1498
|
+
|
|
1499
|
+
mmd_export_token_tree_opendocument(out, source, temp_note->content, scratch);
|
|
1500
|
+
print_const("</text:note-body></text:note>");
|
|
1501
|
+
}
|
|
1502
|
+
}
|
|
1503
|
+
} else {
|
|
1504
|
+
if (temp_short2 == scratch->used_citations->size) {
|
|
1505
|
+
// This is a re-use of a previously used note
|
|
1506
|
+
} else {
|
|
1507
|
+
// This is the first time this note was used
|
|
1508
|
+
// TODO: Not sure how to add an endnote without inserting a marker in the text
|
|
1509
|
+
printf("<text:note text:id=\"cite%d\" text:note-class=\"endnote\"><text:note-body>", temp_short);
|
|
1510
|
+
temp_note = stack_peek_index(scratch->used_citations, temp_short - 1);
|
|
1511
|
+
|
|
1512
|
+
mmd_export_token_tree_opendocument(out, source, temp_note->content, scratch);
|
|
1513
|
+
print_const("</text:note-body></text:note>");
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1516
|
+
|
|
1517
|
+
if (temp_token != t) {
|
|
1518
|
+
// Skip citation on next pass
|
|
1519
|
+
scratch->skip_token = 1;
|
|
1520
|
+
}
|
|
1521
|
+
|
|
1522
|
+
scratch->odf_para_type = temp_short3;
|
|
1523
|
+
|
|
1524
|
+
free(temp_char);
|
|
1525
|
+
} else {
|
|
1526
|
+
// Note-based syntax disabled
|
|
1527
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
1528
|
+
}
|
|
1529
|
+
|
|
1530
|
+
break;
|
|
1531
|
+
|
|
1532
|
+
case PAIR_BRACKET_FOOTNOTE:
|
|
1533
|
+
if (scratch->extensions & EXT_NOTES) {
|
|
1534
|
+
// Note-based syntax enabled
|
|
1535
|
+
|
|
1536
|
+
// Classify this use
|
|
1537
|
+
temp_short2 = scratch->used_footnotes->size;
|
|
1538
|
+
footnote_from_bracket(source, scratch, t, &temp_short);
|
|
1539
|
+
|
|
1540
|
+
if (temp_short == -1) {
|
|
1541
|
+
// This instance is not properly formed
|
|
1542
|
+
print_const("[?");
|
|
1543
|
+
mmd_export_token_tree_opendocument(out, source, t->child->next, scratch);
|
|
1544
|
+
print_const("]");
|
|
1545
|
+
break;
|
|
1546
|
+
}
|
|
1547
|
+
|
|
1548
|
+
temp_short3 = scratch->odf_para_type;
|
|
1549
|
+
scratch->odf_para_type = PAIR_BRACKET_FOOTNOTE;
|
|
1550
|
+
|
|
1551
|
+
if (temp_short2 == scratch->used_footnotes->size) {
|
|
1552
|
+
// This is a re-use of a previously used note
|
|
1553
|
+
|
|
1554
|
+
printf("<text:note text:id=\"fn%d\" text:note-class=\"footnote\"><text:note-body>", temp_short);
|
|
1555
|
+
temp_note = stack_peek_index(scratch->used_footnotes, temp_short - 1);
|
|
1556
|
+
|
|
1557
|
+
mmd_export_token_tree_opendocument(out, source, temp_note->content, scratch);
|
|
1558
|
+
print_const("</text:note-body></text:note>");
|
|
1559
|
+
} else {
|
|
1560
|
+
// This is the first time this note was used
|
|
1561
|
+
|
|
1562
|
+
// This is a new footnote
|
|
1563
|
+
printf("<text:note text:id=\"fn%d\" text:note-class=\"footnote\"><text:note-body>", temp_short);
|
|
1564
|
+
temp_note = stack_peek_index(scratch->used_footnotes, temp_short - 1);
|
|
1565
|
+
|
|
1566
|
+
mmd_export_token_tree_opendocument(out, source, temp_note->content, scratch);
|
|
1567
|
+
print_const("</text:note-body></text:note>");
|
|
1568
|
+
}
|
|
1569
|
+
|
|
1570
|
+
scratch->odf_para_type = temp_short3;
|
|
1571
|
+
} else {
|
|
1572
|
+
// Note-based syntax disabled
|
|
1573
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
1574
|
+
}
|
|
1575
|
+
|
|
1576
|
+
break;
|
|
1577
|
+
|
|
1578
|
+
case PAIR_BRACKET_ABBREVIATION:
|
|
1579
|
+
|
|
1580
|
+
// Which might also be an "auto-tagged" abbreviation
|
|
1581
|
+
if (scratch->extensions & EXT_NOTES) {
|
|
1582
|
+
// Note-based syntax enabled
|
|
1583
|
+
|
|
1584
|
+
// Classify this use
|
|
1585
|
+
temp_short2 = scratch->used_abbreviations->size;
|
|
1586
|
+
temp_short3 = scratch->inline_abbreviations_to_free->size;
|
|
1587
|
+
abbreviation_from_bracket(source, scratch, t, &temp_short);
|
|
1588
|
+
|
|
1589
|
+
if (temp_short == -1) {
|
|
1590
|
+
// This instance is not properly formed
|
|
1591
|
+
print_const("[>");
|
|
1592
|
+
mmd_export_token_tree_opendocument(out, source, t->child->next, scratch);
|
|
1593
|
+
print_const("]");
|
|
1594
|
+
break;
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1597
|
+
// Get instance of the note used
|
|
1598
|
+
temp_note = stack_peek_index(scratch->used_abbreviations, temp_short - 1);
|
|
1599
|
+
|
|
1600
|
+
if (t->child) {
|
|
1601
|
+
t->child->type = TEXT_EMPTY;
|
|
1602
|
+
t->child->mate->type = TEXT_EMPTY;
|
|
1603
|
+
}
|
|
1604
|
+
|
|
1605
|
+
if (temp_short2 == scratch->used_abbreviations->size) {
|
|
1606
|
+
// This is a re-use of a previously used note
|
|
1607
|
+
|
|
1608
|
+
if (temp_short3 == scratch->inline_abbreviations_to_free->size) {
|
|
1609
|
+
// This is a reference definition
|
|
1610
|
+
mmd_print_string_opendocument(out, temp_note->label_text);
|
|
1611
|
+
// mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
1612
|
+
} else {
|
|
1613
|
+
// This is an inline definition
|
|
1614
|
+
mmd_print_string_opendocument(out, temp_note->label_text);
|
|
1615
|
+
// mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
1616
|
+
}
|
|
1617
|
+
} else {
|
|
1618
|
+
// This is the first time this note was used
|
|
1619
|
+
temp_short2 = scratch->odf_para_type;
|
|
1620
|
+
scratch->odf_para_type = PAIR_BRACKET_ABBREVIATION;
|
|
1621
|
+
|
|
1622
|
+
if (temp_short3 == scratch->inline_abbreviations_to_free->size) {
|
|
1623
|
+
// This is a reference definition
|
|
1624
|
+
mmd_print_string_opendocument(out, temp_note->clean_text);
|
|
1625
|
+
print_const(" (");
|
|
1626
|
+
mmd_print_string_opendocument(out, temp_note->label_text);
|
|
1627
|
+
print_const(")");
|
|
1628
|
+
} else {
|
|
1629
|
+
// This is an inline definition
|
|
1630
|
+
mmd_print_string_opendocument(out, temp_note->clean_text);
|
|
1631
|
+
print_const(" (");
|
|
1632
|
+
mmd_print_string_opendocument(out, temp_note->label_text);
|
|
1633
|
+
print_const(")");
|
|
1634
|
+
}
|
|
1635
|
+
|
|
1636
|
+
scratch->odf_para_type = temp_short2;
|
|
1637
|
+
}
|
|
1638
|
+
} else {
|
|
1639
|
+
// Note-based syntax disabled
|
|
1640
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
1641
|
+
}
|
|
1642
|
+
|
|
1643
|
+
break;
|
|
1644
|
+
|
|
1645
|
+
case PAIR_BRACKET_GLOSSARY:
|
|
1646
|
+
|
|
1647
|
+
// Which might also be an "auto-tagged" glossary
|
|
1648
|
+
if (scratch->extensions & EXT_NOTES) {
|
|
1649
|
+
// Note-based syntax enabled
|
|
1650
|
+
|
|
1651
|
+
// Classify this use
|
|
1652
|
+
temp_short2 = scratch->used_glossaries->size;
|
|
1653
|
+
glossary_from_bracket(source, scratch, t, &temp_short);
|
|
1654
|
+
|
|
1655
|
+
if (temp_short == -1) {
|
|
1656
|
+
// This instance is not properly formed
|
|
1657
|
+
print_const("[?");
|
|
1658
|
+
mmd_export_token_tree_opendocument(out, source, t->child->next, scratch);
|
|
1659
|
+
print_const("]");
|
|
1660
|
+
break;
|
|
1661
|
+
}
|
|
1662
|
+
|
|
1663
|
+
// Get instance of the note used
|
|
1664
|
+
temp_note = stack_peek_index(scratch->used_glossaries, temp_short - 1);
|
|
1665
|
+
|
|
1666
|
+
temp_short3 = scratch->odf_para_type;
|
|
1667
|
+
scratch->odf_para_type = PAIR_BRACKET_GLOSSARY;
|
|
1668
|
+
|
|
1669
|
+
if (temp_short2 == scratch->used_glossaries->size) {
|
|
1670
|
+
// This is a re-use of a previously used note
|
|
1671
|
+
|
|
1672
|
+
mmd_print_string_opendocument(out, temp_note->clean_text);
|
|
1673
|
+
} else {
|
|
1674
|
+
// This is the first time this note was used
|
|
1675
|
+
|
|
1676
|
+
mmd_print_string_opendocument(out, temp_note->clean_text);
|
|
1677
|
+
|
|
1678
|
+
printf("<text:note text:id=\"gn%d\" text:note-class=\"glossary\"><text:note-body>", temp_short);
|
|
1679
|
+
mmd_export_token_tree_opendocument(out, source, temp_note->content, scratch);
|
|
1680
|
+
print_const("</text:note-body></text:note>");
|
|
1681
|
+
}
|
|
1682
|
+
|
|
1683
|
+
scratch->odf_para_type = temp_short3;
|
|
1684
|
+
} else {
|
|
1685
|
+
// Note-based syntax disabled
|
|
1686
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
1687
|
+
}
|
|
1688
|
+
|
|
1689
|
+
break;
|
|
1690
|
+
|
|
1691
|
+
case PAIR_BRACKET_VARIABLE:
|
|
1692
|
+
temp_char = text_inside_pair(source, t);
|
|
1693
|
+
temp_char2 = extract_metadata(scratch, temp_char);
|
|
1694
|
+
|
|
1695
|
+
if (temp_char2) {
|
|
1696
|
+
mmd_print_string_opendocument(out, temp_char2);
|
|
1697
|
+
} else {
|
|
1698
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
1699
|
+
}
|
|
1700
|
+
|
|
1701
|
+
// Don't free temp_char2 (it belongs to meta *)
|
|
1702
|
+
free(temp_char);
|
|
1703
|
+
break;
|
|
1704
|
+
|
|
1705
|
+
case PAIR_CRITIC_ADD:
|
|
1706
|
+
|
|
1707
|
+
// Ignore if we're rejecting
|
|
1708
|
+
if (scratch->extensions & EXT_CRITIC_REJECT) {
|
|
1709
|
+
break;
|
|
1710
|
+
}
|
|
1711
|
+
|
|
1712
|
+
if (scratch->extensions & EXT_CRITIC) {
|
|
1713
|
+
t->child->type = TEXT_EMPTY;
|
|
1714
|
+
t->child->mate->type = TEXT_EMPTY;
|
|
1715
|
+
|
|
1716
|
+
if (scratch->extensions & EXT_CRITIC_ACCEPT) {
|
|
1717
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
1718
|
+
} else {
|
|
1719
|
+
print_const("<text:span text:style-name=\"Underline\">");
|
|
1720
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
1721
|
+
print_const("</text:span>");
|
|
1722
|
+
}
|
|
1723
|
+
} else {
|
|
1724
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
1725
|
+
}
|
|
1726
|
+
|
|
1727
|
+
break;
|
|
1728
|
+
|
|
1729
|
+
case PAIR_CRITIC_DEL:
|
|
1730
|
+
|
|
1731
|
+
// Ignore if we're accepting
|
|
1732
|
+
if (scratch->extensions & EXT_CRITIC_ACCEPT) {
|
|
1733
|
+
break;
|
|
1734
|
+
}
|
|
1735
|
+
|
|
1736
|
+
if (scratch->extensions & EXT_CRITIC) {
|
|
1737
|
+
t->child->type = TEXT_EMPTY;
|
|
1738
|
+
t->child->mate->type = TEXT_EMPTY;
|
|
1739
|
+
|
|
1740
|
+
if (scratch->extensions & EXT_CRITIC_REJECT) {
|
|
1741
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
1742
|
+
} else {
|
|
1743
|
+
print_const("<text:span text:style-name=\"Strike\">");
|
|
1744
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
1745
|
+
print_const("</text:span>");
|
|
1746
|
+
}
|
|
1747
|
+
} else {
|
|
1748
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
1749
|
+
}
|
|
1750
|
+
|
|
1751
|
+
break;
|
|
1752
|
+
|
|
1753
|
+
case PAIR_CRITIC_COM:
|
|
1754
|
+
|
|
1755
|
+
// Ignore if we're rejecting or accepting
|
|
1756
|
+
if ((scratch->extensions & EXT_CRITIC_REJECT) ||
|
|
1757
|
+
(scratch->extensions & EXT_CRITIC_ACCEPT)) {
|
|
1758
|
+
break;
|
|
1759
|
+
}
|
|
1760
|
+
|
|
1761
|
+
if (scratch->extensions & EXT_CRITIC) {
|
|
1762
|
+
t->child->type = TEXT_EMPTY;
|
|
1763
|
+
t->child->mate->type = TEXT_EMPTY;
|
|
1764
|
+
print_const("<text:span text:style-name=\"Comment\">");
|
|
1765
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
1766
|
+
print_const("</text:span>");
|
|
1767
|
+
} else {
|
|
1768
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
1769
|
+
}
|
|
1770
|
+
|
|
1771
|
+
break;
|
|
1772
|
+
|
|
1773
|
+
case PAIR_CRITIC_HI:
|
|
1774
|
+
|
|
1775
|
+
// Ignore if we're rejecting or accepting
|
|
1776
|
+
if ((scratch->extensions & EXT_CRITIC_REJECT) ||
|
|
1777
|
+
(scratch->extensions & EXT_CRITIC_ACCEPT)) {
|
|
1778
|
+
t->child->type = TEXT_EMPTY;
|
|
1779
|
+
t->child->mate->type = TEXT_EMPTY;
|
|
1780
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
1781
|
+
break;
|
|
1782
|
+
}
|
|
1783
|
+
|
|
1784
|
+
if (scratch->extensions & EXT_CRITIC) {
|
|
1785
|
+
t->child->type = TEXT_EMPTY;
|
|
1786
|
+
t->child->mate->type = TEXT_EMPTY;
|
|
1787
|
+
print_const("<text:span text:style-name=\"Highlight\">");
|
|
1788
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
1789
|
+
print_const("</text:span>");
|
|
1790
|
+
} else {
|
|
1791
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
1792
|
+
}
|
|
1793
|
+
|
|
1794
|
+
break;
|
|
1795
|
+
|
|
1796
|
+
case CRITIC_SUB_DIV_A:
|
|
1797
|
+
print_const("~");
|
|
1798
|
+
break;
|
|
1799
|
+
|
|
1800
|
+
case CRITIC_SUB_DIV_B:
|
|
1801
|
+
print_const(">");
|
|
1802
|
+
break;
|
|
1803
|
+
|
|
1804
|
+
case PAIR_CRITIC_SUB_DEL:
|
|
1805
|
+
if ((scratch->extensions & EXT_CRITIC) &&
|
|
1806
|
+
(t->next) &&
|
|
1807
|
+
(t->next->type == PAIR_CRITIC_SUB_ADD)) {
|
|
1808
|
+
t->child->type = TEXT_EMPTY;
|
|
1809
|
+
t->child->mate->type = TEXT_EMPTY;
|
|
1810
|
+
|
|
1811
|
+
if (scratch->extensions & EXT_CRITIC_ACCEPT) {
|
|
1812
|
+
|
|
1813
|
+
} else if (scratch->extensions & EXT_CRITIC_REJECT) {
|
|
1814
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
1815
|
+
} else {
|
|
1816
|
+
print_const("<text:span text:style-name=\"Strike\">");
|
|
1817
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
1818
|
+
print_const("</text:span>");
|
|
1819
|
+
}
|
|
1820
|
+
} else {
|
|
1821
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
1822
|
+
}
|
|
1823
|
+
|
|
1824
|
+
break;
|
|
1825
|
+
|
|
1826
|
+
case PAIR_CRITIC_SUB_ADD:
|
|
1827
|
+
if ((scratch->extensions & EXT_CRITIC) &&
|
|
1828
|
+
(t->prev) &&
|
|
1829
|
+
(t->prev->type == PAIR_CRITIC_SUB_DEL)) {
|
|
1830
|
+
t->child->type = TEXT_EMPTY;
|
|
1831
|
+
t->child->mate->type = TEXT_EMPTY;
|
|
1832
|
+
|
|
1833
|
+
if (scratch->extensions & EXT_CRITIC_REJECT) {
|
|
1834
|
+
|
|
1835
|
+
} else if (scratch->extensions & EXT_CRITIC_ACCEPT) {
|
|
1836
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
1837
|
+
} else {
|
|
1838
|
+
print_const("<text:span text:style-name=\"Underline\">");
|
|
1839
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
1840
|
+
print_const("</text:span>");
|
|
1841
|
+
}
|
|
1842
|
+
} else {
|
|
1843
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
1844
|
+
}
|
|
1845
|
+
|
|
1846
|
+
break;
|
|
1847
|
+
|
|
1848
|
+
case PAIR_HTML_COMMENT:
|
|
1849
|
+
break;
|
|
1850
|
+
|
|
1851
|
+
case PAIR_MATH:
|
|
1852
|
+
print_const("<text:span text:style-name=\"math\">");
|
|
1853
|
+
mmd_export_token_tree_opendocument_math(out, source, t->child, scratch);
|
|
1854
|
+
print_const("</text:span>");
|
|
1855
|
+
break;
|
|
1856
|
+
|
|
1857
|
+
case PAIR_EMPH:
|
|
1858
|
+
case PAIR_PAREN:
|
|
1859
|
+
case PAIR_QUOTE_DOUBLE:
|
|
1860
|
+
case PAIR_QUOTE_SINGLE:
|
|
1861
|
+
case PAIR_STAR:
|
|
1862
|
+
case PAIR_STRONG:
|
|
1863
|
+
case PAIR_SUBSCRIPT:
|
|
1864
|
+
case PAIR_SUPERSCRIPT:
|
|
1865
|
+
case PAIR_UL:
|
|
1866
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
1867
|
+
break;
|
|
1868
|
+
|
|
1869
|
+
case PAREN_LEFT:
|
|
1870
|
+
print_char('(');
|
|
1871
|
+
break;
|
|
1872
|
+
|
|
1873
|
+
case PAREN_RIGHT:
|
|
1874
|
+
print_char(')');
|
|
1875
|
+
break;
|
|
1876
|
+
|
|
1877
|
+
case PIPE:
|
|
1878
|
+
print_token(t);
|
|
1879
|
+
break;
|
|
1880
|
+
|
|
1881
|
+
case PLUS:
|
|
1882
|
+
print_char('+');
|
|
1883
|
+
break;
|
|
1884
|
+
|
|
1885
|
+
case QUOTE_SINGLE:
|
|
1886
|
+
if ((t->mate == NULL) || (!(scratch->extensions & EXT_SMART))) {
|
|
1887
|
+
print_const("'");
|
|
1888
|
+
} else {
|
|
1889
|
+
(t->start < t->mate->start) ? ( print_localized(QUOTE_LEFT_SINGLE) ) : ( print_localized(QUOTE_RIGHT_SINGLE) );
|
|
1890
|
+
}
|
|
1891
|
+
|
|
1892
|
+
break;
|
|
1893
|
+
|
|
1894
|
+
case QUOTE_DOUBLE:
|
|
1895
|
+
if ((t->mate == NULL) || (!(scratch->extensions & EXT_SMART))) {
|
|
1896
|
+
print_const(""");
|
|
1897
|
+
} else {
|
|
1898
|
+
(t->start < t->mate->start) ? ( print_localized(QUOTE_LEFT_DOUBLE) ) : ( print_localized(QUOTE_RIGHT_DOUBLE) );
|
|
1899
|
+
}
|
|
1900
|
+
|
|
1901
|
+
break;
|
|
1902
|
+
|
|
1903
|
+
case QUOTE_RIGHT_ALT:
|
|
1904
|
+
if ((t->mate == NULL) || (!(scratch->extensions & EXT_SMART))) {
|
|
1905
|
+
print_const("''");
|
|
1906
|
+
} else {
|
|
1907
|
+
print_localized(QUOTE_RIGHT_DOUBLE);
|
|
1908
|
+
}
|
|
1909
|
+
|
|
1910
|
+
break;
|
|
1911
|
+
|
|
1912
|
+
case SLASH:
|
|
1913
|
+
print_char('/');
|
|
1914
|
+
break;
|
|
1915
|
+
|
|
1916
|
+
case STAR:
|
|
1917
|
+
print_char('*');
|
|
1918
|
+
break;
|
|
1919
|
+
|
|
1920
|
+
case STRONG_START:
|
|
1921
|
+
print_const("<text:span text:style-name=\"MMD-Bold\">");
|
|
1922
|
+
break;
|
|
1923
|
+
|
|
1924
|
+
case STRONG_STOP:
|
|
1925
|
+
print_const("</text:span>");
|
|
1926
|
+
break;
|
|
1927
|
+
|
|
1928
|
+
case SUBSCRIPT:
|
|
1929
|
+
if (t->mate) {
|
|
1930
|
+
(t->start < t->mate->start) ? (print_const("<text:span text:style-name=\"MMD-Subscript\">")) : (print_const("</text:span>"));
|
|
1931
|
+
} else if (t->len != 1) {
|
|
1932
|
+
print_const("<text:span text:style-name=\"MMD-Subscript\">");
|
|
1933
|
+
mmd_export_token_opendocument(out, source, t->child, scratch);
|
|
1934
|
+
print_const("</text:span>");
|
|
1935
|
+
} else {
|
|
1936
|
+
print_const("~");
|
|
1937
|
+
}
|
|
1938
|
+
|
|
1939
|
+
break;
|
|
1940
|
+
|
|
1941
|
+
case SUPERSCRIPT:
|
|
1942
|
+
if (t->mate) {
|
|
1943
|
+
(t->start < t->mate->start) ? (print_const("<text:span text:style-name=\"MMD-Superscript\">")) : (print_const("</text:span>"));
|
|
1944
|
+
} else if (t->len != 1) {
|
|
1945
|
+
print_const("<text:span text:style-name=\"MMD-Superscript\">");
|
|
1946
|
+
mmd_export_token_opendocument(out, source, t->child, scratch);
|
|
1947
|
+
print_const("</text:span>");
|
|
1948
|
+
} else {
|
|
1949
|
+
print_const("^");
|
|
1950
|
+
}
|
|
1951
|
+
|
|
1952
|
+
break;
|
|
1953
|
+
|
|
1954
|
+
case TABLE_CELL:
|
|
1955
|
+
print_const("<table:table-cell");
|
|
1956
|
+
|
|
1957
|
+
if (t->next && t->next->type == TABLE_DIVIDER) {
|
|
1958
|
+
if (t->next->len > 1) {
|
|
1959
|
+
printf(" table:number-columns-spanned=\"%d\"", t->next->len);
|
|
1960
|
+
}
|
|
1961
|
+
}
|
|
1962
|
+
|
|
1963
|
+
if (scratch->in_table_header) {
|
|
1964
|
+
print_const(">\n<text:p text:style-name=\"Table_20_Heading\"");
|
|
1965
|
+
} else {
|
|
1966
|
+
print_const(">\n<text:p");
|
|
1967
|
+
|
|
1968
|
+
switch (scratch->table_alignment[scratch->table_cell_count]) {
|
|
1969
|
+
case 'l':
|
|
1970
|
+
case 'L':
|
|
1971
|
+
default:
|
|
1972
|
+
print_const(" text:style-name=\"MMD-Table\"");
|
|
1973
|
+
break;
|
|
1974
|
+
|
|
1975
|
+
case 'r':
|
|
1976
|
+
case 'R':
|
|
1977
|
+
print_const(" text:style-name=\"MMD-Table-Right\"");
|
|
1978
|
+
break;
|
|
1979
|
+
|
|
1980
|
+
case 'c':
|
|
1981
|
+
case 'C':
|
|
1982
|
+
print_const(" text:style-name=\"MMD-Table-Center\"");
|
|
1983
|
+
break;
|
|
1984
|
+
}
|
|
1985
|
+
}
|
|
1986
|
+
|
|
1987
|
+
print_const(">");
|
|
1988
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
1989
|
+
|
|
1990
|
+
print_const("</text:p>\n</table:table-cell>\n");
|
|
1991
|
+
|
|
1992
|
+
if (t->next) {
|
|
1993
|
+
scratch->table_cell_count += t->next->len;
|
|
1994
|
+
} else {
|
|
1995
|
+
scratch->table_cell_count++;
|
|
1996
|
+
}
|
|
1997
|
+
|
|
1998
|
+
break;
|
|
1999
|
+
|
|
2000
|
+
case TABLE_DIVIDER:
|
|
2001
|
+
break;
|
|
2002
|
+
|
|
2003
|
+
case TABLE_ROW:
|
|
2004
|
+
print_const("<table:table-row>\n");
|
|
2005
|
+
scratch->table_cell_count = 0;
|
|
2006
|
+
mmd_export_token_tree_opendocument(out, source, t->child, scratch);
|
|
2007
|
+
print_const("</table:table-row>\n");
|
|
2008
|
+
break;
|
|
2009
|
+
|
|
2010
|
+
case TEXT_EMPTY:
|
|
2011
|
+
break;
|
|
2012
|
+
|
|
2013
|
+
case TEXT_LINEBREAK:
|
|
2014
|
+
if (t->next) {
|
|
2015
|
+
print_const("<text:line-break/>\n");
|
|
2016
|
+
scratch->padded = 0;
|
|
2017
|
+
}
|
|
2018
|
+
|
|
2019
|
+
break;
|
|
2020
|
+
|
|
2021
|
+
case TEXT_NL:
|
|
2022
|
+
if (t->next) {
|
|
2023
|
+
print_char('\n');
|
|
2024
|
+
}
|
|
2025
|
+
|
|
2026
|
+
break;
|
|
2027
|
+
|
|
2028
|
+
case RAW_FILTER_LEFT:
|
|
2029
|
+
case TEXT_BACKSLASH:
|
|
2030
|
+
case TEXT_BRACE_LEFT:
|
|
2031
|
+
case TEXT_BRACE_RIGHT:
|
|
2032
|
+
case TEXT_HASH:
|
|
2033
|
+
case TEXT_NUMBER_POSS_LIST:
|
|
2034
|
+
case TEXT_PERCENT:
|
|
2035
|
+
case TEXT_PERIOD:
|
|
2036
|
+
case TEXT_PLAIN:
|
|
2037
|
+
case TOC:
|
|
2038
|
+
case UL:
|
|
2039
|
+
print_token(t);
|
|
2040
|
+
break;
|
|
2041
|
+
|
|
2042
|
+
default:
|
|
2043
|
+
fprintf(stderr, "Unknown token type: %d\n", t->type);
|
|
2044
|
+
token_describe(t, source);
|
|
2045
|
+
break;
|
|
2046
|
+
}
|
|
2047
|
+
}
|
|
2048
|
+
|
|
2049
|
+
|
|
2050
|
+
void mmd_export_token_tree_opendocument(DString * out, const char * source, token * t, scratch_pad * scratch) {
|
|
2051
|
+
|
|
2052
|
+
// Prevent stack overflow with "dangerous" input causing extreme recursion
|
|
2053
|
+
if (scratch->recurse_depth == kMaxExportRecursiveDepth) {
|
|
2054
|
+
return;
|
|
2055
|
+
}
|
|
2056
|
+
|
|
2057
|
+
scratch->recurse_depth++;
|
|
2058
|
+
|
|
2059
|
+
while (t != NULL) {
|
|
2060
|
+
if (scratch->skip_token) {
|
|
2061
|
+
scratch->skip_token--;
|
|
2062
|
+
} else {
|
|
2063
|
+
mmd_export_token_opendocument(out, source, t, scratch);
|
|
2064
|
+
}
|
|
2065
|
+
|
|
2066
|
+
t = t->next;
|
|
2067
|
+
}
|
|
2068
|
+
|
|
2069
|
+
scratch->recurse_depth--;
|
|
2070
|
+
}
|
|
2071
|
+
|