jekyll-dice-tray 0.4.0 → 0.5.1
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.js +25 -81
- 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: d9bd0677666a51acbbbb3ca6bf5b67d1f5bb1ef638fa4ba2fc86a3ea5a0f4cc9
|
|
4
|
+
data.tar.gz: 8832cb5174a2d58f10f7aa8534a91b8865b296323d81a097e6d476422b2b1e31
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 558222307d26787647131df280b6e35055d644a9dfe2c97b9f2ce752e5ff179a56b21b96467dcea47633b4fb6a3128536931b2a0600a2b935dabdb5946867ba7
|
|
7
|
+
data.tar.gz: 5e69d92fe00836cef6d4aa013a3f4e320cbed50e4a082a7826f8085ef4ec68b6f9a4b4d96829e4348ff95aa7ce5706e03c336fd8dd81924366343b21dd73dd1b
|
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 (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.
|
|
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. Header dice always search the whole table (side-by-side column groups included)
|
|
8
8
|
- Persists input history, result history, minimize status
|
|
9
9
|
|
|
10
10
|
https://github.com/user-attachments/assets/6ef8d788-a1ee-49d4-ab26-f63899bb4a10
|
|
@@ -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, "");
|
|
@@ -178,14 +179,6 @@
|
|
|
178
179
|
return Array.prototype.slice.call(row.querySelectorAll("td, th"));
|
|
179
180
|
}
|
|
180
181
|
|
|
181
|
-
function cellColumnIndex(row, cell) {
|
|
182
|
-
var cells = rowCells(row);
|
|
183
|
-
for (var i = 0; i < cells.length; i++) {
|
|
184
|
-
if (cells[i] === cell) return i;
|
|
185
|
-
}
|
|
186
|
-
return -1;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
182
|
function rowLooksLikeHeader(row) {
|
|
190
183
|
if (!row) return false;
|
|
191
184
|
if (row.querySelector("th")) return true;
|
|
@@ -268,13 +261,11 @@
|
|
|
268
261
|
return max;
|
|
269
262
|
}
|
|
270
263
|
|
|
271
|
-
function collectRowEntriesForGroups(row, groups
|
|
264
|
+
function collectRowEntriesForGroups(row, groups) {
|
|
272
265
|
var cells = rowCells(row);
|
|
273
266
|
var entries = [];
|
|
274
|
-
var allowAll = !allowedKeyIndices || !allowedKeyIndices.length;
|
|
275
267
|
for (var g = 0; g < groups.length; g++) {
|
|
276
268
|
var group = groups[g];
|
|
277
|
-
if (!allowAll && allowedKeyIndices.indexOf(group.keyIndex) === -1) continue;
|
|
278
269
|
var keyCell = cells[group.keyIndex];
|
|
279
270
|
if (!keyCell) continue;
|
|
280
271
|
var key = parseKeyEntry(normalizeCellText(keyCell));
|
|
@@ -301,16 +292,17 @@
|
|
|
301
292
|
if (!table || !groups || !groups.length) return false;
|
|
302
293
|
var matches = 0;
|
|
303
294
|
eachDataRow(table, headerRow, function (row) {
|
|
304
|
-
matches += collectRowEntriesForGroups(row, groups
|
|
295
|
+
matches += collectRowEntriesForGroups(row, groups).length;
|
|
305
296
|
});
|
|
306
297
|
return matches >= 2;
|
|
307
298
|
}
|
|
308
299
|
|
|
309
|
-
|
|
300
|
+
// Header dice (one or many side-by-side) always search every key column in the table.
|
|
301
|
+
function findLookupMatch(table, headerRow, groups, rollTotal) {
|
|
310
302
|
var exact = null;
|
|
311
303
|
var range = null;
|
|
312
304
|
eachDataRow(table, headerRow, function (row) {
|
|
313
|
-
var entries = collectRowEntriesForGroups(row, groups
|
|
305
|
+
var entries = collectRowEntriesForGroups(row, groups);
|
|
314
306
|
for (var e = 0; e < entries.length; e++) {
|
|
315
307
|
var entry = entries[e];
|
|
316
308
|
if (entry.key.kind === "exact" && entry.key.value === rollTotal) {
|
|
@@ -328,74 +320,27 @@
|
|
|
328
320
|
return exact || range;
|
|
329
321
|
}
|
|
330
322
|
|
|
331
|
-
function headerDiceCount(headerRow) {
|
|
332
|
-
if (!headerRow) return 0;
|
|
333
|
-
return headerRow.querySelectorAll('a[data-dice]').length;
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
function groupForColumn(groups, columnIndex) {
|
|
337
|
-
for (var g = 0; g < groups.length; g++) {
|
|
338
|
-
var group = groups[g];
|
|
339
|
-
if (columnIndex === group.keyIndex) return group;
|
|
340
|
-
if (group.valueIndices.indexOf(columnIndex) !== -1) return group;
|
|
341
|
-
}
|
|
342
|
-
return null;
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
// One die in the header (e.g. d100 over many pairs) => search every group.
|
|
346
|
-
// Several dice (e.g. d10 | Weather | d10 | Terrain | d6 | Mood) => only the clicked group.
|
|
347
|
-
function allowedKeyIndicesForClick(headerRow, clickCell, groups) {
|
|
348
|
-
if (!headerRow || !clickCell || !groups.length) return null;
|
|
349
|
-
if (headerDiceCount(headerRow) <= 1) return null;
|
|
350
|
-
var col = cellColumnIndex(headerRow, clickCell);
|
|
351
|
-
if (col < 0) return null;
|
|
352
|
-
var group = groupForColumn(groups, col);
|
|
353
|
-
return group ? [group.keyIndex] : null;
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
function findFollowingTable(node) {
|
|
357
|
-
var elNode = node;
|
|
358
|
-
while (elNode && elNode !== document.body) {
|
|
359
|
-
var sib = elNode.nextElementSibling;
|
|
360
|
-
while (sib) {
|
|
361
|
-
if (sib.tagName === "TABLE") return sib;
|
|
362
|
-
var nested = sib.querySelector && sib.querySelector("table");
|
|
363
|
-
if (nested) return nested;
|
|
364
|
-
sib = sib.nextElementSibling;
|
|
365
|
-
}
|
|
366
|
-
elNode = elNode.parentElement;
|
|
367
|
-
}
|
|
368
|
-
return null;
|
|
369
|
-
}
|
|
370
|
-
|
|
371
323
|
function getLookupTableContext(anchor, rollTotal) {
|
|
372
324
|
if (!anchor || !anchor.closest || rollTotal == null) return null;
|
|
373
325
|
|
|
374
326
|
var cell = null;
|
|
375
327
|
var table = null;
|
|
376
328
|
var headerRow = null;
|
|
377
|
-
var allowedKeys = null;
|
|
378
329
|
var sourceTable = anchor._jdtSourceTable;
|
|
379
330
|
|
|
380
331
|
if (sourceTable && sourceTable.querySelector) {
|
|
381
332
|
// Re-roll from a previous table result in the tray.
|
|
382
333
|
table = sourceTable;
|
|
383
334
|
headerRow = findTableHeaderRow(table);
|
|
384
|
-
allowedKeys = anchor._jdtAllowedKeyIndices || null;
|
|
385
335
|
} else {
|
|
386
336
|
cell = anchor.closest("td, th");
|
|
387
|
-
if (cell)
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
} else {
|
|
395
|
-
table = findFollowingTable(anchor);
|
|
396
|
-
if (!table) return null;
|
|
397
|
-
headerRow = findTableHeaderRow(table);
|
|
398
|
-
}
|
|
337
|
+
if (!cell) return null;
|
|
338
|
+
table = cell.closest("table");
|
|
339
|
+
if (!table) return null;
|
|
340
|
+
headerRow = findTableHeaderRow(table);
|
|
341
|
+
// With a header, only header-cell dice trigger lookup (data cells may contain other dice).
|
|
342
|
+
// Without a header, any in-table die can trigger lookup.
|
|
343
|
+
if (headerRow && !headerRow.contains(cell)) return null;
|
|
399
344
|
}
|
|
400
345
|
|
|
401
346
|
var keyColumns = inferKeyColumns(table, headerRow);
|
|
@@ -403,10 +348,7 @@
|
|
|
403
348
|
var groups = buildColumnGroups(keyColumns, tableColumnCount(table, headerRow));
|
|
404
349
|
if (!isLookupTable(table, headerRow, groups)) return null;
|
|
405
350
|
|
|
406
|
-
|
|
407
|
-
allowedKeys = allowedKeyIndicesForClick(headerRow, cell, groups);
|
|
408
|
-
}
|
|
409
|
-
var matched = findLookupMatch(table, headerRow, groups, rollTotal, allowedKeys);
|
|
351
|
+
var matched = findLookupMatch(table, headerRow, groups, rollTotal);
|
|
410
352
|
if (!matched) return null;
|
|
411
353
|
|
|
412
354
|
var headerCells = headerRow ? rowCells(headerRow) : [];
|
|
@@ -439,9 +381,7 @@
|
|
|
439
381
|
});
|
|
440
382
|
}
|
|
441
383
|
|
|
442
|
-
return columns.length
|
|
443
|
-
? { columns: columns, _sourceTable: table, _allowedKeyIndices: allowedKeys }
|
|
444
|
-
: null;
|
|
384
|
+
return columns.length ? { columns: columns, _sourceTable: table } : null;
|
|
445
385
|
}
|
|
446
386
|
|
|
447
387
|
function serializableTableContext(tableContext) {
|
|
@@ -478,9 +418,6 @@
|
|
|
478
418
|
if (tableContext._sourceTable && tableContext._sourceTable.querySelector) {
|
|
479
419
|
reroll._jdtSourceTable = tableContext._sourceTable;
|
|
480
420
|
}
|
|
481
|
-
if (tableContext._allowedKeyIndices) {
|
|
482
|
-
reroll._jdtAllowedKeyIndices = tableContext._allowedKeyIndices;
|
|
483
|
-
}
|
|
484
421
|
headerSpan.appendChild(reroll);
|
|
485
422
|
} else if (col.header_html) {
|
|
486
423
|
headerSpan.innerHTML = col.header_html;
|
|
@@ -773,11 +710,17 @@
|
|
|
773
710
|
function showHelp() {
|
|
774
711
|
addSystemEntry(
|
|
775
712
|
"Usage: 1d6, d4, 2d8+1, 2-in-6",
|
|
776
|
-
"
|
|
713
|
+
"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).",
|
|
714
|
+
"Commands: /help, /clear, /version",
|
|
777
715
|
nowTime()
|
|
778
716
|
);
|
|
779
717
|
}
|
|
780
718
|
|
|
719
|
+
function showVersion() {
|
|
720
|
+
var version = root.getAttribute("data-version") || "unknown";
|
|
721
|
+
addSystemEntry("dice tray " + version, "", nowTime());
|
|
722
|
+
}
|
|
723
|
+
|
|
781
724
|
function doRoll(raw, meta) {
|
|
782
725
|
meta = meta || {};
|
|
783
726
|
var anchor = meta.anchor || null;
|
|
@@ -785,6 +728,7 @@
|
|
|
785
728
|
if (p.kind === "empty") return;
|
|
786
729
|
if (p.kind === "help") return showHelp();
|
|
787
730
|
if (p.kind === "clear") return clearStorageAndUi();
|
|
731
|
+
if (p.kind === "version") return showVersion();
|
|
788
732
|
if (p.kind !== "roll" && p.kind !== "bestof2" && p.kind !== "chance") {
|
|
789
733
|
addSystemEntry("Unrecognized roll: " + p.raw, "Try: 1d6, d4, 2-in-6, 2d8+1 or /help", nowTime());
|
|
790
734
|
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>
|