Quellcode durchsuchen

Regexes safely escaped. Renamed MDSpreadsheetBlockReader

main
Rocketsoup vor 1 Jahr
Ursprung
Commit
ab3689c2bf
5 geänderte Dateien mit 55 neuen und 10 gelöschten Zeilen
  1. 39
    2
      js/markdown.js
  2. 2
    2
      js/spreadsheet.js
  3. 1
    1
      markdownjs.html
  4. 1
    1
      spreadsheet.md
  5. 12
    4
      testjs.html

+ 39
- 2
js/markdown.js Datei anzeigen

@@ -449,6 +449,44 @@ class MDUtils {
449 449
 		}
450 450
 		return a == b;
451 451
 	}
452
+
453
+	/**
454
+	 * @param {string} text
455
+	 */
456
+	static escapeRegex(text) {
457
+		// Partially following escaping scheme from not-yet-widely-supported RegExp.escape.
458
+		// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/escape
459
+		const escapeHex = function(ch) {
460
+			const codepoint = ch.codePointAt(0);
461
+			const s = '00' + codepoint.toString(16);
462
+			return `\\x${s.substring(s.length - 2)}`;
463
+		}
464
+		var escaped = '';
465
+		const l = text.length;
466
+		for (var i = 0; i < l; i++) {
467
+			const ch = text.substring(i, i + 1);
468
+			if (i == 0 && /[a-zA-Z0-9]/.exec(ch)) {
469
+				escaped += escapeHex(ch);
470
+			} else if ("^$\\.*+?()[]{}|/".indexOf(ch) >= 0) {
471
+				escaped += `\\${ch}`;
472
+			} else if (",-=<>#&!%:;@~'`\"".indexOf(ch) >= 0) {
473
+				escaped += escapeHex(ch);
474
+			} else if (ch == '\f') {
475
+				escaped += "\\f";
476
+			} else if (ch == '\n') {
477
+				escaped += "\\n";
478
+			} else if (ch == '\r') {
479
+				escaped += "\\r";
480
+			} else if (ch == '\t') {
481
+				escaped += "\\t";
482
+			} else if (ch == '\v') {
483
+				escaped += "\\v";
484
+			} else {
485
+				escaped += ch;
486
+			}
487
+		}
488
+		return escaped;
489
+	}
452 490
 }
453 491
 
454 492
 
@@ -3224,9 +3262,8 @@ class MDState {
3224 3262
 			this.#parent.defineAbbreviation(abbreviation, definition);
3225 3263
 			return;
3226 3264
 		}
3227
-		// FIXME: Escape abbreviation
3228 3265
 		this.#abbreviations[abbreviation] = definition;
3229
-		const regex = new RegExp("\\b(" + abbreviation + ")\\b", "ig");
3266
+		const regex = new RegExp("\\b(" + MDUtils.escapeRegex(abbreviation) + ")\\b", "ig");
3230 3267
 		this.#abbreviationRegexes[abbreviation] = regex;
3231 3268
 	}
3232 3269
 

+ 2
- 2
js/spreadsheet.js Datei anzeigen

@@ -918,7 +918,7 @@ class CellExpressionSet {
918 918
 		if (text === null || search === null || replace === null) {
919 919
 			throw new CellEvaluationException("SUBSTITUTE expects 3 string arguments");
920 920
 		}
921
-		const result = text.replaceAll(search, replace); // FIXME: Not case-insensitive
921
+		const result = text.replace(new RegExp(MDUtils.escapeRegex(search), 'gi'), replace);
922 922
 		return CellValue.fromValue(result);
923 923
 	}
924 924
 
