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/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
2.0.5
|
data/ext/bluecloth.c
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* BlueCloth -- a Ruby implementation of Markdown
|
3
|
-
* $Id$
|
3
|
+
* $Id: bluecloth.c,v 0cda68a5fc00 2011/02/09 22:33:27 ged $
|
4
4
|
*
|
5
5
|
* = Authors
|
6
6
|
*
|
@@ -32,11 +32,11 @@ VALUE bluecloth_default_opthash;
|
|
32
32
|
static MMIOT *
|
33
33
|
bluecloth_alloc( VALUE text, int flags ) {
|
34
34
|
MMIOT *document;
|
35
|
-
|
35
|
+
|
36
36
|
document = mkd_string( RSTRING_PTR(text), RSTRING_LEN(text), flags );
|
37
37
|
if ( !document )
|
38
38
|
rb_raise( rb_eRuntimeError, "Failed to create a BlueCloth object for: %s", RSTRING_PTR(text) );
|
39
|
-
|
39
|
+
|
40
40
|
return document;
|
41
41
|
}
|
42
42
|
|
@@ -44,7 +44,7 @@ bluecloth_alloc( VALUE text, int flags ) {
|
|
44
44
|
/*
|
45
45
|
* GC Free function
|
46
46
|
*/
|
47
|
-
static void
|
47
|
+
static void
|
48
48
|
bluecloth_gc_free( MMIOT *document ) {
|
49
49
|
if ( document ) {
|
50
50
|
mkd_cleanup( document );
|
@@ -100,7 +100,7 @@ bluecloth_check_ptr( VALUE self ) {
|
|
100
100
|
rb_raise( rb_eTypeError, "wrong argument type %s (expected BlueCloth object)",
|
101
101
|
rb_class2name(CLASS_OF( self )) );
|
102
102
|
}
|
103
|
-
|
103
|
+
|
104
104
|
return DATA_PTR( self );
|
105
105
|
}
|
106
106
|
|
@@ -181,12 +181,13 @@ bluecloth_s_discount_version( VALUE klass ) {
|
|
181
181
|
* superscript notation. Defaults to +true+.
|
182
182
|
*
|
183
183
|
*/
|
184
|
-
static VALUE
|
184
|
+
static VALUE
|
185
185
|
bluecloth_initialize( int argc, VALUE *argv, VALUE self ) {
|
186
186
|
if ( !bluecloth_check_ptr(self) ) {
|
187
187
|
MMIOT *document;
|
188
|
-
VALUE text,
|
188
|
+
VALUE text, optflags, fullhash, opthash = Qnil;
|
189
189
|
int flags = 0;
|
190
|
+
VALUE utf8text = Qnil;
|
190
191
|
|
191
192
|
rb_scan_args( argc, argv, "02", &text, &opthash );
|
192
193
|
|
@@ -201,7 +202,7 @@ bluecloth_initialize( int argc, VALUE *argv, VALUE self ) {
|
|
201
202
|
text = rb_str_new( "", 0 );
|
202
203
|
}
|
203
204
|
else {
|
204
|
-
text = rb_obj_as_string(
|
205
|
+
text = rb_obj_dup( rb_obj_as_string(text) );
|
205
206
|
}
|
206
207
|
|
207
208
|
/* Merge the options hash with the defaults and turn it into a flags int */
|
@@ -210,13 +211,21 @@ bluecloth_initialize( int argc, VALUE *argv, VALUE self ) {
|
|
210
211
|
fullhash = rb_funcall( bluecloth_cBlueCloth, rb_intern("opthash_from_flags"), 1, optflags );
|
211
212
|
|
212
213
|
flags = NUM2INT( optflags );
|
214
|
+
|
215
|
+
#ifdef M17N_SUPPORTED
|
216
|
+
bluecloth_debug( "Bytes before utf8ification: %s",
|
217
|
+
RSTRING_PTR(rb_funcall(text, rb_intern("dump"), 0, Qnil)) );
|
218
|
+
utf8text = rb_str_export_to_enc( rb_str_dup(text), rb_utf8_encoding() );
|
219
|
+
DATA_PTR( self ) = document = bluecloth_alloc( utf8text, flags );
|
220
|
+
#else
|
213
221
|
DATA_PTR( self ) = document = bluecloth_alloc( text, flags );
|
222
|
+
#endif /* M17N_SUPPORTED */
|
223
|
+
|
214
224
|
if ( !mkd_compile(document, flags) )
|
215
225
|
rb_raise( rb_eRuntimeError, "Failed to compile markdown" );
|
216
226
|
|
217
|
-
|
218
|
-
|
219
|
-
rb_iv_set( self, "@text", textcopy );
|
227
|
+
OBJ_FREEZE( text );
|
228
|
+
rb_iv_set( self, "@text", text );
|
220
229
|
OBJ_FREEZE( fullhash );
|
221
230
|
rb_iv_set( self, "@options", fullhash );
|
222
231
|
|
@@ -242,12 +251,20 @@ bluecloth_to_html( VALUE self ) {
|
|
242
251
|
VALUE result = Qnil;
|
243
252
|
|
244
253
|
bluecloth_debug( "Compiling document %p", document );
|
245
|
-
|
254
|
+
|
246
255
|
if ( (length = mkd_document( document, &output )) != EOF ) {
|
247
|
-
|
248
|
-
|
256
|
+
#ifdef M17N_SUPPORTED
|
257
|
+
VALUE orig_encoding = rb_obj_encoding( rb_iv_get(self, "@text") );
|
258
|
+
VALUE utf8_result = rb_enc_str_new( output, strlen(output), rb_utf8_encoding() );
|
259
|
+
result = rb_str_encode( utf8_result, orig_encoding, 0, Qnil );
|
260
|
+
bluecloth_debug( "Bytes after un-utf8ification (if necessary): %s",
|
261
|
+
RSTRING_PTR(rb_funcall(result, rb_intern("dump"), 0, Qnil)) );
|
262
|
+
#else
|
263
|
+
result = rb_str_new2( output );
|
264
|
+
#endif /* M17N_SUPPORTED */
|
249
265
|
|
250
266
|
OBJ_INFECT( result, self );
|
267
|
+
|
251
268
|
return result;
|
252
269
|
} else {
|
253
270
|
return Qnil;
|
@@ -283,7 +300,7 @@ bluecloth_header( VALUE self ) {
|
|
283
300
|
VALUE fieldstring, headers = rb_hash_new();
|
284
301
|
|
285
302
|
bluecloth_debug( "Fetching pandoc headers for document %p", document );
|
286
|
-
|
303
|
+
|
287
304
|
if ( (field = mkd_doc_title(document)) ) {
|
288
305
|
fieldstring = rb_str_new2( field );
|
289
306
|
OBJ_INFECT( fieldstring, self );
|
@@ -312,6 +329,9 @@ bluecloth_header( VALUE self ) {
|
|
312
329
|
void Init_bluecloth_ext( void ) {
|
313
330
|
bluecloth_cBlueCloth = rb_define_class( "BlueCloth", rb_cObject );
|
314
331
|
|
332
|
+
mkd_with_html5_tags();
|
333
|
+
mkd_initialize();
|
334
|
+
|
315
335
|
rb_define_alloc_func( bluecloth_cBlueCloth, bluecloth_s_allocate );
|
316
336
|
rb_define_singleton_method( bluecloth_cBlueCloth, "discount_version",
|
317
337
|
bluecloth_s_discount_version, 0 );
|
@@ -321,10 +341,10 @@ void Init_bluecloth_ext( void ) {
|
|
321
341
|
rb_define_method( bluecloth_cBlueCloth, "to_html", bluecloth_to_html, 0 );
|
322
342
|
rb_define_method( bluecloth_cBlueCloth, "header", bluecloth_header, 0 );
|
323
343
|
rb_define_alias( bluecloth_cBlueCloth, "pandoc_header", "header" );
|
324
|
-
|
344
|
+
|
325
345
|
/* The original Markdown text the object was constructed with */
|
326
346
|
rb_define_attr( bluecloth_cBlueCloth, "text", 1, 0 );
|
327
|
-
|
347
|
+
|
328
348
|
/* The options hash that describes the options in effect when the object was created */
|
329
349
|
rb_define_attr( bluecloth_cBlueCloth, "options", 1, 0 );
|
330
350
|
|
@@ -339,22 +359,37 @@ void Init_bluecloth_ext( void ) {
|
|
339
359
|
|
340
360
|
/* Do not do Smartypants-style mangling of quotes, dashes, or ellipses. */
|
341
361
|
rb_define_const( bluecloth_cBlueCloth, "MKD_NOPANTS", INT2FIX(MKD_NOPANTS) );
|
342
|
-
|
362
|
+
|
343
363
|
/* Escape all opening angle brackets in the input text instead of allowing block-level HTML */
|
344
364
|
rb_define_const( bluecloth_cBlueCloth, "MKD_NOHTML", INT2FIX(MKD_NOHTML) );
|
345
365
|
|
346
366
|
/* disable SUPERSCRIPT, RELAXED_EMPHASIS */
|
347
367
|
rb_define_const( bluecloth_cBlueCloth, "MKD_STRICT", INT2FIX(MKD_STRICT) );
|
348
|
-
|
368
|
+
|
349
369
|
/* process text inside an html tag; no <em>, no <bold>, no html or [] expansion */
|
350
370
|
rb_define_const( bluecloth_cBlueCloth, "MKD_TAGTEXT", INT2FIX(MKD_TAGTEXT) );
|
351
|
-
|
371
|
+
|
352
372
|
/* don't allow pseudo-protocols */
|
353
373
|
rb_define_const( bluecloth_cBlueCloth, "MKD_NO_EXT", INT2FIX(MKD_NO_EXT) );
|
354
|
-
|
374
|
+
|
375
|
+
/* Generate code for xml ![CDATA[...]] */
|
376
|
+
rb_define_const( bluecloth_cBlueCloth, "MKD_CDATA", INT2FIX(MKD_CDATA) );
|
377
|
+
|
378
|
+
/* Don't use superscript extension */
|
379
|
+
rb_define_const( bluecloth_cBlueCloth, "MKD_NOSUPERSCRIPT", INT2FIX(MKD_NOSUPERSCRIPT) );
|
380
|
+
|
381
|
+
/* Relaxed emphasis -- emphasis happens everywhere */
|
382
|
+
rb_define_const( bluecloth_cBlueCloth, "MKD_NORELAXED", INT2FIX(MKD_NORELAXED) );
|
383
|
+
|
384
|
+
/* disallow tables */
|
385
|
+
rb_define_const( bluecloth_cBlueCloth, "MKD_NOTABLES", INT2FIX(MKD_NOTABLES) );
|
386
|
+
|
387
|
+
/* forbid ~~strikethrough~~ */
|
388
|
+
rb_define_const( bluecloth_cBlueCloth, "MKD_NOSTRIKETHROUGH", INT2FIX(MKD_NOSTRIKETHROUGH) );
|
389
|
+
|
355
390
|
/* do table-of-contents processing */
|
356
391
|
rb_define_const( bluecloth_cBlueCloth, "MKD_TOC", INT2FIX(MKD_TOC) );
|
357
|
-
|
392
|
+
|
358
393
|
/* MarkdownTest 1.0 Compatibility Mode */
|
359
394
|
rb_define_const( bluecloth_cBlueCloth, "MKD_1_COMPAT", INT2FIX(MKD_1_COMPAT) );
|
360
395
|
|
@@ -367,10 +402,21 @@ void Init_bluecloth_ext( void ) {
|
|
367
402
|
/* Be paranoid about link protocols */
|
368
403
|
rb_define_const( bluecloth_cBlueCloth, "MKD_SAFELINK", INT2FIX(MKD_SAFELINK) );
|
369
404
|
|
370
|
-
|
371
405
|
/* don't process header blocks */
|
372
406
|
rb_define_const( bluecloth_cBlueCloth, "MKD_NOHEADER", INT2FIX(MKD_NOHEADER) );
|
373
407
|
|
408
|
+
/* Expand tabs to 4 spaces */
|
409
|
+
rb_define_const( bluecloth_cBlueCloth, "MKD_TABSTOP", INT2FIX(MKD_TABSTOP) );
|
410
|
+
|
411
|
+
/* Forbid '>%class%' blocks */
|
412
|
+
rb_define_const( bluecloth_cBlueCloth, "MKD_NODIVQUOTE", INT2FIX(MKD_NODIVQUOTE) );
|
413
|
+
|
414
|
+
/* Forbid alphabetic lists */
|
415
|
+
rb_define_const( bluecloth_cBlueCloth, "MKD_NOALPHALIST", INT2FIX(MKD_NOALPHALIST) );
|
416
|
+
|
417
|
+
/* Forbid definition lists */
|
418
|
+
rb_define_const( bluecloth_cBlueCloth, "MKD_NODLIST", INT2FIX(MKD_NODLIST) );
|
419
|
+
|
374
420
|
|
375
421
|
/* Make sure the Ruby side is loaded */
|
376
422
|
rb_require( "bluecloth" );
|
data/ext/bluecloth.h
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* BlueCloth -- a Ruby implementation of Markdown
|
3
|
-
* $Id$
|
3
|
+
* $Id: bluecloth.h,v 0cda68a5fc00 2011/02/09 22:33:27 ged $
|
4
4
|
*
|
5
5
|
*/
|
6
6
|
|
@@ -8,12 +8,23 @@
|
|
8
8
|
#define BLUECLOTH_H
|
9
9
|
|
10
10
|
#include "config.h"
|
11
|
+
#include "assert.h"
|
11
12
|
|
12
13
|
#include "mkdio.h"
|
13
14
|
#include "ruby.h"
|
14
15
|
|
15
|
-
|
16
|
+
void mkd_initialize _(( void ));
|
17
|
+
void mkd_with_html5_tags _(( void ));
|
18
|
+
|
19
|
+
#if defined(HAVE_RUBY_ENCODING_H) && HAVE_RUBY_ENCODING_H
|
20
|
+
# define M17N_SUPPORTED
|
16
21
|
# include "ruby/encoding.h"
|
17
22
|
#endif
|
18
23
|
|
24
|
+
/* Replace the macro from encoding.h that refers to static 'rb_encoding_list' */
|
25
|
+
#ifdef ENC_FROM_ENCINDEX
|
26
|
+
#undef ENC_FROM_ENCINDEX
|
27
|
+
#define ENC_FROM_ENCINDEX(idx) (rb_enc_from_index(idx))
|
28
|
+
#endif
|
29
|
+
|
19
30
|
#endif
|
data/ext/config.h
CHANGED
@@ -1,11 +1,22 @@
|
|
1
1
|
/*
|
2
|
-
*
|
3
|
-
* by ged@tenar.home.faeriemud.org
|
2
|
+
* Hacked-up version of the config file generated by discount
|
4
3
|
*/
|
5
4
|
|
6
5
|
#ifndef CONFIG_H_RZLE3ADO
|
7
6
|
#define CONFIG_H_RZLE3ADO
|
8
7
|
|
8
|
+
#include "extconf.h"
|
9
|
+
|
10
|
+
#if SIZEOF_LONG == 8
|
11
|
+
# define DWORD unsigned int
|
12
|
+
# define WORD unsigned short
|
13
|
+
#else
|
14
|
+
# define DWORD unsigned long
|
15
|
+
# define WORD unsigned int
|
16
|
+
#endif
|
17
|
+
|
18
|
+
#define BYTE unsigned char
|
19
|
+
|
9
20
|
#ifdef RUBY_EXTCONF_H
|
10
21
|
# include RUBY_EXTCONF_H
|
11
22
|
#endif
|
data/ext/css.c
CHANGED
@@ -28,9 +28,10 @@ stylesheets(Paragraph *p, Cstring *f)
|
|
28
28
|
|
29
29
|
for ( ; p ; p = p->next ) {
|
30
30
|
if ( p->typ == STYLE ) {
|
31
|
-
for ( q = p->text; q ; q = q->next )
|
31
|
+
for ( q = p->text; q ; q = q->next ) {
|
32
32
|
Cswrite(f, T(q->text), S(q->text));
|
33
33
|
Csputc('\n', f);
|
34
|
+
}
|
34
35
|
}
|
35
36
|
if ( p->down )
|
36
37
|
stylesheets(p->down, f);
|
@@ -44,17 +45,25 @@ int
|
|
44
45
|
mkd_css(Document *d, char **res)
|
45
46
|
{
|
46
47
|
Cstring f;
|
48
|
+
int size;
|
47
49
|
|
48
|
-
if ( res &&
|
50
|
+
if ( res && d && d->compiled ) {
|
51
|
+
*res = 0;
|
49
52
|
CREATE(f);
|
50
53
|
RESERVE(f, 100);
|
51
54
|
stylesheets(d->code, &f);
|
52
55
|
|
56
|
+
if ( (size = S(f)) > 0 ) {
|
57
|
+
EXPAND(f) = 0;
|
53
58
|
/* HACK ALERT! HACK ALERT! HACK ALERT! */
|
54
|
-
|
59
|
+
*res = T(f);/* we know that a T(Cstring) is a character pointer */
|
55
60
|
/* so we can simply pick it up and carry it away, */
|
56
|
-
|
61
|
+
/* leaving the husk of the Ctring on the stack */
|
57
62
|
/* END HACK ALERT */
|
63
|
+
}
|
64
|
+
else
|
65
|
+
DELETE(f);
|
66
|
+
return size;
|
58
67
|
}
|
59
68
|
return EOF;
|
60
69
|
}
|
@@ -69,7 +78,7 @@ mkd_generatecss(Document *d, FILE *f)
|
|
69
78
|
int written = EOF, size = mkd_css(d, &res);
|
70
79
|
|
71
80
|
if ( size > 0 )
|
72
|
-
written = fwrite(res,
|
81
|
+
written = fwrite(res, 1, size, f);
|
73
82
|
if ( res )
|
74
83
|
free(res);
|
75
84
|
return (written == size) ? size : EOF;
|
data/ext/cstring.h
CHANGED
@@ -10,13 +10,15 @@
|
|
10
10
|
#include <string.h>
|
11
11
|
#include <stdlib.h>
|
12
12
|
|
13
|
-
#
|
13
|
+
#ifndef __WITHOUT_AMALLOC
|
14
|
+
# include "amalloc.h"
|
15
|
+
#endif
|
14
16
|
|
15
17
|
/* expandable Pascal-style string.
|
16
18
|
*/
|
17
19
|
#define STRING(type) struct { type *text; int size, alloc; }
|
18
20
|
|
19
|
-
#define CREATE(x) T(x) = (void*)(S(x) = (x).alloc = 0)
|
21
|
+
#define CREATE(x) ( (T(x) = (void*)0), (S(x) = (x).alloc = 0) )
|
20
22
|
#define EXPAND(x) (S(x)++)[(S(x) < (x).alloc) \
|
21
23
|
? (T(x)) \
|
22
24
|
: (T(x) = T(x) ? realloc(T(x), sizeof T(x)[0] * ((x).alloc += 100)) \
|
data/ext/docheader.c
CHANGED
@@ -14,13 +14,19 @@
|
|
14
14
|
#include "markdown.h"
|
15
15
|
#include "amalloc.h"
|
16
16
|
|
17
|
-
|
17
|
+
static char *
|
18
|
+
onlyifset(Line *l)
|
19
|
+
{
|
20
|
+
char *ret = T(l->text) + l->dle;
|
21
|
+
|
22
|
+
return ret[0] ? ret : 0;
|
23
|
+
}
|
18
24
|
|
19
25
|
char *
|
20
26
|
mkd_doc_title(Document *doc)
|
21
27
|
{
|
22
|
-
if ( doc && doc->
|
23
|
-
return
|
28
|
+
if ( doc && doc->title )
|
29
|
+
return onlyifset(doc->title);
|
24
30
|
return 0;
|
25
31
|
}
|
26
32
|
|
@@ -28,8 +34,8 @@ mkd_doc_title(Document *doc)
|
|
28
34
|
char *
|
29
35
|
mkd_doc_author(Document *doc)
|
30
36
|
{
|
31
|
-
if ( doc && doc->
|
32
|
-
return
|
37
|
+
if ( doc && doc->author )
|
38
|
+
return onlyifset(doc->author);
|
33
39
|
return 0;
|
34
40
|
}
|
35
41
|
|
@@ -37,7 +43,7 @@ mkd_doc_author(Document *doc)
|
|
37
43
|
char *
|
38
44
|
mkd_doc_date(Document *doc)
|
39
45
|
{
|
40
|
-
if ( doc && doc->
|
41
|
-
return
|
46
|
+
if ( doc && doc->date )
|
47
|
+
return onlyifset(doc->date);
|
42
48
|
return 0;
|
43
49
|
}
|
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 */
|