Repository: naturalcrit/homebrewery (js)

Issue:
Brew crashes due to multiple text formatting tags
### Renderer

v3

### Browser

Chrome

### Operating System

Windows

### What happened?

I was fixing my table of contents for my brew (which is still bricked), and suddenly the entire browser went into a full white screen aside from the address bar at the top. After some digging, I was able to determine that this is the result of putting two {} text formatting brackets below one another (presumably the second one attempts to format the first one, which leads to undesired behaviour). The code provided is an example of what I had.

While I was able to save and create another brew using the source code from this one, I would prefer to still keep the previous one to use the same link, as well as partially to keep it as one of my top viewed brews to ease finding it in my pile of brews on my profile.

If you are able to manually change the contents of a brew, please remove the provided bit from page 2 of brew:
https://homebrewery.naturalcrit.com/edit/PRK9DJ9Cm

### Code

```gfm
##### [Grievous Wounds](#p27)
{color:#73310e,font-size:125%}
{text-align:center}
```


Pull request description:
Prevent Injection if preceded by another Injection token
This is a *short and sweet* fix for #2712 (fixes #2712).  It just adds an escape hatch in case of two consecutive inject blocks.

Note:  This is sort of a *half measure*, and should be improved in a future PR.  Specifically, you will see that consecutive mustacheInjectBlock tokens are rendered as plain text after the first, but mustacheInjectInline does not render the subsequent tokens as text (they are absorbed into the previous token).   I think the standard behavior that is desired is to follow the Block process, so that anything that isn't being tokenized is just coming out as plain text.  I don't want to bog this PR down with any further delays, so I'm going ahead without worrying about this for now.

Patch:
diff --git a/shared/naturalcrit/markdown.js b/shared/naturalcrit/markdown.js
index 16623b8a..1960776d 100644
--- a/shared/naturalcrit/markdown.js
+++ b/shared/naturalcrit/markdown.js
@@ -134,7 +134,7 @@ const mustacheInjectInline = {
 		const match = inlineRegex.exec(src);
 		if(match) {
 			const lastToken = tokens[tokens.length - 1];
-			if(!lastToken)
+			if(!lastToken || lastToken.type == 'mustacheInjectInline')
 				return false;
 
 			const tags = ` ${processStyleTags(match[1])}`;
@@ -169,7 +169,7 @@ const mustacheInjectBlock = {
 			const match = inlineRegex.exec(src);
 			if(match) {
 				const lastToken = tokens[tokens.length - 1];
-				if(!lastToken)
+				if(!lastToken || lastToken.type == 'mustacheInjectBlock')
 					return false;
 
 				lastToken.originalType = 'mustacheInjectBlock';
diff --git a/themes/V3/Blank/snippets/imageMask.gen.js b/themes/V3/Blank/snippets/imageMask.gen.js
index 5ddef7a2..cae4bf69 100644
--- a/themes/V3/Blank/snippets/imageMask.gen.js
+++ b/themes/V3/Blank/snippets/imageMask.gen.js
@@ -2,7 +2,7 @@ const _ = require('lodash');
 const dedent = require('dedent-tabs').default;
 
 module.exports = {
-	center :()=>{
+	center : ()=>{
 		return dedent`
 			{{imageMaskCenter${_.random(1, 16)},--offsetX:0%,--offsetY:0%,--rotation:0;
 			  ![](https://i.imgur.com/GZfjDWV.png){height:100%}


Test patch:
diff --git a/tests/markdown/mustache-span.test.js b/tests/markdown/mustache-span.test.js
index 6d249ebc..e7c65ea7 100644
--- a/tests/markdown/mustache-span.test.js
+++ b/tests/markdown/mustache-span.test.js
@@ -105,6 +105,22 @@ test('Renders a mustache span with text, id, class and a couple of css propertie
 	expect(rendered).toBe('<span class="inline-block pen" id="author" style="color:orange; font-family:trebuchet ms;">text</span>');
 });
 
+test('Two consecutive injections into Inline', function() {
+	const source = '{{dog Sample Text}}{cat}{toad}';
+	const rendered = Markdown.render(source);
+	// FIXME: Drops original attributes in favor of injection, rather than adding.
+	// FIXME: Doesn't keep the raw text of second injection.
+	// FIXME: Renders the extra class attribute (which is dropped by the browser).
+	expect(rendered).toBe('<p><span class=" cat"   class="inline-block cat"  >Sample Text</span></p>\n');
+});
+
+test('Two consecutive injections into Block', function() {
+	const source = '{{dog\nSample Text\n}}\n{cat}\n{toad}';
+	const rendered = Markdown.render(source);
+	// FIXME: Renders the extra class attribute (which is dropped by the browser).
+	expect(rendered).toBe('<div class=" cat"   class="block cat"  ><p>Sample Text</p>\n</div><p>{toad}</p>\n');
+});
+
 // TODO: add tests for ID with accordance to CSS spec:
 //
 // From https://drafts.csswg.org/selectors/#id-selectors: