slweb

Једноставни генератор статичких веб страна
Дневник | Датотеке | Референце | ПРОЧИТАЈМЕ | ЛИЦЕНЦА

чување 23ebd520509f26f518b30efdf641536fe5e5ae39
родитељ a3e30e40d97e42eda254512798ea7c0fa6290237
Аутор: Страхиња Радић <contact@strahinja.org>
Датум:   Mon, 22 Mar 2021 16:19:03 +0100

Added variable link-prefix

Signed-off-by: Страхиња Радић <contact@strahinja.org>

Diffstat:
Mindex.html | 2+-
Mslweb.1.in | 7+++++++
Mslweb.c | 426++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------
измењених датотека: 3, додавања: 290(+), брисања: 145(-)

diff --git a/index.html b/index.html @@ -153,7 +153,7 @@ this program. If not, see &lt;<a href="https://www.gnu.org/licenses">https://www <div id="git-log"> Previous commit: -index.slw 2f59c82 2021-03-17 13:17:35 +0100 (Страхиња Радић) (HEAD -> master, origin/master, origin/HEAD) +index.slw a3e30e4 2021-03-20 19:53:53 +0100 (Страхиња Радић) (HEAD -> master, origin/master, origin/HEAD) </div><!--git-log--> diff --git a/slweb.1.in b/slweb.1.in @@ -776,6 +776,13 @@ Contents of this variable will be used for the \fClang\fP attribute of the \fC<html>\fP tag. . .IP \[bu] +.BR link-prefix . +This variable specifies the prefix which will be prepended to relative URLs in +links. Final slash needs to be included if +.B link-prefix +is a complete path. +. +.IP \[bu] .BR meta . Contents of this variable is treated as a filename specifying the CSV file containing a list of values to be inserted into meta tags. The first row of this diff --git a/slweb.c b/slweb.c @@ -21,6 +21,7 @@ static size_t lineno = 0; static size_t colno = 1; +static BOOL output_firstcol = TRUE; static char* input_filename = NULL; static char* input_dirname = NULL; static char* basedir = NULL; @@ -39,7 +40,7 @@ static KeyValue* footnotes = NULL; static KeyValue* pfootnotes = NULL; static size_t footnote_count = 0; static size_t current_footnote = 0; -static uint8_t** inline_footnotes = NULL; +static uint8_t** inline_footnotes = NULL; static size_t inline_footnote_count = 0; static size_t current_inline_footnote = 0; static uint8_t* csv_template = NULL; @@ -344,6 +345,8 @@ print_command(const char* command, print_output(output, "%s%s", cmd_output_line, strip_newlines ? "" : "\n"); } + if (!strip_newlines) + output_firstcol = TRUE; free(cmd_output_line); fclose(cmd_output); @@ -435,6 +438,7 @@ int process_heading_start(FILE* output, UBYTE heading_level) { print_output(output, "<h%d>", heading_level); + output_firstcol = FALSE; return 0; } @@ -446,6 +450,7 @@ process_heading(uint8_t* token, FILE* output, UBYTE heading_level) print_output(output, "%s</h%d>", token ? (char*)token : "", heading_level); + output_firstcol = FALSE; return 0; } @@ -475,6 +480,7 @@ process_git_log(FILE* output) (const uint8_t**)pipe_args, output, FALSE); print_output(output, "</div><!--git-log-->\n"); + output_firstcol = TRUE; free(basename); @@ -931,7 +937,7 @@ process_list_start(FILE* output) int process_list_item_start(FILE* output) { - fprintf(output, "\n<li><p>"); + fprintf(output, "%s<li><p>", output_firstcol ? "" : "\n"); state |= ST_PARA_OPEN; return 0; } @@ -943,8 +949,10 @@ process_list_item_end(FILE* output) { state &= ~ST_PARA_OPEN; fprintf(output, "</p>"); + output_firstcol = FALSE; } fprintf(output, "</li>"); + output_firstcol = FALSE; return 0; } @@ -952,6 +960,7 @@ int process_list_end(FILE* output) { fprintf(output, "</ul>\n"); + output_firstcol = TRUE; return 0; } @@ -959,6 +968,7 @@ int process_numlist_start(FILE* output) { fprintf(output, "<ol>"); + output_firstcol = FALSE; return 0; } @@ -966,13 +976,17 @@ int process_numlist_end(FILE* output) { fprintf(output, "</ol>\n"); + output_firstcol = TRUE; return 0; } int filter_subdirs(const struct dirent* node) { - if (!node || !strcmp(node->d_name, ".") || !strcmp(node->d_name, "..")) + if (!node || ((*node->d_name == '.') + && (!*(node->d_name+1) + || ((*(node->d_name+1) == '.') + && !(*(node->d_name+2)))))) return 0; struct stat st; @@ -995,7 +1009,10 @@ filter_subdirs(const struct dirent* node) int filter_slw(const struct dirent* node) { - if (!node || !strcmp(node->d_name, ".") || !strcmp(node->d_name, "..")) + if (!node || ((*node->d_name == '.') + && (!*(node->d_name+1) + || ((*(node->d_name+1) == '.') + && !(*(node->d_name+2)))))) return 0; size_t node_len = strlen(node->d_name); @@ -1016,8 +1033,12 @@ reverse_alphacompare(const struct dirent** a, const struct dirent** b) } int -process_incdir_subdir(const char* subdirname, FILE* output, BOOL details_open, - uint8_t* macro_body) +process_timestamp(FILE* output, const uint8_t* link_prefix, const char* link, + uint8_t* permalink_macro, uint8_t* date); + +int +process_incdir_subdir(const char* subdirname, const uint8_t* link_prefix, + FILE* output, BOOL details_open, uint8_t* macro_body) { print_output(output, "<li>\n<details%s>\n<summary>", details_open ? " open" : ""); @@ -1027,27 +1048,35 @@ process_incdir_subdir(const char* subdirname, FILE* output, BOOL details_open, struct dirent** namelist; struct dirent** pnamelist; - long names_total; + long names_total = 0; long names_output; char* abs_subdirname = NULL; CALLOC(abs_subdirname, char, BUFSIZE) - snprintf(abs_subdirname, BUFSIZE, "%s/%s", incdir, subdirname); + snprintf(abs_subdirname, BUFSIZE, "%s/%s/%s", basedir, incdir, subdirname); if ((names_total = scandir(abs_subdirname, &namelist, &filter_slw, &reverse_alphacompare)) < 0) { perror("scandir"); - exit(error(errno, (uint8_t*)"incdir_subdir: scandir error")); + exit(error(errno, (uint8_t*)"incdir_subdir: scandir '%s' error", + abs_subdirname)); } pnamelist = namelist; names_output = 0; while (names_output < names_total && pnamelist && *pnamelist) { + int pstatus = 0; + /* + *char* basename = strip_ext((*pnamelist)->d_name); + *char* link = NULL; + *CALLOC(link, char, BUFSIZE) + *snprintf(link, BUFSIZE, "%s/%s", subdirname, basename); + */ + fflush(output); pid_t pid = fork(); - int pstatus = 0; if (pid > 0) wait(&pstatus); @@ -1100,6 +1129,12 @@ process_incdir_subdir(const char* subdirname, FILE* output, BOOL details_open, if (result) { free(buffer); + /*free(link);*/ + /*free(basename);*/ + free(abs_subdirname); + while (names_total--) + free(namelist[names_total]); + free(namelist); return result; } @@ -1114,23 +1149,36 @@ process_incdir_subdir(const char* subdirname, FILE* output, BOOL details_open, fflush(output); free(buffer); + /*free(link);*/ + /*free(basename);*/ + free(abs_subdirname); + while (names_total--) + free(namelist[names_total]); + free(namelist); exit(result); } else exit(error(1, (uint8_t*)"Fork failed")); + /*free(link);*/ + /*free(basename);*/ pnamelist++; names_output++; } + while (names_total--) + free(namelist[names_total]); + free(namelist); free(abs_subdirname); print_output(output, "</div>\n</details>\n</li>\n"); + output_firstcol = FALSE; return 0; } int -process_incdir(uint8_t* token, FILE* output, BOOL read_yaml_macros_and_links) +process_incdir(uint8_t* token, const uint8_t* link_prefix, FILE* output, + BOOL read_yaml_macros_and_links) { if (read_yaml_macros_and_links) return 0; @@ -1141,6 +1189,7 @@ process_incdir(uint8_t* token, FILE* output, BOOL read_yaml_macros_and_links) size_t arg_len = 0; long num = 5; uint8_t* macro_body = NULL; + int names_total = 0; struct dirent** namelist; struct dirent** pnamelist; long names_output; @@ -1181,15 +1230,18 @@ process_incdir(uint8_t* token, FILE* output, BOOL read_yaml_macros_and_links) if (arg) { if (*arg != '=') + { + free(incdir); exit(error(1, (uint8_t*)"incdir: Third argument not macro")); + } macro_body = get_value(macros, macros_count, arg+1, NULL); } } print_output(output, "<ul class=\"incdir\">\n"); - if (scandir(incdir, &namelist, &filter_subdirs, - &reverse_alphacompare) < 0) + if ((names_total = scandir(incdir, &namelist, &filter_subdirs, + &reverse_alphacompare)) < 0) { perror("scandir"); exit(error(errno, (uint8_t*)"incdir: scandir '%s' error", incdir)); @@ -1199,23 +1251,29 @@ process_incdir(uint8_t* token, FILE* output, BOOL read_yaml_macros_and_links) names_output = 0; while (names_output < num && pnamelist && *pnamelist) { - process_incdir_subdir((*pnamelist)->d_name, output, details_open, - macro_body); + process_incdir_subdir((*pnamelist)->d_name, link_prefix, output, + details_open, macro_body); details_open = FALSE; pnamelist++; names_output++; } + while (names_total--) + free(namelist[names_total]); free(namelist); free(incdir); print_output(output, "</ul>\n"); + output_firstcol = TRUE; return 0; } +BOOL +url_is_local(const char* url); + int -process_timestamp(FILE* output, const char* link, uint8_t* permalink_macro, - uint8_t* date) +process_timestamp(FILE* output, const uint8_t* link_prefix, const char* link, + uint8_t* permalink_macro, uint8_t* date) { uint8_t* day = NULL; uint8_t* month = NULL; @@ -1243,26 +1301,29 @@ process_timestamp(FILE* output, const char* link, uint8_t* permalink_macro, if (*ptimestamp_format == 'd' || *ptimestamp_format == 'D') u8_strncat(formatted_date, day, - DATEBUFSIZE-u8_strlen(formatted_date-1)); + DATEBUFSIZE-u8_strlen(formatted_date)-1); else if (*ptimestamp_format == 'm' || *ptimestamp_format == 'M') u8_strncat(formatted_date, month, - DATEBUFSIZE-u8_strlen(formatted_date-1)); + DATEBUFSIZE-u8_strlen(formatted_date)-1); else if (*ptimestamp_format == 'y' || *ptimestamp_format == 'Y') u8_strncat(formatted_date, year, - DATEBUFSIZE-u8_strlen(formatted_date-1)); + DATEBUFSIZE-u8_strlen(formatted_date)-1); else *(formatted_date + u8_strlen(formatted_date)) = *ptimestamp_format; ptimestamp_format++; } - print_output(output, "<a href=\"%s\"" + print_output(output, "<a href=\"%s%s\"" " class=\"timestamp\">%s%s</a>\n", + url_is_local(link) && link_prefix + ? (const char*)link_prefix : "", link, permalink_macro ? (char*)permalink_macro : "", formatted_date); + output_firstcol = TRUE; } } } @@ -1292,7 +1353,17 @@ process_macro(uint8_t* token, FILE* output, BOOL read_yaml_macros_and_links, if (!read_yaml_macros_and_links) { if (seen) + { + uint8_t* eol = u8_strrchr(macro_body, '\n'); + size_t macro_body_len = u8_strlen(macro_body); + if (eol) + output_firstcol = macro_body + macro_body_len - + u8_strrchr(macro_body, '\n') > 0; + else + output_firstcol = !*macro_body + || *(macro_body+macro_body_len-1) == '\n'; print_output(output, "%s", macro_body); + } else state |= ST_MACRO_BODY; } @@ -1324,8 +1395,8 @@ process_macro(uint8_t* token, FILE* output, BOOL read_yaml_macros_and_links, } int -process_tag(uint8_t* token, FILE* output, BOOL read_yaml_macros_and_links, - BOOL* skip_eol, BOOL end_tag) +process_tag(uint8_t* token, const uint8_t* link_prefix, FILE* output, + BOOL read_yaml_macros_and_links, BOOL* skip_eol, BOOL end_tag) { if (!token || u8_strlen(token) < 1) return warning(1, (uint8_t*)"%s:%ld:%ld: Empty tag name", @@ -1346,6 +1417,7 @@ process_tag(uint8_t* token, FILE* output, BOOL read_yaml_macros_and_links, "</div><!--made-by-->\n", MADEBY_URL, COPYRIGHTYEAR); + output_firstcol = TRUE; } else if (startswith((char*)token, "csv")) /* {csv} */ { @@ -1358,7 +1430,7 @@ process_tag(uint8_t* token, FILE* output, BOOL read_yaml_macros_and_links, } else if (startswith((char*)token, "incdir")) /* {incdir} */ { - process_incdir(token, output, read_yaml_macros_and_links); + process_incdir(token, link_prefix, output, read_yaml_macros_and_links); *skip_eol = TRUE; } else if (*token == '=') /* {=macro} */ @@ -1416,6 +1488,7 @@ process_tag(uint8_t* token, FILE* output, BOOL read_yaml_macros_and_links, } } print_output(output, ">"); + output_firstcol = FALSE; } return 0; @@ -1446,6 +1519,7 @@ int process_blockquote(FILE* output, BOOL end_tag) { print_output(output, "<%sblockquote>", end_tag ? "/" : ""); + output_firstcol = FALSE; return 0; } @@ -1453,6 +1527,7 @@ int process_kbd(FILE* output, BOOL end_tag) { print_output(output, "<%skbd>", end_tag ? "/" : ""); + output_firstcol = FALSE; return 0; } @@ -1460,6 +1535,7 @@ int process_table_start(FILE* output) { print_output(output, "<table>\n"); + output_firstcol = TRUE; return 0; } @@ -1467,6 +1543,7 @@ int process_table_header_start(FILE* output) { print_output(output, "<thead>\n<tr><th>"); + output_firstcol = FALSE; return 0; } @@ -1474,6 +1551,7 @@ int process_table_header_cell(FILE* output) { print_output(output, "</th><th>"); + output_firstcol = FALSE; return 0; } @@ -1481,6 +1559,7 @@ int process_table_header_end(FILE* output) { print_output(output, "</th></tr>\n</thead>\n"); + output_firstcol = TRUE; return 0; } @@ -1490,6 +1569,7 @@ process_table_body_start(FILE* output, BOOL start_row) print_output(output, "<tbody>\n"); if (start_row) print_output(output, "<tr><td>"); + output_firstcol = !start_row; return 0; } @@ -1497,6 +1577,7 @@ int process_table_body_row_start(FILE* output) { print_output(output, "<tr><td>"); + output_firstcol = FALSE; return 0; } @@ -1504,6 +1585,7 @@ int process_table_body_cell(FILE* output) { print_output(output, "</td><td>"); + output_firstcol = FALSE; return 0; } @@ -1511,6 +1593,7 @@ int process_table_body_row_end(FILE* output) { print_output(output, "</td></tr>\n"); + output_firstcol = TRUE; return 0; } @@ -1518,14 +1601,16 @@ int process_table_end(FILE* output) { print_output(output, "</tbody>\n</table>\n"); + output_firstcol = TRUE; return 0; } BOOL -url_is_local(char* url) +url_is_local(const char* url) { return !(startswith(url, "http://") || startswith(url, "https://") + || startswith(url, "gemini://") || startswith(url, "ftp://") || startswith(url, "ftps://") || startswith(url, "mailto://")); @@ -1570,65 +1655,73 @@ get_realpath(char** realpath, char* relativeto, char* path) } int -process_inline_link(uint8_t* link_text, uint8_t* link_macro_body, - uint8_t* link_url, FILE* output) +process_inline_link(uint8_t* link_text, const uint8_t* link_prefix, + uint8_t* link_macro_body, uint8_t* link_url, FILE* output) { - print_output(output, "<a href=\"%s\">%s%s</a>", + print_output(output, "<a href=\"%s%s\">%s%s</a>", + link_prefix ? (const char*)link_prefix : "", link_url ? (char*)link_url : "", link_macro_body ? (char*)link_macro_body : "", link_text); + output_firstcol = FALSE; return 0; } int -process_link(uint8_t* link_text, uint8_t* link_macro_body, uint8_t* link_id, - FILE* output) +process_link(uint8_t* link_text, const uint8_t* link_prefix, + uint8_t* link_macro_body, uint8_t* link_id, FILE* output) { uint8_t* url = get_value(links, links_count, link_id, NULL); - return process_inline_link(link_text, link_macro_body, - url, output); + return process_inline_link(link_text, link_prefix, link_macro_body, url, + output); } int -process_inline_image(uint8_t* image_text, uint8_t* image_url, FILE* output, - BOOL add_link, BOOL add_figcaption) +process_inline_image(uint8_t* image_text, const uint8_t* link_prefix, + uint8_t* image_url, FILE* output, BOOL add_link, BOOL add_figcaption) { if (add_figcaption) print_output(output, "<figure>\n"); if (add_link) - print_output(output, "<a href=\"%s\" title=\"%s\" class=\"image\"" + print_output(output, "<a href=\"%s%s\" title=\"%s\" class=\"image\"" " target=\"_blank\">", + link_prefix ? (const char*)link_prefix : "", image_url ? (char*)image_url : "", image_text); print_output(output, "<img src=\"%s\" alt=\"%s\" />", image_url ? (char*)image_url : "", image_text); + output_firstcol = FALSE; if (add_link) print_output(output, "</a>"); if (add_figcaption) + { print_output(output, "<figcaption>%s</figcaption>\n</figure>\n", image_text); + output_firstcol = TRUE; + } return 0; } int -process_image(uint8_t* image_text, uint8_t* image_id, FILE* output, - BOOL add_link, BOOL add_figcaption) +process_image(uint8_t* image_text, const uint8_t* link_prefix, + uint8_t* image_id, FILE* output, BOOL add_link, BOOL add_figcaption) { uint8_t* url = get_value(links, links_count, image_id, NULL); - return process_inline_image(image_text, url, output, add_link, + return process_inline_image(image_text, link_prefix, url, output, add_link, add_figcaption); } int -process_line_start(uint8_t* line, BOOL first_line_in_doc, - BOOL previous_line_blank, BOOL read_yaml_macros_and_links, - BOOL list_para, FILE* output, uint8_t** token, uint8_t** ptoken) +process_line_start(uint8_t* line, const uint8_t* link_prefix, + BOOL first_line_in_doc, BOOL previous_line_blank, + BOOL read_yaml_macros_and_links, BOOL list_para, FILE* output, + uint8_t** token, uint8_t** ptoken) { if ((first_line_in_doc || previous_line_blank) && !(ANY(state, ST_BLOCKQUOTE | ST_PRE))) @@ -1658,14 +1751,20 @@ process_line_start(uint8_t* line, BOOL first_line_in_doc, if (state & ST_FOOTNOTE_TEXT) { if (!read_yaml_macros_and_links && (state & ST_PARA_OPEN)) + { print_output(output, "</p>\n"); + output_firstcol = TRUE; + } state &= ~(ST_FOOTNOTE_TEXT | ST_PARA_OPEN); } } if (!ANY(state, ST_TABLE | ST_TABLE_HEADER | ST_TABLE_LINE)) { if (!read_yaml_macros_and_links) + { print_output(output, "<p>"); + output_firstcol = FALSE; + } state |= ST_PARA_OPEN; } } @@ -1673,23 +1772,29 @@ process_line_start(uint8_t* line, BOOL first_line_in_doc, } int -process_text_token(uint8_t* line, BOOL first_line_in_doc, - BOOL previous_line_blank, - BOOL processed_start_of_line, - BOOL read_yaml_macros_and_links, BOOL list_para, - FILE* output, uint8_t** token, - uint8_t** ptoken, size_t* token_size, - BOOL add_enclosing_paragraph) +process_text_token(uint8_t* line, const uint8_t* link_prefix, + BOOL first_line_in_doc, BOOL previous_line_blank, BOOL + processed_start_of_line, BOOL read_yaml_macros_and_links, + BOOL list_para, FILE* output, uint8_t** token, uint8_t** ptoken, + size_t* token_size, BOOL add_enclosing_paragraph) { if (!(state & ST_YAML)) { if (add_enclosing_paragraph && !processed_start_of_line) - process_line_start(line, first_line_in_doc, previous_line_blank, - read_yaml_macros_and_links, list_para, output, token, ptoken); + process_line_start(line, link_prefix, first_line_in_doc, + previous_line_blank, read_yaml_macros_and_links, list_para, + output, token, ptoken); **ptoken = 0; if (**token && !read_yaml_macros_and_links && !(state & ST_MACRO_BODY)) + { print_output(output, "%s", *token); + uint8_t* eol = u8_strrchr(*token, '\n'); + if (eol) + output_firstcol = *token + u8_strlen(*token) - eol > 0; + else + output_firstcol = FALSE; + } } RESET_TOKEN(*token, *ptoken, *token_size) return 0; @@ -1716,10 +1821,13 @@ process_inline_footnote(uint8_t* token, BOOL read_yaml_macros_and_links, *(inline_footnotes[inline_footnote_count-1] + token_len) = 0; } else + { print_output(output, "<a href=\"#inline-footnote-%d\" id=\"inline-footnote-text-%d\">" "<sup>%d</sup></a>", current_inline_footnote, current_inline_footnote, current_inline_footnote); + output_firstcol = FALSE; + } return 0; } @@ -1747,9 +1855,12 @@ process_footnote(uint8_t* token, BOOL footnote_definition, BOOL footnote_output, } if (footnote_output) + { print_output(output, "<a href=\"#footnote-%d\" id=\"footnote-text-%d\">" "<sup>%d</sup></a>", current_footnote, current_footnote, current_footnote); + output_firstcol = FALSE; + } return 0; } @@ -1763,6 +1874,7 @@ process_horizontal_rule(FILE* output) print_output(output, "<hr />\n"); if (state & ST_PARA_OPEN) print_output(output, "<p>\n"); + output_firstcol = TRUE; return 0; } @@ -1779,10 +1891,13 @@ process_formula(FILE* output, const uint8_t* token, BOOL display_formula) (const uint8_t**)pipe_args, output, TRUE); if (result) + { print_output(output, "%s$%s$%s", display_formula ? "$" : "", token, display_formula ? "$" : ""); + output_firstcol = FALSE; + } return result; } @@ -1841,6 +1956,7 @@ begin_html_and_head(FILE* output) print_output(output, "<meta name=\"viewport\" content=\"width=device-width," " initial-scale=1\" />\n<meta name=\"generator\" content=\"slweb\" />\n"); + output_firstcol = TRUE; return 0; } @@ -1851,8 +1967,11 @@ add_css(FILE* output) while (pvars < vars + vars_count) { if (!u8_strcmp(pvars->key, (uint8_t*)"stylesheet")) + { print_output(output, "<link rel=\"stylesheet\" href=\"%s\" />\n", pvars->value); + output_firstcol = TRUE; + } pvars++; } return 0; @@ -1862,15 +1981,17 @@ int end_head_start_body(FILE* output) { print_output(output, "</head>\n<body>\n"); + output_firstcol = TRUE; return 0; } int -begin_article(FILE* output, const BOOL add_article_header, - const uint8_t* author, const uint8_t* title, - const uint8_t* header_text, const char* title_heading_level, - uint8_t* date, const BOOL ext_in_permalink, const char* permalink_url) +begin_article(FILE* output, const uint8_t* link_prefix, + const BOOL add_article_header, const uint8_t* author, + const uint8_t* title, const uint8_t* header_text, + const char* title_heading_level, uint8_t* date, + const BOOL ext_in_permalink, const char* permalink_url) { if (author || date || header_text || title) print_output(output, "<header>\n"); @@ -1887,6 +2008,7 @@ begin_article(FILE* output, const BOOL add_article_header, if (author) print_output(output, "<address>%s</address>\n", author); + if (date && input_filename) { char* link = strip_ext(input_filename); @@ -1901,14 +2023,16 @@ begin_article(FILE* output, const BOOL add_article_header, strncat(link, timestamp_output_ext, BUFSIZE-strlen(link)-1); if (permalink_url) - process_timestamp(output, permalink_url, permalink_macro, date); + process_timestamp(output, link_prefix, permalink_url, + permalink_macro, date); else if (samedir_permalink && !u8_strcmp(samedir_permalink, (uint8_t*)"1")) { get_realpath(&real_link, input_dirname, link); - process_timestamp(output, real_link, permalink_macro, date); + process_timestamp(output, link_prefix, real_link, permalink_macro, + date); } else - process_timestamp(output, link, permalink_macro, date); + process_timestamp(output, link_prefix, link, permalink_macro, date); free(real_link); free(link); @@ -1917,6 +2041,8 @@ begin_article(FILE* output, const BOOL add_article_header, if (author || date || header_text || title) print_output(output, "</header>\n"); + output_firstcol = author || date || header_text || title; + return 0; } @@ -1928,19 +2054,26 @@ end_footnotes(FILE* output, BOOL add_footnote_div) if (state & ST_PARA_OPEN) { print_output(output, "</p>\n"); + output_firstcol = TRUE; state &= ~ST_PARA_OPEN; } if (add_footnote_div) + { print_output(output, "<div class=\"footnotes\">\n"); + output_firstcol = TRUE; + } process_horizontal_rule(output); for (footnote = 0; footnote < inline_footnote_count; footnote++) + { print_output(output, "<p id=\"inline-footnote-%d\">" "<a href=\"#inline-footnote-text-%d\">%d.</a> %s</p>\n", footnote+1, footnote+1, footnote+1, (char*)inline_footnotes[footnote]); + output_firstcol = TRUE; + } KeyValue* pfootnote = footnotes; footnote = 0; @@ -1950,12 +2083,16 @@ end_footnotes(FILE* output, BOOL add_footnote_div) "<a href=\"#footnote-text-%d\">%d.</a> %s</p>\n", footnote+1, footnote+1, footnote+1, (char*)pfootnote->value); + output_firstcol = TRUE; pfootnote++; footnote++; } if (add_footnote_div) + { print_output(output, "</div><!--footnotes-->\n"); + output_firstcol = TRUE; + } return 0; } @@ -1964,6 +2101,7 @@ int end_body_and_html(FILE* output) { print_output(output, "</body>\n</html>\n"); + output_firstcol = TRUE; return 0; } @@ -1982,6 +2120,7 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, uint8_t* var_add_image_links = NULL; uint8_t* var_add_figcaption = NULL; uint8_t* var_add_footnote_div = NULL; + uint8_t* link_prefix = NULL; uint8_t* pbuffer = NULL; uint8_t* line = NULL; uint8_t* pline = NULL; @@ -2034,6 +2173,7 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, add_figcaption = !(var_add_figcaption && *var_add_figcaption == '0'); var_add_footnote_div = get_value(vars, vars_count, (uint8_t*)"add-footnote-div", NULL); add_footnote_div = var_add_footnote_div && *var_add_footnote_div == '1'; + link_prefix = get_value(vars, vars_count, (uint8_t*)"link-prefix", NULL); CALLOC(line, uint8_t, BUFSIZE) token_size = BUFSIZE; @@ -2042,8 +2182,8 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, pbuffer = buffer; pvars = vars; - plinks = links; pmacros = macros; + plinks = links; pfootnotes = footnotes; lineno = 0; @@ -2054,11 +2194,12 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, end_head_start_body(output); } - begin_article(output, - var_add_article_header && *var_add_article_header == '1', - author, title, header_text, (char*)title_heading_level, date, - ext_in_permalink && *ext_in_permalink != '0', - (char*)permalink_url); + if (!read_yaml_macros_and_links) + begin_article(output, link_prefix, + var_add_article_header && *var_add_article_header == '1', + author, title, header_text, (char*)title_heading_level, date, + ext_in_permalink && *ext_in_permalink != '0', + (char*)permalink_url); RESET_TOKEN(token, ptoken, token_size) @@ -2078,6 +2219,7 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, lineno++; colno = 1; + output_firstcol = TRUE; processed_start_of_line = FALSE; skip_eol = FALSE; /*list_item = FALSE;*/ @@ -2210,6 +2352,7 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, print_output(output, "<pre>"); else print_output(output, "</pre>"); + output_firstcol = FALSE; } /* Skip the rest of the line (language) */ @@ -2239,12 +2382,10 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, else { /* Output existing text up to ` */ - process_text_token(line, first_line_in_doc, - previous_line_blank, - processed_start_of_line, - read_yaml_macros_and_links, - list_para, output, &token, &ptoken, - &token_size, TRUE); + process_text_token(line, link_prefix, first_line_in_doc, + previous_line_blank, processed_start_of_line, + read_yaml_macros_and_links, list_para, output, + &token, &ptoken, &token_size, TRUE); processed_start_of_line = TRUE; if (!read_yaml_macros_and_links @@ -2343,12 +2484,10 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, else { /* Output existing text up to __ */ - process_text_token(line, first_line_in_doc, - previous_line_blank, - processed_start_of_line, - read_yaml_macros_and_links, - list_para, output, &token, &ptoken, - &token_size, TRUE); + process_text_token(line, link_prefix, first_line_in_doc, + previous_line_blank, processed_start_of_line, + read_yaml_macros_and_links, list_para, output, + &token, &ptoken, &token_size, TRUE); processed_start_of_line = TRUE; if (!read_yaml_macros_and_links @@ -2384,12 +2523,10 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, else { /* Output existing text up to _ */ - process_text_token(line, first_line_in_doc, - previous_line_blank, - processed_start_of_line, - read_yaml_macros_and_links, - list_para, output, &token, &ptoken, - &token_size, TRUE); + process_text_token(line, link_prefix, first_line_in_doc, + previous_line_blank, processed_start_of_line, + read_yaml_macros_and_links, list_para, output, + &token, &ptoken, &token_size, TRUE); processed_start_of_line = TRUE; if (!read_yaml_macros_and_links @@ -2464,7 +2601,7 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, if (colno == 1 && pline_len > 1 && *(pline+1) == '[') { - process_line_start(line, first_line_in_doc, + process_line_start(line, link_prefix, first_line_in_doc, previous_line_blank, read_yaml_macros_and_links, list_para, output, &token, &ptoken); @@ -2533,12 +2670,10 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, else { /* Output existing text up to * */ - process_text_token(line, first_line_in_doc, - previous_line_blank, - processed_start_of_line, - read_yaml_macros_and_links, - list_para, output, &token, &ptoken, - &token_size, TRUE); + process_text_token(line, link_prefix, first_line_in_doc, + previous_line_blank, processed_start_of_line, + read_yaml_macros_and_links, list_para, output, + &token, &ptoken, &token_size, TRUE); processed_start_of_line = TRUE; if (!read_yaml_macros_and_links @@ -2575,12 +2710,10 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, else { /* Output existing text up to * */ - process_text_token(line, first_line_in_doc, - previous_line_blank, - processed_start_of_line, - read_yaml_macros_and_links, - list_para, output, &token, &ptoken, - &token_size, TRUE); + process_text_token(line, link_prefix, first_line_in_doc, + previous_line_blank, processed_start_of_line, + read_yaml_macros_and_links, list_para, output, + &token, &ptoken, &token_size, TRUE); processed_start_of_line = TRUE; if (!read_yaml_macros_and_links @@ -2615,18 +2748,19 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, if (colno == 1 && u8_strlen(pline) > 1 - && startswith((char*)pline, " ")) + && startswith((char*)pline, " ")) { list_para = TRUE; - process_text_token(line, first_line_in_doc, - previous_line_blank, - processed_start_of_line, - read_yaml_macros_and_links, - list_para, output, &token, &ptoken, - &token_size, TRUE); + process_text_token(line, link_prefix, first_line_in_doc, + previous_line_blank, processed_start_of_line, + read_yaml_macros_and_links, list_para, output, + &token, &ptoken, &token_size, TRUE); processed_start_of_line = TRUE; - pline += 4; - colno += 4; + while (*pline == ' ' || *pline == '\t') + { + pline++; + colno++; + } break; } @@ -2637,6 +2771,7 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, u8_strncat(ptoken, (uint8_t*)"<br />", BUFSIZE-u8_strlen(token)-1); ptoken += strlen("<br />"); + output_firstcol = FALSE; pline++; colno++; } @@ -2693,7 +2828,7 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, else { /* Output existing text up to { */ - process_text_token(line, first_line_in_doc, + process_text_token(line, link_prefix, first_line_in_doc, previous_line_blank, processed_start_of_line, read_yaml_macros_and_links, list_para, output, &token, &ptoken, &token_size, FALSE); @@ -2741,8 +2876,8 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, state &= ~ST_TAG; *ptoken = 0; - process_tag(token, output, read_yaml_macros_and_links, - &skip_eol, end_tag); + process_tag(token, link_prefix, output, + read_yaml_macros_and_links, &skip_eol, end_tag); RESET_TOKEN(token, ptoken, token_size) end_tag = FALSE; @@ -2786,12 +2921,10 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, else { /* Output existing text up to || */ - process_text_token(line, first_line_in_doc, - previous_line_blank, - processed_start_of_line, - read_yaml_macros_and_links, - list_para, output, &token, &ptoken, - &token_size, TRUE); + process_text_token(line, link_prefix, first_line_in_doc, + previous_line_blank, processed_start_of_line, + read_yaml_macros_and_links, list_para, output, + &token, &ptoken, &token_size, TRUE); processed_start_of_line = TRUE; if (!read_yaml_macros_and_links @@ -2899,6 +3032,8 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, if (!read_yaml_macros_and_links) { print_output(output, "%s", token); + if (*token) + output_firstcol = FALSE; if (u8_strlen(pline) > 1) process_table_header_cell(output); else @@ -2914,6 +3049,8 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, if (!read_yaml_macros_and_links) { print_output(output, "%s", token); + if (*token) + output_firstcol = FALSE; if (u8_strlen(pline) > 1) process_table_body_cell(output); else @@ -3004,7 +3141,7 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, { /* Output existing text up to ! */ *ptoken = 0; - process_text_token(line, first_line_in_doc, + process_text_token(line, link_prefix, first_line_in_doc, previous_line_blank, processed_start_of_line, read_yaml_macros_and_links, list_para, output, &token, &ptoken, &token_size, FALSE); @@ -3061,7 +3198,10 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, if (state & ST_FOOTNOTE_TEXT) { if (!read_yaml_macros_and_links && (state & ST_PARA_OPEN)) + { print_output(output, "</p>\n"); + output_firstcol = TRUE; + } state &= ~(ST_FOOTNOTE_TEXT | ST_PARA_OPEN); } @@ -3072,7 +3212,7 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, { /* Output existing text up to [^ */ *ptoken = 0; - process_text_token(line, first_line_in_doc, + process_text_token(line, link_prefix, first_line_in_doc, previous_line_blank, processed_start_of_line, read_yaml_macros_and_links, list_para, output, &token, &ptoken, &token_size, TRUE); @@ -3090,12 +3230,10 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, { /* Output existing text up to [ */ *ptoken = 0; - process_text_token(line, first_line_in_doc, - previous_line_blank, - processed_start_of_line, - read_yaml_macros_and_links, - list_para, output, &token, &ptoken, &token_size, - TRUE); + process_text_token(line, link_prefix, first_line_in_doc, + previous_line_blank, processed_start_of_line, + read_yaml_macros_and_links, list_para, output, + &token, &ptoken, &token_size, TRUE); } processed_start_of_line = TRUE; @@ -3172,13 +3310,13 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, if (!read_yaml_macros_and_links) { if (state & ST_LINK_SECOND_ARG) - process_inline_link(link_text, + process_inline_link(link_text, link_prefix, get_value(macros, macros_count, link_macro, NULL), token, output); else - process_inline_image(link_text, token, output, - add_image_links, add_figcaption); + process_inline_image(link_text, link_prefix, token, + output, add_image_links, add_figcaption); } RESET_TOKEN(token, ptoken, token_size) state &= ~(ST_LINK | ST_LINK_SECOND_ARG @@ -3236,7 +3374,7 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, else if (state & ST_LINK_SECOND_ARG) { if (!read_yaml_macros_and_links) - process_link(link_text, + process_link(link_text, link_prefix, get_value(macros, macros_count, link_macro, NULL), token, output); @@ -3248,7 +3386,7 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, else if (state & ST_IMAGE_SECOND_ARG) { if (!read_yaml_macros_and_links) - process_image(link_text, token, output, + process_image(link_text, link_prefix, token, output, add_image_links, add_figcaption); RESET_TOKEN(token, ptoken, token_size) state &= ~(ST_IMAGE | ST_IMAGE_SECOND_ARG); @@ -3339,7 +3477,7 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, { /* Output existing text up to ^[ */ *ptoken = 0; - process_text_token(line, first_line_in_doc, + process_text_token(line, link_prefix, first_line_in_doc, previous_line_blank, processed_start_of_line, read_yaml_macros_and_links, list_para, output, &token, &ptoken, &token_size, TRUE); @@ -3403,12 +3541,10 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, if (!(state & ST_DISPLAY_FORMULA)) { /* Output existing text up to $$ */ - process_text_token(line, first_line_in_doc, - previous_line_blank, - processed_start_of_line, - read_yaml_macros_and_links, - list_para, output, &token, &ptoken, &token_size, - TRUE); + process_text_token(line, link_prefix, first_line_in_doc, + previous_line_blank, processed_start_of_line, + read_yaml_macros_and_links, list_para, output, + &token, &ptoken, &token_size, TRUE); } processed_start_of_line = TRUE; @@ -3439,12 +3575,10 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, if (!(state & ST_FORMULA)) { /* Output existing text up to $ */ - process_text_token(line, first_line_in_doc, - previous_line_blank, - processed_start_of_line, - read_yaml_macros_and_links, - list_para, output, &token, &ptoken, &token_size, - TRUE); + process_text_token(line, link_prefix, first_line_in_doc, + previous_line_blank, processed_start_of_line, + read_yaml_macros_and_links, list_para, output, + &token, &ptoken, &token_size, TRUE); } processed_start_of_line = TRUE; @@ -3630,12 +3764,10 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, } else if (!ANY(state, ST_DISPLAY_FORMULA | ST_FORMULA | ST_IMAGE | ST_LINK)) - process_text_token(line, first_line_in_doc, - previous_line_blank, - processed_start_of_line, - read_yaml_macros_and_links, - list_para, output, &token, &ptoken, &token_size, - TRUE); + process_text_token(line, link_prefix, first_line_in_doc, + previous_line_blank, processed_start_of_line, + read_yaml_macros_and_links, list_para, output, + &token, &ptoken, &token_size, TRUE); } if (!ANY(state, ST_PRE | ST_IMAGE_SECOND_ARG | ST_LINK_SECOND_ARG @@ -3645,7 +3777,10 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, if (state & ST_PARA_OPEN) { if (!read_yaml_macros_and_links) + { print_output(output, "</p>"); + output_firstcol = FALSE; + } if (state & ST_LIST) skip_eol = TRUE; state &= ~ST_PARA_OPEN; @@ -3734,7 +3869,10 @@ slweb_parse(uint8_t* buffer, FILE* output, BOOL body_only, if (!skip_eol && !keep_token && !read_yaml_macros_and_links && !ANY(state, ST_YAML | ST_YAML_VAL | ST_LINK_SECOND_ARG | ST_LINK_SECOND_ARG_END)) + { print_output(output, "\n"); + output_firstcol = TRUE; + } if (!keep_token) RESET_TOKEN(token, ptoken, token_size)