From e842599b2229077ec9afebf47c54c0a4a3102194 Mon Sep 17 00:00:00 2001 From: David Bolack Date: Sat, 24 May 2025 22:35:03 -0500 Subject: [PATCH 1/3] Add missing punction and sentence structure characters to mustache style assignment regex --- client/homebrew/editor/editor.jsx | 2 +- shared/naturalcrit/markdown.js | 20 +++++++++++++++----- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/client/homebrew/editor/editor.jsx b/client/homebrew/editor/editor.jsx index cf9a17303..7faa22f16 100644 --- a/client/homebrew/editor/editor.jsx +++ b/client/homebrew/editor/editor.jsx @@ -12,7 +12,7 @@ const MetadataEditor = require('./metadataEditor/metadataEditor.jsx'); const EDITOR_THEME_KEY = 'HOMEBREWERY-EDITOR-THEME'; -const PAGEBREAK_REGEX_V3 = /^(?=\\page(?:break)?(?: *{[^\n{}]*})?$)/m; +const PAGEBREAK_REGEX_V3 = /^(?=\\page(?:break)?(?: *{[^\n]*})?$)/m; const SNIPPETBREAK_REGEX_V3 = /^\\snippet\ .*$/; const SNIPPETBAR_HEIGHT = 25; const DEFAULT_STYLE_TEXT = dedent` diff --git a/shared/naturalcrit/markdown.js b/shared/naturalcrit/markdown.js index ac6988734..42bc5b054 100644 --- a/shared/naturalcrit/markdown.js +++ b/shared/naturalcrit/markdown.js @@ -185,7 +185,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,\-()#%=?. ]*"|[\w\-()#%.]*)|[^"=':{}\s]*)*))\1 *|}}/g; + const inlineRegex = /{{(?=((?:[:=](?:"'['\w,\-()#%=?. \&\:\!\@\$\^\*\<\>\;\:\[\]\{\}\-\_\+\=]*'"|[\w\-()#%.]*)|[^"=':{}\s]*)*))\1 *|}}/g; const match = completeSpan.exec(src); if(match) { //Find closing delimiter @@ -242,7 +242,7 @@ const mustacheDivs = { start(src) { return src.match(/\n *{{[^{]/m)?.index; }, // Hint to Marked.js to stop and check for a match tokenizer(src, tokens) { const completeBlock = /^ *{{[^\n}]* *\n.*\n *}}/s; // Regex for the complete token - const blockRegex = /^ *{{(?=((?:[:=](?:"['\w,\-()#%=?. ]*"|[\w\-()#%.]*)|[^"=':{}\s]*)*))\1 *$|^ *}}$/gm; + const blockRegex = /^ *{{(?=((?:[:=](?:"['\w,\-()#%=?.\&\:\!\@\$\^\*\<\>\;\:\[\]\{\}\-\_\+\= ]*"|[\w\-()#%. ]*)|[^"=':{}\s]*)*))\1 *$|^ *}}$/gm; const match = completeBlock.exec(src); if(match) { //Find closing delimiter @@ -297,7 +297,7 @@ const 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,\-()#%=?. ]*"|[\w\-()#%.]*)|[^"=':{}\s]*)*))\1}/g; + const inlineRegex = /^ *{(?=((?:[:=](?:"['\w,\-()#%=?.\&\:\!\@\$\^\*\<\>\;\:\[\]\{\}\-\_\+\= ]*"|[\w\-()#%.]*)|[^"=':{}\s]*)*))\1}/g; const match = inlineRegex.exec(src); if(match) { const lastToken = tokens[tokens.length - 1]; @@ -343,7 +343,7 @@ const mustacheInjectBlock = { level : 'block', start(src) { return src.match(/\n *{[^{\n]/m)?.index; }, // Hint to Marked.js to stop and check for a match tokenizer(src, tokens) { - const inlineRegex = /^ *{(?=((?:[:=](?:"['\w,\-()#%=?. ]*"|[\w\-()#%.]*)|[^"=':{}\s]*)*))\1}/ym; + const inlineRegex = /^ *{(?=((?:[:=](?:"['\w,\-()#%=?.& ]*"|[\w\-()#%.]*)|[^"=':{}\s]*)*))\1}/ym; const match = inlineRegex.exec(src); if(match) { const lastToken = tokens[tokens.length - 1]; @@ -735,6 +735,16 @@ const voidTags = new Set([ 'input', 'keygen', 'link', 'meta', 'param', 'source' ]); +const notInside = (string, stringMatch1, stringMatch2)=> { + const pos1 = string.indexOf(stringMatch1); + const pos2 = string.indexOf(stringMatch2); + + if((pos1 > 0) && (pos2 > 0) && (pos2 > pos1)) { + return true; + } + return false; +}; + const processStyleTags = (string)=>{ //split tags up. quotes can only occur right after : or =. //TODO: can we simplify to just split on commas? @@ -742,7 +752,7 @@ const processStyleTags = (string)=>{ const id = _.remove(tags, (tag)=>tag.startsWith('#')).map((tag)=>tag.slice(1))[0] || null; const classes = _.remove(tags, (tag)=>(!tag.includes(':')) && (!tag.includes('='))).join(' ') || null; - const attributes = _.remove(tags, (tag)=>(tag.includes('='))).map((tag)=>tag.replace(/="?([^"]*)"?/g, '="$1"')) + const attributes = _.remove(tags, (tag)=>(notInside(tag, '=', ':'))).map((tag)=>tag.replace(/="?([^"]*)"?/g, '="$1"')) ?.filter((attr)=>!attr.startsWith('class="') && !attr.startsWith('style="') && !attr.startsWith('id="')) .reduce((obj, attr)=>{ const index = attr.indexOf('='); From 50d2a0d3a2a842bede5f22feddad7cac1d113485 Mon Sep 17 00:00:00 2001 From: David Bolack Date: Mon, 26 May 2025 23:13:21 -0500 Subject: [PATCH 2/3] FIx regression --- shared/naturalcrit/markdown.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/shared/naturalcrit/markdown.js b/shared/naturalcrit/markdown.js index 42bc5b054..ff61e9793 100644 --- a/shared/naturalcrit/markdown.js +++ b/shared/naturalcrit/markdown.js @@ -185,9 +185,10 @@ 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,\-()#%=?. \&\:\!\@\$\^\*\<\>\;\:\[\]\{\}\-\_\+\=]*'"|[\w\-()#%.]*)|[^"=':{}\s]*)*))\1 *|}}/g; + const inlineRegex = /{{(?=((?:[:=](?:"['\w,\-()#%=?. \&\:\!\@\$\^\*\<\>\;\:\[\]\{\}\-\_\+\=]*"|[\w\-()#%.]*)|[^"=':{}\s]*)*))\1 *|}}/g; const match = completeSpan.exec(src); if(match) { + console.log('MustacheSpans'); //Find closing delimiter let blockCount = 0; let tags = {}; @@ -195,6 +196,7 @@ const mustacheSpans = { let endToken = 0; let delim; while (delim = inlineRegex.exec(match[0])) { + console.log(delim); if(_.isEmpty(tags)) { tags = processStyleTags(delim[0].substring(2)); endTags = delim[0].length; @@ -245,6 +247,7 @@ const mustacheDivs = { const blockRegex = /^ *{{(?=((?:[:=](?:"['\w,\-()#%=?.\&\:\!\@\$\^\*\<\>\;\:\[\]\{\}\-\_\+\= ]*"|[\w\-()#%. ]*)|[^"=':{}\s]*)*))\1 *$|^ *}}$/gm; const match = completeBlock.exec(src); if(match) { + console.log('Mustache Divs'); //Find closing delimiter let blockCount = 0; let tags = {}; @@ -300,6 +303,7 @@ const mustacheInjectInline = { const inlineRegex = /^ *{(?=((?:[:=](?:"['\w,\-()#%=?.\&\:\!\@\$\^\*\<\>\;\:\[\]\{\}\-\_\+\= ]*"|[\w\-()#%.]*)|[^"=':{}\s]*)*))\1}/g; const match = inlineRegex.exec(src); if(match) { + console.log('InlineInject'); const lastToken = tokens[tokens.length - 1]; if(!lastToken || lastToken.type == 'mustacheInjectInline') return false; @@ -739,7 +743,8 @@ const notInside = (string, stringMatch1, stringMatch2)=> { const pos1 = string.indexOf(stringMatch1); const pos2 = string.indexOf(stringMatch2); - if((pos1 > 0) && (pos2 > 0) && (pos2 > pos1)) { + if(((pos1 > 0) && (pos2 == -1)) || + ((pos1 > 0) && (pos2 > 0) && (pos2 > pos1))) { return true; } return false; From 029c105ff1f8c070874c5c04696009a5ca4fe029 Mon Sep 17 00:00:00 2001 From: David Bolack Date: Sat, 23 Aug 2025 14:04:37 -0500 Subject: [PATCH 3/3] Fix \} in divblocks --- shared/naturalcrit/markdown.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/shared/naturalcrit/markdown.js b/shared/naturalcrit/markdown.js index ff61e9793..c07d879ec 100644 --- a/shared/naturalcrit/markdown.js +++ b/shared/naturalcrit/markdown.js @@ -188,7 +188,6 @@ const mustacheSpans = { const inlineRegex = /{{(?=((?:[:=](?:"['\w,\-()#%=?. \&\:\!\@\$\^\*\<\>\;\:\[\]\{\}\-\_\+\=]*"|[\w\-()#%.]*)|[^"=':{}\s]*)*))\1 *|}}/g; const match = completeSpan.exec(src); if(match) { - console.log('MustacheSpans'); //Find closing delimiter let blockCount = 0; let tags = {}; @@ -196,7 +195,6 @@ const mustacheSpans = { let endToken = 0; let delim; while (delim = inlineRegex.exec(match[0])) { - console.log(delim); if(_.isEmpty(tags)) { tags = processStyleTags(delim[0].substring(2)); endTags = delim[0].length; @@ -243,11 +241,10 @@ const mustacheDivs = { 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 completeBlock = /^ *{{[^\n}]* *\n.*\n *}}/s; // Regex for the complete token + const completeBlock = /^ *{{[^\n]* *\n.*\n *}}/s; // Regex for the complete token const blockRegex = /^ *{{(?=((?:[:=](?:"['\w,\-()#%=?.\&\:\!\@\$\^\*\<\>\;\:\[\]\{\}\-\_\+\= ]*"|[\w\-()#%. ]*)|[^"=':{}\s]*)*))\1 *$|^ *}}$/gm; const match = completeBlock.exec(src); if(match) { - console.log('Mustache Divs'); //Find closing delimiter let blockCount = 0; let tags = {}; @@ -303,7 +300,6 @@ const mustacheInjectInline = { const inlineRegex = /^ *{(?=((?:[:=](?:"['\w,\-()#%=?.\&\:\!\@\$\^\*\<\>\;\:\[\]\{\}\-\_\+\= ]*"|[\w\-()#%.]*)|[^"=':{}\s]*)*))\1}/g; const match = inlineRegex.exec(src); if(match) { - console.log('InlineInject'); const lastToken = tokens[tokens.length - 1]; if(!lastToken || lastToken.type == 'mustacheInjectInline') return false;