чување 23ebd520509f26f518b30efdf641536fe5e5ae39
родитељ a3e30e40d97e42eda254512798ea7c0fa6290237
Аутор: Страхиња Радић <contact@strahinja.org>
Датум: Mon, 22 Mar 2021 16:19:03 +0100
Added variable link-prefix
Signed-off-by: Страхиња Радић <contact@strahinja.org>
Diffstat:
измењених датотека: 3, додавања: 290(+), брисања: 145(-)
diff --git a/index.html b/index.html
@@ -153,7 +153,7 @@ this program. If not, see <<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)