Enable line-breaking blockquotes (prefaced by |)

TODO: No indentation on first line
This commit is contained in:
David Baer
2018-07-17 15:56:58 -04:00
parent 44b2187d76
commit 95834f00ff
7 changed files with 57 additions and 13 deletions

View File

@@ -78,7 +78,7 @@
</xsl:template> </xsl:template>
<xsl:template match="ser:p" mode="quote"> <xsl:template match="ser:p" mode="quote">
<text:p text:style-name="Quotations"><text:span text:style-name="T2"><xsl:apply-templates select="*|text()"/></text:span></text:p> <text:p text:style-name="Quotations"><xsl:apply-templates select="*|text()"/></text:p>
</xsl:template> </xsl:template>
<xsl:template match="ser:quote" mode="body"> <xsl:template match="ser:quote" mode="body">

View File

@@ -45,6 +45,7 @@ typedef enum {
TOK_STAR, TOK_STAR,
TOK_REF, TOK_REF,
TOK_URL, TOK_URL,
TOK_BREAK,
/* /*
TOK_DASH, TOK_DASH,
TOK_OPEN_DOUBLE_QUOTE, TOK_OPEN_DOUBLE_QUOTE,
@@ -115,6 +116,11 @@ nextToken(Tokenizer tokenizer) {
result.toktype = TOK_STAR; result.toktype = TOK_STAR;
result.toktext = NULL; result.toktext = NULL;
return result; return result;
} else if (ch == '\n') {
utf8Advance(tokenizer);
result.toktype = TOK_BREAK;
result.toktext = NULL;
return result;
} else if (greekChar(ch)) { } else if (greekChar(ch)) {
while ((ch != 0) && while ((ch != 0) &&
(greekChar(ch) || (ch == ' ') || (ch == ',') || (ch == '.'))) { (greekChar(ch) || (ch == ' ') || (ch == ',') || (ch == '.'))) {
@@ -158,7 +164,7 @@ nextToken(Tokenizer tokenizer) {
result.toktext = strndup(tokenizer->txt + startIndex, endIndex - startIndex); result.toktext = strndup(tokenizer->txt + startIndex, endIndex - startIndex);
return result; return result;
} else if (latinChar(ch)) { } else if (latinChar(ch)) {
while ((ch != 0) && latinChar(ch) && (ch != '*')) { while ((ch != 0) && latinChar(ch) && (ch != '*') && (ch != '\n')) {
utf8Advance(tokenizer); utf8Advance(tokenizer);
ch = utf8CharAt(tokenizer); ch = utf8CharAt(tokenizer);
if (ch == '^') { if (ch == '^') {
@@ -206,6 +212,10 @@ int formatText(const char* txt, FormatElement** dst, CitationRecordQueue* citati
REINIT_QUEUE(formatElementQ); REINIT_QUEUE(formatElementQ);
em = 1; em = 1;
} }
} else if (tok.toktype == TOK_BREAK) {
FormatElement elt = { .elementType = FORMAT_BR, .elementContentLength = 0,
.elementContent = { .textContent = NULL } };
APPEND_QUEUE(FormatElementQueue, formatElementQ, elt);
} else { } else {
FormatElementType t; FormatElementType t;
FormatElement elt = { .elementContent = { .textContent = tok.toktext } } ; FormatElement elt = { .elementContent = { .textContent = tok.toktext } } ;

View File

@@ -34,6 +34,7 @@
typedef enum { typedef enum {
FORMAT_TEXT, FORMAT_TEXT,
FORMAT_EM, FORMAT_EM,
FORMAT_BR,
FORMAT_STRONG, FORMAT_STRONG,
FORMAT_CITATION, FORMAT_CITATION,
FORMAT_GREEK, FORMAT_GREEK,

View File

@@ -38,7 +38,8 @@ typedef struct {
typedef enum { typedef enum {
PARA_DEFAULT, PARA_DEFAULT,
PARA_BLOCKQUOTE PARA_BLOCKQUOTE,
PARA_BLOCKPRESERVE
} SermonParagraphType; } SermonParagraphType;
typedef struct { typedef struct {

View File

@@ -24,14 +24,23 @@ ID [A-Za-z_][A-Za-z_0-9]*
<REFERENCEINTRO>ref { yylloc.first_column = yylloc.last_column + 1; yylloc.last_column = yylloc.first_column + 2; return KW_REF; } <REFERENCEINTRO>ref { yylloc.first_column = yylloc.last_column + 1; yylloc.last_column = yylloc.first_column + 2; return KW_REF; }
<REFERENCEINTRO>: { BEGIN(REFERENCENAME); yylloc.first_column = ++yylloc.last_column; return ':'; } <REFERENCEINTRO>: { BEGIN(REFERENCENAME); yylloc.first_column = ++yylloc.last_column; return ':'; }
<REFERENCENAME>{ID} { yylloc.first_column = yylloc.last_column + 1; yylloc.last_column = yylloc.first_column + strlen(yytext) + 1; yylval.sval = strdup(yytext); return ID; } <REFERENCENAME>{ID} { yylloc.first_column = yylloc.last_column + 1; yylloc.last_column = yylloc.first_column + strlen(yytext) + 1; yylval.sval = strdup(yytext); return ID; }
<REFERENCENAME>: { BEGIN(REFERENCE); yylloc.first_column = ++yylloc.last_column; return ':'; } <REFERENCENAME>: { BEGIN(REFERENCE); yylloc.first_column = ++yylloc.last_column; return ':'; }
<REFERENCE>[^}]* { yylloc.first_column = yylloc.last_column + 1; yylloc.last_column = yylloc.first_column + strlen(yytext) + 1; yylval.sval = strdup(yytext); return REFTEXT; } <REFERENCE>[^}]* { yylloc.first_column = yylloc.last_column + 1; yylloc.last_column = yylloc.first_column + strlen(yytext) + 1; yylval.sval = strdup(yytext); return REFTEXT; }
<REFERENCE>[}] { BEGIN(INITIAL); yylloc.first_column = ++yylloc.last_column; return '}'; } <REFERENCE>[}] { BEGIN(INITIAL); yylloc.first_column = ++yylloc.last_column; return '}'; }
^[^[{>\n].* { yylloc.first_column = ++yylloc.last_column; yylval.sval = strdup(yytext); LEXPRINT("LINE: %s\n", yytext); return LINE; } ^[^[{>|\n].* { yylloc.first_column = ++yylloc.last_column; yylval.sval = strdup(yytext); LEXPRINT("LINE: %s\n", yytext); return LINE; }
^>{WHITESPACE}*\n { yylloc.first_column = yylloc.last_column = 0; yylloc.first_line++; yylloc.last_line++; return '\n'; } ^[>|]{WHITESPACE}*\n { yylloc.first_column = yylloc.last_column = 0; yylloc.first_line++; yylloc.last_line++; return '\n'; }
^>{WHITESPACE}* { BEGIN(BLOCK); yylloc.first_column = yylloc.last_column = 1; return '>'; } ^[>|]{WHITESPACE}* {
<BLOCK>..* { BEGIN(INITIAL); yylloc.first_column = yylloc.last_column + 1; yylloc.last_column = yylloc.first_column + strlen(yytext) - 1; yylval.sval = strdup(yytext); return LINE; } BEGIN(BLOCK);
yylloc.first_column = yylloc.last_column = 1;
return yytext[0];
}
<BLOCK>..* {
BEGIN(INITIAL);
yylloc.first_column = yylloc.last_column + 1;
yylloc.last_column = yylloc.first_column + strlen(yytext) - 1;
yylval.sval = strdup(yytext); return LINE;
}
<INITIAL>\n { yylloc.first_column = yylloc.last_column = 0; yylloc.first_line++; yylloc.last_line++; return '\n'; } <INITIAL>\n { yylloc.first_column = yylloc.last_column = 0; yylloc.first_line++; yylloc.last_line++; return '\n'; }
<<EOF>> { return 0; } <<EOF>> { return 0; }
%% %%

View File

@@ -37,7 +37,13 @@ char* lineQueueToString(LineQueue* lq) {
FOREACH_QUEUE(LineQueue, *lq, ptr) { FOREACH_QUEUE(LineQueue, *lq, ptr) {
strncat(dest + idx, ptr->data, paraLength - idx); strncat(dest + idx, ptr->data, paraLength - idx);
idx += strlen(ptr->data); idx += strlen(ptr->data);
if (ptr->next != NULL) dest[idx++] = ' '; if (ptr->next != NULL) {
if (dest[idx-1] != '\n')
dest[idx++] = ' ';
} else {
if (dest[idx-1] == '\n')
idx--;
}
free(ptr->data); free(ptr->data);
} }
FOREACH_QUEUE_END FOREACH_QUEUE_END
@@ -45,6 +51,14 @@ char* lineQueueToString(LineQueue* lq) {
return dest; return dest;
} }
char *lineWithBreak(const char *txt) {
size_t l = strlen(txt);
char* s = (char*)malloc(l+2);
strncpy(s, txt, l + 2);
s[l] = '\n';
return s;
}
void yyerror(Sermon*, const char*); void yyerror(Sermon*, const char*);
%} %}
@@ -126,7 +140,7 @@ block:
PARSEPRINT("Parsed paragraph:\n%s\n\n", p.paraText); PARSEPRINT("Parsed paragraph:\n%s\n\n", p.paraText);
free(paraText); free(paraText);
} }
| blockquote { | blockquote_or_preserve {
SermonParagraph p = { .paraType = PARA_BLOCKQUOTE }; SermonParagraph p = { .paraType = PARA_BLOCKQUOTE };
char* paraText = lineQueueToString(&lineQ); char* paraText = lineQueueToString(&lineQ);
FormatElement* paraContent = NULL; FormatElement* paraContent = NULL;
@@ -142,10 +156,17 @@ para:
para LINE '\n' { APPEND_QUEUE(LineQueue, lineQ, $2); } para LINE '\n' { APPEND_QUEUE(LineQueue, lineQ, $2); }
| LINE '\n' { DESTROY_QUEUE(LineQueue, lineQ); APPEND_QUEUE(LineQueue, lineQ, $1); } | LINE '\n' { DESTROY_QUEUE(LineQueue, lineQ); APPEND_QUEUE(LineQueue, lineQ, $1); }
; ;
blockquote_or_preserve:
blockquote
| blockpreserve
;
blockquote: blockquote:
blockquote '>' LINE '\n' { APPEND_QUEUE(LineQueue, lineQ, $3); } blockquote '>' LINE '\n' { APPEND_QUEUE(LineQueue, lineQ, $3); }
| '>' LINE '\n' { DESTROY_QUEUE(LineQueue, lineQ); APPEND_QUEUE(LineQueue, lineQ, $2); } | '>' LINE '\n' { DESTROY_QUEUE(LineQueue, lineQ); APPEND_QUEUE(LineQueue, lineQ, $2); }
; ;
blockpreserve:
blockpreserve '|' LINE '\n' { char* s = lineWithBreak($3); APPEND_QUEUE(LineQueue, lineQ, s); free($3); }
| '|' LINE '\n' { char* s = lineWithBreak($2); DESTROY_QUEUE(LineQueue, lineQ); APPEND_QUEUE(LineQueue, lineQ, s); free($2); }
references: references:
references reference break references reference break
| /* empty */ | /* empty */

View File

@@ -83,6 +83,8 @@ formatElementsToXML(
xmlNodePtr em = xmlNewNode(sermon_ns, "em"); xmlNodePtr em = xmlNewNode(sermon_ns, "em");
formatElementsToXML(sermon_ns, em, a[i].elementContent.nestedContent, a[i].elementContentLength, numReferences, sermonReferencesPtr); formatElementsToXML(sermon_ns, em, a[i].elementContent.nestedContent, a[i].elementContentLength, numReferences, sermonReferencesPtr);
xmlAddChild(parentElement, em); xmlAddChild(parentElement, em);
} else if (a[i].elementType == FORMAT_BR) {
xmlAddChild(parentElement, xmlNewNode(sermon_ns, "br"));
} else if (a[i].elementType == FORMAT_TEXT) { } else if (a[i].elementType == FORMAT_TEXT) {
xmlAddChild(parentElement, xmlNewText(a[i].elementContent.textContent)); xmlAddChild(parentElement, xmlNewText(a[i].elementContent.textContent));
} else if (a[i].elementType == FORMAT_GREEK) { } else if (a[i].elementType == FORMAT_GREEK) {