123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- /* markdown: a C implementation of John Gruber's Markdown markup language.
- *
- * Copyright (C) 2010 David L Parsons.
- * The redistribution terms are provided in the COPYRIGHT file that must
- * be distributed with this source code.
- */
- #include <stdio.h>
- #include <string.h>
- #include <stdarg.h>
- #include <stdlib.h>
- #include <time.h>
- #include <ctype.h>
- #include "config.h"
- #include "cstring.h"
- #include "markdown.h"
- #include "amalloc.h"
- /* emmatch: the emphasis mangler that's run after a block
- * of html has been generated.
- *
- * It should create MarkdownTest_1.0 (and _1.0.3)
- * compatible emphasis for non-pathological cases
- * and it should fail in a standards-compliant way
- * when someone attempts to feed it junk.
- *
- * Emmatching is done after the input has been
- * processed into a STRING (f->Q) of text and
- * emphasis blocks. After ___mkd_emblock() finishes,
- * it truncates f->Q and leaves the rendered paragraph
- * if f->out.
- */
- /* empair() -- find the NEAREST matching emphasis token (or
- * subtoken of a 3+ long emphasis token.
- */
- static int
- empair(MMIOT *f, int first, int last, int match)
- {
-
- int i;
- block *begin, *p;
- begin = &T(f->Q)[first];
- for (i=first+1; i <= last; i++) {
- p = &T(f->Q)[i];
- if ( (p->b_type != bTEXT) && (p->b_count <= 0) )
- continue; /* break? */
-
- if ( p->b_type == begin->b_type ) {
- if ( p->b_count == match ) /* exact match */
- return i;
- if ( p->b_count > 2 ) /* fuzzy match */
- return i;
- }
- }
- return 0;
- } /* empair */
- /* emfill() -- if an emphasis token has leftover stars or underscores,
- * convert them back into character and append them to b_text.
- */
- static void
- emfill(block *p)
- {
- int j;
- if ( p->b_type == bTEXT )
- return;
-
- for (j=0; j < p->b_count; j++)
- EXPAND(p->b_text) = p->b_char;
- p->b_count = 0;
- } /* emfill */
- static void
- emclose(MMIOT *f, int first, int last)
- {
- int j;
- for (j=first+1; j<last-1; j++)
- emfill(&T(f->Q)[j]);
- }
- static struct emtags {
- char open[10];
- char close[10];
- int size;
- } emtags[] = { { "<em>" , "</em>", 5 }, { "<strong>", "</strong>", 9 } };
- static void emblock(MMIOT*,int,int);
- /* emmatch() -- match emphasis for a single emphasis token.
- */
- static void
- emmatch(MMIOT *f, int first, int last)
- {
- block *start = &T(f->Q)[first];
- int e, e2, match;
- switch (start->b_count) {
- case 2: if ( e = empair(f,first,last,match=2) )
- break;
- case 1: e = empair(f,first,last,match=1);
- break;
- case 0: return;
- default:
- e = empair(f,first,last,1);
- e2= empair(f,first,last,2);
- if ( e2 >= e ) {
- e = e2;
- match = 2;
- }
- else
- match = 1;
- break;
- }
- if ( e ) {
- /* if we found emphasis to match, match it, recursively call
- * emblock to match emphasis inside the new html block, add
- * the emphasis markers for the block, then (tail) recursively
- * call ourself to match any remaining emphasis on this token.
- */
- block *end = &T(f->Q)[e];
- end->b_count -= match;
- start->b_count -= match;
- emblock(f, first, e);
- PREFIX(start->b_text, emtags[match-1].open, emtags[match-1].size-1);
- SUFFIX(end->b_post, emtags[match-1].close, emtags[match-1].size);
- emmatch(f, first, last);
- }
- } /* emmatch */
- /* emblock() -- walk a blocklist, attempting to match emphasis
- */
- static void
- emblock(MMIOT *f, int first, int last)
- {
- int i;
-
- for ( i = first; i <= last; i++ )
- if ( T(f->Q)[i].b_type != bTEXT )
- emmatch(f, i, last);
- emclose(f, first, last);
- } /* emblock */
- /* ___mkd_emblock() -- emblock a string of blocks, then concatenate the
- * resulting text onto f->out.
- */
- void
- ___mkd_emblock(MMIOT *f)
- {
- int i;
- block *p;
- emblock(f, 0, S(f->Q)-1);
-
- for (i=0; i < S(f->Q); i++) {
- p = &T(f->Q)[i];
- emfill(p);
-
- if ( S(p->b_post) ) { SUFFIX(f->out, T(p->b_post), S(p->b_post));
- DELETE(p->b_post); }
- if ( S(p->b_text) ) { SUFFIX(f->out, T(p->b_text), S(p->b_text));
- DELETE(p->b_text); }
- }
-
- S(f->Q) = 0;
- } /* ___mkd_emblock */
|