14. Export
14.1. Command
{"export", 6, p_export, NULL},
static int p_export(int argc, char *argv[]);
static int p_export(int argc, char *argv[])
{
weewiki_d ww;
int rc;
weewiki_export_d ex;
sqlite3 *db;
const unsigned char *dir;
int export_page;
if (argc < 2) {
export_page = 0;
} else {
export_page = 1;
}
rc = 0;
weewiki_init(&ww);
weewiki_open(&ww, weewiki_dbname_get());
if (!rc) {
db = ww.db;
weewiki_set(&ww);
weewiki_orgparse_setup(&ex.op);
ex.env = weewiki_janet_setup();
weewiki_janet_loadconfig(ex.env);
dir = weewiki_janet_wwdir(ex.env);
if (export_page) {
write_single_file(&ww, &ex, db, dir, argv[1]);
} else {
write_multiple_files(&ww, &ex, db, dir);
}
weewiki_janet_cleanup();
}
weewiki_close(&ww);
weewiki_clean(&ww);
return rc;
}
14.2. Orgparse Export Struct
This is a struct passed into orgparse.
typedef struct weewiki_export_d weewiki_export_d;
struct weewiki_export_d {
weewiki_d *ww;
FILE *fp;
orgparse op;
JanetTable *env;
orgparse_state state;
};
14.3. Orgparse callback setup
Orgparse is used to parse a text buffer and generate HTML content. To do this, a series of callbacks are implemented.
weewiki_orgparse_setup
is enclosed in a ifdef macro
for ORGPARSE_H
. This is done so that orgparse.h
need
not be explicitely included if it not needed.
Honestly, this sort of practice a slippery slope, but in moderation it is quite convenient.
#ifdef ORGPARSE_H /* define if orgparse header included */
void weewiki_orgparse_setup(orgparse *op);
#endif
<<orgparse_callbacks>>
void weewiki_orgparse_setup(orgparse *op)
{
orgparse_init(op);
<<orgparse_html_setup>>
}
14.3.1. Header
Since h1
is only reserved for titles, make all
the header sizes one level smaller.
static void html_header(void *ud,
const char *h,
size_t sz,
int lvl)
{
weewiki_export_d *ex;
FILE *fp;
ex = ud;
fp = ex->fp;
lvl++;
fprintf(fp, "\n<h%d>", lvl);
fwrite(h, 1, sz, fp);
fprintf(fp, "</h%d>\n\n", lvl);
}
orgparse_set_header(op, html_header);
14.3.2. Text
static void html_text(void *ud,
const char *str,
size_t sz)
{
weewiki_export_d *ex;
FILE *fp;
ex = ud;
fp = ex->fp;
fwrite(str, 1, sz, fp);
}
orgparse_set_text(op, html_text);
14.3.3. Bold
static void html_bold(void *ud,
const char *str,
size_t sz)
{
weewiki_export_d *ex;
FILE *fp;
ex = ud;
fp = ex->fp;
fprintf(fp, "<b>");
fwrite(str, 1, sz, fp);
fprintf(fp, "</b>");
}
orgparse_set_bold(op, html_bold);
14.3.4. Aux
static void html_aux(void *ud,
const char *str,
size_t sz)
{
weewiki_export_d *ex;
ex = ud;
janet_dobytes(ex->env,
(const uint8_t *)str, sz,
NULL, NULL);
}
orgparse_set_aux(op, html_aux);
14.3.5. Newline
static void html_newline(void *ud,
const char *str,
size_t sz)
{
weewiki_export_d *ex;
FILE *fp;
ex = ud;
fp = ex->fp;
fprintf(fp, "<br>\n");
}
orgparse_set_newline(op, html_newline);
14.3.6. Code
static void html_code(void *ud,
const char *str,
size_t sz)
{
weewiki_export_d *ex;
FILE *fp;
ex = ud;
fp = ex->fp;
fprintf(fp, "<code>");
fwrite(str, 1, sz, fp);
fprintf(fp, "</code>");
}
orgparse_set_code(op, html_code);
14.3.7. Code Block
static void html_codeblock(void *ud,
const char *str,
size_t sz)
{
weewiki_export_d *ex;
FILE *fp;
size_t n;
ex = ud;
fp = ex->fp;
fprintf(fp, "<pre><code>");
for (n = 0; n < sz; n++) {
switch (str[n]) {
case '<':
fprintf(fp, "<");
break;
case '>':
fprintf(fp, ">");
break;
default:
fputc(str[n], fp);
break;
}
}
fprintf(fp, "</pre></code>\n");
}
orgparse_set_codeblock(op, html_codeblock);
14.3.8. Name
static void html_name(void *ud,
const char *str,
size_t sz)
{
weewiki_export_d *ex;
FILE *fp;
ex = ud;
fp = ex->fp;
fprintf(fp, "<div><b><i><<");
fwrite(str, 1, sz, fp);
fprintf(fp, ">>=</i></b></div>");
}
orgparse_set_name(op, html_name);
14.3.9. Title
static void html_title(void *ud,
const char *str,
size_t sz)
{
weewiki_export_d *ex;
FILE *fp;
ex = ud;
fp = ex->fp;
fprintf(fp, "<title>");
fwrite(str, 1, sz, fp);
fprintf(fp, "</title>\n");
fprintf(fp, "<h1>");
fwrite(str, 1, sz, fp);
fprintf(fp, "</h1>\n");
}
orgparse_set_title(op, html_title);
14.3.10. Link
static void html_link(void *ud,
const char *link,
size_t link_sz,
const char *name,
size_t name_sz)
{
weewiki_export_d *ex;
FILE *fp;
ex = ud;
fp = ex->fp;
fprintf(fp, "<a href=\"");
fwrite(link, 1, link_sz, fp);
fprintf(fp, "\">");
fwrite(name, 1, name_sz, fp);
fprintf(fp, "</a>");
}
orgparse_set_link(op, html_link);
14.3.11. Paragraph
static void html_pgrph(void *ud, int mode)
{
weewiki_export_d *ex;
FILE *fp;
ex = ud;
fp = ex->fp;
if (mode) {
fprintf(fp, "</p>\n");
} else {
fprintf(fp, "<p>");
}
}
orgparse_set_pgrph(op, html_pgrph);
14.4. Run
void weewiki_export_run(weewiki_export_d *ex,
const char *buf,
size_t sz);
void weewiki_export_run(weewiki_export_d *ex,
const char *buf,
size_t sz)
{
orgparse_state_init(&ex->state, &ex->op, buf, sz, ex);
orgparse_state_run(&ex->state);
}
void weewiki_export_continue(weewiki_export_d *ex,
const char *buf,
size_t sz);
void weewiki_export_continue(weewiki_export_d *ex,
const char *buf,
size_t sz)
{
orgparse_state_flags *f;
orgparse_state state;
orgparse_state_init(&state, &ex->op, buf, sz, ex);
f = orgparse_state_flags_get(&ex->state);
orgparse_state_flags_set(&state, f);
orgparse_state_run(&state);
}
14.5. Write File
static void write_file(weewiki_export_d *ex,
const unsigned char *txt,
size_t txt_sz);
static void write_file(weewiki_export_d *ex,
const unsigned char *txt,
size_t txt_sz)
{
janet_dostring(ex->env,
(const unsigned char *)"(html-header)",
NULL, NULL);
weewiki_export_run(ex, (const char *)txt, txt_sz);
orgparse_end(&ex->op, ex, &ex->state);
janet_dostring(ex->env,
(const unsigned char *)"(html-footer)",
NULL, NULL);
}
14.6. Make Filehandle
Generates a filehandle. If null values are passed in,
return stdout
.
static FILE * mkfile(const unsigned char *dir,
const unsigned char *name);
static FILE * mkfile(const unsigned char *dir,
const unsigned char *name)
{
FILE *fp;
char tmp[256];
if (name == NULL) return stdout;
if(!strcmp((const char *)name, "index")) {
sprintf(tmp, "%s/index.html", dir);
} else {
getcwd(tmp, 256);
chdir((const char *)dir);
mkdir((const char*)name, 0755);
chdir(tmp);
sprintf(tmp, "%s/%s/index.html", dir, name);
}
fp = fopen(tmp, "w");
if (fp == NULL) {
fprintf(stderr,
"Could not write to file %s\n",
tmp);
}
return fp;
}
14.7. Write Single File
static void write_single_file(weewiki_d *ww,
weewiki_export_d *ex,
sqlite3 *db,
const unsigned char *dir,
const char *name);
static void write_single_file(weewiki_d *ww,
weewiki_export_d *ex,
sqlite3 *db,
const unsigned char *dir,
const char *name)
{
sqlite3_stmt *stmt;
if (!weewiki_exists(ww, name)) {
fprintf(stderr,
"Could not find page '%s'\n",
name);
return;
}
sqlite3_prepare_v2(db,
"SELECT value "
"FROM wiki WHERE (key==?1);",
-1,
&stmt,
NULL);
sqlite3_bind_text(stmt, 1, name, -1, NULL);
sqlite3_step(stmt);
ex->fp = mkfile(dir, NULL);
ww->fp = ex->fp;
ww->ud = ex;
ww->name = name;
write_file(ex,
sqlite3_column_text(stmt, 0),
sqlite3_column_bytes(stmt, 0));
sqlite3_finalize(stmt);
}
14.8. Write Multiple Files
static void write_multiple_files(weewiki_d *ww,
weewiki_export_d *ex,
sqlite3 *db,
const unsigned char *dir);
static void write_multiple_files(weewiki_d *ww,
weewiki_export_d *ex,
sqlite3 *db,
const unsigned char *dir)
{
sqlite3_stmt *stmt;
int rc;
const unsigned char *key;
sqlite3_prepare_v2(db,
"SELECT key, value "
"FROM wiki "
"WHERE key NOT LIKE \"@%\";",
-1,
&stmt,
NULL);
rc = sqlite3_step(stmt);
while (rc == SQLITE_ROW) {
key = sqlite3_column_text(stmt, 0);
ex->fp = mkfile(dir,
sqlite3_column_text(stmt, 0));
ww->fp = ex->fp;
ww->ud = ex;
ww->name = (const char *)key;
if (ex->fp != NULL) {
fprintf(stdout, "Writing %s\n", key);
write_file(ex,
sqlite3_column_text(stmt, 1),
sqlite3_column_bytes(stmt, 1));
fclose(ex->fp);
} else {
break;
}
rc = sqlite3_step(stmt);
}
sqlite3_finalize(stmt);
}
14.9. Parsing In Janet
With the addition of the weewiki server, there is a growing
need make the Janet functions more flexible. In particular
the org
function, which may or may not use the
weewiki_export_d
data.
The function weewiki_janet_org
is a generic function
called by the cfun_org
function that only requires
the weewiki data (exposed as a global variable), the
text to be parsed, and the length of that text.
void weewiki_janet_org(weewiki_d *ww,
const char *txt,
unsigned int len);
By default, this just calls weewiki_export_continue
,
otherwise, it calls the custom callback.
void weewiki_janet_org(weewiki_d *ww,
const char *txt,
unsigned int len)
{
if (ww->parse == NULL) {
weewiki_export_d *ex;
ex = ww->ud;
weewiki_export_continue(ex, txt, len);
} else {
ww->parse(ww, txt, len);
}
}
prev | home | next