diff --git a/ekc3/ekc3.c b/ekc3/ekc3.c
index df9649f..5f99803 100644
--- a/ekc3/ekc3.c
+++ b/ekc3/ekc3.c
@@ -400,7 +400,7 @@ s_str * ekc3_inspect_block (const s_block *block, s_str *dest)
return dest;
}
-sw ekc3_render (const p_ekc3 *ekc3)
+sw ekc3_render (s_buf *buf, const p_ekc3 *ekc3)
{
const s_list *l;
sw r;
@@ -424,7 +424,7 @@ sw ekc3_render (const p_ekc3 *ekc3)
}
}
else {
- if (! (r = ekc3_render_tag(&l->tag)))
+ if (! (r = ekc3_render_tag(buf, &l->tag)))
return r;
result += r;
}
@@ -433,7 +433,7 @@ sw ekc3_render (const p_ekc3 *ekc3)
return result;
}
-sw ekc3_render_buf (s_buf *in)
+s_str * ekc3_render_buf_to_str (s_buf *in, s_str *dest)
{
p_ekc3 ekc3;
sw r;
@@ -441,18 +441,20 @@ sw ekc3_render_buf (s_buf *in)
ekc3_init(&ekc3);
r = ekc3_buf_parse(in, &ekc3);
if (r < 0) {
- err_puts("ekc3_render_buf: ekc3_buf_parse");
- assert(! "ekc3_render_buf: ekc3_buf_parse");
- return r;
+ err_puts("ekc3_render_buf_to_str: ekc3_buf_parse");
+ assert(! "ekc3_render_buf_to_str: ekc3_buf_parse");
+ return NULL;
+ }
+ if (! ekc3_render_to_str(&ekc3, dest)) {
+ ekc3_clean(&ekc3);
+ return NULL;
}
- r = ekc3_render(&ekc3);
ekc3_clean(&ekc3);
- return r;
+ return dest;
}
-s_str * ekc3_render_file (const s_str *path, s_str *dest)
+s_str * ekc3_render_file_to_str (const s_str *path, s_str *dest)
{
- s_buf buf;
s_tag *file_dir;
s_tag file_dir_save;
s_tag *file_path;
@@ -460,15 +462,14 @@ s_str * ekc3_render_file (const s_str *path, s_str *dest)
FILE *fp;
s_buf in;
char in_data[BUF_SIZE];
- sw r;
- s_str tmp;
+ s_str *result;
buf_init(&in, false, BUF_SIZE, in_data);
fp = file_open(path->ptr.pchar, "rb");
if (! fp)
- return -1;
+ return NULL;
if (! buf_file_open_r(&in, fp)) {
fclose(fp);
- return -1;
+ return NULL;
}
file_dir = frame_get_w(&g_kc3_env.global_frame, &g_sym___DIR__);
file_dir_save = *file_dir;
@@ -476,20 +477,46 @@ s_str * ekc3_render_file (const s_str *path, s_str *dest)
file_path = frame_get_w(&g_kc3_env.global_frame, &g_sym___FILE__);
file_path_save = *file_path;
file_path->data.str = *path;
- if (! ekc3_render_buf(&in, &tmp))
+ result = ekc3_render_buf_to_str(&in, dest);
tag_clean(file_dir);
*file_dir = file_dir_save;
*file_path = file_path_save;
buf_file_close(&in);
fclose(fp);
+ return result;
+}
+
+sw ekc3_render_raw_block (s_buf *buf, const s_block *block)
+{
+ uw i;
+ sw r;
+ s_tag result = {0};
+ assert(buf);
+ assert(block);
+ i = 1;
+ while (i < block->count) {
+ tag_clean(&result);
+ if (! eval_tag(block->tag + i, &result))
+ return -1;
+ i++;
+ }
+ switch (result.type) {
+ case TAG_STR:
+ r = buf_write_str(buf, &result.data.str);
+ break;
+ default:
+ r = buf_inspect_tag(buf, &result);
+ }
+ tag_clean(&result);
return r;
}
-sw ekc3_render_raw_block (const s_block *block)
+sw ekc3_render_raw_block_size (s_pretty *pretty, const s_block *block)
{
uw i;
sw r;
s_tag result = {0};
+ assert(pretty);
assert(block);
i = 1;
while (i < block->count) {
@@ -500,16 +527,49 @@ sw ekc3_render_raw_block (const s_block *block)
}
switch (result.type) {
case TAG_STR:
- r = io_write_str(&result.data.str);
+ r = buf_write_str_size(pretty, &result.data.str);
break;
default:
- r = io_inspect_tag(&result);
+ r = buf_inspect_tag_size(pretty, &result);
}
tag_clean(&result);
return r;
}
-sw ekc3_render_tag (const s_tag *tag)
+sw ekc3_render_size (s_pretty *pretty, const p_ekc3 *ekc3)
+{
+ const s_list *l;
+ sw r;
+ sw result = 0;
+ assert(ekc3);
+ l = *ekc3;
+ while (l) {
+ if (l->tag.type == TAG_SYM &&
+ l->tag.data.sym == sym_1("silent")) {
+ l = list_next(l);
+ if (! l ||
+ l->tag.type != TAG_BLOCK) {
+ err_puts("ekc3_render: :silent without a block");
+ assert(! "ekc3_render: :silent without a block");
+ return -1;
+ }
+ if (! ekc3_eval_silent_block(&l->tag.data.block)) {
+ err_puts("ekc3_render: ekc3_eval_silent_block");
+ assert(! "ekc3_render: ekc3_eval_silent_block");
+ return -1;
+ }
+ }
+ else {
+ if (! (r = ekc3_render_tag_size(pretty, &l->tag)))
+ return r;
+ result += r;
+ }
+ l = list_next(l);
+ }
+ return result;
+}
+
+sw ekc3_render_tag (s_buf *buf, const s_tag *tag)
{
const s_block *block;
s_str escaped = {0};
@@ -521,15 +581,15 @@ sw ekc3_render_tag (const s_tag *tag)
if (block->count > 1 &&
block->tag->type == TAG_IDENT &&
block->tag->data.ident.sym == sym_1("raw")) {
- if ((r = ekc3_render_raw_block(block)) < 0) {
+ if ((r = ekc3_render_raw_block(buf, block)) < 0) {
err_puts("ekc3_render_tag: ekc3_render_raw_block");
assert(! "ekc3_render_tag: ekc3_render_raw_block");
}
return r;
}
if (! ekc3_inspect_block(&tag->data.block, &in)) {
- err_puts("ekc3_render_tag: ekc3_render_block_to_str");
- assert(! "ekc3_render_tag: ekc3_render_block_to_str");
+ err_puts("ekc3_render_tag: ekc3_inspect_block");
+ assert(! "ekc3_render_tag: ekc3_inspect_block");
return -1;
}
if (! html_escape(&in, &escaped)) {
@@ -539,16 +599,16 @@ sw ekc3_render_tag (const s_tag *tag)
return -1;
}
str_clean(&in);
- if ((r = io_write_str(&escaped)) < 0) {
- err_puts("ekc3_render_tag: io_write_str 1");
- assert(! "ekc3_render_tag: io_write_str 1");
+ if ((r = buf_write_str(buf, &escaped)) < 0) {
+ err_puts("ekc3_render_tag: buf_write_str 1");
+ assert(! "ekc3_render_tag: buf_write_str 1");
}
str_clean(&escaped);
return r;
case TAG_STR:
- if ((r = io_write_str(&tag->data.str)) < 0) {
- err_puts("ekc3_render_tag: io_write_str 2");
- assert(! "ekc3_render_tag: io_write_str 2");
+ if ((r = buf_write_str(buf, &tag->data.str)) < 0) {
+ err_puts("ekc3_render_tag: buf_write_str 2");
+ assert(! "ekc3_render_tag: buf_write_str 2");
}
return r;
default:
@@ -561,3 +621,76 @@ sw ekc3_render_tag (const s_tag *tag)
err_write_1("\n");
return -1;
}
+
+sw ekc3_render_tag_size (s_pretty *pretty, const s_tag *tag)
+{
+ const s_block *block;
+ s_str escaped = {0};
+ s_str in = {0};
+ sw r;
+ switch(tag->type) {
+ case TAG_BLOCK:
+ block = &tag->data.block;
+ if (block->count > 1 &&
+ block->tag->type == TAG_IDENT &&
+ block->tag->data.ident.sym == sym_1("raw")) {
+ if ((r = ekc3_render_raw_block_size(pretty, block)) < 0) {
+ err_puts("ekc3_render_tag_size: ekc3_render_raw_block");
+ assert(! "ekc3_render_tag_size: ekc3_render_raw_block");
+ }
+ return r;
+ }
+ if (! ekc3_inspect_block(&tag->data.block, &in)) {
+ err_puts("ekc3_render_tag_size: ekc3_inspect_block");
+ assert(! "ekc3_render_tag_size: ekc3_inspect_block");
+ return -1;
+ }
+ if (! html_escape(&in, &escaped)) {
+ str_clean(&in);
+ err_puts("ekc3_render_tag_size: html_escape");
+ assert(! "ekc3_render_tag_size: html_escape");
+ return -1;
+ }
+ str_clean(&in);
+ if ((r = buf_write_str_size(pretty, &escaped)) < 0) {
+ err_puts("ekc3_render_tag_size: buf_write_str 1");
+ assert(! "ekc3_render_tag_size: buf_write_str 1");
+ }
+ str_clean(&escaped);
+ return r;
+ case TAG_STR:
+ if ((r = buf_write_str_size(pretty, &tag->data.str)) < 0) {
+ err_puts("ekc3_render_tag_size: buf_write_str 2");
+ assert(! "ekc3_render_tag_size: buf_write_str 2");
+ }
+ return r;
+ default:
+ break;
+ }
+ err_write_1("ekc3_render_tag_size: cannot render ");
+ err_write_1(tag_type_to_string(tag->type));
+ err_write_1(": ");
+ err_inspect_tag(tag);
+ err_write_1("\n");
+ return -1;
+}
+
+s_str * ekc3_render_to_str (const p_ekc3 *ekc3, s_str *dest)
+{
+
+ s_buf out;
+ s_pretty pretty = {0};
+ sw r;
+ assert(ekc3);
+ assert(dest);
+ if ((r = ekc3_render_size(&pretty, ekc3)) < 0)
+ return NULL;
+ if (! buf_init_alloc(&out, r))
+ return NULL;
+ if ((r = ekc3_render(&out, ekc3)) < 0) {
+ buf_clean(&out);
+ return NULL;
+ }
+ buf_to_str(&out, dest);
+ return dest;
+}
diff --git a/ekc3/ekc3.h b/ekc3/ekc3.h
index a0cd749..685efad 100644
--- a/ekc3/ekc3.h
+++ b/ekc3/ekc3.h
@@ -29,13 +29,19 @@ sw ekc3_buf_parse (s_buf *buf, p_ekc3 *dest);
sw ekc3_buf_parse_kc3_block (s_buf *buf, s_block *dest);
sw ekc3_buf_parse_kc3_silent_block (s_buf *buf, s_block *dest);
sw ekc3_buf_peek_kc3_silent_block (s_buf *buf);
+bool ekc3_eval_silent_block (const s_block *block);
/* Observers. */
-s_str * ekc3_escape_html (const s_str *html, s_str *dest);
-sw ekc3_render (const p_ekc3 *ekc3);
-sw ekc3_render_block_to_str (const s_block *block, s_str *dest);
-sw ekc3_render_buf (s_buf *in);
-sw ekc3_render_file (const s_str *path);
-sw ekc3_render_tag (const s_tag *tag);
+s_str * ekc3_inspect_block (const s_block *block, s_str *dest);
+sw ekc3_render (s_buf *buf, const p_ekc3 *ekc3);
+s_str * ekc3_render_buf_to_str (s_buf *in, s_str *dest);
+s_str * ekc3_render_file_to_str (const s_str *path, s_str *dest);
+sw ekc3_render_raw_block (s_buf *buf, const s_block *block);
+sw ekc3_render_raw_block_size (s_pretty *pretty,
+ const s_block *block);
+sw ekc3_render_size (s_pretty *pretty, const p_ekc3 *ekc3);
+s_str * ekc3_render_to_str (const p_ekc3 *ekc3, s_str *dest);
+sw ekc3_render_tag (s_buf *buf, const s_tag *tag);
+sw ekc3_render_tag_size (s_pretty *pretty, const s_tag *tag);
#endif /* EKC3_H */
diff --git a/lib/kc3/0.1/ekc3.kc3 b/lib/kc3/0.1/ekc3.kc3
index 625c6a9..097cc19 100644
--- a/lib/kc3/0.1/ekc3.kc3
+++ b/lib/kc3/0.1/ekc3.kc3
@@ -2,6 +2,6 @@ defmodule EKC3 do
dlopen(__DIR__ + "ekc3.so")
- def render_file = cfn Str "ekc3_render_file" (Str, Result)
+ def render_file = cfn Str "ekc3_render_file_to_str" (Str, Result)
end
diff --git a/test/ekc3/title.kc3 b/test/ekc3/title.kc3
index e3e44a8..5c8482f 100644
--- a/test/ekc3/title.kc3
+++ b/test/ekc3/title.kc3
@@ -1,4 +1,4 @@
title = "EKC3 test title"
title_h1 = "<title>\"Title escaped & in title'</title>"
title_h2 = "<h2>Title H2 (raw)</h2>"
-EKC3.render_file(__DIR__ + "title.html.ekc3")
+puts(EKC3.render_file(__DIR__ + "title.html.ekc3"))
diff --git a/test/ekc3/title.out.expected b/test/ekc3/title.out.expected
index 2446475..05b52da 100644
--- a/test/ekc3/title.out.expected
+++ b/test/ekc3/title.out.expected
@@ -1,3 +1,4 @@
+<!doctype html>
<html>
<head>
<title>EKC3 test title</title>
@@ -8,3 +9,4 @@
<h2>Title H2 (raw)</h2>
</body>
</html>
+
diff --git a/test/httpd/app/controllers/doc_controller.kc3 b/test/httpd/app/controllers/doc_controller.kc3
index 0df7bd5..97ace6e 100644
--- a/test/httpd/app/controllers/doc_controller.kc3
+++ b/test/httpd/app/controllers/doc_controller.kc3
@@ -5,8 +5,10 @@ defmodule DocController do
path_md = ".#{request.url}.md"
if File.exists?(path_md) do
md = File.read(path_md)
- body = Markdown.to_html_str(md)
- %HTTP.Response{body: body}
+ md_html = Markdown.to_html_str(md)
+ title = "kc3-lang.org"
+ EKC3.render_file("app/templates/layout.html.ekc3")
+ %HTTP.Response{body: md_html}
else
HTTPd.error_404_page(request)
end