4 #include "include/parser.h"
6 document_t *markdown_load(FILE *input) {
8 int c = 0, i = 0, l = 0, bits = 0;
18 text = cstring_init();
20 while ((c = fgetc(input)) != EOF) {
24 bits = markdown_analyse(text);
26 // if text is markdown hr
27 if(CHECK_BIT(bits, IS_HR) &&
28 CHECK_BIT(line->bits, IS_EMPTY)) {
37 page = next_page(page);
51 line = next_line(line);
65 line->offset = next_nonblank(text, 0);
68 text = cstring_init();
74 } else if(c == '\t') {
76 // expand tab to spaces
77 for (i = 0; i <= 4; i++) {
78 (text->expand)(text, ' ');
82 } else if(isprint(c) || isspace(c)) {
85 (text->expand)(text, c);
87 // increase line lenght
90 } else if(is_utf8(c)) {
93 (text->expand)(text, c);
95 // if utf-8 char > 1 byte add remaing to line
96 for(i = 0; i < length_utf8(c) - 1; i++) {
98 (text->expand)(text, c);
101 // increase line length
107 line = doc->page->line;
108 if(line && line->text->size > 0 && line->text->text[0] == '%') {
110 // assign header to document
113 // find first non-header line
114 while(line->text->size > 0 && line->text->text[0] == '%') {
119 line->prev->next = (void*)0;
120 line->prev = (void*)0;
122 // remove header lines from page
123 doc->page->line = line;
126 // combine underlined H1/H2 in single line
131 if((CHECK_BIT(line->bits, IS_H1) ||
132 CHECK_BIT(line->bits, IS_H2)) &&
133 CHECK_BIT(line->bits, IS_EMPTY) &&
135 !CHECK_BIT(line->prev->bits, IS_EMPTY)) {
137 // remove line from linked list
138 line->prev->next = line->next;
139 line->next->prev = line->prev;
141 // set bits on revious line
142 if(CHECK_BIT(line->bits, IS_H1)) {
143 SET_BIT(line->prev->bits, IS_H1);
145 SET_BIT(line->prev->bits, IS_H2);
149 (line->text->delete)(line->text);
160 int markdown_analyse(cstring_t *text) {
163 equals = 0, hashes = 0,
164 stars = 0, minus = 0,
165 spaces = 0, other = 0;
167 // count leading spaces
168 offset = next_nonblank(text, 0);
170 // strip trailing spaces
171 for(eol = text->size; eol > offset && isspace(text->text[eol - 1]); eol--);
173 for(i = offset; i < eol; i++) {
175 switch(text->text[i]) {
176 case '=': equals++; break;
177 case '#': hashes++; break;
178 case '*': stars++; break;
179 case '-': minus++; break;
180 case ' ': spaces++; break;
181 default: other++; break;
187 hashes + stars + minus + spaces + other == 0) ||
190 text->text[offset] == '#' &&
191 text->text[offset+1] != '#')) {
193 SET_BIT(bits, IS_H1);
198 equals + hashes + stars + spaces + other == 0) ||
201 text->text[offset] == '#' &&
202 text->text[offset+1] == '#')) {
204 SET_BIT(bits, IS_H2);
210 text->text[offset] == '>') {
212 SET_BIT(bits, IS_QUOTE);
217 SET_BIT(bits, IS_CODE);
221 if((minus >= 3 && equals + hashes + stars + other == 0) ||
222 (stars >= 3 && equals + hashes + minus + other == 0)) {
224 SET_BIT(bits, IS_HR);
229 SET_BIT(bits, IS_EMPTY);
235 int is_utf8(char ch) {
239 int length_utf8(char ch) {
248 int next_nonblank(cstring_t *text, int i) {
249 while ((i < text->size) && isspace((text->text)[i]))
254 int next_blank(cstring_t *text, int i) {
255 while ((i < text->size) && !isspace((text->text)[i]))