ESLint upgrade from JSHint (#3906)

* ESLint upgrade from JSHint
* commit corresponding package.json
* `npm run fix` for automatic JS and CSS fixes
* Keep JSHint config for now
This commit is contained in:
Alexandre Alapetite 2021-10-21 11:44:03 +02:00 committed by GitHub
parent cfd625c559
commit b438d8bb3d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 979 additions and 909 deletions

3
.eslintignore Normal file
View File

@ -0,0 +1,3 @@
*.min.js
node_modules/
p/scripts/vendor/

26
.eslintrc.json Normal file
View File

@ -0,0 +1,26 @@
{
"env": {
"browser": true
},
"extends": [
"eslint:recommended",
"standard"
],
"rules": {
"camelcase": "off",
"comma-dangle": ["warn", "always-multiline"],
"eqeqeq": "off",
"indent": ["warn", "tab", { "SwitchCase": 1 }],
"linebreak-style": ["error", "unix"],
"max-len": ["warn", 165],
"no-tabs": "off",
"semi": ["warn", "always"],
"space-before-function-paren": ["warn", {
"anonymous": "always",
"named": "never",
"asyncArrow": "always"
}],
"yoda": "off"
},
"root": true
}

2
.gitignore vendored
View File

@ -1,6 +1,6 @@
/bin
/node_modules
package*.json
package-lock.json
constants.local.php
# Temp files

View File

@ -1,8 +1,9 @@
{
"esversion" : 6,
"esversion" : 8,
"browser" : true,
"globals": {
"confirm": true,
"console": true
}
},
"strict": "global"
}

View File

