jekyll-dice-tray 0.1.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +3 -3
- data/assets/jekyll-dice-tray/dice_tray.css +79 -0
- data/assets/jekyll-dice-tray/dice_tray.js +251 -21
- data/lib/jekyll/dice_tray/html_rewriter.rb +19 -0
- data/lib/jekyll/dice_tray/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d3d407c51d39049511c08f665a5b70a71d0eff1a0ec1522472948ce6350fd670
|
|
4
|
+
data.tar.gz: d2ae3f53ca8018c55bfff796cba3781684076bdeb8ba5bfdc9307c5f3e30c127
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e30263b41fc804cb82a2f6ba76a0697bd31e0e6d5ace3550a94fb6d41d20a25eec1c2db6e65048ea94b549b3137de4a079dc57c7c9f6209b6b841d5b20723ac4
|
|
7
|
+
data.tar.gz: 843991fe95b1a12b60550fc6bc462ea547b46e23b740eda47fe3a454dda4d0e34c4757d7ba8f2f3ae68989814c551b3011fbb571b7f022ab1dd404a4f28942fe
|
data/README.md
CHANGED
|
@@ -4,10 +4,10 @@ A Jekyll plugin gem that:
|
|
|
4
4
|
|
|
5
5
|
- Adds an overlay dice tray that accepts dice rolling input
|
|
6
6
|
- Recognizes dice expressions in rendered pages like `d4`, `1d6`, `1d20+1` and turns them into clickable links that roll in the tray
|
|
7
|
-
-
|
|
7
|
+
- Clicking a lookup-table die in the header row (e.g. `1d12`) rolls and shows the matching row
|
|
8
8
|
- Persists input history, result history, minimize status
|
|
9
|
-
|
|
10
|
-
-
|
|
9
|
+
|
|
10
|
+
https://github.com/user-attachments/assets/6ef8d788-a1ee-49d4-ab26-f63899bb4a10
|
|
11
11
|
|
|
12
12
|
## Install
|
|
13
13
|
|
|
@@ -114,12 +114,67 @@
|
|
|
114
114
|
color: rgba(0, 0, 0, 0.45);
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
+
#jekyll-dice-tray .jdt-success {
|
|
118
|
+
color: #1a7f37;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
#jekyll-dice-tray .jdt-failure {
|
|
122
|
+
color: #cf222e;
|
|
123
|
+
}
|
|
124
|
+
|
|
117
125
|
#jekyll-dice-tray .jdt-entry .jdt-details {
|
|
118
126
|
margin-top: 4px;
|
|
119
127
|
color: rgba(0, 0, 0, 0.55);
|
|
120
128
|
font-size: 12px;
|
|
121
129
|
}
|
|
122
130
|
|
|
131
|
+
#jekyll-dice-tray .jdt-table-context {
|
|
132
|
+
margin-top: 6px;
|
|
133
|
+
padding-top: 6px;
|
|
134
|
+
border-top: 1px dashed rgba(0, 0, 0, 0.08);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
#jekyll-dice-tray .jdt-table-row {
|
|
138
|
+
font-size: 12px;
|
|
139
|
+
line-height: 1.4;
|
|
140
|
+
color: rgba(0, 0, 0, 0.72);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
#jekyll-dice-tray .jdt-table-row + .jdt-table-row {
|
|
144
|
+
margin-top: 2px;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
#jekyll-dice-tray .jdt-table-header {
|
|
148
|
+
font-weight: 600;
|
|
149
|
+
color: rgba(0, 0, 0, 0.55);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
#jekyll-dice-tray .jdt-table-sep {
|
|
153
|
+
color: rgba(0, 0, 0, 0.45);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
#jekyll-dice-tray .jdt-table-value {
|
|
157
|
+
font-family: inherit;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
#jekyll-dice-tray .jdt-table-value a,
|
|
161
|
+
#jekyll-dice-tray .jdt-table-header a {
|
|
162
|
+
text-decoration: underline;
|
|
163
|
+
text-underline-offset: 2px;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
#jekyll-dice-tray .jdt-table-value a.dice-tray-roll {
|
|
167
|
+
color: #ff0000;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
#jekyll-dice-tray .jdt-table-value a:visited {
|
|
171
|
+
color: inherit;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
#jekyll-dice-tray .jdt-table-value a.dice-tray-roll:visited {
|
|
175
|
+
color: #ff0000;
|
|
176
|
+
}
|
|
177
|
+
|
|
123
178
|
a.dice-tray-roll {
|
|
124
179
|
text-decoration: underline;
|
|
125
180
|
text-underline-offset: 2px;
|
|
@@ -168,6 +223,22 @@ a.dice-tray-roll:visited {
|
|
|
168
223
|
color: rgba(255, 255, 255, 0.6);
|
|
169
224
|
}
|
|
170
225
|
|
|
226
|
+
#jekyll-dice-tray .jdt-table-context {
|
|
227
|
+
border-top-color: rgba(255, 255, 255, 0.1);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
#jekyll-dice-tray .jdt-table-row {
|
|
231
|
+
color: rgba(255, 255, 255, 0.78);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
#jekyll-dice-tray .jdt-table-header {
|
|
235
|
+
color: rgba(255, 255, 255, 0.62);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
#jekyll-dice-tray .jdt-table-sep {
|
|
239
|
+
color: rgba(255, 255, 255, 0.48);
|
|
240
|
+
}
|
|
241
|
+
|
|
171
242
|
#jekyll-dice-tray .jdt-result .jdt-rolls {
|
|
172
243
|
color: rgba(255, 255, 255, 0.65);
|
|
173
244
|
}
|
|
@@ -179,5 +250,13 @@ a.dice-tray-roll:visited {
|
|
|
179
250
|
#jekyll-dice-tray .jdt-result .jdt-vs-sep {
|
|
180
251
|
color: rgba(255, 255, 255, 0.48);
|
|
181
252
|
}
|
|
253
|
+
|
|
254
|
+
#jekyll-dice-tray .jdt-success {
|
|
255
|
+
color: #3fb950;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
#jekyll-dice-tray .jdt-failure {
|
|
259
|
+
color: #f85149;
|
|
260
|
+
}
|
|
182
261
|
}
|
|
183
262
|
|
|
@@ -93,6 +93,28 @@
|
|
|
93
93
|
};
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
+
var chance = compact.match(/^(\d{1,3})-in-(\d{1,4})$/i);
|
|
97
|
+
if (chance) {
|
|
98
|
+
var successOn = parseInt(chance[1], 10);
|
|
99
|
+
var sides = parseInt(chance[2], 10);
|
|
100
|
+
|
|
101
|
+
if (!Number.isFinite(successOn) || !Number.isFinite(sides)) {
|
|
102
|
+
return { kind: "invalid", raw: s };
|
|
103
|
+
}
|
|
104
|
+
if (successOn < 1) successOn = 1;
|
|
105
|
+
if (successOn > 100) successOn = 100;
|
|
106
|
+
if (sides < 2) sides = 2;
|
|
107
|
+
if (sides > 10000) sides = 10000;
|
|
108
|
+
if (successOn > sides) return { kind: "invalid", raw: s };
|
|
109
|
+
|
|
110
|
+
return {
|
|
111
|
+
kind: "chance",
|
|
112
|
+
success_on: successOn,
|
|
113
|
+
sides: sides,
|
|
114
|
+
normalized: String(successOn) + "-in-" + String(sides),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
96
118
|
var m = compact.match(/^(\d{0,3})d(\d{1,4})([+-]\d{1,5})?$/i);
|
|
97
119
|
if (!m) return { kind: "invalid", raw: s };
|
|
98
120
|
|
|
@@ -126,6 +148,136 @@
|
|
|
126
148
|
}
|
|
127
149
|
|
|
128
150
|
function mountTray(root) {
|
|
151
|
+
function normalizeCellText(node) {
|
|
152
|
+
return String(node && node.textContent ? node.textContent : "")
|
|
153
|
+
.replace(/\s+/g, " ")
|
|
154
|
+
.trim();
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function cellInnerHtml(node) {
|
|
158
|
+
return node && node.innerHTML ? node.innerHTML.trim() : "";
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function findTableHeaderRow(table) {
|
|
162
|
+
if (!table) return null;
|
|
163
|
+
var thead = table.querySelector("thead");
|
|
164
|
+
if (thead) {
|
|
165
|
+
var theadRows = thead.querySelectorAll("tr");
|
|
166
|
+
if (theadRows.length) return theadRows[theadRows.length - 1];
|
|
167
|
+
}
|
|
168
|
+
var rows = table.querySelectorAll("tr");
|
|
169
|
+
for (var i = 0; i < rows.length; i++) {
|
|
170
|
+
if (rows[i].querySelector("th")) return rows[i];
|
|
171
|
+
}
|
|
172
|
+
return table.querySelector("tr");
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function parseFirstColumnEntry(text) {
|
|
176
|
+
if (!text) return null;
|
|
177
|
+
var normalized = text.replace(/[\u2013\u2014]/g, "-");
|
|
178
|
+
if (/^\d+$/.test(normalized)) {
|
|
179
|
+
return { kind: "exact", value: parseInt(normalized, 10) };
|
|
180
|
+
}
|
|
181
|
+
var rangeMatch = normalized.match(/^(\d+)\s*-\s*(\d+)$/);
|
|
182
|
+
if (rangeMatch) {
|
|
183
|
+
var min = parseInt(rangeMatch[1], 10);
|
|
184
|
+
var max = parseInt(rangeMatch[2], 10);
|
|
185
|
+
if (min <= max) return { kind: "range", min: min, max: max };
|
|
186
|
+
}
|
|
187
|
+
return null;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function firstColumnEntry(row) {
|
|
191
|
+
if (!row) return null;
|
|
192
|
+
var cell = row.querySelector("td, th");
|
|
193
|
+
if (!cell) return null;
|
|
194
|
+
return parseFirstColumnEntry(normalizeCellText(cell));
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function isLookupTable(table, headerRow) {
|
|
198
|
+
if (!table || !headerRow) return false;
|
|
199
|
+
var rows = table.querySelectorAll("tr");
|
|
200
|
+
var matches = 0;
|
|
201
|
+
for (var i = 0; i < rows.length; i++) {
|
|
202
|
+
if (rows[i] === headerRow) continue;
|
|
203
|
+
if (firstColumnEntry(rows[i]) !== null) matches++;
|
|
204
|
+
}
|
|
205
|
+
return matches >= 2;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function findLookupRow(table, headerRow, rollTotal) {
|
|
209
|
+
var rows = table.querySelectorAll("tr");
|
|
210
|
+
var rangeRow = null;
|
|
211
|
+
for (var i = 0; i < rows.length; i++) {
|
|
212
|
+
var row = rows[i];
|
|
213
|
+
if (row === headerRow) continue;
|
|
214
|
+
var entry = firstColumnEntry(row);
|
|
215
|
+
if (!entry) continue;
|
|
216
|
+
if (entry.kind === "exact" && entry.value === rollTotal) return row;
|
|
217
|
+
if (entry.kind === "range" && !rangeRow && rollTotal >= entry.min && rollTotal <= entry.max) {
|
|
218
|
+
rangeRow = row;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
return rangeRow;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function getLookupTableContext(anchor, rollTotal) {
|
|
225
|
+
if (!anchor || !anchor.closest || rollTotal == null) return null;
|
|
226
|
+
var cell = anchor.closest("td, th");
|
|
227
|
+
if (!cell) return null;
|
|
228
|
+
var clickRow = cell.closest("tr");
|
|
229
|
+
if (!clickRow) return null;
|
|
230
|
+
var table = clickRow.closest("table");
|
|
231
|
+
if (!table) return null;
|
|
232
|
+
|
|
233
|
+
var headerRow = findTableHeaderRow(table);
|
|
234
|
+
if (!headerRow || !headerRow.contains(cell)) return null;
|
|
235
|
+
if (!isLookupTable(table, headerRow)) return null;
|
|
236
|
+
|
|
237
|
+
var matchedRow = findLookupRow(table, headerRow, rollTotal);
|
|
238
|
+
if (!matchedRow) return null;
|
|
239
|
+
|
|
240
|
+
var headerCells = Array.prototype.slice.call(headerRow.querySelectorAll("td, th"));
|
|
241
|
+
var valueCells = Array.prototype.slice.call(matchedRow.querySelectorAll("td, th"));
|
|
242
|
+
var columns = [];
|
|
243
|
+
|
|
244
|
+
for (var c = 0; c < valueCells.length; c++) {
|
|
245
|
+
var headerCell = headerCells[c];
|
|
246
|
+
var valueCell = valueCells[c];
|
|
247
|
+
columns.push({
|
|
248
|
+
header: headerCell ? normalizeCellText(headerCell) : "",
|
|
249
|
+
header_html: headerCell ? cellInnerHtml(headerCell) : "",
|
|
250
|
+
value: normalizeCellText(valueCell),
|
|
251
|
+
value_html: cellInnerHtml(valueCell),
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
return columns.length ? { columns: columns } : null;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
function appendTableContext(entry, tableContext) {
|
|
259
|
+
if (!tableContext || !tableContext.columns || !tableContext.columns.length) return;
|
|
260
|
+
|
|
261
|
+
var ctx = el("div", { class: "jdt-table-context" });
|
|
262
|
+
tableContext.columns.forEach(function (col) {
|
|
263
|
+
if (!col || (!col.value && !col.value_html)) return;
|
|
264
|
+
var line = el("div", { class: "jdt-table-row" });
|
|
265
|
+
if (col.header || col.header_html) {
|
|
266
|
+
var headerSpan = el("span", { class: "jdt-table-header" });
|
|
267
|
+
if (col.header_html) headerSpan.innerHTML = col.header_html;
|
|
268
|
+
else headerSpan.textContent = col.header;
|
|
269
|
+
line.appendChild(headerSpan);
|
|
270
|
+
line.appendChild(el("span", { class: "jdt-table-sep" }, ": "));
|
|
271
|
+
}
|
|
272
|
+
var valueSpan = el("span", { class: "jdt-table-value" });
|
|
273
|
+
if (col.value_html) valueSpan.innerHTML = col.value_html;
|
|
274
|
+
else valueSpan.textContent = col.value || "";
|
|
275
|
+
line.appendChild(valueSpan);
|
|
276
|
+
ctx.appendChild(line);
|
|
277
|
+
});
|
|
278
|
+
if (ctx.childNodes.length) entry.appendChild(ctx);
|
|
279
|
+
}
|
|
280
|
+
|
|
129
281
|
var toggle = qs(".jdt-toggle", root);
|
|
130
282
|
var body = qs(".jdt-body", root);
|
|
131
283
|
var input = qs(".jdt-input", root);
|
|
@@ -237,10 +389,31 @@
|
|
|
237
389
|
item.right_label || "",
|
|
238
390
|
item.mod || 0,
|
|
239
391
|
item.time || "",
|
|
240
|
-
item.mode || "high"
|
|
392
|
+
item.mode || "high",
|
|
393
|
+
item.table_context || null,
|
|
394
|
+
true
|
|
395
|
+
);
|
|
396
|
+
} else if (item.kind === "chance") {
|
|
397
|
+
addChanceEntry(
|
|
398
|
+
item.expr || "",
|
|
399
|
+
item.roll,
|
|
400
|
+
item.success_on,
|
|
401
|
+
item.sides,
|
|
402
|
+
!!item.success,
|
|
403
|
+
item.time || "",
|
|
404
|
+
item.table_context || null,
|
|
405
|
+
true
|
|
241
406
|
);
|
|
242
407
|
} else if (item.kind === "roll") {
|
|
243
|
-
addRollEntry(
|
|
408
|
+
addRollEntry(
|
|
409
|
+
item.expr || "",
|
|
410
|
+
item.total,
|
|
411
|
+
item.rolls || [],
|
|
412
|
+
item.mod || 0,
|
|
413
|
+
item.time || "",
|
|
414
|
+
item.table_context || null,
|
|
415
|
+
true
|
|
416
|
+
);
|
|
244
417
|
}
|
|
245
418
|
});
|
|
246
419
|
log.scrollTop = log.scrollHeight;
|
|
@@ -264,10 +437,41 @@
|
|
|
264
437
|
pushHistory({ kind: "system", title: title, body: body, time: timeStr });
|
|
265
438
|
}
|
|
266
439
|
|
|
267
|
-
function
|
|
440
|
+
function addChanceEntry(expr, roll, successOn, sides, success, timeStr, tableContext, skipHistory) {
|
|
441
|
+
var entry = el("div", { class: "jdt-entry", title: expr });
|
|
442
|
+
var colorClass = success ? "jdt-success" : "jdt-failure";
|
|
443
|
+
var result = el("div", { class: "jdt-result" });
|
|
444
|
+
|
|
445
|
+
result.appendChild(el("strong", { class: colorClass }, String(roll)));
|
|
446
|
+
|
|
447
|
+
var bracket = el("span", { class: "jdt-rolls" }, " [");
|
|
448
|
+
bracket.appendChild(el("span", { class: colorClass }, String(roll)));
|
|
449
|
+
bracket.appendChild(el("span", null, "]"));
|
|
450
|
+
result.appendChild(bracket);
|
|
451
|
+
|
|
452
|
+
entry.appendChild(result);
|
|
453
|
+
appendTableContext(entry, tableContext);
|
|
454
|
+
|
|
455
|
+
log.appendChild(entry);
|
|
456
|
+
log.scrollTop = log.scrollHeight;
|
|
457
|
+
|
|
458
|
+
if (skipHistory) return;
|
|
459
|
+
|
|
460
|
+
var item = {
|
|
461
|
+
kind: "chance",
|
|
462
|
+
expr: expr,
|
|
463
|
+
roll: roll,
|
|
464
|
+
success_on: successOn,
|
|
465
|
+
sides: sides,
|
|
466
|
+
success: success,
|
|
467
|
+
time: timeStr,
|
|
468
|
+
};
|
|
469
|
+
if (tableContext) item.table_context = tableContext;
|
|
470
|
+
pushHistory(item);
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
function addRollEntry(expr, total, rolls, mod, timeStr, tableContext, skipHistory) {
|
|
268
474
|
var entry = el("div", { class: "jdt-entry", title: expr });
|
|
269
|
-
// expression
|
|
270
|
-
//entry.appendChild(el("div", { class: "jdt-expr" }, expr));
|
|
271
475
|
|
|
272
476
|
var result = el("div", { class: "jdt-result" });
|
|
273
477
|
result.appendChild(el("strong", null, String(total)));
|
|
@@ -277,18 +481,20 @@
|
|
|
277
481
|
}
|
|
278
482
|
result.appendChild(el("span", { class: "jdt-rolls" }, " " + rollsText));
|
|
279
483
|
|
|
280
|
-
// result
|
|
281
484
|
entry.appendChild(result);
|
|
485
|
+
appendTableContext(entry, tableContext);
|
|
282
486
|
|
|
283
|
-
|
|
284
|
-
//entry.appendChild(el("div", { class: "jdt-details" }, timeStr));
|
|
285
|
-
log.appendChild(entry); // newest at bottom
|
|
487
|
+
log.appendChild(entry);
|
|
286
488
|
log.scrollTop = log.scrollHeight;
|
|
287
489
|
|
|
288
|
-
|
|
490
|
+
if (skipHistory) return;
|
|
491
|
+
|
|
492
|
+
var item = { kind: "roll", expr: expr, total: total, rolls: rolls, mod: mod, time: timeStr };
|
|
493
|
+
if (tableContext) item.table_context = tableContext;
|
|
494
|
+
pushHistory(item);
|
|
289
495
|
}
|
|
290
496
|
|
|
291
|
-
function addBestOf2Entry(expr, chosenTotal, leftRolls, rightRolls, leftIsWinner, leftLabel, rightLabel, mod, timeStr, mode) {
|
|
497
|
+
function addBestOf2Entry(expr, chosenTotal, leftRolls, rightRolls, leftIsWinner, leftLabel, rightLabel, mod, timeStr, mode, tableContext, skipHistory) {
|
|
292
498
|
var entry = el("div", { class: "jdt-entry", title: expr });
|
|
293
499
|
entry.appendChild(el("div", { class: "jdt-expr" }, expr));
|
|
294
500
|
|
|
@@ -318,12 +524,15 @@
|
|
|
318
524
|
}
|
|
319
525
|
|
|
320
526
|
entry.appendChild(result);
|
|
527
|
+
appendTableContext(entry, tableContext);
|
|
321
528
|
entry.appendChild(el("div", { class: "jdt-details" }, timeStr));
|
|
322
529
|
|
|
323
530
|
log.appendChild(entry);
|
|
324
531
|
log.scrollTop = log.scrollHeight;
|
|
325
532
|
|
|
326
|
-
|
|
533
|
+
if (skipHistory) return;
|
|
534
|
+
|
|
535
|
+
var item = {
|
|
327
536
|
kind: "bestof2",
|
|
328
537
|
expr: expr,
|
|
329
538
|
chosen_total: chosenTotal,
|
|
@@ -335,24 +544,44 @@
|
|
|
335
544
|
mode: mode,
|
|
336
545
|
mod: mod,
|
|
337
546
|
time: timeStr,
|
|
338
|
-
}
|
|
547
|
+
};
|
|
548
|
+
if (tableContext) item.table_context = tableContext;
|
|
549
|
+
pushHistory(item);
|
|
339
550
|
}
|
|
340
551
|
|
|
341
552
|
function showHelp() {
|
|
342
553
|
addSystemEntry(
|
|
343
|
-
"Usage: 1d6, d4, 2d8+1",
|
|
344
|
-
"Click linked dice like 1d20+5 or bracket modifiers like [+1] (rolls d20+1). Commands: /help, /clear",
|
|
554
|
+
"Usage: 1d6, d4, 2d8+1, 2-in-6",
|
|
555
|
+
"Click linked dice like 1d20+5, chance like 2-in-6 (roll d6, 1-2 succeed), or bracket modifiers like [+1] (rolls d20+1). Clicking a table die (e.g. 1d12) shows the matching row (first column: single number or range like 3-12). Commands: /help, /clear",
|
|
345
556
|
nowTime()
|
|
346
557
|
);
|
|
347
558
|
}
|
|
348
559
|
|
|
349
|
-
function doRoll(raw) {
|
|
560
|
+
function doRoll(raw, meta) {
|
|
561
|
+
meta = meta || {};
|
|
562
|
+
var anchor = meta.anchor || null;
|
|
350
563
|
var p = parseExpr(raw);
|
|
351
564
|
if (p.kind === "empty") return;
|
|
352
565
|
if (p.kind === "help") return showHelp();
|
|
353
566
|
if (p.kind === "clear") return clearStorageAndUi();
|
|
354
|
-
if (p.kind !== "roll" && p.kind !== "bestof2") {
|
|
355
|
-
addSystemEntry("Unrecognized roll: " + p.raw, "Try: 1d6, d4, 2d8+1 or /help", nowTime());
|
|
567
|
+
if (p.kind !== "roll" && p.kind !== "bestof2" && p.kind !== "chance") {
|
|
568
|
+
addSystemEntry("Unrecognized roll: " + p.raw, "Try: 1d6, d4, 2-in-6, 2d8+1 or /help", nowTime());
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
if (p.kind === "chance") {
|
|
573
|
+
var chanceRoll = rollDice(1, p.sides);
|
|
574
|
+
var roll = chanceRoll.rolls[0];
|
|
575
|
+
var success = roll <= p.success_on;
|
|
576
|
+
addChanceEntry(
|
|
577
|
+
p.normalized,
|
|
578
|
+
roll,
|
|
579
|
+
p.success_on,
|
|
580
|
+
p.sides,
|
|
581
|
+
success,
|
|
582
|
+
nowTime(),
|
|
583
|
+
getLookupTableContext(anchor, roll)
|
|
584
|
+
);
|
|
356
585
|
return;
|
|
357
586
|
}
|
|
358
587
|
|
|
@@ -377,14 +606,15 @@
|
|
|
377
606
|
rightLabel,
|
|
378
607
|
p.mod,
|
|
379
608
|
nowTime(),
|
|
380
|
-
mode
|
|
609
|
+
mode,
|
|
610
|
+
getLookupTableContext(anchor, chosenTotal)
|
|
381
611
|
);
|
|
382
612
|
return;
|
|
383
613
|
}
|
|
384
614
|
|
|
385
615
|
var r = rollDice(p.count, p.sides);
|
|
386
616
|
var total = r.total + p.mod;
|
|
387
|
-
addRollEntry(p.normalized, total, r.rolls, p.mod, nowTime());
|
|
617
|
+
addRollEntry(p.normalized, total, r.rolls, p.mod, nowTime(), getLookupTableContext(anchor, total));
|
|
388
618
|
}
|
|
389
619
|
|
|
390
620
|
toggle.addEventListener("click", function () {
|
|
@@ -446,7 +676,7 @@
|
|
|
446
676
|
if (!expr) return;
|
|
447
677
|
e.preventDefault();
|
|
448
678
|
setExpanded(true);
|
|
449
|
-
doRoll(expr);
|
|
679
|
+
doRoll(expr, { anchor: a });
|
|
450
680
|
});
|
|
451
681
|
|
|
452
682
|
// Public API
|
|
@@ -14,6 +14,14 @@ module Jekyll
|
|
|
14
14
|
(?![A-Za-z0-9_])
|
|
15
15
|
/x
|
|
16
16
|
|
|
17
|
+
CHANCE_RE = /
|
|
18
|
+
(?<![A-Za-z0-9_])
|
|
19
|
+
\d{1,3}
|
|
20
|
+
\s*-\s*in\s*-\s*
|
|
21
|
+
\d{1,4}
|
|
22
|
+
(?![A-Za-z0-9_])
|
|
23
|
+
/ix
|
|
24
|
+
|
|
17
25
|
THAC0_WORD_RE = /THAC0/i
|
|
18
26
|
|
|
19
27
|
BRACKET_INNER_RE = /
|
|
@@ -105,6 +113,17 @@ module Jekyll
|
|
|
105
113
|
}
|
|
106
114
|
end
|
|
107
115
|
|
|
116
|
+
text.to_enum(:scan, CHANCE_RE).each do
|
|
117
|
+
m = Regexp.last_match
|
|
118
|
+
matches << {
|
|
119
|
+
start: m.begin(0),
|
|
120
|
+
end: m.end(0),
|
|
121
|
+
expr: m[0].gsub(/\s+/, ""),
|
|
122
|
+
label_start: m.begin(0),
|
|
123
|
+
label_end: m.end(0),
|
|
124
|
+
}
|
|
125
|
+
end
|
|
126
|
+
|
|
108
127
|
text.to_enum(:scan, THAC0_INLINE_RE).each do
|
|
109
128
|
matches << bracket_mod_hit(text, Regexp.last_match)
|
|
110
129
|
end
|