From: Fletcher T. Penney Date: Fri, 9 Jun 2017 16:45:10 +0000 (-0400) Subject: ADDED: Add syntax for raw source (Addresses #38) X-Git-Tag: 6.1.0^2~21 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=931737a79096f15af7f03572573c323d0eb5737d;p=multimarkdown ADDED: Add syntax for raw source (Addresses #38) --- diff --git a/Sources/libMultiMarkdown/html.c b/Sources/libMultiMarkdown/html.c index d611d88..8a90a2f 100644 --- a/Sources/libMultiMarkdown/html.c +++ b/Sources/libMultiMarkdown/html.c @@ -520,12 +520,38 @@ void mmd_export_token_html(DString * out, const char * source, token * t, scratc break; case BLOCK_CODE_FENCED: pad(out, 2, scratch); - print_const("
child->child, source);
+
 			if (temp_char) {
+				if (strncmp("{=", temp_char, 2) == 0) {
+					// Raw source
+					if (raw_filter_text_matches(temp_char, FORMAT_HTML)) {
+						switch (t->child->tail->type) {
+							case LINE_FENCE_BACKTICK_3:
+							case LINE_FENCE_BACKTICK_4:
+							case LINE_FENCE_BACKTICK_5:
+								temp_token = t->child->tail;
+								break;
+							default:
+								temp_token = NULL;
+						}
+						if (temp_token) {
+							d_string_append_c_array(out, &source[t->child->next->start], temp_token->start - t->child->next->start);
+							scratch->padded = 1;
+						} else {
+							d_string_append_c_array(out, &source[t->child->start + t->child->len], t->start + t->len - t->child->next->start);							
+							scratch->padded = 0;
+						}
+					}
+
+					break;
+				}
+				print_const("
");
@@ -1059,6 +1085,17 @@ void mmd_export_token_html(DString * out, const char * source, token * t, scratc
 			}
 			t->child->type = TEXT_EMPTY;
 			t->child->mate->type = TEXT_EMPTY;
+
+			if (t->next && t->next->type == PAIR_RAW_FILTER) {
+				// Raw text?
+				if (raw_filter_matches(t->next, source, FORMAT_HTML)) {
+					d_string_append_c_array(out, &(source[t->child->start + t->child->len]), t->child->mate->start - t->child->start - t->child->len);
+				}
+				// Skip over PAIR_RAW_FILTER
+				scratch->skip_token = 1;
+				break;
+			}
+
 			print_const("");
 			mmd_export_token_tree_html_raw(out, source, t->child, scratch);
 			print_const("");
@@ -1091,7 +1128,9 @@ void mmd_export_token_html(DString * out, const char * source, token * t, scratc
 
 			free(temp_char);
 			break;
+		case PAIR_BRACE:
 		case PAIR_BRACES:
+		case PAIR_RAW_FILTER:
 			mmd_export_token_tree_html(out, source, t->child, scratch);
 			break;
 		case PAIR_BRACKET:
@@ -1649,6 +1688,7 @@ void mmd_export_token_html(DString * out, const char * source, token * t, scratc
 			if (t->next)
 				print_char('\n');
 			break;
+		case RAW_FILTER_LEFT:
 		case TEXT_BACKSLASH:
 		case TEXT_BRACE_LEFT:
 		case TEXT_BRACE_RIGHT:
diff --git a/Sources/libMultiMarkdown/include/libMultiMarkdown.h b/Sources/libMultiMarkdown/include/libMultiMarkdown.h
index 4d9f832..a523c56 100644
--- a/Sources/libMultiMarkdown/include/libMultiMarkdown.h
+++ b/Sources/libMultiMarkdown/include/libMultiMarkdown.h
@@ -339,12 +339,14 @@ enum token_types {
 	PAIR_BRACKET_CITATION,
 	PAIR_BRACKET_IMAGE,
 	PAIR_BRACKET_VARIABLE,
+	PAIR_BRACE,
 	PAIR_EMPH,
 	PAIR_MATH,
 	PAIR_PAREN,
 	PAIR_QUOTE_SINGLE,
 	PAIR_QUOTE_DOUBLE,
 	PAIR_QUOTE_ALT,
+	PAIR_RAW_FILTER,
 	PAIR_SUBSCRIPT,
 	PAIR_SUPERSCRIPT,
 	PAIR_STAR,
@@ -443,6 +445,7 @@ enum token_types {
 	TOC,
 	
 	TEXT_BACKSLASH,
+	RAW_FILTER_LEFT,
 	TEXT_BRACE_LEFT,
 	TEXT_BRACE_RIGHT,
 	TEXT_EMPTY,
diff --git a/Sources/libMultiMarkdown/latex.c b/Sources/libMultiMarkdown/latex.c
index afcec2d..0e350e5 100644
--- a/Sources/libMultiMarkdown/latex.c
+++ b/Sources/libMultiMarkdown/latex.c
@@ -472,7 +472,31 @@ void mmd_export_token_latex(DString * out, const char * source, token * t, scrat
 			pad(out, 2, scratch);
 
 			temp_char = get_fence_language_specifier(t->child->child, source);
+
 			if (temp_char) {
+				if (strncmp("{=", temp_char, 2) == 0) {
+					// Raw source
+					if (raw_filter_text_matches(temp_char, FORMAT_LATEX)) {
+						switch (t->child->tail->type) {
+							case LINE_FENCE_BACKTICK_3:
+							case LINE_FENCE_BACKTICK_4:
+							case LINE_FENCE_BACKTICK_5:
+								temp_token = t->child->tail;
+								break;
+							default:
+								temp_token = NULL;
+						}
+						if (temp_token) {
+							d_string_append_c_array(out, &source[t->child->next->start], temp_token->start - t->child->next->start);
+							scratch->padded = 1;
+						} else {
+							d_string_append_c_array(out, &source[t->child->start + t->child->len], t->start + t->len - t->child->next->start);							
+							scratch->padded = 0;
+						}
+					}
+
+					break;
+				}
 				printf("\\begin{lstlisting}[language=%s]\n", temp_char);
 			} else {
 				print_const("\\begin{verbatim}\n");
@@ -1012,10 +1036,22 @@ void mmd_export_token_latex(DString * out, const char * source, token * t, scrat
 			}
 			t->child->type = TEXT_EMPTY;
 			t->child->mate->type = TEXT_EMPTY;
+
+			if (t->next && t->next->type == PAIR_RAW_FILTER) {
+				// Raw text?
+				if (raw_filter_matches(t->next, source, FORMAT_LATEX)) {
+					d_string_append_c_array(out, &(source[t->child->start + t->child->len]), t->child->mate->start - t->child->start - t->child->len);
+				}
+				// Skip over PAIR_RAW_FILTER
+				scratch->skip_token = 1;
+				break;
+			}
+
 			print_const("\\texttt{");
 			mmd_export_token_tree_latex_tt(out, source, t->child, scratch);
 			print_const("}");
 			break;
+		case PAIR_BRACE:
 		case PAIR_BRACES:
 			mmd_export_token_tree_latex(out, source, t->child, scratch);
 			break;
@@ -1617,6 +1653,7 @@ void mmd_export_token_latex(DString * out, const char * source, token * t, scrat
 		case TEXT_BRACE_LEFT:
 		case TEXT_BRACE_RIGHT:
 			print_const("\\");
+		case RAW_FILTER_LEFT:
 		case TEXT_NUMBER_POSS_LIST:
 		case TEXT_PERIOD:
 		case TEXT_PLAIN:
diff --git a/Sources/libMultiMarkdown/lexer.c b/Sources/libMultiMarkdown/lexer.c
index 7c844c0..9fc7daa 100644
--- a/Sources/libMultiMarkdown/lexer.c
+++ b/Sources/libMultiMarkdown/lexer.c
@@ -1,4 +1,4 @@
-/* Generated by re2c 0.14.3 on Tue May 30 21:57:22 2017 */
+/* Generated by re2c 0.14.3 on Fri Jun  9 07:53:59 2017 */
 /**
 
 	MultiMarkdown 6 -- Lightweight markup processor to produce HTML, LaTeX, and more.
@@ -284,18 +284,18 @@ yy2:
 	case 14: 	goto yy128;
 	case 15: 	goto yy135;
 	case 16: 	goto yy145;
-	default:	goto yy300;
+	default:	goto yy302;
 	}
 yy3:
 	yyaccept = 0;
 	yych = *(YYMARKER = ++YYCURSOR);
 	switch (yych) {
-	case '+':	goto yy305;
-	case '-':	goto yy304;
-	case '=':	goto yy301;
-	case '>':	goto yy303;
-	case '{':	goto yy299;
-	case '~':	goto yy302;
+	case '+':	goto yy306;
+	case '-':	goto yy305;
+	case '=':	goto yy299;
+	case '>':	goto yy304;
+	case '{':	goto yy301;
+	case '~':	goto yy303;
 	default:	goto yy4;
 	}
 yy4:
@@ -1889,69 +1889,74 @@ yy297:
 	++YYCURSOR;
 	{ return CRITIC_ADD_CLOSE; }
 yy299:
-	yyaccept = 17;
-	yych = *(YYMARKER = ++YYCURSOR);
-	switch (yych) {
-	case 'T':	goto yy316;
+	++YYCURSOR;
+	switch ((yych = *YYCURSOR)) {
+	case '=':	goto yy321;
 	default:	goto yy300;
 	}
 yy300:
-	{ return BRACE_DOUBLE_LEFT; }
+	{ return RAW_FILTER_LEFT; }
 yy301:
-	yych = *++YYCURSOR;
+	yyaccept = 17;
+	yych = *(YYMARKER = ++YYCURSOR);
 	switch (yych) {
-	case '=':	goto yy314;
-	default:	goto yy2;
+	case 'T':	goto yy315;
+	default:	goto yy302;
 	}
 yy302:
-	yych = *++YYCURSOR;
-	switch (yych) {
-	case '~':	goto yy312;
-	default:	goto yy2;
-	}
+	{ return BRACE_DOUBLE_LEFT; }
 yy303:
 	yych = *++YYCURSOR;
 	switch (yych) {
-	case '>':	goto yy310;
+	case '~':	goto yy313;
 	default:	goto yy2;
 	}
 yy304:
 	yych = *++YYCURSOR;
 	switch (yych) {
-	case '-':	goto yy308;
+	case '>':	goto yy311;
 	default:	goto yy2;
 	}
 yy305:
 	yych = *++YYCURSOR;
 	switch (yych) {
-	case '+':	goto yy306;
+	case '-':	goto yy309;
 	default:	goto yy2;
 	}
 yy306:
+	yych = *++YYCURSOR;
+	switch (yych) {
+	case '+':	goto yy307;
+	default:	goto yy2;
+	}
+yy307:
 	++YYCURSOR;
 	{ return CRITIC_ADD_OPEN; }
-yy308:
+yy309:
 	++YYCURSOR;
 	{ return CRITIC_DEL_OPEN; }
-yy310:
+yy311:
 	++YYCURSOR;
 	{ return CRITIC_COM_OPEN; }
-yy312:
+yy313:
 	++YYCURSOR;
 	{ return CRITIC_SUB_OPEN; }
-yy314:
-	++YYCURSOR;
-	{ return CRITIC_HI_OPEN; }
+yy315:
+	yych = *++YYCURSOR;
+	switch (yych) {
+	case 'O':	goto yy316;
+	default:	goto yy2;
+	}
 yy316:
 	yych = *++YYCURSOR;
 	switch (yych) {
-	case 'O':	goto yy317;
+	case 'C':	goto yy317;
 	default:	goto yy2;
 	}
 yy317:
 	yych = *++YYCURSOR;
 	switch (yych) {
-	case 'C':	goto yy318;
+	case '}':	goto yy318;
 	default:	goto yy2;
 	}
 yy318:
@@ -1961,14 +1966,11 @@ yy318:
 	default:	goto yy2;
 	}
 yy319:
-	yych = *++YYCURSOR;
-	switch (yych) {
-	case '}':	goto yy320;
-	default:	goto yy2;
-	}
-yy320:
 	++YYCURSOR;
 	{ return TOC; }
+yy321:
+	++YYCURSOR;
+	{ return CRITIC_HI_OPEN; }
 }
 
 }
diff --git a/Sources/libMultiMarkdown/lexer.re b/Sources/libMultiMarkdown/lexer.re
index b725955..84f33f9 100644
--- a/Sources/libMultiMarkdown/lexer.re
+++ b/Sources/libMultiMarkdown/lexer.re
@@ -224,6 +224,7 @@ int scan(Scanner * s, const char * stop) {
 
 		'#'								{ return TEXT_HASH; }
 		'%'								{ return TEXT_PERCENT; }
+		'{='							{ return RAW_FILTER_LEFT; }
 		'{'								{ return TEXT_BRACE_LEFT; }
 		'}'								{ return TEXT_BRACE_RIGHT; }
 		'\\'							{ return TEXT_BACKSLASH; }
diff --git a/Sources/libMultiMarkdown/mmd.c b/Sources/libMultiMarkdown/mmd.c
index 123e0d9..4ca0c94 100644
--- a/Sources/libMultiMarkdown/mmd.c
+++ b/Sources/libMultiMarkdown/mmd.c
@@ -177,6 +177,11 @@ mmd_engine * mmd_engine_create(DString * d, unsigned long extensions) {
 			token_pair_engine_add_pairing(e->pairings4, SUBSCRIPT, SUBSCRIPT, PAIR_SUBSCRIPT, PAIRING_PRUNE_MATCH);
 		}
 
+		// Text Braces -- for raw text syntax
+		if (!(extensions & EXT_COMPATIBILITY)) {
+			token_pair_engine_add_pairing(e->pairings4, TEXT_BRACE_LEFT, TEXT_BRACE_RIGHT, PAIR_BRACE, PAIRING_PRUNE_MATCH);
+			token_pair_engine_add_pairing(e->pairings4, RAW_FILTER_LEFT, TEXT_BRACE_RIGHT, PAIR_RAW_FILTER, PAIRING_PRUNE_MATCH);
+		}
 	}
 
 	return e;
diff --git a/Sources/libMultiMarkdown/odf.c b/Sources/libMultiMarkdown/odf.c
index 479c329..59810b2 100644
--- a/Sources/libMultiMarkdown/odf.c
+++ b/Sources/libMultiMarkdown/odf.c
@@ -417,6 +417,37 @@ void mmd_export_token_odf(DString * out, const char * source, token * t, scratch
 			break;
 		case BLOCK_CODE_FENCED:
 			pad(out, 2, scratch);
+
+			temp_char = get_fence_language_specifier(t->child->child, source);
+
+			if (temp_char) {
+				if (strncmp("{=", temp_char, 2) == 0) {
+					// Raw source
+					if (raw_filter_text_matches(temp_char, FORMAT_HTML)) {
+						switch (t->child->tail->type) {
+							case LINE_FENCE_BACKTICK_3:
+							case LINE_FENCE_BACKTICK_4:
+							case LINE_FENCE_BACKTICK_5:
+								temp_token = t->child->tail;
+								break;
+							default:
+								temp_token = NULL;
+						}
+						if (temp_token) {
+							d_string_append_c_array(out, &source[t->child->next->start], temp_token->start - t->child->next->start);
+							scratch->padded = 1;
+						} else {
+							d_string_append_c_array(out, &source[t->child->start + t->child->len], t->start + t->len - t->child->next->start);							
+							scratch->padded = 0;
+						}
+					}
+
+					break;
+				}
+			}
+			
+			free(temp_char);
+
 			print_const("");
 			mmd_export_token_tree_odf_raw(out, source, t->child->next, scratch);
 			print_const("");
@@ -950,10 +981,22 @@ void mmd_export_token_odf(DString * out, const char * source, token * t, scratch
 			}
 			t->child->type = TEXT_EMPTY;
 			t->child->mate->type = TEXT_EMPTY;
+
+			if (t->next && t->next->type == PAIR_RAW_FILTER) {
+				// Raw text?
+				if (raw_filter_matches(t->next, source, FORMAT_ODF)) {
+					d_string_append_c_array(out, &(source[t->child->start + t->child->len]), t->child->mate->start - t->child->start - t->child->len);
+				}
+				// Skip over PAIR_RAW_FILTER
+				scratch->skip_token = 1;
+				break;
+			}
+
 			print_const("");
 			mmd_export_token_tree_odf_raw(out, source, t->child, scratch);
 			print_const("");
 			break;
+		case PAIR_BRACE:
 		case PAIR_BRACES:
 			mmd_export_token_tree_odf(out, source, t->child, scratch);
 			break;
@@ -1525,6 +1568,7 @@ void mmd_export_token_odf(DString * out, const char * source, token * t, scratch
 			if (t->next)
 				print_char('\n');
 			break;
+		case RAW_FILTER_LEFT:
 		case TEXT_BACKSLASH:
 		case TEXT_BRACE_LEFT:
 		case TEXT_BRACE_RIGHT:
diff --git a/Sources/libMultiMarkdown/token_pairs.h b/Sources/libMultiMarkdown/token_pairs.h
index 67fc76a..4de480e 100644
--- a/Sources/libMultiMarkdown/token_pairs.h
+++ b/Sources/libMultiMarkdown/token_pairs.h
@@ -65,7 +65,7 @@
 #include "CuTest.h"
 #endif
 
-#define kMaxTokenTypes	200				//!< This needs to be larger than the largest token type being used
+#define kMaxTokenTypes	230				//!< This needs to be larger than the largest token type being used
 #define kLargeStackThreshold 1000		//!< Avoid unnecessary searches of large stacks
 #define kMaxPairRecursiveDepth 1000		//!< Maximum recursion depth to traverse when pairing tokens -- to prevent stack overflow with "pathologic" input
 
diff --git a/Sources/libMultiMarkdown/writer.c b/Sources/libMultiMarkdown/writer.c
index 89dd314..4539eb5 100644
--- a/Sources/libMultiMarkdown/writer.c
+++ b/Sources/libMultiMarkdown/writer.c
@@ -2423,3 +2423,55 @@ void store_asset(scratch_pad * scratch, char * url) {
 	}
 }
 
+
+bool raw_filter_text_matches(char * pattern, short format) {
+	if (!pattern)
+		return false;
+
+	if (strcmp("*", pattern) == 0) {
+		return true;
+	} else if (strcmp("{=*}", pattern) == 0) {
+		return true;
+	} else {
+		switch(format){
+			case FORMAT_HTML:
+				if (strstr(pattern, "html"))
+					return true;
+				break;
+			case FORMAT_ODF:
+				if (strstr(pattern, "odf"))
+					return true;
+				break;
+			case FORMAT_EPUB:
+				if (strstr(pattern, "epub"))
+					return true;
+				break;
+			case FORMAT_MEMOIR:
+			case FORMAT_BEAMER:
+			case FORMAT_LATEX:
+				if (strstr(pattern, "latex"))
+					return true;
+				break;
+		}
+	}
+
+	return false;
+}
+
+
+/// Determine whether raw filter matches specified format
+bool raw_filter_matches(token * t, const char * source, short format) {
+	bool result = false;
+
+	if (t->type != PAIR_RAW_FILTER)
+		return result;
+
+	char * pattern = my_strndup(&source[t->child->start + 2], t->child->mate->start - t->child->start - 2);
+
+	result = raw_filter_text_matches(pattern, format);
+
+	free(pattern);
+
+	return result;
+}
+
diff --git a/Sources/libMultiMarkdown/writer.h b/Sources/libMultiMarkdown/writer.h
index cc4ce29..7771cf1 100644
--- a/Sources/libMultiMarkdown/writer.h
+++ b/Sources/libMultiMarkdown/writer.h
@@ -250,5 +250,9 @@ void store_asset(scratch_pad * scratch_pad, char * url);
 asset * extract_asset(scratch_pad * scratch, char * url);
 void asset_free(asset * a);
 
+bool raw_filter_text_matches(char * pattern, short format);
+bool raw_filter_matches(token * filter, const char * source, short format);
+
+
 #endif
 
diff --git a/tests/MMD6Tests/Raw Source.fodt b/tests/MMD6Tests/Raw Source.fodt
new file mode 100644
index 0000000..22dbb7d
--- /dev/null
+++ b/tests/MMD6Tests/Raw Source.fodt	
@@ -0,0 +1,305 @@
+
+
+
+   
+
+
+
+      
+   
+
+   
+   
+
+
+   
+
+
+   
+   
+
+
+   
+
+
+   
+   
+
+
+   
+   
+
+     
+
+ 
+  
+   
+  
+ 
+
+  
+  
+
+   
+      
+   
+   
+      
+   
+   
+      
+   
+   
+      
+   
+   
+      
+   
+   
+      
+   
+   
+      
+   
+   
+      
+   
+
+   
+
+
+   
+
+
+   
+
+
+
+
+
+   
+
+
+
+	
+		
+			
+		
+	
+	
+		
+			
+		
+	
+	
+		
+			
+		
+	
+	
+		
+			
+		
+	
+	
+		
+			
+		
+	
+	
+		
+			
+		
+	
+	
+		
+			
+		
+	
+	
+		
+			
+		
+	
+	
+		
+			
+		
+	
+	
+		
+			
+		
+	
+
+
+	
+		
+			
+		
+	
+	
+		
+			
+		
+	
+	
+		
+			
+		
+	
+	
+		
+			
+		
+	
+	
+		
+			
+		
+	
+	
+		
+			
+		
+	
+	
+		
+			
+		
+	
+	
+		
+			
+		
+	
+	
+		
+			
+		
+	
+	
+		
+			
+		
+	
+
+
+ 
+  
+    Bibliography
+  
+ 
+
+	Raw Source
+
+
+
+*foo*{*}
+
+
+
+
+
+*foo*
+
+*foo*
+
+5
+
+*foo*
+
+*foo*
+
+*foo*
+
+10
+
+*foo*
+
+*bar*
+
+
+
+
diff --git a/tests/MMD6Tests/Raw Source.html b/tests/MMD6Tests/Raw Source.html
new file mode 100644
index 0000000..f08df02
--- /dev/null
+++ b/tests/MMD6Tests/Raw Source.html	
@@ -0,0 +1,37 @@
+
+
+
+	
+	Raw Source
+
+
+
+

*foo*{*}

+ +

*foo*

+ +

+ +

+ +

*foo*

+ +

5

+ +
*foo*
+
+ +*foo* + +*foo* + +

10

+ +*foo* + +*bar* + + + + + diff --git a/tests/MMD6Tests/Raw Source.htmlc b/tests/MMD6Tests/Raw Source.htmlc new file mode 100644 index 0000000..33640b3 --- /dev/null +++ b/tests/MMD6Tests/Raw Source.htmlc @@ -0,0 +1,36 @@ +

Title: Raw Source +latex config: article

+ +

*foo*{*}

+ +

*foo*{=html}

+ +

*foo*{=latex}

+ +

*foo*{=odf}

+ +

*foo*{=*}

+ +

5

+ +

{*} +*foo*

+ +

{=html} +*foo*

+ +

{=latex} +*foo*

+ +

{=odf} +*foo*

+ +

{=*} +*foo*

+ +

10

+ +

```{=*} +foo

+ +

bar

diff --git a/tests/MMD6Tests/Raw Source.tex b/tests/MMD6Tests/Raw Source.tex new file mode 100644 index 0000000..50a09de --- /dev/null +++ b/tests/MMD6Tests/Raw Source.tex @@ -0,0 +1,33 @@ +\input{mmd6-article-leader} +\def\mytitle{Raw Source} +\input{mmd6-article-begin} + +\texttt{*foo*}\{*\} + + + +*foo* + + + +*foo* + +5 + +\begin{lstlisting}[language={*}] +*foo* +\end{lstlisting} + +*foo* + +*foo* + +10 + +*foo* + +*bar* + + +\input{mmd6-article-footer} +\end{document} diff --git a/tests/MMD6Tests/Raw Source.text b/tests/MMD6Tests/Raw Source.text new file mode 100644 index 0000000..ef70c7d --- /dev/null +++ b/tests/MMD6Tests/Raw Source.text @@ -0,0 +1,41 @@ +Title: Raw Source +latex config: article + +`*foo*`{*} + +`*foo*`{=html} + +`*foo*`{=latex} + +`*foo*`{=odf} + +`*foo*`{=*} + +5 + +```{*} +*foo* +``` + +```{=html} +*foo* +``` + +```{=latex} +*foo* +``` + +```{=odf} +*foo* +``` + +```{=*} +*foo* +``` + +10 + +```{=*} +*foo* + +*bar*