14. Export

14.1. Command

<<argparse_entries>>=
{"export", 6, p_export, NULL},
<<static_funcdefs>>=
static int p_export(int argc, char *argv[]);
<<functions>>=
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.

<<typedefs>>=
typedef struct weewiki_export_d weewiki_export_d;
<<structs>>=
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.

<<funcdefs>>=
#ifdef ORGPARSE_H /* define if orgparse header included */
void weewiki_orgparse_setup(orgparse *op);
#endif
<<functions>>=
<<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.

<<orgparse_callbacks>>=
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_html_setup>>=
orgparse_set_header(op, html_header);

14.3.2. Text

<<orgparse_callbacks>>=
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_html_setup>>=
orgparse_set_text(op, html_text);

14.3.3. Bold

<<orgparse_callbacks>>=
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_html_setup>>=
orgparse_set_bold(op, html_bold);

14.3.4. Aux

<<orgparse_callbacks>>=
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_html_setup>>=
orgparse_set_aux(op, html_aux);

14.3.5. Newline

<<orgparse_callbacks>>=
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_html_setup>>=
orgparse_set_newline(op, html_newline);

14.3.6. Code

<<orgparse_callbacks>>=
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_html_setup>>=
orgparse_set_code(op, html_code);

14.3.7. Code Block

<<orgparse_callbacks>>=
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_html_setup>>=
orgparse_set_codeblock(op, html_codeblock);

14.3.8. Name

<<orgparse_callbacks>>=
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_html_setup>>=
orgparse_set_name(op, html_name);

14.3.9. Title

<<orgparse_callbacks>>=
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_html_setup>>=
orgparse_set_title(op, html_title);

14.3.10. Link

<<orgparse_callbacks>>=
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_html_setup>>=
orgparse_set_link(op, html_link);

14.3.11. Paragraph

<<orgparse_callbacks>>=
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_html_setup>>=
orgparse_set_pgrph(op, html_pgrph);

14.4. Run

<<funcdefs>>=
void weewiki_export_run(weewiki_export_d *ex,
                        const char *buf,
                        size_t sz);
<<functions>>=
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);
}
<<funcdefs>>=
void weewiki_export_continue(weewiki_export_d *ex,
                             const char *buf,
                             size_t sz);
<<functions>>=
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

This generates a file

<<static_funcdefs>>=
static void write_file(weewiki_export_d *ex,
                       const unsigned char *txt,
                       size_t txt_sz);
<<functions>>=
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_funcdefs>>=
static FILE * mkfile(const unsigned char *dir,
                     const unsigned char *name);
<<functions>>=
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_funcdefs>>=
static void write_single_file(weewiki_d *ww,
                              weewiki_export_d *ex,
                              sqlite3 *db,
                              const unsigned char *dir,
                              const char *name);
<<functions>>=
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_funcdefs>>=
static void write_multiple_files(weewiki_d *ww,
                                 weewiki_export_d *ex,
                                 sqlite3 *db,
                                 const unsigned char *dir);
<<functions>>=
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.

<<funcdefs>>=
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.

<<functions>>=
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