Open sorairolake opened 1 year ago
Yes, the thought has crossed my mind also. Question is, how should the API look like? The current API is quite Rust-focused and at least some manual work would be needed to make a reasonable C-API on top of it.
Exposing a function that converts djot directly to html would be simple, but djot to events and events to html would be a lot more useful.
I guess c strings would not be an option, but rather custom types that
work like &str (ptr + len) and Cow
Each event is a variant of the Event ADT/sum type. I guess this could be implemented as a tag in addition to a union for the data. Something like
struct djot_event {
djot_event_tag tag;
djot_event_data data;
};
enum djot_event_tag {
DJOT_EVENT_START;
DJOT_EVENT_END;
DJOT_EVENT_STR;
DJOT_EVENT_SYMBOL;
..
};
union djot_event_data {
struct { djot_container container; djot_attributes attributes } start;
struct { djot_container container } end;
djot_cow_str str;
djot_cow_str symbol;
..
};
struct djot_container {
djot_container_tag tag,
djot_container_data data,
};
..
The parser is currently an iterator of Events, and the html renderer accepts any iterator of Events. We could provide the Parser::next function to allow pulling one event at a time from C. For the html rendering, the C implementation would need to implement a next function that allows the renderer to request the events. So, the C next function will be a callback that in turn calls Parser::next. Might look something like:
jotdown.h:
struct djot_parser;
djot_event djot_parser_next(djot_parser*);
typedef djot_event (*djot_next_event)(void *data);
/* returned value is dynamically allocated, must be freed by caller. */
char *djot_render_html(void *data, djot_next_event callback);
some_client.c
#include <jotdown.h>
struct my_renderer {
djot_parser parser;
..
};
my_renderer my_renderer_new() {
..
}
djot_event my_renderer_next_event(void *data) {
struct my_renderer *r = (struct my_renderer*)data;
struct djot_event ev = djot_parser_next(&r->parser);
/* do something with event */
return ev;
}
int main() {
..
struct my_renderer r = my_renderer_new();
char *html = djot_render_html(&r, my_renderer_next_event);
..
free(html);
..
}
I suppose it should be doable.
Actually, the lua reference implementation does have a minimal C API at https://github.com/jgm/djot.lua/tree/main/clib. It seems to expose direct rendering to HTML and json AST, and modification using lua filters.
As far as I know, there is no C implementation of djot yet. So, I think it would be nice if there is C bindings of this library.
see also: https://github.com/eqrion/cbindgen