diff --git a/client/homebrew/editor/snippetbar/snippets/snippets.js b/client/homebrew/editor/snippetbar/snippets/snippets.js
index 6ecae9429..9abedcf28 100644
--- a/client/homebrew/editor/snippetbar/snippets/snippets.js
+++ b/client/homebrew/editor/snippetbar/snippets/snippets.js
@@ -51,16 +51,13 @@ module.exports = [
name : 'Image',
icon : 'fas fa-image',
gen : dedent`
-
+  {width="325px"}
Credit: Kyounghwan Kim`
},
{
name : 'Background Image',
icon : 'fas fa-tree',
- gen : `
`
+ gen : ` {position="absolute",top="50px",right="30px",width="280px"}`
},
{
name : 'QR Code',
diff --git a/shared/naturalcrit/markdown.js b/shared/naturalcrit/markdown.js
index 37784f740..580ba5b5a 100644
--- a/shared/naturalcrit/markdown.js
+++ b/shared/naturalcrit/markdown.js
@@ -31,7 +31,7 @@ const mustacheSpans = {
start(src) { return src.match(/{{[^{]/)?.index; }, // Hint to Marked.js to stop and check for a match
tokenizer(src, tokens) {
const completeSpan = /^{{[^\n]*}}/; // Regex for the complete token
- const inlineRegex = /{{(?:="[\w,\-. ]*"|[^"'{}\s])*\s*|}}/g;
+ const inlineRegex = /{{(?:="[\w,\-(). ]*"|[^"'{}\s])*\s*|}}/g;
const match = completeSpan.exec(src);
if(match) {
//Find closing delimiter
@@ -77,7 +77,7 @@ const mustacheDivs = {
start(src) { return src.match(/^ *{{[^{]/m)?.index; }, // Hint to Marked.js to stop and check for a match
tokenizer(src, tokens) {
const completeBlock = /^ *{{.*\n *}}/s; // Regex for the complete token
- const blockRegex = /^ *{{(?:="[\w,\-. ]*"|[^"'{}\s])*$|^ *}}$/gm;
+ const blockRegex = /^ *{{(?:="[\w,\-(). ]*"|[^"'{}\s])*$|^ *}}$/gm;
const match = completeBlock.exec(src);
if(match) {
//Find closing delimiter
@@ -116,6 +116,82 @@ const mustacheDivs = {
}
};
+const mustacheInjectInline = {
+ name : 'mustacheInjectInline',
+ level : 'inline',
+ start(src) { return src.match(/ *{[^{\n]/)?.index; }, // Hint to Marked.js to stop and check for a match
+ tokenizer(src, tokens) {
+ const inlineRegex = /^ *{((?:="[\w,\-(). ]*"|[^"'{}\s])*)}/g;
+ const match = inlineRegex.exec(src);
+ if(match) {
+ const lastToken = tokens[tokens.length - 1];
+ if(!lastToken)
+ return false;
+
+ const tags = ` ${processStyleTags(match[1])}`;
+ lastToken.originalType = lastToken.type;
+ lastToken.type = 'mustacheInjectInline';
+ lastToken.tags = tags;
+ return {
+ type : 'text', // Should match "name" above
+ raw : match[0], // Text to consume from the source
+ text : ''
+ };
+ }
+ },
+ renderer(token) {
+ token.type = token.originalType;
+ const text = this.parseInline([token]);
+ const openingTag = /(<[^\s<>]+)([^\n<>]*>.*)/s.exec(text);
+ if(openingTag) {
+ return `${openingTag[1]} class="${token.tags}${openingTag[2]}`;
+ }
+ return text;
+ }
+};
+
+const mustacheInjectBlock = {
+ extensions : [{
+ name : 'mustacheInjectBlock',
+ level : 'block',
+ start(src) { return src.match(/^ *{[^{\n]/m)?.index; }, // Hint to Marked.js to stop and check for a match
+ tokenizer(src, tokens) {
+ const inlineRegex = /^ *{((?:="[\w,\-(). ]*"|[^"'{}\s])*)}/ym;
+ const match = inlineRegex.exec(src);
+ if(match) {
+ const lastToken = tokens[tokens.length - 1];
+ if(!lastToken)
+ return false;
+
+ lastToken.originalType = 'mustacheInjectBlock';
+ lastToken.tags = ` ${processStyleTags(match[1])}`;
+ return {
+ type : 'text', // Should match "name" above
+ raw : match[0], // Text to consume from the source
+ text : ''
+ };
+ }
+ },
+ renderer(token) {
+ token.type = token.originalType;
+ const text = this.parse([token]);
+ const openingTag = /(<[^\s<>]+)([^\n<>]*>.*)/s.exec(text);
+ if(openingTag) {
+ return `${openingTag[1]} class="${token.tags}${openingTag[2]}`;
+ }
+ return text;
+ }
+ }],
+ walkTokens(token) {
+ // After token tree is finished, tag tokens to apply styles to so Renderer can find them
+ // Does not work with tables since Marked.js tables generate invalid "tokens", and changing "type" ruins Marked handling that edge-case
+ if(token.originalType == 'mustacheInjectBlock' && token.type !== 'table') {
+ token.originalType = token.type;
+ token.type = 'mustacheInjectBlock';
+ }
+ }
+};
+
const definitionLists = {
name : 'definitionLists',
level : 'block',
@@ -125,13 +201,11 @@ const definitionLists = {
let match;
let endIndex = 0;
const definitions = [];
- //if(!src.match(/^[^\n]*?::/)) {console.log('return'); return;}
while (match = regex.exec(src)) {
definitions.push({
dt : this.inlineTokens(match[1].trim()),
dd : this.inlineTokens(match[2].trim())
});
- //console.log(regexl)
endIndex = regex.lastIndex;
}
if(definitions.length) {
@@ -146,13 +220,15 @@ const definitionLists = {
return `