checkpoint
This commit is contained in:
@@ -58,29 +58,39 @@ find_prev_line_start(const char *str, const char *current)
|
||||
static bool
|
||||
is_tag_on_own_line(const char *start, const char *tag_start, const TemplateConfig *config)
|
||||
{
|
||||
const char *line_start = find_prev_line_start(start, tag_start);
|
||||
const char *p = line_start;
|
||||
const char *p;
|
||||
|
||||
/* Check if there's only whitespace before the tag */
|
||||
while (p < tag_start && isspace((unsigned char)*p))
|
||||
p++;
|
||||
if (p != tag_start)
|
||||
// Find start of line or buffer
|
||||
const char *line_start = tag_start;
|
||||
while (line_start > start && line_start[-1] != '\n')
|
||||
line_start--;
|
||||
|
||||
// Check all characters before tag_start are whitespace
|
||||
for (p = line_start; p < tag_start; p++) {
|
||||
if (!isspace((unsigned char)*p))
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Find the end of the tag */
|
||||
// Move p from tag_start to after closing braces
|
||||
p = tag_start;
|
||||
while (*p && *p != '\n') {
|
||||
while (*p) {
|
||||
if (strncmp(p, config->Syntax.Braces.close, strlen(config->Syntax.Braces.close)) == 0) {
|
||||
p += strlen(config->Syntax.Braces.close);
|
||||
break;
|
||||
}
|
||||
if (*p == '\n') // tag broken across lines
|
||||
return false;
|
||||
p++;
|
||||
}
|
||||
|
||||
/* Check if there's only whitespace or newline after the tag */
|
||||
while (*p && *p != '\n' && isspace((unsigned char)*p))
|
||||
// Check all characters after closing braces until newline or end are whitespace
|
||||
while (*p && *p != '\n') {
|
||||
if (!isspace((unsigned char)*p))
|
||||
return false;
|
||||
p++;
|
||||
return *p == '\n' || *p == '\0';
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Helper function to trim newline from previous text node */
|
||||
@@ -618,9 +628,11 @@ template_parse_section(MemoryContext context, const char **s_ptr,
|
||||
/* Initialize body_len to the full content length */
|
||||
size_t body_len = end_tag_start - body_start;
|
||||
|
||||
if ((*is_end_on_own_line = is_tag_on_own_line(end_tag_start, end_tag_end, config))) {
|
||||
elog(NOTICE, "TPS: end_tag_start: %.9s", end_tag_start);
|
||||
|
||||
if ((*is_end_on_own_line = is_tag_on_own_line(body_start, end_tag_start, config))) {
|
||||
/* Find the start of the line containing the end tag */
|
||||
const char *line_start = find_prev_line_start(end_tag_start, end_tag_end);
|
||||
const char *line_start = find_prev_line_start(body_start, end_tag_start);
|
||||
/* Update body_len to exclude the line containing the end tag */
|
||||
body_len = line_start - body_start;
|
||||
}
|
||||
@@ -704,6 +716,8 @@ template_parse_section(MemoryContext context, const char **s_ptr,
|
||||
*s_ptr = *s + strlen(config->Syntax.Braces.close);
|
||||
elog(DEBUG1, "TPS: Successfully parsed section, returning at position: %s", *s_ptr);
|
||||
|
||||
elog(LOG, "TPS: is_end_on_own_line: %s", *is_end_on_own_line ? "true" : "false");
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -974,6 +988,21 @@ template_parse(MemoryContext context, const char **s, const TemplateConfig *conf
|
||||
|
||||
/* Choose the tag parser based on the matched type */
|
||||
if (matched_type == 1) {
|
||||
/*
|
||||
FIXME(yukkop): This writen as shit coz I strupid monkey
|
||||
Now it, probably, make many excesive actions.
|
||||
|
||||
Steps to prase, for future rework:
|
||||
1. if `control` tag, then remove all this line from result
|
||||
1. remove whitespaces before (in previous node if it is text node)
|
||||
2. remove whitespaces after until \n (in section body before parse it to nodes)
|
||||
3. remove \n (as previous step)
|
||||
2. if `end` tag, then remove all this line from result
|
||||
1. remove whitespaces before (in last body node if it is text node)
|
||||
2. remove whitespaces after until \n (skip it before parse next nodes)
|
||||
3. remove \n (also skip)
|
||||
3. render sections body
|
||||
*/
|
||||
/* Section tag */
|
||||
elog(LOG, "TPE: Parsing section tag at position: %.50s", *s);
|
||||
|
||||
@@ -981,13 +1010,40 @@ template_parse(MemoryContext context, const char **s, const TemplateConfig *conf
|
||||
bool is_end_on_own_line = false,
|
||||
is_control_on_own_line = is_tag_on_own_line(start, *s, config);
|
||||
|
||||
if (tag_node && is_control_on_own_line) {
|
||||
/* If we have a previous text node, trim its trailing newline */
|
||||
trim_newline_from_prev_text(current);
|
||||
elog(LOG, "TPE: is_control_on_own_line: %s", is_control_on_own_line ? "true" : "false");
|
||||
|
||||
if (is_control_on_own_line && current && current->type == TEMPLATE_NODE_TEXT && current->value->text.content) {
|
||||
/* Find the last newline in the text node */
|
||||
char *content = current->value->text.content;
|
||||
size_t len = strlen(content);
|
||||
size_t last_newline = 0;
|
||||
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
if (content[i] == '\n') {
|
||||
last_newline = i;
|
||||
}
|
||||
}
|
||||
|
||||
elog(LOG, "TPE: Last newline: %zu", last_newline);
|
||||
|
||||
/* If we found a newline, trim everything after it */
|
||||
if (last_newline > 0) {
|
||||
content[last_newline+1] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse the section tag */
|
||||
tag_node = template_parse_section(context, s, config, error_code, is_control_on_own_line, &is_end_on_own_line);
|
||||
|
||||
elog(LOG, "TPE: is_end_on_own_line: %s", is_end_on_own_line ? "true" : "false");
|
||||
|
||||
if (is_end_on_own_line) {
|
||||
/* Remove the end tag from the result */
|
||||
while (**s != '\n') {
|
||||
(*s)++;
|
||||
}
|
||||
(*s)++;
|
||||
}
|
||||
} else if (matched_type == 2) {
|
||||
/* Include tag */
|
||||
elog(LOG, "TPE: Parsing include tag at position: %.50s", *s);
|
||||
|
||||
@@ -29,7 +29,7 @@ BEGIN;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
\ir test_jsonb_path.sql
|
||||
\ir test_template_parser.sql
|
||||
--\ir test_template_parser.sql
|
||||
\ir test_render_exec.sql
|
||||
\ir test_render_interpolate.sql
|
||||
\ir test_render_section.sql
|
||||
|
||||
@@ -192,7 +192,7 @@ BEGIN
|
||||
RAISE NOTICE 'Test %: Complex template with all tag types: PASSED', total_tests;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Complex template with all tag types: FAILED. Expected "%", got "%"',
|
||||
total_tests, expected, test_result;
|
||||
total_tests, pg_temp.test_regexp_replace(expected), pg_temp.test_regexp_replace(test_result);
|
||||
END IF;
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RAISE WARNING 'Test % failed: Error: %', total_tests, SQLERRM;
|
||||
|
||||
@@ -217,8 +217,7 @@ BEGIN
|
||||
);
|
||||
expected := ' item
|
||||
item
|
||||
item
|
||||
';
|
||||
item';
|
||||
IF test_result = expected THEN
|
||||
RAISE NOTICE 'Test %: Section whitespaces 2: PASSED', total_tests;
|
||||
passed_tests := passed_tests + 1;
|
||||
@@ -239,8 +238,7 @@ BEGIN
|
||||
);
|
||||
expected := ' item
|
||||
item
|
||||
item
|
||||
';
|
||||
item';
|
||||
IF test_result = expected THEN
|
||||
RAISE NOTICE 'Test %: Section whitespaces 3: PASSED', total_tests;
|
||||
passed_tests := passed_tests + 1;
|
||||
@@ -283,7 +281,6 @@ BEGIN
|
||||
expected := ' item
|
||||
item
|
||||
item
|
||||
|
||||
';
|
||||
IF test_result = expected THEN
|
||||
RAISE NOTICE 'Test %: Section whitespaces 5: PASSED', total_tests;
|
||||
@@ -295,6 +292,68 @@ BEGIN
|
||||
RAISE WARNING 'Test %: Section whitespaces 5: FAILED with error: %', total_tests, SQLERRM;
|
||||
END;
|
||||
|
||||
-- Test 16: Tabs
|
||||
total_tests := total_tests + 1;
|
||||
BEGIN
|
||||
test_result := hemar.render(
|
||||
'{"array": [1, 2, 3]}'::jsonb,
|
||||
'
|
||||
identation1
|
||||
{{for item in array}}
|
||||
identation2
|
||||
{{end}}
|
||||
identation1
|
||||
'
|
||||
);
|
||||
expected := '
|
||||
identation1
|
||||
identation2
|
||||
identation2
|
||||
identation2
|
||||
identation1
|
||||
';
|
||||
|
||||
IF test_result = expected THEN
|
||||
RAISE NOTICE 'Test %: Tabs: PASSED', total_tests;
|
||||
passed_tests := passed_tests + 1;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Tabs: FAILED. Expected "%", got "%"', total_tests, pg_temp.test_regexp_replace(expected), pg_temp.test_regexp_replace(test_result);
|
||||
END IF;
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RAISE WARNING 'Test %: Tabs: FAILED with error: %', total_tests, SQLERRM;
|
||||
END;
|
||||
|
||||
-- Test 17: Tabs 2
|
||||
total_tests := total_tests + 1;
|
||||
BEGIN
|
||||
test_result := hemar.render(
|
||||
'{"array": [1, 2, 3]}'::jsonb,
|
||||
'
|
||||
identation1
|
||||
{{for item in array}}
|
||||
identation2
|
||||
{{end}}
|
||||
identation1
|
||||
'
|
||||
);
|
||||
expected := '
|
||||
identation1
|
||||
identation2
|
||||
identation2
|
||||
identation2
|
||||
identation1
|
||||
';
|
||||
|
||||
IF test_result = expected THEN
|
||||
RAISE NOTICE 'Test %: Tabs: PASSED', total_tests;
|
||||
passed_tests := passed_tests + 1;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: Tabs: FAILED. Expected "%", got "%"', total_tests, pg_temp.test_regexp_replace(expected), pg_temp.test_regexp_replace(test_result);
|
||||
END IF;
|
||||
EXCEPTION WHEN OTHERS THEN
|
||||
RAISE WARNING 'Test %: Tabs: FAILED with error: %', total_tests, SQLERRM;
|
||||
END;
|
||||
|
||||
-- Print summary
|
||||
IF passed_tests = total_tests THEN
|
||||
RAISE NOTICE '------------------------------------';
|
||||
|
||||
@@ -50,6 +50,38 @@ BEGIN
|
||||
PERFORM pg_sleep(2);
|
||||
RAISE NOTICE 'Starting template parser tests...';
|
||||
|
||||
-- Test 0: bruh
|
||||
total_tests := total_tests + 1;
|
||||
result := test_template_parse(
|
||||
$hemar1$
|
||||
text
|
||||
{{ for i in a }}
|
||||
item
|
||||
item
|
||||
item
|
||||
{{ end }}
|
||||
text
|
||||
$hemar1$,
|
||||
$expected1$Template parsed successfully. Structure:
|
||||
TEXT: "
|
||||
text"
|
||||
SECTION: iterator="i", collection="a"
|
||||
TEXT: " item
|
||||
item
|
||||
item
|
||||
"
|
||||
TEXT: "
|
||||
text
|
||||
"
|
||||
$expected1$
|
||||
);
|
||||
IF result THEN
|
||||
passed_tests := passed_tests + 1;
|
||||
RAISE NOTICE 'Test %: bruh - PASSED', total_tests;
|
||||
ELSE
|
||||
RAISE WARNING 'Test %: bruh - FAILED', total_tests;
|
||||
END IF;
|
||||
|
||||
-- Test 1: Simple interpolation
|
||||
total_tests := total_tests + 1;
|
||||
result := test_template_parse(
|
||||
|
||||
Reference in New Issue
Block a user