Enable line-breaking blockquotes (prefaced by |)
TODO: No indentation on first line
This commit is contained in:
@@ -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">
|
||||||
|
|||||||
12
src/format.c
12
src/format.c
@@ -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 } } ;
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -27,10 +27,19 @@ ID [A-Za-z_][A-Za-z_0-9]*
|
|||||||
<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; }
|
||||||
%%
|
%%
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
Reference in New Issue
Block a user