jekyll-dice-tray 0.3.1 → 0.5.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 +1 -1
- data/assets/jekyll-dice-tray/dice_tray.css +4 -2
- data/assets/jekyll-dice-tray/dice_tray.js +274 -65
- data/lib/jekyll/dice_tray/html_rewriter.rb +1 -1
- 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: 1e3b5e6ffc89df4600f4c4a25d765e3bc5efcd96d3671817cfc19c0edf540e7f
|
|
4
|
+
data.tar.gz: eeb98f0a9a72e5caac9dfa0608f402cfefb90c914c0ecacf2dc170d6484decd8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 76359d77b57187df74358db7c49116928b201ce19ffa3130e3af0584087cce008c220baacbea6185f2e5a39686c27b4c78c6010702a9d2576f258158a9df36b7
|
|
7
|
+
data.tar.gz: 0b6e4439a8265f518ee925cb7f497fe5c3daa6c2dfd180d67ba8e7dcbefab68495f25bb50805b4d594d2cf777b3f32ed4a9172c5564c512de072db5d80db1ccd
|
data/README.md
CHANGED
|
@@ -4,7 +4,7 @@ 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
|
-
- Clicking a lookup-table die
|
|
7
|
+
- Clicking a lookup-table die (any `dN`) rolls and shows the matching entry — supports any number of side-by-side key/value column groups, ranges like `3–12`, and tables with or without headers. One die in the header searches the whole table; multiple dice each search their own column group
|
|
8
8
|
- Persists input history, result history, minimize status
|
|
9
9
|
|
|
10
10
|
https://github.com/user-attachments/assets/6ef8d788-a1ee-49d4-ab26-f63899bb4a10
|
|
@@ -163,7 +163,8 @@
|
|
|
163
163
|
text-underline-offset: 2px;
|
|
164
164
|
}
|
|
165
165
|
|
|
166
|
-
#jekyll-dice-tray .jdt-table-value a.dice-tray-roll
|
|
166
|
+
#jekyll-dice-tray .jdt-table-value a.dice-tray-roll,
|
|
167
|
+
#jekyll-dice-tray .jdt-table-header a.dice-tray-roll {
|
|
167
168
|
color: #ff0000;
|
|
168
169
|
}
|
|
169
170
|
|
|
@@ -171,7 +172,8 @@
|
|
|
171
172
|
color: inherit;
|
|
172
173
|
}
|
|
173
174
|
|
|
174
|
-
#jekyll-dice-tray .jdt-table-value a.dice-tray-roll:visited
|
|
175
|
+
#jekyll-dice-tray .jdt-table-value a.dice-tray-roll:visited,
|
|
176
|
+
#jekyll-dice-tray .jdt-table-header a.dice-tray-roll:visited {
|
|
175
177
|
color: #ff0000;
|
|
176
178
|
}
|
|
177
179
|
|
|
@@ -46,8 +46,9 @@
|
|
|
46
46
|
function parseExpr(input) {
|
|
47
47
|
var s = String(input || "").trim();
|
|
48
48
|
if (!s) return { kind: "empty" };
|
|
49
|
-
if (s === "/help") return { kind: "help" };
|
|
50
|
-
if (s === "/clear") return { kind: "clear" };
|
|
49
|
+
if (s === "/help" || s === "/h") return { kind: "help" };
|
|
50
|
+
if (s === "/clear" || s === "/c") return { kind: "clear" };
|
|
51
|
+
if (s === "/version" || s === "/v") return { kind: "version" };
|
|
51
52
|
|
|
52
53
|
// Allow whitespace variations like "d20 + 2"
|
|
53
54
|
var compact = s.replace(/\s+/g, "");
|
|
@@ -158,21 +159,7 @@
|
|
|
158
159
|
return node && node.innerHTML ? node.innerHTML.trim() : "";
|
|
159
160
|
}
|
|
160
161
|
|
|
161
|
-
function
|
|
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) {
|
|
162
|
+
function parseKeyEntry(text) {
|
|
176
163
|
if (!text) return null;
|
|
177
164
|
var normalized = text.replace(/[\u2013\u2014]/g, "-");
|
|
178
165
|
if (/^\d+$/.test(normalized)) {
|
|
@@ -187,72 +174,270 @@
|
|
|
187
174
|
return null;
|
|
188
175
|
}
|
|
189
176
|
|
|
190
|
-
function
|
|
191
|
-
if (!row) return
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
177
|
+
function rowCells(row) {
|
|
178
|
+
if (!row) return [];
|
|
179
|
+
return Array.prototype.slice.call(row.querySelectorAll("td, th"));
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function cellColumnIndex(row, cell) {
|
|
183
|
+
var cells = rowCells(row);
|
|
184
|
+
for (var i = 0; i < cells.length; i++) {
|
|
185
|
+
if (cells[i] === cell) return i;
|
|
186
|
+
}
|
|
187
|
+
return -1;
|
|
195
188
|
}
|
|
196
189
|
|
|
197
|
-
function
|
|
198
|
-
if (!
|
|
190
|
+
function rowLooksLikeHeader(row) {
|
|
191
|
+
if (!row) return false;
|
|
192
|
+
if (row.querySelector("th")) return true;
|
|
193
|
+
var cells = rowCells(row);
|
|
194
|
+
if (!cells.length) return false;
|
|
195
|
+
var keyCount = 0;
|
|
196
|
+
for (var i = 0; i < cells.length; i++) {
|
|
197
|
+
if (parseKeyEntry(normalizeCellText(cells[i]))) keyCount++;
|
|
198
|
+
}
|
|
199
|
+
// Data rows start with roll keys; header rows are labels / dice expr.
|
|
200
|
+
return keyCount === 0;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function findTableHeaderRow(table) {
|
|
204
|
+
if (!table) return null;
|
|
205
|
+
var thead = table.querySelector("thead");
|
|
206
|
+
if (thead) {
|
|
207
|
+
var theadRows = thead.querySelectorAll("tr");
|
|
208
|
+
if (theadRows.length) {
|
|
209
|
+
var head = theadRows[theadRows.length - 1];
|
|
210
|
+
// Markdown always wraps the first row in <thead>; skip if it's really data.
|
|
211
|
+
if (!parseKeyEntry(normalizeCellText(rowCells(head)[0] || null))) return head;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
199
214
|
var rows = table.querySelectorAll("tr");
|
|
200
|
-
var matches = 0;
|
|
201
215
|
for (var i = 0; i < rows.length; i++) {
|
|
202
|
-
if (rows[i]
|
|
203
|
-
if (firstColumnEntry(rows[i]) !== null) matches++;
|
|
216
|
+
if (rows[i].querySelector("th") && rowLooksLikeHeader(rows[i])) return rows[i];
|
|
204
217
|
}
|
|
205
|
-
|
|
218
|
+
if (rows.length && rowLooksLikeHeader(rows[0])) return rows[0];
|
|
219
|
+
return null;
|
|
206
220
|
}
|
|
207
221
|
|
|
208
|
-
function
|
|
222
|
+
function eachDataRow(table, headerRow, fn) {
|
|
209
223
|
var rows = table.querySelectorAll("tr");
|
|
210
|
-
var rangeRow = null;
|
|
211
224
|
for (var i = 0; i < rows.length; i++) {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
225
|
+
if (rows[i] === headerRow) continue;
|
|
226
|
+
fn(rows[i]);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Infer key columns from data: any column that holds a roll number/range in enough rows.
|
|
231
|
+
// Supports 1..N side-by-side (key, value...) groups for any die size.
|
|
232
|
+
function inferKeyColumns(table, headerRow) {
|
|
233
|
+
var counts = [];
|
|
234
|
+
var rowCount = 0;
|
|
235
|
+
eachDataRow(table, headerRow, function (row) {
|
|
236
|
+
var cells = rowCells(row);
|
|
237
|
+
rowCount++;
|
|
238
|
+
for (var i = 0; i < cells.length; i++) {
|
|
239
|
+
if (!counts[i]) counts[i] = 0;
|
|
240
|
+
if (parseKeyEntry(normalizeCellText(cells[i]))) counts[i]++;
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
if (rowCount < 1) return [];
|
|
244
|
+
var minHits = Math.min(2, rowCount);
|
|
245
|
+
var keys = [];
|
|
246
|
+
for (var c = 0; c < counts.length; c++) {
|
|
247
|
+
if ((counts[c] || 0) >= minHits) keys.push(c);
|
|
248
|
+
}
|
|
249
|
+
return keys;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function buildColumnGroups(keyColumns, columnCount) {
|
|
253
|
+
var groups = [];
|
|
254
|
+
for (var k = 0; k < keyColumns.length; k++) {
|
|
255
|
+
var keyIndex = keyColumns[k];
|
|
256
|
+
var nextKey = k + 1 < keyColumns.length ? keyColumns[k + 1] : columnCount;
|
|
257
|
+
var valueIndices = [];
|
|
258
|
+
for (var v = keyIndex + 1; v < nextKey; v++) valueIndices.push(v);
|
|
259
|
+
groups.push({ keyIndex: keyIndex, valueIndices: valueIndices });
|
|
260
|
+
}
|
|
261
|
+
return groups;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function tableColumnCount(table, headerRow) {
|
|
265
|
+
var max = headerRow ? rowCells(headerRow).length : 0;
|
|
266
|
+
eachDataRow(table, headerRow, function (row) {
|
|
267
|
+
max = Math.max(max, rowCells(row).length);
|
|
268
|
+
});
|
|
269
|
+
return max;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function collectRowEntriesForGroups(row, groups, allowedKeyIndices) {
|
|
273
|
+
var cells = rowCells(row);
|
|
274
|
+
var entries = [];
|
|
275
|
+
var allowAll = !allowedKeyIndices || !allowedKeyIndices.length;
|
|
276
|
+
for (var g = 0; g < groups.length; g++) {
|
|
277
|
+
var group = groups[g];
|
|
278
|
+
if (!allowAll && allowedKeyIndices.indexOf(group.keyIndex) === -1) continue;
|
|
279
|
+
var keyCell = cells[group.keyIndex];
|
|
280
|
+
if (!keyCell) continue;
|
|
281
|
+
var key = parseKeyEntry(normalizeCellText(keyCell));
|
|
282
|
+
if (!key) continue;
|
|
283
|
+
var valueCells = [];
|
|
284
|
+
var valueIndices = [];
|
|
285
|
+
for (var vi = 0; vi < group.valueIndices.length; vi++) {
|
|
286
|
+
var idx = group.valueIndices[vi];
|
|
287
|
+
if (!cells[idx]) continue;
|
|
288
|
+
valueCells.push(cells[idx]);
|
|
289
|
+
valueIndices.push(idx);
|
|
290
|
+
}
|
|
291
|
+
entries.push({
|
|
292
|
+
key: key,
|
|
293
|
+
keyIndex: group.keyIndex,
|
|
294
|
+
valueCells: valueCells,
|
|
295
|
+
valueIndices: valueIndices,
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
return entries;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
function isLookupTable(table, headerRow, groups) {
|
|
302
|
+
if (!table || !groups || !groups.length) return false;
|
|
303
|
+
var matches = 0;
|
|
304
|
+
eachDataRow(table, headerRow, function (row) {
|
|
305
|
+
matches += collectRowEntriesForGroups(row, groups, null).length;
|
|
306
|
+
});
|
|
307
|
+
return matches >= 2;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
function findLookupMatch(table, headerRow, groups, rollTotal, allowedKeyIndices) {
|
|
311
|
+
var exact = null;
|
|
312
|
+
var range = null;
|
|
313
|
+
eachDataRow(table, headerRow, function (row) {
|
|
314
|
+
var entries = collectRowEntriesForGroups(row, groups, allowedKeyIndices);
|
|
315
|
+
for (var e = 0; e < entries.length; e++) {
|
|
316
|
+
var entry = entries[e];
|
|
317
|
+
if (entry.key.kind === "exact" && entry.key.value === rollTotal) {
|
|
318
|
+
if (!exact) exact = { row: row, entry: entry };
|
|
319
|
+
} else if (
|
|
320
|
+
entry.key.kind === "range" &&
|
|
321
|
+
!range &&
|
|
322
|
+
rollTotal >= entry.key.min &&
|
|
323
|
+
rollTotal <= entry.key.max
|
|
324
|
+
) {
|
|
325
|
+
range = { row: row, entry: entry };
|
|
326
|
+
}
|
|
219
327
|
}
|
|
328
|
+
});
|
|
329
|
+
return exact || range;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
function headerDiceCount(headerRow) {
|
|
333
|
+
if (!headerRow) return 0;
|
|
334
|
+
return headerRow.querySelectorAll('a[data-dice]').length;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
function groupForColumn(groups, columnIndex) {
|
|
338
|
+
for (var g = 0; g < groups.length; g++) {
|
|
339
|
+
var group = groups[g];
|
|
340
|
+
if (columnIndex === group.keyIndex) return group;
|
|
341
|
+
if (group.valueIndices.indexOf(columnIndex) !== -1) return group;
|
|
220
342
|
}
|
|
221
|
-
return
|
|
343
|
+
return null;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// One die in the header (e.g. d100 over many pairs) => search every group.
|
|
347
|
+
// Several dice (e.g. d10 | Weather | d10 | Terrain | d6 | Mood) => only the clicked group.
|
|
348
|
+
function allowedKeyIndicesForClick(headerRow, clickCell, groups) {
|
|
349
|
+
if (!headerRow || !clickCell || !groups.length) return null;
|
|
350
|
+
if (headerDiceCount(headerRow) <= 1) return null;
|
|
351
|
+
var col = cellColumnIndex(headerRow, clickCell);
|
|
352
|
+
if (col < 0) return null;
|
|
353
|
+
var group = groupForColumn(groups, col);
|
|
354
|
+
return group ? [group.keyIndex] : null;
|
|
222
355
|
}
|
|
223
356
|
|
|
224
357
|
function getLookupTableContext(anchor, rollTotal) {
|
|
225
358
|
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
359
|
|
|
233
|
-
var
|
|
234
|
-
|
|
235
|
-
|
|
360
|
+
var cell = null;
|
|
361
|
+
var table = null;
|
|
362
|
+
var headerRow = null;
|
|
363
|
+
var allowedKeys = null;
|
|
364
|
+
var sourceTable = anchor._jdtSourceTable;
|
|
365
|
+
|
|
366
|
+
if (sourceTable && sourceTable.querySelector) {
|
|
367
|
+
// Re-roll from a previous table result in the tray.
|
|
368
|
+
table = sourceTable;
|
|
369
|
+
headerRow = findTableHeaderRow(table);
|
|
370
|
+
allowedKeys = anchor._jdtAllowedKeyIndices || null;
|
|
371
|
+
} else {
|
|
372
|
+
cell = anchor.closest("td, th");
|
|
373
|
+
if (!cell) return null;
|
|
374
|
+
table = cell.closest("table");
|
|
375
|
+
if (!table) return null;
|
|
376
|
+
headerRow = findTableHeaderRow(table);
|
|
377
|
+
// With a header, only header-cell dice trigger lookup (data cells may contain other dice).
|
|
378
|
+
// Without a header, any in-table die can trigger lookup.
|
|
379
|
+
if (headerRow && !headerRow.contains(cell)) return null;
|
|
380
|
+
}
|
|
236
381
|
|
|
237
|
-
var
|
|
238
|
-
if (!
|
|
382
|
+
var keyColumns = inferKeyColumns(table, headerRow);
|
|
383
|
+
if (!keyColumns.length) return null;
|
|
384
|
+
var groups = buildColumnGroups(keyColumns, tableColumnCount(table, headerRow));
|
|
385
|
+
if (!isLookupTable(table, headerRow, groups)) return null;
|
|
239
386
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
387
|
+
if (allowedKeys == null && cell && headerRow) {
|
|
388
|
+
allowedKeys = allowedKeyIndicesForClick(headerRow, cell, groups);
|
|
389
|
+
}
|
|
390
|
+
var matched = findLookupMatch(table, headerRow, groups, rollTotal, allowedKeys);
|
|
391
|
+
if (!matched) return null;
|
|
243
392
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
393
|
+
var headerCells = headerRow ? rowCells(headerRow) : [];
|
|
394
|
+
var entry = matched.entry;
|
|
395
|
+
var columns = [];
|
|
396
|
+
var indices = [entry.keyIndex].concat(entry.valueIndices);
|
|
397
|
+
var cells = [rowCells(matched.row)[entry.keyIndex]].concat(entry.valueCells);
|
|
398
|
+
var diceLabel = String(anchor.getAttribute("data-dice") || normalizeCellText(anchor) || "").trim();
|
|
399
|
+
|
|
400
|
+
for (var c = 0; c < cells.length; c++) {
|
|
401
|
+
var valueCell = cells[c];
|
|
402
|
+
if (!valueCell) continue;
|
|
403
|
+
var headerCell = headerCells[indices[c]];
|
|
404
|
+
var headerText = headerCell ? normalizeCellText(headerCell) : "";
|
|
405
|
+
var headerHtml = headerCell ? cellInnerHtml(headerCell) : "";
|
|
406
|
+
// Blank/whitespace key-column headers (common in side-by-side tables) inherit the die notation.
|
|
407
|
+
if (!headerText && c === 0 && diceLabel) {
|
|
408
|
+
headerText = diceLabel;
|
|
409
|
+
headerHtml = "";
|
|
410
|
+
} else if (!headerText) {
|
|
411
|
+
headerHtml = "";
|
|
412
|
+
}
|
|
247
413
|
columns.push({
|
|
248
|
-
header:
|
|
249
|
-
header_html:
|
|
414
|
+
header: headerText,
|
|
415
|
+
header_html: headerHtml,
|
|
250
416
|
value: normalizeCellText(valueCell),
|
|
251
417
|
value_html: cellInnerHtml(valueCell),
|
|
418
|
+
// Key-column die prefix is clickable for a table re-roll.
|
|
419
|
+
reroll_expr: c === 0 && diceLabel ? diceLabel : "",
|
|
252
420
|
});
|
|
253
421
|
}
|
|
254
422
|
|
|
255
|
-
return columns.length
|
|
423
|
+
return columns.length
|
|
424
|
+
? { columns: columns, _sourceTable: table, _allowedKeyIndices: allowedKeys }
|
|
425
|
+
: null;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
function serializableTableContext(tableContext) {
|
|
429
|
+
if (!tableContext || !tableContext.columns || !tableContext.columns.length) return null;
|
|
430
|
+
return {
|
|
431
|
+
columns: tableContext.columns.map(function (col) {
|
|
432
|
+
return {
|
|
433
|
+
header: col.header || "",
|
|
434
|
+
header_html: col.header_html || "",
|
|
435
|
+
value: col.value || "",
|
|
436
|
+
value_html: col.value_html || "",
|
|
437
|
+
reroll_expr: col.reroll_expr || "",
|
|
438
|
+
};
|
|
439
|
+
}),
|
|
440
|
+
};
|
|
256
441
|
}
|
|
257
442
|
|
|
258
443
|
function appendTableContext(entry, tableContext) {
|
|
@@ -262,10 +447,27 @@
|
|
|
262
447
|
tableContext.columns.forEach(function (col) {
|
|
263
448
|
if (!col || (!col.value && !col.value_html)) return;
|
|
264
449
|
var line = el("div", { class: "jdt-table-row" });
|
|
265
|
-
|
|
450
|
+
var headerText = col.header ? String(col.header).trim() : "";
|
|
451
|
+
if (headerText) {
|
|
266
452
|
var headerSpan = el("span", { class: "jdt-table-header" });
|
|
267
|
-
if (col.
|
|
268
|
-
|
|
453
|
+
if (col.reroll_expr) {
|
|
454
|
+
var reroll = el(
|
|
455
|
+
"a",
|
|
456
|
+
{ class: "dice-tray-roll", href: "#", "data-dice": col.reroll_expr },
|
|
457
|
+
headerText
|
|
458
|
+
);
|
|
459
|
+
if (tableContext._sourceTable && tableContext._sourceTable.querySelector) {
|
|
460
|
+
reroll._jdtSourceTable = tableContext._sourceTable;
|
|
461
|
+
}
|
|
462
|
+
if (tableContext._allowedKeyIndices) {
|
|
463
|
+
reroll._jdtAllowedKeyIndices = tableContext._allowedKeyIndices;
|
|
464
|
+
}
|
|
465
|
+
headerSpan.appendChild(reroll);
|
|
466
|
+
} else if (col.header_html) {
|
|
467
|
+
headerSpan.innerHTML = col.header_html;
|
|
468
|
+
} else {
|
|
469
|
+
headerSpan.textContent = headerText;
|
|
470
|
+
}
|
|
269
471
|
line.appendChild(headerSpan);
|
|
270
472
|
line.appendChild(el("span", { class: "jdt-table-sep" }, ": "));
|
|
271
473
|
}
|
|
@@ -466,7 +668,7 @@
|
|
|
466
668
|
success: success,
|
|
467
669
|
time: timeStr,
|
|
468
670
|
};
|
|
469
|
-
if (tableContext) item.table_context = tableContext;
|
|
671
|
+
if (tableContext) item.table_context = serializableTableContext(tableContext);
|
|
470
672
|
pushHistory(item);
|
|
471
673
|
}
|
|
472
674
|
|
|
@@ -490,7 +692,7 @@
|
|
|
490
692
|
if (skipHistory) return;
|
|
491
693
|
|
|
492
694
|
var item = { kind: "roll", expr: expr, total: total, rolls: rolls, mod: mod, time: timeStr };
|
|
493
|
-
if (tableContext) item.table_context = tableContext;
|
|
695
|
+
if (tableContext) item.table_context = serializableTableContext(tableContext);
|
|
494
696
|
pushHistory(item);
|
|
495
697
|
}
|
|
496
698
|
|
|
@@ -545,18 +747,24 @@
|
|
|
545
747
|
mod: mod,
|
|
546
748
|
time: timeStr,
|
|
547
749
|
};
|
|
548
|
-
if (tableContext) item.table_context = tableContext;
|
|
750
|
+
if (tableContext) item.table_context = serializableTableContext(tableContext);
|
|
549
751
|
pushHistory(item);
|
|
550
752
|
}
|
|
551
753
|
|
|
552
754
|
function showHelp() {
|
|
553
755
|
addSystemEntry(
|
|
554
756
|
"Usage: 1d6, d4, 2d8+1, 2-in-6",
|
|
555
|
-
"
|
|
757
|
+
"Type the dice you want to roll, without a prefix. Click linked dice notation in a table to show the matching entry (number or range).",
|
|
758
|
+
"Commands: /help, /clear, /version",
|
|
556
759
|
nowTime()
|
|
557
760
|
);
|
|
558
761
|
}
|
|
559
762
|
|
|
763
|
+
function showVersion() {
|
|
764
|
+
var version = root.getAttribute("data-version") || "unknown";
|
|
765
|
+
addSystemEntry("dice tray " + version, "", nowTime());
|
|
766
|
+
}
|
|
767
|
+
|
|
560
768
|
function doRoll(raw, meta) {
|
|
561
769
|
meta = meta || {};
|
|
562
770
|
var anchor = meta.anchor || null;
|
|
@@ -564,6 +772,7 @@
|
|
|
564
772
|
if (p.kind === "empty") return;
|
|
565
773
|
if (p.kind === "help") return showHelp();
|
|
566
774
|
if (p.kind === "clear") return clearStorageAndUi();
|
|
775
|
+
if (p.kind === "version") return showVersion();
|
|
567
776
|
if (p.kind !== "roll" && p.kind !== "bestof2" && p.kind !== "chance") {
|
|
568
777
|
addSystemEntry("Unrecognized roll: " + p.raw, "Try: 1d6, d4, 2-in-6, 2d8+1 or /help", nowTime());
|
|
569
778
|
return;
|
|
@@ -200,7 +200,7 @@ module Jekyll
|
|
|
200
200
|
return html if html.include?('data-dice-tray-root="true"')
|
|
201
201
|
|
|
202
202
|
tray = <<~HTML
|
|
203
|
-
<div id="jekyll-dice-tray" data-dice-tray-root="true" aria-live="polite">
|
|
203
|
+
<div id="jekyll-dice-tray" data-dice-tray-root="true" data-version="#{VERSION}" aria-live="polite">
|
|
204
204
|
<div class="jdt-header">
|
|
205
205
|
<button type="button" class="jdt-toggle" aria-expanded="false" title="Toggle dice tray">Dice</button>
|
|
206
206
|
</div>
|