@ -33,11 +33,9 @@
"no-eol-whitespace": true,
"property-no-vendor-prefix": true,
"rule-empty-line-before": [
"always",
"except": [
"after-single-line-comment",
"first-nested"
]
"always", {
"except": ["after-single-line-comment","first-nested"]
}
],
"order/properties-order": [
"margin",

View File

@ -45,12 +45,9 @@ jobs:
env:
- HADOLINT="$HOME/hadolint"
install:
- npm install --save-dev jshint stylelint stylelint-order stylelint-scss stylelint-config-recommended-scss
- npm install
- curl -sL -o ${HADOLINT} "https://github.com/hadolint/hadolint/releases/download/v1.18.0/hadolint-$(uname -s)-$(uname -m)" && chmod 700 ${HADOLINT}
script:
- node_modules/jshint/bin/jshint .
# check SCSS separately
- stylelint --syntax scss "**/*.scss"
- stylelint "**/*.css"
- npm test
- bash tests/shellchecks.sh
- git ls-files --exclude='*Dockerfile*' --ignored | xargs --max-lines=1 "$HADOLINT"

View File

@ -1,6 +1,5 @@
// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-3.0
"use strict";
/* jshint esversion:6, strict:global */
'use strict';
function check(url, next) {
if (!url || !next) {
@ -10,8 +9,8 @@ function check(url, next) {
req.open('GET', url, true);
req.setRequestHeader('Authorization', 'GoogleLogin auth=test/1');
req.onerror = function (e) {
next('FAIL: HTTP ' + e);
};
next('FAIL: HTTP ' + e);
};
req.onload = function () {
if (this.status == 200) {
next(this.response);
@ -25,40 +24,40 @@ function check(url, next) {
const jsonVars = JSON.parse(document.getElementById('jsonVars').innerHTML);
check(jsonVars.greader + '/check/compatibility', function next(result1) {
const greaderOutput = document.getElementById('greaderOutput');
if (result1 === 'PASS') {
greaderOutput.innerHTML = '✔️ ' + result1;
} else {
check(jsonVars.greader + '/check%2Fcompatibility', function next(result2) {
if (result2 === 'PASS') {
greaderOutput.innerHTML = '⚠️ WARN: no <code>%2F</code> support, so some clients will not work!';
} else {
check('./greader.php/check/compatibility', function next(result3) {
if (result3 === 'PASS') {
greaderOutput.innerHTML = '⚠️ WARN: Probable invalid base URL in ./data/config.php';
} else {
greaderOutput.innerHTML = '❌ ' + result1;
}
});
}
});
}
});
check(jsonVars.fever + '?api', function next(result1) {
const feverOutput = document.getElementById('feverOutput');
try {
JSON.parse(result1);
feverOutput.innerHTML = '✔️ PASS';
} catch (ex) {
check('./fever.php?api', function next(result2) {
try {
JSON.parse(result2);
feverOutput.innerHTML = '⚠️ WARN: Probable invalid base URL in ./data/config.php';
} catch (ex) {
feverOutput.innerHTML = '❌ ' + result1;
const greaderOutput = document.getElementById('greaderOutput');
if (result1 === 'PASS') {
greaderOutput.innerHTML = '✔️ ' + result1;
} else {
check(jsonVars.greader + '/check%2Fcompatibility', function next(result2) {
if (result2 === 'PASS') {
greaderOutput.innerHTML = '⚠️ WARN: no <code>%2F</code> support, so some clients will not work!';
} else {
check('./greader.php/check/compatibility', function next(result3) {
if (result3 === 'PASS') {
greaderOutput.innerHTML = '⚠️ WARN: Probable invalid base URL in ./data/config.php';
} else {
greaderOutput.innerHTML = '❌ ' + result1;
}
});
}
});
}
});
}
});
check(jsonVars.fever + '?api', function next(result1) {
const feverOutput = document.getElementById('feverOutput');
try {
JSON.parse(result1);
feverOutput.innerHTML = '✔️ PASS';
} catch (ex) {
check('./fever.php?api', function next(result2) {
try {
JSON.parse(result2);
feverOutput.innerHTML = '⚠️ WARN: Probable invalid base URL in ./data/config.php';
} catch (ex) {
feverOutput.innerHTML = '❌ ' + result1;
}
});
}
});
// @license-end

View File

@ -1,16 +1,15 @@
// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-3.0
"use strict";
'use strict';
/* globals context */
/* jshint esversion:6, strict:global */
var loading = false,
dnd_successful = false;
let loading = false;
let dnd_successful = false;
function dragend_process(t) {
t.setAttribute('draggable', 'false');
if (loading) {
setTimeout(function() {
setTimeout(function () {
dragend_process(t);
}, 50);
return;
@ -25,13 +24,14 @@ function dragend_process(t) {
t.remove();
if (p.childElementCount <= 1) {
p.insertAdjacentHTML('afterbegin', '<li class="item feed disabled" dropzone="move"><div class="alert-warn">' + context.i18n.category_empty + '</div></li>');
p.insertAdjacentHTML('afterbegin',
'<li class="item feed disabled" dropzone="move"><div class="alert-warn">' + context.i18n.category_empty + '</div></li>');
}
}
}
var dragFeedId = '',
dragHtml = '';
let dragFeedId = '';
let dragHtml = '';
function init_draggable() {
if (!window.context) {
@ -42,99 +42,99 @@ function init_draggable() {
return;
}
const draggable = '[draggable="true"]',
dropzone = '[dropzone="move"]',
dropSection = document.querySelector('.drop-section');
const draggable = '[draggable="true"]';
const dropzone = '[dropzone="move"]';
const dropSection = document.querySelector('.drop-section');
dropSection.ondragstart = function(ev) {
const li = ev.target.closest ? ev.target.closest(draggable) : null;
if (li) {
const drag = ev.target.closest('[draggable]');
ev.dataTransfer.effectAllowed = 'move';
dragHtml = drag.outerHTML;
dragFeedId = drag.getAttribute('data-feed-id');
ev.dataTransfer.setData('text', dragFeedId);
drag.style.opacity = 0.3;
dnd_successful = false;
}
};
dropSection.ondragstart = function (ev) {
const li = ev.target.closest ? ev.target.closest(draggable) : null;
if (li) {
const drag = ev.target.closest('[draggable]');
ev.dataTransfer.effectAllowed = 'move';
dragHtml = drag.outerHTML;
dragFeedId = drag.getAttribute('data-feed-id');
ev.dataTransfer.setData('text', dragFeedId);
drag.style.opacity = 0.3;
dnd_successful = false;
}
};
dropSection.ondragend = function(ev) {
const li = ev.target.closest ? ev.target.closest(draggable) : null;
if (li) {
dragend_process(li);
}
};
dropSection.ondragend = function (ev) {
const li = ev.target.closest ? ev.target.closest(draggable) : null;
if (li) {
dragend_process(li);
}
};
dropSection.ondragenter = function(ev) {
const li = ev.target.closest ? ev.target.closest(dropzone) : null;
if (li) {
li.classList.add('drag-hover');
return false;
}
};
dropSection.ondragenter = function (ev) {
const li = ev.target.closest ? ev.target.closest(dropzone) : null;
if (li) {
li.classList.add('drag-hover');
return false;
}
};
dropSection.onddragleave = function(ev) {
const li = ev.target.closest ? ev.target.closest(dropzone) : null;
if (li) {
const scroll_top = document.documentElement.scrollTop,
top = li.offsetTop,
left = li.offsetLeft,
right = left + li.clientWidth,
bottom = top + li.clientHeight,
mouse_x = ev.screenX,
mouse_y = ev.clientY + scroll_top;
dropSection.onddragleave = function (ev) {
const li = ev.target.closest ? ev.target.closest(dropzone) : null;
if (li) {
const scroll_top = document.documentElement.scrollTop;
const top = li.offsetTop;
const left = li.offsetLeft;
const right = left + li.clientWidth;
const bottom = top + li.clientHeight;
const mouse_x = ev.screenX;
const mouse_y = ev.clientY + scroll_top;
if (left <= mouse_x && mouse_x <= right &&
if (left <= mouse_x && mouse_x <= right &&
top <= mouse_y && mouse_y <= bottom) {
// HACK because dragleave is triggered when hovering children!
return;
// HACK because dragleave is triggered when hovering children!
return;
}
li.classList.remove('drag-hover');
}
};
dropSection.ondragover = function (ev) {
const li = ev.target.closest ? ev.target.closest(dropzone) : null;
if (li) {
ev.dataTransfer.dropEffect = 'move';
return false;
}
};
dropSection.ondrop = function (ev) {
const li = ev.target.closest ? ev.target.closest(dropzone) : null;
if (li) {
loading = true;
const req = new XMLHttpRequest();
req.open('POST', './?c=feed&a=move', true);
req.responseType = 'json';
req.onload = function (e) {
if (this.status == 200) {
li.insertAdjacentHTML('afterend', dragHtml);
if (li.classList.contains('disabled')) {
li.remove();
}
dnd_successful = true;
}
li.classList.remove('drag-hover');
}
};
};
req.onloadend = function (e) {
loading = false;
dragFeedId = '';
dragHtml = '';
};
req.setRequestHeader('Content-Type', 'application/json');
req.send(JSON.stringify({
f_id: dragFeedId,
c_id: li.parentElement.getAttribute('data-cat-id'),
_csrf: context.csrf,
}));
dropSection.ondragover = function(ev) {
const li = ev.target.closest ? ev.target.closest(dropzone) : null;
if (li) {
ev.dataTransfer.dropEffect = "move";
return false;
}
};
dropSection.ondrop = function(ev) {
const li = ev.target.closest ? ev.target.closest(dropzone) : null;
if (li) {
loading = true;
const req = new XMLHttpRequest();
req.open('POST', './?c=feed&a=move', true);
req.responseType = 'json';
req.onload = function (e) {
if (this.status == 200) {
li.insertAdjacentHTML('afterend', dragHtml);
if (li.classList.contains('disabled')) {
li.remove();
}
dnd_successful = true;
}
};
req.onloadend = function (e) {
loading = false;
dragFeedId = '';
dragHtml = '';
};
req.setRequestHeader('Content-Type', 'application/json');
req.send(JSON.stringify({
f_id: dragFeedId,
c_id: li.parentElement.getAttribute('data-cat-id'),
_csrf: context.csrf,
}));
li.classList.remove('drag-hover');
return false;
}
};
li.classList.remove('drag-hover');
return false;
}
};
}
function archiving() {
@ -143,7 +143,7 @@ function archiving() {
if (e.target.id === 'use_default_purge_options') {
slider.querySelectorAll('.archiving').forEach(function (element) {
element.hidden = e.target.checked;
if (!e.target.checked) element.style.visibility = 'visible'; //Help for Edge 44
if (!e.target.checked) element.style.visibility = 'visible'; // Help for Edge 44
});
}
});

View File

@ -1,8 +1,7 @@
// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-3.0
"use strict";
/* jshint esversion:6, strict:global */
'use strict';
const init_draggable_list = function() {
const init_draggable_list = function () {
if (!window.context) {
if (window.console) {
console.log('FreshRSS draggable list waiting for JS…');

View File

@ -1,7 +1,6 @@
// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-3.0
"use strict";
'use strict';
/* globals context, openNotification, openPopupWithSource, xmlHttpRequestJson */
/* jshint esversion:6, strict:global */
function fix_popup_preview_selector() {
const link = document.getElementById('popup-preview-selector');
@ -20,8 +19,8 @@ function fix_popup_preview_selector() {
});
}
//<crypto form (Web login)>
function poormanSalt() { //If crypto.getRandomValues is not available
// <crypto form (Web login)>
function poormanSalt() { // If crypto.getRandomValues is not available
const base = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ.0123456789/abcdefghijklmnopqrstuvwxyz';
let text = '$2a$04$';
for (let i = 22; i > 0; i--) {
@ -61,8 +60,8 @@ function init_crypto_form() {
const req = new XMLHttpRequest();
req.open('GET', './?c=javascript&a=nonce&user=' + document.getElementById('username').value, false);
req.onerror = function () {
openNotification('Communication error!', 'bad');
};
openNotification('Communication error!', 'bad');
};
req.send();
if (req.status == 200) {
const json = xmlHttpRequestJson(req);
@ -70,9 +69,9 @@ function init_crypto_form() {
openNotification('Invalid user!', 'bad');
} else {
try {
const strong = window.Uint32Array && window.crypto && (typeof window.crypto.getRandomValues === 'function'),
s = dcodeIO.bcrypt.hashSync(document.getElementById('passwordPlain').value, json.salt1),
c = dcodeIO.bcrypt.hashSync(json.nonce + s, strong ? dcodeIO.bcrypt.genSaltSync(4) : poormanSalt());
const strong = window.Uint32Array && window.crypto && (typeof window.crypto.getRandomValues === 'function');
const s = dcodeIO.bcrypt.hashSync(document.getElementById('passwordPlain').value, json.salt1);
const c = dcodeIO.bcrypt.hashSync(json.nonce + s, strong ? dcodeIO.bcrypt.genSaltSync(4) : poormanSalt());
document.getElementById('challenge').value = c;
if (!s || !c) {
openNotification('Crypto error!', 'bad');
@ -91,83 +90,83 @@ function init_crypto_form() {
return success;
};
}
//</crypto form (Web login)>
// </crypto form (Web login)>
function init_password_observers() {
document.querySelectorAll('.toggle-password').forEach(function (a) {
a.onmousedown = function (ev) {
const passwordField = document.getElementById(this.getAttribute('data-toggle'));
passwordField.setAttribute('type', 'text');
this.classList.add('active');
return false;
};
a.onmouseup = function (ev) {
const passwordField = document.getElementById(this.getAttribute('data-toggle'));
passwordField.setAttribute('type', 'password');
this.classList.remove('active');
return false;
};
});
a.onmousedown = function (ev) {
const passwordField = document.getElementById(this.getAttribute('data-toggle'));
passwordField.setAttribute('type', 'text');
this.classList.add('active');
return false;
};
a.onmouseup = function (ev) {
const passwordField = document.getElementById(this.getAttribute('data-toggle'));
passwordField.setAttribute('type', 'password');
this.classList.remove('active');
return false;
};
});
}
function init_select_observers() {
document.querySelectorAll('.select-change').forEach(function (s) {
s.onchange = function (ev) {
const opt = s.options[s.selectedIndex],
url = opt.getAttribute('data-url');
if (url) {
s.disabled = true;
s.value = '';
if (s.form) {
s.form.querySelectorAll('[type=submit]').forEach(function (b) {
b.disabled = true;
});
}
location.href = url;
}
};
});
s.onchange = function (ev) {
const opt = s.options[s.selectedIndex];
const url = opt.getAttribute('data-url');
if (url) {
s.disabled = true;
s.value = '';
if (s.form) {
s.form.querySelectorAll('[type=submit]').forEach(function (b) {
b.disabled = true;
});
}
location.href = url;
}
};
});
}
function init_slider_observers() {
const slider = document.getElementById('slider'),
closer = document.getElementById('close-slider');
const slider = document.getElementById('slider');
const closer = document.getElementById('close-slider');
if (!slider) {
return;
}
document.querySelector('.post').onclick = function (ev) {
const a = ev.target.closest('.open-slider');
if (a) {
if (!context.ajax_loading) {
context.ajax_loading = true;
const a = ev.target.closest('.open-slider');
if (a) {
if (!context.ajax_loading) {
context.ajax_loading = true;
const req = new XMLHttpRequest();
req.open('GET', a.href + '&ajax=1', true);
req.responseType = 'document';
req.onload = function (e) {
slider.innerHTML = this.response.body.innerHTML;
slider.classList.add('active');
closer.classList.add('active');
context.ajax_loading = false;
fix_popup_preview_selector();
};
req.send();
return false;
}
}
};
closer.onclick = function (ev) {
if (data_leave_validation() || confirm(context.i18n.confirmation_default)) {
slider.querySelectorAll('form').forEach(function (f) { f.reset(); });
closer.classList.remove('active');
slider.classList.remove('active');
return true;
} else {
const req = new XMLHttpRequest();
req.open('GET', a.href + '&ajax=1', true);
req.responseType = 'document';
req.onload = function (e) {
slider.innerHTML = this.response.body.innerHTML;
slider.classList.add('active');
closer.classList.add('active');
context.ajax_loading = false;
fix_popup_preview_selector();
};
req.send();
return false;
}
};
}
};
closer.onclick = function (ev) {
if (data_leave_validation() || confirm(context.i18n.confirmation_default)) {
slider.querySelectorAll('form').forEach(function (f) { f.reset(); });
closer.classList.remove('active');
slider.classList.remove('active');
return true;
} else {
return false;
}
};
}
function data_leave_validation() {
@ -187,16 +186,16 @@ function data_leave_validation() {
function init_configuration_alert() {
window.onsubmit = function (e) {
window.hasSubmit = true;
};
window.hasSubmit = true;
};
window.onbeforeunload = function (e) {
if (window.hasSubmit) {
return;
}
if (!data_leave_validation()) {
return false;
}
};
if (window.hasSubmit) {
return;
}
if (!data_leave_validation()) {
return false;
}
};
}
function init_extra() {
@ -204,7 +203,7 @@ function init_extra() {
if (window.console) {
console.log('FreshRSS extra waiting for JS…');
}
window.setTimeout(init_extra, 50); //Wait for all js to be loaded
window.setTimeout(init_extra, 50); // Wait for all js to be loaded
return;
}
init_crypto_form();
@ -219,10 +218,10 @@ if (document.readyState && document.readyState !== 'loading') {
init_extra();
} else {
document.addEventListener('DOMContentLoaded', function () {
if (window.console) {
console.log('FreshRSS extra waiting for DOMContentLoaded…');
}
init_extra();
}, false);
if (window.console) {
console.log('FreshRSS extra waiting for DOMContentLoaded…');
}
init_extra();
}, false);
}
// @license-end

View File

@ -1,9 +1,8 @@
// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-3.0
"use strict";
'use strict';
/* globals context, init_load_more, init_posts, init_stream */
/* jshint esversion:6, strict:global */
var panel_loading = false;
let panel_loading = false;
function load_panel(link) {
if (panel_loading) {
@ -16,63 +15,63 @@ function load_panel(link) {
req.open('GET', link, true);
req.responseType = 'document';
req.onload = function (e) {
if (this.status != 200) {
return;
if (this.status != 200) {
return;
}
const html = this.response;
const foreign = html.querySelectorAll('.nav_menu, #stream .day, #stream .flux, #stream .pagination, #stream.prompt');
const panel = document.getElementById('panel');
foreign.forEach(function (el) {
panel.appendChild(document.adoptNode(el));
});
panel.querySelectorAll('.nav_menu > :not([id="nav_menu_read_all"])').forEach(function (el) {
el.remove();
});
init_load_more(panel);
init_posts();
document.getElementById('overlay').classList.add('visible');
panel.classList.add('visible');
// force le démarrage du scroll en haut.
// Sans ça, si l'on scroll en lisant une catégorie par exemple,
// en en ouvrant une autre ensuite, on se retrouve au même point de scroll
panel.scrollTop = 0;
document.documentElement.scrollTop = 0;
// We already have a click listener in main.js
panel.addEventListener('click', function (ev) {
const b = ev.target.closest('#nav_menu_read_all button, #bigMarkAsRead');
if (b) {
console.log(b.formAction);
const req2 = new XMLHttpRequest();
req2.open('POST', b.formAction, false);
req2.setRequestHeader('Content-Type', 'application/json');
req2.send(JSON.stringify({
_csrf: context.csrf,
}));
if (req2.status == 200) {
location.reload(false);
return false;
}
}
const html = this.response,
foreign = html.querySelectorAll('.nav_menu, #stream .day, #stream .flux, #stream .pagination, #stream.prompt'),
panel = document.getElementById('panel');
foreign.forEach(function (el) {
panel.appendChild(document.adoptNode(el));
});
panel.querySelectorAll('.nav_menu > :not([id="nav_menu_read_all"])').forEach(function (el) {
el.remove();
});
});
init_load_more(panel);
init_posts();
document.getElementById('overlay').classList.add('visible');
panel.classList.add('visible');
// force le démarrage du scroll en haut.
// Sans ça, si l'on scroll en lisant une catégorie par exemple,
// en en ouvrant une autre ensuite, on se retrouve au même point de scroll
panel.scrollTop = 0;
document.documentElement.scrollTop = 0;
//We already have a click listener in main.js
panel.addEventListener('click', function (ev) {
const b = ev.target.closest('#nav_menu_read_all button, #bigMarkAsRead');
if (b) {
console.log(b.formAction);
const req2 = new XMLHttpRequest();
req2.open('POST', b.formAction, false);
req2.setRequestHeader('Content-Type', 'application/json');
req2.send(JSON.stringify({
_csrf: context.csrf,
}));
if (req2.status == 200) {
location.reload(false);
return false;
}
}
});
panel_loading = false;
};
panel_loading = false;
};
req.send();
}
function init_close_panel() {
const panel = document.getElementById('panel');
document.querySelector('#overlay .close').onclick = function (ev) {
panel.innerHTML = '';
panel.classList.remove('visible');
document.getElementById('overlay').classList.remove('visible');
return false;
};
panel.innerHTML = '';
panel.classList.remove('visible');
document.getElementById('overlay').classList.remove('visible');
return false;
};
document.addEventListener('keydown', ev => {
const k = (ev.key.trim() || ev.code).toUpperCase();
if (k === 'ESCAPE' || k === 'ESC') {
@ -85,15 +84,15 @@ function init_close_panel() {
function init_global_view() {
// TODO: should be based on generic classes
document.querySelectorAll('.box a').forEach(function (a) {
a.onclick = function (ev) {
load_panel(a.href);
return false;
};
});
a.onclick = function (ev) {
load_panel(a.href);
return false;
};
});
document.querySelectorAll('.nav_menu #nav_menu_read_all, .nav_menu .toggle_aside').forEach(function (el) {
el.remove();
});
el.remove();
});
const panel = document.getElementById('panel');
init_stream(panel);
@ -104,7 +103,7 @@ function init_all_global_view() {
if (window.console) {
console.log('FreshRSS Global view waiting for JS…');
}
window.setTimeout(init_all_global_view, 50); //Wait for all js to be loaded
window.setTimeout(init_all_global_view, 50); // Wait for all js to be loaded
return;
}
init_global_view();

View File

@ -1,6 +1,5 @@
// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-3.0
"use strict";
/* jshint esversion:6, strict:global */
'use strict';
function show_password(ev) {
const button = ev.currentTarget;
@ -13,7 +12,7 @@ function hide_password(ev) {
const button = ev.currentTarget;
const passwordField = document.getElementById(button.getAttribute('data-toggle'));
passwordField.setAttribute('type', 'password');
button.className = button.className.replace(/(?:^|\s)active(?!\S)/g , '');
button.className = button.className.replace(/(?:^|\s)active(?!\S)/g, '');
return false;
}
const toggles = document.getElementsByClassName('toggle-password');
@ -25,8 +24,8 @@ for (let i = 0; i < toggles.length; i++) {
const auth_type = document.getElementById('auth_type');
function auth_type_change() {
if (auth_type) {
const auth_value = auth_type.value,
password_input = document.getElementById('passwordPlain');
const auth_value = auth_type.value;
const password_input = document.getElementById('passwordPlain');
if (auth_value === 'form') {
password_input.required = true;

View File

@ -1,8 +1,7 @@
// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-3.0
"use strict";
/* jshint esversion:6, strict:global */
'use strict';
const init_integration = function() {
const init_integration = function () {
if (!window.context) {
if (window.console) {
console.log('FreshRSS integration waiting for JS…');

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +1,10 @@
// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-3.0
"use strict";
/* jshint esversion:6, strict:global */
let rendered_node = null,
rendered_view = null,
raw_node = null,
raw_view = null;
'use strict';
let rendered_node = null;
let rendered_view = null;
let raw_node = null;
let raw_view = null;
function update_ui() {
if (rendered_node.checked && !raw_node.checked) {
@ -29,7 +27,6 @@ function init_afterDOM() {
raw_node.addEventListener('click', update_ui);
}
if (document.readyState && document.readyState !== 'loading') {
init_afterDOM();
} else {

View File

@ -1,7 +1,6 @@
// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-3.0
"use strict";
'use strict';
/* globals Chart */
/* jshint esversion:6, strict:global */
function initCharts() {
if (!window.Chart) {
@ -14,13 +13,13 @@ function initCharts() {
const jsonData = document.getElementsByClassName('jsonData-stats');
var jsonDataParsed;
var chartConfig;
let jsonDataParsed;
let chartConfig;
for (var i = 0; i < jsonData.length; i++) {
for (let i = 0; i < jsonData.length; i++) {
jsonDataParsed = JSON.parse(jsonData[i].innerHTML);
switch(jsonDataParsed.charttype) {
switch (jsonDataParsed.charttype) {
case 'bar':
chartConfig = jsonChartBar(jsonDataParsed.label, jsonDataParsed.data, jsonDataParsed.xAxisLabels);
break;
@ -28,13 +27,13 @@ function initCharts() {
chartConfig = jsonChartDoughnut(jsonDataParsed.labels, jsonDataParsed.data);
break;
case 'barWithAverage':
chartConfig = jsonChartBarWithAvarage(jsonDataParsed.labelBarChart, jsonDataParsed.dataBarChart, jsonDataParsed.labelAverage, jsonDataParsed.dataAverage, jsonDataParsed.xAxisLabels);
chartConfig = jsonChartBarWithAvarage(jsonDataParsed.labelBarChart, jsonDataParsed.dataBarChart,
jsonDataParsed.labelAverage, jsonDataParsed.dataAverage, jsonDataParsed.xAxisLabels);
}
new Chart(
document.getElementById(jsonDataParsed.canvasID),
chartConfig
);
/* eslint-disable no-new */
new Chart(document.getElementById(jsonDataParsed.canvasID), chartConfig);
/* eslint-enable no-new */
}
if (window.console) {
@ -55,25 +54,25 @@ function jsonChartBar(label, data, xAxisLabels = '') {
barPercentage: 1.0,
categoryPercentage: 1.0,
order: 2,
}]
}],
},
options: {
scales: {
y: {
beginAtZero: true
beginAtZero: true,
},
x: {
grid: {
display: false,
}
}
},
},
},
plugins: {
legend: {
display: false,
}
}
}
},
},
},
};
}
@ -84,22 +83,22 @@ function jsonChartDoughnut(labels, data) {
labels: labels,
datasets: [{
backgroundColor: [
'#0b84a5', //petrol
'#0b84a5', // petrol
'#f6c85f', // sand
'#6f4e7c', //purple
'#9dd866', //green
'#ca472f', //red
'#ffa056', //orange
'#6f4e7c', // purple
'#9dd866', // green
'#ca472f', // red
'#ffa056', // orange
'#8dddd0', // turkis
'#f6c85f', // sand
'#6f4e7c', //purple
'#9dd866', //green
'#ca472f', //red
'#ffa056', //orange
'#6f4e7c', // purple
'#9dd866', // green
'#ca472f', // red
'#ffa056', // orange
'#8dddd0', // turkis
],
data: data,
}]
}],
},
options: {
layout: {
@ -109,9 +108,9 @@ function jsonChartDoughnut(labels, data) {
legend: {
position: 'bottom',
align: 'start',
}
}
}
},
},
},
};
}
@ -133,15 +132,15 @@ function jsonChartBarWithAvarage(labelBarChart, dataBarChart, labelAverage, data
{
// average line chart
type: 'line',
label: labelAverage, // Todo: i18n
label: labelAverage, // Todo: i18n
borderColor: 'rgb(192,216,0)',
data: {
'-30' : dataAverage,
'-1' : dataAverage,
'-30': dataAverage,
'-1': dataAverage,
},
order: 1,
}
]
},
],
},
options: {
@ -151,41 +150,41 @@ function jsonChartBarWithAvarage(labelBarChart, dataBarChart, labelAverage, data
},
x: {
ticks: {
callback: function(val){
callback: function (val) {
if (xAxisLabels.length > 0) {
return xAxisLabels[val];
} else {
return val;
}
}
},
},
grid: {
display: false,
}
}
},
},
},
elements: {
point: {
radius: 0,
}
},
},
plugins: {
tooltip: {
callbacks: {
title: function(tooltipitem) {
title: function (tooltipitem) {
if (xAxisLabels.length > 0) {
return xAxisLabels[tooltipitem[0].dataIndex];
} else {
return tooltipitem[0].label;
}
}
}
},
},
},
legend: {
display: false,
}
}
}
},
},
},
};
}

View File

@ -879,7 +879,7 @@ input[type="search"] {
}
.subtitle > div:not(:first-of-type)::before {
content: ' · ';
content: ' · ';
}
br {

View File

@ -465,7 +465,7 @@ a.btn {
/*=== Boxes */
.box {
margin: 20px 10px;
margin: 20px 0 20px 20px;
display: inline-block;
max-width: 95%;
width: 20rem;
@ -473,6 +473,11 @@ a.btn {
vertical-align: top;
}
.box.visible-semi {
border-style: dashed;
opacity: 0.5;
}
.box .box-title {
position: relative;
font-size: 1.2rem;
@ -874,7 +879,7 @@ input[type="search"] {
}
.subtitle > div:not(:first-of-type)::before {
content: ' · ';
content: ' · ';
}
br {
@ -1114,7 +1119,7 @@ br {
display: none;
position: fixed;
top: 2%; bottom: 2%;
left: 3%; right: 3%;
right: 3%; left: 3%;
overflow: auto;
}

42
package.json Normal file
View File

@ -0,0 +1,42 @@
{
"name": "freshrss",
"description": "A free, self-hostable aggregator",
"homepage": "https://freshrss.org/",
"readmeFilename": "README.md",
"bugs": {
"url": "https://github.com/FreshRSS/FreshRSS/issues"
},
"keywords": [
"news",
"aggregator",
"RSS",
"Atom",
"WebSub"
],
"repository": {
"type": "git",
"url": "https://github.com/FreshRSS/FreshRSS.git"
},
"license": "AGPL-3.0",
"scripts": {
"eslint": "eslint --ext .js .",
"eslint_fix": "eslint --fix --ext .js .",
"rtlcss": "rtlcss -d p/themes && find . -type f -name '*.rtl.rtl.css' -delete",
"stylelint": "stylelint '**/*.css' && stylelint --syntax scss '**/*.scss'",
"stylelint_fix": "stylelint --fix '**/*.css' && stylelint --fix --syntax scss '**/*.scss'",
"test": "npm run eslint && npm run stylelint",
"fix": "npm run rtlcss && npm run stylelint_fix && npm run eslint_fix"
},
"devDependencies": {
"eslint": "^7.32.0",
"eslint-config-standard": "^16.0.3",
"eslint-plugin-import": "^2.24.2",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^5.1.0",
"rtlcss": "^3.4.0",
"stylelint": "^13.13.1",
"stylelint-config-recommended-scss": "^4.3.0",
"stylelint-order": "^4.1.0",
"stylelint-scss": "^3.21.0"
}
}