rpeg-multimarkdown 0.1.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.
- data/LICENSE +94 -0
- data/README.markdown +58 -0
- data/Rakefile +171 -0
- data/bin/rpeg-multimarkdown +128 -0
- data/ext/extconf.h +3 -0
- data/ext/extconf.rb +15 -0
- data/ext/markdown.c +88 -0
- data/ext/markdown_lib.c +211 -0
- data/ext/markdown_lib.h +28 -0
- data/ext/markdown_output.c +2704 -0
- data/ext/markdown_parser.c +8275 -0
- data/ext/markdown_peg.h +142 -0
- data/ext/odf.c +179 -0
- data/ext/odf.h +3 -0
- data/ext/parsing_functions.c +182 -0
- data/ext/utility_functions.c +535 -0
- data/lib/multimarkdown.rb +1 -0
- data/lib/peg_multimarkdown.rb +74 -0
- data/test/MultiMarkdownTest/BeamerTests/Beamer-Tables.html +76 -0
- data/test/MultiMarkdownTest/BeamerTests/Beamer-Tables.tex +64 -0
- data/test/MultiMarkdownTest/BeamerTests/Beamer-Tables.text +38 -0
- data/test/MultiMarkdownTest/MarkdownTest.pl +182 -0
- data/test/MultiMarkdownTest/MemoirTests/Automatic Labels.html +42 -0
- data/test/MultiMarkdownTest/MemoirTests/Automatic Labels.tex +47 -0
- data/test/MultiMarkdownTest/MemoirTests/Automatic Labels.text +46 -0
- data/test/MultiMarkdownTest/MemoirTests/Base Header Level.html +20 -0
- data/test/MultiMarkdownTest/MemoirTests/Base Header Level.tex +19 -0
- data/test/MultiMarkdownTest/MemoirTests/Base Header Level.text +16 -0
- data/test/MultiMarkdownTest/MemoirTests/BibTeX.html +17 -0
- data/test/MultiMarkdownTest/MemoirTests/BibTeX.tex +12 -0
- data/test/MultiMarkdownTest/MemoirTests/BibTeX.text +11 -0
- data/test/MultiMarkdownTest/MemoirTests/Citations.html +63 -0
- data/test/MultiMarkdownTest/MemoirTests/Citations.tex +48 -0
- data/test/MultiMarkdownTest/MemoirTests/Citations.text +43 -0
- data/test/MultiMarkdownTest/MemoirTests/Definition Lists.html +61 -0
- data/test/MultiMarkdownTest/MemoirTests/Definition Lists.tex +63 -0
- data/test/MultiMarkdownTest/MemoirTests/Definition Lists.text +40 -0
- data/test/MultiMarkdownTest/MemoirTests/Dutch.html +23 -0
- data/test/MultiMarkdownTest/MemoirTests/Dutch.tex +18 -0
- data/test/MultiMarkdownTest/MemoirTests/Dutch.text +17 -0
- data/test/MultiMarkdownTest/MemoirTests/Email.html +48 -0
- data/test/MultiMarkdownTest/MemoirTests/Email.tex +61 -0
- data/test/MultiMarkdownTest/MemoirTests/Email.text +32 -0
- data/test/MultiMarkdownTest/MemoirTests/English.html +23 -0
- data/test/MultiMarkdownTest/MemoirTests/English.tex +18 -0
- data/test/MultiMarkdownTest/MemoirTests/English.text +17 -0
- data/test/MultiMarkdownTest/MemoirTests/Footnotes.html +47 -0
- data/test/MultiMarkdownTest/MemoirTests/Footnotes.tex +28 -0
- data/test/MultiMarkdownTest/MemoirTests/Footnotes.text +26 -0
- data/test/MultiMarkdownTest/MemoirTests/French.html +23 -0
- data/test/MultiMarkdownTest/MemoirTests/French.tex +18 -0
- data/test/MultiMarkdownTest/MemoirTests/French.text +17 -0
- data/test/MultiMarkdownTest/MemoirTests/German.html +23 -0
- data/test/MultiMarkdownTest/MemoirTests/German.tex +18 -0
- data/test/MultiMarkdownTest/MemoirTests/German.text +17 -0
- data/test/MultiMarkdownTest/MemoirTests/GermanGuillemets.html +23 -0
- data/test/MultiMarkdownTest/MemoirTests/GermanGuillemets.tex +18 -0
- data/test/MultiMarkdownTest/MemoirTests/GermanGuillemets.text +17 -0
- data/test/MultiMarkdownTest/MemoirTests/Glossary.html +47 -0
- data/test/MultiMarkdownTest/MemoirTests/Glossary.tex +30 -0
- data/test/MultiMarkdownTest/MemoirTests/Glossary.text +29 -0
- data/test/MultiMarkdownTest/MemoirTests/Line Breaks.html +21 -0
- data/test/MultiMarkdownTest/MemoirTests/Line Breaks.tex +16 -0
- data/test/MultiMarkdownTest/MemoirTests/Line Breaks.text +16 -0
- data/test/MultiMarkdownTest/MemoirTests/Link Attributes.html +40 -0
- data/test/MultiMarkdownTest/MemoirTests/Link Attributes.tex +61 -0
- data/test/MultiMarkdownTest/MemoirTests/Link Attributes.text +51 -0
- data/test/MultiMarkdownTest/MemoirTests/Math.html +22 -0
- data/test/MultiMarkdownTest/MemoirTests/Math.tex +16 -0
- data/test/MultiMarkdownTest/MemoirTests/Math.text +16 -0
- data/test/MultiMarkdownTest/MemoirTests/Memoir Mode.html +24 -0
- data/test/MultiMarkdownTest/MemoirTests/Memoir Mode.tex +23 -0
- data/test/MultiMarkdownTest/MemoirTests/Memoir Mode.text +20 -0
- data/test/MultiMarkdownTest/MemoirTests/MetaData.html +22 -0
- data/test/MultiMarkdownTest/MemoirTests/MetaData.tex +14 -0
- data/test/MultiMarkdownTest/MemoirTests/MetaData.text +15 -0
- data/test/MultiMarkdownTest/MemoirTests/Sanity.html +100 -0
- data/test/MultiMarkdownTest/MemoirTests/Sanity.tex +101 -0
- data/test/MultiMarkdownTest/MemoirTests/Sanity.text +78 -0
- data/test/MultiMarkdownTest/MemoirTests/SmartQuotes.html +26 -0
- data/test/MultiMarkdownTest/MemoirTests/SmartQuotes.tex +21 -0
- data/test/MultiMarkdownTest/MemoirTests/SmartQuotes.text +19 -0
- data/test/MultiMarkdownTest/MemoirTests/Swedish.html +23 -0
- data/test/MultiMarkdownTest/MemoirTests/Swedish.tex +18 -0
- data/test/MultiMarkdownTest/MemoirTests/Swedish.text +17 -0
- data/test/MultiMarkdownTest/MemoirTests/Tables.html +221 -0
- data/test/MultiMarkdownTest/MemoirTests/Tables.tex +134 -0
- data/test/MultiMarkdownTest/MemoirTests/Tables.text +64 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Automatic Labels.html +41 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Automatic Labels.tex +46 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Automatic Labels.text +45 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Base Header Level.html +20 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Base Header Level.tex +19 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Base Header Level.text +16 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/BibTeX.html +16 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/BibTeX.tex +11 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/BibTex.text +10 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Citations.html +62 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Citations.tex +47 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Citations.text +42 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Definition Lists.html +60 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Definition Lists.tex +62 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Definition Lists.text +39 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Dutch.html +23 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Dutch.tex +18 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Dutch.text +17 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Email.html +47 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Email.tex +54 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Email.text +31 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/English.html +23 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/English.tex +18 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/English.text +17 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Errors.html +16 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Errors.tex +11 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Errors.text +11 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Footnotes.html +46 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Footnotes.tex +24 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Footnotes.text +25 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/French.html +23 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/French.tex +18 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/French.text +17 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/German.html +23 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/German.tex +18 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/German.text +17 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/GermanGuillemets.html +23 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/GermanGuillemets.tex +18 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/GermanGuillemets.text +17 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Glossary.html +46 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Glossary.tex +26 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Glossary.text +28 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Headers.html +46 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Headers.tex +52 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Headers.text +49 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Line Breaks.html +20 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Line Breaks.tex +15 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Line Breaks.text +15 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Link Attributes.html +54 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Link Attributes.tex +60 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Link Attributes.text +50 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/List Parsing.html +20 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/List Parsing.tex +17 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/List Parsing.text +11 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/MarkdownInHTML.html +19 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/MarkdownInHTML.tex +13 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/MarkdownInHTML.text +19 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Math.html +21 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Math.tex +15 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Math.text +15 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/MetaData.html +21 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/MetaData.tex +13 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/MetaData.text +14 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Sanity.html +104 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Sanity.tex +100 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Sanity.text +77 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/SmartQuotes.html +29 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/SmartQuotes.tex +24 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/SmartQuotes.text +22 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Swedish.html +23 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Swedish.tex +18 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Swedish.text +17 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Tables.html +230 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Tables.tex +133 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/Tables.text +63 -0
- data/test/MultiMarkdownTest/MultiMarkdownTests/bibtex.bib +119 -0
- data/test/MultiMarkdownTest/README.md +58 -0
- data/test/MultiMarkdownTest/Tests/Amps and angle encoding.html +17 -0
- data/test/MultiMarkdownTest/Tests/Amps and angle encoding.text +21 -0
- data/test/MultiMarkdownTest/Tests/Auto links.html +18 -0
- data/test/MultiMarkdownTest/Tests/Auto links.text +13 -0
- data/test/MultiMarkdownTest/Tests/Backslash escapes.html +118 -0
- data/test/MultiMarkdownTest/Tests/Backslash escapes.text +120 -0
- data/test/MultiMarkdownTest/Tests/Blockquotes with code blocks.html +15 -0
- data/test/MultiMarkdownTest/Tests/Blockquotes with code blocks.text +11 -0
- data/test/MultiMarkdownTest/Tests/Code Blocks.html +18 -0
- data/test/MultiMarkdownTest/Tests/Code Blocks.text +14 -0
- data/test/MultiMarkdownTest/Tests/Code Spans.html +6 -0
- data/test/MultiMarkdownTest/Tests/Code Spans.text +6 -0
- data/test/MultiMarkdownTest/Tests/Compatibility.html +5 -0
- data/test/MultiMarkdownTest/Tests/Compatibility.text +9 -0
- data/test/MultiMarkdownTest/Tests/Hard-wrapped paragraphs with list-like lines.html +8 -0
- data/test/MultiMarkdownTest/Tests/Hard-wrapped paragraphs with list-like lines.text +8 -0
- data/test/MultiMarkdownTest/Tests/Horizontal rules.html +71 -0
- data/test/MultiMarkdownTest/Tests/Horizontal rules.text +67 -0
- data/test/MultiMarkdownTest/Tests/Inline HTML (Advanced).html +15 -0
- data/test/MultiMarkdownTest/Tests/Inline HTML (Advanced).text +15 -0
- data/test/MultiMarkdownTest/Tests/Inline HTML (Simple).html +72 -0
- data/test/MultiMarkdownTest/Tests/Inline HTML (Simple).text +69 -0
- data/test/MultiMarkdownTest/Tests/Inline HTML comments.html +13 -0
- data/test/MultiMarkdownTest/Tests/Inline HTML comments.text +13 -0
- data/test/MultiMarkdownTest/Tests/Links, inline style.html +11 -0
- data/test/MultiMarkdownTest/Tests/Links, inline style.text +12 -0
- data/test/MultiMarkdownTest/Tests/Links, reference style.html +52 -0
- data/test/MultiMarkdownTest/Tests/Links, reference style.text +71 -0
- data/test/MultiMarkdownTest/Tests/Links, shortcut references.html +9 -0
- data/test/MultiMarkdownTest/Tests/Links, shortcut references.text +20 -0
- data/test/MultiMarkdownTest/Tests/Literal quotes in titles.html +3 -0
- data/test/MultiMarkdownTest/Tests/Literal quotes in titles.text +7 -0
- data/test/MultiMarkdownTest/Tests/Markdown Documentation - Basics.html +314 -0
- data/test/MultiMarkdownTest/Tests/Markdown Documentation - Basics.text +306 -0
- data/test/MultiMarkdownTest/Tests/Markdown Documentation - Syntax.html +942 -0
- data/test/MultiMarkdownTest/Tests/Markdown Documentation - Syntax.text +888 -0
- data/test/MultiMarkdownTest/Tests/Nested blockquotes.html +9 -0
- data/test/MultiMarkdownTest/Tests/Nested blockquotes.text +5 -0
- data/test/MultiMarkdownTest/Tests/Ordered and unordered lists.html +148 -0
- data/test/MultiMarkdownTest/Tests/Ordered and unordered lists.text +131 -0
- data/test/MultiMarkdownTest/Tests/Strong and em together.html +7 -0
- data/test/MultiMarkdownTest/Tests/Strong and em together.text +7 -0
- data/test/MultiMarkdownTest/Tests/Tabs.html +25 -0
- data/test/MultiMarkdownTest/Tests/Tabs.text +21 -0
- data/test/MultiMarkdownTest/Tests/Tidyness.html +8 -0
- data/test/MultiMarkdownTest/Tests/Tidyness.text +5 -0
- data/test/benchmark.rb +49 -0
- data/test/multimarkdown_test.rb +89 -0
- metadata +280 -0
data/ext/extconf.h
ADDED
data/ext/extconf.rb
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require 'mkmf'
|
|
2
|
+
|
|
3
|
+
dir_config('peg_multimarkdown')
|
|
4
|
+
|
|
5
|
+
$objs = %w[markdown.o markdown_lib.o markdown_output.o markdown_parser.o]
|
|
6
|
+
|
|
7
|
+
if pkg_config = find_executable('pkg-config')
|
|
8
|
+
$CFLAGS = "-fcommon "+`#{pkg_config} --cflags glib-2.0`
|
|
9
|
+
$LDFLAGS = `#{pkg_config} --libs glib-2.0`
|
|
10
|
+
else
|
|
11
|
+
fail "glib2 not found"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
create_header
|
|
15
|
+
create_makefile('peg_multimarkdown')
|
data/ext/markdown.c
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
#include "ruby.h"
|
|
2
|
+
#include "markdown_peg.h"
|
|
3
|
+
|
|
4
|
+
static VALUE rb_cMultiMarkdown;
|
|
5
|
+
|
|
6
|
+
int get_exts(VALUE self)
|
|
7
|
+
{
|
|
8
|
+
int extensions = 0;
|
|
9
|
+
if ( rb_funcall(self, rb_intern("smart"), 0) == Qtrue )
|
|
10
|
+
extensions = extensions | EXT_SMART ;
|
|
11
|
+
if ( rb_funcall(self, rb_intern("notes"), 0) == Qtrue )
|
|
12
|
+
extensions = extensions | EXT_NOTES ;
|
|
13
|
+
if ( rb_funcall(self, rb_intern("filter_html"), 0) == Qtrue )
|
|
14
|
+
extensions = extensions | EXT_FILTER_HTML ;
|
|
15
|
+
if ( rb_funcall(self, rb_intern("filter_styles"), 0) == Qtrue )
|
|
16
|
+
extensions = extensions | EXT_FILTER_STYLES ;
|
|
17
|
+
if ( rb_funcall(self, rb_intern("process_html"), 0) == Qtrue )
|
|
18
|
+
extensions = extensions | EXT_PROCESS_HTML;
|
|
19
|
+
/* Compatibility overwrites all other extensions */
|
|
20
|
+
if ( rb_funcall(self, rb_intern("compatibility"), 0) == Qtrue )
|
|
21
|
+
extensions = EXT_COMPATIBILITY;
|
|
22
|
+
return extensions;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
static VALUE
|
|
26
|
+
rb_multimarkdown_to_html(int argc, VALUE *argv, VALUE self)
|
|
27
|
+
{
|
|
28
|
+
/* grab char pointer to multimarkdown input text */
|
|
29
|
+
VALUE text = rb_funcall(self, rb_intern("text"), 0);
|
|
30
|
+
Check_Type(text, T_STRING);
|
|
31
|
+
char * ptext = StringValuePtr(text);
|
|
32
|
+
|
|
33
|
+
int extensions = get_exts(self);
|
|
34
|
+
|
|
35
|
+
char *html = markdown_to_string(ptext, extensions, HTML_FORMAT);
|
|
36
|
+
VALUE result = rb_str_new2(html);
|
|
37
|
+
free(html);
|
|
38
|
+
|
|
39
|
+
return result;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
static VALUE
|
|
43
|
+
rb_multimarkdown_to_latex(int argc, VALUE *argv, VALUE self)
|
|
44
|
+
{
|
|
45
|
+
/* grab char pointer to multimarkdown input text */
|
|
46
|
+
VALUE text = rb_funcall(self, rb_intern("text"), 0);
|
|
47
|
+
Check_Type(text, T_STRING);
|
|
48
|
+
char * ptext = StringValuePtr(text);
|
|
49
|
+
|
|
50
|
+
int extensions = get_exts(self);
|
|
51
|
+
|
|
52
|
+
char *latex = markdown_to_string(ptext, extensions, LATEX_FORMAT);
|
|
53
|
+
VALUE result = rb_str_new2(latex);
|
|
54
|
+
free(latex);
|
|
55
|
+
|
|
56
|
+
return result;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
static VALUE
|
|
60
|
+
rb_multimarkdown_extract_metadata(VALUE self, VALUE key)
|
|
61
|
+
{
|
|
62
|
+
/* grab char pointer to multimarkdown input text */
|
|
63
|
+
VALUE text = rb_funcall(self, rb_intern("text"), 0);
|
|
64
|
+
Check_Type(text, T_STRING);
|
|
65
|
+
char * ptext = StringValuePtr(text);
|
|
66
|
+
|
|
67
|
+
Check_Type(key, T_STRING);
|
|
68
|
+
char * pkey = StringValuePtr(key);
|
|
69
|
+
|
|
70
|
+
int extensions = get_exts(self);
|
|
71
|
+
|
|
72
|
+
/* Display metadata on request */
|
|
73
|
+
char *metadata = extract_metadata_value(ptext, extensions, pkey);
|
|
74
|
+
VALUE result = rb_str_new2(metadata);
|
|
75
|
+
free(metadata);
|
|
76
|
+
|
|
77
|
+
return result;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
void Init_peg_multimarkdown()
|
|
81
|
+
{
|
|
82
|
+
rb_cMultiMarkdown = rb_define_class("PEGMultiMarkdown", rb_cObject);
|
|
83
|
+
rb_define_method(rb_cMultiMarkdown, "to_html", rb_multimarkdown_to_html, -1);
|
|
84
|
+
rb_define_method(rb_cMultiMarkdown, "to_latex", rb_multimarkdown_to_latex, -1);
|
|
85
|
+
rb_define_method(rb_cMultiMarkdown, "extract_metadata", rb_multimarkdown_extract_metadata, 1);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// vim: ts=4 sw=4
|
data/ext/markdown_lib.c
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/**********************************************************************
|
|
2
|
+
|
|
3
|
+
markdown_lib.c - markdown in C using a PEG grammar.
|
|
4
|
+
(c) 2008 John MacFarlane (jgm at berkeley dot edu).
|
|
5
|
+
|
|
6
|
+
portions Copyright (c) 2010-2011 Fletcher T. Penney
|
|
7
|
+
|
|
8
|
+
This program is free software; you can redistribute it and/or modify
|
|
9
|
+
it under the terms of the GNU General Public License or the MIT
|
|
10
|
+
license. See LICENSE for details.
|
|
11
|
+
|
|
12
|
+
This program is distributed in the hope that it will be useful,
|
|
13
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
GNU General Public License for more details.
|
|
16
|
+
|
|
17
|
+
***********************************************************************/
|
|
18
|
+
|
|
19
|
+
#include <stdio.h>
|
|
20
|
+
#include <stdlib.h>
|
|
21
|
+
#include <string.h>
|
|
22
|
+
#include "markdown_peg.h"
|
|
23
|
+
|
|
24
|
+
#define TABSTOP 4
|
|
25
|
+
|
|
26
|
+
/* preformat_text - allocate and copy text buffer while
|
|
27
|
+
* performing tab expansion. */
|
|
28
|
+
static GString *preformat_text(char *text) {
|
|
29
|
+
GString *buf;
|
|
30
|
+
char next_char;
|
|
31
|
+
int charstotab;
|
|
32
|
+
|
|
33
|
+
int len = 0;
|
|
34
|
+
|
|
35
|
+
buf = g_string_new("");
|
|
36
|
+
|
|
37
|
+
charstotab = TABSTOP;
|
|
38
|
+
while ((next_char = *text++) != '\0') {
|
|
39
|
+
switch (next_char) {
|
|
40
|
+
case '\t':
|
|
41
|
+
while (charstotab > 0)
|
|
42
|
+
g_string_append_c(buf, ' '), len++, charstotab--;
|
|
43
|
+
break;
|
|
44
|
+
case '\n':
|
|
45
|
+
g_string_append_c(buf, '\n'), len++, charstotab = TABSTOP;
|
|
46
|
+
break;
|
|
47
|
+
default:
|
|
48
|
+
g_string_append_c(buf, next_char), len++, charstotab--;
|
|
49
|
+
}
|
|
50
|
+
if (charstotab == 0)
|
|
51
|
+
charstotab = TABSTOP;
|
|
52
|
+
}
|
|
53
|
+
g_string_append(buf, "\n\n");
|
|
54
|
+
return(buf);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/* print_tree - print tree of elements, for debugging only. */
|
|
58
|
+
static void print_tree(element * elt, int indent) {
|
|
59
|
+
int i;
|
|
60
|
+
char * key;
|
|
61
|
+
while (elt != NULL) {
|
|
62
|
+
for (i = 0; i < indent; i++)
|
|
63
|
+
fputc(' ', stderr);
|
|
64
|
+
switch (elt->key) {
|
|
65
|
+
case LIST: key = "LIST"; break;
|
|
66
|
+
case RAW: key = "RAW"; break;
|
|
67
|
+
case SPACE: key = "SPACE"; break;
|
|
68
|
+
case LINEBREAK: key = "LINEBREAK"; break;
|
|
69
|
+
case ELLIPSIS: key = "ELLIPSIS"; break;
|
|
70
|
+
case EMDASH: key = "EMDASH"; break;
|
|
71
|
+
case ENDASH: key = "ENDASH"; break;
|
|
72
|
+
case APOSTROPHE: key = "APOSTROPHE"; break;
|
|
73
|
+
case SINGLEQUOTED: key = "SINGLEQUOTED"; break;
|
|
74
|
+
case DOUBLEQUOTED: key = "DOUBLEQUOTED"; break;
|
|
75
|
+
case STR: key = "STR"; break;
|
|
76
|
+
case LINK: key = "LINK"; break;
|
|
77
|
+
case IMAGE: key = "IMAGE"; break;
|
|
78
|
+
case CODE: key = "CODE"; break;
|
|
79
|
+
case HTML: key = "HTML"; break;
|
|
80
|
+
case EMPH: key = "EMPH"; break;
|
|
81
|
+
case STRONG: key = "STRONG"; break;
|
|
82
|
+
case PLAIN: key = "PLAIN"; break;
|
|
83
|
+
case PARA: key = "PARA"; break;
|
|
84
|
+
case LISTITEM: key = "LISTITEM"; break;
|
|
85
|
+
case BULLETLIST: key = "BULLETLIST"; break;
|
|
86
|
+
case ORDEREDLIST: key = "ORDEREDLIST"; break;
|
|
87
|
+
case H1: key = "H1"; break;
|
|
88
|
+
case H2: key = "H2"; break;
|
|
89
|
+
case H3: key = "H3"; break;
|
|
90
|
+
case H4: key = "H4"; break;
|
|
91
|
+
case H5: key = "H5"; break;
|
|
92
|
+
case H6: key = "H6"; break;
|
|
93
|
+
case BLOCKQUOTE: key = "BLOCKQUOTE"; break;
|
|
94
|
+
case VERBATIM: key = "VERBATIM"; break;
|
|
95
|
+
case HTMLBLOCK: key = "HTMLBLOCK"; break;
|
|
96
|
+
case HRULE: key = "HRULE"; break;
|
|
97
|
+
case REFERENCE: key = "REFERENCE"; break;
|
|
98
|
+
case NOTE: key = "NOTE"; break;
|
|
99
|
+
default: key = "?";
|
|
100
|
+
}
|
|
101
|
+
if ( elt->key == STR ) {
|
|
102
|
+
fprintf(stderr, "0x%x: %s '%s'\n", (int)elt, key, elt->contents.str);
|
|
103
|
+
} else {
|
|
104
|
+
fprintf(stderr, "0x%x: %s\n", (int)elt, key);
|
|
105
|
+
}
|
|
106
|
+
if (elt->children)
|
|
107
|
+
print_tree(elt->children, indent + 4);
|
|
108
|
+
elt = elt->next;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/* process_raw_blocks - traverses an element list, replacing any RAW elements with
|
|
113
|
+
* the result of parsing them as markdown text, and recursing into the children
|
|
114
|
+
* of parent elements. The result should be a tree of elements without any RAWs. */
|
|
115
|
+
static element * process_raw_blocks(element *input, int extensions, element *references, element *notes, element *labels) {
|
|
116
|
+
element *current = NULL;
|
|
117
|
+
element *last_child = NULL;
|
|
118
|
+
char *contents;
|
|
119
|
+
current = input;
|
|
120
|
+
|
|
121
|
+
while (current != NULL) {
|
|
122
|
+
if (current->key == RAW) {
|
|
123
|
+
/* \001 is used to indicate boundaries between nested lists when there
|
|
124
|
+
* is no blank line. We split the string by \001 and parse
|
|
125
|
+
* each chunk separately. */
|
|
126
|
+
contents = strtok(current->contents.str, "\001");
|
|
127
|
+
current->key = LIST;
|
|
128
|
+
current->children = parse_markdown(contents, extensions, references, notes, labels);
|
|
129
|
+
last_child = current->children;
|
|
130
|
+
while ((contents = strtok(NULL, "\001"))) {
|
|
131
|
+
while (last_child->next != NULL)
|
|
132
|
+
last_child = last_child->next;
|
|
133
|
+
last_child->next = parse_markdown(contents, extensions, references, notes, labels);
|
|
134
|
+
}
|
|
135
|
+
free(current->contents.str);
|
|
136
|
+
current->contents.str = NULL;
|
|
137
|
+
}
|
|
138
|
+
if (current->children != NULL)
|
|
139
|
+
current->children = process_raw_blocks(current->children, extensions, references, notes, labels);
|
|
140
|
+
current = current->next;
|
|
141
|
+
}
|
|
142
|
+
return input;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/* markdown_to_gstring - convert markdown text to the output format specified.
|
|
146
|
+
* Returns a GString, which must be freed after use using g_string_free(). */
|
|
147
|
+
GString * markdown_to_g_string(char *text, int extensions, int output_format) {
|
|
148
|
+
element *result;
|
|
149
|
+
element *references;
|
|
150
|
+
element *notes;
|
|
151
|
+
element *labels;
|
|
152
|
+
GString *formatted_text;
|
|
153
|
+
GString *out;
|
|
154
|
+
out = g_string_new("");
|
|
155
|
+
|
|
156
|
+
formatted_text = preformat_text(text);
|
|
157
|
+
|
|
158
|
+
if (output_format == OPML_FORMAT) {
|
|
159
|
+
result = parse_markdown_for_opml(formatted_text->str, extensions);
|
|
160
|
+
} else {
|
|
161
|
+
references = parse_references(formatted_text->str, extensions);
|
|
162
|
+
notes = parse_notes(formatted_text->str, extensions, references);
|
|
163
|
+
labels = parse_labels(formatted_text->str, extensions, references, notes);
|
|
164
|
+
result = parse_markdown_with_metadata(formatted_text->str, extensions, references, notes, labels);
|
|
165
|
+
|
|
166
|
+
result = process_raw_blocks(result, extensions, references, notes, labels);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
g_string_free(formatted_text, TRUE);
|
|
170
|
+
|
|
171
|
+
print_element_list(out, result, output_format, extensions);
|
|
172
|
+
|
|
173
|
+
free_element_list(result);
|
|
174
|
+
|
|
175
|
+
if (output_format != OPML_FORMAT) {
|
|
176
|
+
free_element_list(references);
|
|
177
|
+
free_element_list(labels);
|
|
178
|
+
}
|
|
179
|
+
return out;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/* markdown_to_string - convert markdown text to the output format specified.
|
|
183
|
+
* Returns a null-terminated string, which must be freed after use. */
|
|
184
|
+
char * markdown_to_string(char *text, int extensions, int output_format) {
|
|
185
|
+
GString *out;
|
|
186
|
+
char *char_out;
|
|
187
|
+
out = markdown_to_g_string(text, extensions, output_format);
|
|
188
|
+
char_out = out->str;
|
|
189
|
+
g_string_free(out, FALSE);
|
|
190
|
+
return char_out;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/* vim:set ts=4 sw=4: */
|
|
194
|
+
|
|
195
|
+
/* extract_metadata_value - parse document and return value of specified
|
|
196
|
+
metadata key (e.g. "LateX Mode")/
|
|
197
|
+
Returns a null-terminated string, which must be freed after use. */
|
|
198
|
+
char * extract_metadata_value(char *text, int extensions, char *key) {
|
|
199
|
+
char *value;
|
|
200
|
+
element *result;
|
|
201
|
+
char *meta;
|
|
202
|
+
GString *formatted_text;
|
|
203
|
+
|
|
204
|
+
formatted_text = preformat_text(text);
|
|
205
|
+
|
|
206
|
+
result = parse_metadata_only(formatted_text->str, extensions);
|
|
207
|
+
|
|
208
|
+
value = metavalue_for_key(key, result->children);
|
|
209
|
+
free_element_list(result);
|
|
210
|
+
return value;
|
|
211
|
+
}
|
data/ext/markdown_lib.h
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#include <stdlib.h>
|
|
2
|
+
#include <stdio.h>
|
|
3
|
+
#include <glib.h>
|
|
4
|
+
|
|
5
|
+
enum markdown_extensions {
|
|
6
|
+
EXT_SMART = 0x01,
|
|
7
|
+
EXT_NOTES = 0x02,
|
|
8
|
+
EXT_FILTER_HTML = 0x04,
|
|
9
|
+
EXT_FILTER_STYLES = 0x08,
|
|
10
|
+
EXT_COMPATIBILITY = 0x10,
|
|
11
|
+
EXT_PROCESS_HTML = 0x20,
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
enum markdown_formats {
|
|
15
|
+
HTML_FORMAT,
|
|
16
|
+
LATEX_FORMAT,
|
|
17
|
+
MEMOIR_FORMAT,
|
|
18
|
+
BEAMER_FORMAT,
|
|
19
|
+
OPML_FORMAT,
|
|
20
|
+
GROFF_MM_FORMAT,
|
|
21
|
+
ODF_FORMAT,
|
|
22
|
+
ODF_BODY_FORMAT
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
GString * markdown_to_g_string(char *text, int extensions, int output_format);
|
|
26
|
+
char * markdown_to_string(char *text, int extensions, int output_format);
|
|
27
|
+
|
|
28
|
+
/* vim: set ts=4 sw=4 : */
|
|
@@ -0,0 +1,2704 @@
|
|
|
1
|
+
/**********************************************************************
|
|
2
|
+
|
|
3
|
+
markdown_output.c - functions for printing Elements parsed by
|
|
4
|
+
markdown_peg.
|
|
5
|
+
(c) 2008 John MacFarlane (jgm at berkeley dot edu).
|
|
6
|
+
|
|
7
|
+
portions Copyright (c) 2010-2011 Fletcher T. Penney
|
|
8
|
+
|
|
9
|
+
This program is free software; you can redistribute it and/or modify
|
|
10
|
+
it under the terms of the GNU General Public License or the MIT
|
|
11
|
+
license. See LICENSE for details.
|
|
12
|
+
|
|
13
|
+
This program is distributed in the hope that it will be useful,
|
|
14
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
15
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
16
|
+
GNU General Public License for more details.
|
|
17
|
+
|
|
18
|
+
***********************************************************************/
|
|
19
|
+
|
|
20
|
+
#include <stdbool.h>
|
|
21
|
+
#include <stdio.h>
|
|
22
|
+
#include <stdlib.h>
|
|
23
|
+
#include <string.h>
|
|
24
|
+
#include <assert.h>
|
|
25
|
+
#include <glib.h>
|
|
26
|
+
#include "markdown_peg.h"
|
|
27
|
+
#include "utility_functions.c"
|
|
28
|
+
#include "odf.c"
|
|
29
|
+
|
|
30
|
+
static int extensions;
|
|
31
|
+
static int base_header_level = 1;
|
|
32
|
+
static char *latex_footer;
|
|
33
|
+
static int table_column = 0;
|
|
34
|
+
static char *table_alignment;
|
|
35
|
+
static char cell_type = 'd';
|
|
36
|
+
static int language = ENGLISH;
|
|
37
|
+
static bool html_footer = FALSE;
|
|
38
|
+
static int odf_type = 0;
|
|
39
|
+
static bool in_list = FALSE;
|
|
40
|
+
static bool no_latex_footnote = FALSE;
|
|
41
|
+
|
|
42
|
+
static void print_html_string(GString *out, char *str, bool obfuscate);
|
|
43
|
+
static void print_html_element_list(GString *out, element *list, bool obfuscate);
|
|
44
|
+
static void print_html_element(GString *out, element *elt, bool obfuscate);
|
|
45
|
+
static void print_latex_string(GString *out, char *str);
|
|
46
|
+
static void print_latex_element_list(GString *out, element *list);
|
|
47
|
+
static void print_latex_element(GString *out, element *elt);
|
|
48
|
+
static void print_groff_string(GString *out, char *str);
|
|
49
|
+
static void print_groff_mm_element_list(GString *out, element *list);
|
|
50
|
+
static void print_groff_mm_element(GString *out, element *elt, int count);
|
|
51
|
+
static void print_odf_code_string(GString *out, char *str);
|
|
52
|
+
static void print_odf_string(GString *out, char *str);
|
|
53
|
+
static void print_odf_element_list(GString *out, element *list);
|
|
54
|
+
static void print_odf_element(GString *out, element *elt);
|
|
55
|
+
static void print_odf_body_element_list(GString *out, element *list);
|
|
56
|
+
static bool list_contains_key(element *list, int key);
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
/* MultiMarkdown Routines */
|
|
60
|
+
static void print_html_header(GString *out, element *elt, bool obfuscate);
|
|
61
|
+
static void print_html_footer(GString *out, bool obfuscate);
|
|
62
|
+
|
|
63
|
+
static void print_latex_header(GString *out, element *elt);
|
|
64
|
+
static void print_latex_footer(GString *out);
|
|
65
|
+
|
|
66
|
+
static void print_memoir_element_list(GString *out, element *list);
|
|
67
|
+
static void print_memoir_element(GString *out, element *elt);
|
|
68
|
+
|
|
69
|
+
static void print_beamer_element_list(GString *out, element *list);
|
|
70
|
+
static void print_beamer_element(GString *out, element *elt);
|
|
71
|
+
|
|
72
|
+
static void print_opml_string(GString *out, char *str);
|
|
73
|
+
static void print_opml_element_list(GString *out, element *list);
|
|
74
|
+
static void print_opml_element(GString *out, element *elt);
|
|
75
|
+
static void print_opml_metadata(GString *out, element *elt);
|
|
76
|
+
static void print_opml_section_and_children(GString *out, element *list);
|
|
77
|
+
|
|
78
|
+
element * print_html_headingsection(GString *out, element *list, bool obfuscate);
|
|
79
|
+
|
|
80
|
+
static bool is_html_complete_doc(element *meta);
|
|
81
|
+
static int find_latex_mode(int format, element *list);
|
|
82
|
+
element * metadata_for_key(char *key, element *list);
|
|
83
|
+
char * metavalue_for_key(char *key, element *list);
|
|
84
|
+
|
|
85
|
+
element * element_for_attribute(char *querystring, element *list);
|
|
86
|
+
char * dimension_for_attribute(char *querystring, element *list);
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
/**********************************************************************
|
|
90
|
+
|
|
91
|
+
Utility functions for printing
|
|
92
|
+
|
|
93
|
+
***********************************************************************/
|
|
94
|
+
|
|
95
|
+
static int padded = 2; /* Number of newlines after last output.
|
|
96
|
+
Starts at 2 so no newlines are needed at start.
|
|
97
|
+
*/
|
|
98
|
+
|
|
99
|
+
static GSList *endnotes = NULL; /* List of endnotes to print after main content. */
|
|
100
|
+
static int notenumber = 0; /* Number of footnote. */
|
|
101
|
+
|
|
102
|
+
/* pad - add newlines if needed */
|
|
103
|
+
static void pad(GString *out, int num) {
|
|
104
|
+
while (num-- > padded)
|
|
105
|
+
g_string_append_printf(out, "\n");;
|
|
106
|
+
padded = num;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/* determine whether a certain element is contained within a given list */
|
|
110
|
+
bool list_contains_key(element *list, int key) {
|
|
111
|
+
element *step = NULL;
|
|
112
|
+
|
|
113
|
+
step = list;
|
|
114
|
+
while ( step != NULL ) {
|
|
115
|
+
if (step->key == key) {
|
|
116
|
+
return TRUE;
|
|
117
|
+
}
|
|
118
|
+
if (step->children != NULL) {
|
|
119
|
+
if (list_contains_key(step->children, key)) {
|
|
120
|
+
return TRUE;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
step = step->next;
|
|
124
|
+
}
|
|
125
|
+
return FALSE;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**********************************************************************
|
|
129
|
+
|
|
130
|
+
Functions for printing Elements as HTML
|
|
131
|
+
|
|
132
|
+
***********************************************************************/
|
|
133
|
+
|
|
134
|
+
/* print_html_string - print string, escaping for HTML
|
|
135
|
+
* If obfuscate selected, convert characters to hex or decimal entities at random */
|
|
136
|
+
static void print_html_string(GString *out, char *str, bool obfuscate) {
|
|
137
|
+
while (*str != '\0') {
|
|
138
|
+
switch (*str) {
|
|
139
|
+
case '&':
|
|
140
|
+
g_string_append_printf(out, "&");
|
|
141
|
+
break;
|
|
142
|
+
case '<':
|
|
143
|
+
g_string_append_printf(out, "<");
|
|
144
|
+
break;
|
|
145
|
+
case '>':
|
|
146
|
+
g_string_append_printf(out, ">");
|
|
147
|
+
break;
|
|
148
|
+
case '"':
|
|
149
|
+
g_string_append_printf(out, """);
|
|
150
|
+
break;
|
|
151
|
+
default:
|
|
152
|
+
if (obfuscate) {
|
|
153
|
+
if (rand() % 2 == 0)
|
|
154
|
+
g_string_append_printf(out, "&#%d;", (int) *str);
|
|
155
|
+
else
|
|
156
|
+
g_string_append_printf(out, "&#x%x;", (unsigned int) *str);
|
|
157
|
+
}
|
|
158
|
+
else
|
|
159
|
+
g_string_append_c(out, *str);
|
|
160
|
+
}
|
|
161
|
+
str++;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/* print_html_element_list - print a list of elements as HTML */
|
|
166
|
+
static void print_html_element_list(GString *out, element *list, bool obfuscate) {
|
|
167
|
+
while (list != NULL) {
|
|
168
|
+
if (list->key == HEADINGSECTION) {
|
|
169
|
+
list = print_html_headingsection(out, list, obfuscate);
|
|
170
|
+
} else {
|
|
171
|
+
print_html_element(out, list, obfuscate);
|
|
172
|
+
list = list->next;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/* add_endnote - add an endnote to global endnotes list. */
|
|
178
|
+
static void add_endnote(element *elt) {
|
|
179
|
+
endnotes = g_slist_prepend(endnotes, elt);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/* print_html_element - print an element as HTML */
|
|
183
|
+
static void print_html_element(GString *out, element *elt, bool obfuscate) {
|
|
184
|
+
int lev;
|
|
185
|
+
char *label;
|
|
186
|
+
element *attribute;
|
|
187
|
+
char *height;
|
|
188
|
+
char *width;
|
|
189
|
+
switch (elt->key) {
|
|
190
|
+
case SPACE:
|
|
191
|
+
g_string_append_printf(out, "%s", elt->contents.str);
|
|
192
|
+
break;
|
|
193
|
+
case LINEBREAK:
|
|
194
|
+
g_string_append_printf(out, "<br/>\n");
|
|
195
|
+
break;
|
|
196
|
+
case STR:
|
|
197
|
+
print_html_string(out, elt->contents.str, obfuscate);
|
|
198
|
+
break;
|
|
199
|
+
case ELLIPSIS:
|
|
200
|
+
localize_typography(out, ELLIP, language, HTMLOUT);
|
|
201
|
+
break;
|
|
202
|
+
case EMDASH:
|
|
203
|
+
localize_typography(out, MDASH, language, HTMLOUT);
|
|
204
|
+
break;
|
|
205
|
+
case ENDASH:
|
|
206
|
+
localize_typography(out, NDASH, language, HTMLOUT);
|
|
207
|
+
break;
|
|
208
|
+
case APOSTROPHE:
|
|
209
|
+
localize_typography(out, APOS, language, HTMLOUT);
|
|
210
|
+
break;
|
|
211
|
+
case SINGLEQUOTED:
|
|
212
|
+
localize_typography(out, LSQUOTE, language, HTMLOUT);
|
|
213
|
+
print_html_element_list(out, elt->children, obfuscate);
|
|
214
|
+
localize_typography(out, RSQUOTE, language, HTMLOUT);
|
|
215
|
+
break;
|
|
216
|
+
case DOUBLEQUOTED:
|
|
217
|
+
localize_typography(out, LDQUOTE, language, HTMLOUT);
|
|
218
|
+
print_html_element_list(out, elt->children, obfuscate);
|
|
219
|
+
localize_typography(out, RDQUOTE, language, HTMLOUT);
|
|
220
|
+
break;
|
|
221
|
+
case CODE:
|
|
222
|
+
g_string_append_printf(out, "<code>");
|
|
223
|
+
print_html_string(out, elt->contents.str, obfuscate);
|
|
224
|
+
g_string_append_printf(out, "</code>");
|
|
225
|
+
break;
|
|
226
|
+
case HTML:
|
|
227
|
+
g_string_append_printf(out, "%s", elt->contents.str);
|
|
228
|
+
break;
|
|
229
|
+
case LINK:
|
|
230
|
+
if (strstr(elt->contents.link->url, "mailto:") == elt->contents.link->url)
|
|
231
|
+
obfuscate = true; /* obfuscate mailto: links */
|
|
232
|
+
g_string_append_printf(out, "<a href=\"");
|
|
233
|
+
print_html_string(out, elt->contents.link->url, obfuscate);
|
|
234
|
+
g_string_append_printf(out, "\"");
|
|
235
|
+
if (strlen(elt->contents.link->title) > 0) {
|
|
236
|
+
g_string_append_printf(out, " title=\"");
|
|
237
|
+
print_html_string(out, elt->contents.link->title, obfuscate);
|
|
238
|
+
g_string_append_printf(out, "\"");
|
|
239
|
+
}
|
|
240
|
+
print_html_element_list(out, elt->contents.link->attr, obfuscate);
|
|
241
|
+
g_string_append_printf(out, ">");
|
|
242
|
+
print_html_element_list(out, elt->contents.link->label, obfuscate);
|
|
243
|
+
g_string_append_printf(out, "</a>");
|
|
244
|
+
break;
|
|
245
|
+
case IMAGEBLOCK:
|
|
246
|
+
pad(out, 2);
|
|
247
|
+
case IMAGE:
|
|
248
|
+
if (elt->key == IMAGEBLOCK) {
|
|
249
|
+
g_string_append_printf(out, "<figure>\n");
|
|
250
|
+
}
|
|
251
|
+
g_string_append_printf(out, "<img src=\"");
|
|
252
|
+
print_html_string(out, elt->contents.link->url, obfuscate);
|
|
253
|
+
g_string_append_printf(out, "\" alt=\"");
|
|
254
|
+
print_raw_element_list(out,elt->contents.link->label);
|
|
255
|
+
if ( extension(EXT_COMPATIBILITY) ) {
|
|
256
|
+
g_string_append_printf(out, "\"");
|
|
257
|
+
} else {
|
|
258
|
+
g_string_append_printf(out, "\" id=\"%s\"",elt->contents.link->identifier);
|
|
259
|
+
}
|
|
260
|
+
if (strlen(elt->contents.link->title) > 0) {
|
|
261
|
+
g_string_append_printf(out, " title=\"");
|
|
262
|
+
print_html_string(out, elt->contents.link->title, obfuscate);
|
|
263
|
+
g_string_append_printf(out, "\"");
|
|
264
|
+
}
|
|
265
|
+
width = NULL;
|
|
266
|
+
height = NULL;
|
|
267
|
+
attribute = element_for_attribute("height", elt->contents.link->attr);
|
|
268
|
+
if (attribute != NULL) {
|
|
269
|
+
height = strdup(attribute->children->contents.str);
|
|
270
|
+
}
|
|
271
|
+
attribute = element_for_attribute("width", elt->contents.link->attr);
|
|
272
|
+
if (attribute != NULL) {
|
|
273
|
+
width = strdup(attribute->children->contents.str);
|
|
274
|
+
}
|
|
275
|
+
if ((height != NULL) || (width != NULL)) {
|
|
276
|
+
g_string_append_printf(out, " style=\"");
|
|
277
|
+
if (height != NULL)
|
|
278
|
+
g_string_append_printf(out, "height:%s;", height);
|
|
279
|
+
if (width != NULL)
|
|
280
|
+
g_string_append_printf(out, "width:%s;", width);
|
|
281
|
+
g_string_append_printf(out, "\"");
|
|
282
|
+
}
|
|
283
|
+
print_html_element_list(out, elt->contents.link->attr, obfuscate);
|
|
284
|
+
g_string_append_printf(out, " />");
|
|
285
|
+
if (elt->key == IMAGEBLOCK) {
|
|
286
|
+
if (elt->contents.link->label != NULL) {
|
|
287
|
+
g_string_append_printf(out, "\n<figcaption>");
|
|
288
|
+
print_html_element_list(out, elt->contents.link->label, obfuscate);
|
|
289
|
+
g_string_append_printf(out, "</figcaption>");
|
|
290
|
+
}
|
|
291
|
+
g_string_append_printf(out, "</figure>\n");
|
|
292
|
+
}
|
|
293
|
+
free(height);
|
|
294
|
+
free(width);
|
|
295
|
+
break;
|
|
296
|
+
case EMPH:
|
|
297
|
+
g_string_append_printf(out, "<em>");
|
|
298
|
+
print_html_element_list(out, elt->children, obfuscate);
|
|
299
|
+
g_string_append_printf(out, "</em>");
|
|
300
|
+
break;
|
|
301
|
+
case STRONG:
|
|
302
|
+
g_string_append_printf(out, "<strong>");
|
|
303
|
+
print_html_element_list(out, elt->children, obfuscate);
|
|
304
|
+
g_string_append_printf(out, "</strong>");
|
|
305
|
+
break;
|
|
306
|
+
case LIST:
|
|
307
|
+
print_html_element_list(out, elt->children, obfuscate);
|
|
308
|
+
break;
|
|
309
|
+
case RAW:
|
|
310
|
+
/* Shouldn't occur - these are handled by process_raw_blocks() */
|
|
311
|
+
assert(elt->key != RAW);
|
|
312
|
+
break;
|
|
313
|
+
case H1: case H2: case H3: case H4: case H5: case H6:
|
|
314
|
+
lev = elt->key - H1 + base_header_level; /* assumes H1 ... H6 are in order */
|
|
315
|
+
if (lev > 6)
|
|
316
|
+
lev = 6;
|
|
317
|
+
pad(out, 2);
|
|
318
|
+
if ( extension(EXT_COMPATIBILITY) ) {
|
|
319
|
+
/* Use regular Markdown header format */
|
|
320
|
+
g_string_append_printf(out, "<h%1d>", lev);
|
|
321
|
+
print_html_element_list(out, elt->children, obfuscate);
|
|
322
|
+
} else if (elt->children->key == AUTOLABEL) {
|
|
323
|
+
/* generate a label for each header (MMD)*/
|
|
324
|
+
g_string_append_printf(out, "<h%d id=\"%s\">", lev,elt->children->contents.str);
|
|
325
|
+
print_html_element_list(out, elt->children->next, obfuscate);
|
|
326
|
+
} else {
|
|
327
|
+
label = label_from_element_list(elt->children, obfuscate);
|
|
328
|
+
g_string_append_printf(out, "<h%d id=\"%s\">", lev, label);
|
|
329
|
+
print_html_element_list(out, elt->children, obfuscate);
|
|
330
|
+
free(label);
|
|
331
|
+
}
|
|
332
|
+
g_string_append_printf(out, "</h%1d>", lev);
|
|
333
|
+
padded = 0;
|
|
334
|
+
break;
|
|
335
|
+
case PLAIN:
|
|
336
|
+
pad(out, 1);
|
|
337
|
+
print_html_element_list(out, elt->children, obfuscate);
|
|
338
|
+
padded = 0;
|
|
339
|
+
break;
|
|
340
|
+
case PARA:
|
|
341
|
+
pad(out, 2);
|
|
342
|
+
g_string_append_printf(out, "<p>");
|
|
343
|
+
print_html_element_list(out, elt->children, obfuscate);
|
|
344
|
+
g_string_append_printf(out, "</p>");
|
|
345
|
+
padded = 0;
|
|
346
|
+
break;
|
|
347
|
+
case HRULE:
|
|
348
|
+
pad(out, 2);
|
|
349
|
+
g_string_append_printf(out, "<hr />");
|
|
350
|
+
padded = 0;
|
|
351
|
+
break;
|
|
352
|
+
case HTMLBLOCK:
|
|
353
|
+
pad(out, 2);
|
|
354
|
+
g_string_append_printf(out, "%s", elt->contents.str);
|
|
355
|
+
padded = 0;
|
|
356
|
+
break;
|
|
357
|
+
case VERBATIM:
|
|
358
|
+
pad(out, 2);
|
|
359
|
+
g_string_append_printf(out, "%s", "<pre><code>");
|
|
360
|
+
print_html_string(out, elt->contents.str, obfuscate);
|
|
361
|
+
g_string_append_printf(out, "%s", "</code></pre>");
|
|
362
|
+
padded = 0;
|
|
363
|
+
break;
|
|
364
|
+
case BULLETLIST:
|
|
365
|
+
pad(out, 2);
|
|
366
|
+
g_string_append_printf(out, "%s", "<ul>");
|
|
367
|
+
padded = 0;
|
|
368
|
+
print_html_element_list(out, elt->children, obfuscate);
|
|
369
|
+
pad(out, 1);
|
|
370
|
+
g_string_append_printf(out, "%s", "</ul>");
|
|
371
|
+
padded = 0;
|
|
372
|
+
break;
|
|
373
|
+
case ORDEREDLIST:
|
|
374
|
+
pad(out, 2);
|
|
375
|
+
g_string_append_printf(out, "%s", "<ol>");
|
|
376
|
+
padded = 0;
|
|
377
|
+
print_html_element_list(out, elt->children, obfuscate);
|
|
378
|
+
pad(out, 1);
|
|
379
|
+
g_string_append_printf(out, "</ol>");
|
|
380
|
+
padded = 0;
|
|
381
|
+
break;
|
|
382
|
+
case LISTITEM:
|
|
383
|
+
pad(out, 1);
|
|
384
|
+
g_string_append_printf(out, "<li>");
|
|
385
|
+
padded = 2;
|
|
386
|
+
print_html_element_list(out, elt->children, obfuscate);
|
|
387
|
+
g_string_append_printf(out, "</li>");
|
|
388
|
+
padded = 0;
|
|
389
|
+
break;
|
|
390
|
+
case BLOCKQUOTE:
|
|
391
|
+
pad(out, 2);
|
|
392
|
+
g_string_append_printf(out, "<blockquote>\n");
|
|
393
|
+
padded = 2;
|
|
394
|
+
print_html_element_list(out, elt->children, obfuscate);
|
|
395
|
+
pad(out, 1);
|
|
396
|
+
g_string_append_printf(out, "</blockquote>");
|
|
397
|
+
padded = 0;
|
|
398
|
+
break;
|
|
399
|
+
case REFERENCE:
|
|
400
|
+
/* Nonprinting */
|
|
401
|
+
break;
|
|
402
|
+
case NOTELABEL:
|
|
403
|
+
/* Nonprinting */
|
|
404
|
+
break;
|
|
405
|
+
case NOTE:
|
|
406
|
+
/* if contents.str == 0, then print note; else ignore, since this
|
|
407
|
+
* is a note block that has been incorporated into the notes list */
|
|
408
|
+
if (elt->contents.str == 0) {
|
|
409
|
+
if ( (elt->children->contents.str == 0) ){
|
|
410
|
+
/* The referenced note has not been used before */
|
|
411
|
+
add_endnote(elt->children);
|
|
412
|
+
++notenumber;
|
|
413
|
+
char buf[5];
|
|
414
|
+
sprintf(buf,"%d",notenumber);
|
|
415
|
+
/* Assign footnote number for future use */
|
|
416
|
+
elt->children->contents.str = strdup(buf);
|
|
417
|
+
if (elt->children->key == GLOSSARYTERM) {
|
|
418
|
+
g_string_append_printf(out, "<a href=\"#fn:%d\" id=\"fnref:%d\" title=\"see footnote\" class=\"footnote glossary\">[%d]</a>",
|
|
419
|
+
notenumber, notenumber, notenumber);
|
|
420
|
+
} else {
|
|
421
|
+
g_string_append_printf(out, "<a href=\"#fn:%d\" id=\"fnref:%d\" title=\"see footnote\" class=\"footnote\">[%d]</a>",
|
|
422
|
+
notenumber, notenumber, notenumber);
|
|
423
|
+
}
|
|
424
|
+
} else {
|
|
425
|
+
/* The referenced note has already been used */
|
|
426
|
+
g_string_append_printf(out, "<a href=\"#fn:%s\" title=\"see footnote\" class=\"footnote\">[%s]</a>",
|
|
427
|
+
elt->children->contents.str, elt->children->contents.str);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
elt->children = NULL;
|
|
431
|
+
break;
|
|
432
|
+
case GLOSSARY:
|
|
433
|
+
/* Shouldn't do anything */
|
|
434
|
+
break;
|
|
435
|
+
case GLOSSARYTERM:
|
|
436
|
+
g_string_append_printf(out,"<span class=\"glossary name\">");
|
|
437
|
+
print_html_string(out, elt->children->contents.str, obfuscate);
|
|
438
|
+
g_string_append_printf(out, "</span>");
|
|
439
|
+
if ((elt->next != NULL) && (elt->next->key == GLOSSARYSORTKEY) ) {
|
|
440
|
+
g_string_append_printf(out, "<span class=\"glossary sort\" style=\"display:none\">");
|
|
441
|
+
print_html_string(out, elt->next->contents.str, obfuscate);
|
|
442
|
+
g_string_append_printf(out, "</span>");
|
|
443
|
+
}
|
|
444
|
+
g_string_append_printf(out, ": ");
|
|
445
|
+
break;
|
|
446
|
+
case GLOSSARYSORTKEY:
|
|
447
|
+
break;
|
|
448
|
+
case NOCITATION:
|
|
449
|
+
case CITATION:
|
|
450
|
+
if ((elt->children != NULL) && (elt->children->key == LOCATOR)) {
|
|
451
|
+
GString *temp = g_string_new("");
|
|
452
|
+
print_html_element(temp,elt->children,obfuscate);
|
|
453
|
+
label = strdup(temp->str);
|
|
454
|
+
g_string_free(temp,true);
|
|
455
|
+
elt->children = elt->children->next;
|
|
456
|
+
} else {
|
|
457
|
+
label = NULL;
|
|
458
|
+
}
|
|
459
|
+
if (strncmp(elt->contents.str,"[#",2) == 0) {
|
|
460
|
+
/* reference specified externally */
|
|
461
|
+
if ( elt->key == NOCITATION ) {
|
|
462
|
+
g_string_append_printf(out, "<span class=\"notcited\" id=\"%s\"/>", elt->contents.str);
|
|
463
|
+
} else {
|
|
464
|
+
g_string_append_printf(out, "<span class=\"externalcitation\">");
|
|
465
|
+
if (label != NULL) g_string_append_printf(out, "[%s]", label);
|
|
466
|
+
g_string_append_printf(out, "%s",elt->contents.str);
|
|
467
|
+
g_string_append_printf(out, "</span>");
|
|
468
|
+
}
|
|
469
|
+
} else {
|
|
470
|
+
/* reference specified within the MMD document */
|
|
471
|
+
if (elt->children->contents.str == NULL) {
|
|
472
|
+
elt->children->key = CITATION;
|
|
473
|
+
add_endnote(elt->children);
|
|
474
|
+
++notenumber;
|
|
475
|
+
char buf[5];
|
|
476
|
+
sprintf(buf,"%d",notenumber);
|
|
477
|
+
|
|
478
|
+
elt->children->contents.str = strdup(buf);
|
|
479
|
+
}
|
|
480
|
+
if (label != NULL) {
|
|
481
|
+
if ( elt->key == NOCITATION ) {
|
|
482
|
+
g_string_append_printf(out, "<span class=\"notcited\" id=\"%s\">",
|
|
483
|
+
elt->children->contents.str);
|
|
484
|
+
} else {
|
|
485
|
+
g_string_append_printf(out, "<a class=\"citation\" href=\"#fn:%s\" title=\"Jump to citation\">[<span class=\"locator\">%s</span>, %s]",
|
|
486
|
+
elt->children->contents.str, label, elt->children->contents.str);
|
|
487
|
+
}
|
|
488
|
+
elt->children = NULL;
|
|
489
|
+
} else {
|
|
490
|
+
g_string_append_printf(out, "<a class=\"citation\" href=\"#fn:%s\" title=\"Jump to citation\">[%s]",
|
|
491
|
+
elt->children->contents.str, elt->children->contents.str);
|
|
492
|
+
elt->children = NULL;
|
|
493
|
+
}
|
|
494
|
+
g_string_append_printf(out, "<span class=\"citekey\" style=\"display:none\">%s</span>", elt->contents.str);
|
|
495
|
+
if (label != NULL) {
|
|
496
|
+
if ( elt->key == NOCITATION ) {
|
|
497
|
+
g_string_append_printf(out,"</span>");
|
|
498
|
+
} else {
|
|
499
|
+
g_string_append_printf(out,"</a>");
|
|
500
|
+
}
|
|
501
|
+
} else {
|
|
502
|
+
g_string_append_printf(out,"</a>");
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
free(label);
|
|
506
|
+
break;
|
|
507
|
+
case LOCATOR:
|
|
508
|
+
print_html_element_list(out, elt->children, obfuscate);
|
|
509
|
+
break;
|
|
510
|
+
case DEFLIST:
|
|
511
|
+
pad(out,1);
|
|
512
|
+
padded = 1;
|
|
513
|
+
g_string_append_printf(out, "<dl>\n");
|
|
514
|
+
print_html_element_list(out, elt->children, obfuscate);
|
|
515
|
+
g_string_append_printf(out, "</dl>\n");
|
|
516
|
+
padded = 0;
|
|
517
|
+
break;
|
|
518
|
+
case TERM:
|
|
519
|
+
pad(out,1);
|
|
520
|
+
g_string_append_printf(out, "<dt>");
|
|
521
|
+
print_html_string(out, elt->contents.str, obfuscate);
|
|
522
|
+
g_string_append_printf(out, "</dt>\n");
|
|
523
|
+
padded = 1;
|
|
524
|
+
break;
|
|
525
|
+
case DEFINITION:
|
|
526
|
+
pad(out,1);
|
|
527
|
+
padded = 1;
|
|
528
|
+
g_string_append_printf(out, "<dd>");
|
|
529
|
+
print_html_element_list(out, elt->children, obfuscate);
|
|
530
|
+
g_string_append_printf(out, "</dd>\n");
|
|
531
|
+
padded = 0;
|
|
532
|
+
break;
|
|
533
|
+
case METADATA:
|
|
534
|
+
/* Metadata is present, so this should be a "complete" document */
|
|
535
|
+
html_footer = is_html_complete_doc(elt);
|
|
536
|
+
if (html_footer) {
|
|
537
|
+
print_html_header(out, elt, obfuscate);
|
|
538
|
+
} else {
|
|
539
|
+
print_html_element_list(out, elt->children, obfuscate);
|
|
540
|
+
}
|
|
541
|
+
break;
|
|
542
|
+
case METAKEY:
|
|
543
|
+
if (strcmp(elt->contents.str, "title") == 0) {
|
|
544
|
+
g_string_append_printf(out, "\t<title>");
|
|
545
|
+
print_html_element(out, elt->children, obfuscate);
|
|
546
|
+
g_string_append_printf(out, "</title>\n");
|
|
547
|
+
} else if (strcmp(elt->contents.str, "css") == 0) {
|
|
548
|
+
g_string_append_printf(out, "\t<link type=\"text/css\" rel=\"stylesheet\" href=\"");
|
|
549
|
+
print_html_element(out, elt->children, obfuscate);
|
|
550
|
+
g_string_append_printf(out, "\"/>\n");
|
|
551
|
+
} else if (strcmp(elt->contents.str, "xhtmlheader") == 0) {
|
|
552
|
+
print_raw_element(out, elt->children);
|
|
553
|
+
g_string_append_printf(out, "\n");
|
|
554
|
+
} else if (strcmp(elt->contents.str, "htmlheader") == 0) {
|
|
555
|
+
print_raw_element(out, elt->children);
|
|
556
|
+
g_string_append_printf(out, "\n");
|
|
557
|
+
} else if (strcmp(elt->contents.str, "baseheaderlevel") == 0) {
|
|
558
|
+
base_header_level = atoi(elt->children->contents.str);
|
|
559
|
+
} else if (strcmp(elt->contents.str, "xhtmlheaderlevel") == 0) {
|
|
560
|
+
base_header_level = atoi(elt->children->contents.str);
|
|
561
|
+
} else if (strcmp(elt->contents.str, "htmlheaderlevel") == 0) {
|
|
562
|
+
base_header_level = atoi(elt->children->contents.str);
|
|
563
|
+
} else if (strcmp(elt->contents.str, "quoteslanguage") == 0) {
|
|
564
|
+
label = label_from_element_list(elt->children, 0);
|
|
565
|
+
if (strcmp(label, "dutch") == 0) { language = DUTCH; } else
|
|
566
|
+
if (strcmp(label, "german") == 0) { language = GERMAN; } else
|
|
567
|
+
if (strcmp(label, "germanguillemets") == 0) { language = GERMANGUILL; } else
|
|
568
|
+
if (strcmp(label, "french") == 0) { language = FRENCH; } else
|
|
569
|
+
if (strcmp(label, "swedish") == 0) { language = SWEDISH; }
|
|
570
|
+
free(label);
|
|
571
|
+
} else {
|
|
572
|
+
g_string_append_printf(out, "\t<meta name=\"");
|
|
573
|
+
print_html_string(out, elt->contents.str, obfuscate);
|
|
574
|
+
g_string_append_printf(out, "\" content=\"");
|
|
575
|
+
print_html_element(out, elt->children, obfuscate);
|
|
576
|
+
g_string_append_printf(out, "\"/>\n");
|
|
577
|
+
}
|
|
578
|
+
break;
|
|
579
|
+
case METAVALUE:
|
|
580
|
+
print_html_string(out, elt->contents.str, obfuscate);
|
|
581
|
+
break;
|
|
582
|
+
case FOOTER:
|
|
583
|
+
break;
|
|
584
|
+
case HEADINGSECTION:
|
|
585
|
+
print_html_element_list(out, elt->children, obfuscate);
|
|
586
|
+
break;
|
|
587
|
+
case TABLE:
|
|
588
|
+
g_string_append_printf(out, "\n\n<table>\n");
|
|
589
|
+
print_html_element_list(out, elt->children, obfuscate);
|
|
590
|
+
g_string_append_printf(out, "</table>\n");
|
|
591
|
+
break;
|
|
592
|
+
case TABLESEPARATOR:
|
|
593
|
+
table_alignment = elt->contents.str;
|
|
594
|
+
break;
|
|
595
|
+
case TABLECAPTION:
|
|
596
|
+
if (elt->children->key == TABLELABEL) {
|
|
597
|
+
label = label_from_element_list(elt->children->children,obfuscate);
|
|
598
|
+
} else {
|
|
599
|
+
label = label_from_element_list(elt->children,obfuscate);
|
|
600
|
+
}
|
|
601
|
+
g_string_append_printf(out, "<caption id=\"%s\">", label);
|
|
602
|
+
print_html_element_list(out, elt->children, obfuscate);
|
|
603
|
+
g_string_append_printf(out, "</caption>\n");
|
|
604
|
+
free(label);
|
|
605
|
+
break;
|
|
606
|
+
case TABLELABEL:
|
|
607
|
+
break;
|
|
608
|
+
case TABLEHEAD:
|
|
609
|
+
/* print column alignment for XSLT processing if needed */
|
|
610
|
+
g_string_append_printf(out, "<colgroup>\n");
|
|
611
|
+
for (table_column=0;table_column<strlen(table_alignment);table_column++) {
|
|
612
|
+
if ( strncmp(&table_alignment[table_column],"r",1) == 0) {
|
|
613
|
+
g_string_append_printf(out, "<col style=\"text-align:right;\"/>\n");
|
|
614
|
+
} else if ( strncmp(&table_alignment[table_column],"c",1) == 0) {
|
|
615
|
+
g_string_append_printf(out, "<col style=\"text-align:center;\"/>\n");
|
|
616
|
+
} else {
|
|
617
|
+
g_string_append_printf(out, "<col style=\"text-align:left;\"/>\n");
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
g_string_append_printf(out, "</colgroup>\n");
|
|
621
|
+
cell_type = 'h';
|
|
622
|
+
g_string_append_printf(out, "\n<thead>\n");
|
|
623
|
+
print_html_element_list(out, elt->children, obfuscate);
|
|
624
|
+
g_string_append_printf(out, "</thead>\n");
|
|
625
|
+
cell_type = 'd';
|
|
626
|
+
break;
|
|
627
|
+
case TABLEBODY:
|
|
628
|
+
g_string_append_printf(out, "\n<tbody>\n");
|
|
629
|
+
print_html_element_list(out, elt->children, obfuscate);
|
|
630
|
+
g_string_append_printf(out, "</tbody>\n");
|
|
631
|
+
break;
|
|
632
|
+
case TABLEROW:
|
|
633
|
+
g_string_append_printf(out, "<tr>\n");
|
|
634
|
+
table_column = 0;
|
|
635
|
+
print_html_element_list(out, elt->children, obfuscate);
|
|
636
|
+
g_string_append_printf(out, "</tr>\n");
|
|
637
|
+
break;
|
|
638
|
+
case TABLECELL:
|
|
639
|
+
if ( strncmp(&table_alignment[table_column],"r",1) == 0) {
|
|
640
|
+
g_string_append_printf(out, "\t<t%c style=\"text-align:right;\"", cell_type);
|
|
641
|
+
} else if ( strncmp(&table_alignment[table_column],"c",1) == 0) {
|
|
642
|
+
g_string_append_printf(out, "\t<t%c style=\"text-align:center;\"", cell_type);
|
|
643
|
+
} else {
|
|
644
|
+
g_string_append_printf(out, "\t<t%c style=\"text-align:left;\"", cell_type);
|
|
645
|
+
}
|
|
646
|
+
if ((elt->children != NULL) && (elt->children->key == CELLSPAN)) {
|
|
647
|
+
g_string_append_printf(out, " colspan=\"%d\"",(int)strlen(elt->children->contents.str)+1);
|
|
648
|
+
}
|
|
649
|
+
g_string_append_printf(out, ">");
|
|
650
|
+
padded = 2;
|
|
651
|
+
print_html_element_list(out, elt->children, obfuscate);
|
|
652
|
+
g_string_append_printf(out, "</t%c>\n", cell_type);
|
|
653
|
+
table_column++;
|
|
654
|
+
break;
|
|
655
|
+
case CELLSPAN:
|
|
656
|
+
break;
|
|
657
|
+
case ATTRKEY:
|
|
658
|
+
if ( (strcmp(elt->contents.str,"height") == 0) ||
|
|
659
|
+
(strcmp(elt->contents.str, "width") == 0)) {
|
|
660
|
+
} else {
|
|
661
|
+
g_string_append_printf(out, " %s=\"%s\"", elt->contents.str,
|
|
662
|
+
elt->children->contents.str);
|
|
663
|
+
}
|
|
664
|
+
break;
|
|
665
|
+
case MATHSPAN:
|
|
666
|
+
if ( elt->contents.str[strlen(elt->contents.str)-1] == ']') {
|
|
667
|
+
elt->contents.str[strlen(elt->contents.str)-3] = '\0';
|
|
668
|
+
g_string_append_printf(out, "<span class=\"math\">%s\\]</span>", elt->contents.str);
|
|
669
|
+
} else {
|
|
670
|
+
elt->contents.str[strlen(elt->contents.str)-3] = '\0';
|
|
671
|
+
g_string_append_printf(out, "<span class=\"math\">%s\\)</span>", elt->contents.str);
|
|
672
|
+
}
|
|
673
|
+
break;
|
|
674
|
+
default:
|
|
675
|
+
fprintf(stderr, "print_html_element encountered unknown element key = %d\n", elt->key);
|
|
676
|
+
exit(EXIT_FAILURE);
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
static void print_html_endnotes(GString *out) {
|
|
681
|
+
int counter = 0;
|
|
682
|
+
GSList *note;
|
|
683
|
+
element *note_elt;
|
|
684
|
+
if (endnotes == NULL)
|
|
685
|
+
return;
|
|
686
|
+
note = g_slist_reverse(endnotes);
|
|
687
|
+
g_string_append_printf(out, "<div class=\"footnotes\">\n<hr />\n<ol>");
|
|
688
|
+
while (note != NULL) {
|
|
689
|
+
note_elt = note->data;
|
|
690
|
+
counter++;
|
|
691
|
+
pad(out, 1);
|
|
692
|
+
if (note_elt->key == CITATION) {
|
|
693
|
+
g_string_append_printf(out, "<li id=\"fn:%s\" class=\"citation\"><span class=\"citekey\" style=\"display:none\">", note_elt->contents.str);
|
|
694
|
+
element *temp = note_elt;
|
|
695
|
+
while ( temp != NULL ) {
|
|
696
|
+
if (temp->key == NOTELABEL)
|
|
697
|
+
print_html_string(out, temp->contents.str, 0);
|
|
698
|
+
temp = temp->next;
|
|
699
|
+
}
|
|
700
|
+
g_string_append_printf(out, "</span>");
|
|
701
|
+
padded = 2;
|
|
702
|
+
print_html_element_list(out, note_elt->children, false);
|
|
703
|
+
pad(out, 1);
|
|
704
|
+
g_string_append_printf(out, "</li>");
|
|
705
|
+
} else {
|
|
706
|
+
g_string_append_printf(out, "<li id=\"fn:%d\">\n", counter);
|
|
707
|
+
padded = 2;
|
|
708
|
+
print_html_element_list(out, note_elt, false);
|
|
709
|
+
g_string_append_printf(out, " <a href=\"#fnref:%d\" title=\"return to article\" class=\"reversefootnote\"> ↩</a>", counter);
|
|
710
|
+
pad(out, 1);
|
|
711
|
+
g_string_append_printf(out, "</li>");
|
|
712
|
+
}
|
|
713
|
+
note = note->next;
|
|
714
|
+
}
|
|
715
|
+
pad(out, 1);
|
|
716
|
+
g_string_append_printf(out, "</ol>\n</div>\n");
|
|
717
|
+
|
|
718
|
+
g_slist_free(endnotes);
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
/**********************************************************************
|
|
722
|
+
|
|
723
|
+
Functions for printing Elements as LaTeX
|
|
724
|
+
|
|
725
|
+
***********************************************************************/
|
|
726
|
+
|
|
727
|
+
/* print_latex_string - print string, escaping for LaTeX */
|
|
728
|
+
static void print_latex_string(GString *out, char *str) {
|
|
729
|
+
char *tmp;
|
|
730
|
+
while (*str != '\0') {
|
|
731
|
+
switch (*str) {
|
|
732
|
+
case '{': case '}': case '$': case '%':
|
|
733
|
+
case '&': case '_': case '#':
|
|
734
|
+
g_string_append_printf(out, "\\%c", *str);
|
|
735
|
+
break;
|
|
736
|
+
case '^':
|
|
737
|
+
g_string_append_printf(out, "\\^{}");
|
|
738
|
+
break;
|
|
739
|
+
case '\\':
|
|
740
|
+
g_string_append_printf(out, "$\\backslash$");
|
|
741
|
+
break;
|
|
742
|
+
case '~':
|
|
743
|
+
g_string_append_printf(out, "\\ensuremath{\\sim}");
|
|
744
|
+
break;
|
|
745
|
+
case '|':
|
|
746
|
+
g_string_append_printf(out, "\\textbar{}");
|
|
747
|
+
break;
|
|
748
|
+
case '<':
|
|
749
|
+
g_string_append_printf(out, "$<$");
|
|
750
|
+
break;
|
|
751
|
+
case '>':
|
|
752
|
+
g_string_append_printf(out, "$>$");
|
|
753
|
+
break;
|
|
754
|
+
case '/':
|
|
755
|
+
str++;
|
|
756
|
+
while (*str == '/') {
|
|
757
|
+
g_string_append_printf(out, "/");
|
|
758
|
+
str++;
|
|
759
|
+
}
|
|
760
|
+
g_string_append_printf(out, "\\slash ");
|
|
761
|
+
str--;
|
|
762
|
+
break;
|
|
763
|
+
case '\n':
|
|
764
|
+
tmp = str;
|
|
765
|
+
tmp--;
|
|
766
|
+
if (*tmp == ' ') {
|
|
767
|
+
tmp--;
|
|
768
|
+
if (*tmp == ' ') {
|
|
769
|
+
g_string_append_printf(out, "\\\\\n");
|
|
770
|
+
} else {
|
|
771
|
+
g_string_append_printf(out, "\n");
|
|
772
|
+
}
|
|
773
|
+
} else {
|
|
774
|
+
g_string_append_printf(out, "\n");
|
|
775
|
+
}
|
|
776
|
+
break;
|
|
777
|
+
default:
|
|
778
|
+
g_string_append_c(out, *str);
|
|
779
|
+
}
|
|
780
|
+
str++;
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
static void print_latex_endnotes(GString *out) {
|
|
785
|
+
GSList *note;
|
|
786
|
+
element *note_elt;
|
|
787
|
+
if (endnotes == NULL)
|
|
788
|
+
return;
|
|
789
|
+
note = g_slist_reverse(endnotes);
|
|
790
|
+
pad(out,2);
|
|
791
|
+
g_string_append_printf(out, "\\begin{thebibliography}{0}");
|
|
792
|
+
while (note != NULL) {
|
|
793
|
+
note_elt = note->data;
|
|
794
|
+
pad(out, 1);
|
|
795
|
+
g_string_append_printf(out, "\\bibitem{%s}\n", note_elt->contents.str);
|
|
796
|
+
padded=2;
|
|
797
|
+
print_latex_element_list(out, note_elt);
|
|
798
|
+
pad(out, 1);
|
|
799
|
+
note = note->next;
|
|
800
|
+
}
|
|
801
|
+
pad(out, 1);
|
|
802
|
+
g_string_append_printf(out, "\\end{thebibliography}\n");
|
|
803
|
+
padded = 1;
|
|
804
|
+
g_slist_free(endnotes);
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
/* print_latex_element_list - print a list of elements as LaTeX */
|
|
808
|
+
static void print_latex_element_list(GString *out, element *list) {
|
|
809
|
+
while (list != NULL) {
|
|
810
|
+
print_latex_element(out, list);
|
|
811
|
+
list = list->next;
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
/* print_latex_element - print an element as LaTeX */
|
|
816
|
+
static void print_latex_element(GString *out, element *elt) {
|
|
817
|
+
int lev;
|
|
818
|
+
char *label;
|
|
819
|
+
char *height;
|
|
820
|
+
char *width;
|
|
821
|
+
double floatnum;
|
|
822
|
+
switch (elt->key) {
|
|
823
|
+
case SPACE:
|
|
824
|
+
g_string_append_printf(out, "%s", elt->contents.str);
|
|
825
|
+
break;
|
|
826
|
+
case LINEBREAK:
|
|
827
|
+
g_string_append_printf(out, "\\\\\n");
|
|
828
|
+
break;
|
|
829
|
+
case STR:
|
|
830
|
+
print_latex_string(out, elt->contents.str);
|
|
831
|
+
break;
|
|
832
|
+
case ELLIPSIS:
|
|
833
|
+
localize_typography(out, ELLIP, language, LATEXOUT);
|
|
834
|
+
break;
|
|
835
|
+
case EMDASH:
|
|
836
|
+
localize_typography(out, MDASH, language, LATEXOUT);
|
|
837
|
+
break;
|
|
838
|
+
case ENDASH:
|
|
839
|
+
localize_typography(out, NDASH, language, LATEXOUT);
|
|
840
|
+
break;
|
|
841
|
+
case APOSTROPHE:
|
|
842
|
+
localize_typography(out, APOS, language, LATEXOUT);
|
|
843
|
+
break;
|
|
844
|
+
case SINGLEQUOTED:
|
|
845
|
+
localize_typography(out, LSQUOTE, language, LATEXOUT);
|
|
846
|
+
print_latex_element_list(out, elt->children);
|
|
847
|
+
localize_typography(out, RSQUOTE, language, LATEXOUT);
|
|
848
|
+
break;
|
|
849
|
+
case DOUBLEQUOTED:
|
|
850
|
+
localize_typography(out, LDQUOTE, language, LATEXOUT);
|
|
851
|
+
print_latex_element_list(out, elt->children);
|
|
852
|
+
localize_typography(out, RDQUOTE, language, LATEXOUT);
|
|
853
|
+
break;
|
|
854
|
+
case CODE:
|
|
855
|
+
g_string_append_printf(out, "\\texttt{");
|
|
856
|
+
print_latex_string(out, elt->contents.str);
|
|
857
|
+
g_string_append_printf(out, "}");
|
|
858
|
+
break;
|
|
859
|
+
case HTML:
|
|
860
|
+
/* don't print HTML */
|
|
861
|
+
/* but do print HTML comments for raw LaTeX */
|
|
862
|
+
if (strncmp(elt->contents.str,"<!--",4) == 0) {
|
|
863
|
+
/* trim "-->" from end */
|
|
864
|
+
elt->contents.str[strlen(elt->contents.str)-3] = '\0';
|
|
865
|
+
g_string_append_printf(out, "%s", &elt->contents.str[4]);
|
|
866
|
+
}
|
|
867
|
+
break;
|
|
868
|
+
case LINK:
|
|
869
|
+
if (elt->contents.link->url[0] == '#') {
|
|
870
|
+
/* This is a link to anchor within document */
|
|
871
|
+
label = label_from_string(elt->contents.link->url,0);
|
|
872
|
+
if (elt->contents.link->label != NULL) {
|
|
873
|
+
print_latex_element_list(out, elt->contents.link->label);
|
|
874
|
+
g_string_append_printf(out, " (\\autoref\{%s})", label);
|
|
875
|
+
} else {
|
|
876
|
+
g_string_append_printf(out, "\\autoref\{%s}", label);
|
|
877
|
+
}
|
|
878
|
+
free(label);
|
|
879
|
+
} else if ( (elt->contents.link->label != NULL) &&
|
|
880
|
+
( elt->contents.link->label->contents.str != NULL) &&
|
|
881
|
+
( strcmp(elt->contents.link->label->contents.str,
|
|
882
|
+
elt->contents.link->url) == 0 )) {
|
|
883
|
+
/* This is a <link> */
|
|
884
|
+
g_string_append_printf(out, "\\href{%s}{", elt->contents.link->url);
|
|
885
|
+
print_latex_string(out, elt->contents.link->url);
|
|
886
|
+
g_string_append_printf(out, "}");
|
|
887
|
+
} else if ( (elt->contents.link->label != NULL) &&
|
|
888
|
+
( elt->contents.link->label->contents.str != NULL) &&
|
|
889
|
+
( strcmp(&elt->contents.link->url[7],
|
|
890
|
+
elt->contents.link->label->contents.str) == 0 )) {
|
|
891
|
+
/* This is a <mailto> */
|
|
892
|
+
g_string_append_printf(out, "\\href{%s}{%s}", elt->contents.link->url, &elt->contents.link->url[7]);
|
|
893
|
+
} else {
|
|
894
|
+
/* This is a [text](link) */
|
|
895
|
+
g_string_append_printf(out, "\\href{%s}{", elt->contents.link->url);
|
|
896
|
+
print_latex_element_list(out, elt->contents.link->label);
|
|
897
|
+
g_string_append_printf(out, "}");
|
|
898
|
+
if ( no_latex_footnote == FALSE ) {
|
|
899
|
+
g_string_append_printf(out, "\\footnote{\\href{%s}{", elt->contents.link->url);
|
|
900
|
+
print_latex_string(out, elt->contents.link->url);
|
|
901
|
+
g_string_append_printf(out, "}}");
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
break;
|
|
905
|
+
case IMAGEBLOCK:
|
|
906
|
+
pad(out, 2);
|
|
907
|
+
case IMAGE:
|
|
908
|
+
/* Figure if we have height, width, neither */
|
|
909
|
+
height = dimension_for_attribute("height", elt->contents.link->attr);
|
|
910
|
+
width = dimension_for_attribute("width", elt->contents.link->attr);
|
|
911
|
+
if (elt->key == IMAGEBLOCK) {
|
|
912
|
+
g_string_append_printf(out, "\\begin{figure}[htbp]\n\\centering\n");
|
|
913
|
+
}
|
|
914
|
+
g_string_append_printf(out, "\\includegraphics[");
|
|
915
|
+
if ((height == NULL) && (width == NULL)) {
|
|
916
|
+
/* No dimensions given */
|
|
917
|
+
g_string_append_printf(out,"keepaspectratio,width=\\textwidth,height=0.75\\textheight");
|
|
918
|
+
} else {
|
|
919
|
+
/* at least one dimension given */
|
|
920
|
+
if ((height != NULL) && (width != NULL)) {
|
|
921
|
+
|
|
922
|
+
} else {
|
|
923
|
+
g_string_append_printf(out, "keepaspectratio,");
|
|
924
|
+
}
|
|
925
|
+
if (width != NULL) {
|
|
926
|
+
if (width[strlen(width)-1] == '%') {
|
|
927
|
+
width[strlen(width)-1] = '\0';
|
|
928
|
+
floatnum = strtod(width, NULL);
|
|
929
|
+
floatnum = floatnum/100;
|
|
930
|
+
g_string_append_printf(out,"width=%.4f\\textwidth,", floatnum);
|
|
931
|
+
} else {
|
|
932
|
+
g_string_append_printf(out,"width=%s,", width);
|
|
933
|
+
}
|
|
934
|
+
} else {
|
|
935
|
+
g_string_append_printf(out, "width=\\textwidth,");
|
|
936
|
+
}
|
|
937
|
+
if (height != NULL) {
|
|
938
|
+
if (height[strlen(height)-1] == '%') {
|
|
939
|
+
height[strlen(height)-1] = '\0';
|
|
940
|
+
floatnum = strtod(height, NULL);
|
|
941
|
+
floatnum = floatnum/100;
|
|
942
|
+
g_string_append_printf(out,"height=%.4f\\textheight,", floatnum);
|
|
943
|
+
} else {
|
|
944
|
+
g_string_append_printf(out,"height=%s",height);
|
|
945
|
+
}
|
|
946
|
+
} else {
|
|
947
|
+
g_string_append_printf(out, "height=0.75\\textheight");
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
|
|
951
|
+
g_string_append_printf(out, "]{%s}\n", elt->contents.link->url);
|
|
952
|
+
if (elt->key == IMAGEBLOCK) {
|
|
953
|
+
if (elt->contents.link->label != NULL) {
|
|
954
|
+
g_string_append_printf(out, "\\caption{");
|
|
955
|
+
print_latex_element_list(out, elt->contents.link->label);
|
|
956
|
+
g_string_append_printf(out, "}\n");
|
|
957
|
+
}
|
|
958
|
+
g_string_append_printf(out, "\\label{%s}\n", elt->contents.link->identifier);
|
|
959
|
+
g_string_append_printf(out,"\\end{figure}\n");
|
|
960
|
+
}
|
|
961
|
+
free(height);
|
|
962
|
+
free(width);
|
|
963
|
+
break;
|
|
964
|
+
case EMPH:
|
|
965
|
+
g_string_append_printf(out, "\\emph{");
|
|
966
|
+
print_latex_element_list(out, elt->children);
|
|
967
|
+
g_string_append_printf(out, "}");
|
|
968
|
+
break;
|
|
969
|
+
case STRONG:
|
|
970
|
+
g_string_append_printf(out, "\\textbf{");
|
|
971
|
+
print_latex_element_list(out, elt->children);
|
|
972
|
+
g_string_append_printf(out, "}");
|
|
973
|
+
break;
|
|
974
|
+
case LIST:
|
|
975
|
+
print_latex_element_list(out, elt->children);
|
|
976
|
+
break;
|
|
977
|
+
case RAW:
|
|
978
|
+
/* Shouldn't occur - these are handled by process_raw_blocks() */
|
|
979
|
+
assert(elt->key != RAW);
|
|
980
|
+
break;
|
|
981
|
+
case H1: case H2: case H3: case H4: case H5: case H6:
|
|
982
|
+
pad(out, 2);
|
|
983
|
+
lev = elt->key - H1 + base_header_level; /* assumes H1 ... H6 are in order */
|
|
984
|
+
switch (lev) {
|
|
985
|
+
case 1:
|
|
986
|
+
g_string_append_printf(out, "\\part{");
|
|
987
|
+
break;
|
|
988
|
+
case 2:
|
|
989
|
+
g_string_append_printf(out, "\\chapter{");
|
|
990
|
+
break;
|
|
991
|
+
case 3:
|
|
992
|
+
g_string_append_printf(out, "\\section{");
|
|
993
|
+
break;
|
|
994
|
+
case 4:
|
|
995
|
+
g_string_append_printf(out, "\\subsection{");
|
|
996
|
+
break;
|
|
997
|
+
case 5:
|
|
998
|
+
g_string_append_printf(out, "\\subsubsection{");
|
|
999
|
+
break;
|
|
1000
|
+
case 6:
|
|
1001
|
+
g_string_append_printf(out, "\\paragraph{");
|
|
1002
|
+
break;
|
|
1003
|
+
case 7:
|
|
1004
|
+
g_string_append_printf(out, "\\subparagraph{");
|
|
1005
|
+
break;
|
|
1006
|
+
default:
|
|
1007
|
+
g_string_append_printf(out, "\\noindent\\textbf{");
|
|
1008
|
+
break;
|
|
1009
|
+
}
|
|
1010
|
+
/* generate a label for each header (MMD);
|
|
1011
|
+
don't allow footnotes since invalid here */
|
|
1012
|
+
no_latex_footnote = TRUE;
|
|
1013
|
+
if (elt->children->key == AUTOLABEL) {
|
|
1014
|
+
label = label_from_string(elt->children->contents.str,0);
|
|
1015
|
+
print_latex_element_list(out, elt->children->next);
|
|
1016
|
+
} else {
|
|
1017
|
+
label = label_from_element_list(elt->children,0);
|
|
1018
|
+
print_latex_element_list(out, elt->children);
|
|
1019
|
+
}
|
|
1020
|
+
no_latex_footnote = FALSE;
|
|
1021
|
+
g_string_append_printf(out, "}\n\\label{");
|
|
1022
|
+
g_string_append_printf(out, "%s", label);
|
|
1023
|
+
g_string_append_printf(out, "}\n");
|
|
1024
|
+
free(label);
|
|
1025
|
+
padded = 1;
|
|
1026
|
+
break;
|
|
1027
|
+
case PLAIN:
|
|
1028
|
+
pad(out, 1);
|
|
1029
|
+
print_latex_element_list(out, elt->children);
|
|
1030
|
+
padded = 0;
|
|
1031
|
+
break;
|
|
1032
|
+
case PARA:
|
|
1033
|
+
pad(out, 2);
|
|
1034
|
+
print_latex_element_list(out, elt->children);
|
|
1035
|
+
padded = 0;
|
|
1036
|
+
break;
|
|
1037
|
+
case HRULE:
|
|
1038
|
+
pad(out, 2);
|
|
1039
|
+
g_string_append_printf(out, "\\begin{center}\\rule{3in}{0.4pt}\\end{center}\n");
|
|
1040
|
+
padded = 0;
|
|
1041
|
+
break;
|
|
1042
|
+
case HTMLBLOCK:
|
|
1043
|
+
/* don't print HTML block */
|
|
1044
|
+
/* but do print HTML comments for raw LaTeX */
|
|
1045
|
+
if (strncmp(elt->contents.str,"<!--",4) == 0) {
|
|
1046
|
+
pad(out, 2);
|
|
1047
|
+
/* trim "-->" from end */
|
|
1048
|
+
elt->contents.str[strlen(elt->contents.str)-3] = '\0';
|
|
1049
|
+
g_string_append_printf(out, "%s", &elt->contents.str[4]);
|
|
1050
|
+
padded = 0;
|
|
1051
|
+
}
|
|
1052
|
+
break;
|
|
1053
|
+
case VERBATIM:
|
|
1054
|
+
pad(out, 1);
|
|
1055
|
+
g_string_append_printf(out, "\n\\begin{verbatim}\n");
|
|
1056
|
+
print_raw_element(out, elt);
|
|
1057
|
+
g_string_append_printf(out, "\\end{verbatim}\n");
|
|
1058
|
+
padded = 0;
|
|
1059
|
+
break;
|
|
1060
|
+
case BULLETLIST:
|
|
1061
|
+
pad(out, 1);
|
|
1062
|
+
g_string_append_printf(out, "\n\\begin{itemize}");
|
|
1063
|
+
padded = 0;
|
|
1064
|
+
print_latex_element_list(out, elt->children);
|
|
1065
|
+
g_string_append_printf(out, "\n\\end{itemize}");
|
|
1066
|
+
padded = 0;
|
|
1067
|
+
break;
|
|
1068
|
+
case ORDEREDLIST:
|
|
1069
|
+
pad(out, 2);
|
|
1070
|
+
g_string_append_printf(out, "\\begin{enumerate}");
|
|
1071
|
+
padded = 0;
|
|
1072
|
+
print_latex_element_list(out, elt->children);
|
|
1073
|
+
pad(out, 1);
|
|
1074
|
+
g_string_append_printf(out, "\\end{enumerate}");
|
|
1075
|
+
padded = 0;
|
|
1076
|
+
break;
|
|
1077
|
+
case LISTITEM:
|
|
1078
|
+
pad(out, 1);
|
|
1079
|
+
g_string_append_printf(out, "\\item ");
|
|
1080
|
+
padded = 2;
|
|
1081
|
+
print_latex_element_list(out, elt->children);
|
|
1082
|
+
g_string_append_printf(out, "\n");
|
|
1083
|
+
break;
|
|
1084
|
+
case BLOCKQUOTE:
|
|
1085
|
+
pad(out, 2);
|
|
1086
|
+
g_string_append_printf(out, "\\begin{quote}");
|
|
1087
|
+
padded = 0;
|
|
1088
|
+
print_latex_element_list(out, elt->children);
|
|
1089
|
+
pad(out, 1);
|
|
1090
|
+
g_string_append_printf(out, "\\end{quote}");
|
|
1091
|
+
padded = 0;
|
|
1092
|
+
break;
|
|
1093
|
+
case NOTELABEL:
|
|
1094
|
+
/* Nonprinting */
|
|
1095
|
+
break;
|
|
1096
|
+
case NOTE:
|
|
1097
|
+
/* if contents.str == 0, then print note; else ignore, since this
|
|
1098
|
+
* is a note block that has been incorporated into the notes list */
|
|
1099
|
+
if (elt->contents.str == 0) {
|
|
1100
|
+
if (elt->children->key == GLOSSARYTERM) {
|
|
1101
|
+
g_string_append_printf(out, "\\newglossaryentry{%s}{", elt->children->children->contents.str);
|
|
1102
|
+
padded = 2;
|
|
1103
|
+
if (elt->children->next->key == GLOSSARYSORTKEY) {
|
|
1104
|
+
g_string_append_printf(out, "sort={");
|
|
1105
|
+
print_latex_string(out, elt->children->next->contents.str);
|
|
1106
|
+
g_string_append_printf(out, "},");
|
|
1107
|
+
}
|
|
1108
|
+
print_latex_element_list(out, elt->children);
|
|
1109
|
+
g_string_append_printf(out, "}}\\glsadd{%s}", elt->children->children->contents.str);
|
|
1110
|
+
padded = 0;
|
|
1111
|
+
} else {
|
|
1112
|
+
g_string_append_printf(out, "\\footnote{");
|
|
1113
|
+
padded = 2;
|
|
1114
|
+
print_latex_element_list(out, elt->children);
|
|
1115
|
+
g_string_append_printf(out, "}");
|
|
1116
|
+
padded = 0;
|
|
1117
|
+
}
|
|
1118
|
+
elt->children = NULL;
|
|
1119
|
+
}
|
|
1120
|
+
break;
|
|
1121
|
+
case GLOSSARY:
|
|
1122
|
+
/* This shouldn't do anything */
|
|
1123
|
+
break;
|
|
1124
|
+
case GLOSSARYTERM:
|
|
1125
|
+
g_string_append_printf(out, "name={");
|
|
1126
|
+
print_latex_string(out, elt->children->contents.str);
|
|
1127
|
+
g_string_append_printf(out, "},description={");
|
|
1128
|
+
break;
|
|
1129
|
+
case GLOSSARYSORTKEY:
|
|
1130
|
+
break;
|
|
1131
|
+
case REFERENCE:
|
|
1132
|
+
/* Nonprinting */
|
|
1133
|
+
break;
|
|
1134
|
+
case NOCITATION:
|
|
1135
|
+
case CITATION:
|
|
1136
|
+
if (strncmp(elt->contents.str,"[#",2) == 0) {
|
|
1137
|
+
/* This should be used as a bibtex citation key after trimming */
|
|
1138
|
+
elt->contents.str[strlen(elt->contents.str)-1] = '\0';
|
|
1139
|
+
if (elt->key == NOCITATION ) {
|
|
1140
|
+
g_string_append_printf(out, "~\\nocite{%s}", &elt->contents.str[2]);
|
|
1141
|
+
} else {
|
|
1142
|
+
if ((elt->children != NULL) && (elt->children->key == LOCATOR)) {
|
|
1143
|
+
if (strcmp(&elt->contents.str[strlen(elt->contents.str) - 1],";") == 0) {
|
|
1144
|
+
g_string_append_printf(out, " \\citet[");
|
|
1145
|
+
elt->contents.str[strlen(elt->contents.str) - 1] = '\0';
|
|
1146
|
+
} else {
|
|
1147
|
+
g_string_append_printf(out, "~\\citep[");
|
|
1148
|
+
}
|
|
1149
|
+
print_latex_element(out,elt->children);
|
|
1150
|
+
g_string_append_printf(out, "]{%s}",&elt->contents.str[2]);
|
|
1151
|
+
} else {
|
|
1152
|
+
if (strcmp(&elt->contents.str[strlen(elt->contents.str) - 1],";") == 0) {
|
|
1153
|
+
elt->contents.str[strlen(elt->contents.str) - 1] = '\0';
|
|
1154
|
+
g_string_append_printf(out, " \\citet{%s}", &elt->contents.str[2]);
|
|
1155
|
+
} else {
|
|
1156
|
+
g_string_append_printf(out, "~\\citep{%s}", &elt->contents.str[2]);
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
} else {
|
|
1161
|
+
/* This citation was specified in the document itself */
|
|
1162
|
+
if (elt->key == NOCITATION ) {
|
|
1163
|
+
g_string_append_printf(out, "~\\nocite{%s}", elt->contents.str);
|
|
1164
|
+
element *temp;
|
|
1165
|
+
temp = elt->children;
|
|
1166
|
+
elt->children = temp->next;
|
|
1167
|
+
free_element(temp);
|
|
1168
|
+
} else {
|
|
1169
|
+
if ((elt->children != NULL) && (elt->children->key == LOCATOR)){
|
|
1170
|
+
if (strcmp(&elt->contents.str[strlen(elt->contents.str) - 1],";") == 0) {
|
|
1171
|
+
g_string_append_printf(out, " \\citet[");
|
|
1172
|
+
elt->contents.str[strlen(elt->contents.str) - 1] = '\0';
|
|
1173
|
+
} else {
|
|
1174
|
+
g_string_append_printf(out, "~\\citep[");
|
|
1175
|
+
}
|
|
1176
|
+
print_latex_element(out,elt->children);
|
|
1177
|
+
g_string_append_printf(out, "]{%s}",elt->contents.str);
|
|
1178
|
+
element *temp;
|
|
1179
|
+
temp = elt->children;
|
|
1180
|
+
elt->children = temp->next;
|
|
1181
|
+
free_element(temp);
|
|
1182
|
+
} else {
|
|
1183
|
+
if (strcmp(&elt->contents.str[strlen(elt->contents.str) - 1],";") == 0) {
|
|
1184
|
+
elt->contents.str[strlen(elt->contents.str) - 1] = '\0';
|
|
1185
|
+
g_string_append_printf(out, " \\citet{%s}", elt->contents.str);
|
|
1186
|
+
} else {
|
|
1187
|
+
g_string_append_printf(out, "~\\citep{%s}", elt->contents.str);
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
if (elt->children->contents.str == NULL) {
|
|
1192
|
+
elt->children->contents.str = strdup(elt->contents.str);
|
|
1193
|
+
add_endnote(elt->children);
|
|
1194
|
+
}
|
|
1195
|
+
elt->children = NULL;
|
|
1196
|
+
}
|
|
1197
|
+
break;
|
|
1198
|
+
case LOCATOR:
|
|
1199
|
+
print_latex_element_list(out, elt->children);
|
|
1200
|
+
break;
|
|
1201
|
+
case DEFLIST:
|
|
1202
|
+
g_string_append_printf(out, "\\begin{description}");
|
|
1203
|
+
padded = 0;
|
|
1204
|
+
print_latex_element_list(out, elt->children);
|
|
1205
|
+
pad(out,1);
|
|
1206
|
+
g_string_append_printf(out, "\\end{description}");
|
|
1207
|
+
padded = 0;
|
|
1208
|
+
break;
|
|
1209
|
+
case TERM:
|
|
1210
|
+
pad(out,2);
|
|
1211
|
+
g_string_append_printf(out, "\\item[%s]", elt->contents.str);
|
|
1212
|
+
padded = 0;
|
|
1213
|
+
break;
|
|
1214
|
+
case DEFINITION:
|
|
1215
|
+
pad(out,2);
|
|
1216
|
+
padded = 2;
|
|
1217
|
+
print_latex_element_list(out, elt->children);
|
|
1218
|
+
padded = 0;
|
|
1219
|
+
break;
|
|
1220
|
+
case METADATA:
|
|
1221
|
+
/* Metadata is present, so this should be a "complete" document */
|
|
1222
|
+
print_latex_header(out, elt);
|
|
1223
|
+
break;
|
|
1224
|
+
case METAKEY:
|
|
1225
|
+
if (strcmp(elt->contents.str, "title") == 0) {
|
|
1226
|
+
g_string_append_printf(out, "\\def\\mytitle{");
|
|
1227
|
+
print_latex_element_list(out, elt->children);
|
|
1228
|
+
g_string_append_printf(out, "}\n");
|
|
1229
|
+
} else if (strcmp(elt->contents.str, "author") == 0) {
|
|
1230
|
+
g_string_append_printf(out, "\\def\\myauthor{");
|
|
1231
|
+
print_latex_element_list(out, elt->children);
|
|
1232
|
+
g_string_append_printf(out, "}\n");
|
|
1233
|
+
} else if (strcmp(elt->contents.str, "date") == 0) {
|
|
1234
|
+
g_string_append_printf(out, "\\def\\mydate{");
|
|
1235
|
+
print_latex_element_list(out, elt->children);
|
|
1236
|
+
g_string_append_printf(out, "}\n");
|
|
1237
|
+
} else if (strcmp(elt->contents.str, "copyright") == 0) {
|
|
1238
|
+
g_string_append_printf(out, "\\def\\mycopyright{");
|
|
1239
|
+
print_latex_element_list(out, elt->children);
|
|
1240
|
+
g_string_append_printf(out, "}\n");
|
|
1241
|
+
} else if (strcmp(elt->contents.str, "baseheaderlevel") == 0) {
|
|
1242
|
+
base_header_level = atoi(elt->children->contents.str);
|
|
1243
|
+
} else if (strcmp(elt->contents.str, "latexheaderlevel") == 0) {
|
|
1244
|
+
base_header_level = atoi(elt->children->contents.str);
|
|
1245
|
+
} else if (strcmp(elt->contents.str, "latexinput") == 0) {
|
|
1246
|
+
g_string_append_printf(out, "\\input{%s}\n", elt->children->contents.str);
|
|
1247
|
+
} else if (strcmp(elt->contents.str, "latexfooter") == 0) {
|
|
1248
|
+
latex_footer = elt->children->contents.str;
|
|
1249
|
+
} else if (strcmp(elt->contents.str, "bibtex") == 0) {
|
|
1250
|
+
g_string_append_printf(out, "\\def\\bibliocommand{\\bibliography{%s}}\n",elt->children->contents.str);
|
|
1251
|
+
} else if (strcmp(elt->contents.str, "xhtmlheader") == 0) {
|
|
1252
|
+
} else if (strcmp(elt->contents.str, "htmlheader") == 0) {
|
|
1253
|
+
} else if (strcmp(elt->contents.str, "css") == 0) {
|
|
1254
|
+
} else if (strcmp(elt->contents.str, "quoteslanguage") == 0) {
|
|
1255
|
+
label = label_from_element_list(elt->children, 0);
|
|
1256
|
+
if (strcmp(label, "dutch") == 0) { language = DUTCH; } else
|
|
1257
|
+
if (strcmp(label, "german") == 0) { language = GERMAN; } else
|
|
1258
|
+
if (strcmp(label, "germanguillemets") == 0) { language = GERMANGUILL; } else
|
|
1259
|
+
if (strcmp(label, "french") == 0) { language = FRENCH; } else
|
|
1260
|
+
if (strcmp(label, "swedish") == 0) { language = SWEDISH; }
|
|
1261
|
+
free(label);
|
|
1262
|
+
} else {
|
|
1263
|
+
g_string_append_printf(out, "\\def\\");
|
|
1264
|
+
print_latex_string(out, elt->contents.str);
|
|
1265
|
+
g_string_append_printf(out, "{");
|
|
1266
|
+
print_latex_element_list(out, elt->children);
|
|
1267
|
+
g_string_append_printf(out, "}\n");
|
|
1268
|
+
}
|
|
1269
|
+
break;
|
|
1270
|
+
case METAVALUE:
|
|
1271
|
+
print_latex_string(out, elt->contents.str);
|
|
1272
|
+
break;
|
|
1273
|
+
case FOOTER:
|
|
1274
|
+
print_latex_endnotes(out);
|
|
1275
|
+
print_latex_footer(out);
|
|
1276
|
+
break;
|
|
1277
|
+
case HEADINGSECTION:
|
|
1278
|
+
print_latex_element_list(out, elt->children);
|
|
1279
|
+
break;
|
|
1280
|
+
case TABLE:
|
|
1281
|
+
pad(out, 2);
|
|
1282
|
+
g_string_append_printf(out, "\\begin{table}[htbp]\n\\begin{minipage}{\\linewidth}\n\\setlength{\\tymax}{0.5\\linewidth}\n\\centering\n\\small\n");
|
|
1283
|
+
print_latex_element_list(out, elt->children);
|
|
1284
|
+
g_string_append_printf(out, "\n\\end{tabular}\n\\end{minipage}\n\\end{table}\n");
|
|
1285
|
+
padded = 0;
|
|
1286
|
+
break;
|
|
1287
|
+
case TABLESEPARATOR:
|
|
1288
|
+
g_string_append_printf(out, "\\begin{tabular}{@{}%s@{}} \\toprule\n", elt->contents.str);
|
|
1289
|
+
break;
|
|
1290
|
+
case TABLECAPTION:
|
|
1291
|
+
if (elt->children->key == TABLELABEL) {
|
|
1292
|
+
label = label_from_element_list(elt->children->children,0);
|
|
1293
|
+
} else {
|
|
1294
|
+
label = label_from_element_list(elt->children,0);
|
|
1295
|
+
}
|
|
1296
|
+
g_string_append_printf(out, "\\caption{");
|
|
1297
|
+
print_latex_element_list(out, elt->children);
|
|
1298
|
+
g_string_append_printf(out, "}\n\\label{%s}\n",label);
|
|
1299
|
+
free(label);
|
|
1300
|
+
break;
|
|
1301
|
+
case TABLELABEL:
|
|
1302
|
+
break;
|
|
1303
|
+
case TABLEHEAD:
|
|
1304
|
+
print_latex_element_list(out, elt->children);
|
|
1305
|
+
g_string_append_printf(out, "\\midrule\n");
|
|
1306
|
+
break;
|
|
1307
|
+
case TABLEBODY:
|
|
1308
|
+
print_latex_element_list(out, elt->children);
|
|
1309
|
+
if ( ( elt->next != NULL ) && (elt->next->key == TABLEBODY) ) {
|
|
1310
|
+
g_string_append_printf(out, "\n\\midrule\n");
|
|
1311
|
+
} else {
|
|
1312
|
+
g_string_append_printf(out, "\n\\bottomrule\n");
|
|
1313
|
+
}
|
|
1314
|
+
break;
|
|
1315
|
+
case TABLEROW:
|
|
1316
|
+
print_latex_element_list(out, elt->children);
|
|
1317
|
+
g_string_append_printf(out, "\\\\\n");
|
|
1318
|
+
break;
|
|
1319
|
+
case TABLECELL:
|
|
1320
|
+
padded = 2;
|
|
1321
|
+
if ((elt->children != NULL) && (elt->children->key == CELLSPAN)) {
|
|
1322
|
+
g_string_append_printf(out, "\\multicolumn{%d}{c}{", (int)strlen(elt->children->contents.str)+1);
|
|
1323
|
+
}
|
|
1324
|
+
print_latex_element_list(out, elt->children);
|
|
1325
|
+
if ((elt->children != NULL) && (elt->children->key == CELLSPAN)) {
|
|
1326
|
+
g_string_append_printf(out, "}");
|
|
1327
|
+
}
|
|
1328
|
+
if (elt->next != NULL) {
|
|
1329
|
+
g_string_append_printf(out, "&");
|
|
1330
|
+
}
|
|
1331
|
+
break;
|
|
1332
|
+
case CELLSPAN:
|
|
1333
|
+
break;
|
|
1334
|
+
case ATTRKEY:
|
|
1335
|
+
g_string_append_printf(out, " %s=\"%s\"", elt->contents.str,
|
|
1336
|
+
elt->children->contents.str);
|
|
1337
|
+
break;
|
|
1338
|
+
case MATHSPAN:
|
|
1339
|
+
if (strncmp(&elt->contents.str[2],"\\begin",5) == 0) {
|
|
1340
|
+
elt->contents.str[strlen(elt->contents.str)-3] = '\0';
|
|
1341
|
+
g_string_append_printf(out, "%s",&elt->contents.str[2]);
|
|
1342
|
+
} else {
|
|
1343
|
+
if ( elt->contents.str[strlen(elt->contents.str)-1] == ']') {
|
|
1344
|
+
elt->contents.str[strlen(elt->contents.str)-3] = '\0';
|
|
1345
|
+
g_string_append_printf(out, "%s\\]", elt->contents.str);
|
|
1346
|
+
} else {
|
|
1347
|
+
elt->contents.str[strlen(elt->contents.str)-3] = '\0';
|
|
1348
|
+
g_string_append_printf(out, "$%s$", &elt->contents.str[2]);
|
|
1349
|
+
}
|
|
1350
|
+
}
|
|
1351
|
+
break;
|
|
1352
|
+
default:
|
|
1353
|
+
fprintf(stderr, "print_latex_element encountered unknown element key = %d\n", elt->key);
|
|
1354
|
+
exit(EXIT_FAILURE);
|
|
1355
|
+
}
|
|
1356
|
+
}
|
|
1357
|
+
|
|
1358
|
+
/**********************************************************************
|
|
1359
|
+
|
|
1360
|
+
Functions for printing Elements as groff (mm macros)
|
|
1361
|
+
|
|
1362
|
+
***********************************************************************/
|
|
1363
|
+
|
|
1364
|
+
static bool in_list_item = false; /* True if we're parsing contents of a list item. */
|
|
1365
|
+
|
|
1366
|
+
/* print_groff_string - print string, escaping for groff */
|
|
1367
|
+
static void print_groff_string(GString *out, char *str) {
|
|
1368
|
+
while (*str != '\0') {
|
|
1369
|
+
switch (*str) {
|
|
1370
|
+
case '\\':
|
|
1371
|
+
g_string_append_printf(out, "\\e");
|
|
1372
|
+
break;
|
|
1373
|
+
default:
|
|
1374
|
+
g_string_append_c(out, *str);
|
|
1375
|
+
}
|
|
1376
|
+
str++;
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
|
|
1380
|
+
/* print_groff_mm_element_list - print a list of elements as groff ms */
|
|
1381
|
+
static void print_groff_mm_element_list(GString *out, element *list) {
|
|
1382
|
+
int count = 1;
|
|
1383
|
+
while (list != NULL) {
|
|
1384
|
+
print_groff_mm_element(out, list, count);
|
|
1385
|
+
list = list->next;
|
|
1386
|
+
count++;
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
|
|
1390
|
+
/* print_groff_mm_element - print an element as groff ms */
|
|
1391
|
+
static void print_groff_mm_element(GString *out, element *elt, int count) {
|
|
1392
|
+
int lev;
|
|
1393
|
+
switch (elt->key) {
|
|
1394
|
+
case SPACE:
|
|
1395
|
+
g_string_append_printf(out, "%s", elt->contents.str);
|
|
1396
|
+
padded = 0;
|
|
1397
|
+
break;
|
|
1398
|
+
case LINEBREAK:
|
|
1399
|
+
pad(out, 1);
|
|
1400
|
+
g_string_append_printf(out, ".br\n");
|
|
1401
|
+
padded = 0;
|
|
1402
|
+
break;
|
|
1403
|
+
case STR:
|
|
1404
|
+
print_groff_string(out, elt->contents.str);
|
|
1405
|
+
padded = 0;
|
|
1406
|
+
break;
|
|
1407
|
+
case ELLIPSIS:
|
|
1408
|
+
g_string_append_printf(out, "...");
|
|
1409
|
+
break;
|
|
1410
|
+
case EMDASH:
|
|
1411
|
+
g_string_append_printf(out, "\\[em]");
|
|
1412
|
+
break;
|
|
1413
|
+
case ENDASH:
|
|
1414
|
+
g_string_append_printf(out, "\\[en]");
|
|
1415
|
+
break;
|
|
1416
|
+
case APOSTROPHE:
|
|
1417
|
+
g_string_append_printf(out, "'");
|
|
1418
|
+
break;
|
|
1419
|
+
case SINGLEQUOTED:
|
|
1420
|
+
g_string_append_printf(out, "`");
|
|
1421
|
+
print_groff_mm_element_list(out, elt->children);
|
|
1422
|
+
g_string_append_printf(out, "'");
|
|
1423
|
+
break;
|
|
1424
|
+
case DOUBLEQUOTED:
|
|
1425
|
+
g_string_append_printf(out, "\\[lq]");
|
|
1426
|
+
print_groff_mm_element_list(out, elt->children);
|
|
1427
|
+
g_string_append_printf(out, "\\[rq]");
|
|
1428
|
+
break;
|
|
1429
|
+
case CODE:
|
|
1430
|
+
g_string_append_printf(out, "\\fC");
|
|
1431
|
+
print_groff_string(out, elt->contents.str);
|
|
1432
|
+
g_string_append_printf(out, "\\fR");
|
|
1433
|
+
padded = 0;
|
|
1434
|
+
break;
|
|
1435
|
+
case HTML:
|
|
1436
|
+
/* don't print HTML */
|
|
1437
|
+
break;
|
|
1438
|
+
case LINK:
|
|
1439
|
+
print_groff_mm_element_list(out, elt->contents.link->label);
|
|
1440
|
+
g_string_append_printf(out, " (%s)", elt->contents.link->url);
|
|
1441
|
+
padded = 0;
|
|
1442
|
+
break;
|
|
1443
|
+
case IMAGE:
|
|
1444
|
+
g_string_append_printf(out, "[IMAGE: ");
|
|
1445
|
+
print_groff_mm_element_list(out, elt->contents.link->label);
|
|
1446
|
+
g_string_append_printf(out, "]");
|
|
1447
|
+
padded = 0;
|
|
1448
|
+
/* not supported */
|
|
1449
|
+
break;
|
|
1450
|
+
case EMPH:
|
|
1451
|
+
g_string_append_printf(out, "\\fI");
|
|
1452
|
+
print_groff_mm_element_list(out, elt->children);
|
|
1453
|
+
g_string_append_printf(out, "\\fR");
|
|
1454
|
+
padded = 0;
|
|
1455
|
+
break;
|
|
1456
|
+
case STRONG:
|
|
1457
|
+
g_string_append_printf(out, "\\fB");
|
|
1458
|
+
print_groff_mm_element_list(out, elt->children);
|
|
1459
|
+
g_string_append_printf(out, "\\fR");
|
|
1460
|
+
padded = 0;
|
|
1461
|
+
break;
|
|
1462
|
+
case LIST:
|
|
1463
|
+
print_groff_mm_element_list(out, elt->children);
|
|
1464
|
+
padded = 0;
|
|
1465
|
+
break;
|
|
1466
|
+
case RAW:
|
|
1467
|
+
/* Shouldn't occur - these are handled by process_raw_blocks() */
|
|
1468
|
+
assert(elt->key != RAW);
|
|
1469
|
+
break;
|
|
1470
|
+
case H1: case H2: case H3: case H4: case H5: case H6:
|
|
1471
|
+
lev = elt->key - H1 + 1;
|
|
1472
|
+
pad(out, 1);
|
|
1473
|
+
g_string_append_printf(out, ".H %d \"", lev);
|
|
1474
|
+
print_groff_mm_element_list(out, elt->children);
|
|
1475
|
+
g_string_append_printf(out, "\"");
|
|
1476
|
+
padded = 0;
|
|
1477
|
+
break;
|
|
1478
|
+
case PLAIN:
|
|
1479
|
+
pad(out, 1);
|
|
1480
|
+
print_groff_mm_element_list(out, elt->children);
|
|
1481
|
+
padded = 0;
|
|
1482
|
+
break;
|
|
1483
|
+
case PARA:
|
|
1484
|
+
pad(out, 1);
|
|
1485
|
+
if (!in_list_item || count != 1)
|
|
1486
|
+
g_string_append_printf(out, ".P\n");
|
|
1487
|
+
print_groff_mm_element_list(out, elt->children);
|
|
1488
|
+
padded = 0;
|
|
1489
|
+
break;
|
|
1490
|
+
case HRULE:
|
|
1491
|
+
pad(out, 1);
|
|
1492
|
+
g_string_append_printf(out, "\\l'\\n(.lu*8u/10u'");
|
|
1493
|
+
padded = 0;
|
|
1494
|
+
break;
|
|
1495
|
+
case HTMLBLOCK:
|
|
1496
|
+
/* don't print HTML block */
|
|
1497
|
+
break;
|
|
1498
|
+
case VERBATIM:
|
|
1499
|
+
pad(out, 1);
|
|
1500
|
+
g_string_append_printf(out, ".VERBON 2\n");
|
|
1501
|
+
print_groff_string(out, elt->contents.str);
|
|
1502
|
+
g_string_append_printf(out, ".VERBOFF");
|
|
1503
|
+
padded = 0;
|
|
1504
|
+
break;
|
|
1505
|
+
case BULLETLIST:
|
|
1506
|
+
pad(out, 1);
|
|
1507
|
+
g_string_append_printf(out, ".BL");
|
|
1508
|
+
padded = 0;
|
|
1509
|
+
print_groff_mm_element_list(out, elt->children);
|
|
1510
|
+
pad(out, 1);
|
|
1511
|
+
g_string_append_printf(out, ".LE 1");
|
|
1512
|
+
padded = 0;
|
|
1513
|
+
break;
|
|
1514
|
+
case ORDEREDLIST:
|
|
1515
|
+
pad(out, 1);
|
|
1516
|
+
g_string_append_printf(out, ".AL");
|
|
1517
|
+
padded = 0;
|
|
1518
|
+
print_groff_mm_element_list(out, elt->children);
|
|
1519
|
+
pad(out, 1);
|
|
1520
|
+
g_string_append_printf(out, ".LE 1");
|
|
1521
|
+
padded = 0;
|
|
1522
|
+
break;
|
|
1523
|
+
case LISTITEM:
|
|
1524
|
+
pad(out, 1);
|
|
1525
|
+
g_string_append_printf(out, ".LI\n");
|
|
1526
|
+
in_list_item = true;
|
|
1527
|
+
padded = 2;
|
|
1528
|
+
print_groff_mm_element_list(out, elt->children);
|
|
1529
|
+
in_list_item = false;
|
|
1530
|
+
break;
|
|
1531
|
+
case BLOCKQUOTE:
|
|
1532
|
+
pad(out, 1);
|
|
1533
|
+
g_string_append_printf(out, ".DS I\n");
|
|
1534
|
+
padded = 2;
|
|
1535
|
+
print_groff_mm_element_list(out, elt->children);
|
|
1536
|
+
pad(out, 1);
|
|
1537
|
+
g_string_append_printf(out, ".DE");
|
|
1538
|
+
padded = 0;
|
|
1539
|
+
break;
|
|
1540
|
+
case NOTELABEL:
|
|
1541
|
+
/* Nonprinting */
|
|
1542
|
+
break;
|
|
1543
|
+
case NOTE:
|
|
1544
|
+
/* if contents.str == 0, then print note; else ignore, since this
|
|
1545
|
+
* is a note block that has been incorporated into the notes list */
|
|
1546
|
+
if (elt->contents.str == 0) {
|
|
1547
|
+
g_string_append_printf(out, "\\*F\n");
|
|
1548
|
+
g_string_append_printf(out, ".FS\n");
|
|
1549
|
+
padded = 2;
|
|
1550
|
+
print_groff_mm_element_list(out, elt->children);
|
|
1551
|
+
pad(out, 1);
|
|
1552
|
+
g_string_append_printf(out, ".FE\n");
|
|
1553
|
+
padded = 1;
|
|
1554
|
+
}
|
|
1555
|
+
break;
|
|
1556
|
+
case REFERENCE:
|
|
1557
|
+
/* Nonprinting */
|
|
1558
|
+
break;
|
|
1559
|
+
default:
|
|
1560
|
+
fprintf(stderr, "print_groff_mm_element encountered unknown element key = %d\n", elt->key);
|
|
1561
|
+
exit(EXIT_FAILURE);
|
|
1562
|
+
}
|
|
1563
|
+
}
|
|
1564
|
+
|
|
1565
|
+
/**********************************************************************
|
|
1566
|
+
|
|
1567
|
+
Functions for printing Elements as ODF
|
|
1568
|
+
|
|
1569
|
+
***********************************************************************/
|
|
1570
|
+
|
|
1571
|
+
/* print_odf_code_string - print string, escaping for HTML and saving newlines
|
|
1572
|
+
*/
|
|
1573
|
+
static void print_odf_code_string(GString *out, char *str) {
|
|
1574
|
+
char *tmp;
|
|
1575
|
+
while (*str != '\0') {
|
|
1576
|
+
switch (*str) {
|
|
1577
|
+
case '&':
|
|
1578
|
+
g_string_append_printf(out, "&");
|
|
1579
|
+
break;
|
|
1580
|
+
case '<':
|
|
1581
|
+
g_string_append_printf(out, "<");
|
|
1582
|
+
break;
|
|
1583
|
+
case '>':
|
|
1584
|
+
g_string_append_printf(out, ">");
|
|
1585
|
+
break;
|
|
1586
|
+
case '"':
|
|
1587
|
+
g_string_append_printf(out, """);
|
|
1588
|
+
break;
|
|
1589
|
+
case '\n':
|
|
1590
|
+
g_string_append_printf(out, "<text:line-break/>");
|
|
1591
|
+
break;
|
|
1592
|
+
case ' ':
|
|
1593
|
+
tmp = str;
|
|
1594
|
+
tmp++;
|
|
1595
|
+
if (*tmp == ' ') {
|
|
1596
|
+
tmp++;
|
|
1597
|
+
if (*tmp == ' ') {
|
|
1598
|
+
tmp++;
|
|
1599
|
+
if (*tmp == ' ') {
|
|
1600
|
+
g_string_append_printf(out, "<text:tab/>");
|
|
1601
|
+
str = tmp;
|
|
1602
|
+
} else {
|
|
1603
|
+
g_string_append_printf(out, " ");
|
|
1604
|
+
}
|
|
1605
|
+
} else {
|
|
1606
|
+
g_string_append_printf(out, " ");
|
|
1607
|
+
}
|
|
1608
|
+
} else {
|
|
1609
|
+
g_string_append_printf(out, " ");
|
|
1610
|
+
}
|
|
1611
|
+
break;
|
|
1612
|
+
default:
|
|
1613
|
+
g_string_append_c(out, *str);
|
|
1614
|
+
}
|
|
1615
|
+
str++;
|
|
1616
|
+
}
|
|
1617
|
+
}
|
|
1618
|
+
|
|
1619
|
+
/* print_odf_string - print string, escaping for HTML and saving newlines */
|
|
1620
|
+
static void print_odf_string(GString *out, char *str) {
|
|
1621
|
+
char *tmp;
|
|
1622
|
+
while (*str != '\0') {
|
|
1623
|
+
switch (*str) {
|
|
1624
|
+
case '&':
|
|
1625
|
+
g_string_append_printf(out, "&");
|
|
1626
|
+
break;
|
|
1627
|
+
case '<':
|
|
1628
|
+
g_string_append_printf(out, "<");
|
|
1629
|
+
break;
|
|
1630
|
+
case '>':
|
|
1631
|
+
g_string_append_printf(out, ">");
|
|
1632
|
+
break;
|
|
1633
|
+
case '"':
|
|
1634
|
+
g_string_append_printf(out, """);
|
|
1635
|
+
break;
|
|
1636
|
+
case '\n':
|
|
1637
|
+
tmp = str;
|
|
1638
|
+
tmp--;
|
|
1639
|
+
if (*tmp == ' ') {
|
|
1640
|
+
tmp--;
|
|
1641
|
+
if (*tmp == ' ') {
|
|
1642
|
+
g_string_append_printf(out, "<text:line-break/>");
|
|
1643
|
+
} else {
|
|
1644
|
+
g_string_append_printf(out, "\n");
|
|
1645
|
+
}
|
|
1646
|
+
} else {
|
|
1647
|
+
g_string_append_printf(out, "\n");
|
|
1648
|
+
}
|
|
1649
|
+
break;
|
|
1650
|
+
case ' ':
|
|
1651
|
+
tmp = str;
|
|
1652
|
+
tmp++;
|
|
1653
|
+
if (*tmp == ' ') {
|
|
1654
|
+
tmp++;
|
|
1655
|
+
if (*tmp == ' ') {
|
|
1656
|
+
tmp++;
|
|
1657
|
+
if (*tmp == ' ') {
|
|
1658
|
+
g_string_append_printf(out, "<text:tab/>");
|
|
1659
|
+
str = tmp;
|
|
1660
|
+
} else {
|
|
1661
|
+
g_string_append_printf(out, " ");
|
|
1662
|
+
}
|
|
1663
|
+
} else {
|
|
1664
|
+
g_string_append_printf(out, " ");
|
|
1665
|
+
}
|
|
1666
|
+
} else {
|
|
1667
|
+
g_string_append_printf(out, " ");
|
|
1668
|
+
}
|
|
1669
|
+
break;
|
|
1670
|
+
default:
|
|
1671
|
+
g_string_append_c(out, *str);
|
|
1672
|
+
}
|
|
1673
|
+
str++;
|
|
1674
|
+
}
|
|
1675
|
+
}
|
|
1676
|
+
|
|
1677
|
+
/* print_odf_element_list - print an element list as ODF */
|
|
1678
|
+
void print_odf_element_list(GString *out, element *list) {
|
|
1679
|
+
while (list != NULL) {
|
|
1680
|
+
print_odf_element(out, list);
|
|
1681
|
+
list = list->next;
|
|
1682
|
+
}
|
|
1683
|
+
}
|
|
1684
|
+
|
|
1685
|
+
/* print_odf_element - print an element as ODF */
|
|
1686
|
+
void print_odf_element(GString *out, element *elt) {
|
|
1687
|
+
int lev;
|
|
1688
|
+
char *label;
|
|
1689
|
+
char *height;
|
|
1690
|
+
char *width;
|
|
1691
|
+
int old_type = 0;
|
|
1692
|
+
switch (elt->key) {
|
|
1693
|
+
case SPACE:
|
|
1694
|
+
g_string_append_printf(out, "%s", elt->contents.str);
|
|
1695
|
+
break;
|
|
1696
|
+
case LINEBREAK:
|
|
1697
|
+
g_string_append_printf(out, "<text:line-break/>");
|
|
1698
|
+
break;
|
|
1699
|
+
case STR:
|
|
1700
|
+
print_html_string(out, elt->contents.str, 0);
|
|
1701
|
+
break;
|
|
1702
|
+
case ELLIPSIS:
|
|
1703
|
+
localize_typography(out, ELLIP, language, HTMLOUT);
|
|
1704
|
+
break;
|
|
1705
|
+
case EMDASH:
|
|
1706
|
+
localize_typography(out, MDASH, language, HTMLOUT);
|
|
1707
|
+
break;
|
|
1708
|
+
case ENDASH:
|
|
1709
|
+
localize_typography(out, NDASH, language, HTMLOUT);
|
|
1710
|
+
break;
|
|
1711
|
+
case APOSTROPHE:
|
|
1712
|
+
localize_typography(out, APOS, language, HTMLOUT);
|
|
1713
|
+
break;
|
|
1714
|
+
case SINGLEQUOTED:
|
|
1715
|
+
localize_typography(out, LSQUOTE, language, HTMLOUT);
|
|
1716
|
+
print_odf_element_list(out, elt->children);
|
|
1717
|
+
localize_typography(out, RSQUOTE, language, HTMLOUT);
|
|
1718
|
+
break;
|
|
1719
|
+
case DOUBLEQUOTED:
|
|
1720
|
+
localize_typography(out, LDQUOTE, language, HTMLOUT);
|
|
1721
|
+
print_odf_element_list(out, elt->children);
|
|
1722
|
+
localize_typography(out, RDQUOTE, language, HTMLOUT);
|
|
1723
|
+
break;
|
|
1724
|
+
case CODE:
|
|
1725
|
+
g_string_append_printf(out, "<text:span text:style-name=\"Source_20_Text\">");
|
|
1726
|
+
print_html_string(out, elt->contents.str, 0);
|
|
1727
|
+
g_string_append_printf(out, "</text:span>");
|
|
1728
|
+
break;
|
|
1729
|
+
case HTML:
|
|
1730
|
+
break;
|
|
1731
|
+
case LINK:
|
|
1732
|
+
if (elt->contents.link->url[0] == '#') {
|
|
1733
|
+
/* This is a cross-reference */
|
|
1734
|
+
label = label_from_string(elt->contents.link->url,0);
|
|
1735
|
+
if (elt->contents.link->label != NULL) {
|
|
1736
|
+
g_string_append_printf(out, "<text:a xlink:type=\"simple\" xlink:href=\"#%s\">",label);
|
|
1737
|
+
print_latex_element_list(out, elt->contents.link->label);
|
|
1738
|
+
g_string_append_printf(out,"</text:a>");
|
|
1739
|
+
} else {
|
|
1740
|
+
|
|
1741
|
+
}
|
|
1742
|
+
} else {
|
|
1743
|
+
g_string_append_printf(out, "<text:a xlink:type=\"simple\" xlink:href=\"");
|
|
1744
|
+
print_html_string(out, elt->contents.link->url, 0);
|
|
1745
|
+
g_string_append_printf(out, "\"");
|
|
1746
|
+
if (strlen(elt->contents.link->title) > 0) {
|
|
1747
|
+
g_string_append_printf(out, " office:name=\"");
|
|
1748
|
+
print_html_string(out, elt->contents.link->title, 0);
|
|
1749
|
+
g_string_append_printf(out, "\"");
|
|
1750
|
+
}
|
|
1751
|
+
/* print_html_element_list(out, elt->contents.link->attr, obfuscate);*/
|
|
1752
|
+
g_string_append_printf(out, ">");
|
|
1753
|
+
print_odf_element_list(out, elt->contents.link->label);
|
|
1754
|
+
g_string_append_printf(out, "</text:a>");
|
|
1755
|
+
}
|
|
1756
|
+
break;
|
|
1757
|
+
case IMAGEBLOCK:
|
|
1758
|
+
g_string_append_printf(out, "<text:p>\n");
|
|
1759
|
+
case IMAGE:
|
|
1760
|
+
height = dimension_for_attribute("height", elt->contents.link->attr);
|
|
1761
|
+
width = dimension_for_attribute("width", elt->contents.link->attr);
|
|
1762
|
+
g_string_append_printf(out, "<draw:frame text:anchor-type=\"as-char\"\ndraw:z-index=\"0\" draw:style-name=\"fr1\" ");
|
|
1763
|
+
/* need both attributes for image to be visible */
|
|
1764
|
+
if ((width != NULL)) {
|
|
1765
|
+
g_string_append_printf(out, "svg:width=\"%s\"\n", width);
|
|
1766
|
+
} else {
|
|
1767
|
+
g_string_append_printf(out, "svg:width=\"95%%\"\n");
|
|
1768
|
+
}
|
|
1769
|
+
g_string_append_printf(out, ">\n<draw:text-box><text:p><draw:frame text:anchor-type=\"as-char\" draw:z-index=\"1\" ");
|
|
1770
|
+
if ((height != NULL) && (width != NULL)) {
|
|
1771
|
+
g_string_append_printf(out, "svg:height=\"%s\"\n",height);
|
|
1772
|
+
g_string_append_printf(out, "svg:width=\"%s\"\n", width);
|
|
1773
|
+
}
|
|
1774
|
+
g_string_append_printf(out, "><draw:image xlink:href=\"");
|
|
1775
|
+
print_odf_string(out, elt->contents.link->url);
|
|
1776
|
+
g_string_append_printf(out,"\" xlink:type=\"simple\" xlink:show=\"embed\" xlink:actuate=\"onLoad\" draw:filter-name=\"<All formats>\"/>\n</draw:frame></text:p>");
|
|
1777
|
+
if (elt->key == IMAGEBLOCK) {
|
|
1778
|
+
g_string_append_printf(out, "<text:p>");
|
|
1779
|
+
if (elt->contents.link->label != NULL) {
|
|
1780
|
+
g_string_append_printf(out, "Figure <text:sequence text:name=\"Figure\" text:formula=\"ooow:Figure+1\" style:num-format=\"1\"> Update Fields to calculate numbers</text:sequence>: ");
|
|
1781
|
+
print_odf_element_list(out, elt->contents.link->label);
|
|
1782
|
+
}
|
|
1783
|
+
g_string_append_printf(out, "</text:p></draw:text-box></draw:frame>\n</text:p>\n");
|
|
1784
|
+
} else {
|
|
1785
|
+
g_string_append_printf(out, "</draw:text-box></draw:frame>\n");
|
|
1786
|
+
}
|
|
1787
|
+
break;
|
|
1788
|
+
case EMPH:
|
|
1789
|
+
g_string_append_printf(out,
|
|
1790
|
+
"<text:span text:style-name=\"MMD-Italic\">");
|
|
1791
|
+
print_odf_element_list(out, elt->children);
|
|
1792
|
+
g_string_append_printf(out, "</text:span>");
|
|
1793
|
+
break;
|
|
1794
|
+
case STRONG:
|
|
1795
|
+
g_string_append_printf(out,
|
|
1796
|
+
"<text:span text:style-name=\"MMD-Bold\">");
|
|
1797
|
+
print_odf_element_list(out, elt->children);
|
|
1798
|
+
g_string_append_printf(out, "</text:span>");
|
|
1799
|
+
break;
|
|
1800
|
+
case LIST:
|
|
1801
|
+
print_odf_element_list(out, elt->children);
|
|
1802
|
+
break;
|
|
1803
|
+
case RAW:
|
|
1804
|
+
/* Shouldn't occur - these are handled by process_raw_blocks() */
|
|
1805
|
+
assert(elt->key != RAW);
|
|
1806
|
+
break;
|
|
1807
|
+
case H1: case H2: case H3: case H4: case H5: case H6:
|
|
1808
|
+
lev = elt->key - H1 + base_header_level; /* assumes H1 ... H6 are in order */
|
|
1809
|
+
g_string_append_printf(out, "<text:h text:outline-level=\"%d\">", lev);
|
|
1810
|
+
if (elt->children->key == AUTOLABEL) {
|
|
1811
|
+
/* generate a label for each header (MMD)*/
|
|
1812
|
+
g_string_append_printf(out,"<text:bookmark text:name=\"%s\"/>", elt->children->contents.str);
|
|
1813
|
+
print_odf_element_list(out, elt->children->next);
|
|
1814
|
+
g_string_append_printf(out,"<text:bookmark-end text:name=\"%s\"/>", elt->children->contents.str);
|
|
1815
|
+
} else {
|
|
1816
|
+
label = label_from_element_list(elt->children, 0);
|
|
1817
|
+
g_string_append_printf(out,"<text:bookmark text:name=\"%s\"/>", label);
|
|
1818
|
+
print_odf_element_list(out, elt->children);
|
|
1819
|
+
g_string_append_printf(out,"<text:bookmark-end text:name=\"%s\"/>", label);
|
|
1820
|
+
free(label);
|
|
1821
|
+
}
|
|
1822
|
+
g_string_append_printf(out, "</text:h>\n");
|
|
1823
|
+
padded = 0;
|
|
1824
|
+
break;
|
|
1825
|
+
case PLAIN:
|
|
1826
|
+
print_odf_element_list(out, elt->children);
|
|
1827
|
+
padded = 0;
|
|
1828
|
+
break;
|
|
1829
|
+
case PARA:
|
|
1830
|
+
g_string_append_printf(out, "<text:p");
|
|
1831
|
+
switch (odf_type) {
|
|
1832
|
+
case DEFINITION:
|
|
1833
|
+
case BLOCKQUOTE:
|
|
1834
|
+
g_string_append_printf(out," text:style-name=\"Quotations\"");
|
|
1835
|
+
break;
|
|
1836
|
+
case CODE:
|
|
1837
|
+
g_string_append_printf(out," text:style-name=\"Preformatted Text\"");
|
|
1838
|
+
break;
|
|
1839
|
+
case VERBATIM:
|
|
1840
|
+
g_string_append_printf(out," text:style-name=\"Preformatted Text\"");
|
|
1841
|
+
break;
|
|
1842
|
+
case ORDEREDLIST:
|
|
1843
|
+
case BULLETLIST:
|
|
1844
|
+
g_string_append_printf(out," text:style-name=\"P2\"");
|
|
1845
|
+
break;
|
|
1846
|
+
case NOTE:
|
|
1847
|
+
g_string_append_printf(out," text:style-name=\"Footnote\"");
|
|
1848
|
+
break;
|
|
1849
|
+
default:
|
|
1850
|
+
g_string_append_printf(out," text:style-name=\"Standard\"");
|
|
1851
|
+
break;
|
|
1852
|
+
}
|
|
1853
|
+
g_string_append_printf(out, ">");
|
|
1854
|
+
print_odf_element_list(out, elt->children);
|
|
1855
|
+
g_string_append_printf(out, "</text:p>\n");
|
|
1856
|
+
break;
|
|
1857
|
+
case HRULE:
|
|
1858
|
+
g_string_append_printf(out,"<text:p text:style-name=\"Horizontal_20_Line\"/>\n");
|
|
1859
|
+
break;
|
|
1860
|
+
case HTMLBLOCK:
|
|
1861
|
+
/* don't print HTML block */
|
|
1862
|
+
/* but do print HTML comments for raw ODF */
|
|
1863
|
+
if (strncmp(elt->contents.str,"<!--",4) == 0) {
|
|
1864
|
+
/* trim "-->" from end */
|
|
1865
|
+
elt->contents.str[strlen(elt->contents.str)-3] = '\0';
|
|
1866
|
+
g_string_append_printf(out, "%s", &elt->contents.str[4]);
|
|
1867
|
+
}
|
|
1868
|
+
break;
|
|
1869
|
+
case VERBATIM:
|
|
1870
|
+
old_type = odf_type;
|
|
1871
|
+
odf_type = VERBATIM;
|
|
1872
|
+
g_string_append_printf(out, "<text:p text:style-name=\"Preformatted Text\">");
|
|
1873
|
+
print_odf_code_string(out, elt->contents.str);
|
|
1874
|
+
g_string_append_printf(out, "</text:p>\n");
|
|
1875
|
+
odf_type = old_type;
|
|
1876
|
+
break;
|
|
1877
|
+
case BULLETLIST:
|
|
1878
|
+
if ((odf_type == BULLETLIST) ||
|
|
1879
|
+
(odf_type == ORDEREDLIST)) {
|
|
1880
|
+
/* I think this was made unnecessary by another change.
|
|
1881
|
+
Same for ORDEREDLIST below */
|
|
1882
|
+
/* g_string_append_printf(out, "</text:p>"); */
|
|
1883
|
+
}
|
|
1884
|
+
old_type = odf_type;
|
|
1885
|
+
odf_type = BULLETLIST;
|
|
1886
|
+
g_string_append_printf(out, "%s", "<text:list>");
|
|
1887
|
+
print_odf_element_list(out, elt->children);
|
|
1888
|
+
g_string_append_printf(out, "%s", "</text:list>");
|
|
1889
|
+
odf_type = old_type;
|
|
1890
|
+
break;
|
|
1891
|
+
case ORDEREDLIST:
|
|
1892
|
+
if ((odf_type == BULLETLIST) ||
|
|
1893
|
+
(odf_type == ORDEREDLIST)) {
|
|
1894
|
+
/* g_string_append_printf(out, "</text:p>"); */
|
|
1895
|
+
}
|
|
1896
|
+
old_type = odf_type;
|
|
1897
|
+
odf_type = ORDEREDLIST;
|
|
1898
|
+
g_string_append_printf(out, "%s", "<text:list>\n");
|
|
1899
|
+
print_odf_element_list(out, elt->children);
|
|
1900
|
+
g_string_append_printf(out, "%s", "</text:list>\n");
|
|
1901
|
+
odf_type = old_type;
|
|
1902
|
+
break;
|
|
1903
|
+
case LISTITEM:
|
|
1904
|
+
g_string_append_printf(out, "<text:list-item>\n");
|
|
1905
|
+
if (elt->children->children->key != PARA) {
|
|
1906
|
+
g_string_append_printf(out, "<text:p text:style-name=\"P2\">");
|
|
1907
|
+
}
|
|
1908
|
+
print_odf_element_list(out, elt->children);
|
|
1909
|
+
|
|
1910
|
+
if ((list_contains_key(elt->children,BULLETLIST) ||
|
|
1911
|
+
(list_contains_key(elt->children,ORDEREDLIST)))) {
|
|
1912
|
+
} else {
|
|
1913
|
+
if (elt->children->children->key != PARA) {
|
|
1914
|
+
g_string_append_printf(out, "</text:p>");
|
|
1915
|
+
}
|
|
1916
|
+
}
|
|
1917
|
+
g_string_append_printf(out, "</text:list-item>\n");
|
|
1918
|
+
break;
|
|
1919
|
+
case BLOCKQUOTE:
|
|
1920
|
+
old_type = odf_type;
|
|
1921
|
+
odf_type = BLOCKQUOTE;
|
|
1922
|
+
print_odf_element_list(out, elt->children);
|
|
1923
|
+
odf_type = old_type;
|
|
1924
|
+
break;
|
|
1925
|
+
case REFERENCE:
|
|
1926
|
+
break;
|
|
1927
|
+
case NOTELABEL:
|
|
1928
|
+
break;
|
|
1929
|
+
case NOTE:
|
|
1930
|
+
old_type = odf_type;
|
|
1931
|
+
odf_type = NOTE;
|
|
1932
|
+
/* if contents.str == 0 then print; else ignore - like above */
|
|
1933
|
+
if (elt->contents.str == 0) {
|
|
1934
|
+
if (elt->children->key == GLOSSARYTERM) {
|
|
1935
|
+
g_string_append_printf(out, "<text:note text:id=\"\" text:note-class=\"glossary\"><text:note-body>\n");
|
|
1936
|
+
print_odf_element_list(out, elt->children);
|
|
1937
|
+
g_string_append_printf(out, "</text:note-body>\n</text:note>\n");
|
|
1938
|
+
} else {
|
|
1939
|
+
g_string_append_printf(out, "<text:note text:id=\"\" text:note-class=\"footnote\"><text:note-body>\n");
|
|
1940
|
+
print_odf_element_list(out, elt->children);
|
|
1941
|
+
g_string_append_printf(out, "</text:note-body>\n</text:note>\n");
|
|
1942
|
+
}
|
|
1943
|
+
}
|
|
1944
|
+
elt->children = NULL;
|
|
1945
|
+
odf_type = old_type;
|
|
1946
|
+
break;
|
|
1947
|
+
case GLOSSARY:
|
|
1948
|
+
break;
|
|
1949
|
+
case GLOSSARYTERM:
|
|
1950
|
+
g_string_append_printf(out, "<text:p text:style-name=\"Glossary\">");
|
|
1951
|
+
print_odf_string(out, elt->children->contents.str);
|
|
1952
|
+
g_string_append_printf(out, ":");
|
|
1953
|
+
g_string_append_printf(out, "</text:p>");
|
|
1954
|
+
break;
|
|
1955
|
+
case GLOSSARYSORTKEY:
|
|
1956
|
+
break;
|
|
1957
|
+
case NOCITATION:
|
|
1958
|
+
case CITATION:
|
|
1959
|
+
if (strncmp(elt->contents.str,"[#",2) == 0) {
|
|
1960
|
+
/* bibtex citation key */
|
|
1961
|
+
g_string_append_printf(out, "%s", elt->contents.str);
|
|
1962
|
+
} else {
|
|
1963
|
+
g_string_append_printf(out, "[#%s]", elt->contents.str);
|
|
1964
|
+
}
|
|
1965
|
+
elt->children = NULL;
|
|
1966
|
+
break;
|
|
1967
|
+
case DEFLIST:
|
|
1968
|
+
print_odf_element_list(out, elt->children);
|
|
1969
|
+
break;
|
|
1970
|
+
case TERM:
|
|
1971
|
+
g_string_append_printf(out, "<text:p><text:span text:style-name=\"MMD-Bold\">");
|
|
1972
|
+
print_odf_string(out, elt->contents.str);
|
|
1973
|
+
g_string_append_printf(out, "</text:span></text:p>");
|
|
1974
|
+
break;
|
|
1975
|
+
case DEFINITION:
|
|
1976
|
+
old_type = odf_type;
|
|
1977
|
+
odf_type = DEFINITION;
|
|
1978
|
+
g_string_append_printf(out, "<text:p text:style-name=\"Quotations\">");
|
|
1979
|
+
print_odf_element_list(out, elt->children);
|
|
1980
|
+
g_string_append_printf(out, "</text:p>");
|
|
1981
|
+
odf_type = old_type;
|
|
1982
|
+
break;
|
|
1983
|
+
case METADATA:
|
|
1984
|
+
g_string_append_printf(out, "<office:meta>\n");
|
|
1985
|
+
print_odf_element_list(out, elt->children);
|
|
1986
|
+
g_string_append_printf(out, "</office:meta>\n");
|
|
1987
|
+
element *header;
|
|
1988
|
+
header = metadata_for_key("odfheader",elt);
|
|
1989
|
+
if (header != NULL) {
|
|
1990
|
+
print_raw_element(out,header->children);
|
|
1991
|
+
}
|
|
1992
|
+
break;
|
|
1993
|
+
case METAKEY:
|
|
1994
|
+
if (strcmp(elt->contents.str, "title") == 0) {
|
|
1995
|
+
g_string_append_printf(out, "<dc:title>");
|
|
1996
|
+
print_odf_element(out, elt->children);
|
|
1997
|
+
g_string_append_printf(out,"</dc:title>\n");
|
|
1998
|
+
} else if (strcmp(elt->contents.str, "css") == 0) {
|
|
1999
|
+
} else if (strcmp(elt->contents.str, "baseheaderlevel") == 0) {
|
|
2000
|
+
base_header_level = atoi(elt->children->contents.str);
|
|
2001
|
+
} else if (strcmp(elt->contents.str, "odfheaderlevel") == 0) {
|
|
2002
|
+
base_header_level = atoi(elt->children->contents.str);
|
|
2003
|
+
} else if (strcmp(elt->contents.str, "xhtmlheader") == 0) {
|
|
2004
|
+
} else if (strcmp(elt->contents.str, "htmlheader") == 0) {
|
|
2005
|
+
} else if (strcmp(elt->contents.str, "odfheader") == 0) {
|
|
2006
|
+
} else if (strcmp(elt->contents.str, "latexfooter") == 0) {
|
|
2007
|
+
} else if (strcmp(elt->contents.str, "latexinput") == 0) {
|
|
2008
|
+
} else if (strcmp(elt->contents.str, "latexmode") == 0) {
|
|
2009
|
+
} else if (strcmp(elt->contents.str, "keywords") == 0) {
|
|
2010
|
+
g_string_append_printf(out, "<meta:keyword>");
|
|
2011
|
+
print_odf_element(out,elt->children);
|
|
2012
|
+
g_string_append_printf(out, "</meta:keyword>\n");
|
|
2013
|
+
} else if (strcmp(elt->contents.str, "quoteslanguage") == 0) {
|
|
2014
|
+
label = label_from_element_list(elt->children, 0);
|
|
2015
|
+
if (strcmp(label, "dutch") == 0) { language = DUTCH; } else
|
|
2016
|
+
if (strcmp(label, "german") == 0) { language = GERMAN; } else
|
|
2017
|
+
if (strcmp(label, "germanguillemets") == 0) { language = GERMANGUILL; } else
|
|
2018
|
+
if (strcmp(label, "french") == 0) { language = FRENCH; } else
|
|
2019
|
+
if (strcmp(label, "swedish") == 0) { language = SWEDISH; }
|
|
2020
|
+
free(label);
|
|
2021
|
+
} else {
|
|
2022
|
+
g_string_append_printf(out, "<meta:user-defined meta:name=\"");
|
|
2023
|
+
print_odf_string(out,elt->contents.str);
|
|
2024
|
+
g_string_append_printf(out, "\">");
|
|
2025
|
+
print_odf_element(out, elt->children);
|
|
2026
|
+
g_string_append_printf(out,"</meta:user-defined>\n");
|
|
2027
|
+
}
|
|
2028
|
+
break;
|
|
2029
|
+
case METAVALUE:
|
|
2030
|
+
print_odf_string(out, elt->contents.str);
|
|
2031
|
+
break;
|
|
2032
|
+
case FOOTER:
|
|
2033
|
+
break;
|
|
2034
|
+
case HEADINGSECTION:
|
|
2035
|
+
print_odf_element_list(out, elt->children);
|
|
2036
|
+
break;
|
|
2037
|
+
case TABLE:
|
|
2038
|
+
g_string_append_printf(out,"\n<table:table>\n");
|
|
2039
|
+
print_odf_element_list(out, elt->children);
|
|
2040
|
+
g_string_append_printf(out, "</table:table>");
|
|
2041
|
+
/* print caption if present */
|
|
2042
|
+
if (elt->children->key == TABLECAPTION) {
|
|
2043
|
+
if (elt->children->children->key == TABLELABEL) {
|
|
2044
|
+
label = label_from_element_list(elt->children->children->children,0);
|
|
2045
|
+
} else {
|
|
2046
|
+
label = label_from_element_list(elt->children->children,0);
|
|
2047
|
+
}
|
|
2048
|
+
g_string_append_printf(out,"<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>:", label);
|
|
2049
|
+
print_odf_element_list(out,elt->children->children);
|
|
2050
|
+
g_string_append_printf(out, "<text:bookmark-end text:name=\"%s\"/></text:p>\n",label);
|
|
2051
|
+
free(label);
|
|
2052
|
+
}
|
|
2053
|
+
break;
|
|
2054
|
+
case TABLESEPARATOR:
|
|
2055
|
+
table_alignment = elt->contents.str;
|
|
2056
|
+
break;
|
|
2057
|
+
case TABLECAPTION:
|
|
2058
|
+
break;
|
|
2059
|
+
case TABLELABEL:
|
|
2060
|
+
break;
|
|
2061
|
+
case TABLEHEAD:
|
|
2062
|
+
for (table_column=0;table_column<strlen(table_alignment);table_column++) {
|
|
2063
|
+
g_string_append_printf(out, "<table:table-column/>\n");
|
|
2064
|
+
}
|
|
2065
|
+
cell_type = 'h';
|
|
2066
|
+
print_odf_element_list(out, elt->children);
|
|
2067
|
+
cell_type = 'd';
|
|
2068
|
+
break;
|
|
2069
|
+
case TABLEBODY:
|
|
2070
|
+
print_odf_element_list(out,elt->children);
|
|
2071
|
+
break;
|
|
2072
|
+
case TABLEROW:
|
|
2073
|
+
g_string_append_printf(out, "<table:table-row>\n");
|
|
2074
|
+
table_column = 0;
|
|
2075
|
+
print_odf_element_list(out,elt->children);
|
|
2076
|
+
g_string_append_printf(out,"</table:table-row>\n");
|
|
2077
|
+
break;
|
|
2078
|
+
case TABLECELL:
|
|
2079
|
+
g_string_append_printf(out, "<table:table-cell");
|
|
2080
|
+
if ((elt->children != NULL) && (elt->children->key == CELLSPAN)) {
|
|
2081
|
+
g_string_append_printf(out, " table:number-columns-spanned=\"%d\"",(int)strlen(elt->children->contents.str)+1);
|
|
2082
|
+
}
|
|
2083
|
+
g_string_append_printf(out,">\n<text:p");
|
|
2084
|
+
if (cell_type == 'h') {
|
|
2085
|
+
g_string_append_printf(out, " text:style-name=\"Table_20_Heading\"");
|
|
2086
|
+
} else {
|
|
2087
|
+
if ( strncmp(&table_alignment[table_column],"r",1) == 0) {
|
|
2088
|
+
g_string_append_printf(out, " text:style-name=\"MMD-Table-Right\"");
|
|
2089
|
+
} else if ( strncmp(&table_alignment[table_column],"c",1) == 0) {
|
|
2090
|
+
g_string_append_printf(out, " text:style-name=\"MMD-Table-Center\"");
|
|
2091
|
+
} else {
|
|
2092
|
+
g_string_append_printf(out, " text:style-name=\"MMD-Table\"");
|
|
2093
|
+
}
|
|
2094
|
+
}
|
|
2095
|
+
g_string_append_printf(out, ">");
|
|
2096
|
+
print_odf_element_list(out,elt->children);
|
|
2097
|
+
g_string_append_printf(out, "</text:p>\n</table:table-cell>\n");
|
|
2098
|
+
table_column++;
|
|
2099
|
+
break;
|
|
2100
|
+
case CELLSPAN:
|
|
2101
|
+
break;
|
|
2102
|
+
case MATHSPAN:
|
|
2103
|
+
if ( elt->contents.str[strlen(elt->contents.str)-1] == ']') {
|
|
2104
|
+
elt->contents.str[strlen(elt->contents.str)-3] = '\0';
|
|
2105
|
+
g_string_append_printf(out, "<text:span text:style-name=\"math\">%s\\]</text:span>", elt->contents.str);
|
|
2106
|
+
} else {
|
|
2107
|
+
elt->contents.str[strlen(elt->contents.str)-3] = '\0';
|
|
2108
|
+
g_string_append_printf(out, "<text:span text:style-name=\"math\">%s\\)</text:span>", elt->contents.str);
|
|
2109
|
+
}
|
|
2110
|
+
break; default:
|
|
2111
|
+
fprintf(stderr, "print_html_element encountered unknown element key = %d\n", elt->key);
|
|
2112
|
+
exit(EXIT_FAILURE);
|
|
2113
|
+
}
|
|
2114
|
+
}
|
|
2115
|
+
|
|
2116
|
+
/**********************************************************************
|
|
2117
|
+
|
|
2118
|
+
Parameterized function for printing an Element.
|
|
2119
|
+
|
|
2120
|
+
***********************************************************************/
|
|
2121
|
+
|
|
2122
|
+
void print_element_list(GString *out, element *elt, int format, int exts) {
|
|
2123
|
+
/* Initialize globals */
|
|
2124
|
+
endnotes = NULL;
|
|
2125
|
+
notenumber = 0;
|
|
2126
|
+
|
|
2127
|
+
/* And MultiMarkdown globals */
|
|
2128
|
+
base_header_level = 1;
|
|
2129
|
+
language = ENGLISH;
|
|
2130
|
+
html_footer = FALSE;
|
|
2131
|
+
no_latex_footnote = FALSE;
|
|
2132
|
+
|
|
2133
|
+
extensions = exts;
|
|
2134
|
+
padded = 2; /* set padding to 2, so no extra blank lines at beginning */
|
|
2135
|
+
|
|
2136
|
+
format = find_latex_mode(format, elt);
|
|
2137
|
+
switch (format) {
|
|
2138
|
+
case HTML_FORMAT:
|
|
2139
|
+
print_html_element_list(out, elt, false);
|
|
2140
|
+
if (endnotes != NULL) {
|
|
2141
|
+
pad(out, 2);
|
|
2142
|
+
print_html_endnotes(out);
|
|
2143
|
+
}
|
|
2144
|
+
if (html_footer == TRUE) print_html_footer(out, false);
|
|
2145
|
+
break;
|
|
2146
|
+
case LATEX_FORMAT:
|
|
2147
|
+
print_latex_element_list(out, elt);
|
|
2148
|
+
break;
|
|
2149
|
+
case MEMOIR_FORMAT:
|
|
2150
|
+
print_memoir_element_list(out, elt);
|
|
2151
|
+
break;
|
|
2152
|
+
case BEAMER_FORMAT:
|
|
2153
|
+
print_beamer_element_list(out, elt);
|
|
2154
|
+
break;
|
|
2155
|
+
case OPML_FORMAT:
|
|
2156
|
+
g_string_append_printf(out, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<opml version=\"1.0\">\n");
|
|
2157
|
+
g_string_append_printf(out, "<body>\n");
|
|
2158
|
+
print_opml_element_list(out, elt);
|
|
2159
|
+
if (html_footer == TRUE) print_opml_metadata(out, elt);
|
|
2160
|
+
g_string_append_printf(out, "</body>\n</opml>");
|
|
2161
|
+
break;
|
|
2162
|
+
case ODF_FORMAT:
|
|
2163
|
+
print_odf_header(out);
|
|
2164
|
+
if (elt->key == METADATA) {
|
|
2165
|
+
/* print metadata */
|
|
2166
|
+
print_odf_element(out,elt);
|
|
2167
|
+
elt = elt->next;
|
|
2168
|
+
}
|
|
2169
|
+
g_string_append_printf(out, "<office:body>\n<office:text>\n");
|
|
2170
|
+
if (elt != NULL) print_odf_element_list(out,elt);
|
|
2171
|
+
print_odf_footer(out);
|
|
2172
|
+
break;
|
|
2173
|
+
case ODF_BODY_FORMAT:
|
|
2174
|
+
if (elt != NULL) print_odf_body_element_list(out, elt);
|
|
2175
|
+
break;
|
|
2176
|
+
case GROFF_MM_FORMAT:
|
|
2177
|
+
print_groff_mm_element_list(out, elt);
|
|
2178
|
+
break;
|
|
2179
|
+
default:
|
|
2180
|
+
fprintf(stderr, "print_element - unknown format = %d\n", format);
|
|
2181
|
+
exit(EXIT_FAILURE);
|
|
2182
|
+
}
|
|
2183
|
+
}
|
|
2184
|
+
|
|
2185
|
+
|
|
2186
|
+
/**********************************************************************
|
|
2187
|
+
|
|
2188
|
+
MultiMarkdown Routines - Used for generating "complete" documents
|
|
2189
|
+
|
|
2190
|
+
***********************************************************************/
|
|
2191
|
+
|
|
2192
|
+
|
|
2193
|
+
void print_html_header(GString *out, element *elt, bool obfuscate) {
|
|
2194
|
+
g_string_append_printf(out,
|
|
2195
|
+
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>\n<!DOCTYPE html>\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n");
|
|
2196
|
+
|
|
2197
|
+
print_html_element_list(out, elt->children, obfuscate);
|
|
2198
|
+
g_string_append_printf(out, "</head>\n<body>\n");
|
|
2199
|
+
}
|
|
2200
|
+
|
|
2201
|
+
|
|
2202
|
+
void print_html_footer(GString *out, bool obfuscate) {
|
|
2203
|
+
g_string_append_printf(out, "\n</body>\n</html>");
|
|
2204
|
+
}
|
|
2205
|
+
|
|
2206
|
+
|
|
2207
|
+
void print_latex_header(GString *out, element *elt) {
|
|
2208
|
+
print_latex_element_list(out, elt->children);
|
|
2209
|
+
}
|
|
2210
|
+
|
|
2211
|
+
|
|
2212
|
+
void print_latex_footer(GString *out) {
|
|
2213
|
+
if (latex_footer != NULL) {
|
|
2214
|
+
pad(out,2);
|
|
2215
|
+
g_string_append_printf(out, "\\input{%s}\n", latex_footer);
|
|
2216
|
+
}
|
|
2217
|
+
g_string_append_printf(out, "\n\\end{document}");
|
|
2218
|
+
}
|
|
2219
|
+
|
|
2220
|
+
|
|
2221
|
+
/* print_memoir_element_list - print an element as LaTeX for memoir class */
|
|
2222
|
+
void print_memoir_element_list(GString *out, element *list) {
|
|
2223
|
+
while (list != NULL) {
|
|
2224
|
+
print_memoir_element(out, list);
|
|
2225
|
+
list = list->next;
|
|
2226
|
+
}
|
|
2227
|
+
}
|
|
2228
|
+
|
|
2229
|
+
|
|
2230
|
+
/* print_memoir_element - print an element as LaTeX for memoir class */
|
|
2231
|
+
static void print_memoir_element(GString *out, element *elt) {
|
|
2232
|
+
int lev;
|
|
2233
|
+
char *label;
|
|
2234
|
+
switch (elt->key) {
|
|
2235
|
+
case VERBATIM:
|
|
2236
|
+
pad(out, 1);
|
|
2237
|
+
g_string_append_printf(out, "\n\\begin{adjustwidth}{2.5em}{2.5em}\n\\begin{verbatim}\n\n");
|
|
2238
|
+
print_raw_element(out, elt);
|
|
2239
|
+
g_string_append_printf(out, "\n\\end{verbatim}\n\\end{adjustwidth}");
|
|
2240
|
+
padded = 0;
|
|
2241
|
+
break;
|
|
2242
|
+
case HEADINGSECTION:
|
|
2243
|
+
print_memoir_element_list(out, elt->children);
|
|
2244
|
+
break;
|
|
2245
|
+
case DEFLIST:
|
|
2246
|
+
g_string_append_printf(out, "\\begin{description}");
|
|
2247
|
+
padded = 0;
|
|
2248
|
+
print_memoir_element_list(out, elt->children);
|
|
2249
|
+
pad(out,1);
|
|
2250
|
+
g_string_append_printf(out, "\\end{description}");
|
|
2251
|
+
padded = 0;
|
|
2252
|
+
break;
|
|
2253
|
+
case DEFINITION:
|
|
2254
|
+
pad(out,2);
|
|
2255
|
+
padded = 2;
|
|
2256
|
+
print_memoir_element_list(out, elt->children);
|
|
2257
|
+
padded = 0;
|
|
2258
|
+
break;
|
|
2259
|
+
default:
|
|
2260
|
+
/* most things are not changed for memoir output */
|
|
2261
|
+
print_latex_element(out, elt);
|
|
2262
|
+
}
|
|
2263
|
+
}
|
|
2264
|
+
|
|
2265
|
+
|
|
2266
|
+
/* print_beamer_element_list - print an element as LaTeX for beamer class */
|
|
2267
|
+
void print_beamer_element_list(GString *out, element *list) {
|
|
2268
|
+
while (list != NULL) {
|
|
2269
|
+
print_beamer_element(out, list);
|
|
2270
|
+
list = list->next;
|
|
2271
|
+
}
|
|
2272
|
+
}
|
|
2273
|
+
|
|
2274
|
+
static void print_beamer_endnotes(GString *out) {
|
|
2275
|
+
GSList *note;
|
|
2276
|
+
element *note_elt;
|
|
2277
|
+
if (endnotes == NULL)
|
|
2278
|
+
return;
|
|
2279
|
+
note = g_slist_reverse(endnotes);
|
|
2280
|
+
pad(out,2);
|
|
2281
|
+
g_string_append_printf(out, "\\part{Bibliography}\n\\begin{frame}[allowframebreaks]\n\\frametitle{Bibliography}\n\\def\\newblock{}\n\\begin{thebibliography}{0}\n");
|
|
2282
|
+
while (note != NULL) {
|
|
2283
|
+
note_elt = note->data;
|
|
2284
|
+
pad(out, 1);
|
|
2285
|
+
g_string_append_printf(out, "\\bibitem{%s}\n", note_elt->contents.str);
|
|
2286
|
+
padded=2;
|
|
2287
|
+
print_latex_element_list(out, note_elt);
|
|
2288
|
+
pad(out, 1);
|
|
2289
|
+
note = note->next;
|
|
2290
|
+
}
|
|
2291
|
+
pad(out, 1);
|
|
2292
|
+
g_string_append_printf(out, "\\end{thebibliography}\n\\end{frame}\n\n");
|
|
2293
|
+
padded = 2;
|
|
2294
|
+
g_slist_free(endnotes);
|
|
2295
|
+
}
|
|
2296
|
+
|
|
2297
|
+
/* print_beamer_element - print an element as LaTeX for beamer class */
|
|
2298
|
+
static void print_beamer_element(GString *out, element *elt) {
|
|
2299
|
+
int lev;
|
|
2300
|
+
char *label;
|
|
2301
|
+
switch (elt->key) {
|
|
2302
|
+
case FOOTER:
|
|
2303
|
+
print_beamer_endnotes(out);
|
|
2304
|
+
g_string_append_printf(out, "\\mode<all>\n");
|
|
2305
|
+
print_latex_footer(out);
|
|
2306
|
+
g_string_append_printf(out, "\\mode*\n");
|
|
2307
|
+
break;
|
|
2308
|
+
case LISTITEM:
|
|
2309
|
+
pad(out, 1);
|
|
2310
|
+
g_string_append_printf(out, "\\item<+-> ");
|
|
2311
|
+
padded = 2;
|
|
2312
|
+
print_latex_element_list(out, elt->children);
|
|
2313
|
+
g_string_append_printf(out, "\n");
|
|
2314
|
+
break;
|
|
2315
|
+
case HEADINGSECTION:
|
|
2316
|
+
if (elt->children->key -H1 + base_header_level == 3) {
|
|
2317
|
+
pad(out,2);
|
|
2318
|
+
g_string_append_printf(out, "\\begin{frame}");
|
|
2319
|
+
if (list_contains_key(elt->children,VERBATIM)) {
|
|
2320
|
+
g_string_append_printf(out, "[fragile]");
|
|
2321
|
+
}
|
|
2322
|
+
padded = 0;
|
|
2323
|
+
print_beamer_element_list(out, elt->children);
|
|
2324
|
+
g_string_append_printf(out, "\n\n\\end{frame}\n\n");
|
|
2325
|
+
padded = 2;
|
|
2326
|
+
} else if (elt->children->key -H1 + base_header_level == 4) {
|
|
2327
|
+
pad(out, 1);
|
|
2328
|
+
g_string_append_printf(out, "\\mode<article>{\n");
|
|
2329
|
+
padded = 0;
|
|
2330
|
+
print_beamer_element_list(out, elt->children->next);
|
|
2331
|
+
g_string_append_printf(out, "\n\n}\n\n");
|
|
2332
|
+
padded = 2;
|
|
2333
|
+
} else {
|
|
2334
|
+
print_beamer_element_list(out, elt->children);
|
|
2335
|
+
}
|
|
2336
|
+
break;
|
|
2337
|
+
case H1: case H2: case H3: case H4: case H5: case H6:
|
|
2338
|
+
pad(out, 2);
|
|
2339
|
+
lev = elt->key - H1 + base_header_level; /* assumes H1 ... H6 are in order */
|
|
2340
|
+
switch (lev) {
|
|
2341
|
+
case 1:
|
|
2342
|
+
g_string_append_printf(out, "\\part{");
|
|
2343
|
+
break;
|
|
2344
|
+
case 2:
|
|
2345
|
+
g_string_append_printf(out, "\\section{");
|
|
2346
|
+
break;
|
|
2347
|
+
case 3:
|
|
2348
|
+
g_string_append_printf(out, "\\frametitle{");
|
|
2349
|
+
break;
|
|
2350
|
+
default:
|
|
2351
|
+
g_string_append_printf(out, "\\emph{");
|
|
2352
|
+
break;
|
|
2353
|
+
}
|
|
2354
|
+
/* generate a label for each header (MMD);
|
|
2355
|
+
don't allow footnotes since invalid here */
|
|
2356
|
+
no_latex_footnote = TRUE;
|
|
2357
|
+
if (elt->children->key == AUTOLABEL) {
|
|
2358
|
+
label = label_from_string(elt->children->contents.str,0);
|
|
2359
|
+
print_latex_element_list(out, elt->children->next);
|
|
2360
|
+
} else {
|
|
2361
|
+
label = label_from_element_list(elt->children,0);
|
|
2362
|
+
print_latex_element_list(out, elt->children);
|
|
2363
|
+
}
|
|
2364
|
+
no_latex_footnote = FALSE;
|
|
2365
|
+
g_string_append_printf(out, "}\n\\label{");
|
|
2366
|
+
g_string_append_printf(out, "%s", label);
|
|
2367
|
+
g_string_append_printf(out, "}\n");
|
|
2368
|
+
free(label);
|
|
2369
|
+
padded = 1;
|
|
2370
|
+
break;
|
|
2371
|
+
default:
|
|
2372
|
+
print_latex_element(out, elt);
|
|
2373
|
+
}
|
|
2374
|
+
}
|
|
2375
|
+
|
|
2376
|
+
|
|
2377
|
+
element * print_html_headingsection(GString *out, element *list, bool obfuscate) {
|
|
2378
|
+
element *base = list;
|
|
2379
|
+
print_html_element_list(out, list->children, obfuscate);
|
|
2380
|
+
|
|
2381
|
+
list = list->next;
|
|
2382
|
+
while ( (list != NULL) && (list->key == HEADINGSECTION) && (list->children->key > base->children->key) && (list->children->key <= H6)) {
|
|
2383
|
+
list = print_html_headingsection(out, list, obfuscate);
|
|
2384
|
+
}
|
|
2385
|
+
|
|
2386
|
+
return list;
|
|
2387
|
+
}
|
|
2388
|
+
|
|
2389
|
+
/* look for "LaTeX Mode" metadata and change format to match */
|
|
2390
|
+
static int find_latex_mode(int format, element *list) {
|
|
2391
|
+
element *latex_mode;
|
|
2392
|
+
char *label;
|
|
2393
|
+
|
|
2394
|
+
if (format != LATEX_FORMAT) return format;
|
|
2395
|
+
|
|
2396
|
+
if (list_contains_key(list,METAKEY)) {
|
|
2397
|
+
latex_mode = metadata_for_key("latexmode", list);
|
|
2398
|
+
if ( latex_mode != NULL) {
|
|
2399
|
+
label = label_from_element_list(latex_mode->children, 0);
|
|
2400
|
+
if (strcmp(label, "beamer") == 0) { format = BEAMER_FORMAT; } else
|
|
2401
|
+
if (strcmp(label, "memoir") == 0) { format = MEMOIR_FORMAT; }
|
|
2402
|
+
free(label);
|
|
2403
|
+
}
|
|
2404
|
+
return format;
|
|
2405
|
+
} else {
|
|
2406
|
+
return format;
|
|
2407
|
+
}
|
|
2408
|
+
}
|
|
2409
|
+
|
|
2410
|
+
|
|
2411
|
+
/* find specified metadata key, if present */
|
|
2412
|
+
element * metadata_for_key(char *key, element *list) {
|
|
2413
|
+
element *step = NULL;
|
|
2414
|
+
step = list;
|
|
2415
|
+
char *label;
|
|
2416
|
+
|
|
2417
|
+
label = label_from_string(key,0);
|
|
2418
|
+
|
|
2419
|
+
while (step != NULL) {
|
|
2420
|
+
if (step->key == METADATA) {
|
|
2421
|
+
/* search METAKEY children */
|
|
2422
|
+
step = step->children;
|
|
2423
|
+
while ( step != NULL) {
|
|
2424
|
+
if (strcmp(step->contents.str, label) == 0) {
|
|
2425
|
+
free(label);
|
|
2426
|
+
return step;
|
|
2427
|
+
}
|
|
2428
|
+
step = step->next;
|
|
2429
|
+
}
|
|
2430
|
+
free(label);
|
|
2431
|
+
return NULL;
|
|
2432
|
+
}
|
|
2433
|
+
step = step->next;
|
|
2434
|
+
}
|
|
2435
|
+
free(label);
|
|
2436
|
+
return NULL;
|
|
2437
|
+
}
|
|
2438
|
+
|
|
2439
|
+
|
|
2440
|
+
/* find specified metadata key, if present */
|
|
2441
|
+
char * metavalue_for_key(char *key, element *list) {
|
|
2442
|
+
element *step = NULL;
|
|
2443
|
+
step = list;
|
|
2444
|
+
char *label;
|
|
2445
|
+
char *result;
|
|
2446
|
+
|
|
2447
|
+
label = label_from_string(key,0);
|
|
2448
|
+
|
|
2449
|
+
while (step != NULL) {
|
|
2450
|
+
if (step->key == METADATA) {
|
|
2451
|
+
/* search METAKEY children */
|
|
2452
|
+
step = step->children;
|
|
2453
|
+
while ( step != NULL) {
|
|
2454
|
+
if (strcmp(step->contents.str, label) == 0) {
|
|
2455
|
+
/* Found a match */
|
|
2456
|
+
if ((strcmp(label,"latexmode") == 0) ||
|
|
2457
|
+
(strcmp(label,"quoteslanguage") == 0)) {
|
|
2458
|
+
result = label_from_string(step->children->contents.str,0);
|
|
2459
|
+
} else {
|
|
2460
|
+
result = strdup(step->children->contents.str);
|
|
2461
|
+
}
|
|
2462
|
+
free(label);
|
|
2463
|
+
return result;
|
|
2464
|
+
}
|
|
2465
|
+
step = step->next;
|
|
2466
|
+
}
|
|
2467
|
+
free(label);
|
|
2468
|
+
return NULL;
|
|
2469
|
+
}
|
|
2470
|
+
step = step->next;
|
|
2471
|
+
}
|
|
2472
|
+
free(label);
|
|
2473
|
+
return NULL;
|
|
2474
|
+
}
|
|
2475
|
+
|
|
2476
|
+
/* find attribute, if present */
|
|
2477
|
+
element * element_for_attribute(char *querystring, element *list) {
|
|
2478
|
+
element *step = NULL;
|
|
2479
|
+
step = list;
|
|
2480
|
+
char *query;
|
|
2481
|
+
query = label_from_string(querystring,0);
|
|
2482
|
+
|
|
2483
|
+
while (step != NULL) {
|
|
2484
|
+
if (strcmp(step->contents.str,query) == 0) {
|
|
2485
|
+
free(query);
|
|
2486
|
+
return step;
|
|
2487
|
+
}
|
|
2488
|
+
step = step->next;
|
|
2489
|
+
}
|
|
2490
|
+
free(query);
|
|
2491
|
+
return NULL;
|
|
2492
|
+
}
|
|
2493
|
+
|
|
2494
|
+
/* convert attribute to dimensions suitable for LaTeX or ODF */
|
|
2495
|
+
/* returns c string that needs to be freed */
|
|
2496
|
+
|
|
2497
|
+
char * dimension_for_attribute(char *querystring, element *list) {
|
|
2498
|
+
element *attribute;
|
|
2499
|
+
char *dimension;
|
|
2500
|
+
char *ptr;
|
|
2501
|
+
int i;
|
|
2502
|
+
char *upper;
|
|
2503
|
+
GString *result;
|
|
2504
|
+
|
|
2505
|
+
attribute = element_for_attribute(querystring, list);
|
|
2506
|
+
if (attribute == NULL) return NULL;
|
|
2507
|
+
|
|
2508
|
+
dimension = strdup(attribute->children->contents.str);
|
|
2509
|
+
upper = strdup(attribute->children->contents.str);
|
|
2510
|
+
|
|
2511
|
+
for(i = 0; dimension[ i ]; i++)
|
|
2512
|
+
dimension[i] = tolower(dimension[ i ]);
|
|
2513
|
+
|
|
2514
|
+
for(i = 0; upper[ i ]; i++)
|
|
2515
|
+
upper[i] = toupper(upper[ i ]);
|
|
2516
|
+
|
|
2517
|
+
if (strstr(dimension, "px")) {
|
|
2518
|
+
ptr = strstr(dimension,"px");
|
|
2519
|
+
ptr[0] = '\0';
|
|
2520
|
+
strcat(ptr,"pt");
|
|
2521
|
+
}
|
|
2522
|
+
|
|
2523
|
+
result = g_string_new(dimension);
|
|
2524
|
+
|
|
2525
|
+
if ((strcmp(dimension,upper) == 0) && (dimension[strlen(dimension) -1] != '%')) {
|
|
2526
|
+
/* no units */
|
|
2527
|
+
g_string_append_printf(result, "pt");
|
|
2528
|
+
}
|
|
2529
|
+
|
|
2530
|
+
free(upper);
|
|
2531
|
+
free(dimension);
|
|
2532
|
+
|
|
2533
|
+
dimension = result->str;
|
|
2534
|
+
g_string_free(result, false);
|
|
2535
|
+
return(dimension);
|
|
2536
|
+
}
|
|
2537
|
+
|
|
2538
|
+
/* Check metadata keys and determine if I need a complete document */
|
|
2539
|
+
static bool is_html_complete_doc(element *meta) {
|
|
2540
|
+
element *step;
|
|
2541
|
+
step = meta->children;
|
|
2542
|
+
|
|
2543
|
+
while (step != NULL) {
|
|
2544
|
+
if ((strcmp(step->contents.str, "baseheaderlevel") != 0) &&
|
|
2545
|
+
(strcmp(step->contents.str, "xhtmlheaderlevel") != 0) &&
|
|
2546
|
+
(strcmp(step->contents.str, "htmlheaderlevel") != 0) &&
|
|
2547
|
+
(strcmp(step->contents.str, "latexheaderlevel") != 0) &&
|
|
2548
|
+
(strcmp(step->contents.str, "odfheaderlevel") != 0) &&
|
|
2549
|
+
(strcmp(step->contents.str, "quoteslanguage") != 0))
|
|
2550
|
+
{
|
|
2551
|
+
return TRUE;
|
|
2552
|
+
}
|
|
2553
|
+
step = step->next;
|
|
2554
|
+
}
|
|
2555
|
+
|
|
2556
|
+
return FALSE;
|
|
2557
|
+
}
|
|
2558
|
+
|
|
2559
|
+
|
|
2560
|
+
/* print_opml_element_list - print an element list as OPML */
|
|
2561
|
+
void print_opml_element_list(GString *out, element *list) {
|
|
2562
|
+
int lev;
|
|
2563
|
+
while (list != NULL) {
|
|
2564
|
+
if (list->key == HEADINGSECTION) {
|
|
2565
|
+
lev = list->children->key;
|
|
2566
|
+
|
|
2567
|
+
print_opml_section_and_children(out, list);
|
|
2568
|
+
|
|
2569
|
+
while ((list->next != NULL) && (list->next->key == HEADINGSECTION)
|
|
2570
|
+
&& (list->next->children->key > lev)) {
|
|
2571
|
+
list = list->next;
|
|
2572
|
+
}
|
|
2573
|
+
} else {
|
|
2574
|
+
print_opml_element(out, list);
|
|
2575
|
+
}
|
|
2576
|
+
list = list->next;
|
|
2577
|
+
}
|
|
2578
|
+
}
|
|
2579
|
+
|
|
2580
|
+
/* print_opml_section_and_children - print section and "children" */
|
|
2581
|
+
static void print_opml_section_and_children(GString *out, element *list) {
|
|
2582
|
+
int lev = list->children->key;
|
|
2583
|
+
/* Print current section, aka "parent" */
|
|
2584
|
+
print_opml_element(out, list);
|
|
2585
|
+
|
|
2586
|
+
/* check for children */
|
|
2587
|
+
while ((list->next != NULL) && (list->next->key == HEADINGSECTION)
|
|
2588
|
+
&& (list->next->children->key > lev)) {
|
|
2589
|
+
/* next item is also HEADINGSECTION and is child */
|
|
2590
|
+
if (list->next->children->key - lev == 1)
|
|
2591
|
+
print_opml_section_and_children(out,list->next);
|
|
2592
|
+
list = list->next;
|
|
2593
|
+
}
|
|
2594
|
+
g_string_append_printf(out, "</outline>\n");
|
|
2595
|
+
}
|
|
2596
|
+
|
|
2597
|
+
/* print_opml_element - print an element as OPML */
|
|
2598
|
+
static void print_opml_element(GString *out, element *elt) {
|
|
2599
|
+
switch (elt->key) {
|
|
2600
|
+
case METADATA:
|
|
2601
|
+
/* Metadata is present, so will need to be appended */
|
|
2602
|
+
html_footer = true;
|
|
2603
|
+
break;
|
|
2604
|
+
case METAKEY:
|
|
2605
|
+
g_string_append_printf(out, "<outline text=\"");
|
|
2606
|
+
print_opml_string(out,elt->contents.str);
|
|
2607
|
+
g_string_append_printf(out, "\" _note=\"");
|
|
2608
|
+
print_opml_string(out, elt->children->contents.str);
|
|
2609
|
+
g_string_append_printf(out, "\"/>");
|
|
2610
|
+
break;
|
|
2611
|
+
case HEADINGSECTION:
|
|
2612
|
+
/* Need to handle "nesting" properly */
|
|
2613
|
+
g_string_append_printf(out, "<outline ");
|
|
2614
|
+
|
|
2615
|
+
/* Print header */
|
|
2616
|
+
print_opml_element(out,elt->children);
|
|
2617
|
+
|
|
2618
|
+
/* print remainder of paragraphs as note */
|
|
2619
|
+
g_string_append_printf(out, " _note=\"");
|
|
2620
|
+
print_opml_element_list(out,elt->children->next);
|
|
2621
|
+
g_string_append_printf(out, "\">");
|
|
2622
|
+
break;
|
|
2623
|
+
case H1: case H2: case H3: case H4: case H5: case H6:
|
|
2624
|
+
g_string_append_printf(out, "text=\"");
|
|
2625
|
+
print_opml_string(out, elt->contents.str);
|
|
2626
|
+
g_string_append_printf(out,"\"");
|
|
2627
|
+
break;
|
|
2628
|
+
case VERBATIM:
|
|
2629
|
+
print_opml_string(out, elt->contents.str);
|
|
2630
|
+
break;
|
|
2631
|
+
case SPACE:
|
|
2632
|
+
print_opml_string(out, elt->contents.str);
|
|
2633
|
+
break;
|
|
2634
|
+
case STR:
|
|
2635
|
+
print_opml_string(out, elt->contents.str);
|
|
2636
|
+
break;
|
|
2637
|
+
case LINEBREAK:
|
|
2638
|
+
g_string_append_printf(out, " ");
|
|
2639
|
+
break;
|
|
2640
|
+
case PLAIN:
|
|
2641
|
+
print_opml_element_list(out,elt->children);
|
|
2642
|
+
if ((elt->next != NULL) && (elt->next->key == PLAIN)) {
|
|
2643
|
+
g_string_append_printf(out, " ");
|
|
2644
|
+
}
|
|
2645
|
+
break;
|
|
2646
|
+
default:
|
|
2647
|
+
fprintf(stderr, "print_opml_element encountered unknown element key = %d\n", elt->key);
|
|
2648
|
+
/*exit(EXIT_FAILURE);*/
|
|
2649
|
+
}
|
|
2650
|
+
}
|
|
2651
|
+
|
|
2652
|
+
/* print_opml_string - print string, escaping for OPML */
|
|
2653
|
+
static void print_opml_string(GString *out, char *str) {
|
|
2654
|
+
while (*str != '\0') {
|
|
2655
|
+
switch (*str) {
|
|
2656
|
+
case '&':
|
|
2657
|
+
g_string_append_printf(out, "&");
|
|
2658
|
+
break;
|
|
2659
|
+
case '<':
|
|
2660
|
+
g_string_append_printf(out, "<");
|
|
2661
|
+
break;
|
|
2662
|
+
case '>':
|
|
2663
|
+
g_string_append_printf(out, ">");
|
|
2664
|
+
break;
|
|
2665
|
+
case '"':
|
|
2666
|
+
g_string_append_printf(out, """);
|
|
2667
|
+
break;
|
|
2668
|
+
case '\n': case '\r':
|
|
2669
|
+
g_string_append_printf(out, " ");
|
|
2670
|
+
break;
|
|
2671
|
+
default:
|
|
2672
|
+
g_string_append_c(out, *str);
|
|
2673
|
+
}
|
|
2674
|
+
str++;
|
|
2675
|
+
}
|
|
2676
|
+
}
|
|
2677
|
+
|
|
2678
|
+
|
|
2679
|
+
/* print_opml_metadata - add metadata as last outline item */
|
|
2680
|
+
static void print_opml_metadata(GString *out, element *elt) {
|
|
2681
|
+
g_string_append_printf(out, "<outline text=\"Metadata\">\n");
|
|
2682
|
+
print_opml_element_list(out, elt->children);
|
|
2683
|
+
g_string_append_printf(out, "</outline>");
|
|
2684
|
+
}
|
|
2685
|
+
|
|
2686
|
+
/* print_odf_body_element - print an element as ODF */
|
|
2687
|
+
void print_odf_body_element(GString *out, element *elt) {
|
|
2688
|
+
switch (elt->key) {
|
|
2689
|
+
case PARA:
|
|
2690
|
+
print_odf_element_list(out, elt->children);
|
|
2691
|
+
break;
|
|
2692
|
+
default:
|
|
2693
|
+
print_odf_element(out, elt);
|
|
2694
|
+
}
|
|
2695
|
+
}
|
|
2696
|
+
|
|
2697
|
+
/* print_odf_body_element_list - print an element list as ODF for specific
|
|
2698
|
+
places, eg image captions */
|
|
2699
|
+
void print_odf_body_element_list(GString *out, element *list) {
|
|
2700
|
+
while (list != NULL) {
|
|
2701
|
+
print_odf_body_element(out, list);
|
|
2702
|
+
list = list->next;
|
|
2703
|
+
}
|
|
2704
|
+
}
|