jekyll-dice-tray 0.3.0 → 0.4.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 +2 -2
- data/assets/jekyll-dice-tray/dice_tray.css +4 -2
- data/assets/jekyll-dice-tray/dice_tray.js +284 -63
- data/lib/jekyll/dice_tray/config.rb +26 -0
- data/lib/jekyll/dice_tray/generator.rb +2 -4
- data/lib/jekyll/dice_tray/hooks.rb +1 -4
- data/lib/jekyll/dice_tray/version.rb +1 -1
- data/lib/jekyll-dice-tray.rb +1 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8ee11a49a55ee16f40ee46a91b01a40d3074da6b6bc1cdde28b7bbe36b41386d
|
|
4
|
+
data.tar.gz: a35ce460b6c0181c03acc99d38916407eac12d1c6d89feae6412335302cedd64
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c754090c423cbd76a96b532e0bccc16d2cd2e76db5006fae17ed1766b5c8e19305a8838346640117de26bc6793e7c41021dbcf05ce61541095b97bd1dfde5edd
|
|
7
|
+
data.tar.gz: 03d2e7cdfaa42614d46fba9fac3eebf0722b6ba324def7a5c40d6f53576aadc0b4f73a17354218aa7ad508b002818c93e49db65f9b1170a37ce389ddbc26e3ea
|
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
|
|
@@ -31,7 +31,7 @@ Optional `_config.yml` settings:
|
|
|
31
31
|
```yml
|
|
32
32
|
dice_tray:
|
|
33
33
|
enabled: true
|
|
34
|
-
assets_path: /assets/jekyll-dice-tray
|
|
34
|
+
assets_path: /assets/jekyll-dice-tray # prefixed with site baseurl automatically
|
|
35
35
|
inject_tray: true
|
|
36
36
|
link_dice_in_markdown: true
|
|
37
37
|
```
|
|
@@ -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
|
|
|
@@ -158,21 +158,7 @@
|
|
|
158
158
|
return node && node.innerHTML ? node.innerHTML.trim() : "";
|
|
159
159
|
}
|
|
160
160
|
|
|
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) {
|
|
161
|
+
function parseKeyEntry(text) {
|
|
176
162
|
if (!text) return null;
|
|
177
163
|
var normalized = text.replace(/[\u2013\u2014]/g, "-");
|
|
178
164
|
if (/^\d+$/.test(normalized)) {
|
|
@@ -187,72 +173,290 @@
|
|
|
187
173
|
return null;
|
|
188
174
|
}
|
|
189
175
|
|
|
190
|
-
function
|
|
191
|
-
if (!row) return
|
|
192
|
-
|
|
193
|
-
if (!cell) return null;
|
|
194
|
-
return parseFirstColumnEntry(normalizeCellText(cell));
|
|
176
|
+
function rowCells(row) {
|
|
177
|
+
if (!row) return [];
|
|
178
|
+
return Array.prototype.slice.call(row.querySelectorAll("td, th"));
|
|
195
179
|
}
|
|
196
180
|
|
|
197
|
-
function
|
|
198
|
-
|
|
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
|
+
function rowLooksLikeHeader(row) {
|
|
190
|
+
if (!row) return false;
|
|
191
|
+
if (row.querySelector("th")) return true;
|
|
192
|
+
var cells = rowCells(row);
|
|
193
|
+
if (!cells.length) return false;
|
|
194
|
+
var keyCount = 0;
|
|
195
|
+
for (var i = 0; i < cells.length; i++) {
|
|
196
|
+
if (parseKeyEntry(normalizeCellText(cells[i]))) keyCount++;
|
|
197
|
+
}
|
|
198
|
+
// Data rows start with roll keys; header rows are labels / dice expr.
|
|
199
|
+
return keyCount === 0;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function findTableHeaderRow(table) {
|
|
203
|
+
if (!table) return null;
|
|
204
|
+
var thead = table.querySelector("thead");
|
|
205
|
+
if (thead) {
|
|
206
|
+
var theadRows = thead.querySelectorAll("tr");
|
|
207
|
+
if (theadRows.length) {
|
|
208
|
+
var head = theadRows[theadRows.length - 1];
|
|
209
|
+
// Markdown always wraps the first row in <thead>; skip if it's really data.
|
|
210
|
+
if (!parseKeyEntry(normalizeCellText(rowCells(head)[0] || null))) return head;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
199
213
|
var rows = table.querySelectorAll("tr");
|
|
200
|
-
var matches = 0;
|
|
201
214
|
for (var i = 0; i < rows.length; i++) {
|
|
202
|
-
if (rows[i]
|
|
203
|
-
if (firstColumnEntry(rows[i]) !== null) matches++;
|
|
215
|
+
if (rows[i].querySelector("th") && rowLooksLikeHeader(rows[i])) return rows[i];
|
|
204
216
|
}
|
|
205
|
-
|
|
217
|
+
if (rows.length && rowLooksLikeHeader(rows[0])) return rows[0];
|
|
218
|
+
return null;
|
|
206
219
|
}
|
|
207
220
|
|
|
208
|
-
function
|
|
221
|
+
function eachDataRow(table, headerRow, fn) {
|
|
209
222
|
var rows = table.querySelectorAll("tr");
|
|
210
|
-
var rangeRow = null;
|
|
211
223
|
for (var i = 0; i < rows.length; i++) {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
224
|
+
if (rows[i] === headerRow) continue;
|
|
225
|
+
fn(rows[i]);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Infer key columns from data: any column that holds a roll number/range in enough rows.
|
|
230
|
+
// Supports 1..N side-by-side (key, value...) groups for any die size.
|
|
231
|
+
function inferKeyColumns(table, headerRow) {
|
|
232
|
+
var counts = [];
|
|
233
|
+
var rowCount = 0;
|
|
234
|
+
eachDataRow(table, headerRow, function (row) {
|
|
235
|
+
var cells = rowCells(row);
|
|
236
|
+
rowCount++;
|
|
237
|
+
for (var i = 0; i < cells.length; i++) {
|
|
238
|
+
if (!counts[i]) counts[i] = 0;
|
|
239
|
+
if (parseKeyEntry(normalizeCellText(cells[i]))) counts[i]++;
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
if (rowCount < 1) return [];
|
|
243
|
+
var minHits = Math.min(2, rowCount);
|
|
244
|
+
var keys = [];
|
|
245
|
+
for (var c = 0; c < counts.length; c++) {
|
|
246
|
+
if ((counts[c] || 0) >= minHits) keys.push(c);
|
|
247
|
+
}
|
|
248
|
+
return keys;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function buildColumnGroups(keyColumns, columnCount) {
|
|
252
|
+
var groups = [];
|
|
253
|
+
for (var k = 0; k < keyColumns.length; k++) {
|
|
254
|
+
var keyIndex = keyColumns[k];
|
|
255
|
+
var nextKey = k + 1 < keyColumns.length ? keyColumns[k + 1] : columnCount;
|
|
256
|
+
var valueIndices = [];
|
|
257
|
+
for (var v = keyIndex + 1; v < nextKey; v++) valueIndices.push(v);
|
|
258
|
+
groups.push({ keyIndex: keyIndex, valueIndices: valueIndices });
|
|
259
|
+
}
|
|
260
|
+
return groups;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function tableColumnCount(table, headerRow) {
|
|
264
|
+
var max = headerRow ? rowCells(headerRow).length : 0;
|
|
265
|
+
eachDataRow(table, headerRow, function (row) {
|
|
266
|
+
max = Math.max(max, rowCells(row).length);
|
|
267
|
+
});
|
|
268
|
+
return max;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
function collectRowEntriesForGroups(row, groups, allowedKeyIndices) {
|
|
272
|
+
var cells = rowCells(row);
|
|
273
|
+
var entries = [];
|
|
274
|
+
var allowAll = !allowedKeyIndices || !allowedKeyIndices.length;
|
|
275
|
+
for (var g = 0; g < groups.length; g++) {
|
|
276
|
+
var group = groups[g];
|
|
277
|
+
if (!allowAll && allowedKeyIndices.indexOf(group.keyIndex) === -1) continue;
|
|
278
|
+
var keyCell = cells[group.keyIndex];
|
|
279
|
+
if (!keyCell) continue;
|
|
280
|
+
var key = parseKeyEntry(normalizeCellText(keyCell));
|
|
281
|
+
if (!key) continue;
|
|
282
|
+
var valueCells = [];
|
|
283
|
+
var valueIndices = [];
|
|
284
|
+
for (var vi = 0; vi < group.valueIndices.length; vi++) {
|
|
285
|
+
var idx = group.valueIndices[vi];
|
|
286
|
+
if (!cells[idx]) continue;
|
|
287
|
+
valueCells.push(cells[idx]);
|
|
288
|
+
valueIndices.push(idx);
|
|
219
289
|
}
|
|
290
|
+
entries.push({
|
|
291
|
+
key: key,
|
|
292
|
+
keyIndex: group.keyIndex,
|
|
293
|
+
valueCells: valueCells,
|
|
294
|
+
valueIndices: valueIndices,
|
|
295
|
+
});
|
|
220
296
|
}
|
|
221
|
-
return
|
|
297
|
+
return entries;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function isLookupTable(table, headerRow, groups) {
|
|
301
|
+
if (!table || !groups || !groups.length) return false;
|
|
302
|
+
var matches = 0;
|
|
303
|
+
eachDataRow(table, headerRow, function (row) {
|
|
304
|
+
matches += collectRowEntriesForGroups(row, groups, null).length;
|
|
305
|
+
});
|
|
306
|
+
return matches >= 2;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
function findLookupMatch(table, headerRow, groups, rollTotal, allowedKeyIndices) {
|
|
310
|
+
var exact = null;
|
|
311
|
+
var range = null;
|
|
312
|
+
eachDataRow(table, headerRow, function (row) {
|
|
313
|
+
var entries = collectRowEntriesForGroups(row, groups, allowedKeyIndices);
|
|
314
|
+
for (var e = 0; e < entries.length; e++) {
|
|
315
|
+
var entry = entries[e];
|
|
316
|
+
if (entry.key.kind === "exact" && entry.key.value === rollTotal) {
|
|
317
|
+
if (!exact) exact = { row: row, entry: entry };
|
|
318
|
+
} else if (
|
|
319
|
+
entry.key.kind === "range" &&
|
|
320
|
+
!range &&
|
|
321
|
+
rollTotal >= entry.key.min &&
|
|
322
|
+
rollTotal <= entry.key.max
|
|
323
|
+
) {
|
|
324
|
+
range = { row: row, entry: entry };
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
});
|
|
328
|
+
return exact || range;
|
|
329
|
+
}
|
|
330
|
+
|
|
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;
|
|
222
369
|
}
|
|
223
370
|
|
|
224
371
|
function getLookupTableContext(anchor, rollTotal) {
|
|
225
372
|
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
373
|
|
|
233
|
-
var
|
|
234
|
-
|
|
235
|
-
|
|
374
|
+
var cell = null;
|
|
375
|
+
var table = null;
|
|
376
|
+
var headerRow = null;
|
|
377
|
+
var allowedKeys = null;
|
|
378
|
+
var sourceTable = anchor._jdtSourceTable;
|
|
379
|
+
|
|
380
|
+
if (sourceTable && sourceTable.querySelector) {
|
|
381
|
+
// Re-roll from a previous table result in the tray.
|
|
382
|
+
table = sourceTable;
|
|
383
|
+
headerRow = findTableHeaderRow(table);
|
|
384
|
+
allowedKeys = anchor._jdtAllowedKeyIndices || null;
|
|
385
|
+
} else {
|
|
386
|
+
cell = anchor.closest("td, th");
|
|
387
|
+
if (cell) {
|
|
388
|
+
table = cell.closest("table");
|
|
389
|
+
if (!table) return null;
|
|
390
|
+
headerRow = findTableHeaderRow(table);
|
|
391
|
+
// With a header, only header-cell dice trigger lookup (data cells may contain other dice).
|
|
392
|
+
// Without a header, any in-table die can trigger lookup.
|
|
393
|
+
if (headerRow && !headerRow.contains(cell)) return null;
|
|
394
|
+
} else {
|
|
395
|
+
table = findFollowingTable(anchor);
|
|
396
|
+
if (!table) return null;
|
|
397
|
+
headerRow = findTableHeaderRow(table);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
var keyColumns = inferKeyColumns(table, headerRow);
|
|
402
|
+
if (!keyColumns.length) return null;
|
|
403
|
+
var groups = buildColumnGroups(keyColumns, tableColumnCount(table, headerRow));
|
|
404
|
+
if (!isLookupTable(table, headerRow, groups)) return null;
|
|
236
405
|
|
|
237
|
-
|
|
238
|
-
|
|
406
|
+
if (allowedKeys == null && cell && headerRow) {
|
|
407
|
+
allowedKeys = allowedKeyIndicesForClick(headerRow, cell, groups);
|
|
408
|
+
}
|
|
409
|
+
var matched = findLookupMatch(table, headerRow, groups, rollTotal, allowedKeys);
|
|
410
|
+
if (!matched) return null;
|
|
239
411
|
|
|
240
|
-
var headerCells =
|
|
241
|
-
var
|
|
412
|
+
var headerCells = headerRow ? rowCells(headerRow) : [];
|
|
413
|
+
var entry = matched.entry;
|
|
242
414
|
var columns = [];
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
415
|
+
var indices = [entry.keyIndex].concat(entry.valueIndices);
|
|
416
|
+
var cells = [rowCells(matched.row)[entry.keyIndex]].concat(entry.valueCells);
|
|
417
|
+
var diceLabel = String(anchor.getAttribute("data-dice") || normalizeCellText(anchor) || "").trim();
|
|
418
|
+
|
|
419
|
+
for (var c = 0; c < cells.length; c++) {
|
|
420
|
+
var valueCell = cells[c];
|
|
421
|
+
if (!valueCell) continue;
|
|
422
|
+
var headerCell = headerCells[indices[c]];
|
|
423
|
+
var headerText = headerCell ? normalizeCellText(headerCell) : "";
|
|
424
|
+
var headerHtml = headerCell ? cellInnerHtml(headerCell) : "";
|
|
425
|
+
// Blank/whitespace key-column headers (common in side-by-side tables) inherit the die notation.
|
|
426
|
+
if (!headerText && c === 0 && diceLabel) {
|
|
427
|
+
headerText = diceLabel;
|
|
428
|
+
headerHtml = "";
|
|
429
|
+
} else if (!headerText) {
|
|
430
|
+
headerHtml = "";
|
|
431
|
+
}
|
|
247
432
|
columns.push({
|
|
248
|
-
header:
|
|
249
|
-
header_html:
|
|
433
|
+
header: headerText,
|
|
434
|
+
header_html: headerHtml,
|
|
250
435
|
value: normalizeCellText(valueCell),
|
|
251
436
|
value_html: cellInnerHtml(valueCell),
|
|
437
|
+
// Key-column die prefix is clickable for a table re-roll.
|
|
438
|
+
reroll_expr: c === 0 && diceLabel ? diceLabel : "",
|
|
252
439
|
});
|
|
253
440
|
}
|
|
254
441
|
|
|
255
|
-
return columns.length
|
|
442
|
+
return columns.length
|
|
443
|
+
? { columns: columns, _sourceTable: table, _allowedKeyIndices: allowedKeys }
|
|
444
|
+
: null;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
function serializableTableContext(tableContext) {
|
|
448
|
+
if (!tableContext || !tableContext.columns || !tableContext.columns.length) return null;
|
|
449
|
+
return {
|
|
450
|
+
columns: tableContext.columns.map(function (col) {
|
|
451
|
+
return {
|
|
452
|
+
header: col.header || "",
|
|
453
|
+
header_html: col.header_html || "",
|
|
454
|
+
value: col.value || "",
|
|
455
|
+
value_html: col.value_html || "",
|
|
456
|
+
reroll_expr: col.reroll_expr || "",
|
|
457
|
+
};
|
|
458
|
+
}),
|
|
459
|
+
};
|
|
256
460
|
}
|
|
257
461
|
|
|
258
462
|
function appendTableContext(entry, tableContext) {
|
|
@@ -262,10 +466,27 @@
|
|
|
262
466
|
tableContext.columns.forEach(function (col) {
|
|
263
467
|
if (!col || (!col.value && !col.value_html)) return;
|
|
264
468
|
var line = el("div", { class: "jdt-table-row" });
|
|
265
|
-
|
|
469
|
+
var headerText = col.header ? String(col.header).trim() : "";
|
|
470
|
+
if (headerText) {
|
|
266
471
|
var headerSpan = el("span", { class: "jdt-table-header" });
|
|
267
|
-
if (col.
|
|
268
|
-
|
|
472
|
+
if (col.reroll_expr) {
|
|
473
|
+
var reroll = el(
|
|
474
|
+
"a",
|
|
475
|
+
{ class: "dice-tray-roll", href: "#", "data-dice": col.reroll_expr },
|
|
476
|
+
headerText
|
|
477
|
+
);
|
|
478
|
+
if (tableContext._sourceTable && tableContext._sourceTable.querySelector) {
|
|
479
|
+
reroll._jdtSourceTable = tableContext._sourceTable;
|
|
480
|
+
}
|
|
481
|
+
if (tableContext._allowedKeyIndices) {
|
|
482
|
+
reroll._jdtAllowedKeyIndices = tableContext._allowedKeyIndices;
|
|
483
|
+
}
|
|
484
|
+
headerSpan.appendChild(reroll);
|
|
485
|
+
} else if (col.header_html) {
|
|
486
|
+
headerSpan.innerHTML = col.header_html;
|
|
487
|
+
} else {
|
|
488
|
+
headerSpan.textContent = headerText;
|
|
489
|
+
}
|
|
269
490
|
line.appendChild(headerSpan);
|
|
270
491
|
line.appendChild(el("span", { class: "jdt-table-sep" }, ": "));
|
|
271
492
|
}
|
|
@@ -466,7 +687,7 @@
|
|
|
466
687
|
success: success,
|
|
467
688
|
time: timeStr,
|
|
468
689
|
};
|
|
469
|
-
if (tableContext) item.table_context = tableContext;
|
|
690
|
+
if (tableContext) item.table_context = serializableTableContext(tableContext);
|
|
470
691
|
pushHistory(item);
|
|
471
692
|
}
|
|
472
693
|
|
|
@@ -490,7 +711,7 @@
|
|
|
490
711
|
if (skipHistory) return;
|
|
491
712
|
|
|
492
713
|
var item = { kind: "roll", expr: expr, total: total, rolls: rolls, mod: mod, time: timeStr };
|
|
493
|
-
if (tableContext) item.table_context = tableContext;
|
|
714
|
+
if (tableContext) item.table_context = serializableTableContext(tableContext);
|
|
494
715
|
pushHistory(item);
|
|
495
716
|
}
|
|
496
717
|
|
|
@@ -545,14 +766,14 @@
|
|
|
545
766
|
mod: mod,
|
|
546
767
|
time: timeStr,
|
|
547
768
|
};
|
|
548
|
-
if (tableContext) item.table_context = tableContext;
|
|
769
|
+
if (tableContext) item.table_context = serializableTableContext(tableContext);
|
|
549
770
|
pushHistory(item);
|
|
550
771
|
}
|
|
551
772
|
|
|
552
773
|
function showHelp() {
|
|
553
774
|
addSystemEntry(
|
|
554
775
|
"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 (
|
|
776
|
+
"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 (any dN) shows the matching entry (number or range; any number of side-by-side key/value column groups; headers optional). Commands: /help, /clear",
|
|
556
777
|
nowTime()
|
|
557
778
|
);
|
|
558
779
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module Jekyll
|
|
2
|
+
module DiceTray
|
|
3
|
+
module Config
|
|
4
|
+
DEFAULT_ASSETS_PATH = "/assets/jekyll-dice-tray"
|
|
5
|
+
|
|
6
|
+
# Site-relative directory for writing static assets (no baseurl).
|
|
7
|
+
def self.assets_dir(site)
|
|
8
|
+
path = configured_path(site)
|
|
9
|
+
path.sub(%r{\A/}, "")
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# URL path for linking assets in HTML (includes baseurl).
|
|
13
|
+
def self.assets_url(site)
|
|
14
|
+
baseurl = site.config["baseurl"].to_s.chomp("/")
|
|
15
|
+
"#{baseurl}#{configured_path(site)}"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.configured_path(site)
|
|
19
|
+
cfg = site.config["dice_tray"] || {}
|
|
20
|
+
path = (cfg["assets_path"] || DEFAULT_ASSETS_PATH).to_s
|
|
21
|
+
path.start_with?("/") ? path : "/#{path}"
|
|
22
|
+
end
|
|
23
|
+
private_class_method :configured_path
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -8,10 +8,8 @@ module Jekyll
|
|
|
8
8
|
cfg = (site.config["dice_tray"] || {})
|
|
9
9
|
return if cfg["enabled"] == false
|
|
10
10
|
|
|
11
|
-
assets_path = cfg["assets_path"] || "/assets/jekyll-dice-tray"
|
|
12
|
-
assets_path = "/#{assets_path}" unless assets_path.start_with?("/")
|
|
13
|
-
|
|
14
11
|
asset_dir = File.expand_path("../../../assets/jekyll-dice-tray", __dir__)
|
|
12
|
+
dest_dir = Config.assets_dir(site)
|
|
15
13
|
|
|
16
14
|
files = {
|
|
17
15
|
"dice_tray.js" => File.join(asset_dir, "dice_tray.js"),
|
|
@@ -23,7 +21,7 @@ module Jekyll
|
|
|
23
21
|
site.static_files << AssetFile.new(
|
|
24
22
|
site,
|
|
25
23
|
site.source,
|
|
26
|
-
|
|
24
|
+
dest_dir,
|
|
27
25
|
name,
|
|
28
26
|
source_path: source_path
|
|
29
27
|
)
|
|
@@ -8,13 +8,10 @@ module Jekyll
|
|
|
8
8
|
next if cfg["enabled"] == false
|
|
9
9
|
next unless doc.respond_to?(:output_ext) && doc.output_ext == ".html"
|
|
10
10
|
|
|
11
|
-
assets_path = cfg["assets_path"] || "/assets/jekyll-dice-tray"
|
|
12
|
-
assets_path = "/#{assets_path}" unless assets_path.start_with?("/")
|
|
13
|
-
|
|
14
11
|
begin
|
|
15
12
|
out = doc.output.to_s
|
|
16
13
|
out = HtmlRewriter.rewrite(out) if cfg.fetch("link_dice_in_markdown", true)
|
|
17
|
-
out = HtmlRewriter.inject_tray(out, assets_path:
|
|
14
|
+
out = HtmlRewriter.inject_tray(out, assets_path: Config.assets_url(site)) if cfg.fetch("inject_tray", true)
|
|
18
15
|
doc.output = out
|
|
19
16
|
rescue StandardError => e
|
|
20
17
|
Jekyll.logger.warn("jekyll-dice-tray:", "Failed to process #{doc.relative_path}: #{e.class}: #{e.message}")
|
data/lib/jekyll-dice-tray.rb
CHANGED
|
@@ -2,6 +2,7 @@ require "jekyll"
|
|
|
2
2
|
require "nokogiri"
|
|
3
3
|
|
|
4
4
|
require_relative "jekyll/dice_tray/version"
|
|
5
|
+
require_relative "jekyll/dice_tray/config"
|
|
5
6
|
require_relative "jekyll/dice_tray/asset_file"
|
|
6
7
|
require_relative "jekyll/dice_tray/generator"
|
|
7
8
|
require_relative "jekyll/dice_tray/html_rewriter"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: jekyll-dice-tray
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- directsun
|
|
@@ -54,6 +54,7 @@ files:
|
|
|
54
54
|
- assets/jekyll-dice-tray/dice_tray.js
|
|
55
55
|
- lib/jekyll-dice-tray.rb
|
|
56
56
|
- lib/jekyll/dice_tray/asset_file.rb
|
|
57
|
+
- lib/jekyll/dice_tray/config.rb
|
|
57
58
|
- lib/jekyll/dice_tray/generator.rb
|
|
58
59
|
- lib/jekyll/dice_tray/hooks.rb
|
|
59
60
|
- lib/jekyll/dice_tray/html_rewriter.rb
|