@@ -2891,7 +2891,7 @@ class SpreadsheetCell {
2891 2891
  * post-process step on any tables in the document tree. Must be used with
2892 2892
  * `MDTableBlockReader`. Tables without at least one formula will not be altered.
2893 2893
  */
2894
-class SpreadsheetBlockReader extends MDBlockReader {
2894
+class MDSpreadsheetBlockReader extends MDBlockReader {
2895 2895
 	readBlock(state) {
2896 2896
 		return null;
2897 2897
 	}

+ 1
- 1
markdownjs.html Datei anzeigen

@@ -86,7 +86,7 @@
86 86
 		<script src="js/markdown.js"></script>
87 87
 		<script src="js/spreadsheet.js"></script>
88 88
 		<script>
89
-			var parser = new Markdown([ ...Markdown.allBlockReaders, new SpreadsheetBlockReader() ], Markdown.allInlineReaders);
89
+			var parser = new Markdown([ ...Markdown.allBlockReaders, new MDSpreadsheetBlockReader() ], Markdown.allInlineReaders);
90 90
 			function onDocumentLoad() {
91 91
 				document.getElementById('markdowninput').addEventListener('input', onMarkdownChange);
92 92
 				setTimeout(onMarkdownChange, 0);

+ 1
- 1
spreadsheet.md Datei anzeigen

@@ -1,6 +1,6 @@
1 1
 # Spreadsheet Expressions
2 2
 
3
-Spreadsheet expressions are an optional feature not enabled in the default parser configurations. To enable it, include `spreadsheet.js` and create a `Markdown` instance with a `SpreadsheetBlockReader`.
3
+Spreadsheet expressions are an optional feature not enabled in the default parser configurations. To enable it, include `spreadsheet.js` and create a `Markdown` instance with a `MDSpreadsheetBlockReader`.
4 4
 
5 5
 ## Expressions
6 6
 

+ 12
- 4
testjs.html Datei anzeigen

@@ -1212,10 +1212,14 @@
1212 1212
 					this.assertEqual(value.type, CellValue.TYPE_STRING);
1213 1213
 					this.assertEqual(value.formattedValue, 'some text');
1214 1214
 					this.assertEqual(value.value, 'some text');
1215
-					value = CellValue.fromCellString("'123");
1215
+					value = CellValue.fromCellString("'0123");
1216 1216
 					this.assertEqual(value.type, CellValue.TYPE_STRING);
1217
-					this.assertEqual(value.formattedValue, '123');
1218
-					this.assertEqual(value.value, '123');
1217
+					this.assertEqual(value.formattedValue, '0123');
1218
+					this.assertEqual(value.value, '0123');
1219
+					value = CellValue.fromCellString("'=123");
1220
+					this.assertEqual(value.type, CellValue.TYPE_STRING);
1221
+					this.assertEqual(value.formattedValue, '=123');
1222
+					this.assertEqual(value.value, '=123');
1219 1223
 				}
1220 1224
 
1221 1225
 				test_fromCellString_formula() {
@@ -1574,6 +1578,7 @@
1574 1578
 
1575 1579
 				test_func_average() {
1576 1580
 					this._test_simple_formula('=AVERAGE(4, 6, 2, 4)', 4);
1581
+					this._test_simple_formula('=AVERAGE(4, 6, 2, "foo", 4)', 4);
1577 1582
 				}
1578 1583
 
1579 1584
 				test_func_ceiling() {
@@ -1611,6 +1616,7 @@
1611 1616
 
1612 1617
 				test_func_log() {
1613 1618
 					this._test_simple_formula('=LOG(1000, 10)', 3);
1619
+					this._test_simple_formula('=LOG(64, 2)', 6);
1614 1620
 				}
1615 1621
 
1616 1622
 				test_func_lower() {
@@ -1664,6 +1670,8 @@
1664 1670
 
1665 1671
 				test_func_substitute() {
1666 1672
 					this._test_simple_formula('=SUBSTITUTE("cat sat on the mat", "at", "ot")', 'cot sot on the mot');
1673
+					this._test_simple_formula('=SUBSTITUTE("cAt saT on the mat", "at", "ot")', 'cot sot on the mot');
1674
+					this._test_simple_formula('=SUBSTITUTE("c.*t s.*t on the m.*t", ".*t", "ot")', 'cot sot on the mot');
1667 1675
 				}
1668 1676
 
1669 1677
 				test_func_sum() {
@@ -1694,7 +1702,7 @@
1694 1702
 				parser;
1695 1703
 
1696 1704
 				setUp() {
1697
-					this.parser = new Markdown([ ...Markdown.allBlockReaders, new SpreadsheetBlockReader() ], Markdown.allInlineReaders);
1705
+					this.parser = new Markdown([ ...Markdown.allBlockReaders, new MDSpreadsheetBlockReader() ], Markdown.allInlineReaders);
1698 1706
 				}
1699 1707
 
1700 1708
 				md(markdown) {

Laden…
Abbrechen
Speichern