luci-app-package-manager: js linting fixes / ES6 treatment
authorPaul Donald <newtwen+github@gmail.com>
Sun, 15 Feb 2026 05:52:47 +0000 (06:52 +0100)
committerPaul Donald <newtwen+github@gmail.com>
Mon, 16 Feb 2026 00:42:57 +0000 (01:42 +0100)
Signed-off-by: Paul Donald <newtwen+github@gmail.com>
applications/luci-app-package-manager/htdocs/luci-static/resources/view/package-manager.js

index 8a70b4bd29ad334810af94f4d0fe8ac5e265c018..48476dbe167f8ce4bc8a552728f132810ae7084c 100644 (file)
@@ -4,7 +4,7 @@
 'require ui';
 'require rpc';
 
-var css = '                                                            \
+const css = '                                                          \
        .controls {                                                     \
                display: flex;                                  \
                margin: .5em 0 1em 0;                   \
@@ -85,7 +85,7 @@ var css = '                                                           \
        }                                                                       \
 ';
 
-var isReadonlyView = !L.hasViewPermission() || null;
+const isReadonlyView = !L.hasViewPermission() || null;
 
 const callMountPoints = rpc.declare({
        object: 'luci',
@@ -93,19 +93,21 @@ const callMountPoints = rpc.declare({
        expect: { result: [] }
 });
 
-var packages = {
+const packages = {
        available: { providers: {}, pkgs: {} },
        installed: { providers: {}, pkgs: {} }
 };
 
-var languages = ['en'];
+const languages = ['en'];
 
-var currentDisplayMode = 'available', currentDisplayRows = [];
+let currentDisplayMode = 'available'
+const currentDisplayRows = [];
 
 function parseList(s, dest)
 {
-       var re = /([^\n]*)\n/g,
-           pkg = null, key = null, val = null, m;
+       const re = /([^\n]*)\n/g;
+       let pkg = null, key = null, val = null, m;
+       let list, stat, mode, installed;
 
        while ((m = re.exec(s)) !== null) {
                if (m[1].match(/^\s(.*)$/)) {
@@ -123,7 +125,7 @@ function parseList(s, dest)
 
                        case 'depends':
                        case 'provides':
-                               var list = val.split(/\s*,\s*/);
+                               list = val.split(/\s*,\s*/);
                                if (list.length !== 1 || list[0].length > 0)
                                        pkg[key] = list;
                                break;
@@ -137,9 +139,9 @@ function parseList(s, dest)
                                break;
 
                        case 'status':
-                               var stat = val.split(/\s+/),
-                                   mode = stat[1],
-                                   installed = stat[2];
+                               stat = val.split(/\s+/);
+                               mode = stat[1];
+                               installed = stat[2];
 
                                switch (mode) {
                                case 'user':
@@ -186,7 +188,7 @@ function parseList(s, dest)
                else if (pkg) {
                        dest.pkgs[pkg.name] = pkg;
 
-                       var provides = dest.providers[pkg.name] ? [] : [ pkg.name ];
+                       const provides = dest.providers[pkg.name] ? [] : [ pkg.name ];
 
                        if (pkg.provides)
                                provides.push.apply(provides, pkg.provides);
@@ -201,10 +203,9 @@ function parseList(s, dest)
 
 function display(pattern)
 {
-       var src = packages[currentDisplayMode === 'updates' ? 'installed' : currentDisplayMode],
-           table = document.querySelector('#packages'),
-           pagers = document.querySelectorAll('.controls > .pager'),
-           i18n_filter = null;
+       const src = packages[currentDisplayMode === 'updates' ? 'installed' : currentDisplayMode];
+       const pagers = document.querySelectorAll('.controls > .pager');
+       let i18n_filter = null;
 
        currentDisplayRows.length = 0;
 
@@ -221,10 +222,10 @@ function display(pattern)
                break;
        }
 
-       for (var name in src.pkgs) {
-               var pkg = src.pkgs[name],
-                   desc = pkg.description || '',
-                   altsize = null;
+       for (let name in src.pkgs) {
+               const pkg = src.pkgs[name];
+               let desc = pkg.description || '';
+               let altsize = null;
 
                if (!pkg.size && packages.available.pkgs[name])
                        altsize = packages.available.pkgs[name].size;
@@ -242,11 +243,11 @@ function display(pattern)
                if (name.indexOf('luci-i18n-') === 0 && (!(i18n_filter instanceof RegExp) || !name.match(i18n_filter)))
                        continue;
 
-               var btn, ver;
+               let btn, ver;
 
                if (currentDisplayMode === 'updates') {
-                       var avail = packages.available.pkgs[name],
-                           inst  = packages.installed.pkgs[name];
+                       const avail = packages.available.pkgs[name];
+                       const inst  = packages.installed.pkgs[name];
 
                        if (!inst || !inst.installed)
                                continue;
@@ -277,7 +278,7 @@ function display(pattern)
                        }, _('Remove…'));
                }
                else {
-                       var inst = packages.installed.pkgs[name];
+                       const inst = packages.installed.pkgs[name];
 
                        ver = truncateVersion(pkg.version || '-');
 
@@ -330,9 +331,9 @@ function display(pattern)
                        return 0;
        });
 
-       for (var i = 0; i < pagers.length; i++) {
-               pagers[i].parentNode.style.display = '';
-               pagers[i].setAttribute('data-offset', 100);
+       for (let pager of pagers) {
+               pager.parentNode.style.display = '';
+               pager.setAttribute('data-offset', 100);
        }
 
        handlePage({ target: pagers[0].querySelector('.prev') });
@@ -340,10 +341,10 @@ function display(pattern)
 
 function handlePage(ev)
 {
-       var filter = document.querySelector('input[name="filter"]'),
-           offset = +ev.target.parentNode.getAttribute('data-offset'),
-           next = ev.target.classList.contains('next'),
-           pagers = document.querySelectorAll('.controls > .pager');
+       const filter = document.querySelector('input[name="filter"]');
+       let offset = +ev.target.parentNode.getAttribute('data-offset');
+       const next = ev.target.classList.contains('next');
+       const pagers = document.querySelectorAll('.controls > .pager');
 
        if ((next && (offset + 100) >= currentDisplayRows.length) ||
            (!next && (offset < 100)))
@@ -351,24 +352,24 @@ function handlePage(ev)
 
        offset += next ? 100 : -100;
 
-       for (var i = 0; i < pagers.length; i++) {
-               pagers[i].setAttribute('data-offset', offset);
-               pagers[i].querySelector('.text').firstChild.data = currentDisplayRows.length
+       for (let pager of pagers) {
+               pager.setAttribute('data-offset', offset);
+               pager.querySelector('.text').firstChild.data = currentDisplayRows.length
                        ? _('Displaying %d-%d of %d').format(1 + offset, Math.min(offset + 100, currentDisplayRows.length), currentDisplayRows.length)
                        : _('No packages');
 
                if (offset < 100)
-                       pagers[i].querySelector('.prev').setAttribute('disabled', 'disabled');
+                       pager.querySelector('.prev').setAttribute('disabled', 'disabled');
                else
-                       pagers[i].querySelector('.prev').removeAttribute('disabled');
+                       pager.querySelector('.prev').removeAttribute('disabled');
 
                if ((offset + 100) >= currentDisplayRows.length)
-                       pagers[i].querySelector('.next').setAttribute('disabled', 'disabled');
+                       pager.querySelector('.next').setAttribute('disabled', 'disabled');
                else
-                       pagers[i].querySelector('.next').removeAttribute('disabled');
+                       pager.querySelector('.next').removeAttribute('disabled');
        }
 
-       var placeholder = _('No information available');
+       let placeholder = _('No information available');
 
        if (filter.value)
                placeholder = [
@@ -382,7 +383,7 @@ function handlePage(ev)
 
 function handleMode(ev)
 {
-       var tab = findParent(ev.target, 'li');
+       const tab = findParent(ev.target, 'li');
        if (tab.getAttribute('data-mode') === currentDisplayMode)
                return;
 
@@ -421,8 +422,8 @@ function orderOf(c)
 
 function compareVersion(val, ref)
 {
-       var vi = 0, ri = 0,
-           isdigit = { 0:1, 1:1, 2:1, 3:1, 4:1, 5:1, 6:1, 7:1, 8:1, 9:1 };
+       let vi = 0, ri = 0;
+       const isdigit = { 0:1, 1:1, 2:1, 3:1, 4:1, 5:1, 6:1, 7:1, 8:1, 9:1 };
 
        val = val || '';
        ref = ref || '';
@@ -431,11 +432,11 @@ function compareVersion(val, ref)
                return 0;
 
        while (vi < val.length || ri < ref.length) {
-               var first_diff = 0;
+               let first_diff = 0;
 
                while ((vi < val.length && !isdigit[val.charAt(vi)]) ||
                       (ri < ref.length && !isdigit[ref.charAt(ri)])) {
-                       var vc = orderOf(val.charAt(vi)), rc = orderOf(ref.charAt(ri));
+                       const vc = orderOf(val.charAt(vi)), rc = orderOf(ref.charAt(ri));
                        if (vc !== rc)
                                return vc - rc;
 
@@ -466,7 +467,7 @@ function compareVersion(val, ref)
 
 function versionSatisfied(ver, ref, vop)
 {
-       var r = compareVersion(ver, ref);
+       const r = compareVersion(ver, ref);
 
        switch (vop) {
        case '<':
@@ -497,7 +498,7 @@ function pkgStatus(pkg, vop, ver, info)
 
        if (pkg.installed) {
                if (vop && !versionSatisfied(pkg.version, ver, vop)) {
-                       var repl = null;
+                       let repl = null;
 
                        (packages.available.providers[pkg.name] || []).forEach(function(p) {
                                if (!repl && versionSatisfied(p.version, ver, vop))
@@ -548,20 +549,20 @@ function pkgStatus(pkg, vop, ver, info)
 
 function renderDependencyItem(dep, info, flat)
 {
-       var li = E('li'),
-           vop = dep.version ? dep.version[0] : null,
-           ver = dep.version ? dep.version[1] : null,
-           depends = [];
+       const li = E('li');
+       const vop = dep.version ? dep.version[0] : null;
+       const ver = dep.version ? dep.version[1] : null;
+       const depends = [];
 
-       for (var i = 0; dep.pkgs && i < dep.pkgs.length; i++) {
-               var pkg = packages.installed.pkgs[dep.pkgs[i]] ||
+       for (let i = 0; dep.pkgs && i < dep.pkgs.length; i++) {
+               const pkg = packages.installed.pkgs[dep.pkgs[i]] ||
                          packages.available.pkgs[dep.pkgs[i]] ||
                          { name: dep.name };
 
                if (i > 0)
                        li.appendChild(document.createTextNode(' | '));
 
-               var text = pkg.name;
+               let text = pkg.name;
 
                if (pkg.installsize)
                        text += ' (%1024mB)'.format(pkg.installsize);
@@ -583,7 +584,7 @@ function renderDependencyItem(dep, info, flat)
                          pkgStatus({ name: dep.name, missing: true }, vop, ver, info) ]));
 
        if (!flat) {
-               var subdeps = renderDependencies(depends, info);
+               const subdeps = renderDependencies(depends, info);
                if (subdeps)
                        li.appendChild(subdeps);
        }
@@ -593,13 +594,13 @@ function renderDependencyItem(dep, info, flat)
 
 function renderDependencies(depends, info, flat)
 {
-       var deps = depends || [],
-           items = [];
+       const deps = depends || [];
+       const items = [];
 
        info.seen = info.seen || [];
 
-       for (var i = 0; i < deps.length; i++) {
-               var dep, vop, ver;
+       for (let i = 0; i < deps.length; i++) {
+               let dep, vop, ver;
 
                if (deps[i] === 'libc')
                        continue;
@@ -617,7 +618,7 @@ function renderDependencies(depends, info, flat)
                if (info.seen[dep])
                        continue;
 
-               var pkgs = [];
+               const pkgs = [];
 
                (packages.installed.providers[dep] || []).forEach(function(p) {
                        if (pkgs.indexOf(p.name) === -1) pkgs.push(p.name);
@@ -655,7 +656,7 @@ function truncateVersion(v, op)
 
 function handleReset(ev)
 {
-       var filter = document.querySelector('input[name="filter"]');
+       const filter = document.querySelector('input[name="filter"]');
 
        filter.value = '';
        display();
@@ -663,11 +664,11 @@ function handleReset(ev)
 
 function handleInstall(ev)
 {
-       var name = ev.target.getAttribute('data-package'),
-           installcmd = ev.target.getAttribute('data-action'),
-           pkg = packages.available.pkgs[name],
-           depcache = {},
-           size;
+       const name = ev.target.getAttribute('data-package');
+       const installcmd = ev.target.getAttribute('data-action');
+       const pkg = packages.available.pkgs[name];
+       const depcache = {};
+       let size;
 
        if (pkg.installsize)
                size = _('~%1024mB installed').format(pkg.installsize);
@@ -676,8 +677,8 @@ function handleInstall(ev)
        else
                size = _('unknown');
 
-       var deps = renderDependencies(pkg.depends, depcache),
-           tree = null, errs = null, inst = null, desc = null;
+       const deps = renderDependencies(pkg.depends, depcache);
+       let tree = null, errs = null, inst = null, desc = null;
 
        if (depcache.errors && depcache.errors.length) {
                errs = E('ul', { 'class': 'errors' });
@@ -686,9 +687,9 @@ function handleInstall(ev)
                });
        }
 
-       var totalsize = pkg.installsize || pkg.size || 0,
-           totalpkgs = 1,
-           suggestsize = 0;
+       let totalsize = pkg.installsize || pkg.size || 0;
+       let totalpkgs = 1;
+       let suggestsize = 0;
 
        if (depcache.install && depcache.install.length)
                depcache.install.forEach(function(ipkg) {
@@ -696,18 +697,18 @@ function handleInstall(ev)
                        totalpkgs++;
                });
 
-       var luci_basename = pkg.name.match(/^luci-([^-]+)-(.+)$/),
-           i18n_packages = [],
-           i18n_tree;
+       const luci_basename = pkg.name.match(/^luci-([^-]+)-(.+)$/);
+       const i18n_packages = [];
+       let i18n_tree;
 
        if (luci_basename && (luci_basename[1] != 'i18n' || luci_basename[2].indexOf('base-') === 0)) {
-               var i18n_filter;
+               let i18n_filter;
 
                if (luci_basename[1] == 'i18n') {
-                       var basenames = [];
+                       const basenames = [];
 
-                       for (var pkgname in packages.installed.pkgs) {
-                               var m = pkgname.match(/^luci-([^-]+)-(.+)$/);
+                       for (let pkgname in packages.installed.pkgs) {
+                               const m = pkgname.match(/^luci-([^-]+)-(.+)$/);
 
                                if (m && m[1] != 'i18n')
                                        basenames.push(m[2]);
@@ -721,11 +722,11 @@ function handleInstall(ev)
                }
 
                if (i18n_filter) {
-                       for (var pkgname in packages.available.pkgs)
+                       for (let pkgname in packages.available.pkgs)
                                if (pkgname != pkg.name && pkgname.match(i18n_filter))
                                        i18n_packages.push(pkgname);
 
-                       var i18ncache = {};
+                       const i18ncache = {};
 
                        i18n_tree = renderDependencies(i18n_packages, i18ncache, true);
 
@@ -816,8 +817,8 @@ function handleInstall(ev)
 
 function handleManualInstall(ev)
 {
-       var name_or_url = document.querySelector('input[name="install"]').value,
-           install = E('div', {
+       const name_or_url = document.querySelector('input[name="install"]').value;
+       let install = E('div', {
                        'class': 'btn cbi-button-action',
                        'data-command': 'install',
                        'data-package': name_or_url,
@@ -825,7 +826,8 @@ function handleManualInstall(ev)
                                document.querySelector('input[name="install"]').value = '';
                                handlePkg(ev);
                        }
-               }, _('Install')), warning;
+               }, _('Install'));
+       let warning;
 
        if (!name_or_url.length) {
                return;
@@ -855,15 +857,15 @@ function handleManualInstall(ev)
 
 function handleConfig(ev)
 {
-       var conf = {};
-       var base_dir = L.hasSystemFeature('apk') ? '/etc/apk' : '/etc/opkg';
+       const conf = {};
+       const base_dir = L.hasSystemFeature('apk') ? '/etc/apk' : '/etc/opkg';
 
        ui.showModal(_('%s Configuration').format(L.hasSystemFeature('apk') ? 'APK' : 'OPKG'), [
                E('p', { 'class': 'spinning' }, _('Loading configuration data…'))
        ]);
 
        fs.list(base_dir).then(function(partials) {
-               var files = [];
+               const files = [];
 
                if (L.hasSystemFeature('apk')) {
                         files.push(base_dir + '/' + 'repositories.d/customfeeds.list',
@@ -873,7 +875,7 @@ function handleConfig(ev)
                         files.push(base_dir + '.conf')
                 }
 
-               for (var i = 0; i < partials.length; i++) {
+               for (let i = 0; i < partials.length; i++) {
                        if (partials[i].type == 'file') {
                                if (L.hasSystemFeature('apk')) {
                                        if (partials[i].name == 'repositories')
@@ -894,9 +896,9 @@ function handleConfig(ev)
                                });
                }));
        }).then(function() {
-               var opkg_text = _('Below is a listing of the various configuration files used by <em>opkg</em>. Use <em>opkg.conf</em> for global settings and <em>customfeeds.conf</em> for custom repository entries. The configuration in the other files may be changed but is usually not preserved by <em>sysupgrade</em>.')
-               var apk_text = _('Below is a listing of the various configuration files used by <em>apk</em>. The configuration in the other files may be changed but is usually not preserved by <em>sysupgrade</em>.')
-               var body = [
+               const opkg_text = _('Below is a listing of the various configuration files used by <em>opkg</em>. Use <em>opkg.conf</em> for global settings and <em>customfeeds.conf</em> for custom repository entries. The configuration in the other files may be changed but is usually not preserved by <em>sysupgrade</em>.')
+               const apk_text = _('Below is a listing of the various configuration files used by <em>apk</em>. The configuration in the other files may be changed but is usually not preserved by <em>sysupgrade</em>.')
+               const body = [
                        E('p', {}, L.hasSystemFeature('apk') ? apk_text : opkg_text)
                ];
 
@@ -917,7 +919,7 @@ function handleConfig(ev)
                        E('div', {
                                'class': 'btn cbi-button-positive',
                                'click': function(ev) {
-                                       var data = {};
+                                       const data = {};
                                        findParent(ev.target, '.modal').querySelectorAll('textarea[name]')
                                                .forEach(function(textarea) {
                                                        data[textarea.getAttribute('name')] = textarea.value
@@ -943,10 +945,10 @@ function handleConfig(ev)
 
 function handleRemove(ev)
 {
-       var name = ev.target.getAttribute('data-package'),
-           pkg = packages.installed.pkgs[name],
-           avail = packages.available.pkgs[name] || {},
-           size, desc;
+       const name = ev.target.getAttribute('data-package');
+       const pkg = packages.installed.pkgs[name];
+       const avail = packages.available.pkgs[name] || {};
+       let size, desc;
 
        if (avail.installsize)
                size = _('~%1024mB installed').format(avail.installsize);
@@ -995,18 +997,18 @@ function handleRemove(ev)
 function handlePkg(ev)
 {
        return new Promise(function(resolveFn, rejectFn) {
-               var cmd = ev.target.getAttribute('data-command'),
-                   pkg = ev.target.getAttribute('data-package'),
-                   rem = document.querySelector('input[name="autoremove"]'),
-                   owr = document.querySelector('input[name="overwrite"]'),
-                   i18n = document.querySelector('input[name="i18ninstall"]');
+               const cmd = ev.target.getAttribute('data-command');
+               const pkg = ev.target.getAttribute('data-package');
+               const rem = document.querySelector('input[name="autoremove"]');
+               const owr = document.querySelector('input[name="overwrite"]');
+               const i18n = document.querySelector('input[name="i18ninstall"]');
 
-               var dlg = ui.showModal(_('Executing package manager'), [
+               const dlg = ui.showModal(_('Executing package manager'), [
                        E('p', { 'class': 'spinning' },
                                _('Waiting for the <em>%s %h</em> command to complete…').format(L.hasSystemFeature('apk') ? 'apk' : 'opkg', cmd))
                ]);
 
-               var argv = [ cmd ];
+               const argv = [ cmd ];
 
                if (cmd == 'remove')
                        argv.push('--force-removal-of-dependent-packages')
@@ -1065,7 +1067,7 @@ function handlePkg(ev)
 
 function handleUpload(ev)
 {
-       var path = '/tmp/upload.%s'.format(L.hasSystemFeature('apk') ? 'apk' : 'ipk');
+       const path = '/tmp/upload.%s'.format(L.hasSystemFeature('apk') ? 'apk' : 'ipk');
        return ui.uploadFile(path).then(L.bind(function(btn, res) {
                ui.showModal(_('Manually install package'), [
                        E('p', {}, _('Installing packages from untrusted sources is a potential security risk! Really attempt to install <em>%h</em>?').format(res.name)),
@@ -1115,8 +1117,8 @@ function updateLists(data)
        packages.installed = { providers: {}, pkgs: {} };
 
        return (data ? Promise.resolve(data) : downloadLists()).then(function(data) {
-               var pg = document.querySelector('.cbi-progressbar'),
-                       mount = L.toArray(data[0].filter(function(m) { return m.mount == '/' || m.mount == '/overlay' }))
+               const pg = document.querySelector('.cbi-progressbar');
+               const mount = L.toArray(data[0].filter(function(m) { return m.mount == '/' || m.mount == '/overlay' }))
                                .sort(function(a, b) { return a.mount > b.mount })[0] || { size: 0, free: 0 };
 
                pg.firstElementChild.style.width = Math.floor(mount.size ? (100 / mount.size) * (mount.size - mount.free) : 100) + '%';
@@ -1125,7 +1127,7 @@ function updateLists(data)
                parseList(data[1], packages.available);
                parseList(data[2], packages.installed);
 
-               for (var pkgname in packages.installed.pkgs)
+               for (let pkgname in packages.installed.pkgs)
                        if (pkgname.indexOf('luci-i18n-base-') === 0)
                                languages.push(pkgname.substring(15));
 
@@ -1133,7 +1135,7 @@ function updateLists(data)
        });
 }
 
-var inputTimeout = null;
+let inputTimeout = null;
 
 function handleInput(ev) {
        if (inputTimeout !== null)
@@ -1145,14 +1147,14 @@ function handleInput(ev) {
 }
 
 return view.extend({
-       load: function() {
+       load() {
                return downloadLists();
        },
 
-       render: function(listData) {
-               var query = decodeURIComponent(L.toArray(location.search.match(/\bquery=([^=]+)\b/))[1] || '');
+       render(listData) {
+               const query = decodeURIComponent(L.toArray(location.search.match(/\bquery=([^=]+)\b/))[1] || '');
 
-               var view = E([], [
+               const view = E([], [
                        E('style', { 'type': 'text/css' }, [ css ]),
 
                        E('h2', {}, _('Software')),