diff --git a/gemtext-parser.c b/gemtext-parser.c index 4ac2a43..72b830f 100644 --- a/gemtext-parser.c +++ b/gemtext-parser.c @@ -302,7 +302,7 @@ void switchMode(gemtextParser *parser, gemtextParserMode mode, char c) { void enterPreformattedMode(gemtextParser *parser) { parser->mode = preformattedMode; - parser->state = preformattedAlt; + parser->state = trimStart; lineBufferReset(&parser->buffer); } @@ -360,13 +360,24 @@ int parsePreformatted(gemtextParser *parser, gemtextLineQueue *lq, char c) { assert(parser->mode == preformattedMode); switch (parser->state) { + case trimStart: + if (c == '\n') { + parser->state = lineStart; + parser->altText = NULL; + } else if (c == ' ' || c == '\t') { + lineBufferRewind(&parser->buffer); + } else { + parser->state = preformattedAlt; + } + break; case preformattedAlt: if (c == '\n') { - parser->state = normalState; + parser->state = lineStart; if (parser->buffer.len > 0) { - buf = strncpy(buf, parser->buffer.buf, parser->buffer.len); + buf = strndup(parser->buffer.buf, parser->buffer.len - 1); if (buf == NULL) return errno; parser->altText = buf; + lineBufferReset(&parser->buffer); } } break; @@ -377,7 +388,11 @@ int parsePreformatted(gemtextParser *parser, gemtextLineQueue *lq, char c) { break; case lineStart: if (c == '\n') { + parser->state = lineStart; + } else if (c == '`') { parser->state = firstBacktickChar; + } else { + parser->state = normalState; } break; case firstBacktickChar: @@ -564,6 +579,7 @@ int parseNormal(gemtextParser *parser, gemtextLineQueue *lq, char c) { parser->state = normalState; parser->mode = normalMode; } + break; case secondBacktickChar: if (c == '`') { enterPreformattedMode(parser); @@ -574,6 +590,7 @@ int parseNormal(gemtextParser *parser, gemtextLineQueue *lq, char c) { parser->state = normalState; parser->mode = normalMode; } + break; default: break; } diff --git a/test/parse-gemtext0.c b/test/parse-gemtext0.c index e574da3..a3949ef 100644 --- a/test/parse-gemtext0.c +++ b/test/parse-gemtext0.c @@ -81,7 +81,17 @@ int main() { assert(memcmp(line->link->display, "This is a link", 14) == 0); gemtextLineDeinit(line); - gemtextLineDeinit(lq.head); + line = gemtextLineQueueTryPop(&lq); + assert(line->lineType == normalLine); + assert(*line->str == '\n'); + gemtextLineDeinit(line); + + line = gemtextLineQueueTryPop(&lq); + assert(line->lineType == preformattedLine); + assert(memcmp(line->node->altText, "Test preformatted block", 23) == 0); + assert(memcmp(line->node->body, "This is a preformatted block", 28) == 0); + gemtextLineDeinit(line); + gemtextParserDeinit(&parser); return ret; } \ No newline at end of file diff --git a/test/test0.gmi b/test/test0.gmi index a1f5319..612dc00 100644 --- a/test/test0.gmi +++ b/test/test0.gmi @@ -10,4 +10,10 @@ This is a simple gemtext file used for testing the gemtext parser. There's nothi * First item * second item -=> gemini://example.org/test.gmi This is a link \ No newline at end of file +=> gemini://example.org/test.gmi This is a link + +``` Test preformatted block +This is a preformatted block. +Everything in this block should appear exactly as entered in a Monospace font, +with no styling applied. +```