浏览代码

Adding spreadsheet formula documentation

main
Rocketsoup 1年前
父节点
当前提交
6aca510bdd
共有 3 个文件被更改,包括 109 次插入2 次删除
  1. 12
    2
      js/markdown.js
  2. 2
    0
      markdown.md
  3. 95
    0
      spreadsheet.md

+ 12
- 2
js/markdown.js 查看文件

@@ -3224,6 +3224,7 @@ class MDState {
3224 3224
 			this.#parent.defineAbbreviation(abbreviation, definition);
3225 3225
 			return;
3226 3226
 		}
3227
+		// FIXME: Escape abbreviation
3227 3228
 		this.#abbreviations[abbreviation] = definition;
3228 3229
 		const regex = new RegExp("\\b(" + abbreviation + ")\\b", "ig");
3229 3230
 		this.#abbreviationRegexes[abbreviation] = regex;
@@ -3280,7 +3281,7 @@ class MDState {
3280 3281
 	 * is not provided it will be relative to `this.p`.
3281 3282
 	 * 
3282 3283
 	 * @param {number} minCount - minimum number of lines
3283
-	 * @param {number|null} p - line pointer
3284
+	 * @param {number|null} p - line pointer, or `null` to use `this.p`
3284 3285
 	 * @returns {boolean} whether at least the given number of lines is available
3285 3286
 	 */
3286 3287
 	hasLines(minCount, p=null) {
@@ -3332,8 +3333,14 @@ class MDState {
3332 3333
 		}
3333 3334
 		if (!this.hasLines(1)) return null;
3334 3335
 		for (const reader of this.blockReadersByPriority) {
3336
+			const startP = this.p;
3335 3337
 			const block = reader.readBlock(this);
3336
-			if (block) return block;
3338
+			if (block) {
3339
+				if (this.p == startP) {
3340
+					throw new Error(`${reader.constructor.name} returned an ${block.constructor.name} without incrementing MDState.p. This could lead to an infinite loop.`);
3341
+				}
3342
+				return block;
3343
+			}
3337 3344
 		}
3338 3345
 		const fallback = this.#readFallbackBlock();
3339 3346
 		return fallback;
@@ -3396,6 +3403,9 @@ class MDState {
3396 3403
 				if (token === null) continue;
3397 3404
 				endText();
3398 3405
 				tokens.push(token);
3406
+				if (token.original == null || token.original.length == 0) {
3407
+					throw new Error(`${reader.constructor.name} returned a token with an empty .original. This would cause an infinite loop.`);
3408
+				}
3399 3409
 				p += token.original.length - 1;
3400 3410
 				found = true;
3401 3411
 				break;

+ 2
- 0
markdown.md 查看文件

@@ -160,6 +160,8 @@ Columns can be right, center, or left aligned with colons in the divider line.
160 160
 | 1 | 2 | 3 |
161 161
 ```
162 162
 
163
+Tables can optionally support simple [spreadsheet expressions](spreadsheet.md) by adding the spreadsheet block reader when configuring a parser.
164
+
163 165
 ### Definition List
164 166
 
165 167
 Definition lists show terms with definitions below them. Useful for glossaries.

+ 95
- 0
spreadsheet.md 查看文件

@@ -0,0 +1,95 @@
1
+# Spreadsheet Expressions
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`.
4
+
5
+## Expressions
6
+
7
+As with many spreadsheet applications, a cell that begins with `=` is treated as a formula.
8
+
9
+## Cell References
10
+
11
+Values in other cells can be referenced with addresses. It consists of a column letter and an optional row number. When the row number is omitted the row is assumed to be the same as where the expression is located.
12
+
13
+Only body rows of a table are included in calculations and can be referenced. Header rows are entirely ignored.
14
+
15
+| Address | Description |
16
+| -- | -- |
17
+| `=A1` | Value from the leftmost column on the first row |
18
+| `=C2` | Value from the third column from the left on the second row |
19
+| `=A` | Value from the leftmost column on the same row as the expression |
20
+| `=AB1` | Value from the 28th column from the left. Letters proceed A to Z for columns 1 to 26, then AA, AB, AC... for 27, 28, 29.... Limited to 2 letters (676 columns), which is way more than could ever reasonably fit in a markdown table. |
21
+
22
+Rows or column references can be fixed for autofilled formulas (discussed below) by using a `$` before the column letters or row number.
23
+
24
+| Address | Description |
25
+| -- | -- |
26
+| `=$A1` | First column and row. If transposed, the row may change but the column will not. |
27
+| `=A$1` | First column and row. If transposed, the column may change but the row will not. |
28
+| `=$A$1` | First column and row even if transposed. |
29
+
30
+## Operators
31
+
32
+| Operator | Description |
33
+| -- | -- |
34
+| _x_ `+` _y_ | Addition |
35
+| _x_ `-` _y_ | Subtraction |
36
+| _x_ `*` _y_ | Multiplication |
37
+| _x_ `/` _y_ | Division |
38
+| `-`_x_ | Unary minus. Negates an argument. |
39
+| _x_ `&` _y_ | Concatenate. Produces a text value. |
40
+| _x_ `<` _y_ | Less than. Produces a Boolean value. |
41
+| _x_ `<=` _y_ | Less than or equal. Produces a Boolean value. |
42
+| _x_ `>` _y_ | Greater than. Produces a Boolean value. |
43
+| _x_ `>=` _y_ | Greater than or equal. Produces a Boolean value. |
44
+| _x_ `==` _y_ | Equal. Produces a Boolean value. |
45
+| _x_ `!=` _y_ | Not equal. Produces a Boolean value. |
46
+| `!`_x_ | Logical not. Produces a Boolean value. |
47
+
48
+## Parentheses
49
+
50
+Calculations can be grouped in parentheses to affect evaluation order.
51
+
52
+| Example | Evaluation order |
53
+| -- | -- |
54
+| `=3*4+1*2` | 1. `=12+1*2` (multiply 3 and 4)<br>2. `=12+2` (multiply 1 and 2)<br>3. `=14` (add 12 and 2) |
55
+| `=3*(4+1)*2` | 1. `=3*5*2` (add 4 and 1)<br>2. `=15*2` (multiply 3 and 5)<br>3. `=30` (multiply 15 and 2) |
56
+
57
+## Functions
58
+
59
+| Function | Description |
60
+| -- | -- |
61
+| `ABS(`_x_`)` | Absolute value |
62
+| `AND(`_x_`,` _y_`,` ... `,` _z_`)` | Boolean AND of 1 or more arguments |
63
+| `AVERAGE(`_x_`,` _y_`,` ... `,` _z_`)` | Statistical mean of 1 or more arguments. Non-numeric values are ignored. |
64
+| `CEILING(`_x_`)` | Rounds a value up |
65
+| `EXP(`_x_`)` | Raises _e_ to the power of _x_ |
66
+| `FLOOR(`_x_`)` | Rounds a value down |
67
+| `IF(`_test_`,` _trueval_`,` _falseval_`)` | Returns _trueval_ if _test_ evaluates to `TRUE`, otherwise returns _falseval_.
68
+| `IFS(`_test1_`,` _val1_`,` _test2_`,` _val2_`,` ... `,` _fallbackval_`)` | Performs multiple if tests. If _test1_ is `TRUE`, returns _val1_. If _test2_ is `TRUE`, returns _val2_. Etc. If no tests are `TRUE`, the final _fallbackval_ is returned. Takes an odd number of arguments of 3 or more. |
69
+| `LN(`_x_`)` | Natural logarithm |
70
+| `LOG(`_x_`,[` _base_`])` | Logarithm with a given _base_, or 10 if _base_ omitted |
71
+| `LOWER(`_x_`)` | Lowercase of a text value |
72
+| `MAX(`_x_`,` _y_`,` ... `,` _z_`)` | Maximum of 1 or more values |
73
+| `MIN(`_x_`,` _y_`,` ... `,` _z_`)` | Minimum of 1 or more values |
74
+| `MOD(`_x_`,` _y_`)` | Modulo division |
75
+| `NOT(`_x_`)` | Boolean NOT |
76
+| `OR(`_x_`,` _y_`,` ... `,` _z_`)` | Boolean OR of 1 or more arguments |
77
+| `POWER(`_x_`,` _y_`)` | Raises _x_ to the _y_ exponent |
78
+| `ROUND(`_x_`, [`_digits_`])` | Rounds a number to the nearest integer. If _digits_ is provided, rounds to that number of digits after the decimal place. Negative _digits_ will round to the nearest 10, 100, etc. |
79
+| `SQRT(`_x_`)` | Square root |
80
+| `SUBSTITUTE(`_text_`,` _pattern_`,` _replacement_`)` | Replaces all occurrences of _pattern_ in _text_ with _replacement_ |
81
+| `SUM(`_x_`,` _y_`,` ... `,` _z_`)` | Sum of 1 or more numeric arguments. Non-numeric values are ignored. |
82
+| `UPPER(`_x_`)` | Upercase of a text value |
83
+| `XOR(`_x_`,` _y_`,` ... `,` _z_`)` | Boolean XOR of 1 or more arguments |
84
+
85
+## Non-Formula Values
86
+
87
+Values that are not formulas with recognized values (e.g. numbers, dollar amounts) will be interpreted and reformatted.
88
+
89
+## Literal Text
90
+
91
+To force a value to behave like text, prefix it with a `'`. E.g. `'0001` will be treated as regular text, not a number, and will not be reformatted. A text value beginning with an equal sign can be prevented from being interpreted as a formula in the same way. `'=A`. The leading apostrophe will be stripped when rendering the table cell. For a literal leading apostrophe, prefix with two apostrophes. `''Kay`
92
+
93
+## Errors
94
+
95
+If an expression cannot be evaluated, the cell will show an error symbol, such as `#REF`, `#SYNTAX`, or `#ERROR`. A more detailed message is in the `title` attribute and can be seen in a tooltip by mousing over it.

正在加载...
取消
保存