чување 923f2dea7646e9e84062a26edb46f9e4e8295dda
родитељ e8066ca2307cc8e24f95138fb18ddc5f3f751f51
Аутор: Страхиња Радић <contact@strahinja.org>
Датум: Mon, 14 Dec 2020 22:33:02 +0100
Added class and id attribute processing
Signed-off-by: Страхиња Радић <contact@strahinja.org>
Diffstat:
измењених датотека: 6, додавања: 257(+), брисања: 144(-)
diff --git a/Makefile b/Makefile
@@ -5,8 +5,8 @@ MANDIR = /usr/local/share/man/man1
CFLAGS=-g
LIBS=-lunistring
BROWSER = surf
-EXAMPLE_PAGES = $(addsuffix /index.slw,examples/basic examples/includes \
- examples/links examples/tags)
+EXAMPLE_PAGES = $(addsuffix /index.slw,examples/basic examples/blockquote \
+ examples/includes examples/links examples/tags)
#EXAMPLE_PAGES += $(addprefix examples/includes,
EXAMPLE_PAGES_HTML = $(EXAMPLE_PAGES:.slw=.html)
diff --git a/TODO b/TODO
@@ -8,9 +8,9 @@ Migration to C checklist
[ ] Add [=command Link](link) form of links
[ ] Add [(Link)](link) form of links
[ ] Add {include} processing
- [ ] Add {.class} processing
- [ ] Add {#id} processing
- [ ] Convert strncat token processing to individual token-based
+ [x] Add {.class} processing
+ [x] Add {#id} processing
+ [x] Convert strncat token processing to individual token-based
[ ] Add {lsdir}
[ ] Add title: processing
[ ] Update manpage
diff --git a/examples/blockquote/index.slw b/examples/blockquote/index.slw
@@ -0,0 +1,11 @@
+This is a document demonstrating quoting:
+> A quoted text
+> which is multiline.
+This isn't quoted
+
+This is a text with lines in-between:
+
+> This is a quote
+
+And another line.
+
diff --git a/examples/links/index.html b/examples/links/index.html
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
-<title>Links test</title>
-<meta charset="utf8" />
-<meta name="viewport" content="width=device-width, initial-scale=1" />
-<meta name="generator" content="slweb" />
-</head>
-<body>
-<p>Links <a href="https://strahinja.org">Test</a>.</p>
-<p>Another <a href="https://suckless.org">link, inline</a>.</p>
-
-</body>
-</html>
diff --git a/index.html b/index.html
@@ -9,14 +9,15 @@
<link rel="stylesheet" href="index.css" />
</head>
<body>
-<main>
+<main>
<h1>slweb</h1>
<p><strong>Slweb</strong> is a static website generator which aims at being simplistic. It uses
<strong>sed</strong>(1) to transform a custom Markdown-like syntax into HTML.</p>
<h2>Install</h2>
+
<pre>
$ git clone https://github.com/Strahinja/slweb.git
$ cd slweb
@@ -24,9 +25,11 @@ $ make && sudo make install
</pre>
<h2>Examples</h2>
+
<p>See the <a href="https://github.com/Strahinja/slweb/tree/master/examples"><code>examples/</code></a> directory in this repository.</p>
<p>Given the file <code>index.slw</code> in the current directory:</p>
+
<pre>
site-name: Test website
site-desc: My first website in slweb
@@ -41,11 +44,13 @@ This is an \_example_ of a statically generated HTML.
</pre>
<p>after using the command:</p>
+
<pre>
$ slweb index.slw > index.html
</pre>
<p>file <code>index.html</code> contains:</p>
+
<pre>
<!DOCTYPE html>
<html lang="en">
@@ -69,13 +74,16 @@ $ slweb index.slw > index.html
</pre>
<h2>TODO (checklist)</h2>
+
<p>See the file <a href="https://github.com/Strahinja/slweb/tree/master/TODO"><code>TODO</code></a> for more information.</p>
+
<h2>Bugs and limitations</h2>
-<p>Bugs can be reported using the <a href="https://github.com/Strahinja/slweb/issues">Github issue tracker</a>. See the manpage (<code>man
+<p>Bugs can be reported using the <a href="https://github.com/Strahinja/slweb/issues">Github issue tracker</a>. See the manpage (<code>man
slweb</code>) after installing <strong>slweb</strong> for more information.</p>
+
<h2>License</h2>
<p>slweb - Simple static website generator.<br />
@@ -92,11 +100,13 @@ PARTICULAR PURPOSE. See the GNU General Public License for more details. </p>
<p>You should have received a copy of the GNU General Public License along with
this program. If not, see <https://www.gnu.org/licenses/>. </p>
+
<div id="git-log">
Previous commit:
-index.slw 339edd4 2020-12-13 21:35:33 +0100 (Страхиња Радић) (HEAD -> switch-to-c, origin/switch-to-c)
+index.slw e8066ca 2020-12-14 11:35:38 +0100 (Страхиња Радић) (HEAD -> master, tag: v0.3.0-alpha, origin/switch-to-c, origin/master, origin/HEAD, switch-to-c)
</div><!--git-log-->
+
<div id="made-by">
Generated by <a href="https://github.com/Strahinja/slweb">slweb</a>
© 2020 Strahinya Radich.
@@ -105,6 +115,5 @@ Generated by <a href="https://github.com/Strahinja/slweb">slweb</a>
</main>
-
</body>
</html>
diff --git a/slweb.c b/slweb.c
@@ -19,6 +19,7 @@
#include "defs.h"
#include <stdint.h>
+#include <unistdio.h>
static size_t lineno = 0;
static size_t colno = 1;
@@ -146,34 +147,34 @@ process_tag(uint8_t* token, FILE* output, BOOL end_tag)
if (!token || u8_strlen(token) < 1)
return warning(1, (uint8_t*)"No tag\n");
- char* basename = (char*) calloc(strlen(filename), sizeof(char));
- char* slash = strrchr(filename, '/');
+ uint8_t* basename = (uint8_t*) calloc(strlen(filename), sizeof(uint8_t));
+ uint8_t* slash = u8_strrchr((uint8_t*)filename, '/');
if (slash)
- strcpy(basename, slash+1);
+ u8_strncpy(basename, slash+1, u8_strlen(slash+1));
else
- strcpy(basename, filename);
+ u8_strncpy(basename, filename, u8_strlen((uint8_t*)filename));
if (!strcmp((char*)token, "git-log"))
{
fprintf(output, "<div id=\"git-log\">\nPrevious commit:\n");
- char* command = (char*) calloc(BUFSIZE, sizeof(char));
- sprintf(command,
+ uint8_t* command = (uint8_t*) calloc(BUFSIZE, sizeof(uint8_t));
+ u8_snprintf(command, BUFSIZE,
"git log -1 --pretty=format:\"%s %%h %%ci (%%cn) %%d\""
" || echo \"(Not in a Git repository)\"",
basename);
- FILE* cmd_output = popen(command, "r");
+ FILE* cmd_output = popen((char*)command, "r");
if (!cmd_output)
{
perror(PROGRAMNAME);
return error(1, (uint8_t*)"Cannot popen\n");
}
- char* cmd_output_line = (char*) calloc(BUFSIZE, sizeof(char));
+ uint8_t* cmd_output_line = (uint8_t*) calloc(BUFSIZE, sizeof(uint8_t));
while (!feof(cmd_output))
{
- if (!fgets(cmd_output_line, BUFSIZE, cmd_output))
+ if (!fgets((char*)cmd_output_line, BUFSIZE, cmd_output))
continue;
- char* eol = strchr(cmd_output_line, '\n');
+ char* eol = strchr((char*)cmd_output_line, '\n');
if (eol)
*eol = '\0';
@@ -196,8 +197,61 @@ process_tag(uint8_t* token, FILE* output, BOOL end_tag)
"</div><!--made-by-->\n");
}
else
- fprintf(output, "<%s%s>", end_tag ? (const char*)"/" : (const char*)"",
- token);
+ {
+ uint8_t* attr_id = u8_strchr(token, (ucs4_t)'#');
+ uint8_t* attr_class = u8_strchr(token, (ucs4_t)'.');
+
+ fprintf(output, "<");
+ if (end_tag)
+ fprintf(output, "/");
+
+ if (*token == '.' || *token == '#')
+ {
+ fprintf(output, "div");
+ }
+
+ while (*token && *token != '#' && *token != '.')
+ fprintf(output, "%c", *token++);
+
+ if (!end_tag)
+ {
+ if (*token == '#')
+ {
+ token++;
+ fprintf(output, " id=\"");
+ while (*token && *token != '.')
+ fprintf(output, "%c", *token++);
+ fprintf(output, "\"");
+
+ if (*token == '.')
+ {
+ token++;
+ fprintf(output, " class=\"");
+ while (*token)
+ fprintf(output, "%c", *token++);
+ fprintf(output, "\"");
+ }
+ }
+ else if (*token == '.')
+ {
+ token++;
+ fprintf(output, " class=\"");
+ while (*token && *token != '#')
+ fprintf(output, "%c", *token++);
+ fprintf(output, "\"");
+ if (*token == '#')
+
+ {
+ token++;
+ fprintf(output, " id=\"");
+ while (*token)
+ fprintf(output, "%c", *token++);
+ fprintf(output, "\"");
+ }
+ }
+ }
+ fprintf(output, ">");
+ }
free(basename);
@@ -205,6 +259,27 @@ process_tag(uint8_t* token, FILE* output, BOOL end_tag)
}
int
+process_bold(FILE* output, BOOL end_tag)
+{
+ fprintf(output, "<%sstrong>", end_tag ? "/" : "");
+ return 0;
+}
+
+int
+process_italic(FILE* output, BOOL end_tag)
+{
+ fprintf(output, "<%sem>", end_tag ? "/" : "");
+ return 0;
+}
+
+int
+process_blockquote(FILE* output, BOOL end_tag)
+{
+ fprintf(output, "<%sblockquote>", end_tag ? "/" : "");
+ return 0;
+}
+
+int
process_link(uint8_t* link_text, uint8_t* link_id, KeyValue* links,
size_t links_count, FILE* output)
{
@@ -242,28 +317,42 @@ process_inline_image(uint8_t* image_text, uint8_t* image_url, FILE* output)
}
int
-process_text_token(USHORT* state,
- BOOL* first_line_in_doc,
- BOOL previous_line_blank,
- BOOL* print_newline,
- BOOL processed_starting_newline,
- BOOL read_yaml_macros_and_links,
- FILE* output,
+process_line_start(USHORT* state, BOOL* first_line_in_doc,
+ BOOL previous_line_blank, BOOL processed_start_of_line,
+ BOOL read_yaml_macros_and_links, FILE* output,
uint8_t** token,
uint8_t** ptoken)
{
if ((*first_line_in_doc || previous_line_blank)
- && !processed_starting_newline
- && !(*state & ST_PRE))
+ && !processed_start_of_line
+ && !(*state & (ST_PRE | ST_BLOCKQUOTE)))
{
if (!read_yaml_macros_and_links)
fprintf(output, "<p>");
*first_line_in_doc = FALSE;
*state |= ST_PARA_OPEN;
}
- if (!read_yaml_macros_and_links)
- finish_and_print_token(token, ptoken, output);
- *print_newline = *state & (ST_PRE | ST_CODE);
+ return 0;
+}
+
+int
+process_text_token(USHORT* state,
+ BOOL* first_line_in_doc,
+ BOOL previous_line_blank,
+ BOOL processed_start_of_line,
+ BOOL read_yaml_macros_and_links,
+ FILE* output,
+ uint8_t** token,
+ uint8_t** ptoken)
+{
+ process_line_start(state, first_line_in_doc, previous_line_blank,
+ processed_start_of_line, read_yaml_macros_and_links,
+ output, token, ptoken);
+ **ptoken = '\0';
+ if (!read_yaml_macros_and_links && **token)
+ fprintf(output, "%s", *token);
+ **token = '\0';
+ *ptoken = *token;
return 0;
}
@@ -341,8 +430,7 @@ slweb_parse(uint8_t* buffer, FILE* output,
BOOL end_tag = FALSE;
BOOL first_line_in_doc = TRUE;
BOOL previous_line_blank = FALSE;
- BOOL print_newline = FALSE;
- BOOL processed_starting_newline = FALSE;
+ BOOL processed_start_of_line = FALSE;
if (!buffer)
return error(1, (uint8_t*)"Empty buffer\n");
@@ -389,7 +477,7 @@ slweb_parse(uint8_t* buffer, FILE* output,
lineno++;
colno = 1;
- processed_starting_newline = FALSE;
+ processed_start_of_line = FALSE;
while (pline && *pline)
{
@@ -470,7 +558,6 @@ slweb_parse(uint8_t* buffer, FILE* output,
else
fprintf(output, "</pre>");
}
- print_newline = TRUE;
pline += 3;
colno += 3;
@@ -536,39 +623,43 @@ slweb_parse(uint8_t* buffer, FILE* output,
if (u8_strlen(pline) > 1 && *(pline+1) == '_')
{
- *ptoken = '\0';
- if (state & ST_BOLD)
- {
- u8_strncat(ptoken, (uint8_t*)"</strong>", strlen("</strong>"));
- ptoken += strlen("</strong>");
- state &= ~ST_BOLD;
- }
- else
- {
- u8_strncat(ptoken, (uint8_t*)"<strong>", strlen("<strong>"));
- ptoken += strlen("<strong>");
- state |= ST_BOLD;
- }
+ /* Output existing text up to __ */
+ process_text_token(&state, &first_line_in_doc,
+ previous_line_blank,
+ processed_start_of_line,
+ read_yaml_macros_and_links,
+ output,
+ &token,
+ &ptoken);
+ processed_start_of_line = TRUE;
+
+ if (!read_yaml_macros_and_links
+ && !(state & (ST_PRE | ST_CODE | ST_HEADING)))
+ process_bold(output, state & ST_BOLD);
+
+ state ^= ST_BOLD;
pline += 2;
colno += 2;
}
else
{
- *ptoken = '\0';
- if (state & ST_ITALIC)
- {
- u8_strncat(ptoken, (uint8_t*)"</em>", strlen("</em>"));
- ptoken += strlen("</em>");
- state &= ~ST_ITALIC;
- }
- else
- {
- u8_strncat(ptoken, (uint8_t*)"<em>", strlen("<em>"));
- ptoken += strlen("<em>");
- state |= ST_ITALIC;
- }
- pline += 2;
- colno += 2;
+ /* Output existing text up to _ */
+ process_text_token(&state, &first_line_in_doc,
+ previous_line_blank,
+ processed_start_of_line,
+ read_yaml_macros_and_links,
+ output,
+ &token,
+ &ptoken);
+ processed_start_of_line = TRUE;
+
+ if (!read_yaml_macros_and_links
+ && !(state & (ST_PRE | ST_CODE | ST_HEADING)))
+ process_italic(output, state & ST_ITALIC);
+
+ state ^= ST_ITALIC;
+ pline++;
+ colno++;
}
break;
@@ -583,39 +674,43 @@ slweb_parse(uint8_t* buffer, FILE* output,
if (u8_strlen(pline) > 1 && *(pline+1) == '*')
{
- *ptoken = '\0';
- if (state & ST_BOLD)
- {
- u8_strncat(ptoken, (uint8_t*)"</strong>", strlen("</strong>"));
- ptoken += strlen("</strong>");
- state &= ~ST_BOLD;
- }
- else
- {
- u8_strncat(ptoken, (uint8_t*)"<strong>", strlen("<strong>"));
- ptoken += strlen("<strong>");
- state |= ST_BOLD;
- }
+ /* Output existing text up to * */
+ process_text_token(&state, &first_line_in_doc,
+ previous_line_blank,
+ processed_start_of_line,
+ read_yaml_macros_and_links,
+ output,
+ &token,
+ &ptoken);
+ processed_start_of_line = TRUE;
+
+ if (!read_yaml_macros_and_links
+ && !(state & (ST_PRE | ST_CODE | ST_HEADING)))
+ process_bold(output, state & ST_BOLD);
+
+ state ^= ST_BOLD;
pline += 2;
colno += 2;
}
else
{
- *ptoken = '\0';
- if (state & ST_ITALIC)
- {
- u8_strncat(ptoken, (uint8_t*)"</em>", strlen("</em>"));
- ptoken += strlen("</em>");
- state &= ~ST_ITALIC;
- }
- else
- {
- u8_strncat(ptoken, (uint8_t*)"<em>", strlen("<em>"));
- ptoken += strlen("<em>");
- state |= ST_ITALIC;
- }
- pline += 2;
- colno += 2;
+ /* Output existing text up to * */
+ process_text_token(&state, &first_line_in_doc,
+ previous_line_blank,
+ processed_start_of_line,
+ read_yaml_macros_and_links,
+ output,
+ &token,
+ &ptoken);
+ processed_start_of_line = TRUE;
+
+ if (!read_yaml_macros_and_links
+ && !(state & (ST_PRE | ST_CODE | ST_HEADING)))
+ process_italic(output, state & ST_ITALIC);
+
+ state ^= ST_ITALIC;
+ pline++;
+ colno++;
}
break;
@@ -654,13 +749,13 @@ slweb_parse(uint8_t* buffer, FILE* output,
if (*token)
{
process_text_token(&state, &first_line_in_doc,
- previous_line_blank, &print_newline,
- processed_starting_newline,
+ previous_line_blank,
+ processed_start_of_line,
read_yaml_macros_and_links,
output,
&token,
&ptoken);
- processed_starting_newline = TRUE;
+ processed_start_of_line = TRUE;
}
state |= ST_TAG;
@@ -705,10 +800,10 @@ slweb_parse(uint8_t* buffer, FILE* output,
state &= ~ST_TAG;
*ptoken = '\0';
+
if (!read_yaml_macros_and_links)
process_tag(token, output, end_tag);
- first_line_in_doc = FALSE;
- print_newline = TRUE;
+
*token = '\0';
ptoken = token;
end_tag = FALSE;
@@ -717,6 +812,27 @@ slweb_parse(uint8_t* buffer, FILE* output,
colno++;
break;
+ case '>':
+ if (!read_yaml_macros_and_links
+ && !(state & (ST_PRE | ST_HEADING))
+ && colno == 1)
+ {
+ if (!read_yaml_macros_and_links
+ && !(state & ST_BLOCKQUOTE))
+ process_blockquote(output, FALSE);
+
+ state |= ST_BLOCKQUOTE;
+
+ pline++;
+ colno++;
+ }
+ else
+ {
+ *ptoken++ = *pline++;
+ colno++;
+ }
+ break;
+
case '!':
if (state & (ST_PRE | ST_HEADING | ST_CODE))
{
@@ -758,13 +874,13 @@ slweb_parse(uint8_t* buffer, FILE* output,
if (*token)
{
process_text_token(&state, &first_line_in_doc,
- previous_line_blank, &print_newline,
- processed_starting_newline,
+ previous_line_blank,
+ processed_start_of_line,
read_yaml_macros_and_links,
output,
&token,
&ptoken);
- processed_starting_newline = TRUE;
+ processed_start_of_line = TRUE;
}
state |= ST_LINK;
@@ -900,11 +1016,6 @@ slweb_parse(uint8_t* buffer, FILE* output,
{
if (*token)
{
- if (!processed_starting_newline
- && !read_yaml_macros_and_links
- && colno != 1 && !(state & ST_PRE))
- fprintf(output, "\n");
-
if (state & ST_LINK_SECOND_ARG)
{
*ptoken = '\0';
@@ -922,44 +1033,37 @@ slweb_parse(uint8_t* buffer, FILE* output,
*token = '\0';
ptoken = token;
heading_level = 0;
- print_newline = TRUE;
}
else
{
process_text_token(&state, &first_line_in_doc,
- previous_line_blank, &print_newline,
- processed_starting_newline,
+ previous_line_blank,
+ processed_start_of_line,
read_yaml_macros_and_links,
output,
&token,
&ptoken);
}
- previous_line_blank = FALSE;
}
- else if (colno == 1)
+
+ if ((state & ST_PARA_OPEN)
+ && !(state & ST_PRE)
+ && (!*pbuffer || *pbuffer == '\n'))
{
- if (!previous_line_blank
- && (state & ST_PARA_OPEN)
- && !(state & ST_PRE))
- {
- if (!read_yaml_macros_and_links)
- fprintf(output, "</p>\n");
- print_newline = FALSE;
- state &= ~ST_PARA_OPEN;
- }
- previous_line_blank = TRUE;
+ if (!read_yaml_macros_and_links)
+ fprintf(output, "</p>");
+ state &= ~ST_PARA_OPEN;
}
- else
- previous_line_blank = FALSE;
-
- processed_starting_newline = TRUE;
- if (!read_yaml_macros_and_links && (print_newline || (state & ST_PRE)))
+ if (state & ST_BLOCKQUOTE
+ && (!*pbuffer || *pbuffer != '>'))
{
- fprintf(output, "\n");
- print_newline = FALSE;
+ state &= ~ST_BLOCKQUOTE;
+ process_blockquote(output, TRUE);
}
+ previous_line_blank = FALSE;
+
}
else if (*token && read_yaml_macros_and_links
&& state & ST_YAML_VAL)
@@ -970,6 +1074,11 @@ slweb_parse(uint8_t* buffer, FILE* output,
u8_strcpy(pvars->value, token);
}
+ if (!read_yaml_macros_and_links && !(state & (ST_YAML | ST_YAML_VAL | ST_LINK_SECOND_ARG)))
+ {
+ fprintf(output, "\n");
+ }
+
*token = '\0';
ptoken = token;
@@ -982,9 +1091,7 @@ slweb_parse(uint8_t* buffer, FILE* output,
while (pbuffer && *pbuffer);
if (!read_yaml_macros_and_links)
- {
end_body_and_html(output);
- }
free(line);
free(token);