4 #include "include/cstring.h"
5 #include "include/markdown.h"
7 document_t *markdown_load(FILE *input) {
9 int c = 0, i = 0, bits = 0;
19 text = cstring_init();
21 while ((c = fgetc(input)) != EOF) {
25 bits = markdown_analyse(text);
27 // if text is markdown hr
28 if(CHECK_BIT(bits, IS_HR) &&
29 CHECK_BIT(line->bits, IS_EMPTY)) {
34 page = next_page(page);
48 line = next_line(line);
59 line->offset = next_nonblank(text, 0);
62 text = cstring_init();
65 } else if(c == '\t') {
67 // expand tab to spaces
68 for (i = 0; i <= 4; i++)
69 (text->expand)(text, ' ');
71 } else if(isprint(c) || isspace(c) || is_utf8(c)) {
74 (text->expand)(text, c);
79 line = doc->page->line;
80 if(line && line->text->size > 0 && line->text->text[0] == '%') {
82 // assign header to document
85 // find first non-header line
86 while(line->text->size > 0 && line->text->text[0] == '%') {
91 line->prev->next = (void*)0;
92 line->prev = (void*)0;
94 // remove header lines from page
95 doc->page->line = line;
98 // combine underlined H1/H2 in single line
103 if((CHECK_BIT(line->bits, IS_H1) ||
104 CHECK_BIT(line->bits, IS_H2)) &&
105 CHECK_BIT(line->bits, IS_EMPTY) &&
107 !CHECK_BIT(line->prev->bits, IS_EMPTY)) {
109 // remove line from linked list
110 line->prev->next = line->next;
111 line->next->prev = line->prev;
113 // set bits on revious line
114 if(CHECK_BIT(line->bits, IS_H1)) {
115 SET_BIT(line->prev->bits, IS_H1);
117 SET_BIT(line->prev->bits, IS_H2);
121 (line->text->delete)(line->text);
132 int markdown_analyse(cstring_t *text) {
135 equals = 0, hashes = 0,
136 stars = 0, minus = 0,
137 spaces = 0, other = 0;
139 // count leading spaces
140 offset = next_nonblank(text, 0);
142 // strip trailing spaces
143 for(eol = text->size; eol > offset && isspace(text->text[eol - 1]); eol--);
145 for(i = offset; i < eol; i++) {
147 switch(text->text[i]) {
148 case '=': equals++; break;
149 case '#': hashes++; break;
150 case '*': stars++; break;
151 case '-': minus++; break;
152 case ' ': spaces++; break;
153 default: other++; break;
159 hashes + stars + minus + spaces + other == 0) ||
162 text->text[offset] == '#' &&
163 text->text[offset+1] != '#')) {
165 SET_BIT(bits, IS_H1);
170 equals + hashes + stars + spaces + other == 0) ||
173 text->text[offset] == '#' &&
174 text->text[offset+1] == '#')) {
176 SET_BIT(bits, IS_H2);
182 text->text[offset] == '>') {
184 SET_BIT(bits, IS_QUOTE);
189 SET_BIT(bits, IS_CODE);
193 if((minus >= 3 && equals + hashes + stars + other == 0) ||
194 (stars >= 3 && equals + hashes + minus + other == 0)) {
196 SET_BIT(bits, IS_HR);
201 SET_BIT(bits, IS_EMPTY);
207 int is_utf8(char ch) {
211 int next_nonblank(cstring_t *text, int i) {
212 while ((i < text->size) && isspace((text->text)[i]))
217 int next_blank(cstring_t *text, int i) {
218 while ((i < text->size) && !isspace((text->text)[i]))