bluecloth 2.0.7-x86-mswin32 → 2.0.11pre158-x86-mswin32
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +0 -0
- data/.gemtest +0 -0
- data/History.md +4 -0
- data/LICENSE +1 -1
- data/Manifest.txt +103 -0
- data/README.md +103 -0
- data/Rakefile +95 -301
- data/ext/VERSION +1 -1
- data/ext/bluecloth.c +69 -23
- data/ext/bluecloth.h +13 -2
- data/ext/config.h +13 -2
- data/ext/css.c +14 -5
- data/ext/cstring.h +4 -2
- data/ext/docheader.c +13 -7
- data/ext/emmatch.c +188 -0
- data/ext/extconf.rb +7 -9
- data/ext/generate.c +333 -293
- data/ext/html5.c +24 -0
- data/ext/markdown.c +326 -185
- data/ext/markdown.h +52 -29
- data/ext/mkdio.c +82 -41
- data/ext/mkdio.h +44 -23
- data/ext/resource.c +4 -2
- data/ext/setup.c +47 -0
- data/ext/tags.c +123 -0
- data/ext/tags.h +19 -0
- data/lib/1.8/bluecloth_ext.so +0 -0
- data/lib/1.9/bluecloth_ext.so +0 -0
- data/lib/bluecloth.rb +77 -42
- data/spec/bluecloth/101_changes_spec.rb +18 -21
- data/spec/bluecloth/TEMPLATE +36 -0
- data/spec/bluecloth/autolinks_spec.rb +4 -7
- data/spec/bluecloth/blockquotes_spec.rb +20 -23
- data/spec/bluecloth/code_spans_spec.rb +2 -5
- data/spec/bluecloth/emphasis_spec.rb +2 -5
- data/spec/bluecloth/entities_spec.rb +2 -5
- data/spec/bluecloth/hrules_spec.rb +2 -5
- data/spec/bluecloth/images_spec.rb +2 -5
- data/spec/bluecloth/inline_html_spec.rb +26 -66
- data/spec/bluecloth/links_spec.rb +1 -5
- data/spec/bluecloth/lists_spec.rb +2 -5
- data/spec/bluecloth/paragraphs_spec.rb +2 -5
- data/spec/bluecloth/titles_spec.rb +2 -5
- data/spec/bluecloth_spec.rb +36 -22
- data/spec/bugfix_spec.rb +90 -10
- data/spec/contributions_spec.rb +2 -3
- data/spec/discount_spec.rb +50 -10
- data/spec/lib/helpers.rb +18 -117
- data/spec/lib/matchers.rb +7 -18
- data/spec/markdowntest_spec.rb +3 -39
- metadata +257 -143
- metadata.gz.sig +0 -0
- data/ChangeLog +0 -387
- data/README +0 -81
- data/Rakefile.local +0 -41
- data/rake/191_compat.rb +0 -26
- data/rake/dependencies.rb +0 -76
- data/rake/helpers.rb +0 -435
- data/rake/hg.rb +0 -273
- data/rake/manual.rb +0 -782
- data/rake/packaging.rb +0 -123
- data/rake/publishing.rb +0 -274
- data/rake/rdoc.rb +0 -30
- data/rake/style.rb +0 -62
- data/rake/svn.rb +0 -668
- data/rake/testing.rb +0 -187
- data/rake/verifytask.rb +0 -64
data/ext/html5.c
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
/* block-level tags for passing html5 blocks through the blender
|
2
|
+
*/
|
3
|
+
#include "tags.h"
|
4
|
+
|
5
|
+
void
|
6
|
+
mkd_with_html5_tags()
|
7
|
+
{
|
8
|
+
static int populated = 0;
|
9
|
+
|
10
|
+
if ( populated ) return;
|
11
|
+
populated = 1;
|
12
|
+
|
13
|
+
mkd_prepare_tags();
|
14
|
+
|
15
|
+
mkd_define_tag("ASIDE", 0);
|
16
|
+
mkd_define_tag("FOOTER", 0);
|
17
|
+
mkd_define_tag("HEADER", 0);
|
18
|
+
mkd_define_tag("HGROUP", 0);
|
19
|
+
mkd_define_tag("NAV", 0);
|
20
|
+
mkd_define_tag("SECTION", 0);
|
21
|
+
mkd_define_tag("ARTICLE", 0);
|
22
|
+
|
23
|
+
mkd_sort_tags();
|
24
|
+
}
|
data/ext/markdown.c
CHANGED
@@ -4,6 +4,8 @@
|
|
4
4
|
* The redistribution terms are provided in the COPYRIGHT file that must
|
5
5
|
* be distributed with this source code.
|
6
6
|
*/
|
7
|
+
#include "config.h"
|
8
|
+
|
7
9
|
#include <stdio.h>
|
8
10
|
#include <string.h>
|
9
11
|
#include <stdarg.h>
|
@@ -11,51 +13,15 @@
|
|
11
13
|
#include <time.h>
|
12
14
|
#include <ctype.h>
|
13
15
|
|
14
|
-
#include "config.h"
|
15
|
-
|
16
16
|
#include "cstring.h"
|
17
17
|
#include "markdown.h"
|
18
18
|
#include "amalloc.h"
|
19
|
-
|
20
|
-
/* block-level tags for passing html blocks through the blender
|
21
|
-
*/
|
22
|
-
struct kw {
|
23
|
-
char *id;
|
24
|
-
int size;
|
25
|
-
int selfclose;
|
26
|
-
} ;
|
27
|
-
|
28
|
-
#define KW(x) { x, sizeof(x)-1, 0 }
|
29
|
-
#define SC(x) { x, sizeof(x)-1, 1 }
|
30
|
-
|
31
|
-
static struct kw blocktags[] = { KW("!--"), KW("STYLE"), KW("SCRIPT"),
|
32
|
-
KW("ADDRESS"), KW("BDO"), KW("BLOCKQUOTE"),
|
33
|
-
KW("CENTER"), KW("DFN"), KW("DIV"), KW("H1"),
|
34
|
-
KW("H2"), KW("H3"), KW("H4"), KW("H5"),
|
35
|
-
KW("H6"), KW("LISTING"), KW("NOBR"),
|
36
|
-
KW("UL"), KW("P"), KW("OL"), KW("DL"),
|
37
|
-
KW("PLAINTEXT"), KW("PRE"), KW("TABLE"),
|
38
|
-
KW("WBR"), KW("XMP"), SC("HR"), SC("BR"),
|
39
|
-
KW("IFRAME"), KW("MAP") };
|
40
|
-
#define SZTAGS (sizeof blocktags / sizeof blocktags[0])
|
41
|
-
#define MAXTAG 11 /* sizeof "BLOCKQUOTE" */
|
19
|
+
#include "tags.h"
|
42
20
|
|
43
21
|
typedef int (*stfu)(const void*,const void*);
|
44
22
|
|
45
23
|
typedef ANCHOR(Paragraph) ParagraphRoot;
|
46
24
|
|
47
|
-
|
48
|
-
/* case insensitive string sort (for qsort() and bsearch() of block tags)
|
49
|
-
*/
|
50
|
-
static int
|
51
|
-
casort(struct kw *a, struct kw *b)
|
52
|
-
{
|
53
|
-
if ( a->size != b->size )
|
54
|
-
return a->size - b->size;
|
55
|
-
return strncasecmp(a->id, b->id, b->size);
|
56
|
-
}
|
57
|
-
|
58
|
-
|
59
25
|
/* case insensitive string sort for Footnote tags.
|
60
26
|
*/
|
61
27
|
int
|
@@ -135,19 +101,28 @@ ___mkd_tidy(Cstring *t)
|
|
135
101
|
}
|
136
102
|
|
137
103
|
|
104
|
+
static struct kw comment = { "!--", 3, 0 };
|
105
|
+
|
138
106
|
static struct kw *
|
139
107
|
isopentag(Line *p)
|
140
108
|
{
|
141
109
|
int i=0, len;
|
142
|
-
|
110
|
+
char *line;
|
143
111
|
|
144
112
|
if ( !p ) return 0;
|
145
113
|
|
114
|
+
line = T(p->text);
|
146
115
|
len = S(p->text);
|
147
116
|
|
148
|
-
if ( len < 3 ||
|
117
|
+
if ( len < 3 || line[0] != '<' )
|
149
118
|
return 0;
|
150
119
|
|
120
|
+
if ( line[1] == '!' && line[2] == '-' && line[3] == '-' )
|
121
|
+
/* comments need special case handling, because
|
122
|
+
* the !-- doesn't need to end in a whitespace
|
123
|
+
*/
|
124
|
+
return &comment;
|
125
|
+
|
151
126
|
/* find how long the tag is so we can check to see if
|
152
127
|
* it's a block-level tag
|
153
128
|
*/
|
@@ -156,13 +131,8 @@ isopentag(Line *p)
|
|
156
131
|
&& !isspace(T(p->text)[i]); ++i )
|
157
132
|
;
|
158
133
|
|
159
|
-
key.id = T(p->text)+1;
|
160
|
-
key.size = i-1;
|
161
|
-
|
162
|
-
if ( ret = bsearch(&key, blocktags, SZTAGS, sizeof key, (stfu)casort))
|
163
|
-
return ret;
|
164
134
|
|
165
|
-
return
|
135
|
+
return mkd_search_tags(T(p->text)+1, i-1);
|
166
136
|
}
|
167
137
|
|
168
138
|
|
@@ -171,6 +141,8 @@ typedef struct _flo {
|
|
171
141
|
int i;
|
172
142
|
} FLO;
|
173
143
|
|
144
|
+
#define floindex(x) (x.i)
|
145
|
+
|
174
146
|
|
175
147
|
static int
|
176
148
|
flogetc(FLO *f)
|
@@ -186,15 +158,56 @@ flogetc(FLO *f)
|
|
186
158
|
}
|
187
159
|
|
188
160
|
|
161
|
+
static void
|
162
|
+
splitline(Line *t, int cutpoint)
|
163
|
+
{
|
164
|
+
if ( t && (cutpoint < S(t->text)) ) {
|
165
|
+
Line *tmp = calloc(1, sizeof *tmp);
|
166
|
+
|
167
|
+
tmp->next = t->next;
|
168
|
+
t->next = tmp;
|
169
|
+
|
170
|
+
tmp->dle = t->dle;
|
171
|
+
SUFFIX(tmp->text, T(t->text)+cutpoint, S(t->text)-cutpoint);
|
172
|
+
S(t->text) = cutpoint;
|
173
|
+
}
|
174
|
+
}
|
175
|
+
|
176
|
+
|
177
|
+
static Line *
|
178
|
+
commentblock(Paragraph *p, int *unclosed)
|
179
|
+
{
|
180
|
+
Line *t, *ret;
|
181
|
+
char *end;
|
182
|
+
|
183
|
+
for ( t = p->text; t ; t = t->next) {
|
184
|
+
if ( end = strstr(T(t->text), "-->") ) {
|
185
|
+
splitline(t, 3 + (end - T(t->text)) );
|
186
|
+
ret = t->next;
|
187
|
+
t->next = 0;
|
188
|
+
return ret;
|
189
|
+
}
|
190
|
+
}
|
191
|
+
*unclosed = 1;
|
192
|
+
return t;
|
193
|
+
|
194
|
+
}
|
195
|
+
|
196
|
+
|
189
197
|
static Line *
|
190
|
-
htmlblock(Paragraph *p, struct kw *tag)
|
198
|
+
htmlblock(Paragraph *p, struct kw *tag, int *unclosed)
|
191
199
|
{
|
192
200
|
Line *ret;
|
193
201
|
FLO f = { p->text, 0 };
|
194
202
|
int c;
|
195
203
|
int i, closing, depth=0;
|
196
204
|
|
197
|
-
|
205
|
+
*unclosed = 0;
|
206
|
+
|
207
|
+
if ( tag == &comment )
|
208
|
+
return commentblock(p, unclosed);
|
209
|
+
|
210
|
+
if ( tag->selfclose ) {
|
198
211
|
ret = f.t->next;
|
199
212
|
f.t->next = 0;
|
200
213
|
return ret;
|
@@ -230,8 +243,11 @@ htmlblock(Paragraph *p, struct kw *tag)
|
|
230
243
|
/* consume trailing gunk in close tag */
|
231
244
|
c = flogetc(&f);
|
232
245
|
}
|
246
|
+
if ( c == EOF )
|
247
|
+
break;
|
233
248
|
if ( !f.t )
|
234
249
|
return 0;
|
250
|
+
splitline(f.t, floindex(f));
|
235
251
|
ret = f.t->next;
|
236
252
|
f.t->next = 0;
|
237
253
|
return ret;
|
@@ -240,27 +256,11 @@ htmlblock(Paragraph *p, struct kw *tag)
|
|
240
256
|
}
|
241
257
|
}
|
242
258
|
}
|
259
|
+
*unclosed = 1;
|
243
260
|
return 0;
|
244
261
|
}
|
245
262
|
|
246
263
|
|
247
|
-
static Line *
|
248
|
-
comment(Paragraph *p)
|
249
|
-
{
|
250
|
-
Line *t, *ret;
|
251
|
-
|
252
|
-
for ( t = p->text; t ; t = t->next) {
|
253
|
-
if ( strstr(T(t->text), "-->") ) {
|
254
|
-
ret = t->next;
|
255
|
-
t->next = 0;
|
256
|
-
return ret;
|
257
|
-
}
|
258
|
-
}
|
259
|
-
return t;
|
260
|
-
|
261
|
-
}
|
262
|
-
|
263
|
-
|
264
264
|
/* tables look like
|
265
265
|
* header|header{|header}
|
266
266
|
* ------|------{|......}
|
@@ -305,8 +305,8 @@ isfootnote(Line *t)
|
|
305
305
|
for ( ++i; i < S(t->text) ; ++i ) {
|
306
306
|
if ( T(t->text)[i] == '[' )
|
307
307
|
return 0;
|
308
|
-
else if ( T(t->text)[i] == ']'
|
309
|
-
return 1;
|
308
|
+
else if ( T(t->text)[i] == ']' )
|
309
|
+
return ( T(t->text)[i+1] == ':' ) ;
|
310
310
|
}
|
311
311
|
return 0;
|
312
312
|
}
|
@@ -315,7 +315,14 @@ isfootnote(Line *t)
|
|
315
315
|
static int
|
316
316
|
isquote(Line *t)
|
317
317
|
{
|
318
|
-
|
318
|
+
int j;
|
319
|
+
|
320
|
+
for ( j=0; j < 4; j++ )
|
321
|
+
if ( T(t->text)[j] == '>' )
|
322
|
+
return 1;
|
323
|
+
else if ( !isspace(T(t->text)[j]) )
|
324
|
+
return 0;
|
325
|
+
return 0;
|
319
326
|
}
|
320
327
|
|
321
328
|
|
@@ -355,6 +362,34 @@ ishr(Line *t)
|
|
355
362
|
}
|
356
363
|
|
357
364
|
|
365
|
+
static int
|
366
|
+
issetext(Line *t, int *htyp)
|
367
|
+
{
|
368
|
+
int i;
|
369
|
+
/* then check for setext-style HEADER
|
370
|
+
* ======
|
371
|
+
*/
|
372
|
+
|
373
|
+
if ( t->next ) {
|
374
|
+
char *q = T(t->next->text);
|
375
|
+
int last = S(t->next->text);
|
376
|
+
|
377
|
+
if ( (*q == '=') || (*q == '-') ) {
|
378
|
+
/* ignore trailing whitespace */
|
379
|
+
while ( (last > 1) && isspace(q[last-1]) )
|
380
|
+
--last;
|
381
|
+
|
382
|
+
for (i=1; i < last; i++)
|
383
|
+
if ( q[0] != q[i] )
|
384
|
+
return 0;
|
385
|
+
*htyp = SETEXT;
|
386
|
+
return 1;
|
387
|
+
}
|
388
|
+
}
|
389
|
+
return 0;
|
390
|
+
}
|
391
|
+
|
392
|
+
|
358
393
|
static int
|
359
394
|
ishdr(Line *t, int *htyp)
|
360
395
|
{
|
@@ -376,75 +411,116 @@ ishdr(Line *t, int *htyp)
|
|
376
411
|
return 1;
|
377
412
|
}
|
378
413
|
|
379
|
-
|
380
|
-
|
381
|
-
*/
|
414
|
+
return issetext(t, htyp);
|
415
|
+
}
|
382
416
|
|
383
|
-
if ( t->next ) {
|
384
|
-
char *q = T(t->next->text);
|
385
417
|
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
418
|
+
static Line*
|
419
|
+
is_discount_dt(Line *t, int *clip)
|
420
|
+
{
|
421
|
+
#if USE_DISCOUNT_DL
|
422
|
+
if ( t && t->next
|
423
|
+
&& (S(t->text) > 2)
|
424
|
+
&& (t->dle == 0)
|
425
|
+
&& (T(t->text)[0] == '=')
|
426
|
+
&& (T(t->text)[S(t->text)-1] == '=') ) {
|
427
|
+
if ( t->next->dle >= 4 ) {
|
428
|
+
*clip = 4;
|
429
|
+
return t;
|
392
430
|
}
|
431
|
+
else
|
432
|
+
return is_discount_dt(t->next, clip);
|
393
433
|
}
|
434
|
+
#endif
|
394
435
|
return 0;
|
395
436
|
}
|
396
437
|
|
397
438
|
|
398
439
|
static int
|
399
|
-
|
440
|
+
is_extra_dd(Line *t)
|
400
441
|
{
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
442
|
+
return (t->dle < 4) && (T(t->text)[t->dle] == ':')
|
443
|
+
&& isspace(T(t->text)[t->dle+1]);
|
444
|
+
}
|
445
|
+
|
446
|
+
|
447
|
+
static Line*
|
448
|
+
is_extra_dt(Line *t, int *clip)
|
449
|
+
{
|
450
|
+
#if USE_EXTRA_DL
|
451
|
+
int i;
|
452
|
+
|
453
|
+
if ( t && t->next && T(t->text)[0] != '='
|
454
|
+
&& T(t->text)[S(t->text)-1] != '=') {
|
455
|
+
Line *x;
|
456
|
+
|
457
|
+
if ( iscode(t) || blankline(t) || ishdr(t,&i) || ishr(t) )
|
458
|
+
return 0;
|
459
|
+
|
460
|
+
if ( (x = skipempty(t->next)) && is_extra_dd(x) ) {
|
461
|
+
*clip = x->dle+2;
|
462
|
+
return t;
|
463
|
+
}
|
464
|
+
|
465
|
+
if ( x=is_extra_dt(t->next, clip) )
|
466
|
+
return x;
|
467
|
+
}
|
410
468
|
#endif
|
469
|
+
return 0;
|
470
|
+
}
|
471
|
+
|
472
|
+
|
473
|
+
static Line*
|
474
|
+
isdefinition(Line *t, int *clip, int *kind)
|
475
|
+
{
|
476
|
+
Line *ret;
|
477
|
+
|
478
|
+
*kind = 1;
|
479
|
+
if ( ret = is_discount_dt(t,clip) )
|
480
|
+
return ret;
|
481
|
+
|
482
|
+
*kind=2;
|
483
|
+
return is_extra_dt(t,clip);
|
411
484
|
}
|
412
485
|
|
413
486
|
|
414
487
|
static int
|
415
|
-
islist(Line *t, int *
|
488
|
+
islist(Line *t, int *clip, DWORD flags, int *list_type)
|
416
489
|
{
|
417
490
|
int i, j;
|
418
491
|
char *q;
|
419
492
|
|
420
|
-
if ( iscode(t)
|
493
|
+
if ( /*iscode(t) ||*/ blankline(t) || ishdr(t,&i) || ishr(t) )
|
421
494
|
return 0;
|
422
495
|
|
423
|
-
if ( isdefinition(t) )
|
424
|
-
*trim = 4;
|
496
|
+
if ( !(flags & (MKD_NODLIST|MKD_STRICT)) && isdefinition(t,clip,list_type) )
|
425
497
|
return DL;
|
426
|
-
}
|
427
498
|
|
428
499
|
if ( strchr("*-+", T(t->text)[t->dle]) && isspace(T(t->text)[t->dle+1]) ) {
|
429
500
|
i = nextnonblank(t, t->dle+1);
|
430
|
-
*
|
431
|
-
|
501
|
+
*clip = (i > 4) ? 4 : i;
|
502
|
+
*list_type = UL;
|
503
|
+
return AL;
|
432
504
|
}
|
433
505
|
|
434
506
|
if ( (j = nextblank(t,t->dle)) > t->dle ) {
|
435
507
|
if ( T(t->text)[j-1] == '.' ) {
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
508
|
+
|
509
|
+
if ( !(flags & (MKD_NOALPHALIST|MKD_STRICT))
|
510
|
+
&& (j == t->dle + 2)
|
511
|
+
&& isalpha(T(t->text)[t->dle]) ) {
|
512
|
+
j = nextnonblank(t,j);
|
513
|
+
*clip = (j > 4) ? 4 : j;
|
514
|
+
*list_type = AL;
|
515
|
+
return AL;
|
516
|
+
}
|
517
|
+
|
443
518
|
strtoul(T(t->text)+t->dle, &q, 10);
|
444
519
|
if ( (q > T(t->text)+t->dle) && (q == T(t->text) + (j-1)) ) {
|
445
520
|
j = nextnonblank(t,j);
|
446
|
-
*
|
447
|
-
|
521
|
+
*clip = (j > 4) ? 4 : j;
|
522
|
+
*list_type = OL;
|
523
|
+
return AL;
|
448
524
|
}
|
449
525
|
}
|
450
526
|
}
|
@@ -475,7 +551,8 @@ headerblock(Paragraph *pp, int htyp)
|
|
475
551
|
* the leading and trailing `#`'s
|
476
552
|
*/
|
477
553
|
|
478
|
-
for (i=0; (T(p->text)[i] == T(p->text)[0]) && (i < S(p->text)-1)
|
554
|
+
for (i=0; (T(p->text)[i] == T(p->text)[0]) && (i < S(p->text)-1)
|
555
|
+
&& (i < 6); i++)
|
479
556
|
;
|
480
557
|
|
481
558
|
pp->hnumber = i;
|
@@ -539,27 +616,33 @@ centered(Line *first, Line *last)
|
|
539
616
|
|
540
617
|
|
541
618
|
static int
|
542
|
-
endoftextblock(Line *t, int toplevelblock)
|
619
|
+
endoftextblock(Line *t, int toplevelblock, DWORD flags)
|
543
620
|
{
|
544
621
|
int z;
|
545
622
|
|
546
|
-
if ( blankline(t)||isquote(t)||
|
623
|
+
if ( blankline(t)||isquote(t)||ishdr(t,&z)||ishr(t) )
|
624
|
+
return 1;
|
625
|
+
|
626
|
+
/* HORRIBLE STANDARDS KLUDGE: non-toplevel paragraphs absorb adjacent
|
627
|
+
* code blocks
|
628
|
+
*/
|
629
|
+
if ( toplevelblock && iscode(t) )
|
547
630
|
return 1;
|
548
631
|
|
549
632
|
/* HORRIBLE STANDARDS KLUDGE: Toplevel paragraphs eat absorb adjacent
|
550
633
|
* list items, but sublevel blocks behave properly.
|
551
634
|
*/
|
552
|
-
return toplevelblock ? 0 : islist(t,&z);
|
635
|
+
return toplevelblock ? 0 : islist(t,&z,flags, &z);
|
553
636
|
}
|
554
637
|
|
555
638
|
|
556
639
|
static Line *
|
557
|
-
textblock(Paragraph *p, int toplevel)
|
640
|
+
textblock(Paragraph *p, int toplevel, DWORD flags)
|
558
641
|
{
|
559
642
|
Line *t, *next;
|
560
643
|
|
561
644
|
for ( t = p->text; t ; t = next ) {
|
562
|
-
if ( ((next = t->next) == 0) || endoftextblock(next, toplevel) ) {
|
645
|
+
if ( ((next = t->next) == 0) || endoftextblock(next, toplevel, flags) ) {
|
563
646
|
p->align = centered(p->text, t);
|
564
647
|
t->next = 0;
|
565
648
|
return next;
|
@@ -586,27 +669,32 @@ szmarkerclass(char *p)
|
|
586
669
|
* check if the first line of a quoted block is the special div-not-quote
|
587
670
|
* marker %[kind:]name%
|
588
671
|
*/
|
672
|
+
#define iscsschar(c) (isalpha(c) || (c == '-') || (c == '_') )
|
673
|
+
|
589
674
|
static int
|
590
|
-
isdivmarker(Line *p, int start)
|
675
|
+
isdivmarker(Line *p, int start, DWORD flags)
|
591
676
|
{
|
592
|
-
|
593
|
-
|
594
|
-
int len = S(p->text);
|
595
|
-
int i;
|
677
|
+
char *s;
|
678
|
+
int last, i;
|
596
679
|
|
597
|
-
if (
|
680
|
+
if ( flags & (MKD_NODIVQUOTE|MKD_STRICT) )
|
681
|
+
return 0;
|
682
|
+
|
683
|
+
last= S(p->text) - (1 + start);
|
684
|
+
s = T(p->text) + start;
|
685
|
+
|
686
|
+
if ( (last <= 0) || (*s != '%') || (s[last] != '%') )
|
687
|
+
return 0;
|
598
688
|
|
599
|
-
i = szmarkerclass(s+
|
600
|
-
len -= start+1;
|
689
|
+
i = szmarkerclass(s+1);
|
601
690
|
|
602
|
-
|
603
|
-
|
691
|
+
if ( !iscsschar(s[i+1]) )
|
692
|
+
return 0;
|
693
|
+
while ( ++i < last )
|
694
|
+
if ( !(isdigit(s[i]) || iscsschar(s[i])) )
|
604
695
|
return 0;
|
605
696
|
|
606
697
|
return 1;
|
607
|
-
#else
|
608
|
-
return 0;
|
609
|
-
#endif
|
610
698
|
}
|
611
699
|
|
612
700
|
|
@@ -622,27 +710,36 @@ isdivmarker(Line *p, int start)
|
|
622
710
|
* way the markdown sample web form at Daring Fireball works.
|
623
711
|
*/
|
624
712
|
static Line *
|
625
|
-
quoteblock(Paragraph *p)
|
713
|
+
quoteblock(Paragraph *p, DWORD flags)
|
626
714
|
{
|
627
715
|
Line *t, *q;
|
628
716
|
int qp;
|
629
717
|
|
630
718
|
for ( t = p->text; t ; t = q ) {
|
631
719
|
if ( isquote(t) ) {
|
632
|
-
|
720
|
+
/* clip leading spaces */
|
721
|
+
for (qp = 0; T(t->text)[qp] != '>'; qp ++)
|
722
|
+
/* assert: the first nonblank character on this line
|
723
|
+
* will be a >
|
724
|
+
*/;
|
725
|
+
/* clip '>' */
|
726
|
+
qp++;
|
727
|
+
/* clip next space, if any */
|
728
|
+
if ( T(t->text)[qp] == ' ' )
|
729
|
+
qp++;
|
633
730
|
CLIP(t->text, 0, qp);
|
634
731
|
t->dle = mkd_firstnonblank(t);
|
635
732
|
}
|
636
733
|
|
637
734
|
q = skipempty(t->next);
|
638
735
|
|
639
|
-
if ( (q == 0) || ((q != t->next) && (!isquote(q) || isdivmarker(q,1))) ) {
|
736
|
+
if ( (q == 0) || ((q != t->next) && (!isquote(q) || isdivmarker(q,1,flags))) ) {
|
640
737
|
___mkd_freeLineRange(t, q);
|
641
738
|
t = q;
|
642
739
|
break;
|
643
740
|
}
|
644
741
|
}
|
645
|
-
if ( isdivmarker(p->text,0) ) {
|
742
|
+
if ( isdivmarker(p->text,0,flags) ) {
|
646
743
|
char *prefix = "class";
|
647
744
|
int i;
|
648
745
|
|
@@ -685,6 +782,8 @@ tableblock(Paragraph *p)
|
|
685
782
|
static Paragraph *Pp(ParagraphRoot *, Line *, int);
|
686
783
|
static Paragraph *compile(Line *, int, MMIOT *);
|
687
784
|
|
785
|
+
typedef int (*linefn)(Line *);
|
786
|
+
|
688
787
|
|
689
788
|
/*
|
690
789
|
* pull in a list block. A list block starts with a list marker and
|
@@ -693,7 +792,7 @@ static Paragraph *compile(Line *, int, MMIOT *);
|
|
693
792
|
* marker, but multiple paragraphs need to start with a 4-space indent.
|
694
793
|
*/
|
695
794
|
static Line *
|
696
|
-
listitem(Paragraph *p, int indent)
|
795
|
+
listitem(Paragraph *p, int indent, DWORD flags, linefn check)
|
697
796
|
{
|
698
797
|
Line *t, *q;
|
699
798
|
int clip = indent;
|
@@ -709,8 +808,9 @@ listitem(Paragraph *p, int indent)
|
|
709
808
|
}
|
710
809
|
|
711
810
|
/* after a blank line, the next block needs to start with a line
|
712
|
-
* that's indented 4
|
713
|
-
*
|
811
|
+
* that's indented 4(? -- reference implementation allows a 1
|
812
|
+
* character indent, but that has unfortunate side effects here)
|
813
|
+
* spaces, but after that the line doesn't need any indentation
|
714
814
|
*/
|
715
815
|
if ( q != t->next ) {
|
716
816
|
if (q->dle < indent) {
|
@@ -718,10 +818,14 @@ listitem(Paragraph *p, int indent)
|
|
718
818
|
t->next = 0;
|
719
819
|
return q;
|
720
820
|
}
|
721
|
-
indent
|
821
|
+
/* indent at least 2, and at most as
|
822
|
+
* as far as the initial line was indented. */
|
823
|
+
indent = clip ? clip : 2;
|
722
824
|
}
|
723
825
|
|
724
|
-
if ( (q->dle < indent) && (ishr(q) || islist(q,&z
|
826
|
+
if ( (q->dle < indent) && (ishr(q) || islist(q,&z,flags,&z)
|
827
|
+
|| (check && (*check)(q)))
|
828
|
+
&& !issetext(q,&z) ) {
|
725
829
|
q = t->next;
|
726
830
|
t->next = 0;
|
727
831
|
return q;
|
@@ -734,39 +838,81 @@ listitem(Paragraph *p, int indent)
|
|
734
838
|
|
735
839
|
|
736
840
|
static Line *
|
737
|
-
|
841
|
+
definition_block(Paragraph *top, int clip, MMIOT *f, int kind)
|
738
842
|
{
|
739
843
|
ParagraphRoot d = { 0, 0 };
|
740
844
|
Paragraph *p;
|
741
|
-
Line *q = top->text, *text, *
|
742
|
-
int
|
743
|
-
para = 0,
|
744
|
-
ltype;
|
845
|
+
Line *q = top->text, *text = 0, *labels;
|
846
|
+
int z, para;
|
745
847
|
|
746
|
-
while ((
|
747
|
-
|
748
|
-
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
848
|
+
while (( labels = q )) {
|
849
|
+
|
850
|
+
if ( (q = isdefinition(labels, &z, &kind)) == 0 )
|
851
|
+
break;
|
852
|
+
|
853
|
+
if ( (text = skipempty(q->next)) == 0 )
|
854
|
+
break;
|
855
|
+
|
856
|
+
if (( para = (text != q->next) ))
|
857
|
+
___mkd_freeLineRange(q, text);
|
858
|
+
|
859
|
+
q->next = 0;
|
860
|
+
if ( kind == 1 /* discount dl */ )
|
861
|
+
for ( q = labels; q; q = q->next ) {
|
862
|
+
CLIP(q->text, 0, 1);
|
863
|
+
S(q->text)--;
|
756
864
|
}
|
865
|
+
|
866
|
+
dd_block:
|
867
|
+
p = Pp(&d, text, LISTITEM);
|
868
|
+
|
869
|
+
text = listitem(p, clip, f->flags, (kind==2) ? is_extra_dd : 0);
|
870
|
+
p->down = compile(p->text, 0, f);
|
871
|
+
p->text = labels; labels = 0;
|
872
|
+
|
873
|
+
if ( para && p->down ) p->down->align = PARA;
|
874
|
+
|
875
|
+
if ( (q = skipempty(text)) == 0 )
|
876
|
+
break;
|
877
|
+
|
878
|
+
if (( para = (q != text) )) {
|
879
|
+
Line anchor;
|
880
|
+
|
881
|
+
anchor.next = text;
|
882
|
+
___mkd_freeLineRange(&anchor,q);
|
883
|
+
text = q;
|
884
|
+
|
757
885
|
}
|
758
|
-
else label = 0;
|
759
886
|
|
887
|
+
if ( kind == 2 && is_extra_dd(q) )
|
888
|
+
goto dd_block;
|
889
|
+
}
|
890
|
+
top->text = 0;
|
891
|
+
top->down = T(d);
|
892
|
+
return text;
|
893
|
+
}
|
894
|
+
|
895
|
+
|
896
|
+
static Line *
|
897
|
+
enumerated_block(Paragraph *top, int clip, MMIOT *f, int list_class)
|
898
|
+
{
|
899
|
+
ParagraphRoot d = { 0, 0 };
|
900
|
+
Paragraph *p;
|
901
|
+
Line *q = top->text, *text;
|
902
|
+
int para = 0, z;
|
903
|
+
|
904
|
+
while (( text = q )) {
|
905
|
+
|
760
906
|
p = Pp(&d, text, LISTITEM);
|
761
|
-
text = listitem(p,
|
907
|
+
text = listitem(p, clip, f->flags, 0);
|
762
908
|
|
763
909
|
p->down = compile(p->text, 0, f);
|
764
|
-
p->text =
|
910
|
+
p->text = 0;
|
765
911
|
|
766
|
-
if ( para &&
|
912
|
+
if ( para && p->down ) p->down->align = PARA;
|
767
913
|
|
768
|
-
if (
|
769
|
-
|
914
|
+
if ( (q = skipempty(text)) == 0
|
915
|
+
|| islist(q, &clip, f->flags, &z) != list_class )
|
770
916
|
break;
|
771
917
|
|
772
918
|
if ( para = (q != text) ) {
|
@@ -774,9 +920,9 @@ listblock(Paragraph *top, int trim, MMIOT *f)
|
|
774
920
|
|
775
921
|
anchor.next = text;
|
776
922
|
___mkd_freeLineRange(&anchor, q);
|
777
|
-
}
|
778
923
|
|
779
|
-
|
924
|
+
if ( p->down ) p->down->align = PARA;
|
925
|
+
}
|
780
926
|
}
|
781
927
|
top->text = 0;
|
782
928
|
top->down = T(d);
|
@@ -908,10 +1054,10 @@ compile_document(Line *ptr, MMIOT *f)
|
|
908
1054
|
ANCHOR(Line) source = { 0, 0 };
|
909
1055
|
Paragraph *p = 0;
|
910
1056
|
struct kw *tag;
|
911
|
-
int eaten;
|
1057
|
+
int eaten, unclosed;
|
912
1058
|
|
913
1059
|
while ( ptr ) {
|
914
|
-
if ( !(f->flags &
|
1060
|
+
if ( !(f->flags & MKD_NOHTML) && (tag = isopentag(ptr)) ) {
|
915
1061
|
/* If we encounter a html/style block, compile and save all
|
916
1062
|
* of the cached source BEFORE processing the html/style.
|
917
1063
|
*/
|
@@ -922,10 +1068,12 @@ compile_document(Line *ptr, MMIOT *f)
|
|
922
1068
|
T(source) = E(source) = 0;
|
923
1069
|
}
|
924
1070
|
p = Pp(&d, ptr, strcmp(tag->id, "STYLE") == 0 ? STYLE : HTML);
|
925
|
-
|
926
|
-
|
927
|
-
|
928
|
-
|
1071
|
+
ptr = htmlblock(p, tag, &unclosed);
|
1072
|
+
if ( unclosed ) {
|
1073
|
+
p->typ = SOURCE;
|
1074
|
+
p->down = compile(p->text, 1, f);
|
1075
|
+
p->text = 0;
|
1076
|
+
}
|
929
1077
|
}
|
930
1078
|
else if ( isfootnote(ptr) ) {
|
931
1079
|
/* footnotes, like cats, sleep anywhere; pull them
|
@@ -967,7 +1115,7 @@ compile(Line *ptr, int toplevel, MMIOT *f)
|
|
967
1115
|
Line *r;
|
968
1116
|
int para = toplevel;
|
969
1117
|
int blocks = 0;
|
970
|
-
int hdr_type, list_type, indent;
|
1118
|
+
int hdr_type, list_type, list_class, indent;
|
971
1119
|
|
972
1120
|
ptr = consume(ptr, ¶);
|
973
1121
|
|
@@ -990,13 +1138,19 @@ compile(Line *ptr, int toplevel, MMIOT *f)
|
|
990
1138
|
ptr = ptr->next;
|
991
1139
|
___mkd_freeLine(r);
|
992
1140
|
}
|
993
|
-
else if ((
|
994
|
-
|
995
|
-
|
1141
|
+
else if (( list_class = islist(ptr, &indent, f->flags, &list_type) )) {
|
1142
|
+
if ( list_class == DL ) {
|
1143
|
+
p = Pp(&d, ptr, DL);
|
1144
|
+
ptr = definition_block(p, indent, f, list_type);
|
1145
|
+
}
|
1146
|
+
else {
|
1147
|
+
p = Pp(&d, ptr, list_type);
|
1148
|
+
ptr = enumerated_block(p, indent, f, list_class);
|
1149
|
+
}
|
996
1150
|
}
|
997
1151
|
else if ( isquote(ptr) ) {
|
998
1152
|
p = Pp(&d, ptr, QUOTE);
|
999
|
-
ptr = quoteblock(p);
|
1153
|
+
ptr = quoteblock(p, f->flags);
|
1000
1154
|
p->down = compile(p->text, 1, f);
|
1001
1155
|
p->text = 0;
|
1002
1156
|
}
|
@@ -1004,13 +1158,13 @@ compile(Line *ptr, int toplevel, MMIOT *f)
|
|
1004
1158
|
p = Pp(&d, ptr, HDR);
|
1005
1159
|
ptr = headerblock(p, hdr_type);
|
1006
1160
|
}
|
1007
|
-
else if ( istable(ptr) && !(f->flags & (
|
1161
|
+
else if ( istable(ptr) && !(f->flags & (MKD_STRICT|MKD_NOTABLES)) ) {
|
1008
1162
|
p = Pp(&d, ptr, TABLE);
|
1009
1163
|
ptr = tableblock(p);
|
1010
1164
|
}
|
1011
1165
|
else {
|
1012
1166
|
p = Pp(&d, ptr, MARKUP);
|
1013
|
-
ptr = textblock(p, toplevel);
|
1167
|
+
ptr = textblock(p, toplevel, f->flags);
|
1014
1168
|
}
|
1015
1169
|
|
1016
1170
|
if ( (para||toplevel) && !p->align )
|
@@ -1028,19 +1182,6 @@ compile(Line *ptr, int toplevel, MMIOT *f)
|
|
1028
1182
|
}
|
1029
1183
|
|
1030
1184
|
|
1031
|
-
static void
|
1032
|
-
initialize()
|
1033
|
-
{
|
1034
|
-
static int first = 1;
|
1035
|
-
|
1036
|
-
if ( first-- > 0 ) {
|
1037
|
-
first = 0;
|
1038
|
-
INITRNG(time(0));
|
1039
|
-
qsort(blocktags, SZTAGS, sizeof blocktags[0], (stfu)casort);
|
1040
|
-
}
|
1041
|
-
}
|
1042
|
-
|
1043
|
-
|
1044
1185
|
/*
|
1045
1186
|
* the guts of the markdown() function, ripped out so I can do
|
1046
1187
|
* debugging.
|
@@ -1050,7 +1191,7 @@ initialize()
|
|
1050
1191
|
* prepare and compile `text`, returning a Paragraph tree.
|
1051
1192
|
*/
|
1052
1193
|
int
|
1053
|
-
mkd_compile(Document *doc,
|
1194
|
+
mkd_compile(Document *doc, DWORD flags)
|
1054
1195
|
{
|
1055
1196
|
if ( !doc )
|
1056
1197
|
return 0;
|
@@ -1060,13 +1201,13 @@ mkd_compile(Document *doc, int flags)
|
|
1060
1201
|
|
1061
1202
|
doc->compiled = 1;
|
1062
1203
|
memset(doc->ctx, 0, sizeof(MMIOT) );
|
1063
|
-
doc->ctx->
|
1064
|
-
doc->ctx->
|
1204
|
+
doc->ctx->cb = &(doc->cb);
|
1205
|
+
doc->ctx->flags = flags & USER_FLAGS;
|
1065
1206
|
CREATE(doc->ctx->in);
|
1066
1207
|
doc->ctx->footnotes = malloc(sizeof doc->ctx->footnotes[0]);
|
1067
1208
|
CREATE(*doc->ctx->footnotes);
|
1068
1209
|
|
1069
|
-
|
1210
|
+
mkd_initialize();
|
1070
1211
|
|
1071
1212
|
doc->code = compile_document(T(doc->content), doc->ctx);
|
1072
1213
|
qsort(T(*doc->ctx->footnotes), S(*doc->ctx->footnotes),
|