devcoach 2.3.1 → 2.4.0-next.575.g9c67058
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.
- package/assets/SKILL.md +3 -2
- package/assets/references/sharing.md +2 -1
- package/assets/static/relative-time.js +78 -15
- package/assets/static/style.css +70 -0
- package/assets/static/table-resize.js +178 -0
- package/dist/{app-SVGKP5WG.js → app-RC2D4BDF.js} +233 -141
- package/dist/bin.js +1 -1
- package/dist/chunk-DGO6MIQO.js +15 -0
- package/dist/chunk-LSO57U2T.js +2 -0
- package/dist/chunk-TQI44CEB.js +75 -0
- package/dist/commands-YNDVJIEM.js +36 -0
- package/dist/{hooks-5YA5PLBW.js → hooks-5UZL55FA.js} +1 -1
- package/dist/server-NLJ7CK6T.js +9 -0
- package/package.json +1 -1
- package/dist/chunk-4PFP67XN.js +0 -2
- package/dist/chunk-JEFYE33I.js +0 -75
- package/dist/chunk-UHF6ARVR.js +0 -15
- package/dist/commands-ECVEHTRX.js +0 -36
- package/dist/server-SM63J4EC.js +0 -9
package/assets/SKILL.md
CHANGED
|
@@ -199,8 +199,9 @@ checkpoints, never touch the notebook.
|
|
|
199
199
|
- "Close / stop the dashboard" → `stop_ui` (same `port`) — it stops whichever dashboard listens
|
|
200
200
|
there, one you opened or one started from a terminal; if the user runs `devcoach ui` in their own
|
|
201
201
|
terminal, Ctrl+C there stops it just as gracefully (in-flight requests finish)
|
|
202
|
-
- "Lessons shared with me" → `get_lessons({imported: true})
|
|
203
|
-
|
|
202
|
+
- "Lessons shared with me" → `get_lessons({imported: true})`; "what did Ada send me" →
|
|
203
|
+
`get_lessons({shared_by: "Ada"})` (exact sender name)
|
|
204
|
+
- "Show me the lesson X shared" → `get_lessons({shared_by: X, search})` → the card,
|
|
204
205
|
without `log_lesson` or the feedback line (see `references/sharing.md`)
|
|
205
206
|
|
|
206
207
|
## Operating notes
|
|
@@ -54,7 +54,8 @@ just starred a lesson → The one offer (below)
|
|
|
54
54
|
## Show a shared lesson
|
|
55
55
|
|
|
56
56
|
"Show me what Ada shared", "read me the lesson I imported", "the lesson about X someone sent":
|
|
57
|
-
`get_lessons({
|
|
57
|
+
`get_lessons({shared_by: "Ada"})` when a sender is named (exact name; `search` also matches the
|
|
58
|
+
sender), else `get_lessons({imported: true, search: …})` — ask if 2+ match — then render it as a normal card —
|
|
58
59
|
both bands, the title line with `Category · Level`, the body, the 💡 tip — **without**
|
|
59
60
|
`log_lesson` and **without** the "Did that land?" line. It is already in their log, taught by
|
|
60
61
|
someone else; it costs nothing on the rate limit. Record feedback only if they volunteer it
|
|
@@ -1,26 +1,80 @@
|
|
|
1
|
-
/* Shared relative-time formatter used by lessons
|
|
1
|
+
/* Shared relative-time formatter used by the lessons list and the lesson page. Every [data-ts]
|
|
2
|
+
gets a relative label; when its cell is too narrow for the long form ("17 minutes ago") it
|
|
3
|
+
switches to the compact one ("17m"), and it is re-evaluated after column drags and resizes. */
|
|
2
4
|
(function () {
|
|
3
|
-
|
|
5
|
+
/* "yesterday" / "today" are only right at day granularity; for weeks the number is always
|
|
6
|
+
spelled out — "last week" for something 13 days old is a lie — and from two months on the
|
|
7
|
+
relative label stops being useful at all: the date is printed instead ("July 27" within the
|
|
8
|
+
current year, "July 27, 2025" for earlier years). */
|
|
9
|
+
var rtfAuto = new Intl.RelativeTimeFormat('en', { numeric: 'auto' });
|
|
10
|
+
var rtfExact = new Intl.RelativeTimeFormat('en', { numeric: 'always' });
|
|
11
|
+
var COMPACT_BELOW = 120; // cell width (px) under which the compact form is used
|
|
12
|
+
|
|
13
|
+
function parts(iso) {
|
|
14
|
+
var date = new Date(iso);
|
|
15
|
+
var now = new Date();
|
|
16
|
+
var diffMs = now - date;
|
|
17
|
+
var mins = Math.floor(diffMs / 60000);
|
|
18
|
+
var days = Math.floor(diffMs / 86400000);
|
|
19
|
+
/* Calendar months between the two dates by label: a July lesson seen in September is two
|
|
20
|
+
months away, whatever the day of month — old enough to print the date. */
|
|
21
|
+
var months = (now.getFullYear() - date.getFullYear()) * 12 + (now.getMonth() - date.getMonth());
|
|
22
|
+
return { diffMs: diffMs, mins: mins, days: days, months: Math.max(0, months) };
|
|
23
|
+
}
|
|
4
24
|
|
|
5
25
|
function relativeTime(iso) {
|
|
26
|
+
var p = parts(iso);
|
|
27
|
+
if (p.diffMs < 0 || p.mins < 1) return 'just now';
|
|
28
|
+
if (p.mins < 60) return rtfAuto.format(-p.mins, 'minute');
|
|
29
|
+
if (p.days === 0) return 'today';
|
|
30
|
+
if (p.days === 1) return 'yesterday';
|
|
31
|
+
if (p.days < 7) return rtfAuto.format(-p.days, 'day');
|
|
32
|
+
if (p.months < 1) return rtfExact.format(-Math.floor(p.days / 7), 'week');
|
|
33
|
+
if (p.months < 2) return rtfExact.format(-p.months, 'month');
|
|
34
|
+
return absoluteDate(iso, 'long');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
var monthDayLong = new Intl.DateTimeFormat('en', { month: 'long', day: 'numeric' });
|
|
38
|
+
var monthDayShort = new Intl.DateTimeFormat('en', { month: 'short', day: 'numeric' });
|
|
39
|
+
var monthDayYear = new Intl.DateTimeFormat('en', { month: 'long', day: 'numeric', year: 'numeric' });
|
|
40
|
+
var monthYear = new Intl.DateTimeFormat('en', { month: 'short', year: 'numeric' });
|
|
41
|
+
|
|
42
|
+
/* Same year → "July 27" (compact: "Jul 27"); an earlier year → "July 27, 2025" (compact:
|
|
43
|
+
"Jul 2025" — at that distance the year matters more than the day). */
|
|
44
|
+
function absoluteDate(iso, style) {
|
|
6
45
|
var date = new Date(iso);
|
|
7
|
-
var
|
|
8
|
-
if (
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
46
|
+
var sameYear = date.getFullYear() === new Date().getFullYear();
|
|
47
|
+
if (style === 'long') return (sameYear ? monthDayLong : monthDayYear).format(date);
|
|
48
|
+
return (sameYear ? monthDayShort : monthYear).format(date);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
var weekdayShort = new Intl.DateTimeFormat('en', { weekday: 'short' });
|
|
52
|
+
|
|
53
|
+
function weekdayDay(date) {
|
|
54
|
+
return weekdayShort.format(date) + ' ' + date.getDate();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/* Compact: "17m" · "today" · "Mon 2" within the last week · "Sep 10" from a week on
|
|
58
|
+
(the full date for earlier years). */
|
|
59
|
+
function compactTime(iso) {
|
|
60
|
+
var p = parts(iso);
|
|
61
|
+
if (p.diffMs < 0 || p.mins < 1) return 'now';
|
|
62
|
+
if (p.mins < 60) return p.mins + 'm';
|
|
63
|
+
if (p.days === 0) return 'today';
|
|
64
|
+
if (p.days < 7) return weekdayDay(new Date(iso));
|
|
65
|
+
return absoluteDate(iso, 'short');
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function isNarrow(el) {
|
|
69
|
+
var cell = el.closest('td, th');
|
|
70
|
+
if (!cell) return false;
|
|
71
|
+
var w = cell.getBoundingClientRect().width;
|
|
72
|
+
return w > 0 && w < COMPACT_BELOW;
|
|
19
73
|
}
|
|
20
74
|
|
|
21
75
|
function applyRelativeTimes(root) {
|
|
22
76
|
root.querySelectorAll('[data-ts]').forEach(function (el) {
|
|
23
|
-
el.textContent = relativeTime(el.dataset.ts);
|
|
77
|
+
el.textContent = isNarrow(el) ? compactTime(el.dataset.ts) : relativeTime(el.dataset.ts);
|
|
24
78
|
});
|
|
25
79
|
}
|
|
26
80
|
|
|
@@ -29,4 +83,13 @@
|
|
|
29
83
|
document.body.addEventListener('htmx:afterSettle', function () {
|
|
30
84
|
applyRelativeTimes(document);
|
|
31
85
|
});
|
|
86
|
+
/* Column drags / resets (table-resize.js) and window resizes change the available width. */
|
|
87
|
+
document.addEventListener('dc:columns-resized', function () {
|
|
88
|
+
applyRelativeTimes(document);
|
|
89
|
+
});
|
|
90
|
+
var timer;
|
|
91
|
+
globalThis.addEventListener('resize', function () {
|
|
92
|
+
clearTimeout(timer);
|
|
93
|
+
timer = setTimeout(function () { applyRelativeTimes(document); }, 150);
|
|
94
|
+
});
|
|
32
95
|
})();
|
package/assets/static/style.css
CHANGED
|
@@ -28,6 +28,9 @@
|
|
|
28
28
|
--md-table-even-bg: #f9fafb;
|
|
29
29
|
--md-strong: #111827;
|
|
30
30
|
--md-em: #7c3aed;
|
|
31
|
+
|
|
32
|
+
--check-border: #cbd5e1;
|
|
33
|
+
--check-bg: #ffffff;
|
|
31
34
|
}
|
|
32
35
|
|
|
33
36
|
.dark {
|
|
@@ -56,6 +59,9 @@
|
|
|
56
59
|
--md-table-even-bg: #111827;
|
|
57
60
|
--md-strong: #f3f4f6;
|
|
58
61
|
--md-em: #c4b5fd;
|
|
62
|
+
|
|
63
|
+
--check-border: #4b5563;
|
|
64
|
+
--check-bg: #111827;
|
|
59
65
|
}
|
|
60
66
|
|
|
61
67
|
/* ── Scrollbar ──────────────────────────────────────────────────────────── */
|
|
@@ -162,3 +168,67 @@
|
|
|
162
168
|
color: var(--md-table-td-color);
|
|
163
169
|
}
|
|
164
170
|
.markdown-body tr:nth-child(even) td { background: var(--md-table-even-bg); }
|
|
171
|
+
|
|
172
|
+
/* ── Lessons table: Select-mode checkboxes + drag-to-resize handles ─────────── */
|
|
173
|
+
|
|
174
|
+
.dc-check {
|
|
175
|
+
appearance: none;
|
|
176
|
+
-webkit-appearance: none;
|
|
177
|
+
width: 18px;
|
|
178
|
+
height: 18px;
|
|
179
|
+
border-radius: 5px;
|
|
180
|
+
border: 1.5px solid var(--check-border);
|
|
181
|
+
background: var(--check-bg);
|
|
182
|
+
vertical-align: middle;
|
|
183
|
+
cursor: pointer;
|
|
184
|
+
transition: background-color 0.12s, border-color 0.12s;
|
|
185
|
+
}
|
|
186
|
+
.dc-check:checked {
|
|
187
|
+
background-color: #4f46e5;
|
|
188
|
+
border-color: #4f46e5;
|
|
189
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='white' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 10.5l3.5 3.5L15 7'/%3E%3C/svg%3E");
|
|
190
|
+
background-size: 72%;
|
|
191
|
+
background-position: center;
|
|
192
|
+
background-repeat: no-repeat;
|
|
193
|
+
}
|
|
194
|
+
.dc-check:focus-visible {
|
|
195
|
+
outline: 2px solid #6366f1;
|
|
196
|
+
outline-offset: 2px;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/* The hit area is the last 10px of the header (inside its padding, so it never covers the label);
|
|
200
|
+
what you see is a 2px line drawn exactly on the column boundary. */
|
|
201
|
+
.dc-resize-handle {
|
|
202
|
+
position: absolute;
|
|
203
|
+
top: 0;
|
|
204
|
+
right: 0;
|
|
205
|
+
width: 10px;
|
|
206
|
+
height: 100%;
|
|
207
|
+
cursor: col-resize;
|
|
208
|
+
z-index: 1;
|
|
209
|
+
}
|
|
210
|
+
.dc-resize-handle::after {
|
|
211
|
+
content: "";
|
|
212
|
+
position: absolute;
|
|
213
|
+
top: 18%;
|
|
214
|
+
bottom: 18%;
|
|
215
|
+
right: 0;
|
|
216
|
+
width: 2px;
|
|
217
|
+
border-radius: 1px;
|
|
218
|
+
background-color: transparent;
|
|
219
|
+
transition: background-color 0.12s;
|
|
220
|
+
}
|
|
221
|
+
.dc-resize-handle:hover::after,
|
|
222
|
+
.dc-resizing .dc-resize-handle:active::after {
|
|
223
|
+
background-color: rgba(99, 102, 241, 0.85);
|
|
224
|
+
}
|
|
225
|
+
.dc-resizing {
|
|
226
|
+
user-select: none;
|
|
227
|
+
cursor: col-resize;
|
|
228
|
+
}
|
|
229
|
+
/* In Select mode every click on a row means "toggle it": links and forms inside stop reacting. */
|
|
230
|
+
.dc-selecting tbody a,
|
|
231
|
+
.dc-selecting tbody form,
|
|
232
|
+
.dc-selecting tbody button {
|
|
233
|
+
pointer-events: none;
|
|
234
|
+
}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
// Drag-to-resize table columns (the lessons table). Widths live on the <col> elements and are
|
|
2
|
+
// remembered per column in localStorage; double-click a handle to reset the two columns beside it,
|
|
3
|
+
// or call window.resetLessonColumns() (the ⋯ menu) to reset them all. Desktop widths only — on
|
|
4
|
+
// narrow screens columns are already hidden and a drag would fight scrolling.
|
|
5
|
+
//
|
|
6
|
+
// A drag moves the boundary between two neighbouring columns: one grows exactly as much as the
|
|
7
|
+
// other shrinks, so the table never changes width. One column (`<col data-flex>`, the title) never
|
|
8
|
+
// gets an explicit width: it absorbs whatever its neighbours give or take, clamped to MIN_FLEX so
|
|
9
|
+
// it stays readable. Stored widths that no longer fit (a narrower window) are dropped on load.
|
|
10
|
+
(function () {
|
|
11
|
+
var MIN = 48;
|
|
12
|
+
var MIN_FLEX = 220;
|
|
13
|
+
var STORAGE = "lessons-col-widths";
|
|
14
|
+
if (!globalThis.matchMedia || !globalThis.matchMedia("(min-width: 1024px)").matches) {
|
|
15
|
+
globalThis.resetLessonColumns = function () {};
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function load() {
|
|
20
|
+
try {
|
|
21
|
+
return JSON.parse(localStorage.getItem(STORAGE) || "{}") || {};
|
|
22
|
+
} catch {
|
|
23
|
+
return {};
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function save(widths) {
|
|
27
|
+
try {
|
|
28
|
+
localStorage.setItem(STORAGE, JSON.stringify(widths));
|
|
29
|
+
} catch {
|
|
30
|
+
/* storage unavailable: widths last for this page only */
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function clamp(v, lo, hi) {
|
|
34
|
+
return Math.min(hi, Math.max(lo, v));
|
|
35
|
+
}
|
|
36
|
+
// Each column declares the narrowest width its content survives (`data-min`); the flex column
|
|
37
|
+
// falls back to MIN_FLEX, the others to MIN.
|
|
38
|
+
function minOf(col) {
|
|
39
|
+
var m = Number(col.dataset.min);
|
|
40
|
+
if (m > 0) return m;
|
|
41
|
+
return col.hasAttribute("data-flex") ? MIN_FLEX : MIN;
|
|
42
|
+
}
|
|
43
|
+
function setWidth(col, px) {
|
|
44
|
+
col.style.width = Math.round(px) + "px";
|
|
45
|
+
}
|
|
46
|
+
// The defaults are inline widths on the <col>s: remember them so resets restore, not wipe.
|
|
47
|
+
function restore(col) {
|
|
48
|
+
col.style.width = col.dataset.defaultWidth || "";
|
|
49
|
+
}
|
|
50
|
+
// Let listeners (relative-time.js) react to the new widths.
|
|
51
|
+
function announce() {
|
|
52
|
+
document.dispatchEvent(new CustomEvent("dc:columns-resized"));
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
var tables = document.querySelectorAll("table[data-resizable]");
|
|
56
|
+
tables.forEach(function (table) {
|
|
57
|
+
var cols = Array.prototype.slice.call(table.querySelectorAll("colgroup > col"));
|
|
58
|
+
var ths = Array.prototype.slice.call(table.querySelectorAll("thead th"));
|
|
59
|
+
if (cols.length !== ths.length) return;
|
|
60
|
+
var widths = load();
|
|
61
|
+
cols.forEach(function (col) {
|
|
62
|
+
col.dataset.defaultWidth = col.style.width || "";
|
|
63
|
+
});
|
|
64
|
+
var flexIndex = cols.findIndex(function (col) {
|
|
65
|
+
return col.hasAttribute("data-flex");
|
|
66
|
+
});
|
|
67
|
+
var flexTh = flexIndex >= 0 ? ths[flexIndex] : null;
|
|
68
|
+
function flexWidth() {
|
|
69
|
+
return flexTh ? flexTh.getBoundingClientRect().width : Infinity;
|
|
70
|
+
}
|
|
71
|
+
function apply() {
|
|
72
|
+
cols.forEach(function (col) {
|
|
73
|
+
var px = widths[col.dataset.col];
|
|
74
|
+
if (typeof px === "number" && px >= minOf(col)) col.style.width = px + "px";
|
|
75
|
+
else restore(col);
|
|
76
|
+
});
|
|
77
|
+
if (flexWidth() < MIN_FLEX) {
|
|
78
|
+
// The remembered layout does not fit this window: fall back to the defaults.
|
|
79
|
+
widths = {};
|
|
80
|
+
cols.forEach(restore);
|
|
81
|
+
}
|
|
82
|
+
announce();
|
|
83
|
+
}
|
|
84
|
+
apply();
|
|
85
|
+
var resizeTimer;
|
|
86
|
+
globalThis.addEventListener("resize", function () {
|
|
87
|
+
clearTimeout(resizeTimer);
|
|
88
|
+
resizeTimer = setTimeout(apply, 150);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
function nextVisible(i) {
|
|
92
|
+
for (var j = i + 1; j < ths.length; j++) {
|
|
93
|
+
if (ths[j].getBoundingClientRect().width > 0) return j;
|
|
94
|
+
}
|
|
95
|
+
return -1;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
ths.forEach(function (th, i) {
|
|
99
|
+
// The star column stays fixed, and the share column (last) is never a drag partner.
|
|
100
|
+
if (i === 0 || i >= ths.length - 2) return;
|
|
101
|
+
var handle = document.createElement("span");
|
|
102
|
+
handle.className = "dc-resize-handle";
|
|
103
|
+
handle.setAttribute("aria-hidden", "true");
|
|
104
|
+
th.appendChild(handle);
|
|
105
|
+
|
|
106
|
+
handle.addEventListener("click", function (e) {
|
|
107
|
+
e.stopPropagation();
|
|
108
|
+
});
|
|
109
|
+
handle.addEventListener("dblclick", function (e) {
|
|
110
|
+
e.stopPropagation();
|
|
111
|
+
var j = nextVisible(i);
|
|
112
|
+
[cols[i], j >= 0 ? cols[j] : null].forEach(function (col) {
|
|
113
|
+
if (!col || col.hasAttribute("data-flex")) return;
|
|
114
|
+
restore(col);
|
|
115
|
+
delete widths[col.dataset.col];
|
|
116
|
+
});
|
|
117
|
+
save(widths);
|
|
118
|
+
announce();
|
|
119
|
+
});
|
|
120
|
+
handle.addEventListener("pointerdown", function (e) {
|
|
121
|
+
if (e.button !== 0) return;
|
|
122
|
+
var j = nextVisible(i);
|
|
123
|
+
if (j < 0) return;
|
|
124
|
+
e.preventDefault();
|
|
125
|
+
e.stopPropagation();
|
|
126
|
+
var left = cols[i];
|
|
127
|
+
var right = cols[j];
|
|
128
|
+
var leftFlex = left.hasAttribute("data-flex");
|
|
129
|
+
var rightFlex = right.hasAttribute("data-flex");
|
|
130
|
+
var startX = e.clientX;
|
|
131
|
+
var startL = th.getBoundingClientRect().width;
|
|
132
|
+
var startR = ths[j].getBoundingClientRect().width;
|
|
133
|
+
var total = startL + startR;
|
|
134
|
+
var minL = minOf(left);
|
|
135
|
+
var minR = minOf(right);
|
|
136
|
+
if (total < minL + minR) return; // nothing to give either way
|
|
137
|
+
handle.setPointerCapture(e.pointerId);
|
|
138
|
+
table.classList.add("dc-resizing");
|
|
139
|
+
function move(ev) {
|
|
140
|
+
var dx = ev.clientX - startX;
|
|
141
|
+
if (leftFlex) {
|
|
142
|
+
setWidth(right, clamp(startR - dx, minR, total - minL));
|
|
143
|
+
} else if (rightFlex) {
|
|
144
|
+
setWidth(left, clamp(startL + dx, minL, total - minR));
|
|
145
|
+
} else {
|
|
146
|
+
var l = clamp(startL + dx, minL, total - minR);
|
|
147
|
+
setWidth(left, l);
|
|
148
|
+
setWidth(right, total - l);
|
|
149
|
+
}
|
|
150
|
+
announce();
|
|
151
|
+
}
|
|
152
|
+
function up() {
|
|
153
|
+
handle.removeEventListener("pointermove", move);
|
|
154
|
+
handle.removeEventListener("pointerup", up);
|
|
155
|
+
handle.removeEventListener("pointercancel", up);
|
|
156
|
+
table.classList.remove("dc-resizing");
|
|
157
|
+
if (!leftFlex) widths[left.dataset.col] = Math.round(th.getBoundingClientRect().width);
|
|
158
|
+
if (!rightFlex) widths[right.dataset.col] = Math.round(ths[j].getBoundingClientRect().width);
|
|
159
|
+
save(widths);
|
|
160
|
+
announce();
|
|
161
|
+
}
|
|
162
|
+
handle.addEventListener("pointermove", move);
|
|
163
|
+
handle.addEventListener("pointerup", up);
|
|
164
|
+
handle.addEventListener("pointercancel", up);
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
globalThis.resetLessonColumns = function () {
|
|
170
|
+
try {
|
|
171
|
+
localStorage.removeItem(STORAGE);
|
|
172
|
+
} catch {
|
|
173
|
+
/* ignore */
|
|
174
|
+
}
|
|
175
|
+
document.querySelectorAll("table[data-resizable] colgroup > col").forEach(restore);
|
|
176
|
+
announce();
|
|
177
|
+
};
|
|
178
|
+
})();
|