Repository: naturalcrit/homebrewery (js)

Issue:
Math functions with multiple parameters cannot take variable names
### Renderer

v3

### Browser

Chrome

### Operating System

Windows

### What happened?

The expectation is the reproduction code will return `2`; instead it returns `$[min(2,DexMod)]`

See reproduction brew here - https://homebrewery.naturalcrit.com/share/VE5qZsAsuAfk

### Code

```gfm
[DexMod]: 4

$[min(2,DexMod)]
```


Pull request:
Tweak variable math split regex
This PR resolves #3622.

This PR adds the comma character to the regex used to split the variable string in order to identify variable names. 

CURRENT:
RegEx: `/[a-z]+\(|[+\-*/^()]/g`

`min(2,var)` => `min(` : matches `[a-z]+\(`; `)` : matches `[+\-*/^()]` => OUTPUT: `2,var`
As variable names cannot contain commas, this never matches a variable name and thus the replacement function does not run.
**NB:** changing the input string to `min(2,(var))` **does work** because the brackets cause the replacement function to correctly identify the variable name.

Without brackets:
![image](https://github.com/user-attachments/assets/8d813428-cad0-4f5e-bbcd-1d78b1325e64)
With brackets:
![image](https://github.com/user-attachments/assets/ea73a9bf-d79c-434a-a899-e40d38590366)


PR:
RegEx: `/[a-z]+\(|[+\-*/^(),]/g`

`min(2,var)` => `min(` : matches `[a-z]+\(`; `,` : matches `[+\-*/^()]`; `)` : matches `[+\-*/^()]` => OUTPUT: `2`,`var`

Without brackets:
![image](https://github.com/user-attachments/assets/ff89b6b8-8104-4a8a-98e8-5682290b1f05)
With brackets:
![image](https://github.com/user-attachments/assets/64dc44f4-26b2-4f2d-9deb-3a40a64410be)


Patch:
diff --git a/shared/naturalcrit/markdown.js b/shared/naturalcrit/markdown.js
index f7f1763e..9388e912 100644
--- a/shared/naturalcrit/markdown.js
+++ b/shared/naturalcrit/markdown.js
@@ -452,7 +452,7 @@ const replaceVar = function(input, hoist=false, allowUnresolved=false) {
 	const label  = match[2];
 
 	//v=====--------------------< HANDLE MATH >-------------------=====v//
-	const mathRegex = /[a-z]+\(|[+\-*/^()]/g;
+	const mathRegex = /[a-z]+\(|[+\-*/^(),]/g;
 	const matches = label.split(mathRegex);
 	const mathVars = matches.filter((match)=>isNaN(match))?.map((s)=>s.trim()); // Capture any variable names
 


Test patch:
diff --git a/tests/markdown/variables.test.js b/tests/markdown/variables.test.js
index 3a03d64f..2c8db375 100644
--- a/tests/markdown/variables.test.js
+++ b/tests/markdown/variables.test.js
@@ -372,14 +372,32 @@ describe('Cross-page variables', ()=>{
 	});
 });
 
-describe('Variable name as a subset of a function or other variable name', ()=>{
-	it('Variable name as a subset of a function', function() {
+describe('Math function parameter handling', ()=>{
+	it('allows variables in single-parameter functions', function() {
+		const source = '[var]:4.1\n\n$[floor(var)]';
+		const rendered = Markdown.render(source).trimReturns();
+		expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<p>4</p>`);
+	});
+	it('allows one variable and a number in two-parameter functions', function() {
+		const source = '[var]:4\n\n$[min(1,var)]';
+		const rendered = Markdown.render(source).trimReturns();
+		expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<p>1</p>`);
+	});
+	it('allows two variables in two-parameter functions', function() {
+		const source = '[var1]:4\n\n[var2]:8\n\n$[min(var1,var2)]';
+		const rendered = Markdown.render(source).trimReturns();
+		expect(rendered, `Input:\n${source}`, { showPrefix: false }).toBe(`<p>4</p>`);
+	});
+});
+
+describe('Variable names that are subsets of other names', ()=>{
+	it('do not conflict with function names', function() {
 		const source = `[a]: -1\n\n$[abs(a)]`;
 		const rendered = Markdown.render(source).trimReturns();
 		expect(rendered).toBe('<p>1</p>');
 	});
 
-	it('Variable name as a subset of another variable name', function() {
+	it('do not conflict with other variable names', function() {
 		const source = `[ab]: 2\n\n[aba]: 8\n\n[ba]: 4\n\n$[ab + aba + ba]`;
 		const rendered = Markdown.render(source).trimReturns();
 		expect(rendered).toBe('<p>14</p>');