// retoor #include "markdown.h" #include #include #include #include #include // --- ANSI Escape Codes --- #define RESET "\033[0m" #define BOLD "\033[1m" #define ITALIC "\033[3m" #define STRIKETHROUGH "\033[9m" #define FG_YELLOW "\033[33m" #define FG_BLUE "\033[34m" #define FG_CYAN "\033[36m" #define FG_MAGENTA "\033[35m" #define BG_YELLOW_FG_BLACK "\033[43;30m" /** * @brief Checks if a given word is a programming language keyword. */ static int is_keyword(const char *word) { const char *keywords[] = { "int", "float", "double", "char", "void", "if", "else", "while", "for", "return", "struct", "printf", "let", "fn", "impl", "match", "enum", "trait", "use", "mod", "pub", "const", "static", "def", "class", "import", "from", "as", "with", "try", "except", "finally", "lambda", "async", "await", "public", "private", "protected", "interface", "extends", "implements", "new", "synchronized", "var", "switch", "case", "break", "continue", "namespace", "template", "typename", "virtual", "override", "friend", "package", "func", "type", "go", "defer", "select", "then", "elif", "fi", "esac", "do", "done", "using"}; for (size_t i = 0; i < sizeof(keywords) / sizeof(keywords[0]); i++) { if (strcmp(word, keywords[i]) == 0) return 1; } return 0; } void highlight_code(const char *code) { const char *ptr = code; char buffer[4096]; size_t index = 0; while (*ptr) { if (isalpha((unsigned char)*ptr) || *ptr == '_') { while (isalnum((unsigned char)*ptr) || *ptr == '_') { if (index < sizeof(buffer) - 1) buffer[index++] = *ptr++; else ptr++; } buffer[index] = '\0'; if (is_keyword(buffer)) printf(FG_BLUE "%s" RESET FG_YELLOW, buffer); else printf("%s", buffer); index = 0; } else if (isdigit((unsigned char)*ptr)) { while (isdigit((unsigned char)*ptr)) { if (index < sizeof(buffer) - 1) buffer[index++] = *ptr++; else ptr++; } buffer[index] = '\0'; printf(FG_CYAN "%s" RESET FG_YELLOW, buffer); index = 0; } else { putchar(*ptr); ptr++; } } } void parse_markdown_to_ansi(const char *markdown) { const char *ptr = markdown; bool is_start_of_line = true; while (*ptr) { if (is_start_of_line && strncmp(ptr, "```", 3) == 0) { ptr += 3; while (*ptr && *ptr != '\n') ptr++; if (*ptr) ptr++; const char *code_start = ptr; const char *code_end = strstr(code_start, "```"); if (code_end) { char *block_buffer = strndup(code_start, (size_t)(code_end - code_start)); printf(FG_YELLOW); highlight_code(block_buffer); printf(RESET); free(block_buffer); ptr = code_end + 3; if (*ptr == '\n') ptr++; is_start_of_line = true; continue; } else { printf(FG_YELLOW); highlight_code(code_start); printf(RESET); break; } } if (is_start_of_line) { const char *line_start_ptr = ptr; int indent_level = 0; while (*ptr == ' ') { indent_level++; ptr++; } bool block_processed = true; if (strncmp(ptr, "###### ", 7) == 0) { printf(BOLD FG_YELLOW); ptr += 7; } else if (strncmp(ptr, "##### ", 6) == 0) { printf(BOLD FG_YELLOW); ptr += 6; } else if (strncmp(ptr, "#### ", 5) == 0) { printf(BOLD FG_YELLOW); ptr += 5; } else if (strncmp(ptr, "### ", 4) == 0) { printf(BOLD FG_YELLOW); ptr += 4; } else if (strncmp(ptr, "## ", 3) == 0) { printf(BOLD FG_YELLOW); ptr += 3; } else if (strncmp(ptr, "# ", 2) == 0) { printf(BOLD FG_YELLOW); ptr += 2; } else if ((strncmp(ptr, "---", 3) == 0 || strncmp(ptr, "***", 3) == 0) && (*(ptr + 3) == '\n' || *(ptr + 3) == '\0')) { printf(FG_CYAN "─────────────────────────────────────────────────────────────────────────" RESET "\n"); ptr += 3; if (*ptr == '\n') ptr++; is_start_of_line = true; continue; } else if (strncmp(ptr, "> ", 2) == 0) { for (int i = 0; i < indent_level; i++) putchar(' '); printf(ITALIC FG_CYAN "▎ " RESET); ptr += 2; is_start_of_line = false; continue; } else if ((*ptr == '*' || *ptr == '-' || *ptr == '+') && *(ptr + 1) == ' ') { for (int i = 0; i < indent_level; i++) putchar(' '); printf(FG_MAGENTA "• " RESET); ptr += 2; is_start_of_line = false; continue; } else { const char *temp_ptr = ptr; while (isdigit((unsigned char)*temp_ptr)) temp_ptr++; if (temp_ptr > ptr && *temp_ptr == '.' && *(temp_ptr + 1) == ' ') { for (int i = 0; i < indent_level; i++) putchar(' '); printf(FG_MAGENTA); fwrite(ptr, 1, (size_t)(temp_ptr - ptr) + 1, stdout); printf(" " RESET); ptr = temp_ptr + 2; is_start_of_line = false; continue; } else { block_processed = false; ptr = line_start_ptr; } } if (block_processed) { while (*ptr && *ptr != '\n') putchar(*ptr++); printf(RESET "\n"); if (*ptr == '\n') ptr++; is_start_of_line = true; continue; } } if (strncmp(ptr, "***", 3) == 0 || strncmp(ptr, "___", 3) == 0) { const char *marker = strncmp(ptr, "***", 3) == 0 ? "***" : "___"; printf(BOLD ITALIC); ptr += 3; const char *end = strstr(ptr, marker); if (end) { fwrite(ptr, 1, (size_t)(end - ptr), stdout); ptr = end + 3; } else { fputs(ptr, stdout); ptr += strlen(ptr); } printf(RESET); continue; } if (strncmp(ptr, "**", 2) == 0 || strncmp(ptr, "__", 2) == 0) { const char *marker = strncmp(ptr, "**", 2) == 0 ? "**" : "__"; printf(BOLD); ptr += 2; const char *end = strstr(ptr, marker); if (end) { fwrite(ptr, 1, (size_t)(end - ptr), stdout); ptr = end + 2; } else { fputs(ptr, stdout); ptr += strlen(ptr); } printf(RESET); continue; } if (strncmp(ptr, "~~", 2) == 0) { printf(STRIKETHROUGH); ptr += 2; const char *end = strstr(ptr, "~~"); if (end) { fwrite(ptr, 1, (size_t)(end - ptr), stdout); ptr = end + 2; } else { fputs(ptr, stdout); ptr += strlen(ptr); } printf(RESET); continue; } if (strncmp(ptr, "==", 2) == 0) { printf(BG_YELLOW_FG_BLACK); ptr += 2; const char *end = strstr(ptr, "=="); if (end) { fwrite(ptr, 1, (size_t)(end - ptr), stdout); ptr = end + 2; } else { fputs(ptr, stdout); ptr += strlen(ptr); } printf(RESET); continue; } if (*ptr == '`' && *(ptr + 1) != '`') { printf(FG_YELLOW); ptr++; const char *start = ptr; while (*ptr && *ptr != '`') ptr++; fwrite(start, 1, (size_t)(ptr - start), stdout); if (*ptr == '`') ptr++; printf(RESET); continue; } if (*ptr == '[') { const char *text_start = ptr + 1; const char *text_end = strchr(text_start, ']'); if (text_end && *(text_end + 1) == '(') { const char *url_start = text_end + 2; const char *url_end = strchr(url_start, ')'); if (url_end) { printf(FG_BLUE); fwrite(text_start, 1, (size_t)(text_end - text_start), stdout); printf(RESET " ("); printf(ITALIC FG_CYAN); fwrite(url_start, 1, (size_t)(url_end - url_start), stdout); printf(RESET ")"); ptr = url_end + 1; continue; } } } if (*ptr == '\n') is_start_of_line = true; else if (!isspace((unsigned char)*ptr)) is_start_of_line = false; putchar(*ptr); ptr++; } }