diff --git a/modules/agent/views/scripts/skills/index.phtml b/modules/agent/views/scripts/skills/index.phtml index 60ce311..887fe95 100644 --- a/modules/agent/views/scripts/skills/index.phtml +++ b/modules/agent/views/scripts/skills/index.phtml @@ -79,6 +79,26 @@ document.addEventListener('DOMContentLoaded', function () { } function toast(res) { ((res && res.messages) || []).forEach(function (m) { TigerDOM.toast(m.message, { type: m.class }); }); } + // A skill entry rides on the button as individual data-* attrs (NOT a JSON blob: esc() doesn't + // quote-escape, so JSON in a double-quoted attribute breaks). attr() adds the missing "-escape. + function attr(s) { return esc(s).replace(/"/g, '"'); } + function entryAttrs(row) { + return ' data-source="' + attr(row.source) + '" data-sourcelabel="' + attr(row.sourceLabel) + '"' + + ' data-name="' + attr(row.name) + '" data-repo="' + attr(row.repo) + '"' + + ' data-ref="' + attr(row.ref) + '" data-path="' + attr(row.path) + '" data-url="' + attr(row.url) + '"'; + } + function readEntry(el) { + return { + source: el.getAttribute('data-source') || '', + sourceLabel: el.getAttribute('data-sourcelabel') || '', + name: el.getAttribute('data-name') || '', + repo: el.getAttribute('data-repo') || '', + ref: el.getAttribute('data-ref') || '', + path: el.getAttribute('data-path') || '', + url: el.getAttribute('data-url') || '' + }; + } + var table = tigerDataTable('#sk-table', { service: { module: 'agent', service: 'skills', action: 'datatable' }, ordering: false, // installed-first pinning is authoritative (server-side) @@ -109,13 +129,10 @@ document.addEventListener('DOMContentLoaded', function () { var h = ''; // View source (always) — key if installed, else the repo/ref/path for a live fetch. h += ' '; if (!row.installed) { - h += ''; } else { h += row.active @@ -130,7 +147,7 @@ document.addEventListener('DOMContentLoaded', function () { // ---- actions (delegated) ---- $('#sk-table tbody').on('click', '.sk-install', function () { - var entry = JSON.parse(this.getAttribute('data-entry') || '{}'); + var entry = readEntry(this); TigerButton.run(this, function () { return api('install', entry); }).then(function (res) { toast(res); table.ajax.reload(null, false); }); @@ -155,7 +172,7 @@ document.addEventListener('DOMContentLoaded', function () { $('#sk-table tbody').on('click', '.sk-src', function () { var b = this; var key = b.getAttribute('data-key'); - srcEntry = key ? null : JSON.parse(b.getAttribute('data-entry') || '{}'); + srcEntry = key ? null : readEntry(b); document.getElementById('sk-src-title').textContent = (b.getAttribute('data-name') || 'SKILL') + '.md'; document.getElementById('sk-src-sub').textContent = b.getAttribute('data-repo') || ''; document.getElementById('sk-src-body').textContent = 'Loading…';