#ifndef SASHIDOWN_H #define SASHIDOWN_H #include #define SASHIDOWN_OUTPUT_DEFAULT 65536 typedef struct { const char *input; size_t input_len; char *output; size_t output_cap; size_t output_len; char *write_ptr; char *write_end; void *line_ix; int overflow; /* set when output buffer is exhausted */ } sashidown_ctx_t; /* Parse markdown to HTML. Returns 0 on success, -1 on error * (null args, or output buffer too small — never silently truncates). */ int sashidown_parse(const char *input, size_t len, char *output, size_t cap, size_t *out_len); typedef enum { SASHIDOWN_FMT_HTML = 0, SASHIDOWN_FMT_ANSI = 1, /* built-in colorful terminal theme */ SASHIDOWN_FMT_JSON = 2, SASHIDOWN_FMT_ANSI_PLAIN = 3, /* monochrome / SGR attributes only */ } sashidown_format_t; /* Single-pass convert. SASHIDOWN_FMT_HTML delegates to sashidown_parse. * Returns 0 on success, -1 on error (null args, bad format, or buffer too small). */ int sashidown_convert(const char *input, size_t len, char *output, size_t cap, size_t *out_len, sashidown_format_t format); /* Allocating wrapper (thread-safe). Caller must free via sashidown_free. */ char *cmark_markdown_to_html(const char *text, int len); void sashidown_free(void *ptr); /* --- Streaming API (AI conversation / incremental input) --- */ typedef struct sashidown_stream sashidown_stream_t; /* Called for each HTML chunk; return non-zero to abort feeding. */ typedef int (*sashidown_stream_cb)(const char *html, size_t len, void *user); typedef struct { sashidown_stream_cb on_html; void *user; size_t output_buf_size; /* default 8192 if 0; grows on overflow */ } sashidown_stream_opts_t; sashidown_stream_t *sashidown_stream_create(const sashidown_stream_opts_t *opts); int sashidown_stream_feed(sashidown_stream_t *s, const char *chunk, size_t len); int sashidown_stream_finish(sashidown_stream_t *s); void sashidown_stream_destroy(sashidown_stream_t *s); /* Bytes held past the confirmation frontier (input_len - render_pos). * Unconfirmed suffix under uncertain future input; O(1) query. */ size_t sashidown_stream_pending(const sashidown_stream_t *s); #endif /* SASHIDOWN_H */