luci-base: js linting fixes
authorPaul Donald <redacted>
Sat, 14 Feb 2026 18:02:34 +0000 (19:02 +0100)
committerPaul Donald <redacted>
Mon, 16 Feb 2026 00:42:57 +0000 (01:42 +0100)
Signed-off-by: Paul Donald <redacted>
modules/luci-base/htdocs/luci-static/resources/cbi.js
modules/luci-base/htdocs/luci-static/resources/firewall.js
modules/luci-base/htdocs/luci-static/resources/form.js
modules/luci-base/htdocs/luci-static/resources/fs.js
modules/luci-base/htdocs/luci-static/resources/luci.js
modules/luci-base/htdocs/luci-static/resources/ui.js
modules/luci-base/htdocs/luci-static/resources/validation.js

index ef3bd18b4d51a7d6ec79f567a7aaba89c230eacf..1b89542c9664874fcd6d01f8c9be022037225585 100644 (file)
@@ -309,7 +309,7 @@ function cbi_init() {
 
        nodes = document.querySelectorAll('[data-strings]');
 
-       for (var i = 0, node; (node = nodes[i]) !== undefined; i++) {
+       for (let i = 0, node; (node = nodes[i]) !== undefined; i++) {
                var str = JSON.parse(node.getAttribute('data-strings'));
                for (var key in str) {
                        for (var key2 in str[key]) {
@@ -321,30 +321,30 @@ function cbi_init() {
 
        nodes = document.querySelectorAll('[data-depends]');
 
-       for (var i = 0, node; (node = nodes[i]) !== undefined; i++) {
+       for (let i = 0, node; (node = nodes[i]) !== undefined; i++) {
                var index = parseInt(node.getAttribute('data-index'), 10);
                var depends = JSON.parse(node.getAttribute('data-depends'));
                if (!isNaN(index) && depends.length > 0) {
-                       for (var alt = 0; alt < depends.length; alt++)
+                       for (let alt = 0; alt < depends.length; alt++)
                                cbi_d_add(node, depends[alt], index);
                }
        }
 
        nodes = document.querySelectorAll('[data-update]');
 
-       for (var i = 0, node; (node = nodes[i]) !== undefined; i++) {
+       for (let i = 0, node; (node = nodes[i]) !== undefined; i++) {
                var events = node.getAttribute('data-update').split(' ');
-               for (var j = 0, event; (event = events[j]) !== undefined; j++)
+               for (let j = 0, event; (event = events[j]) !== undefined; j++)
                        node.addEventListener(event, cbi_d_update);
        }
 
        nodes = document.querySelectorAll('[data-choices]');
 
-       for (var i = 0, node; (node = nodes[i]) !== undefined; i++) {
-               var choices = JSON.parse(node.getAttribute('data-choices')),
+       for (let i = 0, node; (node = nodes[i]) !== undefined; i++) {
+               let choices = JSON.parse(node.getAttribute('data-choices')),
                    options = {};
 
-               for (var j = 0; j < choices[0].length; j++)
+               for (let j = 0; j < choices[0].length; j++)
                        options[choices[0][j]] = choices[1][j];
 
                var def = (node.getAttribute('data-optional') === 'true')
@@ -364,19 +364,19 @@ function cbi_init() {
 
        nodes = document.querySelectorAll('[data-dynlist]');
 
-       for (var i = 0, node; (node = nodes[i]) !== undefined; i++) {
-               var choices = JSON.parse(node.getAttribute('data-dynlist')),
+       for (let i = 0, node; (node = nodes[i]) !== undefined; i++) {
+               let choices = JSON.parse(node.getAttribute('data-dynlist')),
                    values = JSON.parse(node.getAttribute('data-values') || '[]'),
                    options = null;
 
                if (choices[0] && choices[0].length) {
                        options = {};
 
-                       for (var j = 0; j < choices[0].length; j++)
+                       for (let j = 0; j < choices[0].length; j++)
                                options[choices[0][j]] = choices[1][j];
                }
 
-               var dl = new L.ui.DynamicList(values, options, {
+               let dl = new L.ui.DynamicList(values, options, {
                        name: node.getAttribute('data-prefix'),
                        sort: choices[0],
                        datatype: choices[2],
@@ -384,14 +384,14 @@ function cbi_init() {
                        placeholder: node.getAttribute('data-placeholder')
                });
 
-               var n = dl.render();
+               let n = dl.render();
                n.addEventListener('cbi-dynlist-change', cbi_d_update);
                node.parentNode.replaceChild(n, node);
        }
 
        nodes = document.querySelectorAll('[data-type]');
 
-       for (var i = 0, node; (node = nodes[i]) !== undefined; i++) {
+       for (let i = 0, node; (node = nodes[i]) !== undefined; i++) {
                cbi_validate_field(node, node.getAttribute('data-optional') === 'true',
                                   node.getAttribute('data-type'));
        }
@@ -401,7 +401,7 @@ function cbi_init() {
        });
 
        document.querySelectorAll('.cbi-section-remove > input[name^="cbi.rts"]').forEach(function(i) {
-               var handler = function(ev) {
+               let handler = function(ev) {
                        var bits = this.name.split(/\./),
                            section = document.getElementById('cbi-' + bits[2] + '-' + bits[3]);
 
@@ -415,7 +415,7 @@ function cbi_init() {
        var tasks = [];
 
        document.querySelectorAll('[data-ui-widget]').forEach(function(node) {
-               var args = JSON.parse(node.getAttribute('data-ui-widget') || '[]'),
+               let args = JSON.parse(node.getAttribute('data-ui-widget') || '[]'),
                    widget = new (Function.prototype.bind.apply(L.ui[args[0]], args)),
                    markup = widget.render();
 
@@ -562,7 +562,7 @@ function cbi_row_swap(elem, up, store)
                        node.classList.remove('cbi-rowstyle-2');
                        node.classList.add((n++ % 2) ? 'cbi-rowstyle-2' : 'cbi-rowstyle-1');
 
-                       if (/-([^\-]+)$/.test(node.id))
+                       if (/-([^-]+)$/.test(node.id))
                                ids.push(RegExp.$1);
                }
        }
@@ -675,7 +675,7 @@ String.prototype.format = function()
        var re = /^(([^%]*)%('.|0|\x20)?(-)?(\d+)?(\.\d+)?(%|b|c|d|u|f|o|s|x|X|q|h|j|t|m))/;
        var a = b = [], numSubstitutions = 0, numMatches = 0;
 
-       while (a = re.exec(str)) {
+       while ((a = re.exec(str)) !== null) {
                var m = a[1];
                var leftpart = a[2], pPad = a[3], pJustify = a[4], pMinLength = a[5];
                var pPrecision = a[6], pType = a[7];
@@ -810,7 +810,7 @@ String.prototype.format = function()
 
                if (pMinLength) {
                        subst = subst.toString();
-                       for (var i = subst.length; i < pMinLength; i++)
+                       for (let i = subst.length; i < pMinLength; i++)
                                if (pJustify == '-')
                                        subst = subst + ' ';
                                else
@@ -895,13 +895,6 @@ if (!window.requestAnimationFrame) {
  */
 function isElem(e) { return L.dom.elem(e) }
 
-/**
- * Parse an HTML string into a DOM element.
- * @param {string} s - HTML string.
- * @returns {HTMLElement} Parsed DOM element.
- */
-function toElem(s) { return L.dom.parse(s) }
-
 /**
  * Test whether node matches a CSS selector.
  * @param {Node} node - Node to test.
@@ -960,28 +953,6 @@ function cbi_update_table(table, data, placeholder) {
        t.update(data, placeholder);
 }
 
-/**
- * Show a modal dialog with the given title and children content.
- * @deprecated
- * @param {string} title - Title of the modal.
- * @param {HTMLElement|Array<HTMLElement>} children - Content of the modal.
- * @returns {Promise} Promise that resolves when modal shown or when closed depending on L.showModal.
- */
-function showModal(title, children)
-{
-       return L.showModal(title, children);
-}
-
-/**
- * Hide any currently shown modal dialog.
- * @deprecated
- * @returns {*} Return value forwarded from L.hideModal.
- */
-function hideModal()
-{
-       return L.hideModal();
-}
-
 
 document.addEventListener('DOMContentLoaded', function() {
        document.addEventListener('validation-failure', function(ev) {
index 4a10e22bc233c9842fe20c5ce6e3b3c72f0cd853..e85dd8d2eddb7ad85f9d4dacd42b73fa910b9fba 100644 (file)
@@ -143,11 +143,11 @@ Firewall = L.Class.extend({
 
        getZones: function() {
                return initFirewallState().then(function() {
-                       var sections = uci.sections('firewall', 'zone'),
-                           zones = [];
+                       const sections = uci.sections('firewall', 'zone');
+                       const zones = [];
 
-                       for (var i = 0; i < sections.length; i++)
-                               zones.push(new Zone(sections[i]['.name']));
+                       for (let s of sections)
+                               zones.push(new Zone(s['.name']));
 
                        zones.sort(function(a, b) { return a.getName() > b.getName() });
 
@@ -157,11 +157,11 @@ Firewall = L.Class.extend({
 
        getZoneByNetwork: function(network) {
                return initFirewallState().then(function() {
-                       var sections = uci.sections('firewall', 'zone');
+                       const sections = uci.sections('firewall', 'zone');
 
-                       for (var i = 0; i < sections.length; i++)
-                               if (L.toArray(sections[i].network).indexOf(network) != -1)
-                                       return new Zone(sections[i]['.name']);
+                       for (let s of sections)
+                               if (L.toArray(s.network).indexOf(network) != -1)
+                                       return new Zone(s['.name']);
 
                        return null;
                });
@@ -169,8 +169,8 @@ Firewall = L.Class.extend({
 
        deleteZone: function(name) {
                return initFirewallState().then(function() {
-                       var section = uci.get('firewall', name),
-                           found = false;
+                       const section = uci.get('firewall', name);
+                       let found = false;
 
                        if (section != null && section['.type'] == 'zone') {
                                found = true;
@@ -178,28 +178,28 @@ Firewall = L.Class.extend({
                                uci.remove('firewall', section['.name']);
                        }
                        else if (name != null) {
-                               var sections = uci.sections('firewall', 'zone');
+                               const sections = uci.sections('firewall', 'zone');
 
-                               for (var i = 0; i < sections.length; i++) {
-                                       if (sections[i].name != name)
+                               for (let s of sections) {
+                                       if (s.name != name)
                                                continue;
 
                                        found = true;
-                                       uci.remove('firewall', sections[i]['.name']);
+                                       uci.remove('firewall', s['.name']);
                                }
                        }
 
                        if (found == true) {
-                               sections = uci.sections('firewall');
+                               const sections = uci.sections('firewall');
 
-                               for (var i = 0; i < sections.length; i++) {
-                                       if (sections[i]['.type'] != 'rule' &&
-                                           sections[i]['.type'] != 'redirect' &&
-                                           sections[i]['.type'] != 'forwarding')
+                               for (let s of sections) {
+                                       if (s['.type'] != 'rule' &&
+                                           s['.type'] != 'redirect' &&
+                                           s['.type'] != 'forwarding')
                                            continue;
 
-                                       if (sections[i].src == name || sections[i].dest == name)
-                                               uci.remove('firewall', sections[i]['.name']);
+                                       if (s.src == name || s.dest == name)
+                                               uci.remove('firewall', s['.name']);
                                }
                        }
 
@@ -215,31 +215,31 @@ Firewall = L.Class.extend({
                        if (lookupZone(newName) != null)
                                return false;
 
-                       var sections = uci.sections('firewall', 'zone'),
-                           found = false;
+                       const sections = uci.sections('firewall', 'zone');
+                       let found = false;
 
-                       for (var i = 0; i < sections.length; i++) {
-                               if (sections[i].name != oldName)
+                       for (let s of sections) {
+                               if (s.name != oldName)
                                        continue;
 
-                               uci.set('firewall', sections[i]['.name'], 'name', newName);
+                               uci.set('firewall', s['.name'], 'name', newName);
                                found = true;
                        }
 
                        if (found == true) {
-                               sections = uci.sections('firewall');
+                               const sections = uci.sections('firewall');
 
-                               for (var i = 0; i < sections.length; i++) {
-                                       if (sections[i]['.type'] != 'rule' &&
-                                           sections[i]['.type'] != 'redirect' &&
-                                           sections[i]['.type'] != 'forwarding')
+                               for (let s of sections) {
+                                       if (s['.type'] != 'rule' &&
+                                           s['.type'] != 'redirect' &&
+                                           s['.type'] != 'forwarding')
                                            continue;
 
-                                       if (sections[i].src == oldName)
-                                               uci.set('firewall', sections[i]['.name'], 'src', newName);
+                                       if (s.src == oldName)
+                                               uci.set('firewall', s['.name'], 'src', newName);
 
-                                       if (sections[i].dest == oldName)
-                                               uci.set('firewall', sections[i]['.name'], 'dest', newName);
+                                       if (s.dest == oldName)
+                                               uci.set('firewall', s['.name'], 'dest', newName);
                                }
                        }
 
index cb699e7cd8551e3cb2bf27131dcdb40418afd379..c4bb5f8a5bfde2758ced676c19f809293f9913d9 100644 (file)
@@ -308,7 +308,7 @@ const CBIAbstractElement = baseclass.extend(/** @lends LuCI.form.AbstractElement
         * entities decoded.
         */
        stripTags(s) {
-               if (typeof(s) == 'string' && !s.match(/[<>\&]/))
+               if (typeof(s) == 'string' && !s.match(/[<>&]/))
                        return s;
 
                const x = dom.elem(s) ? s : dom.parse(`<div>${s}</div>`);
@@ -3657,7 +3657,7 @@ const CBITableSection = CBITypedSection.extend(/** @lends LuCI.form.TableSection
                                index = i;
                });
 
-               ev.currentTarget.parentNode.querySelectorAll('tr.cbi-section-table-row').forEach(L.bind((tr, i) => {
+               ev.currentTarget.parentNode.querySelectorAll('tr.cbi-section-table-row').forEach(L.bind((tr) => {
                        const sid = tr.getAttribute('data-sid');
                        const opt = tr.childNodes[index].getAttribute('data-name');
                        let val = this.cfgvalue(sid, opt);
index 4daa9ef8b30378c5e5455f2ca66a17db7d4072f7..630373d656209cada2c9c942f5ff6ec24e091c26 100644 (file)
@@ -99,19 +99,19 @@ var rpcErrors = [
  */
 function handleRpcReply(expect, rc) {
        if (typeof(rc) == 'number' && rc != 0) {
-               var e = new Error(rpc.getStatusText(rc)); e.name = rpcErrors[rc] || 'Error';
+               let e = new Error(rpc.getStatusText(rc)); e.name = rpcErrors[rc] || 'Error';
                throw e;
        }
 
        if (expect) {
-               var type = Object.prototype.toString;
+               const type = Object.prototype.toString;
 
-               for (var key in expect) {
+               for (let key in expect) {
                        if (rc != null && key != '')
                                rc = rc[key];
 
                        if (rc == null || type.call(rc) != type.call(expect[key])) {
-                               var e = new Error(_('Unexpected reply data format')); e.name = 'TypeError';
+                               let e = new Error(_('Unexpected reply data format')); e.name = 'TypeError';
                                throw e;
                        }
 
index f0214695d7663ac9c2afec5e76121f105aa8afca..5649d07e77b763a776f4bf925d5aa3fe54b498eb 100644 (file)
@@ -20,7 +20,7 @@
         * Class declaration and inheritance helper
         */
 
-       const toCamelCase = s => s.replace(/(?:^|[\. -])(.)/g, (m0, m1) => m1.toUpperCase());
+       const toCamelCase = s => s.replace(/(?:^|[. -])(.)/g, (m0, m1) => m1.toUpperCase());
 
        /**
         * @class 
                        if (setenv.base_url == null)
                                this.error('InternalError', 'Cannot find url of luci.js');
 
-                       setenv.cgi_base = setenv.scriptname.replace(/\/[^\/]+$/, '');
+                       setenv.cgi_base = setenv.scriptname.replace(/\/[^/]+$/, '');
 
                        Object.assign(env, setenv);
 
index b3259d219900cce7c1057eb23ceaf7ca76ab728d..1b975dfffec18cfc84ce91183973f1164a4d69d7 100644 (file)
@@ -925,7 +925,7 @@ const UISelect = UIElement.extend(/** @lends LuCI.ui.Select.prototype */ {
                        return;
                }
 
-               const radioEls = frameEl.querySelectorAll('input[type="radio"]');
+               const radioEls = this.node.querySelectorAll('input[type="radio"]');
                for (let i = 0; i < radioEls.length; i++)
                        radioEls[i].checked = (radioEls[i].value == value);
        }
@@ -1165,7 +1165,7 @@ const UIDropdown = UIElement.extend(/** @lends LuCI.ui.Dropdown.prototype */ {
 
                const ul = sb.querySelector('ul');
                const more = sb.appendChild(E('span', { class: 'more', tabindex: -1 }, '···'));
-               const open = sb.appendChild(E('span', { class: 'open', tabindex: -1 }, '▾'));
+               sb.appendChild(E('span', { class: 'open', tabindex: -1 }, '▾'));
                const canary = sb.appendChild(E('div'));
                const create = sb.querySelector(this.options.create_query);
                let ndisplay = this.options.display_items;
@@ -1296,7 +1296,6 @@ const UIDropdown = UIElement.extend(/** @lends LuCI.ui.Dropdown.prototype */ {
         * @param {Node} sb
         */
        openDropdown(sb) {
-               const st = window.getComputedStyle(sb, null);
                const ul = sb.querySelector('ul');
                const li = ul.querySelectorAll('li');
                const fl = findParent(sb, '.cbi-value-field');
@@ -2492,7 +2491,6 @@ const UIDynamicList = UIElement.extend(/** @lends LuCI.ui.DynamicList.prototype
                });
 
                dl.addEventListener('touchstart', (e) => {
-                       const touch = e.touches[0];
                        const target = e.target.closest('.item');
                        if (target) {
                                draggedItem = target;
@@ -3245,7 +3243,7 @@ const UIFileUpload = UIElement.extend(/** @lends LuCI.ui.FileUpload.prototype */
        canonicalizePath(path) {
        return path.replace(/\/{2,}/g, '/')                // Collapse multiple slashes
                                .replace(/\/\.(\/|$)/g, '/')           // Remove `/.`
-                               .replace(/[^\/]+\/\.\.(\/|$)/g, '/')   // Resolve `/..`
+                               .replace(/[^/]+\/\.\.(\/|$)/g, '/')   // Resolve `/..`
                                .replace(/\/$/g, (m, o, s) => s.length > 1 ? '' : '/'); // Remove trailing `/` only if not root
        },
 
@@ -3377,7 +3375,7 @@ const UIFileUpload = UIElement.extend(/** @lends LuCI.ui.FileUpload.prototype */
         * @returns {Promise}
         */
        handleDelete(path, fileStat, ev) {
-               const parent = path.replace(/\/[^\/]+$/, '') ?? '/';
+               const parent = path.replace(/\/[^/]+$/, '') ?? '/';
                const name = path.replace(/^.+\//, '');
                let msg;
 
@@ -3436,7 +3434,7 @@ const UIFileUpload = UIElement.extend(/** @lends LuCI.ui.FileUpload.prototype */
                                                const nameinput = ev.target.parentNode.querySelector('input[type="text"]');
                                                const uploadbtn = ev.target.parentNode.querySelector('button.cbi-button-save');
 
-                                               nameinput.value = ev.target.value.replace(/^.+[\/\\]/, '');
+                                               nameinput.value = ev.target.value.replace(/^.+[/\\]/, '');
                                                uploadbtn.disabled = false;
                                        }
                                }),
@@ -3653,7 +3651,7 @@ const UIFileUpload = UIElement.extend(/** @lends LuCI.ui.FileUpload.prototype */
        handleFileBrowser(ev) {
                const button = ev.target;
                const browser = button.nextElementSibling;
-               let path = this.stat ? this.stat.path.replace(/\/[^\/]+$/, '') : (this.options.initial_directory ?? this.options.root_directory);
+               let path = this.stat ? this.stat.path.replace(/\/[^/]+$/, '') : (this.options.initial_directory ?? this.options.root_directory);
 
                if (path.indexOf(this.options.root_directory) != 0)
                        path = this.options.root_directory;
@@ -3864,8 +3862,8 @@ const UITable = baseclass.extend(/** @lends LuCI.ui.table.prototype */ {
                        const trow = table.appendChild(E('tr', { 'class': 'tr placeholder' }));
                        const td = trow.appendChild(E('td', { 'class': 'td' }, placeholder));
 
-                       if (typeof(captionClasses) == 'object')
-                               DOMTokenList.prototype.add.apply(td.classList, L.toArray(captionClasses[0]));
+                       if (typeof(options.captionClasses) == 'object')
+                               DOMTokenList.prototype.add.apply(td.classList, L.toArray(options.captionClasses[0]));
                }
 
                DOMTokenList.prototype.add.apply(table.classList, L.toArray(options.classes));
@@ -4600,7 +4598,6 @@ const UI = baseclass.extend(/** @lends LuCI.ui.prototype */ {
                for (let i = 0; i < items.length; i += 2) {
                        if (items[i+1] !== null && items[i+1] !== undefined) {
                                const sep = separators[(i/2) % separators.length];
-                               const cld = [];
 
                                children.push(E('span', { class: 'nowrap' }, [
                                        items[i] ? E('strong', `${items[i]}: `) : '',
@@ -4695,13 +4692,14 @@ const UI = baseclass.extend(/** @lends LuCI.ui.prototype */ {
 
                        const menu = E('ul', { 'class': 'cbi-tabmenu' });
                        const group = panes[0].parentNode;
-                       const groupId = +group.getAttribute('data-tab-group');
                        let selected = null;
 
                        if (group.getAttribute('data-initialized') === 'true')
                                return;
 
-                       for (let i = 0, pane; pane = panes[i]; i++) {
+                       let pane;
+                       for (let i = 0; i < panes.length; i++) {
+                               pane = panes[i];
                                const name = pane.getAttribute('data-tab');
                                const title = pane.getAttribute('data-tab-title');
                                const active = pane.getAttribute('data-tab-active') === 'true';
@@ -4810,7 +4808,8 @@ const UI = baseclass.extend(/** @lends LuCI.ui.prototype */ {
                 */
                getActiveTabId(pane) {
                        const path = this.getPathForPane(pane);
-                       return +this.getActiveTabState().paths[path] ?? 0;
+                       const p = +(this.getActiveTabState().paths[path]);
+                       return p ?? 0;
                },
 
                /**
@@ -4872,7 +4871,6 @@ const UI = baseclass.extend(/** @lends LuCI.ui.prototype */ {
                        const name = tab.getAttribute('data-tab');
                        const menu = tab.parentNode;
                        const group = menu.nextElementSibling;
-                       const groupId = +group.getAttribute('data-tab-group');
                        let index = 0;
 
                        ev.preventDefault();
@@ -5090,7 +5088,7 @@ const UI = baseclass.extend(/** @lends LuCI.ui.prototype */ {
                                for (let i = 0; i < 2; i++)
                                        for (let j = 0; j < ipaddrs.length; j++)
                                                tasks.push(this.pingDevice(i ? 'https' : 'http', ipaddrs[j])
-                                                       .then(ev => { reachable = ev.target.src.replace(/^(https?:\/\/[^\/]+).*$/, '$1/') }, () => {}));
+                                                       .then(ev => { reachable = ev.target.src.replace(/^(https?:\/\/[^/]+).*$/, '$1/') }, () => {}));
 
                                return Promise.all(tasks).then(() => {
                                        if (reachable) {
index 9e44e47185cb3e2ef8d6be46db882b4464e4db55..6199be9cd09f4c99ec0b4f1433cab6ec7d8f65a5 100644 (file)
@@ -375,18 +375,18 @@ const ValidatorFactory = baseclass.extend({
                                _('valid IPv6 network'));
                },
 
-               iprange(negative) {
-                       return this.assert(this.apply('iprange4', null, [negative]) || this.apply('iprange6', null, [negative]),
+               iprange() {
+                       return this.assert(this.apply('iprange4', null, []) || this.apply('iprange6', null, []),
                                _('valid IP address range'));
                },
 
-               iprange4(negative) {
+               iprange4() {
                        const m = this.value.split('-');
                        return this.assert(m.length == 2 && arrayle(this.factory.parseIPv4(m[0]), this.factory.parseIPv4(m[1])),
                                _('valid IPv4 address range'));
                },
 
-               iprange6(negative) {
+               iprange6() {
                        const m = this.value.split('-');
                        return this.assert(m.length == 2 && arrayle(this.factory.parseIPv6(m[0]), this.factory.parseIPv6(m[1])),
                                _('valid IPv6 address range'));
@@ -449,8 +449,8 @@ const ValidatorFactory = baseclass.extend({
                },
 
                ipaddrport(bracket) {
-                       const m4 = this.value.match(/^([^\[\]:]+):(\d+)$/);
-                       const m6 = this.value.match((bracket == 1) ? /^\[(.+)\]:(\d+)$/ : /^([^\[\]]+):(\d+)$/);
+                       const m4 = this.value.match(/^([^[\]:]+):(\d+)$/);
+                       const m6 = this.value.match((bracket == 1) ? /^\[(.+)\]:(\d+)$/ : /^([^[\]]+):(\d+)$/);
 
                        if (m4)
                                return this.assert(this.apply('ip4addr', m4[1], [true]) && this.apply('port', m4[2]),
@@ -495,7 +495,7 @@ const ValidatorFactory = baseclass.extend({
                        if (v == '.' || v == '..')
                                return this.assert(false, _('valid network device name, not "." or ".."'));
 
-                       return this.assert(v.match(/^[^:\/%\s]{1,15}$/), _('valid network device name between 1 and 15 characters not containing ":", "/", "%" or spaces'));
+                       return this.assert(v.match(/^[^:/%\s]{1,15}$/), _('valid network device name between 1 and 15 characters not containing ":", "/", "%" or spaces'));
                },
 
                range(min, max) {
@@ -591,7 +591,7 @@ const ValidatorFactory = baseclass.extend({
                },
 
                phonedigit() {
-                       return this.assert(this.value.match(/^[0-9\*#!\.]+$/),
+                       return this.assert(this.value.match(/^[0-9*#!.]+$/),
                                _('valid phone digit (0-9, "*", "#", "!" or ".")'));
                },
 
git clone https://git.99rst.org/PROJECT