/* daspkg.js — fetch the live package index, render filterable card grid.
* Source of truth: github.com/borisbat/daspkg-index/packages.json. */
(function () {
'use strict';
var INDEX_URL = 'https://raw.githubusercontent.com/borisbat/daspkg-index/main/packages.json';
var els = {
list: document.getElementById('daspkg-list'),
status: document.getElementById('daspkg-status'),
tags: document.getElementById('daspkg-tags'),
search: document.getElementById('daspkg-search'),
searchClear: document.getElementById('daspkg-search-clear'),
countN: document.getElementById('daspkg-count-n'),
countTotal: document.getElementById('daspkg-count-total'),
publishCount: document.getElementById('daspkg-publish-count'),
};
var state = {
all: [],
allTags: [],
query: '',
activeTags: [],
};
function esc(s) {
return String(s == null ? '' : s)
.replace(/&/g, '&')
.replace(//g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
function applyFilter() {
var q = state.query.trim().toLowerCase();
return state.all.filter(function (p) {
if (state.activeTags.length) {
var tags = p.tags || [];
for (var i = 0; i < state.activeTags.length; i++) {
if (tags.indexOf(state.activeTags[i]) === -1) return false;
}
}
if (!q) return true;
if (p.name && p.name.toLowerCase().indexOf(q) !== -1) return true;
if (p.description && p.description.toLowerCase().indexOf(q) !== -1) return true;
if (p.author && p.author.toLowerCase().indexOf(q) !== -1) return true;
var ts = p.tags || [];
for (var j = 0; j < ts.length; j++) if (ts[j].toLowerCase().indexOf(q) !== -1) return true;
return false;
});
}
function renderTags() {
els.tags.innerHTML = state.allTags.map(function (t) {
var active = state.activeTags.indexOf(t) !== -1;
return '';
}).join('');
}
function renderCards(pkgs) {
if (!pkgs.length) {
els.list.innerHTML = '';
els.status.textContent = 'no packages match the filter';
els.status.hidden = false;
return;
}
els.status.hidden = true;
els.list.innerHTML = pkgs.map(function (p) {
var native = p.has_native
? 'native' : '';
var sdk = p.min_sdk
? 'sdk ≥ ' + esc(p.min_sdk) + '' : '';
var license = p.license
? '' + esc(p.license) + '' : '';
var tags = (p.tags || []).map(function (t) {
return '' + esc(t) + '';
}).join('');
var deps = (p.dependencies && p.dependencies.length)
? '
↳ depends on ' +
p.dependencies.map(esc).join(', ') + '
' : '';
var url = p.url ? 'https://' + p.url : '#';
var installStr = 'daspkg install ' + p.name;
return '' +
'' +
'' +
'
' +
'
' + esc(p.name) + '
' + native + sdk +
'' + license +
'
' +
'' + esc(p.description || '') + '
' +
'' + tags + '
' +
deps +
'' +
'';
}).join('');
}
function updateCounts(visible) {
els.countN.textContent = visible;
els.countTotal.textContent = state.all.length;
els.publishCount.textContent = visible + ' of ' + state.all.length + ' packages';
}
function rerender() {
var pkgs = applyFilter();
renderTags();
renderCards(pkgs);
updateCounts(pkgs.length);
}
function copyToClipboard(text, srcEl) {
var done = function (ok) {
if (!srcEl) return;
var prev = srcEl.textContent;
srcEl.textContent = ok ? '✓' : '⎘';
setTimeout(function () { srcEl.textContent = prev; }, 900);
};
if (navigator.clipboard && navigator.clipboard.writeText) {
navigator.clipboard.writeText(text).then(function () { done(true); }, function () { done(false); });
} else {
try {
var ta = document.createElement('textarea');
ta.value = text;
ta.style.position = 'fixed';
ta.style.opacity = '0';
document.body.appendChild(ta);
ta.select();
var ok = document.execCommand('copy');
document.body.removeChild(ta);
done(ok);
} catch (e) { done(false); }
}
}
function wireEvents() {
els.tags.addEventListener('click', function (e) {
var btn = e.target.closest('[data-tag]');
if (!btn) return;
var tag = btn.getAttribute('data-tag');
var i = state.activeTags.indexOf(tag);
if (i === -1) state.activeTags.push(tag);
else state.activeTags.splice(i, 1);
rerender();
});
els.search.addEventListener('input', function () {
state.query = els.search.value;
els.searchClear.hidden = !state.query;
rerender();
});
els.searchClear.addEventListener('click', function () {
els.search.value = '';
state.query = '';
els.searchClear.hidden = true;
rerender();
els.search.focus();
});
document.addEventListener('click', function (e) {
var copy = e.target.closest('[data-copy]');
if (!copy) return;
e.preventDefault();
e.stopPropagation();
copyToClipboard(copy.getAttribute('data-copy'), copy);
});
}
function init(packages) {
state.all = packages.slice();
var tagSet = {};
state.all.forEach(function (p) {
(p.tags || []).forEach(function (t) { tagSet[t] = true; });
});
state.allTags = Object.keys(tagSet).sort();
wireEvents();
rerender();
}
function fail(err) {
els.status.textContent = 'failed to load package index — ' + (err && err.message ? err.message : 'network error');
els.publishCount.textContent = '— packages';
els.countN.textContent = '0';
els.countTotal.textContent = '0';
}
fetch(INDEX_URL, { cache: 'no-cache' })
.then(function (r) {
if (!r.ok) throw new Error('HTTP ' + r.status);
return r.json();
})
.then(init)
.catch(fail);
}());