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 }