File indexing completed on 2024-04-28 11:21:08

0001 
0002 /*
0003  * github_flavoured -- implement the obnoxious "returns are hard newlines"
0004  *                     feature in github flavoured markdown.
0005  *
0006  * Copyright (C) 2012 David L Parsons.
0007  * The redistribution terms are provided in the COPYRIGHT file that must
0008  * be distributed with this source code.
0009  */
0010 #include "config.h"
0011 #include <stdio.h>
0012 #include <stdlib.h>
0013 #include <ctype.h>
0014 
0015 #include "cstring.h"
0016 #include "markdown.h"
0017 #include "amalloc.h"
0018 
0019 /* build a Document from any old input.
0020  */
0021 typedef int (*getc_func)(void*);
0022 
0023 Document *
0024 gfm_populate(getc_func getc, void* ctx, int flags)
0025 {
0026     Cstring line;
0027     Document *a = __mkd_new_Document();
0028     int c;
0029     int pandoc = 0;
0030 
0031     if ( !a ) return 0;
0032 
0033     a->tabstop = is_flag_set(flags, MKD_TABSTOP) ? 4 : TABSTOP;
0034 
0035     CREATE(line);
0036 
0037     while ( (c = (*getc)(ctx)) != EOF ) {
0038     if ( c == '\n' ) {
0039         if ( pandoc != EOF && pandoc < 3 ) {
0040         if ( S(line) && (T(line)[0] == '%') )
0041             pandoc++;
0042         else
0043             pandoc = EOF;
0044         }
0045             
0046             if (pandoc == EOF) {
0047         EXPAND(line) = ' ';
0048         EXPAND(line) = ' ';
0049         }
0050         __mkd_enqueue(a, &line);
0051         S(line) = 0;
0052     }
0053     else if ( isprint(c) || isspace(c) || (c & 0x80) )
0054         EXPAND(line) = c;
0055     }
0056 
0057     if ( S(line) )
0058     __mkd_enqueue(a, &line);
0059 
0060     DELETE(line);
0061 
0062     if ( (pandoc == 3) && !(is_flag_set(flags, MKD_NOHEADER)
0063      || is_flag_set(flags, MKD_STRICT)) ) {
0064     /* the first three lines started with %, so we have a header.
0065      * clip the first three lines out of content and hang them
0066      * off header.
0067      */
0068     Line *headers = T(a->content);
0069 
0070     a->title = headers;             __mkd_trim_line(a->title, 1);
0071     a->author= headers->next;       __mkd_trim_line(a->author, 1);
0072     a->date  = headers->next->next; __mkd_trim_line(a->date, 1);
0073 
0074     T(a->content) = headers->next->next->next;
0075     }
0076 
0077     return a;
0078 }
0079 
0080 
0081 /* convert a block of text into a linked list
0082  */
0083 Document *
0084 gfm_string(const char *buf, int len, mkd_flag_t flags)
0085 {
0086     struct string_stream about;
0087 
0088     about.data = buf;
0089     about.size = len;
0090 
0091     return gfm_populate((getc_func)__mkd_io_strget, &about, flags & INPUT_MASK);
0092 }
0093 
0094 
0095 /* convert a file into a linked list
0096  */
0097 Document *
0098 gfm_in(FILE *f, mkd_flag_t flags)
0099 {
0100     return gfm_populate((getc_func)fgetc, f, flags & INPUT_MASK);
0101 }