rdiscount-dsc 1.6.9
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/BUILDING +34 -0
- data/COPYING +52 -0
- data/README.markdown +71 -0
- data/Rakefile +182 -0
- data/bin/rdiscount +19 -0
- data/ext/Csio.c +61 -0
- data/ext/amalloc.h +29 -0
- data/ext/basename.c +43 -0
- data/ext/config.h +23 -0
- data/ext/css.c +85 -0
- data/ext/cstring.h +77 -0
- data/ext/docheader.c +49 -0
- data/ext/dumptree.c +152 -0
- data/ext/emmatch.c +188 -0
- data/ext/extconf.rb +18 -0
- data/ext/generate.c +1642 -0
- data/ext/html5.c +24 -0
- data/ext/markdown.c +1215 -0
- data/ext/markdown.h +169 -0
- data/ext/mkdio.c +344 -0
- data/ext/mkdio.h +100 -0
- data/ext/rdiscount.c +106 -0
- data/ext/resource.c +157 -0
- data/ext/tags.c +123 -0
- data/ext/tags.h +19 -0
- data/ext/toc.c +101 -0
- data/ext/xml.c +82 -0
- data/lib/markdown.rb +1 -0
- data/lib/rdiscount.rb +87 -0
- data/man/markdown.7 +1020 -0
- data/man/rdiscount.1 +119 -0
- data/man/rdiscount.1.ronn +98 -0
- data/rdiscount-dsc.gemspec +57 -0
- data/test/benchmark.rb +56 -0
- data/test/benchmark.txt +306 -0
- data/test/markdown_test.rb +159 -0
- data/test/rdiscount_test.rb +111 -0
- metadata +88 -0
data/ext/basename.c
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
/*
|
2
|
+
* mkdio -- markdown front end input functions
|
3
|
+
*
|
4
|
+
* Copyright (C) 2007 David L Parsons.
|
5
|
+
* The redistribution terms are provided in the COPYRIGHT file that must
|
6
|
+
* be distributed with this source code.
|
7
|
+
*/
|
8
|
+
#include "config.h"
|
9
|
+
#include <stdio.h>
|
10
|
+
#include <stdlib.h>
|
11
|
+
#include <ctype.h>
|
12
|
+
|
13
|
+
#include "mkdio.h"
|
14
|
+
#include "cstring.h"
|
15
|
+
#include "amalloc.h"
|
16
|
+
|
17
|
+
static char *
|
18
|
+
e_basename(const char *string, const int size, void *context)
|
19
|
+
{
|
20
|
+
char *ret;
|
21
|
+
char *base = (char*)context;
|
22
|
+
|
23
|
+
if ( base && string && (*string == '/') && (ret=malloc(strlen(base)+size+2)) ) {
|
24
|
+
strcpy(ret, base);
|
25
|
+
strncat(ret, string, size);
|
26
|
+
return ret;
|
27
|
+
}
|
28
|
+
return 0;
|
29
|
+
}
|
30
|
+
|
31
|
+
static void
|
32
|
+
e_free(char *string, void *context)
|
33
|
+
{
|
34
|
+
if ( string ) free(string);
|
35
|
+
}
|
36
|
+
|
37
|
+
void
|
38
|
+
mkd_basename(MMIOT *document, char *base)
|
39
|
+
{
|
40
|
+
mkd_e_url(document, e_basename);
|
41
|
+
mkd_e_data(document, base);
|
42
|
+
mkd_e_free(document, e_free);
|
43
|
+
}
|
data/ext/config.h
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
/*
|
2
|
+
* rdiscount extension discount configuration
|
3
|
+
*/
|
4
|
+
#ifndef __MARKDOWN_D
|
5
|
+
#define __MARKDOWN_D 1
|
6
|
+
|
7
|
+
/* tabs are four spaces */
|
8
|
+
#define TABSTOP 4
|
9
|
+
|
10
|
+
/* these are setup by extconf.rb */
|
11
|
+
#if HAVE_RANDOM
|
12
|
+
#define COINTOSS() (random()&1)
|
13
|
+
#elif HAVE_RAND
|
14
|
+
#define COINTOSS() (rand()&1)
|
15
|
+
#endif
|
16
|
+
|
17
|
+
#if HAVE_SRANDOM
|
18
|
+
#define INITRNG(x) srandom((unsigned int)x)
|
19
|
+
#elif HAVE_SRAND
|
20
|
+
#define INITRNG(x) srand((unsigned int)x)
|
21
|
+
#endif
|
22
|
+
|
23
|
+
#endif/* __MARKDOWN_D */
|
data/ext/css.c
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
/* markdown: a C implementation of John Gruber's Markdown markup language.
|
2
|
+
*
|
3
|
+
* Copyright (C) 2009 David L Parsons.
|
4
|
+
* The redistribution terms are provided in the COPYRIGHT file that must
|
5
|
+
* be distributed with this source code.
|
6
|
+
*/
|
7
|
+
#include <stdio.h>
|
8
|
+
#include <string.h>
|
9
|
+
#include <stdarg.h>
|
10
|
+
#include <stdlib.h>
|
11
|
+
#include <time.h>
|
12
|
+
#include <ctype.h>
|
13
|
+
|
14
|
+
#include "config.h"
|
15
|
+
|
16
|
+
#include "cstring.h"
|
17
|
+
#include "markdown.h"
|
18
|
+
#include "amalloc.h"
|
19
|
+
|
20
|
+
|
21
|
+
/*
|
22
|
+
* dump out stylesheet sections.
|
23
|
+
*/
|
24
|
+
static void
|
25
|
+
stylesheets(Paragraph *p, Cstring *f)
|
26
|
+
{
|
27
|
+
Line* q;
|
28
|
+
|
29
|
+
for ( ; p ; p = p->next ) {
|
30
|
+
if ( p->typ == STYLE ) {
|
31
|
+
for ( q = p->text; q ; q = q->next ) {
|
32
|
+
Cswrite(f, T(q->text), S(q->text));
|
33
|
+
Csputc('\n', f);
|
34
|
+
}
|
35
|
+
}
|
36
|
+
if ( p->down )
|
37
|
+
stylesheets(p->down, f);
|
38
|
+
}
|
39
|
+
}
|
40
|
+
|
41
|
+
|
42
|
+
/* dump any embedded styles to a string
|
43
|
+
*/
|
44
|
+
int
|
45
|
+
mkd_css(Document *d, char **res)
|
46
|
+
{
|
47
|
+
Cstring f;
|
48
|
+
int size;
|
49
|
+
|
50
|
+
if ( res && d && d->compiled ) {
|
51
|
+
*res = 0;
|
52
|
+
CREATE(f);
|
53
|
+
RESERVE(f, 100);
|
54
|
+
stylesheets(d->code, &f);
|
55
|
+
|
56
|
+
if ( (size = S(f)) > 0 ) {
|
57
|
+
EXPAND(f) = 0;
|
58
|
+
/* HACK ALERT! HACK ALERT! HACK ALERT! */
|
59
|
+
*res = T(f);/* we know that a T(Cstring) is a character pointer */
|
60
|
+
/* so we can simply pick it up and carry it away, */
|
61
|
+
/* leaving the husk of the Ctring on the stack */
|
62
|
+
/* END HACK ALERT */
|
63
|
+
}
|
64
|
+
else
|
65
|
+
DELETE(f);
|
66
|
+
return size;
|
67
|
+
}
|
68
|
+
return EOF;
|
69
|
+
}
|
70
|
+
|
71
|
+
|
72
|
+
/* dump any embedded styles to a file
|
73
|
+
*/
|
74
|
+
int
|
75
|
+
mkd_generatecss(Document *d, FILE *f)
|
76
|
+
{
|
77
|
+
char *res;
|
78
|
+
int written = EOF, size = mkd_css(d, &res);
|
79
|
+
|
80
|
+
if ( size > 0 )
|
81
|
+
written = fwrite(res, 1, size, f);
|
82
|
+
if ( res )
|
83
|
+
free(res);
|
84
|
+
return (written == size) ? size : EOF;
|
85
|
+
}
|
data/ext/cstring.h
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
/* two template types: STRING(t) which defines a pascal-style string
|
2
|
+
* of element (t) [STRING(char) is the closest to the pascal string],
|
3
|
+
* and ANCHOR(t) which defines a baseplate that a linked list can be
|
4
|
+
* built up from. [The linked list /must/ contain a ->next pointer
|
5
|
+
* for linking the list together with.]
|
6
|
+
*/
|
7
|
+
#ifndef _CSTRING_D
|
8
|
+
#define _CSTRING_D
|
9
|
+
|
10
|
+
#include <string.h>
|
11
|
+
#include <stdlib.h>
|
12
|
+
|
13
|
+
#ifndef __WITHOUT_AMALLOC
|
14
|
+
# include "amalloc.h"
|
15
|
+
#endif
|
16
|
+
|
17
|
+
/* expandable Pascal-style string.
|
18
|
+
*/
|
19
|
+
#define STRING(type) struct { type *text; int size, alloc; }
|
20
|
+
|
21
|
+
#define CREATE(x) ( (T(x) = (void*)0), (S(x) = (x).alloc = 0) )
|
22
|
+
#define EXPAND(x) (S(x)++)[(S(x) < (x).alloc) \
|
23
|
+
? (T(x)) \
|
24
|
+
: (T(x) = T(x) ? realloc(T(x), sizeof T(x)[0] * ((x).alloc += 100)) \
|
25
|
+
: malloc(sizeof T(x)[0] * ((x).alloc += 100)) )]
|
26
|
+
|
27
|
+
#define DELETE(x) ALLOCATED(x) ? (free(T(x)), S(x) = (x).alloc = 0) \
|
28
|
+
: ( S(x) = 0 )
|
29
|
+
#define CLIP(t,i,sz) \
|
30
|
+
( ((i) >= 0) && ((sz) > 0) && (((i)+(sz)) <= S(t)) ) ? \
|
31
|
+
(memmove(&T(t)[i], &T(t)[i+sz], (S(t)-(i+sz)+1)*sizeof(T(t)[0])), \
|
32
|
+
S(t) -= (sz)) : -1
|
33
|
+
|
34
|
+
#define RESERVE(x, sz) T(x) = ((x).alloc > S(x) + (sz) \
|
35
|
+
? T(x) \
|
36
|
+
: T(x) \
|
37
|
+
? realloc(T(x), sizeof T(x)[0] * ((x).alloc = 100+(sz)+S(x))) \
|
38
|
+
: malloc(sizeof T(x)[0] * ((x).alloc = 100+(sz)+S(x))))
|
39
|
+
#define SUFFIX(t,p,sz) \
|
40
|
+
memcpy(((S(t) += (sz)) - (sz)) + \
|
41
|
+
(T(t) = T(t) ? realloc(T(t), sizeof T(t)[0] * ((t).alloc += sz)) \
|
42
|
+
: malloc(sizeof T(t)[0] * ((t).alloc += sz))), \
|
43
|
+
(p), sizeof(T(t)[0])*(sz))
|
44
|
+
|
45
|
+
#define PREFIX(t,p,sz) \
|
46
|
+
RESERVE( (t), (sz) ); \
|
47
|
+
if ( S(t) ) { memmove(T(t)+(sz), T(t), S(t)); } \
|
48
|
+
memcpy( T(t), (p), (sz) ); \
|
49
|
+
S(t) += (sz)
|
50
|
+
|
51
|
+
/* reference-style links (and images) are stored in an array
|
52
|
+
*/
|
53
|
+
#define T(x) (x).text
|
54
|
+
#define S(x) (x).size
|
55
|
+
#define ALLOCATED(x) (x).alloc
|
56
|
+
|
57
|
+
/* abstract anchor type that defines a list base
|
58
|
+
* with a function that attaches an element to
|
59
|
+
* the end of the list.
|
60
|
+
*
|
61
|
+
* the list base field is named .text so that the T()
|
62
|
+
* macro will work with it.
|
63
|
+
*/
|
64
|
+
#define ANCHOR(t) struct { t *text, *end; }
|
65
|
+
#define E(t) ((t).end)
|
66
|
+
|
67
|
+
#define ATTACH(t, p) ( T(t) ? ( (E(t)->next = (p)), (E(t) = (p)) ) \
|
68
|
+
: ( (T(t) = E(t) = (p)) ) )
|
69
|
+
|
70
|
+
typedef STRING(char) Cstring;
|
71
|
+
|
72
|
+
extern void Csputc(int, Cstring *);
|
73
|
+
extern int Csprintf(Cstring *, char *, ...);
|
74
|
+
extern int Cswrite(Cstring *, char *, int);
|
75
|
+
extern void Csreparse(Cstring *, char *, int, int);
|
76
|
+
|
77
|
+
#endif/*_CSTRING_D*/
|
data/ext/docheader.c
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
/*
|
2
|
+
* docheader -- get values from the document header
|
3
|
+
*
|
4
|
+
* Copyright (C) 2007 David L Parsons.
|
5
|
+
* The redistribution terms are provided in the COPYRIGHT file that must
|
6
|
+
* be distributed with this source code.
|
7
|
+
*/
|
8
|
+
#include "config.h"
|
9
|
+
#include <stdio.h>
|
10
|
+
#include <stdlib.h>
|
11
|
+
#include <ctype.h>
|
12
|
+
|
13
|
+
#include "cstring.h"
|
14
|
+
#include "markdown.h"
|
15
|
+
#include "amalloc.h"
|
16
|
+
|
17
|
+
static char *
|
18
|
+
onlyifset(Line *l)
|
19
|
+
{
|
20
|
+
char *ret = T(l->text) + l->dle;
|
21
|
+
|
22
|
+
return ret[0] ? ret : 0;
|
23
|
+
}
|
24
|
+
|
25
|
+
char *
|
26
|
+
mkd_doc_title(Document *doc)
|
27
|
+
{
|
28
|
+
if ( doc && doc->title )
|
29
|
+
return onlyifset(doc->title);
|
30
|
+
return 0;
|
31
|
+
}
|
32
|
+
|
33
|
+
|
34
|
+
char *
|
35
|
+
mkd_doc_author(Document *doc)
|
36
|
+
{
|
37
|
+
if ( doc && doc->author )
|
38
|
+
return onlyifset(doc->author);
|
39
|
+
return 0;
|
40
|
+
}
|
41
|
+
|
42
|
+
|
43
|
+
char *
|
44
|
+
mkd_doc_date(Document *doc)
|
45
|
+
{
|
46
|
+
if ( doc && doc->date )
|
47
|
+
return onlyifset(doc->date);
|
48
|
+
return 0;
|
49
|
+
}
|
data/ext/dumptree.c
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
/* markdown: a C implementation of John Gruber's Markdown markup language.
|
2
|
+
*
|
3
|
+
* Copyright (C) 2007 David L Parsons.
|
4
|
+
* The redistribution terms are provided in the COPYRIGHT file that must
|
5
|
+
* be distributed with this source code.
|
6
|
+
*/
|
7
|
+
#include <stdio.h>
|
8
|
+
#include "markdown.h"
|
9
|
+
#include "cstring.h"
|
10
|
+
#include "amalloc.h"
|
11
|
+
|
12
|
+
struct frame {
|
13
|
+
int indent;
|
14
|
+
char c;
|
15
|
+
};
|
16
|
+
|
17
|
+
typedef STRING(struct frame) Stack;
|
18
|
+
|
19
|
+
static char *
|
20
|
+
Pptype(int typ)
|
21
|
+
{
|
22
|
+
switch (typ) {
|
23
|
+
case WHITESPACE: return "whitespace";
|
24
|
+
case CODE : return "code";
|
25
|
+
case QUOTE : return "quote";
|
26
|
+
case MARKUP : return "markup";
|
27
|
+
case HTML : return "html";
|
28
|
+
case DL : return "dl";
|
29
|
+
case UL : return "ul";
|
30
|
+
case OL : return "ol";
|
31
|
+
case LISTITEM : return "item";
|
32
|
+
case HDR : return "header";
|
33
|
+
case HR : return "hr";
|
34
|
+
case TABLE : return "table";
|
35
|
+
case SOURCE : return "source";
|
36
|
+
case STYLE : return "style";
|
37
|
+
default : return "mystery node!";
|
38
|
+
}
|
39
|
+
}
|
40
|
+
|
41
|
+
static void
|
42
|
+
pushpfx(int indent, char c, Stack *sp)
|
43
|
+
{
|
44
|
+
struct frame *q = &EXPAND(*sp);
|
45
|
+
|
46
|
+
q->indent = indent;
|
47
|
+
q->c = c;
|
48
|
+
}
|
49
|
+
|
50
|
+
|
51
|
+
static void
|
52
|
+
poppfx(Stack *sp)
|
53
|
+
{
|
54
|
+
S(*sp)--;
|
55
|
+
}
|
56
|
+
|
57
|
+
|
58
|
+
static void
|
59
|
+
changepfx(Stack *sp, char c)
|
60
|
+
{
|
61
|
+
char ch;
|
62
|
+
|
63
|
+
if ( !S(*sp) ) return;
|
64
|
+
|
65
|
+
ch = T(*sp)[S(*sp)-1].c;
|
66
|
+
|
67
|
+
if ( ch == '+' || ch == '|' )
|
68
|
+
T(*sp)[S(*sp)-1].c = c;
|
69
|
+
}
|
70
|
+
|
71
|
+
|
72
|
+
static void
|
73
|
+
printpfx(Stack *sp, FILE *f)
|
74
|
+
{
|
75
|
+
int i;
|
76
|
+
char c;
|
77
|
+
|
78
|
+
if ( !S(*sp) ) return;
|
79
|
+
|
80
|
+
c = T(*sp)[S(*sp)-1].c;
|
81
|
+
|
82
|
+
if ( c == '+' || c == '-' ) {
|
83
|
+
fprintf(f, "--%c", c);
|
84
|
+
T(*sp)[S(*sp)-1].c = (c == '-') ? ' ' : '|';
|
85
|
+
}
|
86
|
+
else
|
87
|
+
for ( i=0; i < S(*sp); i++ ) {
|
88
|
+
if ( i )
|
89
|
+
fprintf(f, " ");
|
90
|
+
fprintf(f, "%*s%c", T(*sp)[i].indent + 2, " ", T(*sp)[i].c);
|
91
|
+
if ( T(*sp)[i].c == '`' )
|
92
|
+
T(*sp)[i].c = ' ';
|
93
|
+
}
|
94
|
+
fprintf(f, "--");
|
95
|
+
}
|
96
|
+
|
97
|
+
|
98
|
+
static void
|
99
|
+
dumptree(Paragraph *pp, Stack *sp, FILE *f)
|
100
|
+
{
|
101
|
+
int count;
|
102
|
+
Line *p;
|
103
|
+
int d;
|
104
|
+
static char *Begin[] = { 0, "P", "center" };
|
105
|
+
|
106
|
+
while ( pp ) {
|
107
|
+
if ( !pp->next )
|
108
|
+
changepfx(sp, '`');
|
109
|
+
printpfx(sp, f);
|
110
|
+
|
111
|
+
d = fprintf(f, "[%s", Pptype(pp->typ));
|
112
|
+
if ( pp->ident )
|
113
|
+
d += fprintf(f, " %s", pp->ident);
|
114
|
+
if ( pp->align )
|
115
|
+
d += fprintf(f, ", <%s>", Begin[pp->align]);
|
116
|
+
|
117
|
+
for (count=0, p=pp->text; p; ++count, (p = p->next) )
|
118
|
+
;
|
119
|
+
|
120
|
+
if ( count )
|
121
|
+
d += fprintf(f, ", %d line%s", count, (count==1)?"":"s");
|
122
|
+
|
123
|
+
d += fprintf(f, "]");
|
124
|
+
|
125
|
+
if ( pp->down ) {
|
126
|
+
pushpfx(d, pp->down->next ? '+' : '-', sp);
|
127
|
+
dumptree(pp->down, sp, f);
|
128
|
+
poppfx(sp);
|
129
|
+
}
|
130
|
+
else fputc('\n', f);
|
131
|
+
pp = pp->next;
|
132
|
+
}
|
133
|
+
}
|
134
|
+
|
135
|
+
|
136
|
+
int
|
137
|
+
mkd_dump(Document *doc, FILE *out, int flags, char *title)
|
138
|
+
{
|
139
|
+
Stack stack;
|
140
|
+
|
141
|
+
if (mkd_compile(doc, flags) ) {
|
142
|
+
|
143
|
+
CREATE(stack);
|
144
|
+
pushpfx(fprintf(out, "%s", title), doc->code->next ? '+' : '-', &stack);
|
145
|
+
dumptree(doc->code, &stack, out);
|
146
|
+
DELETE(stack);
|
147
|
+
|
148
|
+
mkd_cleanup(doc);
|
149
|
+
return 0;
|
150
|
+
}
|
151
|
+
return -1;
|
152
|
+
}
|
data/ext/emmatch.c
ADDED
@@ -0,0 +1,188 @@
|
|
1
|
+
/* markdown: a C implementation of John Gruber's Markdown markup language.
|
2
|
+
*
|
3
|
+
* Copyright (C) 2010 David L Parsons.
|
4
|
+
* The redistribution terms are provided in the COPYRIGHT file that must
|
5
|
+
* be distributed with this source code.
|
6
|
+
*/
|
7
|
+
#include <stdio.h>
|
8
|
+
#include <string.h>
|
9
|
+
#include <stdarg.h>
|
10
|
+
#include <stdlib.h>
|
11
|
+
#include <time.h>
|
12
|
+
#include <ctype.h>
|
13
|
+
|
14
|
+
#include "config.h"
|
15
|
+
|
16
|
+
#include "cstring.h"
|
17
|
+
#include "markdown.h"
|
18
|
+
#include "amalloc.h"
|
19
|
+
|
20
|
+
|
21
|
+
/* emmatch: the emphasis mangler that's run after a block
|
22
|
+
* of html has been generated.
|
23
|
+
*
|
24
|
+
* It should create MarkdownTest_1.0 (and _1.0.3)
|
25
|
+
* compatable emphasis for non-pathological cases
|
26
|
+
* and it should fail in a standards-compliant way
|
27
|
+
* when someone attempts to feed it junk.
|
28
|
+
*
|
29
|
+
* Emmatching is done after the input has been
|
30
|
+
* processed into a STRING (f->Q) of text and
|
31
|
+
* emphasis blocks. After ___mkd_emblock() finishes,
|
32
|
+
* it truncates f->Q and leaves the rendered paragraph
|
33
|
+
* if f->out.
|
34
|
+
*/
|
35
|
+
|
36
|
+
|
37
|
+
/* empair() -- find the NEAREST matching emphasis token (or
|
38
|
+
* subtoken of a 3+ long emphasis token.
|
39
|
+
*/
|
40
|
+
static int
|
41
|
+
empair(MMIOT *f, int first, int last, int match)
|
42
|
+
{
|
43
|
+
|
44
|
+
int i;
|
45
|
+
block *begin, *p;
|
46
|
+
|
47
|
+
begin = &T(f->Q)[first];
|
48
|
+
|
49
|
+
for (i=first+1; i <= last; i++) {
|
50
|
+
p = &T(f->Q)[i];
|
51
|
+
|
52
|
+
if ( (p->b_type != bTEXT) && (p->b_count <= 0) )
|
53
|
+
continue; /* break? */
|
54
|
+
|
55
|
+
if ( p->b_type == begin->b_type ) {
|
56
|
+
if ( p->b_count == match ) /* exact match */
|
57
|
+
return i;
|
58
|
+
|
59
|
+
if ( p->b_count > 2 ) /* fuzzy match */
|
60
|
+
return i;
|
61
|
+
}
|
62
|
+
}
|
63
|
+
return 0;
|
64
|
+
} /* empair */
|
65
|
+
|
66
|
+
|
67
|
+
/* emfill() -- if an emphasis token has leftover stars or underscores,
|
68
|
+
* convert them back into character and append them to b_text.
|
69
|
+
*/
|
70
|
+
static void
|
71
|
+
emfill(block *p)
|
72
|
+
{
|
73
|
+
int j;
|
74
|
+
|
75
|
+
if ( p->b_type == bTEXT )
|
76
|
+
return;
|
77
|
+
|
78
|
+
for (j=0; j < p->b_count; j++)
|
79
|
+
EXPAND(p->b_text) = p->b_char;
|
80
|
+
p->b_count = 0;
|
81
|
+
} /* emfill */
|
82
|
+
|
83
|
+
|
84
|
+
static void
|
85
|
+
emclose(MMIOT *f, int first, int last)
|
86
|
+
{
|
87
|
+
int j;
|
88
|
+
|
89
|
+
for (j=first+1; j<last-1; j++)
|
90
|
+
emfill(&T(f->Q)[j]);
|
91
|
+
}
|
92
|
+
|
93
|
+
|
94
|
+
static struct emtags {
|
95
|
+
char open[10];
|
96
|
+
char close[10];
|
97
|
+
int size;
|
98
|
+
} emtags[] = { { "<em>" , "</em>", 5 }, { "<strong>", "</strong>", 9 } };
|
99
|
+
|
100
|
+
|
101
|
+
static void emblock(MMIOT*,int,int);
|
102
|
+
|
103
|
+
|
104
|
+
/* emmatch() -- match emphasis for a single emphasis token.
|
105
|
+
*/
|
106
|
+
static void
|
107
|
+
emmatch(MMIOT *f, int first, int last)
|
108
|
+
{
|
109
|
+
block *start = &T(f->Q)[first];
|
110
|
+
int e, e2, match;
|
111
|
+
|
112
|
+
switch (start->b_count) {
|
113
|
+
case 2: if ( e = empair(f,first,last,match=2) )
|
114
|
+
break;
|
115
|
+
case 1: e = empair(f,first,last,match=1);
|
116
|
+
break;
|
117
|
+
case 0: return;
|
118
|
+
default:
|
119
|
+
e = empair(f,first,last,1);
|
120
|
+
e2= empair(f,first,last,2);
|
121
|
+
|
122
|
+
if ( e2 >= e ) {
|
123
|
+
e = e2;
|
124
|
+
match = 2;
|
125
|
+
}
|
126
|
+
else
|
127
|
+
match = 1;
|
128
|
+
break;
|
129
|
+
}
|
130
|
+
|
131
|
+
if ( e ) {
|
132
|
+
/* if we found emphasis to match, match it, recursively call
|
133
|
+
* emblock to match emphasis inside the new html block, add
|
134
|
+
* the emphasis markers for the block, then (tail) recursively
|
135
|
+
* call ourself to match any remaining emphasis on this token.
|
136
|
+
*/
|
137
|
+
block *end = &T(f->Q)[e];
|
138
|
+
|
139
|
+
end->b_count -= match;
|
140
|
+
start->b_count -= match;
|
141
|
+
|
142
|
+
emblock(f, first, e);
|
143
|
+
|
144
|
+
PREFIX(start->b_text, emtags[match-1].open, emtags[match-1].size-1);
|
145
|
+
SUFFIX(end->b_post, emtags[match-1].close, emtags[match-1].size);
|
146
|
+
|
147
|
+
emmatch(f, first, last);
|
148
|
+
}
|
149
|
+
} /* emmatch */
|
150
|
+
|
151
|
+
|
152
|
+
/* emblock() -- walk a blocklist, attempting to match emphasis
|
153
|
+
*/
|
154
|
+
static void
|
155
|
+
emblock(MMIOT *f, int first, int last)
|
156
|
+
{
|
157
|
+
int i;
|
158
|
+
|
159
|
+
for ( i = first; i <= last; i++ )
|
160
|
+
if ( T(f->Q)[i].b_type != bTEXT )
|
161
|
+
emmatch(f, i, last);
|
162
|
+
emclose(f, first, last);
|
163
|
+
} /* emblock */
|
164
|
+
|
165
|
+
|
166
|
+
/* ___mkd_emblock() -- emblock a string of blocks, then concatenate the
|
167
|
+
* resulting text onto f->out.
|
168
|
+
*/
|
169
|
+
void
|
170
|
+
___mkd_emblock(MMIOT *f)
|
171
|
+
{
|
172
|
+
int i;
|
173
|
+
block *p;
|
174
|
+
|
175
|
+
emblock(f, 0, S(f->Q)-1);
|
176
|
+
|
177
|
+
for (i=0; i < S(f->Q); i++) {
|
178
|
+
p = &T(f->Q)[i];
|
179
|
+
emfill(p);
|
180
|
+
|
181
|
+
if ( S(p->b_post) ) { SUFFIX(f->out, T(p->b_post), S(p->b_post));
|
182
|
+
DELETE(p->b_post); }
|
183
|
+
if ( S(p->b_text) ) { SUFFIX(f->out, T(p->b_text), S(p->b_text));
|
184
|
+
DELETE(p->b_text); }
|
185
|
+
}
|
186
|
+
|
187
|
+
S(f->Q) = 0;
|
188
|
+
} /* ___mkd_emblock */
|